From 91eb7476eb5f70d30fd28e61550625fefdabaa87 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Mon, 30 Aug 2021 14:47:35 -0700 Subject: [PATCH 001/274] Remove superfluous AutoPacket params Signed-off-by: puvvadar --- .../Code/Source/AutoGen/Multiplayer.AutoPackets.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml index 203750d761..c553bc5351 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/Multiplayer.AutoPackets.xml @@ -32,11 +32,11 @@ - + - + From de512db010c65d667b3c485c20db7aa073c635b3 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Wed, 1 Sep 2021 16:26:56 -0700 Subject: [PATCH 002/274] Determine blended timestamp on client plus minor API cleanup Signed-off-by: puvvadar --- .../Code/Include/Multiplayer/IMultiplayer.h | 6 ++---- .../Include/Multiplayer/NetworkTime/INetworkTime.h | 7 ++----- .../Components/LocalPredictionPlayerInputComponent.cpp | 10 +++++----- .../Code/Source/NetworkTime/NetworkTime.cpp | 8 ++------ Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h | 3 +-- 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index 4f714068db..e32b6188eb 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -193,15 +193,13 @@ namespace Multiplayer m_previousHostFrameId = time->GetHostFrameId(); m_previousHostTimeMs = time->GetHostTimeMs(); m_previousRewindConnectionId = time->GetRewindingConnectionId(); - time->AlterTime(frameId, timeMs, connectionId); m_previousBlendFactor = time->GetHostBlendFactor(); - time->AlterBlendFactor(blendFactor); + time->AlterTime(frameId, timeMs, blendFactor, connectionId); } inline ~ScopedAlterTime() { INetworkTime* time = GetNetworkTime(); - time->AlterTime(m_previousHostFrameId, m_previousHostTimeMs, m_previousRewindConnectionId); - time->AlterBlendFactor(m_previousBlendFactor); + time->AlterTime(m_previousHostFrameId, m_previousHostTimeMs, m_previousBlendFactor, m_previousRewindConnectionId); } private: HostFrameId m_previousHostFrameId = InvalidHostFrameId; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h index ae47aa8373..bfddcbdebb 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h @@ -66,12 +66,9 @@ namespace Multiplayer //! Alters the current HostFrameId and binds that alteration to the provided ConnectionId. //! @param frameId the new HostFrameId to use //! @param timeMs the new HostTimeMs to use + //! @param blendFactor the factor used to blend between values at the current and previous HostFrameId //! @param rewindConnectionId the rewinding ConnectionId - virtual void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) = 0; - - //! Alters the current Host blend factor. Used to drive interpolation in rewound states. - //! @param blendFactor the blend factor to use - virtual void AlterBlendFactor(float blendFactor) = 0; + virtual void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId rewindConnectionId) = 0; //! Syncs all entities contained within a volume to the current rewind state. //! @param rewindVolume the volume to rewind entities within (needed for physics entities) diff --git a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp index 452cb31a7a..f33c7f4ef3 100644 --- a/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/LocalPredictionPlayerInputComponent.cpp @@ -179,12 +179,9 @@ namespace Multiplayer // Discard move input events, client may be speed hacking if (m_clientBankedTime < sv_MaxBankTimeWindowSec) { - // Client blends from previous frame to target so here we subtract blend factor to get to that state - const float blendFactor = AZStd::min(AZStd::max(0.f, input.GetHostBlendFactor()), 1.0f); - const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.0f - blendFactor)); m_clientBankedTime = AZStd::min(m_clientBankedTime + clientInputRateSec, (double)sv_MaxBankTimeWindowSec); // clamp to boundary { - ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs() - blendMs, input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); + ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId()); GetNetBindComponent()->ProcessInput(input, static_cast(clientInputRateSec)); } @@ -430,10 +427,13 @@ namespace Multiplayer NetworkInputArray inputArray(GetEntityHandle()); NetworkInput& input = inputArray[0]; + const float blendFactor = AZStd::min(AZStd::max(0.f, multiplayer->GetCurrentBlendFactor()), 1.0f); + const AZ::TimeMs blendMs = AZ::TimeMs(static_cast(static_cast(cl_InputRateMs)) * (1.0f - blendFactor)); input.SetClientInputId(m_clientInputId); input.SetHostFrameId(networkTime->GetHostFrameId()); - input.SetHostTimeMs(multiplayer->GetCurrentHostTimeMs()); + // Account for the client blending from previous frame to current + input.SetHostTimeMs(multiplayer->GetCurrentHostTimeMs() - blendMs); input.SetHostBlendFactor(multiplayer->GetCurrentBlendFactor()); // Allow components to form the input for this frame diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index db8d6bd2f7..69c97d9c3f 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -79,16 +79,12 @@ namespace Multiplayer m_rewindingConnectionId = AzNetworking::InvalidConnectionId; } - void NetworkTime::AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) + void NetworkTime::AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId rewindConnectionId) { m_hostFrameId = frameId; m_hostTimeMs = timeMs; - m_rewindingConnectionId = rewindConnectionId; - } - - void NetworkTime::AlterBlendFactor(float blendFactor) - { m_hostBlendFactor = blendFactor; + m_rewindingConnectionId = rewindConnectionId; } void NetworkTime::SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h index 0278ddd2b0..7c845db8b6 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h @@ -34,8 +34,7 @@ namespace Multiplayer AzNetworking::ConnectionId GetRewindingConnectionId() const override; HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const override; void ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) override; - void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, AzNetworking::ConnectionId rewindConnectionId) override; - void AlterBlendFactor(float blendFactor) override; + void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId rewindConnectionId) override; void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) override; void ClearRewoundEntities() override; //! @} From a1d836e36b2a0dd1be9bb82ca1f913b89ec827a4 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 2 Sep 2021 13:29:49 -0500 Subject: [PATCH 003/274] AtomTools: Removing unnecessary cmake files and setting up tool variant Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.cpp | 2 +- .../Tools/MaterialEditor/Code/CMakeLists.txt | 19 ++--- .../Code/materialeditor_files.cmake | 1 - .../Code/tool_dependencies.cmake | 22 ------ .../Tools/MaterialEditor/MaterialEditor.xml | 69 ------------------- .../Code/CMakeLists.txt | 10 +-- .../Code/tool_dependencies.cmake | 22 ------ 7 files changed, 10 insertions(+), 135 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake delete mode 100644 Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 36e45bb7ca..bd04ba9395 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -468,7 +468,7 @@ namespace AtomToolsFramework void AtomToolsApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const { - appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; + appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool; } void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt index 6230217ac2..0206cebf8b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt @@ -108,8 +108,14 @@ ly_add_target( Gem::MaterialEditor.Window Gem::MaterialEditor.Viewport Gem::MaterialEditor.Document + RUNTIME_DEPENDENCIES + Gem::AtomToolsFramework.Editor + Gem::EditorPythonBindings.Editor + Gem::ImageProcessingAtom.Editor ) +ly_set_gem_variant_to_load(TARGETS MaterialEditor VARIANTS Tools) + # Add a 'builders' alias to allow the MaterialEditor root gem path to be added to the generated # cmake_dependencies..assetprocessor.setreg to allow the asset scan folder for it to be added ly_create_alias(NAME MaterialEditor.Builders NAMESPACE Gem) @@ -118,24 +124,11 @@ ly_create_alias(NAME MaterialEditor.Builders NAMESPACE Gem) # Editor opens up the MaterialEditor ly_add_dependencies(Editor Gem::MaterialEditor) -ly_add_target_files( - TARGETS - MaterialEditor - FILES - ${CMAKE_CURRENT_LIST_DIR}/../MaterialEditor.xml - OUTPUT_SUBDIRECTORY - Gems/Atom/Tools/MaterialEditor -) - ly_add_target_dependencies( TARGETS MaterialEditor DEPENDENCIES_FILES - tool_dependencies.cmake Source/Platform/${PAL_PLATFORM_NAME}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - # The Material Editor needs the LyShine "Tools" gem variant for the custom LyShine pass - DEPENDENT_TARGETS - Gem::LyShine.Tools ) # Inject the project path into the MaterialEditor VS debugger command arguments if the build system being invoked diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake index 2b554a852e..d4c4364ba7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake @@ -10,5 +10,4 @@ set(FILES Source/main.cpp Source/MaterialEditorApplication.cpp Source/MaterialEditorApplication.h - tool_dependencies.cmake ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake b/Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake deleted file mode 100644 index 8803be3852..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -set(GEM_DEPENDENCIES - Gem::Atom_RHI_Null.Private - Gem::Atom_RHI_DX12.Private - Gem::Atom_RHI_Vulkan.Private - Gem::Atom_RHI.Private - Gem::Atom_Component_DebugCamera - Gem::Atom_RPI.Editor - Gem::Atom_RPI.Builders - Gem::Atom_Feature_Common.Editor - Gem::AtomToolsFramework.Editor - Gem::AtomLyIntegration_CommonFeatures.Editor - Gem::EditorPythonBindings.Editor - Gem::ImageProcessingAtom.Editor -) diff --git a/Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml b/Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml deleted file mode 100644 index 9f91001f66..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt index d7e415a279..5710a186d3 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt @@ -78,15 +78,12 @@ ly_add_target( Gem::ShaderManagementConsole.Window Gem::ShaderManagementConsole.Document RUNTIME_DEPENDENCIES - Gem::Atom_RHI_DX12.Private - Gem::Atom_RHI_Vulkan.Private - Gem::Atom_RHI.Private - Gem::Atom_RPI.Private - Gem::Atom_RPI.Builders - Gem::Atom_Feature_Common.Editor + Gem::AtomToolsFramework.Editor Gem::EditorPythonBindings.Editor ) +ly_set_gem_variant_to_load(TARGETS ShaderManagementConsole VARIANTS Tools) + # Add build dependency to Editor for the ShaderManagementConsole application since # Editor opens up the ShaderManagementConsole ly_add_dependencies(Editor Gem::ShaderManagementConsole) @@ -95,7 +92,6 @@ ly_add_target_dependencies( TARGETS ShaderManagementConsole DEPENDENCIES_FILES - tool_dependencies.cmake Source/Platform/${PAL_PLATFORM_NAME}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake deleted file mode 100644 index 8803be3852..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -set(GEM_DEPENDENCIES - Gem::Atom_RHI_Null.Private - Gem::Atom_RHI_DX12.Private - Gem::Atom_RHI_Vulkan.Private - Gem::Atom_RHI.Private - Gem::Atom_Component_DebugCamera - Gem::Atom_RPI.Editor - Gem::Atom_RPI.Builders - Gem::Atom_Feature_Common.Editor - Gem::AtomToolsFramework.Editor - Gem::AtomLyIntegration_CommonFeatures.Editor - Gem::EditorPythonBindings.Editor - Gem::ImageProcessingAtom.Editor -) From c5d8c194dfced4ef22bc74a4a32402b8dd14d3a6 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Thu, 2 Sep 2021 14:24:46 -0700 Subject: [PATCH 004/274] Cleaning up NetworkTime and reworking how we approach network interpolation Signed-off-by: puvvadar --- .../Multiplayer/Components/NetBindComponent.h | 4 +- .../Components/NetworkTransformComponent.h | 17 +--- .../Source/AutoGen/AutoComponent_Header.jinja | 15 ++-- .../Source/AutoGen/AutoComponent_Source.jinja | 19 ++-- ...etworkTransformComponent.AutoComponent.xml | 4 +- .../Source/Components/NetBindComponent.cpp | 4 +- .../Components/NetworkTransformComponent.cpp | 90 ++++++------------- .../Source/MultiplayerSystemComponent.cpp | 4 +- .../Code/Source/NetworkTime/NetworkTime.cpp | 11 ++- 9 files changed, 66 insertions(+), 102 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index 65bac09726..d09de1ad0d 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -35,7 +35,7 @@ namespace Multiplayer using EntityMigrationStartEvent = AZ::Event; using EntityMigrationEndEvent = AZ::Event<>; using EntityServerMigrationEvent = AZ::Event; - using EntityPreRenderEvent = AZ::Event; + using EntityPreRenderEvent = AZ::Event; using EntityCorrectionEvent = AZ::Event<>; //! @class NetBindComponent @@ -118,7 +118,7 @@ namespace Multiplayer void NotifyMigrationStart(ClientInputId migratedInputId); void NotifyMigrationEnd(); void NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId); - void NotifyPreRender(float deltaTime, float blendFactor); + void NotifyPreRender(float deltaTime); void NotifyCorrection(); void AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index 914aeaadd3..a018279a79 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -29,24 +29,9 @@ namespace Multiplayer void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; private: - void OnPreRender(float deltaTime, float blendFactor); + void OnPreRender(float deltaTime); void OnCorrection(); - void OnRotationChangedEvent(const AZ::Quaternion& rotation); - void OnTranslationChangedEvent(const AZ::Vector3& translation); - void OnScaleChangedEvent(float scale); - void OnResetCountChangedEvent(); - - void UpdateTargetHostFrameId(); - - AZ::Transform m_previousTransform = AZ::Transform::CreateIdentity(); - AZ::Transform m_targetTransform = AZ::Transform::CreateIdentity(); - - AZ::Event::Handler m_rotationEventHandler; - AZ::Event::Handler m_translationEventHandler; - AZ::Event::Handler m_scaleEventHandler; - AZ::Event::Handler m_resetCountEventHandler; - EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; EntityCorrectionEvent::Handler m_entityCorrectionEventHandler; diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index 8cde9613b7..815f7d0348 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -7,21 +7,21 @@ {% macro DeclareNetworkPropertyGetter(Property) %} {% set PropertyName = UpperFirst(Property.attrib['Name']) %} {% if Property.attrib['Container'] == 'Array' %} -{% if Property.attrib['IsRewindable']|booleanTrue %} +{% if Property.attrib['IsRewindable']|booleanTrue %} const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Array() const; -{% else %} +{% else %} const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Array() const; -{% endif %} +{% endif %} const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}(int32_t index) const; {% if Property.attrib['GenerateEventBindings']|booleanTrue %} void {{ PropertyName }}AddEvent(AZ::Event::Handler& handler); {% endif %} {% elif Property.attrib['Container'] == 'Vector' %} -{% if Property.attrib['IsRewindable']|booleanTrue %} +{% if Property.attrib['IsRewindable']|booleanTrue %} const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Vector() const; -{% else %} +{% else %} const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Vector() const; -{% endif %} +{% endif %} const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}(int32_t index) const; const {{ Property.attrib['Type'] }}& {{ PropertyName }}GetBack() const; uint32_t {{ PropertyName }}GetSize() const; @@ -31,6 +31,9 @@ void {{ PropertyName }}SizeChangedAddEvent(AZ::Event::Handler& handler {% endif %} {% else %} const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const; +{% if Property.attrib['IsRewindable']|booleanTrue %} +const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}Previous() const; +{% endif %} {% if Property.attrib['GenerateEventBindings']|booleanTrue %} void {{ PropertyName }}AddEvent(AZ::Event<{{ Property.attrib['Type'] }}>::Handler& handler); {% endif %} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index 079cac329b..a02235cc0f 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -3,11 +3,11 @@ {% macro LowerFirst(text) %}{{ text[0] | lower}}{{ text[1:] }}{% endmacro %} {% macro DefineNetworkPropertyGet(ClassName, Property, Prefix = '') %} {% if Property.attrib['Container'] == 'Array' %} -{% if Property.attrib['IsRewindable']|booleanTrue %} +{% if Property.attrib['IsRewindable']|booleanTrue %} const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const -{% else %} +{% else %} const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const -{% endif %} +{% endif %} { return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }}; } @@ -25,11 +25,11 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even {% endif %} {% elif Property.attrib['Container'] == 'Vector' %} -{% if Property.attrib['IsRewindable']|booleanTrue %} +{% if Property.attrib['IsRewindable']|booleanTrue %} const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const -{% else %} +{% else %} const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const -{% endif %} +{% endif %} { return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }}; } @@ -68,7 +68,12 @@ const {{ Property.attrib['Type'] }}& {{ ClassName }}::Get{{ UpperFirst(Property. { return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }}; } - +{% if Property.attrib['IsRewindable']|booleanTrue %} +const {{ Property.attrib['Type'] }}& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Previous() const +{ + return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }}.GetPrevious(); +} +{% endif %} {% if Property.attrib['GenerateEventBindings']|booleanTrue %} void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Event<{{ Property.attrib['Type'] }}>::Handler& handler) { diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml index cec005cc26..8ab2e61e5e 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkTransformComponent.AutoComponent.xml @@ -12,9 +12,9 @@ - + - + diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index d8e8a765ce..9c7d48e67a 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -403,9 +403,9 @@ namespace Multiplayer m_entityServerMigrationEvent.Signal(m_netEntityHandle, hostId, connectionId); } - void NetBindComponent::NotifyPreRender(float deltaTime, float blendFactor) + void NetBindComponent::NotifyPreRender(float deltaTime) { - m_entityPreRenderEvent.Signal(deltaTime, blendFactor); + m_entityPreRenderEvent.Signal(deltaTime); } void NetBindComponent::NotifyCorrection() diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index fa08794c4d..671228f89d 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -26,11 +26,7 @@ namespace Multiplayer } NetworkTransformComponent::NetworkTransformComponent() - : m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); }) - , m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) - , m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); }) - , m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); }) - , m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); }) + : m_entityPreRenderEventHandler([this](float deltaTime) { OnPreRender(deltaTime); }) , m_entityCorrectionEventHandler([this]() { OnCorrection(); }) { ; @@ -43,15 +39,8 @@ namespace Multiplayer void NetworkTransformComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { - RotationAddEvent(m_rotationEventHandler); - TranslationAddEvent(m_translationEventHandler); - ScaleAddEvent(m_scaleEventHandler); - ResetCountAddEvent(m_resetCountEventHandler); GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); - - // When coming into relevance, reset all blending factors so we don't interpolate to our start position - OnResetCountChangedEvent(); } void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) @@ -59,59 +48,31 @@ namespace Multiplayer ; } - void NetworkTransformComponent::OnRotationChangedEvent(const AZ::Quaternion& rotation) - { - m_previousTransform.SetRotation(m_targetTransform.GetRotation()); - m_targetTransform.SetRotation(rotation); - UpdateTargetHostFrameId(); - } - - void NetworkTransformComponent::OnTranslationChangedEvent(const AZ::Vector3& translation) - { - m_previousTransform.SetTranslation(m_targetTransform.GetTranslation()); - m_targetTransform.SetTranslation(translation); - UpdateTargetHostFrameId(); - } - - void NetworkTransformComponent::OnScaleChangedEvent(float scale) - { - m_previousTransform.SetUniformScale(m_targetTransform.GetUniformScale()); - m_targetTransform.SetUniformScale(scale); - UpdateTargetHostFrameId(); - } - - void NetworkTransformComponent::OnResetCountChangedEvent() - { - m_targetTransform.SetRotation(GetRotation()); - m_targetTransform.SetTranslation(GetTranslation()); - m_targetTransform.SetUniformScale(GetScale()); - m_previousTransform = m_targetTransform; - } - - void NetworkTransformComponent::UpdateTargetHostFrameId() - { - HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId(); - if (currentHostFrameId > m_targetHostFrameId) - { - m_targetHostFrameId = currentHostFrameId; - } - } - - void NetworkTransformComponent::OnPreRender([[maybe_unused]] float deltaTime, float blendFactor) + void NetworkTransformComponent::OnPreRender([[maybe_unused]] float deltaTime) { if (!HasController()) { AZ::Transform blendTransform; - if (Multiplayer::GetNetworkTime() && Multiplayer::GetNetworkTime()->GetHostFrameId() > m_targetHostFrameId) - { - m_previousTransform = m_targetTransform; - blendTransform = m_targetTransform; - } - else + blendTransform.SetRotation(GetRotation()); + blendTransform.SetTranslation(GetTranslation()); + blendTransform.SetUniformScale(GetScale()); + + const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); + if (!!AZ::IsClose(blendFactor, 1.0f)) { - blendTransform.SetRotation(m_previousTransform.GetRotation().Slerp(m_targetTransform.GetRotation(), blendFactor)); - blendTransform.SetTranslation(m_previousTransform.GetTranslation().Lerp(m_targetTransform.GetTranslation(), blendFactor)); - blendTransform.SetUniformScale(AZ::Lerp(m_previousTransform.GetUniformScale(), m_targetTransform.GetUniformScale(), blendFactor)); + AZ::Transform blendTransformPrevious; + blendTransformPrevious.SetRotation(GetRotationPrevious()); + blendTransformPrevious.SetTranslation(GetTranslationPrevious()); + blendTransformPrevious.SetUniformScale(GetScalePrevious()); + + if (!blendTransform.IsClose(blendTransformPrevious)) + { + blendTransform.SetRotation(blendTransformPrevious.GetRotation().Slerp(blendTransform.GetRotation(), blendFactor)); + blendTransform.SetTranslation( + blendTransformPrevious.GetTranslation().Lerp(blendTransform.GetTranslation(), blendFactor)); + blendTransform.SetUniformScale( + AZ::Lerp(blendTransformPrevious.GetUniformScale(), blendTransform.GetUniformScale(), blendFactor)); + } } if (!GetTransformComponent()->GetWorldTM().IsClose(blendTransform)) @@ -124,12 +85,15 @@ namespace Multiplayer void NetworkTransformComponent::OnCorrection() { // Snap to latest - OnResetCountChangedEvent(); + AZ::Transform targetTransform; + targetTransform.SetRotation(GetRotation()); + targetTransform.SetTranslation(GetTranslation()); + targetTransform.SetUniformScale(GetScale()); // Hard set the entities transform - if (!GetTransformComponent()->GetWorldTM().IsClose(m_targetTransform)) + if (!GetTransformComponent()->GetWorldTM().IsClose(targetTransform)) { - GetTransformComponent()->SetWorldTM(m_targetTransform); + GetTransformComponent()->SetWorldTM(targetTransform); } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 2d17b072b3..da0c464061 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -922,7 +922,7 @@ namespace Multiplayer for (NetBindComponent* netBindComponent : gatheredEntities) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime); } } else @@ -934,7 +934,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - netBindComponent->NotifyPreRender(deltaTime, m_renderBlendFactor); + netBindComponent->NotifyPreRender(deltaTime); } } } diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 69c97d9c3f..8edf2a8ce4 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -110,8 +110,15 @@ namespace Multiplayer if (networkTransform != nullptr) { - // We're not presently factoring in interpolated position here - const AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); // Get the rewound position + // Get the rewound position for target host frame ID plus the one preceding it for potential lerp + AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); + const AZ::Vector3 rewindCenterPrevious = networkTransform->GetTranslationPrevious(); + const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); + if (!AZ::IsClose(blendFactor, 1.0f) && !rewindCenter.IsClose(rewindCenterPrevious)) + { + // If we have a blend factor, lerp the translation for accuracy + rewindCenter = rewindCenterPrevious.Lerp(rewindCenter, blendFactor); + } const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb From e9dfa3f8dd160ce97c129e740a242c3f83208d93 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:49:32 -0700 Subject: [PATCH 005/274] Enabling warnings in MSVC Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 647ced54a2..f10ef844a4 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -40,9 +40,14 @@ ly_append_configurations_options( # Enabling warnings that are disabled by default from /W4 # https://docs.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=vs-2019 + /we4263 # 'function': member function does not override any base class virtual member function + /we4264 # 'virtual_function': no override available for virtual member function from base 'class'; function is hidden + /we4265 # 'class': class has virtual functions, but destructor is not virtual + /we4266 # 'function': no override available for virtual member function from base 'type'; function is hidden /we4296 # 'operator': expression is always false /we5233 # explicit lambda capture 'identifier' is not used /we4426 # optimization flags changed after including header, may be due to #pragma optimize() + /we4437 # dynamic_cast from virtual base 'class1' to 'class2' could fail in some contexts #/we4619 # #pragma warning: there is no warning number 'number'. Unfortunately some versions of MSVC 16.X dont filter this warning coming from external headers and Qt has a bad warning in QtCore/qvector.h(340,12) /we4777 # 'function' : format string 'string' requires an argument of type 'type1', but variadic argument number has type 'type2 /we5031 # #pragma warning(pop): likely mismatch, popping warning state pushed in different file From 2e79451280ccc6a8518563095402a5f5dad3cec5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:50:26 -0700 Subject: [PATCH 006/274] Fixes AzCore for MSVC Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/Component/ComponentApplication.cpp | 2 ++ .../AzCore/AzCore/Debug/AssetTrackingTypes.h | 3 ++ .../AzCore/Debug/AssetTrackingTypesImpl.h | 5 +++ .../AzCore/AzCore/Debug/BudgetTracker.h | 2 +- .../AzCore/Serialization/Json/MapSerializer.h | 4 ++- .../Settings/SettingsRegistryMergeUtils.cpp | 4 +++ .../AzCore/AzCore/UnitTest/TestTypes.h | 14 +++++--- .../AzCore/AzCore/std/string/regex.h | 2 +- .../StreamerConfiguration_Windows.cpp | 1 + .../AzCore/Tests/AssetJsonSerializerTests.cpp | 1 + .../AzCore/Tests/IO/Path/PathTests.cpp | 12 +------ Code/Framework/AzCore/Tests/Jobs.cpp | 20 +++++++++-- .../Tests/Math/FrustumPerformanceTests.cpp | 12 +++++-- .../Tests/Math/Matrix3x3PerformanceTests.cpp | 12 +++++-- .../Tests/Math/Matrix3x4PerformanceTests.cpp | 12 +++++-- .../Tests/Math/Matrix4x4PerformanceTests.cpp | 12 +++++-- .../AzCore/Tests/Math/ObbPerformanceTests.cpp | 13 +++++-- .../Tests/Math/PlanePerformanceTests.cpp | 26 +++++++++----- .../Tests/Math/QuaternionPerformanceTests.cpp | 12 +++++-- .../ShapeIntersectionPerformanceTests.cpp | 12 +++++-- .../Tests/Math/TransformPerformanceTests.cpp | 12 +++++-- .../Tests/Math/Vector2PerformanceTests.cpp | 12 +++++-- .../Tests/Math/Vector3PerformanceTests.cpp | 12 +++++-- .../Tests/Math/Vector4PerformanceTests.cpp | 12 +++++-- .../AzCore/Tests/Memory/HphaSchema.cpp | 25 +++++++++++--- .../IO/Streamer/StorageDriveTests_Windows.cpp | 34 ++++++++++++------- .../Json/ArraySerializerTests.cpp | 3 ++ .../Json/BasicContainerSerializerTests.cpp | 6 ++++ .../Json/BoolSerializerTests.cpp | 1 + .../Json/DoubleSerializerTests.cpp | 1 + .../Serialization/Json/MapSerializerTests.cpp | 2 ++ .../Json/SmartPointerSerializerTests.cpp | 7 +++- .../Json/TupleSerializerTests.cpp | 5 +++ .../Json/UnorderedSetSerializerTests.cpp | 3 ++ .../AzCore/Tests/SettingsRegistryTests.cpp | 7 ++++ Code/Framework/AzCore/Tests/TaskTests.cpp | 24 +++++++++++-- 36 files changed, 274 insertions(+), 73 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index c76156c006..168807cd97 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -1249,6 +1249,8 @@ namespace AZ return AZ::SettingsRegistryInterface::VisitResponse::Continue; } + + using SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value) override { // By default the auto load option is true diff --git a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h index c46edbb80e..f538c516c3 100644 --- a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h +++ b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h @@ -86,6 +86,7 @@ namespace AZ class AssetTreeNodeBase { public: + virtual ~AssetTreeNodeBase() = default; virtual const AssetPrimaryInfo* GetAssetPrimaryInfo() const = 0; virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) = 0; }; @@ -94,6 +95,7 @@ namespace AZ class AssetTreeBase { public: + virtual ~AssetTreeBase() = default; virtual AssetTreeNodeBase& GetRoot() = 0; }; @@ -101,6 +103,7 @@ namespace AZ class AssetAllocationTableBase { public: + virtual ~AssetAllocationTableBase() = default; virtual AssetTreeNodeBase* FindAllocation(void* ptr) const = 0; }; } diff --git a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h index 7916a442b5..eac809c406 100644 --- a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h +++ b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h @@ -31,6 +31,8 @@ namespace AZ { } + ~AssetTreeNode() override = default; + const AssetPrimaryInfo* GetAssetPrimaryInfo() const override { return m_primaryinfo; @@ -67,6 +69,8 @@ namespace AZ class AssetTree : public AssetTreeBase { public: + ~AssetTree() override = default; + AssetTreeNodeBase& GetRoot() override { return m_rootAssets; @@ -99,6 +103,7 @@ namespace AZ AllocationTable(mutex_type& mutex) : m_mutex(mutex) { } + ~AllocationTable() override = default; AssetTreeNodeBase* FindAllocation(void* ptr) const override { diff --git a/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h b/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h index 1357bb5870..34d8510349 100644 --- a/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h +++ b/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h @@ -19,7 +19,7 @@ namespace AZ::Debug class BudgetTracker { public: - AZ_RTTI(BudgetTracker, "{E14A746D-BFFE-4C02-90FB-4699B79864A5}"); + AZ_TYPE_INFO(BudgetTracker, "{E14A746D-BFFE-4C02-90FB-4699B79864A5}"); static Budget* GetBudgetFromEnvironment(const char* budgetName, uint32_t crc); ~BudgetTracker(); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h index e0d2635fc3..937c8389ff 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/MapSerializer.h @@ -46,7 +46,8 @@ namespace AZ public: AZ_RTTI(JsonUnorderedMapSerializer, "{EF4478D3-1820-4FDB-A7B7-C9711EB41602}", JsonMapSerializer); AZ_CLASS_ALLOCATOR_DECL; - + + using JsonMapSerializer::Store; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; }; @@ -63,6 +64,7 @@ namespace AZ const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement, const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context) override; + using JsonMapSerializer::Store; JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context) override; }; diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index cb666a7c02..28e5a68e0b 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -78,6 +78,7 @@ namespace AZ::Internal struct EnginePathsVisitor : public AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit( [[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override @@ -355,6 +356,7 @@ namespace AZ::SettingsRegistryMergeUtils : m_settingsSpecialization{ specializations } {} + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit([[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, bool value) override { @@ -761,6 +763,7 @@ namespace AZ::SettingsRegistryMergeUtils return SettingsRegistryInterface::VisitResponse::Continue; } + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view, [[maybe_unused]] AZStd::string_view valueName, SettingsRegistryInterface::Type, AZStd::string_view value) override { if (processingSourcePathKey) @@ -896,6 +899,7 @@ namespace AZ::SettingsRegistryMergeUtils struct CommandLineVisitor : AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type , AZStd::string_view value) override { diff --git a/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h b/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h index c3e3f5210a..71a4e5082b 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h @@ -130,17 +130,23 @@ namespace UnitTest , public AllocatorsBase { public: - // Bring in both const and non-const SetUp and TearDown function into scope to resolve warning 4266 - // no override available for virtual member function from base 'benchmark::Fixture'; function is hidden - using ::benchmark::Fixture::SetUp, ::benchmark::Fixture::TearDown; - //Benchmark interface + void SetUp(const ::benchmark::State& st) override + { + AZ_UNUSED(st); + SetupAllocator(); + } void SetUp(::benchmark::State& st) override { AZ_UNUSED(st); SetupAllocator(); } + void TearDown(const ::benchmark::State& st) override + { + AZ_UNUSED(st); + TeardownAllocator(); + } void TearDown(::benchmark::State& st) override { AZ_UNUSED(st); diff --git a/Code/Framework/AzCore/AzCore/std/string/regex.h b/Code/Framework/AzCore/AzCore/std/string/regex.h index 2ca223937b..e20f67905c 100644 --- a/Code/Framework/AzCore/AzCore/std/string/regex.h +++ b/Code/Framework/AzCore/AzCore/std/string/regex.h @@ -1758,7 +1758,7 @@ namespace AZStd return (*this); } - ~basic_regex() + virtual ~basic_regex() { // destroy the object Clear(); } diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp index fe6d83b7a4..0a73da5a92 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/IO/Streamer/StreamerConfiguration_Windows.cpp @@ -267,6 +267,7 @@ namespace AZ::IO SettingsRegistryInterface::VisitResponse::Continue : SettingsRegistryInterface::VisitResponse::Skip; } + using SettingsRegistryInterface::Visitor::Visit; void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override { diff --git a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp index 2ca564681c..e968ee28fc 100644 --- a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp @@ -100,6 +100,7 @@ namespace JsonSerializationTests AZ::AllocatorInstance::Destroy(); } + using JsonSerializerConformityTestDescriptor>::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); diff --git a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp index 2fca03bc59..ea6f272e18 100644 --- a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp +++ b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp @@ -866,18 +866,8 @@ namespace UnitTest namespace Benchmark { class PathBenchmarkFixture - : public ::benchmark::Fixture - , public ::UnitTest::AllocatorsBase + : public ::UnitTest::AllocatorsBenchmarkFixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override - { - ::UnitTest::AllocatorsBase::SetupAllocator(); - } - void TearDown([[maybe_unused]] const ::benchmark::State& state) override - { - ::UnitTest::AllocatorsBase::TeardownAllocator(); - } protected: AZStd::fixed_vector m_appendPaths{ "foo", "bar", "baz", "bazzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", "boo/bar/base", "C:\\path\\to\\O3DE", "C", "\\\\", "/", R"(test\\path/with\mixed\separators)" }; diff --git a/Code/Framework/AzCore/Tests/Jobs.cpp b/Code/Framework/AzCore/Tests/Jobs.cpp index b63e139dd0..041f4970d1 100644 --- a/Code/Framework/AzCore/Tests/Jobs.cpp +++ b/Code/Framework/AzCore/Tests/Jobs.cpp @@ -1704,7 +1704,7 @@ namespace Benchmark static const AZ::u32 MEDIUM_NUMBER_OF_JOBS = 1024; static const AZ::u32 LARGE_NUMBER_OF_JOBS = 16384; - void SetUp([[maybe_unused]] ::benchmark::State& state) override + void internalSetUp() { AllocatorInstance::Create(); AllocatorInstance::Create(); @@ -1749,8 +1749,16 @@ namespace Benchmark return randomDepthDistribution(randomDepthGenerator); }); } + void SetUp(::benchmark::State&) override + { + internalSetUp(); + } + void SetUp(const ::benchmark::State&) override + { + internalSetUp(); + } - void TearDown([[maybe_unused]] ::benchmark::State& state) override + void internalTearDown() { JobContext::SetGlobalContext(nullptr); @@ -1763,6 +1771,14 @@ namespace Benchmark AllocatorInstance::Destroy(); AllocatorInstance::Destroy(); } + void TearDown(::benchmark::State&) override + { + internalTearDown(); + } + void TearDown(const ::benchmark::State&) override + { + internalTearDown(); + } protected: inline void RunCalculatePiJob(AZ::s32 depth, AZ::s8 priority) diff --git a/Code/Framework/AzCore/Tests/Math/FrustumPerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/FrustumPerformanceTests.cpp index b132c9f726..e26d896e5a 100644 --- a/Code/Framework/AzCore/Tests/Math/FrustumPerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/FrustumPerformanceTests.cpp @@ -19,8 +19,7 @@ namespace Benchmark class BM_MathFrustum : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_testFrustum = AZ::Frustum(AZ::ViewFrustumAttributes(AZ::Transform::CreateIdentity(), 1.0f, 2.0f * atanf(0.5f), 10.0f, 90.0f)); @@ -40,6 +39,15 @@ namespace Benchmark return data; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct Data { diff --git a/Code/Framework/AzCore/Tests/Math/Matrix3x3PerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix3x3PerformanceTests.cpp index f345f26d06..918673d475 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix3x3PerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix3x3PerformanceTests.cpp @@ -23,8 +23,7 @@ namespace Benchmark class BM_MathMatrix3x3 : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_testDataArray.resize(1000); @@ -44,6 +43,15 @@ namespace Benchmark return testData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct TestData { diff --git a/Code/Framework/AzCore/Tests/Math/Matrix3x4PerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix3x4PerformanceTests.cpp index 9aed29005d..63ddefdd2c 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix3x4PerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix3x4PerformanceTests.cpp @@ -21,8 +21,7 @@ namespace Benchmark class BM_MathMatrix3x4 : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const::benchmark::State& state) override + void internalSetUp() { m_testDataArray.resize(1000); @@ -58,6 +57,15 @@ namespace Benchmark return testData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct TestData { diff --git a/Code/Framework/AzCore/Tests/Math/Matrix4x4PerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix4x4PerformanceTests.cpp index 90865064c8..21f440c3a1 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix4x4PerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix4x4PerformanceTests.cpp @@ -20,8 +20,7 @@ namespace Benchmark class BM_MathMatrix4x4 : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_testDataArray.resize(1000); @@ -41,6 +40,15 @@ namespace Benchmark return testData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct TestData { diff --git a/Code/Framework/AzCore/Tests/Math/ObbPerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/ObbPerformanceTests.cpp index 8463758fa5..d1e8ac2225 100644 --- a/Code/Framework/AzCore/Tests/Math/ObbPerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/ObbPerformanceTests.cpp @@ -19,8 +19,7 @@ namespace Benchmark class BM_MathObb : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_position.Set(1.0f, 2.0f, 3.0f); m_rotation = AZ::Quaternion::CreateRotationZ(AZ::Constants::QuarterPi); @@ -28,6 +27,16 @@ namespace Benchmark m_obb = AZ::Obb::CreateFromPositionRotationAndHalfLengths(m_position, m_rotation, m_halfLengths); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + AZ::Obb m_obb; AZ::Vector3 m_position; AZ::Quaternion m_rotation; diff --git a/Code/Framework/AzCore/Tests/Math/PlanePerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/PlanePerformanceTests.cpp index c23ded582c..e066207635 100644 --- a/Code/Framework/AzCore/Tests/Math/PlanePerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/PlanePerformanceTests.cpp @@ -18,14 +18,7 @@ namespace Benchmark class BM_MathPlane : public benchmark::Fixture { - public: - BM_MathPlane() - { - const unsigned int seed = 1; - rng = std::mt19937_64(seed); - } - - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { for (int i = 0; i < m_numIters; ++i) { @@ -39,7 +32,7 @@ namespace Benchmark m_distance = unif(rng); m_dists.push_back(m_distance); - //set these differently so they don't overlap with same values as other vectors + // set these differently so they don't overlap with same values as other vectors m_normal = AZ::Vector3(unif(rng), unif(rng), unif(rng)); m_normal.Normalize(); m_distance = unif(rng); @@ -47,6 +40,21 @@ namespace Benchmark m_planes.push_back(m_plane); } } + public: + BM_MathPlane() + { + const unsigned int seed = 1; + rng = std::mt19937_64(seed); + } + + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } AZ::Plane m_plane; AZ::Vector3 m_normal; diff --git a/Code/Framework/AzCore/Tests/Math/QuaternionPerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/QuaternionPerformanceTests.cpp index 6f5a23d027..486a33ba67 100644 --- a/Code/Framework/AzCore/Tests/Math/QuaternionPerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/QuaternionPerformanceTests.cpp @@ -17,8 +17,7 @@ namespace Benchmark class BM_MathQuaternion : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_quatDataArray.resize(1000); @@ -42,6 +41,15 @@ namespace Benchmark return quatData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct QuatData { diff --git a/Code/Framework/AzCore/Tests/Math/ShapeIntersectionPerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/ShapeIntersectionPerformanceTests.cpp index b088330302..ecab1717b2 100644 --- a/Code/Framework/AzCore/Tests/Math/ShapeIntersectionPerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/ShapeIntersectionPerformanceTests.cpp @@ -35,8 +35,7 @@ namespace Benchmark class BM_MathShapeIntersection : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_testDataArray.resize(1000); @@ -58,6 +57,15 @@ namespace Benchmark return testData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct TestData { diff --git a/Code/Framework/AzCore/Tests/Math/TransformPerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/TransformPerformanceTests.cpp index 193535c020..dde0192ef9 100644 --- a/Code/Framework/AzCore/Tests/Math/TransformPerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/TransformPerformanceTests.cpp @@ -22,8 +22,7 @@ namespace Benchmark class BM_MathTransform : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_testDataArray.resize(1000); @@ -51,6 +50,15 @@ namespace Benchmark return testData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct TestData { diff --git a/Code/Framework/AzCore/Tests/Math/Vector2PerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/Vector2PerformanceTests.cpp index e8506890aa..3ab306ff66 100644 --- a/Code/Framework/AzCore/Tests/Math/Vector2PerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Vector2PerformanceTests.cpp @@ -19,8 +19,7 @@ namespace Benchmark class BM_MathVector2 : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_vecDataArray.resize(1000); @@ -37,6 +36,15 @@ namespace Benchmark return vecData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct VecData { diff --git a/Code/Framework/AzCore/Tests/Math/Vector3PerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/Vector3PerformanceTests.cpp index 27fa01ae95..5f33730bca 100644 --- a/Code/Framework/AzCore/Tests/Math/Vector3PerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Vector3PerformanceTests.cpp @@ -19,8 +19,7 @@ namespace Benchmark class BM_MathVector3 : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_vecDataArray.resize(1000); @@ -37,6 +36,15 @@ namespace Benchmark return vecData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct VecData { diff --git a/Code/Framework/AzCore/Tests/Math/Vector4PerformanceTests.cpp b/Code/Framework/AzCore/Tests/Math/Vector4PerformanceTests.cpp index 4a0bcb49d2..f12851b1ed 100644 --- a/Code/Framework/AzCore/Tests/Math/Vector4PerformanceTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Vector4PerformanceTests.cpp @@ -19,8 +19,7 @@ namespace Benchmark class BM_MathVector4 : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { m_vecDataArray.resize(1000); @@ -38,6 +37,15 @@ namespace Benchmark return vecData; }); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } struct VecData { diff --git a/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp b/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp index aaf4ce1811..85dd79931d 100644 --- a/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp +++ b/Code/Framework/AzCore/Tests/Memory/HphaSchema.cpp @@ -120,19 +120,34 @@ namespace Benchmark class HphaSchemaBenchmarkFixture : public ::benchmark::Fixture { - public: - void SetUp(const ::benchmark::State& state) override + void internalSetUp() { - AZ_UNUSED(state); AZ::AllocatorInstance::Create(); } - void TearDown(const ::benchmark::State& state) override + void internalTearDown() { - AZ_UNUSED(state); AZ::AllocatorInstance::Destroy(); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + static void BM_Allocations(benchmark::State& state, const AllocationSizeArray& allocationArray) { AZStd::vector allocations; diff --git a/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp b/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp index 6d572a02a3..51fa68cc2b 100644 --- a/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp +++ b/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp @@ -1155,6 +1155,21 @@ namespace Benchmark { class StorageDriveWindowsFixture : public benchmark::Fixture { + void internalTearDown() + { + using namespace AZ::IO; + + AZStd::string temp; + m_absolutePath.swap(temp); + + delete m_streamer; + + SystemFile::Delete(TestFileName); + + AZ::IO::FileIOBase::SetInstance(nullptr); + AZ::IO::FileIOBase::SetInstance(m_previousFileIO); + delete m_fileIO; + } public: constexpr static const char* TestFileName = "StreamerBenchmark.bin"; constexpr static size_t FileSize = 64_mib; @@ -1197,20 +1212,13 @@ namespace Benchmark } } - void TearDown([[maybe_unused]] const ::benchmark::State& state) override + void TearDown(const benchmark::State&) override { - using namespace AZ::IO; - - AZStd::string temp; - m_absolutePath.swap(temp); - - delete m_streamer; - - SystemFile::Delete(TestFileName); - - AZ::IO::FileIOBase::SetInstance(nullptr); - AZ::IO::FileIOBase::SetInstance(m_previousFileIO); - delete m_fileIO; + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); } void RepeatedlyReadFile(benchmark::State& state) diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp index e410ba9ca4..8582453683 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/ArraySerializerTests.cpp @@ -35,6 +35,7 @@ namespace JsonSerializationTests features.m_fixedSizeArray = true; } + using JsonSerializerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -243,6 +244,7 @@ namespace JsonSerializationTests ])"; } + using ArraySerializerTestDescriptionBase>::Reflect; void Reflect(AZStd::unique_ptr& context) override { Base::Reflect(context); @@ -299,6 +301,7 @@ namespace JsonSerializationTests AZ::JsonArraySerializer m_serializer; public: + using BaseJsonSerializerFixture::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& context) override { context->RegisterGenericType(); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp index 3bc574c2ce..4a6a8e9e8a 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/BasicContainerSerializerTests.cpp @@ -60,6 +60,7 @@ namespace JsonSerializationTests return "[188, 288, 388]"; } + using BasicContainerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -133,6 +134,7 @@ namespace JsonSerializationTests return "[188, 288, 388]"; } + using BasicContainerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -225,6 +227,7 @@ namespace JsonSerializationTests features.m_supportsPartialInitialization = true; } + using BasicContainerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { SimpleClass::Reflect(context, true); @@ -291,6 +294,7 @@ namespace JsonSerializationTests using Container = AZStd::vector; using BaseClassContainer = AZStd::vector>; + using JsonBasicContainerSerializerTests::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { SimpleClass::Reflect(serializeContext, true); @@ -352,6 +356,7 @@ namespace JsonSerializationTests static constexpr size_t ContainerSize = 4; using Container = AZStd::fixed_vector; + using JsonBasicContainerSerializerTests::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { serializeContext->RegisterGenericType(); @@ -387,6 +392,7 @@ namespace JsonSerializationTests public: using Set = AZStd::set; + using JsonBasicContainerSerializerTests::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { serializeContext->RegisterGenericType(); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp index a670a2a6e1..e9bb404ba8 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/BoolSerializerTests.cpp @@ -83,6 +83,7 @@ namespace JsonSerializationTests BaseJsonSerializerFixture::TearDown(); } + using BaseJsonSerializerFixture::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { serializeContext->Class() diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp index 76aaae393d..53eb855a63 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/DoubleSerializerTests.cpp @@ -95,6 +95,7 @@ namespace JsonSerializationTests BaseJsonSerializerFixture::TearDown(); } + using BaseJsonSerializerFixture::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { serializeContext->Class() diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp index 4979df04be..7ffe3ffee0 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/MapSerializerTests.cpp @@ -44,6 +44,7 @@ namespace JsonSerializationTests features.m_supportsPartialInitialization = false; } + using JsonSerializerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -247,6 +248,7 @@ namespace JsonSerializationTests features.m_supportsPartialInitialization = true; } + using MapBaseTestDescription, Serializer>::Reflect; void Reflect(AZStd::unique_ptr& context) override { SimpleClass::Reflect(context, true); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp index 43dc1a85d9..d89d9bfb33 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp @@ -33,6 +33,7 @@ namespace JsonSerializationTests return AZStd::make_shared(); } + using JsonSerializerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -102,6 +103,7 @@ namespace JsonSerializationTests return *lhs == *rhs; } + using Base::Reflect; void Reflect(AZStd::unique_ptr& context) override { SimpleClass::Reflect(context, true); @@ -176,6 +178,7 @@ namespace JsonSerializationTests features.m_supportsPartialInitialization = true; } + using SmartPointerBaseTestDescription>::Reflect; void Reflect(AZStd::unique_ptr& context) override { SimpleInheritence::Reflect(context, true); @@ -340,6 +343,7 @@ namespace JsonSerializationTests features.m_supportsPartialInitialization = true; } + using SmartPointerBaseTestDescription>::Reflect; void Reflect(AZStd::unique_ptr& context) override { MultipleInheritence::Reflect(context, true); @@ -513,7 +517,8 @@ namespace JsonSerializationTests public: using SmartPointer = typename SmartPointerSimpleDerivedClassTestDescription::SmartPointer; using InstanceSmartPointer = AZStd::shared_ptr; - + + using BaseJsonSerializerFixture::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& context) override { m_description.Reflect(context); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp index ff0fbcc5a6..cfd844f3f5 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TupleSerializerTests.cpp @@ -72,6 +72,7 @@ namespace JsonSerializationTests TupleSerializerTestsInternal::ConfigureFeatures(features); } + using JsonSerializerConformityTestDescriptor>::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->Class()->Field("pair", &PairPlaceholder::m_pair); @@ -126,6 +127,7 @@ namespace JsonSerializationTests TupleSerializerTestsInternal::ConfigureFeatures(features); } + using JsonSerializerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -344,6 +346,7 @@ namespace JsonSerializationTests features.m_enableNewInstanceTests = false; } + using JsonSerializerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->Class() @@ -477,6 +480,7 @@ namespace JsonSerializationTests features.m_typeToInject = rapidjson::kNullType; } + using JsonSerializerConformityTestDescriptor::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -535,6 +539,7 @@ namespace JsonSerializationTests BaseJsonSerializerFixture::TearDown(); } + using BaseJsonSerializerFixture::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { SimpleClass::Reflect(serializeContext, true); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp index 17902b6900..f4a1f48dc5 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/UnorderedSetSerializerTests.cpp @@ -54,6 +54,7 @@ namespace JsonSerializationTests features.m_supportsPartialInitialization = false; } + using JsonSerializerConformityTestDescriptor>::Reflect; void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -108,6 +109,7 @@ namespace JsonSerializationTests context->RegisterGenericType(); } + using JsonSerializerConformityTestDescriptor::Reflect; bool AreEqual(const MultiSet& lhs, const MultiSet& rhs) override { return @@ -139,6 +141,7 @@ namespace JsonSerializationTests BaseJsonSerializerFixture::TearDown(); } + using BaseJsonSerializerFixture::RegisterAdditional; void RegisterAdditional(AZStd::unique_ptr& serializeContext) override { serializeContext->RegisterGenericType(); diff --git a/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp b/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp index 61f93fb860..8485747991 100644 --- a/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp +++ b/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp @@ -423,6 +423,8 @@ namespace SettingsRegistryTests struct : public AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; + using ValueType [[maybe_unused]] = typename SettingsType::ValueType; void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type type, ValueType value) override { @@ -452,6 +454,8 @@ namespace SettingsRegistryTests struct : public AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; + using ValueType [[maybe_unused]] = typename SettingsType::ValueType; void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type type, ValueType value) override { @@ -482,6 +486,7 @@ namespace SettingsRegistryTests struct : public AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit([[maybe_unused]] AZStd::string_view path, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type type, AZ::s64 value) override { EXPECT_EQ(AZ::SettingsRegistryInterface::Type::Integer, type); @@ -517,6 +522,8 @@ namespace SettingsRegistryTests EXPECT_TRUE(path.ends_with(valueName)); return AZ::SettingsRegistryInterface::VisitResponse::Continue; } + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type , AZStd::string_view)override { EXPECT_TRUE(path.ends_with(valueName)); diff --git a/Code/Framework/AzCore/Tests/TaskTests.cpp b/Code/Framework/AzCore/Tests/TaskTests.cpp index f65dffcd99..e743ab6643 100644 --- a/Code/Framework/AzCore/Tests/TaskTests.cpp +++ b/Code/Framework/AzCore/Tests/TaskTests.cpp @@ -551,19 +551,37 @@ namespace Benchmark { class TaskGraphBenchmarkFixture : public ::benchmark::Fixture { - public: - void SetUp(benchmark::State&) override + void internalSetUp() { executor = new TaskExecutor; graph = new TaskGraph; } - void TearDown(benchmark::State&) override + void internalTearDown() { delete graph; delete executor; } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + TaskDescriptor descriptors[4] = { { "critical", "benchmark", TaskPriority::CRITICAL }, { "high", "benchmark", TaskPriority::HIGH }, { "medium", "benchmark", TaskPriority::MEDIUM }, From b52fab0c0c6424832af294dc6f703296ac393598 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 14:57:08 -0700 Subject: [PATCH 007/274] fixes AzFramework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Entity/EntityDebugDisplayBus.h | 2 +- .../AzFramework/AzFramework/Gem/GemInfo.cpp | 1 + .../UnitTest/TestDebugDisplayRequests.h | 4 ++++ .../Tests/OctreePerformanceTests.cpp | 24 ++++++++++++++++--- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h index fddaddf303..0a4e1e01ae 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityDebugDisplayBus.h @@ -102,7 +102,7 @@ namespace AzFramework virtual void PopMatrix() {} protected: - ~DebugDisplayRequests() = default; + virtual ~DebugDisplayRequests() = default; }; /// Inherit from DebugDisplayRequestBus::Handler to implement the DebugDisplayRequests interface. diff --git a/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.cpp b/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.cpp index 62a6334b5d..a7c6b18061 100644 --- a/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.cpp +++ b/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.cpp @@ -34,6 +34,7 @@ namespace AzFramework { } + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override { diff --git a/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.h b/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.h index d4c6992057..72b15c1a69 100644 --- a/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.h +++ b/Code/Framework/AzFramework/AzFramework/UnitTest/TestDebugDisplayRequests.h @@ -19,6 +19,8 @@ namespace UnitTest { public: TestDebugDisplayRequests(); + ~TestDebugDisplayRequests() override = default; + const AZStd::vector& GetPoints() const; void ClearPoints(); //! Returns the AABB of the points generated from received draw calls. @@ -27,7 +29,9 @@ namespace UnitTest // DebugDisplayRequests ... void DrawWireBox(const AZ::Vector3& min, const AZ::Vector3& max) override; void DrawSolidBox(const AZ::Vector3& min, const AZ::Vector3& max) override; + using AzFramework::DebugDisplayRequests::DrawWireQuad; void DrawWireQuad(float width, float height) override; + using AzFramework::DebugDisplayRequests::DrawQuad; void DrawQuad(float width, float height) override; void DrawTriangles(const AZStd::vector& vertices, const AZ::Color& color) override; void DrawTrianglesIndexed(const AZStd::vector& vertices, const AZStd::vector& indices, const AZ::Color& color) override; diff --git a/Code/Framework/AzFramework/Tests/OctreePerformanceTests.cpp b/Code/Framework/AzFramework/Tests/OctreePerformanceTests.cpp index 79332d638b..64fba61e2c 100644 --- a/Code/Framework/AzFramework/Tests/OctreePerformanceTests.cpp +++ b/Code/Framework/AzFramework/Tests/OctreePerformanceTests.cpp @@ -20,8 +20,7 @@ namespace Benchmark class BM_Octree : public benchmark::Fixture { - public: - void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { // Create the SystemAllocator if not available if (!AZ::AllocatorInstance::IsReady()) @@ -72,7 +71,7 @@ namespace Benchmark }); } - void TearDown([[maybe_unused]] const ::benchmark::State& state) override + void internalTearDown() { m_octreeSystemComponent->DestroyVisibilityScene(m_visScene); delete m_octreeSystemComponent; @@ -91,6 +90,25 @@ namespace Benchmark } } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + void InsertEntries(uint32_t entryCount) { for (uint32_t i = 0; i < entryCount; ++i) From bf801da84c5bcc8b6a9e662dcce0771bf951dc5c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 15:08:08 -0700 Subject: [PATCH 008/274] fixes AzNetworking Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h index 15d4cfa10c..0243395d1e 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h @@ -30,6 +30,7 @@ namespace AzNetworking { public: + virtual ~UdpFragmentQueue() = default; //! Updates the UdpFragmentQueue timeout queue. void Update(); From 28795c8f5c21aec7576726980a6ea2c92f5b9a5b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 15:08:23 -0700 Subject: [PATCH 009/274] Fixes AzQtComponents Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h index 702544eea6..2896fc51eb 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Style.h @@ -137,8 +137,10 @@ namespace AzQtComponents int pixelMetric(QStyle::PixelMetric metric, const QStyleOption* option, const QWidget* widget) const override; + using QProxyStyle::polish; void polish(QApplication* application) override; void polish(QWidget* widget) override; + using QProxyStyle::unpolish; void unpolish(QWidget* widget) override; QPalette standardPalette() const override; From 2f71b28b9765239ba7ff4e6892356d42565839a3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 15:08:43 -0700 Subject: [PATCH 010/274] Fixes AzToolsFramework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Application/EditorEntityManager.h | 2 +- .../AzToolsFramework/Asset/AssetUtils.cpp | 1 + .../Commands/PreemptiveUndoCache.h | 2 +- .../AzToolsFramework/Prefab/PrefabUndoCache.h | 2 ++ .../Benchmark/PrefabBenchmarkFixture.cpp | 4 ++-- .../Prefab/Benchmark/PrefabBenchmarkFixture.h | 23 +++++++++++++++---- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/EditorEntityManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/EditorEntityManager.h index f74b971512..5786cc3fbc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/EditorEntityManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/EditorEntityManager.h @@ -17,7 +17,7 @@ namespace AzToolsFramework : public EditorEntityAPI { public: - ~EditorEntityManager(); + virtual ~EditorEntityManager(); void Start(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp index 6e55d9f97c..139bbb563c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Asset/AssetUtils.cpp @@ -97,6 +97,7 @@ namespace AzToolsFramework::AssetUtils struct EnabledPlatformsVisitor : AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override; AZStd::vector m_enabledPlatforms; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Commands/PreemptiveUndoCache.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Commands/PreemptiveUndoCache.h index ed36a4458e..85947f56f6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Commands/PreemptiveUndoCache.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Commands/PreemptiveUndoCache.h @@ -34,7 +34,7 @@ namespace AzToolsFramework static PreemptiveUndoCache* Get(); PreemptiveUndoCache(); - ~PreemptiveUndoCache(); + virtual ~PreemptiveUndoCache(); void RegisterToUndoCacheInterface(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoCache.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoCache.h index b5a8cf9e3a..43cb7f0d2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoCache.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoCache.h @@ -32,6 +32,8 @@ namespace AzToolsFramework public: AZ_CLASS_ALLOCATOR(PrefabUndoCache, AZ::SystemAllocator, 0); + virtual ~PrefabUndoCache() = default; + void Initialize(); void Destroy(); diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp index 9925d5bff3..e5ce22e13a 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.cpp @@ -50,7 +50,7 @@ namespace Benchmark SetupPrefabSystem(); } - void BM_Prefab::SetUp(::benchmark::State & state) + void BM_Prefab::internalSetUp(const benchmark::State& state) { AZ::Debug::TraceMessageBus::Handler::BusConnect(); @@ -59,7 +59,7 @@ namespace Benchmark SetupPrefabSystem(); } - void BM_Prefab::TearDown(::benchmark::State & state) + void BM_Prefab::internalTearDown(const benchmark::State& state) { m_paths = {}; diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.h b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.h index a55d5c7789..bd4b20cd77 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.h +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/Benchmark/PrefabBenchmarkFixture.h @@ -24,12 +24,27 @@ namespace Benchmark : public UnitTest::AllocatorsBenchmarkFixture , public UnitTest::TraceBusRedirector { + void internalSetUp(const benchmark::State& state); + void internalTearDown(const benchmark::State& state); + protected: - using ::benchmark::Fixture::SetUp; - using ::benchmark::Fixture::TearDown; + void SetUp(const benchmark::State& state) override + { + internalSetUp(state); + } + void SetUp(benchmark::State& state) override + { + internalSetUp(state); + } - void SetUp(::benchmark::State& state) override; - void TearDown(::benchmark::State& state) override; + void TearDown(const benchmark::State& state) override + { + internalTearDown(state); + } + void TearDown(benchmark::State& state) override + { + internalTearDown(state); + } AZ::Entity* CreateEntity( const char* entityName, From 40d2fe61a14c9882b6d4bd550159762f2f48e570 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:35:39 -0700 Subject: [PATCH 011/274] Gems/Atom Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Common/Code/Source/Material/DrawListFunctor.h | 1 + .../Code/Source/Material/DrawListFunctorSourceData.h | 1 + .../Material/SubsurfaceTransmissionParameterFunctor.h | 1 + .../SubsurfaceTransmissionParameterFunctorSourceData.h | 1 + .../Common/Code/Source/Material/Transform2DFunctor.h | 1 + .../Code/Source/Material/Transform2DFunctorSourceData.h | 1 + .../RHI/Code/Include/Atom/RHI/PipelineStateDescriptor.h | 9 ++++----- .../RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h | 2 ++ Gems/Atom/RPI/Code/Tests/Common/SerializeTester.h | 3 ++- Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp | 6 +++--- .../RPI/Code/Tests/Material/MaterialFunctorTests.cpp | 3 +++ .../Material/MaterialPropertyValueSourceDataTests.cpp | 1 + .../RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp | 2 ++ .../Code/Tests/Material/MaterialTypeSourceDataTests.cpp | 6 ++++++ 14 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctor.h index eb4bb0ab00..a21fb963e9 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctor.h @@ -26,6 +26,7 @@ namespace AZ static void Reflect(ReflectContext* context); + using RPI::MaterialFunctor::Process; void Process(RuntimeContext& context) override; private: diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctorSourceData.h index 58df14a812..ba5e174101 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctorSourceData.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/DrawListFunctorSourceData.h @@ -27,6 +27,7 @@ namespace AZ static void Reflect(ReflectContext* context); + using RPI::MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override; private: diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h index 10be4a0c47..e412687947 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctor.h @@ -26,6 +26,7 @@ namespace AZ static void Reflect(ReflectContext* context); + using RPI::MaterialFunctor::Process; void Process(RuntimeContext& context) override; private: diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h index c4f07c549d..9d074551c3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/SubsurfaceTransmissionParameterFunctorSourceData.h @@ -25,6 +25,7 @@ namespace AZ static void Reflect(AZ::ReflectContext* context); + using AZ::RPI::MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override; private: diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctor.h b/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctor.h index bee24d90b7..2ef5af6913 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctor.h @@ -34,6 +34,7 @@ namespace AZ static void Reflect(ReflectContext* context); + using RPI::MaterialFunctor::Process; void Process(RuntimeContext& context) override; private: diff --git a/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctorSourceData.h b/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctorSourceData.h index ecac071f94..db7e65fedc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctorSourceData.h +++ b/Gems/Atom/Feature/Common/Code/Source/Material/Transform2DFunctorSourceData.h @@ -25,6 +25,7 @@ namespace AZ static void Reflect(AZ::ReflectContext* context); + using AZ::RPI::MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override; private: diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/PipelineStateDescriptor.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/PipelineStateDescriptor.h index 63f0cb3822..83ab3cb584 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/PipelineStateDescriptor.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/PipelineStateDescriptor.h @@ -44,7 +44,7 @@ namespace AZ /// Returns the hash of the pipeline state descriptor contents. virtual HashValue64 GetHash() const = 0; - virtual bool operator == (const PipelineStateDescriptor& rhs) const; + bool operator == (const PipelineStateDescriptor& rhs) const; /// The pipeline layout describing the shader resource bindings. ConstPtr m_pipelineLayoutDescriptor = nullptr; @@ -77,8 +77,7 @@ namespace AZ /// Computes the hash value for this descriptor. HashValue64 GetHash() const override; - - virtual bool operator == (const PipelineStateDescriptorForDispatch& rhs) const; + bool operator == (const PipelineStateDescriptorForDispatch& rhs) const; /// The compute function containing byte code to compile. ConstPtr m_computeFunction; @@ -102,7 +101,7 @@ namespace AZ /// Computes the hash value for this descriptor. HashValue64 GetHash() const override; - virtual bool operator == (const PipelineStateDescriptorForDraw& rhs) const; + bool operator == (const PipelineStateDescriptorForDraw& rhs) const; /// [Required] The vertex function to compile. ConstPtr m_vertexFunction; @@ -135,7 +134,7 @@ namespace AZ //! Computes the hash value for this descriptor. HashValue64 GetHash() const override; - virtual bool operator == (const PipelineStateDescriptorForRayTracing& rhs) const; + bool operator == (const PipelineStateDescriptorForRayTracing& rhs) const; // The ray tracing shader byte code ConstPtr m_rayTracingFunction; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h index 5429dc13c0..c31f353adb 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/PassFilter.h @@ -53,6 +53,8 @@ namespace AZ //! Construct filter with only pass name. PassHierarchyFilter(const Name& passName); + virtual ~PassHierarchyFilter() = default; + //! Construct filter with pass name and its parents' names in the order of the hierarchy //! This means k-th element is always an ancestor of the (k-1)-th element. //! And the last element is the pass name. diff --git a/Gems/Atom/RPI/Code/Tests/Common/SerializeTester.h b/Gems/Atom/RPI/Code/Tests/Common/SerializeTester.h index 8422756837..df21d13fc0 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/SerializeTester.h +++ b/Gems/Atom/RPI/Code/Tests/Common/SerializeTester.h @@ -23,6 +23,7 @@ namespace UnitTest : m_serializeContext{serializeContext} , m_outStream{&m_buffer} {} + virtual ~SerializeTester() = default; // Serializes an object out to a the internal stream. Resets the stream with each call. virtual void SerializeOut(T* object, AZ::DataStream::StreamType streamType = AZ::DataStream::ST_XML); @@ -76,7 +77,7 @@ namespace UnitTest m_assetHandler = AZ::Data::AssetManager::Instance().GetHandler(AssetDataT::RTTI_Type()); } - ~AssetTester() = default; + virtual ~AssetTester() = default; void SerializeOut(AZ::Data::Asset assetToSave) { diff --git a/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp b/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp index 345637bfe5..86f97b96e9 100644 --- a/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp @@ -40,10 +40,9 @@ namespace AZ : public UnitTest::AssetTester { public: - StreamingImageAssetTester() - { + StreamingImageAssetTester() = default; + ~StreamingImageAssetTester() override = default; - } void SetAssetReady(Data::Asset& asset) override { asset->SetReady(); @@ -55,6 +54,7 @@ namespace AZ { public: ImageMipChainAssetTester() {} + ~ImageMipChainAssetTester() override = default; void SetAssetReady(Data::Asset& asset) override { diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp index 0c84484508..e1e8c91944 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp @@ -41,6 +41,7 @@ namespace UnitTest { } + using MaterialFunctor::Process; void Process(MaterialFunctor::RuntimeContext& context) override { m_processResult = context.SetShaderOptionValue(0, m_shaderOptionIndex, m_shaderOptionValue); @@ -65,6 +66,7 @@ namespace UnitTest public: MOCK_METHOD0(ProcessCalled, void()); + using MaterialFunctor::Process; void Process(RuntimeContext& context) override { ProcessCalled(); @@ -87,6 +89,7 @@ namespace UnitTest : public MaterialFunctorSourceData { public: + using MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override { Ptr functor = aznew PropertyDependencyTestFunctor; diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertyValueSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertyValueSourceDataTests.cpp index 231558bb99..5dde21ece1 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertyValueSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertyValueSourceDataTests.cpp @@ -142,6 +142,7 @@ namespace UnitTest AZStd::string m_propertyName; MaterialPropertyValueSourceData m_propertyValue; + using MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override { Ptr functor = aznew ValueFunctor; diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp index e11a049af2..b9774c84d9 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeAssetTests.cpp @@ -47,6 +47,7 @@ namespace UnitTest ; } + using AZ::RPI::MaterialFunctor::Process; void Process(AZ::RPI::MaterialFunctor::RuntimeContext& context) override { // This code isn't actually called in the unit test, but we include it here just to demonstrate what a real functor might look like. @@ -74,6 +75,7 @@ namespace UnitTest ; } + using AZ::RPI::MaterialFunctor::Process; void Process(AZ::RPI::MaterialFunctor::RuntimeContext& context) override { // This code isn't actually called in the unit test, but we include it here just to demonstrate what a real functor might look like. diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp index 5edf09b67d..179dc7c966 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTypeSourceDataTests.cpp @@ -70,6 +70,7 @@ namespace UnitTest } } + using AZ::RPI::MaterialFunctor::Process; void Process(AZ::RPI::MaterialFunctor::RuntimeContext& context) override { // This code isn't actually called in the unit test, but we include it here just to demonstrate what a real functor might look like. @@ -110,6 +111,7 @@ namespace UnitTest AZStd::string m_floatPropertyInputId; AZStd::string m_float3ShaderSettingOutputId; + using MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override { Ptr functor = aznew Splat3Functor; @@ -138,6 +140,7 @@ namespace UnitTest } } + using AZ::RPI::MaterialFunctor::Process; void Process(AZ::RPI::MaterialFunctor::RuntimeContext& context) override { // This code isn't actually called in the unit test, but we include it here just to demonstrate what a real functor might look like. @@ -174,6 +177,7 @@ namespace UnitTest m_shaderIndex{shaderIndex} {} + using MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor(const RuntimeContext& context) const override { Ptr functor = aznew EnableShaderFunctor; @@ -200,6 +204,7 @@ namespace UnitTest } } + using AZ::RPI::MaterialFunctor::Process; void Process(AZ::RPI::MaterialFunctor::RuntimeContext& context) override { // This code isn't actually called in the unit test, but we include it here just to demonstrate what a real functor might look like. @@ -232,6 +237,7 @@ namespace UnitTest return options; } + using MaterialFunctorSourceData::CreateFunctor; FunctorResult CreateFunctor([[maybe_unused]] const RuntimeContext& context) const override { Ptr functor = aznew SetShaderOptionFunctor; From 30a976baa3499a39d3cead0288275c3f43c67c6e Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:36:00 -0700 Subject: [PATCH 012/274] Gems/AWS Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AWSCore/Code/Source/Framework/JsonObjectHandler.cpp | 1 + .../Tests/Editor/Attribution/AWSAttributionServiceApiTest.cpp | 2 ++ Gems/AWSMetrics/Code/Tests/AWSMetricsServiceApiTest.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/Gems/AWSCore/Code/Source/Framework/JsonObjectHandler.cpp b/Gems/AWSCore/Code/Source/Framework/JsonObjectHandler.cpp index d041a97428..07df7806a9 100644 --- a/Gems/AWSCore/Code/Source/Framework/JsonObjectHandler.cpp +++ b/Gems/AWSCore/Code/Source/Framework/JsonObjectHandler.cpp @@ -19,6 +19,7 @@ namespace AWSCore { public: + virtual ~JsonReaderHandler() = default; using Ch = char; using SizeType = rapidjson::SizeType; diff --git a/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSAttributionServiceApiTest.cpp b/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSAttributionServiceApiTest.cpp index 9b90d5ca8d..4290713e5c 100644 --- a/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSAttributionServiceApiTest.cpp +++ b/Gems/AWSCore/Code/Tests/Editor/Attribution/AWSAttributionServiceApiTest.cpp @@ -21,6 +21,8 @@ namespace AWSCoreUnitTest : public AWSCore::JsonReader { public: + virtual ~JsonReaderMock() = default; + MOCK_METHOD0(Ignore, bool()); MOCK_METHOD1(Accept, bool(bool& target)); MOCK_METHOD1(Accept, bool(AZStd::string& target)); diff --git a/Gems/AWSMetrics/Code/Tests/AWSMetricsServiceApiTest.cpp b/Gems/AWSMetrics/Code/Tests/AWSMetricsServiceApiTest.cpp index bbfc206ab0..8844e727b6 100644 --- a/Gems/AWSMetrics/Code/Tests/AWSMetricsServiceApiTest.cpp +++ b/Gems/AWSMetrics/Code/Tests/AWSMetricsServiceApiTest.cpp @@ -19,6 +19,8 @@ namespace AWSMetrics : public AWSCore::JsonReader { public: + virtual ~JsonReaderMock() = default; + MOCK_METHOD0(Ignore, bool()); MOCK_METHOD1(Accept, bool(bool& target)); MOCK_METHOD1(Accept, bool(AZStd::string& target)); From 53c026b43e3463d99472ad1501ff58573ca3e11e Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:36:17 -0700 Subject: [PATCH 013/274] Gems/EditorPythonBindings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp index 8df196e7cb..cfb5d1db40 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonSystemComponent.cpp @@ -425,6 +425,8 @@ namespace EditorPythonBindings GetGemSourcePathsVisitor(AZ::SettingsRegistryInterface& settingsRegistry) : m_settingsRegistry(settingsRegistry) {} + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override { From 2acd05e595e655f54142a95ed8761ad56f852272 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:36:33 -0700 Subject: [PATCH 014/274] Gems/EMotionFX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.h | 3 +++ .../AnimGraph/ParameterEditor/RotationParameterEditor.cpp | 1 + .../AnimGraph/ParameterEditor/Vector3GizmoParameterEditor.cpp | 1 + Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h | 2 ++ Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h | 2 ++ Gems/EMotionFX/Code/Tests/Mocks/CommandManager.h | 2 +- Gems/EMotionFX/Code/Tests/Mocks/CommandSystemCommandManager.h | 2 ++ 7 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.h index 902354931a..2f9201ffa9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/ManipulatorCallbacks.h @@ -42,6 +42,7 @@ namespace EMStudio /** * update the actor instance. */ + using MCommon::ManipulatorCallback::Update; void Update(const AZ::Vector3& value) override; /** @@ -85,6 +86,7 @@ namespace EMStudio /** * update the actor instance. */ + using MCommon::ManipulatorCallback::Update; void Update(const AZ::Quaternion& value) override; /** @@ -125,6 +127,7 @@ namespace EMStudio /** * update the actor instance. */ + using MCommon::ManipulatorCallback::Update; void Update(const AZ::Vector3& value) override; /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/RotationParameterEditor.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/RotationParameterEditor.cpp index 805ef16b7d..18727f67d2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/RotationParameterEditor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/RotationParameterEditor.cpp @@ -142,6 +142,7 @@ namespace EMStudio , m_manipulatorCallback(manipulatorCallback) {} + using MCommon::ManipulatorCallback::Update; void Update(const AZ::Quaternion& value) override { // call the base class update function diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/Vector3GizmoParameterEditor.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/Vector3GizmoParameterEditor.cpp index cc97f9d979..7a24ece95a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/Vector3GizmoParameterEditor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterEditor/Vector3GizmoParameterEditor.cpp @@ -152,6 +152,7 @@ namespace EMStudio , m_manipulatorCallback(manipulatorCallback) {} + using MCommon::ManipulatorCallback::Update; void Update(const AZ::Vector3& value) override { // call the base class update function diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h index e04f19fa95..b2375180e6 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphInstance.h @@ -11,6 +11,8 @@ namespace EMotionFX class AnimGraphInstance { public: + virtual ~AnimGraphInstance() = default; + //void Output(Pose* outputPose); //void Start(); //void Stop(); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h index 9c73694d2a..065be187c8 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/AnimGraphNode.h @@ -14,6 +14,8 @@ namespace EMotionFX public: AZ_RTTI(AnimGraphNode, "{7F1C0E1D-4D32-4A6D-963C-20193EA28F95}", AnimGraphObject) + virtual ~AnimGraphNode() = default; + MOCK_CONST_METHOD1(CollectOutgoingConnections, void(AZStd::vector>& outConnections)); MOCK_CONST_METHOD2(CollectOutgoingConnections, void(AZStd::vector>& outConnections, const size_t portIndex)); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/CommandManager.h b/Gems/EMotionFX/Code/Tests/Mocks/CommandManager.h index 0146086f06..50a465f5da 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/CommandManager.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/CommandManager.h @@ -11,7 +11,7 @@ namespace MCore class CommandManager { public: - //virtual ~CommandManager(); + virtual ~CommandManager() = default; //bool ExecuteCommand(const char* command, AZStd::string& outCommandResult, bool addToHistory = true, Command** outExecutedCommand = nullptr, CommandLine* outExecutedParamters = nullptr, bool callFromCommandGroup = false, bool clearErrors = true, bool handleErrors = true); //bool ExecuteCommand(const AZStd::string& command, AZStd::string& outCommandResult, bool addToHistory = true, Command** outExecutedCommand = nullptr, CommandLine* outExecutedParamters = nullptr, bool callFromCommandGroup = false, bool clearErrors = true, bool handleErrors = true); diff --git a/Gems/EMotionFX/Code/Tests/Mocks/CommandSystemCommandManager.h b/Gems/EMotionFX/Code/Tests/Mocks/CommandSystemCommandManager.h index adef6392bb..b50e9bf8d5 100644 --- a/Gems/EMotionFX/Code/Tests/Mocks/CommandSystemCommandManager.h +++ b/Gems/EMotionFX/Code/Tests/Mocks/CommandSystemCommandManager.h @@ -12,6 +12,8 @@ namespace CommandSystem : public MCore::CommandManager { public: + virtual ~CommandManager() = default; + MOCK_METHOD0(GetCurrentSelection, SelectionList&()); MOCK_METHOD1(SetCurrentSelection, void(SelectionList& selection)); MOCK_CONST_METHOD0(GetLockSelection, bool()); From dfec238917936197e13fa7a84668966759c13a0c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:36:48 -0700 Subject: [PATCH 015/274] Gems/GraphCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AlignmentContextMenuAction.h | 3 ++- .../AlignmentContextMenuActions.h | 3 ++- .../CommentContextMenuAction.h | 1 + .../CommentContextMenuActions.h | 2 ++ .../BookmarkConstructMenuActions.h | 1 + .../CommentConstructMenuActions.h | 1 + .../ConstructPresetMenuActions.h | 3 +++ .../DisableMenuActions/DisableMenuActions.h | 1 + .../EditMenuActions/EditContextMenuAction.h | 1 + .../EditMenuActions/EditContextMenuActions.h | 6 ++++++ .../NodeGroupContextMenuAction.h | 1 + .../NodeGroupContextMenuActions.h | 10 ++++++++++ .../NodeMenuActions/NodeContextMenuActions.h | 6 ++++-- .../SceneMenuActions/SceneContextMenuActions.h | 2 ++ .../SlotMenuActions/SlotContextMenuActions.h | 18 ++++++++++++++++++ .../GraphCanvasAssetEditorMainWindow.h | 2 ++ 16 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuAction.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuAction.h index 1334dff94a..fb51e76868 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuAction.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuAction.h @@ -22,10 +22,11 @@ namespace GraphCanvas { } + using ContextMenuAction::RefreshAction; void RefreshAction() override { const AZ::EntityId& graphId = GetGraphId(); - const AZ::EntityId& targetId = GetTargetId(); + const AZ::EntityId& targetId = GetTargetId(); bool canAlignSelection = false; SceneRequestBus::EventResult(canAlignSelection, graphId, &SceneRequests::HasMultipleSelection); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuActions.h index bc5d8da1d5..fe261a5ce8 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/AlignmentMenuActions/AlignmentContextMenuActions.h @@ -30,7 +30,8 @@ namespace GraphCanvas bool IsInSubMenu() const override; AZStd::string GetSubMenuPath() const override; - + + using AlignmentContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; private: diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuAction.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuAction.h index 2d2173204c..1ad2f41728 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuAction.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuAction.h @@ -22,6 +22,7 @@ namespace GraphCanvas { } + using ContextMenuAction::RefreshAction; void RefreshAction(const GraphId& graphId, const AZ::EntityId& targetId) override { AZ_UNUSED(targetId); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuActions.h index cb4012ec55..8d19e0f9ab 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/CommentMenuActions/CommentContextMenuActions.h @@ -25,6 +25,8 @@ namespace GraphCanvas using ContextMenuAction::RefreshAction; void RefreshAction() override; + + using CommentContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/BookmarkConstructMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/BookmarkConstructMenuActions.h index e0f6320088..d1ac3b083f 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/BookmarkConstructMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/BookmarkConstructMenuActions.h @@ -20,6 +20,7 @@ namespace GraphCanvas AddBookmarkMenuAction(QObject* parent); virtual ~AddBookmarkMenuAction() = default; + using ConstructContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/CommentConstructMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/CommentConstructMenuActions.h index 1a22f40ea0..3c9c767619 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/CommentConstructMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/CommentConstructMenuActions.h @@ -20,6 +20,7 @@ namespace GraphCanvas AddCommentMenuAction(QObject* parent); virtual ~AddCommentMenuAction() = default; + using ConstructContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/ConstructPresetMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/ConstructPresetMenuActions.h index 9b081c9925..b6c393872f 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/ConstructPresetMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/ConstructMenuActions/ConstructPresetMenuActions.h @@ -28,6 +28,7 @@ namespace GraphCanvas bool IsInSubMenu() const override; AZStd::string GetSubMenuPath() const override; + using ConstructContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; private: @@ -52,6 +53,7 @@ namespace GraphCanvas bool IsInSubMenu() const override; AZStd::string GetSubMenuPath() const override; + using ConstructContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; private: @@ -69,6 +71,7 @@ namespace GraphCanvas CreatePresetFromSelection(QObject* parent = nullptr); virtual ~CreatePresetFromSelection(); + using ContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; static ActionGroupId GetCreateConstructContextMenuActionGroupId() diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/DisableMenuActions/DisableMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/DisableMenuActions/DisableMenuActions.h index 2252f081bb..b66a33bef8 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/DisableMenuActions/DisableMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/DisableMenuActions/DisableMenuActions.h @@ -22,6 +22,7 @@ namespace GraphCanvas void SetEnableState(bool enableState); + using DisableContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; private: diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuAction.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuAction.h index f87374323f..03a16d015b 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuAction.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuAction.h @@ -22,6 +22,7 @@ namespace GraphCanvas { } + using ContextMenuAction::RefreshAction; void RefreshAction(const GraphId& graphId, const AZ::EntityId& targetId) override { AZ_UNUSED(targetId); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuActions.h index 817cd887a6..35195c0c57 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/EditMenuActions/EditContextMenuActions.h @@ -22,6 +22,7 @@ namespace GraphCanvas CutGraphSelectionMenuAction(QObject* parent); virtual ~CutGraphSelectionMenuAction() = default; + using EditContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -34,6 +35,7 @@ namespace GraphCanvas CopyGraphSelectionMenuAction(QObject* parent); virtual ~CopyGraphSelectionMenuAction() = default; + using EditContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -49,6 +51,8 @@ namespace GraphCanvas virtual ~PasteGraphSelectionMenuAction() = default; void RefreshAction() override; + + using EditContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -61,6 +65,7 @@ namespace GraphCanvas DeleteGraphSelectionMenuAction(QObject* parent); virtual ~DeleteGraphSelectionMenuAction() = default; + using EditContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -73,6 +78,7 @@ namespace GraphCanvas DuplicateGraphSelectionMenuAction(QObject* parent); virtual ~DuplicateGraphSelectionMenuAction() = default; + using EditContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuAction.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuAction.h index 28b36074b7..ade04ab8dc 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuAction.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuAction.h @@ -22,6 +22,7 @@ namespace GraphCanvas { } + using ContextMenuAction::RefreshAction; void RefreshAction(const GraphId& graphId, const AZ::EntityId& targetId) override { AZ_UNUSED(targetId); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuActions.h index 2a45e43aee..d0f4101235 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeGroupMenuActions/NodeGroupContextMenuActions.h @@ -25,6 +25,8 @@ namespace GraphCanvas using ContextMenuAction::RefreshAction; void RefreshAction() override; + + using NodeGroupContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; private: @@ -43,6 +45,8 @@ namespace GraphCanvas using ContextMenuAction::RefreshAction; void RefreshAction() override; + + using NodeGroupContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -58,6 +62,8 @@ namespace GraphCanvas using ContextMenuAction::RefreshAction; void RefreshAction() override; + + using NodeGroupContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -73,6 +79,8 @@ namespace GraphCanvas using ContextMenuAction::RefreshAction; void RefreshAction() override; + + using NodeGroupContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -88,6 +96,8 @@ namespace GraphCanvas using ContextMenuAction::RefreshAction; void RefreshAction() override; + + using NodeGroupContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeMenuActions/NodeContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeMenuActions/NodeContextMenuActions.h index 0e812d12e9..0253d31c79 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeMenuActions/NodeContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/NodeMenuActions/NodeContextMenuActions.h @@ -21,12 +21,14 @@ namespace GraphCanvas ManageUnusedSlotsMenuAction(QObject* parent, bool hideSlots); virtual ~ManageUnusedSlotsMenuAction() = default; - + + using NodeContextMenuAction::RefreshAction; void RefreshAction(const GraphId& grpahId, const AZ::EntityId& targetId) override; + + using NodeContextMenuAction::TriggerAction; SceneReaction TriggerAction(const GraphId& graphId, const AZ::Vector2&) override; private: - bool m_hideSlots = true; AZ::EntityId m_targetId; }; diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SceneMenuActions/SceneContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SceneMenuActions/SceneContextMenuActions.h index 54b2efa046..59bfd847fe 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SceneMenuActions/SceneContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SceneMenuActions/SceneContextMenuActions.h @@ -25,6 +25,7 @@ namespace GraphCanvas bool IsInSubMenu() const override; AZStd::string GetSubMenuPath() const override; + using SceneContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -40,6 +41,7 @@ namespace GraphCanvas bool IsInSubMenu() const override; AZStd::string GetSubMenuPath() const override; + using SceneContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.h index 29875882a5..f1875bc41d 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.h @@ -22,7 +22,10 @@ namespace GraphCanvas AddSlotMenuAction(QObject* parent); virtual ~AddSlotMenuAction() = default; + using SlotContextMenuAction::RefreshAction; void RefreshAction() override; + + using SlotContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -35,7 +38,10 @@ namespace GraphCanvas RemoveSlotMenuAction(QObject* parent); virtual ~RemoveSlotMenuAction() = default; + using SlotContextMenuAction::RefreshAction; void RefreshAction() override; + + using SlotContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -49,7 +55,10 @@ namespace GraphCanvas ClearConnectionsMenuAction(QObject* parent); virtual ~ClearConnectionsMenuAction() = default; + using SlotContextMenuAction::RefreshAction; void RefreshAction() override; + + using SlotContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -66,7 +75,10 @@ namespace GraphCanvas ResetToDefaultValueMenuAction(QObject* parent); virtual ~ResetToDefaultValueMenuAction() = default; + using SlotContextMenuAction::RefreshAction; void RefreshAction() override; + + using SlotContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -79,7 +91,10 @@ namespace GraphCanvas ToggleReferenceStateAction(QObject* parent); virtual ~ToggleReferenceStateAction() = default; + using SlotContextMenuAction::RefreshAction; void RefreshAction() override; + + using SlotContextMenuAction::TriggerAction; SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; @@ -92,7 +107,10 @@ namespace GraphCanvas PromoteToVariableAction(QObject* parent); virtual ~PromoteToVariableAction() = default; + using SlotContextMenuAction::RefreshAction; void RefreshAction() override; + + using SlotContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const AZ::Vector2& scenePos) override; }; diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasEditor/GraphCanvasAssetEditorMainWindow.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasEditor/GraphCanvasAssetEditorMainWindow.h index 5aed5d77e7..139c540767 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasEditor/GraphCanvasAssetEditorMainWindow.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasEditor/GraphCanvasAssetEditorMainWindow.h @@ -55,6 +55,8 @@ namespace GraphCanvas struct AssetEditorWindowConfig { + virtual ~AssetEditorWindowConfig() = default; + /// General AssetEditor config parameters EditorId m_editorId; AZStd::string_view m_baseStyleSheet; From f3992935fe2fb76686fbe721fd9884dd6025e9f6 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:37:03 -0700 Subject: [PATCH 016/274] Gems/GraphModel Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Include/GraphModel/Model/Module/InputOutputNodes.h | 2 ++ .../Code/Include/GraphModel/Model/Module/ModuleNode.h | 1 + 2 files changed, 3 insertions(+) diff --git a/Gems/GraphModel/Code/Include/GraphModel/Model/Module/InputOutputNodes.h b/Gems/GraphModel/Code/Include/GraphModel/Model/Module/InputOutputNodes.h index 51e65705b9..2c3da656fb 100644 --- a/Gems/GraphModel/Code/Include/GraphModel/Model/Module/InputOutputNodes.h +++ b/Gems/GraphModel/Code/Include/GraphModel/Model/Module/InputOutputNodes.h @@ -67,6 +67,7 @@ namespace GraphModel //! \param dataType The type of data represented by this node GraphInputNode(GraphModel::GraphPtr graph, DataTypePtr dataType); + using BaseInputOutputNode::PostLoadSetup; void PostLoadSetup(GraphPtr graph, NodeId id) override; //! Returns the value of the DefaultValue slot, which indicates the default value for this input. This @@ -95,6 +96,7 @@ namespace GraphModel //! \param dataType The type of data represented by this node GraphOutputNode(GraphModel::GraphPtr graph, DataTypePtr dataType); + using BaseInputOutputNode::PostLoadSetup; void PostLoadSetup(GraphPtr graph, NodeId id) override; protected: diff --git a/Gems/GraphModel/Code/Include/GraphModel/Model/Module/ModuleNode.h b/Gems/GraphModel/Code/Include/GraphModel/Model/Module/ModuleNode.h index cce45e5159..f63fd6531f 100644 --- a/Gems/GraphModel/Code/Include/GraphModel/Model/Module/ModuleNode.h +++ b/Gems/GraphModel/Code/Include/GraphModel/Model/Module/ModuleNode.h @@ -36,6 +36,7 @@ namespace GraphModel const char* GetTitle() const override; + using Node::PostLoadSetup; void PostLoadSetup(GraphPtr ownerGraph, NodeId id) override; protected: From bc27e5a6c713d93e40ccb8c297a1d083649ca3d9 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:37:17 -0700 Subject: [PATCH 017/274] Gems/ImGui Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/ImGui/Code/Include/ImGuiBus.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/ImGui/Code/Include/ImGuiBus.h b/Gems/ImGui/Code/Include/ImGuiBus.h index 959577e97f..d481ec7843 100644 --- a/Gems/ImGui/Code/Include/ImGuiBus.h +++ b/Gems/ImGui/Code/Include/ImGuiBus.h @@ -70,6 +70,8 @@ namespace ImGui public: AZ_RTTI(IImGuiManager, "{F5A0F08B-F2DA-43B7-8CD2-C6FC71E1A712}"); + virtual ~IImGuiManager() = default; + static const char* GetUniqueName() { return "IImGuiManager"; } virtual DisplayState GetEditorWindowState() const = 0; From 4a972d96f924b3acd3f336a6d70b1d466b63d93b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:37:33 -0700 Subject: [PATCH 018/274] Gems others Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Editor/Menus/SceneContextMenuActions.h | 4 ++++ Gems/LyShine/Code/Editor/Animation/UiAnimViewNode.h | 1 + Gems/Maestro/Code/Source/Components/SequenceAgent.h | 2 ++ .../EntityReplication/EntityReplicationManager.h | 1 + 4 files changed, 8 insertions(+) diff --git a/Gems/LandscapeCanvas/Code/Source/Editor/Menus/SceneContextMenuActions.h b/Gems/LandscapeCanvas/Code/Source/Editor/Menus/SceneContextMenuActions.h index f51dab9bd9..27faad7099 100644 --- a/Gems/LandscapeCanvas/Code/Source/Editor/Menus/SceneContextMenuActions.h +++ b/Gems/LandscapeCanvas/Code/Source/Editor/Menus/SceneContextMenuActions.h @@ -22,7 +22,11 @@ namespace LandscapeCanvasEditor virtual ~FindSelectedNodesAction() = default; GraphCanvas::ActionGroupId GetActionGroupId() const override; + + using GraphCanvas::ContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::ContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; private: diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNode.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNode.h index 80946eb317..c133ec439a 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewNode.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewNode.h @@ -115,6 +115,7 @@ class CUiAnimViewKeyBundle public: CUiAnimViewKeyBundle() : m_bAllOfSameType(true) {} + virtual ~CUiAnimViewKeyBundle() = default; virtual bool AreAllKeysOfSameType() const override { return m_bAllOfSameType; } diff --git a/Gems/Maestro/Code/Source/Components/SequenceAgent.h b/Gems/Maestro/Code/Source/Components/SequenceAgent.h index 892e4ee7d1..333679f372 100644 --- a/Gems/Maestro/Code/Source/Components/SequenceAgent.h +++ b/Gems/Maestro/Code/Source/Components/SequenceAgent.h @@ -20,6 +20,8 @@ namespace Maestro friend class AZ::SerializeContext; protected: + virtual ~SequenceAgent() = default; + // This pure virtual is required for the Editor and RunTime to find the componentTypeId - in the Editor // it accounts for the GenericComponentWrapper component virtual const AZ::Uuid& GetComponentTypeUuid(const AZ::Component& component) const = 0; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h index 731a1a7556..ef05e22e3e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.h @@ -153,6 +153,7 @@ namespace Multiplayer { public: OrphanedEntityRpcs(EntityReplicationManager& replicationManager); + virtual ~OrphanedEntityRpcs() = default; void Update(); bool DispatchOrphanedRpcs(EntityReplicator& entityReplicator); void AddOrphanedRpc(NetEntityId entityId, NetworkEntityRpcMessage& entityRpcMessage); From 27cdf174cf9a3524f9057ca3d20c8dced6f7d5e5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:37:48 -0700 Subject: [PATCH 019/274] Gems/PhysX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Benchmarks/PhysXCharactersBenchmarks.cpp | 24 +++++++-- .../PhysXCharactersRagdollBenchmarks.cpp | 24 +++++++-- .../Tests/Benchmarks/PhysXJointBenchmarks.cpp | 23 +++++++- .../Benchmarks/PhysXRigidBodyBenchmarks.cpp | 52 ++++++++++++++++--- .../Benchmarks/PhysXSceneQueryBenchmarks.cpp | 25 +++++++-- 5 files changed, 128 insertions(+), 20 deletions(-) diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp index 200cbeafde..cd9e3c0395 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp @@ -85,8 +85,7 @@ namespace PhysX::Benchmarks class PhysXCharactersBenchmarkFixture : public PhysX::Benchmarks::PhysXBaseBenchmarkFixture { - public: - virtual void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { PhysX::Benchmarks::PhysXBaseBenchmarkFixture::SetUpInternal(); //need to get the Physics::System to be able to spawn the rigid bodies @@ -95,12 +94,31 @@ namespace PhysX::Benchmarks m_terrainEntity = PhysX::TestUtils::CreateFlatTestTerrain(m_testSceneHandle, CharacterConstants::TerrainSize, CharacterConstants::TerrainSize); } - virtual void TearDown([[maybe_unused]] const ::benchmark::State& state) override + void internalTearDown() { m_terrainEntity = nullptr; PhysX::Benchmarks::PhysXBaseBenchmarkFixture::TearDownInternal(); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + protected: // PhysXBaseBenchmarkFixture Overrides ... AzPhysics::SceneConfiguration GetDefaultSceneConfiguration() override diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersRagdollBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersRagdollBenchmarks.cpp index 8febfcddfc..c82d222e80 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersRagdollBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersRagdollBenchmarks.cpp @@ -70,8 +70,7 @@ namespace PhysX::Benchmarks class PhysXCharactersRagdollBenchmarkFixture : public PhysX::Benchmarks::PhysXBaseBenchmarkFixture { - public: - virtual void SetUp([[maybe_unused]] const ::benchmark::State& state) override + void internalSetUp() { PhysX::Benchmarks::PhysXBaseBenchmarkFixture::SetUpInternal(); //need to get the Physics::System to be able to spawn the rigid bodies @@ -80,12 +79,31 @@ namespace PhysX::Benchmarks m_terrainEntity = PhysX::TestUtils::CreateFlatTestTerrain(m_testSceneHandle, RagdollConstants::TerrainSize, RagdollConstants::TerrainSize); } - virtual void TearDown([[maybe_unused]] const ::benchmark::State& state) override + void internalTearDown() { m_terrainEntity = nullptr; PhysX::Benchmarks::PhysXBaseBenchmarkFixture::TearDownInternal(); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + protected: // PhysXBaseBenchmarkFixture Overrides ... AzPhysics::SceneConfiguration GetDefaultSceneConfiguration() override diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp index 17468b5cc6..df714d7143 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp @@ -184,17 +184,36 @@ namespace PhysX::Benchmarks : public PhysXBaseBenchmarkFixture { public: - virtual void SetUp([[maybe_unused]] const ::benchmark::State &state) override + void internalSetUp() { PhysXBaseBenchmarkFixture::SetUpInternal(); } - virtual void TearDown([[maybe_unused]] const ::benchmark::State &state) override + void internalTearDown() { PhysXBaseBenchmarkFixture::TearDownInternal(); } protected: + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + // PhysXBaseBenchmarkFixture Interface --------- AzPhysics::SceneConfiguration GetDefaultSceneConfiguration() override { diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXRigidBodyBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXRigidBodyBenchmarks.cpp index 0117e9737b..58cbd0da23 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXRigidBodyBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXRigidBodyBenchmarks.cpp @@ -136,8 +136,8 @@ namespace PhysX::Benchmarks class PhysXRigidbodyBenchmarkFixture : public PhysXBaseBenchmarkFixture { - public: - virtual void SetUp([[maybe_unused]] const ::benchmark::State &state) override + protected: + virtual void internalSetUp() { PhysXBaseBenchmarkFixture::SetUpInternal(); //need to get the Physics::System to be able to spawn the rigid bodies @@ -146,11 +146,29 @@ namespace PhysX::Benchmarks m_terrainEntity = PhysX::TestUtils::CreateFlatTestTerrain(m_testSceneHandle, RigidBodyConstants::TerrainSize, RigidBodyConstants::TerrainSize); } - virtual void TearDown([[maybe_unused]] const ::benchmark::State &state) override + virtual void internalTearDown() { m_terrainEntity = nullptr; PhysXBaseBenchmarkFixture::TearDownInternal(); } + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } protected: // PhysXBaseBenchmarkFixture Interface --------- @@ -312,10 +330,9 @@ namespace PhysX::Benchmarks class PhysXRigidbodyCollisionsBenchmarkFixture : public PhysXRigidbodyBenchmarkFixture { - public: - void SetUp(const ::benchmark::State& state) override + void internalSetUp() override { - PhysXRigidbodyBenchmarkFixture::SetUp(state); + PhysXRigidbodyBenchmarkFixture::internalSetUp(); m_collisionBeginCount = 0; m_collisionPersistCount = 0; @@ -346,11 +363,30 @@ namespace PhysX::Benchmarks m_defaultScene->RegisterSceneCollisionEventHandler(m_onSceneCollisionHandler); } - void TearDown(const ::benchmark::State& state) override + void internalTearDown() override { m_onSceneCollisionHandler.Disconnect(); - PhysXRigidbodyBenchmarkFixture::TearDown(state); + PhysXRigidbodyBenchmarkFixture::internalTearDown(); + } + + public: + void SetUp(const benchmark::State&) override + { + internalSetUp(); + } + void SetUp(benchmark::State&) override + { + internalSetUp(); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); } protected: diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXSceneQueryBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXSceneQueryBenchmarks.cpp index 4a6cbae99b..9a8a28a85e 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXSceneQueryBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXSceneQueryBenchmarks.cpp @@ -47,14 +47,12 @@ namespace PhysX::Benchmarks , public PhysX::GenericPhysicsFixture { - public: - //! Spawns box entities in unique locations in 1/8 of sphere with all non-negative dimensions between radii[2, max radius]. //! Accepts 2 parameters from \state. //! //! \state.range(0) - number of box entities to spawn //! \state.range(1) - max radius - void SetUp(const ::benchmark::State& state) override + void internalSetUp(const ::benchmark::State& state) { PhysX::GenericPhysicsFixture::SetUpInternal(); @@ -100,13 +98,32 @@ namespace PhysX::Benchmarks } } - void TearDown([[maybe_unused]] const ::benchmark::State& state) override + void internalTearDown() { m_boxes.clear(); m_entities.clear(); PhysX::GenericPhysicsFixture::TearDownInternal(); } + public: + void SetUp(const benchmark::State& state) override + { + internalSetUp(state); + } + void SetUp(benchmark::State& state) override + { + internalSetUp(state); + } + + void TearDown(const benchmark::State&) override + { + internalTearDown(); + } + void TearDown(benchmark::State&) override + { + internalTearDown(); + } + protected: std::vector m_entities; std::vector m_boxes; From 52607ce2c02cfd520e252885b9f4c98726a5bac1 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:38:07 -0700 Subject: [PATCH 020/274] Gems/ScriptCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../View/Windows/ScriptCanvasContextMenus.h | 21 +++++++++++++++++++ .../Code/Include/ScriptCanvas/Core/Node.h | 7 ++++--- .../DynamicSlotFullCreation.cpp | 9 ++++---- .../VariableListFullCreation.cpp | 4 +--- .../Code/Tests/ScriptCanvasPhysicsTest.cpp | 6 ++++-- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.h index f95ca6c80b..e8e2a8ee4f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.h @@ -61,7 +61,10 @@ namespace ScriptCanvasEditor bool IsInSubMenu() const override; AZStd::string GetSubMenuPath() const override; + using GraphCanvas::SceneContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::SceneContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; }; @@ -77,7 +80,10 @@ namespace ScriptCanvasEditor GraphCanvas::ActionGroupId GetActionGroupId() const override; + using GraphCanvas::ContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::ContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; private: @@ -110,7 +116,10 @@ namespace ScriptCanvasEditor GraphCanvas::ActionGroupId GetActionGroupId() const override; + using SlotManipulationMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using SlotManipulationMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; private: @@ -127,7 +136,10 @@ namespace ScriptCanvasEditor ExposeSlotMenuAction(QObject* parent); virtual ~ExposeSlotMenuAction() = default; + using GraphCanvas::SlotContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::SlotContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; protected: @@ -145,7 +157,10 @@ namespace ScriptCanvasEditor virtual ~SetDataSlotTypeMenuAction() = default; static bool IsSupportedSlotType(const AZ::EntityId& slotId); + using GraphCanvas::SlotContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::SlotContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; private: @@ -164,7 +179,10 @@ namespace ScriptCanvasEditor CreateAzEventHandlerSlotMenuAction(QObject* parent); + using GraphCanvas::SlotContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::SlotContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; static const AZ::BehaviorMethod* FindBehaviorMethodWithAzEventReturn(const GraphCanvas::GraphId& graphId, AZ::EntityId targetId); @@ -239,7 +257,10 @@ namespace ScriptCanvasEditor RenameFunctionDefinitionNodeAction(NodeDescriptorComponent* descriptor, QObject* parent); virtual ~RenameFunctionDefinitionNodeAction() = default; + using GraphCanvas::NodeContextMenuAction::RefreshAction; void RefreshAction(const GraphCanvas::GraphId& graphId, const AZ::EntityId& targetId) override; + + using GraphCanvas::NodeContextMenuAction::TriggerAction; GraphCanvas::ContextMenuAction::SceneReaction TriggerAction(const GraphCanvas::GraphId& graphId, const AZ::Vector2& scenePos) override; NodeDescriptorComponent* m_descriptor; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h index 27f0b3862d..0ef109d383 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h @@ -178,8 +178,8 @@ namespace ScriptCanvas NodePropertyInterface() = default; public: - AZ_RTTI(NodePropertyInterface, "{265A2163-D3AE-4C4E-BDCC-37BA0084BF88}"); + virtual ~NodePropertyInterface() = default; virtual Data::Type GetDataType() = 0; @@ -217,7 +217,7 @@ namespace ScriptCanvas AZ_RTTI((TypedNodePropertyInterface, "{24248937-86FB-406C-8DD5-023B10BD0B60}", DataType), NodePropertyInterface); TypedNodePropertyInterface() = default; - ~TypedNodePropertyInterface() = default; + virtual ~TypedNodePropertyInterface() = default; void SetPropertyReference(DataType* dataReference) { @@ -283,7 +283,7 @@ namespace ScriptCanvas AZ_RTTI((TypedComboBoxNodePropertyInterface, "{24248937-86FB-406C-8DD5-023B10BD0B60}", DataType), TypedNodePropertyInterface, ComboBoxPropertyInterface); TypedComboBoxNodePropertyInterface() = default; - ~TypedComboBoxNodePropertyInterface() = default; + virtual ~TypedComboBoxNodePropertyInterface() = default; // TypedNodePropertyInterface void ResetToDefault() override @@ -354,6 +354,7 @@ namespace ScriptCanvas { public: AZ_RTTI(EnumComboBoxNodePropertyInterface, "{7D46B998-9E05-401A-AC92-37A90BAF8F60}", TypedComboBoxNodePropertyInterface); + virtual ~EnumComboBoxNodePropertyInterface() = default; // No way of identifying Enum types properly yet. Going to fake a BCO object type for now. static const AZ::Uuid k_EnumUUID; diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp index 83ece831eb..090622646a 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp @@ -39,13 +39,14 @@ namespace ScriptCanvasDeveloperEditor { public: - DynamicSlotFullCreationInterface(DeveloperUtils::ConnectionStyle connectionStyle) + DynamicSlotFullCreationInterface(DeveloperUtils::ConnectionStyle connectionStyle) { m_chainConfig.m_connectionStyle = connectionStyle; m_chainConfig.m_skipHandlers = true; } + virtual ~DynamicSlotFullCreationInterface() = default; - void SetupInterface(const AZ::EntityId& activeGraphCanvasGraphId, const ScriptCanvas::ScriptCanvasId& scriptCanvasId) + void SetupInterface(const AZ::EntityId& activeGraphCanvasGraphId, const ScriptCanvas::ScriptCanvasId& scriptCanvasId) override { m_graphCanvasGraphId = activeGraphCanvasGraphId; m_scriptCanvasId = scriptCanvasId; @@ -142,12 +143,12 @@ namespace ScriptCanvasDeveloperEditor } } - bool ShouldProcessItem([[maybe_unused]] const GraphCanvas::NodePaletteTreeItem* nodePaletteTreeItem) const + bool ShouldProcessItem([[maybe_unused]] const GraphCanvas::NodePaletteTreeItem* nodePaletteTreeItem) const override { return !m_availableVariableIds.empty(); } - void ProcessItem(const GraphCanvas::NodePaletteTreeItem* nodePaletteTreeItem) + void ProcessItem(const GraphCanvas::NodePaletteTreeItem* nodePaletteTreeItem) override { AZStd::unordered_set createdPairs; GraphCanvas::GraphCanvasMimeEvent* mimeEvent = nodePaletteTreeItem->CreateMimeEvent(); diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp index c443c57010..4b457e99e2 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/VariableListFullCreation.cpp @@ -37,9 +37,7 @@ namespace ScriptCanvasDeveloperEditor m_variableNameFormat += " %i"; } - ~VariablePaletteFullCreationInterface() - { - } + virtual ~VariablePaletteFullCreationInterface() = default; void SetupInterface([[maybe_unused]] const AZ::EntityId& graphCanvasId, const ScriptCanvas::ScriptCanvasId& scriptCanvasId) { diff --git a/Gems/ScriptCanvasPhysics/Code/Tests/ScriptCanvasPhysicsTest.cpp b/Gems/ScriptCanvasPhysics/Code/Tests/ScriptCanvasPhysicsTest.cpp index ac6109ce30..70d8857b1c 100644 --- a/Gems/ScriptCanvasPhysics/Code/Tests/ScriptCanvasPhysicsTest.cpp +++ b/Gems/ScriptCanvasPhysics/Code/Tests/ScriptCanvasPhysicsTest.cpp @@ -175,7 +175,7 @@ namespace ScriptCanvasPhysicsTests MOCK_CONST_METHOD0(GetNativePointer, void*()); }; - class MockShape + class MockShape : public Physics::Shape { public: @@ -203,10 +203,12 @@ namespace ScriptCanvasPhysicsTests MOCK_METHOD1(SetContactOffset, void(float)); }; - class MockPhysicsMaterial + class MockPhysicsMaterial : public Physics::Material { public: + virtual ~MockPhysicsMaterial() = default; + MOCK_CONST_METHOD0(GetSurfaceType, AZ::Crc32()); MOCK_CONST_METHOD0(GetSurfaceTypeName, const AZStd::string&()); MOCK_METHOD1(SetSurfaceTypeName, void(const AZStd::string&)); From c6593bbdd3a60cdad1886ce96eba9b43d98c92f9 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:38:33 -0700 Subject: [PATCH 021/274] double assignation of the same thing Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/std/algorithm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/std/algorithm.h b/Code/Framework/AzCore/AzCore/std/algorithm.h index 3508eff2b4..e28d127062 100644 --- a/Code/Framework/AzCore/AzCore/std/algorithm.h +++ b/Code/Framework/AzCore/AzCore/std/algorithm.h @@ -831,7 +831,6 @@ namespace AZStd // find first element that value is before, using operator< typename iterator_traits::difference_type count = AZStd::distance(first, last); typename iterator_traits::difference_type step{}; - count = AZStd::distance(first, last); for (; 0 < count; ) { // divide and conquer, find half that contains answer step = count / 2; From 49d35e078860d941a1a8a6c0e26e15a642cd7db9 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:57:18 -0700 Subject: [PATCH 022/274] Final fixes for MSVC Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/CryEdit.h | 1 + Code/Editor/Dialogs/PythonScriptsDialog.cpp | 2 + Code/Editor/Export/ExportManager.h | 2 + Code/Editor/Lib/Tests/IEditorMock.h | 2 + Code/Editor/Objects/BaseObject.h | 3 - Code/Editor/Objects/EntityObject.h | 3 +- Code/Editor/Objects/ObjectManager.cpp | 1 + Code/Editor/TrackView/TrackViewNode.h | 1 + Code/Editor/Util/Variable.h | 158 +++++++++--------- Code/Editor/Viewport.h | 1 + .../tests/resourcecompiler/RCBuilderTest.h | 2 + .../unittests/MockApplicationManager.cpp | 2 + .../utilities/PlatformConfiguration.cpp | 3 + .../native/utilities/PlatformConfiguration.h | 7 + .../Tools/SerializeContextTools/Converter.cpp | 2 + 15 files changed, 108 insertions(+), 82 deletions(-) diff --git a/Code/Editor/CryEdit.h b/Code/Editor/CryEdit.h index 4ab37ac1e5..730af7c034 100644 --- a/Code/Editor/CryEdit.h +++ b/Code/Editor/CryEdit.h @@ -462,6 +462,7 @@ class CCryDocManager CCrySingleDocTemplate* m_pDefTemplate = nullptr; public: CCryDocManager(); + virtual ~CCryDocManager() = default; CCrySingleDocTemplate* SetDefaultTemplate(CCrySingleDocTemplate* pNew); // Copied from MFC to get rid of the silly ugly unoverridable doc-type pick dialog virtual void OnFileNew(); diff --git a/Code/Editor/Dialogs/PythonScriptsDialog.cpp b/Code/Editor/Dialogs/PythonScriptsDialog.cpp index 7c6b445387..e95fb90c0a 100644 --- a/Code/Editor/Dialogs/PythonScriptsDialog.cpp +++ b/Code/Editor/Dialogs/PythonScriptsDialog.cpp @@ -79,6 +79,8 @@ CPythonScriptsDialog::CPythonScriptsDialog(QWidget* parent) GetGemSourcePathsVisitor(AZ::SettingsRegistryInterface& settingsRegistry) : m_settingsRegistry(settingsRegistry) {} + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override { diff --git a/Code/Editor/Export/ExportManager.h b/Code/Editor/Export/ExportManager.h index be81591e56..4417a0ae89 100644 --- a/Code/Editor/Export/ExportManager.h +++ b/Code/Editor/Export/ExportManager.h @@ -92,6 +92,8 @@ namespace Export : public IData { public: + virtual ~CData() = default; + virtual int GetObjectCount() const { return static_cast(m_objects.size()); } virtual Object* GetObject(int index) const { return m_objects[index]; } virtual Object* AddObject(const char* objectName); diff --git a/Code/Editor/Lib/Tests/IEditorMock.h b/Code/Editor/Lib/Tests/IEditorMock.h index 30f1d23576..67a714703b 100644 --- a/Code/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Editor/Lib/Tests/IEditorMock.h @@ -25,6 +25,8 @@ public: } public: + virtual ~CEditorMock() = default; + MOCK_METHOD0(DeleteThis, void()); MOCK_METHOD0(GetSystem, ISystem*()); MOCK_METHOD0(GetClassFactory, IEditorClassFactory* ()); diff --git a/Code/Editor/Objects/BaseObject.h b/Code/Editor/Objects/BaseObject.h index 89e47ae881..c973b2f293 100644 --- a/Code/Editor/Objects/BaseObject.h +++ b/Code/Editor/Objects/BaseObject.h @@ -743,9 +743,6 @@ private: //! Only called once after creation by ObjectManager. void SetClassDesc(CObjectClassDesc* classDesc); - // From CObject, (not implemented) - virtual void Serialize([[maybe_unused]] CArchive& ar) {}; - EScaleWarningLevel GetScaleWarningLevel() const; ERotationWarningLevel GetRotationWarningLevel() const; diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h index d5600d15b7..6150685c45 100644 --- a/Code/Editor/Objects/EntityObject.h +++ b/Code/Editor/Objects/EntityObject.h @@ -116,7 +116,8 @@ public: void UpdateVisibility(bool bVisible); bool ConvertFromObject(CBaseObject* object); - virtual void Serialize(CObjectArchive& ar); + using CBaseObject::Serialize; + void Serialize(CObjectArchive& ar) override; virtual void PostLoad(CObjectArchive& ar); XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode); diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index 30ee1fc57b..13ba2d47de 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -52,6 +52,7 @@ public: GUID guid; public: + virtual ~CXMLObjectClassDesc() = default; REFGUID ClassID() override { return guid; diff --git a/Code/Editor/TrackView/TrackViewNode.h b/Code/Editor/TrackView/TrackViewNode.h index 59df06750b..a3918d61a4 100644 --- a/Code/Editor/TrackView/TrackViewNode.h +++ b/Code/Editor/TrackView/TrackViewNode.h @@ -117,6 +117,7 @@ class CTrackViewKeyBundle public: CTrackViewKeyBundle() : m_bAllOfSameType(true) {} + virtual ~CTrackViewKeyBundle() = default; virtual bool AreAllKeysOfSameType() const override { return m_bAllOfSameType; } diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index 9c3f96a3f6..0965756488 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -379,11 +379,11 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING public: virtual ~CVariableBase() {} - void SetName(const QString& name) { m_name = name; }; + void SetName(const QString& name) override { m_name = name; }; //! Get name of parameter. - QString GetName() const { return m_name; }; + QString GetName() const override { return m_name; }; - QString GetHumanName() const + QString GetHumanName() const override { if (!m_humanName.isEmpty()) { @@ -391,23 +391,23 @@ public: } return m_name; } - void SetHumanName(const QString& name) { m_humanName = name; } + void SetHumanName(const QString& name) override { m_humanName = name; } - void SetDescription(const char* desc) { m_description = desc; }; - void SetDescription(const QString& desc) { m_description = desc; }; + void SetDescription(const char* desc) override { m_description = desc; }; + void SetDescription(const QString& desc) override { m_description = desc; }; //! Get name of parameter. - QString GetDescription() const { return m_description; }; + QString GetDescription() const override { return m_description; }; EType GetType() const { return IVariable::UNKNOWN; }; - int GetSize() const { return sizeof(*this); }; + int GetSize() const override { return sizeof(*this); }; - unsigned char GetDataType() const { return m_dataType; }; - void SetDataType(unsigned char dataType) { m_dataType = dataType; } + unsigned char GetDataType() const override { return m_dataType; }; + void SetDataType(unsigned char dataType) override { m_dataType = dataType; } - void SetFlags(int flags) { m_flags = static_cast(flags); } - int GetFlags() const { return m_flags; } - void SetFlagRecursive(EFlags flag) { m_flags |= flag; } + void SetFlags(int flags) override { m_flags = static_cast(flags); } + int GetFlags() const override { return m_flags; } + void SetFlagRecursive(EFlags flag) override { m_flags |= flag; } void SetUserData(const QVariant &data){ m_userData = data; }; QVariant GetUserData() const { return m_userData; } @@ -415,58 +415,58 @@ public: ////////////////////////////////////////////////////////////////////////// // Set methods. ////////////////////////////////////////////////////////////////////////// - void Set([[maybe_unused]] int value) { assert(0); } - void Set([[maybe_unused]] bool value) { assert(0); } - void Set([[maybe_unused]] float value) { assert(0); } - void Set([[maybe_unused]] double value) { assert(0); } - void Set([[maybe_unused]] const Vec2& value) { assert(0); } - void Set([[maybe_unused]] const Vec3& value) { assert(0); } - void Set([[maybe_unused]] const Vec4& value) { assert(0); } - void Set([[maybe_unused]] const Ang3& value) { assert(0); } - void Set([[maybe_unused]] const Quat& value) { assert(0); } - void Set([[maybe_unused]] const QString& value) { assert(0); } - void Set([[maybe_unused]] const char* value) { assert(0); } - void SetDisplayValue(const QString& value) { Set(value); } + void Set([[maybe_unused]] int value) override { assert(0); } + void Set([[maybe_unused]] bool value) override { assert(0); } + void Set([[maybe_unused]] float value) override { assert(0); } + void Set([[maybe_unused]] double value) override { assert(0); } + void Set([[maybe_unused]] const Vec2& value) override { assert(0); } + void Set([[maybe_unused]] const Vec3& value) override { assert(0); } + void Set([[maybe_unused]] const Vec4& value) override { assert(0); } + void Set([[maybe_unused]] const Ang3& value) override { assert(0); } + void Set([[maybe_unused]] const Quat& value) override { assert(0); } + void Set([[maybe_unused]] const QString& value) override { assert(0); } + void Set([[maybe_unused]] const char* value) override { assert(0); } + void SetDisplayValue(const QString& value) override { Set(value); } ////////////////////////////////////////////////////////////////////////// // Get methods. ////////////////////////////////////////////////////////////////////////// - void Get([[maybe_unused]] int& value) const { assert(0); } - void Get([[maybe_unused]] bool& value) const { assert(0); } - void Get([[maybe_unused]] float& value) const { assert(0); } - void Get([[maybe_unused]] double& value) const { assert(0); } - void Get([[maybe_unused]] Vec2& value) const { assert(0); } - void Get([[maybe_unused]] Vec3& value) const { assert(0); } - void Get([[maybe_unused]] Vec4& value) const { assert(0); } - void Get([[maybe_unused]] Ang3& value) const { assert(0); } - void Get([[maybe_unused]] Quat& value) const { assert(0); } - void Get([[maybe_unused]] QString& value) const { assert(0); } - QString GetDisplayValue() const { QString val; Get(val); return val; } + void Get([[maybe_unused]] int& value) const override { assert(0); } + void Get([[maybe_unused]] bool& value) const override { assert(0); } + void Get([[maybe_unused]] float& value) const override { assert(0); } + void Get([[maybe_unused]] double& value) const override { assert(0); } + void Get([[maybe_unused]] Vec2& value) const override { assert(0); } + void Get([[maybe_unused]] Vec3& value) const override { assert(0); } + void Get([[maybe_unused]] Vec4& value) const override { assert(0); } + void Get([[maybe_unused]] Ang3& value) const override { assert(0); } + void Get([[maybe_unused]] Quat& value) const override { assert(0); } + void Get([[maybe_unused]] QString& value) const override { assert(0); } + QString GetDisplayValue() const override { QString val; Get(val); return val; } ////////////////////////////////////////////////////////////////////////// // IVariableContainer functions ////////////////////////////////////////////////////////////////////////// - virtual void AddVariable([[maybe_unused]] IVariable* var) { assert(0); } + void AddVariable([[maybe_unused]] IVariable* var) override { assert(0); } - virtual bool DeleteVariable([[maybe_unused]] IVariable* var, [[maybe_unused]] bool recursive = false) { return false; } - virtual void DeleteAllVariables() {} + bool DeleteVariable([[maybe_unused]] IVariable* var, [[maybe_unused]] bool recursive = false) override { return false; } + void DeleteAllVariables() override {} - virtual int GetNumVariables() const { return 0; } - virtual IVariable* GetVariable([[maybe_unused]] int index) const { return nullptr; } + int GetNumVariables() const override { return 0; } + IVariable* GetVariable([[maybe_unused]] int index) const override { return nullptr; } - virtual bool IsContainsVariable([[maybe_unused]] IVariable* pVar, [[maybe_unused]] bool bRecursive = false) const { return false; } + bool IsContainsVariable([[maybe_unused]] IVariable* pVar, [[maybe_unused]] bool bRecursive = false) const override { return false; } - virtual IVariable* FindVariable([[maybe_unused]] const char* name, [[maybe_unused]] bool bRecursive = false, [[maybe_unused]] bool bHumanName = false) const { return nullptr; } + IVariable* FindVariable([[maybe_unused]] const char* name, [[maybe_unused]] bool bRecursive = false, [[maybe_unused]] bool bHumanName = false) const override { return nullptr; } - virtual bool IsEmpty() const { return true; } + bool IsEmpty() const override { return true; } ////////////////////////////////////////////////////////////////////////// - void Wire(IVariable* var) + void Wire(IVariable* var) override { m_wiredVars.push_back(var); } ////////////////////////////////////////////////////////////////////////// - void Unwire(IVariable* var) + void Unwire(IVariable* var) override { if (!var) { @@ -480,7 +480,7 @@ public: } ////////////////////////////////////////////////////////////////////////// - void AddOnSetCallback(OnSetCallback* func) + void AddOnSetCallback(OnSetCallback* func) override { if (!stl::find(m_onSetFuncs, func)) { @@ -489,13 +489,13 @@ public: } ////////////////////////////////////////////////////////////////////////// - void RemoveOnSetCallback(OnSetCallback* func) + void RemoveOnSetCallback(OnSetCallback* func) override { stl::find_and_erase(m_onSetFuncs, func); } ////////////////////////////////////////////////////////////////////////// - void ClearOnSetCallbacks() + void ClearOnSetCallbacks() override { m_onSetFuncs.clear(); } @@ -509,7 +509,7 @@ public: } ////////////////////////////////////////////////////////////////////////// - void RemoveOnSetEnumCallback(OnSetCallback* func) + void RemoveOnSetEnumCallback(OnSetCallback* func) override { stl::find_and_erase(m_onSetEnumFuncs, func); } @@ -520,7 +520,7 @@ public: } - virtual void OnSetValue([[maybe_unused]] bool bRecursive) + void OnSetValue([[maybe_unused]] bool bRecursive) override { // If have wired variables or OnSet callback, process them. // Send value to wired variable. @@ -549,7 +549,8 @@ public: } ////////////////////////////////////////////////////////////////////////// - void Serialize(XmlNodeRef node, bool load) + using IVariable::Serialize; + void Serialize(XmlNodeRef node, bool load) override { if (load) { @@ -567,8 +568,8 @@ public: } } - virtual void EnableUpdateCallbacks(bool boEnable){m_boUpdateCallbacksEnabled = boEnable; }; - virtual void SetForceModified(bool bForceModified) { m_bForceModified = bForceModified; } + void EnableUpdateCallbacks(bool boEnable) override{m_boUpdateCallbacksEnabled = boEnable; }; + void SetForceModified(bool bForceModified) override { m_bForceModified = bForceModified; } protected: // Constructor. CVariableBase() @@ -641,13 +642,13 @@ public: CVariableArray(){} //! Get name of parameter. - virtual EType GetType() const { return IVariable::ARRAY; }; - virtual int GetSize() const { return sizeof(CVariableArray); }; + EType GetType() const override { return IVariable::ARRAY; }; + int GetSize() const override { return sizeof(CVariableArray); }; ////////////////////////////////////////////////////////////////////////// // Set methods. ////////////////////////////////////////////////////////////////////////// - virtual void Set(const QString& value) + void Set(const QString& value) override { if (m_strValue != value) { @@ -655,7 +656,7 @@ public: OnSetValue(false); } } - void OnSetValue(bool bRecursive) + void OnSetValue(bool bRecursive) override { CVariableBase::OnSetValue(bRecursive); if (bRecursive) @@ -666,7 +667,7 @@ public: } } } - void SetFlagRecursive(EFlags flag) + void SetFlagRecursive(EFlags flag) override { CVariableBase::SetFlagRecursive(flag); for (Variables::iterator it = m_vars.begin(); it != m_vars.end(); ++it) @@ -677,9 +678,9 @@ public: ////////////////////////////////////////////////////////////////////////// // Get methods. ////////////////////////////////////////////////////////////////////////// - virtual void Get(QString& value) const { value = m_strValue; } + void Get(QString& value) const override { value = m_strValue; } - virtual bool HasDefaultValue() const + bool HasDefaultValue() const override { for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it) { @@ -691,7 +692,7 @@ public: return true; } - virtual void ResetToDefault() + void ResetToDefault() override { for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it) { @@ -700,7 +701,7 @@ public: } ////////////////////////////////////////////////////////////////////////// - IVariable* Clone(bool bRecursive) const + IVariable* Clone(bool bRecursive) const override { CVariableArray* var = new CVariableArray(*this); @@ -713,7 +714,7 @@ public: } ////////////////////////////////////////////////////////////////////////// - void CopyValue(IVariable* fromVar) + void CopyValue(IVariable* fromVar) override { assert(fromVar); if (fromVar->GetType() != IVariable::ARRAY) @@ -733,20 +734,20 @@ public: } ////////////////////////////////////////////////////////////////////////// - virtual int GetNumVariables() const { return static_cast(m_vars.size()); } + int GetNumVariables() const override { return static_cast(m_vars.size()); } - virtual IVariable* GetVariable(int index) const + IVariable* GetVariable(int index) const override { assert(index >= 0 && index < (int)m_vars.size()); return m_vars[index]; } - virtual void AddVariable(IVariable* var) + void AddVariable(IVariable* var) override { m_vars.push_back(var); } - virtual bool DeleteVariable(IVariable* var, bool recursive /*=false*/) + bool DeleteVariable(IVariable* var, bool recursive /*=false*/) override { bool found = stl::find_and_erase(m_vars, var); if (!found && recursive) @@ -762,12 +763,12 @@ public: return found; } - virtual void DeleteAllVariables() + void DeleteAllVariables() override { m_vars.clear(); } - virtual bool IsContainsVariable(IVariable* pVar, bool bRecursive) const + bool IsContainsVariable(IVariable* pVar, bool bRecursive) const override { for (Variables::const_iterator it = m_vars.begin(); it != m_vars.end(); ++it) { @@ -793,14 +794,15 @@ public: return false; } - virtual IVariable* FindVariable(const char* name, bool bRecursive, bool bHumanName) const; + IVariable* FindVariable(const char* name, bool bRecursive, bool bHumanName) const override; - virtual bool IsEmpty() const + bool IsEmpty() const override { return m_vars.empty(); } - void Serialize(XmlNodeRef node, bool load) + using IVariable::Serialize; + void Serialize(XmlNodeRef node, bool load) override { if (load) { @@ -1074,11 +1076,11 @@ class CVariableVoid { public: CVariableVoid(){}; - virtual EType GetType() const { return IVariable::UNKNOWN; }; - virtual IVariable* Clone([[maybe_unused]] bool bRecursive) const { return new CVariableVoid(*this); } - virtual void CopyValue([[maybe_unused]] IVariable* fromVar) {}; - virtual bool HasDefaultValue() const { return true; } - virtual void ResetToDefault() {}; + EType GetType() const override { return IVariable::UNKNOWN; }; + IVariable* Clone([[maybe_unused]] bool bRecursive) const override { return new CVariableVoid(*this); } + void CopyValue([[maybe_unused]] IVariable* fromVar) override {}; + bool HasDefaultValue() const override { return true; } + void ResetToDefault() override {}; protected: CVariableVoid(const CVariableVoid& v) : CVariableBase(v) {}; diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index 6b5bfb5c34..e54eca6083 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -397,6 +397,7 @@ public: //! This method return a vector (p2-p1) in world space alligned to construction plane and restriction axises. //! p1 and p2 must be given in world space and lie on construction plane. + using CViewport::GetCPVector; virtual Vec3 GetCPVector(const Vec3& p1, const Vec3& p2, int axis); //! Snap any given 3D world position to grid lines if snap is enabled. diff --git a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h index 32230be23a..5a6efb2622 100644 --- a/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h +++ b/Code/Tools/AssetProcessor/native/tests/resourcecompiler/RCBuilderTest.h @@ -81,6 +81,8 @@ public: struct MockRecognizerConfiguration : public RecognizerConfiguration { + virtual ~MockRecognizerConfiguration() = default; + const RecognizerContainer& GetAssetRecognizerContainer() const override { return m_recognizerContainer; diff --git a/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp b/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp index bd03e3b225..696ecc710a 100644 --- a/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/MockApplicationManager.cpp @@ -22,6 +22,8 @@ namespace AssetProcessor struct MockRecognizerConfiguration : public RecognizerConfiguration { + virtual ~MockRecognizerConfiguration() = default; + const RecognizerContainer& GetAssetRecognizerContainer() const override { return m_container; diff --git a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp index a1bc508899..52df8e901d 100644 --- a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp @@ -84,6 +84,8 @@ namespace AssetProcessor return !m_platformIdentifierStack.empty() ? AZ::SettingsRegistryInterface::VisitResponse::Continue : AZ::SettingsRegistryInterface::VisitResponse::Skip; } + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit([[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override { if (m_platformIdentifierStack.empty()) @@ -114,6 +116,7 @@ namespace AssetProcessor struct MetaDataTypesVisitor : AZ::SettingsRegistryInterface::Visitor { + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit([[maybe_unused]] AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override { m_metaDataTypes.push_back({ AZ::IO::PathView(valueName, AZ::IO::PosixPathSeparator).LexicallyNormal().String(), value }); diff --git a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.h b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.h index 2c3615c4fc..2c04ca1fad 100644 --- a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.h +++ b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.h @@ -49,6 +49,7 @@ namespace AssetProcessor { } + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override; AZ::SettingsRegistryInterface* m_settingsRegistry; @@ -129,6 +130,8 @@ namespace AssetProcessor { AZ::SettingsRegistryInterface::VisitResponse Traverse(AZStd::string_view jsonPath, AZStd::string_view valueName, AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type) override; + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value) override; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override; @@ -152,6 +155,8 @@ namespace AssetProcessor { AZ::SettingsRegistryInterface::VisitResponse Traverse(AZStd::string_view jsonPath, AZStd::string_view valueName, AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type) override; + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override; AZStd::vector m_excludeAssetRecognizers; @@ -169,6 +174,8 @@ namespace AssetProcessor } AZ::SettingsRegistryInterface::VisitResponse Traverse(AZStd::string_view jsonPath, AZStd::string_view valueName, AZ::SettingsRegistryInterface::VisitAction action, AZ::SettingsRegistryInterface::Type) override; + + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value) override; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value) override; void Visit(AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override; diff --git a/Code/Tools/SerializeContextTools/Converter.cpp b/Code/Tools/SerializeContextTools/Converter.cpp index eff5f140d5..6a8bebdbfc 100644 --- a/Code/Tools/SerializeContextTools/Converter.cpp +++ b/Code/Tools/SerializeContextTools/Converter.cpp @@ -494,6 +494,7 @@ namespace AZ return AZ::SettingsRegistryInterface::VisitResponse::Continue; } + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view, [[maybe_unused]] AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value) override { if (m_processingSourcePathKey) @@ -656,6 +657,7 @@ namespace AZ return AZ::SettingsRegistryInterface::VisitResponse::Continue; } + using AZ::SettingsRegistryInterface::Visitor::Visit; void Visit(AZStd::string_view path, AZStd::string_view valueName, [[maybe_unused]] AZ::SettingsRegistryInterface::Type type, AZStd::string_view value) override { From c78ea3cf208af983bebb58850f9f996843421255 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:57:31 -0700 Subject: [PATCH 023/274] Final fixes for MSVC Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CrySystem/XML/XMLBinaryNode.h | 1 + Code/Legacy/CrySystem/XML/xml.h | 1 + 2 files changed, 2 insertions(+) diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryNode.h b/Code/Legacy/CrySystem/XML/XMLBinaryNode.h index 34e0ca22ce..0ffcd3f19e 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryNode.h +++ b/Code/Legacy/CrySystem/XML/XMLBinaryNode.h @@ -155,6 +155,7 @@ public: bool saveToFile([[maybe_unused]] const char* fileName, [[maybe_unused]] size_t chunkSizeBytes, [[maybe_unused]] AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle) { assert(0); return false; }; // save in small memory chunks //! Set new XML Node attribute (or override attribute with same key). + using IXmlNode::setAttr; void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const char* value) { assert(0); }; void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] int value) { assert(0); }; void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] unsigned int value) { assert(0); }; diff --git a/Code/Legacy/CrySystem/XML/xml.h b/Code/Legacy/CrySystem/XML/xml.h index 912767eae7..de02538c74 100644 --- a/Code/Legacy/CrySystem/XML/xml.h +++ b/Code/Legacy/CrySystem/XML/xml.h @@ -211,6 +211,7 @@ public: bool saveToFile(const char* fileName, size_t chunkSizeBytes, AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle); // save in small memory chunks //! Set new XML Node attribute (or override attribute with same key). + using IXmlNode::setAttr; void setAttr(const char* key, const char* value); void setAttr(const char* key, int value); void setAttr(const char* key, unsigned int value); From 8c51fc24f7fb675816986767bf9ba59a1efa7882 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 07:54:35 -0700 Subject: [PATCH 024/274] Adding clang warning Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/Clang/Configurations_clang.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/Platform/Common/Clang/Configurations_clang.cmake b/cmake/Platform/Common/Clang/Configurations_clang.cmake index 02a94f4e72..d214ad68a2 100644 --- a/cmake/Platform/Common/Clang/Configurations_clang.cmake +++ b/cmake/Platform/Common/Clang/Configurations_clang.cmake @@ -20,7 +20,6 @@ ly_append_configurations_options( -Wrange-loop-analysis -Wno-unknown-warning-option # used as a way to mark warnings that are MSVC only -Wno-format-security - -Wno-inconsistent-missing-override -Wno-parentheses -Wno-reorder -Wno-switch From 6b13e8bfc8c600660c7ce970434f6311c6af0d04 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 16:11:48 -0700 Subject: [PATCH 025/274] Enabling PreFast to find virtual/override issues, some better organization of files Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/LYTestWrappers.cmake | 2 +- cmake/Platform/Common/MSVC/CodeAnalysis.ruleset | 7 +++++++ cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 2 +- cmake/Platform/Common/{ => MSVC}/Directory.Build.props | 3 ++- cmake/Platform/Common/{ => MSVC}/TestProject.props | 0 cmake/Platform/Common/{ => MSVC}/VisualStudio_common.cmake | 0 cmake/Platform/Windows/platform_windows_files.cmake | 6 ++++-- 7 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 cmake/Platform/Common/MSVC/CodeAnalysis.ruleset rename cmake/Platform/Common/{ => MSVC}/Directory.Build.props (91%) rename cmake/Platform/Common/{ => MSVC}/TestProject.props (100%) rename cmake/Platform/Common/{ => MSVC}/VisualStudio_common.cmake (100%) diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index 8e71cb3db1..f319d19763 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -228,7 +228,7 @@ function(ly_add_test) # For test projects that are custom targets, pass a props file that sets the project as "Console" so # it leaves the console open when it finishes - set_target_properties(${unaliased_test_name} PROPERTIES VS_USER_PROPS "${LY_ROOT_FOLDER}/cmake/Platform/Common/TestProject.props") + set_target_properties(${unaliased_test_name} PROPERTIES VS_USER_PROPS "${LY_ROOT_FOLDER}/cmake/Platform/Common/MSVC/TestProject.props") # Include additional dependencies if (ly_add_test_RUNTIME_DEPENDENCIES) diff --git a/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset b/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset new file mode 100644 index 0000000000..a612135e94 --- /dev/null +++ b/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index f10ef844a4..c613b79d87 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -13,7 +13,7 @@ endif() unset(minimum_supported_toolset) include(cmake/Platform/Common/Configurations_common.cmake) -include(cmake/Platform/Common/VisualStudio_common.cmake) +include(cmake/Platform/Common/MSVC/VisualStudio_common.cmake) # Verify that it wasn't invoked with an unsupported target/host architecture. Currently only supports x64/x64 if(CMAKE_VS_PLATFORM_NAME AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "x64") diff --git a/cmake/Platform/Common/Directory.Build.props b/cmake/Platform/Common/MSVC/Directory.Build.props similarity index 91% rename from cmake/Platform/Common/Directory.Build.props rename to cmake/Platform/Common/MSVC/Directory.Build.props index 76e4b28922..4b82cd7048 100644 --- a/cmake/Platform/Common/Directory.Build.props +++ b/cmake/Platform/Common/MSVC/Directory.Build.props @@ -14,6 +14,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT @VCPKG_CONFIGURATION_MAPPING@ false + @LY_ROOT_FOLDER@\cmake\Platform\Common\MSVC\CodeAnalysis.ruleset @@ -25,4 +26,4 @@ SPDX-License-Identifier: Apache-2.0 OR MIT - \ No newline at end of file + diff --git a/cmake/Platform/Common/TestProject.props b/cmake/Platform/Common/MSVC/TestProject.props similarity index 100% rename from cmake/Platform/Common/TestProject.props rename to cmake/Platform/Common/MSVC/TestProject.props diff --git a/cmake/Platform/Common/VisualStudio_common.cmake b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake similarity index 100% rename from cmake/Platform/Common/VisualStudio_common.cmake rename to cmake/Platform/Common/MSVC/VisualStudio_common.cmake diff --git a/cmake/Platform/Windows/platform_windows_files.cmake b/cmake/Platform/Windows/platform_windows_files.cmake index a1e26bd992..fcc47ab6eb 100644 --- a/cmake/Platform/Windows/platform_windows_files.cmake +++ b/cmake/Platform/Windows/platform_windows_files.cmake @@ -7,10 +7,12 @@ # set(FILES - ../Common/Directory.Build.props - ../Common/VisualStudio_common.cmake ../Common/Configurations_common.cmake ../Common/MSVC/Configurations_msvc.cmake + ../Common/MSVC/CodeAnalysis.ruleset + ../Common/MSVC/Directory.Build.props + ../Common/MSVC/TestProject.props + ../Common/MSVC/VisualStudio_common.cmake ../Common/Install_common.cmake ../Common/LYWrappers_default.cmake ../Common/TargetIncludeSystemDirectories_unsupported.cmake From f30ac7204036a35f297f6f567961e2c5301541b3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 16:14:52 -0700 Subject: [PATCH 026/274] fixing AzCore for linux/windows virtual warn Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/Component/ComponentApplication.h | 16 +++---- .../AzCore/Debug/TraceMessagesDriller.h | 20 ++++---- Code/Framework/AzCore/AzCore/Driller/Stream.h | 8 ++-- .../AzCore/AzCore/IO/CompressorZLib.h | 16 +++---- .../AzCore/AzCore/Jobs/Internal/JobNotify.h | 2 +- .../AzCore/AzCore/Math/InterpolationSample.h | 8 ++-- .../AzCore/AzCore/Memory/HeapSchema.h | 20 ++++---- .../AzCore/AzCore/Memory/HphaSchema.h | 22 ++++----- .../AzCore/AzCore/Memory/MallocSchema.h | 20 ++++---- .../AzCore/AzCore/Memory/MemoryDriller.h | 24 +++++----- .../AzCore/Memory/OverrunDetectionAllocator.h | 22 ++++----- Code/Framework/AzCore/AzCore/Module/Module.h | 2 +- .../AzCore/AzCore/RTTI/BehaviorContext.h | 4 +- Code/Framework/AzCore/AzCore/RTTI/RTTI.h | 47 +++++++------------ .../Serialization/Json/JsonSystemComponent.h | 4 +- .../UserSettings/UserSettingsProvider.h | 6 +-- .../AzCore/AzCore/std/parallel/thread.h | 2 +- .../AzCore/std/smart_ptr/shared_count.h | 12 ++--- .../Memory/OverrunDetectionAllocator_WinAPI.h | 10 ++-- 19 files changed, 127 insertions(+), 138 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h index 3768a75d83..bfc541ca09 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h @@ -196,14 +196,14 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// // ComponentApplicationRequests - void RegisterComponentDescriptor(const ComponentDescriptor* descriptor) override final; - void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) override final; - void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) override final; - void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) override final; - void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler) override final; - void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler) override final; - void SignalEntityActivated(Entity* entity) override final; - void SignalEntityDeactivated(Entity* entity) override final; + void RegisterComponentDescriptor(const ComponentDescriptor* descriptor) final; + void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) final; + void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) final; + void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) final; + void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler& handler) final; + void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler& handler) final; + void SignalEntityActivated(Entity* entity) final; + void SignalEntityDeactivated(Entity* entity) final; bool AddEntity(Entity* entity) override; bool RemoveEntity(Entity* entity) override; bool DeleteEntity(const EntityId& id) override; diff --git a/Code/Framework/AzCore/AzCore/Debug/TraceMessagesDriller.h b/Code/Framework/AzCore/AzCore/Debug/TraceMessagesDriller.h index 16d8f4fba3..32726931fc 100644 --- a/Code/Framework/AzCore/AzCore/Debug/TraceMessagesDriller.h +++ b/Code/Framework/AzCore/AzCore/Debug/TraceMessagesDriller.h @@ -28,21 +28,21 @@ namespace AZ protected: ////////////////////////////////////////////////////////////////////////// // Driller - virtual const char* GroupName() const { return "SystemDrillers"; } - virtual const char* GetName() const { return "TraceMessagesDriller"; } - virtual const char* GetDescription() const { return "Handles all system messages like Assert, Exception, Error, Warning, Printf, etc."; } - virtual void Start(const Param* params = NULL, int numParams = 0); - virtual void Stop(); + const char* GroupName() const override { return "SystemDrillers"; } + const char* GetName() const override { return "TraceMessagesDriller"; } + const char* GetDescription() const override { return "Handles all system messages like Assert, Exception, Error, Warning, Printf, etc."; } + void Start(const Param* params = NULL, int numParams = 0) override; + void Stop() override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // TraceMessagesDrillerBus /// Triggered when a AZ_Assert failed. This is terminating event! (the code will break, crash). - virtual void OnAssert(const char* message); - virtual void OnException(const char* message); - virtual void OnError(const char* window, const char* message); - virtual void OnWarning(const char* window, const char* message); - virtual void OnPrintf(const char* window, const char* message); + void OnAssert(const char* message) override; + void OnException(const char* message) override; + void OnError(const char* window, const char* message) override; + void OnWarning(const char* window, const char* message) override; + void OnPrintf(const char* window, const char* message) override; ////////////////////////////////////////////////////////////////////////// }; } // namespace Debug diff --git a/Code/Framework/AzCore/AzCore/Driller/Stream.h b/Code/Framework/AzCore/AzCore/Driller/Stream.h index f883984b11..5efa416ef4 100644 --- a/Code/Framework/AzCore/AzCore/Driller/Stream.h +++ b/Code/Framework/AzCore/AzCore/Driller/Stream.h @@ -443,7 +443,7 @@ namespace AZ const unsigned char* GetData() const { return m_data.data(); } unsigned int GetDataSize() const { return static_cast(m_data.size()); } inline void Reset() { m_data.clear(); } - virtual void WriteBinary(const void* data, unsigned int dataSize) + void WriteBinary(const void* data, unsigned int dataSize) override { m_data.insert(m_data.end(), reinterpret_cast(data), reinterpret_cast(data) + dataSize); } @@ -489,7 +489,7 @@ namespace AZ } unsigned int GetDataLeft() const { return static_cast(m_dataEnd - m_data); } - virtual unsigned int ReadBinary(void* data, unsigned int maxDataSize) + unsigned int ReadBinary(void* data, unsigned int maxDataSize) override { AZ_Assert(m_data != nullptr, "You must call SetData function, before you can read data!"); AZ_Assert(data != nullptr && maxDataSize > 0, "We must have a valid pointer and max data size!"); @@ -523,7 +523,7 @@ namespace AZ bool Open(const char* fileName, int mode, int platformFlags = 0); void Close(); - virtual void WriteBinary(const void* data, unsigned int dataSize); + void WriteBinary(const void* data, unsigned int dataSize) override; }; /** @@ -540,7 +540,7 @@ namespace AZ DrillerInputFileStream(); ~DrillerInputFileStream(); bool Open(const char* fileName, int mode, int platformFlags = 0); - virtual unsigned int ReadBinary(void* data, unsigned int maxDataSize); + unsigned int ReadBinary(void* data, unsigned int maxDataSize) override; void Close(); }; diff --git a/Code/Framework/AzCore/AzCore/IO/CompressorZLib.h b/Code/Framework/AzCore/AzCore/IO/CompressorZLib.h index abd21e1450..dd1fb226c3 100644 --- a/Code/Framework/AzCore/AzCore/IO/CompressorZLib.h +++ b/Code/Framework/AzCore/AzCore/IO/CompressorZLib.h @@ -98,21 +98,21 @@ namespace AZ /// Return compressor type id. static AZ::u32 TypeId(); - virtual AZ::u32 GetTypeId() const { return TypeId(); } + AZ::u32 GetTypeId() const override { return TypeId(); } /// Called when we open a stream to Read for the first time. Data contains the first. dataSize <= m_maxHeaderSize. - virtual bool ReadHeaderAndData(CompressorStream* stream, AZ::u8* data, unsigned int dataSize); + bool ReadHeaderAndData(CompressorStream* stream, AZ::u8* data, unsigned int dataSize) override; /// Called when we are about to start writing to a compressed stream. - virtual bool WriteHeaderAndData(CompressorStream* stream); + bool WriteHeaderAndData(CompressorStream* stream) override; /// Forwarded function from the Device when we from a compressed stream. - virtual SizeType Read(CompressorStream* stream, SizeType byteSize, SizeType offset, void* buffer); + SizeType Read(CompressorStream* stream, SizeType byteSize, SizeType offset, void* buffer) override; /// Forwarded function from the Device when we write to a compressed stream. - virtual SizeType Write(CompressorStream* stream, SizeType byteSize, const void* data, SizeType offset = SizeType(-1)); + SizeType Write(CompressorStream* stream, SizeType byteSize, const void* data, SizeType offset = SizeType(-1)) override; /// Write a seek point. - virtual bool WriteSeekPoint(CompressorStream* stream); + bool WriteSeekPoint(CompressorStream* stream) override; /// Set auto seek point even dataSize bytes. - virtual bool StartCompressor(CompressorStream* stream, int compressionLevel, SizeType autoSeekDataSize); + bool StartCompressor(CompressorStream* stream, int compressionLevel, SizeType autoSeekDataSize) override; /// Called just before we close the stream. All compression data will be flushed and finalized. (You can't add data afterwards). - virtual bool Close(CompressorStream* stream); + bool Close(CompressorStream* stream) override; protected: diff --git a/Code/Framework/AzCore/AzCore/Jobs/Internal/JobNotify.h b/Code/Framework/AzCore/AzCore/Jobs/Internal/JobNotify.h index 9b6a39af4f..1c15b7105e 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/Internal/JobNotify.h +++ b/Code/Framework/AzCore/AzCore/Jobs/Internal/JobNotify.h @@ -31,7 +31,7 @@ namespace AZ { } protected: - virtual void Process() + void Process() override { m_notifyFlag->store(true, AZStd::memory_order_release); } diff --git a/Code/Framework/AzCore/AzCore/Math/InterpolationSample.h b/Code/Framework/AzCore/AzCore/Math/InterpolationSample.h index 12b18f86b8..942f02727e 100644 --- a/Code/Framework/AzCore/AzCore/Math/InterpolationSample.h +++ b/Code/Framework/AzCore/AzCore/Math/InterpolationSample.h @@ -77,7 +77,7 @@ namespace AZ : public Sample { public: - Vector3 GetInterpolatedValue(TimeType time) override final + Vector3 GetInterpolatedValue(TimeType time) final { Vector3 interpolatedValue = m_previousValue; if (m_targetTimestamp != 0) @@ -108,7 +108,7 @@ namespace AZ : public Sample { public: - Quaternion GetInterpolatedValue(TimeType time) override final + Quaternion GetInterpolatedValue(TimeType time) final { Quaternion interpolatedValue = m_previousValue; if (m_targetTimestamp != 0) @@ -144,7 +144,7 @@ namespace AZ : public Sample { public: - Vector3 GetInterpolatedValue(TimeType /*time*/) override final + Vector3 GetInterpolatedValue(TimeType /*time*/) final { return GetTargetValue(); } @@ -155,7 +155,7 @@ namespace AZ : public Sample { public: - Quaternion GetInterpolatedValue(TimeType /*time*/) override final + Quaternion GetInterpolatedValue(TimeType /*time*/) final { return GetTargetValue(); } diff --git a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h index af3e2d9986..15e849309d 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h @@ -48,17 +48,17 @@ namespace AZ HeapSchema(const Descriptor& desc); virtual ~HeapSchema(); - virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0); - virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0); - virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) { (void)ptr; (void)newSize; (void)newAlignment; return NULL; } - virtual size_type Resize(pointer_type ptr, size_type newSize) { (void)ptr; (void)newSize; return 0; } - virtual size_type AllocationSize(pointer_type ptr); + pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; + void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; + pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override { (void)ptr; (void)newSize; (void)newAlignment; return NULL; } + size_type Resize(pointer_type ptr, size_type newSize) override { (void)ptr; (void)newSize; return 0; } + size_type AllocationSize(pointer_type ptr) override; - virtual size_type NumAllocatedBytes() const { return m_used; } - virtual size_type Capacity() const { return m_capacity; } - virtual size_type GetMaxAllocationSize() const; - virtual IAllocatorAllocate* GetSubAllocator() { return m_subAllocator; } - virtual void GarbageCollect() {} + size_type NumAllocatedBytes() const override { return m_used; } + size_type Capacity() const override { return m_capacity; } + size_type GetMaxAllocationSize() const override; + IAllocatorAllocate* GetSubAllocator() override { return m_subAllocator; } + void GarbageCollect() override {} private: AZ_FORCE_INLINE size_type ChunckSize(pointer_type ptr); diff --git a/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h b/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h index fc10bcd768..ea521213bb 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h @@ -56,21 +56,21 @@ namespace AZ HphaSchema(const Descriptor& desc); virtual ~HphaSchema(); - virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0); - virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0); - virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment); + pointer_type Allocate(size_type byteSize, size_type alignment, int flags = 0, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; + void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; + pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override; /// Resizes allocated memory block to the size possible and returns that size. - virtual size_type Resize(pointer_type ptr, size_type newSize); - virtual size_type AllocationSize(pointer_type ptr); + size_type Resize(pointer_type ptr, size_type newSize) override; + size_type AllocationSize(pointer_type ptr) override; - virtual size_type NumAllocatedBytes() const; - virtual size_type Capacity() const; - virtual size_type GetMaxAllocationSize() const; - virtual size_type GetUnAllocatedMemory(bool isPrint = false) const; - virtual IAllocatorAllocate* GetSubAllocator() { return m_desc.m_subAllocator; } + size_type NumAllocatedBytes() const override; + size_type Capacity() const override; + size_type GetMaxAllocationSize() const override; + size_type GetUnAllocatedMemory(bool isPrint = false) const override; + IAllocatorAllocate* GetSubAllocator() override { return m_desc.m_subAllocator; } /// Return unused memory to the OS (if we don't use fixed block). Don't call this unless you really need free memory, it is slow. - virtual void GarbageCollect(); + void GarbageCollect() override; private: // [LY-84974][sconel@][2018-08-10] SliceStrike integration up to CL 671758 diff --git a/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h b/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h index 3a363cb069..b74d07871b 100644 --- a/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h @@ -41,17 +41,17 @@ namespace AZ //--------------------------------------------------------------------- // IAllocatorAllocate //--------------------------------------------------------------------- - virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; - virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; - virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override; - virtual size_type Resize(pointer_type ptr, size_type newSize) override; - virtual size_type AllocationSize(pointer_type ptr) override; + pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; + void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; + pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override; + size_type Resize(pointer_type ptr, size_type newSize) override; + size_type AllocationSize(pointer_type ptr) override; - virtual size_type NumAllocatedBytes() const override; - virtual size_type Capacity() const override; - virtual size_type GetMaxAllocationSize() const override; - virtual IAllocatorAllocate* GetSubAllocator() override; - virtual void GarbageCollect() override; + size_type NumAllocatedBytes() const override; + size_type Capacity() const override; + size_type GetMaxAllocationSize() const override; + IAllocatorAllocate* GetSubAllocator() override; + void GarbageCollect() override; private: typedef void* (*MallocFn)(size_t); diff --git a/Code/Framework/AzCore/AzCore/Memory/MemoryDriller.h b/Code/Framework/AzCore/AzCore/Memory/MemoryDriller.h index 94c364c719..9bcbc85217 100644 --- a/Code/Framework/AzCore/AzCore/Memory/MemoryDriller.h +++ b/Code/Framework/AzCore/AzCore/Memory/MemoryDriller.h @@ -38,24 +38,24 @@ namespace AZ protected: ////////////////////////////////////////////////////////////////////////// // Driller - virtual const char* GroupName() const { return "SystemDrillers"; } - virtual const char* GetName() const { return "MemoryDriller"; } - virtual const char* GetDescription() const { return "Reports all allocators and memory allocations."; } - virtual void Start(const Param* params = NULL, int numParams = 0); - virtual void Stop(); + const char* GroupName() const override { return "SystemDrillers"; } + const char* GetName() const override { return "MemoryDriller"; } + const char* GetDescription() const override { return "Reports all allocators and memory allocations."; } + void Start(const Param* params = NULL, int numParams = 0) override; + void Stop() override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // MemoryDrillerBus - virtual void RegisterAllocator(IAllocator* allocator); - virtual void UnregisterAllocator(IAllocator* allocator); + void RegisterAllocator(IAllocator* allocator) override; + void UnregisterAllocator(IAllocator* allocator) override; - virtual void RegisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, const char* name, const char* fileName, int lineNum, unsigned int stackSuppressCount); - virtual void UnregisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, AllocationInfo* info); - virtual void ReallocateAllocation(IAllocator* allocator, void* prevAddress, void* newAddress, size_t newByteSize, size_t newAlignment); - virtual void ResizeAllocation(IAllocator* allocator, void* address, size_t newSize); + void RegisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, const char* name, const char* fileName, int lineNum, unsigned int stackSuppressCount) override; + void UnregisterAllocation(IAllocator* allocator, void* address, size_t byteSize, size_t alignment, AllocationInfo* info) override; + void ReallocateAllocation(IAllocator* allocator, void* prevAddress, void* newAddress, size_t newByteSize, size_t newAlignment) override; + void ResizeAllocation(IAllocator* allocator, void* address, size_t newSize) override; - virtual void DumpAllAllocations(); + void DumpAllAllocations() override; ////////////////////////////////////////////////////////////////////////// void RegisterAllocatorOutput(IAllocator* allocator); diff --git a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h index 669fda8a04..c6e7b05341 100644 --- a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h @@ -77,17 +77,17 @@ namespace AZ //--------------------------------------------------------------------- // IAllocatorAllocate //--------------------------------------------------------------------- - virtual pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; - virtual void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; - virtual pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override; - virtual size_type Resize(pointer_type ptr, size_type newSize) override; - virtual size_type AllocationSize(pointer_type ptr) override; - - virtual size_type NumAllocatedBytes() const override; - virtual size_type Capacity() const override; - virtual size_type GetMaxAllocationSize() const override; - virtual IAllocatorAllocate* GetSubAllocator() override; - virtual void GarbageCollect() override; + pointer_type Allocate(size_type byteSize, size_type alignment, int flags, const char* name = 0, const char* fileName = 0, int lineNum = 0, unsigned int suppressStackRecord = 0) override; + void DeAllocate(pointer_type ptr, size_type byteSize = 0, size_type alignment = 0) override; + pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type newAlignment) override; + size_type Resize(pointer_type ptr, size_type newSize) override; + size_type AllocationSize(pointer_type ptr) override; + + size_type NumAllocatedBytes() const override; + size_type Capacity() const override; + size_type GetMaxAllocationSize() const override; + IAllocatorAllocate* GetSubAllocator() override; + void GarbageCollect() override; private: OverrunDetectionSchemaImpl* m_impl; diff --git a/Code/Framework/AzCore/AzCore/Module/Module.h b/Code/Framework/AzCore/AzCore/Module/Module.h index a4843f002c..3809bd1bb4 100644 --- a/Code/Framework/AzCore/AzCore/Module/Module.h +++ b/Code/Framework/AzCore/AzCore/Module/Module.h @@ -62,7 +62,7 @@ namespace AZ * DO NOT OVERRIDE. This method will return in the future, but at this point things reflected here are not unreflected for all ReflectContexts (Serialize, Editor, Network, Script, etc.) * Place all calls to non-component reflect functions inside of a component reflect function to ensure that your types are unreflected. */ - virtual void Reflect(AZ::ReflectContext*) final { } + void Reflect(AZ::ReflectContext*) {} /** * Override to require specific components on the system entity. diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h index b436f5adab..0a1af21213 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.h @@ -594,8 +594,8 @@ namespace AZ void SetArgumentName(size_t index, const AZStd::string& name) override; const AZStd::string* GetArgumentToolTip(size_t index) const override; void SetArgumentToolTip(size_t index, const AZStd::string& name) override; - virtual void SetDefaultValue(size_t index, BehaviorDefaultValuePtr defaultValue) override; - virtual BehaviorDefaultValuePtr GetDefaultValue(size_t index) const override; + void SetDefaultValue(size_t index, BehaviorDefaultValuePtr defaultValue) override; + BehaviorDefaultValuePtr GetDefaultValue(size_t index) const override; const BehaviorParameter* GetResult() const override; void OverrideParameterTraits(size_t index, AZ::u32 addTraits, AZ::u32 removeTraits) override; diff --git a/Code/Framework/AzCore/AzCore/RTTI/RTTI.h b/Code/Framework/AzCore/AzCore/RTTI/RTTI.h index fa081a9497..43bc1660ee 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/RTTI.h +++ b/Code/Framework/AzCore/AzCore/RTTI/RTTI.h @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZCORE_RTTI_H -#define AZCORE_RTTI_H + +#pragma once #include #include @@ -44,21 +44,9 @@ namespace AZ /// RTTI typeId typedef void (* RTTI_EnumCallback)(const AZ::TypeId& /*typeId*/, void* /*userData*/); - // Disabling missing override warning because we intentionally want to allow for declaring RTTI base classes that don't impelment RTTI. -#if defined(AZ_COMPILER_CLANG) -# define AZ_PUSH_DISABLE_OVERRIDE_WARNING \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Winconsistent-missing-override\"") -# define AZ_POP_DISABLE_OVERRIDE_WARNING \ - _Pragma("clang diagnostic pop") -#else -# define AZ_PUSH_DISABLE_OVERRIDE_WARNING -# define AZ_POP_DISABLE_OVERRIDE_WARNING -#endif - // We require AZ_TYPE_INFO to be declared #define AZ_RTTI_COMMON() \ - AZ_PUSH_DISABLE_OVERRIDE_WARNING \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ void RTTI_Enable(); \ virtual inline const AZ::TypeId& RTTI_GetType() const { return RTTI_Type(); } \ virtual inline const char* RTTI_GetTypeName() const { return RTTI_TypeName(); } \ @@ -66,7 +54,7 @@ namespace AZ virtual void RTTI_EnumTypes(AZ::RTTI_EnumCallback cb, void* userData) { RTTI_EnumHierarchy(cb, userData); } \ static inline const AZ::TypeId& RTTI_Type() { return TYPEINFO_Uuid(); } \ static inline const char* RTTI_TypeName() { return TYPEINFO_Name(); } \ - AZ_POP_DISABLE_OVERRIDE_WARNING + AZ_POP_DISABLE_WARNING //#define AZ_RTTI_1(_1) static_assert(false,"You must provide a valid classUuid!") @@ -74,8 +62,10 @@ namespace AZ #define AZ_RTTI_1() AZ_RTTI_COMMON() \ static bool RTTI_IsContainType(const AZ::TypeId& id) { return id == RTTI_Type(); } \ static void RTTI_EnumHierarchy(AZ::RTTI_EnumCallback cb, void* userData) { cb(RTTI_Type(), userData); } \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { return (id == RTTI_Type()) ? this : nullptr; } \ - virtual inline void* RTTI_AddressOf(const AZ::TypeId& id) { return (id == RTTI_Type()) ? this : nullptr; } + virtual inline void* RTTI_AddressOf(const AZ::TypeId& id) { return (id == RTTI_Type()) ? this : nullptr; } \ + AZ_POP_DISABLE_WARNING /// AZ_RTTI(BaseClass) #define AZ_RTTI_2(_1) AZ_RTTI_COMMON() \ @@ -85,14 +75,14 @@ namespace AZ static void RTTI_EnumHierarchy(AZ::RTTI_EnumCallback cb, void* userData) { \ cb(RTTI_Type(), userData); \ AZ::Internal::RttiCaller<_1>::RTTI_EnumHierarchy(cb, userData); } \ - AZ_PUSH_DISABLE_OVERRIDE_WARNING \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \ if (id == RTTI_Type()) { return this; } \ return AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); } \ virtual inline void* RTTI_AddressOf(const AZ::TypeId& id) { \ if (id == RTTI_Type()) { return this; } \ return AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); } \ - AZ_POP_DISABLE_OVERRIDE_WARNING + AZ_POP_DISABLE_WARNING /// AZ_RTTI(BaseClass1,BaseClass2) #define AZ_RTTI_3(_1, _2) AZ_RTTI_COMMON() \ @@ -104,7 +94,7 @@ namespace AZ cb(RTTI_Type(), userData); \ AZ::Internal::RttiCaller<_1>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_2>::RTTI_EnumHierarchy(cb, userData); } \ - AZ_PUSH_DISABLE_OVERRIDE_WARNING \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \ if (id == RTTI_Type()) { return this; } \ const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \ @@ -113,7 +103,7 @@ namespace AZ if (id == RTTI_Type()) { return this; } \ void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \ return AZ::Internal::RttiCaller<_2>::RTTI_AddressOf(this, id); } \ - AZ_POP_DISABLE_OVERRIDE_WARNING + AZ_POP_DISABLE_WARNING /// AZ_RTTI(BaseClass1,BaseClass2,BaseClass3) #define AZ_RTTI_4(_1, _2, _3) AZ_RTTI_COMMON() \ @@ -127,7 +117,7 @@ namespace AZ AZ::Internal::RttiCaller<_1>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_2>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_3>::RTTI_EnumHierarchy(cb, userData); } \ - AZ_PUSH_DISABLE_OVERRIDE_WARNING \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \ if (id == RTTI_Type()) { return this; } \ const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \ @@ -138,7 +128,7 @@ namespace AZ void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \ r = AZ::Internal::RttiCaller<_2>::RTTI_AddressOf(this, id); if (r) { return r; } \ return AZ::Internal::RttiCaller<_3>::RTTI_AddressOf(this, id); } \ - AZ_POP_DISABLE_OVERRIDE_WARNING + AZ_POP_DISABLE_WARNING /// AZ_RTTI(BaseClass1,BaseClass2,BaseClass3,BaseClass4) #define AZ_RTTI_5(_1, _2, _3, _4) AZ_RTTI_COMMON() \ @@ -154,7 +144,7 @@ namespace AZ AZ::Internal::RttiCaller<_2>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_3>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_4>::RTTI_EnumHierarchy(cb, userData); } \ - AZ_PUSH_DISABLE_OVERRIDE_WARNING \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \ if (id == RTTI_Type()) { return this; } \ const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \ @@ -167,7 +157,7 @@ namespace AZ r = AZ::Internal::RttiCaller<_2>::RTTI_AddressOf(this, id); if (r) { return r; } \ r = AZ::Internal::RttiCaller<_3>::RTTI_AddressOf(this, id); if (r) { return r; } \ return AZ::Internal::RttiCaller<_4>::RTTI_AddressOf(this, id); } \ - AZ_POP_DISABLE_OVERRIDE_WARNING + AZ_POP_DISABLE_WARNING /// AZ_RTTI(BaseClass1,BaseClass2,BaseClass3,BaseClass4,BaseClass5) #define AZ_RTTI_6(_1, _2, _3, _4, _5) AZ_RTTI_COMMON() \ @@ -185,7 +175,7 @@ namespace AZ AZ::Internal::RttiCaller<_3>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_4>::RTTI_EnumHierarchy(cb, userData); \ AZ::Internal::RttiCaller<_5>::RTTI_EnumHierarchy(cb, userData); } \ - AZ_PUSH_DISABLE_OVERRIDE_WARNING \ + AZ_PUSH_DISABLE_WARNING(26433, "-Winconsistent-missing-override") \ virtual inline const void* RTTI_AddressOf(const AZ::TypeId& id) const { \ if (id == RTTI_Type()) { return this; } \ const void* r = AZ::Internal::RttiCaller<_1>::RTTI_AddressOf(this, id); if (r) { return r; } \ @@ -200,7 +190,7 @@ namespace AZ r = AZ::Internal::RttiCaller<_3>::RTTI_AddressOf(this, id); if (r) { return r; } \ r = AZ::Internal::RttiCaller<_4>::RTTI_AddressOf(this, id); if (r) { return r; } \ return AZ::Internal::RttiCaller<_5>::RTTI_AddressOf(this, id); } \ - AZ_POP_DISABLE_OVERRIDE_WARNING + AZ_POP_DISABLE_WARNING ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MACRO specialization to allow optional parameters for template version of AZ_RTTI @@ -1077,7 +1067,6 @@ namespace AZ { return AZ::Internal::RttiIsTypeOfIdHelper::Check(id, data, typename HasAZRtti>::kind_type()); } + } // namespace AZ -#endif // AZCORE_RTTI_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.h index c46ba32209..a691bb1bcb 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSystemComponent.h @@ -19,8 +19,8 @@ namespace AZ public: AZ_COMPONENT(JsonSystemComponent, "{3C2C7234-9512-4E24-86F0-C40865D7EECE}", Component); - void Activate(); - void Deactivate(); + void Activate() override; + void Deactivate() override; static void Reflect(ReflectContext* reflectContext); }; diff --git a/Code/Framework/AzCore/AzCore/UserSettings/UserSettingsProvider.h b/Code/Framework/AzCore/AzCore/UserSettings/UserSettingsProvider.h index 4721d3baa8..6a807c915e 100644 --- a/Code/Framework/AzCore/AzCore/UserSettings/UserSettingsProvider.h +++ b/Code/Framework/AzCore/AzCore/UserSettings/UserSettingsProvider.h @@ -116,9 +116,9 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// // UserSettingsBus - virtual AZStd::intrusive_ptr FindUserSettings(u32 id); - virtual void AddUserSettings(u32 id, UserSettings* settings); - virtual bool Save(const char* settingsPath, SerializeContext* sc); + AZStd::intrusive_ptr FindUserSettings(u32 id) override; + void AddUserSettings(u32 id, UserSettings* settings) override; + bool Save(const char* settingsPath, SerializeContext* sc) override; ////////////////////////////////////////////////////////////////////////// static void Reflect(ReflectContext* reflection); diff --git a/Code/Framework/AzCore/AzCore/std/parallel/thread.h b/Code/Framework/AzCore/AzCore/std/parallel/thread.h index 9f7830c91b..15d8c9dc8e 100644 --- a/Code/Framework/AzCore/AzCore/std/parallel/thread.h +++ b/Code/Framework/AzCore/AzCore/std/parallel/thread.h @@ -187,7 +187,7 @@ namespace AZStd : m_f(AZStd::move(f)) {} thread_info_impl(Internal::thread_move_t f) : m_f(f) {} - virtual void execute() { m_f(); } + void execute() override { m_f(); } private: F m_f; diff --git a/Code/Framework/AzCore/AzCore/std/smart_ptr/shared_count.h b/Code/Framework/AzCore/AzCore/std/smart_ptr/shared_count.h index c86adbd69e..ac49dc9ae5 100644 --- a/Code/Framework/AzCore/AzCore/std/smart_ptr/shared_count.h +++ b/Code/Framework/AzCore/AzCore/std/smart_ptr/shared_count.h @@ -129,16 +129,16 @@ namespace AZStd { } - virtual void dispose() // nothrow + void dispose() override // nothrow { AZStd::checked_delete(px_); } - virtual void destroy() // nothrow + void destroy() override // nothrow { this->~this_type(); a_.deallocate(this, sizeof(this_type), AZStd::alignment_of::value); } - virtual void* get_deleter(Internal::sp_typeinfo const&) + void* get_deleter(Internal::sp_typeinfo const&) override { return 0; } @@ -176,18 +176,18 @@ namespace AZStd { } - virtual void dispose() // nothrow + void dispose() override // nothrow { d_(p_); } - virtual void destroy() // nothrow + void destroy() override // nothrow { this->~this_type(); a_.deallocate(this, sizeof(this_type), AZStd::alignment_of::value); } - virtual void* get_deleter(Internal::sp_typeinfo const& ti) + void* get_deleter(Internal::sp_typeinfo const& ti) override { return ti == aztypeid(D) ? &reinterpret_cast(d_) : 0; } diff --git a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Memory/OverrunDetectionAllocator_WinAPI.h b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Memory/OverrunDetectionAllocator_WinAPI.h index 19f83374e7..b5cdc11d5d 100644 --- a/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Memory/OverrunDetectionAllocator_WinAPI.h +++ b/Code/Framework/AzCore/Platform/Common/WinAPI/AzCore/Memory/OverrunDetectionAllocator_WinAPI.h @@ -21,7 +21,7 @@ namespace AZ class WinAPIOverrunDetectionSchema : public OverrunDetectionSchema::PlatformAllocator { public: - virtual SystemInformation GetSystemInformation() override + SystemInformation GetSystemInformation() override { SystemInformation result; SYSTEM_INFO info; @@ -32,7 +32,7 @@ namespace AZ return result; } - virtual void* ReserveBytes(size_t amount) override + void* ReserveBytes(size_t amount) override { void* result = VirtualAlloc(0, amount, MEM_RESERVE, PAGE_NOACCESS); @@ -45,12 +45,12 @@ namespace AZ return result; } - virtual void ReleaseReservedBytes(void* base) override + void ReleaseReservedBytes(void* base) override { VirtualFree(base, 0, MEM_RELEASE); } - virtual void* CommitBytes(void* base, size_t amount) override + void* CommitBytes(void* base, size_t amount) override { void* result = VirtualAlloc(base, amount, MEM_COMMIT, PAGE_READWRITE); @@ -63,7 +63,7 @@ namespace AZ return result; } - virtual void DecommitBytes(void* base, size_t amount) override + void DecommitBytes(void* base, size_t amount) override { VirtualFree(base, amount, MEM_DECOMMIT); } From 9e0ff8e55dab4520ae2ac3f19614d0a379faedf3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 18:36:40 -0700 Subject: [PATCH 027/274] disabling external headers for analyzer Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 1 + cmake/Platform/Common/MSVC/Directory.Build.props | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index c613b79d87..01e3063028 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -136,6 +136,7 @@ endif() ly_set(LY_CXX_SYSTEM_INCLUDE_CONFIGURATION_FLAG /experimental:external # Turns on "external" headers feature for MSVC compilers /external:W0 # Set warning level in external headers to 0. This is used to suppress warnings 3rdParty libraries which uses the "system_includes" option in their json configuration + /analyze:external- # disable analysis on external headers ) if(NOT CMAKE_INCLUDE_SYSTEM_FLAG_CXX) ly_set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX /external:I) diff --git a/cmake/Platform/Common/MSVC/Directory.Build.props b/cmake/Platform/Common/MSVC/Directory.Build.props index 4b82cd7048..589e14a6cb 100644 --- a/cmake/Platform/Common/MSVC/Directory.Build.props +++ b/cmake/Platform/Common/MSVC/Directory.Build.props @@ -22,6 +22,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT handles external headers in MSVC, we can remove that code and this --> TurnOffAllWarnings + + true From cc00a535d72b2e36cc7fa7ccfbad83e3dec719ec Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 18:37:45 -0700 Subject: [PATCH 028/274] more Code/Framework fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AzCore/AzCore/Component/Component.h | 2 +- Code/Framework/AzCore/AzCore/RTTI/RTTI.h | 5 +---- .../AzFramework/Archive/ArchiveFileIO.h | 2 +- .../AzFramework/Archive/NestedArchive.h | 20 +++++++++---------- .../AzFramework/Asset/GenericAssetHandler.h | 4 ++-- .../Components/NonUniformScaleComponent.h | 2 +- .../Entity/GameEntityContextComponent.h | 2 +- .../AzFramework/Logging/LoggingComponent.h | 6 +++--- .../Viewport/ViewportControllerList.h | 4 ++-- Code/Framework/AzTest/AzTest/AzTest.h | 8 ++++---- .../Replica/Interest/BitmaskInterestHandler.h | 2 +- 11 files changed, 27 insertions(+), 30 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/Component.h b/Code/Framework/AzCore/AzCore/Component/Component.h index 9b4ae3f55f..3cbb9b5a86 100644 --- a/Code/Framework/AzCore/AzCore/Component/Component.h +++ b/Code/Framework/AzCore/AzCore/Component/Component.h @@ -266,7 +266,7 @@ namespace AZ _ComponentClass::RTTI_Type().ToString().c_str(), descriptor->GetName(), _ComponentClass::RTTI_TypeName()); \ return nullptr; \ } \ - else if (descriptor->GetName() != _ComponentClass::RTTI_TypeName()) \ + if (descriptor->GetName() != _ComponentClass::RTTI_TypeName()) \ { \ AZ_Error("Component", false, "The same component UUID (%s) / name (%s) was registered twice. This isn't allowed, " \ "it can cause lifetime management issues / crashes.\nThis situation can happen by declaring a component " \ diff --git a/Code/Framework/AzCore/AzCore/RTTI/RTTI.h b/Code/Framework/AzCore/AzCore/RTTI/RTTI.h index 43bc1660ee..acf6f64f77 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/RTTI.h +++ b/Code/Framework/AzCore/AzCore/RTTI/RTTI.h @@ -941,10 +941,7 @@ namespace AZ { return AZStd::shared_ptr(ptr, castPtr); } - else - { - return AZStd::shared_ptr(); - } + return AZStd::shared_ptr(); } // RttiCast specialization for intrusive_ptr. diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h index 2cd8f37adc..c99fbb14c5 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h @@ -65,7 +65,7 @@ namespace AZ::IO void SetAlias(const char* alias, const char* path) override; void ClearAlias(const char* alias) override; AZStd::optional ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override; - bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const; + bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override; using FileIOBase::ConvertToAlias; const char* GetAlias(const char* alias) const override; bool ResolvePath(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const override; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h index 8ab943a24e..eac98b2f07 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h @@ -40,7 +40,7 @@ namespace AZ::IO NestedArchive(IArchive* pArchive, AZStd::string_view strBindRoot, ZipDir::CachePtr pCache, uint32_t nFlags = 0); ~NestedArchive() override; - auto GetRootFolderHandle() -> Handle; + auto GetRootFolderHandle() -> Handle override; // Adds a new file to the zip or update an existing one // adds a directory (creates several nested directories if needed) @@ -66,26 +66,26 @@ namespace AZ::IO int RemoveDir(AZStd::string_view szRelativePath) override; // deletes all files from the archive - int RemoveAll(); + int RemoveAll() override; // finds the file; you don't have to close the returned handle - Handle FindFile(AZStd::string_view szRelativePath); + Handle FindFile(AZStd::string_view szRelativePath) override; // returns the size of the file (unpacked) by the handle - uint64_t GetFileSize(Handle fileHandle); + uint64_t GetFileSize(Handle fileHandle) override; // reads the file into the preallocated buffer (must be at least the size of GetFileSize()) - int ReadFile(Handle fileHandle, void* pBuffer); + int ReadFile(Handle fileHandle, void* pBuffer) override; // returns the full path to the archive file - const char* GetFullPath() const; + const char* GetFullPath() const override; ZipDir::Cache* GetCache(); - uint32_t GetFlags() const; - bool SetFlags(uint32_t nFlagsToSet); - bool ResetFlags(uint32_t nFlagsToReset); + uint32_t GetFlags() const override; + bool SetFlags(uint32_t nFlagsToSet) override; + bool ResetFlags(uint32_t nFlagsToReset) override; - bool SetPackAccessible(bool bAccessible); + bool SetPackAccessible(bool bAccessible) override; protected: // returns the pointer to the relative file path to be passed diff --git a/Code/Framework/AzFramework/AzFramework/Asset/GenericAssetHandler.h b/Code/Framework/AzFramework/AzFramework/Asset/GenericAssetHandler.h index 5ead8154e6..4c3f911871 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/GenericAssetHandler.h +++ b/Code/Framework/AzFramework/AzFramework/Asset/GenericAssetHandler.h @@ -75,7 +75,7 @@ namespace AzFramework { public: AZ_RTTI(GenericAssetHandlerBase, "{B153B8B5-25CC-4BB7-A2BD-9A47ECF4123C}", AZ::Data::AssetHandler); - virtual ~GenericAssetHandlerBase() {} + virtual ~GenericAssetHandlerBase() = default; }; template @@ -186,7 +186,7 @@ namespace AzFramework } } - bool CanHandleAsset(const AZ::Data::AssetId& id) const + bool CanHandleAsset(const AZ::Data::AssetId& id) const override { AZStd::string assetPath; EBUS_EVENT_RESULT(assetPath, AZ::Data::AssetCatalogRequestBus, GetAssetPathById, id); diff --git a/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.h b/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.h index 16032e5337..bc1bf1a6b2 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Components/NonUniformScaleComponent.h @@ -28,7 +28,7 @@ namespace AzFramework // AZ::NonUniformScaleRequests::Handler ... AZ::Vector3 GetScale() const override; void SetScale(const AZ::Vector3& scale) override; - void RegisterScaleChangedEvent(AZ::NonUniformScaleChangedEvent::Handler& handler); + void RegisterScaleChangedEvent(AZ::NonUniformScaleChangedEvent::Handler& handler) override; protected: // AZ::Component ... diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h index 831067d728..b9a4ea0da1 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h @@ -69,7 +69,7 @@ namespace AzFramework // EntityContext AZ::Entity* CreateEntity(const char* name) override; void OnRootEntityReloaded() override; - void OnContextEntitiesAdded(const EntityList& entities); + void OnContextEntitiesAdded(const EntityList& entities) override; void OnContextReset() override; bool ValidateEntitiesAreValidForContext(const EntityList& entities) override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzFramework/AzFramework/Logging/LoggingComponent.h b/Code/Framework/AzFramework/AzFramework/Logging/LoggingComponent.h index 98eb6df95a..73f2ff2c75 100644 --- a/Code/Framework/AzFramework/AzFramework/Logging/LoggingComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Logging/LoggingComponent.h @@ -31,9 +31,9 @@ namespace AzFramework ////////////////////////////////////////////////////////////////////////// // AZ::Component - virtual void Init(); - virtual void Activate(); - virtual void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportControllerList.h b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportControllerList.h index 4016f29f8f..7a31665259 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ViewportControllerList.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ViewportControllerList.h @@ -45,10 +45,10 @@ namespace AzFramework //! All current and added controllers will be registered with this viewport. void RegisterViewportContext(ViewportId viewport) override; //! Unregisters a Viewport from this list and all associated controllers. - void UnregisterViewportContext(ViewportId viewport); + void UnregisterViewportContext(ViewportId viewport) override; //! All ViewportControllerLists have a priority of Custom to ensure //! that they receive events at all priorities from any parent controllers. - AzFramework::ViewportControllerPriority GetPriority() const { return ViewportControllerPriority::DispatchToAllPriorities; } + AzFramework::ViewportControllerPriority GetPriority() const override { return ViewportControllerPriority::DispatchToAllPriorities; } //! Returns true if this controller list is enabled, i.e. //! it is accepting and forwarding input and update events to its children. bool IsEnabled() const; diff --git a/Code/Framework/AzTest/AzTest/AzTest.h b/Code/Framework/AzTest/AzTest/AzTest.h index 18e846f9d8..352db1a0b5 100644 --- a/Code/Framework/AzTest/AzTest/AzTest.h +++ b/Code/Framework/AzTest/AzTest/AzTest.h @@ -44,12 +44,12 @@ namespace AZ virtual ~ITestEnvironment() {} - void SetUp() override final + void SetUp() final { SetupEnvironment(); } - void TearDown() override final + void TearDown() final { TeardownEnvironment(); } @@ -218,7 +218,7 @@ namespace AZ public: std::list resultList; - void OnTestEnd(const ::testing::TestInfo& test_info) + void OnTestEnd(const ::testing::TestInfo& test_info) override { std::string result; if (test_info.result()->Failed()) @@ -233,7 +233,7 @@ namespace AZ resultList.emplace_back(formattedResult); } - void OnTestProgramEnd(const ::testing::UnitTest& unit_test) + void OnTestProgramEnd(const ::testing::UnitTest& unit_test) override { for (std::string testResults : resultList) { diff --git a/Code/Framework/GridMate/GridMate/Replica/Interest/BitmaskInterestHandler.h b/Code/Framework/GridMate/GridMate/Replica/Interest/BitmaskInterestHandler.h index 3de3fe8bfe..6b91859c95 100644 --- a/Code/Framework/GridMate/GridMate/Replica/Interest/BitmaskInterestHandler.h +++ b/Code/Framework/GridMate/GridMate/Replica/Interest/BitmaskInterestHandler.h @@ -133,7 +133,7 @@ namespace GridMate typedef AZStd::intrusive_ptr Ptr; bool IsReplicaMigratable() override { return false; } - bool IsBroadcast() { return true; } + bool IsBroadcast() override { return true; } static const char* GetChunkName() { return "BitmaskInterestChunk"; } void OnReplicaActivate(const ReplicaContext& rc) override; From 7d34004b6de173be438d7bd8d796632a3b99b8ac Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 18:38:05 -0700 Subject: [PATCH 029/274] some Code/Legacy fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Legacy/CryCommon/IConsole.h | 44 ++--- Code/Legacy/CryCommon/ILocalizationManager.h | 64 +++---- .../Legacy/CrySystem/LocalizedStringManager.h | 68 +++---- Code/Legacy/CrySystem/System.h | 170 +++++++++--------- Code/Legacy/CrySystem/Timer.h | 54 +++--- Code/Legacy/CrySystem/ViewSystem/View.h | 32 ++-- Code/Legacy/CrySystem/ViewSystem/ViewSystem.h | 68 +++---- Code/Legacy/CrySystem/XConsole.h | 156 ++++++++-------- Code/Legacy/CrySystem/XConsoleVariable.h | 96 +++++----- Code/Legacy/CrySystem/XML/XmlUtils.cpp | 56 +++--- 10 files changed, 404 insertions(+), 404 deletions(-) diff --git a/Code/Legacy/CryCommon/IConsole.h b/Code/Legacy/CryCommon/IConsole.h index f68a82f9dc..b99d4c84b9 100644 --- a/Code/Legacy/CryCommon/IConsole.h +++ b/Code/Legacy/CryCommon/IConsole.h @@ -84,7 +84,7 @@ enum EVarFlags struct ICVarDumpSink { // - virtual ~ICVarDumpSink(){} + virtual ~ICVarDumpSink()= default; virtual void OnElementFound(ICVar* pCVar) = 0; // }; @@ -92,7 +92,7 @@ struct ICVarDumpSink struct IKeyBindDumpSink { // - virtual ~IKeyBindDumpSink(){} + virtual ~IKeyBindDumpSink()= default; virtual void OnKeyBindFound(const char* sBind, const char* sCommand) = 0; // }; @@ -100,7 +100,7 @@ struct IKeyBindDumpSink struct IOutputPrintSink { // - virtual ~IOutputPrintSink(){} + virtual ~IOutputPrintSink()= default; virtual void Print(const char* inszText) = 0; // }; @@ -109,7 +109,7 @@ struct IOutputPrintSink struct IConsoleVarSink { // - virtual ~IConsoleVarSink(){} + virtual ~IConsoleVarSink()= default; // Called by Console before changing console var value, to validate if var can be changed. // Return value: true if ok to change value, false if should not change value. virtual bool OnBeforeVarChange(ICVar* pVar, const char* sNewValue) = 0; @@ -122,7 +122,7 @@ struct IConsoleVarSink struct IConsoleCmdArgs { // - virtual ~IConsoleCmdArgs(){} + virtual ~IConsoleCmdArgs()= default; // Gets number of arguments supplied to the command (including the command itself) virtual int GetArgCount() const = 0; // Gets argument by index, nIndex must be in 0 <= nIndex < GetArgCount() @@ -136,7 +136,7 @@ struct IConsoleCmdArgs struct IConsoleArgumentAutoComplete { // - virtual ~IConsoleArgumentAutoComplete(){} + virtual ~IConsoleArgumentAutoComplete()= default; // Gets number of matches for the argument to auto complete. virtual int GetCount() const = 0; // Gets argument value by index, nIndex must be in 0 <= nIndex < GetCount() @@ -145,10 +145,10 @@ struct IConsoleArgumentAutoComplete }; // This a definition of the console command function that can be added to console with AddCommand. -typedef void (* ConsoleCommandFunc)(IConsoleCmdArgs*); +using ConsoleCommandFunc = void (*)(IConsoleCmdArgs*); // This a definition of the callback function that is called when variable change. -typedef void (* ConsoleVarFunc)(ICVar*); +using ConsoleVarFunc = void (*)(ICVar*); /* Summary: Interface to the engine console. @@ -165,7 +165,7 @@ typedef void (* ConsoleVarFunc)(ICVar*); struct IConsole { // - virtual ~IConsole(){} + virtual ~IConsole()= default; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Deletes the console virtual void Release() = 0; @@ -182,7 +182,7 @@ struct IConsole // help - help text that is shown when you use ? in the console // Return: // pointer to the interface ICVar - virtual ICVar* RegisterString(const char* sName, const char* sValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) = 0; + virtual ICVar* RegisterString(const char* sName, const char* sValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) = 0; // Create a new console variable that store the value in a int // Arguments: // sName - console variable name @@ -191,7 +191,7 @@ struct IConsole // help - help text that is shown when you use ? in the console // Return: // pointer to the interface ICVar - virtual ICVar* RegisterInt(const char* sName, int iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) = 0; + virtual ICVar* RegisterInt(const char* sName, int iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) = 0; // Create a new console variable that store the value in a int64 // Arguments: // sName - console variable name @@ -200,7 +200,7 @@ struct IConsole // help - help text that is shown when you use ? in the console // Return: // pointer to the interface ICVar - virtual ICVar* RegisterInt64(const char* sName, int64 iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) = 0; + virtual ICVar* RegisterInt64(const char* sName, int64 iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) = 0; // Create a new console variable that store the value in a float // Arguments: // sName - console variable name @@ -209,7 +209,7 @@ struct IConsole // help - help text that is shown when you use ? in the console // Return: // pointer to the interface ICVar - virtual ICVar* RegisterFloat(const char* sName, float fValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0) = 0; + virtual ICVar* RegisterFloat(const char* sName, float fValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) = 0; // Create a new console variable that will update the user defined float // Arguments: @@ -220,7 +220,7 @@ struct IConsole // allowModify - allow modification through config vars, prevents missing modifications in release mode // Return: // pointer to the interface ICVar - virtual ICVar* Register(const char* name, float* src, float defaultvalue, int nFlags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true) = 0; + virtual ICVar* Register(const char* name, float* src, float defaultvalue, int nFlags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr, bool allowModify = true) = 0; // Create a new console variable that will update the user defined integer // Arguments: // sName - console variable name @@ -230,7 +230,7 @@ struct IConsole // allowModify - allow modification through config vars, prevents missing modifications in release mode // Return: // pointer to the interface ICVar - virtual ICVar* Register(const char* name, int* src, int defaultvalue, int nFlags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true) = 0; + virtual ICVar* Register(const char* name, int* src, int defaultvalue, int nFlags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr, bool allowModify = true) = 0; // Create a new console variable that will update the user defined pointer to null terminated string // Arguments: @@ -241,7 +241,7 @@ struct IConsole // allowModify - allow modification through config vars, prevents missing modifications in release mode // Return: // pointer to the interface ICVar - virtual ICVar* Register(const char* name, const char** src, const char* defaultvalue, int nFlags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true) = 0; + virtual ICVar* Register(const char* name, const char** src, const char* defaultvalue, int nFlags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr, bool allowModify = true) = 0; // Registers an existing console variable // Should only be used with static duration objects, object is never freed @@ -367,7 +367,7 @@ struct IConsole // sHelp - Help string, will be displayed when typing in console "command ?". // Return // True if successful, false otherwise. - virtual bool AddCommand(const char* sCommand, ConsoleCommandFunc func, int nFlags = 0, const char* sHelp = NULL) = 0; + virtual bool AddCommand(const char* sCommand, ConsoleCommandFunc func, int nFlags = 0, const char* sHelp = nullptr) = 0; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description: @@ -382,7 +382,7 @@ struct IConsole // Return // True if successful, false otherwise. //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - virtual bool AddCommand(const char* sName, const char* sScriptFunc, int nFlags = 0, const char* sHelp = NULL) = 0; + virtual bool AddCommand(const char* sName, const char* sScriptFunc, int nFlags = 0, const char* sHelp = nullptr) = 0; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description: @@ -421,7 +421,7 @@ struct IConsole // szPrefix - 0 or prefix e.g. "sys_spec_" // Return // used size - virtual size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = 0) = 0; + virtual size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = nullptr) = 0; virtual const char* AutoComplete(const char* substr) = 0; virtual const char* AutoCompletePrev(const char* substr) = 0; virtual const char* ProcessCompletion(const char* szInputBuffer) = 0; @@ -488,7 +488,7 @@ struct IConsole // This interface for the remote console struct IRemoteConsoleListener { - virtual ~IRemoteConsoleListener() {} + virtual ~IRemoteConsoleListener() = default; virtual void OnConsoleCommand([[maybe_unused]] const char* cmd) {}; virtual void OnGameplayCommand([[maybe_unused]] const char* cmd) {}; @@ -496,7 +496,7 @@ struct IRemoteConsoleListener struct IRemoteConsole { - virtual ~IRemoteConsole() {}; + virtual ~IRemoteConsole() = default;; virtual void RegisterConsoleVariables() = 0; virtual void UnregisterConsoleVariables() = 0; @@ -535,7 +535,7 @@ struct ICVar // // TODO make protected; - virtual ~ICVar() {} + virtual ~ICVar() = default; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// // delete the variable // NOTE: the variable will automatically unregister itself from the console diff --git a/Code/Legacy/CryCommon/ILocalizationManager.h b/Code/Legacy/CryCommon/ILocalizationManager.h index 0f0ba88250..8646906dfe 100644 --- a/Code/Legacy/CryCommon/ILocalizationManager.h +++ b/Code/Legacy/CryCommon/ILocalizationManager.h @@ -28,7 +28,7 @@ class XmlNodeRef; struct SLocalizedInfoGame { SLocalizedInfoGame () - : szCharacterName(NULL) + : szCharacterName(nullptr) , bUseSubtitle(false) { } @@ -54,15 +54,15 @@ struct SLocalizedSoundInfoGame : public SLocalizedInfoGame { SLocalizedSoundInfoGame() - : sSoundEvent(NULL) + : sSoundEvent(nullptr) , fVolume(0.f) , fRadioRatio (0.f) , bIsDirectRadio(false) , bIsIntercepted(false) , nNumSoundMoods(0) - , pSoundMoods (NULL) + , pSoundMoods (nullptr) , nNumEventParameters(0) - , pEventParameters(NULL) + , pEventParameters(nullptr) { } @@ -86,10 +86,10 @@ struct SLocalizedInfoEditor : public SLocalizedInfoGame { SLocalizedInfoEditor() - : sKey(NULL) - , sOriginalCharacterName(NULL) - , sOriginalActorLine(NULL) - , sUtf8TranslatedActorLine(NULL) + : sKey(nullptr) + , sOriginalCharacterName(nullptr) + , sOriginalActorLine(nullptr) + , sUtf8TranslatedActorLine(nullptr) , nRow(0) { } @@ -137,21 +137,21 @@ struct ILocalizationManager ePILID_MAX_OR_INVALID, //Not a language, denotes the maximum number of languages or an unknown language }; - typedef uint32 TLocalizationBitfield; + using TLocalizationBitfield = uint32; // - virtual ~ILocalizationManager(){} + virtual ~ILocalizationManager()= default; virtual const char* LangNameFromPILID(const ILocalizationManager::EPlatformIndependentLanguageID id) = 0; virtual ILocalizationManager::EPlatformIndependentLanguageID PILIDFromLangName(AZStd::string langName) = 0; virtual ILocalizationManager::EPlatformIndependentLanguageID GetSystemLanguage() { return ILocalizationManager::EPlatformIndependentLanguageID::ePILID_English_US; } virtual ILocalizationManager::TLocalizationBitfield MaskSystemLanguagesFromSupportedLocalizations(const ILocalizationManager::TLocalizationBitfield systemLanguages) = 0; virtual ILocalizationManager::TLocalizationBitfield IsLanguageSupported(const ILocalizationManager::EPlatformIndependentLanguageID id) = 0; - virtual bool SetLanguage([[maybe_unused]] const char* sLanguage) override { return false; } - virtual const char* GetLanguage() override { return nullptr; } + bool SetLanguage([[maybe_unused]] const char* sLanguage) override { return false; } + const char* GetLanguage() override { return nullptr; } - virtual int GetLocalizationFormat() const { return -1; } - virtual AZStd::string GetLocalizedSubtitleFilePath([[maybe_unused]] const AZStd::string& localVideoPath, [[maybe_unused]] const AZStd::string& subtitleFileExtension) const { return ""; } - virtual AZStd::string GetLocalizedLocXMLFilePath([[maybe_unused]] const AZStd::string& localXmlPath) const { return ""; } + int GetLocalizationFormat() const override { return -1; } + AZStd::string GetLocalizedSubtitleFilePath([[maybe_unused]] const AZStd::string& localVideoPath, [[maybe_unused]] const AZStd::string& subtitleFileExtension) const override { return ""; } + AZStd::string GetLocalizedLocXMLFilePath([[maybe_unused]] const AZStd::string& localXmlPath) const override { return ""; } // load the descriptor file with tag information virtual bool InitLocalizationData(const char* sFileName, bool bReload = false) = 0; // request to load loca data by tag. Actual loading will happen during next level load begin event. @@ -161,8 +161,8 @@ struct ILocalizationManager virtual bool ReleaseLocalizationDataByTag(const char* sTag) = 0; virtual bool LoadAllLocalizationData(bool bReload = false) = 0; - virtual bool LoadExcelXmlSpreadsheet([[maybe_unused]] const char* sFileName, [[maybe_unused]] bool bReload = false) override { return false; } - virtual void ReloadData() override {}; + bool LoadExcelXmlSpreadsheet([[maybe_unused]] const char* sFileName, [[maybe_unused]] bool bReload = false) override { return false; } + void ReloadData() override {}; // Summary: // Free localization data. @@ -178,15 +178,15 @@ struct ILocalizationManager // bEnglish - if true, translates the string into the always present English language. // Returns: // true if localization was successful, false otherwise - virtual bool LocalizeString_ch([[maybe_unused]] const char* sString, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } + bool LocalizeString_ch([[maybe_unused]] const char* sString, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } // Summary: // Same as LocalizeString( const char* sString, AZStd::string& outLocalizedString, bool bEnglish=false ) // but at the moment this is faster. - virtual bool LocalizeString_s([[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } + bool LocalizeString_s([[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } // Summary: - virtual void LocalizeAndSubstituteInternal([[maybe_unused]] AZStd::string& locString, [[maybe_unused]] const AZStd::vector& keys, [[maybe_unused]] const AZStd::vector& values) override {} + void LocalizeAndSubstituteInternal([[maybe_unused]] AZStd::string& locString, [[maybe_unused]] const AZStd::vector& keys, [[maybe_unused]] const AZStd::vector& values) override {} // Return the localized version corresponding to a label. // Description: // A label has to start with '@' sign. @@ -196,7 +196,7 @@ struct ILocalizationManager // bEnglish - if true, returns the always present English version of the label. // Returns: // True if localization was successful, false otherwise. - virtual bool LocalizeLabel([[maybe_unused]] const char* sLabel, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } + bool LocalizeLabel([[maybe_unused]] const char* sLabel, [[maybe_unused]] AZStd::string& outLocalizedString, [[maybe_unused]] bool bEnglish = false) override { return false; } virtual bool IsLocalizedInfoFound([[maybe_unused]] const char* sKey) { return false; } // Summary: @@ -224,7 +224,7 @@ struct ILocalizationManager // Summary: // Return number of localization entries. - virtual int GetLocalizedStringCount() override { return -1; } + int GetLocalizedStringCount() override { return -1; } // Summary: // Get the localization info structure at index nIndex. @@ -251,7 +251,7 @@ struct ILocalizationManager // sLocalizedString - Corresponding english language string. // Returns: // True if successful, false otherwise (key not found). - virtual bool GetEnglishString([[maybe_unused]] const char* sKey, [[maybe_unused]] AZStd::string& sLocalizedString) override { return false; } + bool GetEnglishString([[maybe_unused]] const char* sKey, [[maybe_unused]] AZStd::string& sLocalizedString) override { return false; } // Summary: // Get Subtitle for Key or Label . @@ -261,25 +261,25 @@ struct ILocalizationManager // bForceSubtitle - If true, get subtitle (sLocalized or sEnglish) even if not specified in Data file. // Returns: // True if subtitle found (and outSubtitle filled in), false otherwise. - virtual bool GetSubtitle([[maybe_unused]] const char* sKeyOrLabel, [[maybe_unused]] AZStd::string& outSubtitle, [[maybe_unused]] bool bForceSubtitle = false) override { return false; } + bool GetSubtitle([[maybe_unused]] const char* sKeyOrLabel, [[maybe_unused]] AZStd::string& outSubtitle, [[maybe_unused]] bool bForceSubtitle = false) override { return false; } // Description: // These methods format outString depending on sString with ordered arguments // FormatStringMessage(outString, "This is %2 and this is %1", "second", "first"); // Arguments: // outString - This is first and this is second. - virtual void FormatStringMessage_List([[maybe_unused]] AZStd::string& outString, [[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] const char** sParams, [[maybe_unused]] int nParams) override {} - virtual void FormatStringMessage([[maybe_unused]] AZStd::string& outString, [[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] const char* param1, [[maybe_unused]] const char* param2 = 0, [[maybe_unused]] const char* param3 = 0, [[maybe_unused]] const char* param4 = 0) override {} + void FormatStringMessage_List([[maybe_unused]] AZStd::string& outString, [[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] const char** sParams, [[maybe_unused]] int nParams) override {} + void FormatStringMessage([[maybe_unused]] AZStd::string& outString, [[maybe_unused]] const AZStd::string& sString, [[maybe_unused]] const char* param1, [[maybe_unused]] const char* param2 = nullptr, [[maybe_unused]] const char* param3 = nullptr, [[maybe_unused]] const char* param4 = nullptr) override {} - virtual void LocalizeTime([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShowSeconds, [[maybe_unused]] AZStd::string& outTimeString) override {} - virtual void LocalizeDate([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShort, [[maybe_unused]] bool bIncludeWeekday, [[maybe_unused]] AZStd::string& outDateString) override {} - virtual void LocalizeDuration([[maybe_unused]] int seconds, [[maybe_unused]] AZStd::string& outDurationString) override {} - virtual void LocalizeNumber([[maybe_unused]] int number, [[maybe_unused]] AZStd::string& outNumberString) override {} - virtual void LocalizeNumber_Decimal([[maybe_unused]] float number, [[maybe_unused]] int decimals, [[maybe_unused]] AZStd::string& outNumberString) override {} + void LocalizeTime([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShowSeconds, [[maybe_unused]] AZStd::string& outTimeString) override {} + void LocalizeDate([[maybe_unused]] time_t t, [[maybe_unused]] bool bMakeLocalTime, [[maybe_unused]] bool bShort, [[maybe_unused]] bool bIncludeWeekday, [[maybe_unused]] AZStd::string& outDateString) override {} + void LocalizeDuration([[maybe_unused]] int seconds, [[maybe_unused]] AZStd::string& outDurationString) override {} + void LocalizeNumber([[maybe_unused]] int number, [[maybe_unused]] AZStd::string& outNumberString) override {} + void LocalizeNumber_Decimal([[maybe_unused]] float number, [[maybe_unused]] int decimals, [[maybe_unused]] AZStd::string& outNumberString) override {} // Summary: // Returns true if the project has localization configured for use, false otherwise. - virtual bool ProjectUsesLocalization() const override { return false; } + bool ProjectUsesLocalization() const override { return false; } // static ILINE TLocalizationBitfield LocalizationBitfieldFromPILID(EPlatformIndependentLanguageID pilid) diff --git a/Code/Legacy/CrySystem/LocalizedStringManager.h b/Code/Legacy/CrySystem/LocalizedStringManager.h index 1fba05f9ac..c0a57fd93f 100644 --- a/Code/Legacy/CrySystem/LocalizedStringManager.h +++ b/Code/Legacy/CrySystem/LocalizedStringManager.h @@ -27,7 +27,7 @@ class CLocalizedStringsManager , public ISystemEventListener { public: - typedef std::vector TLocalizationTagVec; + using TLocalizationTagVec = std::vector; constexpr const static size_t LOADING_FIXED_STRING_LENGTH = 2048; constexpr const static size_t COMPRESSION_FIXED_BUFFER_LENGTH = 6144; @@ -36,45 +36,45 @@ public: virtual ~CLocalizedStringsManager(); // ILocalizationManager - const char* LangNameFromPILID(const ILocalizationManager::EPlatformIndependentLanguageID id); + const char* LangNameFromPILID(const ILocalizationManager::EPlatformIndependentLanguageID id) override; ILocalizationManager::EPlatformIndependentLanguageID PILIDFromLangName(AZStd::string langName) override; ILocalizationManager::EPlatformIndependentLanguageID GetSystemLanguage() override; - ILocalizationManager::TLocalizationBitfield MaskSystemLanguagesFromSupportedLocalizations(const ILocalizationManager::TLocalizationBitfield systemLanguages); - ILocalizationManager::TLocalizationBitfield IsLanguageSupported(const ILocalizationManager::EPlatformIndependentLanguageID id); + ILocalizationManager::TLocalizationBitfield MaskSystemLanguagesFromSupportedLocalizations(const ILocalizationManager::TLocalizationBitfield systemLanguages) override; + ILocalizationManager::TLocalizationBitfield IsLanguageSupported(const ILocalizationManager::EPlatformIndependentLanguageID id) override; const char* GetLanguage() override; bool SetLanguage(const char* sLanguage) override; int GetLocalizationFormat() const override; - virtual AZStd::string GetLocalizedSubtitleFilePath(const AZStd::string& localVideoPath, const AZStd::string& subtitleFileExtension) const override; - virtual AZStd::string GetLocalizedLocXMLFilePath(const AZStd::string& localXmlPath) const override; - bool InitLocalizationData(const char* sFileName, bool bReload = false); - bool RequestLoadLocalizationDataByTag(const char* sTag); - bool LoadLocalizationDataByTag(const char* sTag, bool bReload = false); - bool ReleaseLocalizationDataByTag(const char* sTag); + AZStd::string GetLocalizedSubtitleFilePath(const AZStd::string& localVideoPath, const AZStd::string& subtitleFileExtension) const override; + AZStd::string GetLocalizedLocXMLFilePath(const AZStd::string& localXmlPath) const override; + bool InitLocalizationData(const char* sFileName, bool bReload = false) override; + bool RequestLoadLocalizationDataByTag(const char* sTag) override; + bool LoadLocalizationDataByTag(const char* sTag, bool bReload = false) override; + bool ReleaseLocalizationDataByTag(const char* sTag) override; bool LoadAllLocalizationData(bool bReload = false) override; bool LoadExcelXmlSpreadsheet(const char* sFileName, bool bReload = false) override; void ReloadData() override; - void FreeData(); + void FreeData() override; bool LocalizeString_s(const AZStd::string& sString, AZStd::string& outLocalizedString, bool bEnglish = false) override; bool LocalizeString_ch(const char* sString, AZStd::string& outLocalizedString, bool bEnglish = false) override; void LocalizeAndSubstituteInternal(AZStd::string& locString, const AZStd::vector& keys, const AZStd::vector& values) override; bool LocalizeLabel(const char* sLabel, AZStd::string& outLocalizedString, bool bEnglish = false) override; - bool IsLocalizedInfoFound(const char* sKey); - bool GetLocalizedInfoByKey(const char* sKey, SLocalizedInfoGame& outGameInfo); - bool GetLocalizedInfoByKey(const char* sKey, SLocalizedSoundInfoGame* pOutSoundInfoGame); - int GetLocalizedStringCount(); - bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoGame& outGameInfo); - bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoEditor& outEditorInfo); + bool IsLocalizedInfoFound(const char* sKey) override; + bool GetLocalizedInfoByKey(const char* sKey, SLocalizedInfoGame& outGameInfo) override; + bool GetLocalizedInfoByKey(const char* sKey, SLocalizedSoundInfoGame* pOutSoundInfoGame) override; + int GetLocalizedStringCount() override; + bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoGame& outGameInfo) override; + bool GetLocalizedInfoByIndex(int nIndex, SLocalizedInfoEditor& outEditorInfo) override; bool GetEnglishString(const char* sKey, AZStd::string& sLocalizedString) override; bool GetSubtitle(const char* sKeyOrLabel, AZStd::string& outSubtitle, bool bForceSubtitle = false) override; void FormatStringMessage_List(AZStd::string& outString, const AZStd::string& sString, const char** sParams, int nParams) override; - void FormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2 = 0, const char* param3 = 0, const char* param4 = 0) override; + void FormatStringMessage(AZStd::string& outString, const AZStd::string& sString, const char* param1, const char* param2 = nullptr, const char* param3 = nullptr, const char* param4 = nullptr) override; void LocalizeTime(time_t t, bool bMakeLocalTime, bool bShowSeconds, AZStd::string& outTimeString) override; void LocalizeDate(time_t t, bool bMakeLocalTime, bool bShort, bool bIncludeWeekday, AZStd::string& outDateString) override; @@ -86,7 +86,7 @@ public: // ~ILocalizationManager // ISystemEventManager - void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam); + void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override; // ~ISystemEventManager int GetMemoryUsage(ICrySizer* pSizer); @@ -100,7 +100,7 @@ private: bool LocalizeStringInternal(const char* pStr, size_t len, AZStd::string& outLocalizedString, bool bEnglish); bool DoLoadExcelXmlSpreadsheet(const char* sFileName, uint8 tagID, bool bReload); - typedef bool(CLocalizedStringsManager::*LoadFunc)(const char*, uint8, bool); + using LoadFunc = bool(CLocalizedStringsManager::*)(const char*, uint8, bool); bool DoLoadAGSXmlDocument(const char* sFileName, uint8 tagID, bool bReload); LoadFunc GetLoadFunction() const; @@ -176,9 +176,9 @@ private: SLocalizedStringEntry() : flags(0) , huffmanTreeIndex(-1) - , pEditorExtension(NULL) + , pEditorExtension(nullptr) { - TranslatedText.psUtf8Uncompressed = NULL; + TranslatedText.psUtf8Uncompressed = nullptr; }; ~SLocalizedStringEntry() { @@ -201,7 +201,7 @@ private: pSizer->AddObject(sCharacterName); - if ((flags & IS_COMPRESSED) == 0 && TranslatedText.psUtf8Uncompressed != NULL) //Number of bytes stored for compressed text is unknown, which throws this GetMemoryUsage off + if ((flags & IS_COMPRESSED) == 0 && TranslatedText.psUtf8Uncompressed != nullptr) //Number of bytes stored for compressed text is unknown, which throws this GetMemoryUsage off { pSizer->AddObject(*TranslatedText.psUtf8Uncompressed); } @@ -211,7 +211,7 @@ private: pSizer->AddObject(SoundMoods); pSizer->AddObject(EventParameters); - if (pEditorExtension != NULL) + if (pEditorExtension != nullptr) { pEditorExtension->GetMemoryUsage(pSizer); } @@ -219,12 +219,12 @@ private: }; //Keys as CRC32. Strings previously, but these proved too large - typedef VectorMap StringsKeyMap; + using StringsKeyMap = VectorMap; struct SLanguage { - typedef std::vector TLocalizedStringEntries; - typedef std::vector THuffmanCoders; + using TLocalizedStringEntries = std::vector; + using THuffmanCoders = std::vector; AZStd::string sLanguage; StringsKeyMap m_keysMap; @@ -268,27 +268,27 @@ private: SLanguage* m_pLanguage; // all loaded Localization Files - typedef std::pair pairFileName; - typedef std::map tmapFilenames; + using pairFileName = std::pair; + using tmapFilenames = std::map; tmapFilenames m_loadedTables; // filenames per tag - typedef std::vector TStringVec; + using TStringVec = std::vector; struct STag { TStringVec filenames; uint8 id; bool loaded; }; - typedef std::map TTagFileNames; + using TTagFileNames = std::map; TTagFileNames m_tagFileNames; TStringVec m_tagLoadRequests; // Array of loaded languages. std::vector m_languages; - typedef std::set PrototypeSoundEvents; + using PrototypeSoundEvents = std::set; PrototypeSoundEvents m_prototypeEvents; // this set is purely used for clever string/string assigning to save memory struct less_strcmp @@ -299,7 +299,7 @@ private: } }; - typedef std::set CharacterNameSet; + using CharacterNameSet = std::set; CharacterNameSet m_characterNameSet; // this set is purely used for clever string/string assigning to save memory // CVARs @@ -312,5 +312,5 @@ private: //Lock for mutable AZStd::mutex m_cs; - typedef AZStd::lock_guard AutoLock; + using AutoLock = AZStd::lock_guard; }; diff --git a/Code/Legacy/CrySystem/System.h b/Code/Legacy/CrySystem/System.h index 738ffd4bfb..3244143cdf 100644 --- a/Code/Legacy/CrySystem/System.h +++ b/Code/Legacy/CrySystem/System.h @@ -159,7 +159,7 @@ class CWatchdogThread; #endif #ifdef WIN32 -typedef void* WIN_HMODULE; +using WIN_HMODULE = void*; #else typedef void* WIN_HMODULE; #endif @@ -174,7 +174,7 @@ struct IDataProbe; #define PHSYICS_OBJECT_ENTITY 0 -typedef void (__cdecl * VTuneFunction)(void); +using VTuneFunction = void (__cdecl *)(void); extern VTuneFunction VTResume; extern VTuneFunction VTPause; @@ -246,10 +246,10 @@ struct CProfilingSystem // Summary: // Resumes vtune data collection. - virtual void VTuneResume(); + void VTuneResume() override; // Summary: // Pauses vtune data collection. - virtual void VTunePause(); + void VTunePause() override; ////////////////////////////////////////////////////////////////////////// }; @@ -286,105 +286,105 @@ public: // interface ILoadConfigurationEntrySink ---------------------------------- - virtual void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup); + void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup) override; // ISystemEventListener - virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam); + void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override; /////////////////////////////////////////////////////////////////////////// //! @name ISystem implementation //@{ virtual bool Init(const SSystemInitParams& startupParams); - virtual void Release(); + void Release() override; - virtual SSystemGlobalEnvironment* GetGlobalEnvironment() { return &m_env; } + SSystemGlobalEnvironment* GetGlobalEnvironment() override { return &m_env; } - virtual bool UpdatePreTickBus(int updateFlags = 0, int nPauseMode = 0); - virtual bool UpdatePostTickBus(int updateFlags = 0, int nPauseMode = 0); - virtual bool UpdateLoadtime(); + bool UpdatePreTickBus(int updateFlags = 0, int nPauseMode = 0) override; + bool UpdatePostTickBus(int updateFlags = 0, int nPauseMode = 0) override; + bool UpdateLoadtime() override; //////////////////////////////////////////////////////////////////////// // CrySystemRequestBus interface implementation ISystem* GetCrySystem() override; //////////////////////////////////////////////////////////////////////// - void Relaunch(bool bRelaunch); - bool IsRelaunch() const { return m_bRelaunch; }; + void Relaunch(bool bRelaunch) override; + bool IsRelaunch() const override { return m_bRelaunch; }; - void SerializingFile(int mode) { m_iLoadingMode = mode; } - int IsSerializingFile() const { return m_iLoadingMode; } - void Quit(); - bool IsQuitting() const; + void SerializingFile(int mode) override { m_iLoadingMode = mode; } + int IsSerializingFile() const override { return m_iLoadingMode; } + void Quit() override; + bool IsQuitting() const override; void ShutdownFileSystem(); // used to cleanup any file resources, such as cache handle. void SetAffinity(); - virtual const char* GetUserName(); - virtual int GetApplicationInstance(); + const char* GetUserName() override; + int GetApplicationInstance() override; int GetApplicationLogInstance(const char* logFilePath) override; - ITimer* GetITimer(){ return m_env.pTimer; } - AZ::IO::IArchive* GetIPak() { return m_env.pCryPak; }; - IConsole* GetIConsole() { return m_env.pConsole; }; - IRemoteConsole* GetIRemoteConsole(); - IMovieSystem* GetIMovieSystem() { return m_env.pMovieSystem; }; - ICryFont* GetICryFont(){ return m_env.pCryFont; } - ILog* GetILog(){ return m_env.pLog; } - ICmdLine* GetICmdLine(){ return m_pCmdLine; } - IViewSystem* GetIViewSystem(); - ILevelSystem* GetILevelSystem(); - ISystemEventDispatcher* GetISystemEventDispatcher() { return m_pSystemEventDispatcher; } - IProfilingSystem* GetIProfilingSystem() { return &m_ProfilingSystem; } + ITimer* GetITimer() override{ return m_env.pTimer; } + AZ::IO::IArchive* GetIPak() override { return m_env.pCryPak; }; + IConsole* GetIConsole() override { return m_env.pConsole; }; + IRemoteConsole* GetIRemoteConsole() override; + IMovieSystem* GetIMovieSystem() override { return m_env.pMovieSystem; }; + ICryFont* GetICryFont() override{ return m_env.pCryFont; } + ILog* GetILog() override{ return m_env.pLog; } + ICmdLine* GetICmdLine() override{ return m_pCmdLine; } + IViewSystem* GetIViewSystem() override; + ILevelSystem* GetILevelSystem() override; + ISystemEventDispatcher* GetISystemEventDispatcher() override { return m_pSystemEventDispatcher; } + IProfilingSystem* GetIProfilingSystem() override { return &m_ProfilingSystem; } ////////////////////////////////////////////////////////////////////////// // retrieves the perlin noise singleton instance - CPNoise3* GetNoiseGen(); - virtual uint64 GetUpdateCounter() { return m_nUpdateCounter; }; + CPNoise3* GetNoiseGen() override; + uint64 GetUpdateCounter() override { return m_nUpdateCounter; }; void DetectGameFolderAccessRights(); - virtual void ExecuteCommandLine(bool deferred=true); + void ExecuteCommandLine(bool deferred=true) override; - virtual void GetUpdateStats(SSystemUpdateStats& stats); + void GetUpdateStats(SSystemUpdateStats& stats) override; ////////////////////////////////////////////////////////////////////////// - virtual XmlNodeRef CreateXmlNode(const char* sNodeName = "", bool bReuseStrings = false, bool bIsProcessingInstruction = false); - virtual XmlNodeRef LoadXmlFromFile(const char* sFilename, bool bReuseStrings = false); - virtual XmlNodeRef LoadXmlFromBuffer(const char* buffer, size_t size, bool bReuseStrings = false, bool bSuppressWarnings = false); - virtual IXmlUtils* GetXmlUtils(); + XmlNodeRef CreateXmlNode(const char* sNodeName = "", bool bReuseStrings = false, bool bIsProcessingInstruction = false) override; + XmlNodeRef LoadXmlFromFile(const char* sFilename, bool bReuseStrings = false) override; + XmlNodeRef LoadXmlFromBuffer(const char* buffer, size_t size, bool bReuseStrings = false, bool bSuppressWarnings = false) override; + IXmlUtils* GetXmlUtils() override; ////////////////////////////////////////////////////////////////////////// - void IgnoreUpdates(bool bIgnore) { m_bIgnoreUpdates = bIgnore; }; + void IgnoreUpdates(bool bIgnore) override { m_bIgnoreUpdates = bIgnore; }; - void SetIProcess(IProcess* process); - IProcess* GetIProcess(){ return m_pProcess; } + void SetIProcess(IProcess* process) override; + IProcess* GetIProcess() override{ return m_pProcess; } - bool IsTestMode() const { return m_bTestMode; } + bool IsTestMode() const override { return m_bTestMode; } //@} void SleepIfNeeded(); - virtual void FatalError(const char* format, ...) PRINTF_PARAMS(2, 3); - virtual void ReportBug(const char* format, ...) PRINTF_PARAMS(2, 3); + void FatalError(const char* format, ...) override PRINTF_PARAMS(2, 3); + void ReportBug(const char* format, ...) override PRINTF_PARAMS(2, 3); // Validator Warning. - void WarningV(EValidatorModule module, EValidatorSeverity severity, int flags, const char* file, const char* format, va_list args); - void Warning(EValidatorModule module, EValidatorSeverity severity, int flags, const char* file, const char* format, ...); - virtual int ShowMessage(const char* text, const char* caption, unsigned int uType); - bool CheckLogVerbosity(int verbosity); + void WarningV(EValidatorModule module, EValidatorSeverity severity, int flags, const char* file, const char* format, va_list args) override; + void Warning(EValidatorModule module, EValidatorSeverity severity, int flags, const char* file, const char* format, ...) override; + int ShowMessage(const char* text, const char* caption, unsigned int uType) override; + bool CheckLogVerbosity(int verbosity) override; //! Return pointer to user defined callback. ISystemUserCallback* GetUserCallback() const { return m_pUserCallback; }; ////////////////////////////////////////////////////////////////////////// - virtual void SaveConfiguration(); - virtual void LoadConfiguration(const char* sFilename, ILoadConfigurationEntrySink* pSink = 0, bool warnIfMissing = true); - virtual ESystemConfigSpec GetMaxConfigSpec() const; - virtual ESystemConfigPlatform GetConfigPlatform() const; - virtual void SetConfigPlatform(ESystemConfigPlatform platform); + void SaveConfiguration() override; + void LoadConfiguration(const char* sFilename, ILoadConfigurationEntrySink* pSink = nullptr, bool warnIfMissing = true) override; + ESystemConfigSpec GetMaxConfigSpec() const override; + ESystemConfigPlatform GetConfigPlatform() const override; + void SetConfigPlatform(ESystemConfigPlatform platform) override; ////////////////////////////////////////////////////////////////////////// - virtual bool IsPaused() const { return m_bPaused; }; + bool IsPaused() const override { return m_bPaused; }; - virtual ILocalizationManager* GetLocalizationManager(); - virtual void debug_GetCallStack(const char** pFunctions, int& nCount); - virtual void debug_LogCallStack(int nMaxFuncs = 32, int nFlags = 0); + ILocalizationManager* GetLocalizationManager() override; + void debug_GetCallStack(const char** pFunctions, int& nCount) override; + void debug_LogCallStack(int nMaxFuncs = 32, int nFlags = 0) override; // Get the current callstack in raw address form (more lightweight than the above functions) // static as memReplay needs it before CSystem has been setup - expose a ISystem interface to this function if you need it outside CrySystem static void debug_GetCallStackRaw(void** callstack, uint32& callstackLength); @@ -399,13 +399,13 @@ public: #if defined(WIN32) friend LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); #endif - virtual void* GetRootWindowMessageHandler(); - virtual void RegisterWindowMessageHandler(IWindowMessageHandler* pHandler); - virtual void UnregisterWindowMessageHandler(IWindowMessageHandler* pHandler); + void* GetRootWindowMessageHandler() override; + void RegisterWindowMessageHandler(IWindowMessageHandler* pHandler) override; + void UnregisterWindowMessageHandler(IWindowMessageHandler* pHandler) override; // IWindowMessageHandler #if defined(WIN32) - virtual bool HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult); + bool HandleMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; #endif // ~IWindowMessageHandler @@ -448,7 +448,7 @@ private: bool ReLaunchMediaCenter(); void UpdateAudioSystems(); - void AddCVarGroupDirectory(const AZStd::string& sPath); + void AddCVarGroupDirectory(const AZStd::string& sPath) override; AZStd::unique_ptr LoadDynamiclibrary(const char* dllName) const; @@ -464,13 +464,13 @@ public: // interface ISystem ------------------------------------------- virtual IDataProbe* GetIDataProbe() { return m_pDataProbe; }; - virtual void SetForceNonDevMode(bool bValue); - virtual bool GetForceNonDevMode() const; - virtual bool WasInDevMode() const { return m_bWasInDevMode; }; - virtual bool IsDevMode() const { return m_bInDevMode && !GetForceNonDevMode(); } + void SetForceNonDevMode(bool bValue) override; + bool GetForceNonDevMode() const override; + bool WasInDevMode() const override { return m_bWasInDevMode; }; + bool IsDevMode() const override { return m_bInDevMode && !GetForceNonDevMode(); } - virtual void SetConsoleDrawEnabled(bool enabled) { m_bDrawConsole = enabled; } - virtual void SetUIDrawEnabled(bool enabled) { m_bDrawUI = enabled; } + void SetConsoleDrawEnabled(bool enabled) override { m_bDrawConsole = enabled; } + void SetUIDrawEnabled(bool enabled) override { m_bDrawUI = enabled; } // ------------------------------------------------------------- @@ -478,10 +478,10 @@ public: //! recreates the variable if necessary ICVar* attachVariable (const char* szVarName, int* pContainer, const char* szComment, int dwFlags = 0); - const CTimeValue& GetLastTickTime(void) const { return m_lastTickTime; } - const ICVar* GetDedicatedMaxRate(void) const { return m_svDedicatedMaxRate; } + const CTimeValue& GetLastTickTime() const { return m_lastTickTime; } + const ICVar* GetDedicatedMaxRate() const { return m_svDedicatedMaxRate; } - std::shared_ptr CreateLocalFileIO(); + std::shared_ptr CreateLocalFileIO() override; private: // ------------------------------------------------------ @@ -654,9 +654,9 @@ public: ////////////////////////////////////////////////////////////////////////// // File version. ////////////////////////////////////////////////////////////////////////// - virtual const SFileVersion& GetFileVersion(); - virtual const SFileVersion& GetProductVersion(); - virtual const SFileVersion& GetBuildVersion(); + const SFileVersion& GetFileVersion() override; + const SFileVersion& GetProductVersion() override; + const SFileVersion& GetBuildVersion() override; bool InitVTuneProfiler(); @@ -671,16 +671,16 @@ public: ////////////////////////////////////////////////////////////////////////// // CryAssert and error related. - virtual bool RegisterErrorObserver(IErrorObserver* errorObserver); - bool UnregisterErrorObserver(IErrorObserver* errorObserver); - virtual void OnAssert(const char* condition, const char* message, const char* fileName, unsigned int fileLineNumber); + bool RegisterErrorObserver(IErrorObserver* errorObserver) override; + bool UnregisterErrorObserver(IErrorObserver* errorObserver) override; + void OnAssert(const char* condition, const char* message, const char* fileName, unsigned int fileLineNumber) override; void OnFatalError(const char* message); - bool IsAssertDialogVisible() const; - void SetAssertVisible(bool bAssertVisble); + bool IsAssertDialogVisible() const override; + void SetAssertVisible(bool bAssertVisble) override; ////////////////////////////////////////////////////////////////////////// - virtual void ClearErrorMessages() + void ClearErrorMessages() override { m_ErrorMessages.clear(); } @@ -690,11 +690,11 @@ public: return m_eRuntimeState == ESYSTEM_EVENT_LEVEL_LOAD_START_LOADINGSCREEN; } - virtual ESystemGlobalState GetSystemGlobalState(void); - virtual void SetSystemGlobalState(ESystemGlobalState systemGlobalState); + ESystemGlobalState GetSystemGlobalState() override; + void SetSystemGlobalState(ESystemGlobalState systemGlobalState) override; #if !defined(_RELEASE) - virtual bool IsSavingResourceList() const { return (g_cvars.archiveVars.nSaveLevelResourceList != 0); } + bool IsSavingResourceList() const override { return (g_cvars.archiveVars.nSaveLevelResourceList != 0); } #endif private: @@ -721,7 +721,7 @@ protected: // ------------------------------------------------------------- float m_Color[4]; bool m_HardFailure; }; - typedef std::list TErrorMessages; + using TErrorMessages = std::list; TErrorMessages m_ErrorMessages; bool m_bHasRenderedErrorMessage; diff --git a/Code/Legacy/CrySystem/Timer.h b/Code/Legacy/CrySystem/Timer.h index 93dffeec13..c988c1fa38 100644 --- a/Code/Legacy/CrySystem/Timer.h +++ b/Code/Legacy/CrySystem/Timer.h @@ -21,7 +21,7 @@ public: // constructor CTimer(); // destructor - ~CTimer() {}; + ~CTimer() = default;; bool Init(); @@ -30,57 +30,57 @@ public: // TODO: Review m_time usage in System.cpp // if it wants Game Time / UI Time or a new Render Time? - virtual void ResetTimer(); - virtual void UpdateOnFrameStart(); - virtual float GetCurrTime(ETimer which = ETIMER_GAME) const; - virtual CTimeValue GetAsyncTime() const; - virtual float GetAsyncCurTime(); // retrieve the actual wall clock time passed since the game started, in seconds - virtual float GetFrameTime(ETimer which = ETIMER_GAME) const; - virtual float GetRealFrameTime() const; - virtual float GetTimeScale() const; - virtual float GetTimeScale(uint32 channel) const; - virtual void SetTimeScale(float scale, uint32 channel = 0); - virtual void ClearTimeScales(); - virtual void EnableTimer(bool bEnable); - virtual float GetFrameRate(); - virtual float GetProfileFrameBlending(float* pfBlendTime = 0, int* piBlendMode = 0); - virtual void Serialize(TSerialize ser); - virtual bool IsTimerEnabled() const; + void ResetTimer() override; + void UpdateOnFrameStart() override; + float GetCurrTime(ETimer which = ETIMER_GAME) const override; + CTimeValue GetAsyncTime() const override; + float GetAsyncCurTime() override; // retrieve the actual wall clock time passed since the game started, in seconds + float GetFrameTime(ETimer which = ETIMER_GAME) const override; + float GetRealFrameTime() const override; + float GetTimeScale() const override; + float GetTimeScale(uint32 channel) const override; + void SetTimeScale(float scale, uint32 channel = 0) override; + void ClearTimeScales() override; + void EnableTimer(bool bEnable) override; + float GetFrameRate() override; + float GetProfileFrameBlending(float* pfBlendTime = nullptr, int* piBlendMode = nullptr) override; + void Serialize(TSerialize ser) override; + bool IsTimerEnabled() const override; //! try to pause/unpause a timer // returns true if successfully paused/unpaused, false otherwise - virtual bool PauseTimer(ETimer which, bool bPause); + bool PauseTimer(ETimer which, bool bPause) override; //! determine if a timer is paused // returns true if paused, false otherwise - virtual bool IsTimerPaused(ETimer which); + bool IsTimerPaused(ETimer which) override; //! try to set a timer // return true if successful, false otherwise - virtual bool SetTimer(ETimer which, float timeInSeconds); + bool SetTimer(ETimer which, float timeInSeconds) override; //! make a tm struct from a time_t in UTC (like gmtime) - virtual void SecondsToDateUTC(time_t time, struct tm& outDateUTC); + void SecondsToDateUTC(time_t time, struct tm& outDateUTC) override; //! make a UTC time from a tm (like timegm, but not available on all platforms) - virtual time_t DateToSecondsUTC(struct tm& timePtr); + time_t DateToSecondsUTC(struct tm& timePtr) override; //! Convert from Tics to Seconds - virtual float TicksToSeconds(int64 ticks) + float TicksToSeconds(int64 ticks) override { return float((double)ticks * m_fSecsPerTick); } //! Get number of ticks per second - virtual int64 GetTicksPerSecond() + int64 GetTicksPerSecond() override { return m_lTicksPerSec; } - virtual const CTimeValue& GetFrameStartTime(ETimer which = ETIMER_GAME) const { return m_CurrTime[(int)which]; } - virtual ITimer* CreateNewTimer(); + const CTimeValue& GetFrameStartTime(ETimer which = ETIMER_GAME) const override { return m_CurrTime[(int)which]; } + ITimer* CreateNewTimer() override; - virtual void EnableFixedTimeMode(bool enable, float timeStep) override; + void EnableFixedTimeMode(bool enable, float timeStep) override; private: // --------------------------------------------------------------------- diff --git a/Code/Legacy/CrySystem/ViewSystem/View.h b/Code/Legacy/CrySystem/ViewSystem/View.h index 689c254897..c58aa19ee5 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.h +++ b/Code/Legacy/CrySystem/ViewSystem/View.h @@ -87,24 +87,24 @@ public: // IView - virtual void Release(); - virtual void Update(float frameTime, bool isActive); + void Release() override; + void Update(float frameTime, bool isActive) override; virtual void ProcessShaking(float frameTime); virtual void ProcessShake(SShake* pShake, float frameTime); - virtual void ResetShaking(); - virtual void ResetBlending() { m_viewParams.ResetBlending(); } - virtual void LinkTo(AZ::Entity* follow); - virtual void Unlink(); - virtual AZ::EntityId GetLinkedId() {return m_linkedTo; }; - virtual void SetCurrentParams(SViewParams& params) { m_viewParams = params; }; - virtual const SViewParams* GetCurrentParams() {return &m_viewParams; } - virtual void SetViewShake(Ang3 shakeAngle, Vec3 shakeShift, float duration, float frequency, float randomness, int shakeID, bool bFlipVec = true, bool bUpdateOnly = false, bool bGroundOnly = false); - virtual void SetViewShakeEx(const SShakeParams& params); - virtual void StopShake(int shakeID); - virtual void SetFrameAdditiveCameraAngles(const Ang3& addFrameAngles); - virtual void SetScale(const float scale); - virtual void SetZoomedScale(const float scale); - virtual void SetActive(const bool bActive); + void ResetShaking() override; + void ResetBlending() override { m_viewParams.ResetBlending(); } + void LinkTo(AZ::Entity* follow) override; + void Unlink() override; + AZ::EntityId GetLinkedId() override {return m_linkedTo; }; + void SetCurrentParams(SViewParams& params) override { m_viewParams = params; }; + const SViewParams* GetCurrentParams() override {return &m_viewParams; } + void SetViewShake(Ang3 shakeAngle, Vec3 shakeShift, float duration, float frequency, float randomness, int shakeID, bool bFlipVec = true, bool bUpdateOnly = false, bool bGroundOnly = false) override; + void SetViewShakeEx(const SShakeParams& params) override; + void StopShake(int shakeID) override; + void SetFrameAdditiveCameraAngles(const Ang3& addFrameAngles) override; + void SetScale(const float scale) override; + void SetZoomedScale(const float scale) override; + void SetActive(const bool bActive) override; // ~IView void PostSerialize() override; diff --git a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h index dd49e09e04..d9e8962d71 100644 --- a/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h +++ b/Code/Legacy/CrySystem/ViewSystem/ViewSystem.h @@ -29,60 +29,60 @@ class CViewSystem { private: - typedef std::map TViewMap; - typedef std::vector TViewIdVector; + using TViewMap = std::map; + using TViewIdVector = std::vector; public: //IViewSystem - virtual IView* CreateView(); - virtual unsigned int AddView(IView* pView) override; - virtual void RemoveView(IView* pView); - virtual void RemoveView(unsigned int viewId); + IView* CreateView() override; + unsigned int AddView(IView* pView) override; + void RemoveView(IView* pView) override; + void RemoveView(unsigned int viewId) override; - virtual void SetActiveView(IView* pView); - virtual void SetActiveView(unsigned int viewId); + void SetActiveView(IView* pView) override; + void SetActiveView(unsigned int viewId) override; //CameraSystemRequestBus AZ::EntityId GetActiveCamera() override { return m_activeViewId ? GetActiveView()->GetLinkedId() : AZ::EntityId(); } //utility functions - virtual IView* GetView(unsigned int viewId); - virtual IView* GetActiveView(); + IView* GetView(unsigned int viewId) override; + IView* GetActiveView() override; - virtual unsigned int GetViewId(IView* pView); - virtual unsigned int GetActiveViewId(); + unsigned int GetViewId(IView* pView) override; + unsigned int GetActiveViewId() override; - virtual void PostSerialize(); + void PostSerialize() override; - virtual IView* GetViewByEntityId(const AZ::EntityId& id, bool forceCreate); + IView* GetViewByEntityId(const AZ::EntityId& id, bool forceCreate) override; - virtual float GetDefaultZNear() { return m_fDefaultCameraNearZ; }; - virtual void SetBlendParams(float fBlendPosSpeed, float fBlendRotSpeed, bool performBlendOut) { m_fBlendInPosSpeed = fBlendPosSpeed; m_fBlendInRotSpeed = fBlendRotSpeed; m_bPerformBlendOut = performBlendOut; }; - virtual void SetOverrideCameraRotation(bool bOverride, Quat rotation); - virtual bool IsPlayingCutScene() const + float GetDefaultZNear() override { return m_fDefaultCameraNearZ; }; + void SetBlendParams(float fBlendPosSpeed, float fBlendRotSpeed, bool performBlendOut) override { m_fBlendInPosSpeed = fBlendPosSpeed; m_fBlendInRotSpeed = fBlendRotSpeed; m_bPerformBlendOut = performBlendOut; }; + void SetOverrideCameraRotation(bool bOverride, Quat rotation) override; + bool IsPlayingCutScene() const override { return m_cutsceneCount > 0; } - virtual void SetDeferredViewSystemUpdate(bool const bDeferred){ m_useDeferredViewSystemUpdate = bDeferred; } - virtual bool UseDeferredViewSystemUpdate() const { return m_useDeferredViewSystemUpdate; } - virtual void SetControlAudioListeners(bool const bActive); + void SetDeferredViewSystemUpdate(bool const bDeferred) override{ m_useDeferredViewSystemUpdate = bDeferred; } + bool UseDeferredViewSystemUpdate() const override { return m_useDeferredViewSystemUpdate; } + void SetControlAudioListeners(bool const bActive) override; //~IViewSystem //IMovieUser - virtual void SetActiveCamera(const SCameraParams& Params); - virtual void BeginCutScene(IAnimSequence* pSeq, unsigned long dwFlags, bool bResetFX); - virtual void EndCutScene(IAnimSequence* pSeq, unsigned long dwFlags); - virtual void SendGlobalEvent(const char* pszEvent); + void SetActiveCamera(const SCameraParams& Params) override; + void BeginCutScene(IAnimSequence* pSeq, unsigned long dwFlags, bool bResetFX) override; + void EndCutScene(IAnimSequence* pSeq, unsigned long dwFlags) override; + void SendGlobalEvent(const char* pszEvent) override; //~IMovieUser // ILevelSystemListener - virtual void OnLevelNotFound([[maybe_unused]] const char* levelName) {}; - virtual void OnLoadingStart([[maybe_unused]] const char* levelName); - virtual void OnLoadingComplete([[maybe_unused]] const char* levelName){}; - virtual void OnLoadingError([[maybe_unused]] const char* levelName, [[maybe_unused]] const char* error){}; - virtual void OnLoadingProgress([[maybe_unused]] const char* levelName, [[maybe_unused]] int progressAmount){}; - virtual void OnUnloadComplete([[maybe_unused]] const char* levelName); + void OnLevelNotFound([[maybe_unused]] const char* levelName) override {}; + void OnLoadingStart([[maybe_unused]] const char* levelName) override; + void OnLoadingComplete([[maybe_unused]] const char* levelName) override{}; + void OnLoadingError([[maybe_unused]] const char* levelName, [[maybe_unused]] const char* error) override{}; + void OnLoadingProgress([[maybe_unused]] const char* levelName, [[maybe_unused]] int progressAmount) override{}; + void OnUnloadComplete([[maybe_unused]] const char* levelName) override; //~ILevelSystemListener CViewSystem(ISystem* pSystem); @@ -91,16 +91,16 @@ public: void Release() override { delete this; }; void Update(float frameTime) override; - virtual void ForceUpdate(float elapsed) { Update(elapsed); } + void ForceUpdate(float elapsed) override { Update(elapsed); } //void RegisterViewClass(const char *name, IView *(*func)()); - bool AddListener(IViewSystemListener* pListener) + bool AddListener(IViewSystemListener* pListener) override { return stl::push_back_unique(m_listeners, pListener); } - bool RemoveListener(IViewSystemListener* pListener) + bool RemoveListener(IViewSystemListener* pListener) override { return stl::find_and_erase(m_listeners, pListener); } diff --git a/Code/Legacy/CrySystem/XConsole.h b/Code/Legacy/CrySystem/XConsole.h index 3ff9824e6f..2069d31a74 100644 --- a/Code/Legacy/CrySystem/XConsole.h +++ b/Code/Legacy/CrySystem/XConsole.h @@ -50,7 +50,7 @@ struct CConsoleCommand ////////////////////////////////////////////////////////////////////////// CConsoleCommand() - : m_func(0) + : m_func(nullptr) , m_nFlags(0) {} size_t sizeofThis () const {return sizeof(*this) + m_sName.capacity() + 1 + m_sCommand.capacity() + 1; } void GetMemoryUsage (class ICrySizer* pSizer) const @@ -70,18 +70,18 @@ struct CConsoleCommandArgs CConsoleCommandArgs(AZStd::string& line, std::vector& args) : m_line(line) , m_args(args) {}; - virtual int GetArgCount() const { return static_cast(m_args.size()); }; + int GetArgCount() const override { return static_cast(m_args.size()); }; // Get argument by index, nIndex must be in 0 <= nIndex < GetArgCount() - virtual const char* GetArg(int nIndex) const + const char* GetArg(int nIndex) const override { assert(nIndex >= 0 && nIndex < GetArgCount()); if (!(nIndex >= 0 && nIndex < GetArgCount())) { - return NULL; + return nullptr; } return m_args[nIndex].c_str(); } - virtual const char* GetCommandLine() const + const char* GetCommandLine() const override { return m_line.c_str(); } @@ -118,9 +118,9 @@ class CXConsole , public AzFramework::CommandRegistrationBus::Handler { public: - typedef std::deque ConsoleBuffer; - typedef ConsoleBuffer::iterator ConsoleBufferItor; - typedef ConsoleBuffer::reverse_iterator ConsoleBufferRItor; + using ConsoleBuffer = std::deque; + using ConsoleBufferItor = ConsoleBuffer::iterator; + using ConsoleBufferRItor = ConsoleBuffer::reverse_iterator; // constructor CXConsole(); @@ -136,71 +136,71 @@ public: void Paste(); // interface IConsole --------------------------------------------------------- - virtual void Release(); - - virtual void Init(ISystem* pSystem); - virtual ICVar* RegisterString(const char* sName, const char* sValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0); - virtual ICVar* RegisterInt(const char* sName, int iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0); - virtual ICVar* RegisterInt64(const char* sName, int64 iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0); - virtual ICVar* RegisterFloat(const char* sName, float fValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = 0); - virtual ICVar* Register(const char* name, float* src, float defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true); - virtual ICVar* Register(const char* name, int* src, int defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true); - virtual ICVar* Register(const char* name, const char** src, const char* defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = 0, bool allowModify = true); - virtual ICVar* Register(ICVar* pVar) { RegisterVar(pVar); return pVar; } - - virtual void UnregisterVariable(const char* sVarName, bool bDelete = false); - virtual void SetScrollMax(int value); - virtual void AddOutputPrintSink(IOutputPrintSink* inpSink); - virtual void RemoveOutputPrintSink(IOutputPrintSink* inpSink); - virtual void ShowConsole(bool show, int iRequestScrollMax = -1); - virtual void DumpCVars(ICVarDumpSink* pCallback, unsigned int nFlagsFilter = 0); - virtual void DumpKeyBinds(IKeyBindDumpSink* pCallback); - virtual void CreateKeyBind(const char* sCmd, const char* sRes); - virtual const char* FindKeyBind(const char* sCmd) const; - virtual void SetImage(ITexture* pImage, bool bDeleteCurrent); - virtual inline ITexture* GetImage() { return m_pImage; } - virtual void StaticBackground(bool bStatic) { m_bStaticBackground = bStatic; } - virtual bool GetLineNo(int indwLineNo, char* outszBuffer, int indwBufferSize) const; - virtual int GetLineCount() const; - virtual ICVar* GetCVar(const char* name); - virtual char* GetVariable(const char* szVarName, const char* szFileName, const char* def_val); - virtual float GetVariable(const char* szVarName, const char* szFileName, float def_val); - virtual void PrintLine(const char* s); - virtual void PrintLinePlus(const char* s); - virtual bool GetStatus(); - virtual void Clear(); - virtual void Update(); - virtual void Draw(); - virtual bool AddCommand(const char* sCommand, ConsoleCommandFunc func, int nFlags = 0, const char* sHelp = NULL); - virtual bool AddCommand(const char* sName, const char* sScriptFunc, int nFlags = 0, const char* sHelp = NULL); - virtual void RemoveCommand(const char* sName); - virtual void ExecuteString(const char* command, bool bSilentMode, bool bDeferExecution = false); - virtual void ExecuteConsoleCommand(const char* command) override; - virtual void ResetCVarsToDefaults() override; - virtual void Exit(const char* command, ...) PRINTF_PARAMS(2, 3); - virtual bool IsOpened(); - virtual int GetNumVars(); - virtual int GetNumVisibleVars(); - virtual size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = 0); + void Release() override; + + void Init(ISystem* pSystem) override; + ICVar* RegisterString(const char* sName, const char* sValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) override; + ICVar* RegisterInt(const char* sName, int iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) override; + ICVar* RegisterInt64(const char* sName, int64 iValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) override; + ICVar* RegisterFloat(const char* sName, float fValue, int nFlags, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr) override; + ICVar* Register(const char* name, float* src, float defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr, bool allowModify = true) override; + ICVar* Register(const char* name, int* src, int defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr, bool allowModify = true) override; + ICVar* Register(const char* name, const char** src, const char* defaultvalue, int flags = 0, const char* help = "", ConsoleVarFunc pChangeFunc = nullptr, bool allowModify = true) override; + ICVar* Register(ICVar* pVar) override { RegisterVar(pVar); return pVar; } + + void UnregisterVariable(const char* sVarName, bool bDelete = false) override; + void SetScrollMax(int value) override; + void AddOutputPrintSink(IOutputPrintSink* inpSink) override; + void RemoveOutputPrintSink(IOutputPrintSink* inpSink) override; + void ShowConsole(bool show, int iRequestScrollMax = -1) override; + void DumpCVars(ICVarDumpSink* pCallback, unsigned int nFlagsFilter = 0) override; + void DumpKeyBinds(IKeyBindDumpSink* pCallback) override; + void CreateKeyBind(const char* sCmd, const char* sRes) override; + const char* FindKeyBind(const char* sCmd) const override; + void SetImage(ITexture* pImage, bool bDeleteCurrent) override; + inline ITexture* GetImage() override { return m_pImage; } + void StaticBackground(bool bStatic) override { m_bStaticBackground = bStatic; } + bool GetLineNo(int indwLineNo, char* outszBuffer, int indwBufferSize) const override; + int GetLineCount() const override; + ICVar* GetCVar(const char* name) override; + char* GetVariable(const char* szVarName, const char* szFileName, const char* def_val) override; + float GetVariable(const char* szVarName, const char* szFileName, float def_val) override; + void PrintLine(const char* s) override; + void PrintLinePlus(const char* s) override; + bool GetStatus() override; + void Clear() override; + void Update() override; + void Draw() override; + bool AddCommand(const char* sCommand, ConsoleCommandFunc func, int nFlags = 0, const char* sHelp = nullptr) override; + bool AddCommand(const char* sName, const char* sScriptFunc, int nFlags = 0, const char* sHelp = nullptr) override; + void RemoveCommand(const char* sName) override; + void ExecuteString(const char* command, bool bSilentMode, bool bDeferExecution = false) override; + void ExecuteConsoleCommand(const char* command) override; + void ResetCVarsToDefaults() override; + void Exit(const char* command, ...) override PRINTF_PARAMS(2, 3); + bool IsOpened() override; + int GetNumVars() override; + int GetNumVisibleVars() override; + size_t GetSortedVars(AZStd::vector& pszArray, const char* szPrefix = nullptr) override; virtual void FindVar(const char* substr); - virtual const char* AutoComplete(const char* substr); - virtual const char* AutoCompletePrev(const char* substr); - virtual const char* ProcessCompletion(const char* szInputBuffer); - virtual void RegisterAutoComplete(const char* sVarOrCommand, IConsoleArgumentAutoComplete* pArgAutoComplete); - virtual void UnRegisterAutoComplete(const char* sVarOrCommand); - virtual void ResetAutoCompletion(); - virtual void GetMemoryUsage (ICrySizer* pSizer) const; - virtual void ResetProgressBar(int nProgressRange); - virtual void TickProgressBar(); - virtual void SetLoadingImage(const char* szFilename); - virtual void AddConsoleVarSink(IConsoleVarSink* pSink); - virtual void RemoveConsoleVarSink(IConsoleVarSink* pSink); - virtual const char* GetHistoryElement(bool bUpOrDown); - virtual void AddCommandToHistory(const char* szCommand); - virtual void SetInputLine(const char* szLine); - virtual void LoadConfigVar(const char* sVariable, const char* sValue); - virtual void EnableActivationKey(bool bEnable); - virtual void SetClientDataProbeString(const char* pName, const char* pValue); + const char* AutoComplete(const char* substr) override; + const char* AutoCompletePrev(const char* substr) override; + const char* ProcessCompletion(const char* szInputBuffer) override; + void RegisterAutoComplete(const char* sVarOrCommand, IConsoleArgumentAutoComplete* pArgAutoComplete) override; + void UnRegisterAutoComplete(const char* sVarOrCommand) override; + void ResetAutoCompletion() override; + void GetMemoryUsage (ICrySizer* pSizer) const override; + void ResetProgressBar(int nProgressRange) override; + void TickProgressBar() override; + void SetLoadingImage(const char* szFilename) override; + void AddConsoleVarSink(IConsoleVarSink* pSink) override; + void RemoveConsoleVarSink(IConsoleVarSink* pSink) override; + const char* GetHistoryElement(bool bUpOrDown) override; + void AddCommandToHistory(const char* szCommand) override; + void SetInputLine(const char* szLine) override; + void LoadConfigVar(const char* sVariable, const char* sValue) override; + void EnableActivationKey(bool bEnable) override; + void SetClientDataProbeString(const char* pName, const char* pValue) override; // InputChannelEventListener / InputTextEventListener bool OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel) override; @@ -208,7 +208,7 @@ public: // interface IRemoteConsoleListener ------------------------------------------------------------------ - virtual void OnConsoleCommand(const char* cmd); + void OnConsoleCommand(const char* cmd) override; // interface IConsoleVarSink ---------------------------------------------------------------------- @@ -227,12 +227,12 @@ public: ICVar* RegisterCVarGroup(const char* sName, const char* szFileName); void SetProcessingGroup(bool isGroup) { m_bIsProcessingGroup = isGroup; } - bool GetIsProcessingGroup(void) const { return m_bIsProcessingGroup; } + bool GetIsProcessingGroup() const { return m_bIsProcessingGroup; } protected: // ---------------------------------------------------------------------------------------- void DrawBuffer(int nScrollPos, const char* szEffect); - void RegisterVar(ICVar* pCVar, ConsoleVarFunc pChangeFunc = 0); + void RegisterVar(ICVar* pCVar, ConsoleVarFunc pChangeFunc = nullptr); bool ProcessInput(const AzFramework::InputChannel& inputChannel); void AddLine(const char* inputStr); @@ -283,7 +283,7 @@ private: // ---------------------------------------------------------- typedef std::map ConsoleVariablesMap; // key points into string stored in ICVar or in .exe/.dll typedef ConsoleVariablesMap::iterator ConsoleVariablesMapItor; - typedef std::vector > ConsoleVariablesVector; + using ConsoleVariablesVector = std::vector >; void LogChangeMessage(const char* name, const bool isConst, const bool isCheat, const bool isReadOnly, const bool isDeprecated, const char* oldValue, const char* newValue, const bool isProcessingGroup, const bool allowChange); @@ -320,9 +320,9 @@ private: // ---------------------------------------------------------- , silentMode(_silentMode) {} }; - typedef std::list TDeferredCommandList; + using TDeferredCommandList = std::list; - typedef std::list ConsoleVarSinks; + using ConsoleVarSinks = std::list; // -------------------------------------------------------------------------------- diff --git a/Code/Legacy/CrySystem/XConsoleVariable.h b/Code/Legacy/CrySystem/XConsoleVariable.h index f761287b41..41ebc8e4fc 100644 --- a/Code/Legacy/CrySystem/XConsoleVariable.h +++ b/Code/Legacy/CrySystem/XConsoleVariable.h @@ -16,7 +16,7 @@ #include "SFunctor.h" class CXConsole; -typedef AZStd::fixed_string<512> stack_string; +using stack_string = AZStd::fixed_string<512>; inline int64 TextToInt64(const char* s, int64 nCurrent, bool bBitfield) { @@ -99,19 +99,19 @@ public: // interface ICVar -------------------------------------------------------------------------------------- - virtual void ClearFlags(int flags); - virtual int GetFlags() const; - virtual int SetFlags(int flags); - virtual const char* GetName() const; - virtual const char* GetHelp(); - virtual void Release(); - virtual void ForceSet(const char* s); - virtual void SetOnChangeCallback(ConsoleVarFunc pChangeFunc); - virtual uint64 AddOnChangeFunctor(const SFunctor& pChangeFunctor) override; - virtual ConsoleVarFunc GetOnChangeCallback() const; + void ClearFlags(int flags) override; + int GetFlags() const override; + int SetFlags(int flags) override; + const char* GetName() const override; + const char* GetHelp() override; + void Release() override; + void ForceSet(const char* s) override; + void SetOnChangeCallback(ConsoleVarFunc pChangeFunc) override; + uint64 AddOnChangeFunctor(const SFunctor& pChangeFunctor) override; + ConsoleVarFunc GetOnChangeCallback() const override; - virtual bool ShouldReset() const { return (m_nFlags & VF_RESETTABLE) != 0; } - virtual void Reset() override + bool ShouldReset() const { return (m_nFlags & VF_RESETTABLE) != 0; } + void Reset() override { if (ShouldReset()) { @@ -121,19 +121,19 @@ public: virtual void ResetImpl() = 0; - virtual void SetLimits(float min, float max) override; - virtual void GetLimits(float& min, float& max) override; - virtual bool HasCustomLimits() override; + void SetLimits(float min, float max) override; + void GetLimits(float& min, float& max) override; + bool HasCustomLimits() override; - virtual int GetRealIVal() const { return GetIVal(); } - virtual bool IsConstCVar() const {return (m_nFlags & VF_CONST_CVAR) != 0; } - virtual void SetDataProbeString(const char* pDataProbeString) + int GetRealIVal() const override { return GetIVal(); } + bool IsConstCVar() const override {return (m_nFlags & VF_CONST_CVAR) != 0; } + void SetDataProbeString(const char* pDataProbeString) override { CRY_ASSERT(m_pDataProbeString == NULL); m_pDataProbeString = new char[ strlen(pDataProbeString) + 1 ]; azstrcpy(m_pDataProbeString, strlen(pDataProbeString) + 1, pDataProbeString); } - virtual const char* GetDataProbeString() const + const char* GetDataProbeString() const override { if (gEnv->IsDedicated() && m_pDataProbeString) { @@ -157,7 +157,7 @@ protected: // ------------------------------------------------------------------ char* m_pDataProbeString; // value client is required to have for data probes int m_nFlags; // e.g. VF_CHEAT, ... - typedef std::vector > ChangeFunctorContainer; + using ChangeFunctorContainer = std::vector >; ChangeFunctorContainer m_changeFunctors; ConsoleVarFunc m_pChangeFunc; // Callback function that is called when this variable changes. CXConsole* m_pConsole; // used for the callback OnBeforeVarChange() @@ -185,15 +185,15 @@ public: // interface ICVar -------------------------------------------------------------------------------------- - virtual int GetIVal() const { return atoi(m_sValue.c_str()); } - virtual int64 GetI64Val() const { return _atoi64(m_sValue.c_str()); } - virtual float GetFVal() const { return (float)atof(m_sValue.c_str()); } - virtual const char* GetString() const { return m_sValue.c_str(); } - virtual void ResetImpl() + int GetIVal() const override { return atoi(m_sValue.c_str()); } + int64 GetI64Val() const override { return _atoi64(m_sValue.c_str()); } + float GetFVal() const override { return (float)atof(m_sValue.c_str()); } + const char* GetString() const override { return m_sValue.c_str(); } + void ResetImpl() override { Set(m_sDefault.c_str()); } - virtual void Set(const char* s) + void Set(const char* s) override { if (!s) { @@ -218,7 +218,7 @@ public: } } - virtual void Set(float f) + void Set(float f) override { stack_string s = stack_string::format("%g", f); @@ -231,7 +231,7 @@ public: Set(s.c_str()); } - virtual void Set(int i) + void Set(int i) override { stack_string s = stack_string::format("%d", i); @@ -243,9 +243,9 @@ public: m_nFlags |= VF_MODIFIED; Set(s.c_str()); } - virtual int GetType() { return CVAR_STRING; } + int GetType() override { return CVAR_STRING; } - virtual void GetMemoryUsage(class ICrySizer* pSizer) const { pSizer->AddObject(this, sizeof(*this)); } + void GetMemoryUsage(class ICrySizer* pSizer) const override { pSizer->AddObject(this, sizeof(*this)); } private: // -------------------------------------------------------------------------------------------- AZStd::string m_sValue; AZStd::string m_sDefault; //!< @@ -277,7 +277,7 @@ public: sprintf_s(szReturnString, "%d", GetIVal()); return szReturnString; } - virtual void ResetImpl() { Set(m_iDefault); } + void ResetImpl() override { Set(m_iDefault); } virtual void Set(const char* s) { int nValue = TextToInt(s, m_iValue, (m_nFlags & VF_BITFIELD) != 0); @@ -340,7 +340,7 @@ public: sprintf_s(szReturnString, "%lld", GetI64Val()); return szReturnString; } - virtual void ResetImpl() { Set(m_iDefault); } + void ResetImpl() override { Set(m_iDefault); } virtual void Set(const char* s) { int64 nValue = TextToInt64(s, m_iValue, (m_nFlags & VF_BITFIELD) != 0); @@ -408,7 +408,7 @@ public: sprintf_s(szReturnString, "%g", m_fValue); // %g -> "2.01", %f -> "2.01000" return szReturnString; } - virtual void ResetImpl() { Set(m_fDefault); } + void ResetImpl() override { Set(m_fDefault); } virtual void Set(const char* s) { float fValue = 0; @@ -475,7 +475,7 @@ public: protected: - virtual const char* GetOwnDataProbeString() const + const char* GetOwnDataProbeString() const override { static char szReturnString[8]; @@ -516,7 +516,7 @@ public: sprintf_s(szReturnString, "%d", m_iValue); return szReturnString; } - virtual void ResetImpl() { Set(m_iDefault); } + void ResetImpl() override { Set(m_iDefault); } virtual void Set(const char* s) { int nValue = TextToInt(s, m_iValue, (m_nFlags & VF_BITFIELD) != 0); @@ -609,7 +609,7 @@ public: sprintf_s(szReturnString, "%g", m_fValue); return szReturnString; } - virtual void ResetImpl() { Set(m_fDefault); } + void ResetImpl() override { Set(m_fDefault); } virtual void Set(const char* s) { float fValue = 0; @@ -673,7 +673,7 @@ public: protected: - virtual const char* GetOwnDataProbeString() const + const char* GetOwnDataProbeString() const override { static char szReturnString[8]; @@ -714,7 +714,7 @@ public: { return m_sValue.c_str(); } - virtual void ResetImpl() { Set(m_sDefault.c_str()); } + void ResetImpl() override { Set(m_sDefault.c_str()); } virtual void Set(const char* s) { if ((m_sValue == s) && (m_nFlags & VF_ALWAYSONCHANGE) == 0) @@ -776,13 +776,13 @@ public: // interface ICVar ----------------------------------------------------------------------------------- - virtual const char* GetHelp(); + const char* GetHelp() override; - virtual int GetRealIVal() const; + int GetRealIVal() const override; virtual void DebugLog(const int iExpectedValue, const ICVar::EConsoleLogMode mode) const; - virtual void Set(int i); + void Set(int i) override; // ConsoleVarFunc ------------------------------------------------------------------------------------ @@ -790,10 +790,10 @@ public: // interface ILoadConfigurationEntrySink ------------------------------------------------------------- - virtual void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup); - virtual void OnLoadConfigurationEntry_End(); + void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup) override; + void OnLoadConfigurationEntry_End() override; - virtual void GetMemoryUsage(class ICrySizer* pSizer) const + void GetMemoryUsage(class ICrySizer* pSizer) const override { pSizer->AddObject(this, sizeof(*this)); pSizer->AddObject(m_sDefaultValue); @@ -815,17 +815,17 @@ private: // -------------------------------------------------------------------- TCVarGroupStateMap m_CVarGroupStates; AZStd::string m_sDefaultValue; // used by OnLoadConfigurationEntry_End() - void ApplyCVars(const SCVarGroup& rGroup, const SCVarGroup* pExclude = 0); + void ApplyCVars(const SCVarGroup& rGroup, const SCVarGroup* pExclude = nullptr); // Arguments: // sKey - must exist, at least in default // pSpec - can be 0 - AZStd::string GetValueSpec(const AZStd::string& sKey, const int* pSpec = 0) const; + AZStd::string GetValueSpec(const AZStd::string& sKey, const int* pSpec = nullptr) const; // should only be used by TestCVars() // Returns: // true=all console variables match the state (excluding default state), false otherwise - bool TestCVars(const SCVarGroup& rGroup, const ICVar::EConsoleLogMode mode, const SCVarGroup* pExclude = 0) const; + bool TestCVars(const SCVarGroup& rGroup, const ICVar::EConsoleLogMode mode, const SCVarGroup* pExclude = nullptr) const; // Arguments: // pGroup - can be 0 to test if the default state is set diff --git a/Code/Legacy/CrySystem/XML/XmlUtils.cpp b/Code/Legacy/CrySystem/XML/XmlUtils.cpp index 56944eb344..4620b3f7a0 100644 --- a/Code/Legacy/CrySystem/XML/XmlUtils.cpp +++ b/Code/Legacy/CrySystem/XML/XmlUtils.cpp @@ -40,11 +40,11 @@ CXmlUtils::CXmlUtils(ISystem* pSystem) #ifdef CRY_COLLECT_XML_NODE_STATS g_pCXmlNode_Stats = new SXmlNodeStats(); #endif - m_pStatsXmlNodePool = 0; + m_pStatsXmlNodePool = nullptr; #ifndef _RELEASE m_statsThreadOwner = CryGetCurrentThreadId(); #endif - m_pXMLPatcher = NULL; + m_pXMLPatcher = nullptr; } ////////////////////////////////////////////////////////////////////////// @@ -129,10 +129,10 @@ class CXmlSerializer public: CXmlSerializer() : m_nRefCount(0) - , m_pReaderImpl(NULL) - , m_pReaderSer(NULL) - , m_pWriterSer(NULL) - , m_pWriterImpl(NULL) + , m_pReaderImpl(nullptr) + , m_pReaderSer(nullptr) + , m_pWriterSer(nullptr) + , m_pWriterImpl(nullptr) { } ~CXmlSerializer() @@ -148,8 +148,8 @@ public: } ////////////////////////////////////////////////////////////////////////// - virtual void AddRef() { ++m_nRefCount; } - virtual void Release() + void AddRef() override { ++m_nRefCount; } + void Release() override { if (--m_nRefCount <= 0) { @@ -157,14 +157,14 @@ public: } } - virtual ISerialize* GetWriter(XmlNodeRef& node) + ISerialize* GetWriter(XmlNodeRef& node) override { ClearAll(); m_pWriterImpl = new CSerializeXMLWriterImpl(node); m_pWriterSer = new CSimpleSerializeWithDefaults(*m_pWriterImpl); return m_pWriterSer; } - virtual ISerialize* GetReader(XmlNodeRef& node) + ISerialize* GetReader(XmlNodeRef& node) override { ClearAll(); m_pReaderImpl = new CSerializeXMLReaderImpl(node); @@ -172,7 +172,7 @@ public: return m_pReaderSer; } - virtual void GetMemoryUsage(ICrySizer* pSizer) const + void GetMemoryUsage(ICrySizer* pSizer) const override { pSizer->Add(*this); pSizer->AddObject(m_pReaderImpl); @@ -271,7 +271,7 @@ public: return m_fileHandle != AZ::IO::InvalidHandle; } ; - virtual void Write(const void* pData, size_t size) + void Write(const void* pData, size_t size) override { if (m_fileHandle != AZ::IO::InvalidHandle) { @@ -292,7 +292,7 @@ bool CXmlUtils::SaveBinaryXmlFile(const char* filename, XmlNodeRef root) } XMLBinary::CXMLBinaryWriter writer; AZStd::string error; - return writer.WriteNode(&fileSink, root, false, 0, error); + return writer.WriteNode(&fileSink, root, false, nullptr, error); } ////////////////////////////////////////////////////////////////////////// @@ -302,7 +302,7 @@ XmlNodeRef CXmlUtils::LoadBinaryXmlFile(const char* filename, bool bEnablePatchi XMLBinary::XMLBinaryReader::EResult result; XmlNodeRef root = reader.LoadFromFile(filename, result); - if (result == XMLBinary::XMLBinaryReader::eResult_Success && bEnablePatching == true && m_pXMLPatcher != NULL) + if (result == XMLBinary::XMLBinaryReader::eResult_Success && bEnablePatching == true && m_pXMLPatcher != nullptr) { root = m_pXMLPatcher->ApplyXMLDataPatch(root, filename); } @@ -326,12 +326,12 @@ public: CXmlTableReader(); virtual ~CXmlTableReader(); - virtual void Release(); + void Release() override; - virtual bool Begin(XmlNodeRef rootNode); - virtual int GetEstimatedRowCount(); - virtual bool ReadRow(int& rowIndex); - virtual bool ReadCell(int& columnIndex, const char*& pContent, size_t& contentSize); + bool Begin(XmlNodeRef rootNode) override; + int GetEstimatedRowCount() override; + bool ReadRow(int& rowIndex) override; + bool ReadCell(int& columnIndex, const char*& pContent, size_t& contentSize) override; float GetCurrentRowHeight() override; private: @@ -372,7 +372,7 @@ void CXmlTableReader::Release() ////////////////////////////////////////////////////////////////////////// bool CXmlTableReader::Begin(XmlNodeRef rootNode) { - m_tableNode = 0; + m_tableNode = nullptr; if (!rootNode) { @@ -391,11 +391,11 @@ bool CXmlTableReader::Begin(XmlNodeRef rootNode) m_tableNode = rootNode->findChild("Table"); } - m_rowNode = 0; + m_rowNode = nullptr; m_rowNodeIndex = -1; m_row = -1; - return (m_tableNode != 0); + return (m_tableNode != nullptr); } ////////////////////////////////////////////////////////////////////////// @@ -441,7 +441,7 @@ bool CXmlTableReader::ReadRow(int& rowIndex) if (!m_rowNode->isTag("Row")) { - m_rowNode = 0; + m_rowNode = nullptr; continue; } @@ -454,7 +454,7 @@ bool CXmlTableReader::ReadRow(int& rowIndex) if (index < m_row) { m_rowNodeIndex = rowNodeCount; - m_rowNode = 0; + m_rowNode = nullptr; return false; } m_row = index; @@ -502,7 +502,7 @@ bool CXmlTableReader::ReadRow(int& rowIndex) ////////////////////////////////////////////////////////////////////////// bool CXmlTableReader::ReadCell(int& columnIndex, const char*& pContent, size_t& contentSize) { - pContent = 0; + pContent = nullptr; contentSize = 0; if (!m_tableNode) @@ -632,7 +632,7 @@ IXmlTableReader* CXmlUtils::CreateXmlTableReader() void CXmlUtils::InitStatsXmlNodePool(uint32 nPoolSize) { CHECK_STATS_THREAD_OWNERSHIP(); - if (0 == m_pStatsXmlNodePool) + if (nullptr == m_pStatsXmlNodePool) { // create special xml node pools for game statistics @@ -651,7 +651,7 @@ void CXmlUtils::InitStatsXmlNodePool(uint32 nPoolSize) XmlNodeRef CXmlUtils::CreateStatsXmlNode(const char* sNodeName) { CHECK_STATS_THREAD_OWNERSHIP(); - if (0 == m_pStatsXmlNodePool) + if (nullptr == m_pStatsXmlNodePool) { CryLog("[CXmlNodePool]: Xml stats nodes pool isn't initialized. Perform default initialization."); InitStatsXmlNodePool(); @@ -682,7 +682,7 @@ void CXmlUtils::SetXMLPatcher(XmlNodeRef* pPatcher) { SAFE_DELETE(m_pXMLPatcher); - if (pPatcher != NULL) + if (pPatcher != nullptr) { m_pXMLPatcher = new CXMLPatcher(*pPatcher); } From a72b8a025fb84deeecb2443e7a57a203c01187d4 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 7 Sep 2021 18:38:16 -0700 Subject: [PATCH 030/274] others Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../AWSNativeSDKInit/AWSLogSystemInterface.h | 14 +++++++++++++- .../Code/Source/AchievementsSystemComponent.h | 2 +- .../RHI/Code/Include/Atom/RHI/FreeListAllocator.h | 2 +- .../Atom/RHI/Code/Include/Atom/RHI/PoolAllocator.h | 2 +- .../Include/Atom/RHI/ShaderResourceGroupPool.h | 2 +- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSLogSystemInterface.h b/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSLogSystemInterface.h index 85d780bf3d..4982d3efbd 100644 --- a/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSLogSystemInterface.h +++ b/Code/Tools/AWSNativeSDKInit/include/AWSNativeSDKInit/AWSLogSystemInterface.h @@ -57,14 +57,26 @@ namespace AWSNativeSDKInit /** * Does a printf style output to the output stream. Don't use this, it's unsafe. See LogStream */ +#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK) + void Log(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const char* formatStr, ...) override; +#else void Log(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const char* formatStr, ...); +#endif /** * Writes the stream to the output stream. */ - void LogStream(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const Aws::OStringStream &messageStream); +#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK) + void LogStream(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const Aws::OStringStream &messageStream) override; +#else + void LogStream(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const Aws::OStringStream& messageStream); +#endif +#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK) + void Flush() override; +#else void Flush(); +#endif private: bool ShouldLog(Aws::Utils::Logging::LogLevel logLevel); diff --git a/Gems/Achievements/Code/Source/AchievementsSystemComponent.h b/Gems/Achievements/Code/Source/AchievementsSystemComponent.h index 840974a2dc..25b28ae690 100644 --- a/Gems/Achievements/Code/Source/AchievementsSystemComponent.h +++ b/Gems/Achievements/Code/Source/AchievementsSystemComponent.h @@ -42,7 +42,7 @@ namespace Achievements //////////////////////////////////////////////////////////////////////////////////////// // AchievementsRequestBus interface implementation void UnlockAchievement(const UnlockAchievementParams& params) override; - void QueryAchievementDetails(const QueryAchievementParams& params); + void QueryAchievementDetails(const QueryAchievementParams& params) override; public: //////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/FreeListAllocator.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/FreeListAllocator.h index 49d5cc9345..ee1cb7c7f4 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/FreeListAllocator.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/FreeListAllocator.h @@ -51,7 +51,7 @@ namespace AZ VirtualAddress Allocate(size_t byteCount, size_t byteAlignment) override; void DeAllocate(VirtualAddress allocation) override; void GarbageCollect() override; - void GarbageCollectForce(); + void GarbageCollectForce() override; size_t GetAllocationCount() const override; size_t GetAllocatedByteCount() const override; const Descriptor& GetDescriptor() const override; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/PoolAllocator.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/PoolAllocator.h index 1392d1a59d..70a9937b1c 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/PoolAllocator.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/PoolAllocator.h @@ -51,7 +51,7 @@ namespace AZ VirtualAddress Allocate(size_t byteCount, size_t byteAlignment) override; void DeAllocate(VirtualAddress allocation) override; void GarbageCollect() override; - void GarbageCollectForce(); + void GarbageCollectForce() override; size_t GetAllocationCount() const override; size_t GetAllocatedByteCount() const override; const Descriptor& GetDescriptor() const override; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupPool.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupPool.h index 44bf80a980..a8775f8625 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupPool.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupPool.h @@ -38,7 +38,7 @@ namespace AZ ResultCode InitGroup(ShaderResourceGroup& srg); //! Returns the descriptor passed at initialization time. - const ShaderResourceGroupPoolDescriptor& GetDescriptor() const; + const ShaderResourceGroupPoolDescriptor& GetDescriptor() const override; //! Returns the SRG layout used when initializing the pool. const ShaderResourceGroupLayout* GetLayout() const; From 0b7c4fff8553bf32ac34870951e7dd9ba473848c Mon Sep 17 00:00:00 2001 From: kberg-amzn Date: Tue, 7 Sep 2021 21:08:51 -0700 Subject: [PATCH 031/274] Clear rewound entities if we attempt to sync rewind state outside of a scoped rewind Signed-off-by: kberg-amzn --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 2 -- Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 69d2726c65..f981966ae1 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -281,8 +281,6 @@ namespace Multiplayer void NetworkEntityManager::RemoveEntities() { - //RewindableObjectState::ClearRewoundEntities(); - AZStd::vector removeList; removeList.swap(m_removeList); for (NetEntityId entityId : removeList) diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index db8d6bd2f7..cd9c1737d6 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -93,6 +93,13 @@ namespace Multiplayer void NetworkTime::SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) { + if (!IsTimeRewound()) + { + // If we're not inside a rewind scope then reset any rewound state and exit + ClearRewoundEntities(); + return; + } + // Since the vis system doesn't support rewound queries, first query with an expanded volume to catch any fast moving entities const AZ::Aabb expandedVolume = rewindVolume.GetExpanded(AZ::Vector3(sv_RewindVolumeExtrudeDistance)); From 860b28c10bbe36d11588121c54630f628dd8a204 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 8 Sep 2021 08:48:32 -0700 Subject: [PATCH 032/274] more fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Memory/Memory.h | 2 +- .../Asset/AssetProcessorMessages.h | 4 +- .../TargetManagement/TargetManagementAPI.h | 2 +- .../UdpTransport/UdpFragmentQueue.h | 2 +- .../Tests/TcpTransport/TcpTransportTests.cpp | 2 +- .../Tests/UdpTransport/UdpTransportTests.cpp | 2 +- .../UI/Logging/LogPanel_Panel.h | 8 +- .../GridMate/Carrier/DefaultHandshake.h | 16 +-- .../GridMate/Carrier/DefaultSimulator.h | 16 +-- .../GridMate/GridMate/Carrier/SocketDriver.h | 42 +++--- .../GridMate/Drillers/SessionDriller.h | 34 ++--- .../GridMate/GridMate/Replica/DataSet.h | 4 +- .../GridMate/Replica/MigrationSequence.h | 4 +- Code/Legacy/CryCommon/IMiniLog.h | 4 +- Code/Legacy/CryCommon/SimpleSerialize.h | 20 +-- .../CrySystem/LevelSystem/LevelSystem.h | 41 +++--- Code/Legacy/CrySystem/XConsoleVariable.h | 78 +++++------ Code/Legacy/CrySystem/XML/XMLBinaryNode.h | 126 +++++++++--------- Code/Tools/GridHub/GridHub/gridhub.hxx | 22 +-- Code/Tools/GridHub/GridHub/main.cpp | 4 +- .../RemoteConsole/Core/RemoteConsoleCore.h | 12 +- .../Framework/ServiceRequestJobConfig.h | 2 +- .../Source/AssetValidationSystemComponent.h | 2 +- Gems/Atom/RHI/Code/CMakeLists.txt | 3 - .../Code/Source/RHI/MemoryTypeAllocator.h | 2 +- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Scope.h | 2 +- .../RPI.Reflect/Material/ShaderCollection.cpp | 2 +- .../Code/Source/Engine/AudioSystem.h | 2 +- .../Include/CrashReporting/GameCrashHandler.h | 10 +- .../CrashReporting/GameCrashUploader.h | 2 +- .../Code/Source/DebugDrawSystemComponent.h | 2 +- .../Code/MCore/Source/AttributeBool.h | 2 +- .../Code/MCore/Source/AttributeInt32.h | 2 +- .../ExpressionEvaluationSystemComponent.cpp | 6 +- Gems/LyShine/Code/Source/Sprite.h | 4 +- .../Code/Source/LZ4Compressor.h | 12 +- .../Code/Source/PresenceSystemComponent.h | 2 +- .../Platform/Common/MSVC/CodeAnalysis.ruleset | 5 +- 38 files changed, 251 insertions(+), 256 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Memory/Memory.h b/Code/Framework/AzCore/AzCore/Memory/Memory.h index af175c7a64..d2c570d48d 100644 --- a/Code/Framework/AzCore/AzCore/Memory/Memory.h +++ b/Code/Framework/AzCore/AzCore/Memory/Memory.h @@ -844,7 +844,7 @@ namespace AZ return AZ::AllocatorInstance::Get().GetUnAllocatedMemory(isPrint); } - virtual IAllocatorAllocate* GetSubAllocator() override + IAllocatorAllocate* GetSubAllocator() override { return AZ::AllocatorInstance::Get().GetSubAllocator(); } diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h b/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h index d6d67c2aa2..ac811ae478 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetProcessorMessages.h @@ -866,7 +866,7 @@ namespace AzFramework FileIsReadOnlyResponse() = default; FileIsReadOnlyResponse(bool isReadOnly); - unsigned int GetMessageType() const; + unsigned int GetMessageType() const override; bool m_isReadOnly; }; @@ -945,7 +945,7 @@ namespace AzFramework FileModTimeRequest() = default; FileModTimeRequest(const AZ::OSString& filePath); - unsigned int GetMessageType() const; + unsigned int GetMessageType() const override; AZ::OSString m_filePath; }; diff --git a/Code/Framework/AzFramework/AzFramework/TargetManagement/TargetManagementAPI.h b/Code/Framework/AzFramework/AzFramework/TargetManagement/TargetManagementAPI.h index 6582e145cb..bbfb4c88c1 100644 --- a/Code/Framework/AzFramework/AzFramework/TargetManagement/TargetManagementAPI.h +++ b/Code/Framework/AzFramework/AzFramework/TargetManagement/TargetManagementAPI.h @@ -195,7 +195,7 @@ namespace AzFramework TmMsgCallback(const MsgCB& cb = NULL) : m_cb(cb) {} - virtual void OnReceivedMsg(TmMsgPtr msg) + void OnReceivedMsg(TmMsgPtr msg) override { if (m_cb) { diff --git a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h index 0243395d1e..9c929d63e8 100644 --- a/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h +++ b/Code/Framework/AzNetworking/AzNetworking/UdpTransport/UdpFragmentQueue.h @@ -54,7 +54,7 @@ namespace AzNetworking //! Handler callback for timed out items. //! @param item containing registered timeout details //! @return ETimeoutResult for whether to re-register or discard the timeout params - virtual TimeoutResult HandleTimeout(TimeoutQueue::TimeoutItem& item) override; + TimeoutResult HandleTimeout(TimeoutQueue::TimeoutItem& item) override; TimeoutQueue m_timeoutQueue; SequenceGenerator m_sequenceGenerator; diff --git a/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp b/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp index 9dc7ae0ccf..bc9ecab2cb 100644 --- a/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp +++ b/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp @@ -33,7 +33,7 @@ namespace UnitTest ; } - PacketDispatchResult OnPacketReceived([[maybe_unused]] IConnection* connection, const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) + PacketDispatchResult OnPacketReceived([[maybe_unused]] IConnection* connection, const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) override { EXPECT_TRUE((packetHeader.GetPacketType() == static_cast(CorePackets::PacketType::InitiateConnectionPacket)) || (packetHeader.GetPacketType() == static_cast(CorePackets::PacketType::HeartbeatPacket))); diff --git a/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp b/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp index 02c7085023..c4de3fc6dd 100644 --- a/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp +++ b/Code/Framework/AzNetworking/Tests/UdpTransport/UdpTransportTests.cpp @@ -36,7 +36,7 @@ namespace UnitTest ; } - PacketDispatchResult OnPacketReceived([[maybe_unused]] IConnection* connection, const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) + PacketDispatchResult OnPacketReceived([[maybe_unused]] IConnection* connection, const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) override { EXPECT_TRUE((packetHeader.GetPacketType() == static_cast(CorePackets::PacketType::InitiateConnectionPacket)) || (packetHeader.GetPacketType() == static_cast(CorePackets::PacketType::HeartbeatPacket))); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/LogPanel_Panel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/LogPanel_Panel.h index 18a03cafe9..fdf7866284 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/LogPanel_Panel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/LogPanel_Panel.h @@ -300,13 +300,13 @@ namespace AzToolsFramework bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) override; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - void setEditorData(QWidget* editor, const QModelIndex& index) const; - void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + void setEditorData(QWidget* editor, const QModelIndex& index) const override; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; - void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const; + void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override; QWidget* pOwnerWidget; QLabel* m_painterLabel; diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h index 9225cca8d7..4e1d6f59bb 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h +++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultHandshake.h @@ -25,34 +25,34 @@ namespace GridMate DefaultHandshake(unsigned int timeOut, VersionType version); virtual ~DefaultHandshake(); /// Called from the system to write initial handshake data. - virtual void OnInitiate(ConnectionID id, WriteBuffer& wb); + void OnInitiate(ConnectionID id, WriteBuffer& wb) override; /** * Called when a system receives a handshake initiation from another system. * You can write a reply in the WriteBuffer. * return true if you accept this connection and false if you reject it. */ - virtual HandshakeErrorCode OnReceiveRequest(ConnectionID id, ReadBuffer& rb, WriteBuffer& wb); + HandshakeErrorCode OnReceiveRequest(ConnectionID id, ReadBuffer& rb, WriteBuffer& wb) override; /** * If we already have a valid connection and we receive another connection request, the system will * call this function to verify the state of the connection. */ - virtual bool OnConfirmRequest(ConnectionID id, ReadBuffer& rb); + bool OnConfirmRequest(ConnectionID id, ReadBuffer& rb) override; /** * Called when we receive Ack from the other system on our initial data \ref OnInitiate. * return true to accept the ack or false to reject the handshake. */ - virtual bool OnReceiveAck(ConnectionID id, ReadBuffer& rb); + bool OnReceiveAck(ConnectionID id, ReadBuffer& rb) override; /** * Called when we receive Ack from the other system while we were connected. This callback is called * so we can just confirm that our connection is valid! */ - virtual bool OnConfirmAck(ConnectionID id, ReadBuffer& rb); + bool OnConfirmAck(ConnectionID id, ReadBuffer& rb) override; /// Return true if you want to reject early reject a connection. - virtual bool OnNewConnection(const AZStd::string& address); + bool OnNewConnection(const AZStd::string& address) override; /// Called when we close a connection. - virtual void OnDisconnect(ConnectionID id); + void OnDisconnect(ConnectionID id) override; /// Return timeout in milliseconds of the handshake procedure. - virtual unsigned int GetHandshakeTimeOutMS() const { return m_handshakeTimeOutMS; } + unsigned int GetHandshakeTimeOutMS() const override { return m_handshakeTimeOutMS; } private: unsigned int m_handshakeTimeOutMS; VersionType m_version; diff --git a/Code/Framework/GridMate/GridMate/Carrier/DefaultSimulator.h b/Code/Framework/GridMate/GridMate/Carrier/DefaultSimulator.h index 07681a5837..e975223442 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/DefaultSimulator.h +++ b/Code/Framework/GridMate/GridMate/Carrier/DefaultSimulator.h @@ -23,21 +23,21 @@ namespace GridMate friend class CarrierThread; /// Called from Carrier, so simulator can use the low level driver directly. - virtual void BindDriver(Driver* driver); + void BindDriver(Driver* driver) override; /// Called from Carrier when driver can no longer be used(ie. will be destroyed) - virtual void UnbindDriver(); + void UnbindDriver() override; /// Called when Carrier has established a new connection. - virtual void OnConnect(const AZStd::intrusive_ptr& address); + void OnConnect(const AZStd::intrusive_ptr& address) override; /// Called when Carrier has lost a connection. - virtual void OnDisconnect(const AZStd::intrusive_ptr& address); + void OnDisconnect(const AZStd::intrusive_ptr& address) override; /// Called when Carrier has send a package. - virtual bool OnSend(const AZStd::intrusive_ptr& to, const void* data, unsigned int dataSize); + bool OnSend(const AZStd::intrusive_ptr& to, const void* data, unsigned int dataSize) override; /// Called when Carrier receives package receive. - virtual bool OnReceive(const AZStd::intrusive_ptr& from, const void* data, unsigned int dataSize); + bool OnReceive(const AZStd::intrusive_ptr& from, const void* data, unsigned int dataSize) override; /// Called from Carrier when no more data has arrived and you can supply you data (with latency, out of order, etc. - virtual unsigned int ReceiveDataFrom(AZStd::intrusive_ptr& from, char* data, unsigned int maxDataSize); + unsigned int ReceiveDataFrom(AZStd::intrusive_ptr& from, char* data, unsigned int maxDataSize) override; - virtual void Update(); + void Update() override; public: GM_CLASS_ALLOCATOR(DefaultSimulator); diff --git a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h index 835414b374..eb4130a477 100644 --- a/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h +++ b/Code/Framework/GridMate/GridMate/Carrier/SocketDriver.h @@ -88,11 +88,11 @@ namespace GridMate bool operator==(const SocketDriverAddress& rhs) const; bool operator!=(const SocketDriverAddress& rhs) const; - virtual AZStd::string ToString() const; - virtual AZStd::string ToAddress() const; - virtual AZStd::string GetIP() const; - virtual unsigned int GetPort() const; - virtual const void* GetTargetAddress(unsigned int& addressSize) const; + AZStd::string ToString() const override; + AZStd::string ToAddress() const override; + AZStd::string GetIP() const override; + unsigned int GetPort() const override; + const void* GetTargetAddress(unsigned int& addressSize) const override; union { @@ -117,11 +117,11 @@ namespace GridMate * Platform specific functionality. */ /// Return maximum number of active connections at the same time. - virtual unsigned int GetMaxNumConnections() const { return 32; } + unsigned int GetMaxNumConnections() const override { return 32; } /// Return maximum data size we can send/receive at once in bytes, supported by the platform. - virtual unsigned int GetMaxSendSize() const; + unsigned int GetMaxSendSize() const override; /// Return packet overhead size in bytes. - virtual unsigned int GetPacketOverheadSize() const; + unsigned int GetPacketOverheadSize() const override; /** * User should implement create and bind a UDP socket. This socket will be used for all communications. @@ -132,39 +132,39 @@ namespace GridMate * \param receiveBufferSize socket receive buffer size in bytes, use 0 for default values. * \param sendBufferSize socket send buffer size, use 0 for default values. */ - virtual ResultCode Initialize(int familyType = BSD_AF_INET, const char* address = nullptr, unsigned int port = 0, bool isBroadcast = false, unsigned int receiveBufferSize = 0, unsigned int sendBufferSize = 0); + ResultCode Initialize(int familyType = BSD_AF_INET, const char* address = nullptr, unsigned int port = 0, bool isBroadcast = false, unsigned int receiveBufferSize = 0, unsigned int sendBufferSize = 0) override; /// Returns communication port (must be called after Initialize, otherwise it will return 0) - virtual unsigned int GetPort() const; + unsigned int GetPort() const override; /// Send data to a user defined address - virtual ResultCode Send(const AZStd::intrusive_ptr& to, const char* data, unsigned int dataSize); + ResultCode Send(const AZStd::intrusive_ptr& to, const char* data, unsigned int dataSize) override; /** * Receives a datagram and stores the source address. maxDataSize must be >= than GetMaxSendSize(). Returns the num of of received bytes. * \note If a datagram from a new connection is received, NewConnectionCB will be called. If it rejects the connection the returned from pointer * will be NULL while the actual data will be returned. */ - virtual unsigned int Receive(char* data, unsigned int maxDataSize, AZStd::intrusive_ptr& from, ResultCode* resultCode = 0); + unsigned int Receive(char* data, unsigned int maxDataSize, AZStd::intrusive_ptr& from, ResultCode* resultCode = 0) override; /** * Wait for data to be to the ready for receive. Time out is the maximum time to wait * before this function returns. If left to default value it will be in blocking mode (wait until data is ready to be received). * \returns true if there is data to be received (always true if timeOut == 0), otherwise false. */ - virtual bool WaitForData(AZStd::chrono::microseconds timeOut = AZStd::chrono::microseconds(0)); + bool WaitForData(AZStd::chrono::microseconds timeOut = AZStd::chrono::microseconds(0)) override; /** * When you enter wait for data mode, for many reasons you might want to stop wait for data. * If you implement this function you need to make sure it's a thread safe function. */ - virtual void StopWaitForData(); + void StopWaitForData() override; /// Return true if WaitForData was interrupted before the timeOut expired, otherwise false. - virtual bool WasStopeedWaitingForData() { return m_isStoppedWaitForData; } + bool WasStopeedWaitingForData() override { return m_isStoppedWaitForData; } /// @{ Address conversion functionality. They MUST implemented thread safe. Generally this is not a problem since they just part local data. /// Create address from ip and port. If ip == NULL we will assign a broadcast address. - virtual AZStd::string IPPortToAddress(const char* ip, unsigned int port) const { return IPPortToAddressString(ip, port); } - virtual bool AddressToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) const { return AddressStringToIPPort(address, ip, port); } + AZStd::string IPPortToAddress(const char* ip, unsigned int port) const override { return IPPortToAddressString(ip, port); } + bool AddressToIPPort(const AZStd::string& address, AZStd::string& ip, unsigned int& port) const override { return AddressStringToIPPort(address, ip, port); } /// Create address for the socket driver from IP and port static AZStd::string IPPortToAddressString(const char* ip, unsigned int port); /// Decompose an address to IP and port @@ -174,7 +174,7 @@ namespace GridMate static BSDSocketFamilyType AddressFamilyType(const char* ip) { return AddressFamilyType(AZStd::string(ip)); } /// @} - virtual AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address) = 0; + AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address) override = 0; /// Additional CreateDriverAddress function should be implemented. virtual AZStd::intrusive_ptr CreateDriverAddress(const sockaddr* sockAddr) = 0; @@ -352,10 +352,10 @@ namespace GridMate * \note Driver address allocates internal resources, use it only when you intend to communicate. Otherwise operate with * the string address. */ - virtual AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address); - virtual AZStd::intrusive_ptr CreateDriverAddress(const sockaddr* addr); + AZStd::intrusive_ptr CreateDriverAddress(const AZStd::string& address) override; + AZStd::intrusive_ptr CreateDriverAddress(const sockaddr* addr) override; /// Called only from the DriverAddress when the use count becomes 0 - virtual void DestroyDriverAddress(DriverAddress* address); + void DestroyDriverAddress(DriverAddress* address) override; typedef AZStd::unordered_set AddressSetType; AddressSetType m_addressMap; diff --git a/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h b/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h index 59f178976f..7af318287a 100644 --- a/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h +++ b/Code/Framework/GridMate/GridMate/Drillers/SessionDriller.h @@ -33,42 +33,42 @@ namespace GridMate ////////////////////////////////////////////////////////////////////////// // Driller - virtual const char* GroupName() const { return "GridMate"; } - virtual const char* GetName() const { return "SessionDriller"; } - virtual const char* GetDescription() const { return "Drills GridSession, Search, etc."; } - virtual void Start(const Param* params = NULL, int numParams = 0); - virtual void Stop(); + const char* GroupName() const override { return "GridMate"; } + const char* GetName() const override { return "SessionDriller"; } + const char* GetDescription() const override { return "Drills GridSession, Search, etc."; } + void Start(const Param* params = NULL, int numParams = 0) override; + void Stop() override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Session Event Bus /// Callback that is called when the Session service is ready to process sessions. - virtual void OnSessionServiceReady(); + void OnSessionServiceReady() override; //virtual OnCommucationChanged() = 0 Callback that notifies the title when a member's communication settings change. /// Callback that notifies the title when a game search query have completed. - virtual void OnGridSearchComplete(GridSearch* gridSearch); + void OnGridSearchComplete(GridSearch* gridSearch) override; /// Callback that notifies the title when a new member joins the game session. - virtual void OnMemberJoined(GridSession* session, GridMember* member); + void OnMemberJoined(GridSession* session, GridMember* member) override; /// Callback that notifies the title that a member is leaving the game session. member pointer is NOT valid after the callback returns. - virtual void OnMemberLeaving(GridSession* session, GridMember* member); + void OnMemberLeaving(GridSession* session, GridMember* member) override; // \todo a better way will be (after we solve migration) is to supply a reason to OnMemberLeaving... like the member was kicked. // this will require that we actually remove the replica at the same moment. /// Callback that host decided to kick a member. You will receive a OnMemberLeaving when the actual member leaves the session. - virtual void OnMemberKicked(GridSession* session, GridMember* member); + void OnMemberKicked(GridSession* session, GridMember* member) override; /// After this callback it is safe to access session features. If host session is fully operational if client wait for OnSessionJoined. - virtual void OnSessionCreated(GridSession* session); + void OnSessionCreated(GridSession* session) override; /// Called on client machines to indicate that we join successfully. - virtual void OnSessionJoined(GridSession* session); + void OnSessionJoined(GridSession* session) override; /// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns. - virtual void OnSessionDelete(GridSession* session); + void OnSessionDelete(GridSession* session) override; /// Called when a session error occurs. - virtual void OnSessionError(GridSession* session, const AZStd::string& errorMsg); + void OnSessionError(GridSession* session, const AZStd::string& errorMsg) override; /// Called when the actual game(match) starts - virtual void OnSessionStart(GridSession* session); + void OnSessionStart(GridSession* session) override; /// Called when the actual game(match) ends - virtual void OnSessionEnd(GridSession* session); + void OnSessionEnd(GridSession* session) override; /// Called when we have our last chance to write statistics data for member in the session. - virtual void OnWriteStatistics(GridSession* session, GridMember* member, StatisticsData& data); + void OnWriteStatistics(GridSession* session, GridMember* member, StatisticsData& data) override; ////////////////////////////////////////////////////////////////////////// }; } diff --git a/Code/Framework/GridMate/GridMate/Replica/DataSet.h b/Code/Framework/GridMate/GridMate/Replica/DataSet.h index b0c5e669c1..1c1b6209c5 100644 --- a/Code/Framework/GridMate/GridMate/Replica/DataSet.h +++ b/Code/Framework/GridMate/GridMate/Replica/DataSet.h @@ -525,12 +525,12 @@ namespace GridMate void Set(const DataType& val) { m_value = val; } const DataType& Get() const { return m_value; } - virtual void Marshal(WriteBuffer& wb) + void Marshal(WriteBuffer& wb) override { wb.Write(m_value, m_marshaler); } - virtual void Unmarshal(ReadBuffer& rb) + void Unmarshal(ReadBuffer& rb) override { rb.Read(m_value, m_marshaler); } diff --git a/Code/Framework/GridMate/GridMate/Replica/MigrationSequence.h b/Code/Framework/GridMate/GridMate/Replica/MigrationSequence.h index ea4ed683b7..35febb873a 100644 --- a/Code/Framework/GridMate/GridMate/Replica/MigrationSequence.h +++ b/Code/Framework/GridMate/GridMate/Replica/MigrationSequence.h @@ -64,8 +64,8 @@ namespace GridMate /////////////////////////////////////////////////////////////////// // ReplicaMgrCallbackBus - virtual void OnDeactivateReplica(ReplicaId replicaId, ReplicaManager* pMgr) override; - virtual void OnPeerRemoved(PeerId peerId, ReplicaManager* pMgr) override; + void OnDeactivateReplica(ReplicaId replicaId, ReplicaManager* pMgr) override; + void OnPeerRemoved(PeerId peerId, ReplicaManager* pMgr) override; /////////////////////////////////////////////////////////////////// void OnReceivedAckUpstreamSuspended(PeerId from, AZ::u32 requestTime); diff --git a/Code/Legacy/CryCommon/IMiniLog.h b/Code/Legacy/CryCommon/IMiniLog.h index 51ff5f586e..ad6921cf09 100644 --- a/Code/Legacy/CryCommon/IMiniLog.h +++ b/Code/Legacy/CryCommon/IMiniLog.h @@ -119,8 +119,8 @@ struct CNullMiniLog // The default implementation just won't do anything //##@{ void LogV([[maybe_unused]] const char* szFormat, [[maybe_unused]] va_list args) {} - void LogV([[maybe_unused]] ELogType nType, [[maybe_unused]] const char* szFormat, [[maybe_unused]] va_list args) {} - void LogV ([[maybe_unused]] ELogType nType, [[maybe_unused]] int flags, [[maybe_unused]] const char* szFormat, [[maybe_unused]] va_list args) {} + void LogV([[maybe_unused]] ELogType nType, [[maybe_unused]] const char* szFormat, [[maybe_unused]] va_list args) override {} + void LogV ([[maybe_unused]] ELogType nType, [[maybe_unused]] int flags, [[maybe_unused]] const char* szFormat, [[maybe_unused]] va_list args) override {} //##@} }; diff --git a/Code/Legacy/CryCommon/SimpleSerialize.h b/Code/Legacy/CryCommon/SimpleSerialize.h index 2fd57b7bc3..8b7108ba6a 100644 --- a/Code/Legacy/CryCommon/SimpleSerialize.h +++ b/Code/Legacy/CryCommon/SimpleSerialize.h @@ -54,39 +54,39 @@ public: { } - void BeginGroup(const char* szName) + void BeginGroup(const char* szName) override { m_impl.BeginGroup(szName); } - bool BeginOptionalGroup(const char* szName, bool condition) + bool BeginOptionalGroup(const char* szName, bool condition) override { return m_impl.BeginOptionalGroup(szName, condition); } - void EndGroup() + void EndGroup() override { m_impl.EndGroup(); } - bool IsReading() const + bool IsReading() const override { return m_impl.IsReading(); } - void WriteStringValue(const char* name, SSerializeString& value) + void WriteStringValue(const char* name, SSerializeString& value) override { m_impl.Value(name, value); } - void ReadStringValue(const char* name, SSerializeString& curValue) + void ReadStringValue(const char* name, SSerializeString& curValue) override { m_impl.Value(name, curValue); } -#define SERIALIZATION_TYPE(T) \ - void Value(const char* name, T& x) override \ - { \ - m_impl.Value(name, x); \ +#define SERIALIZATION_TYPE(T) \ + void Value(const char* name, T& x) override \ + { \ + m_impl.Value(name, x); \ } #include "SerializationTypes.h" #undef SERIALIZATION_TYPE diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.h b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.h index 836d2c2484..d7230347e9 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.h +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.h @@ -25,9 +25,9 @@ public: CLevelInfo() = default; // ILevelInfo - virtual const char* GetName() const { return m_levelName.c_str(); } - virtual const char* GetPath() const { return m_levelPath.c_str(); } - virtual const char* GetAssetName() const { return m_levelAssetName.c_str(); } + const char* GetName() const override { return m_levelName.c_str(); } + const char* GetPath() const override { return m_levelPath.c_str(); } + const char* GetAssetName() const override { return m_levelAssetName.c_str(); } // ~ILevelInfo @@ -62,9 +62,9 @@ public: CLevel() {} virtual ~CLevel() = default; - virtual void Release() { delete this; } + void Release() override { delete this; } - virtual ILevelInfo* GetLevelInfo() { return &m_levelInfo; } + ILevelInfo* GetLevelInfo() override { return &m_levelInfo; } private: CLevelInfo m_levelInfo; @@ -77,38 +77,35 @@ public: CLevelSystem(ISystem* pSystem, const char* levelsFolder); virtual ~CLevelSystem(); - void Release() { delete this; }; + void Release() override { delete this; }; // ILevelSystem - virtual void Rescan(const char* levelsFolder); - virtual int GetLevelCount(); - virtual ILevelInfo* GetLevelInfo(int level); - virtual ILevelInfo* GetLevelInfo(const char* levelName); + void Rescan(const char* levelsFolder) override; + int GetLevelCount() override; + ILevelInfo* GetLevelInfo(int level) override; + ILevelInfo* GetLevelInfo(const char* levelName) override; - virtual void AddListener(ILevelSystemListener* pListener); - virtual void RemoveListener(ILevelSystemListener* pListener); + void AddListener(ILevelSystemListener* pListener) override; + void RemoveListener(ILevelSystemListener* pListener) override; - virtual bool LoadLevel(const char* levelName); - virtual void UnloadLevel(); - virtual bool IsLevelLoaded() { return m_bLevelLoaded; } + bool LoadLevel(const char* levelName) override; + void UnloadLevel() override; + bool IsLevelLoaded() override { return m_bLevelLoaded; } const char* GetCurrentLevelName() const override { if (m_pCurrentLevel && m_pCurrentLevel->GetLevelInfo()) { return m_pCurrentLevel->GetLevelInfo()->GetName(); } - else - { - return ""; - } + return ""; } // If the level load failed then we need to have a different shutdown procedure vs when a level is naturally unloaded - virtual void SetLevelLoadFailed(bool loadFailed) { m_levelLoadFailed = loadFailed; } - virtual bool GetLevelLoadFailed() { return m_levelLoadFailed; } + void SetLevelLoadFailed(bool loadFailed) override { m_levelLoadFailed = loadFailed; } + bool GetLevelLoadFailed() override { return m_levelLoadFailed; } // Unsupported by legacy level system. - virtual AZ::Data::AssetType GetLevelAssetType() const { return {}; } + AZ::Data::AssetType GetLevelAssetType() const override { return {}; } // ~ILevelSystem diff --git a/Code/Legacy/CrySystem/XConsoleVariable.h b/Code/Legacy/CrySystem/XConsoleVariable.h index 13808e7dd6..3ff71f9f39 100644 --- a/Code/Legacy/CrySystem/XConsoleVariable.h +++ b/Code/Legacy/CrySystem/XConsoleVariable.h @@ -34,7 +34,7 @@ public: void Release() override; void ForceSet(const char* s) override; void SetOnChangeCallback(ConsoleVarFunc pChangeFunc) override; - virtual uint64 AddOnChangeFunctor(const SFunctor& pChangeFunctor) override; + uint64 AddOnChangeFunctor(const AZStd::function& pChangeFunctor) override; ConsoleVarFunc GetOnChangeCallback() const override; bool ShouldReset() const { return (m_nFlags & VF_RESETTABLE) != 0; } @@ -77,7 +77,7 @@ protected: // ------------------------------------------------------------------ char* m_pDataProbeString; // value client is required to have for data probes int m_nFlags; // e.g. VF_CHEAT, ... - typedef std::vector> > ChangeFunctorContainer; + using ChangeFunctorContainer = std::vector> >; ChangeFunctorContainer m_changeFunctors; ConsoleVarFunc m_pChangeFunc; // Callback function that is called when this variable changes. CXConsole* m_pConsole; // used for the callback OnBeforeVarChange() @@ -169,15 +169,15 @@ public: // interface ICVar -------------------------------------------------------------------------------------- - virtual int GetIVal() const { return (int)m_fValue; } - virtual int64 GetI64Val() const { return (int64)m_fValue; } - virtual float GetFVal() const { return m_fValue; } - virtual const char* GetString() const; - virtual void ResetImpl() { Set(m_fDefault); } - virtual void Set(const char* s); - virtual void Set(float f); - virtual void Set(int i); - virtual int GetType() { return CVAR_FLOAT; } + int GetIVal() const override { return (int)m_fValue; } + int64 GetI64Val() const override { return (int64)m_fValue; } + float GetFVal() const override { return m_fValue; } + const char* GetString() const override; + void ResetImpl() override { Set(m_fDefault); } + void Set(const char* s) override; + void Set(float f) override; + void Set(int i) override; + int GetType() override { return CVAR_FLOAT; } protected: @@ -212,15 +212,15 @@ public: // interface ICVar -------------------------------------------------------------------------------------- - virtual int GetIVal() const { return m_iValue; } - virtual int64 GetI64Val() const { return m_iValue; } - virtual float GetFVal() const { return (float)m_iValue; } - virtual const char* GetString() const; - virtual void ResetImpl() { Set(m_iDefault); } - virtual void Set(const char* s); - virtual void Set(float f); - virtual void Set(int i); - virtual int GetType() { return CVAR_INT; } + int GetIVal() const override { return m_iValue; } + int64 GetI64Val() const override { return m_iValue; } + float GetFVal() const override { return (float)m_iValue; } + const char* GetString() const override; + void ResetImpl() override { Set(m_iDefault); } + void Set(const char* s) override; + void Set(float f) override; + void Set(int i) override; + int GetType() override { return CVAR_INT; } private: // -------------------------------------------------------------------------------------------- @@ -246,26 +246,26 @@ public: // interface ICVar -------------------------------------------------------------------------------------- - virtual int GetIVal() const { return atoi(m_sValue.c_str()); } - virtual int64 GetI64Val() const { return _atoi64(m_sValue.c_str()); } - virtual float GetFVal() const { return (float)atof(m_sValue.c_str()); } - virtual const char* GetString() const + int GetIVal() const override { return atoi(m_sValue.c_str()); } + int64 GetI64Val() const override { return _atoi64(m_sValue.c_str()); } + float GetFVal() const override { return (float)atof(m_sValue.c_str()); } + const char* GetString() const override { return m_sValue.c_str(); } - virtual void ResetImpl() { Set(m_sDefault.c_str()); } - virtual void Set(const char* s); - virtual void Set(float f) + void ResetImpl() override { Set(m_sDefault.c_str()); } + void Set(const char* s) override; + void Set(float f) override { stack_string s = stack_string::format("%g", f); Set(s.c_str()); } - virtual void Set(int i) + void Set(int i) override { stack_string s = stack_string::format("%d", i); Set(s.c_str()); } - virtual int GetType() { return CVAR_STRING; } + int GetType() override { return CVAR_STRING; } private: // -------------------------------------------------------------------------------------------- @@ -290,19 +290,19 @@ public: // interface ICVar -------------------------------------------------------------------------------------- - virtual int GetIVal() const { return (int)m_fValue; } - virtual int64 GetI64Val() const { return (int64)m_fValue; } - virtual float GetFVal() const { return m_fValue; } - virtual const char* GetString() const; - virtual void ResetImpl() { Set(m_fDefault); } - virtual void Set(const char* s); - virtual void Set(float f); - virtual void Set(int i); - virtual int GetType() { return CVAR_FLOAT; } + int GetIVal() const override { return (int)m_fValue; } + int64 GetI64Val() const override { return (int64)m_fValue; } + float GetFVal() const override { return m_fValue; } + const char* GetString() const override; + void ResetImpl() override { Set(m_fDefault); } + void Set(const char* s) override; + void Set(float f) override; + void Set(int i) override; + int GetType() override { return CVAR_FLOAT; } protected: - virtual const char *GetOwnDataProbeString() const + const char *GetOwnDataProbeString() const override { static char szReturnString[8]; diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryNode.h b/Code/Legacy/CrySystem/XML/XMLBinaryNode.h index d6c66e79f3..b4706f1b85 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryNode.h +++ b/Code/Legacy/CrySystem/XML/XMLBinaryNode.h @@ -63,17 +63,17 @@ public: //void* operator new( size_t nSize ); //void operator delete( void *ptr ); - virtual void DeleteThis() { } + void DeleteThis() override { } //! Create new XML node. - XmlNodeRef createNode(const char* tag); + XmlNodeRef createNode(const char* tag) override; // Summary: // Reference counting. - virtual void AddRef() { ++m_pData->nRefCount; }; + void AddRef() override { ++m_pData->nRefCount; }; // Notes: // When ref count reach zero XML node dies. - virtual void Release() + void Release() override { if (--m_pData->nRefCount <= 0) { @@ -82,105 +82,105 @@ public: }; //! Get XML node tag. - const char* getTag() const { return _string(_node()->nTagStringOffset); }; - void setTag([[maybe_unused]] const char* tag) { assert(0); }; + const char* getTag() const override { return _string(_node()->nTagStringOffset); }; + void setTag([[maybe_unused]] const char* tag) override { assert(0); }; //! Return true if given tag is equal to node tag. - bool isTag(const char* tag) const; + bool isTag(const char* tag) const override; //! Get XML Node attributes. - virtual int getNumAttributes() const { return (int)_node()->nAttributeCount; }; + int getNumAttributes() const override { return (int)_node()->nAttributeCount; }; //! Return attribute key and value by attribute index. - virtual bool getAttributeByIndex(int index, const char** key, const char** value); + bool getAttributeByIndex(int index, const char** key, const char** value) override; //! Return attribute key and value by attribute index, string version. virtual bool getAttributeByIndex(int index, XmlString& key, XmlString& value); - virtual void shareChildren([[maybe_unused]] const XmlNodeRef& fromNode) { assert(0); }; - virtual void copyAttributes(XmlNodeRef fromNode) { assert(0); }; + void shareChildren([[maybe_unused]] const XmlNodeRef& fromNode) override { assert(0); }; + void copyAttributes(XmlNodeRef fromNode) override { assert(0); }; //! Get XML Node attribute for specified key. - const char* getAttr(const char* key) const; + const char* getAttr(const char* key) const override; //! Get XML Node attribute for specified key. // Returns true if the attribute exists, false otherwise. - bool getAttr(const char* key, const char** value) const; + bool getAttr(const char* key, const char** value) const override; //! Check if attributes with specified key exist. - bool haveAttr(const char* key) const; + bool haveAttr(const char* key) const override; - XmlNodeRef newChild([[maybe_unused]] const char* tagName) { assert(0); return 0; }; - void replaceChild([[maybe_unused]] int inChild, [[maybe_unused]] const XmlNodeRef& node) { assert(0); }; - void insertChild([[maybe_unused]] int inChild, [[maybe_unused]] const XmlNodeRef& node) { assert(0); }; - void addChild([[maybe_unused]] const XmlNodeRef& node) { assert(0); }; - void removeChild([[maybe_unused]] const XmlNodeRef& node) { assert(0); }; + XmlNodeRef newChild([[maybe_unused]] const char* tagName) override { assert(0); return 0; }; + void replaceChild([[maybe_unused]] int inChild, [[maybe_unused]] const XmlNodeRef& node) override { assert(0); }; + void insertChild([[maybe_unused]] int inChild, [[maybe_unused]] const XmlNodeRef& node) override { assert(0); }; + void addChild([[maybe_unused]] const XmlNodeRef& node) override { assert(0); }; + void removeChild([[maybe_unused]] const XmlNodeRef& node) override { assert(0); }; //! Remove all child nodes. - void removeAllChilds() { assert(0); }; + void removeAllChilds() override { assert(0); }; //! Get number of child XML nodes. - int getChildCount() const { return (int)_node()->nChildCount; }; + int getChildCount() const override { return (int)_node()->nChildCount; }; //! Get XML Node child nodes. - XmlNodeRef getChild(int i) const; + XmlNodeRef getChild(int i) const override; //! Find node with specified tag. - XmlNodeRef findChild(const char* tag) const; + XmlNodeRef findChild(const char* tag) const override; void deleteChild([[maybe_unused]] const char* tag) { assert(0); }; - void deleteChildAt([[maybe_unused]] int nIndex) { assert(0); }; + void deleteChildAt([[maybe_unused]] int nIndex) override { assert(0); }; //! Get parent XML node. - XmlNodeRef getParent() const; + XmlNodeRef getParent() const override; //! Returns content of this node. - const char* getContent() const { return _string(_node()->nContentStringOffset); }; - void setContent([[maybe_unused]] const char* str) { assert(0); }; + const char* getContent() const override { return _string(_node()->nContentStringOffset); }; + void setContent([[maybe_unused]] const char* str) override { assert(0); }; - XmlNodeRef clone() { assert(0); return 0; }; + XmlNodeRef clone() override { assert(0); return 0; }; //! Returns line number for XML tag. - int getLine() const { return 0; }; + int getLine() const override { return 0; }; //! Set line number in xml. - void setLine([[maybe_unused]] int line) { assert(0); }; + void setLine([[maybe_unused]] int line) override { assert(0); }; //! Returns XML of this node and sub nodes. - virtual IXmlStringData* getXMLData([[maybe_unused]] int nReserveMem = 0) const { assert(0); return 0; }; - XmlString getXML([[maybe_unused]] int level = 0) const { assert(0); return ""; }; - bool saveToFile([[maybe_unused]] const char* fileName) { assert(0); return false; }; // saves in one huge chunk - bool saveToFile([[maybe_unused]] const char* fileName, [[maybe_unused]] size_t chunkSizeBytes, [[maybe_unused]] AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle) { assert(0); return false; }; // save in small memory chunks + IXmlStringData* getXMLData([[maybe_unused]] int nReserveMem = 0) const override { assert(0); return 0; }; + XmlString getXML([[maybe_unused]] int level = 0) const override { assert(0); return ""; }; + bool saveToFile([[maybe_unused]] const char* fileName) override { assert(0); return false; }; // saves in one huge chunk + bool saveToFile([[maybe_unused]] const char* fileName, [[maybe_unused]] size_t chunkSizeBytes, [[maybe_unused]] AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle) override { assert(0); return false; }; // save in small memory chunks //! Set new XML Node attribute (or override attribute with same key). using IXmlNode::setAttr; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const char* value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] int value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] unsigned int value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] int64 value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] uint64 value, [[maybe_unused]] bool useHexFormat = true /* ignored */) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] float value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] f64 value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Vec2& value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Ang3& value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Vec3& value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Vec4& value) { assert(0); }; - void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Quat& value) { assert(0); }; - void delAttr([[maybe_unused]] const char* key) { assert(0); }; - void removeAllAttributes() { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const char* value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] int value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] unsigned int value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] int64 value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] uint64 value, [[maybe_unused]] bool useHexFormat = true /* ignored */) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] float value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] f64 value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Vec2& value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Ang3& value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Vec3& value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Vec4& value) override { assert(0); }; + void setAttr([[maybe_unused]] const char* key, [[maybe_unused]] const Quat& value) override { assert(0); }; + void delAttr([[maybe_unused]] const char* key) override { assert(0); }; + void removeAllAttributes() override { assert(0); }; //! Get attribute value of node. - bool getAttr(const char* key, int& value) const; - bool getAttr(const char* key, unsigned int& value) const; - bool getAttr(const char* key, int64& value) const; - bool getAttr(const char* key, uint64& value, bool useHexFormat = true /* ignored */) const; - bool getAttr(const char* key, float& value) const; - bool getAttr(const char* key, f64& value) const; - bool getAttr(const char* key, bool& value) const; - bool getAttr(const char* key, XmlString& value) const {const char* v(NULL); bool boHasAttribute(getAttr(key, &v)); value = v; return boHasAttribute; } - bool getAttr(const char* key, Vec2& value) const; - bool getAttr(const char* key, Ang3& value) const; - bool getAttr(const char* key, Vec3& value) const; - bool getAttr(const char* key, Vec4& value) const; - bool getAttr(const char* key, Quat& value) const; - bool getAttr(const char* key, ColorB& value) const; + bool getAttr(const char* key, int& value) const override; + bool getAttr(const char* key, unsigned int& value) const override; + bool getAttr(const char* key, int64& value) const override; + bool getAttr(const char* key, uint64& value, bool useHexFormat = true /* ignored */) const override; + bool getAttr(const char* key, float& value) const override; + bool getAttr(const char* key, f64& value) const override; + bool getAttr(const char* key, bool& value) const override; + bool getAttr(const char* key, XmlString& value) const override {const char* v(NULL); bool boHasAttribute(getAttr(key, &v)); value = v; return boHasAttribute; } + bool getAttr(const char* key, Vec2& value) const override; + bool getAttr(const char* key, Ang3& value) const override; + bool getAttr(const char* key, Vec3& value) const override; + bool getAttr(const char* key, Vec4& value) const override; + bool getAttr(const char* key, Quat& value) const override; + bool getAttr(const char* key, ColorB& value) const override; private: ////////////////////////////////////////////////////////////////////////// @@ -217,7 +217,7 @@ private: } protected: - virtual void setParent([[maybe_unused]] const XmlNodeRef& inRef) { assert(0); } + void setParent([[maybe_unused]] const XmlNodeRef& inRef) override { assert(0); } ////////////////////////////////////////////////////////////////////////// private: diff --git a/Code/Tools/GridHub/GridHub/gridhub.hxx b/Code/Tools/GridHub/GridHub/gridhub.hxx index 849dbb92e1..14ed468345 100644 --- a/Code/Tools/GridHub/GridHub/gridhub.hxx +++ b/Code/Tools/GridHub/GridHub/gridhub.hxx @@ -57,8 +57,8 @@ public slots: protected: void SanityCheckDetectionTimeout(); - void timerEvent(QTimerEvent *event); - void closeEvent(QCloseEvent *event); + void timerEvent(QTimerEvent *event) override; + void closeEvent(QCloseEvent *event) override; void SystemTick(); private: @@ -125,7 +125,7 @@ public: /// Callback that is called when the Session service is ready to process sessions. void OnSessionServiceReady() override {} /// Callback that notifies the title when a game search query have completed. - void OnGridSearchComplete(GridMate::GridSearch* gridSearch) { (void)gridSearch; } + void OnGridSearchComplete(GridMate::GridSearch* gridSearch) override { (void)gridSearch; } /// Callback that notifies the title when a new member joins the game session. void OnMemberJoined(GridMate::GridSession* session, GridMate::GridMember* member) override; /// Callback that notifies the title that a member is leaving the game session. member pointer is NOT valid after the callback returns. @@ -133,25 +133,25 @@ public: // \todo a better way will be (after we solve migration) is to supply a reason to OnMemberLeaving... like the member was kicked. // this will require that we actually remove the replica at the same moment. /// Callback that host decided to kick a member. You will receive a OnMemberLeaving when the actual member leaves the session. - void OnMemberKicked(GridMate::GridSession* session, GridMate::GridMember* member, AZ::u8 reason) { (void)session;(void)member;(void)reason; } + void OnMemberKicked(GridMate::GridSession* session, GridMate::GridMember* member, AZ::u8 reason) override { (void)session;(void)member;(void)reason; } /// After this callback it is safe to access session features. If host session is fully operational if client wait for OnSessionJoined. void OnSessionCreated(GridMate::GridSession* session) override; /// Called on client machines to indicate that we join successfully. - void OnSessionJoined(GridMate::GridSession* session) { (void)session; } + void OnSessionJoined(GridMate::GridSession* session) override { (void)session; } /// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns. void OnSessionDelete(GridMate::GridSession* session) override; /// Called when a session error occurs. - void OnSessionError(GridMate::GridSession* session, const AZStd::string& errorMsg ) { (void)session; (void)errorMsg; } + void OnSessionError(GridMate::GridSession* session, const AZStd::string& errorMsg ) override { (void)session; (void)errorMsg; } /// Called when the actual game(match) starts - void OnSessionStart(GridMate::GridSession* session) { (void)session; } + void OnSessionStart(GridMate::GridSession* session) override { (void)session; } /// Called when the actual game(match) ends - void OnSessionEnd(GridMate::GridSession* session) { (void)session; } + void OnSessionEnd(GridMate::GridSession* session) override { (void)session; } /// Called when we start a host migration. - void OnMigrationStart(GridMate::GridSession* session) { (void)session; } + void OnMigrationStart(GridMate::GridSession* session) override { (void)session; } /// Called so the user can select a member that should be the new Host. Value will be ignored if NULL, current host or the member has invalid connection id. - void OnMigrationElectHost(GridMate::GridSession* session,GridMate::GridMember*& newHost) { (void)session;(void)newHost; } + void OnMigrationElectHost(GridMate::GridSession* session,GridMate::GridMember*& newHost) override { (void)session;(void)newHost; } /// Called when the host migration has completed. - void OnMigrationEnd(GridMate::GridSession* session,GridMate::GridMember* newHost) { (void)session;(void)newHost; } + void OnMigrationEnd(GridMate::GridSession* session,GridMate::GridMember* newHost) override { (void)session;(void)newHost; } ////////////////////////////////////////////////////////////////////////// void SetUI(GridHub* ui) { m_ui = ui; } diff --git a/Code/Tools/GridHub/GridHub/main.cpp b/Code/Tools/GridHub/GridHub/main.cpp index 3b853910be..fe27301714 100644 --- a/Code/Tools/GridHub/GridHub/main.cpp +++ b/Code/Tools/GridHub/GridHub/main.cpp @@ -140,7 +140,7 @@ protected: * ComponentApplication::RegisterCoreComponents and then register the application * specific core components. */ - virtual void RegisterCoreComponents(); + void RegisterCoreComponents() override; /** AZ::SystemTickBus::Handler @@ -220,7 +220,7 @@ public: } //virtual bool QGridHubApplication::winEventFilter( MSG *msg , long *result) - virtual bool nativeEventFilter(const QByteArray &eventType, void *message, [[maybe_unused]] long *result) + bool nativeEventFilter(const QByteArray &eventType, void *message, [[maybe_unused]] long *result) override { #ifdef AZ_PLATFORM_WINDOWS if ((eventType == "windows_generic_MSG")||(eventType == "windows_dispatcher_MSG")) diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h index d9a6f7aba6..458cfc44a2 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.h @@ -94,11 +94,11 @@ struct SNoDataEvent { SNoDataEvent() : IRemoteEvent(T) {}; - virtual IRemoteEvent* Clone() { return new SNoDataEvent(); } + IRemoteEvent* Clone() override { return new SNoDataEvent(); } protected: - virtual void WriteToBuffer([[maybe_unused]] char* buffer, int& size, [[maybe_unused]] int maxsize) { size = 0; } - virtual IRemoteEvent* CreateFromBuffer([[maybe_unused]] const char* buffer, [[maybe_unused]] int size) { return Clone(); } + void WriteToBuffer([[maybe_unused]] char* buffer, int& size, [[maybe_unused]] int maxsize) override { size = 0; } + IRemoteEvent* CreateFromBuffer([[maybe_unused]] const char* buffer, [[maybe_unused]] int size) override { return Clone(); } }; ///////////////////////////////////////////////////////////////////////////////////////////// @@ -109,17 +109,17 @@ struct SStringEvent SStringEvent(const char* data) : IRemoteEvent(T) , m_data(data) {}; - virtual IRemoteEvent* Clone() { return new SStringEvent(GetData()); } + IRemoteEvent* Clone() override { return new SStringEvent(GetData()); } const char* GetData() const { return m_data.c_str(); } protected: - virtual void WriteToBuffer(char* buffer, int& size, int maxsize) + void WriteToBuffer(char* buffer, int& size, int maxsize) override { const char* data = GetData(); size = min((int)strlen(data), maxsize); memcpy(buffer, data, size); } - virtual IRemoteEvent* CreateFromBuffer(const char* buffer, [[maybe_unused]] int size) { return new SStringEvent(buffer); } + IRemoteEvent* CreateFromBuffer(const char* buffer, [[maybe_unused]] int size) override { return new SStringEvent(buffer); } private: AZStd::string m_data; diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h index 240331496e..10b14ed5af 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h @@ -75,7 +75,7 @@ namespace AWSCore return (m_requestUrl.length() > 0); } - std::shared_ptr GetCredentialsProvider() + std::shared_ptr GetCredentialsProvider() override { ServiceClientJobConfigType::EnsureSettingsApplied(); return m_credentialsProvider; diff --git a/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.h b/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.h index 8f7a177ca2..e8b2c0acc3 100644 --- a/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.h +++ b/Gems/AssetValidation/Code/Source/AssetValidationSystemComponent.h @@ -92,7 +92,7 @@ namespace AssetValidation //////////////////////////////////////////////////////////////////////// // ArchiveNotificationBus interface implementation - void FileAccess(const char* filePath) /*override*/; + void FileAccess(const char* filePath) override /*override*/; //////////////////////////////////////////////////////////////////////// bool AddSeedList(const char* seedPath) override; diff --git a/Gems/Atom/RHI/Code/CMakeLists.txt b/Gems/Atom/RHI/Code/CMakeLists.txt index 879fc7d2ce..ae471b1ca1 100644 --- a/Gems/Atom/RHI/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Code/CMakeLists.txt @@ -55,9 +55,6 @@ ly_add_target( Gem::Atom_RHI.Reflect PUBLIC ${RENDERDOC_DEPENDENCY} - COMPILE_DEFINITIONS - PUBLIC - ${RENDERDOC_DEFINE} ) ly_add_target( diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MemoryTypeAllocator.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MemoryTypeAllocator.h index c628cb61e0..8fd083d4b9 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MemoryTypeAllocator.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/MemoryTypeAllocator.h @@ -38,7 +38,7 @@ namespace AZ void Init(const Descriptor& descriptor); - void Shutdown(); + void Shutdown() override; void GarbageCollect(); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Scope.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Scope.h index 86140e2c7c..dad356cab6 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Scope.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Scope.h @@ -142,7 +142,7 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// // FrameEventBus::Handler - void OnFrameCompileEnd(RHI::FrameGraph& frameGraph); + void OnFrameCompileEnd(RHI::FrameGraph& frameGraph) override; ////////////////////////////////////////////////////////////////////////// // Returns if a barrier can be converted to an implicit subpass barrier. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp index 180f6a5d99..7b3b6b7a28 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/ShaderCollection.cpp @@ -22,7 +22,7 @@ namespace AZ : public SerializeContext::IEventHandler { //! Called right before we start reading from the instance pointed by classPtr. - virtual void OnReadBegin(void* classPtr) + void OnReadBegin(void* classPtr) override { ShaderCollection::Item* shaderVariantReference = reinterpret_cast(classPtr); shaderVariantReference->m_shaderVariantId = shaderVariantReference->m_shaderOptionGroup.GetShaderVariantId(); diff --git a/Gems/AudioSystem/Code/Source/Engine/AudioSystem.h b/Gems/AudioSystem/Code/Source/Engine/AudioSystem.h index 1d8f8fb286..615d202e25 100644 --- a/Gems/AudioSystem/Code/Source/Engine/AudioSystem.h +++ b/Gems/AudioSystem/Code/Source/Engine/AudioSystem.h @@ -120,7 +120,7 @@ namespace Audio void FreeAudioProxy(IAudioProxy* const pIAudioProxy) override; TAudioSourceId CreateAudioSource(const SAudioInputConfig& sourceConfig) override; - void DestroyAudioSource(TAudioSourceId sourceId); + void DestroyAudioSource(TAudioSourceId sourceId) override; // When AUDIO_RELEASE is defined, these two functions always return nullptr const char* GetAudioControlName(const EAudioControlType controlType, const TATLIDType atlID) const override; diff --git a/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashHandler.h b/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashHandler.h index 08d3ccf90b..e5aaaa2e93 100644 --- a/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashHandler.h +++ b/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashHandler.h @@ -22,13 +22,13 @@ namespace CrashHandler static void InitCrashHandler(const std::string& moduleTag, const std::string& devRoot, const std::string& crashUrl = {}, const std::string& crashToken = {}, const std::string& handlerFolder = {}, const CrashHandlerAnnotations& baseAnnotations = CrashHandlerAnnotations(), const CrashHandlerArguments& argumentVec = CrashHandlerArguments()); protected: - virtual const char* GetCrashHandlerExecutableName() const override; - virtual std::string DetermineAppPath() const override; + const char* GetCrashHandlerExecutableName() const override; + std::string DetermineAppPath() const override; - virtual std::string GetCrashSubmissionURL() const override; - virtual std::string GetCrashSubmissionToken() const override; + std::string GetCrashSubmissionURL() const override; + std::string GetCrashSubmissionToken() const override; - virtual std::string GetCrashHandlerPath(const std::string& lyAppRoot) const override; + std::string GetCrashHandlerPath(const std::string& lyAppRoot) const override; }; diff --git a/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h b/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h index 48d2bd25f7..c48440bed4 100644 --- a/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h +++ b/Gems/CrashReporting/Code/Include/CrashReporting/GameCrashUploader.h @@ -17,7 +17,7 @@ namespace O3de { public: GameCrashUploader(int& argcount, char** argv); - virtual bool CheckConfirmation(const crashpad::CrashReportDatabase::Report& report) override; + bool CheckConfirmation(const crashpad::CrashReportDatabase::Report& report) override; static std::string GetRootFolder(); }; diff --git a/Gems/DebugDraw/Code/Source/DebugDrawSystemComponent.h b/Gems/DebugDraw/Code/Source/DebugDrawSystemComponent.h index 24a6eae3aa..b534bd3bd4 100644 --- a/Gems/DebugDraw/Code/Source/DebugDrawSystemComponent.h +++ b/Gems/DebugDraw/Code/Source/DebugDrawSystemComponent.h @@ -117,7 +117,7 @@ namespace DebugDraw void OnBeginPrepareRender() override; // AZ::Render::Bootstrap::NotificationBus - void OnBootstrapSceneReady(AZ::RPI::Scene* scene); + void OnBootstrapSceneReady(AZ::RPI::Scene* scene) override; // EntityBus void OnEntityDeactivated(const AZ::EntityId& entityId) override; diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h index bf5d13d8fe..1dac643667 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeBool.h @@ -44,7 +44,7 @@ namespace MCore // overloaded from the attribute base class Attribute* Clone() const override { return AttributeBool::Create(m_value); } const char* GetTypeString() const override { return "AttributeBool"; } - bool InitFrom(const Attribute* other); + bool InitFrom(const Attribute* other) override; bool InitFromString(const AZStd::string& valueString) override { return AzFramework::StringFunc::LooksLikeBool(valueString.c_str(), &m_value); diff --git a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h index e195d584a5..ebde060209 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h +++ b/Gems/EMotionFX/Code/MCore/Source/AttributeInt32.h @@ -45,7 +45,7 @@ namespace MCore // overloaded from the attribute base class Attribute* Clone() const override { return AttributeInt32::Create(m_value); } const char* GetTypeString() const override { return "AttributeInt32"; } - bool InitFrom(const Attribute* other); + bool InitFrom(const Attribute* other) override; bool InitFromString(const AZStd::string& valueString) override { return AzFramework::StringFunc::LooksLikeInt(valueString.c_str(), &m_value); diff --git a/Gems/ExpressionEvaluation/Code/Source/ExpressionEvaluationSystemComponent.cpp b/Gems/ExpressionEvaluation/Code/Source/ExpressionEvaluationSystemComponent.cpp index 1a72f30e7c..5c4b9c61d9 100644 --- a/Gems/ExpressionEvaluation/Code/Source/ExpressionEvaluationSystemComponent.cpp +++ b/Gems/ExpressionEvaluation/Code/Source/ExpressionEvaluationSystemComponent.cpp @@ -37,12 +37,12 @@ namespace ExpressionEvaluation } - ExpressionParserId GetParserId() const + ExpressionParserId GetParserId() const override { return InternalTypes::Interfaces::InternalParser; } - ParseResult ParseElement(const AZStd::string& inputText, size_t offset) const + ParseResult ParseElement(const AZStd::string& inputText, size_t offset) const override { ParseResult result; AZStd::smatch match; @@ -69,7 +69,7 @@ namespace ExpressionEvaluation return result; } - void EvaluateToken(const ElementInformation& parseResult, ExpressionResultStack& evaluationStack) const + void EvaluateToken(const ElementInformation& parseResult, ExpressionResultStack& evaluationStack) const override { AZ_UNUSED(parseResult); AZ_UNUSED(evaluationStack); diff --git a/Gems/LyShine/Code/Source/Sprite.h b/Gems/LyShine/Code/Source/Sprite.h index 8a645b78b1..0b2c790cf6 100644 --- a/Gems/LyShine/Code/Source/Sprite.h +++ b/Gems/LyShine/Code/Source/Sprite.h @@ -44,7 +44,7 @@ public: // member functions AZ::Vector2 GetSize() override; AZ::Vector2 GetCellSize(int cellIndex) override; const SpriteSheetCellContainer& GetSpriteSheetCells() const override; - virtual void SetSpriteSheetCells(const SpriteSheetCellContainer& cells); + void SetSpriteSheetCells(const SpriteSheetCellContainer& cells) override; void ClearSpriteSheetCells() override; void AddSpriteSheetCell(const SpriteSheetCell& spriteSheetCell) override; AZ::Vector2 GetCellUvSize(int cellIndex) const override; @@ -96,7 +96,7 @@ protected: // member functions bool CellIndexWithinRange(int cellIndex) const; private: // types - typedef AZStd::unordered_map, stl::equality_string_caseless > CSpriteHashMap; + using CSpriteHashMap = AZStd::unordered_map, stl::equality_string_caseless >; private: // member functions bool LoadFromXmlFile(); diff --git a/Gems/MultiplayerCompression/Code/Source/LZ4Compressor.h b/Gems/MultiplayerCompression/Code/Source/LZ4Compressor.h index 640cf03ee4..f7fec70813 100644 --- a/Gems/MultiplayerCompression/Code/Source/LZ4Compressor.h +++ b/Gems/MultiplayerCompression/Code/Source/LZ4Compressor.h @@ -31,13 +31,13 @@ namespace MultiplayerCompression LZ4Compressor() = default; const char* GetName() const { return CompressorName; } - AzNetworking::CompressorType GetType() const { return CompressorType; }; + AzNetworking::CompressorType GetType() const override { return CompressorType; }; - bool Init() { return true; } - size_t GetMaxChunkSize(size_t maxCompSize) const; - size_t GetMaxCompressedBufferSize(size_t uncompSize) const; + bool Init() override { return true; } + size_t GetMaxChunkSize(size_t maxCompSize) const override; + size_t GetMaxCompressedBufferSize(size_t uncompSize) const override; - AzNetworking::CompressorError Compress(const void* uncompData, size_t uncompSize, void* compData, size_t compDataSize, size_t& compSize); - AzNetworking::CompressorError Decompress(const void* compData, size_t compDataSize, void* uncompData, size_t uncompDataSize, size_t& consumedSize, size_t& uncompSize); + AzNetworking::CompressorError Compress(const void* uncompData, size_t uncompSize, void* compData, size_t compDataSize, size_t& compSize) override; + AzNetworking::CompressorError Decompress(const void* compData, size_t compDataSize, void* uncompData, size_t uncompDataSize, size_t& consumedSize, size_t& uncompSize) override; }; } diff --git a/Gems/Presence/Code/Source/PresenceSystemComponent.h b/Gems/Presence/Code/Source/PresenceSystemComponent.h index cc3ab48bae..bc4ec01906 100644 --- a/Gems/Presence/Code/Source/PresenceSystemComponent.h +++ b/Gems/Presence/Code/Source/PresenceSystemComponent.h @@ -43,7 +43,7 @@ namespace Presence //////////////////////////////////////////////////////////////////////// //! PresenceRequestBus interface implementation void SetPresence(const SetPresenceParams& params) override; - void QueryPresence(const QueryPresenceParams& params); + void QueryPresence(const QueryPresenceParams& params) override; public: //////////////////////////////////////////////////////////////////////// diff --git a/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset b/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset index a612135e94..2a248b216b 100644 --- a/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset +++ b/cmake/Platform/Common/MSVC/CodeAnalysis.ruleset @@ -1,7 +1,8 @@  - - + + + \ No newline at end of file From 76219f6c5f150f56ed38da85424f00189792d6a6 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 8 Sep 2021 17:25:02 -0500 Subject: [PATCH 033/274] Releasing style manager with window Signed-off-by: Guthrie Adams --- .../Code/Source/Application/AtomToolsApplication.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index bd04ba9395..bad4ad97de 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -87,6 +87,7 @@ namespace AtomToolsFramework AtomToolsApplication ::~AtomToolsApplication() { + m_styleManager.reset(); AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); @@ -206,6 +207,7 @@ namespace AtomToolsFramework { // before modules are unloaded, destroy UI to free up any assets it cached AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); + m_styleManager.reset(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); @@ -461,6 +463,7 @@ namespace AtomToolsFramework void AtomToolsApplication::Stop() { AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); + m_styleManager.reset(); UnloadSettings(); Base::Stop(); From a0ada8fcd388d441f018fc1619845682a09f9c27 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 9 Sep 2021 16:44:35 +0100 Subject: [PATCH 034/274] Reworked net entities instantiation in order to fix entity references e.g. parent-child relationship. Note: Only entities within network spawnable keep the references until the ticket system refactoring is done Signed-off-by: pereslav --- .../Code/Source/MultiplayerGem.cpp | 2 - .../NetworkEntity/NetworkEntityManager.cpp | 68 ++++++++++- .../NetworkEntity/NetworkEntityManager.h | 7 ++ .../NetworkEntity/NetworkEntityTracker.h | 1 + .../Pipeline/NetBindMarkerComponent.cpp | 115 ------------------ .../Source/Pipeline/NetBindMarkerComponent.h | 47 ------- .../Pipeline/NetworkPrefabProcessor.cpp | 24 +--- .../NetworkSpawnableHolderComponent.cpp | 2 +- .../NetworkSpawnableHolderComponent.h | 2 +- Gems/Multiplayer/Code/Tests/MainTools.cpp | 2 - Gems/Multiplayer/Code/multiplayer_files.cmake | 2 - 11 files changed, 78 insertions(+), 194 deletions(-) delete mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp delete mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 1ad7be1a0a..8028e0c5d1 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -23,7 +22,6 @@ namespace Multiplayer AzNetworking::NetworkingSystemComponent::CreateDescriptor(), MultiplayerSystemComponent::CreateDescriptor(), NetBindComponent::CreateDescriptor(), - NetBindMarkerComponent::CreateDescriptor(), NetworkSpawnableHolderComponent::CreateDescriptor(), }); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 69d2726c65..88f0b221ec 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -467,6 +467,54 @@ namespace Multiplayer return netEntityId; } + AzFramework::EntitySpawnTicket NetworkEntityManager::RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable) + { + const AzFramework::Spawnable::EntityList& entityList = rootSpawnable->GetEntities(); + if (entityList.size() == 0) + { + AZ_Assert(false, "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()) + return {}; + } + + // The first entity in every spawnable is the root one + const AZ::Entity* rootEntity = (entityList.begin())->get(); + + const auto* holderComponent = rootEntity->FindComponent(); + if(!holderComponent) + { + // This spawnable doesn't have a corresponding network spawnable. + return {}; + } + + // Retrieve the corresponding network spawnable asset + AZ::Data::Asset netSpawnableAsset = holderComponent->GetNetworkSpawnableAsset(); + + // Prepare the parameters for the spawning process + AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; + optionalArgs.m_priority = AzFramework::SpawnablePriority_High; + + // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene + optionalArgs.m_preInsertionCallback = [spawnableAssetId = netSpawnableAsset.GetId()](AzFramework::EntitySpawnTicket::Id, + AzFramework::SpawnableEntityContainerView entities) + { + for (uint32_t netEntityIndex = 0; netEntityIndex < entities.size(); netEntityIndex++) + { + AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); + AZ::Name spawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(spawnableAssetId); + + PrefabEntityId prefabEntityId; + prefabEntityId.m_prefabName = spawnableName; + prefabEntityId.m_entityOffset = netEntityIndex; + AZ::Interface::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority); + } + }; + + // Spawn with the newly created ticket. This allows the calling code to manage the lifetime of the constructed entities + AzFramework::EntitySpawnTicket ticket(netSpawnableAsset); + AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(ticket, AZStd::move(optionalArgs)); + return ticket; + } + void NetworkEntityManager::OnRootSpawnableAssigned( [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) { @@ -477,11 +525,15 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(true); } + + if(ShouldSpawnNetEntities()) + { + m_rootNetSpawnableTicket = RequestNetSpawnableInstantiation(rootSpawnable); + } } void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) { - // TODO: Do we need to clear all entities here? auto* multiplayer = GetMultiplayer(); const auto agentType = multiplayer->GetAgentType(); @@ -489,6 +541,12 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(false); } + + // Despawn any remaining net entities created locally + if (m_rootNetSpawnableTicket.IsValid()) + { + AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_rootNetSpawnableTicket); + } } void NetworkEntityManager::SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) @@ -506,4 +564,12 @@ namespace Multiplayer netEntity->GetName().c_str()); } } + + bool NetworkEntityManager::ShouldSpawnNetEntities() const + { + const auto agentType = GetMultiplayer()->GetAgentType(); + const bool shouldSpawnNetEntities = + (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); + return shouldSpawnNetEntities; + } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 9ccc576447..a5956b448f 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,11 @@ namespace Multiplayer private: void RemoveEntities(); NetEntityId NextId(); + bool ShouldSpawnNetEntities() const; + + // Note: This is an async function. + // The instantiated entities are not available immediately but will be constructed by the spawnable system + AzFramework::EntitySpawnTicket RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable); NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; @@ -120,5 +126,6 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; + AzFramework::EntitySpawnTicket m_rootNetSpawnableTicket; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h index 09238acaee..0e632dc7b4 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h @@ -37,6 +37,7 @@ namespace Multiplayer NetworkEntityHandle Get(NetEntityId netEntityId); ConstNetworkEntityHandle Get(NetEntityId netEntityId) const; + //! Returns Net Entity ID for a given AZ Entity ID. NetEntityId Get(const AZ::EntityId& entityId) const; //! Returns true if the netEntityId exists. diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp deleted file mode 100644 index c8abac25cb..0000000000 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace Multiplayer -{ - void NetBindMarkerComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("NetEntityIndex", &NetBindMarkerComponent::m_netEntityIndex) - ->Field("NetSpawnableAsset", &NetBindMarkerComponent::m_networkSpawnableAsset); - } - } - - AzFramework::Spawnable* GetSpawnableFromAsset(AZ::Data::Asset& asset) - { - AzFramework::Spawnable* spawnable = asset.GetAs(); - if (!spawnable) - { - asset = - AZ::Data::AssetManager::Instance().GetAsset(asset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad); - AZ::Data::AssetManager::Instance().BlockUntilLoadComplete(asset); - - spawnable = asset.GetAs(); - } - - return spawnable; - } - - - void NetBindMarkerComponent::Activate() - { - const auto agentType = AZ::Interface::Get()->GetAgentType(); - const bool spawnImmediately = - (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); - - if (spawnImmediately && m_networkSpawnableAsset.GetId().IsValid()) - { - AZ::Transform worldTm = GetEntity()->FindComponent()->GetWorldTM(); - auto preInsertionCallback = - [worldTm = AZStd::move(worldTm), netEntityIndex = m_netEntityIndex, spawnableAssetId = m_networkSpawnableAsset.GetId()] - (AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) - { - if (entities.size() == 1) - { - AZ::Entity* netEntity = *entities.begin(); - - auto* transformComponent = netEntity->FindComponent(); - transformComponent->SetWorldTM(worldTm); - - AZ::Name spawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(spawnableAssetId); - PrefabEntityId prefabEntityId; - prefabEntityId.m_prefabName = spawnableName; - prefabEntityId.m_entityOffset = static_cast(netEntityIndex); - AZ::Interface::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority); - } - else - { - AZ_Error("NetBindMarkerComponent", false, "Requested to spawn 1 entity, but received %d", entities.size()); - } - }; - - m_netSpawnTicket = AzFramework::EntitySpawnTicket(m_networkSpawnableAsset); - AzFramework::SpawnEntitiesOptionalArgs optionalArgs; - optionalArgs.m_preInsertionCallback = AZStd::move(preInsertionCallback); - AzFramework::SpawnableEntitiesInterface::Get()->SpawnEntities( - m_netSpawnTicket, { m_netEntityIndex }, AZStd::move(optionalArgs)); - } - } - - void NetBindMarkerComponent::Deactivate() - { - if(m_netSpawnTicket.IsValid()) - { - AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_netSpawnTicket); - } - } - - size_t NetBindMarkerComponent::GetNetEntityIndex() const - { - return m_netEntityIndex; - } - - void NetBindMarkerComponent::SetNetEntityIndex(size_t netEntityIndex) - { - m_netEntityIndex = netEntityIndex; - } - - void NetBindMarkerComponent::SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset) - { - m_networkSpawnableAsset = networkSpawnableAsset; - } - - AZ::Data::Asset NetBindMarkerComponent::GetNetworkSpawnableAsset() const - { - return m_networkSpawnableAsset; - } - -} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h deleted file mode 100644 index dce3252200..0000000000 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include -#include - -namespace Multiplayer -{ - //! @class NetBindMarkerComponent - //! @brief Component for tracking net entities in the original non-networked spawnable. - class NetBindMarkerComponent final : public AZ::Component - { - public: - AZ_COMPONENT(NetBindMarkerComponent, "{40612C1B-427D-45C6-A2F0-04E16DF5B718}"); - - static void Reflect(AZ::ReflectContext* context); - - NetBindMarkerComponent() = default; - ~NetBindMarkerComponent() override = default; - - //! AZ::Component overrides. - //! @{ - void Activate() override; - void Deactivate() override; - //! @} - - size_t GetNetEntityIndex() const; - void SetNetEntityIndex(size_t val); - - void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); - AZ::Data::Asset GetNetworkSpawnableAsset() const; - - private: - AZ::Data::Asset m_networkSpawnableAsset{AZ::Data::AssetLoadBehavior::PreLoad}; - size_t m_netEntityIndex = 0; - AzFramework::EntitySpawnTicket m_netSpawnTicket; - }; -} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index acfec5eb38..e0990aa785 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -46,7 +45,7 @@ namespace Multiplayer { if (auto* serializeContext = azrtti_cast(context); serializeContext != nullptr) { - serializeContext->Class()->Version(1); + serializeContext->Class()->Version(2); } } @@ -137,8 +136,6 @@ namespace Multiplayer networkSpawnableAsset.Create(networkSpawnable->GetId()); networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad); - size_t netEntitiesIndexCounter = 0; - for (auto* prefabEntity : prefabNetEntities) { Instance* instance = netEntityToInstanceMap[prefabEntity]; @@ -148,30 +145,11 @@ namespace Multiplayer AZ_Assert(netEntity, "Unable to detach entity %s [%s] from the source prefab instance", prefabEntity->GetName().c_str(), entityId.ToString().c_str()); - // Net entity will need a new ID to avoid IDs collision - netEntity->SetId(AZ::Entity::MakeId()); netEntity->InvalidateDependencies(); netEntity->EvaluateDependencies(); // Insert the entity into the target net spawnable netSpawnableEntities.emplace_back(netEntity); - - // Use the old ID for the breadcrumb entity to keep parent-child relationship in the original spawnable - AZ::Entity* breadcrumbEntity = aznew AZ::Entity(entityId, netEntity->GetName()); - breadcrumbEntity->SetRuntimeActiveByDefault(netEntity->IsRuntimeActiveByDefault()); - - // Marker component is responsible to spawning entities based on the index. - NetBindMarkerComponent* netBindMarkerComponent = breadcrumbEntity->CreateComponent(); - netBindMarkerComponent->SetNetEntityIndex(netEntitiesIndexCounter); - netBindMarkerComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); - - // Copy the transform component from the original entity to have the correct transform and parent-child relationship - AzFramework::TransformComponent* transformComponent = netEntity->FindComponent(); - breadcrumbEntity->CreateComponent(*transformComponent); - - instance->AddEntity(*breadcrumbEntity); - - netEntitiesIndexCounter++; } // Add net spawnable asset holder to the prefab root diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index c40cb3677b..e83f6fea84 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -39,7 +39,7 @@ namespace Multiplayer m_networkSpawnableAsset = networkSpawnableAsset; } - AZ::Data::Asset NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset() + AZ::Data::Asset NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset() const { return m_networkSpawnableAsset; } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h index d369bbefd3..f32e8d31ab 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -33,7 +33,7 @@ namespace Multiplayer //! @} void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); - AZ::Data::Asset GetNetworkSpawnableAsset(); + AZ::Data::Asset GetNetworkSpawnableAsset() const; private: AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; diff --git a/Gems/Multiplayer/Code/Tests/MainTools.cpp b/Gems/Multiplayer/Code/Tests/MainTools.cpp index 89b2492bc6..53dfad62d1 100644 --- a/Gems/Multiplayer/Code/Tests/MainTools.cpp +++ b/Gems/Multiplayer/Code/Tests/MainTools.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -30,7 +29,6 @@ namespace Multiplayer { AZStd::vector descriptors({ NetBindComponent::CreateDescriptor(), - NetBindMarkerComponent::CreateDescriptor(), NetworkSpawnableHolderComponent::CreateDescriptor() }); diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 0b2adb1530..bdc0129137 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -101,8 +101,6 @@ set(FILES Source/NetworkInput/NetworkInputMigrationVector.h Source/NetworkTime/NetworkTime.cpp Source/NetworkTime/NetworkTime.h - Source/Pipeline/NetBindMarkerComponent.cpp - Source/Pipeline/NetBindMarkerComponent.h Source/Pipeline/NetworkSpawnableHolderComponent.cpp Source/Pipeline/NetworkSpawnableHolderComponent.h Source/Physics/PhysicsUtils.cpp From c2b2cc060a788edb0d398578384de5939eb6c4f8 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 9 Sep 2021 10:52:12 -0500 Subject: [PATCH 035/274] WIP Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.h | 7 +++++ .../Application/AtomToolsApplication.cpp | 26 ++++++++++++------- .../Viewport/MaterialViewportRenderer.cpp | 7 ----- .../Viewport/MaterialViewportRenderer.h | 5 ---- .../Viewport/MaterialViewportWidget.cpp | 12 ++++++--- .../Code/Source/HttpRequestManager.cpp | 2 +- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index d55755a242..f87aca641d 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -35,6 +36,7 @@ namespace AtomToolsFramework , public AzQtComponents::AzQtApplication , protected AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler , protected AzFramework::AssetSystemStatusBus::Handler + , protected AzFramework::AssetCatalogEventBus::Handler , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler , protected AZ::UserSettingsOwnerRequestBus::Handler , protected AtomToolsMainWindowNotificationBus::Handler @@ -67,6 +69,11 @@ namespace AtomToolsFramework void OnMainWindowClosing() override; ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // AzFramework::AssetCatalogEventBus::Handler overrides ... + void OnCatalogLoaded(const char* catalogFile) override; + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// // AssetDatabaseRequestsBus::Handler overrides... bool GetAssetDatabaseLocation(AZStd::string& result) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index bad4ad97de..5751271312 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -91,6 +92,7 @@ namespace AtomToolsFramework AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } void AtomToolsApplication::CreateReflectionManager() @@ -173,16 +175,11 @@ namespace AtomToolsFramework AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast( &AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); + AzFramework::AssetCatalogEventBus::Handler::BusConnect(); AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); - AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); - LoadSettings(); - AtomToolsMainWindowNotificationBus::Handler::BusConnect(); - - AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); - auto editorPythonEventsInterface = AZ::Interface::Get(); if (editorPythonEventsInterface) { @@ -192,9 +189,6 @@ namespace AtomToolsFramework editorPythonEventsInterface->StartPython(); } - // Delay execution of commands and scripts post initialization - QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); - m_timer.start(); } @@ -203,12 +197,26 @@ namespace AtomToolsFramework ExitMainLoop(); } + void AtomToolsApplication::OnCatalogLoaded(const char* catalogFile) + { + AZ_UNUSED(catalogFile); + + // Delay execution of commands and scripts post initialization + AZ::TickBus::QueueFunction([this]() { + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); + AtomToolsMainWindowNotificationBus::Handler::BusConnect(); + ProcessCommandLine(m_commandLine); + }); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + } + void AtomToolsApplication::Destroy() { // before modules are unloaded, destroy UI to free up any assets it cached AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); m_styleManager.reset(); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index f98cdce91b..ceaed0e498 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -247,12 +247,10 @@ namespace MaterialEditor MaterialViewportNotificationBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect(); AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId()); - AzFramework::WindowSystemRequestBus::Handler::BusConnect(); } MaterialViewportRenderer::~MaterialViewportRenderer() { - AzFramework::WindowSystemRequestBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); @@ -303,11 +301,6 @@ namespace MaterialEditor return m_viewportController; } - AzFramework::NativeWindowHandle MaterialViewportRenderer::GetDefaultWindowHandle() - { - return (m_windowContext) ? m_windowContext->GetWindowHandle() : nullptr; - } - void MaterialViewportRenderer::OnDocumentOpened(const AZ::Uuid& documentId) { AZ::Data::Instance materialInstance; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h index 240d66fd43..df77b91356 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h @@ -16,7 +16,6 @@ #include #include #include -#include #include namespace AZ @@ -46,7 +45,6 @@ namespace MaterialEditor , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler , public MaterialViewportNotificationBus::Handler , public AZ::TransformNotificationBus::MultiHandler - , public AzFramework::WindowSystemRequestBus::Handler { public: AZ_CLASS_ALLOCATOR(MaterialViewportRenderer, AZ::SystemAllocator, 0); @@ -81,9 +79,6 @@ namespace MaterialEditor // AZ::TransformNotificationBus::MultiHandler overrides... void OnTransformChanged(const AZ::Transform&, const AZ::Transform&) override; - // AzFramework::WindowSystemRequestBus::Handler overrides ... - AzFramework::NativeWindowHandle GetDefaultWindowHandle() override; - using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle; AZ::Data::Instance m_swapChainPass; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp index c78951ed45..d2fe78cb89 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp @@ -13,17 +13,18 @@ #include #include -#include -#include +#include +#include -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknow n-warning-option") // disable warnings spawned by QT #include #include -#include "Source/Viewport/ui_MaterialViewportWidget.h" +#include "Viewport/ui_MaterialViewportWidget.h" AZ_POP_DISABLE_WARNING #include #include +#include namespace Platform { @@ -45,6 +46,9 @@ namespace MaterialEditor dispatcher->installNativeEventFilter(this); } + AzFramework::WindowSystemNotificationBus::Broadcast( + &AzFramework::WindowSystemNotificationBus::Events::OnWindowCreated, GetViewportContext()->GetWindowHandle()); + // The viewport context created by AtomToolsFramework::RenderViewportWidget has no name. // Systems like frame capturing and post FX expect there to be a context with DefaultViewportContextName auto viewportContextManager = AZ::Interface::Get(); diff --git a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp index 8ed40c1599..c4753d2e94 100644 --- a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp +++ b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp @@ -50,7 +50,7 @@ namespace HttpRequestor { m_thread.join(); } - + AWSNativeSDKInit::InitializationManager::Shutdown(); } void Manager::AddRequest(Parameters && httpRequestParameters) From d8365038147d0205ae64df7c80c605ff042366f4 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 9 Sep 2021 11:50:13 -0700 Subject: [PATCH 036/274] some more fixes Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Application/ToolsApplication.h | 2 +- .../Entity/EditorEntitySortComponent.h | 2 +- .../Instance/InstanceToTemplatePropagator.h | 2 +- .../SliceMetadataEntityContextComponent.h | 4 +-- .../EditorInspectorComponent.h | 2 +- .../EditorNonUniformScaleComponent.h | 2 +- .../UI/Logging/TracePrintFLogPanel.h | 10 +++---- .../UI/PropertyEditor/PropertyEditorAPI.h | 26 +++++++++---------- .../PropertyEditor/PropertyManagerComponent.h | 12 ++++----- .../UI/Slice/SlicePushWidget.hxx | 2 +- .../AtomLyIntegration/AtomFont/AtomFont.h | 2 +- .../Code/Source/AtomFontSystemComponent.h | 2 +- .../Code/Source/BarrierInputKeyboard.h | 6 ++--- .../Code/EMotionFX/Source/AnimGraphHubNode.h | 2 +- .../EMotionFX/Source/AnimGraphReferenceNode.h | 4 +-- .../Integration/System/SystemComponent.cpp | 2 +- .../Code/Include/ScriptCanvas/Core/Node.h | 18 ++++++------- .../ScriptCanvas/Debugger/ClientTransceiver.h | 2 +- .../TerrainSurfaceDataSystemComponent.h | 2 +- 19 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h index e7fa543faf..0e70fe0b41 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h @@ -37,7 +37,7 @@ namespace AzToolsFramework ToolsApplication(int* argc = nullptr, char*** argv = nullptr); ~ToolsApplication(); - void Stop(); + void Stop() override; void CreateReflectionManager() override; void Reflect(AZ::ReflectContext* context) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h index b5a771f658..d728191c64 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntitySortComponent.h @@ -65,7 +65,7 @@ namespace AzToolsFramework /** * Called right before we start reading from the instance pointed by classPtr. */ - void OnReadBegin(void* classPtr) + void OnReadBegin(void* classPtr) override { EditorEntitySortComponent* component = reinterpret_cast(classPtr); component->PrepareSave(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.h index 57d92d78f4..75acb410c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/InstanceToTemplatePropagator.h @@ -31,7 +31,7 @@ namespace AzToolsFramework void AppendEntityAliasToPatchPaths(PrefabDom& providedPatch, const AZ::EntityId& entityId) override; - InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId); + InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId) override; bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceMetadataEntityContextComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceMetadataEntityContextComponent.h index 08fa9f03ce..71e4e8d8f3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceMetadataEntityContextComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Slice/SliceMetadataEntityContextComponent.h @@ -76,10 +76,10 @@ namespace AzToolsFramework void ResetContext() override; void GetRequiredComponentTypes(AZ::ComponentTypeList& required) override; bool IsSliceMetadataEntity(const AZ::EntityId entityId) override; - AZ::Entity* GetMetadataEntity(const AZ::EntityId entityId); + AZ::Entity* GetMetadataEntity(const AZ::EntityId entityId) override; AZ::EntityId GetMetadataEntityIdFromEditorEntity(const AZ::EntityId editorEntityId) override; AZ::EntityId GetMetadataEntityIdFromSliceAddress(const AZ::SliceComponent::SliceInstanceAddress& address) override; - void AddMetadataEntityToContext(const AZ::SliceComponent::SliceInstanceAddress& /*sliceAddress*/, AZ::Entity& entity); + void AddMetadataEntityToContext(const AZ::SliceComponent::SliceInstanceAddress& /*sliceAddress*/, AZ::Entity& entity) override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorInspectorComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorInspectorComponent.h index ecc7e34c76..f9170e67b0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorInspectorComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorInspectorComponent.h @@ -61,7 +61,7 @@ namespace AzToolsFramework /** * Called right before we start reading from the instance pointed by classPtr. */ - void OnReadBegin(void* classPtr) + void OnReadBegin(void* classPtr) override { EditorInspectorComponent* component = reinterpret_cast(classPtr); component->PrepareSave(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h index 66d7cd67d7..0c1ec4c153 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h @@ -37,7 +37,7 @@ namespace AzToolsFramework // AZ::NonUniformScaleRequestBus::Handler ... AZ::Vector3 GetScale() const override; void SetScale(const AZ::Vector3& scale) override; - void RegisterScaleChangedEvent(AZ::NonUniformScaleChangedEvent::Handler& handler); + void RegisterScaleChangedEvent(AZ::NonUniformScaleChangedEvent::Handler& handler) override; private: static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/TracePrintFLogPanel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/TracePrintFLogPanel.h index 78462e842f..755e27db67 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/TracePrintFLogPanel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Logging/TracePrintFLogPanel.h @@ -62,11 +62,11 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // TraceMessagesBus - virtual bool OnAssert(const char* message); - virtual bool OnException(const char* message); - virtual bool OnError(const char* window, const char* message); - virtual bool OnWarning(const char* window, const char* message); - virtual bool OnPrintf(const char* window, const char* message); + bool OnAssert(const char* message) override; + bool OnException(const char* message) override; + bool OnError(const char* window, const char* message) override; + bool OnWarning(const char* window, const char* message) override; + bool OnPrintf(const char* window, const char* message) override; ////////////////////////////////////////////////////////////////////////// /// Log a message received from the TraceMessageBus diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h index 9ab896ab9d..6d3ccd45bd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h @@ -55,12 +55,12 @@ namespace AzToolsFramework // GUI is a pointer to the GUI used to editor your property (the one you created in CreateGUI) // and instance is a the actual value (PropertyType). // you may not cache the pointer to anything. - virtual void WriteGUIValuesIntoProperty(size_t index, WidgetType* GUI, PropertyType& instance, InstanceDataNode* node) = 0; + void WriteGUIValuesIntoProperty(size_t index, WidgetType* GUI, PropertyType& instance, InstanceDataNode* node) override = 0; // this will get called in order to initialize your gui. It will be called once for each instance. // for example if you have multiple objects selected, index will go from 0 to however many there are. // you may not cache the pointer to anything. - virtual bool ReadValuesIntoGUI(size_t index, WidgetType* GUI, const PropertyType& instance, InstanceDataNode* node) = 0; + bool ReadValuesIntoGUI(size_t index, WidgetType* GUI, const PropertyType& instance, InstanceDataNode* node) override = 0; // this will be called in order to initialize or refresh your gui. Your class will be fed one attribute at a time // you may override this to interpret the attributes as you wish - use attrValue->Read() for example, to interpret it as an int. @@ -87,19 +87,19 @@ namespace AzToolsFramework // and cause the next row to tab to your last button, when the user hits shift+tab on the next row. // if your widget is a single widget or has a single focus proxy there is no need to override. // you may not cache the pointer to anything. - virtual QWidget* GetFirstInTabOrder(WidgetType* widget) { return widget; } - virtual QWidget* GetLastInTabOrder(WidgetType* widget) { return widget; } + QWidget* GetFirstInTabOrder(WidgetType* widget) override { return widget; } + QWidget* GetLastInTabOrder(WidgetType* widget) override { return widget; } // implement this function in order to set your internal tab order between child controls. // just call a series of QWidget::setTabOrder // you may not cache the pointer to anything. - virtual void UpdateWidgetInternalTabbing(WidgetType* /*widget*/) { } + void UpdateWidgetInternalTabbing(WidgetType* /*widget*/) override {} // you must implement CreateGUI: // create an instance of the GUI that is used to edit this property type. // the QWidget pointer you return also serves as a handle for accessing data. This means that in order to trigger // a write, you need to call RequestWrite(...) on that same widget handle you return. - virtual QWidget* CreateGUI(QWidget *pParent) override = 0; + QWidget* CreateGUI(QWidget *pParent) override = 0; // you MAY override this if you wish to pool your widgets or reuse them. The default implementation simply calls delete. //virtual QWidget* DestroyGUI(QWidget* object) override; @@ -129,24 +129,24 @@ namespace AzToolsFramework return false; } - virtual QWidget* GetFirstInTabOrder(WidgetType* widget) { return widget; } + QWidget* GetFirstInTabOrder(WidgetType* widget) override { return widget; } virtual QWidget* GetLastInTabOrder(WidgetType* widget) { return widget; } virtual void UpdateWidgetInternalTabbing(WidgetType* /*widget*/) { } - virtual QWidget* CreateGUI(QWidget *pParent) override = 0; + QWidget* CreateGUI(QWidget *pParent) override = 0; protected: - virtual bool HandlesType(const AZ::Uuid& id) const override + bool HandlesType(const AZ::Uuid& id) const override { (void)id; return true; } - virtual const AZ::Uuid& GetHandledType() const override + const AZ::Uuid& GetHandledType() const override { return nullUuid; } - virtual void WriteGUIValuesIntoProperty_Internal(QWidget* widget, InstanceDataNode* node) override + void WriteGUIValuesIntoProperty_Internal(QWidget* widget, InstanceDataNode* node) override { for (size_t i = 0; i < node->GetNumInstances(); ++i) { @@ -154,13 +154,13 @@ namespace AzToolsFramework } } - virtual void WriteGUIValuesIntoTempProperty_Internal(QWidget* widget, void* tempValue, const AZ::Uuid& propertyType, AZ::SerializeContext* serializeContext) override + void WriteGUIValuesIntoTempProperty_Internal(QWidget* widget, void* tempValue, const AZ::Uuid& propertyType, AZ::SerializeContext* serializeContext) override { (void)serializeContext; WriteGUIValuesIntoProperty(0, reinterpret_cast(widget), tempValue, propertyType); } - virtual void ReadValuesIntoGUI_Internal(QWidget* widget, InstanceDataNode* node) override + void ReadValuesIntoGUI_Internal(QWidget* widget, InstanceDataNode* node) override { AZ_PROFILE_FUNCTION(AzToolsFramework); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h index 4be288f52b..423bf401af 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h @@ -34,11 +34,11 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // AZ::Component - virtual void Init(); - virtual void Activate(); - virtual void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; - virtual PropertyHandlerBase* ResolvePropertyHandler(AZ::u32 handlerName, const AZ::Uuid& handlerType) override; + PropertyHandlerBase* ResolvePropertyHandler(AZ::u32 handlerName, const AZ::Uuid& handlerType) override; ////////////////////////////////////////////////////////////////////////// private: @@ -57,8 +57,8 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // PropertyTypeRegistrationMessages::Bus::Handler - virtual void RegisterPropertyType(PropertyHandlerBase* pHandler) override; - virtual void UnregisterPropertyType(PropertyHandlerBase* pHandler) override; + void RegisterPropertyType(PropertyHandlerBase* pHandler) override; + void UnregisterPropertyType(PropertyHandlerBase* pHandler) override; ////////////////////////////////////////////////////////////////////////// typedef AZStd::unordered_multimap HandlerMap; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.hxx index 61cbf4a541..879d0d4abc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Slice/SlicePushWidget.hxx @@ -235,7 +235,7 @@ namespace AzToolsFramework void PopulateFieldTreeRemovedEntities(); /// Event filter for key presses. - bool eventFilter(QObject* target, QEvent *event); + bool eventFilter(QObject* target, QEvent *event) override; /// Conduct the push operation for all selected fields. bool PushSelectedFields(); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h index 8862462093..b1a91b5aa5 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont.h @@ -82,7 +82,7 @@ namespace AZ FontFamilyPtr LoadFontFamily(const char* fontFamilyName) override; FontFamilyPtr GetFontFamily(const char* fontFamilyName) override; void AddCharsToFontTextures(FontFamilyPtr fontFamily, const char* chars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override; - AZStd::string GetLoadedFontNames() const; + AZStd::string GetLoadedFontNames() const override; void OnLanguageChanged() override; void ReloadAllFonts() override; ////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h index 02290e0fed..59f057ddaf 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h @@ -38,7 +38,7 @@ namespace AZ //////////////////////////////////////////////////////////////////////// // CrySystemEventBus - void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& initParams); + void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& initParams) override; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// diff --git a/Gems/BarrierInput/Code/Source/BarrierInputKeyboard.h b/Gems/BarrierInput/Code/Source/BarrierInputKeyboard.h index d7321faaec..946d0df11a 100644 --- a/Gems/BarrierInput/Code/Source/BarrierInputKeyboard.h +++ b/Gems/BarrierInput/Code/Source/BarrierInputKeyboard.h @@ -64,15 +64,15 @@ namespace BarrierInput //////////////////////////////////////////////////////////////////////////////////////////// //! \ref RawInputNotificationsBarrier::OnRawKeyboardKeyDownEvent - virtual void OnRawKeyboardKeyDownEvent(uint32_t scanCode, ModifierMask activeModifiers); + void OnRawKeyboardKeyDownEvent(uint32_t scanCode, ModifierMask activeModifiers) override; //////////////////////////////////////////////////////////////////////////////////////////// //! \ref RawInputNotificationsBarrier::OnRawKeyboardKeyUpEvent - virtual void OnRawKeyboardKeyUpEvent(uint32_t scanCode, ModifierMask activeModifiers); + void OnRawKeyboardKeyUpEvent(uint32_t scanCode, ModifierMask activeModifiers) override; //////////////////////////////////////////////////////////////////////////////////////////// //! \ref RawInputNotificationsBarrier::OnRawKeyboardKeyRepeatEvent - virtual void OnRawKeyboardKeyRepeatEvent(uint32_t scanCode, ModifierMask activeModifiers); + void OnRawKeyboardKeyRepeatEvent(uint32_t scanCode, ModifierMask activeModifiers) override; //////////////////////////////////////////////////////////////////////////////////////////// //! Thread safe method to queue raw key events to be processed in the main thread update diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.h index 6db908cf33..99ad6ced7d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphHubNode.h @@ -61,7 +61,7 @@ namespace EMotionFX bool GetSupportsVisualization() const override { return true; } AnimGraphPose* GetMainOutputPose(AnimGraphInstance* animGraphInstance) const override { return GetOutputPose(animGraphInstance, OUTPUTPORT_RESULT)->GetValue(); } bool GetHasOutputPose() const override { return true; } - bool GetCanBeEntryNode() const { return true; } + bool GetCanBeEntryNode() const override { return true; } bool GetCanBeInsideStateMachineOnly() const override { return true; } bool GetHasVisualOutputPorts() const override { return false; } bool GetCanHaveOnlyOneInsideParent() const override { return false; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h index db4dc0ea3e..db1d6e1279 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphReferenceNode.h @@ -82,8 +82,8 @@ namespace EMotionFX AnimGraphReferenceNode(); ~AnimGraphReferenceNode(); - void Reinit(); - void RecursiveReinit(); + void Reinit() override; + void RecursiveReinit() override; bool InitAfterLoading(AnimGraph* animGraph) override; AnimGraphObjectData* CreateUniqueData(AnimGraphInstance* animGraphInstance) override { return aznew UniqueData(this, animGraphInstance); } diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index b5a252e293..56c22bb1ff 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -115,7 +115,7 @@ namespace EMotionFX public: AZ_CLASS_ALLOCATOR(EMotionFXEventHandler, EMotionFXAllocator, 0); - const AZStd::vector GetHandledEventTypes() const + const AZStd::vector GetHandledEventTypes() const override { return { EVENT_TYPE_ON_EVENT, diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h index 0ef109d383..a54f330e18 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h @@ -69,14 +69,14 @@ namespace ScriptCanvas { public: /// Called right before we start reading from the instance pointed by classPtr. - void OnReadBegin(void* objectPtr) + void OnReadBegin(void* objectPtr) override { t_Class* deserializedObject = reinterpret_cast(objectPtr); deserializedObject->OnReadBegin(); } /// Called after we are done reading from the instance pointed by classPtr. - void OnReadEnd(void* objectPtr) + void OnReadEnd(void* objectPtr) override { t_Class* deserializedObject = reinterpret_cast(objectPtr); deserializedObject->OnReadEnd(); @@ -224,7 +224,7 @@ namespace ScriptCanvas m_dataType = dataReference; } - virtual Data::Type GetDataType() override + Data::Type GetDataType() override { return Data::FromAZType(azrtti_typeid()); } @@ -310,7 +310,7 @@ namespace ScriptCanvas } // ComboBoxPropertyInterface - int GetSelectedIndex() const + int GetSelectedIndex() const override { int counter = -1; @@ -328,7 +328,7 @@ namespace ScriptCanvas return counter; } - void SetSelectedIndex(int index) + void SetSelectedIndex(int index) override { if (index >= 0 || index < m_displaySet.size()) { @@ -513,13 +513,13 @@ namespace ScriptCanvas //! Node internal initialization, for custom init, use OnInit - void Init() override final; + void Init() final; //! Node internal activation and housekeeping, for custom activation configuration use OnActivate - void Activate() override final; + void Activate() final; //! Node internal deactivation and housekeeping, for custom deactivation configuration use OnDeactivate - void Deactivate() override final; + void Deactivate() final; void PostActivate(); @@ -591,7 +591,7 @@ namespace ScriptCanvas NodeDisabledFlag GetNodeDisabledFlag() const; void SetNodeDisabledFlag(NodeDisabledFlag disabledFlag); - bool RemoveVariableReferences(const AZStd::unordered_set< ScriptCanvas::VariableId >& variableIds); + bool RemoveVariableReferences(const AZStd::unordered_set< ScriptCanvas::VariableId >& variableIds) override; //// Slot* GetSlotByName(AZStd::string_view slotName) const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.h index 23406fbf56..78e293c4b0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ClientTransceiver.h @@ -78,7 +78,7 @@ namespace ScriptCanvas ////////////////////////////////////////////////////////////////////////// // TargetManagerClient void DesiredTargetConnected(bool connected) override; - void DesiredTargetChanged(AZ::u32 newId, AZ::u32 oldId); + void DesiredTargetChanged(AZ::u32 newId, AZ::u32 oldId) override; void TargetJoinedNetwork(AzFramework::TargetInfo info) override; void TargetLeftNetwork(AzFramework::TargetInfo info) override; ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.h b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.h index a742eab78c..d9c7893c77 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceDataSystemComponent.h @@ -56,7 +56,7 @@ namespace Terrain ////////////////////////////////////////////////////////////////////////// // SurfaceDataProviderRequestBus - void GetSurfacePoints(const AZ::Vector3& inPosition, SurfaceData::SurfacePointList& surfacePointList) const; + void GetSurfacePoints(const AZ::Vector3& inPosition, SurfaceData::SurfacePointList& surfacePointList) const override; ////////////////////////////////////////////////////////////////////////// // AzFramework::Terrain::TerrainDataNotificationBus From e1829ac05238797da5245a3b9392003e5812ea62 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza Date: Fri, 10 Sep 2021 11:19:58 +0200 Subject: [PATCH 037/274] Added EntityExists for automation Signed-off-by: AMZN-AlexOteiza --- .../AzToolsFramework/API/ToolsApplicationAPI.h | 3 +++ .../Application/ToolsApplication.cpp | 14 ++++++++++---- .../Application/ToolsApplication.h | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index d4707a3e8c..c037747a08 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -414,6 +414,9 @@ namespace AzToolsFramework //! Gets an existing entity id from a known id. virtual AZ::EntityId GetExistingEntity(AZ::u64 id) = 0; + //! Returns if an entity with the given id exists + virtual bool EntityExists(AZ::EntityId id) = 0; + /*! * Delete all currently-selected entities. */ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 6de529e456..0a6022eeba 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -378,6 +378,7 @@ namespace AzToolsFramework ->Event("CreateNewEntityAtPosition", &ToolsApplicationRequests::CreateNewEntityAtPosition) ->Event("GetCurrentLevelEntityId", &ToolsApplicationRequests::GetCurrentLevelEntityId) ->Event("GetExistingEntity", &ToolsApplicationRequests::GetExistingEntity) + ->Event("EntityExists", &ToolsApplicationRequests::EntityExists) ->Event("DeleteEntityById", &ToolsApplicationRequests::DeleteEntityById) ->Event("DeleteEntities", &ToolsApplicationRequests::DeleteEntities) ->Event("DeleteEntityAndAllDescendants", &ToolsApplicationRequests::DeleteEntityAndAllDescendants) @@ -483,7 +484,7 @@ namespace AzToolsFramework EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext); AZ_Assert(serializeContext, "No serialization context found"); - const AZ::Entity::ComponentArrayType& editorComponents = source.GetComponents(); + const AZ::Entity::ComponentArrayType& editorComponents = source.GetUserComponents(); // Propagate components from source entity to target, in preparation for exporting target. for (AZ::Component* component : editorComponents) @@ -493,15 +494,15 @@ namespace AzToolsFramework if (asEditorComponent) { - const size_t oldComponentCount = target.GetComponents().size(); + const size_t oldComponentCount = target.GetUserComponents().size(); asEditorComponent->BuildGameEntity(&target); // Applying same Id persistence trick as we do in the slice compiler. Once we're off levels, // this code all goes away and everything runs through the slice compiler. - if (target.GetComponents().size() > oldComponentCount) + if (target.GetUserComponents().size() > oldComponentCount) { - AZ::Component* newComponent = target.GetComponents().back(); + AZ::Component* newComponent = target.GetUserComponents().back(); AZ_Error("Export", asEditorComponent->GetId() != AZ::InvalidComponentId, "For entity \"%s\", component \"%s\" doesn't have a valid component id", source.GetName().c_str(), asEditorComponent->RTTI_GetType().ToString().c_str()); newComponent->SetId(asEditorComponent->GetId()); @@ -783,6 +784,11 @@ namespace AzToolsFramework return AZ::EntityId{id}; } + bool ToolsApplication::EntityExists(AZ::EntityId id) + { + return FindEntity(id) != nullptr; + } + void ToolsApplication::DeleteSelected() { if (IsPrefabSystemEnabled()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h index e7fa543faf..d05ec5728d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.h @@ -115,6 +115,7 @@ namespace AzToolsFramework AZ::EntityId CreateNewEntity(AZ::EntityId parentId = AZ::EntityId()) override; AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& pos, AZ::EntityId parentId = AZ::EntityId()) override; AZ::EntityId GetExistingEntity(AZ::u64 id) override; + bool EntityExists(AZ::EntityId id) override; void DeleteSelected() override; void DeleteEntityById(AZ::EntityId entityId) override; void DeleteEntities(const EntityIdList& entities) override; From 0f0812c198b3e337d8976610281f6205cf00c65c Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza Date: Fri, 10 Sep 2021 11:25:51 +0200 Subject: [PATCH 038/274] Reverted unintended change Signed-off-by: AMZN-AlexOteiza --- .../AzToolsFramework/Application/ToolsApplication.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 0a6022eeba..75d31321c2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -484,7 +484,7 @@ namespace AzToolsFramework EBUS_EVENT_RESULT(serializeContext, AZ::ComponentApplicationBus, GetSerializeContext); AZ_Assert(serializeContext, "No serialization context found"); - const AZ::Entity::ComponentArrayType& editorComponents = source.GetUserComponents(); + const AZ::Entity::ComponentArrayType& editorComponents = source.GetComponents(); // Propagate components from source entity to target, in preparation for exporting target. for (AZ::Component* component : editorComponents) @@ -494,15 +494,15 @@ namespace AzToolsFramework if (asEditorComponent) { - const size_t oldComponentCount = target.GetUserComponents().size(); + const size_t oldComponentCount = target.GetComponents().size(); asEditorComponent->BuildGameEntity(&target); // Applying same Id persistence trick as we do in the slice compiler. Once we're off levels, // this code all goes away and everything runs through the slice compiler. - if (target.GetUserComponents().size() > oldComponentCount) + if (target.GetComponents().size() > oldComponentCount) { - AZ::Component* newComponent = target.GetUserComponents().back(); + AZ::Component* newComponent = target.GetComponents().back(); AZ_Error("Export", asEditorComponent->GetId() != AZ::InvalidComponentId, "For entity \"%s\", component \"%s\" doesn't have a valid component id", source.GetName().c_str(), asEditorComponent->RTTI_GetType().ToString().c_str()); newComponent->SetId(asEditorComponent->GetId()); From ddd662f6b9bebcb32a88b7d0835bfe5a68492073 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza Date: Fri, 10 Sep 2021 14:28:40 +0200 Subject: [PATCH 039/274] rename to tmp name --- .../Gem/PythonTests/{physics => physics_}/CMakeLists.txt | 0 .../PythonTests/{physics => physics_}/TestSuite_InDevelopment.py | 0 .../Gem/PythonTests/{physics => physics_}/TestSuite_Main.py | 0 .../PythonTests/{physics => physics_}/TestSuite_Main_Optimized.py | 0 .../Gem/PythonTests/{physics => physics_}/TestSuite_Periodic.py | 0 .../Gem/PythonTests/{physics => physics_}/TestSuite_Sandbox.py | 0 .../Gem/PythonTests/{physics => physics_}/TestSuite_Utils.py | 0 .../Gem/PythonTests/{physics => physics_}/__init__.py | 0 .../tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py | 0 .../tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py | 0 .../Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py | 0 .../tests/Physics_WorldBodyBusWorksOnEditorComponents.py | 0 .../character_controller/CharacterController_SwitchLevels.py | 0 .../tests/collider/Collider_AddColliderComponent.py | 0 .../tests/collider/Collider_AddingNewGroupWorks.py | 0 .../tests/collider/Collider_BoxShapeEditting.py | 0 .../tests/collider/Collider_CapsuleShapeEditting.py | 0 .../tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py | 0 .../tests/collider/Collider_ColliderPositionOffset.py | 0 .../tests/collider/Collider_ColliderRotationOffset.py | 0 .../tests/collider/Collider_CollisionGroupsWorkflow.py | 0 .../Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py | 0 .../tests/collider/Collider_MultipleSurfaceSlots.py | 0 .../collider/Collider_NoneCollisionGroupSameLayerNotCollide.py | 0 .../Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py | 0 ...Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py | 0 .../tests/collider/Collider_PxMeshConvexMeshCollides.py | 0 .../tests/collider/Collider_PxMeshErrorIfNoMesh.py | 0 .../collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py | 0 .../collider/Collider_SameCollisionGroupDiffLayersCollide.py | 0 .../collider/Collider_SameCollisionGroupSameCustomLayerCollide.py | 0 .../tests/collider/Collider_SameCollisionGroupSameLayerCollide.py | 0 .../tests/collider/Collider_SphereShapeEditting.py | 0 .../tests/collider/Collider_TriggerPassThrough.py | 0 .../tests/force_region/ForceRegion_CapsuleShapedForce.py | 0 .../force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py | 0 .../ForceRegion_HighValuesDirectionAxesWorkWithNoError.py | 0 .../tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py | 0 .../force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py | 0 .../force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py | 0 .../force_region/ForceRegion_LinearDampingForceOnRigidBodies.py | 0 .../force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py | 0 .../force_region/ForceRegion_MovingForceRegionChangesNetForce.py | 0 .../force_region/ForceRegion_MultipleComponentsCombineForces.py | 0 .../ForceRegion_MultipleForcesInSameComponentCombineForces.py | 0 .../force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py | 0 .../force_region/ForceRegion_ParentChildForcesCombineForces.py | 0 .../tests/force_region/ForceRegion_PointForceOnRigidBodies.py | 0 .../tests/force_region/ForceRegion_PositionOffset.py | 0 .../tests/force_region/ForceRegion_PxMeshShapedForce.py | 0 .../tests/force_region/ForceRegion_RotationalOffset.py | 0 .../force_region/ForceRegion_SimpleDragForceOnRigidBodies.py | 0 .../tests/force_region/ForceRegion_SliceFileInstantiates.py | 0 .../ForceRegion_SmallMagnitudeDeviationOnLargeForces.py | 0 .../tests/force_region/ForceRegion_SphereShapedForce.py | 0 .../tests/force_region/ForceRegion_SplineForceOnRigidBodies.py | 0 .../force_region/ForceRegion_SplineRegionWithModifiedTransform.py | 0 .../force_region/ForceRegion_WithNonTriggerColliderWarning.py | 0 .../force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py | 0 .../force_region/ForceRegion_ZeroLinearDampingDoesNothing.py | 0 .../force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py | 0 .../tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py | 0 .../force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py | 0 .../tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py | 0 .../force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py | 0 .../{physics => physics_}/tests/joints/JointsHelper.py | 0 .../tests/joints/Joints_Ball2BodiesConstrained.py | 0 .../{physics => physics_}/tests/joints/Joints_BallBreakable.py | 0 .../tests/joints/Joints_BallLeadFollowerCollide.py | 0 .../tests/joints/Joints_BallNoLimitsConstrained.py | 0 .../tests/joints/Joints_BallSoftLimitsConstrained.py | 0 .../tests/joints/Joints_Fixed2BodiesConstrained.py | 0 .../{physics => physics_}/tests/joints/Joints_FixedBreakable.py | 0 .../tests/joints/Joints_FixedLeadFollowerCollide.py | 0 .../tests/joints/Joints_GlobalFrameConstrained.py | 0 .../tests/joints/Joints_Hinge2BodiesConstrained.py | 0 .../{physics => physics_}/tests/joints/Joints_HingeBreakable.py | 0 .../tests/joints/Joints_HingeLeadFollowerCollide.py | 0 .../tests/joints/Joints_HingeNoLimitsConstrained.py | 0 .../tests/joints/Joints_HingeSoftLimitsConstrained.py | 0 .../{physics => physics_}/tests/material/AddModifyDelete_Utils.py | 0 .../tests/material/Material_CanBeAssignedToTerrain.py | 0 .../tests/material/Material_CharacterController.py | 0 .../tests/material/Material_ComponentsInSyncWithLibrary.py | 0 .../material/Material_DefaultLibraryConsistentOnAllFeatures.py | 0 .../material/Material_DefaultLibraryUpdatedAcrossLevels_after.py | 0 .../material/Material_DefaultLibraryUpdatedAcrossLevels_before.py | 0 .../tests/material/Material_DefaultMaterialLibraryChangesWork.py | 0 .../tests/material/Material_DynamicFriction.py | 0 .../tests/material/Material_EmptyLibraryUsesDefault.py | 0 .../tests/material/Material_FrictionCombine.py | 0 .../tests/material/Material_FrictionCombinePriorityOrder.py | 0 .../tests/material/Material_LibraryChangesReflectInstantly.py | 0 .../tests/material/Material_LibraryClearingAssignsDefault.py | 0 .../Material_LibraryCrudOperationsReflectOnCharacterController.py | 0 .../material/Material_LibraryCrudOperationsReflectOnCollider.py | 0 .../Material_LibraryCrudOperationsReflectOnRagdollBones.py | 0 .../material/Material_LibraryCrudOperationsReflectOnTerrain.py | 0 .../tests/material/Material_LibraryUpdatedAcrossLevels.py | 0 .../tests/material/Material_NoEffectIfNoColliderShape.py | 0 .../tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py | 0 .../{physics => physics_}/tests/material/Material_RagdollBones.py | 0 .../{physics => physics_}/tests/material/Material_Restitution.py | 0 .../tests/material/Material_RestitutionCombine.py | 0 .../tests/material/Material_RestitutionCombinePriorityOrder.py | 0 .../tests/material/Material_StaticFriction.py | 0 .../{physics => physics_}/tests/material/Physmaterial_Editor.py | 0 .../tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py | 0 .../tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py | 0 .../tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py | 0 .../tests/ragdoll/Ragdoll_WorldBodyBusWorks.py | 0 .../tests/rigid_body/RigidBody_AddRigidBodyComponent.py | 0 .../tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py | 0 .../tests/rigid_body/RigidBody_COM_ComputingWorks.py | 0 .../tests/rigid_body/RigidBody_COM_ManualSettingWorks.py | 0 .../tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py | 0 .../tests/rigid_body/RigidBody_ComputeInertiaWorks.py | 0 .../tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py | 0 .../RigidBody_EnablingGravityWorksUsingNotificationsPoC.py | 0 .../tests/rigid_body/RigidBody_InitialAngularVelocity.py | 0 .../tests/rigid_body/RigidBody_InitialLinearVelocity.py | 0 .../tests/rigid_body/RigidBody_KinematicModeWorks.py | 0 .../tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py | 0 .../tests/rigid_body/RigidBody_MassDifferentValuesWorks.py | 0 .../tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py | 0 .../tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py | 0 .../tests/rigid_body/RigidBody_SetGravityWorks.py | 0 .../tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py | 0 .../tests/rigid_body/RigidBody_StartAsleepWorks.py | 0 .../tests/rigid_body/RigidBody_StartGravityEnabledWorks.py | 0 .../tests/script_canvas/ScriptCanvas_CollisionEvents.py | 0 .../script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py | 0 ...iptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py | 0 .../tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py | 0 .../tests/script_canvas/ScriptCanvas_OverlapNode.py | 0 .../tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py | 0 .../tests/script_canvas/ScriptCanvas_PostUpdateEvent.py | 0 .../tests/script_canvas/ScriptCanvas_PreUpdateEvent.py | 0 .../script_canvas/ScriptCanvas_SetKinematicTargetTransform.py | 0 .../tests/script_canvas/ScriptCanvas_ShapeCast.py | 0 .../script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py | 0 .../tests/script_canvas/ScriptCanvas_TriggerEvents.py | 0 .../tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py | 0 .../tests/shape_collider/ShapeCollider_CylinderShapeCollides.py | 0 .../shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py | 0 .../ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py | 0 .../tests/terrain/Terrain_AddPhysTerrainComponent.py | 0 .../tests/terrain/Terrain_CanAddMultipleTerrainComponents.py | 0 .../tests/terrain/Terrain_CollisionAgainstRigidBody.py | 0 .../tests/terrain/Terrain_MultipleResolutionsValid.py | 0 .../tests/terrain/Terrain_MultipleTerrainComponentsWarning.py | 0 .../tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py | 0 .../tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py | 0 .../tests/terrain/Terrain_TerrainTexturePainterWorks.py | 0 .../Gem/PythonTests/{physics => physics_}/utils/FileManagement.py | 0 .../{physics => physics_}/utils/UtilTest_Managed_Files.py | 0 .../{physics => physics_}/utils/UtilTest_Physmaterial_Editor.py | 0 .../{physics => physics_}/utils/UtilTest_PhysxConfig_Default.py | 0 .../{physics => physics_}/utils/UtilTest_PhysxConfig_Override.py | 0 .../utils/UtilTest_Tracer_PicksErrorsAndWarnings.py | 0 160 files changed, 0 insertions(+), 0 deletions(-) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/CMakeLists.txt (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/TestSuite_InDevelopment.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/TestSuite_Main.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/TestSuite_Main_Optimized.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/TestSuite_Periodic.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/TestSuite_Sandbox.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/TestSuite_Utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/__init__.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/Physics_WorldBodyBusWorksOnEditorComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/character_controller/CharacterController_SwitchLevels.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_AddColliderComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_AddingNewGroupWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_BoxShapeEditting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_CapsuleShapeEditting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_ColliderPositionOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_ColliderRotationOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_CollisionGroupsWorkflow.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_MultipleSurfaceSlots.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_PxMeshConvexMeshCollides.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_PxMeshErrorIfNoMesh.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_SphereShapeEditting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/collider/Collider_TriggerPassThrough.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_CapsuleShapedForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_PointForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_PositionOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_PxMeshShapedForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_RotationalOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_SliceFileInstantiates.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_SphereShapedForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/JointsHelper.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_Ball2BodiesConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_BallBreakable.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_BallLeadFollowerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_BallNoLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_BallSoftLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_Fixed2BodiesConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_FixedBreakable.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_FixedLeadFollowerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_GlobalFrameConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_Hinge2BodiesConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_HingeBreakable.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_HingeLeadFollowerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_HingeNoLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/joints/Joints_HingeSoftLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/AddModifyDelete_Utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_CanBeAssignedToTerrain.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_CharacterController.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_ComponentsInSyncWithLibrary.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_DefaultMaterialLibraryChangesWork.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_DynamicFriction.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_EmptyLibraryUsesDefault.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_FrictionCombine.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_FrictionCombinePriorityOrder.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryChangesReflectInstantly.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryClearingAssignsDefault.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_LibraryUpdatedAcrossLevels.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_NoEffectIfNoColliderShape.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_RagdollBones.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_Restitution.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_RestitutionCombine.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_RestitutionCombinePriorityOrder.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Material_StaticFriction.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/material/Physmaterial_Editor.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_AddRigidBodyComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_COM_ComputingWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_ComputeInertiaWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_InitialAngularVelocity.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_InitialLinearVelocity.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_KinematicModeWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_SetGravityWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_StartAsleepWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_CollisionEvents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_OverlapNode.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_ShapeCast.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/script_canvas/ScriptCanvas_TriggerEvents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_AddPhysTerrainComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_CollisionAgainstRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_MultipleResolutionsValid.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/tests/terrain/Terrain_TerrainTexturePainterWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/utils/FileManagement.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/utils/UtilTest_Managed_Files.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/utils/UtilTest_Physmaterial_Editor.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/utils/UtilTest_PhysxConfig_Default.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/utils/UtilTest_PhysxConfig_Override.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics => physics_}/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py (100%) diff --git a/AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/physics_/CMakeLists.txt similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/CMakeLists.txt rename to AutomatedTesting/Gem/PythonTests/physics_/CMakeLists.txt diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_InDevelopment.py b/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_InDevelopment.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/TestSuite_InDevelopment.py rename to AutomatedTesting/Gem/PythonTests/physics_/TestSuite_InDevelopment.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py rename to AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main_Optimized.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main_Optimized.py rename to AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main_Optimized.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Periodic.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py rename to AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Periodic.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Sandbox.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py rename to AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Sandbox.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Utils.py b/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/TestSuite_Utils.py rename to AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Utils.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/__init__.py b/AutomatedTesting/Gem/PythonTests/physics_/__init__.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/__init__.py rename to AutomatedTesting/Gem/PythonTests/physics_/__init__.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/Physics_WorldBodyBusWorksOnEditorComponents.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_WorldBodyBusWorksOnEditorComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/Physics_WorldBodyBusWorksOnEditorComponents.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_WorldBodyBusWorksOnEditorComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/character_controller/CharacterController_SwitchLevels.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/character_controller/CharacterController_SwitchLevels.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/character_controller/CharacterController_SwitchLevels.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/character_controller/CharacterController_SwitchLevels.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_AddColliderComponent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddColliderComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_AddColliderComponent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddColliderComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_AddingNewGroupWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddingNewGroupWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_AddingNewGroupWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddingNewGroupWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_BoxShapeEditting.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_BoxShapeEditting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_BoxShapeEditting.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_BoxShapeEditting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_CapsuleShapeEditting.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CapsuleShapeEditting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_CapsuleShapeEditting.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CapsuleShapeEditting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_ColliderPositionOffset.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderPositionOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_ColliderPositionOffset.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderPositionOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_ColliderRotationOffset.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderRotationOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_ColliderRotationOffset.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderRotationOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_CollisionGroupsWorkflow.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CollisionGroupsWorkflow.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_CollisionGroupsWorkflow.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CollisionGroupsWorkflow.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_MultipleSurfaceSlots.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_MultipleSurfaceSlots.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_MultipleSurfaceSlots.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_MultipleSurfaceSlots.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshConvexMeshCollides.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshConvexMeshCollides.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshConvexMeshCollides.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshConvexMeshCollides.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshErrorIfNoMesh.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshErrorIfNoMesh.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshErrorIfNoMesh.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshErrorIfNoMesh.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SphereShapeEditting.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SphereShapeEditting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_SphereShapeEditting.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SphereShapeEditting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_TriggerPassThrough.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_TriggerPassThrough.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/collider/Collider_TriggerPassThrough.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_TriggerPassThrough.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_CapsuleShapedForce.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_CapsuleShapedForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_CapsuleShapedForce.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_CapsuleShapedForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_PointForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PointForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_PointForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PointForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_PositionOffset.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PositionOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_PositionOffset.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PositionOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_PxMeshShapedForce.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PxMeshShapedForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_PxMeshShapedForce.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PxMeshShapedForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_RotationalOffset.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_RotationalOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_RotationalOffset.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_RotationalOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SliceFileInstantiates.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SliceFileInstantiates.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SliceFileInstantiates.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SliceFileInstantiates.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SphereShapedForce.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SphereShapedForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SphereShapedForce.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SphereShapedForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/JointsHelper.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/JointsHelper.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/JointsHelper.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/JointsHelper.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_Ball2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Ball2BodiesConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_Ball2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Ball2BodiesConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallBreakable.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallBreakable.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallBreakable.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallBreakable.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallLeadFollowerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallLeadFollowerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallNoLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallNoLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallNoLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallSoftLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_BallSoftLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallSoftLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_Fixed2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Fixed2BodiesConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_Fixed2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Fixed2BodiesConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_FixedBreakable.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedBreakable.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_FixedBreakable.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedBreakable.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedLeadFollowerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_FixedLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedLeadFollowerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_GlobalFrameConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_GlobalFrameConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_GlobalFrameConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_GlobalFrameConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_Hinge2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Hinge2BodiesConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_Hinge2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Hinge2BodiesConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeBreakable.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeBreakable.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeBreakable.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeBreakable.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeLeadFollowerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeLeadFollowerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeNoLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeNoLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeNoLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeSoftLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/joints/Joints_HingeSoftLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeSoftLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/AddModifyDelete_Utils.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/AddModifyDelete_Utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/AddModifyDelete_Utils.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/AddModifyDelete_Utils.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_CanBeAssignedToTerrain.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CanBeAssignedToTerrain.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_CanBeAssignedToTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CanBeAssignedToTerrain.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_CharacterController.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CharacterController.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_CharacterController.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CharacterController.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_ComponentsInSyncWithLibrary.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_ComponentsInSyncWithLibrary.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_ComponentsInSyncWithLibrary.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_ComponentsInSyncWithLibrary.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultMaterialLibraryChangesWork.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultMaterialLibraryChangesWork.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DefaultMaterialLibraryChangesWork.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultMaterialLibraryChangesWork.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DynamicFriction.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DynamicFriction.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_DynamicFriction.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DynamicFriction.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_EmptyLibraryUsesDefault.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_EmptyLibraryUsesDefault.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_EmptyLibraryUsesDefault.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_EmptyLibraryUsesDefault.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_FrictionCombine.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombine.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_FrictionCombine.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombine.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_FrictionCombinePriorityOrder.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombinePriorityOrder.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_FrictionCombinePriorityOrder.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombinePriorityOrder.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryChangesReflectInstantly.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryChangesReflectInstantly.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryChangesReflectInstantly.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryChangesReflectInstantly.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryClearingAssignsDefault.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryClearingAssignsDefault.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryClearingAssignsDefault.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryClearingAssignsDefault.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryUpdatedAcrossLevels.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryUpdatedAcrossLevels.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_LibraryUpdatedAcrossLevels.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryUpdatedAcrossLevels.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_NoEffectIfNoColliderShape.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_NoEffectIfNoColliderShape.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_NoEffectIfNoColliderShape.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_NoEffectIfNoColliderShape.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_RagdollBones.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RagdollBones.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_RagdollBones.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RagdollBones.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_Restitution.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_Restitution.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_Restitution.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_Restitution.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_RestitutionCombine.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombine.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_RestitutionCombine.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombine.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_RestitutionCombinePriorityOrder.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombinePriorityOrder.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_RestitutionCombinePriorityOrder.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombinePriorityOrder.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_StaticFriction.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_StaticFriction.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Material_StaticFriction.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_StaticFriction.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/material/Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Physmaterial_Editor.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/material/Physmaterial_Editor.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/material/Physmaterial_Editor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_AddRigidBodyComponent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AddRigidBodyComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_AddRigidBodyComponent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AddRigidBodyComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_COM_ComputingWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ComputingWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_COM_ComputingWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ComputingWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_ComputeInertiaWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_ComputeInertiaWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_ComputeInertiaWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_ComputeInertiaWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_InitialAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialAngularVelocity.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_InitialAngularVelocity.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialAngularVelocity.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_InitialLinearVelocity.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialLinearVelocity.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_InitialLinearVelocity.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialLinearVelocity.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_KinematicModeWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_KinematicModeWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_KinematicModeWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_KinematicModeWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_SetGravityWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SetGravityWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_SetGravityWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SetGravityWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_StartAsleepWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartAsleepWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_StartAsleepWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartAsleepWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_CollisionEvents.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_CollisionEvents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_CollisionEvents.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_CollisionEvents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_OverlapNode.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_OverlapNode.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_OverlapNode.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_OverlapNode.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_ShapeCast.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_ShapeCast.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_ShapeCast.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_ShapeCast.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_TriggerEvents.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_TriggerEvents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/script_canvas/ScriptCanvas_TriggerEvents.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_TriggerEvents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_AddPhysTerrainComponent.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_AddPhysTerrainComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_AddPhysTerrainComponent.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_AddPhysTerrainComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_CollisionAgainstRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CollisionAgainstRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_CollisionAgainstRigidBody.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CollisionAgainstRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_MultipleResolutionsValid.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleResolutionsValid.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_MultipleResolutionsValid.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleResolutionsValid.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_TerrainTexturePainterWorks.py b/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_TerrainTexturePainterWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/tests/terrain/Terrain_TerrainTexturePainterWorks.py rename to AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_TerrainTexturePainterWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/utils/FileManagement.py b/AutomatedTesting/Gem/PythonTests/physics_/utils/FileManagement.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/utils/FileManagement.py rename to AutomatedTesting/Gem/PythonTests/physics_/utils/FileManagement.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Managed_Files.py b/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Managed_Files.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Managed_Files.py rename to AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Managed_Files.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Physmaterial_Editor.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Physmaterial_Editor.py rename to AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Physmaterial_Editor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Default.py b/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Default.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Default.py rename to AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Default.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Override.py b/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Override.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_PhysxConfig_Override.py rename to AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Override.py diff --git a/AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py b/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py rename to AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py From 5441ab4baca64c5b7dc7695dc0c2950fa71e0dd2 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza Date: Fri, 10 Sep 2021 14:29:17 +0200 Subject: [PATCH 040/274] Rename to final folder name --- .../Gem/PythonTests/{physics_ => Physics}/CMakeLists.txt | 0 .../PythonTests/{physics_ => Physics}/TestSuite_InDevelopment.py | 0 .../Gem/PythonTests/{physics_ => Physics}/TestSuite_Main.py | 0 .../PythonTests/{physics_ => Physics}/TestSuite_Main_Optimized.py | 0 .../Gem/PythonTests/{physics_ => Physics}/TestSuite_Periodic.py | 0 .../Gem/PythonTests/{physics_ => Physics}/TestSuite_Sandbox.py | 0 .../Gem/PythonTests/{physics_ => Physics}/TestSuite_Utils.py | 0 .../Gem/PythonTests/{physics_ => Physics}/__init__.py | 0 .../tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py | 0 .../tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py | 0 .../Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py | 0 .../tests/Physics_WorldBodyBusWorksOnEditorComponents.py | 0 .../character_controller/CharacterController_SwitchLevels.py | 0 .../tests/collider/Collider_AddColliderComponent.py | 0 .../tests/collider/Collider_AddingNewGroupWorks.py | 0 .../tests/collider/Collider_BoxShapeEditting.py | 0 .../tests/collider/Collider_CapsuleShapeEditting.py | 0 .../tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py | 0 .../tests/collider/Collider_ColliderPositionOffset.py | 0 .../tests/collider/Collider_ColliderRotationOffset.py | 0 .../tests/collider/Collider_CollisionGroupsWorkflow.py | 0 .../Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py | 0 .../tests/collider/Collider_MultipleSurfaceSlots.py | 0 .../collider/Collider_NoneCollisionGroupSameLayerNotCollide.py | 0 .../Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py | 0 ...Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py | 0 .../tests/collider/Collider_PxMeshConvexMeshCollides.py | 0 .../tests/collider/Collider_PxMeshErrorIfNoMesh.py | 0 .../collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py | 0 .../collider/Collider_SameCollisionGroupDiffLayersCollide.py | 0 .../collider/Collider_SameCollisionGroupSameCustomLayerCollide.py | 0 .../tests/collider/Collider_SameCollisionGroupSameLayerCollide.py | 0 .../tests/collider/Collider_SphereShapeEditting.py | 0 .../tests/collider/Collider_TriggerPassThrough.py | 0 .../tests/force_region/ForceRegion_CapsuleShapedForce.py | 0 .../force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py | 0 .../ForceRegion_HighValuesDirectionAxesWorkWithNoError.py | 0 .../tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py | 0 .../force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py | 0 .../force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py | 0 .../force_region/ForceRegion_LinearDampingForceOnRigidBodies.py | 0 .../force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py | 0 .../force_region/ForceRegion_MovingForceRegionChangesNetForce.py | 0 .../force_region/ForceRegion_MultipleComponentsCombineForces.py | 0 .../ForceRegion_MultipleForcesInSameComponentCombineForces.py | 0 .../force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py | 0 .../force_region/ForceRegion_ParentChildForcesCombineForces.py | 0 .../tests/force_region/ForceRegion_PointForceOnRigidBodies.py | 0 .../tests/force_region/ForceRegion_PositionOffset.py | 0 .../tests/force_region/ForceRegion_PxMeshShapedForce.py | 0 .../tests/force_region/ForceRegion_RotationalOffset.py | 0 .../force_region/ForceRegion_SimpleDragForceOnRigidBodies.py | 0 .../tests/force_region/ForceRegion_SliceFileInstantiates.py | 0 .../ForceRegion_SmallMagnitudeDeviationOnLargeForces.py | 0 .../tests/force_region/ForceRegion_SphereShapedForce.py | 0 .../tests/force_region/ForceRegion_SplineForceOnRigidBodies.py | 0 .../force_region/ForceRegion_SplineRegionWithModifiedTransform.py | 0 .../force_region/ForceRegion_WithNonTriggerColliderWarning.py | 0 .../force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py | 0 .../force_region/ForceRegion_ZeroLinearDampingDoesNothing.py | 0 .../force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py | 0 .../tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py | 0 .../force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py | 0 .../tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py | 0 .../force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py | 0 .../{physics_ => Physics}/tests/joints/JointsHelper.py | 0 .../tests/joints/Joints_Ball2BodiesConstrained.py | 0 .../{physics_ => Physics}/tests/joints/Joints_BallBreakable.py | 0 .../tests/joints/Joints_BallLeadFollowerCollide.py | 0 .../tests/joints/Joints_BallNoLimitsConstrained.py | 0 .../tests/joints/Joints_BallSoftLimitsConstrained.py | 0 .../tests/joints/Joints_Fixed2BodiesConstrained.py | 0 .../{physics_ => Physics}/tests/joints/Joints_FixedBreakable.py | 0 .../tests/joints/Joints_FixedLeadFollowerCollide.py | 0 .../tests/joints/Joints_GlobalFrameConstrained.py | 0 .../tests/joints/Joints_Hinge2BodiesConstrained.py | 0 .../{physics_ => Physics}/tests/joints/Joints_HingeBreakable.py | 0 .../tests/joints/Joints_HingeLeadFollowerCollide.py | 0 .../tests/joints/Joints_HingeNoLimitsConstrained.py | 0 .../tests/joints/Joints_HingeSoftLimitsConstrained.py | 0 .../{physics_ => Physics}/tests/material/AddModifyDelete_Utils.py | 0 .../tests/material/Material_CanBeAssignedToTerrain.py | 0 .../tests/material/Material_CharacterController.py | 0 .../tests/material/Material_ComponentsInSyncWithLibrary.py | 0 .../material/Material_DefaultLibraryConsistentOnAllFeatures.py | 0 .../material/Material_DefaultLibraryUpdatedAcrossLevels_after.py | 0 .../material/Material_DefaultLibraryUpdatedAcrossLevels_before.py | 0 .../tests/material/Material_DefaultMaterialLibraryChangesWork.py | 0 .../tests/material/Material_DynamicFriction.py | 0 .../tests/material/Material_EmptyLibraryUsesDefault.py | 0 .../tests/material/Material_FrictionCombine.py | 0 .../tests/material/Material_FrictionCombinePriorityOrder.py | 0 .../tests/material/Material_LibraryChangesReflectInstantly.py | 0 .../tests/material/Material_LibraryClearingAssignsDefault.py | 0 .../Material_LibraryCrudOperationsReflectOnCharacterController.py | 0 .../material/Material_LibraryCrudOperationsReflectOnCollider.py | 0 .../Material_LibraryCrudOperationsReflectOnRagdollBones.py | 0 .../material/Material_LibraryCrudOperationsReflectOnTerrain.py | 0 .../tests/material/Material_LibraryUpdatedAcrossLevels.py | 0 .../tests/material/Material_NoEffectIfNoColliderShape.py | 0 .../tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py | 0 .../{physics_ => Physics}/tests/material/Material_RagdollBones.py | 0 .../{physics_ => Physics}/tests/material/Material_Restitution.py | 0 .../tests/material/Material_RestitutionCombine.py | 0 .../tests/material/Material_RestitutionCombinePriorityOrder.py | 0 .../tests/material/Material_StaticFriction.py | 0 .../{physics_ => Physics}/tests/material/Physmaterial_Editor.py | 0 .../tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py | 0 .../tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py | 0 .../tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py | 0 .../tests/ragdoll/Ragdoll_WorldBodyBusWorks.py | 0 .../tests/rigid_body/RigidBody_AddRigidBodyComponent.py | 0 .../tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py | 0 .../tests/rigid_body/RigidBody_COM_ComputingWorks.py | 0 .../tests/rigid_body/RigidBody_COM_ManualSettingWorks.py | 0 .../tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py | 0 .../tests/rigid_body/RigidBody_ComputeInertiaWorks.py | 0 .../tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py | 0 .../RigidBody_EnablingGravityWorksUsingNotificationsPoC.py | 0 .../tests/rigid_body/RigidBody_InitialAngularVelocity.py | 0 .../tests/rigid_body/RigidBody_InitialLinearVelocity.py | 0 .../tests/rigid_body/RigidBody_KinematicModeWorks.py | 0 .../tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py | 0 .../tests/rigid_body/RigidBody_MassDifferentValuesWorks.py | 0 .../tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py | 0 .../tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py | 0 .../tests/rigid_body/RigidBody_SetGravityWorks.py | 0 .../tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py | 0 .../tests/rigid_body/RigidBody_StartAsleepWorks.py | 0 .../tests/rigid_body/RigidBody_StartGravityEnabledWorks.py | 0 .../tests/script_canvas/ScriptCanvas_CollisionEvents.py | 0 .../script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py | 0 ...iptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py | 0 .../tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py | 0 .../tests/script_canvas/ScriptCanvas_OverlapNode.py | 0 .../tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py | 0 .../tests/script_canvas/ScriptCanvas_PostUpdateEvent.py | 0 .../tests/script_canvas/ScriptCanvas_PreUpdateEvent.py | 0 .../script_canvas/ScriptCanvas_SetKinematicTargetTransform.py | 0 .../tests/script_canvas/ScriptCanvas_ShapeCast.py | 0 .../script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py | 0 .../tests/script_canvas/ScriptCanvas_TriggerEvents.py | 0 .../tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py | 0 .../tests/shape_collider/ShapeCollider_CylinderShapeCollides.py | 0 .../shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py | 0 .../ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py | 0 .../tests/terrain/Terrain_AddPhysTerrainComponent.py | 0 .../tests/terrain/Terrain_CanAddMultipleTerrainComponents.py | 0 .../tests/terrain/Terrain_CollisionAgainstRigidBody.py | 0 .../tests/terrain/Terrain_MultipleResolutionsValid.py | 0 .../tests/terrain/Terrain_MultipleTerrainComponentsWarning.py | 0 .../tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py | 0 .../tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py | 0 .../tests/terrain/Terrain_TerrainTexturePainterWorks.py | 0 .../Gem/PythonTests/{physics_ => Physics}/utils/FileManagement.py | 0 .../{physics_ => Physics}/utils/UtilTest_Managed_Files.py | 0 .../{physics_ => Physics}/utils/UtilTest_Physmaterial_Editor.py | 0 .../{physics_ => Physics}/utils/UtilTest_PhysxConfig_Default.py | 0 .../{physics_ => Physics}/utils/UtilTest_PhysxConfig_Override.py | 0 .../utils/UtilTest_Tracer_PicksErrorsAndWarnings.py | 0 160 files changed, 0 insertions(+), 0 deletions(-) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/CMakeLists.txt (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/TestSuite_InDevelopment.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/TestSuite_Main.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/TestSuite_Main_Optimized.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/TestSuite_Periodic.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/TestSuite_Sandbox.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/TestSuite_Utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/__init__.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/Physics_WorldBodyBusWorksOnEditorComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/character_controller/CharacterController_SwitchLevels.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_AddColliderComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_AddingNewGroupWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_BoxShapeEditting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_CapsuleShapeEditting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_ColliderPositionOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_ColliderRotationOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_CollisionGroupsWorkflow.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_MultipleSurfaceSlots.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_PxMeshConvexMeshCollides.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_PxMeshErrorIfNoMesh.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_SphereShapeEditting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/collider/Collider_TriggerPassThrough.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_CapsuleShapedForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_PointForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_PositionOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_PxMeshShapedForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_RotationalOffset.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_SliceFileInstantiates.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_SphereShapedForce.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/JointsHelper.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_Ball2BodiesConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_BallBreakable.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_BallLeadFollowerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_BallNoLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_BallSoftLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_Fixed2BodiesConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_FixedBreakable.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_FixedLeadFollowerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_GlobalFrameConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_Hinge2BodiesConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_HingeBreakable.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_HingeLeadFollowerCollide.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_HingeNoLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/joints/Joints_HingeSoftLimitsConstrained.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/AddModifyDelete_Utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_CanBeAssignedToTerrain.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_CharacterController.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_ComponentsInSyncWithLibrary.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_DefaultMaterialLibraryChangesWork.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_DynamicFriction.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_EmptyLibraryUsesDefault.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_FrictionCombine.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_FrictionCombinePriorityOrder.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryChangesReflectInstantly.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryClearingAssignsDefault.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_LibraryUpdatedAcrossLevels.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_NoEffectIfNoColliderShape.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_RagdollBones.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_Restitution.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_RestitutionCombine.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_RestitutionCombinePriorityOrder.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Material_StaticFriction.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/material/Physmaterial_Editor.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_AddRigidBodyComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_COM_ComputingWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_ComputeInertiaWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_InitialAngularVelocity.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_InitialLinearVelocity.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_KinematicModeWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_SetGravityWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_StartAsleepWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_CollisionEvents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_OverlapNode.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_ShapeCast.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/script_canvas/ScriptCanvas_TriggerEvents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_AddPhysTerrainComponent.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_CollisionAgainstRigidBody.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_MultipleResolutionsValid.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/tests/terrain/Terrain_TerrainTexturePainterWorks.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/utils/FileManagement.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/utils/UtilTest_Managed_Files.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/utils/UtilTest_Physmaterial_Editor.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/utils/UtilTest_PhysxConfig_Default.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/utils/UtilTest_PhysxConfig_Override.py (100%) rename AutomatedTesting/Gem/PythonTests/{physics_ => Physics}/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py (100%) diff --git a/AutomatedTesting/Gem/PythonTests/physics_/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Physics/CMakeLists.txt similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/CMakeLists.txt rename to AutomatedTesting/Gem/PythonTests/Physics/CMakeLists.txt diff --git a/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_InDevelopment.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_InDevelopment.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/TestSuite_InDevelopment.py rename to AutomatedTesting/Gem/PythonTests/Physics/TestSuite_InDevelopment.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main.py rename to AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main_Optimized.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Main_Optimized.py rename to AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Main_Optimized.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Periodic.py rename to AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Sandbox.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Sandbox.py rename to AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Sandbox.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Utils.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/TestSuite_Utils.py rename to AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Utils.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/__init__.py b/AutomatedTesting/Gem/PythonTests/Physics/__init__.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/__init__.py rename to AutomatedTesting/Gem/PythonTests/Physics/__init__.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_DynamicSliceWithPhysNotSpawnsStaticSlice.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_UndoRedoWorksOnEntityWithPhysComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_VerifyColliderRigidBodyMeshAndTerrainWorkTogether.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_WorldBodyBusWorksOnEditorComponents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_WorldBodyBusWorksOnEditorComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/Physics_WorldBodyBusWorksOnEditorComponents.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/Physics_WorldBodyBusWorksOnEditorComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/character_controller/CharacterController_SwitchLevels.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/character_controller/CharacterController_SwitchLevels.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/character_controller/CharacterController_SwitchLevels.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/character_controller/CharacterController_SwitchLevels.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddColliderComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddColliderComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddColliderComponent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddColliderComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddingNewGroupWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddingNewGroupWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_AddingNewGroupWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_AddingNewGroupWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_BoxShapeEditting.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_BoxShapeEditting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_BoxShapeEditting.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_BoxShapeEditting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CapsuleShapeEditting.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_CapsuleShapeEditting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CapsuleShapeEditting.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_CapsuleShapeEditting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_CheckDefaultShapeSettingIsPxMesh.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderPositionOffset.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_ColliderPositionOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderPositionOffset.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_ColliderPositionOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderRotationOffset.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_ColliderRotationOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_ColliderRotationOffset.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_ColliderRotationOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CollisionGroupsWorkflow.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_CollisionGroupsWorkflow.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_CollisionGroupsWorkflow.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_CollisionGroupsWorkflow.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_DiffCollisionGroupDiffCollidingLayersNotCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_MultipleSurfaceSlots.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_MultipleSurfaceSlots.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_MultipleSurfaceSlots.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_MultipleSurfaceSlots.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_NoneCollisionGroupSameLayerNotCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshAutoAssignedWhenAddingRenderMeshComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshAutoAssignedWhenModifyingRenderMeshComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshConvexMeshCollides.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshConvexMeshCollides.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshConvexMeshCollides.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshConvexMeshCollides.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshErrorIfNoMesh.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshErrorIfNoMesh.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshErrorIfNoMesh.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshErrorIfNoMesh.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_PxMeshNotAutoAssignedWhenNoPhysicsFbx.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupDiffLayersCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameLayerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SphereShapeEditting.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SphereShapeEditting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_SphereShapeEditting.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SphereShapeEditting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_TriggerPassThrough.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_TriggerPassThrough.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/collider/Collider_TriggerPassThrough.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_TriggerPassThrough.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_CapsuleShapedForce.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_CapsuleShapedForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_CapsuleShapedForce.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_CapsuleShapedForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_DirectionHasNoAffectOnTotalForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_HighValuesDirectionAxesWorkWithNoError.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ImpulsesBoxShapedRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ImpulsesCapsuleShapedRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ImpulsesPxMeshShapedRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_LinearDampingForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_LocalSpaceForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MovingForceRegionChangesNetForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleComponentsCombineForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_NoQuiverOnHighLinearDampingForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ParentChildForcesCombineForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PointForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_PointForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PointForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_PointForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PositionOffset.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_PositionOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PositionOffset.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_PositionOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PxMeshShapedForce.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_PxMeshShapedForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_PxMeshShapedForce.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_PxMeshShapedForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_RotationalOffset.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_RotationalOffset.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_RotationalOffset.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_RotationalOffset.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SimpleDragForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SliceFileInstantiates.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SliceFileInstantiates.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SliceFileInstantiates.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SliceFileInstantiates.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SmallMagnitudeDeviationOnLargeForces.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SphereShapedForce.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SphereShapedForce.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SphereShapedForce.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SphereShapedForce.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_WithNonTriggerColliderWarning.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_WorldSpaceForceOnRigidBodies.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroLinearDampingDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroLocalSpaceForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroSimpleDragForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroSplineForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroWorldSpaceForceDoesNothing.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/JointsHelper.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/JointsHelper.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Ball2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_Ball2BodiesConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Ball2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_Ball2BodiesConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallBreakable.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallBreakable.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallBreakable.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallBreakable.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallNoLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallNoLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallNoLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallSoftLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_BallSoftLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallSoftLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Fixed2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_Fixed2BodiesConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Fixed2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_Fixed2BodiesConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedBreakable.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedBreakable.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedBreakable.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedBreakable.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_FixedLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_GlobalFrameConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_GlobalFrameConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_GlobalFrameConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_GlobalFrameConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Hinge2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_Hinge2BodiesConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_Hinge2BodiesConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_Hinge2BodiesConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeBreakable.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeBreakable.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeBreakable.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeBreakable.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeLeadFollowerCollide.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeLeadFollowerCollide.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeLeadFollowerCollide.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeNoLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeSoftLimitsConstrained.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/joints/Joints_HingeSoftLimitsConstrained.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeSoftLimitsConstrained.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/AddModifyDelete_Utils.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/AddModifyDelete_Utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/AddModifyDelete_Utils.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/AddModifyDelete_Utils.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CanBeAssignedToTerrain.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_CanBeAssignedToTerrain.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CanBeAssignedToTerrain.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_CanBeAssignedToTerrain.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CharacterController.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_CharacterController.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_CharacterController.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_CharacterController.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_ComponentsInSyncWithLibrary.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_ComponentsInSyncWithLibrary.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_ComponentsInSyncWithLibrary.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_ComponentsInSyncWithLibrary.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryConsistentOnAllFeatures.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultMaterialLibraryChangesWork.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultMaterialLibraryChangesWork.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DefaultMaterialLibraryChangesWork.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultMaterialLibraryChangesWork.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DynamicFriction.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DynamicFriction.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_DynamicFriction.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DynamicFriction.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_EmptyLibraryUsesDefault.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_EmptyLibraryUsesDefault.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_EmptyLibraryUsesDefault.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_EmptyLibraryUsesDefault.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombine.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_FrictionCombine.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombine.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_FrictionCombine.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombinePriorityOrder.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_FrictionCombinePriorityOrder.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_FrictionCombinePriorityOrder.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_FrictionCombinePriorityOrder.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryChangesReflectInstantly.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryChangesReflectInstantly.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryChangesReflectInstantly.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryChangesReflectInstantly.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryClearingAssignsDefault.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryClearingAssignsDefault.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryClearingAssignsDefault.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryClearingAssignsDefault.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnCharacterController.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnCollider.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnRagdollBones.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryCrudOperationsReflectOnTerrain.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryUpdatedAcrossLevels.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryUpdatedAcrossLevels.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_LibraryUpdatedAcrossLevels.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryUpdatedAcrossLevels.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_NoEffectIfNoColliderShape.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_NoEffectIfNoColliderShape.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_NoEffectIfNoColliderShape.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_NoEffectIfNoColliderShape.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_PerFaceMaterialGetsCorrectMaterial.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RagdollBones.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_RagdollBones.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RagdollBones.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_RagdollBones.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_Restitution.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_Restitution.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_Restitution.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_Restitution.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombine.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_RestitutionCombine.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombine.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_RestitutionCombine.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombinePriorityOrder.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_RestitutionCombinePriorityOrder.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_RestitutionCombinePriorityOrder.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_RestitutionCombinePriorityOrder.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_StaticFriction.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_StaticFriction.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Material_StaticFriction.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_StaticFriction.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/material/Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Physmaterial_Editor.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/material/Physmaterial_Editor.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/material/Physmaterial_Editor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_AddPhysxRagdollComponentWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_LevelSwitchDoesNotCrash.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_OldRagdollSerializationNoErrors.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/ragdoll/Ragdoll_WorldBodyBusWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AddRigidBodyComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_AddRigidBodyComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AddRigidBodyComponent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_AddRigidBodyComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_AngularDampingAffectsRotation.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ComputingWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_COM_ComputingWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ComputingWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_COM_ComputingWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_COM_ManualSettingWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_COM_NotIncludesTriggerShapes.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_ComputeInertiaWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_ComputeInertiaWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_ComputeInertiaWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_ComputeInertiaWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_EnablingGravityWorksPoC.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_EnablingGravityWorksUsingNotificationsPoC.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_InitialAngularVelocity.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialAngularVelocity.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_InitialAngularVelocity.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialLinearVelocity.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_InitialLinearVelocity.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_InitialLinearVelocity.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_InitialLinearVelocity.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_KinematicModeWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_KinematicModeWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_LinearDampingAffectsMotion.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_MassDifferentValuesWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_MaxAngularVelocityWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_MomentOfInertiaManualSetting.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SetGravityWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_SetGravityWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SetGravityWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_SetGravityWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_SleepWhenBelowKineticThreshold.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartAsleepWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_StartAsleepWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartAsleepWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_StartAsleepWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_StartGravityEnabledWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_CollisionEvents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_CollisionEvents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_CollisionEvents.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_CollisionEvents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsName.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_GetCollisionNameReturnsNothingWhenHasToggledLayer.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_MultipleRaycastNode.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_OverlapNode.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_OverlapNode.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_OverlapNode.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_OverlapNode.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_PostPhysicsUpdate.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_PostUpdateEvent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_PreUpdateEvent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SetKinematicTargetTransform.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_ShapeCast.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_ShapeCast.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_ShapeCast.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_ShapeCast.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_TriggerEvents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_TriggerEvents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/script_canvas/ScriptCanvas_TriggerEvents.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_TriggerEvents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_CanBeAddedWitNoWarnings.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_CylinderShapeCollides.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_InactiveWhenNoShapeComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/shape_collider/ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_AddPhysTerrainComponent.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_AddPhysTerrainComponent.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_AddPhysTerrainComponent.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_AddPhysTerrainComponent.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_CanAddMultipleTerrainComponents.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CollisionAgainstRigidBody.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_CollisionAgainstRigidBody.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_CollisionAgainstRigidBody.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_CollisionAgainstRigidBody.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleResolutionsValid.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_MultipleResolutionsValid.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleResolutionsValid.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_MultipleResolutionsValid.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_MultipleTerrainComponentsWarning.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_NoPhysTerrainComponentNoCollision.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_SpawnSecondTerrainComponentWarning.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_TerrainTexturePainterWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_TerrainTexturePainterWorks.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/tests/terrain/Terrain_TerrainTexturePainterWorks.py rename to AutomatedTesting/Gem/PythonTests/Physics/tests/terrain/Terrain_TerrainTexturePainterWorks.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/utils/FileManagement.py b/AutomatedTesting/Gem/PythonTests/Physics/utils/FileManagement.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/utils/FileManagement.py rename to AutomatedTesting/Gem/PythonTests/Physics/utils/FileManagement.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Managed_Files.py b/AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_Managed_Files.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Managed_Files.py rename to AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_Managed_Files.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_Physmaterial_Editor.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Physmaterial_Editor.py rename to AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_Physmaterial_Editor.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Default.py b/AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_PhysxConfig_Default.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Default.py rename to AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_PhysxConfig_Default.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Override.py b/AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_PhysxConfig_Override.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_PhysxConfig_Override.py rename to AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_PhysxConfig_Override.py diff --git a/AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py b/AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/physics_/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py rename to AutomatedTesting/Gem/PythonTests/Physics/utils/UtilTest_Tracer_PicksErrorsAndWarnings.py From 78d0b46f08645c10b8aa92d347e4881bf298dd22 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza Date: Fri, 10 Sep 2021 14:37:45 +0200 Subject: [PATCH 041/274] Updated path in CMakeLists.txt Signed-off-by: AMZN-AlexOteiza --- AutomatedTesting/Gem/PythonTests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index a54229f6ba..7fd3b3a241 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -21,7 +21,7 @@ add_subdirectory(assetpipeline) add_subdirectory(atom_renderer) ## Physics ## -add_subdirectory(physics) +add_subdirectory(Physics) ## ScriptCanvas ## add_subdirectory(scripting) From 43355e47cacd3218b76be66236a4ba6f67e56572 Mon Sep 17 00:00:00 2001 From: Jonny Galloway Date: Fri, 10 Sep 2021 14:00:36 -0500 Subject: [PATCH 042/274] minor bug fixes based on finding defects while using (#4035) Signed-off-by: Jonny Gallowy --- .../ColorGrading/exr_to_3dl_azasset.py | 4 +- .../ColorGrading/from_3dl_to_azasset.py | 3 - .../test-grade_inv-Log2-48nits_32_LUT.azasset | 65543 ++++++++-------- .../cmdline/CMD_ColorGradingTools.bat | 22 +- .../Tools/ColorGrading/cmdline/Env_Core.bat | 3 - .../cmdline/User_Env.bat.template | 2 +- 6 files changed, 32789 insertions(+), 32788 deletions(-) diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py index 6c2aa1d5bb..a3aae9cb94 100644 --- a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/exr_to_3dl_azasset.py @@ -113,7 +113,9 @@ if __name__ == '__main__': lut_intervals, lut_values = generate_lut_values(image_spec, image_buffer) write_3DL(args.o, image_spec.height, lut_intervals, lut_values) - write_azasset(args.o, image_spec.height, lut_intervals, lut_values) + + # write_azasset(file_path, lut_intervals, lut_values, azasset_json=AZASSET_LUT) + write_azasset(args.o, lut_intervals, lut_values) # example from command line # python % DCCSI_COLORGRADING_SCRIPTS %\lut_helper.py - -i C: \Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\linear_32_LUT.exr - -op pre - grading - -shaper Log2 - 48nits - -o C: \Depot\o3de\Gems\Atom\Feature\Common\Tools\ColorGrading\Resources\LUTs\base_Log2-48nits_32_LUT.exr diff --git a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py index ba37994e63..da9e5f9d34 100644 --- a/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py +++ b/Gems/Atom/Feature/Common/Editor/Scripts/ColorGrading/from_3dl_to_azasset.py @@ -31,11 +31,8 @@ if ColorGrading.initialize.start(): sys.exit(1) # ------------------------------------------------------------------------ - -# ------------------------------------------------------------------------ from ColorGrading import AZASSET_LUT - # ------------------------------------------------------------------------ def find_first_line(alist): for lno, line in enumerate(alist): diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset index a91e9d0c1a..bd1ccbf572 100644 --- a/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/Resources/TestData/Nuke/HDR/Test_Grade/test-grade_inv-Log2-48nits_32_LUT.azasset @@ -4,32777 +4,32774 @@ "ClassName": "LookupTableAsset", "ClassData": { "Name": "LookupTable", - "Intervals": [ - 0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], - "Values": [ - 0, 0, 0, - 0, 0, 0, - 0, 15, 0, - 0, 104, 0, - 0, 201, 0, - 0, 305, 0, - 0, 415, 0, - 0, 530, 0, - 0, 649, 0, - 0, 771, 0, - 0, 895, 0, - 0, 1022, 0, - 0, 1149, 0, - 0, 1278, 0, - 0, 1408, 0, - 0, 1538, 0, - 0, 1668, 0, - 0, 1799, 0, - 0, 1931, 0, - 0, 2062, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2457, 0, - 0, 2589, 0, - 0, 2721, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3381, 0, - 0, 3514, 0, - 0, 3646, 0, - 130, 0, 20, - 28, 0, 0, - 0, 33, 0, - 0, 119, 0, - 0, 213, 0, - 0, 315, 0, - 0, 423, 0, - 0, 536, 0, - 0, 654, 0, - 0, 775, 0, - 0, 898, 0, - 0, 1024, 0, - 0, 1151, 0, - 0, 1279, 0, - 0, 1408, 0, - 0, 1538, 0, - 0, 1669, 0, - 0, 1800, 0, - 0, 1931, 0, - 0, 2062, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2589, 0, - 0, 2721, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3381, 0, - 0, 3514, 0, - 0, 3646, 0, - 342, 0, 170, - 280, 0, 102, - 183, 56, 0, - 7, 139, 0, - 0, 229, 0, - 0, 328, 0, - 0, 433, 0, - 0, 544, 0, - 0, 660, 0, - 0, 779, 0, - 0, 902, 0, - 0, 1026, 0, - 0, 1153, 0, - 0, 1281, 0, - 0, 1410, 0, - 0, 1539, 0, - 0, 1670, 0, - 0, 1800, 0, - 0, 1931, 0, - 0, 2063, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2589, 0, - 0, 2721, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3381, 0, - 0, 3514, 0, - 0, 3646, 0, - 526, 0, 315, - 486, 18, 266, - 426, 86, 192, - 331, 163, 68, - 163, 250, 0, - 0, 344, 0, - 0, 446, 0, - 0, 555, 0, - 0, 668, 0, - 0, 785, 0, - 0, 906, 0, - 0, 1030, 0, - 0, 1156, 0, - 0, 1283, 0, - 0, 1411, 0, - 0, 1540, 0, - 0, 1670, 0, - 0, 1801, 0, - 0, 1932, 0, - 0, 2063, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 693, 8, 457, - 666, 60, 422, - 626, 123, 370, - 568, 195, 290, - 475, 276, 155, - 312, 366, 0, - 0, 463, 0, - 0, 568, 0, - 0, 678, 0, - 0, 794, 0, - 0, 913, 0, - 0, 1035, 0, - 0, 1159, 0, - 0, 1285, 0, - 0, 1413, 0, - 0, 1542, 0, - 0, 1672, 0, - 0, 1802, 0, - 0, 1932, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 850, 65, 596, - 831, 112, 570, - 804, 168, 534, - 765, 233, 479, - 707, 308, 395, - 616, 393, 250, - 457, 485, 0, - 82, 585, 0, - 0, 692, 0, - 0, 804, 0, - 0, 921, 0, - 0, 1041, 0, - 0, 1164, 0, - 0, 1289, 0, - 0, 1416, 0, - 0, 1544, 0, - 0, 1673, 0, - 0, 1803, 0, - 0, 1933, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 999, 131, 733, - 986, 172, 714, - 967, 222, 688, - 940, 280, 650, - 901, 348, 594, - 844, 426, 505, - 755, 513, 352, - 598, 608, 3, - 235, 710, 0, - 0, 818, 0, - 0, 932, 0, - 0, 1049, 0, - 0, 1170, 0, - 0, 1294, 0, - 0, 1420, 0, - 0, 1547, 0, - 0, 1675, 0, - 0, 1805, 0, - 0, 1935, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1144, 207, 869, - 1134, 242, 855, - 1121, 285, 836, - 1102, 336, 809, - 1075, 397, 770, - 1037, 468, 712, - 980, 547, 621, - 892, 636, 461, - 737, 732, 82, - 382, 836, 0, - 0, 946, 0, - 0, 1060, 0, - 0, 1179, 0, - 0, 1300, 0, - 0, 1424, 0, - 0, 1550, 0, - 0, 1678, 0, - 0, 1807, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1286, 293, 1004, - 1278, 322, 994, - 1268, 358, 980, - 1255, 402, 960, - 1236, 455, 932, - 1210, 518, 893, - 1172, 590, 833, - 1115, 671, 740, - 1027, 761, 574, - 874, 859, 170, - 525, 964, 0, - 0, 1074, 0, - 0, 1190, 0, - 0, 1309, 0, - 0, 1431, 0, - 0, 1555, 0, - 0, 1682, 0, - 0, 1809, 0, - 0, 1938, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1424, 386, 1138, - 1419, 410, 1131, - 1412, 440, 1120, - 1402, 477, 1106, - 1389, 523, 1086, - 1370, 577, 1058, - 1343, 641, 1018, - 1306, 714, 958, - 1250, 797, 862, - 1162, 888, 692, - 1010, 987, 267, - 665, 1093, 0, - 0, 1204, 0, - 0, 1320, 0, - 0, 1439, 0, - 0, 1562, 0, - 0, 1687, 0, - 0, 1813, 0, - 0, 1941, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1562, 487, 1272, - 1558, 506, 1266, - 1552, 531, 1258, - 1545, 561, 1248, - 1535, 599, 1234, - 1522, 646, 1213, - 1503, 701, 1185, - 1477, 766, 1144, - 1439, 840, 1084, - 1383, 924, 987, - 1296, 1016, 813, - 1145, 1116, 370, - 802, 1222, 0, - 0, 1334, 0, - 0, 1450, 0, - 0, 1570, 0, - 0, 1693, 0, - 0, 1818, 0, - 0, 1945, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2331, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1697, 595, 1405, - 1695, 610, 1401, - 1691, 629, 1395, - 1685, 654, 1387, - 1678, 685, 1377, - 1668, 724, 1362, - 1655, 771, 1342, - 1636, 827, 1314, - 1610, 893, 1273, - 1572, 968, 1211, - 1517, 1053, 1113, - 1430, 1145, 937, - 1279, 1246, 479, - 939, 1352, 0, - 0, 1465, 0, - 0, 1581, 0, - 0, 1701, 0, - 0, 1824, 0, - 0, 1950, 0, - 0, 2076, 0, - 0, 2204, 0, - 0, 2334, 0, - 0, 2463, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1832, 707, 1538, - 1830, 719, 1535, - 1827, 735, 1531, - 1823, 755, 1525, - 1818, 780, 1517, - 1811, 811, 1507, - 1801, 851, 1492, - 1788, 898, 1472, - 1769, 955, 1443, - 1743, 1021, 1402, - 1705, 1097, 1340, - 1650, 1182, 1241, - 1563, 1275, 1062, - 1412, 1376, 594, - 1074, 1483, 0, - 0, 1596, 0, - 0, 1712, 0, - 0, 1833, 0, - 0, 1956, 0, - 0, 2081, 0, - 0, 2208, 0, - 0, 2336, 0, - 0, 2466, 0, - 0, 2595, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1966, 824, 1671, - 1965, 834, 1668, - 1963, 846, 1665, - 1960, 861, 1661, - 1956, 881, 1655, - 1951, 907, 1647, - 1943, 939, 1637, - 1934, 978, 1622, - 1920, 1026, 1602, - 1902, 1084, 1573, - 1875, 1150, 1531, - 1838, 1227, 1469, - 1782, 1312, 1370, - 1696, 1406, 1190, - 1545, 1507, 712, - 1209, 1614, 0, - 0, 1727, 0, - 0, 1844, 0, - 0, 1964, 0, - 0, 2088, 0, - 0, 2213, 0, - 0, 2340, 0, - 0, 2468, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 2100, 945, 1803, - 2099, 952, 1802, - 2097, 961, 1799, - 2095, 973, 1796, - 2092, 989, 1792, - 2088, 1009, 1786, - 2083, 1035, 1778, - 2076, 1067, 1768, - 2066, 1107, 1753, - 2053, 1156, 1732, - 2034, 1213, 1703, - 2008, 1280, 1662, - 1970, 1357, 1599, - 1915, 1442, 1499, - 1828, 1536, 1318, - 1678, 1638, 834, - 1342, 1745, 0, - 0, 1858, 0, - 0, 1976, 0, - 0, 2096, 0, - 0, 2220, 0, - 0, 2345, 0, - 0, 2472, 0, - 0, 2600, 0, - 0, 2730, 0, - 0, 2859, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2233, 1068, 1936, - 2232, 1074, 1935, - 2231, 1081, 1933, - 2230, 1090, 1930, - 2227, 1102, 1927, - 2225, 1118, 1923, - 2221, 1139, 1917, - 2215, 1164, 1909, - 2208, 1197, 1899, - 2198, 1237, 1884, - 2185, 1286, 1863, - 2166, 1343, 1834, - 2140, 1411, 1793, - 2103, 1488, 1730, - 2047, 1573, 1629, - 1961, 1668, 1447, - 1811, 1769, 958, - 1476, 1877, 0, - 0, 1990, 0, - 0, 2107, 0, - 0, 2228, 0, - 0, 2351, 0, - 0, 2477, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2862, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2366, 1194, 2068, - 2366, 1198, 2067, - 2365, 1203, 2066, - 2364, 1210, 2064, - 2362, 1220, 2062, - 2360, 1232, 2059, - 2357, 1248, 2054, - 2353, 1268, 2049, - 2348, 1294, 2041, - 2340, 1327, 2030, - 2331, 1367, 2015, - 2317, 1416, 1995, - 2299, 1474, 1966, - 2273, 1542, 1924, - 2235, 1619, 1861, - 2180, 1705, 1760, - 2093, 1799, 1577, - 1944, 1901, 1084, - 1609, 2009, 0, - 0, 2122, 0, - 0, 2239, 0, - 0, 2360, 0, - 0, 2483, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2499, 1321, 2200, - 2499, 1324, 2200, - 2498, 1328, 2199, - 2497, 1333, 2197, - 2496, 1340, 2196, - 2494, 1350, 2193, - 2492, 1362, 2190, - 2489, 1378, 2186, - 2485, 1399, 2180, - 2480, 1425, 2172, - 2473, 1458, 2161, - 2463, 1498, 2147, - 2450, 1547, 2126, - 2431, 1605, 2097, - 2405, 1673, 2055, - 2367, 1750, 1992, - 2312, 1836, 1891, - 2226, 1931, 1708, - 2076, 2032, 1211, - 1742, 2140, 0, - 0, 2254, 0, - 0, 2371, 0, - 0, 2492, 0, - 0, 2615, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2996, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2632, 1449, 2333, - 2631, 1451, 2332, - 2631, 1454, 2331, - 2630, 1458, 2330, - 2629, 1464, 2329, - 2628, 1471, 2327, - 2626, 1481, 2325, - 2624, 1493, 2322, - 2621, 1509, 2318, - 2617, 1530, 2312, - 2612, 1556, 2304, - 2605, 1589, 2293, - 2595, 1629, 2278, - 2582, 1678, 2258, - 2563, 1736, 2229, - 2537, 1804, 2187, - 2500, 1881, 2123, - 2444, 1968, 2023, - 2358, 2062, 1839, - 2208, 2164, 1340, - 1874, 2272, 0, - 0, 2385, 0, - 0, 2503, 0, - 0, 2624, 0, - 0, 2747, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3128, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2764, 1578, 2465, - 2764, 1580, 2465, - 2763, 1582, 2464, - 2763, 1585, 2463, - 2762, 1589, 2462, - 2761, 1595, 2461, - 2760, 1602, 2459, - 2759, 1612, 2457, - 2756, 1624, 2454, - 2753, 1640, 2449, - 2750, 1661, 2444, - 2744, 1687, 2436, - 2737, 1720, 2425, - 2727, 1760, 2410, - 2714, 1809, 2389, - 2695, 1868, 2360, - 2669, 1936, 2318, - 2632, 2013, 2255, - 2577, 2099, 2154, - 2490, 2194, 1970, - 2341, 2296, 1469, - 2007, 2404, 0, - 0, 2517, 0, - 0, 2635, 0, - 0, 2756, 0, - 0, 2879, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3260, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1708, 2597, - 2896, 1709, 2597, - 2896, 1711, 2596, - 2896, 1713, 2596, - 2895, 1716, 2595, - 2894, 1721, 2594, - 2893, 1726, 2593, - 2892, 1733, 2591, - 2891, 1743, 2589, - 2889, 1755, 2586, - 2886, 1771, 2581, - 2882, 1792, 2575, - 2876, 1818, 2568, - 2869, 1851, 2557, - 2859, 1892, 2542, - 2846, 1941, 2521, - 2828, 1999, 2492, - 2801, 2067, 2450, - 2764, 2145, 2387, - 2709, 2231, 2286, - 2622, 2326, 2101, - 2473, 2428, 1599, - 2139, 2536, 0, - 0, 2649, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3011, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3029, 1838, 2729, - 3029, 1839, 2729, - 3028, 1841, 2729, - 3028, 1842, 2728, - 3028, 1845, 2728, - 3027, 1848, 2727, - 3027, 1852, 2726, - 3026, 1858, 2725, - 3024, 1865, 2723, - 3023, 1874, 2721, - 3021, 1887, 2717, - 3018, 1903, 2713, - 3014, 1924, 2707, - 3009, 1950, 2699, - 3001, 1983, 2689, - 2992, 2024, 2674, - 2978, 2073, 2653, - 2960, 2131, 2624, - 2934, 2199, 2582, - 2896, 2277, 2519, - 2841, 2363, 2418, - 2755, 2458, 2233, - 2605, 2560, 1730, - 2272, 2668, 0, - 0, 2781, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3143, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3161, 1969, 2861, - 3161, 1970, 2861, - 3161, 1971, 2861, - 3160, 1972, 2861, - 3160, 1974, 2860, - 3160, 1976, 2860, - 3159, 1980, 2859, - 3159, 1984, 2858, - 3158, 1989, 2857, - 3157, 1996, 2855, - 3155, 2006, 2853, - 3153, 2018, 2849, - 3150, 2035, 2845, - 3146, 2055, 2839, - 3141, 2082, 2831, - 3134, 2115, 2821, - 3124, 2155, 2806, - 3110, 2205, 2785, - 3092, 2263, 2756, - 3066, 2331, 2714, - 3028, 2409, 2651, - 2973, 2495, 2549, - 2887, 2590, 2365, - 2737, 2692, 1861, - 2404, 2800, 0, - 0, 2913, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3293, 2100, 2994, - 3293, 2101, 2993, - 3293, 2102, 2993, - 3293, 2103, 2993, - 3293, 2104, 2993, - 3292, 2106, 2992, - 3292, 2108, 2992, - 3291, 2111, 2991, - 3291, 2115, 2990, - 3290, 2121, 2989, - 3289, 2128, 2987, - 3287, 2138, 2985, - 3285, 2150, 2981, - 3282, 2166, 2977, - 3278, 2187, 2971, - 3273, 2213, 2963, - 3266, 2246, 2953, - 3256, 2287, 2938, - 3242, 2336, 2917, - 3224, 2395, 2888, - 3198, 2463, 2846, - 3161, 2541, 2783, - 3105, 2627, 2681, - 3019, 2722, 2497, - 2870, 2824, 1992, - 2536, 2932, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3660, 0, - 3425, 2232, 3126, - 3425, 2232, 3126, - 3425, 2233, 3125, - 3425, 2233, 3125, - 3425, 2234, 3125, - 3425, 2236, 3125, - 3424, 2238, 3124, - 3424, 2240, 3124, - 3424, 2243, 3123, - 3423, 2247, 3122, - 3422, 2253, 3121, - 3421, 2260, 3119, - 3419, 2270, 3117, - 3417, 2282, 3113, - 3414, 2298, 3109, - 3410, 2319, 3103, - 3405, 2345, 3095, - 3398, 2378, 3085, - 3388, 2419, 3070, - 3375, 2468, 3049, - 3356, 2527, 3020, - 3330, 2595, 2978, - 3293, 2673, 2915, - 3237, 2759, 2813, - 3151, 2854, 2629, - 3002, 2956, 2124, - 2668, 3064, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2363, 3258, - 3557, 2364, 3258, - 3557, 2364, 3258, - 3557, 2365, 3258, - 3557, 2365, 3257, - 3557, 2366, 3257, - 3557, 2368, 3257, - 3557, 2370, 3256, - 3556, 2372, 3256, - 3556, 2375, 3255, - 3555, 2379, 3254, - 3554, 2385, 3253, - 3553, 2392, 3251, - 3551, 2402, 3249, - 3549, 2414, 3245, - 3546, 2430, 3241, - 3542, 2451, 3235, - 3537, 2477, 3227, - 3530, 2510, 3217, - 3520, 2551, 3202, - 3507, 2600, 3181, - 3488, 2659, 3152, - 3462, 2727, 3110, - 3425, 2805, 3047, - 3369, 2891, 2945, - 3283, 2986, 2760, - 3134, 3088, 2255, - 2800, 3196, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3690, 2495, 3390, - 3690, 2495, 3390, - 3690, 2496, 3390, - 3689, 2496, 3390, - 3689, 2497, 3390, - 3689, 2497, 3389, - 3689, 2498, 3389, - 3689, 2500, 3389, - 3689, 2501, 3388, - 3688, 2504, 3388, - 3688, 2507, 3387, - 3687, 2511, 3386, - 3686, 2517, 3385, - 3685, 2524, 3383, - 3683, 2534, 3381, - 3681, 2546, 3378, - 3678, 2562, 3373, - 3674, 2583, 3367, - 3669, 2609, 3360, - 3662, 2642, 3349, - 3652, 2683, 3334, - 3639, 2732, 3313, - 3620, 2791, 3284, - 3594, 2859, 3242, - 3557, 2937, 3179, - 3502, 3023, 3077, - 3415, 3118, 2892, - 3266, 3220, 2387, - 2933, 3328, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3822, 2627, 3522, - 3822, 2627, 3522, - 3822, 2627, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2629, 3522, - 3821, 2629, 3521, - 3821, 2630, 3521, - 3821, 2632, 3521, - 3821, 2633, 3521, - 3820, 2636, 3520, - 3820, 2639, 3519, - 3819, 2643, 3518, - 3818, 2649, 3517, - 3817, 2656, 3515, - 3816, 2666, 3513, - 3813, 2678, 3510, - 3810, 2694, 3505, - 3807, 2715, 3499, - 3801, 2741, 3492, - 3794, 2774, 3481, - 3784, 2815, 3466, - 3771, 2864, 3445, - 3752, 2923, 3416, - 3726, 2991, 3374, - 3689, 3069, 3311, - 3634, 3155, 3209, - 3547, 3250, 3024, - 3398, 3352, 2519, - 3065, 3460, 0, - 0, 3574, 0, - 0, 3691, 0, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3953, 2761, 3654, - 3953, 2762, 3653, - 3953, 2764, 3653, - 3953, 2765, 3653, - 3952, 2768, 3652, - 3952, 2771, 3651, - 3951, 2775, 3650, - 3950, 2781, 3649, - 3949, 2788, 3647, - 3948, 2798, 3645, - 3945, 2810, 3642, - 3943, 2826, 3637, - 3939, 2847, 3632, - 3933, 2873, 3624, - 3926, 2906, 3613, - 3916, 2947, 3598, - 3903, 2996, 3577, - 3884, 3055, 3548, - 3858, 3123, 3506, - 3821, 3201, 3443, - 3766, 3287, 3341, - 3679, 3382, 3156, - 3530, 3484, 2651, - 3197, 3592, 0, - 0, 3706, 0, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2893, 3786, - 4085, 2894, 3785, - 4085, 2896, 3785, - 4085, 2897, 3785, - 4085, 2900, 3784, - 4084, 2903, 3783, - 4083, 2907, 3782, - 4083, 2913, 3781, - 4081, 2920, 3779, - 4080, 2930, 3777, - 4078, 2942, 3774, - 4075, 2958, 3769, - 4071, 2979, 3764, - 4065, 3005, 3756, - 4058, 3038, 3745, - 4049, 3079, 3730, - 4035, 3128, 3709, - 4017, 3187, 3680, - 3991, 3255, 3638, - 3953, 3333, 3575, - 3898, 3419, 3473, - 3812, 3514, 3289, - 3662, 3616, 2783, - 3329, 3725, 0, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3025, 3918, - 4095, 3026, 3917, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3032, 3916, - 4095, 3035, 3915, - 4095, 3039, 3915, - 4095, 3045, 3913, - 4095, 3052, 3911, - 4095, 3062, 3909, - 4095, 3074, 3906, - 4095, 3090, 3902, - 4095, 3111, 3896, - 4095, 3137, 3888, - 4095, 3170, 3877, - 4095, 3211, 3862, - 4095, 3261, 3842, - 4095, 3319, 3812, - 4095, 3387, 3770, - 4085, 3465, 3707, - 4030, 3551, 3605, - 3944, 3646, 3421, - 3794, 3748, 2915, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3167, 4048, - 4095, 3171, 4047, - 4095, 3177, 4045, - 4095, 3184, 4044, - 4095, 3194, 4041, - 4095, 3206, 4038, - 4095, 3222, 4034, - 4095, 3243, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3343, 3994, - 4095, 3393, 3974, - 4095, 3451, 3944, - 4095, 3519, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 0, 0, - 0, 0, 0, - 0, 49, 0, - 0, 132, 0, - 0, 224, 0, - 0, 324, 0, - 0, 430, 0, - 0, 542, 0, - 0, 658, 0, - 0, 778, 0, - 0, 901, 0, - 0, 1025, 0, - 0, 1152, 0, - 0, 1280, 0, - 0, 1409, 0, - 0, 1539, 0, - 0, 1669, 0, - 0, 1800, 0, - 0, 1931, 0, - 0, 2063, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2589, 0, - 0, 2721, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3381, 0, - 0, 3514, 0, - 0, 3646, 0, - 104, 0, 80, - 0, 0, 0, - 0, 66, 0, - 0, 147, 0, - 0, 236, 0, - 0, 333, 0, - 0, 438, 0, - 0, 548, 0, - 0, 662, 0, - 0, 781, 0, - 0, 903, 0, - 0, 1028, 0, - 0, 1154, 0, - 0, 1281, 0, - 0, 1410, 0, - 0, 1540, 0, - 0, 1670, 0, - 0, 1800, 0, - 0, 1931, 0, - 0, 2063, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2721, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3381, 0, - 0, 3514, 0, - 0, 3646, 0, - 326, 0, 214, - 262, 20, 152, - 160, 88, 54, - 0, 165, 0, - 0, 251, 0, - 0, 346, 0, - 0, 447, 0, - 0, 555, 0, - 0, 668, 0, - 0, 786, 0, - 0, 907, 0, - 0, 1030, 0, - 0, 1156, 0, - 0, 1283, 0, - 0, 1411, 0, - 0, 1540, 0, - 0, 1670, 0, - 0, 1801, 0, - 0, 1932, 0, - 0, 2063, 0, - 0, 2194, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 515, 0, 347, - 474, 52, 302, - 413, 116, 234, - 315, 188, 122, - 139, 271, 0, - 0, 361, 0, - 0, 460, 0, - 0, 565, 0, - 0, 676, 0, - 0, 792, 0, - 0, 911, 0, - 0, 1034, 0, - 0, 1158, 0, - 0, 1285, 0, - 0, 1413, 0, - 0, 1542, 0, - 0, 1671, 0, - 0, 1802, 0, - 0, 1932, 0, - 0, 2063, 0, - 0, 2195, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 686, 42, 481, - 658, 92, 447, - 618, 150, 399, - 558, 218, 324, - 463, 295, 200, - 295, 382, 0, - 0, 477, 0, - 0, 579, 0, - 0, 687, 0, - 0, 800, 0, - 0, 918, 0, - 0, 1039, 0, - 0, 1162, 0, - 0, 1288, 0, - 0, 1415, 0, - 0, 1543, 0, - 0, 1673, 0, - 0, 1802, 0, - 0, 1933, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 844, 96, 614, - 825, 140, 589, - 798, 192, 554, - 758, 255, 502, - 700, 327, 422, - 607, 408, 287, - 444, 498, 4, - 53, 596, 0, - 0, 700, 0, - 0, 811, 0, - 0, 926, 0, - 0, 1045, 0, - 0, 1167, 0, - 0, 1291, 0, - 0, 1418, 0, - 0, 1545, 0, - 0, 1674, 0, - 0, 1804, 0, - 0, 1934, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 996, 158, 746, - 982, 197, 728, - 963, 244, 702, - 936, 300, 666, - 897, 365, 611, - 839, 440, 527, - 748, 525, 382, - 589, 617, 65, - 214, 718, 0, - 0, 824, 0, - 0, 936, 0, - 0, 1053, 0, - 0, 1173, 0, - 0, 1296, 0, - 0, 1421, 0, - 0, 1548, 0, - 0, 1676, 0, - 0, 1805, 0, - 0, 1935, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1141, 230, 879, - 1131, 263, 865, - 1118, 304, 846, - 1099, 354, 820, - 1072, 412, 782, - 1034, 481, 726, - 976, 558, 638, - 887, 645, 484, - 730, 740, 135, - 367, 842, 0, - 0, 950, 0, - 0, 1064, 0, - 0, 1181, 0, - 0, 1302, 0, - 0, 1426, 0, - 0, 1552, 0, - 0, 1679, 0, - 0, 1807, 0, - 0, 1937, 0, - 0, 2067, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1284, 312, 1011, - 1276, 340, 1001, - 1266, 374, 987, - 1253, 417, 968, - 1234, 468, 941, - 1207, 529, 902, - 1169, 600, 844, - 1112, 679, 753, - 1024, 768, 593, - 869, 865, 214, - 514, 968, 0, - 0, 1078, 0, - 0, 1192, 0, - 0, 1311, 0, - 0, 1432, 0, - 0, 1557, 0, - 0, 1683, 0, - 0, 1810, 0, - 0, 1939, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1423, 402, 1144, - 1418, 425, 1136, - 1410, 454, 1126, - 1401, 490, 1112, - 1387, 534, 1092, - 1368, 587, 1064, - 1342, 650, 1025, - 1304, 722, 966, - 1247, 803, 872, - 1159, 893, 706, - 1006, 991, 302, - 657, 1096, 0, - 0, 1206, 0, - 0, 1322, 0, - 0, 1441, 0, - 0, 1563, 0, - 0, 1687, 0, - 0, 1814, 0, - 0, 1941, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1561, 500, 1276, - 1557, 518, 1270, - 1551, 542, 1263, - 1544, 572, 1252, - 1534, 609, 1238, - 1521, 655, 1218, - 1502, 709, 1190, - 1476, 773, 1150, - 1438, 846, 1090, - 1382, 929, 994, - 1294, 1020, 824, - 1142, 1119, 399, - 797, 1225, 0, - 0, 1336, 0, - 0, 1452, 0, - 0, 1571, 0, - 0, 1694, 0, - 0, 1819, 0, - 0, 1945, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1697, 605, 1408, - 1694, 619, 1404, - 1690, 639, 1398, - 1684, 663, 1391, - 1677, 694, 1380, - 1667, 732, 1366, - 1654, 778, 1346, - 1635, 833, 1317, - 1609, 898, 1277, - 1571, 973, 1216, - 1515, 1056, 1119, - 1428, 1148, 945, - 1277, 1248, 502, - 935, 1354, 0, - 0, 1466, 0, - 0, 1582, 0, - 0, 1702, 0, - 0, 1825, 0, - 0, 1950, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1832, 715, 1540, - 1830, 727, 1537, - 1827, 742, 1533, - 1823, 761, 1527, - 1817, 786, 1519, - 1810, 818, 1509, - 1800, 856, 1494, - 1787, 903, 1474, - 1768, 959, 1446, - 1742, 1025, 1405, - 1704, 1100, 1343, - 1649, 1185, 1245, - 1562, 1277, 1069, - 1411, 1378, 612, - 1071, 1484, 0, - 0, 1597, 0, - 0, 1713, 0, - 0, 1833, 0, - 0, 1956, 0, - 0, 2082, 0, - 0, 2208, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1966, 830, 1672, - 1964, 840, 1670, - 1962, 851, 1667, - 1959, 867, 1663, - 1955, 887, 1657, - 1950, 912, 1649, - 1943, 943, 1639, - 1933, 983, 1624, - 1920, 1030, 1604, - 1901, 1087, 1575, - 1875, 1153, 1534, - 1837, 1229, 1472, - 1782, 1314, 1373, - 1695, 1407, 1194, - 1544, 1508, 726, - 1206, 1615, 0, - 0, 1728, 0, - 0, 1845, 0, - 0, 1965, 0, - 0, 2088, 0, - 0, 2213, 0, - 0, 2340, 0, - 0, 2468, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 2100, 950, 1805, - 2099, 957, 1803, - 2097, 966, 1801, - 2095, 978, 1797, - 2092, 993, 1793, - 2088, 1013, 1787, - 2083, 1039, 1780, - 2075, 1071, 1769, - 2066, 1110, 1754, - 2052, 1159, 1734, - 2034, 1216, 1705, - 2007, 1282, 1663, - 1970, 1359, 1601, - 1914, 1444, 1502, - 1828, 1538, 1322, - 1678, 1639, 844, - 1341, 1746, 0, - 0, 1859, 0, - 0, 1976, 0, - 0, 2097, 0, - 0, 2220, 0, - 0, 2345, 0, - 0, 2472, 0, - 0, 2600, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2233, 1072, 1937, - 2232, 1077, 1935, - 2231, 1084, 1934, - 2229, 1093, 1931, - 2227, 1106, 1928, - 2224, 1121, 1924, - 2220, 1142, 1918, - 2215, 1167, 1910, - 2208, 1200, 1900, - 2198, 1239, 1885, - 2185, 1288, 1864, - 2166, 1345, 1836, - 2140, 1412, 1794, - 2103, 1489, 1731, - 2047, 1575, 1631, - 1960, 1669, 1450, - 1810, 1770, 966, - 1475, 1878, 0, - 0, 1990, 0, - 0, 2108, 0, - 0, 2228, 0, - 0, 2352, 0, - 0, 2477, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2366, 1196, 2069, - 2365, 1200, 2068, - 2365, 1206, 2067, - 2363, 1213, 2065, - 2362, 1222, 2063, - 2360, 1234, 2059, - 2357, 1250, 2055, - 2353, 1271, 2049, - 2347, 1297, 2041, - 2340, 1329, 2031, - 2330, 1369, 2016, - 2317, 1418, 1995, - 2298, 1475, 1966, - 2272, 1543, 1925, - 2235, 1620, 1862, - 2180, 1706, 1762, - 2093, 1800, 1579, - 1943, 1901, 1090, - 1608, 2009, 0, - 0, 2122, 0, - 0, 2239, 0, - 0, 2360, 0, - 0, 2483, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2499, 1323, 2201, - 2498, 1326, 2200, - 2498, 1330, 2199, - 2497, 1335, 2198, - 2496, 1342, 2196, - 2494, 1352, 2194, - 2492, 1364, 2191, - 2489, 1380, 2186, - 2485, 1400, 2181, - 2480, 1426, 2173, - 2473, 1459, 2162, - 2463, 1499, 2147, - 2449, 1548, 2127, - 2431, 1606, 2098, - 2405, 1674, 2056, - 2367, 1751, 1993, - 2312, 1837, 1892, - 2225, 1931, 1709, - 2076, 2033, 1216, - 1741, 2141, 0, - 0, 2254, 0, - 0, 2371, 0, - 0, 2492, 0, - 0, 2615, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2996, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2631, 1450, 2333, - 2631, 1453, 2333, - 2631, 1456, 2332, - 2630, 1460, 2331, - 2629, 1465, 2330, - 2628, 1473, 2328, - 2626, 1482, 2325, - 2624, 1494, 2322, - 2621, 1510, 2318, - 2617, 1531, 2312, - 2612, 1557, 2304, - 2605, 1590, 2294, - 2595, 1630, 2279, - 2582, 1679, 2258, - 2563, 1737, 2229, - 2537, 1805, 2187, - 2500, 1882, 2124, - 2444, 1968, 2023, - 2358, 2063, 1840, - 2208, 2164, 1343, - 1874, 2272, 0, - 0, 2386, 0, - 0, 2503, 0, - 0, 2624, 0, - 0, 2747, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3128, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2764, 1579, 2465, - 2764, 1581, 2465, - 2763, 1583, 2464, - 2763, 1586, 2464, - 2762, 1590, 2463, - 2761, 1596, 2461, - 2760, 1603, 2460, - 2758, 1613, 2457, - 2756, 1625, 2454, - 2753, 1641, 2450, - 2749, 1662, 2444, - 2744, 1688, 2436, - 2737, 1721, 2425, - 2727, 1761, 2410, - 2714, 1810, 2390, - 2695, 1868, 2361, - 2669, 1936, 2319, - 2632, 2013, 2256, - 2576, 2100, 2155, - 2490, 2194, 1971, - 2341, 2296, 1472, - 2006, 2404, 0, - 0, 2518, 0, - 0, 2635, 0, - 0, 2756, 0, - 0, 2879, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1709, 2597, - 2896, 1710, 2597, - 2896, 1712, 2597, - 2895, 1714, 2596, - 2895, 1717, 2595, - 2894, 1721, 2594, - 2893, 1727, 2593, - 2892, 1734, 2591, - 2891, 1744, 2589, - 2888, 1756, 2586, - 2886, 1772, 2581, - 2882, 1793, 2576, - 2876, 1819, 2568, - 2869, 1852, 2557, - 2859, 1892, 2542, - 2846, 1942, 2522, - 2827, 2000, 2492, - 2801, 2068, 2450, - 2764, 2145, 2387, - 2709, 2232, 2286, - 2622, 2326, 2102, - 2473, 2428, 1601, - 2139, 2536, 0, - 0, 2650, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3011, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3029, 1839, 2729, - 3029, 1840, 2729, - 3028, 1841, 2729, - 3028, 1843, 2729, - 3028, 1845, 2728, - 3027, 1849, 2727, - 3026, 1853, 2726, - 3026, 1858, 2725, - 3024, 1865, 2723, - 3023, 1875, 2721, - 3021, 1887, 2718, - 3018, 1904, 2713, - 3014, 1924, 2708, - 3009, 1950, 2700, - 3001, 1983, 2689, - 2992, 2024, 2674, - 2978, 2073, 2653, - 2960, 2132, 2624, - 2934, 2199, 2582, - 2896, 2277, 2519, - 2841, 2363, 2418, - 2754, 2458, 2234, - 2605, 2560, 1732, - 2271, 2668, 0, - 0, 2781, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3161, 1970, 2862, - 3161, 1970, 2861, - 3161, 1971, 2861, - 3160, 1973, 2861, - 3160, 1975, 2860, - 3160, 1977, 2860, - 3159, 1980, 2859, - 3159, 1984, 2858, - 3158, 1990, 2857, - 3157, 1997, 2855, - 3155, 2006, 2853, - 3153, 2019, 2850, - 3150, 2035, 2845, - 3146, 2056, 2839, - 3141, 2082, 2832, - 3133, 2115, 2821, - 3124, 2156, 2806, - 3110, 2205, 2785, - 3092, 2263, 2756, - 3066, 2331, 2714, - 3028, 2409, 2651, - 2973, 2495, 2550, - 2887, 2590, 2365, - 2737, 2692, 1862, - 2404, 2800, 0, - 0, 2914, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3293, 2101, 2994, - 3293, 2101, 2994, - 3293, 2102, 2993, - 3293, 2103, 2993, - 3293, 2104, 2993, - 3292, 2106, 2992, - 3292, 2109, 2992, - 3291, 2112, 2991, - 3291, 2116, 2990, - 3290, 2121, 2989, - 3289, 2129, 2987, - 3287, 2138, 2985, - 3285, 2151, 2982, - 3282, 2167, 2977, - 3278, 2187, 2971, - 3273, 2214, 2963, - 3266, 2247, 2953, - 3256, 2287, 2938, - 3242, 2337, 2917, - 3224, 2395, 2888, - 3198, 2463, 2846, - 3160, 2541, 2783, - 3105, 2627, 2681, - 3019, 2722, 2497, - 2870, 2824, 1993, - 2536, 2932, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3660, 0, - 3425, 2232, 3126, - 3425, 2232, 3126, - 3425, 2233, 3126, - 3425, 2234, 3125, - 3425, 2235, 3125, - 3425, 2236, 3125, - 3424, 2238, 3124, - 3424, 2240, 3124, - 3424, 2243, 3123, - 3423, 2248, 3122, - 3422, 2253, 3121, - 3421, 2260, 3119, - 3419, 2270, 3117, - 3417, 2282, 3114, - 3414, 2299, 3109, - 3410, 2319, 3103, - 3405, 2346, 3095, - 3398, 2379, 3085, - 3388, 2419, 3070, - 3375, 2469, 3049, - 3356, 2527, 3020, - 3330, 2595, 2978, - 3293, 2673, 2915, - 3237, 2759, 2813, - 3151, 2854, 2629, - 3002, 2956, 2124, - 2668, 3064, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2364, 3258, - 3557, 2364, 3258, - 3557, 2364, 3258, - 3557, 2365, 3258, - 3557, 2366, 3257, - 3557, 2367, 3257, - 3557, 2368, 3257, - 3557, 2370, 3256, - 3556, 2372, 3256, - 3556, 2375, 3255, - 3555, 2379, 3254, - 3554, 2385, 3253, - 3553, 2392, 3251, - 3551, 2402, 3249, - 3549, 2414, 3246, - 3546, 2430, 3241, - 3542, 2451, 3235, - 3537, 2477, 3228, - 3530, 2510, 3217, - 3520, 2551, 3202, - 3507, 2600, 3181, - 3488, 2659, 3152, - 3462, 2727, 3110, - 3425, 2805, 3047, - 3369, 2891, 2945, - 3283, 2986, 2761, - 3134, 3088, 2256, - 2800, 3196, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3690, 2495, 3390, - 3690, 2495, 3390, - 3690, 2496, 3390, - 3689, 2496, 3390, - 3689, 2497, 3390, - 3689, 2497, 3389, - 3689, 2498, 3389, - 3689, 2500, 3389, - 3689, 2502, 3389, - 3688, 2504, 3388, - 3688, 2507, 3387, - 3687, 2511, 3386, - 3686, 2517, 3385, - 3685, 2524, 3383, - 3683, 2534, 3381, - 3681, 2546, 3378, - 3678, 2562, 3373, - 3674, 2583, 3367, - 3669, 2609, 3360, - 3662, 2642, 3349, - 3652, 2683, 3334, - 3639, 2732, 3313, - 3620, 2791, 3284, - 3594, 2859, 3242, - 3557, 2937, 3179, - 3502, 3023, 3077, - 3415, 3118, 2893, - 3266, 3220, 2387, - 2933, 3328, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3822, 2627, 3522, - 3822, 2627, 3522, - 3822, 2627, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3821, 2629, 3522, - 3821, 2629, 3522, - 3821, 2630, 3521, - 3821, 2632, 3521, - 3821, 2634, 3521, - 3820, 2636, 3520, - 3820, 2639, 3519, - 3819, 2643, 3518, - 3818, 2649, 3517, - 3817, 2656, 3515, - 3815, 2666, 3513, - 3813, 2678, 3510, - 3810, 2694, 3505, - 3807, 2715, 3500, - 3801, 2741, 3492, - 3794, 2774, 3481, - 3784, 2815, 3466, - 3771, 2864, 3445, - 3752, 2923, 3416, - 3726, 2991, 3374, - 3689, 3069, 3311, - 3634, 3155, 3209, - 3547, 3250, 3025, - 3398, 3352, 2519, - 3065, 3460, 0, - 0, 3574, 0, - 0, 3691, 0, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3953, 2761, 3654, - 3953, 2762, 3653, - 3953, 2764, 3653, - 3953, 2766, 3653, - 3952, 2768, 3652, - 3952, 2771, 3651, - 3951, 2775, 3650, - 3950, 2781, 3649, - 3949, 2788, 3647, - 3948, 2798, 3645, - 3945, 2810, 3642, - 3943, 2826, 3637, - 3939, 2847, 3632, - 3933, 2873, 3624, - 3926, 2906, 3613, - 3916, 2947, 3598, - 3903, 2996, 3577, - 3884, 3055, 3548, - 3858, 3123, 3506, - 3821, 3201, 3443, - 3766, 3287, 3341, - 3679, 3382, 3157, - 3530, 3484, 2651, - 3197, 3592, 0, - 0, 3706, 0, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2893, 3786, - 4085, 2894, 3785, - 4085, 2896, 3785, - 4085, 2898, 3785, - 4085, 2900, 3784, - 4084, 2903, 3783, - 4083, 2907, 3782, - 4083, 2913, 3781, - 4081, 2920, 3779, - 4080, 2930, 3777, - 4078, 2942, 3774, - 4075, 2958, 3769, - 4071, 2979, 3764, - 4065, 3005, 3756, - 4058, 3038, 3745, - 4049, 3079, 3730, - 4035, 3129, 3709, - 4017, 3187, 3680, - 3991, 3255, 3638, - 3953, 3333, 3575, - 3898, 3419, 3473, - 3811, 3514, 3289, - 3662, 3616, 2783, - 3329, 3725, 0, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3032, 3916, - 4095, 3035, 3916, - 4095, 3039, 3915, - 4095, 3045, 3913, - 4095, 3052, 3911, - 4095, 3062, 3909, - 4095, 3074, 3906, - 4095, 3090, 3902, - 4095, 3111, 3896, - 4095, 3137, 3888, - 4095, 3171, 3877, - 4095, 3211, 3862, - 4095, 3261, 3842, - 4095, 3319, 3812, - 4095, 3387, 3770, - 4085, 3465, 3707, - 4030, 3551, 3605, - 3944, 3646, 3421, - 3794, 3748, 2915, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3167, 4048, - 4095, 3171, 4047, - 4095, 3177, 4045, - 4095, 3184, 4044, - 4095, 3194, 4041, - 4095, 3206, 4038, - 4095, 3222, 4034, - 4095, 3243, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3343, 3994, - 4095, 3393, 3974, - 4095, 3451, 3944, - 4095, 3519, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 0, 36, - 0, 24, 0, - 0, 91, 0, - 0, 168, 0, - 0, 254, 0, - 0, 348, 0, - 0, 449, 0, - 0, 557, 0, - 0, 669, 0, - 0, 787, 0, - 0, 907, 0, - 0, 1031, 0, - 0, 1156, 0, - 0, 1283, 0, - 0, 1411, 0, - 0, 1541, 0, - 0, 1671, 0, - 0, 1801, 0, - 0, 1932, 0, - 0, 2063, 0, - 0, 2195, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 67, 0, 149, - 0, 42, 77, - 0, 107, 0, - 0, 181, 0, - 0, 264, 0, - 0, 356, 0, - 0, 456, 0, - 0, 562, 0, - 0, 674, 0, - 0, 790, 0, - 0, 910, 0, - 0, 1033, 0, - 0, 1158, 0, - 0, 1284, 0, - 0, 1412, 0, - 0, 1541, 0, - 0, 1671, 0, - 0, 1801, 0, - 0, 1932, 0, - 0, 2063, 0, - 0, 2195, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2853, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3249, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 303, 13, 267, - 236, 65, 212, - 127, 127, 127, - 0, 198, 0, - 0, 279, 0, - 0, 368, 0, - 0, 465, 0, - 0, 570, 0, - 0, 680, 0, - 0, 795, 0, - 0, 913, 0, - 0, 1035, 0, - 0, 1160, 0, - 0, 1286, 0, - 0, 1413, 0, - 0, 1542, 0, - 0, 1672, 0, - 0, 1802, 0, - 0, 1933, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2326, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2985, 0, - 0, 3117, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 500, 45, 387, - 458, 94, 346, - 394, 152, 284, - 292, 220, 186, - 105, 297, 8, - 0, 383, 0, - 0, 478, 0, - 0, 579, 0, - 0, 687, 0, - 0, 801, 0, - 0, 918, 0, - 0, 1039, 0, - 0, 1162, 0, - 0, 1288, 0, - 0, 1415, 0, - 0, 1543, 0, - 0, 1673, 0, - 0, 1803, 0, - 0, 1933, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 676, 85, 511, - 647, 130, 480, - 606, 184, 434, - 545, 248, 366, - 447, 321, 254, - 271, 403, 43, - 0, 494, 0, - 0, 592, 0, - 0, 697, 0, - 0, 808, 0, - 0, 924, 0, - 0, 1044, 0, - 0, 1166, 0, - 0, 1291, 0, - 0, 1417, 0, - 0, 1545, 0, - 0, 1674, 0, - 0, 1803, 0, - 0, 1934, 0, - 0, 2064, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 837, 134, 636, - 818, 175, 613, - 790, 224, 579, - 750, 282, 531, - 690, 350, 456, - 596, 428, 332, - 427, 514, 85, - 12, 609, 0, - 0, 711, 0, - 0, 819, 0, - 0, 932, 0, - 0, 1050, 0, - 0, 1171, 0, - 0, 1294, 0, - 0, 1420, 0, - 0, 1547, 0, - 0, 1675, 0, - 0, 1805, 0, - 0, 1935, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 991, 192, 763, - 977, 228, 746, - 957, 272, 721, - 930, 325, 686, - 891, 387, 634, - 832, 459, 554, - 740, 540, 419, - 577, 630, 136, - 186, 728, 0, - 0, 832, 0, - 0, 943, 0, - 0, 1058, 0, - 0, 1177, 0, - 0, 1299, 0, - 0, 1423, 0, - 0, 1550, 0, - 0, 1677, 0, - 0, 1806, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1138, 259, 892, - 1128, 290, 878, - 1114, 329, 860, - 1095, 376, 834, - 1068, 432, 798, - 1029, 497, 743, - 971, 572, 659, - 880, 657, 514, - 721, 749, 197, - 347, 850, 0, - 0, 956, 0, - 0, 1068, 0, - 0, 1185, 0, - 0, 1305, 0, - 0, 1428, 0, - 0, 1553, 0, - 0, 1680, 0, - 0, 1808, 0, - 0, 1937, 0, - 0, 2067, 0, - 0, 2198, 0, - 0, 2328, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1281, 336, 1021, - 1274, 362, 1011, - 1264, 395, 997, - 1250, 436, 978, - 1231, 486, 952, - 1204, 544, 914, - 1166, 613, 858, - 1109, 690, 770, - 1019, 777, 616, - 862, 872, 267, - 499, 974, 0, - 0, 1082, 0, - 0, 1196, 0, - 0, 1314, 0, - 0, 1435, 0, - 0, 1558, 0, - 0, 1684, 0, - 0, 1811, 0, - 0, 1939, 0, - 0, 2069, 0, - 0, 2199, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1421, 422, 1151, - 1416, 444, 1143, - 1408, 472, 1133, - 1398, 506, 1119, - 1385, 549, 1100, - 1366, 601, 1073, - 1339, 661, 1034, - 1301, 732, 976, - 1245, 811, 885, - 1156, 900, 725, - 1001, 997, 346, - 646, 1100, 0, - 0, 1210, 0, - 0, 1324, 0, - 0, 1443, 0, - 0, 1565, 0, - 0, 1689, 0, - 0, 1815, 0, - 0, 1942, 0, - 0, 2071, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1559, 516, 1281, - 1555, 534, 1276, - 1550, 557, 1268, - 1543, 586, 1258, - 1533, 622, 1244, - 1519, 666, 1224, - 1500, 719, 1197, - 1474, 782, 1157, - 1436, 854, 1098, - 1380, 935, 1004, - 1291, 1025, 838, - 1138, 1123, 434, - 789, 1228, 0, - 0, 1339, 0, - 0, 1454, 0, - 0, 1573, 0, - 0, 1695, 0, - 0, 1820, 0, - 0, 1946, 0, - 0, 2074, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1696, 617, 1412, - 1693, 632, 1408, - 1689, 651, 1402, - 1683, 674, 1395, - 1676, 704, 1384, - 1666, 741, 1370, - 1653, 787, 1350, - 1634, 841, 1322, - 1608, 905, 1282, - 1570, 978, 1222, - 1514, 1061, 1126, - 1426, 1152, 956, - 1274, 1251, 531, - 929, 1357, 0, - 0, 1468, 0, - 0, 1584, 0, - 0, 1703, 0, - 0, 1826, 0, - 0, 1951, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1831, 725, 1543, - 1829, 737, 1540, - 1826, 752, 1536, - 1822, 771, 1530, - 1817, 795, 1523, - 1809, 826, 1512, - 1800, 864, 1498, - 1786, 910, 1478, - 1767, 965, 1449, - 1741, 1030, 1409, - 1703, 1105, 1348, - 1648, 1188, 1251, - 1560, 1280, 1077, - 1409, 1380, 634, - 1067, 1486, 0, - 0, 1598, 0, - 0, 1714, 0, - 0, 1834, 0, - 0, 1957, 0, - 0, 2082, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1965, 838, 1675, - 1964, 847, 1672, - 1962, 859, 1669, - 1959, 874, 1665, - 1955, 894, 1659, - 1949, 918, 1652, - 1942, 950, 1641, - 1932, 988, 1626, - 1919, 1035, 1606, - 1900, 1092, 1578, - 1874, 1157, 1537, - 1837, 1232, 1475, - 1781, 1317, 1377, - 1694, 1409, 1201, - 1543, 1510, 744, - 1203, 1617, 0, - 0, 1729, 0, - 0, 1845, 0, - 0, 1966, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 2099, 956, 1806, - 2098, 963, 1805, - 2097, 972, 1802, - 2094, 983, 1799, - 2091, 999, 1795, - 2087, 1019, 1789, - 2082, 1044, 1781, - 2075, 1076, 1771, - 2065, 1115, 1756, - 2052, 1162, 1736, - 2033, 1219, 1707, - 2007, 1285, 1666, - 1969, 1361, 1604, - 1914, 1446, 1505, - 1827, 1539, 1326, - 1676, 1640, 858, - 1338, 1747, 0, - 0, 1860, 0, - 0, 1977, 0, - 0, 2097, 0, - 0, 2220, 0, - 0, 2345, 0, - 0, 2472, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2233, 1076, 1938, - 2232, 1082, 1937, - 2231, 1089, 1935, - 2229, 1098, 1933, - 2227, 1110, 1929, - 2224, 1125, 1925, - 2220, 1146, 1919, - 2215, 1171, 1912, - 2208, 1203, 1901, - 2198, 1243, 1886, - 2184, 1291, 1866, - 2166, 1348, 1837, - 2140, 1415, 1796, - 2102, 1491, 1733, - 2047, 1576, 1634, - 1960, 1670, 1454, - 1810, 1771, 976, - 1473, 1878, 0, - 0, 1991, 0, - 0, 2108, 0, - 0, 2229, 0, - 0, 2352, 0, - 0, 2477, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2366, 1200, 2070, - 2365, 1204, 2069, - 2364, 1209, 2068, - 2363, 1216, 2066, - 2361, 1226, 2063, - 2359, 1238, 2060, - 2356, 1253, 2056, - 2352, 1274, 2050, - 2347, 1299, 2042, - 2340, 1332, 2032, - 2330, 1371, 2017, - 2317, 1420, 1997, - 2298, 1477, 1968, - 2272, 1544, 1926, - 2235, 1621, 1863, - 2179, 1707, 1763, - 2092, 1801, 1582, - 1943, 1902, 1098, - 1607, 2010, 0, - 0, 2123, 0, - 0, 2240, 0, - 0, 2360, 0, - 0, 2484, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2499, 1325, 2202, - 2498, 1328, 2201, - 2498, 1332, 2200, - 2497, 1338, 2199, - 2495, 1345, 2197, - 2494, 1354, 2195, - 2492, 1367, 2191, - 2489, 1382, 2187, - 2485, 1403, 2181, - 2480, 1429, 2174, - 2472, 1461, 2163, - 2463, 1501, 2148, - 2449, 1550, 2128, - 2431, 1608, 2099, - 2404, 1675, 2057, - 2367, 1752, 1994, - 2312, 1838, 1894, - 2225, 1932, 1711, - 2075, 2033, 1222, - 1740, 2141, 0, - 0, 2254, 0, - 0, 2371, 0, - 0, 2492, 0, - 0, 2616, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2996, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2631, 1452, 2334, - 2631, 1455, 2333, - 2630, 1458, 2332, - 2630, 1462, 2331, - 2629, 1467, 2330, - 2628, 1474, 2328, - 2626, 1484, 2326, - 2624, 1496, 2323, - 2621, 1512, 2319, - 2617, 1533, 2313, - 2612, 1559, 2305, - 2605, 1591, 2294, - 2595, 1631, 2279, - 2581, 1680, 2259, - 2563, 1738, 2230, - 2537, 1806, 2188, - 2499, 1883, 2125, - 2444, 1969, 2024, - 2357, 2063, 1842, - 2208, 2165, 1348, - 1873, 2273, 0, - 0, 2386, 0, - 0, 2503, 0, - 0, 2624, 0, - 0, 2748, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2764, 1581, 2466, - 2764, 1582, 2465, - 2763, 1585, 2465, - 2763, 1588, 2464, - 2762, 1592, 2463, - 2761, 1597, 2462, - 2760, 1605, 2460, - 2758, 1614, 2458, - 2756, 1626, 2454, - 2753, 1642, 2450, - 2749, 1663, 2444, - 2744, 1689, 2436, - 2737, 1722, 2426, - 2727, 1762, 2411, - 2714, 1811, 2390, - 2695, 1869, 2361, - 2669, 1937, 2319, - 2632, 2014, 2256, - 2576, 2100, 2155, - 2490, 2195, 1972, - 2340, 2297, 1475, - 2006, 2405, 0, - 0, 2518, 0, - 0, 2635, 0, - 0, 2756, 0, - 0, 2880, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1710, 2598, - 2896, 1711, 2597, - 2896, 1713, 2597, - 2895, 1715, 2596, - 2895, 1718, 2596, - 2894, 1723, 2595, - 2893, 1728, 2593, - 2892, 1735, 2592, - 2891, 1745, 2589, - 2888, 1757, 2586, - 2885, 1773, 2582, - 2882, 1794, 2576, - 2876, 1820, 2568, - 2869, 1853, 2557, - 2859, 1893, 2542, - 2846, 1942, 2522, - 2827, 2001, 2493, - 2801, 2068, 2451, - 2764, 2146, 2388, - 2709, 2232, 2287, - 2622, 2326, 2103, - 2473, 2428, 1604, - 2139, 2536, 0, - 0, 2650, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3012, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3029, 1840, 2730, - 3028, 1841, 2729, - 3028, 1842, 2729, - 3028, 1844, 2729, - 3028, 1846, 2728, - 3027, 1849, 2727, - 3026, 1854, 2726, - 3026, 1859, 2725, - 3024, 1866, 2723, - 3023, 1876, 2721, - 3021, 1888, 2718, - 3018, 1904, 2714, - 3014, 1925, 2708, - 3008, 1951, 2700, - 3001, 1984, 2689, - 2992, 2025, 2674, - 2978, 2074, 2654, - 2960, 2132, 2625, - 2933, 2200, 2582, - 2896, 2277, 2519, - 2841, 2364, 2418, - 2754, 2458, 2234, - 2605, 2560, 1733, - 2271, 2668, 0, - 0, 2782, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3161, 1970, 2862, - 3161, 1971, 2862, - 3161, 1972, 2861, - 3160, 1973, 2861, - 3160, 1975, 2861, - 3160, 1978, 2860, - 3159, 1981, 2859, - 3159, 1985, 2858, - 3158, 1990, 2857, - 3156, 1998, 2855, - 3155, 2007, 2853, - 3153, 2020, 2850, - 3150, 2036, 2845, - 3146, 2056, 2840, - 3141, 2083, 2832, - 3133, 2115, 2821, - 3124, 2156, 2806, - 3110, 2205, 2785, - 3092, 2264, 2756, - 3066, 2332, 2714, - 3028, 2409, 2651, - 2973, 2495, 2550, - 2887, 2590, 2366, - 2737, 2692, 1864, - 2403, 2800, 0, - 0, 2914, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3293, 2101, 2994, - 3293, 2102, 2994, - 3293, 2103, 2993, - 3293, 2104, 2993, - 3293, 2105, 2993, - 3292, 2107, 2993, - 3292, 2109, 2992, - 3291, 2112, 2991, - 3291, 2116, 2990, - 3290, 2122, 2989, - 3289, 2129, 2987, - 3287, 2139, 2985, - 3285, 2151, 2982, - 3282, 2167, 2977, - 3278, 2188, 2972, - 3273, 2214, 2964, - 3266, 2247, 2953, - 3256, 2288, 2938, - 3242, 2337, 2917, - 3224, 2395, 2888, - 3198, 2463, 2846, - 3160, 2541, 2783, - 3105, 2627, 2682, - 3019, 2722, 2497, - 2869, 2824, 1994, - 2536, 2932, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3660, 0, - 3425, 2232, 3126, - 3425, 2233, 3126, - 3425, 2233, 3126, - 3425, 2234, 3125, - 3425, 2235, 3125, - 3425, 2236, 3125, - 3424, 2238, 3125, - 3424, 2241, 3124, - 3424, 2244, 3123, - 3423, 2248, 3122, - 3422, 2253, 3121, - 3421, 2261, 3119, - 3419, 2270, 3117, - 3417, 2283, 3114, - 3414, 2299, 3109, - 3410, 2320, 3103, - 3405, 2346, 3096, - 3398, 2379, 3085, - 3388, 2420, 3070, - 3375, 2469, 3049, - 3356, 2527, 3020, - 3330, 2595, 2978, - 3293, 2673, 2915, - 3237, 2759, 2814, - 3151, 2854, 2629, - 3002, 2956, 2125, - 2668, 3064, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2364, 3258, - 3557, 2364, 3258, - 3557, 2365, 3258, - 3557, 2365, 3258, - 3557, 2366, 3257, - 3557, 2367, 3257, - 3557, 2368, 3257, - 3557, 2370, 3257, - 3556, 2372, 3256, - 3556, 2375, 3255, - 3555, 2380, 3254, - 3554, 2385, 3253, - 3553, 2392, 3251, - 3551, 2402, 3249, - 3549, 2414, 3246, - 3546, 2431, 3241, - 3542, 2451, 3235, - 3537, 2478, 3228, - 3530, 2511, 3217, - 3520, 2551, 3202, - 3507, 2601, 3181, - 3488, 2659, 3152, - 3462, 2727, 3110, - 3425, 2805, 3047, - 3369, 2891, 2945, - 3283, 2986, 2761, - 3134, 3088, 2256, - 2800, 3196, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3690, 2495, 3390, - 3690, 2496, 3390, - 3690, 2496, 3390, - 3689, 2496, 3390, - 3689, 2497, 3390, - 3689, 2498, 3389, - 3689, 2499, 3389, - 3689, 2500, 3389, - 3689, 2502, 3389, - 3688, 2504, 3388, - 3688, 2507, 3387, - 3687, 2511, 3386, - 3686, 2517, 3385, - 3685, 2524, 3383, - 3683, 2534, 3381, - 3681, 2546, 3378, - 3678, 2562, 3373, - 3674, 2583, 3368, - 3669, 2610, 3360, - 3662, 2643, 3349, - 3652, 2683, 3334, - 3639, 2733, 3313, - 3620, 2791, 3284, - 3594, 2859, 3242, - 3557, 2937, 3179, - 3502, 3023, 3077, - 3415, 3118, 2893, - 3266, 3220, 2388, - 2932, 3328, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3822, 2627, 3522, - 3822, 2627, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3821, 2629, 3522, - 3821, 2630, 3522, - 3821, 2631, 3521, - 3821, 2632, 3521, - 3821, 2634, 3521, - 3820, 2636, 3520, - 3820, 2639, 3519, - 3819, 2643, 3518, - 3818, 2649, 3517, - 3817, 2656, 3515, - 3815, 2666, 3513, - 3813, 2678, 3510, - 3810, 2694, 3505, - 3807, 2715, 3500, - 3801, 2742, 3492, - 3794, 2775, 3481, - 3784, 2815, 3466, - 3771, 2865, 3445, - 3752, 2923, 3416, - 3726, 2991, 3374, - 3689, 3069, 3311, - 3634, 3155, 3209, - 3547, 3250, 3025, - 3398, 3352, 2520, - 3065, 3460, 0, - 0, 3574, 0, - 0, 3691, 0, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3953, 2762, 3654, - 3953, 2763, 3653, - 3953, 2764, 3653, - 3953, 2766, 3653, - 3952, 2768, 3652, - 3952, 2771, 3651, - 3951, 2775, 3650, - 3950, 2781, 3649, - 3949, 2788, 3647, - 3948, 2798, 3645, - 3945, 2810, 3642, - 3943, 2826, 3637, - 3939, 2847, 3632, - 3933, 2873, 3624, - 3926, 2907, 3613, - 3916, 2947, 3598, - 3903, 2997, 3577, - 3884, 3055, 3548, - 3858, 3123, 3506, - 3821, 3201, 3443, - 3766, 3287, 3341, - 3679, 3382, 3157, - 3530, 3484, 2651, - 3197, 3592, 0, - 0, 3706, 0, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4085, 2895, 3785, - 4085, 2896, 3785, - 4085, 2898, 3785, - 4085, 2900, 3784, - 4084, 2903, 3783, - 4083, 2907, 3782, - 4083, 2913, 3781, - 4081, 2920, 3779, - 4080, 2930, 3777, - 4078, 2942, 3774, - 4075, 2958, 3770, - 4071, 2979, 3764, - 4065, 3005, 3756, - 4058, 3039, 3745, - 4049, 3079, 3730, - 4035, 3129, 3709, - 4017, 3187, 3680, - 3991, 3255, 3638, - 3953, 3333, 3575, - 3898, 3419, 3473, - 3811, 3514, 3289, - 3662, 3616, 2783, - 3329, 3725, 0, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3032, 3916, - 4095, 3035, 3916, - 4095, 3039, 3915, - 4095, 3045, 3913, - 4095, 3052, 3911, - 4095, 3062, 3909, - 4095, 3074, 3906, - 4095, 3090, 3902, - 4095, 3111, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3211, 3862, - 4095, 3261, 3842, - 4095, 3319, 3812, - 4095, 3387, 3770, - 4085, 3465, 3707, - 4030, 3551, 3606, - 3944, 3646, 3421, - 3794, 3748, 2915, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3167, 4048, - 4095, 3171, 4047, - 4095, 3177, 4045, - 4095, 3184, 4044, - 4095, 3194, 4041, - 4095, 3206, 4038, - 4095, 3222, 4034, - 4095, 3243, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3343, 3994, - 4095, 3393, 3974, - 4095, 3451, 3944, - 4095, 3519, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 33, 135, - 0, 83, 61, - 0, 142, 0, - 0, 211, 0, - 0, 290, 0, - 0, 377, 0, - 0, 473, 0, - 0, 576, 0, - 0, 684, 0, - 0, 798, 0, - 0, 916, 0, - 0, 1037, 0, - 0, 1161, 0, - 0, 1287, 0, - 0, 1414, 0, - 0, 1543, 0, - 0, 1672, 0, - 0, 1802, 0, - 0, 1933, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 11, 50, 228, - 0, 99, 168, - 0, 156, 74, - 0, 223, 0, - 0, 300, 0, - 0, 386, 0, - 0, 480, 0, - 0, 581, 0, - 0, 689, 0, - 0, 802, 0, - 0, 919, 0, - 0, 1039, 0, - 0, 1163, 0, - 0, 1288, 0, - 0, 1415, 0, - 0, 1543, 0, - 0, 1673, 0, - 0, 1803, 0, - 0, 1933, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 271, 73, 329, - 199, 119, 281, - 79, 174, 209, - 0, 239, 91, - 0, 313, 0, - 0, 397, 0, - 0, 489, 0, - 0, 588, 0, - 0, 694, 0, - 0, 806, 0, - 0, 922, 0, - 0, 1042, 0, - 0, 1165, 0, - 0, 1290, 0, - 0, 1416, 0, - 0, 1544, 0, - 0, 1673, 0, - 0, 1803, 0, - 0, 1934, 0, - 0, 2064, 0, - 0, 2195, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 480, 102, 436, - 435, 145, 399, - 368, 197, 344, - 259, 259, 259, - 54, 330, 113, - 0, 411, 0, - 0, 500, 0, - 0, 597, 0, - 0, 702, 0, - 0, 812, 0, - 0, 927, 0, - 0, 1045, 0, - 0, 1167, 0, - 0, 1292, 0, - 0, 1418, 0, - 0, 1546, 0, - 0, 1674, 0, - 0, 1804, 0, - 0, 1934, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2458, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 662, 137, 548, - 632, 177, 519, - 590, 226, 478, - 526, 284, 416, - 424, 352, 318, - 237, 429, 140, - 0, 515, 0, - 0, 610, 0, - 0, 711, 0, - 0, 819, 0, - 0, 933, 0, - 0, 1050, 0, - 0, 1171, 0, - 0, 1294, 0, - 0, 1420, 0, - 0, 1547, 0, - 0, 1675, 0, - 0, 1805, 0, - 0, 1935, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 828, 181, 665, - 808, 217, 643, - 779, 262, 612, - 738, 316, 566, - 677, 380, 498, - 579, 453, 386, - 403, 535, 175, - 0, 626, 0, - 0, 724, 0, - 0, 830, 0, - 0, 941, 0, - 0, 1056, 0, - 0, 1176, 0, - 0, 1298, 0, - 0, 1423, 0, - 0, 1549, 0, - 0, 1677, 0, - 0, 1806, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 984, 233, 785, - 970, 266, 768, - 950, 307, 745, - 922, 356, 712, - 882, 414, 663, - 822, 482, 588, - 728, 560, 464, - 559, 646, 217, - 144, 741, 0, - 0, 843, 0, - 0, 951, 0, - 0, 1064, 0, - 0, 1182, 0, - 0, 1303, 0, - 0, 1426, 0, - 0, 1552, 0, - 0, 1679, 0, - 0, 1807, 0, - 0, 1937, 0, - 0, 2067, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1133, 295, 908, - 1123, 324, 895, - 1109, 360, 878, - 1089, 404, 853, - 1062, 457, 818, - 1023, 519, 766, - 964, 591, 686, - 872, 672, 551, - 709, 762, 268, - 318, 860, 0, - 0, 964, 0, - 0, 1075, 0, - 0, 1190, 0, - 0, 1309, 0, - 0, 1431, 0, - 0, 1555, 0, - 0, 1682, 0, - 0, 1809, 0, - 0, 1938, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1277, 366, 1033, - 1270, 391, 1024, - 1260, 422, 1010, - 1246, 461, 992, - 1227, 508, 967, - 1200, 564, 930, - 1161, 629, 876, - 1103, 705, 791, - 1013, 789, 646, - 853, 882, 329, - 479, 982, 0, - 0, 1088, 0, - 0, 1201, 0, - 0, 1317, 0, - 0, 1437, 0, - 0, 1560, 0, - 0, 1685, 0, - 0, 1812, 0, - 0, 1940, 0, - 0, 2069, 0, - 0, 2199, 0, - 0, 2330, 0, - 0, 2460, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1418, 447, 1160, - 1413, 468, 1153, - 1406, 494, 1143, - 1396, 528, 1129, - 1382, 568, 1111, - 1363, 618, 1084, - 1336, 677, 1046, - 1298, 745, 990, - 1241, 822, 902, - 1151, 909, 748, - 994, 1004, 399, - 631, 1106, 0, - 0, 1214, 0, - 0, 1328, 0, - 0, 1446, 0, - 0, 1567, 0, - 0, 1690, 0, - 0, 1816, 0, - 0, 1943, 0, - 0, 2072, 0, - 0, 2201, 0, - 0, 2331, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1557, 537, 1288, - 1553, 554, 1283, - 1548, 576, 1275, - 1540, 604, 1265, - 1531, 639, 1251, - 1517, 681, 1232, - 1498, 733, 1205, - 1471, 793, 1166, - 1433, 864, 1108, - 1377, 944, 1017, - 1288, 1032, 857, - 1133, 1129, 478, - 778, 1232, 0, - 0, 1342, 0, - 0, 1456, 0, - 0, 1575, 0, - 0, 1697, 0, - 0, 1821, 0, - 0, 1947, 0, - 0, 2074, 0, - 0, 2203, 0, - 0, 2332, 0, - 0, 2463, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1694, 634, 1417, - 1691, 648, 1413, - 1687, 666, 1408, - 1682, 689, 1400, - 1675, 718, 1390, - 1665, 754, 1376, - 1651, 798, 1356, - 1632, 851, 1329, - 1606, 914, 1289, - 1568, 986, 1230, - 1512, 1067, 1136, - 1424, 1157, 970, - 1270, 1255, 567, - 921, 1360, 0, - 0, 1471, 0, - 0, 1586, 0, - 0, 1705, 0, - 0, 1827, 0, - 0, 1952, 0, - 0, 2078, 0, - 0, 2206, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1830, 738, 1547, - 1828, 750, 1544, - 1825, 764, 1540, - 1821, 783, 1534, - 1815, 806, 1527, - 1808, 836, 1516, - 1798, 873, 1502, - 1785, 919, 1482, - 1766, 973, 1454, - 1740, 1037, 1414, - 1702, 1110, 1354, - 1646, 1193, 1258, - 1558, 1284, 1088, - 1406, 1383, 663, - 1061, 1489, 0, - 0, 1600, 0, - 0, 1716, 0, - 0, 1836, 0, - 0, 1958, 0, - 0, 2083, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1965, 849, 1678, - 1963, 857, 1675, - 1961, 869, 1672, - 1958, 884, 1668, - 1954, 903, 1662, - 1949, 927, 1655, - 1941, 958, 1644, - 1932, 996, 1630, - 1918, 1042, 1610, - 1899, 1097, 1582, - 1873, 1162, 1541, - 1835, 1237, 1480, - 1780, 1320, 1383, - 1692, 1412, 1209, - 1541, 1512, 766, - 1199, 1618, 0, - 0, 1730, 0, - 0, 1847, 0, - 0, 1966, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 2099, 964, 1809, - 2098, 970, 1807, - 2096, 979, 1804, - 2094, 991, 1801, - 2091, 1006, 1797, - 2087, 1026, 1791, - 2082, 1051, 1784, - 2074, 1082, 1773, - 2065, 1120, 1759, - 2051, 1167, 1738, - 2032, 1224, 1710, - 2006, 1289, 1669, - 1969, 1364, 1607, - 1913, 1449, 1509, - 1826, 1542, 1333, - 1675, 1642, 876, - 1335, 1749, 0, - 0, 1861, 0, - 0, 1978, 0, - 0, 2098, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2232, 1083, 1940, - 2231, 1088, 1938, - 2230, 1095, 1937, - 2229, 1104, 1934, - 2226, 1116, 1931, - 2224, 1131, 1927, - 2220, 1151, 1921, - 2214, 1176, 1913, - 2207, 1208, 1903, - 2197, 1247, 1888, - 2184, 1294, 1868, - 2165, 1351, 1839, - 2139, 1417, 1798, - 2101, 1493, 1736, - 2046, 1578, 1637, - 1959, 1671, 1459, - 1809, 1772, 990, - 1470, 1879, 0, - 0, 1992, 0, - 0, 2109, 0, - 0, 2229, 0, - 0, 2352, 0, - 0, 2478, 0, - 0, 2604, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2366, 1204, 2071, - 2365, 1208, 2070, - 2364, 1214, 2069, - 2363, 1221, 2067, - 2361, 1230, 2065, - 2359, 1242, 2062, - 2356, 1258, 2057, - 2352, 1278, 2052, - 2347, 1303, 2044, - 2340, 1335, 2033, - 2330, 1375, 2018, - 2316, 1423, 1998, - 2298, 1480, 1969, - 2272, 1547, 1928, - 2234, 1623, 1865, - 2179, 1708, 1766, - 2092, 1802, 1586, - 1942, 1903, 1108, - 1605, 2010, 0, - 0, 2123, 0, - 0, 2240, 0, - 0, 2361, 0, - 0, 2484, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2498, 1329, 2203, - 2498, 1332, 2202, - 2497, 1336, 2201, - 2496, 1341, 2200, - 2495, 1348, 2198, - 2494, 1358, 2196, - 2491, 1370, 2192, - 2488, 1385, 2188, - 2485, 1406, 2182, - 2479, 1431, 2175, - 2472, 1464, 2164, - 2462, 1504, 2149, - 2449, 1552, 2129, - 2430, 1609, 2100, - 2404, 1677, 2058, - 2367, 1753, 1995, - 2311, 1839, 1896, - 2225, 1933, 1714, - 2075, 2034, 1230, - 1739, 2142, 0, - 0, 2255, 0, - 0, 2372, 0, - 0, 2492, 0, - 0, 2616, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2631, 1455, 2334, - 2631, 1457, 2334, - 2630, 1460, 2333, - 2630, 1464, 2332, - 2629, 1470, 2331, - 2628, 1477, 2329, - 2626, 1486, 2327, - 2624, 1499, 2324, - 2621, 1514, 2319, - 2617, 1535, 2313, - 2612, 1561, 2306, - 2604, 1593, 2295, - 2595, 1633, 2280, - 2581, 1682, 2260, - 2563, 1740, 2231, - 2537, 1807, 2189, - 2499, 1884, 2126, - 2444, 1970, 2026, - 2357, 2064, 1844, - 2207, 2165, 1354, - 1872, 2273, 0, - 0, 2386, 0, - 0, 2504, 0, - 0, 2624, 0, - 0, 2748, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2764, 1583, 2466, - 2763, 1584, 2466, - 2763, 1587, 2465, - 2763, 1590, 2464, - 2762, 1594, 2464, - 2761, 1599, 2462, - 2760, 1607, 2460, - 2758, 1616, 2458, - 2756, 1628, 2455, - 2753, 1644, 2451, - 2749, 1665, 2445, - 2744, 1691, 2437, - 2737, 1723, 2426, - 2727, 1764, 2411, - 2714, 1812, 2391, - 2695, 1870, 2362, - 2669, 1938, 2320, - 2631, 2015, 2257, - 2576, 2101, 2156, - 2490, 2195, 1974, - 2340, 2297, 1480, - 2005, 2405, 0, - 0, 2518, 0, - 0, 2635, 0, - 0, 2756, 0, - 0, 2880, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1711, 2598, - 2896, 1713, 2598, - 2896, 1714, 2597, - 2895, 1717, 2597, - 2895, 1720, 2596, - 2894, 1724, 2595, - 2893, 1730, 2594, - 2892, 1737, 2592, - 2890, 1746, 2590, - 2888, 1759, 2586, - 2885, 1775, 2582, - 2881, 1795, 2576, - 2876, 1821, 2568, - 2869, 1854, 2558, - 2859, 1894, 2543, - 2846, 1943, 2522, - 2827, 2001, 2493, - 2801, 2069, 2451, - 2764, 2146, 2388, - 2708, 2232, 2288, - 2622, 2327, 2104, - 2472, 2429, 1608, - 2138, 2537, 0, - 0, 2650, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3012, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3029, 1841, 2730, - 3028, 1842, 2730, - 3028, 1843, 2729, - 3028, 1845, 2729, - 3028, 1847, 2728, - 3027, 1851, 2728, - 3026, 1855, 2727, - 3025, 1860, 2725, - 3024, 1867, 2724, - 3023, 1877, 2721, - 3020, 1889, 2718, - 3018, 1905, 2714, - 3014, 1926, 2708, - 3008, 1952, 2700, - 3001, 1985, 2689, - 2991, 2025, 2675, - 2978, 2074, 2654, - 2959, 2133, 2625, - 2933, 2200, 2583, - 2896, 2278, 2520, - 2841, 2364, 2419, - 2754, 2459, 2235, - 2605, 2560, 1736, - 2271, 2668, 0, - 0, 2782, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3161, 1971, 2862, - 3161, 1972, 2862, - 3161, 1973, 2862, - 3160, 1974, 2861, - 3160, 1976, 2861, - 3160, 1978, 2860, - 3159, 1981, 2860, - 3159, 1986, 2859, - 3158, 1991, 2857, - 3156, 1998, 2856, - 3155, 2008, 2853, - 3153, 2020, 2850, - 3150, 2036, 2846, - 3146, 2057, 2840, - 3141, 2083, 2832, - 3133, 2116, 2821, - 3124, 2157, 2806, - 3110, 2206, 2786, - 3092, 2264, 2757, - 3066, 2332, 2715, - 3028, 2409, 2651, - 2973, 2496, 2550, - 2886, 2590, 2366, - 2737, 2692, 1866, - 2403, 2800, 0, - 0, 2914, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3293, 2102, 2994, - 3293, 2102, 2994, - 3293, 2103, 2994, - 3293, 2104, 2993, - 3292, 2105, 2993, - 3292, 2107, 2993, - 3292, 2110, 2992, - 3291, 2113, 2991, - 3291, 2117, 2990, - 3290, 2122, 2989, - 3289, 2130, 2987, - 3287, 2139, 2985, - 3285, 2152, 2982, - 3282, 2168, 2978, - 3278, 2188, 2972, - 3273, 2215, 2964, - 3266, 2248, 2953, - 3256, 2288, 2938, - 3242, 2337, 2918, - 3224, 2396, 2888, - 3198, 2464, 2846, - 3160, 2541, 2783, - 3105, 2628, 2682, - 3019, 2722, 2498, - 2869, 2824, 1996, - 2536, 2932, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3660, 0, - 3425, 2233, 3126, - 3425, 2233, 3126, - 3425, 2234, 3126, - 3425, 2235, 3126, - 3425, 2236, 3125, - 3425, 2237, 3125, - 3424, 2239, 3125, - 3424, 2241, 3124, - 3423, 2244, 3123, - 3423, 2248, 3122, - 3422, 2254, 3121, - 3421, 2261, 3119, - 3419, 2271, 3117, - 3417, 2283, 3114, - 3414, 2299, 3109, - 3410, 2320, 3104, - 3405, 2346, 3096, - 3398, 2379, 3085, - 3388, 2420, 3070, - 3375, 2469, 3049, - 3356, 2527, 3020, - 3330, 2595, 2978, - 3293, 2673, 2915, - 3237, 2759, 2814, - 3151, 2854, 2629, - 3002, 2956, 2126, - 2668, 3064, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2364, 3258, - 3557, 2365, 3258, - 3557, 2365, 3258, - 3557, 2365, 3258, - 3557, 2366, 3258, - 3557, 2367, 3257, - 3557, 2369, 3257, - 3556, 2370, 3257, - 3556, 2373, 3256, - 3556, 2376, 3255, - 3555, 2380, 3254, - 3554, 2386, 3253, - 3553, 2393, 3251, - 3551, 2402, 3249, - 3549, 2415, 3246, - 3546, 2431, 3241, - 3542, 2452, 3236, - 3537, 2478, 3228, - 3530, 2511, 3217, - 3520, 2552, 3202, - 3507, 2601, 3181, - 3488, 2659, 3152, - 3462, 2727, 3110, - 3425, 2805, 3047, - 3369, 2891, 2946, - 3283, 2986, 2761, - 3134, 3088, 2257, - 2800, 3196, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3690, 2496, 3390, - 3690, 2496, 3390, - 3690, 2496, 3390, - 3689, 2497, 3390, - 3689, 2497, 3390, - 3689, 2498, 3390, - 3689, 2499, 3389, - 3689, 2500, 3389, - 3689, 2502, 3389, - 3688, 2504, 3388, - 3688, 2508, 3387, - 3687, 2512, 3386, - 3686, 2517, 3385, - 3685, 2525, 3383, - 3683, 2534, 3381, - 3681, 2547, 3378, - 3678, 2563, 3373, - 3674, 2583, 3368, - 3669, 2610, 3360, - 3662, 2643, 3349, - 3652, 2683, 3334, - 3639, 2733, 3313, - 3620, 2791, 3284, - 3594, 2859, 3242, - 3557, 2937, 3179, - 3501, 3023, 3078, - 3415, 3118, 2893, - 3266, 3220, 2389, - 2932, 3328, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3822, 2627, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3821, 2629, 3522, - 3821, 2630, 3522, - 3821, 2631, 3521, - 3821, 2632, 3521, - 3821, 2634, 3521, - 3820, 2636, 3520, - 3820, 2639, 3519, - 3819, 2644, 3518, - 3818, 2649, 3517, - 3817, 2656, 3515, - 3815, 2666, 3513, - 3813, 2678, 3510, - 3810, 2695, 3505, - 3806, 2715, 3500, - 3801, 2742, 3492, - 3794, 2775, 3481, - 3784, 2815, 3466, - 3771, 2865, 3445, - 3752, 2923, 3416, - 3726, 2991, 3374, - 3689, 3069, 3311, - 3634, 3155, 3210, - 3547, 3250, 3025, - 3398, 3352, 2520, - 3065, 3460, 0, - 0, 3574, 0, - 0, 3691, 0, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3953, 2762, 3654, - 3953, 2763, 3653, - 3953, 2764, 3653, - 3953, 2766, 3653, - 3952, 2768, 3652, - 3952, 2771, 3651, - 3951, 2775, 3650, - 3950, 2781, 3649, - 3949, 2788, 3647, - 3948, 2798, 3645, - 3945, 2810, 3642, - 3943, 2826, 3637, - 3939, 2847, 3632, - 3933, 2874, 3624, - 3926, 2907, 3613, - 3916, 2947, 3598, - 3903, 2997, 3577, - 3884, 3055, 3548, - 3858, 3123, 3506, - 3821, 3201, 3443, - 3766, 3287, 3342, - 3679, 3382, 3157, - 3530, 3484, 2652, - 3197, 3593, 0, - 0, 3706, 0, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4085, 2895, 3785, - 4085, 2896, 3785, - 4085, 2898, 3785, - 4085, 2900, 3784, - 4084, 2903, 3783, - 4083, 2907, 3782, - 4082, 2913, 3781, - 4081, 2920, 3779, - 4080, 2930, 3777, - 4078, 2942, 3774, - 4075, 2958, 3770, - 4071, 2979, 3764, - 4065, 3006, 3756, - 4058, 3039, 3745, - 4048, 3079, 3730, - 4035, 3129, 3710, - 4017, 3187, 3680, - 3990, 3255, 3638, - 3953, 3333, 3575, - 3898, 3419, 3474, - 3811, 3514, 3289, - 3662, 3616, 2783, - 3329, 3725, 0, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3032, 3916, - 4095, 3035, 3916, - 4095, 3039, 3915, - 4095, 3045, 3913, - 4095, 3052, 3911, - 4095, 3062, 3909, - 4095, 3074, 3906, - 4095, 3090, 3902, - 4095, 3111, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3211, 3862, - 4095, 3261, 3842, - 4095, 3319, 3812, - 4095, 3387, 3770, - 4085, 3465, 3707, - 4030, 3552, 3606, - 3944, 3646, 3421, - 3794, 3748, 2915, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3167, 4048, - 4095, 3171, 4047, - 4095, 3177, 4045, - 4095, 3184, 4044, - 4095, 3194, 4041, - 4095, 3206, 4038, - 4095, 3222, 4034, - 4095, 3243, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3343, 3994, - 4095, 3393, 3974, - 4095, 3451, 3944, - 4095, 3519, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 108, 241, - 0, 151, 183, - 0, 203, 91, - 0, 264, 0, - 0, 334, 0, - 0, 414, 0, - 0, 503, 0, - 0, 600, 0, - 0, 704, 0, - 0, 813, 0, - 0, 928, 0, - 0, 1046, 0, - 0, 1168, 0, - 0, 1292, 0, - 0, 1418, 0, - 0, 1546, 0, - 0, 1674, 0, - 0, 1804, 0, - 0, 1934, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 123, 316, - 0, 165, 267, - 0, 215, 193, - 0, 274, 69, - 0, 343, 0, - 0, 422, 0, - 0, 509, 0, - 0, 605, 0, - 0, 708, 0, - 0, 816, 0, - 0, 930, 0, - 0, 1048, 0, - 0, 1170, 0, - 0, 1293, 0, - 0, 1419, 0, - 0, 1546, 0, - 0, 1675, 0, - 0, 1804, 0, - 0, 1934, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 225, 143, 400, - 144, 182, 360, - 6, 231, 300, - 0, 288, 206, - 0, 355, 37, - 0, 432, 0, - 0, 518, 0, - 0, 612, 0, - 0, 713, 0, - 0, 821, 0, - 0, 934, 0, - 0, 1051, 0, - 0, 1171, 0, - 0, 1295, 0, - 0, 1420, 0, - 0, 1547, 0, - 0, 1676, 0, - 0, 1805, 0, - 0, 1935, 0, - 0, 2065, 0, - 0, 2196, 0, - 0, 2327, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 451, 167, 493, - 403, 205, 461, - 331, 251, 413, - 211, 306, 341, - 0, 371, 223, - 0, 445, 0, - 0, 529, 0, - 0, 621, 0, - 0, 720, 0, - 0, 826, 0, - 0, 938, 0, - 0, 1054, 0, - 0, 1174, 0, - 0, 1297, 0, - 0, 1422, 0, - 0, 1548, 0, - 0, 1676, 0, - 0, 1805, 0, - 0, 1935, 0, - 0, 2066, 0, - 0, 2196, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2590, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 643, 198, 593, - 612, 234, 568, - 567, 277, 531, - 500, 329, 476, - 391, 391, 391, - 186, 462, 245, - 0, 543, 0, - 0, 632, 0, - 0, 730, 0, - 0, 834, 0, - 0, 944, 0, - 0, 1059, 0, - 0, 1178, 0, - 0, 1299, 0, - 0, 1424, 0, - 0, 1550, 0, - 0, 1678, 0, - 0, 1806, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 815, 237, 700, - 794, 269, 680, - 765, 310, 651, - 722, 358, 610, - 658, 417, 548, - 556, 484, 450, - 369, 561, 272, - 0, 647, 0, - 0, 742, 0, - 0, 844, 0, - 0, 952, 0, - 0, 1065, 0, - 0, 1182, 0, - 0, 1303, 0, - 0, 1426, 0, - 0, 1552, 0, - 0, 1679, 0, - 0, 1808, 0, - 0, 1937, 0, - 0, 2067, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 974, 283, 813, - 960, 313, 797, - 940, 350, 775, - 911, 395, 744, - 870, 448, 699, - 809, 512, 630, - 711, 585, 518, - 535, 667, 307, - 81, 758, 0, - 0, 856, 0, - 0, 962, 0, - 0, 1073, 0, - 0, 1188, 0, - 0, 1308, 0, - 0, 1430, 0, - 0, 1555, 0, - 0, 1681, 0, - 0, 1809, 0, - 0, 1938, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1126, 339, 929, - 1116, 365, 917, - 1102, 398, 900, - 1082, 439, 877, - 1054, 488, 844, - 1014, 546, 795, - 954, 614, 720, - 860, 692, 596, - 691, 778, 349, - 276, 873, 0, - 0, 975, 0, - 0, 1083, 0, - 0, 1196, 0, - 0, 1314, 0, - 0, 1435, 0, - 0, 1558, 0, - 0, 1684, 0, - 0, 1811, 0, - 0, 1939, 0, - 0, 2069, 0, - 0, 2199, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1272, 404, 1049, - 1265, 427, 1040, - 1255, 456, 1027, - 1241, 492, 1010, - 1221, 536, 985, - 1194, 589, 950, - 1155, 651, 898, - 1096, 723, 818, - 1004, 804, 683, - 841, 894, 400, - 450, 992, 0, - 0, 1096, 0, - 0, 1207, 0, - 0, 1322, 0, - 0, 1441, 0, - 0, 1563, 0, - 0, 1688, 0, - 0, 1814, 0, - 0, 1942, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1415, 479, 1172, - 1409, 499, 1165, - 1402, 523, 1156, - 1392, 554, 1143, - 1378, 593, 1124, - 1359, 640, 1099, - 1332, 696, 1062, - 1293, 762, 1008, - 1235, 837, 923, - 1145, 921, 778, - 985, 1014, 461, - 611, 1114, 0, - 0, 1221, 0, - 0, 1333, 0, - 0, 1449, 0, - 0, 1569, 0, - 0, 1692, 0, - 0, 1817, 0, - 0, 1944, 0, - 0, 2072, 0, - 0, 2202, 0, - 0, 2331, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1555, 563, 1298, - 1551, 579, 1292, - 1545, 600, 1285, - 1538, 627, 1275, - 1528, 660, 1262, - 1514, 701, 1243, - 1495, 750, 1216, - 1468, 809, 1178, - 1430, 877, 1122, - 1373, 955, 1034, - 1283, 1041, 880, - 1127, 1136, 531, - 763, 1238, 0, - 0, 1347, 0, - 0, 1460, 0, - 0, 1578, 0, - 0, 1699, 0, - 0, 1822, 0, - 0, 1948, 0, - 0, 2075, 0, - 0, 2204, 0, - 0, 2333, 0, - 0, 2463, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1692, 656, 1424, - 1689, 669, 1420, - 1685, 686, 1415, - 1680, 708, 1408, - 1673, 736, 1397, - 1663, 771, 1384, - 1649, 813, 1364, - 1630, 865, 1337, - 1604, 926, 1298, - 1565, 996, 1240, - 1509, 1076, 1149, - 1420, 1164, 989, - 1265, 1261, 610, - 910, 1365, 0, - 0, 1474, 0, - 0, 1589, 0, - 0, 1707, 0, - 0, 1829, 0, - 0, 1953, 0, - 0, 2079, 0, - 0, 2206, 0, - 0, 2335, 0, - 0, 2464, 0, - 0, 2595, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1828, 756, 1553, - 1826, 766, 1550, - 1823, 780, 1545, - 1819, 798, 1540, - 1814, 821, 1532, - 1807, 850, 1522, - 1797, 886, 1508, - 1783, 930, 1488, - 1764, 983, 1461, - 1738, 1046, 1421, - 1700, 1118, 1362, - 1644, 1199, 1268, - 1556, 1289, 1103, - 1402, 1387, 699, - 1053, 1492, 0, - 0, 1603, 0, - 0, 1718, 0, - 0, 1837, 0, - 0, 1959, 0, - 0, 2084, 0, - 0, 2210, 0, - 0, 2338, 0, - 0, 2467, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1964, 862, 1682, - 1962, 871, 1679, - 1960, 882, 1676, - 1957, 896, 1672, - 1953, 915, 1667, - 1948, 938, 1659, - 1940, 968, 1649, - 1930, 1006, 1634, - 1917, 1051, 1614, - 1898, 1105, 1586, - 1872, 1169, 1546, - 1834, 1243, 1486, - 1778, 1325, 1391, - 1690, 1416, 1220, - 1538, 1515, 795, - 1193, 1621, 0, - 0, 1732, 0, - 0, 1848, 0, - 0, 1968, 0, - 0, 2090, 0, - 0, 2215, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 2098, 974, 1812, - 2097, 981, 1810, - 2095, 989, 1808, - 2093, 1001, 1804, - 2090, 1016, 1800, - 2086, 1035, 1795, - 2081, 1059, 1787, - 2074, 1090, 1776, - 2064, 1128, 1762, - 2050, 1174, 1742, - 2032, 1230, 1714, - 2005, 1294, 1673, - 1968, 1369, 1612, - 1912, 1452, 1515, - 1824, 1545, 1341, - 1673, 1644, 898, - 1331, 1751, 0, - 0, 1862, 0, - 0, 1979, 0, - 0, 2099, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2232, 1091, 1942, - 2231, 1096, 1941, - 2230, 1103, 1939, - 2228, 1111, 1937, - 2226, 1123, 1933, - 2223, 1138, 1929, - 2219, 1158, 1924, - 2214, 1183, 1916, - 2206, 1214, 1905, - 2197, 1253, 1891, - 2183, 1300, 1870, - 2165, 1356, 1842, - 2138, 1421, 1801, - 2101, 1497, 1739, - 2045, 1581, 1641, - 1958, 1674, 1465, - 1807, 1774, 1008, - 1467, 1881, 0, - 0, 1993, 0, - 0, 2110, 0, - 0, 2230, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2365, 1211, 2073, - 2364, 1215, 2072, - 2364, 1220, 2071, - 2362, 1227, 2069, - 2361, 1236, 2066, - 2359, 1248, 2063, - 2356, 1263, 2059, - 2352, 1283, 2053, - 2346, 1308, 2046, - 2339, 1340, 2035, - 2329, 1379, 2020, - 2316, 1427, 2000, - 2297, 1483, 1971, - 2271, 1550, 1930, - 2234, 1625, 1868, - 2178, 1710, 1769, - 2091, 1804, 1591, - 1941, 1904, 1122, - 1603, 2011, 0, - 0, 2124, 0, - 0, 2241, 0, - 0, 2361, 0, - 0, 2484, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2498, 1334, 2204, - 2498, 1337, 2203, - 2497, 1341, 2202, - 2496, 1346, 2201, - 2495, 1353, 2199, - 2493, 1362, 2197, - 2491, 1374, 2194, - 2488, 1390, 2189, - 2484, 1410, 2184, - 2479, 1435, 2176, - 2472, 1467, 2165, - 2462, 1507, 2150, - 2449, 1555, 2130, - 2430, 1612, 2101, - 2404, 1679, 2060, - 2366, 1755, 1997, - 2311, 1840, 1898, - 2224, 1934, 1718, - 2074, 2035, 1241, - 1737, 2142, 0, - 0, 2255, 0, - 0, 2372, 0, - 0, 2493, 0, - 0, 2616, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2631, 1459, 2335, - 2631, 1461, 2335, - 2630, 1464, 2334, - 2629, 1468, 2333, - 2628, 1473, 2332, - 2627, 1480, 2330, - 2626, 1490, 2328, - 2624, 1502, 2324, - 2621, 1518, 2320, - 2617, 1538, 2314, - 2611, 1564, 2307, - 2604, 1596, 2296, - 2594, 1636, 2281, - 2581, 1684, 2261, - 2562, 1742, 2232, - 2536, 1809, 2190, - 2499, 1885, 2128, - 2443, 1971, 2028, - 2357, 2065, 1846, - 2207, 2166, 1362, - 1871, 2274, 0, - 0, 2387, 0, - 0, 2504, 0, - 0, 2625, 0, - 0, 2748, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2764, 1585, 2467, - 2763, 1587, 2466, - 2763, 1589, 2466, - 2762, 1593, 2465, - 2762, 1597, 2464, - 2761, 1602, 2463, - 2760, 1609, 2461, - 2758, 1618, 2459, - 2756, 1631, 2456, - 2753, 1647, 2451, - 2749, 1667, 2446, - 2744, 1693, 2438, - 2737, 1725, 2427, - 2727, 1765, 2412, - 2713, 1814, 2392, - 2695, 1872, 2363, - 2669, 1939, 2321, - 2631, 2016, 2258, - 2576, 2102, 2158, - 2489, 2196, 1976, - 2340, 2297, 1486, - 2004, 2405, 0, - 0, 2518, 0, - 0, 2636, 0, - 0, 2756, 0, - 0, 2880, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1713, 2599, - 2896, 1715, 2598, - 2896, 1717, 2598, - 2895, 1719, 2597, - 2895, 1722, 2597, - 2894, 1726, 2596, - 2893, 1731, 2594, - 2892, 1739, 2593, - 2890, 1748, 2590, - 2888, 1760, 2587, - 2885, 1776, 2583, - 2881, 1797, 2577, - 2876, 1823, 2569, - 2869, 1855, 2558, - 2859, 1896, 2544, - 2846, 1944, 2523, - 2827, 2002, 2494, - 2801, 2070, 2452, - 2764, 2147, 2389, - 2708, 2233, 2289, - 2622, 2327, 2106, - 2472, 2429, 1612, - 2137, 2537, 0, - 0, 2650, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3012, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3028, 1843, 2730, - 3028, 1844, 2730, - 3028, 1845, 2730, - 3028, 1847, 2729, - 3027, 1849, 2729, - 3027, 1852, 2728, - 3026, 1856, 2727, - 3025, 1862, 2726, - 3024, 1869, 2724, - 3023, 1878, 2722, - 3020, 1891, 2719, - 3017, 1907, 2714, - 3014, 1927, 2708, - 3008, 1953, 2701, - 3001, 1986, 2690, - 2991, 2026, 2675, - 2978, 2075, 2654, - 2959, 2133, 2625, - 2933, 2201, 2583, - 2896, 2278, 2520, - 2840, 2364, 2420, - 2754, 2459, 2236, - 2605, 2561, 1740, - 2270, 2669, 0, - 0, 2782, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3161, 1972, 2862, - 3161, 1973, 2862, - 3160, 1974, 2862, - 3160, 1975, 2862, - 3160, 1977, 2861, - 3160, 1980, 2861, - 3159, 1983, 2860, - 3158, 1987, 2859, - 3158, 1992, 2858, - 3156, 1999, 2856, - 3155, 2009, 2853, - 3153, 2021, 2850, - 3150, 2037, 2846, - 3146, 2058, 2840, - 3140, 2084, 2832, - 3133, 2117, 2821, - 3124, 2157, 2807, - 3110, 2206, 2786, - 3092, 2265, 2757, - 3065, 2333, 2715, - 3028, 2410, 2652, - 2973, 2496, 2551, - 2886, 2591, 2367, - 2737, 2692, 1868, - 2403, 2801, 0, - 0, 2914, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3293, 2103, 2994, - 3293, 2103, 2994, - 3293, 2104, 2994, - 3293, 2105, 2994, - 3292, 2106, 2993, - 3292, 2108, 2993, - 3292, 2110, 2992, - 3291, 2114, 2992, - 3291, 2118, 2991, - 3290, 2123, 2989, - 3289, 2130, 2988, - 3287, 2140, 2985, - 3285, 2152, 2982, - 3282, 2168, 2978, - 3278, 2189, 2972, - 3273, 2215, 2964, - 3265, 2248, 2953, - 3256, 2289, 2938, - 3242, 2338, 2918, - 3224, 2396, 2889, - 3198, 2464, 2847, - 3160, 2541, 2784, - 3105, 2628, 2682, - 3019, 2722, 2498, - 2869, 2824, 1998, - 2535, 2932, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3660, 0, - 3425, 2234, 3126, - 3425, 2234, 3126, - 3425, 2235, 3126, - 3425, 2235, 3126, - 3425, 2236, 3126, - 3425, 2238, 3125, - 3424, 2239, 3125, - 3424, 2242, 3124, - 3423, 2245, 3124, - 3423, 2249, 3123, - 3422, 2255, 3121, - 3421, 2262, 3119, - 3419, 2271, 3117, - 3417, 2284, 3114, - 3414, 2300, 3110, - 3410, 2320, 3104, - 3405, 2347, 3096, - 3398, 2380, 3085, - 3388, 2420, 3070, - 3374, 2469, 3050, - 3356, 2528, 3021, - 3330, 2596, 2978, - 3292, 2673, 2915, - 3237, 2760, 2814, - 3151, 2854, 2630, - 3001, 2956, 2128, - 2668, 3064, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2365, 3258, - 3557, 2365, 3258, - 3557, 2365, 3258, - 3557, 2366, 3258, - 3557, 2367, 3258, - 3557, 2368, 3257, - 3557, 2369, 3257, - 3556, 2371, 3257, - 3556, 2373, 3256, - 3556, 2376, 3255, - 3555, 2380, 3254, - 3554, 2386, 3253, - 3553, 2393, 3251, - 3551, 2403, 3249, - 3549, 2415, 3246, - 3546, 2431, 3242, - 3542, 2452, 3236, - 3537, 2478, 3228, - 3530, 2511, 3217, - 3520, 2552, 3202, - 3507, 2601, 3182, - 3488, 2660, 3152, - 3462, 2728, 3110, - 3425, 2805, 3047, - 3369, 2892, 2946, - 3283, 2986, 2761, - 3134, 3088, 2258, - 2800, 3196, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3690, 2496, 3390, - 3690, 2496, 3390, - 3689, 2497, 3390, - 3689, 2497, 3390, - 3689, 2498, 3390, - 3689, 2498, 3390, - 3689, 2499, 3389, - 3689, 2501, 3389, - 3689, 2502, 3389, - 3688, 2505, 3388, - 3688, 2508, 3387, - 3687, 2512, 3386, - 3686, 2518, 3385, - 3685, 2525, 3383, - 3683, 2534, 3381, - 3681, 2547, 3378, - 3678, 2563, 3374, - 3674, 2584, 3368, - 3669, 2610, 3360, - 3662, 2643, 3349, - 3652, 2684, 3334, - 3639, 2733, 3314, - 3620, 2791, 3284, - 3594, 2859, 3242, - 3557, 2937, 3179, - 3501, 3023, 3078, - 3415, 3118, 2893, - 3266, 3220, 2389, - 2932, 3328, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2629, 3522, - 3821, 2629, 3522, - 3821, 2630, 3522, - 3821, 2631, 3521, - 3821, 2632, 3521, - 3821, 2634, 3521, - 3820, 2637, 3520, - 3820, 2640, 3519, - 3819, 2644, 3518, - 3818, 2649, 3517, - 3817, 2657, 3515, - 3815, 2666, 3513, - 3813, 2679, 3510, - 3810, 2695, 3506, - 3806, 2716, 3500, - 3801, 2742, 3492, - 3794, 2775, 3481, - 3784, 2816, 3466, - 3771, 2865, 3446, - 3752, 2923, 3416, - 3726, 2991, 3374, - 3689, 3069, 3311, - 3634, 3155, 3210, - 3547, 3250, 3025, - 3398, 3352, 2521, - 3064, 3460, 0, - 0, 3574, 0, - 0, 3691, 0, - 3954, 2759, 3654, - 3954, 2759, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3954, 2761, 3654, - 3953, 2762, 3654, - 3953, 2763, 3653, - 3953, 2764, 3653, - 3953, 2766, 3653, - 3952, 2768, 3652, - 3952, 2772, 3651, - 3951, 2776, 3650, - 3950, 2781, 3649, - 3949, 2788, 3647, - 3948, 2798, 3645, - 3945, 2811, 3642, - 3943, 2827, 3638, - 3939, 2847, 3632, - 3933, 2874, 3624, - 3926, 2907, 3613, - 3916, 2947, 3598, - 3903, 2997, 3578, - 3884, 3055, 3548, - 3858, 3123, 3506, - 3821, 3201, 3443, - 3766, 3287, 3342, - 3679, 3382, 3157, - 3530, 3484, 2652, - 3197, 3593, 0, - 0, 3706, 0, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4085, 2895, 3786, - 4085, 2896, 3785, - 4085, 2898, 3785, - 4085, 2900, 3784, - 4084, 2903, 3784, - 4083, 2908, 3783, - 4082, 2913, 3781, - 4081, 2920, 3779, - 4080, 2930, 3777, - 4078, 2942, 3774, - 4075, 2959, 3770, - 4071, 2979, 3764, - 4065, 3006, 3756, - 4058, 3039, 3745, - 4048, 3079, 3730, - 4035, 3129, 3710, - 4017, 3187, 3680, - 3990, 3255, 3638, - 3953, 3333, 3575, - 3898, 3420, 3474, - 3811, 3514, 3289, - 3662, 3616, 2784, - 3329, 3725, 0, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3032, 3916, - 4095, 3035, 3916, - 4095, 3040, 3915, - 4095, 3045, 3913, - 4095, 3052, 3912, - 4095, 3062, 3909, - 4095, 3074, 3906, - 4095, 3091, 3902, - 4095, 3111, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3211, 3862, - 4095, 3261, 3842, - 4095, 3319, 3812, - 4095, 3387, 3770, - 4085, 3465, 3707, - 4030, 3552, 3606, - 3944, 3646, 3421, - 3794, 3748, 2916, - 4095, 3155, 4051, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3167, 4048, - 4095, 3172, 4047, - 4095, 3177, 4045, - 4095, 3184, 4044, - 4095, 3194, 4041, - 4095, 3206, 4038, - 4095, 3223, 4034, - 4095, 3243, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3343, 3994, - 4095, 3393, 3974, - 4095, 3451, 3945, - 4095, 3519, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 193, 352, - 0, 229, 307, - 0, 273, 239, - 0, 326, 129, - 0, 388, 0, - 0, 459, 0, - 0, 540, 0, - 0, 630, 0, - 0, 728, 0, - 0, 833, 0, - 0, 943, 0, - 0, 1058, 0, - 0, 1177, 0, - 0, 1299, 0, - 0, 1423, 0, - 0, 1550, 0, - 0, 1677, 0, - 0, 1806, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 205, 412, - 0, 240, 373, - 0, 283, 315, - 0, 335, 223, - 0, 396, 62, - 0, 466, 0, - 0, 546, 0, - 0, 635, 0, - 0, 732, 0, - 0, 836, 0, - 0, 945, 0, - 0, 1060, 0, - 0, 1178, 0, - 0, 1300, 0, - 0, 1424, 0, - 0, 1550, 0, - 0, 1678, 0, - 0, 1807, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 154, 222, 481, - 58, 255, 448, - 0, 297, 399, - 0, 347, 325, - 0, 407, 201, - 0, 476, 0, - 0, 554, 0, - 0, 641, 0, - 0, 737, 0, - 0, 840, 0, - 0, 949, 0, - 0, 1062, 0, - 0, 1180, 0, - 0, 1302, 0, - 0, 1425, 0, - 0, 1551, 0, - 0, 1679, 0, - 0, 1807, 0, - 0, 1936, 0, - 0, 2066, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 409, 242, 560, - 357, 275, 532, - 276, 315, 492, - 138, 363, 433, - 0, 420, 338, - 0, 488, 170, - 0, 564, 0, - 0, 650, 0, - 0, 744, 0, - 0, 845, 0, - 0, 953, 0, - 0, 1066, 0, - 0, 1183, 0, - 0, 1304, 0, - 0, 1427, 0, - 0, 1552, 0, - 0, 1679, 0, - 0, 1808, 0, - 0, 1937, 0, - 0, 2067, 0, - 0, 2197, 0, - 0, 2328, 0, - 0, 2459, 0, - 0, 2591, 0, - 0, 2722, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 616, 269, 648, - 583, 299, 625, - 535, 337, 593, - 463, 383, 546, - 343, 438, 474, - 109, 503, 355, - 0, 577, 124, - 0, 661, 0, - 0, 753, 0, - 0, 852, 0, - 0, 958, 0, - 0, 1070, 0, - 0, 1186, 0, - 0, 1306, 0, - 0, 1429, 0, - 0, 1554, 0, - 0, 1681, 0, - 0, 1809, 0, - 0, 1938, 0, - 0, 2067, 0, - 0, 2198, 0, - 0, 2328, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 796, 302, 744, - 775, 330, 726, - 744, 366, 700, - 700, 409, 663, - 632, 461, 608, - 523, 523, 523, - 318, 594, 377, - 0, 675, 54, - 0, 764, 0, - 0, 862, 0, - 0, 966, 0, - 0, 1076, 0, - 0, 1191, 0, - 0, 1310, 0, - 0, 1432, 0, - 0, 1556, 0, - 0, 1682, 0, - 0, 1810, 0, - 0, 1938, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 962, 343, 847, - 947, 369, 832, - 926, 401, 812, - 897, 442, 784, - 854, 490, 742, - 790, 549, 680, - 688, 616, 582, - 501, 693, 404, - 0, 780, 0, - 0, 874, 0, - 0, 976, 0, - 0, 1084, 0, - 0, 1197, 0, - 0, 1314, 0, - 0, 1435, 0, - 0, 1559, 0, - 0, 1684, 0, - 0, 1811, 0, - 0, 1940, 0, - 0, 2069, 0, - 0, 2199, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1117, 392, 956, - 1107, 415, 945, - 1092, 445, 929, - 1072, 482, 907, - 1043, 527, 876, - 1002, 581, 831, - 941, 644, 762, - 843, 717, 650, - 667, 799, 439, - 213, 890, 0, - 0, 988, 0, - 0, 1094, 0, - 0, 1205, 0, - 0, 1320, 0, - 0, 1440, 0, - 0, 1562, 0, - 0, 1687, 0, - 0, 1813, 0, - 0, 1941, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1266, 450, 1070, - 1258, 471, 1061, - 1248, 497, 1049, - 1234, 530, 1032, - 1214, 571, 1009, - 1186, 620, 976, - 1146, 678, 927, - 1086, 746, 852, - 992, 824, 728, - 824, 910, 481, - 408, 1005, 0, - 0, 1107, 0, - 0, 1215, 0, - 0, 1328, 0, - 0, 1446, 0, - 0, 1567, 0, - 0, 1690, 0, - 0, 1816, 0, - 0, 1943, 0, - 0, 2072, 0, - 0, 2201, 0, - 0, 2331, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1410, 519, 1188, - 1405, 536, 1182, - 1397, 559, 1172, - 1387, 588, 1160, - 1373, 624, 1142, - 1353, 668, 1117, - 1326, 721, 1082, - 1287, 783, 1030, - 1228, 855, 950, - 1136, 936, 815, - 973, 1026, 532, - 582, 1124, 0, - 0, 1229, 0, - 0, 1339, 0, - 0, 1454, 0, - 0, 1573, 0, - 0, 1695, 0, - 0, 1820, 0, - 0, 1946, 0, - 0, 2074, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1551, 596, 1310, - 1547, 611, 1305, - 1542, 631, 1297, - 1534, 655, 1288, - 1524, 687, 1275, - 1510, 725, 1256, - 1491, 772, 1231, - 1464, 828, 1194, - 1425, 894, 1140, - 1367, 969, 1055, - 1277, 1053, 910, - 1117, 1146, 593, - 743, 1246, 0, - 0, 1353, 0, - 0, 1465, 0, - 0, 1581, 0, - 0, 1702, 0, - 0, 1824, 0, - 0, 1950, 0, - 0, 2076, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2463, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1690, 683, 1434, - 1687, 695, 1430, - 1683, 711, 1424, - 1677, 732, 1417, - 1670, 759, 1407, - 1660, 792, 1394, - 1646, 833, 1375, - 1627, 882, 1348, - 1600, 941, 1310, - 1562, 1009, 1254, - 1505, 1087, 1166, - 1415, 1173, 1013, - 1259, 1268, 663, - 895, 1370, 0, - 0, 1479, 0, - 0, 1592, 0, - 0, 1710, 0, - 0, 1831, 0, - 0, 1954, 0, - 0, 2080, 0, - 0, 2207, 0, - 0, 2336, 0, - 0, 2465, 0, - 0, 2595, 0, - 0, 2726, 0, - 0, 2856, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1826, 777, 1560, - 1824, 788, 1557, - 1821, 801, 1552, - 1817, 818, 1547, - 1812, 840, 1540, - 1805, 868, 1530, - 1795, 903, 1516, - 1781, 945, 1496, - 1762, 997, 1469, - 1736, 1058, 1430, - 1697, 1128, 1372, - 1641, 1208, 1281, - 1552, 1296, 1121, - 1397, 1393, 742, - 1042, 1497, 0, - 0, 1606, 0, - 0, 1721, 0, - 0, 1839, 0, - 0, 1961, 0, - 0, 2085, 0, - 0, 2211, 0, - 0, 2338, 0, - 0, 2467, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1962, 880, 1687, - 1961, 888, 1685, - 1958, 898, 1682, - 1955, 912, 1678, - 1951, 930, 1672, - 1946, 953, 1664, - 1939, 982, 1654, - 1929, 1018, 1640, - 1915, 1062, 1620, - 1897, 1116, 1593, - 1870, 1178, 1553, - 1832, 1250, 1494, - 1776, 1331, 1400, - 1688, 1422, 1235, - 1534, 1520, 831, - 1185, 1624, 0, - 0, 1735, 0, - 0, 1850, 0, - 0, 1969, 0, - 0, 2091, 0, - 0, 2216, 0, - 0, 2342, 0, - 0, 2470, 0, - 0, 2599, 0, - 0, 2728, 0, - 0, 2859, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2097, 988, 1815, - 2096, 994, 1814, - 2094, 1003, 1811, - 2092, 1014, 1808, - 2089, 1028, 1804, - 2085, 1047, 1799, - 2080, 1071, 1791, - 2072, 1100, 1781, - 2063, 1138, 1766, - 2049, 1183, 1746, - 2030, 1237, 1719, - 2004, 1301, 1678, - 1966, 1375, 1618, - 1910, 1457, 1523, - 1822, 1548, 1352, - 1670, 1647, 927, - 1325, 1753, 0, - 0, 1864, 0, - 0, 1980, 0, - 0, 2100, 0, - 0, 2222, 0, - 0, 2347, 0, - 0, 2474, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2231, 1101, 1945, - 2230, 1106, 1944, - 2229, 1113, 1942, - 2227, 1122, 1940, - 2225, 1133, 1936, - 2222, 1148, 1932, - 2218, 1167, 1927, - 2213, 1191, 1919, - 2206, 1222, 1908, - 2196, 1260, 1894, - 2182, 1306, 1874, - 2164, 1362, 1846, - 2137, 1427, 1805, - 2100, 1501, 1744, - 2044, 1585, 1647, - 1956, 1677, 1473, - 1805, 1776, 1031, - 1463, 1883, 0, - 0, 1994, 0, - 0, 2111, 0, - 0, 2231, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2364, 1219, 2075, - 2364, 1223, 2074, - 2363, 1228, 2073, - 2362, 1235, 2071, - 2360, 1244, 2069, - 2358, 1255, 2066, - 2355, 1270, 2061, - 2351, 1290, 2056, - 2346, 1315, 2048, - 2339, 1346, 2037, - 2329, 1385, 2023, - 2315, 1432, 2003, - 2297, 1488, 1974, - 2270, 1553, 1933, - 2233, 1629, 1871, - 2177, 1713, 1773, - 2090, 1806, 1597, - 1939, 1906, 1140, - 1599, 2013, 0, - 0, 2125, 0, - 0, 2242, 0, - 0, 2362, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2498, 1340, 2206, - 2497, 1343, 2205, - 2497, 1347, 2204, - 2496, 1352, 2203, - 2494, 1359, 2201, - 2493, 1368, 2199, - 2491, 1380, 2195, - 2488, 1395, 2191, - 2484, 1415, 2185, - 2478, 1440, 2178, - 2471, 1472, 2167, - 2461, 1511, 2152, - 2448, 1559, 2132, - 2429, 1615, 2103, - 2403, 1682, 2062, - 2366, 1757, 2000, - 2310, 1842, 1901, - 2223, 1936, 1723, - 2073, 2036, 1254, - 1735, 2144, 0, - 0, 2256, 0, - 0, 2373, 0, - 0, 2493, 0, - 0, 2616, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2631, 1463, 2337, - 2630, 1466, 2336, - 2630, 1469, 2335, - 2629, 1473, 2334, - 2628, 1478, 2333, - 2627, 1485, 2331, - 2625, 1494, 2329, - 2623, 1506, 2326, - 2620, 1522, 2322, - 2616, 1542, 2316, - 2611, 1567, 2308, - 2604, 1599, 2297, - 2594, 1639, 2283, - 2581, 1687, 2262, - 2562, 1744, 2233, - 2536, 1811, 2192, - 2498, 1887, 2130, - 2443, 1972, 2030, - 2356, 2066, 1850, - 2206, 2167, 1373, - 1869, 2275, 0, - 0, 2387, 0, - 0, 2504, 0, - 0, 2625, 0, - 0, 2748, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2763, 1589, 2468, - 2763, 1591, 2467, - 2763, 1593, 2467, - 2762, 1596, 2466, - 2761, 1600, 2465, - 2761, 1605, 2464, - 2759, 1613, 2462, - 2758, 1622, 2460, - 2756, 1634, 2457, - 2753, 1650, 2452, - 2749, 1670, 2447, - 2743, 1696, 2439, - 2736, 1728, 2428, - 2727, 1768, 2413, - 2713, 1816, 2393, - 2694, 1874, 2364, - 2668, 1941, 2322, - 2631, 2017, 2260, - 2575, 2103, 2160, - 2489, 2197, 1978, - 2339, 2298, 1494, - 2003, 2406, 0, - 0, 2519, 0, - 0, 2636, 0, - 0, 2757, 0, - 0, 2880, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1716, 2599, - 2896, 1717, 2599, - 2895, 1719, 2599, - 2895, 1722, 2598, - 2894, 1725, 2597, - 2894, 1729, 2596, - 2893, 1734, 2595, - 2892, 1741, 2593, - 2890, 1751, 2591, - 2888, 1763, 2588, - 2885, 1779, 2583, - 2881, 1799, 2578, - 2876, 1825, 2570, - 2869, 1857, 2559, - 2859, 1897, 2544, - 2845, 1946, 2524, - 2827, 2004, 2495, - 2801, 2071, 2453, - 2763, 2148, 2390, - 2708, 2234, 2290, - 2621, 2328, 2108, - 2472, 2430, 1618, - 2136, 2537, 0, - 0, 2650, 0, - 0, 2768, 0, - 0, 2888, 0, - 0, 3012, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3028, 1845, 2731, - 3028, 1846, 2731, - 3028, 1847, 2730, - 3028, 1849, 2730, - 3027, 1851, 2729, - 3027, 1854, 2729, - 3026, 1858, 2728, - 3025, 1864, 2726, - 3024, 1871, 2725, - 3022, 1880, 2722, - 3020, 1892, 2719, - 3017, 1908, 2715, - 3013, 1929, 2709, - 3008, 1955, 2701, - 3001, 1987, 2690, - 2991, 2028, 2676, - 2978, 2076, 2655, - 2959, 2134, 2626, - 2933, 2202, 2584, - 2896, 2279, 2521, - 2840, 2365, 2421, - 2754, 2459, 2238, - 2604, 2561, 1744, - 2269, 2669, 0, - 0, 2782, 0, - 0, 2900, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3161, 1974, 2863, - 3161, 1975, 2862, - 3160, 1976, 2862, - 3160, 1977, 2862, - 3160, 1979, 2862, - 3160, 1981, 2861, - 3159, 1984, 2860, - 3158, 1988, 2859, - 3157, 1994, 2858, - 3156, 2001, 2856, - 3155, 2010, 2854, - 3152, 2023, 2851, - 3150, 2039, 2846, - 3146, 2059, 2841, - 3140, 2085, 2833, - 3133, 2118, 2822, - 3123, 2158, 2807, - 3110, 2207, 2787, - 3091, 2266, 2758, - 3065, 2333, 2716, - 3028, 2410, 2653, - 2973, 2497, 2552, - 2886, 2591, 2368, - 2737, 2693, 1872, - 2402, 2801, 0, - 0, 2914, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3293, 2104, 2994, - 3293, 2104, 2994, - 3293, 2105, 2994, - 3293, 2106, 2994, - 3292, 2107, 2994, - 3292, 2109, 2993, - 3292, 2112, 2993, - 3291, 2115, 2992, - 3291, 2119, 2991, - 3290, 2124, 2990, - 3288, 2132, 2988, - 3287, 2141, 2986, - 3285, 2153, 2982, - 3282, 2169, 2978, - 3278, 2190, 2972, - 3273, 2216, 2964, - 3265, 2249, 2954, - 3256, 2290, 2939, - 3242, 2339, 2918, - 3224, 2397, 2889, - 3198, 2465, 2847, - 3160, 2542, 2784, - 3105, 2628, 2683, - 3018, 2723, 2499, - 2869, 2825, 2000, - 2535, 2933, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3661, 0, - 3425, 2234, 3126, - 3425, 2235, 3126, - 3425, 2235, 3126, - 3425, 2236, 3126, - 3425, 2237, 3126, - 3425, 2238, 3125, - 3424, 2240, 3125, - 3424, 2243, 3124, - 3423, 2246, 3124, - 3423, 2250, 3123, - 3422, 2255, 3121, - 3421, 2263, 3120, - 3419, 2272, 3117, - 3417, 2284, 3114, - 3414, 2301, 3110, - 3410, 2321, 3104, - 3405, 2347, 3096, - 3398, 2380, 3085, - 3388, 2421, 3071, - 3374, 2470, 3050, - 3356, 2528, 3021, - 3330, 2596, 2979, - 3292, 2674, 2916, - 3237, 2760, 2815, - 3151, 2855, 2631, - 3001, 2956, 2130, - 2667, 3065, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2365, 3258, - 3557, 2366, 3258, - 3557, 2366, 3258, - 3557, 2367, 3258, - 3557, 2367, 3258, - 3557, 2368, 3258, - 3557, 2370, 3257, - 3556, 2371, 3257, - 3556, 2374, 3256, - 3556, 2377, 3256, - 3555, 2381, 3255, - 3554, 2387, 3253, - 3553, 2394, 3252, - 3551, 2403, 3249, - 3549, 2416, 3246, - 3546, 2432, 3242, - 3542, 2453, 3236, - 3537, 2479, 3228, - 3530, 2512, 3217, - 3520, 2552, 3202, - 3507, 2602, 3182, - 3488, 2660, 3153, - 3462, 2728, 3111, - 3425, 2805, 3047, - 3369, 2892, 2946, - 3283, 2986, 2762, - 3134, 3088, 2260, - 2800, 3197, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3690, 2497, 3390, - 3690, 2497, 3390, - 3689, 2497, 3390, - 3689, 2498, 3390, - 3689, 2498, 3390, - 3689, 2499, 3390, - 3689, 2500, 3390, - 3689, 2501, 3389, - 3689, 2503, 3389, - 3688, 2505, 3388, - 3688, 2508, 3388, - 3687, 2513, 3387, - 3686, 2518, 3385, - 3685, 2525, 3384, - 3683, 2535, 3381, - 3681, 2547, 3378, - 3678, 2563, 3374, - 3674, 2584, 3368, - 3669, 2610, 3360, - 3662, 2643, 3349, - 3652, 2684, 3334, - 3639, 2733, 3314, - 3620, 2792, 3285, - 3594, 2860, 3242, - 3557, 2937, 3179, - 3501, 3024, 3078, - 3415, 3118, 2894, - 3266, 3220, 2391, - 2932, 3329, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2628, 3522, - 3822, 2629, 3522, - 3822, 2629, 3522, - 3821, 2630, 3522, - 3821, 2630, 3522, - 3821, 2631, 3522, - 3821, 2633, 3521, - 3821, 2635, 3521, - 3820, 2637, 3520, - 3820, 2640, 3520, - 3819, 2644, 3519, - 3818, 2650, 3517, - 3817, 2657, 3515, - 3815, 2667, 3513, - 3813, 2679, 3510, - 3810, 2695, 3506, - 3806, 2716, 3500, - 3801, 2742, 3492, - 3794, 2775, 3481, - 3784, 2816, 3466, - 3771, 2865, 3446, - 3752, 2924, 3416, - 3726, 2992, 3374, - 3689, 3069, 3311, - 3634, 3156, 3210, - 3547, 3250, 3025, - 3398, 3352, 2521, - 3064, 3461, 0, - 0, 3574, 0, - 0, 3692, 0, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3954, 2761, 3654, - 3953, 2762, 3654, - 3953, 2763, 3654, - 3953, 2764, 3653, - 3953, 2766, 3653, - 3952, 2769, 3652, - 3952, 2772, 3652, - 3951, 2776, 3651, - 3950, 2781, 3649, - 3949, 2789, 3647, - 3948, 2798, 3645, - 3945, 2811, 3642, - 3942, 2827, 3638, - 3939, 2848, 3632, - 3933, 2874, 3624, - 3926, 2907, 3613, - 3916, 2948, 3598, - 3903, 2997, 3578, - 3884, 3055, 3548, - 3858, 3123, 3506, - 3821, 3201, 3443, - 3766, 3288, 3342, - 3679, 3382, 3157, - 3530, 3484, 2653, - 3197, 3593, 0, - 0, 3706, 0, - 4086, 2891, 3786, - 4086, 2891, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4085, 2895, 3786, - 4085, 2896, 3785, - 4085, 2898, 3785, - 4085, 2900, 3784, - 4084, 2904, 3784, - 4083, 2908, 3783, - 4082, 2913, 3781, - 4081, 2921, 3780, - 4080, 2930, 3777, - 4078, 2943, 3774, - 4075, 2959, 3770, - 4071, 2980, 3764, - 4065, 3006, 3756, - 4058, 3039, 3745, - 4048, 3080, 3730, - 4035, 3129, 3710, - 4017, 3187, 3680, - 3990, 3255, 3638, - 3953, 3333, 3575, - 3898, 3420, 3474, - 3811, 3514, 3289, - 3662, 3616, 2784, - 3329, 3725, 0, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3032, 3916, - 4095, 3036, 3916, - 4095, 3040, 3915, - 4095, 3045, 3913, - 4095, 3052, 3912, - 4095, 3062, 3909, - 4095, 3075, 3906, - 4095, 3091, 3902, - 4095, 3111, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3212, 3862, - 4095, 3261, 3842, - 4095, 3319, 3813, - 4095, 3387, 3770, - 4085, 3465, 3707, - 4030, 3552, 3606, - 3944, 3646, 3421, - 3794, 3748, 2916, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3155, 4050, - 4095, 3155, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3167, 4048, - 4095, 3172, 4047, - 4095, 3177, 4045, - 4095, 3184, 4044, - 4095, 3194, 4041, - 4095, 3206, 4038, - 4095, 3223, 4034, - 4095, 3243, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3344, 3994, - 4095, 3393, 3974, - 4095, 3451, 3945, - 4095, 3520, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 286, 468, - 0, 316, 433, - 0, 352, 383, - 0, 397, 305, - 0, 450, 175, - 0, 514, 0, - 0, 586, 0, - 0, 668, 0, - 0, 759, 0, - 0, 857, 0, - 0, 962, 0, - 0, 1073, 0, - 0, 1189, 0, - 0, 1308, 0, - 0, 1430, 0, - 0, 1555, 0, - 0, 1681, 0, - 0, 1809, 0, - 0, 1938, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 296, 515, - 0, 325, 484, - 0, 361, 439, - 0, 405, 371, - 0, 458, 261, - 0, 520, 54, - 0, 592, 0, - 0, 673, 0, - 0, 762, 0, - 0, 860, 0, - 0, 965, 0, - 0, 1075, 0, - 0, 1190, 0, - 0, 1309, 0, - 0, 1431, 0, - 0, 1556, 0, - 0, 1682, 0, - 0, 1810, 0, - 0, 1938, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 38, 310, 571, - 0, 338, 544, - 0, 372, 505, - 0, 415, 447, - 0, 467, 355, - 0, 528, 195, - 0, 599, 0, - 0, 678, 0, - 0, 767, 0, - 0, 864, 0, - 0, 968, 0, - 0, 1077, 0, - 0, 1192, 0, - 0, 1311, 0, - 0, 1432, 0, - 0, 1556, 0, - 0, 1682, 0, - 0, 1810, 0, - 0, 1939, 0, - 0, 2068, 0, - 0, 2198, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 347, 327, 637, - 286, 354, 613, - 190, 387, 580, - 17, 429, 531, - 0, 479, 457, - 0, 539, 333, - 0, 608, 87, - 0, 686, 0, - 0, 774, 0, - 0, 869, 0, - 0, 972, 0, - 0, 1081, 0, - 0, 1194, 0, - 0, 1312, 0, - 0, 1434, 0, - 0, 1558, 0, - 0, 1683, 0, - 0, 1811, 0, - 0, 1939, 0, - 0, 2069, 0, - 0, 2199, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 577, 349, 712, - 541, 375, 692, - 489, 407, 664, - 408, 447, 624, - 270, 495, 565, - 0, 553, 470, - 0, 620, 302, - 0, 696, 0, - 0, 782, 0, - 0, 876, 0, - 0, 977, 0, - 0, 1085, 0, - 0, 1198, 0, - 0, 1315, 0, - 0, 1436, 0, - 0, 1559, 0, - 0, 1684, 0, - 0, 1812, 0, - 0, 1940, 0, - 0, 2069, 0, - 0, 2199, 0, - 0, 2329, 0, - 0, 2460, 0, - 0, 2591, 0, - 0, 2723, 0, - 0, 2854, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 771, 377, 796, - 748, 401, 780, - 715, 431, 757, - 668, 469, 725, - 595, 515, 678, - 475, 571, 606, - 241, 635, 487, - 0, 709, 256, - 0, 793, 0, - 0, 885, 0, - 0, 984, 0, - 0, 1091, 0, - 0, 1202, 0, - 0, 1318, 0, - 0, 1438, 0, - 0, 1561, 0, - 0, 1686, 0, - 0, 1813, 0, - 0, 1941, 0, - 0, 2070, 0, - 0, 2199, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 944, 411, 889, - 928, 434, 876, - 907, 462, 858, - 876, 498, 832, - 832, 541, 795, - 764, 594, 740, - 655, 655, 655, - 450, 726, 509, - 0, 807, 186, - 0, 896, 0, - 0, 994, 0, - 0, 1098, 0, - 0, 1208, 0, - 0, 1323, 0, - 0, 1442, 0, - 0, 1564, 0, - 0, 1688, 0, - 0, 1814, 0, - 0, 1942, 0, - 0, 2071, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1105, 454, 990, - 1094, 475, 979, - 1079, 501, 965, - 1058, 533, 944, - 1029, 574, 916, - 986, 623, 874, - 922, 681, 813, - 820, 748, 714, - 633, 825, 536, - 113, 912, 73, - 0, 1006, 0, - 0, 1108, 0, - 0, 1216, 0, - 0, 1329, 0, - 0, 1446, 0, - 0, 1567, 0, - 0, 1691, 0, - 0, 1816, 0, - 0, 1943, 0, - 0, 2072, 0, - 0, 2201, 0, - 0, 2331, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1257, 506, 1097, - 1249, 524, 1088, - 1239, 547, 1077, - 1224, 577, 1061, - 1204, 614, 1039, - 1175, 659, 1008, - 1134, 713, 963, - 1073, 776, 894, - 975, 849, 783, - 799, 931, 571, - 345, 1022, 0, - 0, 1121, 0, - 0, 1226, 0, - 0, 1337, 0, - 0, 1452, 0, - 0, 1572, 0, - 0, 1694, 0, - 0, 1819, 0, - 0, 1945, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1404, 566, 1209, - 1398, 582, 1202, - 1390, 603, 1193, - 1380, 629, 1181, - 1366, 662, 1165, - 1346, 703, 1141, - 1318, 752, 1108, - 1278, 811, 1059, - 1218, 878, 984, - 1124, 956, 860, - 956, 1042, 613, - 540, 1137, 0, - 0, 1239, 0, - 0, 1347, 0, - 0, 1461, 0, - 0, 1578, 0, - 0, 1699, 0, - 0, 1823, 0, - 0, 1948, 0, - 0, 2075, 0, - 0, 2204, 0, - 0, 2333, 0, - 0, 2463, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1546, 637, 1325, - 1542, 651, 1320, - 1537, 668, 1314, - 1529, 691, 1304, - 1519, 720, 1292, - 1505, 756, 1274, - 1486, 800, 1249, - 1458, 853, 1214, - 1419, 915, 1162, - 1360, 987, 1082, - 1268, 1068, 947, - 1105, 1158, 665, - 714, 1256, 0, - 0, 1361, 0, - 0, 1471, 0, - 0, 1586, 0, - 0, 1705, 0, - 0, 1827, 0, - 0, 1952, 0, - 0, 2078, 0, - 0, 2206, 0, - 0, 2335, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1686, 717, 1446, - 1683, 728, 1442, - 1679, 743, 1437, - 1674, 763, 1430, - 1666, 787, 1420, - 1656, 819, 1407, - 1642, 857, 1388, - 1623, 904, 1363, - 1596, 960, 1326, - 1557, 1026, 1272, - 1500, 1101, 1187, - 1409, 1185, 1042, - 1250, 1278, 725, - 875, 1378, 0, - 0, 1485, 0, - 0, 1597, 0, - 0, 1713, 0, - 0, 1834, 0, - 0, 1957, 0, - 0, 2082, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1824, 805, 1569, - 1822, 815, 1566, - 1819, 827, 1562, - 1815, 843, 1556, - 1809, 864, 1549, - 1802, 891, 1539, - 1792, 924, 1526, - 1778, 965, 1507, - 1759, 1014, 1480, - 1732, 1073, 1442, - 1694, 1141, 1386, - 1637, 1219, 1298, - 1547, 1305, 1145, - 1391, 1400, 795, - 1028, 1502, 0, - 0, 1611, 0, - 0, 1724, 0, - 0, 1842, 0, - 0, 1963, 0, - 0, 2087, 0, - 0, 2212, 0, - 0, 2339, 0, - 0, 2468, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1960, 902, 1694, - 1959, 910, 1692, - 1956, 920, 1689, - 1953, 933, 1685, - 1949, 950, 1679, - 1944, 972, 1672, - 1937, 1000, 1662, - 1927, 1035, 1648, - 1913, 1077, 1628, - 1894, 1129, 1601, - 1868, 1190, 1562, - 1830, 1260, 1505, - 1773, 1340, 1413, - 1684, 1428, 1253, - 1530, 1525, 875, - 1174, 1629, 0, - 0, 1738, 0, - 0, 1853, 0, - 0, 1971, 0, - 0, 2093, 0, - 0, 2217, 0, - 0, 2343, 0, - 0, 2471, 0, - 0, 2599, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2095, 1005, 1821, - 2094, 1012, 1819, - 2093, 1020, 1817, - 2090, 1030, 1814, - 2087, 1044, 1810, - 2084, 1062, 1804, - 2078, 1085, 1797, - 2071, 1114, 1786, - 2061, 1150, 1772, - 2047, 1195, 1753, - 2029, 1248, 1725, - 2002, 1310, 1685, - 1964, 1382, 1626, - 1908, 1464, 1533, - 1820, 1554, 1367, - 1667, 1652, 963, - 1317, 1756, 0, - 0, 1867, 0, - 0, 1982, 0, - 0, 2101, 0, - 0, 2223, 0, - 0, 2348, 0, - 0, 2474, 0, - 0, 2602, 0, - 0, 2731, 0, - 0, 2860, 0, - 0, 2991, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2230, 1115, 1949, - 2229, 1120, 1948, - 2228, 1126, 1946, - 2226, 1135, 1944, - 2224, 1146, 1941, - 2221, 1160, 1936, - 2217, 1179, 1931, - 2212, 1203, 1923, - 2205, 1233, 1913, - 2195, 1270, 1898, - 2181, 1315, 1879, - 2162, 1369, 1851, - 2136, 1433, 1810, - 2098, 1507, 1750, - 2042, 1589, 1655, - 1955, 1681, 1484, - 1802, 1780, 1059, - 1457, 1885, 0, - 0, 1996, 0, - 0, 2112, 0, - 0, 2232, 0, - 0, 2354, 0, - 0, 2479, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2364, 1229, 2078, - 2363, 1233, 2077, - 2362, 1238, 2076, - 2361, 1245, 2074, - 2359, 1254, 2072, - 2357, 1265, 2069, - 2354, 1280, 2064, - 2350, 1299, 2059, - 2345, 1323, 2051, - 2338, 1354, 2041, - 2328, 1392, 2026, - 2314, 1438, 2006, - 2296, 1494, 1978, - 2269, 1559, 1937, - 2232, 1633, 1876, - 2176, 1717, 1779, - 2089, 1809, 1606, - 1937, 1908, 1163, - 1595, 2015, 0, - 0, 2127, 0, - 0, 2243, 0, - 0, 2363, 0, - 0, 2486, 0, - 0, 2611, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2497, 1348, 2208, - 2497, 1351, 2207, - 2496, 1355, 2206, - 2495, 1360, 2205, - 2494, 1367, 2203, - 2492, 1376, 2201, - 2490, 1387, 2198, - 2487, 1402, 2193, - 2483, 1422, 2188, - 2478, 1447, 2180, - 2471, 1478, 2169, - 2461, 1517, 2155, - 2447, 1564, 2135, - 2429, 1620, 2106, - 2402, 1686, 2065, - 2365, 1761, 2004, - 2309, 1845, 1906, - 2222, 1938, 1729, - 2071, 2038, 1272, - 1731, 2145, 0, - 0, 2257, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2630, 1470, 2338, - 2630, 1472, 2338, - 2629, 1475, 2337, - 2629, 1479, 2336, - 2628, 1484, 2335, - 2627, 1491, 2333, - 2625, 1500, 2331, - 2623, 1512, 2327, - 2620, 1527, 2323, - 2616, 1547, 2317, - 2611, 1572, 2310, - 2603, 1604, 2299, - 2594, 1643, 2284, - 2580, 1691, 2264, - 2561, 1748, 2236, - 2535, 1814, 2194, - 2498, 1890, 2132, - 2442, 1974, 2033, - 2355, 2068, 1855, - 2205, 2168, 1386, - 1867, 2276, 0, - 0, 2388, 0, - 0, 2505, 0, - 0, 2625, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2763, 1594, 2469, - 2763, 1595, 2469, - 2762, 1598, 2468, - 2762, 1601, 2467, - 2761, 1605, 2466, - 2760, 1610, 2465, - 2759, 1617, 2463, - 2757, 1626, 2461, - 2755, 1638, 2458, - 2752, 1654, 2454, - 2748, 1674, 2448, - 2743, 1699, 2440, - 2736, 1731, 2429, - 2726, 1771, 2415, - 2713, 1819, 2394, - 2694, 1876, 2366, - 2668, 1943, 2324, - 2630, 2019, 2262, - 2575, 2104, 2162, - 2488, 2198, 1982, - 2338, 2299, 1505, - 2001, 2407, 0, - 0, 2519, 0, - 0, 2637, 0, - 0, 2757, 0, - 0, 2880, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2896, 1720, 2600, - 2895, 1721, 2600, - 2895, 1723, 2600, - 2895, 1725, 2599, - 2894, 1728, 2598, - 2894, 1732, 2597, - 2893, 1738, 2596, - 2891, 1745, 2594, - 2890, 1754, 2592, - 2888, 1766, 2589, - 2885, 1782, 2584, - 2881, 1802, 2579, - 2876, 1828, 2571, - 2868, 1860, 2560, - 2859, 1900, 2545, - 2845, 1948, 2525, - 2827, 2006, 2496, - 2800, 2073, 2454, - 2763, 2149, 2392, - 2708, 2235, 2292, - 2621, 2329, 2111, - 2471, 2430, 1626, - 2135, 2538, 0, - 0, 2651, 0, - 0, 2768, 0, - 0, 2889, 0, - 0, 3012, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3028, 1847, 2732, - 3028, 1848, 2731, - 3028, 1850, 2731, - 3027, 1851, 2731, - 3027, 1854, 2730, - 3027, 1857, 2729, - 3026, 1861, 2728, - 3025, 1866, 2727, - 3024, 1873, 2725, - 3022, 1883, 2723, - 3020, 1895, 2720, - 3017, 1911, 2716, - 3013, 1931, 2710, - 3008, 1957, 2702, - 3001, 1989, 2691, - 2991, 2030, 2676, - 2978, 2078, 2656, - 2959, 2136, 2627, - 2933, 2203, 2585, - 2895, 2280, 2522, - 2840, 2366, 2422, - 2753, 2460, 2240, - 2604, 2562, 1750, - 2268, 2670, 0, - 0, 2783, 0, - 0, 2900, 0, - 0, 3021, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 3160, 1976, 2863, - 3160, 1977, 2863, - 3160, 1978, 2863, - 3160, 1979, 2862, - 3160, 1981, 2862, - 3159, 1983, 2862, - 3159, 1986, 2861, - 3158, 1990, 2860, - 3157, 1996, 2858, - 3156, 2003, 2857, - 3154, 2012, 2854, - 3152, 2025, 2851, - 3149, 2040, 2847, - 3146, 2061, 2841, - 3140, 2087, 2833, - 3133, 2120, 2822, - 3123, 2160, 2808, - 3110, 2209, 2787, - 3091, 2267, 2758, - 3065, 2334, 2716, - 3028, 2411, 2653, - 2972, 2497, 2553, - 2886, 2592, 2370, - 2736, 2693, 1876, - 2401, 2801, 0, - 0, 2914, 0, - 0, 3032, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3529, 0, - 0, 3657, 0, - 3293, 2105, 2995, - 3293, 2106, 2995, - 3293, 2107, 2995, - 3292, 2108, 2994, - 3292, 2109, 2994, - 3292, 2111, 2994, - 3292, 2113, 2993, - 3291, 2116, 2992, - 3290, 2120, 2991, - 3290, 2126, 2990, - 3288, 2133, 2988, - 3287, 2142, 2986, - 3285, 2155, 2983, - 3282, 2171, 2978, - 3278, 2191, 2973, - 3272, 2217, 2965, - 3265, 2250, 2954, - 3256, 2291, 2939, - 3242, 2339, 2919, - 3224, 2398, 2890, - 3197, 2465, 2848, - 3160, 2542, 2785, - 3105, 2629, 2684, - 3018, 2723, 2500, - 2869, 2825, 2004, - 2534, 2933, 0, - 0, 3046, 0, - 0, 3164, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3661, 0, - 3425, 2236, 3127, - 3425, 2236, 3127, - 3425, 2237, 3126, - 3425, 2237, 3126, - 3425, 2238, 3126, - 3424, 2240, 3126, - 3424, 2241, 3125, - 3424, 2244, 3125, - 3423, 2247, 3124, - 3423, 2251, 3123, - 3422, 2256, 3122, - 3421, 2264, 3120, - 3419, 2273, 3118, - 3417, 2286, 3114, - 3414, 2302, 3110, - 3410, 2322, 3104, - 3405, 2348, 3096, - 3397, 2381, 3086, - 3388, 2422, 3071, - 3374, 2471, 3050, - 3356, 2529, 3021, - 3330, 2597, 2979, - 3292, 2674, 2916, - 3237, 2760, 2815, - 3150, 2855, 2631, - 3001, 2957, 2132, - 2667, 3065, 0, - 0, 3178, 0, - 0, 3296, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3557, 2366, 3259, - 3557, 2367, 3258, - 3557, 2367, 3258, - 3557, 2367, 3258, - 3557, 2368, 3258, - 3557, 2369, 3258, - 3557, 2371, 3258, - 3556, 2372, 3257, - 3556, 2375, 3257, - 3555, 2378, 3256, - 3555, 2382, 3255, - 3554, 2387, 3254, - 3553, 2395, 3252, - 3551, 2404, 3249, - 3549, 2417, 3246, - 3546, 2433, 3242, - 3542, 2453, 3236, - 3537, 2480, 3228, - 3530, 2512, 3217, - 3520, 2553, 3203, - 3506, 2602, 3182, - 3488, 2660, 3153, - 3462, 2728, 3111, - 3424, 2806, 3048, - 3369, 2892, 2947, - 3283, 2987, 2763, - 3133, 3089, 2262, - 2799, 3197, 0, - 0, 3310, 0, - 0, 3428, 0, - 0, 3548, 0, - 0, 3672, 0, - 3689, 2497, 3390, - 3689, 2497, 3390, - 3689, 2498, 3390, - 3689, 2498, 3390, - 3689, 2499, 3390, - 3689, 2499, 3390, - 3689, 2500, 3390, - 3689, 2502, 3389, - 3688, 2504, 3389, - 3688, 2506, 3388, - 3688, 2509, 3388, - 3687, 2513, 3387, - 3686, 2519, 3385, - 3685, 2526, 3384, - 3683, 2535, 3381, - 3681, 2548, 3378, - 3678, 2564, 3374, - 3674, 2585, 3368, - 3669, 2611, 3360, - 3662, 2644, 3349, - 3652, 2684, 3334, - 3639, 2734, 3314, - 3620, 2792, 3285, - 3594, 2860, 3243, - 3557, 2937, 3179, - 3501, 3024, 3078, - 3415, 3119, 2894, - 3266, 3220, 2392, - 2932, 3329, 0, - 0, 3442, 0, - 0, 3560, 0, - 0, 3680, 0, - 3822, 2628, 3522, - 3822, 2629, 3522, - 3822, 2629, 3522, - 3822, 2629, 3522, - 3821, 2630, 3522, - 3821, 2630, 3522, - 3821, 2631, 3522, - 3821, 2632, 3522, - 3821, 2633, 3521, - 3821, 2635, 3521, - 3820, 2637, 3520, - 3820, 2641, 3520, - 3819, 2645, 3519, - 3818, 2650, 3517, - 3817, 2657, 3516, - 3815, 2667, 3513, - 3813, 2679, 3510, - 3810, 2696, 3506, - 3806, 2716, 3500, - 3801, 2743, 3492, - 3794, 2775, 3481, - 3784, 2816, 3466, - 3771, 2865, 3446, - 3752, 2924, 3417, - 3726, 2992, 3375, - 3689, 3069, 3311, - 3633, 3156, 3210, - 3547, 3250, 3026, - 3398, 3352, 2523, - 3064, 3461, 0, - 0, 3574, 0, - 0, 3692, 0, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2760, 3654, - 3954, 2761, 3654, - 3954, 2761, 3654, - 3954, 2762, 3654, - 3953, 2763, 3654, - 3953, 2764, 3654, - 3953, 2765, 3653, - 3953, 2767, 3653, - 3952, 2769, 3652, - 3952, 2772, 3652, - 3951, 2776, 3651, - 3950, 2782, 3649, - 3949, 2789, 3648, - 3948, 2799, 3645, - 3945, 2811, 3642, - 3942, 2827, 3638, - 3939, 2848, 3632, - 3933, 2874, 3624, - 3926, 2907, 3613, - 3916, 2948, 3598, - 3903, 2997, 3578, - 3884, 3056, 3549, - 3858, 3124, 3506, - 3821, 3201, 3443, - 3766, 3288, 3342, - 3679, 3382, 3157, - 3530, 3484, 2654, - 3196, 3593, 0, - 0, 3706, 0, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4086, 2894, 3786, - 4085, 2895, 3786, - 4085, 2897, 3785, - 4085, 2898, 3785, - 4085, 2901, 3784, - 4084, 2904, 3784, - 4083, 2908, 3783, - 4082, 2914, 3781, - 4081, 2921, 3780, - 4080, 2930, 3777, - 4077, 2943, 3774, - 4075, 2959, 3770, - 4071, 2980, 3764, - 4065, 3006, 3756, - 4058, 3039, 3745, - 4048, 3080, 3730, - 4035, 3129, 3710, - 4017, 3188, 3681, - 3990, 3256, 3638, - 3953, 3333, 3575, - 3898, 3420, 3474, - 3811, 3514, 3289, - 3662, 3616, 2785, - 3329, 3725, 0, - 4095, 3023, 3919, - 4095, 3023, 3918, - 4095, 3023, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3917, - 4095, 3030, 3917, - 4095, 3033, 3916, - 4095, 3036, 3916, - 4095, 3040, 3915, - 4095, 3045, 3913, - 4095, 3053, 3912, - 4095, 3062, 3909, - 4095, 3075, 3906, - 4095, 3091, 3902, - 4095, 3112, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3212, 3862, - 4095, 3261, 3842, - 4095, 3319, 3813, - 4095, 3388, 3770, - 4085, 3465, 3707, - 4030, 3552, 3606, - 3944, 3646, 3421, - 3794, 3748, 2916, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4049, - 4095, 3162, 4049, - 4095, 3164, 4048, - 4095, 3168, 4048, - 4095, 3172, 4047, - 4095, 3177, 4045, - 4095, 3185, 4044, - 4095, 3194, 4041, - 4095, 3207, 4038, - 4095, 3223, 4034, - 4095, 3244, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3344, 3994, - 4095, 3393, 3974, - 4095, 3451, 3945, - 4095, 3520, 3902, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3778, 3553, - 0, 387, 587, - 0, 410, 561, - 0, 440, 523, - 0, 477, 468, - 0, 523, 381, - 0, 577, 231, - 0, 641, 0, - 0, 714, 0, - 0, 797, 0, - 0, 888, 0, - 0, 987, 0, - 0, 1093, 0, - 0, 1204, 0, - 0, 1320, 0, - 0, 1439, 0, - 0, 1562, 0, - 0, 1687, 0, - 0, 1813, 0, - 0, 1941, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 395, 624, - 0, 418, 600, - 0, 448, 565, - 0, 484, 515, - 0, 529, 437, - 0, 583, 307, - 0, 646, 42, - 0, 718, 0, - 0, 800, 0, - 0, 891, 0, - 0, 989, 0, - 0, 1094, 0, - 0, 1205, 0, - 0, 1321, 0, - 0, 1440, 0, - 0, 1562, 0, - 0, 1687, 0, - 0, 1813, 0, - 0, 1941, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 406, 669, - 0, 428, 647, - 0, 457, 616, - 0, 493, 571, - 0, 537, 503, - 0, 590, 393, - 0, 652, 186, - 0, 724, 0, - 0, 805, 0, - 0, 894, 0, - 0, 992, 0, - 0, 1097, 0, - 0, 1207, 0, - 0, 1322, 0, - 0, 1441, 0, - 0, 1563, 0, - 0, 1688, 0, - 0, 1814, 0, - 0, 1942, 0, - 0, 2070, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 247, 420, 722, - 170, 442, 703, - 41, 470, 676, - 0, 505, 637, - 0, 547, 579, - 0, 599, 487, - 0, 660, 327, - 0, 731, 0, - 0, 811, 0, - 0, 899, 0, - 0, 996, 0, - 0, 1100, 0, - 0, 1210, 0, - 0, 1324, 0, - 0, 1443, 0, - 0, 1564, 0, - 0, 1688, 0, - 0, 1815, 0, - 0, 1942, 0, - 0, 2071, 0, - 0, 2200, 0, - 0, 2330, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2986, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 519, 438, 786, - 479, 459, 769, - 418, 486, 745, - 322, 520, 712, - 149, 561, 663, - 0, 611, 589, - 0, 671, 465, - 0, 740, 219, - 0, 818, 0, - 0, 906, 0, - 0, 1001, 0, - 0, 1104, 0, - 0, 1213, 0, - 0, 1327, 0, - 0, 1445, 0, - 0, 1566, 0, - 0, 1690, 0, - 0, 1815, 0, - 0, 1943, 0, - 0, 2071, 0, - 0, 2201, 0, - 0, 2331, 0, - 0, 2461, 0, - 0, 2592, 0, - 0, 2723, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 734, 461, 858, - 709, 481, 844, - 673, 507, 824, - 621, 539, 797, - 540, 579, 756, - 402, 627, 697, - 110, 685, 602, - 0, 752, 434, - 0, 828, 18, - 0, 914, 0, - 0, 1008, 0, - 0, 1109, 0, - 0, 1217, 0, - 0, 1330, 0, - 0, 1447, 0, - 0, 1568, 0, - 0, 1691, 0, - 0, 1817, 0, - 0, 1944, 0, - 0, 2072, 0, - 0, 2201, 0, - 0, 2331, 0, - 0, 2462, 0, - 0, 2592, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 919, 490, 940, - 903, 509, 929, - 880, 533, 912, - 847, 563, 889, - 800, 601, 857, - 727, 647, 810, - 607, 703, 738, - 373, 767, 619, - 0, 842, 388, - 0, 925, 0, - 0, 1017, 0, - 0, 1116, 0, - 0, 1223, 0, - 0, 1334, 0, - 0, 1451, 0, - 0, 1570, 0, - 0, 1693, 0, - 0, 1818, 0, - 0, 1945, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1087, 526, 1031, - 1076, 544, 1021, - 1061, 566, 1008, - 1039, 594, 990, - 1008, 630, 964, - 964, 673, 927, - 896, 726, 872, - 787, 787, 787, - 582, 859, 641, - 0, 939, 318, - 0, 1029, 0, - 0, 1126, 0, - 0, 1230, 0, - 0, 1340, 0, - 0, 1455, 0, - 0, 1574, 0, - 0, 1696, 0, - 0, 1820, 0, - 0, 1946, 0, - 0, 2074, 0, - 0, 2203, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1245, 570, 1130, - 1237, 586, 1122, - 1226, 607, 1111, - 1211, 633, 1097, - 1190, 665, 1076, - 1161, 706, 1048, - 1118, 755, 1006, - 1055, 813, 945, - 952, 880, 846, - 765, 958, 669, - 245, 1044, 205, - 0, 1138, 0, - 0, 1240, 0, - 0, 1348, 0, - 0, 1461, 0, - 0, 1578, 0, - 0, 1699, 0, - 0, 1823, 0, - 0, 1948, 0, - 0, 2075, 0, - 0, 2204, 0, - 0, 2333, 0, - 0, 2463, 0, - 0, 2594, 0, - 0, 2724, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1395, 623, 1235, - 1389, 638, 1229, - 1381, 656, 1220, - 1371, 679, 1209, - 1356, 709, 1193, - 1336, 746, 1171, - 1308, 791, 1140, - 1267, 845, 1095, - 1205, 908, 1026, - 1107, 981, 915, - 932, 1063, 703, - 477, 1154, 0, - 0, 1253, 0, - 0, 1358, 0, - 0, 1469, 0, - 0, 1585, 0, - 0, 1704, 0, - 0, 1826, 0, - 0, 1951, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1540, 686, 1346, - 1536, 698, 1341, - 1530, 715, 1334, - 1522, 735, 1326, - 1512, 762, 1313, - 1498, 794, 1297, - 1478, 835, 1273, - 1450, 884, 1240, - 1410, 943, 1191, - 1351, 1011, 1116, - 1256, 1088, 993, - 1088, 1174, 745, - 672, 1269, 0, - 0, 1371, 0, - 0, 1479, 0, - 0, 1593, 0, - 0, 1710, 0, - 0, 1831, 0, - 0, 1955, 0, - 0, 2080, 0, - 0, 2207, 0, - 0, 2336, 0, - 0, 2465, 0, - 0, 2595, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1681, 758, 1461, - 1678, 769, 1458, - 1674, 783, 1453, - 1669, 801, 1446, - 1661, 823, 1436, - 1651, 852, 1424, - 1637, 888, 1406, - 1618, 932, 1381, - 1590, 985, 1346, - 1551, 1047, 1295, - 1492, 1119, 1215, - 1400, 1200, 1079, - 1237, 1290, 797, - 846, 1388, 0, - 0, 1493, 0, - 0, 1603, 0, - 0, 1718, 0, - 0, 1837, 0, - 0, 1959, 0, - 0, 2084, 0, - 0, 2210, 0, - 0, 2338, 0, - 0, 2467, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1820, 840, 1581, - 1818, 849, 1578, - 1815, 860, 1574, - 1811, 875, 1569, - 1806, 895, 1562, - 1798, 920, 1552, - 1788, 951, 1539, - 1774, 989, 1521, - 1755, 1036, 1495, - 1728, 1092, 1458, - 1689, 1158, 1404, - 1632, 1233, 1319, - 1541, 1317, 1174, - 1382, 1410, 857, - 1007, 1510, 0, - 0, 1617, 0, - 0, 1729, 0, - 0, 1846, 0, - 0, 1966, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1958, 930, 1703, - 1956, 937, 1701, - 1954, 947, 1698, - 1951, 959, 1694, - 1947, 976, 1689, - 1941, 996, 1681, - 1934, 1023, 1671, - 1924, 1056, 1658, - 1910, 1097, 1639, - 1891, 1146, 1613, - 1865, 1205, 1575, - 1826, 1273, 1518, - 1769, 1351, 1430, - 1679, 1437, 1277, - 1523, 1532, 927, - 1160, 1635, 0, - 0, 1743, 0, - 0, 1856, 0, - 0, 1974, 0, - 0, 2095, 0, - 0, 2219, 0, - 0, 2344, 0, - 0, 2471, 0, - 0, 2600, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2094, 1028, 1828, - 2092, 1034, 1826, - 2091, 1042, 1824, - 2088, 1052, 1821, - 2086, 1065, 1817, - 2082, 1082, 1811, - 2076, 1104, 1804, - 2069, 1132, 1794, - 2059, 1167, 1780, - 2045, 1210, 1761, - 2026, 1261, 1733, - 2000, 1322, 1695, - 1962, 1392, 1637, - 1905, 1472, 1545, - 1816, 1561, 1385, - 1662, 1657, 1007, - 1307, 1761, 0, - 0, 1870, 0, - 0, 1985, 0, - 0, 2103, 0, - 0, 2225, 0, - 0, 2349, 0, - 0, 2475, 0, - 0, 2603, 0, - 0, 2731, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2228, 1133, 1954, - 2228, 1138, 1953, - 2226, 1144, 1951, - 2225, 1152, 1949, - 2223, 1163, 1946, - 2220, 1176, 1942, - 2216, 1194, 1936, - 2210, 1217, 1929, - 2203, 1246, 1918, - 2193, 1282, 1904, - 2180, 1327, 1885, - 2161, 1380, 1857, - 2134, 1442, 1817, - 2096, 1514, 1758, - 2040, 1596, 1665, - 1952, 1686, 1499, - 1799, 1784, 1095, - 1449, 1888, 0, - 0, 1999, 0, - 0, 2114, 0, - 0, 2233, 0, - 0, 2356, 0, - 0, 2480, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2863, 0, - 0, 2992, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2363, 1243, 2082, - 2362, 1247, 2081, - 2361, 1252, 2080, - 2360, 1258, 2078, - 2358, 1267, 2076, - 2356, 1278, 2073, - 2353, 1292, 2068, - 2349, 1311, 2063, - 2344, 1335, 2055, - 2337, 1365, 2045, - 2327, 1402, 2031, - 2313, 1447, 2011, - 2294, 1502, 1983, - 2268, 1565, 1942, - 2230, 1639, 1882, - 2174, 1721, 1787, - 2087, 1813, 1617, - 1934, 1912, 1191, - 1589, 2017, 0, - 0, 2129, 0, - 0, 2244, 0, - 0, 2364, 0, - 0, 2486, 0, - 0, 2611, 0, - 0, 2738, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3124, 0, - 0, 3255, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2496, 1359, 2211, - 2496, 1362, 2210, - 2495, 1365, 2209, - 2494, 1370, 2208, - 2493, 1377, 2206, - 2491, 1386, 2204, - 2489, 1397, 2201, - 2486, 1412, 2196, - 2482, 1431, 2191, - 2477, 1455, 2183, - 2470, 1486, 2173, - 2460, 1524, 2158, - 2446, 1570, 2138, - 2428, 1626, 2110, - 2402, 1691, 2069, - 2364, 1765, 2008, - 2308, 1849, 1911, - 2221, 1941, 1738, - 2069, 2041, 1295, - 1727, 2147, 0, - 0, 2259, 0, - 0, 2375, 0, - 0, 2495, 0, - 0, 2618, 0, - 0, 2743, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3648, 0, - 2630, 1478, 2340, - 2629, 1480, 2340, - 2629, 1483, 2339, - 2628, 1487, 2338, - 2627, 1492, 2337, - 2626, 1499, 2335, - 2624, 1508, 2333, - 2622, 1519, 2330, - 2619, 1535, 2326, - 2615, 1554, 2320, - 2610, 1579, 2312, - 2603, 1610, 2302, - 2593, 1649, 2287, - 2579, 1696, 2267, - 2561, 1752, 2238, - 2535, 1818, 2197, - 2497, 1893, 2136, - 2441, 1977, 2038, - 2354, 2070, 1861, - 2203, 2170, 1404, - 1864, 2277, 0, - 0, 2389, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 2763, 1600, 2471, - 2762, 1602, 2470, - 2762, 1604, 2470, - 2761, 1607, 2469, - 2761, 1611, 2468, - 2760, 1616, 2467, - 2759, 1623, 2465, - 2757, 1632, 2463, - 2755, 1644, 2460, - 2752, 1659, 2455, - 2748, 1679, 2450, - 2743, 1704, 2442, - 2735, 1736, 2431, - 2726, 1775, 2417, - 2712, 1823, 2396, - 2694, 1880, 2368, - 2667, 1946, 2326, - 2630, 2022, 2264, - 2574, 2107, 2165, - 2487, 2200, 1987, - 2337, 2301, 1518, - 1999, 2408, 0, - 0, 2520, 0, - 0, 2637, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 2895, 1725, 2601, - 2895, 1726, 2601, - 2895, 1728, 2601, - 2894, 1730, 2600, - 2894, 1733, 2599, - 2893, 1737, 2599, - 2892, 1742, 2597, - 2891, 1749, 2595, - 2890, 1758, 2593, - 2887, 1770, 2590, - 2884, 1786, 2586, - 2881, 1806, 2580, - 2875, 1832, 2572, - 2868, 1864, 2561, - 2858, 1903, 2547, - 2845, 1951, 2526, - 2826, 2008, 2498, - 2800, 2075, 2456, - 2763, 2151, 2394, - 2707, 2237, 2294, - 2620, 2330, 2114, - 2470, 2431, 1637, - 2133, 2539, 0, - 0, 2652, 0, - 0, 2769, 0, - 0, 2889, 0, - 0, 3012, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3028, 1851, 2733, - 3028, 1852, 2732, - 3027, 1853, 2732, - 3027, 1855, 2732, - 3027, 1857, 2731, - 3026, 1860, 2730, - 3026, 1864, 2729, - 3025, 1870, 2728, - 3024, 1877, 2726, - 3022, 1886, 2724, - 3020, 1898, 2721, - 3017, 1914, 2717, - 3013, 1934, 2711, - 3008, 1960, 2703, - 3000, 1992, 2692, - 2991, 2032, 2677, - 2977, 2080, 2657, - 2959, 2138, 2628, - 2933, 2205, 2586, - 2895, 2282, 2524, - 2840, 2367, 2424, - 2753, 2461, 2243, - 2603, 2562, 1758, - 2267, 2670, 0, - 0, 2783, 0, - 0, 2900, 0, - 0, 3021, 0, - 0, 3144, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 3160, 1979, 2864, - 3160, 1979, 2864, - 3160, 1980, 2863, - 3160, 1982, 2863, - 3160, 1983, 2863, - 3159, 1986, 2862, - 3159, 1989, 2861, - 3158, 1993, 2861, - 3157, 1998, 2859, - 3156, 2005, 2857, - 3154, 2015, 2855, - 3152, 2027, 2852, - 3149, 2043, 2848, - 3145, 2063, 2842, - 3140, 2089, 2834, - 3133, 2122, 2823, - 3123, 2162, 2809, - 3110, 2210, 2788, - 3091, 2268, 2759, - 3065, 2335, 2717, - 3028, 2412, 2654, - 2972, 2498, 2554, - 2886, 2592, 2372, - 2736, 2694, 1882, - 2401, 2802, 0, - 0, 2915, 0, - 0, 3032, 0, - 0, 3153, 0, - 0, 3276, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 3293, 2107, 2995, - 3293, 2108, 2995, - 3292, 2109, 2995, - 3292, 2110, 2995, - 3292, 2111, 2995, - 3292, 2113, 2994, - 3291, 2115, 2994, - 3291, 2118, 2993, - 3290, 2122, 2992, - 3289, 2128, 2991, - 3288, 2135, 2989, - 3287, 2144, 2986, - 3284, 2157, 2983, - 3282, 2173, 2979, - 3278, 2193, 2973, - 3272, 2219, 2965, - 3265, 2252, 2955, - 3255, 2292, 2940, - 3242, 2341, 2919, - 3223, 2399, 2890, - 3197, 2466, 2848, - 3160, 2543, 2785, - 3104, 2629, 2685, - 3018, 2724, 2502, - 2868, 2825, 2008, - 2534, 2933, 0, - 0, 3046, 0, - 0, 3164, 0, - 0, 3285, 0, - 0, 3408, 0, - 0, 3534, 0, - 0, 3661, 0, - 3425, 2237, 3127, - 3425, 2238, 3127, - 3425, 2238, 3127, - 3425, 2239, 3127, - 3425, 2240, 3126, - 3424, 2241, 3126, - 3424, 2243, 3126, - 3424, 2245, 3125, - 3423, 2248, 3124, - 3423, 2252, 3123, - 3422, 2258, 3122, - 3420, 2265, 3120, - 3419, 2275, 3118, - 3417, 2287, 3115, - 3414, 2303, 3111, - 3410, 2323, 3105, - 3405, 2350, 3097, - 3397, 2382, 3086, - 3388, 2423, 3071, - 3374, 2472, 3051, - 3356, 2530, 3022, - 3330, 2597, 2980, - 3292, 2675, 2917, - 3237, 2761, 2816, - 3150, 2855, 2633, - 3001, 2957, 2136, - 2666, 3065, 0, - 0, 3178, 0, - 0, 3296, 0, - 0, 3417, 0, - 0, 3540, 0, - 0, 3666, 0, - 3557, 2367, 3259, - 3557, 2368, 3259, - 3557, 2368, 3259, - 3557, 2369, 3259, - 3557, 2369, 3258, - 3557, 2370, 3258, - 3557, 2372, 3258, - 3556, 2373, 3257, - 3556, 2376, 3257, - 3555, 2379, 3256, - 3555, 2383, 3255, - 3554, 2389, 3254, - 3553, 2396, 3252, - 3551, 2405, 3250, - 3549, 2418, 3247, - 3546, 2434, 3242, - 3542, 2454, 3236, - 3537, 2480, 3229, - 3530, 2513, 3218, - 3520, 2554, 3203, - 3506, 2603, 3182, - 3488, 2661, 3153, - 3462, 2729, 3111, - 3424, 2806, 3048, - 3369, 2892, 2947, - 3283, 2987, 2763, - 3133, 3089, 2264, - 2799, 3197, 0, - 0, 3310, 0, - 0, 3428, 0, - 0, 3548, 0, - 0, 3672, 0, - 3689, 2498, 3391, - 3689, 2498, 3391, - 3689, 2499, 3391, - 3689, 2499, 3390, - 3689, 2500, 3390, - 3689, 2500, 3390, - 3689, 2501, 3390, - 3689, 2503, 3390, - 3688, 2504, 3389, - 3688, 2507, 3389, - 3688, 2510, 3388, - 3687, 2514, 3387, - 3686, 2520, 3386, - 3685, 2527, 3384, - 3683, 2536, 3382, - 3681, 2549, 3378, - 3678, 2565, 3374, - 3674, 2585, 3368, - 3669, 2612, 3360, - 3662, 2644, 3350, - 3652, 2685, 3335, - 3639, 2734, 3314, - 3620, 2792, 3285, - 3594, 2860, 3243, - 3557, 2938, 3180, - 3501, 3024, 3079, - 3415, 3119, 2895, - 3265, 3221, 2394, - 2932, 3329, 0, - 0, 3442, 0, - 0, 3560, 0, - 0, 3681, 0, - 3822, 2629, 3523, - 3822, 2629, 3523, - 3822, 2630, 3523, - 3822, 2630, 3522, - 3821, 2630, 3522, - 3821, 2631, 3522, - 3821, 2632, 3522, - 3821, 2633, 3522, - 3821, 2634, 3522, - 3821, 2636, 3521, - 3820, 2638, 3521, - 3820, 2641, 3520, - 3819, 2645, 3519, - 3818, 2651, 3518, - 3817, 2658, 3516, - 3815, 2668, 3513, - 3813, 2680, 3510, - 3810, 2696, 3506, - 3806, 2717, 3500, - 3801, 2743, 3492, - 3794, 2776, 3481, - 3784, 2817, 3467, - 3771, 2866, 3446, - 3752, 2924, 3417, - 3726, 2992, 3375, - 3689, 3069, 3312, - 3633, 3156, 3210, - 3547, 3251, 3026, - 3398, 3353, 2524, - 3064, 3461, 0, - 0, 3574, 0, - 0, 3692, 0, - 3954, 2760, 3655, - 3954, 2761, 3655, - 3954, 2761, 3654, - 3954, 2761, 3654, - 3954, 2761, 3654, - 3954, 2762, 3654, - 3953, 2762, 3654, - 3953, 2763, 3654, - 3953, 2764, 3654, - 3953, 2765, 3653, - 3953, 2767, 3653, - 3952, 2769, 3652, - 3952, 2773, 3652, - 3951, 2777, 3651, - 3950, 2782, 3649, - 3949, 2790, 3648, - 3947, 2799, 3645, - 3945, 2812, 3642, - 3942, 2828, 3638, - 3939, 2848, 3632, - 3933, 2875, 3624, - 3926, 2908, 3613, - 3916, 2948, 3598, - 3903, 2997, 3578, - 3884, 3056, 3549, - 3858, 3124, 3507, - 3821, 3201, 3443, - 3766, 3288, 3342, - 3679, 3383, 3158, - 3530, 3485, 2655, - 3196, 3593, 0, - 0, 3706, 0, - 4086, 2892, 3787, - 4086, 2892, 3787, - 4086, 2892, 3787, - 4086, 2892, 3786, - 4086, 2893, 3786, - 4086, 2893, 3786, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4086, 2895, 3786, - 4085, 2896, 3786, - 4085, 2897, 3785, - 4085, 2899, 3785, - 4084, 2901, 3784, - 4084, 2904, 3784, - 4083, 2908, 3783, - 4082, 2914, 3781, - 4081, 2921, 3780, - 4080, 2931, 3777, - 4077, 2943, 3774, - 4075, 2959, 3770, - 4071, 2980, 3764, - 4065, 3006, 3756, - 4058, 3039, 3745, - 4048, 3080, 3730, - 4035, 3129, 3710, - 4016, 3188, 3681, - 3990, 3256, 3639, - 3953, 3333, 3575, - 3898, 3420, 3474, - 3811, 3515, 3289, - 3662, 3617, 2786, - 3329, 3725, 0, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3024, 3918, - 4095, 3024, 3918, - 4095, 3025, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3029, 3917, - 4095, 3030, 3917, - 4095, 3033, 3916, - 4095, 3036, 3916, - 4095, 3040, 3915, - 4095, 3046, 3913, - 4095, 3053, 3912, - 4095, 3062, 3909, - 4095, 3075, 3906, - 4095, 3091, 3902, - 4095, 3112, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3212, 3862, - 4095, 3261, 3842, - 4095, 3320, 3813, - 4095, 3388, 3771, - 4085, 3465, 3707, - 4030, 3552, 3606, - 3943, 3647, 3421, - 3794, 3749, 2917, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3155, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4050, - 4095, 3156, 4050, - 4095, 3157, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3161, 4049, - 4095, 3162, 4049, - 4095, 3165, 4048, - 4095, 3168, 4048, - 4095, 3172, 4047, - 4095, 3177, 4045, - 4095, 3185, 4044, - 4095, 3194, 4041, - 4095, 3207, 4038, - 4095, 3223, 4034, - 4095, 3244, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3344, 3994, - 4095, 3393, 3974, - 4095, 3452, 3945, - 4095, 3520, 3903, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3779, 3553, - 0, 494, 709, - 0, 513, 690, - 0, 537, 662, - 0, 567, 621, - 0, 604, 561, - 0, 650, 466, - 0, 705, 295, - 0, 770, 0, - 0, 843, 0, - 0, 927, 0, - 0, 1018, 0, - 0, 1118, 0, - 0, 1223, 0, - 0, 1335, 0, - 0, 1451, 0, - 0, 1571, 0, - 0, 1693, 0, - 0, 1818, 0, - 0, 1945, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 500, 738, - 0, 519, 719, - 0, 543, 693, - 0, 572, 655, - 0, 610, 600, - 0, 655, 513, - 0, 709, 363, - 0, 773, 25, - 0, 846, 0, - 0, 929, 0, - 0, 1020, 0, - 0, 1119, 0, - 0, 1225, 0, - 0, 1336, 0, - 0, 1452, 0, - 0, 1571, 0, - 0, 1694, 0, - 0, 1819, 0, - 0, 1945, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 509, 773, - 0, 527, 756, - 0, 550, 732, - 0, 580, 697, - 0, 616, 647, - 0, 661, 569, - 0, 715, 440, - 0, 778, 174, - 0, 850, 0, - 0, 932, 0, - 0, 1023, 0, - 0, 1121, 0, - 0, 1227, 0, - 0, 1337, 0, - 0, 1453, 0, - 0, 1572, 0, - 0, 1694, 0, - 0, 1819, 0, - 0, 1946, 0, - 0, 2073, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 66, 520, 816, - 0, 538, 801, - 0, 561, 779, - 0, 589, 748, - 0, 625, 703, - 0, 669, 635, - 0, 722, 525, - 0, 784, 318, - 0, 856, 0, - 0, 937, 0, - 0, 1027, 0, - 0, 1124, 0, - 0, 1229, 0, - 0, 1339, 0, - 0, 1454, 0, - 0, 1573, 0, - 0, 1695, 0, - 0, 1820, 0, - 0, 1946, 0, - 0, 2074, 0, - 0, 2202, 0, - 0, 2332, 0, - 0, 2462, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3118, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 429, 534, 868, - 379, 552, 854, - 302, 574, 835, - 173, 602, 808, - 0, 637, 769, - 0, 680, 711, - 0, 731, 620, - 0, 792, 459, - 0, 863, 78, - 0, 943, 0, - 0, 1031, 0, - 0, 1128, 0, - 0, 1232, 0, - 0, 1342, 0, - 0, 1456, 0, - 0, 1575, 0, - 0, 1696, 0, - 0, 1821, 0, - 0, 1947, 0, - 0, 2074, 0, - 0, 2203, 0, - 0, 2332, 0, - 0, 2463, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2855, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 680, 553, 930, - 652, 570, 918, - 611, 591, 901, - 550, 618, 878, - 454, 652, 844, - 281, 693, 796, - 0, 743, 721, - 0, 803, 597, - 0, 872, 351, - 0, 950, 0, - 0, 1038, 0, - 0, 1133, 0, - 0, 1236, 0, - 0, 1345, 0, - 0, 1459, 0, - 0, 1577, 0, - 0, 1698, 0, - 0, 1822, 0, - 0, 1948, 0, - 0, 2075, 0, - 0, 2203, 0, - 0, 2333, 0, - 0, 2463, 0, - 0, 2593, 0, - 0, 2724, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 884, 577, 1001, - 866, 593, 990, - 841, 613, 976, - 806, 639, 956, - 753, 671, 929, - 672, 711, 889, - 534, 759, 829, - 243, 817, 734, - 0, 884, 566, - 0, 960, 150, - 0, 1046, 0, - 0, 1140, 0, - 0, 1241, 0, - 0, 1349, 0, - 0, 1462, 0, - 0, 1579, 0, - 0, 1700, 0, - 0, 1823, 0, - 0, 1949, 0, - 0, 2076, 0, - 0, 2204, 0, - 0, 2333, 0, - 0, 2463, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1063, 607, 1081, - 1051, 622, 1072, - 1035, 641, 1061, - 1012, 665, 1044, - 979, 696, 1022, - 932, 733, 989, - 859, 780, 942, - 739, 835, 870, - 505, 899, 751, - 0, 974, 520, - 0, 1057, 0, - 0, 1149, 0, - 0, 1249, 0, - 0, 1355, 0, - 0, 1466, 0, - 0, 1583, 0, - 0, 1702, 0, - 0, 1825, 0, - 0, 1950, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1228, 644, 1170, - 1219, 658, 1163, - 1208, 676, 1153, - 1193, 698, 1140, - 1171, 727, 1122, - 1140, 762, 1096, - 1096, 805, 1059, - 1029, 858, 1005, - 919, 919, 919, - 715, 991, 773, - 63, 1071, 450, - 0, 1161, 0, - 0, 1258, 0, - 0, 1362, 0, - 0, 1472, 0, - 0, 1587, 0, - 0, 1706, 0, - 0, 1828, 0, - 0, 1952, 0, - 0, 2078, 0, - 0, 2206, 0, - 0, 2335, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1383, 690, 1267, - 1377, 702, 1262, - 1369, 718, 1254, - 1358, 739, 1243, - 1343, 765, 1229, - 1322, 798, 1208, - 1293, 838, 1180, - 1250, 887, 1139, - 1187, 945, 1077, - 1084, 1013, 978, - 897, 1090, 801, - 377, 1176, 337, - 0, 1270, 0, - 0, 1372, 0, - 0, 1480, 0, - 0, 1593, 0, - 0, 1711, 0, - 0, 1831, 0, - 0, 1955, 0, - 0, 2080, 0, - 0, 2208, 0, - 0, 2336, 0, - 0, 2465, 0, - 0, 2595, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1531, 745, 1371, - 1527, 756, 1367, - 1521, 770, 1361, - 1513, 788, 1352, - 1503, 812, 1341, - 1488, 841, 1325, - 1468, 878, 1303, - 1440, 923, 1272, - 1399, 977, 1227, - 1337, 1040, 1158, - 1239, 1113, 1047, - 1064, 1195, 835, - 609, 1286, 120, - 0, 1385, 0, - 0, 1490, 0, - 0, 1601, 0, - 0, 1717, 0, - 0, 1836, 0, - 0, 1958, 0, - 0, 2083, 0, - 0, 2210, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1675, 809, 1481, - 1672, 818, 1478, - 1668, 831, 1473, - 1662, 847, 1466, - 1655, 867, 1458, - 1644, 894, 1445, - 1630, 927, 1429, - 1610, 967, 1405, - 1582, 1016, 1372, - 1542, 1075, 1323, - 1483, 1143, 1249, - 1388, 1220, 1125, - 1220, 1307, 878, - 804, 1401, 0, - 0, 1503, 0, - 0, 1611, 0, - 0, 1725, 0, - 0, 1842, 0, - 0, 1963, 0, - 0, 2087, 0, - 0, 2212, 0, - 0, 2340, 0, - 0, 2468, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1816, 882, 1596, - 1813, 890, 1593, - 1810, 901, 1590, - 1806, 915, 1585, - 1801, 933, 1578, - 1793, 955, 1569, - 1783, 984, 1556, - 1769, 1020, 1538, - 1750, 1064, 1514, - 1722, 1117, 1478, - 1683, 1179, 1427, - 1625, 1251, 1347, - 1532, 1333, 1212, - 1369, 1422, 929, - 978, 1520, 0, - 0, 1625, 0, - 0, 1735, 0, - 0, 1850, 0, - 0, 1969, 0, - 0, 2092, 0, - 0, 2216, 0, - 0, 2342, 0, - 0, 2470, 0, - 0, 2599, 0, - 0, 2728, 0, - 0, 2859, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1954, 965, 1715, - 1952, 972, 1713, - 1950, 981, 1710, - 1947, 992, 1706, - 1943, 1007, 1701, - 1938, 1027, 1694, - 1930, 1052, 1684, - 1920, 1083, 1671, - 1906, 1121, 1653, - 1887, 1168, 1627, - 1860, 1224, 1590, - 1821, 1290, 1536, - 1764, 1365, 1452, - 1673, 1449, 1307, - 1514, 1542, 989, - 1139, 1642, 0, - 0, 1749, 0, - 0, 1861, 0, - 0, 1978, 0, - 0, 2098, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 2091, 1056, 1837, - 2090, 1062, 1835, - 2088, 1069, 1833, - 2086, 1079, 1830, - 2083, 1091, 1826, - 2079, 1108, 1821, - 2073, 1129, 1813, - 2066, 1155, 1803, - 2056, 1188, 1790, - 2042, 1229, 1771, - 2023, 1278, 1745, - 1997, 1337, 1707, - 1958, 1405, 1650, - 1901, 1483, 1562, - 1812, 1570, 1409, - 1655, 1664, 1059, - 1292, 1767, 0, - 0, 1875, 0, - 0, 1988, 0, - 0, 2106, 0, - 0, 2227, 0, - 0, 2351, 0, - 0, 2476, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2227, 1156, 1961, - 2226, 1160, 1960, - 2224, 1166, 1958, - 2223, 1174, 1956, - 2221, 1184, 1953, - 2218, 1197, 1949, - 2214, 1214, 1943, - 2208, 1236, 1936, - 2201, 1264, 1926, - 2191, 1299, 1912, - 2177, 1342, 1893, - 2158, 1393, 1866, - 2132, 1454, 1827, - 2094, 1524, 1769, - 2037, 1604, 1678, - 1948, 1693, 1517, - 1794, 1789, 1139, - 1439, 1893, 0, - 0, 2002, 0, - 0, 2117, 0, - 0, 2235, 0, - 0, 2357, 0, - 0, 2481, 0, - 0, 2607, 0, - 0, 2735, 0, - 0, 2863, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3647, 0, - 2361, 1261, 2087, - 2361, 1265, 2086, - 2360, 1270, 2085, - 2358, 1276, 2083, - 2357, 1284, 2081, - 2355, 1295, 2078, - 2352, 1309, 2074, - 2348, 1327, 2068, - 2342, 1349, 2061, - 2335, 1378, 2050, - 2325, 1415, 2036, - 2312, 1459, 2017, - 2293, 1512, 1989, - 2266, 1574, 1949, - 2228, 1646, 1890, - 2172, 1728, 1797, - 2084, 1818, 1631, - 1931, 1916, 1227, - 1581, 2021, 0, - 0, 2131, 0, - 0, 2246, 0, - 0, 2365, 0, - 0, 2488, 0, - 0, 2612, 0, - 0, 2738, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2495, 1373, 2215, - 2495, 1376, 2214, - 2494, 1379, 2213, - 2493, 1384, 2212, - 2492, 1391, 2210, - 2490, 1399, 2208, - 2488, 1410, 2205, - 2485, 1424, 2201, - 2481, 1443, 2195, - 2476, 1467, 2187, - 2469, 1497, 2177, - 2459, 1534, 2163, - 2445, 1579, 2143, - 2427, 1634, 2115, - 2400, 1698, 2074, - 2362, 1771, 2014, - 2306, 1854, 1919, - 2219, 1945, 1749, - 2066, 2044, 1323, - 1721, 2149, 0, - 0, 2261, 0, - 0, 2376, 0, - 0, 2496, 0, - 0, 2619, 0, - 0, 2743, 0, - 0, 2870, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3649, 0, - 2629, 1489, 2343, - 2628, 1491, 2343, - 2628, 1494, 2342, - 2627, 1497, 2341, - 2626, 1503, 2340, - 2625, 1509, 2338, - 2623, 1518, 2336, - 2621, 1529, 2333, - 2618, 1544, 2329, - 2614, 1563, 2323, - 2609, 1588, 2315, - 2602, 1618, 2305, - 2592, 1656, 2290, - 2579, 1703, 2270, - 2560, 1758, 2242, - 2534, 1823, 2201, - 2496, 1897, 2140, - 2440, 1981, 2043, - 2353, 2073, 1870, - 2201, 2173, 1427, - 1859, 2279, 0, - 0, 2391, 0, - 0, 2507, 0, - 0, 2627, 0, - 0, 2750, 0, - 0, 2875, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 2762, 1608, 2473, - 2762, 1610, 2473, - 2761, 1612, 2472, - 2761, 1615, 2471, - 2760, 1619, 2470, - 2759, 1624, 2469, - 2758, 1631, 2467, - 2756, 1640, 2465, - 2754, 1652, 2462, - 2751, 1667, 2458, - 2747, 1686, 2452, - 2742, 1711, 2444, - 2735, 1742, 2434, - 2725, 1781, 2419, - 2712, 1828, 2399, - 2693, 1884, 2370, - 2667, 1950, 2329, - 2629, 2025, 2268, - 2573, 2109, 2170, - 2486, 2202, 1993, - 2335, 2302, 1536, - 1996, 2409, 0, - 0, 2521, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 2895, 1731, 2603, - 2895, 1732, 2603, - 2894, 1734, 2602, - 2894, 1736, 2602, - 2893, 1739, 2601, - 2893, 1743, 2600, - 2892, 1748, 2599, - 2891, 1755, 2597, - 2889, 1764, 2595, - 2887, 1776, 2592, - 2884, 1791, 2587, - 2880, 1811, 2582, - 2875, 1836, 2574, - 2868, 1868, 2563, - 2858, 1907, 2549, - 2844, 1955, 2528, - 2826, 2012, 2500, - 2800, 2078, 2458, - 2762, 2154, 2396, - 2706, 2239, 2298, - 2619, 2332, 2119, - 2469, 2433, 1651, - 2131, 2540, 0, - 0, 2652, 0, - 0, 2769, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3028, 1856, 2734, - 3027, 1857, 2734, - 3027, 1858, 2733, - 3027, 1860, 2733, - 3027, 1862, 2732, - 3026, 1865, 2732, - 3025, 1869, 2731, - 3024, 1874, 2729, - 3023, 1881, 2728, - 3022, 1890, 2725, - 3019, 1902, 2722, - 3017, 1918, 2718, - 3013, 1938, 2712, - 3007, 1964, 2704, - 3000, 1996, 2694, - 2990, 2035, 2679, - 2977, 2083, 2658, - 2958, 2140, 2630, - 2932, 2207, 2588, - 2895, 2283, 2526, - 2839, 2369, 2426, - 2752, 2462, 2246, - 2602, 2563, 1769, - 2265, 2671, 0, - 0, 2784, 0, - 0, 2901, 0, - 0, 3021, 0, - 0, 3144, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 3160, 1982, 2865, - 3160, 1983, 2865, - 3160, 1984, 2864, - 3160, 1985, 2864, - 3159, 1987, 2864, - 3159, 1989, 2863, - 3158, 1992, 2862, - 3158, 1996, 2861, - 3157, 2002, 2860, - 3156, 2009, 2858, - 3154, 2018, 2856, - 3152, 2030, 2853, - 3149, 2046, 2849, - 3145, 2066, 2843, - 3140, 2092, 2835, - 3133, 2124, 2824, - 3123, 2164, 2810, - 3109, 2212, 2789, - 3091, 2270, 2760, - 3065, 2337, 2719, - 3027, 2414, 2656, - 2972, 2499, 2556, - 2885, 2593, 2375, - 2735, 2695, 1890, - 2399, 2802, 0, - 0, 2915, 0, - 0, 3032, 0, - 0, 3153, 0, - 0, 3276, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 3292, 2110, 2996, - 3292, 2111, 2996, - 3292, 2111, 2996, - 3292, 2112, 2996, - 3292, 2114, 2995, - 3292, 2116, 2995, - 3291, 2118, 2994, - 3291, 2121, 2994, - 3290, 2125, 2993, - 3289, 2130, 2991, - 3288, 2138, 2990, - 3286, 2147, 2987, - 3284, 2159, 2984, - 3281, 2175, 2980, - 3277, 2195, 2974, - 3272, 2221, 2966, - 3265, 2254, 2955, - 3255, 2294, 2941, - 3242, 2342, 2920, - 3223, 2400, 2891, - 3197, 2467, 2849, - 3160, 2544, 2787, - 3104, 2630, 2686, - 3018, 2724, 2504, - 2868, 2826, 2015, - 2533, 2934, 0, - 0, 3047, 0, - 0, 3164, 0, - 0, 3285, 0, - 0, 3408, 0, - 0, 3534, 0, - 0, 3661, 0, - 3425, 2239, 3128, - 3425, 2240, 3127, - 3425, 2240, 3127, - 3425, 2241, 3127, - 3424, 2242, 3127, - 3424, 2243, 3127, - 3424, 2245, 3126, - 3424, 2247, 3126, - 3423, 2250, 3125, - 3422, 2254, 3124, - 3421, 2260, 3123, - 3420, 2267, 3121, - 3419, 2276, 3119, - 3417, 2289, 3115, - 3414, 2305, 3111, - 3410, 2325, 3105, - 3404, 2351, 3097, - 3397, 2384, 3087, - 3387, 2424, 3072, - 3374, 2473, 3051, - 3355, 2531, 3022, - 3329, 2598, 2980, - 3292, 2675, 2918, - 3237, 2761, 2817, - 3150, 2856, 2634, - 3000, 2957, 2141, - 2666, 3065, 0, - 0, 3178, 0, - 0, 3296, 0, - 0, 3417, 0, - 0, 3540, 0, - 0, 3666, 0, - 3557, 2369, 3259, - 3557, 2369, 3259, - 3557, 2370, 3259, - 3557, 2370, 3259, - 3557, 2371, 3259, - 3557, 2372, 3259, - 3556, 2373, 3258, - 3556, 2375, 3258, - 3556, 2377, 3257, - 3555, 2380, 3257, - 3555, 2385, 3256, - 3554, 2390, 3254, - 3553, 2397, 3252, - 3551, 2407, 3250, - 3549, 2419, 3247, - 3546, 2435, 3243, - 3542, 2456, 3237, - 3537, 2482, 3229, - 3529, 2514, 3218, - 3520, 2555, 3203, - 3506, 2604, 3183, - 3488, 2662, 3154, - 3462, 2729, 3112, - 3424, 2807, 3049, - 3369, 2893, 2948, - 3282, 2987, 2765, - 3133, 3089, 2268, - 2799, 3197, 0, - 0, 3310, 0, - 0, 3428, 0, - 0, 3549, 0, - 0, 3672, 0, - 3689, 2499, 3391, - 3689, 2499, 3391, - 3689, 2500, 3391, - 3689, 2500, 3391, - 3689, 2501, 3391, - 3689, 2501, 3390, - 3689, 2502, 3390, - 3689, 2504, 3390, - 3688, 2506, 3390, - 3688, 2508, 3389, - 3687, 2511, 3388, - 3687, 2515, 3387, - 3686, 2521, 3386, - 3685, 2528, 3384, - 3683, 2537, 3382, - 3681, 2550, 3379, - 3678, 2566, 3374, - 3674, 2586, 3369, - 3669, 2613, 3361, - 3662, 2645, 3350, - 3652, 2686, 3335, - 3639, 2735, 3314, - 3620, 2793, 3285, - 3594, 2861, 3243, - 3556, 2938, 3180, - 3501, 3024, 3079, - 3415, 3119, 2896, - 3265, 3221, 2397, - 2931, 3329, 0, - 0, 3442, 0, - 0, 3560, 0, - 0, 3681, 0, - 3822, 2630, 3523, - 3822, 2630, 3523, - 3821, 2630, 3523, - 3821, 2631, 3523, - 3821, 2631, 3523, - 3821, 2632, 3522, - 3821, 2632, 3522, - 3821, 2633, 3522, - 3821, 2635, 3522, - 3821, 2637, 3521, - 3820, 2639, 3521, - 3820, 2642, 3520, - 3819, 2646, 3519, - 3818, 2652, 3518, - 3817, 2659, 3516, - 3815, 2668, 3514, - 3813, 2681, 3510, - 3810, 2697, 3506, - 3806, 2717, 3500, - 3801, 2744, 3492, - 3794, 2777, 3482, - 3784, 2817, 3467, - 3771, 2866, 3446, - 3752, 2925, 3417, - 3726, 2992, 3375, - 3689, 3070, 3312, - 3633, 3156, 3211, - 3547, 3251, 3027, - 3398, 3353, 2526, - 3064, 3461, 0, - 0, 3574, 0, - 0, 3692, 0, - 3954, 2761, 3655, - 3954, 2761, 3655, - 3954, 2761, 3655, - 3954, 2762, 3655, - 3954, 2762, 3655, - 3954, 2762, 3654, - 3953, 2763, 3654, - 3953, 2764, 3654, - 3953, 2765, 3654, - 3953, 2766, 3654, - 3953, 2768, 3653, - 3952, 2770, 3653, - 3952, 2773, 3652, - 3951, 2777, 3651, - 3950, 2783, 3650, - 3949, 2790, 3648, - 3947, 2800, 3645, - 3945, 2812, 3642, - 3942, 2828, 3638, - 3938, 2849, 3632, - 3933, 2875, 3624, - 3926, 2908, 3614, - 3916, 2949, 3599, - 3903, 2998, 3578, - 3884, 3056, 3549, - 3858, 3124, 3507, - 3821, 3202, 3444, - 3766, 3288, 3343, - 3679, 3383, 3158, - 3530, 3485, 2656, - 3196, 3593, 0, - 0, 3706, 0, - 4086, 2892, 3787, - 4086, 2893, 3787, - 4086, 2893, 3787, - 4086, 2893, 3787, - 4086, 2893, 3787, - 4086, 2893, 3786, - 4086, 2894, 3786, - 4086, 2894, 3786, - 4085, 2895, 3786, - 4085, 2896, 3786, - 4085, 2897, 3786, - 4085, 2899, 3785, - 4084, 2902, 3785, - 4084, 2905, 3784, - 4083, 2909, 3783, - 4082, 2914, 3782, - 4081, 2922, 3780, - 4080, 2931, 3777, - 4077, 2944, 3774, - 4075, 2960, 3770, - 4071, 2980, 3764, - 4065, 3007, 3756, - 4058, 3040, 3745, - 4048, 3080, 3731, - 4035, 3130, 3710, - 4016, 3188, 3681, - 3990, 3256, 3639, - 3953, 3333, 3575, - 3898, 3420, 3474, - 3811, 3515, 3290, - 3662, 3617, 2787, - 3328, 3725, 0, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3024, 3919, - 4095, 3025, 3919, - 4095, 3025, 3918, - 4095, 3025, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3918, - 4095, 3029, 3918, - 4095, 3031, 3917, - 4095, 3033, 3917, - 4095, 3036, 3916, - 4095, 3040, 3915, - 4095, 3046, 3914, - 4095, 3053, 3912, - 4095, 3063, 3909, - 4095, 3075, 3906, - 4095, 3091, 3902, - 4095, 3112, 3896, - 4095, 3138, 3888, - 4095, 3171, 3877, - 4095, 3212, 3863, - 4095, 3261, 3842, - 4095, 3320, 3813, - 4095, 3388, 3771, - 4085, 3465, 3707, - 4030, 3552, 3606, - 3943, 3647, 3422, - 3794, 3749, 2918, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3157, 4050, - 4095, 3157, 4050, - 4095, 3158, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3161, 4050, - 4095, 3163, 4049, - 4095, 3165, 4049, - 4095, 3168, 4048, - 4095, 3172, 4047, - 4095, 3178, 4046, - 4095, 3185, 4044, - 4095, 3195, 4041, - 4095, 3207, 4038, - 4095, 3223, 4034, - 4095, 3244, 4028, - 4095, 3270, 4020, - 4095, 3303, 4009, - 4095, 3344, 3995, - 4095, 3393, 3974, - 4095, 3452, 3945, - 4095, 3520, 3903, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3779, 3553, - 0, 606, 834, - 0, 621, 819, - 0, 640, 798, - 0, 664, 769, - 0, 695, 726, - 0, 733, 662, - 0, 779, 559, - 0, 834, 370, - 0, 899, 0, - 0, 973, 0, - 0, 1057, 0, - 0, 1149, 0, - 0, 1248, 0, - 0, 1355, 0, - 0, 1466, 0, - 0, 1583, 0, - 0, 1702, 0, - 0, 1825, 0, - 0, 1950, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3250, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 611, 856, - 0, 626, 842, - 0, 645, 822, - 0, 669, 794, - 0, 699, 753, - 0, 737, 693, - 0, 782, 598, - 0, 837, 427, - 0, 902, 2, - 0, 976, 0, - 0, 1059, 0, - 0, 1150, 0, - 0, 1250, 0, - 0, 1356, 0, - 0, 1467, 0, - 0, 1583, 0, - 0, 1703, 0, - 0, 1825, 0, - 0, 1950, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 618, 883, - 0, 632, 870, - 0, 651, 851, - 0, 675, 825, - 0, 705, 788, - 0, 742, 732, - 0, 787, 645, - 0, 841, 495, - 0, 905, 157, - 0, 979, 0, - 0, 1061, 0, - 0, 1152, 0, - 0, 1251, 0, - 0, 1357, 0, - 0, 1468, 0, - 0, 1584, 0, - 0, 1703, 0, - 0, 1826, 0, - 0, 1951, 0, - 0, 2077, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 627, 918, - 0, 641, 905, - 0, 659, 888, - 0, 682, 864, - 0, 712, 829, - 0, 748, 779, - 0, 793, 702, - 0, 847, 572, - 0, 910, 306, - 0, 983, 0, - 0, 1064, 0, - 0, 1155, 0, - 0, 1253, 0, - 0, 1359, 0, - 0, 1469, 0, - 0, 1585, 0, - 0, 1704, 0, - 0, 1827, 0, - 0, 1951, 0, - 0, 2078, 0, - 0, 2205, 0, - 0, 2334, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 271, 638, 960, - 198, 652, 948, - 78, 670, 933, - 0, 693, 911, - 0, 721, 880, - 0, 757, 835, - 0, 801, 768, - 0, 854, 657, - 0, 916, 450, - 0, 988, 0, - 0, 1069, 0, - 0, 1159, 0, - 0, 1256, 0, - 0, 1361, 0, - 0, 1471, 0, - 0, 1586, 0, - 0, 1705, 0, - 0, 1827, 0, - 0, 1952, 0, - 0, 2078, 0, - 0, 2206, 0, - 0, 2335, 0, - 0, 2464, 0, - 0, 2594, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2987, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 595, 653, 1011, - 561, 667, 1000, - 511, 684, 986, - 434, 706, 967, - 305, 734, 940, - 43, 769, 901, - 0, 812, 843, - 0, 863, 752, - 0, 924, 591, - 0, 995, 210, - 0, 1075, 0, - 0, 1164, 0, - 0, 1260, 0, - 0, 1364, 0, - 0, 1474, 0, - 0, 1588, 0, - 0, 1707, 0, - 0, 1829, 0, - 0, 1953, 0, - 0, 2079, 0, - 0, 2206, 0, - 0, 2335, 0, - 0, 2464, 0, - 0, 2595, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 832, 672, 1071, - 812, 685, 1062, - 784, 702, 1050, - 743, 723, 1033, - 682, 750, 1010, - 586, 784, 976, - 413, 825, 928, - 0, 875, 853, - 0, 935, 729, - 0, 1004, 483, - 0, 1082, 0, - 0, 1170, 0, - 0, 1265, 0, - 0, 1368, 0, - 0, 1477, 0, - 0, 1591, 0, - 0, 1709, 0, - 0, 1830, 0, - 0, 1954, 0, - 0, 2080, 0, - 0, 2207, 0, - 0, 2335, 0, - 0, 2465, 0, - 0, 2595, 0, - 0, 2725, 0, - 0, 2856, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3382, 0, - 0, 3514, 0, - 0, 3646, 0, - 1029, 697, 1140, - 1016, 709, 1133, - 998, 725, 1122, - 973, 745, 1108, - 938, 771, 1089, - 885, 803, 1061, - 804, 843, 1021, - 666, 891, 961, - 375, 949, 866, - 0, 1016, 698, - 0, 1093, 282, - 0, 1178, 0, - 0, 1272, 0, - 0, 1374, 0, - 0, 1481, 0, - 0, 1594, 0, - 0, 1711, 0, - 0, 1832, 0, - 0, 1955, 0, - 0, 2081, 0, - 0, 2208, 0, - 0, 2336, 0, - 0, 2465, 0, - 0, 2595, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1204, 728, 1220, - 1195, 739, 1213, - 1183, 754, 1205, - 1167, 773, 1193, - 1144, 797, 1176, - 1111, 828, 1154, - 1064, 866, 1121, - 991, 912, 1074, - 872, 967, 1002, - 637, 1032, 883, - 0, 1106, 652, - 0, 1189, 0, - 0, 1281, 0, - 0, 1381, 0, - 0, 1487, 0, - 0, 1599, 0, - 0, 1715, 0, - 0, 1835, 0, - 0, 1957, 0, - 0, 2082, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1366, 766, 1308, - 1360, 777, 1302, - 1352, 790, 1295, - 1340, 808, 1286, - 1325, 830, 1272, - 1303, 859, 1254, - 1272, 894, 1228, - 1228, 938, 1191, - 1161, 990, 1137, - 1052, 1052, 1052, - 847, 1123, 905, - 195, 1203, 583, - 0, 1293, 0, - 0, 1390, 0, - 0, 1494, 0, - 0, 1604, 0, - 0, 1719, 0, - 0, 1838, 0, - 0, 1960, 0, - 0, 2084, 0, - 0, 2210, 0, - 0, 2338, 0, - 0, 2467, 0, - 0, 2596, 0, - 0, 2727, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 1519, 813, 1404, - 1515, 822, 1399, - 1509, 834, 1394, - 1501, 850, 1386, - 1490, 871, 1375, - 1475, 897, 1361, - 1454, 930, 1341, - 1425, 970, 1312, - 1383, 1019, 1271, - 1319, 1077, 1209, - 1216, 1145, 1110, - 1029, 1222, 933, - 509, 1308, 469, - 0, 1402, 0, - 0, 1504, 0, - 0, 1612, 0, - 0, 1725, 0, - 0, 1843, 0, - 0, 1963, 0, - 0, 2087, 0, - 0, 2213, 0, - 0, 2340, 0, - 0, 2468, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1666, 868, 1507, - 1663, 877, 1504, - 1659, 888, 1499, - 1653, 902, 1493, - 1645, 920, 1484, - 1635, 944, 1473, - 1620, 973, 1457, - 1600, 1010, 1435, - 1572, 1055, 1404, - 1531, 1109, 1359, - 1469, 1172, 1290, - 1372, 1245, 1179, - 1196, 1327, 967, - 741, 1418, 252, - 0, 1517, 0, - 0, 1622, 0, - 0, 1733, 0, - 0, 1849, 0, - 0, 1968, 0, - 0, 2091, 0, - 0, 2215, 0, - 0, 2342, 0, - 0, 2470, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1809, 933, 1616, - 1807, 941, 1613, - 1804, 950, 1610, - 1800, 963, 1605, - 1794, 979, 1599, - 1787, 999, 1590, - 1776, 1026, 1578, - 1762, 1059, 1561, - 1742, 1099, 1537, - 1715, 1148, 1504, - 1675, 1207, 1455, - 1615, 1275, 1381, - 1520, 1352, 1257, - 1352, 1439, 1010, - 936, 1533, 0, - 0, 1635, 0, - 0, 1743, 0, - 0, 1857, 0, - 0, 1974, 0, - 0, 2095, 0, - 0, 2219, 0, - 0, 2344, 0, - 0, 2472, 0, - 0, 2600, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1949, 1008, 1730, - 1948, 1014, 1728, - 1946, 1022, 1725, - 1943, 1033, 1722, - 1938, 1047, 1717, - 1933, 1065, 1710, - 1925, 1088, 1701, - 1915, 1116, 1688, - 1901, 1152, 1670, - 1882, 1196, 1646, - 1855, 1249, 1610, - 1815, 1312, 1559, - 1757, 1383, 1479, - 1664, 1465, 1344, - 1501, 1555, 1061, - 1110, 1652, 0, - 0, 1757, 0, - 0, 1867, 0, - 0, 1983, 0, - 0, 2102, 0, - 0, 2224, 0, - 0, 2348, 0, - 0, 2474, 0, - 0, 2602, 0, - 0, 2731, 0, - 0, 2860, 0, - 0, 2991, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2087, 1092, 1849, - 2086, 1097, 1847, - 2085, 1104, 1845, - 2082, 1113, 1842, - 2079, 1124, 1838, - 2075, 1140, 1833, - 2070, 1159, 1826, - 2062, 1184, 1816, - 2052, 1215, 1803, - 2039, 1254, 1785, - 2019, 1300, 1759, - 1992, 1357, 1722, - 1954, 1422, 1668, - 1896, 1497, 1584, - 1805, 1581, 1439, - 1646, 1674, 1121, - 1271, 1774, 0, - 0, 1881, 0, - 0, 1993, 0, - 0, 2110, 0, - 0, 2230, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2224, 1184, 1970, - 2223, 1189, 1969, - 2222, 1194, 1967, - 2220, 1201, 1965, - 2218, 1211, 1962, - 2215, 1224, 1958, - 2211, 1240, 1953, - 2206, 1261, 1945, - 2198, 1287, 1936, - 2188, 1320, 1922, - 2175, 1361, 1903, - 2156, 1410, 1877, - 2129, 1469, 1839, - 2090, 1537, 1782, - 2033, 1615, 1694, - 1944, 1702, 1541, - 1787, 1797, 1191, - 1424, 1899, 0, - 0, 2007, 0, - 0, 2121, 0, - 0, 2238, 0, - 0, 2359, 0, - 0, 2483, 0, - 0, 2608, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2359, 1284, 2094, - 2359, 1288, 2093, - 2358, 1292, 2092, - 2357, 1298, 2090, - 2355, 1306, 2088, - 2353, 1316, 2085, - 2350, 1329, 2081, - 2346, 1346, 2075, - 2340, 1368, 2068, - 2333, 1396, 2058, - 2323, 1431, 2044, - 2309, 1474, 2025, - 2291, 1525, 1998, - 2264, 1586, 1959, - 2226, 1656, 1901, - 2169, 1736, 1810, - 2080, 1825, 1649, - 1926, 1921, 1271, - 1571, 2025, 0, - 0, 2135, 0, - 0, 2249, 0, - 0, 2368, 0, - 0, 2489, 0, - 0, 2613, 0, - 0, 2739, 0, - 0, 2867, 0, - 0, 2995, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2494, 1391, 2220, - 2493, 1393, 2219, - 2493, 1397, 2218, - 2492, 1402, 2217, - 2491, 1408, 2215, - 2489, 1416, 2213, - 2487, 1427, 2210, - 2484, 1441, 2206, - 2480, 1459, 2200, - 2474, 1482, 2193, - 2467, 1511, 2183, - 2457, 1547, 2168, - 2444, 1591, 2149, - 2425, 1644, 2121, - 2398, 1706, 2082, - 2361, 1779, 2022, - 2304, 1860, 1929, - 2216, 1950, 1763, - 2063, 2048, 1359, - 1714, 2153, 0, - 0, 2263, 0, - 0, 2378, 0, - 0, 2498, 0, - 0, 2620, 0, - 0, 2744, 0, - 0, 2871, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 2628, 1503, 2347, - 2627, 1505, 2347, - 2627, 1508, 2346, - 2626, 1511, 2345, - 2625, 1516, 2344, - 2624, 1523, 2342, - 2622, 1531, 2340, - 2620, 1542, 2337, - 2617, 1557, 2333, - 2613, 1575, 2327, - 2608, 1599, 2319, - 2601, 1629, 2309, - 2591, 1666, 2295, - 2577, 1711, 2275, - 2559, 1766, 2247, - 2532, 1830, 2207, - 2495, 1903, 2146, - 2438, 1986, 2051, - 2351, 2077, 1881, - 2199, 2176, 1456, - 1853, 2281, 0, - 0, 2393, 0, - 0, 2509, 0, - 0, 2628, 0, - 0, 2751, 0, - 0, 2875, 0, - 0, 3002, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3650, 0, - 2761, 1619, 2476, - 2761, 1621, 2476, - 2760, 1623, 2475, - 2760, 1626, 2474, - 2759, 1630, 2473, - 2758, 1635, 2472, - 2757, 1641, 2470, - 2756, 1650, 2468, - 2753, 1661, 2465, - 2750, 1676, 2461, - 2747, 1695, 2455, - 2741, 1720, 2447, - 2734, 1750, 2437, - 2724, 1788, 2422, - 2711, 1835, 2402, - 2692, 1890, 2374, - 2666, 1955, 2333, - 2628, 2029, 2272, - 2572, 2113, 2176, - 2485, 2205, 2002, - 2333, 2305, 1559, - 1991, 2411, 0, - 0, 2523, 0, - 0, 2639, 0, - 0, 2759, 0, - 0, 2882, 0, - 0, 3007, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3520, 0, - 0, 3651, 0, - 2894, 1739, 2605, - 2894, 1740, 2605, - 2894, 1742, 2605, - 2893, 1744, 2604, - 2893, 1747, 2603, - 2892, 1751, 2602, - 2891, 1756, 2601, - 2890, 1763, 2599, - 2888, 1772, 2597, - 2886, 1784, 2594, - 2883, 1799, 2590, - 2879, 1818, 2584, - 2874, 1843, 2576, - 2867, 1874, 2566, - 2857, 1913, 2551, - 2844, 1960, 2531, - 2825, 2016, 2502, - 2799, 2082, 2461, - 2761, 2157, 2400, - 2705, 2241, 2302, - 2618, 2334, 2125, - 2468, 2434, 1668, - 2128, 2541, 0, - 0, 2653, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 3027, 1862, 2735, - 3027, 1863, 2735, - 3027, 1864, 2735, - 3026, 1866, 2735, - 3026, 1868, 2734, - 3026, 1871, 2733, - 3025, 1875, 2732, - 3024, 1880, 2731, - 3023, 1887, 2729, - 3021, 1896, 2727, - 3019, 1908, 2724, - 3016, 1924, 2720, - 3012, 1943, 2714, - 3007, 1969, 2706, - 3000, 2000, 2695, - 2990, 2039, 2681, - 2976, 2087, 2660, - 2958, 2144, 2632, - 2932, 2210, 2590, - 2894, 2286, 2528, - 2838, 2371, 2430, - 2752, 2464, 2251, - 2601, 2565, 1783, - 2263, 2672, 0, - 0, 2784, 0, - 0, 2901, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 3160, 1987, 2866, - 3160, 1988, 2866, - 3159, 1989, 2866, - 3159, 1990, 2865, - 3159, 1992, 2865, - 3159, 1994, 2864, - 3158, 1997, 2864, - 3157, 2001, 2863, - 3157, 2006, 2861, - 3155, 2013, 2860, - 3154, 2023, 2857, - 3152, 2035, 2854, - 3149, 2050, 2850, - 3145, 2070, 2844, - 3139, 2096, 2836, - 3132, 2128, 2826, - 3122, 2167, 2811, - 3109, 2215, 2791, - 3090, 2272, 2762, - 3064, 2339, 2720, - 3027, 2415, 2658, - 2971, 2501, 2558, - 2884, 2594, 2378, - 2734, 2696, 1901, - 2397, 2803, 0, - 0, 2916, 0, - 0, 3033, 0, - 0, 3153, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 3292, 2114, 2997, - 3292, 2114, 2997, - 3292, 2115, 2997, - 3292, 2116, 2997, - 3292, 2117, 2996, - 3291, 2119, 2996, - 3291, 2121, 2995, - 3291, 2124, 2995, - 3290, 2128, 2994, - 3289, 2134, 2992, - 3288, 2141, 2990, - 3286, 2150, 2988, - 3284, 2162, 2985, - 3281, 2178, 2981, - 3277, 2198, 2975, - 3272, 2224, 2967, - 3265, 2256, 2956, - 3255, 2296, 2942, - 3241, 2344, 2921, - 3223, 2402, 2892, - 3197, 2469, 2851, - 3159, 2546, 2788, - 3104, 2631, 2688, - 3017, 2725, 2507, - 2867, 2827, 2023, - 2531, 2934, 0, - 0, 3047, 0, - 0, 3164, 0, - 0, 3285, 0, - 0, 3408, 0, - 0, 3534, 0, - 0, 3661, 0, - 3425, 2242, 3128, - 3425, 2242, 3128, - 3425, 2243, 3128, - 3424, 2244, 3128, - 3424, 2245, 3128, - 3424, 2246, 3127, - 3424, 2248, 3127, - 3423, 2250, 3126, - 3423, 2253, 3126, - 3422, 2257, 3125, - 3421, 2262, 3123, - 3420, 2270, 3122, - 3418, 2279, 3119, - 3416, 2291, 3116, - 3413, 2307, 3112, - 3410, 2327, 3106, - 3404, 2353, 3098, - 3397, 2386, 3087, - 3387, 2426, 3073, - 3374, 2474, 3052, - 3355, 2532, 3023, - 3329, 2600, 2981, - 3292, 2676, 2919, - 3236, 2762, 2818, - 3150, 2856, 2636, - 3000, 2958, 2147, - 2665, 3066, 0, - 0, 3179, 0, - 0, 3296, 0, - 0, 3417, 0, - 0, 3540, 0, - 0, 3666, 0, - 3557, 2371, 3260, - 3557, 2371, 3260, - 3557, 2372, 3260, - 3557, 2372, 3259, - 3557, 2373, 3259, - 3557, 2374, 3259, - 3556, 2375, 3259, - 3556, 2377, 3258, - 3556, 2379, 3258, - 3555, 2382, 3257, - 3554, 2387, 3256, - 3554, 2392, 3255, - 3552, 2399, 3253, - 3551, 2409, 3251, - 3549, 2421, 3247, - 3546, 2437, 3243, - 3542, 2457, 3237, - 3537, 2483, 3230, - 3529, 2516, 3219, - 3520, 2556, 3204, - 3506, 2605, 3183, - 3488, 2663, 3154, - 3461, 2730, 3113, - 3424, 2807, 3050, - 3369, 2894, 2949, - 3282, 2988, 2766, - 3133, 3090, 2273, - 2798, 3197, 0, - 0, 3311, 0, - 0, 3428, 0, - 0, 3549, 0, - 0, 3672, 0, - 3689, 2501, 3391, - 3689, 2501, 3391, - 3689, 2501, 3391, - 3689, 2502, 3391, - 3689, 2502, 3391, - 3689, 2503, 3391, - 3689, 2504, 3391, - 3689, 2505, 3390, - 3688, 2507, 3390, - 3688, 2509, 3389, - 3687, 2513, 3389, - 3687, 2517, 3388, - 3686, 2522, 3386, - 3685, 2529, 3385, - 3683, 2539, 3382, - 3681, 2551, 3379, - 3678, 2567, 3375, - 3674, 2588, 3369, - 3669, 2614, 3361, - 3662, 2646, 3350, - 3652, 2687, 3336, - 3638, 2736, 3315, - 3620, 2794, 3286, - 3594, 2862, 3244, - 3556, 2939, 3181, - 3501, 3025, 3080, - 3414, 3119, 2897, - 3265, 3221, 2400, - 2931, 3329, 0, - 0, 3442, 0, - 0, 3560, 0, - 0, 3681, 0, - 3821, 2631, 3523, - 3821, 2631, 3523, - 3821, 2632, 3523, - 3821, 2632, 3523, - 3821, 2632, 3523, - 3821, 2633, 3523, - 3821, 2634, 3523, - 3821, 2635, 3522, - 3821, 2636, 3522, - 3820, 2638, 3522, - 3820, 2640, 3521, - 3820, 2643, 3520, - 3819, 2647, 3519, - 3818, 2653, 3518, - 3817, 2660, 3516, - 3815, 2669, 3514, - 3813, 2682, 3511, - 3810, 2698, 3506, - 3806, 2718, 3501, - 3801, 2745, 3493, - 3794, 2777, 3482, - 3784, 2818, 3467, - 3771, 2867, 3447, - 3752, 2925, 3418, - 3726, 2993, 3375, - 3689, 3070, 3312, - 3633, 3157, 3211, - 3547, 3251, 3028, - 3397, 3353, 2529, - 3063, 3461, 0, - 0, 3574, 0, - 0, 3692, 0, - 3954, 2762, 3655, - 3954, 2762, 3655, - 3954, 2762, 3655, - 3954, 2762, 3655, - 3954, 2763, 3655, - 3953, 2763, 3655, - 3953, 2764, 3655, - 3953, 2765, 3654, - 3953, 2766, 3654, - 3953, 2767, 3654, - 3953, 2769, 3653, - 3952, 2771, 3653, - 3952, 2774, 3652, - 3951, 2778, 3651, - 3950, 2784, 3650, - 3949, 2791, 3648, - 3947, 2800, 3646, - 3945, 2813, 3643, - 3942, 2829, 3638, - 3938, 2850, 3632, - 3933, 2876, 3625, - 3926, 2909, 3614, - 3916, 2949, 3599, - 3903, 2998, 3578, - 3884, 3057, 3549, - 3858, 3125, 3507, - 3821, 3202, 3444, - 3765, 3288, 3343, - 3679, 3383, 3159, - 3530, 3485, 2658, - 3196, 3593, 0, - 0, 3706, 0, - 4086, 2893, 3787, - 4086, 2893, 3787, - 4086, 2893, 3787, - 4086, 2893, 3787, - 4086, 2894, 3787, - 4086, 2894, 3787, - 4086, 2894, 3787, - 4086, 2895, 3786, - 4085, 2896, 3786, - 4085, 2897, 3786, - 4085, 2898, 3786, - 4085, 2900, 3785, - 4084, 2902, 3785, - 4084, 2905, 3784, - 4083, 2909, 3783, - 4082, 2915, 3782, - 4081, 2922, 3780, - 4080, 2932, 3778, - 4077, 2944, 3774, - 4074, 2960, 3770, - 4071, 2981, 3764, - 4065, 3007, 3756, - 4058, 3040, 3746, - 4048, 3081, 3731, - 4035, 3130, 3710, - 4016, 3188, 3681, - 3990, 3256, 3639, - 3953, 3334, 3576, - 3898, 3420, 3475, - 3811, 3515, 3290, - 3662, 3617, 2788, - 3328, 3725, 0, - 4095, 3024, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3026, 3918, - 4095, 3026, 3918, - 4095, 3027, 3918, - 4095, 3028, 3918, - 4095, 3030, 3918, - 4095, 3031, 3917, - 4095, 3034, 3917, - 4095, 3037, 3916, - 4095, 3041, 3915, - 4095, 3046, 3914, - 4095, 3054, 3912, - 4095, 3063, 3910, - 4095, 3076, 3906, - 4095, 3092, 3902, - 4095, 3113, 3896, - 4095, 3139, 3888, - 4095, 3172, 3878, - 4095, 3212, 3863, - 4095, 3262, 3842, - 4095, 3320, 3813, - 4095, 3388, 3771, - 4085, 3466, 3708, - 4030, 3552, 3606, - 3943, 3647, 3422, - 3794, 3749, 2919, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3156, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3158, 4050, - 4095, 3158, 4050, - 4095, 3159, 4050, - 4095, 3160, 4050, - 4095, 3161, 4050, - 4095, 3163, 4049, - 4095, 3165, 4049, - 4095, 3168, 4048, - 4095, 3173, 4047, - 4095, 3178, 4046, - 4095, 3185, 4044, - 4095, 3195, 4041, - 4095, 3207, 4038, - 4095, 3224, 4034, - 4095, 3244, 4028, - 4095, 3271, 4020, - 4095, 3304, 4009, - 4095, 3344, 3995, - 4095, 3393, 3974, - 4095, 3452, 3945, - 4095, 3520, 3903, - 4095, 3597, 3839, - 4095, 3684, 3738, - 4076, 3779, 3554, - 0, 723, 961, - 0, 734, 949, - 0, 749, 934, - 0, 769, 912, - 0, 793, 881, - 0, 824, 837, - 0, 862, 769, - 0, 908, 660, - 0, 964, 453, - 0, 1029, 0, - 0, 1104, 0, - 0, 1187, 0, - 0, 1280, 0, - 0, 1380, 0, - 0, 1486, 0, - 0, 1598, 0, - 0, 1714, 0, - 0, 1834, 0, - 0, 1957, 0, - 0, 2082, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 727, 977, - 0, 738, 966, - 0, 753, 951, - 0, 772, 930, - 0, 796, 901, - 0, 827, 858, - 0, 865, 794, - 0, 911, 691, - 0, 966, 502, - 0, 1031, 0, - 0, 1105, 0, - 0, 1189, 0, - 0, 1281, 0, - 0, 1380, 0, - 0, 1487, 0, - 0, 1598, 0, - 0, 1715, 0, - 0, 1835, 0, - 0, 1957, 0, - 0, 2082, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 732, 998, - 0, 743, 988, - 0, 758, 974, - 0, 777, 954, - 0, 801, 926, - 0, 831, 886, - 0, 869, 825, - 0, 915, 730, - 0, 969, 560, - 0, 1034, 134, - 0, 1108, 0, - 0, 1191, 0, - 0, 1282, 0, - 0, 1382, 0, - 0, 1488, 0, - 0, 1599, 0, - 0, 1715, 0, - 0, 1835, 0, - 0, 1958, 0, - 0, 2082, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 739, 1025, - 0, 750, 1015, - 0, 764, 1002, - 0, 783, 983, - 0, 807, 957, - 0, 837, 920, - 0, 874, 864, - 0, 919, 777, - 0, 973, 627, - 0, 1037, 289, - 0, 1111, 0, - 0, 1193, 0, - 0, 1284, 0, - 0, 1383, 0, - 0, 1489, 0, - 0, 1600, 0, - 0, 1716, 0, - 0, 1836, 0, - 0, 1958, 0, - 0, 2083, 0, - 0, 2209, 0, - 0, 2337, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 0, 748, 1059, - 0, 759, 1050, - 0, 773, 1037, - 0, 791, 1020, - 0, 815, 996, - 0, 844, 962, - 0, 880, 911, - 0, 925, 834, - 0, 979, 704, - 0, 1042, 438, - 0, 1115, 0, - 0, 1197, 0, - 0, 1287, 0, - 0, 1386, 0, - 0, 1491, 0, - 0, 1602, 0, - 0, 1717, 0, - 0, 1836, 0, - 0, 1959, 0, - 0, 2083, 0, - 0, 2210, 0, - 0, 2338, 0, - 0, 2466, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3119, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 450, 760, 1100, - 403, 770, 1092, - 330, 784, 1080, - 210, 802, 1065, - 0, 825, 1043, - 0, 853, 1012, - 0, 889, 967, - 0, 933, 900, - 0, 986, 790, - 0, 1048, 582, - 0, 1120, 0, - 0, 1201, 0, - 0, 1291, 0, - 0, 1388, 0, - 0, 1493, 0, - 0, 1603, 0, - 0, 1718, 0, - 0, 1837, 0, - 0, 1960, 0, - 0, 2084, 0, - 0, 2210, 0, - 0, 2338, 0, - 0, 2467, 0, - 0, 2596, 0, - 0, 2726, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 751, 775, 1150, - 727, 785, 1143, - 693, 799, 1132, - 643, 816, 1119, - 566, 838, 1099, - 437, 866, 1072, - 175, 901, 1033, - 0, 944, 975, - 0, 995, 884, - 0, 1056, 723, - 0, 1127, 342, - 0, 1207, 0, - 0, 1296, 0, - 0, 1392, 0, - 0, 1496, 0, - 0, 1606, 0, - 0, 1720, 0, - 0, 1839, 0, - 0, 1961, 0, - 0, 2085, 0, - 0, 2211, 0, - 0, 2338, 0, - 0, 2467, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2857, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3514, 0, - 0, 3646, 0, - 978, 795, 1209, - 964, 805, 1203, - 944, 817, 1194, - 916, 834, 1182, - 875, 855, 1165, - 814, 882, 1142, - 718, 916, 1108, - 545, 957, 1060, - 108, 1008, 985, - 0, 1067, 862, - 0, 1136, 615, - 0, 1215, 0, - 0, 1302, 0, - 0, 1397, 0, - 0, 1500, 0, - 0, 1609, 0, - 0, 1723, 0, - 0, 1841, 0, - 0, 1962, 0, - 0, 2086, 0, - 0, 2212, 0, - 0, 2339, 0, - 0, 2468, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2858, 0, - 0, 2988, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1170, 820, 1278, - 1161, 829, 1273, - 1148, 841, 1265, - 1130, 857, 1255, - 1105, 877, 1240, - 1070, 903, 1221, - 1017, 935, 1193, - 936, 975, 1153, - 798, 1023, 1093, - 507, 1081, 998, - 0, 1148, 830, - 0, 1225, 414, - 0, 1310, 0, - 0, 1404, 0, - 0, 1506, 0, - 0, 1613, 0, - 0, 1726, 0, - 0, 1843, 0, - 0, 1964, 0, - 0, 2087, 0, - 0, 2213, 0, - 0, 2340, 0, - 0, 2468, 0, - 0, 2597, 0, - 0, 2727, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1343, 851, 1356, - 1336, 860, 1352, - 1327, 871, 1345, - 1316, 886, 1337, - 1299, 905, 1325, - 1276, 929, 1308, - 1244, 960, 1286, - 1196, 998, 1253, - 1123, 1044, 1206, - 1004, 1099, 1134, - 769, 1164, 1015, - 0, 1238, 784, - 0, 1321, 0, - 0, 1413, 0, - 0, 1513, 0, - 0, 1619, 0, - 0, 1731, 0, - 0, 1847, 0, - 0, 1967, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 1502, 890, 1444, - 1498, 898, 1440, - 1492, 909, 1434, - 1484, 922, 1427, - 1472, 940, 1418, - 1457, 962, 1404, - 1435, 991, 1386, - 1405, 1026, 1360, - 1360, 1070, 1323, - 1293, 1122, 1269, - 1184, 1184, 1184, - 979, 1255, 1037, - 327, 1335, 715, - 0, 1425, 0, - 0, 1522, 0, - 0, 1626, 0, - 0, 1736, 0, - 0, 1851, 0, - 0, 1970, 0, - 0, 2092, 0, - 0, 2216, 0, - 0, 2343, 0, - 0, 2470, 0, - 0, 2599, 0, - 0, 2728, 0, - 0, 2859, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1654, 938, 1539, - 1651, 945, 1536, - 1647, 954, 1532, - 1641, 967, 1526, - 1633, 982, 1518, - 1622, 1003, 1507, - 1607, 1029, 1493, - 1586, 1062, 1473, - 1557, 1102, 1444, - 1515, 1151, 1403, - 1451, 1209, 1341, - 1349, 1277, 1243, - 1161, 1354, 1065, - 641, 1440, 601, - 0, 1534, 0, - 0, 1636, 0, - 0, 1744, 0, - 0, 1857, 0, - 0, 1975, 0, - 0, 2096, 0, - 0, 2219, 0, - 0, 2345, 0, - 0, 2472, 0, - 0, 2600, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1801, 994, 1642, - 1798, 1000, 1639, - 1795, 1009, 1636, - 1791, 1020, 1631, - 1785, 1034, 1625, - 1778, 1052, 1617, - 1767, 1076, 1605, - 1752, 1105, 1589, - 1732, 1142, 1567, - 1704, 1187, 1536, - 1663, 1241, 1491, - 1601, 1304, 1423, - 1504, 1377, 1311, - 1328, 1459, 1099, - 874, 1550, 384, - 0, 1649, 0, - 0, 1754, 0, - 0, 1865, 0, - 0, 1981, 0, - 0, 2100, 0, - 0, 2223, 0, - 0, 2347, 0, - 0, 2474, 0, - 0, 2602, 0, - 0, 2731, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1943, 1060, 1750, - 1941, 1066, 1748, - 1939, 1073, 1746, - 1936, 1082, 1742, - 1932, 1095, 1737, - 1926, 1111, 1731, - 1919, 1132, 1722, - 1908, 1158, 1710, - 1894, 1191, 1693, - 1874, 1231, 1670, - 1847, 1281, 1636, - 1807, 1339, 1587, - 1747, 1407, 1513, - 1652, 1484, 1389, - 1484, 1571, 1142, - 1068, 1665, 0, - 0, 1767, 0, - 0, 1876, 0, - 0, 1989, 0, - 0, 2106, 0, - 0, 2227, 0, - 0, 2351, 0, - 0, 2477, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 2083, 1136, 1864, - 2082, 1140, 1862, - 2080, 1146, 1860, - 2078, 1155, 1858, - 2075, 1165, 1854, - 2071, 1179, 1849, - 2065, 1197, 1842, - 2058, 1220, 1833, - 2047, 1249, 1820, - 2033, 1284, 1802, - 2014, 1328, 1778, - 1987, 1381, 1743, - 1947, 1444, 1691, - 1889, 1516, 1611, - 1796, 1597, 1476, - 1633, 1687, 1193, - 1242, 1784, 0, - 0, 1889, 0, - 0, 1999, 0, - 0, 2115, 0, - 0, 2234, 0, - 0, 2356, 0, - 0, 2480, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2863, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3647, 0, - 2221, 1220, 1982, - 2220, 1224, 1981, - 2218, 1229, 1979, - 2217, 1236, 1977, - 2214, 1245, 1974, - 2211, 1257, 1970, - 2207, 1272, 1965, - 2202, 1291, 1958, - 2195, 1316, 1948, - 2185, 1347, 1935, - 2171, 1386, 1917, - 2151, 1433, 1891, - 2124, 1489, 1854, - 2086, 1554, 1800, - 2028, 1629, 1716, - 1937, 1713, 1571, - 1778, 1806, 1253, - 1403, 1906, 0, - 0, 2013, 0, - 0, 2125, 0, - 0, 2242, 0, - 0, 2362, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2357, 1313, 2103, - 2356, 1316, 2102, - 2355, 1321, 2101, - 2354, 1326, 2099, - 2352, 1334, 2097, - 2350, 1343, 2094, - 2347, 1356, 2090, - 2343, 1372, 2085, - 2338, 1393, 2078, - 2330, 1419, 2068, - 2320, 1452, 2054, - 2307, 1493, 2035, - 2288, 1543, 2009, - 2261, 1601, 1971, - 2222, 1669, 1915, - 2165, 1747, 1826, - 2076, 1834, 1673, - 1919, 1929, 1323, - 1556, 2031, 0, - 0, 2139, 0, - 0, 2253, 0, - 0, 2370, 0, - 0, 2491, 0, - 0, 2615, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2996, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2492, 1414, 2227, - 2491, 1416, 2226, - 2491, 1420, 2225, - 2490, 1424, 2224, - 2489, 1430, 2222, - 2487, 1438, 2220, - 2485, 1448, 2217, - 2482, 1461, 2213, - 2478, 1479, 2208, - 2472, 1501, 2200, - 2465, 1528, 2190, - 2455, 1563, 2176, - 2442, 1606, 2157, - 2423, 1657, 2130, - 2396, 1718, 2091, - 2358, 1788, 2033, - 2301, 1868, 1942, - 2213, 1957, 1782, - 2058, 2053, 1403, - 1703, 2157, 0, - 0, 2267, 0, - 0, 2381, 0, - 0, 2500, 0, - 0, 2621, 0, - 0, 2745, 0, - 0, 2871, 0, - 0, 2999, 0, - 0, 3128, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 2626, 1521, 2353, - 2626, 1523, 2352, - 2625, 1526, 2351, - 2625, 1529, 2350, - 2624, 1534, 2349, - 2623, 1540, 2347, - 2621, 1548, 2345, - 2619, 1559, 2342, - 2616, 1573, 2338, - 2612, 1591, 2332, - 2607, 1614, 2325, - 2599, 1643, 2315, - 2589, 1679, 2301, - 2576, 1723, 2281, - 2557, 1776, 2253, - 2531, 1839, 2214, - 2493, 1911, 2154, - 2436, 1992, 2061, - 2348, 2082, 1895, - 2195, 2180, 1491, - 1846, 2285, 0, - 0, 2395, 0, - 0, 2511, 0, - 0, 2630, 0, - 0, 2752, 0, - 0, 2876, 0, - 0, 3003, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 2760, 1633, 2480, - 2760, 1635, 2479, - 2759, 1637, 2479, - 2759, 1640, 2478, - 2758, 1643, 2477, - 2757, 1648, 2476, - 2756, 1655, 2474, - 2755, 1663, 2472, - 2752, 1674, 2469, - 2749, 1689, 2465, - 2745, 1707, 2459, - 2740, 1731, 2451, - 2733, 1761, 2441, - 2723, 1798, 2427, - 2710, 1843, 2407, - 2691, 1898, 2379, - 2664, 1962, 2339, - 2627, 2035, 2278, - 2571, 2118, 2183, - 2483, 2209, 2013, - 2331, 2308, 1588, - 1986, 2414, 0, - 0, 2525, 0, - 0, 2641, 0, - 0, 2760, 0, - 0, 2883, 0, - 0, 3007, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 2893, 1750, 2608, - 2893, 1751, 2608, - 2893, 1753, 2608, - 2893, 1755, 2607, - 2892, 1758, 2606, - 2891, 1762, 2605, - 2891, 1767, 2604, - 2889, 1773, 2602, - 2888, 1782, 2600, - 2886, 1793, 2597, - 2883, 1808, 2593, - 2879, 1827, 2587, - 2873, 1852, 2579, - 2866, 1882, 2569, - 2856, 1920, 2554, - 2843, 1967, 2534, - 2824, 2022, 2506, - 2798, 2087, 2465, - 2760, 2161, 2404, - 2704, 2245, 2308, - 2617, 2337, 2134, - 2465, 2437, 1691, - 2123, 2543, 0, - 0, 2655, 0, - 0, 2771, 0, - 0, 2891, 0, - 0, 3014, 0, - 0, 3139, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3652, 0, - 3026, 1870, 2738, - 3026, 1871, 2737, - 3026, 1873, 2737, - 3026, 1874, 2737, - 3025, 1876, 2736, - 3025, 1879, 2735, - 3024, 1883, 2735, - 3023, 1888, 2733, - 3022, 1895, 2732, - 3021, 1904, 2729, - 3018, 1916, 2726, - 3015, 1931, 2722, - 3012, 1950, 2716, - 3006, 1975, 2708, - 2999, 2006, 2698, - 2989, 2045, 2683, - 2976, 2092, 2663, - 2957, 2148, 2635, - 2931, 2214, 2593, - 2893, 2289, 2532, - 2838, 2373, 2434, - 2750, 2466, 2258, - 2600, 2567, 1800, - 2260, 2673, 0, - 0, 2786, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 3159, 1993, 2868, - 3159, 1994, 2868, - 3159, 1995, 2867, - 3159, 1996, 2867, - 3159, 1998, 2867, - 3158, 2000, 2866, - 3158, 2003, 2865, - 3157, 2007, 2864, - 3156, 2012, 2863, - 3155, 2019, 2861, - 3153, 2028, 2859, - 3151, 2040, 2856, - 3148, 2056, 2852, - 3144, 2075, 2846, - 3139, 2101, 2838, - 3132, 2132, 2827, - 3122, 2172, 2813, - 3109, 2219, 2793, - 3090, 2276, 2764, - 3064, 2342, 2723, - 3026, 2418, 2661, - 2971, 2503, 2562, - 2884, 2596, 2383, - 2733, 2697, 1915, - 2395, 2804, 0, - 0, 2917, 0, - 0, 3033, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 3292, 2119, 2998, - 3292, 2119, 2998, - 3292, 2120, 2998, - 3292, 2121, 2998, - 3291, 2122, 2997, - 3291, 2124, 2997, - 3291, 2126, 2997, - 3290, 2129, 2996, - 3290, 2133, 2995, - 3289, 2138, 2994, - 3287, 2145, 2992, - 3286, 2155, 2989, - 3284, 2167, 2986, - 3281, 2182, 2982, - 3277, 2202, 2976, - 3272, 2228, 2968, - 3264, 2260, 2958, - 3255, 2299, 2943, - 3241, 2347, 2923, - 3222, 2405, 2894, - 3196, 2471, 2852, - 3159, 2548, 2790, - 3103, 2633, 2691, - 3017, 2727, 2510, - 2866, 2828, 2033, - 2530, 2935, 0, - 0, 3048, 0, - 0, 3165, 0, - 0, 3285, 0, - 0, 3409, 0, - 0, 3534, 0, - 0, 3661, 0, - 3424, 2246, 3129, - 3424, 2246, 3129, - 3424, 2246, 3129, - 3424, 2247, 3129, - 3424, 2248, 3129, - 3424, 2249, 3128, - 3424, 2251, 3128, - 3423, 2253, 3127, - 3423, 2257, 3127, - 3422, 2261, 3126, - 3421, 2266, 3124, - 3420, 2273, 3123, - 3418, 2282, 3120, - 3416, 2294, 3117, - 3413, 2310, 3113, - 3409, 2330, 3107, - 3404, 2356, 3099, - 3397, 2388, 3088, - 3387, 2428, 3074, - 3374, 2477, 3053, - 3355, 2534, 3024, - 3329, 2601, 2983, - 3291, 2678, 2920, - 3236, 2763, 2820, - 3149, 2857, 2639, - 2999, 2959, 2155, - 2663, 3066, 0, - 0, 3179, 0, - 0, 3297, 0, - 0, 3417, 0, - 0, 3540, 0, - 0, 3666, 0, - 3557, 2374, 3260, - 3557, 2374, 3260, - 3557, 2374, 3260, - 3557, 2375, 3260, - 3556, 2376, 3260, - 3556, 2377, 3260, - 3556, 2378, 3259, - 3556, 2380, 3259, - 3555, 2382, 3259, - 3555, 2385, 3258, - 3554, 2389, 3257, - 3553, 2395, 3255, - 3552, 2402, 3254, - 3551, 2411, 3251, - 3548, 2423, 3248, - 3546, 2439, 3244, - 3542, 2459, 3238, - 3536, 2485, 3230, - 3529, 2518, 3220, - 3519, 2558, 3205, - 3506, 2607, 3184, - 3487, 2664, 3155, - 3461, 2732, 3114, - 3424, 2808, 3051, - 3368, 2894, 2950, - 3282, 2989, 2768, - 3132, 3090, 2279, - 2797, 3198, 0, - 0, 3311, 0, - 0, 3428, 0, - 0, 3549, 0, - 0, 3672, 0, - 3689, 2503, 3392, - 3689, 2503, 3392, - 3689, 2503, 3392, - 3689, 2504, 3392, - 3689, 2504, 3392, - 3689, 2505, 3391, - 3689, 2506, 3391, - 3688, 2507, 3391, - 3688, 2509, 3390, - 3688, 2511, 3390, - 3687, 2515, 3389, - 3687, 2519, 3388, - 3686, 2524, 3387, - 3684, 2531, 3385, - 3683, 2541, 3383, - 3681, 2553, 3380, - 3678, 2569, 3375, - 3674, 2589, 3369, - 3669, 2615, 3362, - 3661, 2648, 3351, - 3652, 2688, 3336, - 3638, 2737, 3316, - 3620, 2795, 3287, - 3594, 2863, 3245, - 3556, 2940, 3182, - 3501, 3026, 3081, - 3414, 3120, 2898, - 3265, 3222, 2405, - 2930, 3330, 0, - 0, 3443, 0, - 0, 3560, 0, - 0, 3681, 0, - 3821, 2633, 3524, - 3821, 2633, 3523, - 3821, 2633, 3523, - 3821, 2633, 3523, - 3821, 2634, 3523, - 3821, 2634, 3523, - 3821, 2635, 3523, - 3821, 2636, 3523, - 3821, 2637, 3522, - 3820, 2639, 3522, - 3820, 2642, 3521, - 3819, 2645, 3521, - 3819, 2649, 3520, - 3818, 2654, 3518, - 3817, 2661, 3517, - 3815, 2671, 3514, - 3813, 2683, 3511, - 3810, 2699, 3507, - 3806, 2720, 3501, - 3801, 2746, 3493, - 3794, 2779, 3482, - 3784, 2819, 3468, - 3770, 2868, 3447, - 3752, 2926, 3418, - 3726, 2994, 3376, - 3688, 3071, 3313, - 3633, 3157, 3212, - 3547, 3252, 3029, - 3397, 3353, 2532, - 3063, 3461, 0, - 0, 3575, 0, - 0, 3692, 0, - 3954, 2763, 3655, - 3954, 2763, 3655, - 3954, 2763, 3655, - 3954, 2764, 3655, - 3953, 2764, 3655, - 3953, 2764, 3655, - 3953, 2765, 3655, - 3953, 2766, 3655, - 3953, 2767, 3654, - 3953, 2768, 3654, - 3953, 2770, 3654, - 3952, 2772, 3653, - 3952, 2775, 3652, - 3951, 2779, 3651, - 3950, 2785, 3650, - 3949, 2792, 3648, - 3947, 2802, 3646, - 3945, 2814, 3643, - 3942, 2830, 3639, - 3938, 2851, 3633, - 3933, 2877, 3625, - 3926, 2910, 3614, - 3916, 2950, 3599, - 3903, 2999, 3579, - 3884, 3057, 3550, - 3858, 3125, 3508, - 3821, 3202, 3444, - 3765, 3289, 3344, - 3679, 3383, 3160, - 3529, 3485, 2661, - 3195, 3593, 0, - 0, 3706, 0, - 4086, 2894, 3787, - 4086, 2894, 3787, - 4086, 2894, 3787, - 4086, 2894, 3787, - 4086, 2895, 3787, - 4086, 2895, 3787, - 4086, 2895, 3787, - 4085, 2896, 3787, - 4085, 2897, 3786, - 4085, 2898, 3786, - 4085, 2899, 3786, - 4085, 2901, 3786, - 4084, 2903, 3785, - 4084, 2906, 3784, - 4083, 2910, 3783, - 4082, 2916, 3782, - 4081, 2923, 3780, - 4079, 2933, 3778, - 4077, 2945, 3775, - 4074, 2961, 3770, - 4071, 2982, 3765, - 4065, 3008, 3757, - 4058, 3041, 3746, - 4048, 3081, 3731, - 4035, 3130, 3710, - 4016, 3189, 3681, - 3990, 3257, 3639, - 3953, 3334, 3576, - 3898, 3420, 3475, - 3811, 3515, 3291, - 3662, 3617, 2790, - 3328, 3725, 0, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3025, 3919, - 4095, 3026, 3919, - 4095, 3026, 3919, - 4095, 3026, 3919, - 4095, 3027, 3919, - 4095, 3027, 3919, - 4095, 3028, 3918, - 4095, 3029, 3918, - 4095, 3030, 3918, - 4095, 3032, 3917, - 4095, 3034, 3917, - 4095, 3037, 3916, - 4095, 3042, 3915, - 4095, 3047, 3914, - 4095, 3054, 3912, - 4095, 3064, 3910, - 4095, 3076, 3906, - 4095, 3092, 3902, - 4095, 3113, 3896, - 4095, 3139, 3888, - 4095, 3172, 3878, - 4095, 3213, 3863, - 4095, 3262, 3842, - 4095, 3320, 3813, - 4095, 3388, 3771, - 4085, 3466, 3708, - 4030, 3552, 3607, - 3943, 3647, 3422, - 3794, 3749, 2920, - 4095, 3156, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3159, 4050, - 4095, 3159, 4050, - 4095, 3160, 4050, - 4095, 3162, 4050, - 4095, 3163, 4049, - 4095, 3166, 4049, - 4095, 3169, 4048, - 4095, 3173, 4047, - 4095, 3179, 4046, - 4095, 3186, 4044, - 4095, 3195, 4042, - 4095, 3208, 4038, - 4095, 3224, 4034, - 4095, 3245, 4028, - 4095, 3271, 4020, - 4095, 3304, 4010, - 4095, 3345, 3995, - 4095, 3394, 3974, - 4095, 3452, 3945, - 4095, 3520, 3903, - 4095, 3598, 3840, - 4095, 3684, 3738, - 4075, 3779, 3554, - 0, 843, 1089, - 0, 852, 1080, - 0, 864, 1068, - 0, 879, 1052, - 0, 898, 1030, - 0, 923, 998, - 0, 954, 952, - 0, 992, 882, - 0, 1039, 767, - 0, 1094, 545, - 0, 1160, 0, - 0, 1234, 0, - 0, 1318, 0, - 0, 1411, 0, - 0, 1511, 0, - 0, 1617, 0, - 0, 1729, 0, - 0, 1846, 0, - 0, 1966, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 0, 846, 1101, - 0, 855, 1093, - 0, 867, 1082, - 0, 881, 1066, - 0, 901, 1044, - 0, 925, 1013, - 0, 956, 969, - 0, 994, 901, - 0, 1041, 792, - 0, 1096, 585, - 0, 1161, 0, - 0, 1236, 0, - 0, 1319, 0, - 0, 1412, 0, - 0, 1512, 0, - 0, 1618, 0, - 0, 1730, 0, - 0, 1846, 0, - 0, 1966, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 0, 850, 1117, - 0, 859, 1109, - 0, 870, 1098, - 0, 885, 1083, - 0, 904, 1063, - 0, 928, 1033, - 0, 959, 990, - 0, 997, 926, - 0, 1043, 823, - 0, 1098, 634, - 0, 1163, 101, - 0, 1237, 0, - 0, 1321, 0, - 0, 1413, 0, - 0, 1513, 0, - 0, 1619, 0, - 0, 1730, 0, - 0, 1847, 0, - 0, 1967, 0, - 0, 2089, 0, - 0, 2214, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 0, 856, 1138, - 0, 864, 1130, - 0, 875, 1120, - 0, 890, 1106, - 0, 909, 1086, - 0, 933, 1058, - 0, 963, 1018, - 0, 1001, 957, - 0, 1047, 862, - 0, 1101, 692, - 0, 1166, 266, - 0, 1240, 0, - 0, 1323, 0, - 0, 1414, 0, - 0, 1514, 0, - 0, 1620, 0, - 0, 1731, 0, - 0, 1847, 0, - 0, 1967, 0, - 0, 2090, 0, - 0, 2215, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3251, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 0, 863, 1164, - 0, 871, 1157, - 0, 882, 1147, - 0, 897, 1134, - 0, 915, 1115, - 0, 939, 1089, - 0, 969, 1052, - 0, 1006, 996, - 0, 1051, 909, - 0, 1106, 759, - 0, 1169, 421, - 0, 1243, 0, - 0, 1325, 0, - 0, 1417, 0, - 0, 1515, 0, - 0, 1621, 0, - 0, 1732, 0, - 0, 1848, 0, - 0, 1968, 0, - 0, 2090, 0, - 0, 2215, 0, - 0, 2341, 0, - 0, 2469, 0, - 0, 2598, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3646, 0, - 133, 872, 1198, - 32, 880, 1191, - 0, 891, 1182, - 0, 905, 1169, - 0, 923, 1152, - 0, 947, 1128, - 0, 976, 1094, - 0, 1013, 1043, - 0, 1057, 966, - 0, 1111, 836, - 0, 1174, 570, - 0, 1247, 0, - 0, 1329, 0, - 0, 1419, 0, - 0, 1518, 0, - 0, 1623, 0, - 0, 1734, 0, - 0, 1849, 0, - 0, 1968, 0, - 0, 2091, 0, - 0, 2215, 0, - 0, 2342, 0, - 0, 2470, 0, - 0, 2599, 0, - 0, 2728, 0, - 0, 2858, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 615, 884, 1238, - 582, 892, 1232, - 535, 902, 1224, - 462, 916, 1213, - 342, 934, 1197, - 107, 957, 1175, - 0, 986, 1144, - 0, 1021, 1100, - 0, 1065, 1032, - 0, 1118, 922, - 0, 1180, 714, - 0, 1252, 39, - 0, 1333, 0, - 0, 1423, 0, - 0, 1521, 0, - 0, 1625, 0, - 0, 1735, 0, - 0, 1851, 0, - 0, 1970, 0, - 0, 2092, 0, - 0, 2216, 0, - 0, 2342, 0, - 0, 2470, 0, - 0, 2599, 0, - 0, 2728, 0, - 0, 2859, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 901, 899, 1288, - 883, 907, 1282, - 859, 917, 1275, - 825, 931, 1265, - 775, 948, 1251, - 698, 970, 1231, - 569, 998, 1204, - 307, 1033, 1165, - 0, 1076, 1107, - 0, 1127, 1016, - 0, 1188, 855, - 0, 1259, 474, - 0, 1339, 0, - 0, 1428, 0, - 0, 1524, 0, - 0, 1628, 0, - 0, 1738, 0, - 0, 1852, 0, - 0, 1971, 0, - 0, 2093, 0, - 0, 2217, 0, - 0, 2343, 0, - 0, 2470, 0, - 0, 2599, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2989, 0, - 0, 3120, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1121, 919, 1346, - 1110, 927, 1341, - 1096, 937, 1335, - 1076, 949, 1326, - 1048, 966, 1314, - 1007, 987, 1297, - 947, 1014, 1274, - 850, 1048, 1241, - 677, 1089, 1192, - 240, 1140, 1117, - 0, 1199, 994, - 0, 1268, 747, - 0, 1347, 0, - 0, 1434, 0, - 0, 1530, 0, - 0, 1632, 0, - 0, 1741, 0, - 0, 1855, 0, - 0, 1973, 0, - 0, 2094, 0, - 0, 2218, 0, - 0, 2344, 0, - 0, 2471, 0, - 0, 2600, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1309, 945, 1414, - 1302, 952, 1410, - 1293, 961, 1405, - 1280, 973, 1397, - 1262, 989, 1387, - 1237, 1009, 1372, - 1202, 1035, 1353, - 1149, 1067, 1325, - 1068, 1107, 1285, - 930, 1156, 1225, - 639, 1213, 1130, - 0, 1280, 962, - 0, 1357, 546, - 0, 1442, 0, - 0, 1536, 0, - 0, 1638, 0, - 0, 1745, 0, - 0, 1858, 0, - 0, 1976, 0, - 0, 2096, 0, - 0, 2220, 0, - 0, 2345, 0, - 0, 2472, 0, - 0, 2600, 0, - 0, 2729, 0, - 0, 2859, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 1479, 977, 1492, - 1475, 983, 1488, - 1468, 992, 1484, - 1460, 1003, 1477, - 1448, 1018, 1469, - 1431, 1037, 1457, - 1408, 1061, 1441, - 1376, 1092, 1418, - 1328, 1130, 1385, - 1255, 1176, 1338, - 1136, 1231, 1266, - 901, 1296, 1148, - 0, 1370, 916, - 0, 1453, 0, - 0, 1545, 0, - 0, 1645, 0, - 0, 1751, 0, - 0, 1863, 0, - 0, 1979, 0, - 0, 2099, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1638, 1016, 1579, - 1635, 1022, 1576, - 1630, 1030, 1572, - 1624, 1041, 1567, - 1616, 1054, 1559, - 1604, 1072, 1550, - 1589, 1094, 1537, - 1567, 1123, 1518, - 1537, 1158, 1492, - 1492, 1202, 1455, - 1425, 1254, 1401, - 1316, 1316, 1316, - 1111, 1387, 1169, - 459, 1468, 847, - 0, 1557, 0, - 0, 1654, 0, - 0, 1758, 0, - 0, 1869, 0, - 0, 1983, 0, - 0, 2102, 0, - 0, 2224, 0, - 0, 2348, 0, - 0, 2475, 0, - 0, 2602, 0, - 0, 2731, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1789, 1064, 1673, - 1786, 1070, 1671, - 1783, 1077, 1668, - 1779, 1086, 1664, - 1773, 1099, 1658, - 1765, 1115, 1650, - 1754, 1135, 1640, - 1739, 1161, 1625, - 1719, 1194, 1605, - 1689, 1234, 1576, - 1647, 1283, 1535, - 1583, 1341, 1473, - 1481, 1409, 1375, - 1293, 1486, 1197, - 773, 1572, 733, - 0, 1667, 0, - 0, 1768, 0, - 0, 1876, 0, - 0, 1989, 0, - 0, 2107, 0, - 0, 2228, 0, - 0, 2351, 0, - 0, 2477, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1934, 1121, 1775, - 1933, 1126, 1774, - 1930, 1133, 1771, - 1927, 1141, 1768, - 1923, 1152, 1763, - 1917, 1166, 1757, - 1910, 1184, 1749, - 1899, 1208, 1737, - 1885, 1237, 1721, - 1864, 1274, 1700, - 1836, 1319, 1668, - 1795, 1373, 1623, - 1734, 1436, 1555, - 1636, 1509, 1443, - 1460, 1592, 1231, - 1006, 1682, 516, - 0, 1781, 0, - 0, 1886, 0, - 0, 1997, 0, - 0, 2113, 0, - 0, 2232, 0, - 0, 2355, 0, - 0, 2479, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2863, 0, - 0, 2992, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 2076, 1188, 1884, - 2075, 1192, 1882, - 2074, 1198, 1880, - 2071, 1205, 1878, - 2068, 1214, 1874, - 2064, 1227, 1869, - 2058, 1243, 1863, - 2051, 1264, 1854, - 2041, 1290, 1842, - 2026, 1323, 1825, - 2007, 1363, 1802, - 1979, 1413, 1768, - 1939, 1471, 1720, - 1879, 1539, 1645, - 1784, 1616, 1521, - 1616, 1703, 1274, - 1200, 1798, 0, - 0, 1899, 0, - 0, 2008, 0, - 0, 2121, 0, - 0, 2239, 0, - 0, 2359, 0, - 0, 2483, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2216, 1264, 1997, - 2215, 1268, 1996, - 2214, 1272, 1995, - 2212, 1279, 1992, - 2210, 1287, 1990, - 2207, 1297, 1986, - 2203, 1311, 1981, - 2197, 1329, 1974, - 2190, 1352, 1965, - 2179, 1381, 1952, - 2165, 1417, 1935, - 2146, 1461, 1910, - 2119, 1513, 1875, - 2079, 1576, 1823, - 2021, 1648, 1743, - 1928, 1729, 1608, - 1765, 1819, 1325, - 1374, 1916, 0, - 0, 2021, 0, - 0, 2132, 0, - 0, 2247, 0, - 0, 2366, 0, - 0, 2488, 0, - 0, 2612, 0, - 0, 2739, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2353, 1349, 2115, - 2353, 1352, 2114, - 2352, 1356, 2113, - 2350, 1361, 2111, - 2349, 1368, 2109, - 2347, 1377, 2106, - 2344, 1389, 2102, - 2340, 1404, 2097, - 2334, 1423, 2090, - 2327, 1448, 2080, - 2317, 1479, 2067, - 2303, 1518, 2049, - 2284, 1565, 2023, - 2257, 1621, 1987, - 2218, 1686, 1932, - 2160, 1761, 1848, - 2069, 1846, 1703, - 1910, 1938, 1386, - 1535, 2039, 0, - 0, 2145, 0, - 0, 2257, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2489, 1443, 2236, - 2489, 1445, 2235, - 2488, 1449, 2234, - 2487, 1453, 2233, - 2486, 1458, 2231, - 2484, 1466, 2229, - 2482, 1475, 2226, - 2479, 1488, 2222, - 2475, 1504, 2217, - 2470, 1525, 2210, - 2462, 1551, 2200, - 2452, 1584, 2186, - 2439, 1625, 2167, - 2420, 1675, 2141, - 2393, 1733, 2103, - 2355, 1802, 2047, - 2297, 1879, 1958, - 2208, 1966, 1805, - 2051, 2061, 1456, - 1688, 2163, 0, - 0, 2271, 0, - 0, 2385, 0, - 0, 2502, 0, - 0, 2623, 0, - 0, 2747, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3128, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2624, 1544, 2359, - 2624, 1546, 2359, - 2624, 1549, 2358, - 2623, 1552, 2357, - 2622, 1556, 2356, - 2621, 1562, 2354, - 2619, 1570, 2352, - 2617, 1580, 2349, - 2614, 1593, 2345, - 2610, 1611, 2340, - 2605, 1633, 2332, - 2597, 1661, 2322, - 2587, 1695, 2308, - 2574, 1738, 2289, - 2555, 1789, 2262, - 2528, 1850, 2223, - 2490, 1921, 2165, - 2433, 2000, 2074, - 2345, 2089, 1914, - 2190, 2186, 1535, - 1835, 2289, 0, - 0, 2399, 0, - 0, 2513, 0, - 0, 2632, 0, - 0, 2753, 0, - 0, 2877, 0, - 0, 3004, 0, - 0, 3131, 0, - 0, 3260, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 2759, 1651, 2485, - 2758, 1653, 2485, - 2758, 1655, 2484, - 2758, 1658, 2483, - 2757, 1661, 2482, - 2756, 1666, 2481, - 2755, 1672, 2480, - 2753, 1680, 2477, - 2751, 1691, 2474, - 2748, 1705, 2470, - 2744, 1723, 2465, - 2739, 1746, 2457, - 2731, 1775, 2447, - 2721, 1811, 2433, - 2708, 1855, 2413, - 2689, 1908, 2385, - 2663, 1971, 2346, - 2625, 2043, 2287, - 2568, 2124, 2193, - 2480, 2214, 2027, - 2327, 2312, 1623, - 1978, 2417, 0, - 0, 2527, 0, - 0, 2643, 0, - 0, 2762, 0, - 0, 2884, 0, - 0, 3008, 0, - 0, 3135, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 2892, 1764, 2612, - 2892, 1765, 2612, - 2892, 1767, 2612, - 2892, 1769, 2611, - 2891, 1772, 2610, - 2890, 1775, 2609, - 2889, 1780, 2608, - 2888, 1787, 2606, - 2887, 1795, 2604, - 2884, 1806, 2601, - 2882, 1821, 2597, - 2878, 1839, 2591, - 2872, 1863, 2584, - 2865, 1893, 2573, - 2855, 1930, 2559, - 2842, 1976, 2539, - 2823, 2030, 2511, - 2797, 2094, 2471, - 2759, 2167, 2411, - 2703, 2250, 2315, - 2615, 2341, 2145, - 2463, 2440, 1720, - 2118, 2546, 0, - 0, 2657, 0, - 0, 2773, 0, - 0, 2892, 0, - 0, 3015, 0, - 0, 3140, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3653, 0, - 3026, 1881, 2741, - 3026, 1882, 2740, - 3025, 1883, 2740, - 3025, 1885, 2740, - 3025, 1887, 2739, - 3024, 1890, 2738, - 3024, 1894, 2737, - 3023, 1899, 2736, - 3021, 1905, 2734, - 3020, 1914, 2732, - 3018, 1926, 2729, - 3015, 1940, 2725, - 3011, 1960, 2719, - 3005, 1984, 2712, - 2998, 2015, 2701, - 2988, 2053, 2687, - 2975, 2099, 2667, - 2956, 2154, 2638, - 2930, 2219, 2598, - 2892, 2294, 2537, - 2836, 2377, 2440, - 2749, 2469, 2266, - 2598, 2569, 1823, - 2256, 2675, 0, - 0, 2787, 0, - 0, 2903, 0, - 0, 3023, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 3159, 2002, 2870, - 3159, 2002, 2870, - 3158, 2003, 2870, - 3158, 2005, 2869, - 3158, 2006, 2869, - 3158, 2008, 2868, - 3157, 2011, 2868, - 3156, 2015, 2867, - 3156, 2020, 2865, - 3154, 2027, 2864, - 3153, 2036, 2861, - 3151, 2048, 2858, - 3148, 2063, 2854, - 3144, 2082, 2848, - 3138, 2107, 2840, - 3131, 2139, 2830, - 3121, 2177, 2815, - 3108, 2224, 2795, - 3089, 2280, 2767, - 3063, 2346, 2726, - 3025, 2421, 2664, - 2970, 2506, 2566, - 2883, 2598, 2390, - 2732, 2699, 1933, - 2392, 2805, 0, - 0, 2918, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3403, 0, - 0, 3529, 0, - 0, 3658, 0, - 3291, 2125, 3000, - 3291, 2125, 3000, - 3291, 2126, 3000, - 3291, 2127, 2999, - 3291, 2128, 2999, - 3291, 2130, 2999, - 3290, 2132, 2998, - 3290, 2135, 2997, - 3289, 2139, 2996, - 3288, 2145, 2995, - 3287, 2151, 2993, - 3285, 2161, 2991, - 3283, 2172, 2988, - 3280, 2188, 2984, - 3276, 2208, 2978, - 3271, 2233, 2970, - 3264, 2264, 2960, - 3254, 2304, 2945, - 3241, 2351, 2925, - 3222, 2408, 2896, - 3196, 2474, 2855, - 3158, 2550, 2793, - 3103, 2635, 2694, - 3016, 2728, 2515, - 2865, 2829, 2047, - 2527, 2936, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3534, 0, - 0, 3661, 0, - 3424, 2250, 3130, - 3424, 2251, 3130, - 3424, 2251, 3130, - 3424, 2252, 3130, - 3424, 2253, 3130, - 3423, 2254, 3130, - 3423, 2256, 3129, - 3423, 2258, 3129, - 3422, 2261, 3128, - 3422, 2265, 3127, - 3421, 2271, 3126, - 3420, 2278, 3124, - 3418, 2287, 3122, - 3416, 2299, 3118, - 3413, 2314, 3114, - 3409, 2334, 3108, - 3404, 2360, 3101, - 3396, 2392, 3090, - 3387, 2431, 3075, - 3373, 2479, 3055, - 3355, 2537, 3026, - 3328, 2603, 2984, - 3291, 2680, 2922, - 3235, 2765, 2823, - 3149, 2859, 2643, - 2999, 2960, 2165, - 2662, 3067, 0, - 0, 3180, 0, - 0, 3297, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3666, 0, - 3557, 2377, 3261, - 3557, 2378, 3261, - 3556, 2378, 3261, - 3556, 2379, 3261, - 3556, 2379, 3261, - 3556, 2380, 3261, - 3556, 2382, 3260, - 3556, 2383, 3260, - 3555, 2386, 3259, - 3555, 2389, 3259, - 3554, 2393, 3258, - 3553, 2398, 3256, - 3552, 2405, 3255, - 3550, 2414, 3252, - 3548, 2427, 3249, - 3545, 2442, 3245, - 3541, 2462, 3239, - 3536, 2488, 3231, - 3529, 2520, 3221, - 3519, 2560, 3206, - 3506, 2609, 3185, - 3487, 2666, 3157, - 3461, 2733, 3115, - 3423, 2810, 3052, - 3368, 2896, 2952, - 3281, 2989, 2771, - 3131, 3091, 2287, - 2795, 3198, 0, - 0, 3311, 0, - 0, 3429, 0, - 0, 3549, 0, - 0, 3673, 0, - 3689, 2506, 3393, - 3689, 2506, 3393, - 3689, 2506, 3392, - 3689, 2506, 3392, - 3689, 2507, 3392, - 3689, 2508, 3392, - 3688, 2509, 3392, - 3688, 2510, 3392, - 3688, 2512, 3391, - 3688, 2514, 3391, - 3687, 2517, 3390, - 3686, 2521, 3389, - 3686, 2527, 3388, - 3684, 2534, 3386, - 3683, 2543, 3383, - 3681, 2555, 3380, - 3678, 2571, 3376, - 3674, 2592, 3370, - 3668, 2617, 3362, - 3661, 2650, 3352, - 3651, 2690, 3337, - 3638, 2739, 3316, - 3619, 2796, 3287, - 3593, 2864, 3246, - 3556, 2941, 3183, - 3500, 3026, 3083, - 3414, 3121, 2900, - 3264, 3222, 2411, - 2929, 3330, 0, - 0, 3443, 0, - 0, 3560, 0, - 0, 3681, 0, - 3821, 2635, 3524, - 3821, 2635, 3524, - 3821, 2635, 3524, - 3821, 2635, 3524, - 3821, 2636, 3524, - 3821, 2636, 3524, - 3821, 2637, 3523, - 3821, 2638, 3523, - 3821, 2639, 3523, - 3820, 2641, 3523, - 3820, 2644, 3522, - 3819, 2647, 3521, - 3819, 2651, 3520, - 3818, 2656, 3519, - 3817, 2663, 3517, - 3815, 2673, 3515, - 3813, 2685, 3512, - 3810, 2701, 3507, - 3806, 2721, 3502, - 3801, 2747, 3494, - 3794, 2780, 3483, - 3784, 2820, 3468, - 3770, 2869, 3448, - 3752, 2927, 3419, - 3726, 2995, 3377, - 3688, 3072, 3314, - 3633, 3158, 3213, - 3546, 3252, 3030, - 3397, 3354, 2537, - 3062, 3462, 0, - 0, 3575, 0, - 0, 3692, 0, - 3953, 2765, 3656, - 3953, 2765, 3656, - 3953, 2765, 3656, - 3953, 2765, 3656, - 3953, 2765, 3655, - 3953, 2766, 3655, - 3953, 2766, 3655, - 3953, 2767, 3655, - 3953, 2768, 3655, - 3953, 2770, 3655, - 3952, 2771, 3654, - 3952, 2774, 3654, - 3952, 2777, 3653, - 3951, 2781, 3652, - 3950, 2786, 3651, - 3949, 2793, 3649, - 3947, 2803, 3646, - 3945, 2815, 3643, - 3942, 2831, 3639, - 3938, 2852, 3633, - 3933, 2878, 3625, - 3926, 2911, 3615, - 3916, 2951, 3600, - 3903, 3000, 3579, - 3884, 3058, 3550, - 3858, 3126, 3508, - 3821, 3203, 3445, - 3765, 3289, 3344, - 3679, 3384, 3161, - 3529, 3485, 2664, - 3195, 3593, 0, - 0, 3707, 0, - 4086, 2895, 3787, - 4086, 2895, 3787, - 4086, 2895, 3787, - 4086, 2896, 3787, - 4086, 2896, 3787, - 4086, 2896, 3787, - 4086, 2896, 3787, - 4085, 2897, 3787, - 4085, 2898, 3787, - 4085, 2899, 3787, - 4085, 2900, 3786, - 4085, 2902, 3786, - 4084, 2904, 3785, - 4084, 2907, 3785, - 4083, 2911, 3784, - 4082, 2917, 3782, - 4081, 2924, 3780, - 4079, 2934, 3778, - 4077, 2946, 3775, - 4074, 2962, 3771, - 4070, 2983, 3765, - 4065, 3009, 3757, - 4058, 3042, 3746, - 4048, 3082, 3731, - 4035, 3131, 3711, - 4016, 3189, 3682, - 3990, 3257, 3640, - 3953, 3334, 3577, - 3897, 3421, 3476, - 3811, 3515, 3292, - 3662, 3617, 2793, - 3327, 3725, 0, - 4095, 3026, 3919, - 4095, 3026, 3919, - 4095, 3026, 3919, - 4095, 3026, 3919, - 4095, 3026, 3919, - 4095, 3027, 3919, - 4095, 3027, 3919, - 4095, 3027, 3919, - 4095, 3028, 3919, - 4095, 3029, 3919, - 4095, 3030, 3918, - 4095, 3031, 3918, - 4095, 3033, 3918, - 4095, 3035, 3917, - 4095, 3038, 3916, - 4095, 3042, 3915, - 4095, 3048, 3914, - 4095, 3055, 3912, - 4095, 3065, 3910, - 4095, 3077, 3907, - 4095, 3093, 3902, - 4095, 3114, 3897, - 4095, 3140, 3889, - 4095, 3173, 3878, - 4095, 3213, 3863, - 4095, 3263, 3843, - 4095, 3321, 3813, - 4095, 3389, 3771, - 4085, 3466, 3708, - 4030, 3552, 3607, - 3943, 3647, 3423, - 3794, 3749, 2922, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3157, 4051, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3159, 4051, - 4095, 3159, 4051, - 4095, 3160, 4050, - 4095, 3161, 4050, - 4095, 3162, 4050, - 4095, 3164, 4049, - 4095, 3166, 4049, - 4095, 3170, 4048, - 4095, 3174, 4047, - 4095, 3179, 4046, - 4095, 3186, 4044, - 4095, 3196, 4042, - 4095, 3208, 4039, - 4095, 3224, 4034, - 4095, 3245, 4028, - 4095, 3271, 4021, - 4095, 3304, 4010, - 4095, 3345, 3995, - 4095, 3394, 3974, - 4095, 3453, 3945, - 4095, 3520, 3903, - 4095, 3598, 3840, - 4095, 3684, 3739, - 4075, 3779, 3555, - 0, 966, 1218, - 0, 973, 1211, - 0, 982, 1202, - 0, 994, 1191, - 0, 1009, 1174, - 0, 1028, 1151, - 0, 1053, 1119, - 0, 1084, 1071, - 0, 1122, 999, - 0, 1169, 879, - 0, 1225, 645, - 0, 1291, 0, - 0, 1366, 0, - 0, 1450, 0, - 0, 1542, 0, - 0, 1643, 0, - 0, 1749, 0, - 0, 1861, 0, - 0, 1978, 0, - 0, 2098, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3383, 0, - 0, 3515, 0, - 0, 3647, 0, - 0, 969, 1227, - 0, 975, 1221, - 0, 984, 1212, - 0, 996, 1201, - 0, 1011, 1185, - 0, 1030, 1162, - 0, 1055, 1130, - 0, 1086, 1084, - 0, 1124, 1014, - 0, 1171, 899, - 0, 1226, 677, - 0, 1292, 0, - 0, 1367, 0, - 0, 1451, 0, - 0, 1543, 0, - 0, 1643, 0, - 0, 1750, 0, - 0, 1862, 0, - 0, 1978, 0, - 0, 2098, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 0, 972, 1239, - 0, 978, 1233, - 0, 987, 1225, - 0, 999, 1214, - 0, 1014, 1198, - 0, 1033, 1176, - 0, 1057, 1146, - 0, 1088, 1101, - 0, 1126, 1033, - 0, 1173, 924, - 0, 1228, 717, - 0, 1293, 53, - 0, 1368, 0, - 0, 1452, 0, - 0, 1544, 0, - 0, 1644, 0, - 0, 1750, 0, - 0, 1862, 0, - 0, 1978, 0, - 0, 2098, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 0, 976, 1255, - 0, 982, 1249, - 0, 991, 1241, - 0, 1002, 1230, - 0, 1017, 1215, - 0, 1036, 1195, - 0, 1061, 1165, - 0, 1091, 1122, - 0, 1129, 1058, - 0, 1175, 955, - 0, 1231, 766, - 0, 1295, 233, - 0, 1370, 0, - 0, 1453, 0, - 0, 1545, 0, - 0, 1645, 0, - 0, 1751, 0, - 0, 1863, 0, - 0, 1979, 0, - 0, 2099, 0, - 0, 2221, 0, - 0, 2346, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 0, 981, 1276, - 0, 988, 1270, - 0, 996, 1263, - 0, 1008, 1252, - 0, 1022, 1238, - 0, 1041, 1218, - 0, 1065, 1190, - 0, 1095, 1150, - 0, 1133, 1090, - 0, 1179, 994, - 0, 1234, 824, - 0, 1298, 398, - 0, 1372, 0, - 0, 1455, 0, - 0, 1547, 0, - 0, 1646, 0, - 0, 1752, 0, - 0, 1863, 0, - 0, 1979, 0, - 0, 2099, 0, - 0, 2222, 0, - 0, 2347, 0, - 0, 2473, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 0, 988, 1302, - 0, 995, 1297, - 0, 1003, 1289, - 0, 1014, 1280, - 0, 1029, 1266, - 0, 1047, 1247, - 0, 1071, 1221, - 0, 1101, 1184, - 0, 1138, 1128, - 0, 1183, 1041, - 0, 1238, 891, - 0, 1301, 553, - 0, 1375, 0, - 0, 1457, 0, - 0, 1549, 0, - 0, 1648, 0, - 0, 1753, 0, - 0, 1864, 0, - 0, 1980, 0, - 0, 2100, 0, - 0, 2222, 0, - 0, 2347, 0, - 0, 2474, 0, - 0, 2601, 0, - 0, 2730, 0, - 0, 2860, 0, - 0, 2990, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 329, 998, 1335, - 265, 1004, 1330, - 164, 1012, 1323, - 0, 1023, 1314, - 0, 1037, 1301, - 0, 1055, 1284, - 0, 1079, 1260, - 0, 1108, 1226, - 0, 1145, 1175, - 0, 1189, 1098, - 0, 1243, 968, - 0, 1306, 702, - 0, 1379, 0, - 0, 1461, 0, - 0, 1551, 0, - 0, 1650, 0, - 0, 1755, 0, - 0, 1866, 0, - 0, 1981, 0, - 0, 2101, 0, - 0, 2223, 0, - 0, 2347, 0, - 0, 2474, 0, - 0, 2602, 0, - 0, 2731, 0, - 0, 2860, 0, - 0, 2991, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 770, 1010, 1375, - 747, 1016, 1370, - 715, 1024, 1364, - 667, 1035, 1356, - 594, 1048, 1345, - 474, 1066, 1329, - 239, 1089, 1307, - 0, 1118, 1276, - 0, 1154, 1232, - 0, 1197, 1164, - 0, 1250, 1054, - 0, 1312, 846, - 0, 1384, 171, - 0, 1465, 0, - 0, 1555, 0, - 0, 1653, 0, - 0, 1757, 0, - 0, 1868, 0, - 0, 1983, 0, - 0, 2102, 0, - 0, 2224, 0, - 0, 2348, 0, - 0, 2474, 0, - 0, 2602, 0, - 0, 2731, 0, - 0, 2860, 0, - 0, 2991, 0, - 0, 3121, 0, - 0, 3252, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1045, 1025, 1424, - 1033, 1031, 1420, - 1016, 1039, 1414, - 992, 1049, 1407, - 957, 1063, 1397, - 907, 1080, 1383, - 830, 1102, 1364, - 702, 1130, 1336, - 440, 1165, 1297, - 0, 1208, 1239, - 0, 1260, 1148, - 0, 1321, 987, - 0, 1391, 606, - 0, 1471, 0, - 0, 1560, 0, - 0, 1657, 0, - 0, 1760, 0, - 0, 1870, 0, - 0, 1985, 0, - 0, 2103, 0, - 0, 2225, 0, - 0, 2349, 0, - 0, 2475, 0, - 0, 2603, 0, - 0, 2731, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1261, 1046, 1482, - 1253, 1051, 1478, - 1242, 1059, 1473, - 1228, 1069, 1467, - 1208, 1082, 1458, - 1180, 1098, 1446, - 1139, 1119, 1429, - 1079, 1146, 1406, - 982, 1180, 1373, - 810, 1222, 1324, - 372, 1272, 1249, - 0, 1331, 1126, - 0, 1400, 879, - 0, 1479, 0, - 0, 1566, 0, - 0, 1662, 0, - 0, 1764, 0, - 0, 1873, 0, - 0, 1987, 0, - 0, 2105, 0, - 0, 2226, 0, - 0, 2350, 0, - 0, 2476, 0, - 0, 2603, 0, - 0, 2732, 0, - 0, 2861, 0, - 0, 2991, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1446, 1072, 1550, - 1441, 1077, 1546, - 1434, 1084, 1542, - 1425, 1093, 1537, - 1412, 1105, 1529, - 1394, 1121, 1519, - 1370, 1141, 1505, - 1334, 1167, 1485, - 1282, 1199, 1457, - 1200, 1239, 1417, - 1063, 1288, 1357, - 771, 1345, 1263, - 0, 1412, 1094, - 0, 1489, 678, - 0, 1575, 0, - 0, 1668, 0, - 0, 1770, 0, - 0, 1877, 0, - 0, 1990, 0, - 0, 2108, 0, - 0, 2228, 0, - 0, 2352, 0, - 0, 2477, 0, - 0, 2604, 0, - 0, 2732, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3515, 0, - 0, 3647, 0, - 1615, 1104, 1627, - 1611, 1109, 1624, - 1607, 1115, 1621, - 1600, 1124, 1616, - 1592, 1135, 1609, - 1580, 1150, 1601, - 1563, 1169, 1589, - 1540, 1193, 1573, - 1508, 1224, 1550, - 1460, 1262, 1518, - 1388, 1308, 1470, - 1268, 1363, 1398, - 1033, 1428, 1280, - 0, 1502, 1048, - 0, 1585, 57, - 0, 1677, 0, - 0, 1777, 0, - 0, 1883, 0, - 0, 1995, 0, - 0, 2111, 0, - 0, 2231, 0, - 0, 2354, 0, - 0, 2479, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 1772, 1144, 1713, - 1770, 1148, 1711, - 1767, 1154, 1708, - 1762, 1162, 1704, - 1756, 1173, 1699, - 1748, 1186, 1692, - 1737, 1204, 1682, - 1721, 1226, 1669, - 1699, 1255, 1650, - 1669, 1290, 1624, - 1624, 1334, 1588, - 1557, 1386, 1533, - 1448, 1448, 1448, - 1243, 1519, 1301, - 591, 1600, 979, - 0, 1689, 0, - 0, 1786, 0, - 0, 1891, 0, - 0, 2001, 0, - 0, 2116, 0, - 0, 2234, 0, - 0, 2356, 0, - 0, 2481, 0, - 0, 2607, 0, - 0, 2734, 0, - 0, 2863, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3647, 0, - 1923, 1192, 1807, - 1921, 1196, 1805, - 1919, 1202, 1803, - 1915, 1209, 1800, - 1911, 1218, 1796, - 1905, 1231, 1790, - 1897, 1247, 1782, - 1886, 1267, 1772, - 1871, 1293, 1757, - 1851, 1326, 1737, - 1821, 1366, 1708, - 1779, 1415, 1667, - 1715, 1473, 1605, - 1613, 1541, 1507, - 1426, 1618, 1329, - 905, 1704, 865, - 0, 1799, 0, - 0, 1900, 0, - 0, 2008, 0, - 0, 2122, 0, - 0, 2239, 0, - 0, 2360, 0, - 0, 2483, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2068, 1250, 1909, - 2067, 1253, 1908, - 2065, 1258, 1906, - 2063, 1265, 1903, - 2059, 1273, 1900, - 2055, 1284, 1895, - 2049, 1298, 1889, - 2042, 1317, 1881, - 2031, 1340, 1869, - 2017, 1370, 1854, - 1997, 1406, 1832, - 1968, 1451, 1801, - 1927, 1505, 1755, - 1866, 1569, 1687, - 1768, 1641, 1575, - 1592, 1724, 1364, - 1138, 1815, 648, - 0, 1913, 0, - 0, 2018, 0, - 0, 2129, 0, - 0, 2245, 0, - 0, 2364, 0, - 0, 2487, 0, - 0, 2612, 0, - 0, 2738, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3124, 0, - 0, 3255, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 2210, 1317, 2017, - 2209, 1320, 2016, - 2207, 1324, 2014, - 2206, 1330, 2012, - 2203, 1337, 2010, - 2200, 1347, 2006, - 2196, 1359, 2001, - 2191, 1375, 1995, - 2183, 1396, 1986, - 2173, 1422, 1974, - 2158, 1455, 1957, - 2139, 1496, 1934, - 2111, 1545, 1900, - 2071, 1603, 1852, - 2011, 1671, 1777, - 1916, 1749, 1653, - 1748, 1835, 1406, - 1333, 1930, 0, - 0, 2032, 0, - 0, 2140, 0, - 0, 2253, 0, - 0, 2371, 0, - 0, 2492, 0, - 0, 2615, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2996, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2349, 1394, 2130, - 2348, 1396, 2129, - 2347, 1400, 2128, - 2346, 1404, 2127, - 2344, 1411, 2125, - 2342, 1419, 2122, - 2339, 1429, 2118, - 2335, 1443, 2113, - 2329, 1461, 2106, - 2322, 1484, 2097, - 2312, 1513, 2084, - 2298, 1549, 2067, - 2278, 1593, 2042, - 2251, 1646, 2007, - 2211, 1708, 1955, - 2153, 1780, 1875, - 2061, 1861, 1740, - 1898, 1951, 1457, - 1507, 2049, 0, - 0, 2153, 0, - 0, 2264, 0, - 0, 2379, 0, - 0, 2498, 0, - 0, 2620, 0, - 0, 2744, 0, - 0, 2871, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 2486, 1479, 2248, - 2485, 1482, 2247, - 2485, 1484, 2246, - 2484, 1488, 2245, - 2483, 1493, 2243, - 2481, 1500, 2241, - 2479, 1509, 2238, - 2476, 1521, 2234, - 2472, 1536, 2229, - 2466, 1555, 2222, - 2459, 1580, 2213, - 2449, 1611, 2199, - 2435, 1650, 2181, - 2416, 1697, 2155, - 2389, 1753, 2119, - 2350, 1818, 2064, - 2292, 1893, 1980, - 2201, 1978, 1835, - 2042, 2070, 1518, - 1668, 2171, 0, - 0, 2277, 0, - 0, 2389, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 2622, 1573, 2368, - 2621, 1575, 2368, - 2621, 1578, 2367, - 2620, 1581, 2366, - 2619, 1585, 2365, - 2618, 1590, 2363, - 2616, 1598, 2361, - 2614, 1607, 2358, - 2611, 1620, 2354, - 2607, 1636, 2349, - 2602, 1657, 2342, - 2595, 1683, 2332, - 2585, 1716, 2318, - 2571, 1757, 2299, - 2552, 1807, 2273, - 2525, 1865, 2235, - 2487, 1934, 2179, - 2430, 2011, 2091, - 2340, 2098, 1937, - 2183, 2193, 1588, - 1820, 2295, 0, - 0, 2403, 0, - 0, 2517, 0, - 0, 2634, 0, - 0, 2755, 0, - 0, 2879, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3260, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2757, 1675, 2492, - 2756, 1676, 2491, - 2756, 1678, 2491, - 2756, 1681, 2490, - 2755, 1684, 2489, - 2754, 1688, 2488, - 2753, 1694, 2486, - 2751, 1702, 2484, - 2749, 1712, 2481, - 2746, 1726, 2477, - 2742, 1743, 2472, - 2737, 1765, 2464, - 2729, 1793, 2454, - 2719, 1827, 2440, - 2706, 1870, 2421, - 2687, 1922, 2394, - 2660, 1982, 2355, - 2622, 2053, 2297, - 2566, 2132, 2206, - 2477, 2221, 2046, - 2322, 2318, 1667, - 1967, 2421, 0, - 0, 2531, 0, - 0, 2645, 0, - 0, 2764, 0, - 0, 2885, 0, - 0, 3010, 0, - 0, 3136, 0, - 0, 3263, 0, - 0, 3392, 0, - 0, 3521, 0, - 0, 3651, 0, - 2891, 1782, 2617, - 2891, 1784, 2617, - 2890, 1785, 2617, - 2890, 1787, 2616, - 2890, 1790, 2615, - 2889, 1793, 2615, - 2888, 1798, 2613, - 2887, 1804, 2612, - 2885, 1812, 2609, - 2883, 1823, 2606, - 2880, 1837, 2602, - 2876, 1855, 2597, - 2871, 1878, 2589, - 2863, 1907, 2579, - 2854, 1943, 2565, - 2840, 1987, 2545, - 2821, 2040, 2518, - 2795, 2103, 2478, - 2757, 2175, 2419, - 2701, 2256, 2325, - 2612, 2346, 2159, - 2459, 2444, 1755, - 2110, 2549, 0, - 0, 2659, 0, - 0, 2775, 0, - 0, 2894, 0, - 0, 3016, 0, - 0, 3140, 0, - 0, 3267, 0, - 0, 3395, 0, - 0, 3523, 0, - 0, 3653, 0, - 3025, 1895, 2745, - 3024, 1896, 2744, - 3024, 1897, 2744, - 3024, 1899, 2744, - 3024, 1901, 2743, - 3023, 1904, 2742, - 3022, 1908, 2741, - 3022, 1912, 2740, - 3020, 1919, 2738, - 3019, 1927, 2736, - 3017, 1938, 2733, - 3014, 1953, 2729, - 3010, 1971, 2723, - 3004, 1995, 2716, - 2997, 2025, 2705, - 2987, 2062, 2691, - 2974, 2108, 2671, - 2955, 2162, 2643, - 2929, 2226, 2603, - 2891, 2299, 2543, - 2835, 2382, 2447, - 2747, 2473, 2277, - 2595, 2572, 1852, - 2250, 2678, 0, - 0, 2789, 0, - 0, 2905, 0, - 0, 3024, 0, - 0, 3147, 0, - 0, 3272, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 3158, 2013, 2873, - 3158, 2013, 2873, - 3158, 2014, 2872, - 3157, 2015, 2872, - 3157, 2017, 2872, - 3157, 2019, 2871, - 3156, 2022, 2871, - 3156, 2026, 2870, - 3155, 2031, 2868, - 3154, 2038, 2867, - 3152, 2046, 2864, - 3150, 2058, 2861, - 3147, 2073, 2857, - 3143, 2092, 2851, - 3138, 2116, 2844, - 3130, 2147, 2833, - 3120, 2185, 2819, - 3107, 2231, 2799, - 3088, 2286, 2770, - 3062, 2351, 2730, - 3024, 2426, 2669, - 2968, 2509, 2572, - 2881, 2601, 2398, - 2730, 2701, 1955, - 2388, 2807, 0, - 0, 2919, 0, - 0, 3035, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 3291, 2133, 3002, - 3291, 2134, 3002, - 3291, 2135, 3002, - 3291, 2135, 3002, - 3290, 2137, 3001, - 3290, 2138, 3001, - 3290, 2141, 3000, - 3289, 2143, 3000, - 3288, 2147, 2999, - 3288, 2153, 2997, - 3286, 2159, 2996, - 3285, 2168, 2993, - 3283, 2180, 2990, - 3280, 2195, 2986, - 3276, 2215, 2980, - 3270, 2239, 2973, - 3263, 2271, 2962, - 3253, 2309, 2947, - 3240, 2356, 2927, - 3221, 2412, 2899, - 3195, 2478, 2858, - 3157, 2553, 2796, - 3102, 2638, 2698, - 3015, 2730, 2522, - 2864, 2831, 2065, - 2524, 2938, 0, - 0, 3050, 0, - 0, 3166, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 3424, 2257, 3132, - 3424, 2257, 3132, - 3423, 2258, 3132, - 3423, 2258, 3132, - 3423, 2259, 3132, - 3423, 2261, 3131, - 3423, 2262, 3131, - 3422, 2264, 3130, - 3422, 2267, 3130, - 3421, 2271, 3129, - 3420, 2277, 3127, - 3419, 2284, 3126, - 3417, 2293, 3123, - 3415, 2304, 3120, - 3412, 2320, 3116, - 3408, 2340, 3110, - 3403, 2365, 3102, - 3396, 2397, 3092, - 3386, 2436, 3077, - 3373, 2483, 3057, - 3354, 2540, 3028, - 3328, 2606, 2987, - 3290, 2682, 2925, - 3235, 2767, 2826, - 3148, 2860, 2647, - 2997, 2961, 2179, - 2659, 3068, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3666, 0, - 3556, 2382, 3263, - 3556, 2382, 3263, - 3556, 2383, 3262, - 3556, 2383, 3262, - 3556, 2384, 3262, - 3556, 2385, 3262, - 3556, 2386, 3262, - 3555, 2388, 3261, - 3555, 2390, 3261, - 3554, 2393, 3260, - 3554, 2397, 3259, - 3553, 2403, 3258, - 3552, 2410, 3256, - 3550, 2419, 3254, - 3548, 2431, 3250, - 3545, 2446, 3246, - 3541, 2466, 3240, - 3536, 2492, 3233, - 3529, 2524, 3222, - 3519, 2564, 3207, - 3505, 2612, 3187, - 3487, 2669, 3158, - 3461, 2736, 3117, - 3423, 2812, 3054, - 3368, 2897, 2955, - 3281, 2991, 2775, - 3131, 3092, 2297, - 2794, 3199, 0, - 0, 3312, 0, - 0, 3429, 0, - 0, 3550, 0, - 0, 3673, 0, - 3689, 2509, 3394, - 3689, 2509, 3393, - 3689, 2510, 3393, - 3689, 2510, 3393, - 3688, 2511, 3393, - 3688, 2511, 3393, - 3688, 2512, 3393, - 3688, 2514, 3392, - 3688, 2515, 3392, - 3687, 2518, 3392, - 3687, 2521, 3391, - 3686, 2525, 3390, - 3685, 2530, 3389, - 3684, 2537, 3387, - 3682, 2546, 3384, - 3680, 2559, 3381, - 3677, 2574, 3377, - 3673, 2595, 3371, - 3668, 2620, 3363, - 3661, 2653, 3353, - 3651, 2692, 3338, - 3638, 2741, 3318, - 3619, 2798, 3289, - 3593, 2865, 3247, - 3556, 2942, 3184, - 3500, 3028, 3084, - 3413, 3122, 2903, - 3264, 3223, 2419, - 2928, 3331, 0, - 0, 3443, 0, - 0, 3561, 0, - 0, 3681, 0, - 3821, 2637, 3525, - 3821, 2638, 3525, - 3821, 2638, 3525, - 3821, 2638, 3525, - 3821, 2639, 3524, - 3821, 2639, 3524, - 3821, 2640, 3524, - 3821, 2641, 3524, - 3820, 2642, 3524, - 3820, 2644, 3523, - 3820, 2646, 3523, - 3819, 2649, 3522, - 3818, 2653, 3521, - 3818, 2659, 3520, - 3816, 2666, 3518, - 3815, 2675, 3516, - 3813, 2687, 3512, - 3810, 2703, 3508, - 3806, 2724, 3502, - 3801, 2750, 3494, - 3793, 2782, 3484, - 3784, 2822, 3469, - 3770, 2871, 3448, - 3752, 2929, 3420, - 3725, 2996, 3378, - 3688, 3073, 3315, - 3633, 3159, 3215, - 3546, 3253, 3032, - 3396, 3354, 2543, - 3061, 3462, 0, - 0, 3575, 0, - 0, 3692, 0, - 3953, 2767, 3656, - 3953, 2767, 3656, - 3953, 2767, 3656, - 3953, 2767, 3656, - 3953, 2768, 3656, - 3953, 2768, 3656, - 3953, 2769, 3656, - 3953, 2769, 3656, - 3953, 2770, 3655, - 3953, 2772, 3655, - 3952, 2773, 3655, - 3952, 2776, 3654, - 3951, 2779, 3653, - 3951, 2783, 3652, - 3950, 2788, 3651, - 3949, 2795, 3649, - 3947, 2805, 3647, - 3945, 2817, 3644, - 3942, 2833, 3639, - 3938, 2854, 3634, - 3933, 2880, 3626, - 3926, 2912, 3615, - 3916, 2952, 3600, - 3902, 3001, 3580, - 3884, 3059, 3551, - 3858, 3127, 3509, - 3820, 3204, 3446, - 3765, 3290, 3345, - 3678, 3384, 3162, - 3529, 3486, 2669, - 3194, 3594, 0, - 0, 3707, 0, - 4086, 2897, 3788, - 4086, 2897, 3788, - 4086, 2897, 3788, - 4086, 2897, 3788, - 4086, 2897, 3788, - 4085, 2898, 3788, - 4085, 2898, 3787, - 4085, 2899, 3787, - 4085, 2899, 3787, - 4085, 2900, 3787, - 4085, 2902, 3787, - 4085, 2903, 3786, - 4084, 2906, 3786, - 4084, 2909, 3785, - 4083, 2913, 3784, - 4082, 2918, 3783, - 4081, 2926, 3781, - 4079, 2935, 3779, - 4077, 2947, 3775, - 4074, 2963, 3771, - 4070, 2984, 3765, - 4065, 3010, 3757, - 4058, 3043, 3747, - 4048, 3083, 3732, - 4035, 3132, 3711, - 4016, 3190, 3682, - 3990, 3258, 3640, - 3953, 3335, 3577, - 3897, 3421, 3476, - 3811, 3516, 3293, - 3661, 3617, 2796, - 3327, 3725, 0, - 4095, 3027, 3919, - 4095, 3027, 3919, - 4095, 3027, 3919, - 4095, 3027, 3919, - 4095, 3028, 3919, - 4095, 3028, 3919, - 4095, 3028, 3919, - 4095, 3029, 3919, - 4095, 3029, 3919, - 4095, 3030, 3919, - 4095, 3031, 3919, - 4095, 3032, 3918, - 4095, 3034, 3918, - 4095, 3036, 3917, - 4095, 3039, 3917, - 4095, 3044, 3916, - 4095, 3049, 3914, - 4095, 3056, 3913, - 4095, 3066, 3910, - 4095, 3078, 3907, - 4095, 3094, 3903, - 4095, 3115, 3897, - 4095, 3141, 3889, - 4095, 3174, 3878, - 4095, 3214, 3863, - 4095, 3263, 3843, - 4095, 3321, 3814, - 4095, 3389, 3772, - 4085, 3467, 3709, - 4030, 3553, 3608, - 3943, 3647, 3424, - 3794, 3749, 2925, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3158, 4051, - 4095, 3159, 4051, - 4095, 3159, 4051, - 4095, 3159, 4051, - 4095, 3160, 4051, - 4095, 3160, 4051, - 4095, 3161, 4051, - 4095, 3162, 4050, - 4095, 3163, 4050, - 4095, 3165, 4050, - 4095, 3167, 4049, - 4095, 3170, 4048, - 4095, 3175, 4047, - 4095, 3180, 4046, - 4095, 3187, 4044, - 4095, 3197, 4042, - 4095, 3209, 4039, - 4095, 3225, 4035, - 4095, 3246, 4029, - 4095, 3272, 4021, - 4095, 3305, 4010, - 4095, 3346, 3995, - 4095, 3395, 3975, - 4095, 3453, 3946, - 4095, 3521, 3903, - 4095, 3598, 3840, - 4095, 3685, 3739, - 4075, 3779, 3555, - 0, 1092, 1347, - 0, 1097, 1342, - 0, 1104, 1336, - 0, 1112, 1327, - 0, 1124, 1315, - 0, 1139, 1298, - 0, 1159, 1275, - 0, 1183, 1242, - 0, 1215, 1193, - 0, 1253, 1119, - 0, 1300, 996, - 0, 1356, 751, - 0, 1422, 0, - 0, 1497, 0, - 0, 1581, 0, - 0, 1674, 0, - 0, 1774, 0, - 0, 1881, 0, - 0, 1993, 0, - 0, 2110, 0, - 0, 2230, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 0, 1093, 1354, - 0, 1098, 1350, - 0, 1105, 1343, - 0, 1114, 1335, - 0, 1126, 1323, - 0, 1141, 1306, - 0, 1160, 1283, - 0, 1185, 1251, - 0, 1216, 1203, - 0, 1254, 1131, - 0, 1301, 1011, - 0, 1357, 777, - 0, 1423, 0, - 0, 1498, 0, - 0, 1582, 0, - 0, 1674, 0, - 0, 1775, 0, - 0, 1881, 0, - 0, 1993, 0, - 0, 2110, 0, - 0, 2230, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 0, 1096, 1364, - 0, 1101, 1359, - 0, 1107, 1353, - 0, 1116, 1344, - 0, 1128, 1333, - 0, 1143, 1317, - 0, 1162, 1294, - 0, 1187, 1262, - 0, 1218, 1216, - 0, 1256, 1146, - 0, 1303, 1031, - 0, 1359, 809, - 0, 1424, 0, - 0, 1499, 0, - 0, 1583, 0, - 0, 1675, 0, - 0, 1775, 0, - 0, 1882, 0, - 0, 1994, 0, - 0, 2110, 0, - 0, 2230, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 0, 1099, 1376, - 0, 1104, 1371, - 0, 1110, 1365, - 0, 1119, 1357, - 0, 1131, 1346, - 0, 1146, 1330, - 0, 1165, 1308, - 0, 1189, 1278, - 0, 1220, 1233, - 0, 1258, 1165, - 0, 1305, 1056, - 0, 1360, 850, - 0, 1425, 185, - 0, 1500, 0, - 0, 1584, 0, - 0, 1676, 0, - 0, 1776, 0, - 0, 1882, 0, - 0, 1994, 0, - 0, 2110, 0, - 0, 2230, 0, - 0, 2353, 0, - 0, 2478, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 0, 1103, 1392, - 0, 1108, 1387, - 0, 1114, 1381, - 0, 1123, 1373, - 0, 1135, 1363, - 0, 1149, 1348, - 0, 1168, 1327, - 0, 1193, 1297, - 0, 1223, 1255, - 0, 1261, 1190, - 0, 1307, 1087, - 0, 1363, 898, - 0, 1427, 365, - 0, 1502, 0, - 0, 1585, 0, - 0, 1677, 0, - 0, 1777, 0, - 0, 1883, 0, - 0, 1995, 0, - 0, 2111, 0, - 0, 2231, 0, - 0, 2354, 0, - 0, 2479, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 0, 1108, 1412, - 0, 1113, 1408, - 0, 1120, 1402, - 0, 1128, 1395, - 0, 1140, 1384, - 0, 1154, 1370, - 0, 1173, 1350, - 0, 1197, 1322, - 0, 1227, 1282, - 0, 1265, 1222, - 0, 1311, 1126, - 0, 1366, 956, - 0, 1430, 530, - 0, 1504, 0, - 0, 1587, 0, - 0, 1679, 0, - 0, 1778, 0, - 0, 1884, 0, - 0, 1995, 0, - 0, 2112, 0, - 0, 2231, 0, - 0, 2354, 0, - 0, 2479, 0, - 0, 2605, 0, - 0, 2733, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3122, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 0, 1115, 1438, - 0, 1120, 1434, - 0, 1127, 1429, - 0, 1135, 1421, - 0, 1146, 1412, - 0, 1161, 1398, - 0, 1179, 1380, - 0, 1203, 1353, - 0, 1233, 1316, - 0, 1270, 1260, - 0, 1315, 1173, - 0, 1370, 1023, - 0, 1434, 686, - 0, 1507, 0, - 0, 1590, 0, - 0, 1681, 0, - 0, 1780, 0, - 0, 1885, 0, - 0, 1996, 0, - 0, 2112, 0, - 0, 2232, 0, - 0, 2354, 0, - 0, 2479, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2862, 0, - 0, 2992, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 503, 1125, 1470, - 461, 1130, 1467, - 397, 1136, 1462, - 296, 1144, 1455, - 111, 1155, 1446, - 0, 1169, 1433, - 0, 1188, 1416, - 0, 1211, 1392, - 0, 1240, 1358, - 0, 1277, 1307, - 0, 1322, 1230, - 0, 1375, 1100, - 0, 1438, 834, - 0, 1511, 0, - 0, 1593, 0, - 0, 1683, 0, - 0, 1782, 0, - 0, 1887, 0, - 0, 1998, 0, - 0, 2113, 0, - 0, 2233, 0, - 0, 2355, 0, - 0, 2480, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2863, 0, - 0, 2992, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3384, 0, - 0, 3516, 0, - 0, 3647, 0, - 919, 1137, 1510, - 902, 1142, 1507, - 879, 1148, 1502, - 847, 1156, 1496, - 799, 1167, 1488, - 726, 1180, 1477, - 606, 1198, 1461, - 371, 1221, 1439, - 0, 1250, 1409, - 0, 1286, 1364, - 0, 1330, 1296, - 0, 1382, 1186, - 0, 1444, 978, - 0, 1516, 303, - 0, 1597, 0, - 0, 1687, 0, - 0, 1785, 0, - 0, 1889, 0, - 0, 2000, 0, - 0, 2115, 0, - 0, 2234, 0, - 0, 2356, 0, - 0, 2480, 0, - 0, 2606, 0, - 0, 2734, 0, - 0, 2863, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3253, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3647, 0, - 1186, 1153, 1559, - 1177, 1158, 1556, - 1165, 1164, 1552, - 1148, 1171, 1546, - 1124, 1182, 1539, - 1090, 1195, 1529, - 1039, 1212, 1515, - 962, 1234, 1496, - 834, 1262, 1468, - 572, 1297, 1429, - 0, 1340, 1371, - 0, 1392, 1280, - 0, 1453, 1119, - 0, 1523, 738, - 0, 1603, 0, - 0, 1692, 0, - 0, 1789, 0, - 0, 1892, 0, - 0, 2002, 0, - 0, 2117, 0, - 0, 2235, 0, - 0, 2357, 0, - 0, 2481, 0, - 0, 2607, 0, - 0, 2735, 0, - 0, 2863, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3647, 0, - 1398, 1174, 1617, - 1393, 1178, 1614, - 1385, 1184, 1610, - 1375, 1191, 1606, - 1360, 1201, 1599, - 1340, 1214, 1590, - 1312, 1230, 1578, - 1271, 1251, 1561, - 1211, 1278, 1538, - 1114, 1312, 1505, - 942, 1354, 1456, - 504, 1404, 1382, - 0, 1463, 1258, - 0, 1532, 1012, - 0, 1611, 0, - 0, 1698, 0, - 0, 1794, 0, - 0, 1896, 0, - 0, 2005, 0, - 0, 2119, 0, - 0, 2237, 0, - 0, 2358, 0, - 0, 2482, 0, - 0, 2608, 0, - 0, 2735, 0, - 0, 2864, 0, - 0, 2993, 0, - 0, 3123, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3647, 0, - 1582, 1200, 1684, - 1579, 1204, 1682, - 1573, 1209, 1679, - 1567, 1216, 1674, - 1557, 1225, 1669, - 1544, 1237, 1661, - 1527, 1253, 1651, - 1502, 1273, 1637, - 1466, 1299, 1617, - 1414, 1331, 1589, - 1332, 1371, 1549, - 1195, 1420, 1489, - 903, 1477, 1395, - 0, 1544, 1226, - 0, 1621, 810, - 0, 1707, 0, - 0, 1801, 0, - 0, 1902, 0, - 0, 2010, 0, - 0, 2123, 0, - 0, 2240, 0, - 0, 2360, 0, - 0, 2484, 0, - 0, 2609, 0, - 0, 2736, 0, - 0, 2864, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 1750, 1232, 1761, - 1747, 1236, 1759, - 1744, 1241, 1756, - 1739, 1248, 1753, - 1732, 1256, 1748, - 1724, 1268, 1742, - 1712, 1282, 1733, - 1695, 1301, 1721, - 1672, 1326, 1705, - 1640, 1356, 1682, - 1592, 1394, 1650, - 1520, 1440, 1602, - 1400, 1495, 1530, - 1165, 1560, 1412, - 102, 1634, 1180, - 0, 1718, 189, - 0, 1809, 0, - 0, 1909, 0, - 0, 2015, 0, - 0, 2127, 0, - 0, 2243, 0, - 0, 2363, 0, - 0, 2486, 0, - 0, 2611, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 1906, 1272, 1846, - 1905, 1276, 1845, - 1902, 1280, 1843, - 1899, 1286, 1840, - 1894, 1294, 1836, - 1888, 1305, 1831, - 1880, 1319, 1824, - 1869, 1336, 1814, - 1853, 1359, 1801, - 1831, 1387, 1782, - 1801, 1422, 1757, - 1756, 1466, 1720, - 1689, 1518, 1665, - 1580, 1580, 1580, - 1375, 1651, 1434, - 723, 1732, 1111, - 0, 1821, 0, - 0, 1918, 0, - 0, 2023, 0, - 0, 2133, 0, - 0, 2248, 0, - 0, 2366, 0, - 0, 2488, 0, - 0, 2613, 0, - 0, 2739, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2056, 1321, 1941, - 2055, 1324, 1939, - 2053, 1328, 1938, - 2051, 1334, 1935, - 2047, 1341, 1932, - 2043, 1350, 1928, - 2037, 1363, 1922, - 2029, 1379, 1914, - 2018, 1399, 1904, - 2003, 1425, 1889, - 1983, 1458, 1869, - 1953, 1498, 1840, - 1911, 1547, 1799, - 1847, 1605, 1737, - 1745, 1673, 1639, - 1558, 1750, 1461, - 1037, 1836, 997, - 0, 1931, 0, - 0, 2032, 0, - 0, 2140, 0, - 0, 2254, 0, - 0, 2371, 0, - 0, 2492, 0, - 0, 2615, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2996, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 2201, 1379, 2042, - 2200, 1382, 2041, - 2199, 1386, 2040, - 2197, 1390, 2038, - 2195, 1397, 2035, - 2191, 1405, 2032, - 2187, 1416, 2027, - 2182, 1430, 2021, - 2174, 1449, 2013, - 2163, 1472, 2001, - 2149, 1502, 1986, - 2129, 1538, 1964, - 2100, 1583, 1933, - 2059, 1637, 1887, - 1998, 1701, 1819, - 1900, 1774, 1707, - 1724, 1856, 1496, - 1270, 1947, 780, - 0, 2045, 0, - 0, 2151, 0, - 0, 2262, 0, - 0, 2377, 0, - 0, 2497, 0, - 0, 2619, 0, - 0, 2744, 0, - 0, 2870, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 2342, 1447, 2150, - 2342, 1449, 2149, - 2341, 1452, 2148, - 2339, 1456, 2146, - 2338, 1462, 2145, - 2335, 1469, 2142, - 2332, 1479, 2138, - 2328, 1491, 2133, - 2323, 1507, 2127, - 2315, 1528, 2118, - 2305, 1554, 2106, - 2290, 1587, 2089, - 2271, 1628, 2066, - 2243, 1677, 2032, - 2203, 1735, 1984, - 2143, 1803, 1909, - 2049, 1881, 1785, - 1880, 1967, 1538, - 1465, 2062, 3, - 0, 2164, 0, - 0, 2272, 0, - 0, 2385, 0, - 0, 2503, 0, - 0, 2624, 0, - 0, 2747, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3128, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2481, 1524, 2263, - 2481, 1526, 2262, - 2480, 1528, 2261, - 2479, 1532, 2260, - 2478, 1537, 2259, - 2476, 1543, 2257, - 2474, 1551, 2254, - 2471, 1561, 2250, - 2467, 1575, 2245, - 2461, 1593, 2238, - 2454, 1616, 2229, - 2444, 1645, 2216, - 2430, 1681, 2199, - 2410, 1725, 2174, - 2383, 1778, 2139, - 2344, 1840, 2087, - 2285, 1912, 2007, - 2193, 1993, 1872, - 2030, 2083, 1589, - 1639, 2181, 0, - 0, 2285, 0, - 0, 2396, 0, - 0, 2511, 0, - 0, 2630, 0, - 0, 2752, 0, - 0, 2876, 0, - 0, 3003, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 2618, 1610, 2380, - 2618, 1611, 2380, - 2617, 1614, 2379, - 2617, 1617, 2378, - 2616, 1620, 2377, - 2615, 1626, 2375, - 2613, 1632, 2373, - 2611, 1641, 2370, - 2608, 1653, 2367, - 2604, 1668, 2361, - 2598, 1687, 2354, - 2591, 1712, 2345, - 2581, 1743, 2331, - 2567, 1782, 2313, - 2548, 1829, 2287, - 2521, 1885, 2251, - 2482, 1950, 2197, - 2424, 2026, 2112, - 2333, 2110, 1967, - 2174, 2202, 1650, - 1800, 2303, 0, - 0, 2409, 0, - 0, 2522, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 2754, 1704, 2501, - 2754, 1705, 2500, - 2754, 1707, 2500, - 2753, 1710, 2499, - 2752, 1713, 2498, - 2751, 1717, 2497, - 2750, 1723, 2496, - 2749, 1730, 2493, - 2746, 1739, 2490, - 2743, 1752, 2486, - 2739, 1768, 2481, - 2734, 1789, 2474, - 2727, 1815, 2464, - 2717, 1849, 2450, - 2703, 1889, 2432, - 2684, 1939, 2405, - 2657, 1997, 2367, - 2619, 2066, 2311, - 2562, 2143, 2223, - 2472, 2230, 2069, - 2315, 2325, 1720, - 1952, 2427, 0, - 0, 2535, 0, - 0, 2649, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3011, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3392, 0, - 0, 3522, 0, - 0, 3652, 0, - 2889, 1806, 2624, - 2889, 1807, 2624, - 2889, 1808, 2624, - 2888, 1810, 2623, - 2888, 1813, 2622, - 2887, 1816, 2621, - 2886, 1821, 2620, - 2885, 1826, 2619, - 2883, 1834, 2616, - 2881, 1844, 2613, - 2878, 1858, 2609, - 2874, 1875, 2604, - 2869, 1897, 2596, - 2861, 1925, 2586, - 2852, 1959, 2572, - 2838, 2002, 2553, - 2819, 2054, 2526, - 2792, 2114, 2487, - 2754, 2185, 2429, - 2698, 2265, 2338, - 2609, 2353, 2178, - 2454, 2450, 1799, - 2099, 2553, 0, - 0, 2663, 0, - 0, 2777, 0, - 0, 2896, 0, - 0, 3018, 0, - 0, 3142, 0, - 0, 3268, 0, - 0, 3395, 0, - 0, 3524, 0, - 0, 3653, 0, - 3023, 1914, 2750, - 3023, 1915, 2749, - 3023, 1916, 2749, - 3023, 1917, 2749, - 3022, 1919, 2748, - 3022, 1922, 2748, - 3021, 1925, 2747, - 3020, 1930, 2745, - 3019, 1936, 2744, - 3017, 1944, 2741, - 3015, 1955, 2738, - 3012, 1969, 2734, - 3008, 1987, 2729, - 3003, 2010, 2721, - 2996, 2039, 2711, - 2986, 2075, 2697, - 2972, 2119, 2677, - 2953, 2172, 2650, - 2927, 2235, 2610, - 2889, 2307, 2551, - 2833, 2388, 2457, - 2744, 2478, 2291, - 2591, 2576, 1888, - 2242, 2681, 0, - 0, 2792, 0, - 0, 2907, 0, - 0, 3026, 0, - 0, 3148, 0, - 0, 3273, 0, - 0, 3399, 0, - 0, 3527, 0, - 0, 3655, 0, - 3157, 2027, 2877, - 3157, 2028, 2877, - 3157, 2028, 2876, - 3156, 2030, 2876, - 3156, 2031, 2876, - 3156, 2033, 2875, - 3155, 2036, 2874, - 3155, 2040, 2874, - 3154, 2045, 2872, - 3152, 2051, 2871, - 3151, 2059, 2868, - 3149, 2071, 2865, - 3146, 2085, 2861, - 3142, 2104, 2855, - 3136, 2127, 2848, - 3129, 2157, 2837, - 3119, 2194, 2823, - 3106, 2240, 2803, - 3087, 2294, 2775, - 3061, 2358, 2735, - 3023, 2431, 2675, - 2967, 2514, 2579, - 2879, 2605, 2409, - 2727, 2704, 1984, - 2382, 2810, 0, - 0, 2921, 0, - 0, 3037, 0, - 0, 3157, 0, - 0, 3279, 0, - 0, 3404, 0, - 0, 3530, 0, - 0, 3658, 0, - 3290, 2144, 3005, - 3290, 2145, 3005, - 3290, 2145, 3005, - 3290, 2146, 3005, - 3290, 2148, 3004, - 3289, 2149, 3004, - 3289, 2151, 3003, - 3288, 2154, 3003, - 3288, 2158, 3002, - 3287, 2163, 3000, - 3286, 2170, 2999, - 3284, 2178, 2996, - 3282, 2190, 2993, - 3279, 2205, 2989, - 3275, 2224, 2983, - 3270, 2248, 2976, - 3262, 2279, 2965, - 3253, 2317, 2951, - 3239, 2363, 2931, - 3220, 2418, 2902, - 3194, 2483, 2862, - 3156, 2558, 2801, - 3101, 2641, 2704, - 3013, 2733, 2530, - 2862, 2833, 2087, - 2520, 2939, 0, - 0, 3051, 0, - 0, 3168, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 3423, 2265, 3134, - 3423, 2265, 3134, - 3423, 2266, 3134, - 3423, 2267, 3134, - 3423, 2268, 3134, - 3422, 2269, 3133, - 3422, 2270, 3133, - 3422, 2273, 3132, - 3421, 2276, 3132, - 3421, 2279, 3131, - 3420, 2285, 3130, - 3418, 2291, 3128, - 3417, 2300, 3125, - 3415, 2312, 3122, - 3412, 2327, 3118, - 3408, 2347, 3112, - 3403, 2371, 3105, - 3395, 2403, 3094, - 3386, 2441, 3080, - 3372, 2488, 3059, - 3353, 2545, 3031, - 3327, 2610, 2990, - 3290, 2685, 2928, - 3234, 2770, 2830, - 3147, 2863, 2654, - 2996, 2963, 2197, - 2656, 3070, 0, - 0, 3182, 0, - 0, 3298, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 3556, 2388, 3264, - 3556, 2389, 3264, - 3556, 2389, 3264, - 3556, 2390, 3264, - 3555, 2390, 3264, - 3555, 2391, 3264, - 3555, 2393, 3263, - 3555, 2394, 3263, - 3554, 2397, 3262, - 3554, 2400, 3262, - 3553, 2403, 3261, - 3552, 2409, 3259, - 3551, 2416, 3258, - 3550, 2425, 3255, - 3547, 2437, 3252, - 3544, 2452, 3248, - 3541, 2472, 3242, - 3535, 2497, 3234, - 3528, 2529, 3224, - 3518, 2568, 3209, - 3505, 2615, 3189, - 3486, 2672, 3160, - 3460, 2738, 3119, - 3422, 2814, 3057, - 3367, 2899, 2958, - 3280, 2992, 2780, - 3130, 3093, 2311, - 2791, 3200, 0, - 0, 3313, 0, - 0, 3430, 0, - 0, 3550, 0, - 0, 3673, 0, - 3688, 2514, 3395, - 3688, 2514, 3395, - 3688, 2515, 3395, - 3688, 2515, 3395, - 3688, 2515, 3394, - 3688, 2516, 3394, - 3688, 2517, 3394, - 3688, 2518, 3394, - 3687, 2520, 3393, - 3687, 2522, 3393, - 3686, 2525, 3392, - 3686, 2529, 3391, - 3685, 2535, 3390, - 3684, 2542, 3388, - 3682, 2551, 3386, - 3680, 2563, 3383, - 3677, 2579, 3378, - 3673, 2599, 3373, - 3668, 2624, 3365, - 3661, 2656, 3354, - 3651, 2696, 3339, - 3637, 2744, 3319, - 3619, 2801, 3290, - 3593, 2868, 3249, - 3555, 2944, 3186, - 3500, 3029, 3087, - 3413, 3123, 2907, - 3263, 3224, 2429, - 2926, 3331, 0, - 0, 3444, 0, - 0, 3561, 0, - 0, 3682, 0, - 3821, 2641, 3526, - 3821, 2641, 3526, - 3821, 2641, 3526, - 3821, 2642, 3526, - 3821, 2642, 3525, - 3821, 2643, 3525, - 3820, 2643, 3525, - 3820, 2644, 3525, - 3820, 2646, 3525, - 3820, 2647, 3524, - 3819, 2650, 3524, - 3819, 2653, 3523, - 3818, 2657, 3522, - 3817, 2662, 3521, - 3816, 2669, 3519, - 3815, 2679, 3517, - 3812, 2691, 3513, - 3809, 2706, 3509, - 3806, 2727, 3503, - 3800, 2752, 3495, - 3793, 2785, 3485, - 3783, 2825, 3470, - 3770, 2873, 3450, - 3751, 2930, 3421, - 3725, 2998, 3379, - 3688, 3074, 3316, - 3632, 3160, 3216, - 3546, 3254, 3035, - 3396, 3355, 2551, - 3060, 3463, 0, - 0, 3576, 0, - 0, 3693, 0, - 3953, 2769, 3657, - 3953, 2770, 3657, - 3953, 2770, 3657, - 3953, 2770, 3657, - 3953, 2770, 3657, - 3953, 2771, 3657, - 3953, 2771, 3656, - 3953, 2772, 3656, - 3953, 2773, 3656, - 3952, 2774, 3656, - 3952, 2776, 3655, - 3952, 2778, 3655, - 3951, 2781, 3654, - 3951, 2785, 3653, - 3950, 2791, 3652, - 3948, 2798, 3650, - 3947, 2807, 3648, - 3945, 2820, 3644, - 3942, 2835, 3640, - 3938, 2856, 3634, - 3933, 2882, 3627, - 3925, 2914, 3616, - 3916, 2954, 3601, - 3902, 3003, 3581, - 3884, 3061, 3552, - 3858, 3128, 3510, - 3820, 3205, 3447, - 3765, 3291, 3347, - 3678, 3385, 3165, - 3528, 3486, 2675, - 3193, 3594, 0, - 0, 3707, 0, - 4085, 2899, 3788, - 4085, 2899, 3788, - 4085, 2899, 3788, - 4085, 2899, 3788, - 4085, 2899, 3788, - 4085, 2900, 3788, - 4085, 2900, 3788, - 4085, 2901, 3788, - 4085, 2901, 3788, - 4085, 2902, 3787, - 4085, 2904, 3787, - 4084, 2905, 3787, - 4084, 2908, 3786, - 4084, 2911, 3785, - 4083, 2915, 3784, - 4082, 2920, 3783, - 4081, 2928, 3781, - 4079, 2937, 3779, - 4077, 2949, 3776, - 4074, 2965, 3772, - 4070, 2986, 3766, - 4065, 3012, 3758, - 4058, 3044, 3747, - 4048, 3084, 3732, - 4035, 3133, 3712, - 4016, 3191, 3683, - 3990, 3259, 3641, - 3952, 3336, 3578, - 3897, 3422, 3477, - 3811, 3516, 3295, - 3661, 3618, 2801, - 3326, 3726, 0, - 4095, 3029, 3920, - 4095, 3029, 3920, - 4095, 3029, 3920, - 4095, 3029, 3920, - 4095, 3029, 3920, - 4095, 3029, 3920, - 4095, 3030, 3920, - 4095, 3030, 3920, - 4095, 3031, 3919, - 4095, 3031, 3919, - 4095, 3032, 3919, - 4095, 3034, 3919, - 4095, 3035, 3918, - 4095, 3038, 3918, - 4095, 3041, 3917, - 4095, 3045, 3916, - 4095, 3050, 3915, - 4095, 3058, 3913, - 4095, 3067, 3911, - 4095, 3079, 3907, - 4095, 3095, 3903, - 4095, 3116, 3897, - 4095, 3142, 3889, - 4095, 3175, 3879, - 4095, 3215, 3864, - 4095, 3264, 3843, - 4095, 3322, 3814, - 4095, 3390, 3772, - 4085, 3467, 3709, - 4029, 3553, 3609, - 3943, 3648, 3425, - 3793, 3750, 2928, - 4095, 3159, 4052, - 4095, 3159, 4052, - 4095, 3159, 4052, - 4095, 3159, 4052, - 4095, 3160, 4052, - 4095, 3160, 4051, - 4095, 3160, 4051, - 4095, 3160, 4051, - 4095, 3161, 4051, - 4095, 3161, 4051, - 4095, 3162, 4051, - 4095, 3163, 4051, - 4095, 3164, 4050, - 4095, 3166, 4050, - 4095, 3168, 4049, - 4095, 3171, 4049, - 4095, 3176, 4048, - 4095, 3181, 4046, - 4095, 3188, 4045, - 4095, 3198, 4042, - 4095, 3210, 4039, - 4095, 3226, 4035, - 4095, 3247, 4029, - 4095, 3273, 4021, - 4095, 3306, 4010, - 4095, 3346, 3996, - 4095, 3395, 3975, - 4095, 3454, 3946, - 4095, 3521, 3904, - 4095, 3599, 3841, - 4095, 3685, 3740, - 4075, 3780, 3556, - 0, 1218, 1478, - 0, 1222, 1474, - 0, 1228, 1469, - 0, 1234, 1463, - 0, 1243, 1454, - 0, 1255, 1441, - 0, 1270, 1424, - 0, 1290, 1401, - 0, 1314, 1367, - 0, 1346, 1318, - 0, 1384, 1242, - 0, 1431, 1116, - 0, 1488, 863, - 0, 1553, 0, - 0, 1629, 0, - 0, 1713, 0, - 0, 1806, 0, - 0, 1906, 0, - 0, 2013, 0, - 0, 2125, 0, - 0, 2242, 0, - 0, 2362, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1220, 1483, - 0, 1224, 1479, - 0, 1229, 1475, - 0, 1236, 1468, - 0, 1245, 1459, - 0, 1256, 1447, - 0, 1271, 1430, - 0, 1291, 1407, - 0, 1316, 1374, - 0, 1347, 1325, - 0, 1385, 1251, - 0, 1432, 1128, - 0, 1488, 883, - 0, 1554, 0, - 0, 1629, 0, - 0, 1713, 0, - 0, 1806, 0, - 0, 1906, 0, - 0, 2013, 0, - 0, 2125, 0, - 0, 2242, 0, - 0, 2362, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1222, 1490, - 0, 1225, 1486, - 0, 1231, 1482, - 0, 1237, 1475, - 0, 1246, 1467, - 0, 1258, 1455, - 0, 1273, 1438, - 0, 1292, 1415, - 0, 1317, 1383, - 0, 1348, 1335, - 0, 1387, 1263, - 0, 1433, 1143, - 0, 1489, 909, - 0, 1555, 0, - 0, 1630, 0, - 0, 1714, 0, - 0, 1807, 0, - 0, 1907, 0, - 0, 2013, 0, - 0, 2125, 0, - 0, 2242, 0, - 0, 2362, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1224, 1499, - 0, 1228, 1496, - 0, 1233, 1491, - 0, 1240, 1485, - 0, 1248, 1476, - 0, 1260, 1465, - 0, 1275, 1449, - 0, 1294, 1426, - 0, 1319, 1395, - 0, 1350, 1348, - 0, 1388, 1278, - 0, 1435, 1163, - 0, 1491, 942, - 0, 1556, 111, - 0, 1631, 0, - 0, 1715, 0, - 0, 1807, 0, - 0, 1907, 0, - 0, 2014, 0, - 0, 2126, 0, - 0, 2242, 0, - 0, 2362, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1227, 1511, - 0, 1231, 1508, - 0, 1236, 1503, - 0, 1243, 1497, - 0, 1251, 1489, - 0, 1263, 1478, - 0, 1278, 1462, - 0, 1297, 1441, - 0, 1321, 1410, - 0, 1352, 1365, - 0, 1390, 1298, - 0, 1437, 1188, - 0, 1492, 982, - 0, 1557, 317, - 0, 1632, 0, - 0, 1716, 0, - 0, 1808, 0, - 0, 1908, 0, - 0, 2014, 0, - 0, 2126, 0, - 0, 2243, 0, - 0, 2363, 0, - 0, 2485, 0, - 0, 2610, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1231, 1527, - 0, 1235, 1524, - 0, 1240, 1519, - 0, 1247, 1514, - 0, 1255, 1506, - 0, 1267, 1495, - 0, 1281, 1480, - 0, 1300, 1459, - 0, 1325, 1429, - 0, 1355, 1387, - 0, 1393, 1322, - 0, 1439, 1219, - 0, 1495, 1030, - 0, 1559, 497, - 0, 1634, 0, - 0, 1717, 0, - 0, 1809, 0, - 0, 1909, 0, - 0, 2015, 0, - 0, 2127, 0, - 0, 2243, 0, - 0, 2363, 0, - 0, 2486, 0, - 0, 2611, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3254, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1237, 1547, - 0, 1240, 1544, - 0, 1245, 1540, - 0, 1252, 1534, - 0, 1260, 1527, - 0, 1272, 1516, - 0, 1286, 1502, - 0, 1305, 1482, - 0, 1329, 1454, - 0, 1360, 1414, - 0, 1397, 1354, - 0, 1443, 1258, - 0, 1498, 1088, - 0, 1562, 662, - 0, 1636, 0, - 0, 1719, 0, - 0, 1811, 0, - 0, 1910, 0, - 0, 2016, 0, - 0, 2128, 0, - 0, 2244, 0, - 0, 2363, 0, - 0, 2486, 0, - 0, 2611, 0, - 0, 2737, 0, - 0, 2865, 0, - 0, 2994, 0, - 0, 3124, 0, - 0, 3255, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 0, 1244, 1573, - 0, 1248, 1570, - 0, 1252, 1566, - 0, 1259, 1561, - 0, 1267, 1554, - 0, 1278, 1544, - 0, 1293, 1530, - 0, 1311, 1512, - 0, 1335, 1486, - 0, 1365, 1448, - 0, 1402, 1392, - 0, 1448, 1306, - 0, 1502, 1155, - 0, 1566, 818, - 0, 1639, 0, - 0, 1722, 0, - 0, 1813, 0, - 0, 1912, 0, - 0, 2017, 0, - 0, 2129, 0, - 0, 2244, 0, - 0, 2364, 0, - 0, 2486, 0, - 0, 2611, 0, - 0, 2738, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3124, 0, - 0, 3255, 0, - 0, 3385, 0, - 0, 3516, 0, - 0, 3648, 0, - 664, 1253, 1605, - 635, 1257, 1602, - 593, 1262, 1599, - 530, 1268, 1594, - 428, 1276, 1587, - 243, 1287, 1578, - 0, 1301, 1566, - 0, 1320, 1548, - 0, 1343, 1524, - 0, 1372, 1490, - 0, 1409, 1440, - 0, 1454, 1362, - 0, 1507, 1232, - 0, 1570, 966, - 0, 1643, 0, - 0, 1725, 0, - 0, 1816, 0, - 0, 1914, 0, - 0, 2019, 0, - 0, 2130, 0, - 0, 2245, 0, - 0, 2365, 0, - 0, 2487, 0, - 0, 2612, 0, - 0, 2738, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3124, 0, - 0, 3255, 0, - 0, 3385, 0, - 0, 3517, 0, - 0, 3648, 0, - 1063, 1266, 1645, - 1051, 1269, 1642, - 1034, 1274, 1639, - 1011, 1280, 1635, - 979, 1288, 1628, - 931, 1299, 1620, - 858, 1313, 1609, - 738, 1330, 1593, - 503, 1353, 1571, - 0, 1382, 1541, - 0, 1418, 1496, - 0, 1462, 1428, - 0, 1514, 1318, - 0, 1577, 1110, - 0, 1648, 435, - 0, 1729, 0, - 0, 1819, 0, - 0, 1917, 0, - 0, 2021, 0, - 0, 2132, 0, - 0, 2247, 0, - 0, 2366, 0, - 0, 2488, 0, - 0, 2612, 0, - 0, 2739, 0, - 0, 2866, 0, - 0, 2995, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 1325, 1282, 1693, - 1318, 1285, 1691, - 1309, 1290, 1688, - 1297, 1296, 1684, - 1280, 1303, 1678, - 1256, 1314, 1671, - 1222, 1327, 1661, - 1172, 1344, 1647, - 1095, 1366, 1628, - 966, 1394, 1601, - 704, 1429, 1562, - 0, 1472, 1503, - 0, 1524, 1412, - 0, 1585, 1251, - 0, 1655, 870, - 0, 1735, 0, - 0, 1824, 0, - 0, 1921, 0, - 0, 2024, 0, - 0, 2134, 0, - 0, 2249, 0, - 0, 2367, 0, - 0, 2489, 0, - 0, 2613, 0, - 0, 2739, 0, - 0, 2867, 0, - 0, 2995, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 1535, 1302, 1751, - 1530, 1306, 1749, - 1525, 1310, 1746, - 1517, 1316, 1742, - 1507, 1323, 1738, - 1492, 1333, 1731, - 1472, 1346, 1722, - 1444, 1362, 1710, - 1404, 1384, 1693, - 1343, 1411, 1670, - 1246, 1444, 1637, - 1074, 1486, 1588, - 636, 1536, 1514, - 0, 1595, 1390, - 0, 1664, 1144, - 0, 1743, 0, - 0, 1830, 0, - 0, 1926, 0, - 0, 2029, 0, - 0, 2137, 0, - 0, 2251, 0, - 0, 2369, 0, - 0, 2490, 0, - 0, 2614, 0, - 0, 2740, 0, - 0, 2867, 0, - 0, 2996, 0, - 0, 3125, 0, - 0, 3255, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 1717, 1329, 1818, - 1714, 1332, 1816, - 1711, 1336, 1814, - 1706, 1341, 1811, - 1699, 1348, 1806, - 1689, 1357, 1801, - 1676, 1370, 1793, - 1659, 1385, 1783, - 1634, 1406, 1769, - 1598, 1431, 1749, - 1546, 1464, 1721, - 1465, 1503, 1681, - 1327, 1552, 1621, - 1035, 1609, 1527, - 0, 1676, 1358, - 0, 1753, 942, - 0, 1839, 0, - 0, 1933, 0, - 0, 2034, 0, - 0, 2142, 0, - 0, 2255, 0, - 0, 2372, 0, - 0, 2492, 0, - 0, 2616, 0, - 0, 2741, 0, - 0, 2868, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 1884, 1361, 1894, - 1882, 1364, 1893, - 1879, 1368, 1891, - 1876, 1373, 1888, - 1871, 1380, 1885, - 1865, 1388, 1880, - 1856, 1400, 1874, - 1844, 1414, 1865, - 1827, 1433, 1853, - 1805, 1458, 1837, - 1772, 1488, 1814, - 1724, 1526, 1782, - 1652, 1572, 1734, - 1532, 1627, 1662, - 1297, 1692, 1544, - 234, 1766, 1313, - 0, 1850, 322, - 0, 1942, 0, - 0, 2041, 0, - 0, 2147, 0, - 0, 2259, 0, - 0, 2375, 0, - 0, 2495, 0, - 0, 2618, 0, - 0, 2743, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3648, 0, - 2040, 1402, 1980, - 2038, 1405, 1979, - 2037, 1408, 1977, - 2034, 1413, 1975, - 2031, 1419, 1972, - 2026, 1427, 1968, - 2020, 1437, 1963, - 2012, 1451, 1956, - 2001, 1468, 1946, - 1985, 1491, 1933, - 1964, 1519, 1914, - 1933, 1555, 1889, - 1888, 1598, 1852, - 1821, 1650, 1797, - 1712, 1712, 1712, - 1507, 1783, 1566, - 855, 1864, 1243, - 0, 1953, 0, - 0, 2051, 0, - 0, 2155, 0, - 0, 2265, 0, - 0, 2380, 0, - 0, 2499, 0, - 0, 2620, 0, - 0, 2745, 0, - 0, 2871, 0, - 0, 2999, 0, - 0, 3127, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 2189, 1451, 2074, - 2188, 1453, 2073, - 2187, 1456, 2071, - 2185, 1461, 2070, - 2183, 1466, 2067, - 2180, 1473, 2064, - 2175, 1483, 2060, - 2169, 1495, 2054, - 2161, 1511, 2046, - 2151, 1531, 2036, - 2136, 1557, 2021, - 2115, 1590, 2001, - 2085, 1630, 1972, - 2043, 1679, 1931, - 1979, 1737, 1869, - 1877, 1805, 1771, - 1690, 1882, 1593, - 1170, 1968, 1129, - 0, 2063, 0, - 0, 2165, 0, - 0, 2273, 0, - 0, 2386, 0, - 0, 2503, 0, - 0, 2624, 0, - 0, 2747, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3128, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2334, 1509, 2175, - 2333, 1511, 2174, - 2332, 1514, 2173, - 2331, 1518, 2172, - 2329, 1522, 2170, - 2327, 1529, 2167, - 2324, 1537, 2164, - 2319, 1548, 2159, - 2314, 1562, 2153, - 2306, 1581, 2145, - 2295, 1604, 2134, - 2281, 1634, 2118, - 2261, 1671, 2096, - 2232, 1716, 2065, - 2191, 1769, 2019, - 2130, 1833, 1951, - 2032, 1906, 1839, - 1856, 1988, 1628, - 1402, 2079, 912, - 0, 2177, 0, - 0, 2283, 0, - 0, 2394, 0, - 0, 2509, 0, - 0, 2629, 0, - 0, 2751, 0, - 0, 2876, 0, - 0, 3002, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 2475, 1577, 2283, - 2474, 1579, 2282, - 2474, 1581, 2281, - 2473, 1584, 2280, - 2472, 1588, 2279, - 2470, 1594, 2277, - 2468, 1601, 2274, - 2464, 1611, 2270, - 2460, 1623, 2266, - 2455, 1639, 2259, - 2447, 1660, 2250, - 2437, 1686, 2238, - 2423, 1719, 2221, - 2403, 1760, 2198, - 2375, 1809, 2165, - 2335, 1867, 2116, - 2275, 1935, 2041, - 2181, 2013, 1917, - 2012, 2099, 1670, - 1597, 2194, 135, - 0, 2296, 0, - 0, 2404, 0, - 0, 2517, 0, - 0, 2635, 0, - 0, 2756, 0, - 0, 2879, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3260, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2614, 1654, 2395, - 2613, 1656, 2395, - 2613, 1658, 2394, - 2612, 1660, 2393, - 2611, 1664, 2392, - 2610, 1669, 2391, - 2608, 1675, 2389, - 2606, 1683, 2386, - 2603, 1694, 2382, - 2599, 1707, 2377, - 2593, 1725, 2370, - 2586, 1748, 2361, - 2576, 1777, 2348, - 2562, 1813, 2331, - 2542, 1857, 2306, - 2515, 1910, 2271, - 2476, 1972, 2219, - 2417, 2044, 2139, - 2325, 2125, 2004, - 2162, 2215, 1721, - 1771, 2313, 0, - 0, 2417, 0, - 0, 2528, 0, - 0, 2643, 0, - 0, 2762, 0, - 0, 2884, 0, - 0, 3009, 0, - 0, 3135, 0, - 0, 3263, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 2751, 1741, 2513, - 2750, 1742, 2512, - 2750, 1744, 2512, - 2750, 1746, 2511, - 2749, 1749, 2510, - 2748, 1753, 2509, - 2747, 1758, 2507, - 2745, 1764, 2505, - 2743, 1773, 2502, - 2740, 1785, 2499, - 2736, 1800, 2493, - 2730, 1819, 2486, - 2723, 1844, 2477, - 2713, 1875, 2464, - 2699, 1914, 2445, - 2680, 1961, 2420, - 2653, 2017, 2383, - 2614, 2083, 2329, - 2556, 2158, 2244, - 2466, 2242, 2099, - 2306, 2335, 1782, - 1932, 2435, 0, - 0, 2542, 0, - 0, 2654, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 2887, 1835, 2633, - 2886, 1836, 2633, - 2886, 1838, 2633, - 2886, 1839, 2632, - 2885, 1842, 2631, - 2884, 1845, 2630, - 2884, 1849, 2629, - 2882, 1855, 2628, - 2881, 1862, 2625, - 2878, 1872, 2623, - 2875, 1884, 2619, - 2871, 1900, 2613, - 2866, 1921, 2606, - 2859, 1948, 2596, - 2849, 1981, 2582, - 2835, 2021, 2564, - 2816, 2071, 2537, - 2789, 2130, 2499, - 2751, 2198, 2443, - 2694, 2275, 2355, - 2604, 2362, 2201, - 2447, 2457, 1852, - 2084, 2559, 0, - 0, 2668, 0, - 0, 2781, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3143, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 3021, 1937, 2757, - 3021, 1938, 2756, - 3021, 1939, 2756, - 3021, 1940, 2756, - 3020, 1942, 2755, - 3020, 1945, 2754, - 3019, 1948, 2754, - 3018, 1953, 2752, - 3017, 1959, 2751, - 3015, 1966, 2748, - 3013, 1977, 2745, - 3010, 1990, 2741, - 3006, 2007, 2736, - 3001, 2029, 2728, - 2994, 2057, 2718, - 2984, 2092, 2705, - 2970, 2134, 2685, - 2951, 2186, 2658, - 2924, 2247, 2619, - 2886, 2317, 2561, - 2830, 2397, 2470, - 2741, 2485, 2310, - 2586, 2582, 1931, - 2231, 2685, 0, - 0, 2795, 0, - 0, 2910, 0, - 0, 3028, 0, - 0, 3150, 0, - 0, 3274, 0, - 0, 3400, 0, - 0, 3527, 0, - 0, 3656, 0, - 3155, 2045, 2882, - 3155, 2046, 2882, - 3155, 2047, 2882, - 3155, 2048, 2881, - 3155, 2049, 2881, - 3154, 2051, 2880, - 3154, 2054, 2880, - 3153, 2057, 2879, - 3152, 2062, 2877, - 3151, 2068, 2876, - 3149, 2077, 2874, - 3147, 2087, 2870, - 3144, 2101, 2866, - 3140, 2119, 2861, - 3135, 2142, 2853, - 3128, 2171, 2843, - 3118, 2207, 2829, - 3104, 2251, 2809, - 3085, 2304, 2782, - 3059, 2367, 2742, - 3021, 2439, 2683, - 2965, 2520, 2589, - 2877, 2610, 2423, - 2723, 2708, 2020, - 2374, 2813, 0, - 0, 2924, 0, - 0, 3039, 0, - 0, 3158, 0, - 0, 3280, 0, - 0, 3405, 0, - 0, 3531, 0, - 0, 3659, 0, - 3289, 2158, 3009, - 3289, 2159, 3009, - 3289, 2160, 3009, - 3289, 2160, 3009, - 3288, 2162, 3008, - 3288, 2163, 3008, - 3288, 2165, 3007, - 3287, 2168, 3007, - 3287, 2172, 3006, - 3286, 2177, 3004, - 3285, 2183, 3003, - 3283, 2192, 3000, - 3281, 2203, 2997, - 3278, 2217, 2993, - 3274, 2236, 2988, - 3269, 2259, 2980, - 3261, 2289, 2969, - 3251, 2326, 2955, - 3238, 2372, 2935, - 3219, 2426, 2907, - 3193, 2490, 2867, - 3155, 2563, 2807, - 3099, 2646, 2711, - 3011, 2737, 2541, - 2859, 2836, 2116, - 2514, 2942, 0, - 0, 3053, 0, - 0, 3169, 0, - 0, 3289, 0, - 0, 3411, 0, - 0, 3536, 0, - 0, 3662, 0, - 3422, 2276, 3137, - 3422, 2276, 3137, - 3422, 2277, 3137, - 3422, 2278, 3137, - 3422, 2278, 3137, - 3422, 2280, 3136, - 3421, 2281, 3136, - 3421, 2283, 3135, - 3420, 2286, 3135, - 3420, 2290, 3134, - 3419, 2295, 3133, - 3418, 2302, 3131, - 3416, 2310, 3128, - 3414, 2322, 3125, - 3411, 2337, 3121, - 3407, 2356, 3115, - 3402, 2380, 3108, - 3394, 2411, 3097, - 3385, 2449, 3083, - 3371, 2495, 3063, - 3352, 2551, 3035, - 3326, 2615, 2994, - 3289, 2690, 2933, - 3233, 2773, 2836, - 3145, 2866, 2662, - 2994, 2965, 2219, - 2652, 3072, 0, - 0, 3183, 0, - 0, 3300, 0, - 0, 3420, 0, - 0, 3542, 0, - 0, 3667, 0, - 3555, 2397, 3267, - 3555, 2397, 3266, - 3555, 2398, 3266, - 3555, 2398, 3266, - 3555, 2399, 3266, - 3555, 2400, 3266, - 3555, 2401, 3266, - 3554, 2403, 3265, - 3554, 2405, 3265, - 3553, 2408, 3264, - 3553, 2412, 3263, - 3552, 2417, 3262, - 3551, 2423, 3260, - 3549, 2432, 3258, - 3547, 2444, 3254, - 3544, 2459, 3250, - 3540, 2479, 3245, - 3535, 2504, 3237, - 3527, 2535, 3226, - 3518, 2573, 3212, - 3504, 2621, 3191, - 3485, 2677, 3163, - 3459, 2742, 3122, - 3422, 2818, 3060, - 3366, 2902, 2962, - 3279, 2995, 2786, - 3128, 3095, 2329, - 2788, 3202, 0, - 0, 3314, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 3688, 2520, 3396, - 3688, 2521, 3396, - 3688, 2521, 3396, - 3688, 2521, 3396, - 3688, 2522, 3396, - 3688, 2522, 3396, - 3687, 2523, 3396, - 3687, 2525, 3395, - 3687, 2526, 3395, - 3687, 2529, 3394, - 3686, 2532, 3394, - 3685, 2536, 3393, - 3684, 2541, 3391, - 3683, 2548, 3390, - 3682, 2557, 3387, - 3679, 2569, 3384, - 3677, 2584, 3380, - 3673, 2604, 3374, - 3667, 2629, 3366, - 3660, 2661, 3356, - 3650, 2700, 3341, - 3637, 2748, 3321, - 3618, 2804, 3292, - 3592, 2871, 3251, - 3555, 2946, 3189, - 3499, 3031, 3090, - 3412, 3125, 2912, - 3262, 3225, 2443, - 2923, 3332, 0, - 0, 3445, 0, - 0, 3562, 0, - 0, 3682, 0, - 3820, 2646, 3527, - 3820, 2646, 3527, - 3820, 2646, 3527, - 3820, 2647, 3527, - 3820, 2647, 3527, - 3820, 2648, 3527, - 3820, 2648, 3526, - 3820, 2649, 3526, - 3820, 2651, 3526, - 3819, 2652, 3525, - 3819, 2654, 3525, - 3819, 2658, 3524, - 3818, 2662, 3523, - 3817, 2667, 3522, - 3816, 2674, 3520, - 3814, 2683, 3518, - 3812, 2695, 3515, - 3809, 2711, 3510, - 3805, 2731, 3505, - 3800, 2756, 3497, - 3793, 2788, 3486, - 3783, 2828, 3471, - 3769, 2876, 3451, - 3751, 2933, 3422, - 3725, 3000, 3381, - 3687, 3076, 3318, - 3632, 3161, 3219, - 3545, 3255, 3039, - 3395, 3356, 2562, - 3058, 3463, 0, - 0, 3576, 0, - 0, 3693, 0, - 3953, 2773, 3658, - 3953, 2773, 3658, - 3953, 2773, 3658, - 3953, 2774, 3658, - 3953, 2774, 3658, - 3953, 2774, 3658, - 3953, 2775, 3657, - 3953, 2776, 3657, - 3952, 2777, 3657, - 3952, 2778, 3657, - 3952, 2780, 3656, - 3952, 2782, 3656, - 3951, 2785, 3655, - 3950, 2789, 3654, - 3949, 2794, 3653, - 3948, 2801, 3651, - 3947, 2811, 3649, - 3944, 2823, 3645, - 3942, 2839, 3641, - 3938, 2859, 3635, - 3932, 2885, 3628, - 3925, 2917, 3617, - 3915, 2957, 3602, - 3902, 3005, 3582, - 3883, 3063, 3553, - 3857, 3130, 3511, - 3820, 3206, 3449, - 3764, 3292, 3349, - 3678, 3386, 3167, - 3528, 3487, 2683, - 3192, 3595, 0, - 0, 3708, 0, - 4085, 2901, 3789, - 4085, 2902, 3789, - 4085, 2902, 3789, - 4085, 2902, 3789, - 4085, 2902, 3789, - 4085, 2902, 3789, - 4085, 2903, 3789, - 4085, 2903, 3789, - 4085, 2904, 3788, - 4085, 2905, 3788, - 4085, 2906, 3788, - 4084, 2908, 3787, - 4084, 2910, 3787, - 4083, 2913, 3786, - 4083, 2918, 3785, - 4082, 2923, 3784, - 4081, 2930, 3782, - 4079, 2939, 3780, - 4077, 2952, 3777, - 4074, 2968, 3772, - 4070, 2988, 3767, - 4065, 3014, 3759, - 4058, 3046, 3748, - 4048, 3086, 3733, - 4034, 3135, 3713, - 4016, 3193, 3684, - 3990, 3260, 3642, - 3952, 3337, 3579, - 3897, 3423, 3479, - 3810, 3517, 3297, - 3660, 3618, 2807, - 3325, 3726, 0, - 4095, 3031, 3920, - 4095, 3031, 3920, - 4095, 3031, 3920, - 4095, 3031, 3920, - 4095, 3031, 3920, - 4095, 3031, 3920, - 4095, 3032, 3920, - 4095, 3032, 3920, - 4095, 3033, 3920, - 4095, 3033, 3920, - 4095, 3034, 3920, - 4095, 3036, 3919, - 4095, 3037, 3919, - 4095, 3040, 3918, - 4095, 3043, 3918, - 4095, 3047, 3917, - 4095, 3052, 3915, - 4095, 3060, 3914, - 4095, 3069, 3911, - 4095, 3081, 3908, - 4095, 3097, 3904, - 4095, 3118, 3898, - 4095, 3144, 3890, - 4095, 3176, 3879, - 4095, 3217, 3864, - 4095, 3265, 3844, - 4095, 3323, 3815, - 4095, 3391, 3773, - 4085, 3468, 3710, - 4029, 3554, 3610, - 3943, 3648, 3427, - 3793, 3750, 2933, - 4095, 3161, 4052, - 4095, 3161, 4052, - 4095, 3161, 4052, - 4095, 3161, 4052, - 4095, 3161, 4052, - 4095, 3161, 4052, - 4095, 3161, 4052, - 4095, 3162, 4052, - 4095, 3162, 4052, - 4095, 3163, 4052, - 4095, 3163, 4051, - 4095, 3164, 4051, - 4095, 3166, 4051, - 4095, 3168, 4050, - 4095, 3170, 4050, - 4095, 3173, 4049, - 4095, 3177, 4048, - 4095, 3183, 4047, - 4095, 3190, 4045, - 4095, 3199, 4043, - 4095, 3212, 4040, - 4095, 3228, 4035, - 4095, 3248, 4029, - 4095, 3274, 4022, - 4095, 3307, 4011, - 4095, 3347, 3996, - 4095, 3396, 3975, - 4095, 3454, 3946, - 4095, 3522, 3904, - 4095, 3599, 3841, - 4095, 3685, 3741, - 4075, 3780, 3557, - 0, 1347, 1608, - 0, 1350, 1606, - 0, 1354, 1602, - 0, 1359, 1597, - 0, 1365, 1590, - 0, 1374, 1581, - 0, 1386, 1569, - 0, 1401, 1552, - 0, 1421, 1528, - 0, 1446, 1494, - 0, 1477, 1444, - 0, 1516, 1367, - 0, 1563, 1239, - 0, 1619, 979, - 0, 1685, 0, - 0, 1760, 0, - 0, 1845, 0, - 0, 1938, 0, - 0, 2038, 0, - 0, 2145, 0, - 0, 2257, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1348, 1612, - 0, 1351, 1610, - 0, 1354, 1606, - 0, 1360, 1601, - 0, 1366, 1595, - 0, 1375, 1586, - 0, 1387, 1573, - 0, 1402, 1557, - 0, 1422, 1533, - 0, 1447, 1499, - 0, 1478, 1450, - 0, 1516, 1374, - 0, 1564, 1248, - 0, 1620, 995, - 0, 1685, 0, - 0, 1761, 0, - 0, 1845, 0, - 0, 1938, 0, - 0, 2038, 0, - 0, 2145, 0, - 0, 2257, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1349, 1618, - 0, 1352, 1615, - 0, 1356, 1611, - 0, 1361, 1607, - 0, 1368, 1600, - 0, 1377, 1591, - 0, 1388, 1579, - 0, 1403, 1563, - 0, 1423, 1539, - 0, 1448, 1506, - 0, 1479, 1457, - 0, 1517, 1383, - 0, 1564, 1260, - 0, 1620, 1015, - 0, 1686, 0, - 0, 1761, 0, - 0, 1845, 0, - 0, 1938, 0, - 0, 2038, 0, - 0, 2145, 0, - 0, 2257, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1351, 1625, - 0, 1354, 1622, - 0, 1358, 1619, - 0, 1363, 1614, - 0, 1369, 1607, - 0, 1378, 1599, - 0, 1390, 1587, - 0, 1405, 1570, - 0, 1424, 1548, - 0, 1449, 1515, - 0, 1480, 1467, - 0, 1519, 1395, - 0, 1565, 1275, - 0, 1621, 1041, - 0, 1687, 0, - 0, 1762, 0, - 0, 1846, 0, - 0, 1939, 0, - 0, 2039, 0, - 0, 2145, 0, - 0, 2258, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1353, 1634, - 0, 1356, 1631, - 0, 1360, 1628, - 0, 1365, 1623, - 0, 1372, 1617, - 0, 1381, 1608, - 0, 1392, 1597, - 0, 1407, 1581, - 0, 1426, 1558, - 0, 1451, 1527, - 0, 1482, 1480, - 0, 1520, 1410, - 0, 1567, 1295, - 0, 1623, 1074, - 0, 1688, 244, - 0, 1763, 0, - 0, 1847, 0, - 0, 1939, 0, - 0, 2039, 0, - 0, 2146, 0, - 0, 2258, 0, - 0, 2374, 0, - 0, 2494, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3386, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1356, 1646, - 0, 1359, 1643, - 0, 1363, 1640, - 0, 1368, 1636, - 0, 1375, 1629, - 0, 1383, 1621, - 0, 1395, 1610, - 0, 1410, 1594, - 0, 1429, 1573, - 0, 1453, 1542, - 0, 1484, 1497, - 0, 1522, 1430, - 0, 1569, 1320, - 0, 1624, 1114, - 0, 1690, 449, - 0, 1764, 0, - 0, 1848, 0, - 0, 1940, 0, - 0, 2040, 0, - 0, 2146, 0, - 0, 2258, 0, - 0, 2375, 0, - 0, 2495, 0, - 0, 2617, 0, - 0, 2742, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1360, 1662, - 0, 1363, 1659, - 0, 1367, 1656, - 0, 1372, 1652, - 0, 1379, 1646, - 0, 1387, 1638, - 0, 1399, 1627, - 0, 1414, 1612, - 0, 1433, 1591, - 0, 1457, 1561, - 0, 1487, 1519, - 0, 1525, 1455, - 0, 1572, 1351, - 0, 1627, 1162, - 0, 1692, 629, - 0, 1766, 0, - 0, 1849, 0, - 0, 1941, 0, - 0, 2041, 0, - 0, 2147, 0, - 0, 2259, 0, - 0, 2375, 0, - 0, 2495, 0, - 0, 2618, 0, - 0, 2743, 0, - 0, 2869, 0, - 0, 2997, 0, - 0, 3126, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3648, 0, - 0, 1366, 1682, - 0, 1369, 1679, - 0, 1373, 1676, - 0, 1377, 1672, - 0, 1384, 1666, - 0, 1393, 1659, - 0, 1404, 1648, - 0, 1418, 1634, - 0, 1437, 1614, - 0, 1461, 1586, - 0, 1492, 1546, - 0, 1529, 1486, - 0, 1575, 1390, - 0, 1630, 1220, - 0, 1694, 795, - 0, 1768, 0, - 0, 1851, 0, - 0, 1943, 0, - 0, 2042, 0, - 0, 2148, 0, - 0, 2260, 0, - 0, 2376, 0, - 0, 2495, 0, - 0, 2618, 0, - 0, 2743, 0, - 0, 2870, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3649, 0, - 0, 1373, 1707, - 0, 1376, 1705, - 0, 1380, 1702, - 0, 1385, 1698, - 0, 1391, 1693, - 0, 1399, 1686, - 0, 1411, 1676, - 0, 1425, 1662, - 0, 1444, 1644, - 0, 1467, 1618, - 0, 1497, 1580, - 0, 1534, 1525, - 0, 1580, 1438, - 0, 1634, 1287, - 0, 1698, 950, - 0, 1771, 0, - 0, 1854, 0, - 0, 1945, 0, - 0, 2044, 0, - 0, 2149, 0, - 0, 2261, 0, - 0, 2377, 0, - 0, 2496, 0, - 0, 2619, 0, - 0, 2743, 0, - 0, 2870, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3256, 0, - 0, 3387, 0, - 0, 3517, 0, - 0, 3649, 0, - 817, 1383, 1739, - 796, 1385, 1737, - 767, 1389, 1734, - 725, 1394, 1731, - 662, 1400, 1726, - 560, 1408, 1719, - 375, 1419, 1710, - 0, 1433, 1698, - 0, 1452, 1680, - 0, 1475, 1656, - 0, 1504, 1622, - 0, 1541, 1572, - 0, 1586, 1494, - 0, 1639, 1364, - 0, 1702, 1098, - 0, 1775, 0, - 0, 1857, 0, - 0, 1948, 0, - 0, 2046, 0, - 0, 2151, 0, - 0, 2262, 0, - 0, 2378, 0, - 0, 2497, 0, - 0, 2619, 0, - 0, 2744, 0, - 0, 2870, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 1204, 1395, 1779, - 1195, 1398, 1777, - 1183, 1401, 1775, - 1166, 1406, 1771, - 1143, 1412, 1767, - 1111, 1420, 1761, - 1063, 1431, 1752, - 990, 1445, 1741, - 870, 1462, 1725, - 635, 1485, 1704, - 0, 1514, 1673, - 0, 1550, 1628, - 0, 1594, 1560, - 0, 1646, 1450, - 0, 1709, 1243, - 0, 1780, 567, - 0, 1861, 0, - 0, 1951, 0, - 0, 2049, 0, - 0, 2154, 0, - 0, 2264, 0, - 0, 2379, 0, - 0, 2498, 0, - 0, 2620, 0, - 0, 2744, 0, - 0, 2871, 0, - 0, 2998, 0, - 0, 3127, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 1462, 1411, 1827, - 1457, 1414, 1825, - 1450, 1417, 1823, - 1441, 1422, 1820, - 1429, 1428, 1816, - 1412, 1436, 1811, - 1388, 1446, 1803, - 1354, 1459, 1793, - 1304, 1476, 1779, - 1227, 1498, 1760, - 1098, 1526, 1733, - 836, 1561, 1694, - 0, 1604, 1636, - 0, 1656, 1544, - 0, 1717, 1383, - 0, 1787, 1003, - 0, 1867, 0, - 0, 1956, 0, - 0, 2053, 0, - 0, 2157, 0, - 0, 2266, 0, - 0, 2381, 0, - 0, 2499, 0, - 0, 2621, 0, - 0, 2745, 0, - 0, 2871, 0, - 0, 2999, 0, - 0, 3128, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 1670, 1432, 1884, - 1667, 1435, 1883, - 1663, 1438, 1881, - 1657, 1442, 1878, - 1649, 1448, 1875, - 1639, 1455, 1870, - 1624, 1465, 1863, - 1604, 1478, 1854, - 1576, 1494, 1842, - 1536, 1516, 1826, - 1475, 1543, 1802, - 1378, 1576, 1769, - 1206, 1618, 1720, - 769, 1668, 1646, - 0, 1728, 1522, - 0, 1797, 1276, - 0, 1875, 0, - 0, 1962, 0, - 0, 2058, 0, - 0, 2161, 0, - 0, 2270, 0, - 0, 2383, 0, - 0, 2501, 0, - 0, 2623, 0, - 0, 2746, 0, - 0, 2872, 0, - 0, 3000, 0, - 0, 3128, 0, - 0, 3257, 0, - 0, 3387, 0, - 0, 3518, 0, - 0, 3649, 0, - 1851, 1458, 1951, - 1849, 1461, 1950, - 1847, 1464, 1948, - 1843, 1468, 1946, - 1838, 1473, 1943, - 1831, 1480, 1939, - 1821, 1490, 1933, - 1809, 1502, 1925, - 1791, 1517, 1915, - 1766, 1538, 1901, - 1730, 1563, 1881, - 1678, 1596, 1853, - 1597, 1636, 1813, - 1459, 1684, 1753, - 1167, 1741, 1659, - 0, 1809, 1491, - 0, 1885, 1074, - 0, 1971, 0, - 0, 2065, 0, - 0, 2166, 0, - 0, 2274, 0, - 0, 2387, 0, - 0, 2504, 0, - 0, 2625, 0, - 0, 2748, 0, - 0, 2873, 0, - 0, 3000, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 2017, 1491, 2027, - 2016, 1494, 2026, - 2014, 1496, 2025, - 2011, 1500, 2023, - 2008, 1505, 2020, - 2003, 1512, 2017, - 1997, 1520, 2012, - 1988, 1532, 2006, - 1976, 1547, 1997, - 1960, 1566, 1985, - 1937, 1590, 1969, - 1904, 1620, 1946, - 1856, 1658, 1914, - 1784, 1704, 1867, - 1664, 1759, 1794, - 1430, 1824, 1676, - 367, 1898, 1445, - 0, 1982, 454, - 0, 2074, 0, - 0, 2173, 0, - 0, 2279, 0, - 0, 2391, 0, - 0, 2507, 0, - 0, 2627, 0, - 0, 2750, 0, - 0, 2875, 0, - 0, 3002, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 2173, 1532, 2113, - 2172, 1534, 2112, - 2171, 1537, 2111, - 2169, 1540, 2109, - 2166, 1545, 2107, - 2163, 1551, 2104, - 2158, 1559, 2100, - 2152, 1569, 2095, - 2144, 1583, 2088, - 2133, 1600, 2078, - 2117, 1623, 2065, - 2096, 1651, 2047, - 2065, 1687, 2021, - 2021, 1730, 1984, - 1953, 1782, 1929, - 1844, 1844, 1844, - 1639, 1915, 1698, - 988, 1996, 1375, - 0, 2085, 0, - 0, 2183, 0, - 0, 2287, 0, - 0, 2397, 0, - 0, 2512, 0, - 0, 2631, 0, - 0, 2753, 0, - 0, 2877, 0, - 0, 3003, 0, - 0, 3131, 0, - 0, 3259, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 2322, 1581, 2206, - 2321, 1583, 2206, - 2320, 1585, 2205, - 2319, 1588, 2204, - 2317, 1593, 2202, - 2315, 1598, 2199, - 2312, 1605, 2196, - 2307, 1615, 2192, - 2301, 1627, 2186, - 2293, 1643, 2179, - 2283, 1663, 2168, - 2268, 1690, 2153, - 2247, 1722, 2133, - 2218, 1763, 2105, - 2175, 1811, 2063, - 2111, 1870, 2001, - 2009, 1937, 1903, - 1822, 2014, 1725, - 1302, 2100, 1261, - 0, 2195, 0, - 0, 2297, 0, - 0, 2405, 0, - 0, 2518, 0, - 0, 2635, 0, - 0, 2756, 0, - 0, 2880, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2466, 1640, 2308, - 2466, 1641, 2307, - 2465, 1643, 2306, - 2464, 1646, 2305, - 2463, 1650, 2304, - 2461, 1655, 2302, - 2459, 1661, 2299, - 2456, 1669, 2296, - 2451, 1680, 2292, - 2446, 1694, 2285, - 2438, 1713, 2277, - 2427, 1736, 2266, - 2413, 1766, 2250, - 2393, 1803, 2228, - 2364, 1848, 2197, - 2323, 1902, 2152, - 2262, 1965, 2083, - 2164, 2038, 1971, - 1988, 2120, 1760, - 1534, 2211, 1044, - 0, 2309, 0, - 0, 2415, 0, - 0, 2526, 0, - 0, 2641, 0, - 0, 2761, 0, - 0, 2883, 0, - 0, 3008, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 2607, 1708, 2415, - 2607, 1709, 2415, - 2607, 1711, 2414, - 2606, 1713, 2413, - 2605, 1716, 2412, - 2604, 1721, 2411, - 2602, 1726, 2409, - 2600, 1733, 2406, - 2597, 1743, 2402, - 2592, 1755, 2398, - 2587, 1771, 2391, - 2579, 1792, 2382, - 2569, 1818, 2370, - 2555, 1851, 2353, - 2535, 1892, 2330, - 2507, 1941, 2297, - 2467, 1999, 2248, - 2407, 2067, 2173, - 2313, 2145, 2049, - 2144, 2231, 1802, - 1729, 2326, 267, - 0, 2428, 0, - 0, 2536, 0, - 0, 2649, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3011, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 2746, 1785, 2528, - 2746, 1786, 2528, - 2745, 1788, 2527, - 2745, 1790, 2526, - 2744, 1793, 2526, - 2743, 1796, 2524, - 2742, 1801, 2523, - 2740, 1807, 2521, - 2738, 1815, 2518, - 2735, 1826, 2514, - 2731, 1839, 2509, - 2726, 1857, 2502, - 2718, 1880, 2493, - 2708, 1909, 2480, - 2694, 1945, 2463, - 2674, 1989, 2438, - 2647, 2042, 2403, - 2608, 2104, 2351, - 2549, 2176, 2271, - 2457, 2257, 2136, - 2294, 2347, 1853, - 1903, 2445, 0, - 0, 2549, 0, - 0, 2660, 0, - 0, 2775, 0, - 0, 2894, 0, - 0, 3016, 0, - 0, 3141, 0, - 0, 3267, 0, - 0, 3395, 0, - 0, 3523, 0, - 0, 3653, 0, - 2883, 1872, 2645, - 2883, 1873, 2645, - 2883, 1874, 2644, - 2882, 1876, 2644, - 2882, 1878, 2643, - 2881, 1881, 2642, - 2880, 1885, 2641, - 2879, 1890, 2640, - 2877, 1897, 2637, - 2875, 1905, 2635, - 2872, 1917, 2631, - 2868, 1932, 2625, - 2862, 1952, 2618, - 2855, 1976, 2609, - 2845, 2008, 2596, - 2831, 2046, 2577, - 2812, 2093, 2552, - 2785, 2149, 2515, - 2746, 2215, 2461, - 2688, 2290, 2376, - 2598, 2374, 2231, - 2438, 2467, 1914, - 2064, 2567, 0, - 0, 2674, 0, - 0, 2786, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3271, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 3019, 1967, 2766, - 3019, 1967, 2765, - 3018, 1968, 2765, - 3018, 1970, 2765, - 3018, 1971, 2764, - 3017, 1974, 2763, - 3017, 1977, 2763, - 3016, 1981, 2761, - 3014, 1987, 2760, - 3013, 1994, 2758, - 3011, 2004, 2755, - 3008, 2016, 2751, - 3004, 2032, 2745, - 2998, 2053, 2738, - 2991, 2080, 2728, - 2981, 2113, 2715, - 2967, 2154, 2696, - 2948, 2203, 2669, - 2921, 2262, 2631, - 2883, 2330, 2575, - 2826, 2408, 2487, - 2736, 2494, 2334, - 2580, 2589, 1984, - 2216, 2691, 0, - 0, 2800, 0, - 0, 2913, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3275, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3154, 2069, 2889, - 3153, 2069, 2889, - 3153, 2070, 2888, - 3153, 2071, 2888, - 3153, 2072, 2888, - 3152, 2074, 2887, - 3152, 2077, 2887, - 3151, 2080, 2886, - 3150, 2085, 2884, - 3149, 2091, 2883, - 3147, 2098, 2881, - 3145, 2109, 2878, - 3142, 2122, 2873, - 3138, 2139, 2868, - 3133, 2161, 2861, - 3126, 2189, 2850, - 3116, 2224, 2837, - 3102, 2266, 2817, - 3083, 2318, 2790, - 3057, 2379, 2751, - 3018, 2449, 2693, - 2962, 2529, 2602, - 2873, 2617, 2442, - 2718, 2714, 2063, - 2363, 2818, 0, - 0, 2927, 0, - 0, 3042, 0, - 0, 3160, 0, - 0, 3282, 0, - 0, 3406, 0, - 0, 3532, 0, - 0, 3659, 0, - 3288, 2177, 3014, - 3288, 2177, 3014, - 3287, 2178, 3014, - 3287, 2179, 3014, - 3287, 2180, 3013, - 3287, 2181, 3013, - 3286, 2183, 3012, - 3286, 2186, 3012, - 3285, 2190, 3011, - 3284, 2194, 3010, - 3283, 2200, 3008, - 3281, 2209, 3006, - 3279, 2219, 3003, - 3276, 2233, 2998, - 3272, 2251, 2993, - 3267, 2274, 2985, - 3260, 2303, 2975, - 3250, 2339, 2961, - 3236, 2383, 2941, - 3217, 2437, 2914, - 3191, 2499, 2874, - 3153, 2571, 2815, - 3097, 2652, 2721, - 3009, 2743, 2556, - 2855, 2840, 2152, - 2506, 2945, 0, - 0, 3056, 0, - 0, 3171, 0, - 0, 3290, 0, - 0, 3412, 0, - 0, 3537, 0, - 0, 3663, 0, - 3421, 2290, 3141, - 3421, 2291, 3141, - 3421, 2291, 3141, - 3421, 2292, 3141, - 3421, 2293, 3141, - 3421, 2294, 3140, - 3420, 2295, 3140, - 3420, 2297, 3139, - 3419, 2300, 3139, - 3419, 2304, 3138, - 3418, 2309, 3136, - 3417, 2315, 3135, - 3415, 2324, 3132, - 3413, 2335, 3129, - 3410, 2349, 3125, - 3406, 2368, 3120, - 3401, 2392, 3112, - 3393, 2421, 3102, - 3384, 2459, 3087, - 3370, 2504, 3067, - 3351, 2558, 3039, - 3325, 2622, 2999, - 3287, 2696, 2939, - 3231, 2778, 2844, - 3143, 2869, 2673, - 2991, 2968, 2248, - 2646, 3074, 0, - 0, 3185, 0, - 0, 3301, 0, - 0, 3421, 0, - 0, 3543, 0, - 0, 3668, 0, - 3554, 2408, 3269, - 3554, 2408, 3269, - 3554, 2408, 3269, - 3554, 2409, 3269, - 3554, 2410, 3269, - 3554, 2411, 3269, - 3554, 2412, 3268, - 3553, 2413, 3268, - 3553, 2416, 3268, - 3553, 2418, 3267, - 3552, 2422, 3266, - 3551, 2427, 3265, - 3550, 2434, 3263, - 3548, 2443, 3261, - 3546, 2454, 3257, - 3543, 2469, 3253, - 3539, 2488, 3248, - 3534, 2512, 3240, - 3527, 2543, 3229, - 3517, 2581, 3215, - 3503, 2627, 3195, - 3485, 2683, 3167, - 3458, 2747, 3126, - 3421, 2822, 3065, - 3365, 2905, 2968, - 3277, 2998, 2794, - 3126, 3097, 2352, - 2784, 3204, 0, - 0, 3315, 0, - 0, 3432, 0, - 0, 3552, 0, - 0, 3674, 0, - 3687, 2529, 3399, - 3687, 2529, 3399, - 3687, 2529, 3399, - 3687, 2530, 3398, - 3687, 2530, 3398, - 3687, 2531, 3398, - 3687, 2532, 3398, - 3687, 2533, 3398, - 3686, 2535, 3397, - 3686, 2537, 3397, - 3685, 2540, 3396, - 3685, 2544, 3395, - 3684, 2549, 3394, - 3683, 2556, 3392, - 3681, 2565, 3390, - 3679, 2576, 3387, - 3676, 2591, 3382, - 3672, 2611, 3377, - 3667, 2636, 3369, - 3660, 2667, 3358, - 3650, 2706, 3344, - 3636, 2753, 3324, - 3618, 2809, 3295, - 3591, 2874, 3254, - 3554, 2950, 3192, - 3498, 3034, 3094, - 3411, 3127, 2918, - 3260, 3227, 2461, - 2920, 3334, 0, - 0, 3446, 0, - 0, 3563, 0, - 0, 3683, 0, - 3820, 2652, 3529, - 3820, 2652, 3529, - 3820, 2653, 3528, - 3820, 2653, 3528, - 3820, 2653, 3528, - 3820, 2654, 3528, - 3820, 2655, 3528, - 3820, 2656, 3528, - 3819, 2657, 3528, - 3819, 2658, 3527, - 3819, 2661, 3527, - 3818, 2664, 3526, - 3817, 2668, 3525, - 3817, 2673, 3524, - 3815, 2680, 3522, - 3814, 2689, 3519, - 3812, 2701, 3516, - 3809, 2716, 3512, - 3805, 2736, 3506, - 3799, 2761, 3499, - 3792, 2793, 3488, - 3782, 2832, 3473, - 3769, 2880, 3453, - 3750, 2936, 3424, - 3724, 3003, 3383, - 3687, 3078, 3321, - 3631, 3163, 3222, - 3544, 3257, 3044, - 3394, 3357, 2575, - 3056, 3465, 0, - 0, 3577, 0, - 0, 3694, 0, - 3953, 2778, 3659, - 3953, 2778, 3659, - 3953, 2778, 3659, - 3953, 2778, 3659, - 3952, 2779, 3659, - 3952, 2779, 3659, - 3952, 2780, 3659, - 3952, 2780, 3658, - 3952, 2781, 3658, - 3952, 2783, 3658, - 3952, 2784, 3658, - 3951, 2787, 3657, - 3951, 2790, 3656, - 3950, 2794, 3655, - 3949, 2799, 3654, - 3948, 2806, 3652, - 3946, 2815, 3650, - 3944, 2827, 3647, - 3941, 2843, 3642, - 3937, 2863, 3637, - 3932, 2888, 3629, - 3925, 2920, 3618, - 3915, 2960, 3604, - 3902, 3008, 3583, - 3883, 3065, 3554, - 3857, 3132, 3513, - 3819, 3208, 3450, - 3764, 3293, 3351, - 3677, 3387, 3171, - 3527, 3488, 2694, - 3190, 3596, 0, - 0, 3708, 0, - 4085, 2905, 3790, - 4085, 2905, 3790, - 4085, 2905, 3790, - 4085, 2905, 3790, - 4085, 2906, 3790, - 4085, 2906, 3790, - 4085, 2906, 3790, - 4085, 2907, 3789, - 4085, 2908, 3789, - 4084, 2909, 3789, - 4084, 2910, 3789, - 4084, 2912, 3788, - 4084, 2914, 3788, - 4083, 2917, 3787, - 4082, 2921, 3786, - 4082, 2926, 3785, - 4080, 2933, 3783, - 4079, 2943, 3781, - 4077, 2955, 3778, - 4074, 2971, 3773, - 4070, 2991, 3768, - 4064, 3017, 3760, - 4057, 3049, 3749, - 4047, 3089, 3734, - 4034, 3137, 3714, - 4015, 3195, 3685, - 3989, 3262, 3643, - 3952, 3338, 3581, - 3896, 3424, 3481, - 3810, 3518, 3299, - 3660, 3619, 2815, - 3324, 3727, 0, - 4095, 3033, 3921, - 4095, 3034, 3921, - 4095, 3034, 3921, - 4095, 3034, 3921, - 4095, 3034, 3921, - 4095, 3034, 3921, - 4095, 3034, 3921, - 4095, 3035, 3921, - 4095, 3035, 3921, - 4095, 3036, 3920, - 4095, 3037, 3920, - 4095, 3038, 3920, - 4095, 3040, 3920, - 4095, 3042, 3919, - 4095, 3046, 3918, - 4095, 3050, 3917, - 4095, 3055, 3916, - 4095, 3062, 3914, - 4095, 3072, 3912, - 4095, 3084, 3909, - 4095, 3100, 3904, - 4095, 3120, 3899, - 4095, 3146, 3891, - 4095, 3178, 3880, - 4095, 3218, 3865, - 4095, 3267, 3845, - 4095, 3325, 3816, - 4095, 3392, 3774, - 4084, 3469, 3711, - 4029, 3555, 3611, - 3942, 3649, 3429, - 3793, 3751, 2939, - 4095, 3163, 4053, - 4095, 3163, 4052, - 4095, 3163, 4052, - 4095, 3163, 4052, - 4095, 3163, 4052, - 4095, 3163, 4052, - 4095, 3164, 4052, - 4095, 3164, 4052, - 4095, 3164, 4052, - 4095, 3165, 4052, - 4095, 3166, 4052, - 4095, 3167, 4052, - 4095, 3168, 4051, - 4095, 3170, 4051, - 4095, 3172, 4050, - 4095, 3175, 4050, - 4095, 3179, 4049, - 4095, 3185, 4047, - 4095, 3192, 4046, - 4095, 3201, 4043, - 4095, 3213, 4040, - 4095, 3229, 4036, - 4095, 3250, 4030, - 4095, 3276, 4022, - 4095, 3308, 4011, - 4095, 3349, 3997, - 4095, 3397, 3976, - 4095, 3455, 3947, - 4095, 3523, 3905, - 4095, 3600, 3842, - 4095, 3686, 3742, - 4075, 3780, 3559, - 0, 1476, 1739, - 0, 1478, 1737, - 0, 1481, 1735, - 0, 1485, 1731, - 0, 1490, 1726, - 0, 1497, 1719, - 0, 1506, 1710, - 0, 1518, 1698, - 0, 1533, 1681, - 0, 1552, 1657, - 0, 1577, 1622, - 0, 1609, 1572, - 0, 1647, 1494, - 0, 1695, 1365, - 0, 1751, 1099, - 0, 1817, 0, - 0, 1892, 0, - 0, 1976, 0, - 0, 2069, 0, - 0, 2170, 0, - 0, 2277, 0, - 0, 2389, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3518, 0, - 0, 3649, 0, - 0, 1477, 1742, - 0, 1479, 1740, - 0, 1482, 1738, - 0, 1486, 1734, - 0, 1491, 1729, - 0, 1498, 1723, - 0, 1507, 1713, - 0, 1518, 1701, - 0, 1533, 1684, - 0, 1553, 1660, - 0, 1578, 1626, - 0, 1609, 1576, - 0, 1648, 1500, - 0, 1695, 1371, - 0, 1751, 1111, - 0, 1817, 0, - 0, 1892, 0, - 0, 1977, 0, - 0, 2070, 0, - 0, 2170, 0, - 0, 2277, 0, - 0, 2389, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1478, 1746, - 0, 1480, 1744, - 0, 1483, 1742, - 0, 1487, 1738, - 0, 1492, 1733, - 0, 1499, 1727, - 0, 1507, 1718, - 0, 1519, 1706, - 0, 1534, 1689, - 0, 1554, 1665, - 0, 1579, 1631, - 0, 1610, 1582, - 0, 1649, 1506, - 0, 1696, 1380, - 0, 1752, 1127, - 0, 1818, 0, - 0, 1893, 0, - 0, 1977, 0, - 0, 2070, 0, - 0, 2170, 0, - 0, 2277, 0, - 0, 2389, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1479, 1752, - 0, 1481, 1750, - 0, 1484, 1747, - 0, 1488, 1744, - 0, 1493, 1739, - 0, 1500, 1732, - 0, 1509, 1723, - 0, 1520, 1711, - 0, 1535, 1695, - 0, 1555, 1671, - 0, 1580, 1638, - 0, 1611, 1590, - 0, 1650, 1515, - 0, 1696, 1392, - 0, 1753, 1147, - 0, 1818, 0, - 0, 1893, 0, - 0, 1978, 0, - 0, 2070, 0, - 0, 2171, 0, - 0, 2277, 0, - 0, 2389, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1481, 1759, - 0, 1483, 1757, - 0, 1486, 1754, - 0, 1490, 1751, - 0, 1495, 1746, - 0, 1502, 1740, - 0, 1510, 1731, - 0, 1522, 1719, - 0, 1537, 1703, - 0, 1556, 1680, - 0, 1581, 1647, - 0, 1612, 1600, - 0, 1651, 1527, - 0, 1698, 1407, - 0, 1754, 1173, - 0, 1819, 122, - 0, 1894, 0, - 0, 1978, 0, - 0, 2071, 0, - 0, 2171, 0, - 0, 2278, 0, - 0, 2390, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1483, 1768, - 0, 1485, 1766, - 0, 1488, 1763, - 0, 1492, 1760, - 0, 1497, 1755, - 0, 1504, 1749, - 0, 1513, 1741, - 0, 1524, 1729, - 0, 1539, 1713, - 0, 1558, 1691, - 0, 1583, 1659, - 0, 1614, 1612, - 0, 1652, 1542, - 0, 1699, 1427, - 0, 1755, 1206, - 0, 1820, 376, - 0, 1895, 0, - 0, 1979, 0, - 0, 2071, 0, - 0, 2171, 0, - 0, 2278, 0, - 0, 2390, 0, - 0, 2506, 0, - 0, 2626, 0, - 0, 2749, 0, - 0, 2874, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1486, 1780, - 0, 1488, 1778, - 0, 1491, 1776, - 0, 1495, 1772, - 0, 1500, 1768, - 0, 1507, 1762, - 0, 1516, 1753, - 0, 1527, 1742, - 0, 1542, 1726, - 0, 1561, 1705, - 0, 1586, 1674, - 0, 1616, 1629, - 0, 1655, 1562, - 0, 1701, 1452, - 0, 1757, 1246, - 0, 1822, 581, - 0, 1896, 0, - 0, 1980, 0, - 0, 2072, 0, - 0, 2172, 0, - 0, 2279, 0, - 0, 2390, 0, - 0, 2507, 0, - 0, 2627, 0, - 0, 2750, 0, - 0, 2875, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3258, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1490, 1795, - 0, 1493, 1794, - 0, 1495, 1791, - 0, 1499, 1788, - 0, 1504, 1784, - 0, 1511, 1778, - 0, 1519, 1770, - 0, 1531, 1759, - 0, 1546, 1744, - 0, 1565, 1723, - 0, 1589, 1694, - 0, 1620, 1651, - 0, 1657, 1587, - 0, 1704, 1484, - 0, 1759, 1294, - 0, 1824, 762, - 0, 1898, 0, - 0, 1981, 0, - 0, 2073, 0, - 0, 2173, 0, - 0, 2279, 0, - 0, 2391, 0, - 0, 2507, 0, - 0, 2627, 0, - 0, 2750, 0, - 0, 2875, 0, - 0, 3001, 0, - 0, 3129, 0, - 0, 3259, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1496, 1815, - 0, 1498, 1814, - 0, 1501, 1811, - 0, 1505, 1808, - 0, 1510, 1804, - 0, 1516, 1799, - 0, 1525, 1791, - 0, 1536, 1781, - 0, 1551, 1766, - 0, 1569, 1746, - 0, 1593, 1718, - 0, 1624, 1678, - 0, 1661, 1618, - 0, 1707, 1522, - 0, 1762, 1352, - 0, 1826, 927, - 0, 1900, 0, - 0, 1983, 0, - 0, 2075, 0, - 0, 2174, 0, - 0, 2280, 0, - 0, 2392, 0, - 0, 2508, 0, - 0, 2628, 0, - 0, 2750, 0, - 0, 2875, 0, - 0, 3002, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3649, 0, - 0, 1503, 1841, - 0, 1505, 1839, - 0, 1508, 1837, - 0, 1512, 1834, - 0, 1517, 1830, - 0, 1523, 1825, - 0, 1532, 1818, - 0, 1543, 1808, - 0, 1557, 1795, - 0, 1576, 1776, - 0, 1599, 1750, - 0, 1629, 1712, - 0, 1666, 1657, - 0, 1712, 1570, - 0, 1766, 1419, - 0, 1830, 1082, - 0, 1903, 0, - 0, 1986, 0, - 0, 2077, 0, - 0, 2176, 0, - 0, 2282, 0, - 0, 2393, 0, - 0, 2509, 0, - 0, 2628, 0, - 0, 2751, 0, - 0, 2875, 0, - 0, 3002, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3388, 0, - 0, 3519, 0, - 0, 3650, 0, - 964, 1513, 1873, - 949, 1515, 1871, - 928, 1518, 1869, - 899, 1521, 1867, - 857, 1526, 1863, - 794, 1532, 1858, - 692, 1541, 1851, - 507, 1551, 1842, - 0, 1566, 1830, - 0, 1584, 1813, - 0, 1607, 1788, - 0, 1637, 1754, - 0, 1673, 1704, - 0, 1718, 1626, - 0, 1771, 1496, - 0, 1835, 1231, - 0, 1907, 0, - 0, 1989, 0, - 0, 2080, 0, - 0, 2178, 0, - 0, 2283, 0, - 0, 2394, 0, - 0, 2510, 0, - 0, 2629, 0, - 0, 2751, 0, - 0, 2876, 0, - 0, 3002, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 1342, 1525, 1912, - 1336, 1527, 1911, - 1327, 1530, 1909, - 1315, 1533, 1907, - 1299, 1538, 1903, - 1276, 1544, 1899, - 1243, 1552, 1893, - 1195, 1563, 1884, - 1123, 1577, 1873, - 1003, 1595, 1857, - 767, 1617, 1836, - 0, 1646, 1805, - 0, 1682, 1760, - 0, 1726, 1692, - 0, 1779, 1582, - 0, 1841, 1375, - 0, 1912, 699, - 0, 1994, 0, - 0, 2083, 0, - 0, 2181, 0, - 0, 2286, 0, - 0, 2396, 0, - 0, 2511, 0, - 0, 2630, 0, - 0, 2752, 0, - 0, 2877, 0, - 0, 3003, 0, - 0, 3130, 0, - 0, 3259, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 1598, 1542, 1960, - 1594, 1543, 1959, - 1589, 1546, 1957, - 1582, 1549, 1955, - 1573, 1554, 1952, - 1561, 1560, 1948, - 1544, 1568, 1943, - 1520, 1578, 1935, - 1486, 1591, 1925, - 1436, 1608, 1911, - 1359, 1631, 1892, - 1230, 1659, 1865, - 968, 1693, 1826, - 0, 1736, 1768, - 0, 1788, 1676, - 0, 1849, 1516, - 0, 1919, 1135, - 0, 1999, 0, - 0, 2088, 0, - 0, 2185, 0, - 0, 2289, 0, - 0, 2398, 0, - 0, 2513, 0, - 0, 2632, 0, - 0, 2753, 0, - 0, 2877, 0, - 0, 3003, 0, - 0, 3131, 0, - 0, 3260, 0, - 0, 3389, 0, - 0, 3519, 0, - 0, 3650, 0, - 1804, 1562, 2017, - 1802, 1564, 2016, - 1799, 1567, 2015, - 1795, 1570, 2013, - 1789, 1574, 2010, - 1781, 1580, 2007, - 1771, 1587, 2002, - 1756, 1597, 1995, - 1737, 1610, 1987, - 1708, 1626, 1974, - 1668, 1648, 1958, - 1607, 1675, 1934, - 1511, 1708, 1901, - 1338, 1750, 1852, - 901, 1800, 1778, - 0, 1860, 1654, - 0, 1929, 1408, - 0, 2007, 0, - 0, 2095, 0, - 0, 2190, 0, - 0, 2293, 0, - 0, 2402, 0, - 0, 2515, 0, - 0, 2633, 0, - 0, 2755, 0, - 0, 2878, 0, - 0, 3004, 0, - 0, 3132, 0, - 0, 3260, 0, - 0, 3389, 0, - 0, 3520, 0, - 0, 3650, 0, - 1985, 1589, 2084, - 1983, 1591, 2083, - 1981, 1593, 2082, - 1979, 1596, 2080, - 1975, 1600, 2078, - 1970, 1605, 2075, - 1963, 1612, 2071, - 1953, 1622, 2065, - 1941, 1634, 2058, - 1923, 1650, 2047, - 1898, 1670, 2033, - 1862, 1695, 2013, - 1810, 1728, 1985, - 1729, 1768, 1945, - 1591, 1816, 1886, - 1299, 1874, 1791, - 0, 1941, 1623, - 0, 2017, 1207, - 0, 2103, 0, - 0, 2197, 0, - 0, 2298, 0, - 0, 2406, 0, - 0, 2519, 0, - 0, 2636, 0, - 0, 2757, 0, - 0, 2880, 0, - 0, 3005, 0, - 0, 3132, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3650, 0, - 2150, 1622, 2160, - 2149, 1623, 2159, - 2148, 1626, 2158, - 2146, 1628, 2157, - 2143, 1632, 2155, - 2140, 1637, 2152, - 2135, 1644, 2149, - 2129, 1653, 2144, - 2120, 1664, 2138, - 2108, 1679, 2129, - 2092, 1698, 2117, - 2069, 1722, 2101, - 2036, 1752, 2078, - 1989, 1790, 2046, - 1916, 1836, 1999, - 1796, 1892, 1927, - 1562, 1956, 1808, - 499, 2030, 1577, - 0, 2114, 586, - 0, 2206, 0, - 0, 2305, 0, - 0, 2412, 0, - 0, 2523, 0, - 0, 2639, 0, - 0, 2759, 0, - 0, 2882, 0, - 0, 3007, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3520, 0, - 0, 3651, 0, - 2306, 1663, 2246, - 2305, 1664, 2245, - 2304, 1666, 2244, - 2303, 1669, 2243, - 2301, 1672, 2241, - 2298, 1677, 2239, - 2295, 1683, 2236, - 2291, 1691, 2232, - 2284, 1701, 2227, - 2276, 1715, 2220, - 2265, 1732, 2210, - 2249, 1755, 2197, - 2228, 1783, 2179, - 2197, 1819, 2153, - 2153, 1862, 2116, - 2085, 1915, 2061, - 1976, 1976, 1976, - 1771, 2047, 1830, - 1120, 2128, 1507, - 0, 2217, 0, - 0, 2315, 0, - 0, 2419, 0, - 0, 2529, 0, - 0, 2644, 0, - 0, 2763, 0, - 0, 2885, 0, - 0, 3009, 0, - 0, 3135, 0, - 0, 3263, 0, - 0, 3392, 0, - 0, 3521, 0, - 0, 3651, 0, - 2455, 1712, 2339, - 2454, 1713, 2339, - 2453, 1715, 2338, - 2452, 1717, 2337, - 2451, 1721, 2336, - 2449, 1725, 2334, - 2447, 1730, 2332, - 2444, 1737, 2328, - 2439, 1747, 2324, - 2434, 1759, 2318, - 2426, 1775, 2311, - 2415, 1796, 2300, - 2400, 1822, 2285, - 2379, 1854, 2265, - 2350, 1895, 2237, - 2307, 1944, 2195, - 2243, 2002, 2134, - 2141, 2069, 2035, - 1954, 2146, 1857, - 1434, 2233, 1394, - 0, 2327, 0, - 0, 2429, 0, - 0, 2537, 0, - 0, 2650, 0, - 0, 2767, 0, - 0, 2888, 0, - 0, 3012, 0, - 0, 3137, 0, - 0, 3264, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 2599, 1771, 2440, - 2598, 1772, 2440, - 2598, 1773, 2439, - 2597, 1775, 2438, - 2596, 1778, 2437, - 2595, 1782, 2436, - 2593, 1787, 2434, - 2591, 1793, 2432, - 2588, 1801, 2428, - 2584, 1812, 2424, - 2578, 1827, 2418, - 2570, 1845, 2409, - 2560, 1868, 2398, - 2545, 1898, 2382, - 2525, 1935, 2360, - 2496, 1980, 2329, - 2455, 2034, 2284, - 2394, 2097, 2215, - 2296, 2170, 2104, - 2120, 2252, 1892, - 1666, 2343, 1176, - 0, 2441, 0, - 0, 2547, 0, - 0, 2658, 0, - 0, 2773, 0, - 0, 2893, 0, - 0, 3015, 0, - 0, 3140, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3653, 0, - 2740, 1839, 2548, - 2740, 1840, 2547, - 2739, 1841, 2547, - 2739, 1843, 2546, - 2738, 1845, 2545, - 2737, 1848, 2544, - 2736, 1853, 2543, - 2734, 1858, 2541, - 2732, 1865, 2538, - 2729, 1875, 2535, - 2725, 1887, 2530, - 2719, 1903, 2523, - 2711, 1924, 2514, - 2701, 1950, 2502, - 2687, 1983, 2486, - 2667, 2024, 2462, - 2639, 2073, 2429, - 2599, 2132, 2380, - 2539, 2199, 2305, - 2445, 2277, 2181, - 2277, 2363, 1934, - 1861, 2458, 400, - 0, 2560, 0, - 0, 2668, 0, - 0, 2781, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 2878, 1917, 2660, - 2878, 1917, 2660, - 2878, 1919, 2660, - 2878, 1920, 2659, - 2877, 1922, 2659, - 2876, 1925, 2658, - 2875, 1928, 2657, - 2874, 1933, 2655, - 2872, 1939, 2653, - 2870, 1947, 2650, - 2867, 1958, 2646, - 2863, 1972, 2641, - 2858, 1989, 2635, - 2850, 2012, 2625, - 2840, 2041, 2613, - 2826, 2077, 2595, - 2807, 2121, 2570, - 2779, 2174, 2535, - 2740, 2236, 2483, - 2681, 2308, 2403, - 2589, 2389, 2268, - 2426, 2479, 1986, - 2035, 2577, 0, - 0, 2682, 0, - 0, 2792, 0, - 0, 2907, 0, - 0, 3026, 0, - 0, 3148, 0, - 0, 3273, 0, - 0, 3399, 0, - 0, 3527, 0, - 0, 3656, 0, - 3015, 2003, 2777, - 3015, 2004, 2777, - 3015, 2005, 2777, - 3015, 2006, 2776, - 3014, 2008, 2776, - 3014, 2010, 2775, - 3013, 2013, 2774, - 3012, 2017, 2773, - 3011, 2022, 2772, - 3009, 2029, 2770, - 3007, 2038, 2767, - 3004, 2049, 2763, - 3000, 2064, 2758, - 2995, 2084, 2751, - 2987, 2108, 2741, - 2977, 2140, 2728, - 2963, 2178, 2709, - 2944, 2225, 2684, - 2917, 2281, 2647, - 2878, 2347, 2593, - 2821, 2422, 2508, - 2730, 2506, 2363, - 2570, 2599, 2046, - 2196, 2699, 0, - 0, 2806, 0, - 0, 2918, 0, - 0, 3034, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3529, 0, - 0, 3658, 0, - 3151, 2098, 2898, - 3151, 2099, 2898, - 3151, 2099, 2897, - 3150, 2100, 2897, - 3150, 2102, 2897, - 3150, 2104, 2896, - 3149, 2106, 2896, - 3149, 2109, 2895, - 3148, 2113, 2893, - 3147, 2119, 2892, - 3145, 2126, 2890, - 3143, 2136, 2887, - 3140, 2148, 2883, - 3136, 2164, 2877, - 3130, 2185, 2870, - 3123, 2212, 2860, - 3113, 2245, 2847, - 3099, 2286, 2828, - 3080, 2335, 2801, - 3053, 2394, 2763, - 3015, 2462, 2707, - 2958, 2540, 2619, - 2868, 2626, 2466, - 2712, 2721, 2116, - 2349, 2823, 0, - 0, 2932, 0, - 0, 3045, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3407, 0, - 0, 3533, 0, - 0, 3660, 0, - 3286, 2200, 3021, - 3286, 2201, 3021, - 3286, 2201, 3021, - 3285, 2202, 3021, - 3285, 2203, 3020, - 3285, 2205, 3020, - 3284, 2206, 3019, - 3284, 2209, 3019, - 3283, 2212, 3018, - 3282, 2217, 3016, - 3281, 2223, 3015, - 3280, 2231, 3013, - 3277, 2241, 3010, - 3274, 2254, 3006, - 3270, 2271, 3000, - 3265, 2293, 2993, - 3258, 2321, 2983, - 3248, 2356, 2969, - 3234, 2398, 2949, - 3215, 2450, 2922, - 3189, 2511, 2883, - 3151, 2581, 2825, - 3094, 2661, 2734, - 3005, 2749, 2574, - 2850, 2846, 2196, - 2495, 2950, 0, - 0, 3059, 0, - 0, 3174, 0, - 0, 3292, 0, - 0, 3414, 0, - 0, 3538, 0, - 0, 3664, 0, - 3420, 2309, 3146, - 3420, 2309, 3146, - 3420, 2309, 3146, - 3420, 2310, 3146, - 3419, 2311, 3146, - 3419, 2312, 3145, - 3419, 2313, 3145, - 3418, 2315, 3145, - 3418, 2318, 3144, - 3417, 2322, 3143, - 3416, 2326, 3142, - 3415, 2333, 3140, - 3414, 2341, 3138, - 3411, 2351, 3135, - 3408, 2365, 3131, - 3404, 2383, 3125, - 3399, 2406, 3117, - 3392, 2435, 3107, - 3382, 2471, 3093, - 3368, 2516, 3074, - 3350, 2569, 3046, - 3323, 2631, 3006, - 3285, 2703, 2947, - 3229, 2785, 2853, - 3141, 2875, 2688, - 2988, 2973, 2284, - 2638, 3077, 0, - 0, 3188, 0, - 0, 3303, 0, - 0, 3422, 0, - 0, 3544, 0, - 0, 3669, 0, - 3553, 2422, 3273, - 3553, 2422, 3273, - 3553, 2423, 3273, - 3553, 2423, 3273, - 3553, 2424, 3273, - 3553, 2425, 3273, - 3553, 2426, 3272, - 3552, 2427, 3272, - 3552, 2430, 3271, - 3552, 2432, 3271, - 3551, 2436, 3270, - 3550, 2441, 3269, - 3549, 2447, 3267, - 3547, 2456, 3265, - 3545, 2467, 3261, - 3542, 2481, 3257, - 3538, 2500, 3252, - 3533, 2524, 3244, - 3525, 2554, 3234, - 3516, 2591, 3219, - 3502, 2636, 3200, - 3483, 2690, 3172, - 3457, 2754, 3131, - 3419, 2828, 3071, - 3363, 2910, 2976, - 3275, 3002, 2805, - 3123, 3100, 2380, - 2778, 3206, 0, - 0, 3317, 0, - 0, 3433, 0, - 0, 3553, 0, - 0, 3675, 0, - 3687, 2540, 3402, - 3687, 2540, 3402, - 3686, 2540, 3401, - 3686, 2541, 3401, - 3686, 2541, 3401, - 3686, 2542, 3401, - 3686, 2543, 3401, - 3686, 2544, 3401, - 3686, 2545, 3400, - 3685, 2548, 3400, - 3685, 2550, 3399, - 3684, 2554, 3398, - 3683, 2559, 3397, - 3682, 2566, 3395, - 3680, 2575, 3393, - 3678, 2586, 3390, - 3675, 2601, 3385, - 3671, 2620, 3380, - 3666, 2644, 3372, - 3659, 2675, 3362, - 3649, 2713, 3347, - 3635, 2759, 3327, - 3617, 2815, 3299, - 3590, 2880, 3258, - 3553, 2954, 3197, - 3497, 3038, 3100, - 3410, 3130, 2926, - 3258, 3229, 2484, - 2916, 3336, 0, - 0, 3448, 0, - 0, 3564, 0, - 0, 3684, 0, - 3819, 2661, 3531, - 3819, 2661, 3531, - 3819, 2661, 3531, - 3819, 2661, 3531, - 3819, 2662, 3531, - 3819, 2662, 3530, - 3819, 2663, 3530, - 3819, 2664, 3530, - 3819, 2665, 3530, - 3818, 2667, 3529, - 3818, 2669, 3529, - 3818, 2672, 3528, - 3817, 2676, 3527, - 3816, 2681, 3526, - 3815, 2688, 3524, - 3813, 2697, 3522, - 3811, 2708, 3519, - 3808, 2723, 3514, - 3804, 2743, 3509, - 3799, 2768, 3501, - 3792, 2799, 3490, - 3782, 2838, 3476, - 3768, 2885, 3456, - 3750, 2941, 3427, - 3723, 3007, 3386, - 3686, 3082, 3325, - 3630, 3166, 3227, - 3543, 3259, 3050, - 3392, 3359, 2593, - 3052, 3466, 0, - 0, 3578, 0, - 0, 3695, 0, - 3952, 2784, 3661, - 3952, 2784, 3661, - 3952, 2785, 3661, - 3952, 2785, 3661, - 3952, 2785, 3661, - 3952, 2785, 3660, - 3952, 2786, 3660, - 3952, 2787, 3660, - 3952, 2788, 3660, - 3951, 2789, 3660, - 3951, 2791, 3659, - 3951, 2793, 3659, - 3950, 2796, 3658, - 3950, 2800, 3657, - 3949, 2805, 3656, - 3947, 2812, 3654, - 3946, 2821, 3652, - 3944, 2833, 3648, - 3941, 2848, 3644, - 3937, 2868, 3638, - 3932, 2893, 3631, - 3924, 2925, 3620, - 3915, 2964, 3605, - 3901, 3012, 3585, - 3882, 3068, 3556, - 3856, 3135, 3515, - 3819, 3211, 3453, - 3763, 3295, 3354, - 3676, 3389, 3176, - 3526, 3489, 2707, - 3188, 3597, 0, - 0, 3709, 0, - 4085, 2910, 3791, - 4085, 2910, 3791, - 4085, 2910, 3791, - 4085, 2910, 3791, - 4085, 2911, 3791, - 4085, 2911, 3791, - 4085, 2911, 3791, - 4084, 2912, 3791, - 4084, 2912, 3791, - 4084, 2913, 3790, - 4084, 2915, 3790, - 4084, 2916, 3790, - 4083, 2919, 3789, - 4083, 2922, 3788, - 4082, 2926, 3787, - 4081, 2931, 3786, - 4080, 2938, 3784, - 4078, 2947, 3782, - 4076, 2959, 3779, - 4073, 2975, 3775, - 4069, 2995, 3769, - 4064, 3020, 3761, - 4057, 3052, 3750, - 4047, 3092, 3736, - 4034, 3140, 3715, - 4015, 3197, 3686, - 3989, 3264, 3645, - 3951, 3340, 3583, - 3896, 3425, 3483, - 3809, 3519, 3303, - 3659, 3620, 2826, - 3322, 3728, 0, - 4095, 3037, 3922, - 4095, 3037, 3922, - 4095, 3037, 3922, - 4095, 3037, 3922, - 4095, 3038, 3922, - 4095, 3038, 3922, - 4095, 3038, 3922, - 4095, 3039, 3922, - 4095, 3039, 3922, - 4095, 3040, 3921, - 4095, 3041, 3921, - 4095, 3042, 3921, - 4095, 3044, 3920, - 4095, 3046, 3920, - 4095, 3049, 3919, - 4095, 3053, 3918, - 4095, 3059, 3917, - 4095, 3066, 3915, - 4095, 3075, 3913, - 4095, 3087, 3910, - 4095, 3103, 3905, - 4095, 3123, 3900, - 4095, 3149, 3892, - 4095, 3181, 3881, - 4095, 3221, 3866, - 4095, 3269, 3846, - 4095, 3327, 3817, - 4095, 3394, 3775, - 4084, 3470, 3713, - 4029, 3556, 3613, - 3942, 3650, 3432, - 3792, 3751, 2947, - 4095, 3166, 4053, - 4095, 3166, 4053, - 4095, 3166, 4053, - 4095, 3166, 4053, - 4095, 3166, 4053, - 4095, 3166, 4053, - 4095, 3166, 4053, - 4095, 3167, 4053, - 4095, 3167, 4053, - 4095, 3168, 4053, - 4095, 3168, 4053, - 4095, 3169, 4052, - 4095, 3171, 4052, - 4095, 3172, 4052, - 4095, 3175, 4051, - 4095, 3178, 4050, - 4095, 3182, 4049, - 4095, 3187, 4048, - 4095, 3194, 4046, - 4095, 3204, 4044, - 4095, 3216, 4041, - 4095, 3232, 4037, - 4095, 3252, 4031, - 4095, 3278, 4023, - 4095, 3310, 4012, - 4095, 3350, 3997, - 4095, 3399, 3977, - 4095, 3457, 3948, - 4095, 3524, 3906, - 4095, 3601, 3843, - 4095, 3687, 3743, - 4074, 3781, 3561, - 0, 1606, 1871, - 0, 1607, 1869, - 0, 1610, 1867, - 0, 1612, 1864, - 0, 1616, 1861, - 0, 1622, 1856, - 0, 1628, 1849, - 0, 1637, 1840, - 0, 1649, 1827, - 0, 1664, 1810, - 0, 1684, 1786, - 0, 1709, 1751, - 0, 1740, 1701, - 0, 1779, 1623, - 0, 1826, 1491, - 0, 1883, 1222, - 0, 1949, 0, - 0, 2024, 0, - 0, 2108, 0, - 0, 2201, 0, - 0, 2302, 0, - 0, 2409, 0, - 0, 2521, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1606, 1873, - 0, 1608, 1871, - 0, 1610, 1869, - 0, 1613, 1867, - 0, 1617, 1863, - 0, 1622, 1858, - 0, 1629, 1851, - 0, 1638, 1842, - 0, 1650, 1830, - 0, 1665, 1813, - 0, 1684, 1789, - 0, 1709, 1754, - 0, 1741, 1704, - 0, 1779, 1626, - 0, 1827, 1497, - 0, 1883, 1231, - 0, 1949, 0, - 0, 2024, 0, - 0, 2109, 0, - 0, 2202, 0, - 0, 2302, 0, - 0, 2409, 0, - 0, 2521, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1607, 1876, - 0, 1609, 1874, - 0, 1611, 1872, - 0, 1614, 1870, - 0, 1618, 1866, - 0, 1623, 1861, - 0, 1630, 1855, - 0, 1639, 1846, - 0, 1650, 1833, - 0, 1666, 1816, - 0, 1685, 1792, - 0, 1710, 1758, - 0, 1741, 1708, - 0, 1780, 1632, - 0, 1827, 1503, - 0, 1883, 1243, - 0, 1949, 0, - 0, 2024, 0, - 0, 2109, 0, - 0, 2202, 0, - 0, 2302, 0, - 0, 2409, 0, - 0, 2521, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1608, 1880, - 0, 1610, 1878, - 0, 1612, 1876, - 0, 1615, 1874, - 0, 1619, 1870, - 0, 1624, 1865, - 0, 1631, 1859, - 0, 1640, 1850, - 0, 1651, 1838, - 0, 1666, 1821, - 0, 1686, 1797, - 0, 1711, 1763, - 0, 1742, 1714, - 0, 1781, 1638, - 0, 1828, 1512, - 0, 1884, 1259, - 0, 1950, 0, - 0, 2025, 0, - 0, 2109, 0, - 0, 2202, 0, - 0, 2302, 0, - 0, 2409, 0, - 0, 2521, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1609, 1885, - 0, 1611, 1884, - 0, 1613, 1882, - 0, 1616, 1879, - 0, 1620, 1876, - 0, 1625, 1871, - 0, 1632, 1864, - 0, 1641, 1855, - 0, 1652, 1843, - 0, 1668, 1827, - 0, 1687, 1803, - 0, 1712, 1770, - 0, 1743, 1722, - 0, 1782, 1647, - 0, 1829, 1524, - 0, 1885, 1280, - 0, 1950, 0, - 0, 2025, 0, - 0, 2110, 0, - 0, 2202, 0, - 0, 2303, 0, - 0, 2409, 0, - 0, 2522, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1611, 1892, - 0, 1613, 1891, - 0, 1615, 1889, - 0, 1618, 1886, - 0, 1622, 1883, - 0, 1627, 1878, - 0, 1634, 1872, - 0, 1642, 1863, - 0, 1654, 1851, - 0, 1669, 1835, - 0, 1689, 1812, - 0, 1713, 1779, - 0, 1744, 1732, - 0, 1783, 1659, - 0, 1830, 1540, - 0, 1886, 1305, - 0, 1951, 254, - 0, 2026, 0, - 0, 2110, 0, - 0, 2203, 0, - 0, 2303, 0, - 0, 2410, 0, - 0, 2522, 0, - 0, 2638, 0, - 0, 2758, 0, - 0, 2881, 0, - 0, 3006, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1614, 1901, - 0, 1615, 1900, - 0, 1617, 1898, - 0, 1620, 1896, - 0, 1624, 1892, - 0, 1629, 1887, - 0, 1636, 1881, - 0, 1645, 1873, - 0, 1656, 1861, - 0, 1671, 1845, - 0, 1691, 1823, - 0, 1715, 1791, - 0, 1746, 1745, - 0, 1784, 1674, - 0, 1831, 1559, - 0, 1887, 1338, - 0, 1952, 508, - 0, 2027, 0, - 0, 2111, 0, - 0, 2203, 0, - 0, 2304, 0, - 0, 2410, 0, - 0, 2522, 0, - 0, 2639, 0, - 0, 2759, 0, - 0, 2881, 0, - 0, 3007, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3390, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1617, 1913, - 0, 1618, 1912, - 0, 1620, 1910, - 0, 1623, 1908, - 0, 1627, 1904, - 0, 1632, 1900, - 0, 1639, 1894, - 0, 1648, 1885, - 0, 1659, 1874, - 0, 1674, 1859, - 0, 1693, 1837, - 0, 1718, 1806, - 0, 1748, 1761, - 0, 1787, 1694, - 0, 1833, 1584, - 0, 1889, 1378, - 0, 1954, 713, - 0, 2028, 0, - 0, 2112, 0, - 0, 2204, 0, - 0, 2304, 0, - 0, 2411, 0, - 0, 2522, 0, - 0, 2639, 0, - 0, 2759, 0, - 0, 2882, 0, - 0, 3007, 0, - 0, 3133, 0, - 0, 3261, 0, - 0, 3391, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1621, 1929, - 0, 1622, 1928, - 0, 1625, 1926, - 0, 1627, 1923, - 0, 1631, 1920, - 0, 1636, 1916, - 0, 1643, 1910, - 0, 1652, 1902, - 0, 1663, 1891, - 0, 1678, 1876, - 0, 1697, 1855, - 0, 1721, 1826, - 0, 1752, 1783, - 0, 1790, 1719, - 0, 1836, 1616, - 0, 1891, 1426, - 0, 1956, 894, - 0, 2030, 0, - 0, 2113, 0, - 0, 2206, 0, - 0, 2305, 0, - 0, 2411, 0, - 0, 2523, 0, - 0, 2639, 0, - 0, 2759, 0, - 0, 2882, 0, - 0, 3007, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1626, 1949, - 0, 1628, 1948, - 0, 1630, 1946, - 0, 1633, 1944, - 0, 1637, 1940, - 0, 1642, 1936, - 0, 1648, 1931, - 0, 1657, 1923, - 0, 1668, 1913, - 0, 1683, 1898, - 0, 1701, 1878, - 0, 1726, 1851, - 0, 1756, 1810, - 0, 1793, 1750, - 0, 1839, 1655, - 0, 1894, 1484, - 0, 1958, 1059, - 0, 2032, 0, - 0, 2115, 0, - 0, 2207, 0, - 0, 2306, 0, - 0, 2412, 0, - 0, 2524, 0, - 0, 2640, 0, - 0, 2760, 0, - 0, 2882, 0, - 0, 3007, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3520, 0, - 0, 3651, 0, - 0, 1634, 1974, - 0, 1635, 1973, - 0, 1637, 1971, - 0, 1640, 1969, - 0, 1644, 1966, - 0, 1649, 1962, - 0, 1655, 1957, - 0, 1664, 1950, - 0, 1675, 1940, - 0, 1689, 1927, - 0, 1708, 1908, - 0, 1731, 1882, - 0, 1761, 1844, - 0, 1798, 1789, - 0, 1844, 1702, - 0, 1898, 1552, - 0, 1962, 1214, - 0, 2035, 0, - 0, 2118, 0, - 0, 2209, 0, - 0, 2308, 0, - 0, 2414, 0, - 0, 2525, 0, - 0, 2641, 0, - 0, 2760, 0, - 0, 2883, 0, - 0, 3008, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 1107, 1643, 2006, - 1096, 1645, 2005, - 1081, 1647, 2003, - 1061, 1650, 2001, - 1031, 1653, 1999, - 989, 1658, 1995, - 926, 1664, 1990, - 824, 1673, 1983, - 639, 1684, 1974, - 132, 1698, 1962, - 0, 1716, 1945, - 0, 1739, 1921, - 0, 1769, 1886, - 0, 1805, 1836, - 0, 1850, 1758, - 0, 1904, 1628, - 0, 1967, 1363, - 0, 2039, 0, - 0, 2121, 0, - 0, 2212, 0, - 0, 2310, 0, - 0, 2415, 0, - 0, 2526, 0, - 0, 2642, 0, - 0, 2761, 0, - 0, 2883, 0, - 0, 3008, 0, - 0, 3134, 0, - 0, 3262, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 1479, 1656, 2045, - 1474, 1657, 2044, - 1468, 1659, 2043, - 1459, 1662, 2041, - 1447, 1666, 2039, - 1431, 1670, 2035, - 1408, 1676, 2031, - 1375, 1684, 2025, - 1327, 1695, 2016, - 1255, 1709, 2005, - 1135, 1727, 1989, - 899, 1749, 1968, - 0, 1778, 1937, - 0, 1814, 1892, - 0, 1858, 1824, - 0, 1911, 1714, - 0, 1973, 1507, - 0, 2045, 831, - 0, 2126, 0, - 0, 2215, 0, - 0, 2313, 0, - 0, 2418, 0, - 0, 2528, 0, - 0, 2643, 0, - 0, 2762, 0, - 0, 2884, 0, - 0, 3009, 0, - 0, 3135, 0, - 0, 3263, 0, - 0, 3391, 0, - 0, 3521, 0, - 0, 3651, 0, - 1732, 1672, 2093, - 1730, 1674, 2092, - 1726, 1676, 2091, - 1721, 1678, 2089, - 1715, 1681, 2087, - 1706, 1686, 2084, - 1693, 1692, 2080, - 1676, 1700, 2075, - 1652, 1710, 2067, - 1618, 1723, 2057, - 1568, 1741, 2043, - 1491, 1763, 2024, - 1362, 1791, 1997, - 1100, 1826, 1958, - 0, 1868, 1900, - 0, 1920, 1808, - 0, 1981, 1648, - 0, 2052, 1267, - 0, 2132, 0, - 0, 2220, 0, - 0, 2317, 0, - 0, 2421, 0, - 0, 2530, 0, - 0, 2645, 0, - 0, 2764, 0, - 0, 2885, 0, - 0, 3009, 0, - 0, 3136, 0, - 0, 3263, 0, - 0, 3392, 0, - 0, 3521, 0, - 0, 3651, 0, - 1938, 1693, 2150, - 1936, 1694, 2150, - 1934, 1696, 2148, - 1931, 1699, 2147, - 1927, 1702, 2145, - 1921, 1706, 2142, - 1913, 1712, 2139, - 1903, 1719, 2134, - 1889, 1729, 2127, - 1869, 1742, 2119, - 1840, 1759, 2106, - 1800, 1780, 2090, - 1739, 1807, 2066, - 1643, 1841, 2033, - 1470, 1882, 1984, - 1033, 1932, 1910, - 0, 1992, 1786, - 0, 2061, 1540, - 0, 2139, 54, - 0, 2227, 0, - 0, 2322, 0, - 0, 2425, 0, - 0, 2534, 0, - 0, 2648, 0, - 0, 2766, 0, - 0, 2887, 0, - 0, 3011, 0, - 0, 3136, 0, - 0, 3264, 0, - 0, 3392, 0, - 0, 3522, 0, - 0, 3652, 0, - 2118, 1720, 2217, - 2117, 1721, 2216, - 2116, 1723, 2215, - 2113, 1725, 2214, - 2111, 1728, 2212, - 2107, 1732, 2210, - 2102, 1737, 2207, - 2095, 1744, 2203, - 2086, 1754, 2197, - 2073, 1766, 2190, - 2055, 1782, 2179, - 2030, 1802, 2165, - 1994, 1828, 2145, - 1942, 1860, 2118, - 1861, 1900, 2077, - 1723, 1948, 2018, - 1431, 2006, 1923, - 0, 2073, 1755, - 0, 2149, 1339, - 0, 2235, 0, - 0, 2329, 0, - 0, 2430, 0, - 0, 2538, 0, - 0, 2651, 0, - 0, 2768, 0, - 0, 2889, 0, - 0, 3012, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 2283, 1753, 2293, - 2282, 1754, 2292, - 2281, 1756, 2292, - 2280, 1758, 2290, - 2278, 1761, 2289, - 2275, 1764, 2287, - 2272, 1769, 2285, - 2267, 1776, 2281, - 2261, 1785, 2276, - 2252, 1796, 2270, - 2240, 1811, 2261, - 2224, 1830, 2249, - 2201, 1854, 2233, - 2168, 1884, 2210, - 2121, 1922, 2178, - 2048, 1968, 2131, - 1928, 2024, 2059, - 1694, 2088, 1940, - 631, 2163, 1709, - 0, 2246, 718, - 0, 2338, 0, - 0, 2437, 0, - 0, 2544, 0, - 0, 2655, 0, - 0, 2772, 0, - 0, 2891, 0, - 0, 3014, 0, - 0, 3139, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3653, 0, - 2439, 1794, 2378, - 2438, 1795, 2378, - 2437, 1796, 2377, - 2436, 1798, 2376, - 2435, 1801, 2375, - 2433, 1804, 2373, - 2430, 1809, 2371, - 2427, 1815, 2368, - 2423, 1823, 2364, - 2417, 1833, 2359, - 2408, 1847, 2352, - 2397, 1864, 2342, - 2382, 1887, 2329, - 2360, 1915, 2311, - 2329, 1951, 2285, - 2285, 1994, 2248, - 2217, 2047, 2193, - 2108, 2108, 2108, - 1903, 2180, 1962, - 1252, 2260, 1639, - 0, 2350, 0, - 0, 2447, 0, - 0, 2551, 0, - 0, 2661, 0, - 0, 2776, 0, - 0, 2895, 0, - 0, 3017, 0, - 0, 3141, 0, - 0, 3267, 0, - 0, 3395, 0, - 0, 3524, 0, - 0, 3653, 0, - 2587, 1843, 2472, - 2587, 1844, 2471, - 2586, 1845, 2471, - 2585, 1847, 2470, - 2584, 1850, 2469, - 2583, 1853, 2468, - 2581, 1857, 2466, - 2579, 1862, 2464, - 2576, 1869, 2460, - 2571, 1879, 2456, - 2566, 1891, 2451, - 2558, 1907, 2443, - 2547, 1928, 2432, - 2532, 1954, 2418, - 2511, 1986, 2397, - 2482, 2027, 2369, - 2439, 2076, 2327, - 2375, 2134, 2266, - 2273, 2201, 2167, - 2086, 2279, 1990, - 1566, 2365, 1526, - 0, 2459, 0, - 0, 2561, 0, - 0, 2669, 0, - 0, 2782, 0, - 0, 2899, 0, - 0, 3020, 0, - 0, 3144, 0, - 0, 3269, 0, - 0, 3396, 0, - 0, 3525, 0, - 0, 3654, 0, - 2731, 1902, 2573, - 2731, 1903, 2572, - 2731, 1904, 2572, - 2730, 1906, 2571, - 2729, 1908, 2570, - 2728, 1910, 2569, - 2727, 1914, 2568, - 2725, 1919, 2566, - 2723, 1925, 2564, - 2720, 1933, 2560, - 2716, 1944, 2556, - 2710, 1959, 2550, - 2702, 1977, 2541, - 2692, 2000, 2530, - 2677, 2030, 2514, - 2657, 2067, 2492, - 2629, 2112, 2461, - 2588, 2166, 2416, - 2526, 2229, 2347, - 2428, 2302, 2236, - 2252, 2384, 2024, - 1798, 2475, 1309, - 0, 2574, 0, - 0, 2679, 0, - 0, 2790, 0, - 0, 2906, 0, - 0, 3025, 0, - 0, 3147, 0, - 0, 3272, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 2872, 1970, 2680, - 2872, 1971, 2680, - 2872, 1972, 2679, - 2871, 1973, 2679, - 2871, 1975, 2678, - 2870, 1977, 2677, - 2869, 1981, 2676, - 2868, 1985, 2675, - 2866, 1990, 2673, - 2864, 1998, 2670, - 2861, 2007, 2667, - 2857, 2019, 2662, - 2851, 2036, 2655, - 2843, 2056, 2646, - 2833, 2083, 2634, - 2819, 2115, 2618, - 2799, 2156, 2594, - 2771, 2205, 2561, - 2731, 2264, 2512, - 2672, 2332, 2437, - 2577, 2409, 2314, - 2409, 2495, 2066, - 1993, 2590, 532, - 0, 2692, 0, - 0, 2800, 0, - 0, 2914, 0, - 0, 3031, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3657, 0, - 3011, 2048, 2793, - 3011, 2049, 2792, - 3010, 2050, 2792, - 3010, 2051, 2792, - 3010, 2052, 2791, - 3009, 2054, 2791, - 3008, 2057, 2790, - 3007, 2060, 2789, - 3006, 2065, 2787, - 3005, 2071, 2785, - 3002, 2079, 2782, - 2999, 2090, 2779, - 2995, 2104, 2774, - 2990, 2122, 2767, - 2982, 2144, 2757, - 2972, 2173, 2745, - 2958, 2209, 2727, - 2939, 2253, 2702, - 2911, 2306, 2667, - 2872, 2368, 2616, - 2813, 2440, 2536, - 2721, 2521, 2400, - 2558, 2611, 2118, - 2167, 2709, 0, - 0, 2814, 0, - 0, 2924, 0, - 0, 3039, 0, - 0, 3158, 0, - 0, 3280, 0, - 0, 3405, 0, - 0, 3531, 0, - 0, 3659, 0, - 3148, 2135, 2910, - 3147, 2135, 2909, - 3147, 2136, 2909, - 3147, 2137, 2909, - 3147, 2138, 2909, - 3146, 2140, 2908, - 3146, 2142, 2907, - 3145, 2145, 2907, - 3144, 2149, 2905, - 3143, 2154, 2904, - 3141, 2161, 2902, - 3139, 2170, 2899, - 3136, 2181, 2895, - 3132, 2196, 2890, - 3127, 2216, 2883, - 3119, 2241, 2873, - 3109, 2272, 2860, - 3095, 2310, 2842, - 3076, 2357, 2816, - 3049, 2413, 2779, - 3010, 2479, 2725, - 2953, 2554, 2640, - 2862, 2638, 2495, - 2703, 2731, 2178, - 2328, 2831, 0, - 0, 2938, 0, - 0, 3050, 0, - 0, 3167, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 3283, 2230, 3030, - 3283, 2230, 3030, - 3283, 2231, 3030, - 3283, 2232, 3030, - 3283, 2233, 3029, - 3282, 2234, 3029, - 3282, 2236, 3028, - 3281, 2238, 3028, - 3281, 2241, 3027, - 3280, 2245, 3026, - 3279, 2251, 3024, - 3277, 2258, 3022, - 3275, 2268, 3019, - 3272, 2280, 3015, - 3268, 2297, 3010, - 3262, 2317, 3002, - 3255, 2344, 2992, - 3245, 2377, 2979, - 3231, 2418, 2960, - 3212, 2467, 2933, - 3186, 2526, 2896, - 3147, 2594, 2839, - 3090, 2672, 2751, - 3000, 2758, 2598, - 2844, 2853, 2248, - 2481, 2955, 0, - 0, 3064, 0, - 0, 3177, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3418, 2332, 3153, - 3418, 2332, 3153, - 3418, 2333, 3153, - 3418, 2333, 3153, - 3417, 2334, 3153, - 3417, 2335, 3152, - 3417, 2337, 3152, - 3417, 2339, 3151, - 3416, 2341, 3151, - 3415, 2344, 3150, - 3414, 2349, 3149, - 3413, 2355, 3147, - 3412, 2363, 3145, - 3409, 2373, 3142, - 3406, 2386, 3138, - 3403, 2403, 3132, - 3397, 2425, 3125, - 3390, 2453, 3115, - 3380, 2488, 3101, - 3366, 2531, 3082, - 3347, 2582, 3054, - 3321, 2643, 3016, - 3283, 2713, 2958, - 3226, 2793, 2866, - 3137, 2882, 2706, - 2983, 2978, 2328, - 2627, 3082, 0, - 0, 3191, 0, - 0, 3306, 0, - 0, 3424, 0, - 0, 3546, 0, - 0, 3670, 0, - 3552, 2440, 3279, - 3552, 2441, 3278, - 3552, 2441, 3278, - 3552, 2441, 3278, - 3552, 2442, 3278, - 3551, 2443, 3278, - 3551, 2444, 3278, - 3551, 2446, 3277, - 3551, 2448, 3277, - 3550, 2450, 3276, - 3549, 2454, 3275, - 3549, 2458, 3274, - 3547, 2465, 3272, - 3546, 2473, 3270, - 3543, 2484, 3267, - 3541, 2497, 3263, - 3537, 2515, 3257, - 3531, 2538, 3250, - 3524, 2567, 3239, - 3514, 2603, 3225, - 3500, 2648, 3206, - 3482, 2701, 3178, - 3455, 2763, 3138, - 3417, 2835, 3079, - 3361, 2917, 2986, - 3273, 3007, 2820, - 3120, 3105, 2416, - 2770, 3209, 0, - 0, 3320, 0, - 0, 3435, 0, - 0, 3554, 0, - 0, 3676, 0, - 3685, 2554, 3406, - 3685, 2554, 3405, - 3685, 2554, 3405, - 3685, 2555, 3405, - 3685, 2555, 3405, - 3685, 2556, 3405, - 3685, 2557, 3405, - 3685, 2558, 3405, - 3684, 2560, 3404, - 3684, 2562, 3404, - 3684, 2564, 3403, - 3683, 2568, 3402, - 3682, 2573, 3401, - 3681, 2579, 3399, - 3679, 2588, 3397, - 3677, 2599, 3394, - 3674, 2613, 3389, - 3670, 2632, 3384, - 3665, 2656, 3376, - 3658, 2686, 3366, - 3648, 2723, 3351, - 3634, 2768, 3332, - 3615, 2823, 3304, - 3589, 2886, 3263, - 3551, 2960, 3203, - 3495, 3042, 3108, - 3408, 3134, 2938, - 3255, 3233, 2512, - 2910, 3338, 0, - 0, 3449, 0, - 0, 3565, 0, - 0, 3685, 0, - 3819, 2672, 3534, - 3819, 2672, 3534, - 3819, 2672, 3534, - 3819, 2672, 3534, - 3818, 2673, 3533, - 3818, 2673, 3533, - 3818, 2674, 3533, - 3818, 2675, 3533, - 3818, 2676, 3533, - 3818, 2678, 3532, - 3817, 2680, 3532, - 3817, 2683, 3531, - 3816, 2686, 3530, - 3815, 2691, 3529, - 3814, 2698, 3527, - 3812, 2707, 3525, - 3810, 2718, 3522, - 3807, 2733, 3517, - 3803, 2752, 3512, - 3798, 2776, 3504, - 3791, 2807, 3494, - 3781, 2845, 3479, - 3767, 2891, 3459, - 3749, 2947, 3431, - 3722, 3012, 3390, - 3685, 3086, 3329, - 3629, 3170, 3232, - 3542, 3262, 3059, - 3390, 3362, 2616, - 3048, 3468, 0, - 0, 3580, 0, - 0, 3696, 0, - 3952, 2793, 3663, - 3952, 2793, 3663, - 3952, 2793, 3663, - 3951, 2793, 3663, - 3951, 2793, 3663, - 3951, 2794, 3663, - 3951, 2794, 3663, - 3951, 2795, 3662, - 3951, 2796, 3662, - 3951, 2797, 3662, - 3951, 2799, 3661, - 3950, 2801, 3661, - 3950, 2804, 3660, - 3949, 2808, 3659, - 3948, 2813, 3658, - 3947, 2820, 3656, - 3945, 2829, 3654, - 3943, 2840, 3651, - 3940, 2856, 3646, - 3936, 2875, 3641, - 3931, 2900, 3633, - 3924, 2931, 3622, - 3914, 2970, 3608, - 3900, 3017, 3588, - 3882, 3073, 3559, - 3856, 3139, 3518, - 3818, 3214, 3457, - 3762, 3298, 3359, - 3675, 3391, 3182, - 3524, 3491, 2725, - 3184, 3598, 0, - 0, 3710, 0, - 4084, 2916, 3793, - 4084, 2916, 3793, - 4084, 2916, 3793, - 4084, 2917, 3793, - 4084, 2917, 3793, - 4084, 2917, 3793, - 4084, 2918, 3793, - 4084, 2918, 3792, - 4084, 2919, 3792, - 4084, 2920, 3792, - 4083, 2921, 3792, - 4083, 2923, 3791, - 4083, 2925, 3791, - 4082, 2928, 3790, - 4082, 2932, 3789, - 4081, 2937, 3788, - 4080, 2944, 3786, - 4078, 2953, 3784, - 4076, 2965, 3781, - 4073, 2980, 3776, - 4069, 3000, 3771, - 4064, 3025, 3763, - 4056, 3057, 3752, - 4047, 3096, 3738, - 4033, 3144, 3717, - 4015, 3201, 3689, - 3988, 3267, 3647, - 3951, 3343, 3585, - 3895, 3428, 3486, - 3808, 3521, 3308, - 3658, 3622, 2839, - 3320, 3729, 0, - 4095, 3042, 3923, - 4095, 3042, 3923, - 4095, 3042, 3923, - 4095, 3042, 3923, - 4095, 3042, 3923, - 4095, 3043, 3923, - 4095, 3043, 3923, - 4095, 3043, 3923, - 4095, 3044, 3923, - 4095, 3045, 3923, - 4095, 3046, 3922, - 4095, 3047, 3922, - 4095, 3049, 3922, - 4095, 3051, 3921, - 4095, 3054, 3920, - 4095, 3058, 3919, - 4095, 3063, 3918, - 4095, 3070, 3916, - 4095, 3079, 3914, - 4095, 3091, 3911, - 4095, 3107, 3907, - 4095, 3127, 3901, - 4095, 3152, 3893, - 4095, 3184, 3882, - 4095, 3224, 3868, - 4095, 3272, 3847, - 4095, 3329, 3819, - 4095, 3396, 3777, - 4084, 3472, 3715, - 4028, 3558, 3615, - 3941, 3651, 3435, - 3791, 3752, 2958, - 4095, 3169, 4054, - 4095, 3169, 4054, - 4095, 3169, 4054, - 4095, 3169, 4054, - 4095, 3169, 4054, - 4095, 3170, 4054, - 4095, 3170, 4054, - 4095, 3170, 4054, - 4095, 3171, 4054, - 4095, 3171, 4054, - 4095, 3172, 4054, - 4095, 3173, 4053, - 4095, 3174, 4053, - 4095, 3176, 4053, - 4095, 3178, 4052, - 4095, 3181, 4051, - 4095, 3185, 4050, - 4095, 3191, 4049, - 4095, 3198, 4047, - 4095, 3207, 4045, - 4095, 3219, 4042, - 4095, 3235, 4037, - 4095, 3255, 4032, - 4095, 3281, 4024, - 4095, 3313, 4013, - 4095, 3353, 3998, - 4095, 3401, 3978, - 4095, 3459, 3949, - 4095, 3526, 3907, - 4095, 3602, 3845, - 4095, 3688, 3745, - 4074, 3782, 3564, - 0, 1736, 2002, - 0, 1737, 2001, - 0, 1739, 2000, - 0, 1741, 1998, - 0, 1744, 1995, - 0, 1748, 1991, - 0, 1753, 1986, - 0, 1760, 1979, - 0, 1769, 1970, - 0, 1781, 1958, - 0, 1796, 1940, - 0, 1816, 1916, - 0, 1841, 1881, - 0, 1872, 1830, - 0, 1911, 1752, - 0, 1958, 1620, - 0, 2015, 1347, - 0, 2080, 0, - 0, 2156, 0, - 0, 2240, 0, - 0, 2333, 0, - 0, 2434, 0, - 0, 2541, 0, - 0, 2653, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 0, 1737, 2004, - 0, 1738, 2003, - 0, 1739, 2001, - 0, 1742, 1999, - 0, 1745, 1997, - 0, 1749, 1993, - 0, 1754, 1988, - 0, 1761, 1981, - 0, 1769, 1972, - 0, 1781, 1960, - 0, 1796, 1942, - 0, 1816, 1918, - 0, 1841, 1883, - 0, 1872, 1833, - 0, 1911, 1755, - 0, 1958, 1624, - 0, 2015, 1354, - 0, 2081, 0, - 0, 2156, 0, - 0, 2241, 0, - 0, 2333, 0, - 0, 2434, 0, - 0, 2541, 0, - 0, 2653, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 0, 1737, 2006, - 0, 1738, 2005, - 0, 1740, 2004, - 0, 1742, 2002, - 0, 1745, 1999, - 0, 1749, 1995, - 0, 1754, 1990, - 0, 1761, 1984, - 0, 1770, 1974, - 0, 1782, 1962, - 0, 1797, 1945, - 0, 1817, 1921, - 0, 1841, 1886, - 0, 1873, 1836, - 0, 1912, 1759, - 0, 1959, 1629, - 0, 2015, 1363, - 0, 2081, 0, - 0, 2156, 0, - 0, 2241, 0, - 0, 2334, 0, - 0, 2434, 0, - 0, 2541, 0, - 0, 2653, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 0, 1738, 2009, - 0, 1739, 2008, - 0, 1741, 2007, - 0, 1743, 2005, - 0, 1746, 2002, - 0, 1750, 1998, - 0, 1755, 1993, - 0, 1762, 1987, - 0, 1771, 1978, - 0, 1782, 1965, - 0, 1798, 1948, - 0, 1817, 1924, - 0, 1842, 1890, - 0, 1873, 1840, - 0, 1912, 1764, - 0, 1959, 1636, - 0, 2015, 1375, - 0, 2081, 0, - 0, 2157, 0, - 0, 2241, 0, - 0, 2334, 0, - 0, 2434, 0, - 0, 2541, 0, - 0, 2653, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 0, 1739, 2013, - 0, 1740, 2012, - 0, 1742, 2011, - 0, 1744, 2009, - 0, 1747, 2006, - 0, 1751, 2002, - 0, 1756, 1997, - 0, 1763, 1991, - 0, 1772, 1982, - 0, 1783, 1970, - 0, 1798, 1953, - 0, 1818, 1929, - 0, 1843, 1895, - 0, 1874, 1846, - 0, 1913, 1771, - 0, 1960, 1645, - 0, 2016, 1391, - 0, 2082, 0, - 0, 2157, 0, - 0, 2241, 0, - 0, 2334, 0, - 0, 2434, 0, - 0, 2541, 0, - 0, 2653, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 0, 1740, 2018, - 0, 1741, 2017, - 0, 1743, 2016, - 0, 1745, 2014, - 0, 1748, 2011, - 0, 1752, 2008, - 0, 1757, 2003, - 0, 1764, 1996, - 0, 1773, 1988, - 0, 1785, 1975, - 0, 1800, 1959, - 0, 1819, 1935, - 0, 1844, 1902, - 0, 1875, 1854, - 0, 1914, 1779, - 0, 1961, 1656, - 0, 2017, 1412, - 0, 2082, 13, - 0, 2157, 0, - 0, 2242, 0, - 0, 2334, 0, - 0, 2435, 0, - 0, 2541, 0, - 0, 2654, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3138, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3522, 0, - 0, 3652, 0, - 0, 1742, 2025, - 0, 1743, 2024, - 0, 1745, 2023, - 0, 1747, 2021, - 0, 1750, 2018, - 0, 1754, 2015, - 0, 1759, 2010, - 0, 1766, 2004, - 0, 1775, 1995, - 0, 1786, 1983, - 0, 1801, 1967, - 0, 1821, 1944, - 0, 1845, 1911, - 0, 1876, 1864, - 0, 1915, 1791, - 0, 1962, 1672, - 0, 2018, 1438, - 0, 2083, 386, - 0, 2158, 0, - 0, 2242, 0, - 0, 2335, 0, - 0, 2435, 0, - 0, 2542, 0, - 0, 2654, 0, - 0, 2770, 0, - 0, 2890, 0, - 0, 3013, 0, - 0, 3139, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3523, 0, - 0, 3652, 0, - 0, 1744, 2035, - 0, 1746, 2033, - 0, 1747, 2032, - 0, 1749, 2030, - 0, 1752, 2028, - 0, 1756, 2024, - 0, 1761, 2020, - 0, 1768, 2013, - 0, 1777, 2005, - 0, 1788, 1993, - 0, 1803, 1977, - 0, 1823, 1955, - 0, 1847, 1923, - 0, 1878, 1877, - 0, 1917, 1806, - 0, 1963, 1691, - 0, 2019, 1470, - 0, 2084, 640, - 0, 2159, 0, - 0, 2243, 0, - 0, 2336, 0, - 0, 2436, 0, - 0, 2542, 0, - 0, 2654, 0, - 0, 2771, 0, - 0, 2891, 0, - 0, 3014, 0, - 0, 3139, 0, - 0, 3265, 0, - 0, 3393, 0, - 0, 3523, 0, - 0, 3652, 0, - 0, 1748, 2046, - 0, 1749, 2045, - 0, 1750, 2044, - 0, 1753, 2042, - 0, 1755, 2040, - 0, 1759, 2036, - 0, 1764, 2032, - 0, 1771, 2026, - 0, 1780, 2018, - 0, 1791, 2006, - 0, 1806, 1991, - 0, 1825, 1969, - 0, 1850, 1938, - 0, 1881, 1893, - 0, 1919, 1826, - 0, 1965, 1716, - 0, 2021, 1510, - 0, 2086, 846, - 0, 2160, 0, - 0, 2244, 0, - 0, 2336, 0, - 0, 2436, 0, - 0, 2543, 0, - 0, 2655, 0, - 0, 2771, 0, - 0, 2891, 0, - 0, 3014, 0, - 0, 3139, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3652, 0, - 0, 1752, 2062, - 0, 1753, 2061, - 0, 1755, 2060, - 0, 1757, 2058, - 0, 1760, 2055, - 0, 1763, 2052, - 0, 1768, 2048, - 0, 1775, 2042, - 0, 1784, 2034, - 0, 1795, 2023, - 0, 1810, 2008, - 0, 1829, 1987, - 0, 1853, 1958, - 0, 1884, 1915, - 0, 1922, 1851, - 0, 1968, 1748, - 0, 2023, 1559, - 0, 2088, 1026, - 0, 2162, 0, - 0, 2246, 0, - 0, 2338, 0, - 0, 2437, 0, - 0, 2543, 0, - 0, 2655, 0, - 0, 2771, 0, - 0, 2891, 0, - 0, 3014, 0, - 0, 3139, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3652, 0, - 0, 1757, 2082, - 0, 1759, 2081, - 0, 1760, 2080, - 0, 1762, 2078, - 0, 1765, 2076, - 0, 1769, 2073, - 0, 1774, 2068, - 0, 1780, 2063, - 0, 1789, 2055, - 0, 1800, 2045, - 0, 1815, 2030, - 0, 1834, 2011, - 0, 1858, 1983, - 0, 1888, 1942, - 0, 1925, 1882, - 0, 1971, 1787, - 0, 2026, 1616, - 0, 2090, 1191, - 0, 2164, 0, - 0, 2247, 0, - 0, 2339, 0, - 0, 2438, 0, - 0, 2544, 0, - 0, 2656, 0, - 0, 2772, 0, - 0, 2892, 0, - 0, 3014, 0, - 0, 3139, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3653, 0, - 30, 1765, 2107, - 0, 1766, 2106, - 0, 1767, 2105, - 0, 1770, 2103, - 0, 1772, 2101, - 0, 1776, 2098, - 0, 1781, 2094, - 0, 1787, 2089, - 0, 1796, 2082, - 0, 1807, 2072, - 0, 1821, 2059, - 0, 1840, 2040, - 0, 1864, 2014, - 0, 1893, 1976, - 0, 1931, 1921, - 0, 1976, 1834, - 0, 2030, 1684, - 0, 2094, 1346, - 0, 2167, 0, - 0, 2250, 0, - 0, 2341, 0, - 0, 2440, 0, - 0, 2546, 0, - 0, 2657, 0, - 0, 2773, 0, - 0, 2892, 0, - 0, 3015, 0, - 0, 3140, 0, - 0, 3266, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3653, 0, - 1247, 1774, 2139, - 1239, 1775, 2138, - 1228, 1777, 2137, - 1213, 1779, 2136, - 1193, 1782, 2133, - 1163, 1785, 2131, - 1121, 1790, 2127, - 1058, 1796, 2122, - 956, 1805, 2116, - 771, 1816, 2106, - 265, 1830, 2094, - 0, 1848, 2077, - 0, 1871, 2053, - 0, 1901, 2018, - 0, 1937, 1968, - 0, 1982, 1890, - 0, 2036, 1760, - 0, 2099, 1495, - 0, 2171, 0, - 0, 2253, 0, - 0, 2344, 0, - 0, 2442, 0, - 0, 2547, 0, - 0, 2658, 0, - 0, 2774, 0, - 0, 2893, 0, - 0, 3015, 0, - 0, 3140, 0, - 0, 3267, 0, - 0, 3394, 0, - 0, 3523, 0, - 0, 3653, 0, - 1614, 1787, 2178, - 1611, 1788, 2178, - 1606, 1790, 2177, - 1600, 1792, 2175, - 1591, 1794, 2173, - 1579, 1798, 2171, - 1563, 1802, 2167, - 1540, 1808, 2163, - 1507, 1817, 2157, - 1459, 1827, 2149, - 1387, 1841, 2137, - 1267, 1859, 2122, - 1031, 1881, 2100, - 0, 1910, 2069, - 0, 1946, 2024, - 0, 1990, 1956, - 0, 2043, 1846, - 0, 2105, 1639, - 0, 2177, 963, - 0, 2258, 0, - 0, 2348, 0, - 0, 2445, 0, - 0, 2550, 0, - 0, 2660, 0, - 0, 2775, 0, - 0, 2894, 0, - 0, 3016, 0, - 0, 3141, 0, - 0, 3267, 0, - 0, 3395, 0, - 0, 3523, 0, - 0, 3653, 0, - 1867, 1803, 2226, - 1865, 1804, 2225, - 1862, 1806, 2224, - 1858, 1808, 2223, - 1853, 1810, 2222, - 1847, 1814, 2219, - 1838, 1818, 2216, - 1825, 1824, 2212, - 1808, 1832, 2207, - 1784, 1842, 2199, - 1750, 1855, 2189, - 1700, 1873, 2175, - 1623, 1895, 2156, - 1494, 1923, 2129, - 1232, 1958, 2090, - 0, 2000, 2032, - 0, 2052, 1940, - 0, 2113, 1780, - 0, 2184, 1399, - 0, 2264, 0, - 0, 2352, 0, - 0, 2449, 0, - 0, 2553, 0, - 0, 2663, 0, - 0, 2777, 0, - 0, 2896, 0, - 0, 3017, 0, - 0, 3142, 0, - 0, 3268, 0, - 0, 3395, 0, - 0, 3524, 0, - 0, 3653, 0, - 2071, 1824, 2283, - 2070, 1825, 2282, - 2068, 1827, 2282, - 2066, 1828, 2281, - 2063, 1831, 2279, - 2059, 1834, 2277, - 2053, 1838, 2274, - 2046, 1844, 2271, - 2035, 1851, 2266, - 2021, 1861, 2260, - 2001, 1874, 2251, - 1973, 1891, 2239, - 1932, 1912, 2222, - 1871, 1939, 2198, - 1775, 1973, 2165, - 1602, 2014, 2117, - 1165, 2064, 2042, - 0, 2124, 1918, - 0, 2193, 1672, - 0, 2271, 186, - 0, 2359, 0, - 0, 2454, 0, - 0, 2557, 0, - 0, 2666, 0, - 0, 2780, 0, - 0, 2898, 0, - 0, 3019, 0, - 0, 3143, 0, - 0, 3268, 0, - 0, 3396, 0, - 0, 3524, 0, - 0, 3654, 0, - 2251, 1851, 2350, - 2250, 1852, 2349, - 2249, 1853, 2348, - 2248, 1855, 2347, - 2246, 1857, 2346, - 2243, 1860, 2344, - 2239, 1864, 2342, - 2234, 1869, 2339, - 2227, 1877, 2335, - 2218, 1886, 2329, - 2205, 1898, 2322, - 2187, 1914, 2311, - 2162, 1934, 2297, - 2127, 1960, 2277, - 2074, 1992, 2250, - 1993, 2032, 2210, - 1855, 2080, 2150, - 1563, 2138, 2055, - 0, 2205, 1887, - 0, 2281, 1471, - 0, 2367, 0, - 0, 2461, 0, - 0, 2562, 0, - 0, 2670, 0, - 0, 2783, 0, - 0, 2900, 0, - 0, 3021, 0, - 0, 3144, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 2416, 1884, 2425, - 2415, 1885, 2425, - 2415, 1886, 2424, - 2413, 1888, 2424, - 2412, 1890, 2423, - 2410, 1893, 2421, - 2408, 1896, 2419, - 2404, 1901, 2417, - 2399, 1908, 2413, - 2393, 1917, 2408, - 2384, 1928, 2402, - 2372, 1943, 2393, - 2356, 1962, 2382, - 2333, 1986, 2365, - 2300, 2017, 2342, - 2253, 2054, 2310, - 2180, 2101, 2263, - 2060, 2156, 2191, - 1826, 2220, 2072, - 763, 2295, 1841, - 0, 2378, 850, - 0, 2470, 0, - 0, 2570, 0, - 0, 2676, 0, - 0, 2787, 0, - 0, 2904, 0, - 0, 3023, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 2571, 1925, 2511, - 2571, 1926, 2510, - 2570, 1927, 2510, - 2569, 1928, 2509, - 2568, 1930, 2508, - 2567, 1933, 2507, - 2565, 1936, 2505, - 2563, 1941, 2503, - 2559, 1947, 2500, - 2555, 1955, 2496, - 2549, 1965, 2491, - 2540, 1979, 2484, - 2529, 1997, 2474, - 2514, 2019, 2461, - 2492, 2048, 2443, - 2461, 2083, 2417, - 2417, 2126, 2380, - 2350, 2179, 2326, - 2240, 2240, 2240, - 2036, 2312, 2094, - 1384, 2392, 1771, - 0, 2482, 0, - 0, 2579, 0, - 0, 2683, 0, - 0, 2793, 0, - 0, 2908, 0, - 0, 3027, 0, - 0, 3149, 0, - 0, 3273, 0, - 0, 3399, 0, - 0, 3527, 0, - 0, 3656, 0, - 2720, 1975, 2604, - 2719, 1975, 2604, - 2719, 1976, 2603, - 2718, 1978, 2603, - 2718, 1979, 2602, - 2717, 1982, 2601, - 2715, 1985, 2600, - 2713, 1989, 2598, - 2711, 1994, 2596, - 2708, 2002, 2593, - 2704, 2011, 2588, - 2698, 2023, 2583, - 2690, 2039, 2575, - 2679, 2060, 2564, - 2664, 2086, 2550, - 2643, 2119, 2529, - 2614, 2159, 2501, - 2571, 2208, 2460, - 2508, 2266, 2398, - 2405, 2333, 2299, - 2218, 2411, 2122, - 1698, 2497, 1658, - 0, 2591, 0, - 0, 2693, 0, - 0, 2801, 0, - 0, 2914, 0, - 0, 3032, 0, - 0, 3152, 0, - 0, 3276, 0, - 0, 3401, 0, - 0, 3529, 0, - 0, 3657, 0, - 2864, 2033, 2705, - 2863, 2034, 2705, - 2863, 2035, 2704, - 2863, 2036, 2704, - 2862, 2038, 2703, - 2861, 2040, 2703, - 2860, 2042, 2702, - 2859, 2046, 2700, - 2857, 2051, 2698, - 2855, 2057, 2696, - 2852, 2066, 2692, - 2848, 2076, 2688, - 2842, 2091, 2682, - 2834, 2109, 2673, - 2824, 2133, 2662, - 2809, 2162, 2646, - 2789, 2199, 2624, - 2761, 2244, 2593, - 2720, 2298, 2548, - 2658, 2361, 2479, - 2560, 2434, 2368, - 2385, 2516, 2156, - 1930, 2607, 1441, - 0, 2706, 0, - 0, 2811, 0, - 0, 2922, 0, - 0, 3038, 0, - 0, 3157, 0, - 0, 3279, 0, - 0, 3404, 0, - 0, 3531, 0, - 0, 3658, 0, - 3004, 2102, 2812, - 3004, 2102, 2812, - 3004, 2103, 2812, - 3004, 2104, 2811, - 3003, 2105, 2811, - 3003, 2107, 2810, - 3002, 2110, 2810, - 3001, 2113, 2808, - 3000, 2117, 2807, - 2998, 2122, 2805, - 2996, 2130, 2802, - 2993, 2139, 2799, - 2989, 2152, 2794, - 2983, 2168, 2787, - 2976, 2188, 2779, - 2965, 2215, 2766, - 2951, 2248, 2750, - 2931, 2288, 2726, - 2903, 2337, 2693, - 2863, 2396, 2644, - 2804, 2464, 2570, - 2709, 2541, 2446, - 2541, 2628, 2199, - 2125, 2722, 664, - 0, 2824, 0, - 0, 2932, 0, - 0, 3046, 0, - 0, 3163, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3660, 0, - 3143, 2180, 2925, - 3143, 2180, 2925, - 3143, 2181, 2924, - 3142, 2182, 2924, - 3142, 2183, 2924, - 3142, 2184, 2923, - 3141, 2186, 2923, - 3141, 2189, 2922, - 3140, 2192, 2921, - 3138, 2197, 2919, - 3137, 2203, 2917, - 3134, 2211, 2914, - 3131, 2222, 2911, - 3127, 2236, 2906, - 3122, 2254, 2899, - 3114, 2276, 2890, - 3104, 2305, 2877, - 3090, 2341, 2859, - 3071, 2385, 2835, - 3043, 2438, 2799, - 3004, 2500, 2748, - 2945, 2572, 2668, - 2853, 2653, 2532, - 2690, 2743, 2250, - 2299, 2841, 0, - 0, 2946, 0, - 0, 3056, 0, - 0, 3171, 0, - 0, 3290, 0, - 0, 3412, 0, - 0, 3537, 0, - 0, 3663, 0, - 3280, 2267, 3042, - 3280, 2267, 3042, - 3280, 2267, 3041, - 3279, 2268, 3041, - 3279, 2269, 3041, - 3279, 2270, 3041, - 3278, 2272, 3040, - 3278, 2274, 3039, - 3277, 2277, 3039, - 3276, 2281, 3037, - 3275, 2286, 3036, - 3273, 2293, 3034, - 3271, 2302, 3031, - 3268, 2313, 3027, - 3264, 2328, 3022, - 3259, 2348, 3015, - 3251, 2373, 3005, - 3241, 2404, 2992, - 3227, 2442, 2974, - 3208, 2489, 2948, - 3181, 2545, 2911, - 3142, 2611, 2857, - 3085, 2686, 2773, - 2994, 2770, 2628, - 2835, 2863, 2310, - 2460, 2963, 0, - 0, 3070, 0, - 0, 3182, 0, - 0, 3299, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 3415, 2362, 3162, - 3415, 2362, 3162, - 3415, 2362, 3162, - 3415, 2363, 3162, - 3415, 2364, 3162, - 3415, 2365, 3161, - 3414, 2366, 3161, - 3414, 2368, 3160, - 3414, 2370, 3160, - 3413, 2373, 3159, - 3412, 2377, 3158, - 3411, 2383, 3156, - 3409, 2390, 3154, - 3407, 2400, 3151, - 3404, 2412, 3147, - 3400, 2429, 3142, - 3394, 2449, 3134, - 3387, 2476, 3124, - 3377, 2509, 3111, - 3363, 2550, 3092, - 3344, 2599, 3066, - 3318, 2658, 3028, - 3279, 2726, 2971, - 3222, 2804, 2883, - 3132, 2891, 2730, - 2976, 2985, 2380, - 2613, 3088, 0, - 0, 3196, 0, - 0, 3309, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3550, 2464, 3285, - 3550, 2464, 3285, - 3550, 2464, 3285, - 3550, 2465, 3285, - 3550, 2465, 3285, - 3550, 2466, 3285, - 3549, 2467, 3284, - 3549, 2469, 3284, - 3549, 2471, 3284, - 3548, 2473, 3283, - 3548, 2477, 3282, - 3547, 2481, 3281, - 3545, 2487, 3279, - 3544, 2495, 3277, - 3542, 2505, 3274, - 3539, 2518, 3270, - 3535, 2535, 3264, - 3529, 2557, 3257, - 3522, 2585, 3247, - 3512, 2620, 3233, - 3498, 2663, 3214, - 3479, 2714, 3187, - 3453, 2775, 3148, - 3415, 2845, 3090, - 3358, 2925, 2999, - 3269, 3014, 2838, - 3115, 3110, 2460, - 2760, 3214, 0, - 0, 3323, 0, - 0, 3438, 0, - 0, 3556, 0, - 0, 3678, 0, - 3684, 2572, 3411, - 3684, 2572, 3411, - 3684, 2573, 3411, - 3684, 2573, 3410, - 3684, 2574, 3410, - 3684, 2574, 3410, - 3684, 2575, 3410, - 3683, 2576, 3410, - 3683, 2578, 3409, - 3683, 2580, 3409, - 3682, 2582, 3408, - 3682, 2586, 3407, - 3681, 2591, 3406, - 3679, 2597, 3404, - 3678, 2605, 3402, - 3676, 2616, 3399, - 3673, 2630, 3395, - 3669, 2647, 3389, - 3663, 2670, 3382, - 3656, 2699, 3371, - 3646, 2736, 3357, - 3633, 2780, 3338, - 3614, 2833, 3310, - 3587, 2895, 3270, - 3549, 2967, 3211, - 3493, 3049, 3118, - 3405, 3139, 2952, - 3252, 3237, 2548, - 2902, 3342, 0, - 0, 3452, 0, - 0, 3567, 0, - 0, 3686, 0, - 3818, 2686, 3538, - 3818, 2686, 3538, - 3818, 2686, 3538, - 3818, 2686, 3537, - 3817, 2687, 3537, - 3817, 2687, 3537, - 3817, 2688, 3537, - 3817, 2689, 3537, - 3817, 2690, 3537, - 3817, 2692, 3536, - 3816, 2694, 3536, - 3816, 2696, 3535, - 3815, 2700, 3534, - 3814, 2705, 3533, - 3813, 2711, 3531, - 3811, 2720, 3529, - 3809, 2731, 3526, - 3806, 2745, 3522, - 3802, 2764, 3516, - 3797, 2788, 3508, - 3790, 2818, 3498, - 3780, 2855, 3484, - 3766, 2900, 3464, - 3748, 2955, 3436, - 3721, 3018, 3395, - 3683, 3092, 3335, - 3627, 3174, 3240, - 3540, 3266, 3070, - 3387, 3365, 2644, - 3042, 3470, 0, - 0, 3582, 0, - 0, 3697, 0, - 3951, 2804, 3666, - 3951, 2804, 3666, - 3951, 2804, 3666, - 3951, 2804, 3666, - 3951, 2804, 3666, - 3951, 2805, 3666, - 3951, 2805, 3665, - 3950, 2806, 3665, - 3950, 2807, 3665, - 3950, 2808, 3665, - 3950, 2810, 3664, - 3949, 2812, 3664, - 3949, 2815, 3663, - 3948, 2818, 3662, - 3947, 2823, 3661, - 3946, 2830, 3659, - 3944, 2839, 3657, - 3942, 2850, 3654, - 3939, 2865, 3650, - 3935, 2884, 3644, - 3930, 2909, 3636, - 3923, 2939, 3626, - 3913, 2977, 3611, - 3900, 3024, 3591, - 3881, 3079, 3563, - 3855, 3144, 3522, - 3817, 3218, 3461, - 3761, 3302, 3364, - 3674, 3394, 3191, - 3522, 3494, 2748, - 3180, 3600, 0, - 0, 3712, 0, - 4084, 2925, 3795, - 4084, 2925, 3795, - 4084, 2925, 3795, - 4084, 2925, 3795, - 4084, 2925, 3795, - 4084, 2926, 3795, - 4083, 2926, 3795, - 4083, 2926, 3795, - 4083, 2927, 3794, - 4083, 2928, 3794, - 4083, 2929, 3794, - 4083, 2931, 3794, - 4082, 2933, 3793, - 4082, 2936, 3792, - 4081, 2940, 3791, - 4080, 2945, 3790, - 4079, 2952, 3788, - 4077, 2961, 3786, - 4075, 2972, 3783, - 4072, 2988, 3779, - 4068, 3007, 3773, - 4063, 3032, 3765, - 4056, 3063, 3755, - 4046, 3102, 3740, - 4033, 3149, 3720, - 4014, 3205, 3691, - 3988, 3271, 3650, - 3950, 3346, 3589, - 3894, 3430, 3491, - 3807, 3523, 3314, - 3656, 3623, 2857, - 3317, 3730, 0, - 4095, 3048, 3925, - 4095, 3048, 3925, - 4095, 3048, 3925, - 4095, 3049, 3925, - 4095, 3049, 3925, - 4095, 3049, 3925, - 4095, 3049, 3925, - 4095, 3050, 3925, - 4095, 3050, 3924, - 4095, 3051, 3924, - 4095, 3052, 3924, - 4095, 3053, 3924, - 4095, 3055, 3923, - 4095, 3057, 3923, - 4095, 3060, 3922, - 4095, 3064, 3921, - 4095, 3069, 3920, - 4095, 3076, 3918, - 4095, 3085, 3916, - 4095, 3097, 3913, - 4095, 3112, 3908, - 4095, 3132, 3903, - 4095, 3157, 3895, - 4095, 3189, 3884, - 4095, 3228, 3870, - 4095, 3276, 3849, - 4095, 3333, 3821, - 4095, 3399, 3779, - 4083, 3475, 3717, - 4027, 3560, 3619, - 3940, 3653, 3440, - 3790, 3754, 2972, - 4095, 3174, 4055, - 4095, 3174, 4055, - 4095, 3174, 4055, - 4095, 3174, 4055, - 4095, 3174, 4055, - 4095, 3174, 4055, - 4095, 3175, 4055, - 4095, 3175, 4055, - 4095, 3175, 4055, - 4095, 3176, 4055, - 4095, 3177, 4055, - 4095, 3178, 4055, - 4095, 3179, 4054, - 4095, 3181, 4054, - 4095, 3183, 4053, - 4095, 3186, 4053, - 4095, 3190, 4052, - 4095, 3195, 4050, - 4095, 3202, 4049, - 4095, 3211, 4046, - 4095, 3223, 4043, - 4095, 3239, 4039, - 4095, 3259, 4033, - 4095, 3285, 4025, - 4095, 3317, 4015, - 4095, 3356, 4000, - 4095, 3404, 3979, - 4095, 3461, 3951, - 4095, 3528, 3909, - 4095, 3604, 3847, - 4095, 3690, 3747, - 4073, 3783, 3567, - 0, 1867, 2134, - 0, 1868, 2133, - 0, 1869, 2132, - 0, 1871, 2130, - 0, 1873, 2128, - 0, 1876, 2126, - 0, 1880, 2122, - 0, 1885, 2117, - 0, 1892, 2110, - 0, 1901, 2101, - 0, 1913, 2088, - 0, 1928, 2071, - 0, 1948, 2047, - 0, 1973, 2012, - 0, 2004, 1961, - 0, 2043, 1882, - 0, 2090, 1749, - 0, 2146, 1473, - 0, 2212, 0, - 0, 2288, 0, - 0, 2372, 0, - 0, 2465, 0, - 0, 2566, 0, - 0, 2673, 0, - 0, 2785, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 0, 1867, 2135, - 0, 1868, 2134, - 0, 1869, 2133, - 0, 1871, 2132, - 0, 1873, 2130, - 0, 1876, 2127, - 0, 1880, 2123, - 0, 1885, 2118, - 0, 1892, 2112, - 0, 1901, 2102, - 0, 1913, 2090, - 0, 1928, 2072, - 0, 1948, 2048, - 0, 1973, 2013, - 0, 2004, 1962, - 0, 2043, 1884, - 0, 2090, 1752, - 0, 2147, 1479, - 0, 2213, 0, - 0, 2288, 0, - 0, 2372, 0, - 0, 2465, 0, - 0, 2566, 0, - 0, 2673, 0, - 0, 2785, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3654, 0, - 0, 1868, 2137, - 0, 1869, 2136, - 0, 1870, 2135, - 0, 1872, 2133, - 0, 1874, 2131, - 0, 1877, 2129, - 0, 1881, 2125, - 0, 1886, 2120, - 0, 1893, 2113, - 0, 1902, 2104, - 0, 1913, 2092, - 0, 1929, 2074, - 0, 1948, 2050, - 0, 1973, 2016, - 0, 2004, 1965, - 0, 2043, 1887, - 0, 2091, 1756, - 0, 2147, 1486, - 0, 2213, 0, - 0, 2288, 0, - 0, 2373, 0, - 0, 2466, 0, - 0, 2566, 0, - 0, 2673, 0, - 0, 2785, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 0, 1868, 2139, - 0, 1869, 2138, - 0, 1870, 2137, - 0, 1872, 2136, - 0, 1874, 2134, - 0, 1877, 2131, - 0, 1881, 2127, - 0, 1886, 2122, - 0, 1893, 2116, - 0, 1902, 2107, - 0, 1914, 2094, - 0, 1929, 2077, - 0, 1949, 2053, - 0, 1974, 2019, - 0, 2005, 1968, - 0, 2044, 1891, - 0, 2091, 1761, - 0, 2147, 1495, - 0, 2213, 0, - 0, 2288, 0, - 0, 2373, 0, - 0, 2466, 0, - 0, 2566, 0, - 0, 2673, 0, - 0, 2785, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 0, 1869, 2142, - 0, 1870, 2141, - 0, 1871, 2140, - 0, 1873, 2139, - 0, 1875, 2137, - 0, 1878, 2134, - 0, 1882, 2130, - 0, 1887, 2125, - 0, 1894, 2119, - 0, 1903, 2110, - 0, 1915, 2097, - 0, 1930, 2080, - 0, 1949, 2056, - 0, 1974, 2022, - 0, 2005, 1973, - 0, 2044, 1896, - 0, 2091, 1768, - 0, 2148, 1508, - 0, 2213, 0, - 0, 2289, 0, - 0, 2373, 0, - 0, 2466, 0, - 0, 2566, 0, - 0, 2673, 0, - 0, 2785, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 0, 1870, 2146, - 0, 1871, 2145, - 0, 1872, 2144, - 0, 1874, 2143, - 0, 1876, 2141, - 0, 1879, 2138, - 0, 1883, 2134, - 0, 1888, 2130, - 0, 1895, 2123, - 0, 1904, 2114, - 0, 1915, 2102, - 0, 1931, 2085, - 0, 1950, 2061, - 0, 1975, 2028, - 0, 2006, 1978, - 0, 2045, 1903, - 0, 2092, 1777, - 0, 2148, 1523, - 0, 2214, 0, - 0, 2289, 0, - 0, 2373, 0, - 0, 2466, 0, - 0, 2567, 0, - 0, 2673, 0, - 0, 2786, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3270, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 0, 1871, 2151, - 0, 1872, 2151, - 0, 1874, 2149, - 0, 1875, 2148, - 0, 1877, 2146, - 0, 1880, 2143, - 0, 1884, 2140, - 0, 1889, 2135, - 0, 1896, 2129, - 0, 1905, 2120, - 0, 1917, 2108, - 0, 1932, 2091, - 0, 1951, 2068, - 0, 1976, 2034, - 0, 2007, 1986, - 0, 2046, 1912, - 0, 2093, 1788, - 0, 2149, 1544, - 0, 2214, 145, - 0, 2290, 0, - 0, 2374, 0, - 0, 2467, 0, - 0, 2567, 0, - 0, 2674, 0, - 0, 2786, 0, - 0, 2902, 0, - 0, 3022, 0, - 0, 3145, 0, - 0, 3271, 0, - 0, 3397, 0, - 0, 3525, 0, - 0, 3655, 0, - 0, 1873, 2158, - 0, 1874, 2157, - 0, 1875, 2156, - 0, 1877, 2155, - 0, 1879, 2153, - 0, 1882, 2150, - 0, 1886, 2147, - 0, 1891, 2142, - 0, 1898, 2136, - 0, 1907, 2127, - 0, 1918, 2115, - 0, 1933, 2099, - 0, 1953, 2076, - 0, 1977, 2043, - 0, 2009, 1996, - 0, 2047, 1923, - 0, 2094, 1804, - 0, 2150, 1570, - 0, 2215, 518, - 0, 2290, 0, - 0, 2374, 0, - 0, 2467, 0, - 0, 2567, 0, - 0, 2674, 0, - 0, 2786, 0, - 0, 2902, 0, - 0, 3023, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3397, 0, - 0, 3526, 0, - 0, 3655, 0, - 0, 1876, 2167, - 0, 1876, 2167, - 0, 1878, 2166, - 0, 1879, 2164, - 0, 1882, 2162, - 0, 1884, 2160, - 0, 1888, 2156, - 0, 1893, 2152, - 0, 1900, 2145, - 0, 1909, 2137, - 0, 1920, 2125, - 0, 1935, 2109, - 0, 1955, 2087, - 0, 1979, 2055, - 0, 2010, 2009, - 0, 2049, 1938, - 0, 2095, 1823, - 0, 2151, 1602, - 0, 2216, 772, - 0, 2291, 0, - 0, 2375, 0, - 0, 2468, 0, - 0, 2568, 0, - 0, 2674, 0, - 0, 2786, 0, - 0, 2903, 0, - 0, 3023, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 0, 1879, 2179, - 0, 1880, 2179, - 0, 1881, 2178, - 0, 1883, 2176, - 0, 1885, 2174, - 0, 1888, 2172, - 0, 1891, 2168, - 0, 1896, 2164, - 0, 1903, 2158, - 0, 1912, 2150, - 0, 1923, 2138, - 0, 1938, 2123, - 0, 1957, 2101, - 0, 1982, 2070, - 0, 2013, 2026, - 0, 2051, 1958, - 0, 2097, 1848, - 0, 2153, 1642, - 0, 2218, 978, - 0, 2293, 0, - 0, 2376, 0, - 0, 2469, 0, - 0, 2568, 0, - 0, 2675, 0, - 0, 2787, 0, - 0, 2903, 0, - 0, 3023, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 0, 1883, 2195, - 0, 1884, 2194, - 0, 1885, 2193, - 0, 1887, 2192, - 0, 1889, 2190, - 0, 1892, 2188, - 0, 1895, 2184, - 0, 1900, 2180, - 0, 1907, 2174, - 0, 1916, 2166, - 0, 1927, 2155, - 0, 1942, 2140, - 0, 1961, 2119, - 0, 1985, 2090, - 0, 2016, 2047, - 0, 2054, 1983, - 0, 2100, 1880, - 0, 2155, 1691, - 0, 2220, 1158, - 0, 2294, 0, - 0, 2378, 0, - 0, 2470, 0, - 0, 2569, 0, - 0, 2676, 0, - 0, 2787, 0, - 0, 2904, 0, - 0, 3023, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 0, 1889, 2215, - 0, 1889, 2214, - 0, 1891, 2213, - 0, 1892, 2212, - 0, 1894, 2210, - 0, 1897, 2208, - 0, 1901, 2205, - 0, 1906, 2200, - 0, 1912, 2195, - 0, 1921, 2187, - 0, 1932, 2177, - 0, 1947, 2163, - 0, 1966, 2143, - 0, 1990, 2115, - 0, 2020, 2074, - 0, 2058, 2014, - 0, 2103, 1919, - 0, 2158, 1748, - 0, 2223, 1323, - 0, 2296, 0, - 0, 2380, 0, - 0, 2471, 0, - 0, 2571, 0, - 0, 2677, 0, - 0, 2788, 0, - 0, 2904, 0, - 0, 3024, 0, - 0, 3146, 0, - 0, 3271, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 241, 1896, 2240, - 162, 1897, 2239, - 31, 1898, 2238, - 0, 1900, 2237, - 0, 1902, 2236, - 0, 1904, 2233, - 0, 1908, 2230, - 0, 1913, 2227, - 0, 1919, 2221, - 0, 1928, 2214, - 0, 1939, 2204, - 0, 1953, 2191, - 0, 1972, 2172, - 0, 1996, 2146, - 0, 2026, 2108, - 0, 2063, 2053, - 0, 2108, 1966, - 0, 2162, 1816, - 0, 2226, 1478, - 0, 2299, 0, - 0, 2382, 0, - 0, 2473, 0, - 0, 2572, 0, - 0, 2678, 0, - 0, 2789, 0, - 0, 2905, 0, - 0, 3024, 0, - 0, 3147, 0, - 0, 3272, 0, - 0, 3398, 0, - 0, 3526, 0, - 0, 3655, 0, - 1385, 1906, 2272, - 1379, 1906, 2271, - 1371, 1908, 2270, - 1360, 1909, 2269, - 1345, 1911, 2268, - 1325, 1914, 2266, - 1296, 1917, 2263, - 1253, 1922, 2259, - 1190, 1929, 2254, - 1089, 1937, 2248, - 903, 1948, 2239, - 397, 1962, 2226, - 0, 1980, 2209, - 0, 2003, 2185, - 0, 2033, 2150, - 0, 2069, 2100, - 0, 2114, 2023, - 0, 2168, 1893, - 0, 2231, 1627, - 0, 2303, 0, - 0, 2385, 0, - 0, 2476, 0, - 0, 2574, 0, - 0, 2680, 0, - 0, 2790, 0, - 0, 2906, 0, - 0, 3025, 0, - 0, 3148, 0, - 0, 3272, 0, - 0, 3399, 0, - 0, 3526, 0, - 0, 3655, 0, - 1749, 1918, 2311, - 1747, 1919, 2310, - 1743, 1920, 2310, - 1738, 1922, 2309, - 1732, 1924, 2307, - 1723, 1926, 2305, - 1711, 1930, 2303, - 1695, 1934, 2300, - 1672, 1941, 2295, - 1639, 1949, 2289, - 1592, 1959, 2281, - 1519, 1973, 2269, - 1399, 1991, 2254, - 1164, 2014, 2232, - 83, 2042, 2201, - 0, 2078, 2156, - 0, 2122, 2088, - 0, 2175, 1978, - 0, 2237, 1771, - 0, 2309, 1096, - 0, 2390, 0, - 0, 2480, 0, - 0, 2577, 0, - 0, 2682, 0, - 0, 2792, 0, - 0, 2907, 0, - 0, 3026, 0, - 0, 3148, 0, - 0, 3273, 0, - 0, 3399, 0, - 0, 3527, 0, - 0, 3656, 0, - 2000, 1935, 2359, - 1999, 1935, 2358, - 1997, 1936, 2358, - 1994, 1938, 2357, - 1990, 1940, 2355, - 1985, 1942, 2354, - 1979, 1946, 2351, - 1970, 1950, 2348, - 1957, 1956, 2344, - 1940, 1964, 2339, - 1916, 1974, 2331, - 1882, 1988, 2321, - 1832, 2005, 2307, - 1755, 2027, 2288, - 1626, 2055, 2261, - 1364, 2090, 2222, - 0, 2133, 2164, - 0, 2184, 2073, - 0, 2245, 1912, - 0, 2316, 1531, - 0, 2396, 0, - 0, 2484, 0, - 0, 2581, 0, - 0, 2685, 0, - 0, 2795, 0, - 0, 2909, 0, - 0, 3028, 0, - 0, 3149, 0, - 0, 3274, 0, - 0, 3400, 0, - 0, 3527, 0, - 0, 3656, 0, - 2205, 1955, 2416, - 2204, 1956, 2415, - 2202, 1957, 2415, - 2201, 1959, 2414, - 2198, 1960, 2413, - 2195, 1963, 2411, - 2191, 1966, 2409, - 2185, 1970, 2407, - 2178, 1976, 2403, - 2167, 1984, 2398, - 2153, 1993, 2392, - 2133, 2006, 2383, - 2105, 2023, 2371, - 2064, 2044, 2354, - 2003, 2071, 2331, - 1907, 2105, 2297, - 1734, 2146, 2249, - 1297, 2196, 2174, - 0, 2256, 2050, - 0, 2325, 1804, - 0, 2403, 318, - 0, 2491, 0, - 0, 2586, 0, - 0, 2689, 0, - 0, 2798, 0, - 0, 2912, 0, - 0, 3030, 0, - 0, 3151, 0, - 0, 3275, 0, - 0, 3401, 0, - 0, 3528, 0, - 0, 3656, 0, - 2384, 1982, 2482, - 2383, 1983, 2482, - 2382, 1984, 2481, - 2381, 1985, 2480, - 2380, 1987, 2479, - 2378, 1989, 2478, - 2375, 1992, 2476, - 2371, 1996, 2474, - 2366, 2002, 2471, - 2359, 2009, 2467, - 2350, 2018, 2461, - 2337, 2030, 2454, - 2319, 2046, 2443, - 2294, 2066, 2429, - 2259, 2092, 2410, - 2206, 2124, 2382, - 2125, 2164, 2342, - 1987, 2212, 2282, - 1696, 2270, 2187, - 0, 2337, 2019, - 0, 2414, 1603, - 0, 2499, 0, - 0, 2593, 0, - 0, 2694, 0, - 0, 2802, 0, - 0, 2915, 0, - 0, 3032, 0, - 0, 3153, 0, - 0, 3276, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 2549, 2015, 2558, - 2548, 2016, 2558, - 2547, 2017, 2557, - 2547, 2018, 2557, - 2546, 2020, 2556, - 2544, 2022, 2555, - 2542, 2025, 2553, - 2540, 2029, 2551, - 2536, 2034, 2549, - 2531, 2040, 2545, - 2525, 2049, 2541, - 2516, 2060, 2534, - 2504, 2075, 2526, - 2488, 2094, 2514, - 2465, 2118, 2497, - 2432, 2149, 2475, - 2385, 2187, 2442, - 2312, 2233, 2395, - 2192, 2288, 2323, - 1958, 2352, 2204, - 895, 2427, 1973, - 0, 2510, 982, - 0, 2602, 0, - 0, 2702, 0, - 0, 2808, 0, - 0, 2919, 0, - 0, 3036, 0, - 0, 3156, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 2703, 2056, 2643, - 2703, 2057, 2643, - 2703, 2058, 2642, - 2702, 2059, 2642, - 2701, 2060, 2641, - 2700, 2062, 2640, - 2699, 2065, 2639, - 2697, 2068, 2637, - 2695, 2073, 2635, - 2691, 2079, 2632, - 2687, 2087, 2629, - 2681, 2097, 2623, - 2673, 2111, 2616, - 2661, 2129, 2607, - 2646, 2151, 2593, - 2624, 2180, 2575, - 2593, 2215, 2549, - 2549, 2259, 2512, - 2482, 2311, 2458, - 2373, 2373, 2373, - 2168, 2444, 2226, - 1516, 2524, 1903, - 0, 2614, 0, - 0, 2711, 0, - 0, 2815, 0, - 0, 2925, 0, - 0, 3040, 0, - 0, 3159, 0, - 0, 3281, 0, - 0, 3405, 0, - 0, 3531, 0, - 0, 3659, 0, - 2852, 2106, 2736, - 2852, 2107, 2736, - 2851, 2107, 2736, - 2851, 2108, 2735, - 2850, 2110, 2735, - 2850, 2111, 2734, - 2849, 2114, 2733, - 2847, 2117, 2732, - 2846, 2121, 2730, - 2843, 2126, 2728, - 2840, 2134, 2725, - 2836, 2143, 2720, - 2830, 2155, 2715, - 2822, 2171, 2707, - 2811, 2192, 2696, - 2796, 2218, 2682, - 2775, 2251, 2662, - 2746, 2291, 2633, - 2703, 2340, 2592, - 2640, 2398, 2530, - 2537, 2466, 2431, - 2350, 2543, 2254, - 1830, 2629, 1790, - 0, 2723, 0, - 0, 2825, 0, - 0, 2933, 0, - 0, 3046, 0, - 0, 3164, 0, - 0, 3284, 0, - 0, 3408, 0, - 0, 3533, 0, - 0, 3661, 0, - 2996, 2165, 2837, - 2996, 2165, 2837, - 2995, 2166, 2837, - 2995, 2167, 2836, - 2995, 2168, 2836, - 2994, 2170, 2835, - 2994, 2172, 2835, - 2993, 2174, 2834, - 2991, 2178, 2832, - 2990, 2183, 2830, - 2987, 2189, 2828, - 2984, 2198, 2825, - 2980, 2209, 2820, - 2974, 2223, 2814, - 2966, 2241, 2805, - 2956, 2265, 2794, - 2941, 2294, 2778, - 2921, 2331, 2756, - 2893, 2376, 2725, - 2852, 2430, 2680, - 2790, 2493, 2611, - 2693, 2566, 2500, - 2517, 2648, 2288, - 2062, 2739, 1573, - 0, 2838, 0, - 0, 2943, 0, - 0, 3054, 0, - 0, 3170, 0, - 0, 3289, 0, - 0, 3412, 0, - 0, 3536, 0, - 0, 3663, 0, - 3137, 2233, 2944, - 3136, 2234, 2944, - 3136, 2234, 2944, - 3136, 2235, 2944, - 3136, 2236, 2944, - 3135, 2238, 2943, - 3135, 2239, 2942, - 3134, 2242, 2942, - 3133, 2245, 2941, - 3132, 2249, 2939, - 3130, 2254, 2937, - 3128, 2262, 2934, - 3125, 2271, 2931, - 3121, 2284, 2926, - 3115, 2300, 2920, - 3108, 2320, 2911, - 3097, 2347, 2899, - 3083, 2380, 2882, - 3063, 2420, 2858, - 3036, 2469, 2825, - 2996, 2528, 2776, - 2936, 2596, 2702, - 2841, 2673, 2578, - 2673, 2760, 2331, - 2257, 2854, 796, - 0, 2956, 0, - 0, 3064, 0, - 0, 3178, 0, - 0, 3295, 0, - 0, 3416, 0, - 0, 3540, 0, - 0, 3665, 0, - 3275, 2311, 3057, - 3275, 2312, 3057, - 3275, 2312, 3057, - 3275, 2313, 3057, - 3275, 2314, 3056, - 3274, 2315, 3056, - 3274, 2316, 3055, - 3273, 2318, 3055, - 3273, 2321, 3054, - 3272, 2324, 3053, - 3270, 2329, 3051, - 3269, 2335, 3049, - 3267, 2343, 3046, - 3263, 2354, 3043, - 3259, 2368, 3038, - 3254, 2386, 3031, - 3246, 2409, 3022, - 3236, 2437, 3009, - 3222, 2473, 2991, - 3203, 2517, 2967, - 3175, 2570, 2931, - 3136, 2633, 2880, - 3078, 2704, 2800, - 2985, 2786, 2665, - 2822, 2875, 2382, - 2431, 2973, 0, - 0, 3078, 0, - 0, 3188, 0, - 0, 3303, 0, - 0, 3422, 0, - 0, 3545, 0, - 0, 3669, 0, - 3412, 2398, 3174, - 3412, 2399, 3174, - 3412, 2399, 3174, - 3412, 2400, 3174, - 3411, 2400, 3173, - 3411, 2401, 3173, - 3411, 2402, 3173, - 3411, 2404, 3172, - 3410, 2406, 3172, - 3409, 2409, 3171, - 3408, 2413, 3170, - 3407, 2418, 3168, - 3406, 2425, 3166, - 3403, 2434, 3163, - 3400, 2445, 3159, - 3396, 2461, 3154, - 3391, 2480, 3147, - 3383, 2505, 3137, - 3373, 2536, 3124, - 3360, 2574, 3106, - 3340, 2621, 3080, - 3313, 2677, 3043, - 3275, 2743, 2989, - 3217, 2818, 2905, - 3126, 2902, 2760, - 2967, 2995, 2442, - 2592, 3095, 0, - 0, 3202, 0, - 0, 3314, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 3547, 2493, 3294, - 3547, 2494, 3294, - 3547, 2494, 3294, - 3547, 2494, 3294, - 3547, 2495, 3294, - 3547, 2496, 3294, - 3547, 2497, 3293, - 3547, 2498, 3293, - 3546, 2500, 3293, - 3546, 2502, 3292, - 3545, 2505, 3291, - 3544, 2510, 3290, - 3543, 2515, 3288, - 3541, 2522, 3286, - 3539, 2532, 3283, - 3536, 2545, 3279, - 3532, 2561, 3274, - 3527, 2582, 3266, - 3519, 2608, 3257, - 3509, 2641, 3243, - 3496, 2682, 3224, - 3476, 2731, 3198, - 3450, 2790, 3160, - 3411, 2858, 3103, - 3354, 2936, 3015, - 3265, 3023, 2862, - 3108, 3118, 2512, - 2745, 3220, 0, - 0, 3328, 0, - 0, 3442, 0, - 0, 3559, 0, - 0, 3680, 0, - 3682, 2596, 3418, - 3682, 2596, 3417, - 3682, 2596, 3417, - 3682, 2597, 3417, - 3682, 2597, 3417, - 3682, 2598, 3417, - 3682, 2598, 3417, - 3681, 2599, 3417, - 3681, 2601, 3416, - 3681, 2603, 3416, - 3680, 2605, 3415, - 3680, 2609, 3414, - 3679, 2613, 3413, - 3677, 2619, 3411, - 3676, 2627, 3409, - 3674, 2637, 3406, - 3671, 2650, 3402, - 3667, 2667, 3396, - 3661, 2689, 3389, - 3654, 2717, 3379, - 3644, 2752, 3365, - 3630, 2795, 3346, - 3612, 2846, 3319, - 3585, 2907, 3280, - 3547, 2977, 3222, - 3490, 3057, 3131, - 3401, 3146, 2970, - 3247, 3242, 2592, - 2892, 3346, 0, - 0, 3456, 0, - 0, 3570, 0, - 0, 3689, 0, - 3816, 2704, 3543, - 3816, 2704, 3543, - 3816, 2705, 3543, - 3816, 2705, 3543, - 3816, 2705, 3543, - 3816, 2706, 3542, - 3816, 2706, 3542, - 3816, 2707, 3542, - 3815, 2708, 3542, - 3815, 2710, 3541, - 3815, 2712, 3541, - 3814, 2714, 3540, - 3814, 2718, 3539, - 3813, 2723, 3538, - 3811, 2729, 3536, - 3810, 2737, 3534, - 3808, 2748, 3531, - 3805, 2762, 3527, - 3801, 2780, 3521, - 3795, 2803, 3514, - 3788, 2832, 3504, - 3778, 2868, 3489, - 3765, 2912, 3470, - 3746, 2965, 3442, - 3719, 3027, 3403, - 3681, 3099, 3343, - 3625, 3181, 3250, - 3537, 3271, 3084, - 3384, 3369, 2680, - 3034, 3474, 0, - 0, 3584, 0, - 0, 3699, 0, - 3950, 2818, 3670, - 3950, 2818, 3670, - 3950, 2818, 3670, - 3950, 2818, 3670, - 3950, 2819, 3670, - 3950, 2819, 3669, - 3949, 2819, 3669, - 3949, 2820, 3669, - 3949, 2821, 3669, - 3949, 2822, 3669, - 3949, 2824, 3668, - 3948, 2826, 3668, - 3948, 2829, 3667, - 3947, 2832, 3666, - 3946, 2837, 3665, - 3945, 2844, 3663, - 3943, 2852, 3661, - 3941, 2863, 3658, - 3938, 2878, 3654, - 3934, 2896, 3648, - 3929, 2920, 3640, - 3922, 2950, 3630, - 3912, 2987, 3616, - 3898, 3032, 3596, - 3880, 3087, 3568, - 3853, 3151, 3528, - 3815, 3224, 3467, - 3759, 3307, 3372, - 3672, 3398, 3202, - 3520, 3497, 2776, - 3174, 3602, 0, - 0, 3714, 0, - 4083, 2936, 3798, - 4083, 2936, 3798, - 4083, 2936, 3798, - 4083, 2936, 3798, - 4083, 2936, 3798, - 4083, 2936, 3798, - 4083, 2937, 3798, - 4083, 2937, 3798, - 4082, 2938, 3797, - 4082, 2939, 3797, - 4082, 2940, 3797, - 4082, 2942, 3796, - 4081, 2944, 3796, - 4081, 2947, 3795, - 4080, 2951, 3794, - 4079, 2956, 3793, - 4078, 2962, 3791, - 4077, 2971, 3789, - 4074, 2982, 3786, - 4071, 2997, 3782, - 4068, 3016, 3776, - 4062, 3041, 3768, - 4055, 3071, 3758, - 4045, 3109, 3743, - 4032, 3156, 3723, - 4013, 3211, 3695, - 3987, 3276, 3654, - 3949, 3350, 3593, - 3893, 3434, 3496, - 3806, 3526, 3323, - 3654, 3626, 2880, - 3312, 3732, 0, - 4095, 3057, 3927, - 4095, 3057, 3927, - 4095, 3057, 3927, - 4095, 3057, 3927, - 4095, 3057, 3927, - 4095, 3057, 3927, - 4095, 3058, 3927, - 4095, 3058, 3927, - 4095, 3059, 3927, - 4095, 3059, 3927, - 4095, 3060, 3926, - 4095, 3061, 3926, - 4095, 3063, 3926, - 4095, 3065, 3925, - 4095, 3068, 3924, - 4095, 3072, 3923, - 4095, 3077, 3922, - 4095, 3084, 3920, - 4095, 3093, 3918, - 4095, 3105, 3915, - 4095, 3120, 3911, - 4095, 3139, 3905, - 4095, 3164, 3897, - 4095, 3195, 3887, - 4095, 3234, 3872, - 4095, 3281, 3852, - 4095, 3337, 3823, - 4095, 3403, 3782, - 4082, 3478, 3721, - 4026, 3562, 3623, - 3939, 3655, 3446, - 3788, 3755, 2989, - 4095, 3180, 4057, - 4095, 3180, 4057, - 4095, 3180, 4057, - 4095, 3181, 4057, - 4095, 3181, 4057, - 4095, 3181, 4057, - 4095, 3181, 4057, - 4095, 3181, 4057, - 4095, 3182, 4057, - 4095, 3182, 4057, - 4095, 3183, 4056, - 4095, 3184, 4056, - 4095, 3185, 4056, - 4095, 3187, 4055, - 4095, 3189, 4055, - 4095, 3192, 4054, - 4095, 3196, 4053, - 4095, 3201, 4052, - 4095, 3208, 4050, - 4095, 3217, 4048, - 4095, 3229, 4045, - 4095, 3245, 4040, - 4095, 3264, 4035, - 4095, 3290, 4027, - 4095, 3321, 4016, - 4095, 3360, 4002, - 4095, 3408, 3981, - 4095, 3465, 3953, - 4095, 3531, 3911, - 4095, 3607, 3849, - 4095, 3692, 3751, - 4073, 3785, 3572, - 0, 1998, 2266, - 0, 1999, 2265, - 0, 2000, 2264, - 0, 2001, 2263, - 0, 2003, 2262, - 0, 2005, 2260, - 0, 2008, 2257, - 0, 2012, 2253, - 0, 2017, 2248, - 0, 2024, 2241, - 0, 2033, 2232, - 0, 2045, 2219, - 0, 2060, 2202, - 0, 2079, 2177, - 0, 2104, 2143, - 0, 2136, 2091, - 0, 2175, 2012, - 0, 2222, 1879, - 0, 2278, 1601, - 0, 2344, 0, - 0, 2420, 0, - 0, 2504, 0, - 0, 2597, 0, - 0, 2698, 0, - 0, 2805, 0, - 0, 2917, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 0, 1998, 2267, - 0, 1999, 2266, - 0, 2000, 2265, - 0, 2001, 2264, - 0, 2003, 2263, - 0, 2005, 2260, - 0, 2008, 2258, - 0, 2012, 2254, - 0, 2017, 2249, - 0, 2024, 2242, - 0, 2033, 2233, - 0, 2045, 2220, - 0, 2060, 2203, - 0, 2080, 2179, - 0, 2105, 2144, - 0, 2136, 2093, - 0, 2175, 2014, - 0, 2222, 1881, - 0, 2279, 1606, - 0, 2344, 0, - 0, 2420, 0, - 0, 2504, 0, - 0, 2597, 0, - 0, 2698, 0, - 0, 2805, 0, - 0, 2917, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 0, 1999, 2268, - 0, 1999, 2267, - 0, 2000, 2266, - 0, 2002, 2265, - 0, 2003, 2264, - 0, 2005, 2262, - 0, 2008, 2259, - 0, 2012, 2255, - 0, 2017, 2250, - 0, 2024, 2244, - 0, 2033, 2234, - 0, 2045, 2222, - 0, 2060, 2204, - 0, 2080, 2180, - 0, 2105, 2145, - 0, 2136, 2095, - 0, 2175, 2016, - 0, 2222, 1884, - 0, 2279, 1611, - 0, 2345, 0, - 0, 2420, 0, - 0, 2505, 0, - 0, 2598, 0, - 0, 2698, 0, - 0, 2805, 0, - 0, 2917, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 0, 1999, 2270, - 0, 2000, 2269, - 0, 2001, 2268, - 0, 2002, 2267, - 0, 2004, 2265, - 0, 2006, 2263, - 0, 2009, 2261, - 0, 2013, 2257, - 0, 2018, 2252, - 0, 2025, 2245, - 0, 2034, 2236, - 0, 2045, 2224, - 0, 2061, 2206, - 0, 2080, 2182, - 0, 2105, 2148, - 0, 2137, 2097, - 0, 2175, 2019, - 0, 2223, 1888, - 0, 2279, 1618, - 0, 2345, 0, - 0, 2420, 0, - 0, 2505, 0, - 0, 2598, 0, - 0, 2698, 0, - 0, 2805, 0, - 0, 2917, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 0, 2000, 2272, - 0, 2000, 2271, - 0, 2001, 2270, - 0, 2003, 2269, - 0, 2004, 2268, - 0, 2006, 2266, - 0, 2009, 2263, - 0, 2013, 2259, - 0, 2018, 2254, - 0, 2025, 2248, - 0, 2034, 2239, - 0, 2046, 2226, - 0, 2061, 2209, - 0, 2081, 2185, - 0, 2106, 2151, - 0, 2137, 2100, - 0, 2176, 2023, - 0, 2223, 1893, - 0, 2279, 1627, - 0, 2345, 0, - 0, 2420, 0, - 0, 2505, 0, - 0, 2598, 0, - 0, 2698, 0, - 0, 2805, 0, - 0, 2917, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3402, 0, - 0, 3529, 0, - 0, 3657, 0, - 0, 2000, 2275, - 0, 2001, 2274, - 0, 2002, 2273, - 0, 2003, 2272, - 0, 2005, 2271, - 0, 2007, 2269, - 0, 2010, 2266, - 0, 2014, 2262, - 0, 2019, 2258, - 0, 2026, 2251, - 0, 2035, 2242, - 0, 2047, 2230, - 0, 2062, 2212, - 0, 2081, 2189, - 0, 2106, 2155, - 0, 2138, 2105, - 0, 2176, 2028, - 0, 2223, 1900, - 0, 2280, 1640, - 0, 2345, 0, - 0, 2421, 0, - 0, 2505, 0, - 0, 2598, 0, - 0, 2698, 0, - 0, 2805, 0, - 0, 2917, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3403, 0, - 0, 3529, 0, - 0, 3658, 0, - 0, 2001, 2279, - 0, 2002, 2278, - 0, 2003, 2277, - 0, 2004, 2276, - 0, 2006, 2275, - 0, 2008, 2273, - 0, 2011, 2270, - 0, 2015, 2267, - 0, 2020, 2262, - 0, 2027, 2255, - 0, 2036, 2246, - 0, 2048, 2234, - 0, 2063, 2217, - 0, 2082, 2193, - 0, 2107, 2160, - 0, 2138, 2110, - 0, 2177, 2035, - 0, 2224, 1909, - 0, 2280, 1655, - 0, 2346, 0, - 0, 2421, 0, - 0, 2505, 0, - 0, 2598, 0, - 0, 2699, 0, - 0, 2805, 0, - 0, 2918, 0, - 0, 3034, 0, - 0, 3154, 0, - 0, 3277, 0, - 0, 3403, 0, - 0, 3529, 0, - 0, 3658, 0, - 0, 2003, 2284, - 0, 2003, 2283, - 0, 2004, 2283, - 0, 2006, 2282, - 0, 2007, 2280, - 0, 2009, 2278, - 0, 2012, 2275, - 0, 2016, 2272, - 0, 2021, 2267, - 0, 2028, 2261, - 0, 2037, 2252, - 0, 2049, 2240, - 0, 2064, 2223, - 0, 2083, 2200, - 0, 2108, 2166, - 0, 2139, 2118, - 0, 2178, 2044, - 0, 2225, 1921, - 0, 2281, 1676, - 0, 2347, 277, - 0, 2422, 0, - 0, 2506, 0, - 0, 2599, 0, - 0, 2699, 0, - 0, 2806, 0, - 0, 2918, 0, - 0, 3034, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3529, 0, - 0, 3658, 0, - 0, 2005, 2291, - 0, 2005, 2290, - 0, 2006, 2290, - 0, 2007, 2288, - 0, 2009, 2287, - 0, 2011, 2285, - 0, 2014, 2283, - 0, 2018, 2279, - 0, 2023, 2274, - 0, 2030, 2268, - 0, 2039, 2259, - 0, 2050, 2247, - 0, 2065, 2231, - 0, 2085, 2208, - 0, 2110, 2175, - 0, 2141, 2128, - 0, 2179, 2055, - 0, 2226, 1936, - 0, 2282, 1702, - 0, 2347, 650, - 0, 2422, 0, - 0, 2507, 0, - 0, 2599, 0, - 0, 2699, 0, - 0, 2806, 0, - 0, 2918, 0, - 0, 3035, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 0, 2007, 2300, - 0, 2008, 2299, - 0, 2009, 2299, - 0, 2010, 2298, - 0, 2011, 2296, - 0, 2014, 2294, - 0, 2017, 2292, - 0, 2020, 2288, - 0, 2025, 2284, - 0, 2032, 2277, - 0, 2041, 2269, - 0, 2053, 2257, - 0, 2068, 2241, - 0, 2087, 2219, - 0, 2111, 2187, - 0, 2142, 2141, - 0, 2181, 2071, - 0, 2227, 1955, - 0, 2283, 1734, - 0, 2349, 904, - 0, 2423, 0, - 0, 2507, 0, - 0, 2600, 0, - 0, 2700, 0, - 0, 2806, 0, - 0, 2918, 0, - 0, 3035, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 0, 2010, 2312, - 0, 2011, 2311, - 0, 2012, 2311, - 0, 2013, 2310, - 0, 2015, 2308, - 0, 2017, 2306, - 0, 2020, 2304, - 0, 2023, 2301, - 0, 2029, 2296, - 0, 2035, 2290, - 0, 2044, 2282, - 0, 2055, 2270, - 0, 2070, 2255, - 0, 2090, 2233, - 0, 2114, 2202, - 0, 2145, 2158, - 0, 2183, 2090, - 0, 2229, 1980, - 0, 2285, 1774, - 0, 2350, 1110, - 0, 2425, 0, - 0, 2508, 0, - 0, 2601, 0, - 0, 2700, 0, - 0, 2807, 0, - 0, 2919, 0, - 0, 3035, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 0, 2014, 2327, - 0, 2015, 2327, - 0, 2016, 2326, - 0, 2017, 2325, - 0, 2019, 2324, - 0, 2021, 2322, - 0, 2024, 2320, - 0, 2028, 2316, - 0, 2033, 2312, - 0, 2039, 2306, - 0, 2048, 2298, - 0, 2059, 2287, - 0, 2074, 2272, - 0, 2093, 2251, - 0, 2117, 2222, - 0, 2148, 2179, - 0, 2186, 2115, - 0, 2232, 2012, - 0, 2287, 1823, - 0, 2352, 1290, - 0, 2426, 0, - 0, 2510, 0, - 0, 2602, 0, - 0, 2701, 0, - 0, 2808, 0, - 0, 2919, 0, - 0, 3036, 0, - 0, 3155, 0, - 0, 3278, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 0, 2020, 2347, - 0, 2021, 2347, - 0, 2022, 2346, - 0, 2023, 2345, - 0, 2024, 2344, - 0, 2026, 2342, - 0, 2029, 2340, - 0, 2033, 2337, - 0, 2038, 2333, - 0, 2044, 2327, - 0, 2053, 2319, - 0, 2064, 2309, - 0, 2079, 2295, - 0, 2098, 2275, - 0, 2122, 2247, - 0, 2152, 2206, - 0, 2190, 2146, - 0, 2235, 2051, - 0, 2290, 1881, - 0, 2355, 1455, - 0, 2429, 0, - 0, 2512, 0, - 0, 2603, 0, - 0, 2703, 0, - 0, 2809, 0, - 0, 2920, 0, - 0, 3036, 0, - 0, 3156, 0, - 0, 3279, 0, - 0, 3403, 0, - 0, 3530, 0, - 0, 3658, 0, - 423, 2027, 2373, - 373, 2028, 2372, - 295, 2029, 2371, - 163, 2030, 2370, - 0, 2032, 2369, - 0, 2034, 2368, - 0, 2036, 2365, - 0, 2040, 2363, - 0, 2045, 2359, - 0, 2051, 2353, - 0, 2060, 2346, - 0, 2071, 2336, - 0, 2085, 2323, - 0, 2104, 2304, - 0, 2128, 2278, - 0, 2158, 2241, - 0, 2195, 2185, - 0, 2240, 2098, - 0, 2294, 1948, - 0, 2358, 1610, - 0, 2432, 0, - 0, 2514, 0, - 0, 2605, 0, - 0, 2704, 0, - 0, 2810, 0, - 0, 2921, 0, - 0, 3037, 0, - 0, 3157, 0, - 0, 3279, 0, - 0, 3404, 0, - 0, 3530, 0, - 0, 3658, 0, - 1521, 2037, 2404, - 1517, 2038, 2404, - 1511, 2039, 2403, - 1503, 2040, 2402, - 1492, 2041, 2401, - 1477, 2043, 2400, - 1457, 2046, 2398, - 1428, 2050, 2395, - 1385, 2054, 2391, - 1322, 2061, 2386, - 1221, 2069, 2380, - 1036, 2080, 2371, - 529, 2094, 2358, - 0, 2112, 2341, - 0, 2135, 2317, - 0, 2165, 2283, - 0, 2201, 2232, - 0, 2246, 2155, - 0, 2300, 2025, - 0, 2363, 1759, - 0, 2436, 0, - 0, 2518, 0, - 0, 2608, 0, - 0, 2707, 0, - 0, 2812, 0, - 0, 2923, 0, - 0, 3038, 0, - 0, 3157, 0, - 0, 3280, 0, - 0, 3404, 0, - 0, 3531, 0, - 0, 3659, 0, - 1883, 2050, 2444, - 1881, 2050, 2443, - 1879, 2051, 2443, - 1875, 2052, 2442, - 1870, 2054, 2441, - 1864, 2056, 2439, - 1855, 2058, 2437, - 1843, 2062, 2435, - 1827, 2066, 2432, - 1804, 2073, 2427, - 1771, 2081, 2421, - 1724, 2091, 2413, - 1651, 2105, 2401, - 1531, 2123, 2386, - 1296, 2146, 2364, - 216, 2174, 2333, - 0, 2210, 2288, - 0, 2254, 2221, - 0, 2307, 2111, - 0, 2369, 1903, - 0, 2441, 1228, - 0, 2522, 0, - 0, 2612, 0, - 0, 2709, 0, - 0, 2814, 0, - 0, 2924, 0, - 0, 3039, 0, - 0, 3158, 0, - 0, 3280, 0, - 0, 3405, 0, - 0, 3531, 0, - 0, 3659, 0, - 2133, 2066, 2491, - 2132, 2067, 2491, - 2131, 2067, 2490, - 2129, 2068, 2490, - 2126, 2070, 2489, - 2122, 2072, 2487, - 2118, 2074, 2486, - 2111, 2078, 2484, - 2102, 2082, 2481, - 2089, 2088, 2476, - 2072, 2096, 2471, - 2048, 2106, 2464, - 2014, 2120, 2453, - 1964, 2137, 2440, - 1887, 2159, 2420, - 1758, 2187, 2393, - 1496, 2222, 2354, - 0, 2265, 2296, - 0, 2316, 2205, - 0, 2377, 2044, - 0, 2448, 1663, - 0, 2528, 0, - 0, 2617, 0, - 0, 2713, 0, - 0, 2817, 0, - 0, 2927, 0, - 0, 3041, 0, - 0, 3160, 0, - 0, 3282, 0, - 0, 3406, 0, - 0, 3532, 0, - 0, 3659, 0, - 2337, 2087, 2548, - 2337, 2088, 2548, - 2336, 2088, 2547, - 2334, 2089, 2547, - 2333, 2091, 2546, - 2330, 2093, 2545, - 2327, 2095, 2543, - 2323, 2098, 2541, - 2317, 2103, 2539, - 2310, 2108, 2535, - 2299, 2116, 2530, - 2285, 2126, 2524, - 2265, 2138, 2515, - 2237, 2155, 2503, - 2196, 2176, 2486, - 2135, 2203, 2463, - 2039, 2237, 2429, - 1866, 2278, 2381, - 1429, 2329, 2306, - 0, 2388, 2182, - 0, 2457, 1936, - 0, 2536, 450, - 0, 2623, 0, - 0, 2718, 0, - 0, 2821, 0, - 0, 2930, 0, - 0, 3044, 0, - 0, 3162, 0, - 0, 3283, 0, - 0, 3407, 0, - 0, 3533, 0, - 0, 3660, 0, - 2517, 2114, 2614, - 2516, 2114, 2614, - 2515, 2115, 2614, - 2515, 2116, 2613, - 2513, 2117, 2612, - 2512, 2119, 2612, - 2510, 2121, 2610, - 2507, 2124, 2609, - 2503, 2128, 2606, - 2498, 2134, 2603, - 2491, 2141, 2599, - 2482, 2150, 2593, - 2469, 2162, 2586, - 2451, 2178, 2576, - 2426, 2198, 2561, - 2391, 2224, 2542, - 2338, 2256, 2514, - 2257, 2296, 2474, - 2119, 2344, 2414, - 1828, 2402, 2319, - 0, 2469, 2151, - 0, 2546, 1735, - 0, 2631, 0, - 0, 2725, 0, - 0, 2827, 0, - 0, 2934, 0, - 0, 3047, 0, - 0, 3164, 0, - 0, 3285, 0, - 0, 3408, 0, - 0, 3534, 0, - 0, 3661, 0, - 2681, 2147, 2690, - 2681, 2147, 2690, - 2680, 2148, 2690, - 2680, 2149, 2689, - 2679, 2150, 2689, - 2678, 2152, 2688, - 2676, 2154, 2687, - 2674, 2157, 2685, - 2672, 2161, 2683, - 2668, 2166, 2681, - 2663, 2172, 2677, - 2657, 2181, 2673, - 2648, 2192, 2666, - 2636, 2207, 2658, - 2620, 2226, 2646, - 2597, 2250, 2629, - 2565, 2281, 2607, - 2517, 2319, 2574, - 2444, 2365, 2527, - 2325, 2420, 2455, - 2090, 2485, 2336, - 1027, 2559, 2105, - 0, 2642, 1114, - 0, 2734, 0, - 0, 2834, 0, - 0, 2940, 0, - 0, 3052, 0, - 0, 3168, 0, - 0, 3288, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 2836, 2188, 2775, - 2836, 2189, 2775, - 2835, 2189, 2775, - 2835, 2190, 2774, - 2834, 2191, 2774, - 2833, 2193, 2773, - 2832, 2194, 2772, - 2831, 2197, 2771, - 2829, 2201, 2770, - 2827, 2205, 2767, - 2823, 2211, 2765, - 2819, 2219, 2761, - 2813, 2230, 2755, - 2805, 2243, 2748, - 2793, 2261, 2739, - 2778, 2283, 2725, - 2756, 2312, 2707, - 2726, 2347, 2681, - 2681, 2391, 2644, - 2614, 2443, 2590, - 2505, 2505, 2505, - 2300, 2576, 2358, - 1648, 2656, 2036, - 0, 2746, 0, - 0, 2843, 0, - 0, 2947, 0, - 0, 3057, 0, - 0, 3172, 0, - 0, 3291, 0, - 0, 3413, 0, - 0, 3537, 0, - 0, 3664, 0, - 2984, 2238, 2869, - 2984, 2238, 2868, - 2984, 2239, 2868, - 2983, 2239, 2868, - 2983, 2240, 2868, - 2983, 2242, 2867, - 2982, 2244, 2866, - 2981, 2246, 2865, - 2979, 2249, 2864, - 2978, 2253, 2862, - 2975, 2259, 2860, - 2972, 2266, 2857, - 2968, 2275, 2853, - 2962, 2287, 2847, - 2954, 2303, 2839, - 2943, 2324, 2828, - 2928, 2350, 2814, - 2907, 2383, 2794, - 2878, 2423, 2765, - 2836, 2472, 2724, - 2772, 2530, 2662, - 2669, 2598, 2563, - 2482, 2675, 2386, - 1962, 2761, 1922, - 0, 2855, 0, - 0, 2957, 0, - 0, 3065, 0, - 0, 3178, 0, - 0, 3296, 0, - 0, 3417, 0, - 0, 3540, 0, - 0, 3666, 0, - 3128, 2297, 2969, - 3128, 2297, 2969, - 3128, 2298, 2969, - 3128, 2298, 2969, - 3127, 2299, 2969, - 3127, 2300, 2968, - 3126, 2302, 2968, - 3126, 2304, 2967, - 3125, 2307, 2966, - 3123, 2310, 2964, - 3122, 2315, 2962, - 3119, 2321, 2960, - 3116, 2330, 2957, - 3112, 2341, 2952, - 3106, 2355, 2946, - 3099, 2373, 2938, - 3088, 2397, 2926, - 3073, 2426, 2910, - 3053, 2463, 2888, - 3025, 2508, 2857, - 2984, 2562, 2812, - 2922, 2625, 2744, - 2825, 2698, 2632, - 2649, 2780, 2420, - 2195, 2871, 1705, - 0, 2970, 0, - 0, 3075, 0, - 0, 3186, 0, - 0, 3302, 0, - 0, 3421, 0, - 0, 3544, 0, - 0, 3668, 0, - 3269, 2365, 3077, - 3269, 2366, 3077, - 3269, 2366, 3076, - 3268, 2367, 3076, - 3268, 2367, 3076, - 3268, 2368, 3076, - 3268, 2370, 3075, - 3267, 2371, 3075, - 3266, 2374, 3074, - 3265, 2377, 3073, - 3264, 2381, 3071, - 3262, 2387, 3069, - 3260, 2394, 3067, - 3257, 2403, 3063, - 3253, 2416, 3058, - 3247, 2432, 3052, - 3240, 2453, 3043, - 3229, 2479, 3031, - 3215, 2512, 3014, - 3195, 2552, 2990, - 3168, 2601, 2957, - 3128, 2660, 2908, - 3068, 2728, 2834, - 2973, 2805, 2710, - 2805, 2892, 2463, - 2389, 2986, 928, - 0, 3088, 0, - 0, 3197, 0, - 0, 3310, 0, - 0, 3427, 0, - 0, 3548, 0, - 0, 3672, 0, - 3407, 2443, 3189, - 3407, 2444, 3189, - 3407, 2444, 3189, - 3407, 2444, 3189, - 3407, 2445, 3189, - 3407, 2446, 3188, - 3406, 2447, 3188, - 3406, 2448, 3188, - 3405, 2450, 3187, - 3405, 2453, 3186, - 3404, 2457, 3185, - 3403, 2461, 3183, - 3401, 2467, 3181, - 3399, 2475, 3179, - 3396, 2486, 3175, - 3392, 2500, 3170, - 3386, 2518, 3163, - 3379, 2541, 3154, - 3368, 2570, 3141, - 3354, 2605, 3123, - 3335, 2649, 3099, - 3308, 2702, 3064, - 3268, 2765, 3012, - 3210, 2836, 2932, - 3117, 2918, 2797, - 2954, 3008, 2514, - 2563, 3105, 0, - 0, 3210, 0, - 0, 3320, 0, - 0, 3436, 0, - 0, 3555, 0, - 0, 3677, 0, - 3544, 2530, 3306, - 3544, 2530, 3306, - 3544, 2531, 3306, - 3544, 2531, 3306, - 3544, 2532, 3306, - 3544, 2532, 3305, - 3543, 2533, 3305, - 3543, 2534, 3305, - 3543, 2536, 3304, - 3542, 2538, 3304, - 3541, 2541, 3303, - 3541, 2545, 3302, - 3539, 2550, 3300, - 3538, 2557, 3298, - 3535, 2566, 3295, - 3532, 2578, 3291, - 3528, 2593, 3286, - 3523, 2612, 3279, - 3516, 2637, 3269, - 3505, 2668, 3256, - 3492, 2707, 3238, - 3472, 2754, 3212, - 3445, 2810, 3175, - 3407, 2875, 3121, - 3349, 2950, 3037, - 3258, 3034, 2892, - 3099, 3127, 2574, - 2724, 3227, 0, - 0, 3334, 0, - 0, 3446, 0, - 0, 3563, 0, - 0, 3683, 0, - 3680, 2625, 3427, - 3680, 2626, 3426, - 3680, 2626, 3426, - 3679, 2626, 3426, - 3679, 2626, 3426, - 3679, 2627, 3426, - 3679, 2628, 3426, - 3679, 2629, 3426, - 3679, 2630, 3425, - 3678, 2632, 3425, - 3678, 2634, 3424, - 3677, 2637, 3423, - 3676, 2642, 3422, - 3675, 2647, 3420, - 3673, 2655, 3418, - 3671, 2664, 3415, - 3668, 2677, 3411, - 3664, 2693, 3406, - 3659, 2714, 3399, - 3651, 2740, 3389, - 3641, 2773, 3375, - 3628, 2814, 3356, - 3609, 2863, 3330, - 3582, 2922, 3292, - 3543, 2990, 3236, - 3486, 3068, 3147, - 3397, 3155, 2994, - 3240, 3250, 2644, - 2877, 3352, 0, - 0, 3460, 0, - 0, 3574, 0, - 0, 3691, 0, - 3814, 2728, 3550, - 3814, 2728, 3550, - 3814, 2728, 3550, - 3814, 2728, 3550, - 3814, 2729, 3549, - 3814, 2729, 3549, - 3814, 2730, 3549, - 3814, 2730, 3549, - 3814, 2732, 3549, - 3813, 2733, 3548, - 3813, 2735, 3548, - 3812, 2737, 3547, - 3812, 2741, 3546, - 3811, 2745, 3545, - 3810, 2751, 3543, - 3808, 2759, 3541, - 3806, 2769, 3538, - 3803, 2782, 3534, - 3799, 2800, 3528, - 3793, 2822, 3521, - 3786, 2849, 3511, - 3776, 2884, 3497, - 3763, 2927, 3478, - 3744, 2978, 3451, - 3717, 3039, 3412, - 3679, 3109, 3354, - 3622, 3189, 3263, - 3534, 3278, 3102, - 3379, 3374, 2724, - 3024, 3478, 0, - 0, 3588, 0, - 0, 3702, 0, - 3948, 2836, 3675, - 3948, 2836, 3675, - 3948, 2836, 3675, - 3948, 2837, 3675, - 3948, 2837, 3675, - 3948, 2837, 3675, - 3948, 2838, 3675, - 3948, 2838, 3674, - 3948, 2839, 3674, - 3948, 2840, 3674, - 3947, 2842, 3673, - 3947, 2844, 3673, - 3946, 2847, 3672, - 3946, 2850, 3671, - 3945, 2855, 3670, - 3944, 2861, 3668, - 3942, 2869, 3666, - 3940, 2880, 3663, - 3937, 2894, 3659, - 3933, 2912, 3653, - 3928, 2935, 3646, - 3920, 2964, 3636, - 3910, 3000, 3622, - 3897, 3044, 3602, - 3878, 3097, 3574, - 3852, 3160, 3535, - 3814, 3232, 3475, - 3757, 3313, 3382, - 3669, 3403, 3216, - 3516, 3501, 2812, - 3167, 3606, 0, - 0, 3716, 0, - 4082, 2950, 3802, - 4082, 2950, 3802, - 4082, 2950, 3802, - 4082, 2950, 3802, - 4082, 2950, 3802, - 4082, 2951, 3802, - 4082, 2951, 3802, - 4082, 2952, 3801, - 4081, 2952, 3801, - 4081, 2953, 3801, - 4081, 2954, 3801, - 4081, 2956, 3800, - 4080, 2958, 3800, - 4080, 2961, 3799, - 4079, 2964, 3798, - 4078, 2969, 3797, - 4077, 2976, 3795, - 4075, 2984, 3793, - 4073, 2995, 3790, - 4070, 3010, 3786, - 4066, 3028, 3780, - 4061, 3052, 3772, - 4054, 3082, 3762, - 4044, 3119, 3748, - 4030, 3164, 3728, - 4012, 3219, 3700, - 3985, 3283, 3660, - 3948, 3356, 3599, - 3892, 3439, 3504, - 3804, 3530, 3334, - 3652, 3629, 2909, - 3307, 3735, 0, - 4095, 3068, 3930, - 4095, 3068, 3930, - 4095, 3068, 3930, - 4095, 3068, 3930, - 4095, 3068, 3930, - 4095, 3068, 3930, - 4095, 3069, 3930, - 4095, 3069, 3930, - 4095, 3069, 3930, - 4095, 3070, 3929, - 4095, 3071, 3929, - 4095, 3072, 3929, - 4095, 3074, 3929, - 4095, 3076, 3928, - 4095, 3079, 3927, - 4095, 3083, 3926, - 4095, 3088, 3925, - 4095, 3094, 3923, - 4095, 3103, 3921, - 4095, 3114, 3918, - 4095, 3129, 3914, - 4095, 3148, 3908, - 4095, 3173, 3900, - 4095, 3203, 3890, - 4095, 3241, 3875, - 4095, 3288, 3855, - 4095, 3343, 3827, - 4095, 3408, 3786, - 4081, 3482, 3725, - 4025, 3566, 3629, - 3938, 3658, 3455, - 3786, 3758, 3012, - 4095, 3189, 4059, - 4095, 3189, 4059, - 4095, 3189, 4059, - 4095, 3189, 4059, - 4095, 3189, 4059, - 4095, 3189, 4059, - 4095, 3189, 4059, - 4095, 3190, 4059, - 4095, 3190, 4059, - 4095, 3191, 4059, - 4095, 3191, 4059, - 4095, 3192, 4058, - 4095, 3193, 4058, - 4095, 3195, 4058, - 4095, 3197, 4057, - 4095, 3200, 4056, - 4095, 3204, 4055, - 4095, 3209, 4054, - 4095, 3216, 4052, - 4095, 3225, 4050, - 4095, 3237, 4047, - 4095, 3252, 4043, - 4095, 3271, 4037, - 4095, 3296, 4029, - 4095, 3327, 4019, - 4095, 3366, 4004, - 4095, 3413, 3984, - 4095, 3469, 3956, - 4095, 3535, 3914, - 4095, 3610, 3853, - 4095, 3694, 3755, - 4071, 3787, 3579, - 0, 2129, 2398, - 0, 2130, 2397, - 0, 2131, 2396, - 0, 2132, 2396, - 0, 2133, 2394, - 0, 2135, 2393, - 0, 2137, 2391, - 0, 2140, 2388, - 0, 2144, 2384, - 0, 2149, 2379, - 0, 2156, 2373, - 0, 2165, 2363, - 0, 2176, 2351, - 0, 2192, 2333, - 0, 2211, 2309, - 0, 2236, 2274, - 0, 2268, 2222, - 0, 2307, 2143, - 0, 2354, 2009, - 0, 2410, 1731, - 0, 2476, 0, - 0, 2552, 0, - 0, 2636, 0, - 0, 2729, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2130, 2398, - 0, 2130, 2398, - 0, 2131, 2397, - 0, 2132, 2396, - 0, 2133, 2395, - 0, 2135, 2394, - 0, 2137, 2392, - 0, 2140, 2389, - 0, 2144, 2385, - 0, 2149, 2380, - 0, 2156, 2373, - 0, 2165, 2364, - 0, 2177, 2352, - 0, 2192, 2334, - 0, 2212, 2310, - 0, 2237, 2275, - 0, 2268, 2223, - 0, 2307, 2144, - 0, 2354, 2011, - 0, 2411, 1734, - 0, 2476, 0, - 0, 2552, 0, - 0, 2636, 0, - 0, 2729, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2130, 2399, - 0, 2130, 2399, - 0, 2131, 2398, - 0, 2132, 2397, - 0, 2133, 2396, - 0, 2135, 2395, - 0, 2137, 2393, - 0, 2140, 2390, - 0, 2144, 2386, - 0, 2149, 2381, - 0, 2156, 2374, - 0, 2165, 2365, - 0, 2177, 2353, - 0, 2192, 2335, - 0, 2212, 2311, - 0, 2237, 2276, - 0, 2268, 2225, - 0, 2307, 2146, - 0, 2354, 2013, - 0, 2411, 1738, - 0, 2477, 0, - 0, 2552, 0, - 0, 2637, 0, - 0, 2730, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2130, 2400, - 0, 2131, 2400, - 0, 2131, 2399, - 0, 2132, 2399, - 0, 2134, 2397, - 0, 2135, 2396, - 0, 2138, 2394, - 0, 2140, 2391, - 0, 2144, 2387, - 0, 2150, 2382, - 0, 2156, 2376, - 0, 2165, 2367, - 0, 2177, 2354, - 0, 2192, 2337, - 0, 2212, 2312, - 0, 2237, 2278, - 0, 2268, 2227, - 0, 2307, 2148, - 0, 2354, 2016, - 0, 2411, 1743, - 0, 2477, 0, - 0, 2552, 0, - 0, 2637, 0, - 0, 2730, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2131, 2402, - 0, 2131, 2402, - 0, 2132, 2401, - 0, 2133, 2400, - 0, 2134, 2399, - 0, 2136, 2398, - 0, 2138, 2396, - 0, 2141, 2393, - 0, 2145, 2389, - 0, 2150, 2384, - 0, 2157, 2377, - 0, 2166, 2368, - 0, 2177, 2356, - 0, 2193, 2339, - 0, 2212, 2314, - 0, 2237, 2280, - 0, 2269, 2229, - 0, 2307, 2151, - 0, 2355, 2020, - 0, 2411, 1750, - 0, 2477, 0, - 0, 2552, 0, - 0, 2637, 0, - 0, 2730, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2131, 2404, - 0, 2132, 2404, - 0, 2132, 2403, - 0, 2133, 2402, - 0, 2135, 2401, - 0, 2136, 2400, - 0, 2139, 2398, - 0, 2141, 2395, - 0, 2145, 2391, - 0, 2151, 2387, - 0, 2157, 2380, - 0, 2166, 2371, - 0, 2178, 2358, - 0, 2193, 2341, - 0, 2213, 2317, - 0, 2238, 2283, - 0, 2269, 2232, - 0, 2308, 2155, - 0, 2355, 2025, - 0, 2411, 1760, - 0, 2477, 0, - 0, 2553, 0, - 0, 2637, 0, - 0, 2730, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3049, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2132, 2407, - 0, 2133, 2407, - 0, 2133, 2406, - 0, 2134, 2405, - 0, 2135, 2404, - 0, 2137, 2403, - 0, 2139, 2401, - 0, 2142, 2398, - 0, 2146, 2395, - 0, 2151, 2390, - 0, 2158, 2383, - 0, 2167, 2374, - 0, 2179, 2362, - 0, 2194, 2345, - 0, 2213, 2321, - 0, 2238, 2287, - 0, 2270, 2237, - 0, 2308, 2160, - 0, 2356, 2032, - 0, 2412, 1772, - 0, 2478, 0, - 0, 2553, 0, - 0, 2637, 0, - 0, 2730, 0, - 0, 2830, 0, - 0, 2937, 0, - 0, 3050, 0, - 0, 3166, 0, - 0, 3286, 0, - 0, 3409, 0, - 0, 3535, 0, - 0, 3661, 0, - 0, 2133, 2411, - 0, 2134, 2411, - 0, 2134, 2410, - 0, 2135, 2409, - 0, 2136, 2408, - 0, 2138, 2407, - 0, 2140, 2405, - 0, 2143, 2402, - 0, 2147, 2399, - 0, 2152, 2394, - 0, 2159, 2387, - 0, 2168, 2378, - 0, 2180, 2366, - 0, 2195, 2349, - 0, 2214, 2325, - 0, 2239, 2292, - 0, 2270, 2242, - 0, 2309, 2167, - 0, 2356, 2041, - 0, 2412, 1788, - 0, 2478, 0, - 0, 2553, 0, - 0, 2638, 0, - 0, 2730, 0, - 0, 2831, 0, - 0, 2937, 0, - 0, 3050, 0, - 0, 3166, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 0, 2134, 2417, - 0, 2135, 2416, - 0, 2136, 2416, - 0, 2136, 2415, - 0, 2138, 2414, - 0, 2139, 2412, - 0, 2142, 2410, - 0, 2144, 2408, - 0, 2148, 2404, - 0, 2154, 2399, - 0, 2160, 2393, - 0, 2169, 2384, - 0, 2181, 2372, - 0, 2196, 2355, - 0, 2215, 2332, - 0, 2240, 2299, - 0, 2271, 2250, - 0, 2310, 2176, - 0, 2357, 2053, - 0, 2413, 1808, - 0, 2479, 410, - 0, 2554, 0, - 0, 2638, 0, - 0, 2731, 0, - 0, 2831, 0, - 0, 2938, 0, - 0, 3050, 0, - 0, 3166, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 0, 2136, 2424, - 0, 2137, 2423, - 0, 2137, 2422, - 0, 2138, 2422, - 0, 2140, 2421, - 0, 2141, 2419, - 0, 2143, 2417, - 0, 2146, 2415, - 0, 2150, 2411, - 0, 2155, 2406, - 0, 2162, 2400, - 0, 2171, 2391, - 0, 2182, 2379, - 0, 2198, 2363, - 0, 2217, 2340, - 0, 2242, 2308, - 0, 2273, 2260, - 0, 2311, 2187, - 0, 2358, 2068, - 0, 2414, 1834, - 0, 2479, 782, - 0, 2554, 0, - 0, 2639, 0, - 0, 2731, 0, - 0, 2831, 0, - 0, 2938, 0, - 0, 3050, 0, - 0, 3167, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 0, 2139, 2433, - 0, 2139, 2432, - 0, 2140, 2432, - 0, 2141, 2431, - 0, 2142, 2430, - 0, 2144, 2428, - 0, 2146, 2426, - 0, 2149, 2424, - 0, 2152, 2420, - 0, 2158, 2416, - 0, 2164, 2410, - 0, 2173, 2401, - 0, 2185, 2389, - 0, 2200, 2373, - 0, 2219, 2351, - 0, 2244, 2319, - 0, 2274, 2273, - 0, 2313, 2203, - 0, 2360, 2088, - 0, 2415, 1866, - 0, 2481, 1036, - 0, 2555, 0, - 0, 2639, 0, - 0, 2732, 0, - 0, 2832, 0, - 0, 2938, 0, - 0, 3050, 0, - 0, 3167, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 0, 2142, 2444, - 0, 2142, 2444, - 0, 2143, 2443, - 0, 2144, 2443, - 0, 2145, 2442, - 0, 2147, 2440, - 0, 2149, 2438, - 0, 2152, 2436, - 0, 2156, 2433, - 0, 2161, 2428, - 0, 2167, 2422, - 0, 2176, 2414, - 0, 2188, 2402, - 0, 2202, 2387, - 0, 2222, 2365, - 0, 2246, 2334, - 0, 2277, 2290, - 0, 2315, 2222, - 0, 2362, 2113, - 0, 2417, 1906, - 0, 2482, 1242, - 0, 2557, 0, - 0, 2640, 0, - 0, 2733, 0, - 0, 2833, 0, - 0, 2939, 0, - 0, 3051, 0, - 0, 3167, 0, - 0, 3287, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 0, 2146, 2460, - 0, 2146, 2460, - 0, 2147, 2459, - 0, 2148, 2458, - 0, 2149, 2457, - 0, 2151, 2456, - 0, 2153, 2454, - 0, 2156, 2452, - 0, 2160, 2448, - 0, 2165, 2444, - 0, 2171, 2438, - 0, 2180, 2430, - 0, 2191, 2419, - 0, 2206, 2404, - 0, 2225, 2383, - 0, 2249, 2354, - 0, 2280, 2311, - 0, 2318, 2247, - 0, 2364, 2144, - 0, 2419, 1955, - 0, 2484, 1422, - 0, 2558, 0, - 0, 2642, 0, - 0, 2734, 0, - 0, 2834, 0, - 0, 2940, 0, - 0, 3051, 0, - 0, 3168, 0, - 0, 3288, 0, - 0, 3410, 0, - 0, 3535, 0, - 0, 3662, 0, - 0, 2152, 2480, - 0, 2152, 2479, - 0, 2153, 2479, - 0, 2154, 2478, - 0, 2155, 2477, - 0, 2156, 2476, - 0, 2159, 2474, - 0, 2161, 2472, - 0, 2165, 2469, - 0, 2170, 2465, - 0, 2177, 2459, - 0, 2185, 2451, - 0, 2196, 2441, - 0, 2211, 2427, - 0, 2230, 2407, - 0, 2254, 2379, - 0, 2284, 2339, - 0, 2322, 2278, - 0, 2368, 2183, - 0, 2422, 2013, - 0, 2487, 1587, - 0, 2561, 0, - 0, 2644, 0, - 0, 2735, 0, - 0, 2835, 0, - 0, 2941, 0, - 0, 3052, 0, - 0, 3168, 0, - 0, 3288, 0, - 0, 3411, 0, - 0, 3536, 0, - 0, 3662, 0, - 590, 2159, 2505, - 556, 2159, 2505, - 505, 2160, 2504, - 427, 2161, 2503, - 295, 2162, 2503, - 26, 2164, 2501, - 0, 2166, 2500, - 0, 2169, 2498, - 0, 2172, 2495, - 0, 2177, 2491, - 0, 2184, 2485, - 0, 2192, 2478, - 0, 2203, 2468, - 0, 2218, 2455, - 0, 2236, 2436, - 0, 2260, 2410, - 0, 2290, 2373, - 0, 2327, 2317, - 0, 2372, 2230, - 0, 2427, 2080, - 0, 2490, 1742, - 0, 2564, 0, - 0, 2646, 0, - 0, 2737, 0, - 0, 2836, 0, - 0, 2942, 0, - 0, 3053, 0, - 0, 3169, 0, - 0, 3289, 0, - 0, 3411, 0, - 0, 3536, 0, - 0, 3662, 0, - 1656, 2169, 2537, - 1653, 2169, 2536, - 1649, 2170, 2536, - 1643, 2171, 2535, - 1635, 2172, 2534, - 1624, 2173, 2533, - 1610, 2175, 2532, - 1589, 2178, 2530, - 1560, 2182, 2527, - 1518, 2186, 2523, - 1454, 2193, 2518, - 1353, 2201, 2512, - 1168, 2212, 2503, - 661, 2226, 2490, - 0, 2244, 2473, - 0, 2268, 2449, - 0, 2297, 2415, - 0, 2334, 2364, - 0, 2378, 2287, - 0, 2432, 2157, - 0, 2495, 1891, - 0, 2568, 0, - 0, 2650, 0, - 0, 2740, 0, - 0, 2839, 0, - 0, 2944, 0, - 0, 3055, 0, - 0, 3170, 0, - 0, 3289, 0, - 0, 3412, 0, - 0, 3536, 0, - 0, 3663, 0, - 2017, 2181, 2576, - 2015, 2182, 2576, - 2013, 2182, 2575, - 2011, 2183, 2575, - 2007, 2184, 2574, - 2002, 2186, 2573, - 1996, 2188, 2571, - 1987, 2190, 2570, - 1975, 2194, 2567, - 1959, 2199, 2564, - 1936, 2205, 2559, - 1903, 2213, 2553, - 1856, 2223, 2545, - 1783, 2237, 2533, - 1663, 2255, 2518, - 1428, 2278, 2496, - 348, 2307, 2465, - 0, 2342, 2420, - 0, 2386, 2353, - 0, 2439, 2243, - 0, 2501, 2035, - 0, 2573, 1360, - 0, 2654, 0, - 0, 2744, 0, - 0, 2842, 0, - 0, 2946, 0, - 0, 3056, 0, - 0, 3172, 0, - 0, 3291, 0, - 0, 3413, 0, - 0, 3537, 0, - 0, 3663, 0, - 2266, 2198, 2624, - 2266, 2198, 2623, - 2264, 2199, 2623, - 2263, 2200, 2622, - 2261, 2201, 2622, - 2258, 2202, 2621, - 2255, 2204, 2620, - 2250, 2206, 2618, - 2243, 2210, 2616, - 2234, 2214, 2613, - 2222, 2220, 2609, - 2204, 2228, 2603, - 2180, 2238, 2596, - 2146, 2252, 2586, - 2096, 2269, 2572, - 2019, 2291, 2552, - 1890, 2319, 2525, - 1628, 2354, 2486, - 0, 2397, 2428, - 0, 2448, 2337, - 0, 2509, 2176, - 0, 2580, 1795, - 0, 2660, 0, - 0, 2749, 0, - 0, 2845, 0, - 0, 2949, 0, - 0, 3059, 0, - 0, 3173, 0, - 0, 3292, 0, - 0, 3414, 0, - 0, 3538, 0, - 0, 3664, 0, - 2470, 2219, 2680, - 2469, 2219, 2680, - 2469, 2220, 2680, - 2468, 2220, 2679, - 2466, 2221, 2679, - 2465, 2223, 2678, - 2462, 2225, 2677, - 2459, 2227, 2675, - 2455, 2230, 2673, - 2450, 2235, 2671, - 2442, 2240, 2667, - 2431, 2248, 2662, - 2417, 2258, 2656, - 2397, 2270, 2647, - 2369, 2287, 2635, - 2328, 2308, 2618, - 2267, 2335, 2595, - 2171, 2369, 2561, - 1998, 2410, 2513, - 1561, 2461, 2438, - 0, 2520, 2315, - 0, 2589, 2068, - 0, 2668, 582, - 0, 2755, 0, - 0, 2851, 0, - 0, 2953, 0, - 0, 3062, 0, - 0, 3176, 0, - 0, 3294, 0, - 0, 3415, 0, - 0, 3539, 0, - 0, 3665, 0, - 2649, 2245, 2747, - 2649, 2246, 2746, - 2648, 2246, 2746, - 2648, 2247, 2746, - 2647, 2248, 2745, - 2646, 2249, 2745, - 2644, 2251, 2744, - 2642, 2253, 2742, - 2639, 2256, 2741, - 2635, 2260, 2738, - 2630, 2266, 2735, - 2623, 2273, 2731, - 2614, 2282, 2726, - 2601, 2294, 2718, - 2583, 2310, 2708, - 2558, 2330, 2693, - 2523, 2356, 2674, - 2470, 2388, 2646, - 2389, 2428, 2606, - 2251, 2476, 2546, - 1960, 2534, 2451, - 0, 2601, 2283, - 0, 2678, 1867, - 0, 2763, 0, - 0, 2857, 0, - 0, 2959, 0, - 0, 3066, 0, - 0, 3179, 0, - 0, 3296, 0, - 0, 3417, 0, - 0, 3540, 0, - 0, 3666, 0, - 2813, 2279, 2823, - 2813, 2279, 2822, - 2813, 2280, 2822, - 2812, 2280, 2822, - 2812, 2281, 2821, - 2811, 2282, 2821, - 2810, 2284, 2820, - 2808, 2286, 2819, - 2806, 2289, 2817, - 2804, 2293, 2816, - 2800, 2298, 2813, - 2796, 2304, 2809, - 2789, 2313, 2805, - 2780, 2324, 2798, - 2769, 2339, 2790, - 2752, 2358, 2778, - 2729, 2382, 2762, - 2697, 2413, 2739, - 2649, 2451, 2706, - 2576, 2497, 2659, - 2457, 2552, 2587, - 2222, 2617, 2468, - 1159, 2691, 2237, - 0, 2774, 1246, - 0, 2866, 0, - 0, 2966, 0, - 0, 3072, 0, - 0, 3184, 0, - 0, 3300, 0, - 0, 3420, 0, - 0, 3542, 0, - 0, 3667, 0, - 2968, 2320, 2907, - 2968, 2320, 2907, - 2968, 2321, 2907, - 2967, 2321, 2907, - 2967, 2322, 2906, - 2966, 2323, 2906, - 2966, 2325, 2905, - 2965, 2327, 2904, - 2963, 2329, 2903, - 2961, 2333, 2902, - 2959, 2337, 2900, - 2956, 2343, 2897, - 2951, 2351, 2893, - 2945, 2362, 2888, - 2937, 2375, 2880, - 2925, 2393, 2871, - 2910, 2415, 2857, - 2888, 2444, 2839, - 2858, 2479, 2813, - 2813, 2523, 2776, - 2746, 2575, 2722, - 2637, 2637, 2637, - 2432, 2708, 2490, - 1780, 2789, 2168, - 0, 2878, 0, - 0, 2975, 0, - 0, 3079, 0, - 0, 3190, 0, - 0, 3304, 0, - 0, 3423, 0, - 0, 3545, 0, - 0, 3669, 0, - 3116, 2370, 3001, - 3116, 2370, 3001, - 3116, 2370, 3001, - 3116, 2371, 3000, - 3116, 2372, 3000, - 3115, 2373, 3000, - 3115, 2374, 2999, - 3114, 2376, 2998, - 3113, 2378, 2997, - 3112, 2381, 2996, - 3110, 2385, 2994, - 3107, 2391, 2992, - 3104, 2398, 2989, - 3100, 2407, 2985, - 3094, 2420, 2979, - 3086, 2436, 2971, - 3075, 2456, 2961, - 3060, 2482, 2946, - 3039, 2515, 2926, - 3010, 2555, 2897, - 2968, 2604, 2856, - 2904, 2662, 2794, - 2802, 2730, 2696, - 2614, 2807, 2518, - 2094, 2893, 2054, - 0, 2987, 0, - 0, 3089, 0, - 0, 3197, 0, - 0, 3310, 0, - 0, 3428, 0, - 0, 3549, 0, - 0, 3672, 0, - 3260, 2429, 3102, - 3260, 2429, 3102, - 3260, 2429, 3101, - 3260, 2430, 3101, - 3260, 2430, 3101, - 3259, 2431, 3101, - 3259, 2432, 3100, - 3258, 2434, 3100, - 3258, 2436, 3099, - 3257, 2439, 3098, - 3255, 2442, 3096, - 3254, 2447, 3095, - 3251, 2453, 3092, - 3248, 2462, 3089, - 3244, 2473, 3084, - 3238, 2487, 3078, - 3231, 2505, 3070, - 3220, 2529, 3058, - 3206, 2558, 3042, - 3185, 2595, 3021, - 3157, 2640, 2989, - 3116, 2694, 2944, - 3054, 2757, 2876, - 2957, 2830, 2764, - 2781, 2913, 2552, - 2327, 3003, 1837, - 0, 3102, 0, - 0, 3207, 0, - 0, 3318, 0, - 0, 3434, 0, - 0, 3553, 0, - 0, 3676, 0, - 3401, 2497, 3209, - 3401, 2497, 3209, - 3401, 2498, 3209, - 3401, 2498, 3208, - 3401, 2499, 3208, - 3400, 2499, 3208, - 3400, 2500, 3208, - 3400, 2502, 3207, - 3399, 2503, 3207, - 3398, 2506, 3206, - 3397, 2509, 3205, - 3396, 2513, 3203, - 3394, 2519, 3201, - 3392, 2526, 3199, - 3389, 2535, 3195, - 3385, 2548, 3190, - 3379, 2564, 3184, - 3372, 2585, 3175, - 3361, 2611, 3163, - 3347, 2644, 3146, - 3328, 2684, 3123, - 3300, 2734, 3089, - 3260, 2792, 3040, - 3200, 2860, 2966, - 3105, 2937, 2842, - 2937, 3024, 2595, - 2521, 3118, 1060, - 0, 3220, 0, - 0, 3329, 0, - 0, 3442, 0, - 0, 3560, 0, - 0, 3680, 0, - 3539, 2575, 3321, - 3539, 2575, 3321, - 3539, 2576, 3321, - 3539, 2576, 3321, - 3539, 2576, 3321, - 3539, 2577, 3321, - 3539, 2578, 3320, - 3538, 2579, 3320, - 3538, 2581, 3320, - 3537, 2582, 3319, - 3537, 2585, 3318, - 3536, 2589, 3317, - 3535, 2593, 3315, - 3533, 2599, 3313, - 3531, 2608, 3311, - 3528, 2618, 3307, - 3524, 2632, 3302, - 3518, 2650, 3295, - 3511, 2673, 3286, - 3500, 2702, 3273, - 3486, 2738, 3255, - 3467, 2782, 3231, - 3440, 2834, 3196, - 3400, 2897, 3144, - 3342, 2969, 3064, - 3249, 3050, 2929, - 3086, 3140, 2646, - 2695, 3237, 0, - 0, 3342, 0, - 0, 3452, 0, - 0, 3568, 0, - 0, 3687, 0, - 3676, 2662, 3438, - 3676, 2662, 3438, - 3676, 2663, 3438, - 3676, 2663, 3438, - 3676, 2663, 3438, - 3676, 2664, 3438, - 3676, 2664, 3438, - 3675, 2665, 3437, - 3675, 2667, 3437, - 3675, 2668, 3436, - 3674, 2670, 3436, - 3674, 2673, 3435, - 3673, 2677, 3434, - 3671, 2682, 3432, - 3670, 2689, 3430, - 3668, 2698, 3427, - 3665, 2710, 3423, - 3661, 2725, 3418, - 3655, 2744, 3411, - 3648, 2769, 3401, - 3638, 2800, 3388, - 3624, 2839, 3370, - 3605, 2886, 3344, - 3578, 2942, 3308, - 3539, 3007, 3253, - 3481, 3082, 3169, - 3390, 3167, 3024, - 3231, 3259, 2706, - 2856, 3359, 0, - 0, 3466, 0, - 0, 3578, 0, - 0, 3695, 0, - 3812, 2757, 3559, - 3812, 2757, 3559, - 3812, 2758, 3559, - 3812, 2758, 3558, - 3812, 2758, 3558, - 3811, 2759, 3558, - 3811, 2759, 3558, - 3811, 2760, 3558, - 3811, 2761, 3558, - 3811, 2762, 3557, - 3810, 2764, 3557, - 3810, 2766, 3556, - 3809, 2770, 3555, - 3808, 2774, 3554, - 3807, 2779, 3552, - 3805, 2787, 3550, - 3803, 2796, 3547, - 3800, 2809, 3543, - 3796, 2825, 3538, - 3791, 2846, 3531, - 3783, 2872, 3521, - 3773, 2905, 3507, - 3760, 2946, 3488, - 3741, 2996, 3462, - 3714, 3054, 3424, - 3675, 3122, 3368, - 3618, 3200, 3279, - 3529, 3287, 3126, - 3372, 3382, 2777, - 3009, 3484, 0, - 0, 3592, 0, - 0, 3706, 0, - 3946, 2860, 3682, - 3946, 2860, 3682, - 3946, 2860, 3682, - 3946, 2860, 3682, - 3946, 2860, 3682, - 3946, 2861, 3682, - 3946, 2861, 3681, - 3946, 2862, 3681, - 3946, 2863, 3681, - 3946, 2864, 3681, - 3945, 2865, 3680, - 3945, 2867, 3680, - 3944, 2869, 3679, - 3944, 2873, 3678, - 3943, 2877, 3677, - 3942, 2883, 3675, - 3940, 2891, 3673, - 3938, 2901, 3670, - 3935, 2914, 3666, - 3931, 2932, 3661, - 3926, 2954, 3653, - 3918, 2981, 3643, - 3908, 3016, 3629, - 3895, 3059, 3610, - 3876, 3110, 3583, - 3849, 3171, 3544, - 3811, 3242, 3486, - 3754, 3321, 3395, - 3666, 3410, 3235, - 3511, 3507, 2856, - 3156, 3610, 0, - 0, 3720, 0, - 4080, 2968, 3807, - 4080, 2968, 3807, - 4080, 2968, 3807, - 4080, 2969, 3807, - 4080, 2969, 3807, - 4080, 2969, 3807, - 4080, 2969, 3807, - 4080, 2970, 3807, - 4080, 2970, 3806, - 4080, 2971, 3806, - 4080, 2972, 3806, - 4079, 2974, 3806, - 4079, 2976, 3805, - 4078, 2979, 3804, - 4078, 2982, 3803, - 4077, 2987, 3802, - 4076, 2993, 3800, - 4074, 3001, 3798, - 4072, 3012, 3795, - 4069, 3026, 3791, - 4065, 3044, 3786, - 4060, 3067, 3778, - 4052, 3096, 3768, - 4042, 3132, 3754, - 4029, 3176, 3734, - 4010, 3229, 3706, - 3984, 3292, 3667, - 3946, 3364, 3608, - 3889, 3445, 3514, - 3801, 3535, 3348, - 3648, 3633, 2944, - 3299, 3738, 0, - 4095, 3082, 3934, - 4095, 3082, 3934, - 4095, 3082, 3934, - 4095, 3082, 3934, - 4095, 3082, 3934, - 4095, 3082, 3934, - 4095, 3083, 3934, - 4095, 3083, 3934, - 4095, 3084, 3934, - 4095, 3084, 3933, - 4095, 3085, 3933, - 4095, 3086, 3933, - 4095, 3088, 3932, - 4095, 3090, 3932, - 4095, 3093, 3931, - 4095, 3096, 3930, - 4095, 3101, 3929, - 4095, 3108, 3927, - 4095, 3116, 3925, - 4095, 3127, 3922, - 4095, 3142, 3918, - 4095, 3160, 3912, - 4095, 3184, 3905, - 4095, 3214, 3894, - 4095, 3251, 3880, - 4095, 3297, 3860, - 4095, 3351, 3832, - 4095, 3415, 3792, - 4080, 3488, 3732, - 4024, 3571, 3636, - 3936, 3662, 3466, - 3784, 3761, 3041, - 4095, 3200, 4062, - 4095, 3200, 4062, - 4095, 3200, 4062, - 4095, 3200, 4062, - 4095, 3200, 4062, - 4095, 3200, 4062, - 4095, 3200, 4062, - 4095, 3201, 4062, - 4095, 3201, 4062, - 4095, 3202, 4062, - 4095, 3202, 4062, - 4095, 3203, 4061, - 4095, 3204, 4061, - 4095, 3206, 4061, - 4095, 3208, 4060, - 4095, 3211, 4059, - 4095, 3215, 4058, - 4095, 3220, 4057, - 4095, 3226, 4055, - 4095, 3235, 4053, - 4095, 3247, 4050, - 4095, 3261, 4046, - 4095, 3280, 4040, - 4095, 3305, 4032, - 4095, 3335, 4022, - 4095, 3374, 4008, - 4095, 3420, 3988, - 4095, 3475, 3959, - 4095, 3540, 3918, - 4095, 3614, 3858, - 4095, 3698, 3761, - 4070, 3790, 3587, - 0, 2261, 2529, - 0, 2261, 2529, - 0, 2262, 2529, - 0, 2263, 2528, - 0, 2264, 2527, - 0, 2265, 2526, - 0, 2267, 2524, - 0, 2269, 2522, - 0, 2272, 2520, - 0, 2276, 2516, - 0, 2281, 2511, - 0, 2288, 2504, - 0, 2297, 2495, - 0, 2308, 2482, - 0, 2324, 2465, - 0, 2343, 2440, - 0, 2368, 2405, - 0, 2400, 2354, - 0, 2439, 2274, - 0, 2486, 2140, - 0, 2542, 1860, - 0, 2608, 0, - 0, 2684, 0, - 0, 2768, 0, - 0, 2861, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3667, 0, - 0, 2261, 2530, - 0, 2262, 2530, - 0, 2262, 2529, - 0, 2263, 2529, - 0, 2264, 2528, - 0, 2265, 2527, - 0, 2267, 2525, - 0, 2269, 2523, - 0, 2272, 2520, - 0, 2276, 2517, - 0, 2281, 2512, - 0, 2288, 2505, - 0, 2297, 2495, - 0, 2309, 2483, - 0, 2324, 2465, - 0, 2343, 2441, - 0, 2368, 2406, - 0, 2400, 2354, - 0, 2439, 2275, - 0, 2486, 2141, - 0, 2543, 1863, - 0, 2608, 0, - 0, 2684, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3667, 0, - 0, 2261, 2531, - 0, 2262, 2530, - 0, 2262, 2530, - 0, 2263, 2529, - 0, 2264, 2528, - 0, 2265, 2527, - 0, 2267, 2526, - 0, 2269, 2524, - 0, 2272, 2521, - 0, 2276, 2517, - 0, 2281, 2512, - 0, 2288, 2505, - 0, 2297, 2496, - 0, 2309, 2484, - 0, 2324, 2466, - 0, 2344, 2442, - 0, 2369, 2407, - 0, 2400, 2355, - 0, 2439, 2276, - 0, 2486, 2143, - 0, 2543, 1866, - 0, 2609, 0, - 0, 2684, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3667, 0, - 0, 2262, 2532, - 0, 2262, 2531, - 0, 2263, 2531, - 0, 2263, 2530, - 0, 2264, 2529, - 0, 2265, 2528, - 0, 2267, 2527, - 0, 2269, 2525, - 0, 2272, 2522, - 0, 2276, 2518, - 0, 2281, 2513, - 0, 2288, 2506, - 0, 2297, 2497, - 0, 2309, 2485, - 0, 2324, 2467, - 0, 2344, 2443, - 0, 2369, 2408, - 0, 2400, 2357, - 0, 2439, 2278, - 0, 2486, 2145, - 0, 2543, 1870, - 0, 2609, 0, - 0, 2684, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3667, 0, - 0, 2262, 2533, - 0, 2262, 2533, - 0, 2263, 2532, - 0, 2264, 2531, - 0, 2264, 2531, - 0, 2266, 2529, - 0, 2267, 2528, - 0, 2270, 2526, - 0, 2273, 2523, - 0, 2276, 2520, - 0, 2282, 2515, - 0, 2288, 2508, - 0, 2297, 2499, - 0, 2309, 2486, - 0, 2324, 2469, - 0, 2344, 2444, - 0, 2369, 2410, - 0, 2400, 2359, - 0, 2439, 2280, - 0, 2487, 2148, - 0, 2543, 1875, - 0, 2609, 0, - 0, 2684, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3667, 0, - 0, 2262, 2535, - 0, 2263, 2534, - 0, 2263, 2534, - 0, 2264, 2533, - 0, 2265, 2532, - 0, 2266, 2531, - 0, 2268, 2530, - 0, 2270, 2528, - 0, 2273, 2525, - 0, 2277, 2521, - 0, 2282, 2516, - 0, 2289, 2510, - 0, 2298, 2500, - 0, 2310, 2488, - 0, 2325, 2471, - 0, 2344, 2446, - 0, 2369, 2412, - 0, 2401, 2361, - 0, 2440, 2283, - 0, 2487, 2152, - 0, 2543, 1882, - 0, 2609, 0, - 0, 2684, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3181, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3541, 0, - 0, 3667, 0, - 0, 2263, 2537, - 0, 2263, 2537, - 0, 2264, 2536, - 0, 2265, 2535, - 0, 2265, 2535, - 0, 2267, 2533, - 0, 2268, 2532, - 0, 2271, 2530, - 0, 2274, 2527, - 0, 2277, 2524, - 0, 2283, 2519, - 0, 2289, 2512, - 0, 2298, 2503, - 0, 2310, 2490, - 0, 2325, 2473, - 0, 2345, 2449, - 0, 2370, 2415, - 0, 2401, 2364, - 0, 2440, 2287, - 0, 2487, 2157, - 0, 2543, 1892, - 0, 2609, 0, - 0, 2685, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2962, 0, - 0, 3069, 0, - 0, 3182, 0, - 0, 3298, 0, - 0, 3418, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2264, 2540, - 0, 2264, 2539, - 0, 2265, 2539, - 0, 2265, 2538, - 0, 2266, 2538, - 0, 2267, 2536, - 0, 2269, 2535, - 0, 2271, 2533, - 0, 2274, 2530, - 0, 2278, 2527, - 0, 2283, 2522, - 0, 2290, 2515, - 0, 2299, 2506, - 0, 2311, 2494, - 0, 2326, 2477, - 0, 2346, 2453, - 0, 2370, 2419, - 0, 2402, 2369, - 0, 2440, 2292, - 0, 2488, 2164, - 0, 2544, 1904, - 0, 2610, 0, - 0, 2685, 0, - 0, 2769, 0, - 0, 2862, 0, - 0, 2963, 0, - 0, 3069, 0, - 0, 3182, 0, - 0, 3298, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2265, 2544, - 0, 2265, 2543, - 0, 2266, 2543, - 0, 2266, 2542, - 0, 2267, 2542, - 0, 2268, 2540, - 0, 2270, 2539, - 0, 2272, 2537, - 0, 2275, 2534, - 0, 2279, 2531, - 0, 2284, 2526, - 0, 2291, 2519, - 0, 2300, 2510, - 0, 2312, 2498, - 0, 2327, 2481, - 0, 2346, 2458, - 0, 2371, 2424, - 0, 2402, 2375, - 0, 2441, 2299, - 0, 2488, 2173, - 0, 2544, 1920, - 0, 2610, 0, - 0, 2685, 0, - 0, 2770, 0, - 0, 2862, 0, - 0, 2963, 0, - 0, 3070, 0, - 0, 3182, 0, - 0, 3298, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2266, 2549, - 0, 2266, 2549, - 0, 2267, 2548, - 0, 2268, 2548, - 0, 2269, 2547, - 0, 2270, 2546, - 0, 2271, 2544, - 0, 2274, 2542, - 0, 2277, 2540, - 0, 2280, 2536, - 0, 2286, 2531, - 0, 2292, 2525, - 0, 2301, 2516, - 0, 2313, 2504, - 0, 2328, 2487, - 0, 2348, 2464, - 0, 2372, 2431, - 0, 2403, 2382, - 0, 2442, 2308, - 0, 2489, 2185, - 0, 2545, 1940, - 0, 2611, 542, - 0, 2686, 0, - 0, 2770, 0, - 0, 2863, 0, - 0, 2963, 0, - 0, 3070, 0, - 0, 3182, 0, - 0, 3299, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2268, 2556, - 0, 2268, 2556, - 0, 2269, 2555, - 0, 2269, 2555, - 0, 2270, 2554, - 0, 2272, 2553, - 0, 2273, 2551, - 0, 2275, 2549, - 0, 2278, 2547, - 0, 2282, 2543, - 0, 2287, 2538, - 0, 2294, 2532, - 0, 2303, 2523, - 0, 2315, 2512, - 0, 2330, 2495, - 0, 2349, 2472, - 0, 2374, 2440, - 0, 2405, 2392, - 0, 2443, 2320, - 0, 2490, 2200, - 0, 2546, 1966, - 0, 2612, 914, - 0, 2687, 0, - 0, 2771, 0, - 0, 2863, 0, - 0, 2963, 0, - 0, 3070, 0, - 0, 3182, 0, - 0, 3299, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2270, 2565, - 0, 2271, 2565, - 0, 2271, 2564, - 0, 2272, 2564, - 0, 2273, 2563, - 0, 2274, 2562, - 0, 2276, 2560, - 0, 2278, 2559, - 0, 2281, 2556, - 0, 2285, 2553, - 0, 2290, 2548, - 0, 2296, 2542, - 0, 2305, 2533, - 0, 2317, 2522, - 0, 2332, 2505, - 0, 2351, 2483, - 0, 2376, 2451, - 0, 2407, 2405, - 0, 2445, 2335, - 0, 2492, 2220, - 0, 2547, 1998, - 0, 2613, 1168, - 0, 2688, 0, - 0, 2772, 0, - 0, 2864, 0, - 0, 2964, 0, - 0, 3071, 0, - 0, 3183, 0, - 0, 3299, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2273, 2577, - 0, 2274, 2577, - 0, 2274, 2576, - 0, 2275, 2576, - 0, 2276, 2575, - 0, 2277, 2574, - 0, 2279, 2572, - 0, 2281, 2571, - 0, 2284, 2568, - 0, 2288, 2565, - 0, 2293, 2560, - 0, 2299, 2554, - 0, 2308, 2546, - 0, 2320, 2535, - 0, 2335, 2519, - 0, 2354, 2497, - 0, 2378, 2467, - 0, 2409, 2422, - 0, 2447, 2354, - 0, 2494, 2245, - 0, 2549, 2038, - 0, 2614, 1374, - 0, 2689, 0, - 0, 2773, 0, - 0, 2865, 0, - 0, 2965, 0, - 0, 3071, 0, - 0, 3183, 0, - 0, 3299, 0, - 0, 3419, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2278, 2592, - 0, 2278, 2592, - 0, 2279, 2592, - 0, 2279, 2591, - 0, 2280, 2590, - 0, 2281, 2589, - 0, 2283, 2588, - 0, 2285, 2586, - 0, 2288, 2584, - 0, 2292, 2581, - 0, 2297, 2576, - 0, 2303, 2570, - 0, 2312, 2562, - 0, 2323, 2551, - 0, 2338, 2536, - 0, 2357, 2516, - 0, 2382, 2486, - 0, 2412, 2443, - 0, 2450, 2379, - 0, 2496, 2276, - 0, 2551, 2087, - 0, 2616, 1554, - 0, 2690, 0, - 0, 2774, 0, - 0, 2866, 0, - 0, 2966, 0, - 0, 3072, 0, - 0, 3184, 0, - 0, 3300, 0, - 0, 3420, 0, - 0, 3542, 0, - 0, 3667, 0, - 0, 2283, 2612, - 0, 2284, 2612, - 0, 2284, 2611, - 0, 2285, 2611, - 0, 2286, 2610, - 0, 2287, 2609, - 0, 2289, 2608, - 0, 2291, 2606, - 0, 2293, 2604, - 0, 2297, 2601, - 0, 2302, 2597, - 0, 2309, 2591, - 0, 2317, 2584, - 0, 2329, 2573, - 0, 2343, 2559, - 0, 2362, 2539, - 0, 2386, 2511, - 0, 2416, 2471, - 0, 2454, 2410, - 0, 2500, 2315, - 0, 2555, 2145, - 0, 2619, 1719, - 0, 2693, 0, - 0, 2776, 0, - 0, 2868, 0, - 0, 2967, 0, - 0, 3073, 0, - 0, 3184, 0, - 0, 3300, 0, - 0, 3420, 0, - 0, 3543, 0, - 0, 3668, 0, - 746, 2291, 2637, - 722, 2291, 2637, - 688, 2292, 2637, - 637, 2292, 2636, - 559, 2293, 2636, - 428, 2294, 2635, - 158, 2296, 2633, - 0, 2298, 2632, - 0, 2301, 2630, - 0, 2304, 2627, - 0, 2309, 2623, - 0, 2316, 2618, - 0, 2324, 2610, - 0, 2335, 2601, - 0, 2350, 2587, - 0, 2368, 2568, - 0, 2392, 2542, - 0, 2422, 2505, - 0, 2459, 2449, - 0, 2504, 2362, - 0, 2559, 2212, - 0, 2622, 1874, - 0, 2696, 0, - 0, 2778, 0, - 0, 2870, 0, - 0, 2969, 0, - 0, 3074, 0, - 0, 3185, 0, - 0, 3301, 0, - 0, 3421, 0, - 0, 3543, 0, - 0, 3668, 0, - 1791, 2300, 2669, - 1789, 2301, 2669, - 1785, 2301, 2668, - 1781, 2302, 2668, - 1775, 2303, 2667, - 1767, 2304, 2667, - 1757, 2305, 2665, - 1742, 2307, 2664, - 1721, 2310, 2662, - 1692, 2314, 2659, - 1650, 2319, 2656, - 1586, 2325, 2651, - 1485, 2333, 2644, - 1300, 2344, 2635, - 793, 2358, 2622, - 0, 2376, 2605, - 0, 2400, 2581, - 0, 2429, 2547, - 0, 2466, 2496, - 0, 2510, 2419, - 0, 2564, 2289, - 0, 2627, 2023, - 0, 2700, 0, - 0, 2782, 0, - 0, 2872, 0, - 0, 2971, 0, - 0, 3076, 0, - 0, 3187, 0, - 0, 3302, 0, - 0, 3422, 0, - 0, 3544, 0, - 0, 3668, 0, - 2150, 2313, 2708, - 2149, 2313, 2708, - 2147, 2314, 2708, - 2145, 2314, 2707, - 2143, 2315, 2707, - 2139, 2316, 2706, - 2135, 2318, 2705, - 2128, 2320, 2704, - 2119, 2323, 2702, - 2108, 2326, 2699, - 2091, 2331, 2696, - 2068, 2337, 2691, - 2036, 2345, 2685, - 1988, 2356, 2677, - 1915, 2369, 2666, - 1795, 2387, 2650, - 1560, 2410, 2628, - 480, 2439, 2597, - 0, 2474, 2553, - 0, 2518, 2485, - 0, 2571, 2375, - 0, 2633, 2167, - 0, 2705, 1492, - 0, 2786, 0, - 0, 2876, 0, - 0, 2974, 0, - 0, 3078, 0, - 0, 3189, 0, - 0, 3304, 0, - 0, 3423, 0, - 0, 3545, 0, - 0, 3669, 0, - 2399, 2329, 2756, - 2398, 2330, 2756, - 2398, 2330, 2755, - 2396, 2331, 2755, - 2395, 2332, 2754, - 2393, 2333, 2754, - 2390, 2334, 2753, - 2387, 2336, 2752, - 2382, 2339, 2750, - 2375, 2342, 2748, - 2366, 2346, 2745, - 2354, 2352, 2741, - 2337, 2360, 2735, - 2313, 2370, 2728, - 2278, 2384, 2718, - 2228, 2401, 2704, - 2151, 2423, 2684, - 2023, 2451, 2657, - 1760, 2486, 2618, - 0, 2529, 2560, - 0, 2581, 2469, - 0, 2642, 2308, - 0, 2712, 1927, - 0, 2792, 0, - 0, 2881, 0, - 0, 2978, 0, - 0, 3081, 0, - 0, 3191, 0, - 0, 3306, 0, - 0, 3424, 0, - 0, 3546, 0, - 0, 3670, 0, - 2602, 2350, 2813, - 2602, 2351, 2812, - 2602, 2351, 2812, - 2601, 2352, 2812, - 2600, 2353, 2811, - 2599, 2354, 2811, - 2597, 2355, 2810, - 2595, 2357, 2809, - 2591, 2359, 2807, - 2587, 2362, 2805, - 2582, 2367, 2803, - 2574, 2372, 2799, - 2563, 2380, 2794, - 2549, 2390, 2788, - 2529, 2402, 2779, - 2501, 2419, 2767, - 2460, 2440, 2750, - 2400, 2467, 2727, - 2303, 2501, 2694, - 2131, 2543, 2645, - 1693, 2593, 2570, - 0, 2652, 2447, - 0, 2721, 2200, - 0, 2800, 714, - 0, 2887, 0, - 0, 2983, 0, - 0, 3085, 0, - 0, 3194, 0, - 0, 3308, 0, - 0, 3426, 0, - 0, 3547, 0, - 0, 3671, 0, - 2781, 2377, 2879, - 2781, 2377, 2879, - 2781, 2378, 2879, - 2780, 2378, 2878, - 2780, 2379, 2878, - 2779, 2380, 2877, - 2778, 2381, 2877, - 2776, 2383, 2876, - 2774, 2385, 2874, - 2771, 2388, 2873, - 2767, 2392, 2870, - 2762, 2398, 2867, - 2755, 2405, 2863, - 2746, 2414, 2858, - 2733, 2426, 2850, - 2715, 2442, 2840, - 2691, 2462, 2826, - 2655, 2488, 2806, - 2602, 2520, 2778, - 2521, 2560, 2738, - 2384, 2609, 2678, - 2092, 2666, 2584, - 0, 2733, 2415, - 0, 2810, 1999, - 0, 2895, 0, - 0, 2989, 0, - 0, 3091, 0, - 0, 3198, 0, - 0, 3311, 0, - 0, 3429, 0, - 0, 3549, 0, - 0, 3673, 0, - 2946, 2411, 2955, - 2945, 2411, 2955, - 2945, 2411, 2954, - 2945, 2412, 2954, - 2944, 2412, 2954, - 2944, 2413, 2953, - 2943, 2414, 2953, - 2942, 2416, 2952, - 2940, 2418, 2951, - 2939, 2421, 2950, - 2936, 2425, 2948, - 2932, 2430, 2945, - 2928, 2436, 2942, - 2921, 2445, 2937, - 2913, 2456, 2930, - 2901, 2471, 2922, - 2884, 2490, 2910, - 2861, 2514, 2894, - 2829, 2545, 2871, - 2781, 2583, 2838, - 2709, 2629, 2791, - 2589, 2684, 2719, - 2354, 2749, 2601, - 1291, 2823, 2369, - 0, 2906, 1378, - 0, 2998, 0, - 0, 3098, 0, - 0, 3204, 0, - 0, 3316, 0, - 0, 3432, 0, - 0, 3552, 0, - 0, 3675, 0, - 3100, 2452, 3040, - 3100, 2452, 3040, - 3100, 2452, 3039, - 3100, 2453, 3039, - 3099, 2453, 3039, - 3099, 2454, 3039, - 3098, 2455, 3038, - 3098, 2457, 3037, - 3097, 2459, 3037, - 3095, 2461, 3035, - 3093, 2465, 3034, - 3091, 2469, 3032, - 3088, 2475, 3029, - 3083, 2483, 3025, - 3077, 2494, 3020, - 3069, 2507, 3013, - 3058, 2525, 3003, - 3042, 2547, 2990, - 3020, 2576, 2971, - 2990, 2611, 2945, - 2945, 2655, 2909, - 2878, 2707, 2854, - 2769, 2769, 2769, - 2564, 2840, 2622, - 1912, 2921, 2300, - 0, 3010, 0, - 0, 3107, 0, - 0, 3212, 0, - 0, 3322, 0, - 0, 3437, 0, - 0, 3555, 0, - 0, 3677, 0, - 3249, 2501, 3133, - 3248, 2502, 3133, - 3248, 2502, 3133, - 3248, 2502, 3133, - 3248, 2503, 3132, - 3248, 2504, 3132, - 3247, 2505, 3132, - 3247, 2506, 3131, - 3246, 2508, 3130, - 3245, 2510, 3129, - 3244, 2513, 3128, - 3242, 2517, 3126, - 3239, 2523, 3124, - 3236, 2530, 3121, - 3232, 2539, 3117, - 3226, 2552, 3111, - 3218, 2568, 3103, - 3207, 2588, 3093, - 3192, 2614, 3078, - 3172, 2647, 3058, - 3142, 2687, 3029, - 3100, 2736, 2988, - 3036, 2794, 2926, - 2934, 2862, 2828, - 2746, 2939, 2650, - 2226, 3025, 2186, - 0, 3120, 0, - 0, 3221, 0, - 0, 3329, 0, - 0, 3443, 0, - 0, 3560, 0, - 0, 3681, 0, - 3392, 2560, 3234, - 3392, 2561, 3234, - 3392, 2561, 3234, - 3392, 2561, 3233, - 3392, 2562, 3233, - 3392, 2562, 3233, - 3391, 2563, 3233, - 3391, 2564, 3232, - 3391, 2566, 3232, - 3390, 2568, 3231, - 3389, 2571, 3230, - 3388, 2574, 3229, - 3386, 2579, 3227, - 3383, 2586, 3224, - 3380, 2594, 3221, - 3376, 2605, 3216, - 3370, 2619, 3210, - 3363, 2637, 3202, - 3352, 2661, 3190, - 3338, 2691, 3175, - 3317, 2727, 3153, - 3289, 2772, 3121, - 3248, 2826, 3076, - 3187, 2890, 3008, - 3089, 2962, 2896, - 2913, 3045, 2685, - 2459, 3135, 1969, - 0, 3234, 0, - 0, 3339, 0, - 0, 3450, 0, - 0, 3566, 0, - 0, 3685, 0, - 3533, 2629, 3341, - 3533, 2629, 3341, - 3533, 2629, 3341, - 3533, 2630, 3341, - 3533, 2630, 3341, - 3533, 2631, 3340, - 3532, 2631, 3340, - 3532, 2632, 3340, - 3532, 2634, 3339, - 3531, 2636, 3339, - 3530, 2638, 3338, - 3530, 2641, 3337, - 3528, 2645, 3335, - 3527, 2651, 3333, - 3524, 2658, 3331, - 3521, 2668, 3327, - 3517, 2680, 3322, - 3512, 2696, 3316, - 3504, 2717, 3307, - 3494, 2743, 3295, - 3479, 2776, 3278, - 3460, 2817, 3255, - 3432, 2866, 3221, - 3392, 2924, 3173, - 3332, 2992, 3098, - 3237, 3069, 2974, - 3069, 3156, 2727, - 2654, 3251, 1192, - 0, 3353, 0, - 0, 3461, 0, - 0, 3574, 0, - 0, 3692, 0, - 3672, 2707, 3453, - 3672, 2707, 3453, - 3671, 2707, 3453, - 3671, 2708, 3453, - 3671, 2708, 3453, - 3671, 2709, 3453, - 3671, 2709, 3453, - 3671, 2710, 3453, - 3671, 2711, 3452, - 3670, 2713, 3452, - 3670, 2715, 3451, - 3669, 2717, 3450, - 3668, 2721, 3449, - 3667, 2725, 3448, - 3665, 2732, 3446, - 3663, 2740, 3443, - 3660, 2750, 3439, - 3656, 2764, 3434, - 3650, 2782, 3427, - 3643, 2805, 3418, - 3633, 2834, 3405, - 3619, 2870, 3388, - 3599, 2914, 3363, - 3572, 2967, 3328, - 3532, 3029, 3276, - 3474, 3101, 3196, - 3382, 3182, 3061, - 3218, 3272, 2778, - 2827, 3370, 0, - 0, 3474, 0, - 0, 3585, 0, - 0, 3700, 0, - 3808, 2794, 3570, - 3808, 2794, 3570, - 3808, 2794, 3570, - 3808, 2795, 3570, - 3808, 2795, 3570, - 3808, 2795, 3570, - 3808, 2796, 3570, - 3808, 2796, 3570, - 3808, 2797, 3569, - 3807, 2799, 3569, - 3807, 2800, 3569, - 3806, 2803, 3568, - 3806, 2805, 3567, - 3805, 2809, 3566, - 3804, 2814, 3564, - 3802, 2821, 3562, - 3800, 2830, 3559, - 3797, 2842, 3555, - 3793, 2857, 3550, - 3787, 2876, 3543, - 3780, 2901, 3533, - 3770, 2932, 3520, - 3756, 2971, 3502, - 3737, 3018, 3476, - 3710, 3074, 3440, - 3671, 3139, 3385, - 3613, 3214, 3301, - 3522, 3299, 3156, - 3363, 3391, 2839, - 2989, 3492, 0, - 0, 3598, 0, - 0, 3710, 0, - 3944, 2889, 3691, - 3944, 2889, 3691, - 3944, 2890, 3691, - 3944, 2890, 3691, - 3944, 2890, 3691, - 3944, 2890, 3691, - 3944, 2891, 3690, - 3943, 2891, 3690, - 3943, 2892, 3690, - 3943, 2893, 3690, - 3943, 2894, 3689, - 3942, 2896, 3689, - 3942, 2898, 3688, - 3941, 2902, 3687, - 3940, 2906, 3686, - 3939, 2911, 3684, - 3937, 2919, 3682, - 3935, 2928, 3679, - 3932, 2941, 3675, - 3928, 2957, 3670, - 3923, 2978, 3663, - 3916, 3004, 3653, - 3906, 3037, 3639, - 3892, 3078, 3620, - 3873, 3128, 3594, - 3846, 3186, 3556, - 3808, 3255, 3500, - 3750, 3332, 3412, - 3661, 3419, 3258, - 3504, 3514, 2909, - 3141, 3616, 0, - 0, 3724, 0, - 4079, 2992, 3814, - 4079, 2992, 3814, - 4078, 2992, 3814, - 4078, 2992, 3814, - 4078, 2992, 3814, - 4078, 2992, 3814, - 4078, 2993, 3814, - 4078, 2993, 3813, - 4078, 2994, 3813, - 4078, 2995, 3813, - 4078, 2996, 3813, - 4077, 2997, 3812, - 4077, 2999, 3812, - 4077, 3002, 3811, - 4076, 3005, 3810, - 4075, 3009, 3809, - 4074, 3015, 3807, - 4072, 3023, 3805, - 4070, 3033, 3802, - 4067, 3047, 3798, - 4063, 3064, 3793, - 4058, 3086, 3785, - 4050, 3114, 3775, - 4040, 3148, 3761, - 4027, 3191, 3742, - 4008, 3242, 3715, - 3981, 3303, 3676, - 3943, 3374, 3618, - 3886, 3453, 3527, - 3798, 3542, 3367, - 3643, 3639, 2988, - 3288, 3742, 0, - 4095, 3100, 3939, - 4095, 3100, 3939, - 4095, 3100, 3939, - 4095, 3101, 3939, - 4095, 3101, 3939, - 4095, 3101, 3939, - 4095, 3101, 3939, - 4095, 3101, 3939, - 4095, 3102, 3939, - 4095, 3103, 3939, - 4095, 3103, 3938, - 4095, 3105, 3938, - 4095, 3106, 3938, - 4095, 3108, 3937, - 4095, 3111, 3936, - 4095, 3114, 3936, - 4095, 3119, 3934, - 4095, 3125, 3933, - 4095, 3133, 3930, - 4095, 3144, 3927, - 4095, 3158, 3923, - 4095, 3176, 3918, - 4095, 3199, 3910, - 4095, 3228, 3900, - 4095, 3264, 3886, - 4095, 3308, 3866, - 4095, 3361, 3839, - 4095, 3424, 3799, - 4078, 3496, 3740, - 4021, 3577, 3646, - 3933, 3667, 3480, - 3780, 3765, 3076, - 4095, 3214, 4066, - 4095, 3214, 4066, - 4095, 3214, 4066, - 4095, 3214, 4066, - 4095, 3214, 4066, - 4095, 3214, 4066, - 4095, 3215, 4066, - 4095, 3215, 4066, - 4095, 3215, 4066, - 4095, 3216, 4066, - 4095, 3216, 4066, - 4095, 3217, 4065, - 4095, 3218, 4065, - 4095, 3220, 4065, - 4095, 3222, 4064, - 4095, 3225, 4063, - 4095, 3229, 4062, - 4095, 3233, 4061, - 4095, 3240, 4059, - 4095, 3248, 4057, - 4095, 3259, 4054, - 4095, 3274, 4050, - 4095, 3292, 4044, - 4095, 3316, 4037, - 4095, 3346, 4026, - 4095, 3383, 4012, - 4095, 3429, 3992, - 4095, 3483, 3964, - 4095, 3547, 3924, - 4095, 3620, 3864, - 4095, 3703, 3768, - 4068, 3794, 3598, - 0, 2393, 2661, - 0, 2393, 2661, - 0, 2393, 2661, - 0, 2394, 2660, - 0, 2395, 2660, - 0, 2396, 2659, - 0, 2397, 2658, - 0, 2399, 2656, - 0, 2401, 2654, - 0, 2404, 2651, - 0, 2408, 2648, - 0, 2413, 2643, - 0, 2420, 2636, - 0, 2429, 2627, - 0, 2440, 2614, - 0, 2456, 2596, - 0, 2475, 2572, - 0, 2500, 2537, - 0, 2532, 2485, - 0, 2571, 2406, - 0, 2618, 2271, - 0, 2674, 1991, - 0, 2740, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3313, 0, - 0, 3430, 0, - 0, 3550, 0, - 0, 3673, 0, - 0, 2393, 2662, - 0, 2393, 2662, - 0, 2394, 2661, - 0, 2394, 2661, - 0, 2395, 2660, - 0, 2396, 2659, - 0, 2397, 2658, - 0, 2399, 2657, - 0, 2401, 2655, - 0, 2404, 2652, - 0, 2408, 2648, - 0, 2413, 2643, - 0, 2420, 2636, - 0, 2429, 2627, - 0, 2441, 2614, - 0, 2456, 2597, - 0, 2475, 2572, - 0, 2500, 2537, - 0, 2532, 2486, - 0, 2571, 2406, - 0, 2618, 2272, - 0, 2675, 1992, - 0, 2740, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3313, 0, - 0, 3430, 0, - 0, 3550, 0, - 0, 3673, 0, - 0, 2393, 2662, - 0, 2393, 2662, - 0, 2394, 2662, - 0, 2394, 2661, - 0, 2395, 2661, - 0, 2396, 2660, - 0, 2397, 2659, - 0, 2399, 2657, - 0, 2401, 2655, - 0, 2404, 2652, - 0, 2408, 2649, - 0, 2413, 2644, - 0, 2420, 2637, - 0, 2429, 2628, - 0, 2441, 2615, - 0, 2456, 2597, - 0, 2476, 2573, - 0, 2501, 2538, - 0, 2532, 2487, - 0, 2571, 2407, - 0, 2618, 2273, - 0, 2675, 1995, - 0, 2741, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3313, 0, - 0, 3430, 0, - 0, 3550, 0, - 0, 3673, 0, - 0, 2393, 2663, - 0, 2393, 2663, - 0, 2394, 2662, - 0, 2394, 2662, - 0, 2395, 2661, - 0, 2396, 2661, - 0, 2397, 2659, - 0, 2399, 2658, - 0, 2401, 2656, - 0, 2404, 2653, - 0, 2408, 2649, - 0, 2413, 2644, - 0, 2420, 2638, - 0, 2429, 2628, - 0, 2441, 2616, - 0, 2456, 2598, - 0, 2476, 2574, - 0, 2501, 2539, - 0, 2532, 2488, - 0, 2571, 2408, - 0, 2618, 2275, - 0, 2675, 1998, - 0, 2741, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3313, 0, - 0, 3430, 0, - 0, 3550, 0, - 0, 3674, 0, - 0, 2393, 2664, - 0, 2394, 2664, - 0, 2394, 2663, - 0, 2395, 2663, - 0, 2395, 2662, - 0, 2396, 2661, - 0, 2398, 2660, - 0, 2399, 2659, - 0, 2401, 2657, - 0, 2404, 2654, - 0, 2408, 2650, - 0, 2413, 2645, - 0, 2420, 2639, - 0, 2429, 2629, - 0, 2441, 2617, - 0, 2456, 2599, - 0, 2476, 2575, - 0, 2501, 2540, - 0, 2532, 2489, - 0, 2571, 2410, - 0, 2618, 2277, - 0, 2675, 2002, - 0, 2741, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3313, 0, - 0, 3430, 0, - 0, 3550, 0, - 0, 3674, 0, - 0, 2394, 2665, - 0, 2394, 2665, - 0, 2394, 2665, - 0, 2395, 2664, - 0, 2396, 2664, - 0, 2397, 2663, - 0, 2398, 2662, - 0, 2399, 2660, - 0, 2402, 2658, - 0, 2405, 2655, - 0, 2409, 2652, - 0, 2414, 2647, - 0, 2421, 2640, - 0, 2430, 2631, - 0, 2441, 2618, - 0, 2457, 2601, - 0, 2476, 2576, - 0, 2501, 2542, - 0, 2533, 2491, - 0, 2571, 2412, - 0, 2619, 2280, - 0, 2675, 2007, - 0, 2741, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3314, 0, - 0, 3430, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2394, 2667, - 0, 2394, 2667, - 0, 2395, 2666, - 0, 2395, 2666, - 0, 2396, 2665, - 0, 2397, 2664, - 0, 2398, 2663, - 0, 2400, 2662, - 0, 2402, 2660, - 0, 2405, 2657, - 0, 2409, 2653, - 0, 2414, 2648, - 0, 2421, 2642, - 0, 2430, 2633, - 0, 2442, 2620, - 0, 2457, 2603, - 0, 2477, 2579, - 0, 2501, 2544, - 0, 2533, 2493, - 0, 2572, 2415, - 0, 2619, 2284, - 0, 2675, 2014, - 0, 2741, 0, - 0, 2816, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3094, 0, - 0, 3201, 0, - 0, 3314, 0, - 0, 3430, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2395, 2669, - 0, 2395, 2669, - 0, 2395, 2669, - 0, 2396, 2668, - 0, 2397, 2668, - 0, 2398, 2667, - 0, 2399, 2666, - 0, 2400, 2664, - 0, 2403, 2662, - 0, 2406, 2659, - 0, 2410, 2656, - 0, 2415, 2651, - 0, 2422, 2644, - 0, 2430, 2635, - 0, 2442, 2623, - 0, 2457, 2605, - 0, 2477, 2581, - 0, 2502, 2547, - 0, 2533, 2497, - 0, 2572, 2419, - 0, 2619, 2289, - 0, 2676, 2024, - 0, 2741, 0, - 0, 2817, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3095, 0, - 0, 3201, 0, - 0, 3314, 0, - 0, 3430, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2395, 2672, - 0, 2396, 2672, - 0, 2396, 2672, - 0, 2397, 2671, - 0, 2397, 2670, - 0, 2398, 2670, - 0, 2400, 2669, - 0, 2401, 2667, - 0, 2403, 2665, - 0, 2406, 2662, - 0, 2410, 2659, - 0, 2415, 2654, - 0, 2422, 2647, - 0, 2431, 2638, - 0, 2443, 2626, - 0, 2458, 2609, - 0, 2478, 2585, - 0, 2503, 2551, - 0, 2534, 2501, - 0, 2573, 2424, - 0, 2620, 2296, - 0, 2676, 2036, - 0, 2742, 0, - 0, 2817, 0, - 0, 2901, 0, - 0, 2994, 0, - 0, 3095, 0, - 0, 3202, 0, - 0, 3314, 0, - 0, 3430, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2397, 2676, - 0, 2397, 2676, - 0, 2397, 2676, - 0, 2398, 2675, - 0, 2398, 2674, - 0, 2399, 2674, - 0, 2401, 2673, - 0, 2402, 2671, - 0, 2404, 2669, - 0, 2407, 2666, - 0, 2411, 2663, - 0, 2416, 2658, - 0, 2423, 2651, - 0, 2432, 2642, - 0, 2444, 2630, - 0, 2459, 2613, - 0, 2478, 2590, - 0, 2503, 2556, - 0, 2535, 2507, - 0, 2573, 2431, - 0, 2620, 2305, - 0, 2677, 2052, - 0, 2742, 0, - 0, 2817, 0, - 0, 2902, 0, - 0, 2995, 0, - 0, 3095, 0, - 0, 3202, 0, - 0, 3314, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2398, 2681, - 0, 2398, 2681, - 0, 2399, 2681, - 0, 2399, 2680, - 0, 2400, 2680, - 0, 2401, 2679, - 0, 2402, 2678, - 0, 2404, 2676, - 0, 2406, 2674, - 0, 2409, 2672, - 0, 2413, 2668, - 0, 2418, 2663, - 0, 2424, 2657, - 0, 2433, 2648, - 0, 2445, 2636, - 0, 2460, 2619, - 0, 2480, 2596, - 0, 2504, 2563, - 0, 2536, 2514, - 0, 2574, 2440, - 0, 2621, 2317, - 0, 2677, 2072, - 0, 2743, 674, - 0, 2818, 0, - 0, 2902, 0, - 0, 2995, 0, - 0, 3095, 0, - 0, 3202, 0, - 0, 3314, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2400, 2688, - 0, 2400, 2688, - 0, 2400, 2688, - 0, 2401, 2687, - 0, 2402, 2687, - 0, 2402, 2686, - 0, 2404, 2685, - 0, 2405, 2683, - 0, 2408, 2681, - 0, 2410, 2679, - 0, 2414, 2675, - 0, 2419, 2671, - 0, 2426, 2664, - 0, 2435, 2656, - 0, 2447, 2644, - 0, 2462, 2627, - 0, 2481, 2604, - 0, 2506, 2572, - 0, 2537, 2524, - 0, 2575, 2452, - 0, 2622, 2332, - 0, 2678, 2098, - 0, 2744, 1046, - 0, 2819, 0, - 0, 2903, 0, - 0, 2995, 0, - 0, 3096, 0, - 0, 3202, 0, - 0, 3314, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2402, 2697, - 0, 2402, 2697, - 0, 2403, 2697, - 0, 2403, 2696, - 0, 2404, 2696, - 0, 2405, 2695, - 0, 2406, 2694, - 0, 2408, 2693, - 0, 2410, 2691, - 0, 2413, 2688, - 0, 2417, 2685, - 0, 2422, 2680, - 0, 2428, 2674, - 0, 2437, 2665, - 0, 2449, 2654, - 0, 2464, 2638, - 0, 2483, 2615, - 0, 2508, 2583, - 0, 2539, 2537, - 0, 2577, 2467, - 0, 2624, 2352, - 0, 2680, 2130, - 0, 2745, 1300, - 0, 2820, 0, - 0, 2904, 0, - 0, 2996, 0, - 0, 3096, 0, - 0, 3203, 0, - 0, 3315, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2405, 2709, - 0, 2406, 2709, - 0, 2406, 2709, - 0, 2406, 2708, - 0, 2407, 2708, - 0, 2408, 2707, - 0, 2409, 2706, - 0, 2411, 2705, - 0, 2413, 2703, - 0, 2416, 2700, - 0, 2420, 2697, - 0, 2425, 2692, - 0, 2431, 2686, - 0, 2440, 2678, - 0, 2452, 2667, - 0, 2467, 2651, - 0, 2486, 2629, - 0, 2510, 2599, - 0, 2541, 2554, - 0, 2579, 2486, - 0, 2626, 2377, - 0, 2681, 2170, - 0, 2746, 1506, - 0, 2821, 0, - 0, 2905, 0, - 0, 2997, 0, - 0, 3097, 0, - 0, 3203, 0, - 0, 3315, 0, - 0, 3431, 0, - 0, 3551, 0, - 0, 3674, 0, - 0, 2410, 2725, - 0, 2410, 2724, - 0, 2410, 2724, - 0, 2411, 2724, - 0, 2411, 2723, - 0, 2412, 2722, - 0, 2413, 2721, - 0, 2415, 2720, - 0, 2417, 2718, - 0, 2420, 2716, - 0, 2424, 2713, - 0, 2429, 2708, - 0, 2435, 2702, - 0, 2444, 2694, - 0, 2456, 2684, - 0, 2470, 2669, - 0, 2489, 2648, - 0, 2514, 2618, - 0, 2544, 2575, - 0, 2582, 2511, - 0, 2628, 2408, - 0, 2684, 2219, - 0, 2748, 1686, - 0, 2823, 0, - 0, 2906, 0, - 0, 2998, 0, - 0, 3098, 0, - 0, 3204, 0, - 0, 3316, 0, - 0, 3432, 0, - 0, 3552, 0, - 0, 3675, 0, - 0, 2415, 2744, - 0, 2415, 2744, - 0, 2416, 2744, - 0, 2416, 2744, - 0, 2417, 2743, - 0, 2418, 2742, - 0, 2419, 2741, - 0, 2421, 2740, - 0, 2423, 2738, - 0, 2426, 2736, - 0, 2429, 2733, - 0, 2434, 2729, - 0, 2441, 2723, - 0, 2449, 2716, - 0, 2461, 2705, - 0, 2475, 2691, - 0, 2494, 2671, - 0, 2518, 2643, - 0, 2548, 2603, - 0, 2586, 2543, - 0, 2632, 2447, - 0, 2687, 2277, - 0, 2751, 1851, - 0, 2825, 0, - 0, 2908, 0, - 0, 3000, 0, - 0, 3099, 0, - 0, 3205, 0, - 0, 3316, 0, - 0, 3432, 0, - 0, 3552, 0, - 0, 3675, 0, - 896, 2423, 2770, - 879, 2423, 2769, - 854, 2423, 2769, - 820, 2424, 2769, - 769, 2424, 2768, - 691, 2425, 2768, - 560, 2426, 2767, - 290, 2428, 2766, - 0, 2430, 2764, - 0, 2433, 2762, - 0, 2436, 2759, - 0, 2441, 2755, - 0, 2448, 2750, - 0, 2456, 2742, - 0, 2467, 2733, - 0, 2482, 2719, - 0, 2500, 2701, - 0, 2524, 2674, - 0, 2554, 2637, - 0, 2591, 2581, - 0, 2636, 2494, - 0, 2691, 2344, - 0, 2755, 2007, - 0, 2828, 0, - 0, 2910, 0, - 0, 3002, 0, - 0, 3101, 0, - 0, 3206, 0, - 0, 3317, 0, - 0, 3433, 0, - 0, 3553, 0, - 0, 3675, 0, - 1925, 2432, 2801, - 1923, 2432, 2801, - 1921, 2433, 2801, - 1917, 2433, 2801, - 1913, 2434, 2800, - 1907, 2435, 2799, - 1899, 2436, 2799, - 1889, 2438, 2798, - 1874, 2440, 2796, - 1853, 2442, 2794, - 1824, 2446, 2791, - 1782, 2451, 2788, - 1718, 2457, 2783, - 1617, 2465, 2776, - 1432, 2476, 2767, - 925, 2490, 2754, - 0, 2508, 2737, - 0, 2532, 2713, - 0, 2561, 2679, - 0, 2598, 2628, - 0, 2642, 2551, - 0, 2696, 2421, - 0, 2759, 2155, - 0, 2832, 0, - 0, 2914, 0, - 0, 3004, 0, - 0, 3103, 0, - 0, 3208, 0, - 0, 3319, 0, - 0, 3434, 0, - 0, 3554, 0, - 0, 3676, 0, - 2283, 2445, 2841, - 2282, 2445, 2840, - 2281, 2445, 2840, - 2279, 2446, 2840, - 2278, 2447, 2839, - 2275, 2447, 2839, - 2271, 2449, 2838, - 2267, 2450, 2837, - 2260, 2452, 2836, - 2252, 2455, 2834, - 2240, 2458, 2831, - 2223, 2463, 2828, - 2200, 2469, 2823, - 2168, 2477, 2817, - 2120, 2488, 2809, - 2047, 2501, 2798, - 1927, 2519, 2782, - 1692, 2542, 2760, - 612, 2571, 2729, - 0, 2607, 2685, - 0, 2650, 2617, - 0, 2703, 2507, - 0, 2765, 2299, - 0, 2837, 1624, - 0, 2918, 0, - 0, 3008, 0, - 0, 3106, 0, - 0, 3210, 0, - 0, 3321, 0, - 0, 3436, 0, - 0, 3555, 0, - 0, 3677, 0, - 2532, 2461, 2888, - 2531, 2462, 2888, - 2531, 2462, 2888, - 2530, 2462, 2887, - 2529, 2463, 2887, - 2527, 2464, 2887, - 2525, 2465, 2886, - 2522, 2466, 2885, - 2519, 2468, 2884, - 2514, 2471, 2882, - 2507, 2474, 2880, - 2498, 2479, 2877, - 2486, 2484, 2873, - 2469, 2492, 2867, - 2445, 2503, 2860, - 2411, 2516, 2850, - 2360, 2533, 2836, - 2283, 2555, 2817, - 2155, 2583, 2789, - 1893, 2618, 2750, - 0, 2661, 2692, - 0, 2713, 2601, - 0, 2774, 2440, - 0, 2844, 2059, - 0, 2924, 0, - 0, 3013, 0, - 0, 3110, 0, - 0, 3213, 0, - 0, 3323, 0, - 0, 3438, 0, - 0, 3556, 0, - 0, 3678, 0, - 2735, 2482, 2945, - 2735, 2483, 2945, - 2734, 2483, 2945, - 2734, 2483, 2944, - 2733, 2484, 2944, - 2732, 2485, 2944, - 2731, 2486, 2943, - 2729, 2487, 2942, - 2727, 2489, 2941, - 2724, 2491, 2940, - 2719, 2495, 2938, - 2714, 2499, 2935, - 2706, 2504, 2931, - 2696, 2512, 2927, - 2681, 2522, 2920, - 2661, 2535, 2911, - 2633, 2551, 2899, - 2592, 2572, 2882, - 2532, 2599, 2859, - 2435, 2633, 2826, - 2263, 2675, 2777, - 1825, 2725, 2702, - 0, 2784, 2579, - 0, 2853, 2332, - 0, 2932, 847, - 0, 3019, 0, - 0, 3115, 0, - 0, 3217, 0, - 0, 3326, 0, - 0, 3440, 0, - 0, 3558, 0, - 0, 3679, 0, - 2914, 2509, 3011, - 2913, 2509, 3011, - 2913, 2510, 3011, - 2913, 2510, 3011, - 2912, 2510, 3010, - 2912, 2511, 3010, - 2911, 2512, 3009, - 2910, 2513, 3009, - 2908, 2515, 3008, - 2906, 2517, 3007, - 2903, 2521, 3005, - 2900, 2525, 3003, - 2894, 2530, 3000, - 2888, 2537, 2995, - 2878, 2546, 2990, - 2865, 2558, 2982, - 2848, 2574, 2972, - 2823, 2594, 2958, - 2787, 2620, 2938, - 2735, 2652, 2910, - 2653, 2692, 2870, - 2516, 2741, 2810, - 2224, 2798, 2716, - 0, 2865, 2547, - 0, 2942, 2131, - 0, 3028, 0, - 0, 3122, 0, - 0, 3223, 0, - 0, 3331, 0, - 0, 3443, 0, - 0, 3561, 0, - 0, 3681, 0, - 3078, 2542, 3087, - 3078, 2543, 3087, - 3077, 2543, 3087, - 3077, 2543, 3087, - 3077, 2544, 3086, - 3076, 2544, 3086, - 3076, 2545, 3086, - 3075, 2547, 3085, - 3074, 2548, 3084, - 3073, 2550, 3083, - 3071, 2553, 3082, - 3068, 2557, 3080, - 3064, 2562, 3077, - 3060, 2569, 3074, - 3053, 2577, 3069, - 3045, 2589, 3063, - 3033, 2603, 3054, - 3016, 2622, 3042, - 2993, 2647, 3026, - 2961, 2677, 3003, - 2913, 2715, 2971, - 2841, 2761, 2923, - 2721, 2816, 2851, - 2486, 2881, 2733, - 1423, 2955, 2501, - 0, 3039, 1510, - 0, 3130, 0, - 0, 3230, 0, - 0, 3336, 0, - 0, 3448, 0, - 0, 3564, 0, - 0, 3684, 0, - 3232, 2584, 3172, - 3232, 2584, 3172, - 3232, 2584, 3172, - 3232, 2584, 3172, - 3232, 2585, 3171, - 3232, 2585, 3171, - 3231, 2586, 3171, - 3231, 2587, 3170, - 3230, 2589, 3170, - 3229, 2591, 3169, - 3227, 2593, 3167, - 3226, 2597, 3166, - 3223, 2601, 3164, - 3220, 2607, 3161, - 3215, 2615, 3157, - 3209, 2626, 3152, - 3201, 2639, 3145, - 3190, 2657, 3135, - 3174, 2680, 3122, - 3152, 2708, 3103, - 3122, 2743, 3078, - 3077, 2787, 3041, - 3010, 2839, 2986, - 2901, 2901, 2901, - 2696, 2972, 2754, - 2044, 3053, 2432, - 0, 3142, 0, - 0, 3239, 0, - 0, 3344, 0, - 0, 3454, 0, - 0, 3569, 0, - 0, 3687, 0, - 3381, 2633, 3265, - 3381, 2634, 3265, - 3381, 2634, 3265, - 3380, 2634, 3265, - 3380, 2634, 3265, - 3380, 2635, 3265, - 3380, 2636, 3264, - 3379, 2637, 3264, - 3379, 2638, 3263, - 3378, 2640, 3263, - 3377, 2642, 3262, - 3376, 2645, 3260, - 3374, 2649, 3259, - 3372, 2655, 3256, - 3368, 2662, 3253, - 3364, 2671, 3249, - 3358, 2684, 3243, - 3350, 2700, 3235, - 3339, 2720, 3225, - 3324, 2746, 3210, - 3304, 2779, 3190, - 3274, 2819, 3161, - 3232, 2868, 3120, - 3168, 2926, 3058, - 3066, 2994, 2960, - 2879, 3071, 2782, - 2358, 3157, 2318, - 0, 3252, 0, - 0, 3353, 0, - 0, 3461, 0, - 0, 3575, 0, - 0, 3692, 0, - 3525, 2692, 3366, - 3525, 2693, 3366, - 3524, 2693, 3366, - 3524, 2693, 3366, - 3524, 2693, 3366, - 3524, 2694, 3365, - 3524, 2695, 3365, - 3524, 2695, 3365, - 3523, 2697, 3364, - 3523, 2698, 3364, - 3522, 2700, 3363, - 3521, 2703, 3362, - 3520, 2707, 3361, - 3518, 2711, 3359, - 3516, 2718, 3356, - 3512, 2726, 3353, - 3508, 2737, 3348, - 3503, 2751, 3342, - 3495, 2770, 3334, - 3484, 2793, 3322, - 3470, 2823, 3307, - 3450, 2859, 3285, - 3421, 2904, 3254, - 3380, 2958, 3208, - 3319, 3022, 3140, - 3221, 3095, 3028, - 3045, 3177, 2817, - 2591, 3268, 2101, - 0, 3366, 0, - 0, 3471, 0, - 0, 3582, 0, - 0, 3698, 0, - 3665, 2761, 3473, - 3665, 2761, 3473, - 3665, 2761, 3473, - 3665, 2762, 3473, - 3665, 2762, 3473, - 3665, 2762, 3473, - 3665, 2763, 3472, - 3665, 2764, 3472, - 3664, 2765, 3472, - 3664, 2766, 3471, - 3663, 2768, 3471, - 3663, 2770, 3470, - 3662, 2773, 3469, - 3660, 2777, 3467, - 3659, 2783, 3465, - 3656, 2790, 3463, - 3653, 2800, 3459, - 3649, 2812, 3454, - 3644, 2828, 3448, - 3636, 2849, 3439, - 3626, 2875, 3427, - 3611, 2908, 3410, - 3592, 2949, 3387, - 3564, 2998, 3353, - 3524, 3056, 3305, - 3464, 3124, 3230, - 3370, 3202, 3106, - 3201, 3288, 2859, - 2786, 3383, 1324, - 0, 3485, 0, - 0, 3593, 0, - 0, 3706, 0, - 3804, 2839, 3586, - 3804, 2839, 3586, - 3804, 2839, 3586, - 3804, 2840, 3585, - 3803, 2840, 3585, - 3803, 2840, 3585, - 3803, 2841, 3585, - 3803, 2841, 3585, - 3803, 2842, 3585, - 3803, 2843, 3584, - 3802, 2845, 3584, - 3802, 2847, 3583, - 3801, 2849, 3582, - 3800, 2853, 3581, - 3799, 2858, 3580, - 3797, 2864, 3578, - 3795, 2872, 3575, - 3792, 2882, 3571, - 3788, 2896, 3566, - 3782, 2914, 3559, - 3775, 2937, 3550, - 3765, 2966, 3537, - 3751, 3002, 3520, - 3731, 3046, 3495, - 3704, 3099, 3460, - 3665, 3161, 3408, - 3606, 3233, 3328, - 3514, 3314, 3193, - 3351, 3404, 2910, - 2960, 3502, 0, - 0, 3606, 0, - 0, 3717, 0, - 3940, 2926, 3703, - 3940, 2926, 3702, - 3940, 2926, 3702, - 3940, 2926, 3702, - 3940, 2927, 3702, - 3940, 2927, 3702, - 3940, 2927, 3702, - 3940, 2928, 3702, - 3940, 2929, 3702, - 3940, 2930, 3702, - 3939, 2931, 3701, - 3939, 2932, 3701, - 3938, 2935, 3700, - 3938, 2938, 3699, - 3937, 2941, 3698, - 3936, 2947, 3696, - 3934, 2953, 3694, - 3932, 2962, 3691, - 3929, 2974, 3687, - 3925, 2989, 3682, - 3919, 3008, 3675, - 3912, 3033, 3666, - 3902, 3064, 3652, - 3888, 3103, 3634, - 3869, 3150, 3608, - 3842, 3206, 3572, - 3803, 3271, 3517, - 3745, 3347, 3433, - 3654, 3431, 3288, - 3495, 3523, 2971, - 3121, 3624, 0, - 0, 3730, 0, - 4076, 3021, 3823, - 4076, 3021, 3823, - 4076, 3021, 3823, - 4076, 3022, 3823, - 4076, 3022, 3823, - 4076, 3022, 3823, - 4076, 3022, 3823, - 4076, 3023, 3822, - 4076, 3023, 3822, - 4075, 3024, 3822, - 4075, 3025, 3822, - 4075, 3026, 3821, - 4075, 3028, 3821, - 4074, 3031, 3820, - 4073, 3034, 3819, - 4072, 3038, 3818, - 4071, 3043, 3817, - 4070, 3051, 3814, - 4067, 3060, 3811, - 4064, 3073, 3807, - 4060, 3089, 3802, - 4055, 3110, 3795, - 4048, 3136, 3785, - 4038, 3170, 3771, - 4024, 3210, 3753, - 4005, 3260, 3726, - 3978, 3318, 3688, - 3940, 3387, 3632, - 3883, 3464, 3544, - 3793, 3551, 3390, - 3636, 3646, 3041, - 3273, 3748, 0, - 4095, 3124, 3946, - 4095, 3124, 3946, - 4095, 3124, 3946, - 4095, 3124, 3946, - 4095, 3124, 3946, - 4095, 3124, 3946, - 4095, 3125, 3946, - 4095, 3125, 3946, - 4095, 3125, 3946, - 4095, 3126, 3945, - 4095, 3127, 3945, - 4095, 3128, 3945, - 4095, 3129, 3945, - 4095, 3131, 3944, - 4095, 3134, 3943, - 4095, 3137, 3942, - 4095, 3142, 3941, - 4095, 3147, 3940, - 4095, 3155, 3937, - 4095, 3165, 3934, - 4095, 3179, 3930, - 4095, 3196, 3925, - 4095, 3218, 3917, - 4095, 3246, 3907, - 4095, 3280, 3893, - 4095, 3323, 3874, - 4095, 3375, 3847, - 4095, 3435, 3808, - 4075, 3506, 3750, - 4019, 3586, 3659, - 3930, 3674, 3499, - 3775, 3771, 3120, - 4095, 3232, 4071, - 4095, 3232, 4071, - 4095, 3232, 4071, - 4095, 3232, 4071, - 4095, 3233, 4071, - 4095, 3233, 4071, - 4095, 3233, 4071, - 4095, 3233, 4071, - 4095, 3234, 4071, - 4095, 3234, 4071, - 4095, 3235, 4071, - 4095, 3236, 4070, - 4095, 3237, 4070, - 4095, 3238, 4070, - 4095, 3240, 4069, - 4095, 3243, 4069, - 4095, 3246, 4068, - 4095, 3251, 4066, - 4095, 3257, 4065, - 4095, 3265, 4062, - 4095, 3276, 4059, - 4095, 3290, 4055, - 4095, 3308, 4050, - 4095, 3331, 4042, - 4095, 3360, 4032, - 4095, 3396, 4018, - 4095, 3440, 3998, - 4095, 3493, 3971, - 4095, 3556, 3931, - 4095, 3628, 3872, - 4095, 3709, 3778, - 4065, 3799, 3612, - 0, 2525, 2793, - 0, 2525, 2793, - 0, 2525, 2793, - 0, 2525, 2793, - 0, 2526, 2792, - 0, 2527, 2792, - 0, 2528, 2791, - 0, 2529, 2790, - 0, 2531, 2788, - 0, 2533, 2786, - 0, 2536, 2783, - 0, 2540, 2779, - 0, 2545, 2774, - 0, 2552, 2768, - 0, 2561, 2758, - 0, 2572, 2746, - 0, 2588, 2728, - 0, 2607, 2704, - 0, 2632, 2668, - 0, 2664, 2617, - 0, 2703, 2537, - 0, 2750, 2402, - 0, 2807, 2121, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3445, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2525, 2794, - 0, 2525, 2794, - 0, 2525, 2793, - 0, 2526, 2793, - 0, 2526, 2792, - 0, 2527, 2792, - 0, 2528, 2791, - 0, 2529, 2790, - 0, 2531, 2788, - 0, 2533, 2786, - 0, 2536, 2783, - 0, 2540, 2780, - 0, 2545, 2775, - 0, 2552, 2768, - 0, 2561, 2759, - 0, 2573, 2746, - 0, 2588, 2728, - 0, 2607, 2704, - 0, 2632, 2669, - 0, 2664, 2617, - 0, 2703, 2538, - 0, 2750, 2403, - 0, 2807, 2123, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2525, 2794, - 0, 2525, 2794, - 0, 2525, 2794, - 0, 2526, 2793, - 0, 2526, 2793, - 0, 2527, 2792, - 0, 2528, 2791, - 0, 2529, 2790, - 0, 2531, 2789, - 0, 2533, 2787, - 0, 2536, 2784, - 0, 2540, 2780, - 0, 2545, 2775, - 0, 2552, 2768, - 0, 2561, 2759, - 0, 2573, 2746, - 0, 2588, 2729, - 0, 2608, 2704, - 0, 2633, 2669, - 0, 2664, 2618, - 0, 2703, 2538, - 0, 2750, 2404, - 0, 2807, 2124, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2525, 2795, - 0, 2525, 2794, - 0, 2525, 2794, - 0, 2526, 2794, - 0, 2526, 2793, - 0, 2527, 2793, - 0, 2528, 2792, - 0, 2529, 2791, - 0, 2531, 2789, - 0, 2533, 2787, - 0, 2536, 2784, - 0, 2540, 2781, - 0, 2545, 2776, - 0, 2552, 2769, - 0, 2561, 2760, - 0, 2573, 2747, - 0, 2588, 2730, - 0, 2608, 2705, - 0, 2633, 2670, - 0, 2664, 2619, - 0, 2703, 2539, - 0, 2750, 2405, - 0, 2807, 2127, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2525, 2795, - 0, 2525, 2795, - 0, 2526, 2795, - 0, 2526, 2795, - 0, 2526, 2794, - 0, 2527, 2793, - 0, 2528, 2793, - 0, 2529, 2791, - 0, 2531, 2790, - 0, 2533, 2788, - 0, 2536, 2785, - 0, 2540, 2781, - 0, 2545, 2776, - 0, 2552, 2770, - 0, 2561, 2760, - 0, 2573, 2748, - 0, 2588, 2730, - 0, 2608, 2706, - 0, 2633, 2671, - 0, 2664, 2620, - 0, 2703, 2540, - 0, 2750, 2407, - 0, 2807, 2130, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2525, 2796, - 0, 2526, 2796, - 0, 2526, 2796, - 0, 2526, 2795, - 0, 2527, 2795, - 0, 2527, 2794, - 0, 2528, 2794, - 0, 2530, 2792, - 0, 2531, 2791, - 0, 2533, 2789, - 0, 2536, 2786, - 0, 2540, 2782, - 0, 2546, 2777, - 0, 2552, 2771, - 0, 2561, 2761, - 0, 2573, 2749, - 0, 2588, 2731, - 0, 2608, 2707, - 0, 2633, 2672, - 0, 2664, 2621, - 0, 2703, 2542, - 0, 2751, 2409, - 0, 2807, 2134, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2526, 2798, - 0, 2526, 2797, - 0, 2526, 2797, - 0, 2527, 2797, - 0, 2527, 2796, - 0, 2528, 2796, - 0, 2529, 2795, - 0, 2530, 2794, - 0, 2532, 2792, - 0, 2534, 2790, - 0, 2537, 2787, - 0, 2541, 2784, - 0, 2546, 2779, - 0, 2553, 2772, - 0, 2562, 2763, - 0, 2573, 2750, - 0, 2589, 2733, - 0, 2608, 2709, - 0, 2633, 2674, - 0, 2665, 2623, - 0, 2703, 2544, - 0, 2751, 2412, - 0, 2807, 2139, - 0, 2873, 0, - 0, 2948, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2526, 2799, - 0, 2526, 2799, - 0, 2527, 2799, - 0, 2527, 2798, - 0, 2527, 2798, - 0, 2528, 2797, - 0, 2529, 2797, - 0, 2530, 2795, - 0, 2532, 2794, - 0, 2534, 2792, - 0, 2537, 2789, - 0, 2541, 2785, - 0, 2546, 2780, - 0, 2553, 2774, - 0, 2562, 2765, - 0, 2574, 2752, - 0, 2589, 2735, - 0, 2609, 2711, - 0, 2634, 2676, - 0, 2665, 2625, - 0, 2704, 2547, - 0, 2751, 2416, - 0, 2807, 2146, - 0, 2873, 0, - 0, 2949, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3226, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2527, 2801, - 0, 2527, 2801, - 0, 2527, 2801, - 0, 2528, 2801, - 0, 2528, 2800, - 0, 2529, 2800, - 0, 2530, 2799, - 0, 2531, 2798, - 0, 2533, 2796, - 0, 2535, 2794, - 0, 2538, 2791, - 0, 2542, 2788, - 0, 2547, 2783, - 0, 2554, 2776, - 0, 2563, 2767, - 0, 2574, 2755, - 0, 2590, 2737, - 0, 2609, 2713, - 0, 2634, 2679, - 0, 2665, 2629, - 0, 2704, 2551, - 0, 2751, 2421, - 0, 2808, 2156, - 0, 2873, 0, - 0, 2949, 0, - 0, 3033, 0, - 0, 3126, 0, - 0, 3227, 0, - 0, 3333, 0, - 0, 3446, 0, - 0, 3562, 0, - 0, 3683, 0, - 0, 2527, 2804, - 0, 2528, 2804, - 0, 2528, 2804, - 0, 2528, 2804, - 0, 2529, 2803, - 0, 2529, 2803, - 0, 2530, 2802, - 0, 2532, 2801, - 0, 2533, 2799, - 0, 2536, 2797, - 0, 2538, 2794, - 0, 2542, 2791, - 0, 2548, 2786, - 0, 2554, 2779, - 0, 2563, 2770, - 0, 2575, 2758, - 0, 2590, 2741, - 0, 2610, 2717, - 0, 2635, 2683, - 0, 2666, 2633, - 0, 2705, 2556, - 0, 2752, 2428, - 0, 2808, 2168, - 0, 2874, 0, - 0, 2949, 0, - 0, 3034, 0, - 0, 3126, 0, - 0, 3227, 0, - 0, 3334, 0, - 0, 3446, 0, - 0, 3563, 0, - 0, 3683, 0, - 0, 2528, 2808, - 0, 2529, 2808, - 0, 2529, 2808, - 0, 2529, 2808, - 0, 2530, 2807, - 0, 2531, 2807, - 0, 2531, 2806, - 0, 2533, 2805, - 0, 2534, 2803, - 0, 2537, 2801, - 0, 2539, 2799, - 0, 2543, 2795, - 0, 2549, 2790, - 0, 2555, 2783, - 0, 2564, 2775, - 0, 2576, 2762, - 0, 2591, 2745, - 0, 2611, 2722, - 0, 2635, 2688, - 0, 2667, 2639, - 0, 2705, 2563, - 0, 2752, 2437, - 0, 2809, 2184, - 0, 2874, 0, - 0, 2949, 0, - 0, 3034, 0, - 0, 3127, 0, - 0, 3227, 0, - 0, 3334, 0, - 0, 3446, 0, - 0, 3563, 0, - 0, 3683, 0, - 0, 2530, 2814, - 0, 2530, 2813, - 0, 2530, 2813, - 0, 2531, 2813, - 0, 2531, 2812, - 0, 2532, 2812, - 0, 2533, 2811, - 0, 2534, 2810, - 0, 2536, 2808, - 0, 2538, 2806, - 0, 2541, 2804, - 0, 2545, 2800, - 0, 2550, 2795, - 0, 2557, 2789, - 0, 2565, 2780, - 0, 2577, 2768, - 0, 2592, 2751, - 0, 2612, 2728, - 0, 2636, 2695, - 0, 2668, 2646, - 0, 2706, 2572, - 0, 2753, 2449, - 0, 2809, 2204, - 0, 2875, 806, - 0, 2950, 0, - 0, 3034, 0, - 0, 3127, 0, - 0, 3227, 0, - 0, 3334, 0, - 0, 3446, 0, - 0, 3563, 0, - 0, 3683, 0, - 0, 2532, 2821, - 0, 2532, 2820, - 0, 2532, 2820, - 0, 2532, 2820, - 0, 2533, 2819, - 0, 2534, 2819, - 0, 2535, 2818, - 0, 2536, 2817, - 0, 2537, 2815, - 0, 2540, 2814, - 0, 2543, 2811, - 0, 2546, 2807, - 0, 2552, 2803, - 0, 2558, 2796, - 0, 2567, 2788, - 0, 2579, 2776, - 0, 2594, 2759, - 0, 2613, 2736, - 0, 2638, 2704, - 0, 2669, 2656, - 0, 2708, 2584, - 0, 2754, 2464, - 0, 2810, 2230, - 0, 2876, 1179, - 0, 2951, 0, - 0, 3035, 0, - 0, 3128, 0, - 0, 3228, 0, - 0, 3334, 0, - 0, 3446, 0, - 0, 3563, 0, - 0, 3683, 0, - 0, 2534, 2830, - 0, 2534, 2829, - 0, 2534, 2829, - 0, 2535, 2829, - 0, 2535, 2828, - 0, 2536, 2828, - 0, 2537, 2827, - 0, 2538, 2826, - 0, 2540, 2825, - 0, 2542, 2823, - 0, 2545, 2820, - 0, 2549, 2817, - 0, 2554, 2812, - 0, 2561, 2806, - 0, 2569, 2797, - 0, 2581, 2786, - 0, 2596, 2770, - 0, 2615, 2747, - 0, 2640, 2716, - 0, 2671, 2669, - 0, 2709, 2599, - 0, 2756, 2484, - 0, 2812, 2263, - 0, 2877, 1432, - 0, 2952, 0, - 0, 3036, 0, - 0, 3128, 0, - 0, 3228, 0, - 0, 3335, 0, - 0, 3447, 0, - 0, 3563, 0, - 0, 3683, 0, - 0, 2537, 2842, - 0, 2537, 2841, - 0, 2538, 2841, - 0, 2538, 2841, - 0, 2539, 2840, - 0, 2539, 2840, - 0, 2540, 2839, - 0, 2541, 2838, - 0, 2543, 2837, - 0, 2545, 2835, - 0, 2548, 2832, - 0, 2552, 2829, - 0, 2557, 2824, - 0, 2564, 2818, - 0, 2572, 2810, - 0, 2584, 2799, - 0, 2599, 2783, - 0, 2618, 2761, - 0, 2642, 2731, - 0, 2673, 2686, - 0, 2711, 2618, - 0, 2758, 2509, - 0, 2813, 2303, - 0, 2878, 1638, - 0, 2953, 0, - 0, 3037, 0, - 0, 3129, 0, - 0, 3229, 0, - 0, 3335, 0, - 0, 3447, 0, - 0, 3564, 0, - 0, 3684, 0, - 0, 2541, 2857, - 0, 2542, 2857, - 0, 2542, 2857, - 0, 2542, 2856, - 0, 2543, 2856, - 0, 2543, 2855, - 0, 2544, 2854, - 0, 2546, 2854, - 0, 2547, 2852, - 0, 2549, 2850, - 0, 2552, 2848, - 0, 2556, 2845, - 0, 2561, 2840, - 0, 2568, 2835, - 0, 2576, 2827, - 0, 2588, 2816, - 0, 2602, 2801, - 0, 2621, 2780, - 0, 2646, 2750, - 0, 2676, 2708, - 0, 2714, 2643, - 0, 2760, 2540, - 0, 2816, 2351, - 0, 2880, 1818, - 0, 2955, 0, - 0, 3038, 0, - 0, 3130, 0, - 0, 3230, 0, - 0, 3336, 0, - 0, 3448, 0, - 0, 3564, 0, - 0, 3684, 0, - 0, 2547, 2877, - 0, 2547, 2877, - 0, 2547, 2876, - 0, 2548, 2876, - 0, 2548, 2876, - 0, 2549, 2875, - 0, 2550, 2874, - 0, 2551, 2873, - 0, 2553, 2872, - 0, 2555, 2870, - 0, 2558, 2868, - 0, 2561, 2865, - 0, 2566, 2861, - 0, 2573, 2855, - 0, 2581, 2848, - 0, 2593, 2837, - 0, 2607, 2823, - 0, 2626, 2803, - 0, 2650, 2775, - 0, 2680, 2735, - 0, 2718, 2675, - 0, 2764, 2579, - 0, 2819, 2409, - 0, 2883, 1983, - 0, 2957, 0, - 0, 3040, 0, - 0, 3132, 0, - 0, 3231, 0, - 0, 3337, 0, - 0, 3449, 0, - 0, 3565, 0, - 0, 3684, 0, - 1040, 2554, 2902, - 1028, 2555, 2902, - 1011, 2555, 2902, - 986, 2555, 2901, - 952, 2556, 2901, - 901, 2556, 2900, - 823, 2557, 2900, - 692, 2558, 2899, - 422, 2560, 2898, - 0, 2562, 2896, - 0, 2565, 2894, - 0, 2569, 2891, - 0, 2573, 2887, - 0, 2580, 2882, - 0, 2588, 2875, - 0, 2599, 2865, - 0, 2614, 2851, - 0, 2632, 2833, - 0, 2656, 2806, - 0, 2686, 2769, - 0, 2723, 2713, - 0, 2768, 2627, - 0, 2823, 2476, - 0, 2887, 2139, - 0, 2960, 0, - 0, 3043, 0, - 0, 3134, 0, - 0, 3233, 0, - 0, 3338, 0, - 0, 3450, 0, - 0, 3565, 0, - 0, 3685, 0, - 2058, 2564, 2934, - 2057, 2564, 2933, - 2055, 2565, 2933, - 2053, 2565, 2933, - 2050, 2565, 2933, - 2045, 2566, 2932, - 2039, 2567, 2932, - 2032, 2568, 2931, - 2021, 2570, 2930, - 2006, 2572, 2928, - 1985, 2574, 2926, - 1956, 2578, 2923, - 1914, 2583, 2920, - 1850, 2589, 2915, - 1749, 2597, 2908, - 1564, 2608, 2899, - 1057, 2622, 2887, - 0, 2641, 2869, - 0, 2664, 2845, - 0, 2693, 2811, - 0, 2730, 2761, - 0, 2775, 2683, - 0, 2828, 2553, - 0, 2891, 2287, - 0, 2964, 0, - 0, 3046, 0, - 0, 3137, 0, - 0, 3235, 0, - 0, 3340, 0, - 0, 3451, 0, - 0, 3566, 0, - 0, 3686, 0, - 2415, 2577, 2973, - 2415, 2577, 2973, - 2414, 2577, 2972, - 2413, 2578, 2972, - 2412, 2578, 2972, - 2410, 2579, 2971, - 2407, 2580, 2971, - 2404, 2581, 2970, - 2399, 2582, 2969, - 2392, 2584, 2968, - 2384, 2587, 2966, - 2372, 2590, 2963, - 2355, 2595, 2960, - 2332, 2601, 2956, - 2300, 2609, 2949, - 2252, 2620, 2941, - 2179, 2633, 2930, - 2059, 2651, 2914, - 1824, 2674, 2892, - 744, 2703, 2862, - 0, 2739, 2817, - 0, 2783, 2749, - 0, 2835, 2639, - 0, 2898, 2431, - 0, 2969, 1756, - 0, 3050, 0, - 0, 3140, 0, - 0, 3238, 0, - 0, 3342, 0, - 0, 3453, 0, - 0, 3568, 0, - 0, 3687, 0, - 2664, 2593, 3020, - 2664, 2593, 3020, - 2663, 2594, 3020, - 2663, 2594, 3020, - 2662, 2594, 3020, - 2661, 2595, 3019, - 2659, 2596, 3019, - 2657, 2597, 3018, - 2654, 2598, 3017, - 2651, 2600, 3016, - 2646, 2603, 3014, - 2639, 2606, 3012, - 2630, 2611, 3009, - 2618, 2617, 3005, - 2601, 2624, 2999, - 2577, 2635, 2992, - 2543, 2648, 2982, - 2493, 2665, 2968, - 2416, 2687, 2949, - 2287, 2715, 2922, - 2025, 2750, 2883, - 0, 2793, 2824, - 0, 2845, 2733, - 0, 2906, 2572, - 0, 2976, 2191, - 0, 3056, 0, - 0, 3145, 0, - 0, 3242, 0, - 0, 3345, 0, - 0, 3455, 0, - 0, 3570, 0, - 0, 3688, 0, - 2867, 2614, 3077, - 2867, 2614, 3077, - 2867, 2615, 3077, - 2866, 2615, 3077, - 2866, 2615, 3076, - 2865, 2616, 3076, - 2864, 2617, 3076, - 2863, 2618, 3075, - 2861, 2619, 3074, - 2859, 2621, 3073, - 2856, 2623, 3072, - 2851, 2627, 3070, - 2846, 2631, 3067, - 2838, 2637, 3063, - 2828, 2644, 3059, - 2813, 2654, 3052, - 2793, 2667, 3043, - 2765, 2683, 3031, - 2724, 2705, 3014, - 2664, 2731, 2991, - 2567, 2765, 2958, - 2395, 2807, 2909, - 1957, 2857, 2835, - 0, 2916, 2711, - 0, 2985, 2465, - 0, 3064, 979, - 0, 3151, 0, - 0, 3247, 0, - 0, 3350, 0, - 0, 3458, 0, - 0, 3572, 0, - 0, 3690, 0, - 3046, 2641, 3143, - 3046, 2641, 3143, - 3046, 2641, 3143, - 3045, 2642, 3143, - 3045, 2642, 3143, - 3044, 2643, 3142, - 3044, 2643, 3142, - 3043, 2644, 3142, - 3042, 2646, 3141, - 3040, 2647, 3140, - 3038, 2650, 3139, - 3035, 2653, 3137, - 3032, 2657, 3135, - 3027, 2662, 3132, - 3020, 2669, 3127, - 3010, 2678, 3122, - 2997, 2691, 3114, - 2980, 2706, 3104, - 2955, 2727, 3090, - 2919, 2752, 3070, - 2867, 2785, 3042, - 2786, 2824, 3002, - 2648, 2873, 2942, - 2356, 2930, 2848, - 0, 2997, 2679, - 0, 3074, 2263, - 0, 3160, 0, - 0, 3254, 0, - 0, 3355, 0, - 0, 3463, 0, - 0, 3576, 0, - 0, 3693, 0, - 3210, 2674, 3219, - 3210, 2674, 3219, - 3210, 2675, 3219, - 3210, 2675, 3219, - 3209, 2675, 3219, - 3209, 2676, 3218, - 3209, 2677, 3218, - 3208, 2677, 3218, - 3207, 2679, 3217, - 3206, 2680, 3216, - 3205, 2682, 3215, - 3203, 2685, 3214, - 3200, 2689, 3212, - 3197, 2694, 3209, - 3192, 2701, 3206, - 3185, 2709, 3201, - 3177, 2721, 3195, - 3165, 2735, 3186, - 3148, 2754, 3174, - 3126, 2779, 3158, - 3093, 2809, 3135, - 3045, 2847, 3103, - 2973, 2893, 3055, - 2853, 2948, 2983, - 2618, 3013, 2865, - 1555, 3087, 2634, - 0, 3171, 1643, - 0, 3263, 0, - 0, 3362, 0, - 0, 3468, 0, - 0, 3580, 0, - 0, 3696, 0, - 3365, 2716, 3304, - 3365, 2716, 3304, - 3364, 2716, 3304, - 3364, 2716, 3304, - 3364, 2716, 3304, - 3364, 2717, 3303, - 3364, 2718, 3303, - 3363, 2718, 3303, - 3363, 2719, 3302, - 3362, 2721, 3302, - 3361, 2723, 3301, - 3359, 2725, 3300, - 3358, 2729, 3298, - 3355, 2734, 3296, - 3352, 2740, 3293, - 3347, 2748, 3289, - 3341, 2758, 3284, - 3333, 2772, 3277, - 3322, 2789, 3267, - 3306, 2812, 3254, - 3285, 2840, 3235, - 3254, 2876, 3210, - 3209, 2919, 3173, - 3142, 2971, 3118, - 3033, 3033, 3033, - 2828, 3104, 2887, - 2176, 3185, 2564, - 0, 3274, 0, - 0, 3372, 0, - 0, 3476, 0, - 0, 3586, 0, - 0, 3701, 0, - 3513, 2765, 3397, - 3513, 2765, 3397, - 3513, 2766, 3397, - 3513, 2766, 3397, - 3513, 2766, 3397, - 3512, 2767, 3397, - 3512, 2767, 3397, - 3512, 2768, 3396, - 3511, 2769, 3396, - 3511, 2770, 3395, - 3510, 2772, 3395, - 3509, 2774, 3394, - 3508, 2777, 3392, - 3506, 2781, 3391, - 3504, 2787, 3388, - 3500, 2794, 3385, - 3496, 2804, 3381, - 3490, 2816, 3375, - 3482, 2832, 3367, - 3471, 2852, 3357, - 3457, 2878, 3342, - 3436, 2911, 3322, - 3406, 2951, 3293, - 3364, 3000, 3252, - 3300, 3058, 3190, - 3198, 3126, 3092, - 3011, 3203, 2914, - 2491, 3289, 2450, - 0, 3384, 0, - 0, 3486, 0, - 0, 3594, 0, - 0, 3707, 0, - 3657, 2824, 3498, - 3657, 2824, 3498, - 3657, 2825, 3498, - 3657, 2825, 3498, - 3656, 2825, 3498, - 3656, 2825, 3498, - 3656, 2826, 3497, - 3656, 2827, 3497, - 3656, 2827, 3497, - 3655, 2829, 3497, - 3655, 2830, 3496, - 3654, 2832, 3495, - 3653, 2835, 3494, - 3652, 2839, 3493, - 3650, 2843, 3491, - 3648, 2850, 3488, - 3645, 2858, 3485, - 3640, 2869, 3480, - 3635, 2883, 3474, - 3627, 2902, 3466, - 3616, 2925, 3454, - 3602, 2955, 3439, - 3582, 2992, 3417, - 3553, 3036, 3386, - 3512, 3090, 3340, - 3451, 3154, 3272, - 3353, 3227, 3160, - 3177, 3309, 2949, - 2723, 3400, 2233, - 0, 3498, 0, - 0, 3604, 0, - 0, 3715, 0, - 3797, 2893, 3605, - 3797, 2893, 3605, - 3797, 2893, 3605, - 3797, 2893, 3605, - 3797, 2894, 3605, - 3797, 2894, 3605, - 3797, 2894, 3605, - 3797, 2895, 3605, - 3797, 2896, 3604, - 3796, 2897, 3604, - 3796, 2898, 3604, - 3795, 2900, 3603, - 3795, 2902, 3602, - 3794, 2905, 3601, - 3792, 2909, 3600, - 3791, 2915, 3598, - 3788, 2922, 3595, - 3785, 2932, 3591, - 3781, 2944, 3587, - 3776, 2960, 3580, - 3768, 2981, 3571, - 3758, 3007, 3559, - 3744, 3040, 3542, - 3724, 3081, 3519, - 3696, 3130, 3486, - 3656, 3188, 3437, - 3596, 3256, 3362, - 3502, 3334, 3238, - 3333, 3420, 2991, - 2918, 3515, 1456, - 0, 3617, 0, - 0, 3725, 0, - 3936, 2971, 3718, - 3936, 2971, 3718, - 3936, 2971, 3718, - 3936, 2971, 3718, - 3936, 2972, 3718, - 3936, 2972, 3717, - 3935, 2972, 3717, - 3935, 2973, 3717, - 3935, 2973, 3717, - 3935, 2974, 3717, - 3935, 2975, 3716, - 3934, 2977, 3716, - 3934, 2979, 3715, - 3933, 2981, 3714, - 3932, 2985, 3713, - 3931, 2990, 3712, - 3929, 2996, 3710, - 3927, 3004, 3707, - 3924, 3015, 3703, - 3920, 3028, 3698, - 3914, 3046, 3691, - 3907, 3069, 3682, - 3897, 3098, 3669, - 3883, 3134, 3652, - 3863, 3178, 3627, - 3836, 3231, 3592, - 3797, 3293, 3540, - 3738, 3365, 3460, - 3646, 3446, 3325, - 3483, 3536, 3042, - 3092, 3634, 0, - 0, 3738, 0, - 4073, 3058, 3835, - 4073, 3058, 3835, - 4072, 3058, 3835, - 4072, 3058, 3835, - 4072, 3059, 3834, - 4072, 3059, 3834, - 4072, 3059, 3834, - 4072, 3059, 3834, - 4072, 3060, 3834, - 4072, 3061, 3834, - 4072, 3062, 3834, - 4071, 3063, 3833, - 4071, 3064, 3833, - 4071, 3067, 3832, - 4070, 3070, 3831, - 4069, 3073, 3830, - 4068, 3079, 3828, - 4066, 3085, 3826, - 4064, 3094, 3823, - 4061, 3106, 3820, - 4057, 3121, 3814, - 4051, 3140, 3807, - 4044, 3165, 3798, - 4034, 3196, 3784, - 4020, 3235, 3766, - 4001, 3282, 3741, - 3974, 3338, 3704, - 3935, 3404, 3650, - 3877, 3479, 3565, - 3787, 3563, 3420, - 3627, 3656, 3103, - 3253, 3756, 0, - 4095, 3153, 3955, - 4095, 3153, 3955, - 4095, 3153, 3955, - 4095, 3154, 3955, - 4095, 3154, 3955, - 4095, 3154, 3955, - 4095, 3154, 3955, - 4095, 3154, 3955, - 4095, 3155, 3955, - 4095, 3155, 3954, - 4095, 3156, 3954, - 4095, 3157, 3954, - 4095, 3159, 3954, - 4095, 3160, 3953, - 4095, 3163, 3952, - 4095, 3166, 3951, - 4095, 3170, 3950, - 4095, 3176, 3949, - 4095, 3183, 3946, - 4095, 3192, 3943, - 4095, 3205, 3940, - 4095, 3221, 3934, - 4095, 3242, 3927, - 4095, 3269, 3917, - 4095, 3302, 3903, - 4095, 3342, 3885, - 4095, 3392, 3858, - 4095, 3451, 3820, - 4072, 3519, 3764, - 4015, 3596, 3676, - 3925, 3683, 3522, - 3768, 3778, 3173, - 4095, 3256, 4078, - 4095, 3256, 4078, - 4095, 3256, 4078, - 4095, 3256, 4078, - 4095, 3256, 4078, - 4095, 3256, 4078, - 4095, 3256, 4078, - 4095, 3257, 4078, - 4095, 3257, 4078, - 4095, 3257, 4078, - 4095, 3258, 4078, - 4095, 3259, 4077, - 4095, 3260, 4077, - 4095, 3261, 4077, - 4095, 3263, 4076, - 4095, 3266, 4075, - 4095, 3269, 4075, - 4095, 3274, 4073, - 4095, 3280, 4072, - 4095, 3287, 4069, - 4095, 3297, 4066, - 4095, 3311, 4062, - 4095, 3328, 4057, - 4095, 3350, 4049, - 4095, 3378, 4039, - 4095, 3413, 4025, - 4095, 3455, 4006, - 4095, 3507, 3979, - 4095, 3567, 3940, - 4095, 3638, 3882, - 4095, 3718, 3791, - 4062, 3806, 3631, - 0, 2656, 2925, - 0, 2657, 2925, - 0, 2657, 2925, - 0, 2657, 2925, - 0, 2658, 2924, - 0, 2658, 2924, - 0, 2659, 2923, - 0, 2660, 2923, - 0, 2661, 2921, - 0, 2663, 2920, - 0, 2665, 2918, - 0, 2668, 2915, - 0, 2672, 2911, - 0, 2677, 2906, - 0, 2684, 2899, - 0, 2693, 2890, - 0, 2705, 2878, - 0, 2720, 2860, - 0, 2739, 2835, - 0, 2764, 2800, - 0, 2796, 2749, - 0, 2835, 2669, - 0, 2882, 2534, - 0, 2939, 2253, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2657, 2926, - 0, 2657, 2926, - 0, 2657, 2925, - 0, 2657, 2925, - 0, 2658, 2925, - 0, 2658, 2924, - 0, 2659, 2924, - 0, 2660, 2923, - 0, 2661, 2922, - 0, 2663, 2920, - 0, 2665, 2918, - 0, 2668, 2915, - 0, 2672, 2912, - 0, 2677, 2907, - 0, 2684, 2900, - 0, 2693, 2890, - 0, 2705, 2878, - 0, 2720, 2860, - 0, 2739, 2836, - 0, 2765, 2801, - 0, 2796, 2749, - 0, 2835, 2669, - 0, 2882, 2535, - 0, 2939, 2254, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2657, 2926, - 0, 2657, 2926, - 0, 2657, 2926, - 0, 2657, 2925, - 0, 2658, 2925, - 0, 2658, 2925, - 0, 2659, 2924, - 0, 2660, 2923, - 0, 2661, 2922, - 0, 2663, 2920, - 0, 2665, 2918, - 0, 2668, 2916, - 0, 2672, 2912, - 0, 2677, 2907, - 0, 2684, 2900, - 0, 2693, 2891, - 0, 2705, 2878, - 0, 2720, 2861, - 0, 2740, 2836, - 0, 2765, 2801, - 0, 2796, 2749, - 0, 2835, 2670, - 0, 2882, 2535, - 0, 2939, 2255, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2657, 2926, - 0, 2657, 2926, - 0, 2657, 2926, - 0, 2657, 2926, - 0, 2658, 2925, - 0, 2658, 2925, - 0, 2659, 2924, - 0, 2660, 2923, - 0, 2661, 2922, - 0, 2663, 2921, - 0, 2665, 2919, - 0, 2668, 2916, - 0, 2672, 2912, - 0, 2677, 2907, - 0, 2684, 2900, - 0, 2693, 2891, - 0, 2705, 2879, - 0, 2720, 2861, - 0, 2740, 2836, - 0, 2765, 2801, - 0, 2796, 2750, - 0, 2835, 2670, - 0, 2882, 2536, - 0, 2939, 2257, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2657, 2927, - 0, 2657, 2927, - 0, 2657, 2927, - 0, 2657, 2926, - 0, 2658, 2926, - 0, 2658, 2925, - 0, 2659, 2925, - 0, 2660, 2924, - 0, 2661, 2923, - 0, 2663, 2921, - 0, 2665, 2919, - 0, 2668, 2917, - 0, 2672, 2913, - 0, 2677, 2908, - 0, 2684, 2901, - 0, 2693, 2892, - 0, 2705, 2879, - 0, 2720, 2862, - 0, 2740, 2837, - 0, 2765, 2802, - 0, 2796, 2751, - 0, 2835, 2671, - 0, 2882, 2537, - 0, 2939, 2259, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2657, 2928, - 0, 2657, 2927, - 0, 2657, 2927, - 0, 2658, 2927, - 0, 2658, 2927, - 0, 2659, 2926, - 0, 2659, 2926, - 0, 2660, 2925, - 0, 2661, 2924, - 0, 2663, 2922, - 0, 2665, 2920, - 0, 2668, 2917, - 0, 2672, 2914, - 0, 2677, 2909, - 0, 2684, 2902, - 0, 2693, 2893, - 0, 2705, 2880, - 0, 2720, 2862, - 0, 2740, 2838, - 0, 2765, 2803, - 0, 2796, 2752, - 0, 2835, 2673, - 0, 2882, 2539, - 0, 2939, 2262, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2657, 2929, - 0, 2657, 2928, - 0, 2658, 2928, - 0, 2658, 2928, - 0, 2658, 2928, - 0, 2659, 2927, - 0, 2660, 2926, - 0, 2660, 2926, - 0, 2662, 2925, - 0, 2663, 2923, - 0, 2666, 2921, - 0, 2669, 2918, - 0, 2672, 2915, - 0, 2678, 2910, - 0, 2684, 2903, - 0, 2693, 2894, - 0, 2705, 2881, - 0, 2720, 2864, - 0, 2740, 2839, - 0, 2765, 2804, - 0, 2796, 2753, - 0, 2835, 2674, - 0, 2883, 2541, - 0, 2939, 2266, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2658, 2930, - 0, 2658, 2930, - 0, 2658, 2929, - 0, 2658, 2929, - 0, 2659, 2929, - 0, 2659, 2928, - 0, 2660, 2928, - 0, 2661, 2927, - 0, 2662, 2926, - 0, 2664, 2924, - 0, 2666, 2922, - 0, 2669, 2919, - 0, 2673, 2916, - 0, 2678, 2911, - 0, 2685, 2904, - 0, 2694, 2895, - 0, 2706, 2882, - 0, 2721, 2865, - 0, 2740, 2841, - 0, 2765, 2806, - 0, 2797, 2755, - 0, 2836, 2676, - 0, 2883, 2544, - 0, 2939, 2271, - 0, 3005, 0, - 0, 3080, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3358, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2658, 2931, - 0, 2658, 2931, - 0, 2658, 2931, - 0, 2659, 2931, - 0, 2659, 2931, - 0, 2660, 2930, - 0, 2660, 2929, - 0, 2661, 2929, - 0, 2662, 2927, - 0, 2664, 2926, - 0, 2666, 2924, - 0, 2669, 2921, - 0, 2673, 2918, - 0, 2678, 2913, - 0, 2685, 2906, - 0, 2694, 2897, - 0, 2706, 2884, - 0, 2721, 2867, - 0, 2741, 2843, - 0, 2766, 2808, - 0, 2797, 2757, - 0, 2836, 2679, - 0, 2883, 2548, - 0, 2939, 2279, - 0, 3005, 0, - 0, 3081, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3359, 0, - 0, 3465, 0, - 0, 3578, 0, - 0, 3694, 0, - 0, 2659, 2934, - 0, 2659, 2934, - 0, 2659, 2933, - 0, 2659, 2933, - 0, 2660, 2933, - 0, 2660, 2932, - 0, 2661, 2932, - 0, 2662, 2931, - 0, 2663, 2930, - 0, 2665, 2928, - 0, 2667, 2926, - 0, 2670, 2924, - 0, 2674, 2920, - 0, 2679, 2915, - 0, 2686, 2908, - 0, 2695, 2899, - 0, 2706, 2887, - 0, 2722, 2870, - 0, 2741, 2845, - 0, 2766, 2811, - 0, 2797, 2761, - 0, 2836, 2683, - 0, 2883, 2553, - 0, 2940, 2288, - 0, 3006, 0, - 0, 3081, 0, - 0, 3165, 0, - 0, 3258, 0, - 0, 3359, 0, - 0, 3466, 0, - 0, 3578, 0, - 0, 3695, 0, - 0, 2659, 2937, - 0, 2659, 2937, - 0, 2660, 2936, - 0, 2660, 2936, - 0, 2660, 2936, - 0, 2661, 2935, - 0, 2662, 2935, - 0, 2663, 2934, - 0, 2664, 2933, - 0, 2665, 2931, - 0, 2668, 2929, - 0, 2671, 2927, - 0, 2674, 2923, - 0, 2680, 2918, - 0, 2686, 2911, - 0, 2695, 2902, - 0, 2707, 2890, - 0, 2722, 2873, - 0, 2742, 2849, - 0, 2767, 2815, - 0, 2798, 2765, - 0, 2837, 2688, - 0, 2884, 2560, - 0, 2940, 2300, - 0, 3006, 0, - 0, 3081, 0, - 0, 3166, 0, - 0, 3258, 0, - 0, 3359, 0, - 0, 3466, 0, - 0, 3578, 0, - 0, 3695, 0, - 0, 2660, 2941, - 0, 2660, 2941, - 0, 2661, 2940, - 0, 2661, 2940, - 0, 2661, 2940, - 0, 2662, 2939, - 0, 2663, 2939, - 0, 2664, 2938, - 0, 2665, 2937, - 0, 2666, 2935, - 0, 2669, 2933, - 0, 2672, 2931, - 0, 2675, 2927, - 0, 2681, 2922, - 0, 2687, 2916, - 0, 2696, 2907, - 0, 2708, 2894, - 0, 2723, 2877, - 0, 2743, 2854, - 0, 2768, 2820, - 0, 2799, 2771, - 0, 2837, 2695, - 0, 2885, 2569, - 0, 2941, 2316, - 0, 3006, 0, - 0, 3082, 0, - 0, 3166, 0, - 0, 3259, 0, - 0, 3359, 0, - 0, 3466, 0, - 0, 3578, 0, - 0, 3695, 0, - 0, 2662, 2946, - 0, 2662, 2946, - 0, 2662, 2946, - 0, 2662, 2945, - 0, 2663, 2945, - 0, 2663, 2945, - 0, 2664, 2944, - 0, 2665, 2943, - 0, 2666, 2942, - 0, 2668, 2941, - 0, 2670, 2939, - 0, 2673, 2936, - 0, 2677, 2932, - 0, 2682, 2928, - 0, 2689, 2921, - 0, 2698, 2912, - 0, 2709, 2900, - 0, 2724, 2883, - 0, 2744, 2860, - 0, 2769, 2827, - 0, 2800, 2778, - 0, 2838, 2704, - 0, 2885, 2581, - 0, 2941, 2336, - 0, 3007, 938, - 0, 3082, 0, - 0, 3166, 0, - 0, 3259, 0, - 0, 3359, 0, - 0, 3466, 0, - 0, 3578, 0, - 0, 3695, 0, - 0, 2663, 2953, - 0, 2664, 2953, - 0, 2664, 2952, - 0, 2664, 2952, - 0, 2665, 2952, - 0, 2665, 2951, - 0, 2666, 2951, - 0, 2667, 2950, - 0, 2668, 2949, - 0, 2670, 2948, - 0, 2672, 2946, - 0, 2675, 2943, - 0, 2679, 2940, - 0, 2684, 2935, - 0, 2690, 2928, - 0, 2699, 2920, - 0, 2711, 2908, - 0, 2726, 2891, - 0, 2745, 2868, - 0, 2770, 2836, - 0, 2801, 2788, - 0, 2840, 2716, - 0, 2886, 2596, - 0, 2942, 2362, - 0, 3008, 1311, - 0, 3083, 0, - 0, 3167, 0, - 0, 3260, 0, - 0, 3360, 0, - 0, 3466, 0, - 0, 3579, 0, - 0, 3695, 0, - 0, 2666, 2962, - 0, 2666, 2962, - 0, 2666, 2962, - 0, 2667, 2961, - 0, 2667, 2961, - 0, 2667, 2961, - 0, 2668, 2960, - 0, 2669, 2959, - 0, 2670, 2958, - 0, 2672, 2957, - 0, 2674, 2955, - 0, 2677, 2952, - 0, 2681, 2949, - 0, 2686, 2944, - 0, 2693, 2938, - 0, 2701, 2929, - 0, 2713, 2918, - 0, 2728, 2902, - 0, 2747, 2879, - 0, 2772, 2848, - 0, 2803, 2801, - 0, 2841, 2731, - 0, 2888, 2616, - 0, 2944, 2395, - 0, 3009, 1565, - 0, 3084, 0, - 0, 3168, 0, - 0, 3260, 0, - 0, 3360, 0, - 0, 3467, 0, - 0, 3579, 0, - 0, 3695, 0, - 0, 2669, 2974, - 0, 2669, 2974, - 0, 2669, 2973, - 0, 2670, 2973, - 0, 2670, 2973, - 0, 2671, 2972, - 0, 2671, 2972, - 0, 2672, 2971, - 0, 2673, 2970, - 0, 2675, 2969, - 0, 2677, 2967, - 0, 2680, 2964, - 0, 2684, 2961, - 0, 2689, 2957, - 0, 2696, 2950, - 0, 2704, 2942, - 0, 2716, 2931, - 0, 2731, 2915, - 0, 2750, 2894, - 0, 2774, 2863, - 0, 2805, 2818, - 0, 2843, 2751, - 0, 2890, 2641, - 0, 2945, 2435, - 0, 3010, 1770, - 0, 3085, 0, - 0, 3169, 0, - 0, 3261, 0, - 0, 3361, 0, - 0, 3467, 0, - 0, 3579, 0, - 0, 3696, 0, - 0, 2673, 2989, - 0, 2673, 2989, - 0, 2674, 2989, - 0, 2674, 2989, - 0, 2674, 2988, - 0, 2675, 2988, - 0, 2676, 2987, - 0, 2676, 2987, - 0, 2678, 2986, - 0, 2679, 2984, - 0, 2681, 2982, - 0, 2684, 2980, - 0, 2688, 2977, - 0, 2693, 2973, - 0, 2700, 2967, - 0, 2708, 2959, - 0, 2720, 2948, - 0, 2735, 2933, - 0, 2754, 2912, - 0, 2778, 2882, - 0, 2808, 2840, - 0, 2846, 2775, - 0, 2893, 2672, - 0, 2948, 2483, - 0, 3013, 1950, - 0, 3087, 0, - 0, 3170, 0, - 0, 3262, 0, - 0, 3362, 0, - 0, 3468, 0, - 0, 3580, 0, - 0, 3696, 0, - 0, 2679, 3009, - 0, 2679, 3009, - 0, 2679, 3009, - 0, 2680, 3008, - 0, 2680, 3008, - 0, 2680, 3008, - 0, 2681, 3007, - 0, 2682, 3007, - 0, 2683, 3006, - 0, 2685, 3004, - 0, 2687, 3003, - 0, 2690, 3000, - 0, 2693, 2997, - 0, 2698, 2993, - 0, 2705, 2987, - 0, 2714, 2980, - 0, 2725, 2969, - 0, 2739, 2955, - 0, 2758, 2935, - 0, 2782, 2907, - 0, 2813, 2867, - 0, 2850, 2807, - 0, 2896, 2711, - 0, 2951, 2541, - 0, 3015, 2115, - 0, 3089, 0, - 0, 3172, 0, - 0, 3264, 0, - 0, 3363, 0, - 0, 3469, 0, - 0, 3581, 0, - 0, 3697, 0, - 1182, 2686, 3034, - 1173, 2686, 3034, - 1160, 2687, 3034, - 1143, 2687, 3034, - 1119, 2687, 3033, - 1084, 2688, 3033, - 1033, 2688, 3033, - 955, 2689, 3032, - 824, 2691, 3031, - 554, 2692, 3030, - 0, 2694, 3028, - 0, 2697, 3026, - 0, 2701, 3023, - 0, 2706, 3019, - 0, 2712, 3014, - 0, 2720, 3007, - 0, 2731, 2997, - 0, 2746, 2983, - 0, 2764, 2965, - 0, 2788, 2939, - 0, 2818, 2901, - 0, 2855, 2846, - 0, 2901, 2759, - 0, 2955, 2608, - 0, 3019, 2271, - 0, 3092, 0, - 0, 3175, 0, - 0, 3266, 0, - 0, 3365, 0, - 0, 3470, 0, - 0, 3582, 0, - 0, 3697, 0, - 2191, 2696, 3066, - 2190, 2696, 3066, - 2189, 2696, 3066, - 2187, 2697, 3065, - 2185, 2697, 3065, - 2182, 2698, 3065, - 2177, 2698, 3064, - 2172, 2699, 3064, - 2164, 2700, 3063, - 2153, 2702, 3062, - 2138, 2704, 3060, - 2117, 2706, 3058, - 2088, 2710, 3055, - 2046, 2715, 3052, - 1983, 2721, 3047, - 1881, 2729, 3040, - 1696, 2740, 3031, - 1189, 2754, 3019, - 0, 2773, 3001, - 0, 2796, 2977, - 0, 2825, 2943, - 0, 2862, 2893, - 0, 2907, 2815, - 0, 2960, 2685, - 0, 3023, 2419, - 0, 3096, 0, - 0, 3178, 0, - 0, 3269, 0, - 0, 3367, 0, - 0, 3472, 0, - 0, 3583, 0, - 0, 3699, 0, - 2548, 2709, 3105, - 2548, 2709, 3105, - 2547, 2709, 3105, - 2546, 2709, 3105, - 2545, 2710, 3104, - 2544, 2710, 3104, - 2542, 2711, 3104, - 2539, 2712, 3103, - 2536, 2713, 3102, - 2531, 2714, 3101, - 2524, 2716, 3100, - 2516, 2719, 3098, - 2504, 2722, 3095, - 2487, 2727, 3092, - 2464, 2733, 3088, - 2432, 2741, 3082, - 2384, 2752, 3073, - 2311, 2766, 3062, - 2191, 2783, 3046, - 1956, 2806, 3025, - 876, 2835, 2994, - 0, 2871, 2949, - 0, 2915, 2881, - 0, 2967, 2771, - 0, 3030, 2564, - 0, 3101, 1888, - 0, 3182, 0, - 0, 3272, 0, - 0, 3370, 0, - 0, 3474, 0, - 0, 3585, 0, - 0, 3700, 0, - 2796, 2725, 3153, - 2796, 2725, 3152, - 2796, 2725, 3152, - 2795, 2726, 3152, - 2795, 2726, 3152, - 2794, 2726, 3152, - 2793, 2727, 3151, - 2791, 2728, 3151, - 2789, 2729, 3150, - 2787, 2730, 3149, - 2783, 2732, 3148, - 2778, 2735, 3146, - 2771, 2738, 3144, - 2762, 2743, 3141, - 2750, 2749, 3137, - 2733, 2756, 3131, - 2709, 2767, 3124, - 2675, 2780, 3114, - 2625, 2797, 3100, - 2548, 2819, 3081, - 2419, 2847, 3054, - 2157, 2882, 3015, - 0, 2925, 2957, - 0, 2977, 2865, - 0, 3038, 2704, - 0, 3108, 2323, - 0, 3188, 0, - 0, 3277, 0, - 0, 3374, 0, - 0, 3478, 0, - 0, 3587, 0, - 0, 3702, 0, - 2999, 2746, 3209, - 2999, 2746, 3209, - 2999, 2746, 3209, - 2999, 2747, 3209, - 2998, 2747, 3209, - 2998, 2747, 3209, - 2997, 2748, 3208, - 2996, 2749, 3208, - 2995, 2750, 3207, - 2993, 2751, 3206, - 2991, 2753, 3205, - 2988, 2755, 3204, - 2984, 2759, 3202, - 2978, 2763, 3199, - 2970, 2769, 3196, - 2960, 2776, 3191, - 2945, 2786, 3184, - 2925, 2799, 3175, - 2897, 2815, 3163, - 2857, 2837, 3147, - 2796, 2864, 3123, - 2699, 2897, 3090, - 2527, 2939, 3041, - 2089, 2989, 2967, - 0, 3048, 2843, - 0, 3118, 2597, - 0, 3196, 1111, - 0, 3283, 0, - 0, 3379, 0, - 0, 3482, 0, - 0, 3590, 0, - 0, 3704, 0, - 3178, 2773, 3276, - 3178, 2773, 3275, - 3178, 2773, 3275, - 3178, 2773, 3275, - 3177, 2774, 3275, - 3177, 2774, 3275, - 3177, 2775, 3275, - 3176, 2775, 3274, - 3175, 2776, 3274, - 3174, 2778, 3273, - 3172, 2779, 3272, - 3170, 2782, 3271, - 3167, 2785, 3269, - 3164, 2789, 3267, - 3159, 2794, 3264, - 3152, 2801, 3260, - 3142, 2811, 3254, - 3130, 2823, 3246, - 3112, 2838, 3236, - 3087, 2859, 3222, - 3051, 2884, 3202, - 2999, 2917, 3174, - 2918, 2956, 3134, - 2780, 3005, 3074, - 2488, 3062, 2980, - 0, 3130, 2811, - 0, 3206, 2395, - 0, 3292, 0, - 0, 3386, 0, - 0, 3487, 0, - 0, 3595, 0, - 0, 3708, 0, - 3342, 2806, 3351, - 3342, 2806, 3351, - 3342, 2807, 3351, - 3342, 2807, 3351, - 3342, 2807, 3351, - 3341, 2807, 3351, - 3341, 2808, 3350, - 3341, 2809, 3350, - 3340, 2810, 3350, - 3339, 2811, 3349, - 3338, 2812, 3348, - 3337, 2814, 3347, - 3335, 2817, 3346, - 3332, 2821, 3344, - 3329, 2826, 3341, - 3324, 2833, 3338, - 3318, 2841, 3333, - 3309, 2853, 3327, - 3297, 2867, 3318, - 3281, 2886, 3306, - 3258, 2911, 3290, - 3225, 2941, 3267, - 3177, 2979, 3235, - 3105, 3025, 3187, - 2985, 3080, 3115, - 2750, 3145, 2997, - 1687, 3219, 2766, - 0, 3303, 1775, - 0, 3395, 0, - 0, 3494, 0, - 0, 3600, 0, - 0, 3712, 0, - 3497, 2847, 3436, - 3497, 2848, 3436, - 3497, 2848, 3436, - 3497, 2848, 3436, - 3496, 2848, 3436, - 3496, 2849, 3436, - 3496, 2849, 3436, - 3496, 2850, 3435, - 3495, 2850, 3435, - 3495, 2852, 3434, - 3494, 2853, 3434, - 3493, 2855, 3433, - 3492, 2858, 3432, - 3490, 2861, 3430, - 3487, 2866, 3428, - 3484, 2872, 3425, - 3479, 2880, 3421, - 3473, 2890, 3416, - 3465, 2904, 3409, - 3454, 2921, 3399, - 3438, 2944, 3386, - 3417, 2972, 3368, - 3386, 3008, 3342, - 3341, 3051, 3305, - 3274, 3103, 3250, - 3165, 3165, 3165, - 2960, 3236, 3019, - 2308, 3317, 2696, - 0, 3406, 0, - 0, 3504, 0, - 0, 3608, 0, - 0, 3718, 0, - 3645, 2897, 3529, - 3645, 2897, 3529, - 3645, 2898, 3529, - 3645, 2898, 3529, - 3645, 2898, 3529, - 3645, 2898, 3529, - 3644, 2899, 3529, - 3644, 2899, 3529, - 3644, 2900, 3528, - 3644, 2901, 3528, - 3643, 2902, 3527, - 3642, 2904, 3527, - 3641, 2906, 3526, - 3640, 2909, 3524, - 3638, 2914, 3523, - 3636, 2919, 3520, - 3633, 2926, 3517, - 3628, 2936, 3513, - 3622, 2948, 3507, - 3614, 2964, 3500, - 3604, 2984, 3489, - 3589, 3011, 3474, - 3568, 3043, 3454, - 3539, 3084, 3426, - 3496, 3132, 3384, - 3432, 3191, 3322, - 3330, 3258, 3224, - 3143, 3335, 3046, - 2623, 3421, 2582, - 0, 3516, 0, - 0, 3618, 0, - 0, 3726, 0, - 3789, 2956, 3630, - 3789, 2956, 3630, - 3789, 2957, 3630, - 3789, 2957, 3630, - 3789, 2957, 3630, - 3789, 2957, 3630, - 3788, 2958, 3630, - 3788, 2958, 3630, - 3788, 2959, 3629, - 3788, 2960, 3629, - 3787, 2961, 3629, - 3787, 2962, 3628, - 3786, 2964, 3627, - 3785, 2967, 3626, - 3784, 2971, 3625, - 3782, 2976, 3623, - 3780, 2982, 3620, - 3777, 2990, 3617, - 3772, 3001, 3613, - 3767, 3015, 3606, - 3759, 3034, 3598, - 3748, 3057, 3587, - 3734, 3087, 3571, - 3714, 3124, 3549, - 3685, 3169, 3518, - 3644, 3222, 3473, - 3583, 3286, 3404, - 3485, 3359, 3292, - 3309, 3441, 3081, - 2855, 3532, 2365, - 0, 3630, 0, - 0, 3736, 0, - 3929, 3025, 3737, - 3929, 3025, 3737, - 3929, 3025, 3737, - 3929, 3025, 3737, - 3929, 3026, 3737, - 3929, 3026, 3737, - 3929, 3026, 3737, - 3929, 3026, 3737, - 3929, 3027, 3737, - 3929, 3028, 3736, - 3928, 3029, 3736, - 3928, 3030, 3736, - 3927, 3032, 3735, - 3927, 3034, 3734, - 3926, 3037, 3733, - 3925, 3042, 3732, - 3923, 3047, 3730, - 3921, 3054, 3727, - 3918, 3064, 3723, - 3913, 3076, 3719, - 3908, 3092, 3712, - 3900, 3113, 3703, - 3890, 3139, 3691, - 3876, 3172, 3674, - 3856, 3213, 3651, - 3828, 3262, 3618, - 3788, 3320, 3569, - 3728, 3388, 3494, - 3634, 3466, 3370, - 3465, 3552, 3123, - 3050, 3647, 1588, - 0, 3749, 0, - 4068, 3103, 3850, - 4068, 3103, 3850, - 4068, 3103, 3850, - 4068, 3103, 3850, - 4068, 3104, 3850, - 4068, 3104, 3850, - 4068, 3104, 3850, - 4068, 3104, 3849, - 4067, 3105, 3849, - 4067, 3105, 3849, - 4067, 3106, 3849, - 4067, 3107, 3849, - 4066, 3109, 3848, - 4066, 3111, 3847, - 4065, 3114, 3847, - 4064, 3117, 3845, - 4063, 3122, 3844, - 4061, 3128, 3842, - 4059, 3136, 3839, - 4056, 3147, 3835, - 4052, 3160, 3830, - 4046, 3178, 3823, - 4039, 3201, 3814, - 4029, 3230, 3801, - 4015, 3266, 3784, - 3995, 3310, 3759, - 3968, 3363, 3724, - 3929, 3425, 3672, - 3870, 3497, 3592, - 3778, 3578, 3457, - 3615, 3668, 3174, - 3224, 3766, 0, - 4095, 3190, 3967, - 4095, 3190, 3967, - 4095, 3190, 3967, - 4095, 3190, 3967, - 4095, 3191, 3967, - 4095, 3191, 3967, - 4095, 3191, 3967, - 4095, 3191, 3966, - 4095, 3192, 3966, - 4095, 3192, 3966, - 4095, 3193, 3966, - 4095, 3194, 3966, - 4095, 3195, 3965, - 4095, 3197, 3965, - 4095, 3199, 3964, - 4095, 3202, 3963, - 4095, 3206, 3962, - 4095, 3211, 3961, - 4095, 3217, 3958, - 4095, 3226, 3956, - 4095, 3238, 3952, - 4095, 3253, 3946, - 4095, 3273, 3939, - 4095, 3297, 3930, - 4095, 3328, 3917, - 4095, 3367, 3898, - 4095, 3414, 3873, - 4095, 3470, 3836, - 4067, 3536, 3782, - 4009, 3611, 3697, - 3919, 3695, 3552, - 3759, 3788, 3235, - 4095, 3285, 4087, - 4095, 3285, 4087, - 4095, 3286, 4087, - 4095, 3286, 4087, - 4095, 3286, 4087, - 4095, 3286, 4087, - 4095, 3286, 4087, - 4095, 3286, 4087, - 4095, 3287, 4087, - 4095, 3287, 4087, - 4095, 3288, 4087, - 4095, 3288, 4086, - 4095, 3289, 4086, - 4095, 3291, 4086, - 4095, 3292, 4085, - 4095, 3295, 4084, - 4095, 3298, 4084, - 4095, 3302, 4082, - 4095, 3308, 4081, - 4095, 3315, 4079, - 4095, 3325, 4076, - 4095, 3337, 4072, - 4095, 3353, 4066, - 4095, 3374, 4059, - 4095, 3401, 4049, - 4095, 3434, 4036, - 4095, 3475, 4017, - 4095, 3524, 3990, - 4095, 3583, 3952, - 4095, 3651, 3896, - 4095, 3729, 3808, - 4057, 3815, 3655, - 0, 2788, 3057, - 0, 2789, 3057, - 0, 2789, 3057, - 0, 2789, 3057, - 0, 2789, 3057, - 0, 2790, 3056, - 0, 2790, 3056, - 0, 2791, 3055, - 0, 2792, 3054, - 0, 2793, 3053, - 0, 2795, 3052, - 0, 2797, 3050, - 0, 2800, 3047, - 0, 2804, 3043, - 0, 2809, 3038, - 0, 2816, 3031, - 0, 2825, 3022, - 0, 2837, 3009, - 0, 2852, 2992, - 0, 2872, 2967, - 0, 2897, 2932, - 0, 2928, 2880, - 0, 2967, 2801, - 0, 3014, 2666, - 0, 3071, 2384, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2788, 3058, - 0, 2789, 3058, - 0, 2789, 3057, - 0, 2789, 3057, - 0, 2789, 3057, - 0, 2790, 3057, - 0, 2790, 3056, - 0, 2791, 3055, - 0, 2792, 3055, - 0, 2793, 3053, - 0, 2795, 3052, - 0, 2797, 3050, - 0, 2800, 3047, - 0, 2804, 3043, - 0, 2809, 3038, - 0, 2816, 3032, - 0, 2825, 3022, - 0, 2837, 3010, - 0, 2852, 2992, - 0, 2872, 2967, - 0, 2897, 2932, - 0, 2928, 2881, - 0, 2967, 2801, - 0, 3014, 2666, - 0, 3071, 2385, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2788, 3058, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2789, 3057, - 0, 2789, 3057, - 0, 2790, 3057, - 0, 2790, 3056, - 0, 2791, 3056, - 0, 2792, 3055, - 0, 2793, 3054, - 0, 2795, 3052, - 0, 2797, 3050, - 0, 2800, 3047, - 0, 2804, 3044, - 0, 2809, 3039, - 0, 2816, 3032, - 0, 2825, 3023, - 0, 2837, 3010, - 0, 2852, 2992, - 0, 2872, 2968, - 0, 2897, 2933, - 0, 2928, 2881, - 0, 2967, 2801, - 0, 3014, 2667, - 0, 3071, 2386, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2789, 3057, - 0, 2790, 3057, - 0, 2790, 3057, - 0, 2791, 3056, - 0, 2792, 3055, - 0, 2793, 3054, - 0, 2795, 3052, - 0, 2797, 3050, - 0, 2800, 3048, - 0, 2804, 3044, - 0, 2809, 3039, - 0, 2816, 3032, - 0, 2825, 3023, - 0, 2837, 3010, - 0, 2852, 2993, - 0, 2872, 2968, - 0, 2897, 2933, - 0, 2928, 2881, - 0, 2967, 2802, - 0, 3014, 2667, - 0, 3071, 2387, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2789, 3059, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2789, 3058, - 0, 2790, 3058, - 0, 2790, 3057, - 0, 2791, 3056, - 0, 2792, 3056, - 0, 2793, 3054, - 0, 2795, 3053, - 0, 2797, 3051, - 0, 2800, 3048, - 0, 2804, 3044, - 0, 2809, 3039, - 0, 2816, 3033, - 0, 2825, 3023, - 0, 2837, 3011, - 0, 2852, 2993, - 0, 2872, 2969, - 0, 2897, 2934, - 0, 2928, 2882, - 0, 2967, 2802, - 0, 3014, 2668, - 0, 3071, 2389, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2789, 3059, - 0, 2789, 3059, - 0, 2789, 3059, - 0, 2789, 3059, - 0, 2790, 3058, - 0, 2790, 3058, - 0, 2791, 3058, - 0, 2791, 3057, - 0, 2792, 3056, - 0, 2793, 3055, - 0, 2795, 3053, - 0, 2797, 3051, - 0, 2800, 3049, - 0, 2804, 3045, - 0, 2809, 3040, - 0, 2816, 3033, - 0, 2825, 3024, - 0, 2837, 3011, - 0, 2852, 2994, - 0, 2872, 2969, - 0, 2897, 2934, - 0, 2928, 2883, - 0, 2967, 2803, - 0, 3014, 2670, - 0, 3071, 2391, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2789, 3060, - 0, 2789, 3060, - 0, 2789, 3060, - 0, 2789, 3059, - 0, 2790, 3059, - 0, 2790, 3059, - 0, 2791, 3058, - 0, 2791, 3058, - 0, 2792, 3057, - 0, 2794, 3056, - 0, 2795, 3054, - 0, 2797, 3052, - 0, 2800, 3049, - 0, 2804, 3046, - 0, 2810, 3041, - 0, 2816, 3034, - 0, 2825, 3025, - 0, 2837, 3012, - 0, 2852, 2995, - 0, 2872, 2970, - 0, 2897, 2935, - 0, 2928, 2884, - 0, 2967, 2805, - 0, 3015, 2671, - 0, 3071, 2394, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3490, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2789, 3061, - 0, 2789, 3061, - 0, 2789, 3061, - 0, 2790, 3060, - 0, 2790, 3060, - 0, 2790, 3060, - 0, 2791, 3059, - 0, 2792, 3059, - 0, 2793, 3058, - 0, 2794, 3057, - 0, 2795, 3055, - 0, 2798, 3053, - 0, 2801, 3050, - 0, 2805, 3047, - 0, 2810, 3042, - 0, 2817, 3035, - 0, 2826, 3026, - 0, 2837, 3013, - 0, 2853, 2996, - 0, 2872, 2971, - 0, 2897, 2936, - 0, 2929, 2885, - 0, 2967, 2806, - 0, 3015, 2673, - 0, 3071, 2398, - 0, 3137, 0, - 0, 3212, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3491, 0, - 0, 3597, 0, - 0, 3710, 0, - 0, 2790, 3062, - 0, 2790, 3062, - 0, 2790, 3062, - 0, 2790, 3062, - 0, 2790, 3061, - 0, 2791, 3061, - 0, 2791, 3060, - 0, 2792, 3060, - 0, 2793, 3059, - 0, 2794, 3058, - 0, 2796, 3056, - 0, 2798, 3054, - 0, 2801, 3052, - 0, 2805, 3048, - 0, 2810, 3043, - 0, 2817, 3036, - 0, 2826, 3027, - 0, 2838, 3014, - 0, 2853, 2997, - 0, 2872, 2973, - 0, 2897, 2938, - 0, 2929, 2887, - 0, 2968, 2809, - 0, 3015, 2676, - 0, 3071, 2404, - 0, 3137, 0, - 0, 3213, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3491, 0, - 0, 3598, 0, - 0, 3710, 0, - 0, 2790, 3064, - 0, 2790, 3064, - 0, 2790, 3063, - 0, 2790, 3063, - 0, 2791, 3063, - 0, 2791, 3063, - 0, 2792, 3062, - 0, 2792, 3062, - 0, 2793, 3061, - 0, 2795, 3060, - 0, 2796, 3058, - 0, 2798, 3056, - 0, 2801, 3053, - 0, 2805, 3050, - 0, 2810, 3045, - 0, 2817, 3038, - 0, 2826, 3029, - 0, 2838, 3016, - 0, 2853, 2999, - 0, 2873, 2975, - 0, 2898, 2940, - 0, 2929, 2890, - 0, 2968, 2811, - 0, 3015, 2680, - 0, 3072, 2411, - 0, 3137, 0, - 0, 3213, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3491, 0, - 0, 3598, 0, - 0, 3710, 0, - 0, 2791, 3066, - 0, 2791, 3066, - 0, 2791, 3066, - 0, 2791, 3065, - 0, 2791, 3065, - 0, 2792, 3065, - 0, 2792, 3064, - 0, 2793, 3064, - 0, 2794, 3063, - 0, 2795, 3062, - 0, 2797, 3060, - 0, 2799, 3058, - 0, 2802, 3056, - 0, 2806, 3052, - 0, 2811, 3047, - 0, 2818, 3040, - 0, 2827, 3031, - 0, 2838, 3019, - 0, 2854, 3002, - 0, 2873, 2978, - 0, 2898, 2943, - 0, 2930, 2893, - 0, 2968, 2815, - 0, 3016, 2685, - 0, 3072, 2420, - 0, 3138, 0, - 0, 3213, 0, - 0, 3297, 0, - 0, 3390, 0, - 0, 3491, 0, - 0, 3598, 0, - 0, 3710, 0, - 0, 2791, 3069, - 0, 2791, 3069, - 0, 2792, 3069, - 0, 2792, 3068, - 0, 2792, 3068, - 0, 2792, 3068, - 0, 2793, 3067, - 0, 2794, 3067, - 0, 2795, 3066, - 0, 2796, 3065, - 0, 2798, 3063, - 0, 2800, 3061, - 0, 2803, 3059, - 0, 2807, 3055, - 0, 2812, 3050, - 0, 2819, 3043, - 0, 2827, 3034, - 0, 2839, 3022, - 0, 2854, 3005, - 0, 2874, 2981, - 0, 2899, 2947, - 0, 2930, 2897, - 0, 2969, 2821, - 0, 3016, 2692, - 0, 3072, 2432, - 0, 3138, 0, - 0, 3213, 0, - 0, 3298, 0, - 0, 3391, 0, - 0, 3491, 0, - 0, 3598, 0, - 0, 3710, 0, - 0, 2792, 3073, - 0, 2792, 3073, - 0, 2793, 3073, - 0, 2793, 3072, - 0, 2793, 3072, - 0, 2793, 3072, - 0, 2794, 3071, - 0, 2795, 3071, - 0, 2796, 3070, - 0, 2797, 3069, - 0, 2799, 3067, - 0, 2801, 3065, - 0, 2804, 3063, - 0, 2808, 3059, - 0, 2813, 3054, - 0, 2819, 3048, - 0, 2828, 3039, - 0, 2840, 3026, - 0, 2855, 3010, - 0, 2875, 2986, - 0, 2900, 2952, - 0, 2931, 2903, - 0, 2970, 2827, - 0, 3017, 2701, - 0, 3073, 2448, - 0, 3138, 0, - 0, 3214, 0, - 0, 3298, 0, - 0, 3391, 0, - 0, 3491, 0, - 0, 3598, 0, - 0, 3710, 0, - 0, 2794, 3078, - 0, 2794, 3078, - 0, 2794, 3078, - 0, 2794, 3078, - 0, 2794, 3077, - 0, 2795, 3077, - 0, 2795, 3077, - 0, 2796, 3076, - 0, 2797, 3075, - 0, 2798, 3074, - 0, 2800, 3073, - 0, 2802, 3071, - 0, 2805, 3068, - 0, 2809, 3064, - 0, 2814, 3060, - 0, 2821, 3053, - 0, 2830, 3044, - 0, 2841, 3032, - 0, 2856, 3016, - 0, 2876, 2992, - 0, 2901, 2959, - 0, 2932, 2911, - 0, 2970, 2836, - 0, 3017, 2713, - 0, 3074, 2468, - 0, 3139, 1070, - 0, 3214, 0, - 0, 3298, 0, - 0, 3391, 0, - 0, 3491, 0, - 0, 3598, 0, - 0, 3710, 0, - 0, 2795, 3085, - 0, 2796, 3085, - 0, 2796, 3085, - 0, 2796, 3085, - 0, 2796, 3084, - 0, 2797, 3084, - 0, 2797, 3084, - 0, 2798, 3083, - 0, 2799, 3082, - 0, 2800, 3081, - 0, 2802, 3080, - 0, 2804, 3078, - 0, 2807, 3075, - 0, 2811, 3072, - 0, 2816, 3067, - 0, 2822, 3060, - 0, 2831, 3052, - 0, 2843, 3040, - 0, 2858, 3023, - 0, 2877, 3001, - 0, 2902, 2968, - 0, 2933, 2920, - 0, 2972, 2848, - 0, 3019, 2728, - 0, 3075, 2494, - 0, 3140, 1443, - 0, 3215, 0, - 0, 3299, 0, - 0, 3392, 0, - 0, 3492, 0, - 0, 3599, 0, - 0, 3711, 0, - 0, 2798, 3094, - 0, 2798, 3094, - 0, 2798, 3094, - 0, 2798, 3094, - 0, 2799, 3093, - 0, 2799, 3093, - 0, 2800, 3093, - 0, 2800, 3092, - 0, 2801, 3091, - 0, 2802, 3090, - 0, 2804, 3089, - 0, 2806, 3087, - 0, 2809, 3084, - 0, 2813, 3081, - 0, 2818, 3076, - 0, 2825, 3070, - 0, 2834, 3062, - 0, 2845, 3050, - 0, 2860, 3034, - 0, 2879, 3011, - 0, 2904, 2980, - 0, 2935, 2933, - 0, 2973, 2863, - 0, 3020, 2748, - 0, 3076, 2527, - 0, 3141, 1697, - 0, 3216, 0, - 0, 3300, 0, - 0, 3392, 0, - 0, 3492, 0, - 0, 3599, 0, - 0, 3711, 0, - 0, 2801, 3106, - 0, 2801, 3106, - 0, 2801, 3106, - 0, 2802, 3106, - 0, 2802, 3105, - 0, 2802, 3105, - 0, 2803, 3105, - 0, 2803, 3104, - 0, 2804, 3103, - 0, 2806, 3102, - 0, 2807, 3101, - 0, 2809, 3099, - 0, 2812, 3096, - 0, 2816, 3093, - 0, 2821, 3089, - 0, 2828, 3083, - 0, 2837, 3074, - 0, 2848, 3063, - 0, 2863, 3047, - 0, 2882, 3026, - 0, 2907, 2995, - 0, 2937, 2950, - 0, 2976, 2883, - 0, 3022, 2773, - 0, 3078, 2567, - 0, 3143, 1902, - 0, 3217, 0, - 0, 3301, 0, - 0, 3393, 0, - 0, 3493, 0, - 0, 3599, 0, - 0, 3711, 0, - 0, 2805, 3121, - 0, 2805, 3121, - 0, 2806, 3121, - 0, 2806, 3121, - 0, 2806, 3121, - 0, 2806, 3120, - 0, 2807, 3120, - 0, 2808, 3119, - 0, 2809, 3119, - 0, 2810, 3118, - 0, 2811, 3116, - 0, 2814, 3115, - 0, 2816, 3112, - 0, 2820, 3109, - 0, 2825, 3105, - 0, 2832, 3099, - 0, 2840, 3091, - 0, 2852, 3080, - 0, 2867, 3065, - 0, 2886, 3044, - 0, 2910, 3014, - 0, 2940, 2972, - 0, 2978, 2908, - 0, 3025, 2805, - 0, 3080, 2615, - 0, 3145, 2083, - 0, 3219, 0, - 0, 3302, 0, - 0, 3394, 0, - 0, 3494, 0, - 0, 3600, 0, - 0, 3712, 0, - 0, 2811, 3141, - 0, 2811, 3141, - 0, 2811, 3141, - 0, 2811, 3141, - 0, 2812, 3141, - 0, 2812, 3140, - 0, 2813, 3140, - 0, 2813, 3139, - 0, 2814, 3139, - 0, 2815, 3138, - 0, 2817, 3136, - 0, 2819, 3135, - 0, 2822, 3132, - 0, 2826, 3129, - 0, 2831, 3125, - 0, 2837, 3120, - 0, 2846, 3112, - 0, 2857, 3101, - 0, 2872, 3087, - 0, 2890, 3067, - 0, 2914, 3039, - 0, 2945, 2999, - 0, 2982, 2939, - 0, 3028, 2843, - 0, 3083, 2673, - 0, 3147, 2248, - 0, 3221, 0, - 0, 3304, 0, - 0, 3396, 0, - 0, 3495, 0, - 0, 3601, 0, - 0, 3713, 0, - 1321, 2818, 3166, - 1314, 2818, 3166, - 1305, 2819, 3166, - 1292, 2819, 3166, - 1275, 2819, 3166, - 1251, 2819, 3165, - 1216, 2820, 3165, - 1165, 2821, 3165, - 1087, 2821, 3164, - 956, 2823, 3163, - 686, 2824, 3162, - 0, 2826, 3160, - 0, 2829, 3158, - 0, 2833, 3155, - 0, 2838, 3151, - 0, 2844, 3146, - 0, 2853, 3139, - 0, 2864, 3129, - 0, 2878, 3115, - 0, 2897, 3097, - 0, 2920, 3071, - 0, 2950, 3033, - 0, 2987, 2978, - 0, 3033, 2891, - 0, 3087, 2740, - 0, 3151, 2403, - 0, 3224, 0, - 0, 3307, 0, - 0, 3398, 0, - 0, 3497, 0, - 0, 3603, 0, - 0, 3714, 0, - 2324, 2828, 3198, - 2323, 2828, 3198, - 2322, 2828, 3198, - 2321, 2828, 3198, - 2319, 2829, 3197, - 2317, 2829, 3197, - 2314, 2830, 3197, - 2309, 2830, 3196, - 2304, 2831, 3196, - 2296, 2832, 3195, - 2285, 2834, 3194, - 2270, 2836, 3192, - 2249, 2839, 3190, - 2220, 2842, 3188, - 2178, 2847, 3184, - 2115, 2853, 3179, - 2013, 2862, 3172, - 1828, 2872, 3163, - 1321, 2887, 3151, - 0, 2905, 3134, - 0, 2928, 3109, - 0, 2957, 3075, - 0, 2994, 3025, - 0, 3039, 2947, - 0, 3092, 2817, - 0, 3156, 2552, - 0, 3228, 0, - 0, 3310, 0, - 0, 3401, 0, - 0, 3499, 0, - 0, 3604, 0, - 0, 3715, 0, - 2680, 2841, 3237, - 2680, 2841, 3237, - 2680, 2841, 3237, - 2679, 2841, 3237, - 2678, 2841, 3237, - 2677, 2842, 3236, - 2676, 2842, 3236, - 2674, 2843, 3236, - 2671, 2844, 3235, - 2668, 2845, 3234, - 2663, 2846, 3233, - 2657, 2848, 3232, - 2648, 2851, 3230, - 2636, 2854, 3228, - 2620, 2859, 3224, - 2597, 2865, 3220, - 2564, 2873, 3214, - 2516, 2884, 3205, - 2444, 2898, 3194, - 2324, 2915, 3178, - 2088, 2938, 3157, - 1008, 2967, 3126, - 0, 3003, 3081, - 0, 3047, 3013, - 0, 3100, 2903, - 0, 3162, 2696, - 0, 3233, 2020, - 0, 3315, 0, - 0, 3404, 0, - 0, 3502, 0, - 0, 3607, 0, - 0, 3717, 0, - 2929, 2857, 3285, - 2929, 2857, 3285, - 2928, 2857, 3285, - 2928, 2858, 3284, - 2927, 2858, 3284, - 2927, 2858, 3284, - 2926, 2859, 3284, - 2925, 2859, 3283, - 2923, 2860, 3283, - 2921, 2861, 3282, - 2919, 2863, 3281, - 2915, 2864, 3280, - 2910, 2867, 3278, - 2903, 2870, 3276, - 2894, 2875, 3273, - 2882, 2881, 3269, - 2865, 2889, 3264, - 2841, 2899, 3256, - 2807, 2912, 3246, - 2757, 2929, 3232, - 2680, 2952, 3213, - 2551, 2980, 3186, - 2289, 3014, 3147, - 0, 3057, 3089, - 0, 3109, 2997, - 0, 3170, 2837, - 0, 3240, 2456, - 0, 3320, 0, - 0, 3409, 0, - 0, 3506, 0, - 0, 3610, 0, - 0, 3719, 0, - 3132, 2878, 3341, - 3132, 2878, 3341, - 3131, 2878, 3341, - 3131, 2879, 3341, - 3131, 2879, 3341, - 3130, 2879, 3341, - 3130, 2880, 3341, - 3129, 2880, 3340, - 3128, 2881, 3340, - 3127, 2882, 3339, - 3125, 2883, 3338, - 3123, 2885, 3337, - 3120, 2888, 3336, - 3116, 2891, 3334, - 3110, 2895, 3331, - 3102, 2901, 3328, - 3092, 2908, 3323, - 3077, 2918, 3316, - 3057, 2931, 3307, - 3029, 2947, 3295, - 2989, 2969, 3279, - 2928, 2996, 3255, - 2832, 3029, 3222, - 2659, 3071, 3173, - 2222, 3121, 3099, - 0, 3181, 2975, - 0, 3250, 2729, - 0, 3328, 1243, - 0, 3415, 0, - 0, 3511, 0, - 0, 3614, 0, - 0, 3723, 0, - 3310, 2905, 3408, - 3310, 2905, 3408, - 3310, 2905, 3408, - 3310, 2905, 3407, - 3310, 2906, 3407, - 3309, 2906, 3407, - 3309, 2906, 3407, - 3309, 2907, 3407, - 3308, 2907, 3406, - 3307, 2908, 3406, - 3306, 2910, 3405, - 3304, 2911, 3404, - 3302, 2914, 3403, - 3300, 2917, 3401, - 3296, 2921, 3399, - 3291, 2926, 3396, - 3284, 2933, 3392, - 3274, 2943, 3386, - 3262, 2955, 3378, - 3244, 2970, 3368, - 3219, 2991, 3354, - 3183, 3016, 3334, - 3131, 3049, 3306, - 3050, 3089, 3266, - 2912, 3137, 3207, - 2620, 3195, 3112, - 0, 3262, 2944, - 0, 3338, 2528, - 0, 3424, 0, - 0, 3518, 0, - 0, 3619, 0, - 0, 3727, 0, - 3474, 2938, 3483, - 3474, 2938, 3483, - 3474, 2939, 3483, - 3474, 2939, 3483, - 3474, 2939, 3483, - 3474, 2939, 3483, - 3474, 2940, 3483, - 3473, 2940, 3483, - 3473, 2941, 3482, - 3472, 2942, 3482, - 3471, 2943, 3481, - 3470, 2944, 3480, - 3469, 2947, 3479, - 3467, 2949, 3478, - 3464, 2953, 3476, - 3461, 2958, 3473, - 3456, 2965, 3470, - 3450, 2973, 3465, - 3441, 2985, 3459, - 3429, 3000, 3450, - 3413, 3019, 3438, - 3390, 3043, 3422, - 3357, 3073, 3399, - 3310, 3111, 3367, - 3237, 3157, 3320, - 3117, 3213, 3248, - 2883, 3277, 3129, - 1820, 3351, 2898, - 0, 3435, 1907, - 0, 3527, 0, - 0, 3626, 0, - 0, 3732, 0, - 3629, 2980, 3568, - 3629, 2980, 3568, - 3629, 2980, 3568, - 3629, 2980, 3568, - 3629, 2980, 3568, - 3629, 2980, 3568, - 3628, 2981, 3568, - 3628, 2981, 3568, - 3628, 2982, 3567, - 3627, 2983, 3567, - 3627, 2984, 3566, - 3626, 2985, 3566, - 3625, 2987, 3565, - 3624, 2990, 3564, - 3622, 2993, 3562, - 3619, 2998, 3560, - 3616, 3004, 3557, - 3612, 3012, 3553, - 3605, 3022, 3548, - 3597, 3036, 3541, - 3586, 3053, 3531, - 3570, 3076, 3518, - 3549, 3104, 3500, - 3518, 3140, 3474, - 3474, 3183, 3437, - 3406, 3235, 3382, - 3297, 3297, 3297, - 3092, 3368, 3151, - 2441, 3449, 2828, - 0, 3538, 0, - 0, 3636, 0, - 0, 3740, 0, - 3777, 3029, 3662, - 3777, 3029, 3662, - 3777, 3030, 3662, - 3777, 3030, 3661, - 3777, 3030, 3661, - 3777, 3030, 3661, - 3777, 3030, 3661, - 3777, 3031, 3661, - 3776, 3031, 3661, - 3776, 3032, 3660, - 3776, 3033, 3660, - 3775, 3034, 3660, - 3774, 3036, 3659, - 3773, 3038, 3658, - 3772, 3042, 3657, - 3770, 3046, 3655, - 3768, 3051, 3652, - 3765, 3058, 3649, - 3760, 3068, 3645, - 3754, 3080, 3639, - 3747, 3096, 3632, - 3736, 3117, 3621, - 3721, 3143, 3606, - 3700, 3175, 3586, - 3671, 3216, 3558, - 3628, 3265, 3516, - 3564, 3323, 3455, - 3462, 3390, 3356, - 3275, 3467, 3178, - 2755, 3554, 2715, - 0, 3648, 0, - 0, 3750, 0, - 3921, 3088, 3762, - 3921, 3088, 3762, - 3921, 3089, 3762, - 3921, 3089, 3762, - 3921, 3089, 3762, - 3921, 3089, 3762, - 3921, 3089, 3762, - 3921, 3090, 3762, - 3920, 3090, 3762, - 3920, 3091, 3761, - 3920, 3092, 3761, - 3919, 3093, 3761, - 3919, 3094, 3760, - 3918, 3096, 3759, - 3917, 3099, 3758, - 3916, 3103, 3757, - 3914, 3108, 3755, - 3912, 3114, 3753, - 3909, 3122, 3749, - 3905, 3133, 3745, - 3899, 3148, 3738, - 3891, 3166, 3730, - 3881, 3189, 3719, - 3866, 3219, 3703, - 3846, 3256, 3681, - 3817, 3301, 3650, - 3776, 3355, 3605, - 3715, 3418, 3536, - 3617, 3491, 3424, - 3441, 3573, 3213, - 2987, 3664, 2497, - 0, 3762, 0, - 4062, 3157, 3869, - 4062, 3157, 3869, - 4062, 3157, 3869, - 4062, 3157, 3869, - 4062, 3157, 3869, - 4061, 3158, 3869, - 4061, 3158, 3869, - 4061, 3158, 3869, - 4061, 3159, 3869, - 4061, 3159, 3869, - 4061, 3160, 3869, - 4060, 3161, 3868, - 4060, 3162, 3868, - 4060, 3164, 3867, - 4059, 3166, 3866, - 4058, 3169, 3865, - 4057, 3174, 3864, - 4055, 3179, 3862, - 4053, 3186, 3859, - 4050, 3196, 3856, - 4045, 3208, 3851, - 4040, 3224, 3844, - 4032, 3245, 3835, - 4022, 3271, 3823, - 4008, 3304, 3806, - 3988, 3345, 3783, - 3960, 3394, 3750, - 3920, 3452, 3701, - 3860, 3520, 3626, - 3766, 3598, 3502, - 3598, 3684, 3255, - 3182, 3779, 1720, - 4095, 3235, 3982, - 4095, 3235, 3982, - 4095, 3235, 3982, - 4095, 3235, 3982, - 4095, 3235, 3982, - 4095, 3236, 3982, - 4095, 3236, 3982, - 4095, 3236, 3982, - 4095, 3236, 3982, - 4095, 3237, 3981, - 4095, 3238, 3981, - 4095, 3238, 3981, - 4095, 3239, 3981, - 4095, 3241, 3980, - 4095, 3243, 3979, - 4095, 3246, 3979, - 4095, 3249, 3978, - 4095, 3254, 3976, - 4095, 3260, 3974, - 4095, 3268, 3971, - 4095, 3279, 3967, - 4095, 3293, 3962, - 4095, 3310, 3956, - 4095, 3333, 3946, - 4095, 3362, 3934, - 4095, 3398, 3916, - 4095, 3442, 3891, - 4095, 3495, 3856, - 4061, 3557, 3804, - 4002, 3629, 3724, - 3910, 3710, 3589, - 3747, 3800, 3306, - 4095, 3322, 4095, - 4095, 3322, 4095, - 4095, 3322, 4095, - 4095, 3322, 4095, - 4095, 3322, 4095, - 4095, 3323, 4095, - 4095, 3323, 4095, - 4095, 3323, 4095, - 4095, 3323, 4095, - 4095, 3324, 4095, - 4095, 3324, 4095, - 4095, 3325, 4095, - 4095, 3326, 4095, - 4095, 3327, 4095, - 4095, 3329, 4095, - 4095, 3331, 4095, - 4095, 3334, 4095, - 4095, 3338, 4094, - 4095, 3343, 4093, - 4095, 3350, 4090, - 4095, 3358, 4088, - 4095, 3370, 4084, - 4095, 3385, 4079, - 4095, 3405, 4071, - 4095, 3429, 4062, - 4095, 3461, 4049, - 4095, 3499, 4030, - 4095, 3546, 4005, - 4095, 3602, 3968, - 4095, 3668, 3914, - 4095, 3743, 3829, - 4051, 3827, 3684, - 0, 2920, 3190, - 0, 2920, 3189, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2922, 3188, - 0, 2922, 3188, - 0, 2923, 3187, - 0, 2924, 3186, - 0, 2925, 3185, - 0, 2927, 3184, - 0, 2929, 3182, - 0, 2932, 3179, - 0, 2936, 3175, - 0, 2941, 3170, - 0, 2948, 3163, - 0, 2957, 3154, - 0, 2969, 3141, - 0, 2984, 3124, - 0, 3004, 3099, - 0, 3029, 3064, - 0, 3060, 3012, - 0, 3099, 2932, - 0, 3146, 2798, - 0, 3203, 2515, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3622, 0, - 0, 3729, 0, - 0, 2920, 3190, - 0, 2920, 3190, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2922, 3189, - 0, 2922, 3188, - 0, 2923, 3187, - 0, 2924, 3187, - 0, 2925, 3185, - 0, 2927, 3184, - 0, 2929, 3182, - 0, 2932, 3179, - 0, 2936, 3175, - 0, 2941, 3170, - 0, 2948, 3163, - 0, 2957, 3154, - 0, 2969, 3142, - 0, 2984, 3124, - 0, 3004, 3099, - 0, 3029, 3064, - 0, 3060, 3013, - 0, 3099, 2933, - 0, 3146, 2798, - 0, 3203, 2516, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3622, 0, - 0, 3729, 0, - 0, 2920, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2921, 3189, - 0, 2922, 3189, - 0, 2922, 3188, - 0, 2923, 3188, - 0, 2924, 3187, - 0, 2925, 3186, - 0, 2927, 3184, - 0, 2929, 3182, - 0, 2932, 3179, - 0, 2936, 3176, - 0, 2941, 3170, - 0, 2948, 3164, - 0, 2957, 3154, - 0, 2969, 3142, - 0, 2984, 3124, - 0, 3004, 3100, - 0, 3029, 3064, - 0, 3060, 3013, - 0, 3099, 2933, - 0, 3146, 2798, - 0, 3203, 2517, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3622, 0, - 0, 3729, 0, - 0, 2920, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3189, - 0, 2922, 3189, - 0, 2922, 3188, - 0, 2923, 3188, - 0, 2924, 3187, - 0, 2925, 3186, - 0, 2927, 3184, - 0, 2929, 3182, - 0, 2932, 3179, - 0, 2936, 3176, - 0, 2941, 3171, - 0, 2948, 3164, - 0, 2957, 3155, - 0, 2969, 3142, - 0, 2984, 3124, - 0, 3004, 3100, - 0, 3029, 3065, - 0, 3060, 3013, - 0, 3099, 2933, - 0, 3146, 2799, - 0, 3203, 2518, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3622, 0, - 0, 3729, 0, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2922, 3189, - 0, 2922, 3189, - 0, 2923, 3188, - 0, 2924, 3187, - 0, 2925, 3186, - 0, 2927, 3185, - 0, 2929, 3183, - 0, 2932, 3180, - 0, 2936, 3176, - 0, 2941, 3171, - 0, 2948, 3164, - 0, 2957, 3155, - 0, 2969, 3142, - 0, 2984, 3125, - 0, 3004, 3100, - 0, 3029, 3065, - 0, 3060, 3014, - 0, 3099, 2934, - 0, 3146, 2799, - 0, 3203, 2519, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3622, 0, - 0, 3729, 0, - 0, 2921, 3191, - 0, 2921, 3191, - 0, 2921, 3191, - 0, 2921, 3190, - 0, 2921, 3190, - 0, 2922, 3190, - 0, 2922, 3190, - 0, 2922, 3189, - 0, 2923, 3188, - 0, 2924, 3188, - 0, 2925, 3187, - 0, 2927, 3185, - 0, 2929, 3183, - 0, 2932, 3180, - 0, 2936, 3176, - 0, 2941, 3171, - 0, 2948, 3165, - 0, 2957, 3155, - 0, 2969, 3143, - 0, 2984, 3125, - 0, 3004, 3101, - 0, 3029, 3066, - 0, 3060, 3014, - 0, 3099, 2935, - 0, 3146, 2800, - 0, 3203, 2521, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3622, 0, - 0, 3729, 0, - 0, 2921, 3191, - 0, 2921, 3191, - 0, 2921, 3191, - 0, 2921, 3191, - 0, 2921, 3191, - 0, 2922, 3190, - 0, 2922, 3190, - 0, 2923, 3190, - 0, 2923, 3189, - 0, 2924, 3188, - 0, 2925, 3187, - 0, 2927, 3186, - 0, 2929, 3183, - 0, 2932, 3181, - 0, 2936, 3177, - 0, 2941, 3172, - 0, 2948, 3165, - 0, 2957, 3156, - 0, 2969, 3143, - 0, 2984, 3126, - 0, 3004, 3101, - 0, 3029, 3066, - 0, 3060, 3015, - 0, 3099, 2936, - 0, 3147, 2802, - 0, 3203, 2523, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3623, 0, - 0, 3729, 0, - 0, 2921, 3192, - 0, 2921, 3192, - 0, 2921, 3192, - 0, 2921, 3192, - 0, 2922, 3191, - 0, 2922, 3191, - 0, 2922, 3191, - 0, 2923, 3190, - 0, 2923, 3190, - 0, 2924, 3189, - 0, 2926, 3188, - 0, 2927, 3186, - 0, 2930, 3184, - 0, 2933, 3181, - 0, 2936, 3178, - 0, 2942, 3173, - 0, 2948, 3166, - 0, 2957, 3157, - 0, 2969, 3144, - 0, 2984, 3127, - 0, 3004, 3102, - 0, 3029, 3067, - 0, 3061, 3016, - 0, 3099, 2937, - 0, 3147, 2803, - 0, 3203, 2526, - 0, 3269, 0, - 0, 3344, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2921, 3193, - 0, 2921, 3193, - 0, 2921, 3193, - 0, 2922, 3193, - 0, 2922, 3192, - 0, 2922, 3192, - 0, 2922, 3192, - 0, 2923, 3191, - 0, 2924, 3191, - 0, 2925, 3190, - 0, 2926, 3189, - 0, 2928, 3187, - 0, 2930, 3185, - 0, 2933, 3182, - 0, 2937, 3179, - 0, 2942, 3174, - 0, 2949, 3167, - 0, 2958, 3158, - 0, 2969, 3145, - 0, 2985, 3128, - 0, 3004, 3103, - 0, 3029, 3069, - 0, 3061, 3017, - 0, 3100, 2938, - 0, 3147, 2806, - 0, 3203, 2530, - 0, 3269, 0, - 0, 3345, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2922, 3194, - 0, 2922, 3194, - 0, 2922, 3194, - 0, 2922, 3194, - 0, 2922, 3194, - 0, 2922, 3193, - 0, 2923, 3193, - 0, 2923, 3193, - 0, 2924, 3192, - 0, 2925, 3191, - 0, 2926, 3190, - 0, 2928, 3188, - 0, 2930, 3186, - 0, 2933, 3184, - 0, 2937, 3180, - 0, 2942, 3175, - 0, 2949, 3168, - 0, 2958, 3159, - 0, 2970, 3147, - 0, 2985, 3129, - 0, 3005, 3105, - 0, 3030, 3070, - 0, 3061, 3019, - 0, 3100, 2941, - 0, 3147, 2808, - 0, 3203, 2536, - 0, 3269, 0, - 0, 3345, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2922, 3196, - 0, 2922, 3196, - 0, 2922, 3196, - 0, 2922, 3196, - 0, 2923, 3195, - 0, 2923, 3195, - 0, 2923, 3195, - 0, 2924, 3194, - 0, 2924, 3194, - 0, 2925, 3193, - 0, 2927, 3192, - 0, 2928, 3190, - 0, 2931, 3188, - 0, 2933, 3185, - 0, 2937, 3182, - 0, 2943, 3177, - 0, 2949, 3170, - 0, 2958, 3161, - 0, 2970, 3148, - 0, 2985, 3131, - 0, 3005, 3107, - 0, 3030, 3072, - 0, 3061, 3022, - 0, 3100, 2944, - 0, 3147, 2812, - 0, 3204, 2543, - 0, 3269, 0, - 0, 3345, 0, - 0, 3429, 0, - 0, 3522, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2923, 3198, - 0, 2923, 3198, - 0, 2923, 3198, - 0, 2923, 3198, - 0, 2923, 3198, - 0, 2923, 3197, - 0, 2924, 3197, - 0, 2924, 3197, - 0, 2925, 3196, - 0, 2926, 3195, - 0, 2927, 3194, - 0, 2929, 3192, - 0, 2931, 3190, - 0, 2934, 3188, - 0, 2938, 3184, - 0, 2943, 3179, - 0, 2950, 3172, - 0, 2959, 3163, - 0, 2971, 3151, - 0, 2986, 3134, - 0, 3005, 3110, - 0, 3030, 3075, - 0, 3062, 3025, - 0, 3100, 2947, - 0, 3148, 2818, - 0, 3204, 2552, - 0, 3270, 0, - 0, 3345, 0, - 0, 3430, 0, - 0, 3522, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2923, 3201, - 0, 2923, 3201, - 0, 2924, 3201, - 0, 2924, 3201, - 0, 2924, 3201, - 0, 2924, 3200, - 0, 2925, 3200, - 0, 2925, 3200, - 0, 2926, 3199, - 0, 2927, 3198, - 0, 2928, 3197, - 0, 2930, 3195, - 0, 2932, 3193, - 0, 2935, 3191, - 0, 2939, 3187, - 0, 2944, 3182, - 0, 2951, 3176, - 0, 2960, 3167, - 0, 2971, 3154, - 0, 2986, 3137, - 0, 3006, 3113, - 0, 3031, 3079, - 0, 3062, 3029, - 0, 3101, 2953, - 0, 3148, 2824, - 0, 3204, 2564, - 0, 3270, 0, - 0, 3345, 0, - 0, 3430, 0, - 0, 3523, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2924, 3205, - 0, 2924, 3205, - 0, 2925, 3205, - 0, 2925, 3205, - 0, 2925, 3205, - 0, 2925, 3204, - 0, 2926, 3204, - 0, 2926, 3203, - 0, 2927, 3203, - 0, 2928, 3202, - 0, 2929, 3201, - 0, 2931, 3199, - 0, 2933, 3197, - 0, 2936, 3195, - 0, 2940, 3191, - 0, 2945, 3186, - 0, 2952, 3180, - 0, 2961, 3171, - 0, 2972, 3159, - 0, 2987, 3142, - 0, 3007, 3118, - 0, 3032, 3084, - 0, 3063, 3035, - 0, 3102, 2959, - 0, 3149, 2833, - 0, 3205, 2580, - 0, 3271, 0, - 0, 3346, 0, - 0, 3430, 0, - 0, 3523, 0, - 0, 3623, 0, - 0, 3730, 0, - 0, 2926, 3210, - 0, 2926, 3210, - 0, 2926, 3210, - 0, 2926, 3210, - 0, 2926, 3210, - 0, 2927, 3210, - 0, 2927, 3209, - 0, 2927, 3209, - 0, 2928, 3208, - 0, 2929, 3207, - 0, 2930, 3206, - 0, 2932, 3205, - 0, 2934, 3203, - 0, 2937, 3200, - 0, 2941, 3197, - 0, 2946, 3192, - 0, 2953, 3185, - 0, 2962, 3176, - 0, 2973, 3164, - 0, 2989, 3148, - 0, 3008, 3124, - 0, 3033, 3091, - 0, 3064, 3043, - 0, 3103, 2968, - 0, 3150, 2845, - 0, 3206, 2601, - 0, 3271, 1202, - 0, 3346, 0, - 0, 3431, 0, - 0, 3523, 0, - 0, 3624, 0, - 0, 3730, 0, - 0, 2927, 3217, - 0, 2928, 3217, - 0, 2928, 3217, - 0, 2928, 3217, - 0, 2928, 3217, - 0, 2928, 3216, - 0, 2929, 3216, - 0, 2929, 3216, - 0, 2930, 3215, - 0, 2931, 3214, - 0, 2932, 3213, - 0, 2934, 3212, - 0, 2936, 3210, - 0, 2939, 3207, - 0, 2943, 3204, - 0, 2948, 3199, - 0, 2955, 3193, - 0, 2963, 3184, - 0, 2975, 3172, - 0, 2990, 3156, - 0, 3010, 3133, - 0, 3034, 3100, - 0, 3065, 3053, - 0, 3104, 2980, - 0, 3151, 2860, - 0, 3207, 2626, - 0, 3272, 1575, - 0, 3347, 0, - 0, 3431, 0, - 0, 3524, 0, - 0, 3624, 0, - 0, 3731, 0, - 0, 2930, 3226, - 0, 2930, 3226, - 0, 2930, 3226, - 0, 2930, 3226, - 0, 2930, 3226, - 0, 2931, 3226, - 0, 2931, 3225, - 0, 2932, 3225, - 0, 2932, 3224, - 0, 2933, 3223, - 0, 2934, 3222, - 0, 2936, 3221, - 0, 2938, 3219, - 0, 2941, 3216, - 0, 2945, 3213, - 0, 2950, 3208, - 0, 2957, 3202, - 0, 2966, 3194, - 0, 2977, 3182, - 0, 2992, 3166, - 0, 3012, 3144, - 0, 3036, 3112, - 0, 3067, 3066, - 0, 3105, 2995, - 0, 3152, 2880, - 0, 3208, 2659, - 0, 3273, 1829, - 0, 3348, 0, - 0, 3432, 0, - 0, 3524, 0, - 0, 3624, 0, - 0, 3731, 0, - 0, 2933, 3238, - 0, 2933, 3238, - 0, 2933, 3238, - 0, 2933, 3238, - 0, 2934, 3238, - 0, 2934, 3237, - 0, 2934, 3237, - 0, 2935, 3237, - 0, 2936, 3236, - 0, 2936, 3235, - 0, 2938, 3234, - 0, 2939, 3233, - 0, 2941, 3231, - 0, 2944, 3229, - 0, 2948, 3225, - 0, 2953, 3221, - 0, 2960, 3215, - 0, 2969, 3206, - 0, 2980, 3195, - 0, 2995, 3179, - 0, 3014, 3158, - 0, 3039, 3127, - 0, 3069, 3082, - 0, 3108, 3015, - 0, 3154, 2905, - 0, 3210, 2699, - 0, 3275, 2034, - 0, 3349, 0, - 0, 3433, 0, - 0, 3525, 0, - 0, 3625, 0, - 0, 3732, 0, - 0, 2937, 3254, - 0, 2937, 3253, - 0, 2938, 3253, - 0, 2938, 3253, - 0, 2938, 3253, - 0, 2938, 3253, - 0, 2939, 3252, - 0, 2939, 3252, - 0, 2940, 3252, - 0, 2941, 3251, - 0, 2942, 3250, - 0, 2943, 3248, - 0, 2946, 3247, - 0, 2948, 3244, - 0, 2952, 3241, - 0, 2957, 3237, - 0, 2964, 3231, - 0, 2973, 3223, - 0, 2984, 3212, - 0, 2999, 3197, - 0, 3018, 3176, - 0, 3042, 3147, - 0, 3073, 3104, - 0, 3110, 3040, - 0, 3157, 2937, - 0, 3212, 2747, - 0, 3277, 2215, - 0, 3351, 0, - 0, 3434, 0, - 0, 3526, 0, - 0, 3626, 0, - 0, 3732, 0, - 0, 2943, 3273, - 0, 2943, 3273, - 0, 2943, 3273, - 0, 2943, 3273, - 0, 2944, 3273, - 0, 2944, 3273, - 0, 2944, 3272, - 0, 2945, 3272, - 0, 2945, 3271, - 0, 2946, 3271, - 0, 2947, 3270, - 0, 2949, 3268, - 0, 2951, 3267, - 0, 2954, 3264, - 0, 2958, 3261, - 0, 2963, 3257, - 0, 2969, 3252, - 0, 2978, 3244, - 0, 2989, 3234, - 0, 3004, 3219, - 0, 3022, 3199, - 0, 3046, 3171, - 0, 3077, 3131, - 0, 3114, 3071, - 0, 3160, 2976, - 0, 3215, 2805, - 0, 3279, 2380, - 0, 3353, 0, - 0, 3436, 0, - 0, 3528, 0, - 0, 3627, 0, - 0, 3733, 0, - 1458, 2950, 3298, - 1453, 2950, 3298, - 1446, 2951, 3298, - 1437, 2951, 3298, - 1424, 2951, 3298, - 1407, 2951, 3298, - 1383, 2952, 3298, - 1348, 2952, 3297, - 1297, 2953, 3297, - 1219, 2954, 3296, - 1088, 2955, 3295, - 818, 2956, 3294, - 0, 2958, 3292, - 0, 2961, 3290, - 0, 2965, 3287, - 0, 2970, 3283, - 0, 2976, 3278, - 0, 2985, 3271, - 0, 2996, 3261, - 0, 3010, 3248, - 0, 3029, 3229, - 0, 3052, 3203, - 0, 3082, 3165, - 0, 3119, 3110, - 0, 3165, 3023, - 0, 3219, 2873, - 0, 3283, 2535, - 0, 3356, 0, - 0, 3439, 0, - 0, 3530, 0, - 0, 3629, 0, - 0, 3735, 0, - 2457, 2960, 3330, - 2456, 2960, 3330, - 2456, 2960, 3330, - 2455, 2960, 3330, - 2453, 2961, 3330, - 2451, 2961, 3330, - 2449, 2961, 3329, - 2446, 2962, 3329, - 2442, 2962, 3328, - 2436, 2963, 3328, - 2428, 2964, 3327, - 2417, 2966, 3326, - 2402, 2968, 3324, - 2382, 2971, 3322, - 2352, 2974, 3320, - 2310, 2979, 3316, - 2247, 2985, 3311, - 2145, 2994, 3304, - 1960, 3004, 3295, - 1453, 3019, 3283, - 0, 3037, 3266, - 0, 3060, 3242, - 0, 3090, 3207, - 0, 3126, 3157, - 0, 3171, 3079, - 0, 3225, 2949, - 0, 3288, 2684, - 0, 3360, 0, - 0, 3442, 0, - 0, 3533, 0, - 0, 3631, 0, - 0, 3736, 0, - 2813, 2973, 3369, - 2813, 2973, 3369, - 2812, 2973, 3369, - 2812, 2973, 3369, - 2811, 2973, 3369, - 2810, 2974, 3369, - 2809, 2974, 3369, - 2808, 2974, 3368, - 2806, 2975, 3368, - 2803, 2976, 3367, - 2800, 2977, 3366, - 2795, 2978, 3365, - 2789, 2980, 3364, - 2780, 2983, 3362, - 2768, 2987, 3360, - 2752, 2991, 3356, - 2729, 2997, 3352, - 2696, 3005, 3346, - 2648, 3016, 3337, - 2576, 3030, 3326, - 2456, 3048, 3310, - 2220, 3070, 3289, - 1140, 3099, 3258, - 0, 3135, 3213, - 0, 3179, 3145, - 0, 3232, 3035, - 0, 3294, 2828, - 0, 3366, 2152, - 0, 3447, 0, - 0, 3536, 0, - 0, 3634, 0, - 0, 3739, 0, - 3061, 2989, 3417, - 3061, 2989, 3417, - 3061, 2989, 3417, - 3060, 2989, 3417, - 3060, 2990, 3417, - 3060, 2990, 3416, - 3059, 2990, 3416, - 3058, 2991, 3416, - 3057, 2991, 3415, - 3055, 2992, 3415, - 3053, 2993, 3414, - 3051, 2995, 3413, - 3047, 2997, 3412, - 3042, 2999, 3410, - 3036, 3002, 3408, - 3027, 3007, 3405, - 3014, 3013, 3401, - 2997, 3021, 3396, - 2973, 3031, 3388, - 2939, 3044, 3378, - 2889, 3062, 3364, - 2812, 3084, 3345, - 2683, 3112, 3318, - 2421, 3147, 3279, - 0, 3189, 3221, - 0, 3241, 3129, - 0, 3302, 2969, - 0, 3373, 2588, - 0, 3452, 0, - 0, 3541, 0, - 0, 3638, 0, - 0, 3742, 0, - 3264, 3010, 3474, - 3264, 3010, 3474, - 3264, 3010, 3473, - 3263, 3010, 3473, - 3263, 3011, 3473, - 3263, 3011, 3473, - 3263, 3011, 3473, - 3262, 3012, 3473, - 3261, 3012, 3472, - 3260, 3013, 3472, - 3259, 3014, 3471, - 3257, 3015, 3470, - 3255, 3017, 3469, - 3252, 3020, 3468, - 3248, 3023, 3466, - 3242, 3027, 3463, - 3234, 3033, 3460, - 3224, 3040, 3455, - 3210, 3050, 3448, - 3190, 3063, 3440, - 3161, 3080, 3427, - 3121, 3101, 3411, - 3060, 3128, 3387, - 2964, 3162, 3354, - 2791, 3203, 3305, - 2354, 3253, 3231, - 0, 3313, 3107, - 0, 3382, 2861, - 0, 3460, 1375, - 0, 3548, 0, - 0, 3643, 0, - 0, 3746, 0, - 3442, 3037, 3540, - 3442, 3037, 3540, - 3442, 3037, 3540, - 3442, 3037, 3540, - 3442, 3037, 3540, - 3442, 3038, 3539, - 3442, 3038, 3539, - 3441, 3038, 3539, - 3441, 3039, 3539, - 3440, 3040, 3538, - 3439, 3041, 3538, - 3438, 3042, 3537, - 3437, 3044, 3536, - 3434, 3046, 3535, - 3432, 3049, 3533, - 3428, 3053, 3531, - 3423, 3058, 3528, - 3416, 3065, 3524, - 3407, 3075, 3518, - 3394, 3087, 3511, - 3376, 3103, 3500, - 3351, 3123, 3486, - 3315, 3149, 3466, - 3263, 3181, 3438, - 3182, 3221, 3398, - 3044, 3269, 3339, - 2752, 3327, 3244, - 0, 3394, 3076, - 0, 3470, 2660, - 0, 3556, 0, - 0, 3650, 0, - 0, 3751, 0, - 3606, 3070, 3616, - 3606, 3070, 3616, - 3606, 3071, 3616, - 3606, 3071, 3615, - 3606, 3071, 3615, - 3606, 3071, 3615, - 3606, 3071, 3615, - 3606, 3072, 3615, - 3605, 3072, 3615, - 3605, 3073, 3614, - 3604, 3074, 3614, - 3603, 3075, 3613, - 3602, 3077, 3613, - 3601, 3079, 3611, - 3599, 3082, 3610, - 3596, 3085, 3608, - 3593, 3090, 3605, - 3588, 3097, 3602, - 3582, 3106, 3597, - 3573, 3117, 3591, - 3561, 3132, 3582, - 3545, 3151, 3570, - 3522, 3175, 3554, - 3489, 3205, 3531, - 3442, 3243, 3499, - 3369, 3289, 3452, - 3249, 3345, 3380, - 3015, 3409, 3261, - 1952, 3483, 3030, - 0, 3567, 2039, - 0, 3659, 0, - 0, 3758, 0, - 3761, 3112, 3700, - 3761, 3112, 3700, - 3761, 3112, 3700, - 3761, 3112, 3700, - 3761, 3112, 3700, - 3761, 3112, 3700, - 3761, 3112, 3700, - 3760, 3113, 3700, - 3760, 3113, 3700, - 3760, 3114, 3699, - 3759, 3115, 3699, - 3759, 3116, 3699, - 3758, 3117, 3698, - 3757, 3119, 3697, - 3756, 3122, 3696, - 3754, 3125, 3694, - 3751, 3130, 3692, - 3748, 3136, 3689, - 3744, 3144, 3685, - 3738, 3154, 3680, - 3729, 3168, 3673, - 3718, 3185, 3663, - 3702, 3208, 3650, - 3681, 3236, 3632, - 3650, 3272, 3606, - 3606, 3315, 3569, - 3538, 3368, 3514, - 3429, 3429, 3429, - 3224, 3501, 3283, - 2573, 3581, 2960, - 0, 3671, 0, - 0, 3768, 0, - 3909, 3161, 3794, - 3909, 3161, 3794, - 3909, 3162, 3794, - 3909, 3162, 3794, - 3909, 3162, 3794, - 3909, 3162, 3794, - 3909, 3162, 3793, - 3909, 3162, 3793, - 3909, 3163, 3793, - 3908, 3163, 3793, - 3908, 3164, 3793, - 3908, 3165, 3792, - 3907, 3166, 3792, - 3906, 3168, 3791, - 3905, 3171, 3790, - 3904, 3174, 3789, - 3902, 3178, 3787, - 3900, 3183, 3785, - 3897, 3190, 3781, - 3892, 3200, 3777, - 3887, 3212, 3771, - 3879, 3228, 3764, - 3868, 3249, 3753, - 3853, 3275, 3739, - 3832, 3307, 3718, - 3803, 3348, 3690, - 3760, 3397, 3648, - 3696, 3455, 3587, - 3594, 3522, 3488, - 3407, 3599, 3311, - 2887, 3686, 2847, - 0, 3780, 0, - 4053, 3220, 3894, - 4053, 3221, 3894, - 4053, 3221, 3894, - 4053, 3221, 3894, - 4053, 3221, 3894, - 4053, 3221, 3894, - 4053, 3221, 3894, - 4053, 3221, 3894, - 4053, 3222, 3894, - 4052, 3222, 3894, - 4052, 3223, 3894, - 4052, 3224, 3893, - 4052, 3225, 3893, - 4051, 3226, 3892, - 4050, 3229, 3891, - 4049, 3231, 3890, - 4048, 3235, 3889, - 4046, 3240, 3887, - 4044, 3246, 3885, - 4041, 3254, 3881, - 4037, 3265, 3877, - 4031, 3280, 3871, - 4023, 3298, 3862, - 4013, 3321, 3851, - 3998, 3351, 3835, - 3978, 3388, 3813, - 3950, 3433, 3782, - 3908, 3487, 3737, - 3847, 3550, 3668, - 3749, 3623, 3557, - 3573, 3705, 3345, - 3119, 3796, 2630, - 4095, 3289, 4002, - 4095, 3289, 4002, - 4095, 3289, 4002, - 4095, 3289, 4002, - 4095, 3289, 4001, - 4095, 3290, 4001, - 4095, 3290, 4001, - 4095, 3290, 4001, - 4095, 3290, 4001, - 4095, 3291, 4001, - 4095, 3291, 4001, - 4095, 3292, 4001, - 4095, 3293, 4000, - 4095, 3294, 4000, - 4095, 3296, 3999, - 4095, 3298, 3998, - 4095, 3302, 3997, - 4095, 3306, 3996, - 4095, 3311, 3994, - 4095, 3318, 3991, - 4095, 3328, 3988, - 4095, 3340, 3983, - 4095, 3357, 3976, - 4095, 3377, 3967, - 4095, 3403, 3955, - 4095, 3436, 3939, - 4095, 3477, 3915, - 4092, 3526, 3882, - 4052, 3585, 3833, - 3993, 3653, 3758, - 3898, 3730, 3634, - 3730, 3816, 3387, - 4095, 3367, 4095, - 4095, 3367, 4095, - 4095, 3367, 4095, - 4095, 3367, 4095, - 4095, 3367, 4095, - 4095, 3368, 4095, - 4095, 3368, 4095, - 4095, 3368, 4095, - 4095, 3368, 4095, - 4095, 3369, 4095, - 4095, 3369, 4095, - 4095, 3370, 4095, - 4095, 3370, 4095, - 4095, 3372, 4095, - 4095, 3373, 4095, - 4095, 3375, 4095, - 4095, 3378, 4095, - 4095, 3381, 4095, - 4095, 3386, 4095, - 4095, 3392, 4095, - 4095, 3400, 4095, - 4095, 3411, 4095, - 4095, 3425, 4094, - 4095, 3442, 4088, - 4095, 3465, 4078, - 4095, 3494, 4066, - 4095, 3530, 4048, - 4095, 3574, 4023, - 4095, 3627, 3988, - 4095, 3689, 3936, - 4095, 3761, 3857, - 4042, 3842, 3721, - 0, 3052, 3322, - 0, 3052, 3322, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3054, 3320, - 0, 3054, 3320, - 0, 3055, 3319, - 0, 3056, 3318, - 0, 3057, 3317, - 0, 3059, 3316, - 0, 3061, 3314, - 0, 3064, 3311, - 0, 3068, 3307, - 0, 3073, 3302, - 0, 3080, 3295, - 0, 3089, 3286, - 0, 3101, 3273, - 0, 3116, 3256, - 0, 3136, 3231, - 0, 3161, 3196, - 0, 3192, 3144, - 0, 3231, 3064, - 0, 3278, 2929, - 0, 3335, 2647, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3052, 3322, - 0, 3052, 3322, - 0, 3053, 3322, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3054, 3320, - 0, 3054, 3320, - 0, 3055, 3319, - 0, 3056, 3319, - 0, 3057, 3317, - 0, 3059, 3316, - 0, 3061, 3314, - 0, 3064, 3311, - 0, 3068, 3307, - 0, 3073, 3302, - 0, 3080, 3295, - 0, 3089, 3286, - 0, 3101, 3273, - 0, 3116, 3256, - 0, 3136, 3231, - 0, 3161, 3196, - 0, 3192, 3144, - 0, 3231, 3065, - 0, 3278, 2930, - 0, 3335, 2648, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3052, 3322, - 0, 3052, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3054, 3321, - 0, 3054, 3320, - 0, 3055, 3319, - 0, 3056, 3319, - 0, 3057, 3318, - 0, 3059, 3316, - 0, 3061, 3314, - 0, 3064, 3311, - 0, 3068, 3307, - 0, 3073, 3302, - 0, 3080, 3296, - 0, 3089, 3286, - 0, 3101, 3274, - 0, 3116, 3256, - 0, 3136, 3231, - 0, 3161, 3196, - 0, 3192, 3145, - 0, 3231, 3065, - 0, 3278, 2930, - 0, 3335, 2648, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3052, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3321, - 0, 3053, 3321, - 0, 3054, 3321, - 0, 3054, 3320, - 0, 3055, 3320, - 0, 3056, 3319, - 0, 3057, 3318, - 0, 3059, 3316, - 0, 3061, 3314, - 0, 3064, 3311, - 0, 3068, 3308, - 0, 3073, 3303, - 0, 3080, 3296, - 0, 3089, 3286, - 0, 3101, 3274, - 0, 3116, 3256, - 0, 3136, 3232, - 0, 3161, 3197, - 0, 3192, 3145, - 0, 3231, 3065, - 0, 3278, 2930, - 0, 3335, 2649, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3321, - 0, 3054, 3321, - 0, 3054, 3321, - 0, 3055, 3320, - 0, 3056, 3319, - 0, 3057, 3318, - 0, 3059, 3316, - 0, 3061, 3314, - 0, 3064, 3312, - 0, 3068, 3308, - 0, 3073, 3303, - 0, 3080, 3296, - 0, 3089, 3287, - 0, 3101, 3274, - 0, 3116, 3256, - 0, 3136, 3232, - 0, 3161, 3197, - 0, 3192, 3145, - 0, 3231, 3065, - 0, 3278, 2931, - 0, 3335, 2650, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3053, 3323, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3053, 3322, - 0, 3054, 3322, - 0, 3054, 3321, - 0, 3054, 3321, - 0, 3055, 3320, - 0, 3056, 3319, - 0, 3057, 3318, - 0, 3059, 3317, - 0, 3061, 3315, - 0, 3064, 3312, - 0, 3068, 3308, - 0, 3073, 3303, - 0, 3080, 3296, - 0, 3089, 3287, - 0, 3101, 3274, - 0, 3116, 3257, - 0, 3136, 3232, - 0, 3161, 3197, - 0, 3192, 3146, - 0, 3231, 3066, - 0, 3279, 2932, - 0, 3335, 2651, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3322, - 0, 3054, 3322, - 0, 3054, 3322, - 0, 3055, 3321, - 0, 3055, 3321, - 0, 3056, 3320, - 0, 3057, 3319, - 0, 3059, 3317, - 0, 3061, 3315, - 0, 3064, 3312, - 0, 3068, 3309, - 0, 3073, 3304, - 0, 3080, 3297, - 0, 3089, 3287, - 0, 3101, 3275, - 0, 3116, 3257, - 0, 3136, 3233, - 0, 3161, 3198, - 0, 3192, 3146, - 0, 3231, 3067, - 0, 3279, 2932, - 0, 3335, 2653, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3053, 3323, - 0, 3054, 3323, - 0, 3054, 3322, - 0, 3055, 3322, - 0, 3055, 3321, - 0, 3056, 3320, - 0, 3058, 3319, - 0, 3059, 3318, - 0, 3061, 3316, - 0, 3064, 3313, - 0, 3068, 3309, - 0, 3074, 3304, - 0, 3080, 3297, - 0, 3089, 3288, - 0, 3101, 3275, - 0, 3116, 3258, - 0, 3136, 3233, - 0, 3161, 3198, - 0, 3192, 3147, - 0, 3231, 3068, - 0, 3279, 2934, - 0, 3335, 2655, - 0, 3401, 0, - 0, 3476, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3053, 3324, - 0, 3053, 3324, - 0, 3053, 3324, - 0, 3053, 3324, - 0, 3053, 3324, - 0, 3054, 3324, - 0, 3054, 3323, - 0, 3054, 3323, - 0, 3055, 3322, - 0, 3056, 3322, - 0, 3057, 3321, - 0, 3058, 3320, - 0, 3059, 3318, - 0, 3062, 3316, - 0, 3065, 3314, - 0, 3069, 3310, - 0, 3074, 3305, - 0, 3081, 3298, - 0, 3090, 3289, - 0, 3101, 3276, - 0, 3117, 3259, - 0, 3136, 3234, - 0, 3161, 3199, - 0, 3193, 3148, - 0, 3231, 3069, - 0, 3279, 2935, - 0, 3335, 2658, - 0, 3401, 0, - 0, 3477, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3053, 3325, - 0, 3053, 3325, - 0, 3053, 3325, - 0, 3054, 3325, - 0, 3054, 3325, - 0, 3054, 3325, - 0, 3054, 3324, - 0, 3055, 3324, - 0, 3055, 3323, - 0, 3056, 3323, - 0, 3057, 3322, - 0, 3058, 3321, - 0, 3060, 3319, - 0, 3062, 3317, - 0, 3065, 3314, - 0, 3069, 3311, - 0, 3074, 3306, - 0, 3081, 3299, - 0, 3090, 3290, - 0, 3102, 3277, - 0, 3117, 3260, - 0, 3136, 3235, - 0, 3161, 3201, - 0, 3193, 3149, - 0, 3232, 3071, - 0, 3279, 2938, - 0, 3335, 2662, - 0, 3401, 0, - 0, 3477, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3054, 3326, - 0, 3054, 3326, - 0, 3054, 3326, - 0, 3054, 3326, - 0, 3054, 3326, - 0, 3054, 3326, - 0, 3055, 3326, - 0, 3055, 3325, - 0, 3055, 3325, - 0, 3056, 3324, - 0, 3057, 3323, - 0, 3058, 3322, - 0, 3060, 3321, - 0, 3062, 3319, - 0, 3065, 3316, - 0, 3069, 3312, - 0, 3074, 3307, - 0, 3081, 3300, - 0, 3090, 3291, - 0, 3102, 3279, - 0, 3117, 3261, - 0, 3137, 3237, - 0, 3162, 3202, - 0, 3193, 3151, - 0, 3232, 3073, - 0, 3279, 2941, - 0, 3335, 2668, - 0, 3401, 0, - 0, 3477, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3054, 3328, - 0, 3054, 3328, - 0, 3054, 3328, - 0, 3054, 3328, - 0, 3054, 3328, - 0, 3055, 3327, - 0, 3055, 3327, - 0, 3055, 3327, - 0, 3056, 3326, - 0, 3057, 3326, - 0, 3057, 3325, - 0, 3059, 3324, - 0, 3060, 3322, - 0, 3063, 3320, - 0, 3066, 3318, - 0, 3069, 3314, - 0, 3075, 3309, - 0, 3081, 3302, - 0, 3090, 3293, - 0, 3102, 3281, - 0, 3117, 3263, - 0, 3137, 3239, - 0, 3162, 3204, - 0, 3193, 3154, - 0, 3232, 3076, - 0, 3279, 2944, - 0, 3336, 2675, - 0, 3402, 0, - 0, 3477, 0, - 0, 3561, 0, - 0, 3654, 0, - 0, 3755, 0, - 0, 3055, 3330, - 0, 3055, 3330, - 0, 3055, 3330, - 0, 3055, 3330, - 0, 3055, 3330, - 0, 3055, 3330, - 0, 3056, 3329, - 0, 3056, 3329, - 0, 3056, 3329, - 0, 3057, 3328, - 0, 3058, 3327, - 0, 3059, 3326, - 0, 3061, 3325, - 0, 3063, 3323, - 0, 3066, 3320, - 0, 3070, 3316, - 0, 3075, 3311, - 0, 3082, 3305, - 0, 3091, 3295, - 0, 3103, 3283, - 0, 3118, 3266, - 0, 3137, 3242, - 0, 3162, 3207, - 0, 3194, 3157, - 0, 3233, 3080, - 0, 3280, 2950, - 0, 3336, 2684, - 0, 3402, 0, - 0, 3477, 0, - 0, 3562, 0, - 0, 3655, 0, - 0, 3755, 0, - 0, 3055, 3333, - 0, 3055, 3333, - 0, 3055, 3333, - 0, 3056, 3333, - 0, 3056, 3333, - 0, 3056, 3333, - 0, 3056, 3332, - 0, 3057, 3332, - 0, 3057, 3332, - 0, 3058, 3331, - 0, 3059, 3330, - 0, 3060, 3329, - 0, 3062, 3328, - 0, 3064, 3326, - 0, 3067, 3323, - 0, 3071, 3319, - 0, 3076, 3314, - 0, 3083, 3308, - 0, 3092, 3299, - 0, 3103, 3286, - 0, 3119, 3269, - 0, 3138, 3245, - 0, 3163, 3211, - 0, 3194, 3161, - 0, 3233, 3085, - 0, 3280, 2957, - 0, 3336, 2696, - 0, 3402, 0, - 0, 3477, 0, - 0, 3562, 0, - 0, 3655, 0, - 0, 3755, 0, - 0, 3056, 3337, - 0, 3056, 3337, - 0, 3056, 3337, - 0, 3057, 3337, - 0, 3057, 3337, - 0, 3057, 3337, - 0, 3057, 3336, - 0, 3058, 3336, - 0, 3058, 3336, - 0, 3059, 3335, - 0, 3060, 3334, - 0, 3061, 3333, - 0, 3063, 3332, - 0, 3065, 3330, - 0, 3068, 3327, - 0, 3072, 3323, - 0, 3077, 3318, - 0, 3084, 3312, - 0, 3093, 3303, - 0, 3104, 3291, - 0, 3119, 3274, - 0, 3139, 3250, - 0, 3164, 3216, - 0, 3195, 3167, - 0, 3234, 3092, - 0, 3281, 2966, - 0, 3337, 2712, - 0, 3403, 0, - 0, 3478, 0, - 0, 3562, 0, - 0, 3655, 0, - 0, 3755, 0, - 0, 3058, 3342, - 0, 3058, 3342, - 0, 3058, 3342, - 0, 3058, 3342, - 0, 3058, 3342, - 0, 3058, 3342, - 0, 3059, 3342, - 0, 3059, 3341, - 0, 3060, 3341, - 0, 3060, 3340, - 0, 3061, 3339, - 0, 3062, 3338, - 0, 3064, 3337, - 0, 3066, 3335, - 0, 3069, 3332, - 0, 3073, 3329, - 0, 3078, 3324, - 0, 3085, 3317, - 0, 3094, 3309, - 0, 3106, 3296, - 0, 3121, 3280, - 0, 3140, 3256, - 0, 3165, 3223, - 0, 3196, 3175, - 0, 3235, 3100, - 0, 3282, 2977, - 0, 3338, 2733, - 0, 3403, 1334, - 0, 3478, 0, - 0, 3563, 0, - 0, 3655, 0, - 0, 3756, 0, - 0, 3059, 3349, - 0, 3060, 3349, - 0, 3060, 3349, - 0, 3060, 3349, - 0, 3060, 3349, - 0, 3060, 3349, - 0, 3060, 3349, - 0, 3061, 3348, - 0, 3061, 3348, - 0, 3062, 3347, - 0, 3063, 3346, - 0, 3064, 3345, - 0, 3066, 3344, - 0, 3068, 3342, - 0, 3071, 3339, - 0, 3075, 3336, - 0, 3080, 3331, - 0, 3087, 3325, - 0, 3096, 3316, - 0, 3107, 3304, - 0, 3122, 3288, - 0, 3142, 3265, - 0, 3166, 3232, - 0, 3197, 3185, - 0, 3236, 3112, - 0, 3283, 2993, - 0, 3339, 2758, - 0, 3404, 1707, - 0, 3479, 0, - 0, 3563, 0, - 0, 3656, 0, - 0, 3756, 0, - 0, 3062, 3358, - 0, 3062, 3358, - 0, 3062, 3358, - 0, 3062, 3358, - 0, 3062, 3358, - 0, 3063, 3358, - 0, 3063, 3358, - 0, 3063, 3357, - 0, 3064, 3357, - 0, 3064, 3356, - 0, 3065, 3355, - 0, 3067, 3354, - 0, 3068, 3353, - 0, 3070, 3351, - 0, 3073, 3349, - 0, 3077, 3345, - 0, 3082, 3341, - 0, 3089, 3334, - 0, 3098, 3326, - 0, 3109, 3314, - 0, 3124, 3298, - 0, 3144, 3276, - 0, 3168, 3244, - 0, 3199, 3198, - 0, 3238, 3127, - 0, 3284, 3012, - 0, 3340, 2791, - 0, 3405, 1961, - 0, 3480, 0, - 0, 3564, 0, - 0, 3657, 0, - 0, 3757, 0, - 0, 3065, 3370, - 0, 3065, 3370, - 0, 3065, 3370, - 0, 3065, 3370, - 0, 3066, 3370, - 0, 3066, 3370, - 0, 3066, 3369, - 0, 3066, 3369, - 0, 3067, 3369, - 0, 3068, 3368, - 0, 3069, 3367, - 0, 3070, 3366, - 0, 3071, 3365, - 0, 3074, 3363, - 0, 3076, 3361, - 0, 3080, 3357, - 0, 3085, 3353, - 0, 3092, 3347, - 0, 3101, 3338, - 0, 3112, 3327, - 0, 3127, 3312, - 0, 3146, 3290, - 0, 3171, 3259, - 0, 3202, 3214, - 0, 3240, 3147, - 0, 3286, 3037, - 0, 3342, 2831, - 0, 3407, 2166, - 0, 3481, 0, - 0, 3565, 0, - 0, 3657, 0, - 0, 3757, 0, - 0, 3069, 3386, - 0, 3069, 3386, - 0, 3070, 3386, - 0, 3070, 3385, - 0, 3070, 3385, - 0, 3070, 3385, - 0, 3070, 3385, - 0, 3071, 3385, - 0, 3071, 3384, - 0, 3072, 3384, - 0, 3073, 3383, - 0, 3074, 3382, - 0, 3076, 3381, - 0, 3078, 3379, - 0, 3081, 3376, - 0, 3084, 3373, - 0, 3089, 3369, - 0, 3096, 3363, - 0, 3105, 3355, - 0, 3116, 3344, - 0, 3131, 3329, - 0, 3150, 3308, - 0, 3174, 3279, - 0, 3205, 3236, - 0, 3243, 3172, - 0, 3289, 3069, - 0, 3344, 2880, - 0, 3409, 2347, - 0, 3483, 0, - 0, 3567, 0, - 0, 3659, 0, - 0, 3758, 0, - 0, 3075, 3405, - 0, 3075, 3405, - 0, 3075, 3405, - 0, 3075, 3405, - 0, 3075, 3405, - 0, 3076, 3405, - 0, 3076, 3405, - 0, 3076, 3404, - 0, 3077, 3404, - 0, 3077, 3404, - 0, 3078, 3403, - 0, 3080, 3402, - 0, 3081, 3401, - 0, 3083, 3399, - 0, 3086, 3397, - 0, 3090, 3393, - 0, 3095, 3389, - 0, 3101, 3384, - 0, 3110, 3376, - 0, 3121, 3366, - 0, 3136, 3351, - 0, 3155, 3332, - 0, 3179, 3304, - 0, 3209, 3263, - 0, 3246, 3203, - 0, 3292, 3108, - 0, 3347, 2937, - 0, 3411, 2512, - 0, 3485, 0, - 0, 3568, 0, - 0, 3660, 0, - 0, 3759, 0, - 1593, 3082, 3431, - 1590, 3082, 3431, - 1585, 3083, 3431, - 1578, 3083, 3430, - 1569, 3083, 3430, - 1556, 3083, 3430, - 1539, 3083, 3430, - 1515, 3084, 3430, - 1480, 3084, 3429, - 1429, 3085, 3429, - 1351, 3086, 3428, - 1220, 3087, 3427, - 950, 3088, 3426, - 0, 3090, 3424, - 0, 3093, 3422, - 0, 3097, 3419, - 0, 3102, 3415, - 0, 3108, 3410, - 0, 3117, 3403, - 0, 3128, 3393, - 0, 3142, 3380, - 0, 3161, 3361, - 0, 3184, 3335, - 0, 3214, 3297, - 0, 3252, 3242, - 0, 3297, 3155, - 0, 3351, 3005, - 0, 3415, 2667, - 0, 3488, 0, - 0, 3571, 0, - 0, 3662, 0, - 0, 3761, 0, - 2589, 3092, 3462, - 2589, 3092, 3462, - 2588, 3092, 3462, - 2588, 3092, 3462, - 2587, 3092, 3462, - 2585, 3093, 3462, - 2584, 3093, 3462, - 2581, 3093, 3461, - 2578, 3094, 3461, - 2574, 3094, 3461, - 2568, 3095, 3460, - 2560, 3096, 3459, - 2549, 3098, 3458, - 2534, 3100, 3456, - 2514, 3103, 3454, - 2484, 3106, 3452, - 2442, 3111, 3448, - 2379, 3117, 3443, - 2277, 3126, 3436, - 2092, 3137, 3427, - 1586, 3151, 3415, - 0, 3169, 3398, - 0, 3192, 3374, - 0, 3222, 3339, - 0, 3258, 3289, - 0, 3303, 3211, - 0, 3357, 3081, - 0, 3420, 2816, - 0, 3492, 0, - 0, 3574, 0, - 0, 3665, 0, - 0, 3763, 0, - 2945, 3105, 3501, - 2945, 3105, 3501, - 2945, 3105, 3501, - 2944, 3105, 3501, - 2944, 3105, 3501, - 2943, 3105, 3501, - 2942, 3106, 3501, - 2941, 3106, 3501, - 2940, 3106, 3500, - 2938, 3107, 3500, - 2935, 3108, 3499, - 2932, 3109, 3499, - 2927, 3110, 3497, - 2921, 3112, 3496, - 2912, 3115, 3494, - 2900, 3119, 3492, - 2884, 3123, 3488, - 2861, 3129, 3484, - 2828, 3137, 3478, - 2780, 3148, 3470, - 2708, 3162, 3458, - 2588, 3180, 3443, - 2352, 3202, 3421, - 1272, 3231, 3390, - 0, 3267, 3345, - 0, 3311, 3277, - 0, 3364, 3167, - 0, 3426, 2960, - 0, 3498, 2284, - 0, 3579, 0, - 0, 3669, 0, - 0, 3766, 0, - 3193, 3121, 3549, - 3193, 3121, 3549, - 3193, 3121, 3549, - 3193, 3121, 3549, - 3192, 3122, 3549, - 3192, 3122, 3549, - 3192, 3122, 3548, - 3191, 3122, 3548, - 3190, 3123, 3548, - 3189, 3123, 3548, - 3188, 3124, 3547, - 3186, 3125, 3546, - 3183, 3127, 3545, - 3179, 3129, 3544, - 3174, 3131, 3543, - 3168, 3135, 3540, - 3159, 3139, 3537, - 3146, 3145, 3533, - 3129, 3153, 3528, - 3105, 3163, 3520, - 3071, 3176, 3510, - 3021, 3194, 3496, - 2944, 3216, 3477, - 2815, 3244, 3450, - 2553, 3279, 3411, - 0, 3321, 3353, - 0, 3373, 3261, - 0, 3434, 3101, - 0, 3505, 2720, - 0, 3585, 0, - 0, 3673, 0, - 0, 3770, 0, - 3396, 3142, 3606, - 3396, 3142, 3606, - 3396, 3142, 3606, - 3396, 3142, 3606, - 3396, 3143, 3605, - 3395, 3143, 3605, - 3395, 3143, 3605, - 3395, 3143, 3605, - 3394, 3144, 3605, - 3393, 3144, 3604, - 3392, 3145, 3604, - 3391, 3146, 3603, - 3389, 3148, 3603, - 3387, 3149, 3601, - 3384, 3152, 3600, - 3380, 3155, 3598, - 3374, 3159, 3595, - 3367, 3165, 3592, - 3356, 3172, 3587, - 3342, 3182, 3581, - 3322, 3195, 3572, - 3294, 3212, 3560, - 3253, 3233, 3543, - 3192, 3260, 3519, - 3096, 3294, 3486, - 2923, 3335, 3437, - 2486, 3385, 3363, - 0, 3445, 3239, - 0, 3514, 2993, - 0, 3592, 1507, - 0, 3680, 0, - 0, 3775, 0, - 3575, 3169, 3672, - 3575, 3169, 3672, - 3574, 3169, 3672, - 3574, 3169, 3672, - 3574, 3169, 3672, - 3574, 3169, 3672, - 3574, 3170, 3672, - 3574, 3170, 3671, - 3573, 3170, 3671, - 3573, 3171, 3671, - 3572, 3172, 3670, - 3571, 3173, 3670, - 3570, 3174, 3669, - 3569, 3176, 3668, - 3567, 3178, 3667, - 3564, 3181, 3665, - 3560, 3185, 3663, - 3555, 3190, 3660, - 3548, 3198, 3656, - 3539, 3207, 3650, - 3526, 3219, 3643, - 3508, 3235, 3632, - 3483, 3255, 3618, - 3448, 3281, 3598, - 3395, 3313, 3571, - 3314, 3353, 3531, - 3176, 3401, 3471, - 2884, 3459, 3376, - 0, 3526, 3208, - 0, 3602, 2792, - 0, 3688, 0, - 0, 3782, 0, - 3739, 3202, 3748, - 3739, 3202, 3748, - 3739, 3203, 3748, - 3738, 3203, 3748, - 3738, 3203, 3748, - 3738, 3203, 3747, - 3738, 3203, 3747, - 3738, 3203, 3747, - 3738, 3204, 3747, - 3737, 3204, 3747, - 3737, 3205, 3746, - 3736, 3206, 3746, - 3736, 3207, 3745, - 3734, 3209, 3745, - 3733, 3211, 3744, - 3731, 3214, 3742, - 3728, 3217, 3740, - 3725, 3222, 3738, - 3720, 3229, 3734, - 3714, 3238, 3729, - 3705, 3249, 3723, - 3693, 3264, 3714, - 3677, 3283, 3703, - 3654, 3307, 3686, - 3621, 3338, 3663, - 3574, 3375, 3631, - 3501, 3422, 3584, - 3381, 3477, 3512, - 3147, 3541, 3393, - 2084, 3616, 3162, - 0, 3699, 2171, - 0, 3791, 0, - 3893, 3244, 3833, - 3893, 3244, 3833, - 3893, 3244, 3833, - 3893, 3244, 3832, - 3893, 3244, 3832, - 3893, 3244, 3832, - 3893, 3244, 3832, - 3893, 3244, 3832, - 3893, 3245, 3832, - 3892, 3245, 3832, - 3892, 3246, 3832, - 3892, 3247, 3831, - 3891, 3248, 3831, - 3890, 3249, 3830, - 3889, 3251, 3829, - 3888, 3254, 3828, - 3886, 3257, 3826, - 3884, 3262, 3824, - 3880, 3268, 3821, - 3876, 3276, 3817, - 3870, 3286, 3812, - 3861, 3300, 3805, - 3850, 3318, 3795, - 3835, 3340, 3782, - 3813, 3368, 3764, - 3782, 3404, 3738, - 3738, 3447, 3701, - 3670, 3500, 3646, - 3561, 3561, 3561, - 3357, 3633, 3415, - 2705, 3713, 3092, - 0, 3803, 0, - 4041, 3293, 3926, - 4041, 3293, 3926, - 4041, 3294, 3926, - 4041, 3294, 3926, - 4041, 3294, 3926, - 4041, 3294, 3926, - 4041, 3294, 3926, - 4041, 3294, 3926, - 4041, 3295, 3925, - 4041, 3295, 3925, - 4041, 3296, 3925, - 4040, 3296, 3925, - 4040, 3297, 3924, - 4039, 3299, 3924, - 4039, 3300, 3923, - 4038, 3303, 3922, - 4036, 3306, 3921, - 4034, 3310, 3919, - 4032, 3315, 3917, - 4029, 3322, 3914, - 4025, 3332, 3909, - 4019, 3344, 3904, - 4011, 3360, 3896, - 4000, 3381, 3885, - 3985, 3407, 3871, - 3964, 3440, 3850, - 3935, 3480, 3822, - 3892, 3529, 3781, - 3829, 3587, 3719, - 3726, 3654, 3620, - 3539, 3732, 3443, - 3019, 3818, 2979, - 4095, 3353, 4027, - 4095, 3353, 4027, - 4095, 3353, 4027, - 4095, 3353, 4027, - 4095, 3353, 4026, - 4095, 3353, 4026, - 4095, 3353, 4026, - 4095, 3353, 4026, - 4095, 3354, 4026, - 4095, 3354, 4026, - 4095, 3354, 4026, - 4095, 3355, 4026, - 4095, 3356, 4025, - 4095, 3357, 4025, - 4095, 3359, 4024, - 4095, 3361, 4024, - 4095, 3363, 4023, - 4095, 3367, 4021, - 4095, 3372, 4019, - 4095, 3378, 4017, - 4095, 3387, 4013, - 4095, 3397, 4009, - 4095, 3412, 4003, - 4095, 3430, 3994, - 4095, 3454, 3983, - 4095, 3483, 3967, - 4095, 3520, 3945, - 4082, 3565, 3914, - 4041, 3619, 3869, - 3979, 3682, 3800, - 3881, 3755, 3689, - 3706, 3837, 3477, - 4095, 3421, 4095, - 4095, 3421, 4095, - 4095, 3421, 4095, - 4095, 3421, 4095, - 4095, 3421, 4095, - 4095, 3421, 4095, - 4095, 3422, 4095, - 4095, 3422, 4095, - 4095, 3422, 4095, - 4095, 3422, 4095, - 4095, 3423, 4095, - 4095, 3423, 4095, - 4095, 3424, 4095, - 4095, 3425, 4095, - 4095, 3426, 4095, - 4095, 3428, 4095, - 4095, 3431, 4095, - 4095, 3434, 4095, - 4095, 3438, 4095, - 4095, 3443, 4095, - 4095, 3451, 4095, - 4095, 3460, 4095, - 4095, 3473, 4095, - 4095, 3489, 4095, - 4095, 3509, 4095, - 4095, 3536, 4087, - 4095, 3568, 4071, - 4095, 3609, 4047, - 4095, 3658, 4014, - 4095, 3717, 3965, - 4095, 3785, 3891, - 4030, 3862, 3767, - 0, 3184, 3454, - 0, 3184, 3454, - 0, 3185, 3454, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3186, 3452, - 0, 3186, 3452, - 0, 3187, 3451, - 0, 3188, 3450, - 0, 3189, 3449, - 0, 3191, 3448, - 0, 3193, 3446, - 0, 3196, 3443, - 0, 3200, 3439, - 0, 3205, 3434, - 0, 3212, 3427, - 0, 3221, 3418, - 0, 3233, 3405, - 0, 3248, 3388, - 0, 3268, 3363, - 0, 3293, 3328, - 0, 3324, 3276, - 0, 3363, 3196, - 0, 3410, 3061, - 0, 3467, 2779, - 0, 3533, 0, - 0, 3608, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3184, 3454, - 0, 3184, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3186, 3452, - 0, 3186, 3452, - 0, 3187, 3451, - 0, 3188, 3451, - 0, 3189, 3449, - 0, 3191, 3448, - 0, 3193, 3446, - 0, 3196, 3443, - 0, 3200, 3439, - 0, 3205, 3434, - 0, 3212, 3427, - 0, 3221, 3418, - 0, 3233, 3405, - 0, 3248, 3388, - 0, 3268, 3363, - 0, 3293, 3328, - 0, 3324, 3276, - 0, 3363, 3196, - 0, 3410, 3061, - 0, 3467, 2779, - 0, 3533, 0, - 0, 3608, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3184, 3454, - 0, 3184, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3186, 3453, - 0, 3186, 3452, - 0, 3187, 3451, - 0, 3188, 3451, - 0, 3189, 3449, - 0, 3191, 3448, - 0, 3193, 3446, - 0, 3196, 3443, - 0, 3200, 3439, - 0, 3205, 3434, - 0, 3212, 3428, - 0, 3221, 3418, - 0, 3233, 3406, - 0, 3248, 3388, - 0, 3268, 3363, - 0, 3293, 3328, - 0, 3324, 3277, - 0, 3363, 3197, - 0, 3411, 3062, - 0, 3467, 2780, - 0, 3533, 0, - 0, 3608, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3184, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3453, - 0, 3185, 3453, - 0, 3186, 3453, - 0, 3186, 3452, - 0, 3187, 3452, - 0, 3188, 3451, - 0, 3189, 3450, - 0, 3191, 3448, - 0, 3193, 3446, - 0, 3196, 3443, - 0, 3200, 3440, - 0, 3205, 3434, - 0, 3212, 3428, - 0, 3221, 3418, - 0, 3233, 3406, - 0, 3248, 3388, - 0, 3268, 3364, - 0, 3293, 3328, - 0, 3324, 3277, - 0, 3363, 3197, - 0, 3411, 3062, - 0, 3467, 2780, - 0, 3533, 0, - 0, 3608, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3184, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3453, - 0, 3186, 3453, - 0, 3186, 3453, - 0, 3186, 3452, - 0, 3187, 3452, - 0, 3188, 3451, - 0, 3189, 3450, - 0, 3191, 3448, - 0, 3193, 3446, - 0, 3196, 3443, - 0, 3200, 3440, - 0, 3205, 3435, - 0, 3212, 3428, - 0, 3221, 3419, - 0, 3233, 3406, - 0, 3248, 3388, - 0, 3268, 3364, - 0, 3293, 3329, - 0, 3324, 3277, - 0, 3363, 3197, - 0, 3411, 3062, - 0, 3467, 2781, - 0, 3533, 0, - 0, 3608, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3186, 3453, - 0, 3186, 3453, - 0, 3186, 3453, - 0, 3187, 3452, - 0, 3188, 3451, - 0, 3189, 3450, - 0, 3191, 3448, - 0, 3193, 3446, - 0, 3196, 3444, - 0, 3200, 3440, - 0, 3205, 3435, - 0, 3212, 3428, - 0, 3221, 3419, - 0, 3233, 3406, - 0, 3248, 3389, - 0, 3268, 3364, - 0, 3293, 3329, - 0, 3324, 3277, - 0, 3363, 3198, - 0, 3411, 3063, - 0, 3467, 2782, - 0, 3533, 0, - 0, 3608, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3185, 3454, - 0, 3186, 3454, - 0, 3186, 3453, - 0, 3187, 3453, - 0, 3187, 3452, - 0, 3188, 3451, - 0, 3189, 3450, - 0, 3191, 3449, - 0, 3193, 3447, - 0, 3196, 3444, - 0, 3200, 3440, - 0, 3205, 3435, - 0, 3212, 3428, - 0, 3221, 3419, - 0, 3233, 3406, - 0, 3248, 3389, - 0, 3268, 3364, - 0, 3293, 3329, - 0, 3324, 3278, - 0, 3363, 3198, - 0, 3411, 3064, - 0, 3467, 2783, - 0, 3533, 0, - 0, 3609, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3454, - 0, 3186, 3454, - 0, 3186, 3454, - 0, 3187, 3453, - 0, 3187, 3453, - 0, 3188, 3452, - 0, 3190, 3451, - 0, 3191, 3449, - 0, 3193, 3447, - 0, 3196, 3444, - 0, 3200, 3441, - 0, 3205, 3436, - 0, 3212, 3429, - 0, 3221, 3420, - 0, 3233, 3407, - 0, 3248, 3389, - 0, 3268, 3365, - 0, 3293, 3330, - 0, 3324, 3278, - 0, 3363, 3199, - 0, 3411, 3065, - 0, 3467, 2785, - 0, 3533, 0, - 0, 3609, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3185, 3456, - 0, 3185, 3456, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3185, 3455, - 0, 3186, 3455, - 0, 3186, 3455, - 0, 3186, 3454, - 0, 3187, 3454, - 0, 3187, 3453, - 0, 3188, 3452, - 0, 3190, 3451, - 0, 3191, 3450, - 0, 3194, 3448, - 0, 3197, 3445, - 0, 3200, 3441, - 0, 3206, 3436, - 0, 3212, 3429, - 0, 3221, 3420, - 0, 3233, 3407, - 0, 3248, 3390, - 0, 3268, 3365, - 0, 3293, 3331, - 0, 3325, 3279, - 0, 3363, 3200, - 0, 3411, 3066, - 0, 3467, 2787, - 0, 3533, 0, - 0, 3609, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3185, 3456, - 0, 3185, 3456, - 0, 3185, 3456, - 0, 3185, 3456, - 0, 3185, 3456, - 0, 3186, 3456, - 0, 3186, 3456, - 0, 3186, 3455, - 0, 3186, 3455, - 0, 3187, 3455, - 0, 3188, 3454, - 0, 3189, 3453, - 0, 3190, 3452, - 0, 3192, 3450, - 0, 3194, 3448, - 0, 3197, 3446, - 0, 3201, 3442, - 0, 3206, 3437, - 0, 3213, 3430, - 0, 3222, 3421, - 0, 3233, 3408, - 0, 3249, 3391, - 0, 3268, 3366, - 0, 3293, 3331, - 0, 3325, 3280, - 0, 3364, 3201, - 0, 3411, 3067, - 0, 3467, 2790, - 0, 3533, 0, - 0, 3609, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3185, 3457, - 0, 3185, 3457, - 0, 3185, 3457, - 0, 3185, 3457, - 0, 3186, 3457, - 0, 3186, 3457, - 0, 3186, 3457, - 0, 3186, 3456, - 0, 3187, 3456, - 0, 3187, 3456, - 0, 3188, 3455, - 0, 3189, 3454, - 0, 3190, 3453, - 0, 3192, 3451, - 0, 3194, 3449, - 0, 3197, 3447, - 0, 3201, 3443, - 0, 3206, 3438, - 0, 3213, 3431, - 0, 3222, 3422, - 0, 3234, 3409, - 0, 3249, 3392, - 0, 3268, 3368, - 0, 3293, 3333, - 0, 3325, 3282, - 0, 3364, 3203, - 0, 3411, 3070, - 0, 3467, 2794, - 0, 3533, 0, - 0, 3609, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3186, 3459, - 0, 3186, 3458, - 0, 3186, 3458, - 0, 3186, 3458, - 0, 3186, 3458, - 0, 3186, 3458, - 0, 3186, 3458, - 0, 3187, 3458, - 0, 3187, 3457, - 0, 3188, 3457, - 0, 3188, 3456, - 0, 3189, 3455, - 0, 3190, 3454, - 0, 3192, 3453, - 0, 3194, 3451, - 0, 3197, 3448, - 0, 3201, 3444, - 0, 3206, 3439, - 0, 3213, 3432, - 0, 3222, 3423, - 0, 3234, 3411, - 0, 3249, 3393, - 0, 3269, 3369, - 0, 3294, 3334, - 0, 3325, 3283, - 0, 3364, 3205, - 0, 3411, 3073, - 0, 3468, 2800, - 0, 3533, 0, - 0, 3609, 0, - 0, 3693, 0, - 0, 3786, 0, - 0, 3186, 3460, - 0, 3186, 3460, - 0, 3186, 3460, - 0, 3186, 3460, - 0, 3186, 3460, - 0, 3187, 3460, - 0, 3187, 3460, - 0, 3187, 3459, - 0, 3187, 3459, - 0, 3188, 3458, - 0, 3189, 3458, - 0, 3190, 3457, - 0, 3191, 3456, - 0, 3193, 3454, - 0, 3195, 3452, - 0, 3198, 3450, - 0, 3202, 3446, - 0, 3207, 3441, - 0, 3214, 3434, - 0, 3223, 3425, - 0, 3234, 3413, - 0, 3250, 3395, - 0, 3269, 3371, - 0, 3294, 3337, - 0, 3325, 3286, - 0, 3364, 3208, - 0, 3411, 3077, - 0, 3468, 2807, - 0, 3534, 0, - 0, 3609, 0, - 0, 3694, 0, - 0, 3787, 0, - 0, 3187, 3462, - 0, 3187, 3462, - 0, 3187, 3462, - 0, 3187, 3462, - 0, 3187, 3462, - 0, 3187, 3462, - 0, 3187, 3462, - 0, 3188, 3462, - 0, 3188, 3461, - 0, 3189, 3461, - 0, 3189, 3460, - 0, 3190, 3459, - 0, 3191, 3458, - 0, 3193, 3457, - 0, 3195, 3455, - 0, 3198, 3452, - 0, 3202, 3448, - 0, 3207, 3443, - 0, 3214, 3437, - 0, 3223, 3428, - 0, 3235, 3415, - 0, 3250, 3398, - 0, 3270, 3374, - 0, 3295, 3339, - 0, 3326, 3289, - 0, 3365, 3212, - 0, 3412, 3082, - 0, 3468, 2816, - 0, 3534, 0, - 0, 3609, 0, - 0, 3694, 0, - 0, 3787, 0, - 0, 3187, 3465, - 0, 3187, 3465, - 0, 3187, 3465, - 0, 3188, 3465, - 0, 3188, 3465, - 0, 3188, 3465, - 0, 3188, 3465, - 0, 3188, 3465, - 0, 3189, 3464, - 0, 3189, 3464, - 0, 3190, 3463, - 0, 3191, 3462, - 0, 3192, 3461, - 0, 3194, 3460, - 0, 3196, 3458, - 0, 3199, 3455, - 0, 3203, 3451, - 0, 3208, 3446, - 0, 3215, 3440, - 0, 3224, 3431, - 0, 3235, 3418, - 0, 3251, 3401, - 0, 3270, 3377, - 0, 3295, 3343, - 0, 3326, 3293, - 0, 3365, 3217, - 0, 3412, 3089, - 0, 3469, 2829, - 0, 3534, 0, - 0, 3610, 0, - 0, 3694, 0, - 0, 3787, 0, - 0, 3188, 3469, - 0, 3188, 3469, - 0, 3188, 3469, - 0, 3189, 3469, - 0, 3189, 3469, - 0, 3189, 3469, - 0, 3189, 3469, - 0, 3189, 3468, - 0, 3190, 3468, - 0, 3190, 3468, - 0, 3191, 3467, - 0, 3192, 3466, - 0, 3193, 3465, - 0, 3195, 3464, - 0, 3197, 3462, - 0, 3200, 3459, - 0, 3204, 3455, - 0, 3209, 3451, - 0, 3216, 3444, - 0, 3225, 3435, - 0, 3236, 3423, - 0, 3252, 3406, - 0, 3271, 3382, - 0, 3296, 3349, - 0, 3327, 3299, - 0, 3366, 3224, - 0, 3413, 3098, - 0, 3469, 2844, - 0, 3535, 106, - 0, 3610, 0, - 0, 3694, 0, - 0, 3787, 0, - 0, 3190, 3475, - 0, 3190, 3475, - 0, 3190, 3474, - 0, 3190, 3474, - 0, 3190, 3474, - 0, 3190, 3474, - 0, 3190, 3474, - 0, 3191, 3474, - 0, 3191, 3473, - 0, 3192, 3473, - 0, 3192, 3472, - 0, 3193, 3471, - 0, 3195, 3470, - 0, 3196, 3469, - 0, 3198, 3467, - 0, 3201, 3464, - 0, 3205, 3461, - 0, 3210, 3456, - 0, 3217, 3449, - 0, 3226, 3441, - 0, 3238, 3429, - 0, 3253, 3412, - 0, 3272, 3389, - 0, 3297, 3355, - 0, 3328, 3307, - 0, 3367, 3233, - 0, 3414, 3109, - 0, 3470, 2865, - 0, 3535, 1466, - 0, 3611, 0, - 0, 3695, 0, - 0, 3788, 0, - 0, 3192, 3481, - 0, 3192, 3481, - 0, 3192, 3481, - 0, 3192, 3481, - 0, 3192, 3481, - 0, 3192, 3481, - 0, 3192, 3481, - 0, 3193, 3481, - 0, 3193, 3480, - 0, 3193, 3480, - 0, 3194, 3479, - 0, 3195, 3478, - 0, 3196, 3477, - 0, 3198, 3476, - 0, 3200, 3474, - 0, 3203, 3471, - 0, 3207, 3468, - 0, 3212, 3463, - 0, 3219, 3457, - 0, 3228, 3448, - 0, 3239, 3436, - 0, 3254, 3420, - 0, 3274, 3397, - 0, 3298, 3364, - 0, 3329, 3317, - 0, 3368, 3244, - 0, 3415, 3125, - 0, 3471, 2891, - 0, 3536, 1839, - 0, 3611, 0, - 0, 3695, 0, - 0, 3788, 0, - 0, 3194, 3491, - 0, 3194, 3491, - 0, 3194, 3490, - 0, 3194, 3490, - 0, 3194, 3490, - 0, 3194, 3490, - 0, 3195, 3490, - 0, 3195, 3490, - 0, 3195, 3489, - 0, 3196, 3489, - 0, 3197, 3488, - 0, 3197, 3488, - 0, 3199, 3487, - 0, 3200, 3485, - 0, 3202, 3483, - 0, 3205, 3481, - 0, 3209, 3477, - 0, 3214, 3473, - 0, 3221, 3466, - 0, 3230, 3458, - 0, 3241, 3446, - 0, 3256, 3430, - 0, 3276, 3408, - 0, 3300, 3376, - 0, 3331, 3330, - 0, 3370, 3259, - 0, 3416, 3144, - 0, 3472, 2923, - 0, 3537, 2093, - 0, 3612, 0, - 0, 3696, 0, - 0, 3789, 0, - 0, 3197, 3502, - 0, 3197, 3502, - 0, 3197, 3502, - 0, 3197, 3502, - 0, 3197, 3502, - 0, 3198, 3502, - 0, 3198, 3502, - 0, 3198, 3502, - 0, 3199, 3501, - 0, 3199, 3501, - 0, 3200, 3500, - 0, 3201, 3500, - 0, 3202, 3498, - 0, 3203, 3497, - 0, 3206, 3495, - 0, 3209, 3493, - 0, 3212, 3489, - 0, 3217, 3485, - 0, 3224, 3479, - 0, 3233, 3471, - 0, 3244, 3459, - 0, 3259, 3444, - 0, 3278, 3422, - 0, 3303, 3391, - 0, 3334, 3347, - 0, 3372, 3279, - 0, 3418, 3169, - 0, 3474, 2963, - 0, 3539, 2299, - 0, 3613, 0, - 0, 3697, 0, - 0, 3790, 0, - 0, 3201, 3518, - 0, 3201, 3518, - 0, 3202, 3518, - 0, 3202, 3518, - 0, 3202, 3518, - 0, 3202, 3517, - 0, 3202, 3517, - 0, 3202, 3517, - 0, 3203, 3517, - 0, 3203, 3516, - 0, 3204, 3516, - 0, 3205, 3515, - 0, 3206, 3514, - 0, 3208, 3513, - 0, 3210, 3511, - 0, 3213, 3508, - 0, 3216, 3505, - 0, 3221, 3501, - 0, 3228, 3495, - 0, 3237, 3487, - 0, 3248, 3476, - 0, 3263, 3461, - 0, 3282, 3440, - 0, 3306, 3411, - 0, 3337, 3368, - 0, 3375, 3304, - 0, 3421, 3201, - 0, 3476, 3012, - 0, 3541, 2479, - 0, 3615, 0, - 0, 3699, 0, - 0, 3791, 0, - 0, 3207, 3538, - 0, 3207, 3538, - 0, 3207, 3537, - 0, 3207, 3537, - 0, 3207, 3537, - 0, 3207, 3537, - 0, 3208, 3537, - 0, 3208, 3537, - 0, 3208, 3537, - 0, 3209, 3536, - 0, 3210, 3536, - 0, 3210, 3535, - 0, 3212, 3534, - 0, 3213, 3533, - 0, 3215, 3531, - 0, 3218, 3529, - 0, 3222, 3526, - 0, 3227, 3521, - 0, 3233, 3516, - 0, 3242, 3508, - 0, 3253, 3498, - 0, 3268, 3483, - 0, 3287, 3464, - 0, 3311, 3436, - 0, 3341, 3395, - 0, 3379, 3335, - 0, 3424, 3240, - 0, 3479, 3069, - 0, 3544, 2644, - 0, 3617, 0, - 0, 3701, 0, - 0, 3792, 0, - 1728, 3214, 3563, - 1725, 3214, 3563, - 1722, 3215, 3563, - 1717, 3215, 3563, - 1710, 3215, 3563, - 1701, 3215, 3562, - 1688, 3215, 3562, - 1671, 3215, 3562, - 1647, 3216, 3562, - 1612, 3216, 3561, - 1562, 3217, 3561, - 1483, 3218, 3560, - 1352, 3219, 3559, - 1082, 3220, 3558, - 0, 3223, 3557, - 0, 3225, 3554, - 0, 3229, 3551, - 0, 3234, 3548, - 0, 3240, 3542, - 0, 3249, 3535, - 0, 3260, 3525, - 0, 3274, 3512, - 0, 3293, 3493, - 0, 3317, 3467, - 0, 3346, 3429, - 0, 3384, 3374, - 0, 3429, 3287, - 0, 3483, 3137, - 0, 3547, 2799, - 0, 3620, 0, - 0, 3703, 0, - 0, 3794, 0, - 2722, 3224, 3594, - 2721, 3224, 3594, - 2721, 3224, 3594, - 2720, 3224, 3594, - 2720, 3224, 3594, - 2719, 3225, 3594, - 2717, 3225, 3594, - 2716, 3225, 3594, - 2713, 3225, 3593, - 2710, 3226, 3593, - 2706, 3227, 3593, - 2700, 3227, 3592, - 2692, 3229, 3591, - 2681, 3230, 3590, - 2666, 3232, 3589, - 2646, 3235, 3587, - 2617, 3238, 3584, - 2574, 3243, 3580, - 2511, 3250, 3575, - 2410, 3258, 3569, - 2224, 3269, 3559, - 1718, 3283, 3547, - 0, 3301, 3530, - 0, 3324, 3506, - 0, 3354, 3471, - 0, 3390, 3421, - 0, 3435, 3343, - 0, 3489, 3214, - 0, 3552, 2948, - 0, 3624, 0, - 0, 3706, 0, - 0, 3797, 0, - 3077, 3237, 3634, - 3077, 3237, 3634, - 3077, 3237, 3633, - 3077, 3237, 3633, - 3076, 3237, 3633, - 3076, 3237, 3633, - 3075, 3237, 3633, - 3075, 3238, 3633, - 3073, 3238, 3633, - 3072, 3239, 3632, - 3070, 3239, 3632, - 3068, 3240, 3631, - 3064, 3241, 3631, - 3059, 3243, 3630, - 3053, 3245, 3628, - 3044, 3247, 3626, - 3032, 3251, 3624, - 3016, 3255, 3621, - 2993, 3262, 3616, - 2960, 3270, 3610, - 2913, 3280, 3602, - 2840, 3294, 3590, - 2720, 3312, 3575, - 2485, 3335, 3553, - 1404, 3363, 3522, - 0, 3399, 3477, - 0, 3443, 3409, - 0, 3496, 3299, - 0, 3558, 3092, - 0, 3630, 2417, - 0, 3711, 0, - 0, 3801, 0, - 3325, 3253, 3681, - 3325, 3253, 3681, - 3325, 3253, 3681, - 3325, 3253, 3681, - 3325, 3254, 3681, - 3325, 3254, 3681, - 3324, 3254, 3681, - 3324, 3254, 3681, - 3323, 3254, 3680, - 3322, 3255, 3680, - 3321, 3255, 3680, - 3320, 3256, 3679, - 3318, 3257, 3678, - 3315, 3259, 3678, - 3311, 3261, 3676, - 3306, 3263, 3675, - 3300, 3267, 3672, - 3291, 3271, 3669, - 3278, 3277, 3665, - 3261, 3285, 3660, - 3237, 3295, 3652, - 3203, 3308, 3642, - 3153, 3326, 3628, - 3076, 3348, 3609, - 2947, 3376, 3582, - 2685, 3411, 3543, - 0, 3454, 3485, - 0, 3505, 3394, - 0, 3566, 3233, - 0, 3637, 2852, - 0, 3717, 0, - 0, 3805, 0, - 3528, 3274, 3738, - 3528, 3274, 3738, - 3528, 3274, 3738, - 3528, 3274, 3738, - 3528, 3275, 3738, - 3528, 3275, 3738, - 3527, 3275, 3737, - 3527, 3275, 3737, - 3527, 3275, 3737, - 3526, 3276, 3737, - 3525, 3276, 3737, - 3525, 3277, 3736, - 3523, 3278, 3735, - 3522, 3280, 3735, - 3519, 3281, 3734, - 3516, 3284, 3732, - 3512, 3287, 3730, - 3506, 3291, 3728, - 3499, 3297, 3724, - 3488, 3305, 3719, - 3474, 3314, 3713, - 3454, 3327, 3704, - 3426, 3344, 3692, - 3385, 3365, 3675, - 3324, 3392, 3652, - 3228, 3426, 3618, - 3055, 3467, 3570, - 2618, 3517, 3495, - 0, 3577, 3371, - 0, 3646, 3125, - 0, 3724, 1639, - 0, 3812, 0, - 3707, 3301, 3804, - 3707, 3301, 3804, - 3707, 3301, 3804, - 3707, 3301, 3804, - 3707, 3301, 3804, - 3706, 3301, 3804, - 3706, 3302, 3804, - 3706, 3302, 3804, - 3706, 3302, 3803, - 3705, 3303, 3803, - 3705, 3303, 3803, - 3704, 3304, 3803, - 3703, 3305, 3802, - 3702, 3306, 3801, - 3701, 3308, 3800, - 3699, 3310, 3799, - 3696, 3313, 3797, - 3692, 3317, 3795, - 3687, 3323, 3792, - 3680, 3330, 3788, - 3671, 3339, 3782, - 3658, 3351, 3775, - 3640, 3367, 3764, - 3615, 3387, 3750, - 3580, 3413, 3730, - 3527, 3445, 3703, - 3446, 3485, 3663, - 3308, 3533, 3603, - 3017, 3591, 3508, - 0, 3658, 3340, - 0, 3734, 2924, - 0, 3820, 0, - 3871, 3334, 3880, - 3871, 3334, 3880, - 3871, 3335, 3880, - 3871, 3335, 3880, - 3871, 3335, 3880, - 3871, 3335, 3880, - 3870, 3335, 3880, - 3870, 3335, 3879, - 3870, 3335, 3879, - 3870, 3336, 3879, - 3869, 3336, 3879, - 3869, 3337, 3879, - 3868, 3338, 3878, - 3868, 3339, 3878, - 3867, 3341, 3877, - 3865, 3343, 3876, - 3863, 3346, 3874, - 3861, 3349, 3872, - 3857, 3354, 3870, - 3852, 3361, 3866, - 3846, 3370, 3862, - 3837, 3381, 3855, - 3825, 3396, 3846, - 3809, 3415, 3835, - 3786, 3439, 3818, - 3753, 3470, 3796, - 3706, 3507, 3763, - 3633, 3554, 3716, - 3513, 3609, 3644, - 3279, 3673, 3525, - 2216, 3748, 3294, - 0, 3831, 2303, - 4025, 3376, 3965, - 4025, 3376, 3965, - 4025, 3376, 3965, - 4025, 3376, 3965, - 4025, 3376, 3965, - 4025, 3376, 3965, - 4025, 3376, 3964, - 4025, 3376, 3964, - 4025, 3377, 3964, - 4025, 3377, 3964, - 4024, 3377, 3964, - 4024, 3378, 3964, - 4024, 3379, 3963, - 4023, 3380, 3963, - 4022, 3381, 3962, - 4021, 3383, 3961, - 4020, 3386, 3960, - 4018, 3389, 3958, - 4016, 3394, 3956, - 4012, 3400, 3953, - 4008, 3408, 3950, - 4002, 3418, 3944, - 3993, 3432, 3937, - 3982, 3450, 3928, - 3967, 3472, 3914, - 3945, 3501, 3896, - 3914, 3536, 3870, - 3870, 3579, 3833, - 3803, 3632, 3779, - 3693, 3693, 3693, - 3489, 3765, 3547, - 2837, 3845, 3224, - 4095, 3425, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3426, 4058, - 4095, 3427, 4057, - 4095, 3427, 4057, - 4095, 3428, 4057, - 4095, 3428, 4057, - 4095, 3429, 4056, - 4095, 3431, 4056, - 4095, 3432, 4055, - 4095, 3435, 4054, - 4095, 3438, 4053, - 4095, 3442, 4051, - 4095, 3447, 4049, - 4095, 3455, 4046, - 4095, 3464, 4041, - 4095, 3476, 4036, - 4095, 3492, 4028, - 4095, 3513, 4017, - 4095, 3539, 4003, - 4095, 3572, 3982, - 4067, 3612, 3954, - 4024, 3661, 3913, - 3961, 3719, 3851, - 3858, 3787, 3752, - 3671, 3864, 3575, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3485, 4095, - 4095, 3486, 4095, - 4095, 3486, 4095, - 4095, 3486, 4095, - 4095, 3487, 4095, - 4095, 3488, 4095, - 4095, 3489, 4095, - 4095, 3491, 4095, - 4095, 3493, 4095, - 4095, 3495, 4095, - 4095, 3499, 4095, - 4095, 3504, 4095, - 4095, 3510, 4095, - 4095, 3519, 4095, - 4095, 3530, 4095, - 4095, 3544, 4095, - 4095, 3562, 4095, - 4095, 3586, 4095, - 4095, 3615, 4095, - 4095, 3652, 4077, - 4095, 3697, 4046, - 4095, 3751, 4001, - 4095, 3814, 3932, - 4014, 3887, 3821, - 0, 3316, 3586, - 0, 3316, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3318, 3584, - 0, 3318, 3584, - 0, 3319, 3583, - 0, 3320, 3582, - 0, 3321, 3581, - 0, 3323, 3580, - 0, 3325, 3578, - 0, 3328, 3575, - 0, 3332, 3571, - 0, 3337, 3566, - 0, 3344, 3559, - 0, 3353, 3550, - 0, 3365, 3537, - 0, 3380, 3520, - 0, 3400, 3495, - 0, 3425, 3460, - 0, 3456, 3408, - 0, 3495, 3328, - 0, 3543, 3193, - 0, 3599, 2911, - 0, 3665, 0, - 0, 3740, 0, - 0, 3825, 0, - 0, 3316, 3586, - 0, 3316, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3318, 3585, - 0, 3318, 3584, - 0, 3319, 3583, - 0, 3320, 3583, - 0, 3321, 3581, - 0, 3323, 3580, - 0, 3325, 3578, - 0, 3328, 3575, - 0, 3332, 3571, - 0, 3337, 3566, - 0, 3344, 3559, - 0, 3353, 3550, - 0, 3365, 3537, - 0, 3380, 3520, - 0, 3400, 3495, - 0, 3425, 3460, - 0, 3456, 3408, - 0, 3495, 3328, - 0, 3543, 3193, - 0, 3599, 2911, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3316, 3586, - 0, 3316, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3318, 3585, - 0, 3318, 3585, - 0, 3318, 3584, - 0, 3319, 3583, - 0, 3320, 3583, - 0, 3321, 3581, - 0, 3323, 3580, - 0, 3325, 3578, - 0, 3328, 3575, - 0, 3332, 3571, - 0, 3337, 3566, - 0, 3344, 3560, - 0, 3353, 3550, - 0, 3365, 3538, - 0, 3380, 3520, - 0, 3400, 3495, - 0, 3425, 3460, - 0, 3456, 3408, - 0, 3495, 3329, - 0, 3543, 3194, - 0, 3599, 2911, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3316, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3585, - 0, 3317, 3585, - 0, 3318, 3585, - 0, 3318, 3585, - 0, 3318, 3584, - 0, 3319, 3584, - 0, 3320, 3583, - 0, 3321, 3582, - 0, 3323, 3580, - 0, 3325, 3578, - 0, 3328, 3575, - 0, 3332, 3571, - 0, 3337, 3566, - 0, 3344, 3560, - 0, 3353, 3550, - 0, 3365, 3538, - 0, 3380, 3520, - 0, 3400, 3495, - 0, 3425, 3460, - 0, 3456, 3409, - 0, 3495, 3329, - 0, 3543, 3194, - 0, 3599, 2912, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3585, - 0, 3318, 3585, - 0, 3318, 3585, - 0, 3318, 3584, - 0, 3319, 3584, - 0, 3320, 3583, - 0, 3321, 3582, - 0, 3323, 3580, - 0, 3325, 3578, - 0, 3328, 3575, - 0, 3332, 3572, - 0, 3337, 3567, - 0, 3344, 3560, - 0, 3353, 3551, - 0, 3365, 3538, - 0, 3380, 3520, - 0, 3400, 3496, - 0, 3425, 3460, - 0, 3456, 3409, - 0, 3495, 3329, - 0, 3543, 3194, - 0, 3599, 2912, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3318, 3585, - 0, 3318, 3585, - 0, 3319, 3584, - 0, 3319, 3584, - 0, 3320, 3583, - 0, 3321, 3582, - 0, 3323, 3580, - 0, 3325, 3578, - 0, 3328, 3576, - 0, 3332, 3572, - 0, 3337, 3567, - 0, 3344, 3560, - 0, 3353, 3551, - 0, 3365, 3538, - 0, 3380, 3520, - 0, 3400, 3496, - 0, 3425, 3461, - 0, 3456, 3409, - 0, 3495, 3329, - 0, 3543, 3194, - 0, 3599, 2913, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3318, 3586, - 0, 3318, 3585, - 0, 3319, 3585, - 0, 3319, 3584, - 0, 3320, 3583, - 0, 3321, 3582, - 0, 3323, 3581, - 0, 3325, 3579, - 0, 3328, 3576, - 0, 3332, 3572, - 0, 3337, 3567, - 0, 3344, 3560, - 0, 3353, 3551, - 0, 3365, 3538, - 0, 3380, 3521, - 0, 3400, 3496, - 0, 3425, 3461, - 0, 3456, 3409, - 0, 3495, 3330, - 0, 3543, 3195, - 0, 3599, 2914, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3317, 3586, - 0, 3318, 3586, - 0, 3318, 3585, - 0, 3319, 3585, - 0, 3319, 3584, - 0, 3320, 3584, - 0, 3322, 3582, - 0, 3323, 3581, - 0, 3325, 3579, - 0, 3328, 3576, - 0, 3332, 3572, - 0, 3338, 3567, - 0, 3344, 3561, - 0, 3353, 3551, - 0, 3365, 3539, - 0, 3380, 3521, - 0, 3400, 3496, - 0, 3425, 3461, - 0, 3456, 3410, - 0, 3495, 3330, - 0, 3543, 3196, - 0, 3599, 2915, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3318, 3587, - 0, 3318, 3586, - 0, 3318, 3586, - 0, 3319, 3585, - 0, 3319, 3585, - 0, 3320, 3584, - 0, 3322, 3583, - 0, 3323, 3581, - 0, 3326, 3579, - 0, 3328, 3576, - 0, 3332, 3573, - 0, 3338, 3568, - 0, 3344, 3561, - 0, 3353, 3552, - 0, 3365, 3539, - 0, 3380, 3521, - 0, 3400, 3497, - 0, 3425, 3462, - 0, 3457, 3410, - 0, 3495, 3331, - 0, 3543, 3197, - 0, 3599, 2917, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3317, 3587, - 0, 3318, 3587, - 0, 3318, 3587, - 0, 3318, 3586, - 0, 3319, 3586, - 0, 3320, 3585, - 0, 3321, 3584, - 0, 3322, 3583, - 0, 3323, 3582, - 0, 3326, 3580, - 0, 3329, 3577, - 0, 3333, 3573, - 0, 3338, 3568, - 0, 3345, 3561, - 0, 3354, 3552, - 0, 3365, 3540, - 0, 3381, 3522, - 0, 3400, 3498, - 0, 3425, 3463, - 0, 3457, 3411, - 0, 3496, 3332, - 0, 3543, 3198, - 0, 3599, 2919, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3317, 3588, - 0, 3318, 3588, - 0, 3318, 3588, - 0, 3318, 3587, - 0, 3319, 3587, - 0, 3319, 3587, - 0, 3320, 3586, - 0, 3321, 3585, - 0, 3322, 3584, - 0, 3324, 3583, - 0, 3326, 3580, - 0, 3329, 3578, - 0, 3333, 3574, - 0, 3338, 3569, - 0, 3345, 3562, - 0, 3354, 3553, - 0, 3365, 3540, - 0, 3381, 3523, - 0, 3400, 3498, - 0, 3425, 3464, - 0, 3457, 3412, - 0, 3496, 3333, - 0, 3543, 3200, - 0, 3599, 2922, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3317, 3589, - 0, 3317, 3589, - 0, 3317, 3589, - 0, 3317, 3589, - 0, 3318, 3589, - 0, 3318, 3589, - 0, 3318, 3589, - 0, 3318, 3589, - 0, 3318, 3588, - 0, 3319, 3588, - 0, 3319, 3588, - 0, 3320, 3587, - 0, 3321, 3586, - 0, 3322, 3585, - 0, 3324, 3583, - 0, 3326, 3581, - 0, 3329, 3579, - 0, 3333, 3575, - 0, 3338, 3570, - 0, 3345, 3563, - 0, 3354, 3554, - 0, 3366, 3541, - 0, 3381, 3524, - 0, 3401, 3500, - 0, 3426, 3465, - 0, 3457, 3414, - 0, 3496, 3335, - 0, 3543, 3202, - 0, 3600, 2927, - 0, 3665, 0, - 0, 3741, 0, - 0, 3825, 0, - 0, 3318, 3591, - 0, 3318, 3591, - 0, 3318, 3591, - 0, 3318, 3590, - 0, 3318, 3590, - 0, 3318, 3590, - 0, 3318, 3590, - 0, 3318, 3590, - 0, 3319, 3590, - 0, 3319, 3589, - 0, 3320, 3589, - 0, 3320, 3588, - 0, 3321, 3587, - 0, 3323, 3586, - 0, 3324, 3585, - 0, 3326, 3583, - 0, 3329, 3580, - 0, 3333, 3576, - 0, 3338, 3571, - 0, 3345, 3565, - 0, 3354, 3555, - 0, 3366, 3543, - 0, 3381, 3525, - 0, 3401, 3501, - 0, 3426, 3466, - 0, 3457, 3415, - 0, 3496, 3337, - 0, 3543, 3205, - 0, 3600, 2932, - 0, 3666, 0, - 0, 3741, 0, - 0, 3826, 0, - 0, 3318, 3592, - 0, 3318, 3592, - 0, 3318, 3592, - 0, 3318, 3592, - 0, 3318, 3592, - 0, 3318, 3592, - 0, 3319, 3592, - 0, 3319, 3592, - 0, 3319, 3591, - 0, 3320, 3591, - 0, 3320, 3591, - 0, 3321, 3590, - 0, 3322, 3589, - 0, 3323, 3588, - 0, 3325, 3586, - 0, 3327, 3584, - 0, 3330, 3582, - 0, 3334, 3578, - 0, 3339, 3573, - 0, 3346, 3566, - 0, 3355, 3557, - 0, 3366, 3545, - 0, 3382, 3527, - 0, 3401, 3503, - 0, 3426, 3469, - 0, 3458, 3418, - 0, 3496, 3340, - 0, 3544, 3209, - 0, 3600, 2939, - 0, 3666, 0, - 0, 3741, 0, - 0, 3826, 0, - 0, 3319, 3595, - 0, 3319, 3595, - 0, 3319, 3594, - 0, 3319, 3594, - 0, 3319, 3594, - 0, 3319, 3594, - 0, 3319, 3594, - 0, 3319, 3594, - 0, 3320, 3594, - 0, 3320, 3593, - 0, 3321, 3593, - 0, 3321, 3592, - 0, 3322, 3591, - 0, 3324, 3590, - 0, 3325, 3589, - 0, 3327, 3587, - 0, 3330, 3584, - 0, 3334, 3580, - 0, 3339, 3575, - 0, 3346, 3569, - 0, 3355, 3560, - 0, 3367, 3547, - 0, 3382, 3530, - 0, 3402, 3506, - 0, 3427, 3472, - 0, 3458, 3421, - 0, 3497, 3344, - 0, 3544, 3214, - 0, 3600, 2948, - 0, 3666, 0, - 0, 3741, 0, - 0, 3826, 0, - 0, 3319, 3598, - 0, 3319, 3597, - 0, 3320, 3597, - 0, 3320, 3597, - 0, 3320, 3597, - 0, 3320, 3597, - 0, 3320, 3597, - 0, 3320, 3597, - 0, 3320, 3597, - 0, 3321, 3596, - 0, 3321, 3596, - 0, 3322, 3595, - 0, 3323, 3594, - 0, 3324, 3593, - 0, 3326, 3592, - 0, 3328, 3590, - 0, 3331, 3587, - 0, 3335, 3583, - 0, 3340, 3579, - 0, 3347, 3572, - 0, 3356, 3563, - 0, 3368, 3550, - 0, 3383, 3533, - 0, 3402, 3510, - 0, 3427, 3475, - 0, 3459, 3426, - 0, 3497, 3349, - 0, 3544, 3221, - 0, 3601, 2961, - 0, 3666, 0, - 0, 3742, 0, - 0, 3826, 0, - 0, 3320, 3601, - 0, 3320, 3601, - 0, 3321, 3601, - 0, 3321, 3601, - 0, 3321, 3601, - 0, 3321, 3601, - 0, 3321, 3601, - 0, 3321, 3601, - 0, 3321, 3601, - 0, 3322, 3600, - 0, 3322, 3600, - 0, 3323, 3599, - 0, 3324, 3598, - 0, 3325, 3597, - 0, 3327, 3596, - 0, 3329, 3594, - 0, 3332, 3591, - 0, 3336, 3587, - 0, 3341, 3583, - 0, 3348, 3576, - 0, 3357, 3567, - 0, 3368, 3555, - 0, 3384, 3538, - 0, 3403, 3514, - 0, 3428, 3481, - 0, 3459, 3431, - 0, 3498, 3356, - 0, 3545, 3230, - 0, 3601, 2976, - 0, 3667, 238, - 0, 3742, 0, - 0, 3826, 0, - 0, 3322, 3607, - 0, 3322, 3607, - 0, 3322, 3607, - 0, 3322, 3607, - 0, 3322, 3606, - 0, 3322, 3606, - 0, 3322, 3606, - 0, 3323, 3606, - 0, 3323, 3606, - 0, 3323, 3605, - 0, 3324, 3605, - 0, 3324, 3604, - 0, 3325, 3604, - 0, 3327, 3603, - 0, 3328, 3601, - 0, 3330, 3599, - 0, 3333, 3596, - 0, 3337, 3593, - 0, 3342, 3588, - 0, 3349, 3582, - 0, 3358, 3573, - 0, 3370, 3561, - 0, 3385, 3544, - 0, 3404, 3521, - 0, 3429, 3487, - 0, 3460, 3439, - 0, 3499, 3365, - 0, 3546, 3241, - 0, 3602, 2997, - 0, 3668, 1599, - 0, 3743, 0, - 0, 3827, 0, - 0, 3324, 3614, - 0, 3324, 3614, - 0, 3324, 3614, - 0, 3324, 3613, - 0, 3324, 3613, - 0, 3324, 3613, - 0, 3324, 3613, - 0, 3324, 3613, - 0, 3325, 3613, - 0, 3325, 3612, - 0, 3326, 3612, - 0, 3326, 3611, - 0, 3327, 3611, - 0, 3328, 3609, - 0, 3330, 3608, - 0, 3332, 3606, - 0, 3335, 3603, - 0, 3339, 3600, - 0, 3344, 3595, - 0, 3351, 3589, - 0, 3360, 3580, - 0, 3371, 3568, - 0, 3386, 3552, - 0, 3406, 3529, - 0, 3431, 3496, - 0, 3462, 3449, - 0, 3500, 3376, - 0, 3547, 3257, - 0, 3603, 3023, - 0, 3668, 1971, - 0, 3743, 0, - 0, 3827, 0, - 0, 3326, 3623, - 0, 3326, 3623, - 0, 3326, 3623, - 0, 3326, 3623, - 0, 3326, 3622, - 0, 3326, 3622, - 0, 3327, 3622, - 0, 3327, 3622, - 0, 3327, 3622, - 0, 3327, 3621, - 0, 3328, 3621, - 0, 3329, 3620, - 0, 3330, 3620, - 0, 3331, 3619, - 0, 3332, 3617, - 0, 3335, 3615, - 0, 3337, 3613, - 0, 3341, 3609, - 0, 3346, 3605, - 0, 3353, 3598, - 0, 3362, 3590, - 0, 3374, 3578, - 0, 3388, 3562, - 0, 3408, 3540, - 0, 3432, 3508, - 0, 3463, 3462, - 0, 3502, 3392, - 0, 3548, 3276, - 0, 3604, 3055, - 0, 3669, 2225, - 0, 3744, 0, - 0, 3828, 0, - 0, 3329, 3635, - 0, 3329, 3635, - 0, 3329, 3634, - 0, 3329, 3634, - 0, 3329, 3634, - 0, 3330, 3634, - 0, 3330, 3634, - 0, 3330, 3634, - 0, 3330, 3634, - 0, 3331, 3633, - 0, 3331, 3633, - 0, 3332, 3632, - 0, 3333, 3632, - 0, 3334, 3631, - 0, 3336, 3629, - 0, 3338, 3627, - 0, 3341, 3625, - 0, 3344, 3622, - 0, 3349, 3617, - 0, 3356, 3611, - 0, 3365, 3603, - 0, 3376, 3591, - 0, 3391, 3576, - 0, 3410, 3554, - 0, 3435, 3523, - 0, 3466, 3479, - 0, 3504, 3411, - 0, 3550, 3301, - 0, 3606, 3095, - 0, 3671, 2431, - 0, 3746, 0, - 0, 3829, 0, - 0, 3333, 3650, - 0, 3333, 3650, - 0, 3334, 3650, - 0, 3334, 3650, - 0, 3334, 3650, - 0, 3334, 3650, - 0, 3334, 3649, - 0, 3334, 3649, - 0, 3334, 3649, - 0, 3335, 3649, - 0, 3335, 3648, - 0, 3336, 3648, - 0, 3337, 3647, - 0, 3338, 3646, - 0, 3340, 3645, - 0, 3342, 3643, - 0, 3345, 3641, - 0, 3349, 3637, - 0, 3354, 3633, - 0, 3360, 3627, - 0, 3369, 3619, - 0, 3380, 3608, - 0, 3395, 3593, - 0, 3414, 3572, - 0, 3438, 3543, - 0, 3469, 3500, - 0, 3507, 3436, - 0, 3553, 3333, - 0, 3608, 3144, - 0, 3673, 2611, - 0, 3747, 0, - 0, 3831, 0, - 0, 3339, 3670, - 0, 3339, 3670, - 0, 3339, 3670, - 0, 3339, 3670, - 0, 3339, 3670, - 0, 3339, 3669, - 0, 3340, 3669, - 0, 3340, 3669, - 0, 3340, 3669, - 0, 3340, 3669, - 0, 3341, 3668, - 0, 3342, 3668, - 0, 3343, 3667, - 0, 3344, 3666, - 0, 3345, 3665, - 0, 3347, 3663, - 0, 3350, 3661, - 0, 3354, 3658, - 0, 3359, 3654, - 0, 3365, 3648, - 0, 3374, 3640, - 0, 3385, 3630, - 0, 3400, 3616, - 0, 3419, 3596, - 0, 3443, 3568, - 0, 3473, 3527, - 0, 3511, 3467, - 0, 3556, 3372, - 0, 3611, 3202, - 0, 3676, 2776, - 0, 3750, 0, - 0, 3833, 0, - 1862, 3346, 3695, - 1860, 3347, 3695, - 1858, 3347, 3695, - 1854, 3347, 3695, - 1849, 3347, 3695, - 1842, 3347, 3695, - 1833, 3347, 3695, - 1821, 3347, 3694, - 1803, 3347, 3694, - 1779, 3348, 3694, - 1744, 3348, 3693, - 1694, 3349, 3693, - 1616, 3350, 3692, - 1484, 3351, 3691, - 1214, 3353, 3690, - 0, 3355, 3689, - 0, 3357, 3686, - 0, 3361, 3684, - 0, 3366, 3680, - 0, 3372, 3674, - 0, 3381, 3667, - 0, 3392, 3657, - 0, 3406, 3644, - 0, 3425, 3625, - 0, 3449, 3599, - 0, 3479, 3562, - 0, 3516, 3506, - 0, 3561, 3419, - 0, 3615, 3269, - 0, 3679, 2931, - 0, 3753, 0, - 0, 3835, 0, - 2854, 3356, 3727, - 2854, 3356, 3727, - 2853, 3356, 3726, - 2853, 3356, 3726, - 2853, 3356, 3726, - 2852, 3357, 3726, - 2851, 3357, 3726, - 2849, 3357, 3726, - 2848, 3357, 3726, - 2845, 3358, 3726, - 2842, 3358, 3725, - 2838, 3359, 3725, - 2832, 3360, 3724, - 2824, 3361, 3723, - 2813, 3362, 3722, - 2798, 3364, 3721, - 2778, 3367, 3719, - 2749, 3371, 3716, - 2706, 3375, 3712, - 2643, 3382, 3707, - 2542, 3390, 3701, - 2357, 3401, 3692, - 1850, 3415, 3679, - 0, 3433, 3662, - 0, 3456, 3638, - 0, 3486, 3604, - 0, 3522, 3553, - 0, 3567, 3476, - 0, 3621, 3346, - 0, 3684, 3080, - 0, 3757, 0, - 0, 3838, 0, - 3210, 3369, 3766, - 3209, 3369, 3766, - 3209, 3369, 3766, - 3209, 3369, 3766, - 3209, 3369, 3766, - 3209, 3369, 3765, - 3208, 3369, 3765, - 3207, 3370, 3765, - 3207, 3370, 3765, - 3206, 3370, 3765, - 3204, 3371, 3764, - 3202, 3371, 3764, - 3200, 3372, 3763, - 3196, 3373, 3763, - 3191, 3375, 3762, - 3185, 3377, 3760, - 3176, 3379, 3758, - 3164, 3383, 3756, - 3148, 3387, 3753, - 3125, 3394, 3748, - 3092, 3402, 3742, - 3045, 3412, 3734, - 2972, 3426, 3722, - 2852, 3444, 3707, - 2617, 3467, 3685, - 1537, 3495, 3654, - 0, 3531, 3609, - 0, 3575, 3542, - 0, 3628, 3431, - 0, 3690, 3224, - 0, 3762, 2549, - 0, 3843, 0, - 3457, 3385, 3813, - 3457, 3385, 3813, - 3457, 3385, 3813, - 3457, 3385, 3813, - 3457, 3385, 3813, - 3457, 3386, 3813, - 3457, 3386, 3813, - 3456, 3386, 3813, - 3456, 3386, 3813, - 3455, 3387, 3812, - 3454, 3387, 3812, - 3453, 3388, 3812, - 3452, 3388, 3811, - 3450, 3389, 3811, - 3447, 3391, 3810, - 3443, 3393, 3808, - 3439, 3395, 3807, - 3432, 3399, 3805, - 3423, 3403, 3802, - 3410, 3409, 3797, - 3393, 3417, 3792, - 3369, 3427, 3785, - 3335, 3441, 3774, - 3285, 3458, 3761, - 3208, 3480, 3741, - 3079, 3508, 3714, - 2817, 3543, 3675, - 0, 3586, 3617, - 0, 3637, 3526, - 0, 3698, 3365, - 0, 3769, 2984, - 0, 3849, 0, - 3660, 3406, 3870, - 3660, 3406, 3870, - 3660, 3406, 3870, - 3660, 3406, 3870, - 3660, 3407, 3870, - 3660, 3407, 3870, - 3660, 3407, 3870, - 3660, 3407, 3870, - 3659, 3407, 3869, - 3659, 3408, 3869, - 3658, 3408, 3869, - 3658, 3409, 3869, - 3657, 3409, 3868, - 3655, 3410, 3868, - 3654, 3412, 3867, - 3651, 3414, 3866, - 3648, 3416, 3864, - 3644, 3419, 3862, - 3638, 3424, 3860, - 3631, 3429, 3856, - 3620, 3437, 3851, - 3606, 3446, 3845, - 3586, 3459, 3836, - 3558, 3476, 3824, - 3517, 3497, 3807, - 3456, 3524, 3784, - 3360, 3558, 3750, - 3187, 3599, 3702, - 2750, 3650, 3627, - 0, 3709, 3503, - 0, 3778, 3257, - 0, 3856, 1771, - 3839, 3433, 3936, - 3839, 3433, 3936, - 3839, 3433, 3936, - 3839, 3433, 3936, - 3839, 3433, 3936, - 3839, 3433, 3936, - 3838, 3433, 3936, - 3838, 3434, 3936, - 3838, 3434, 3936, - 3838, 3434, 3936, - 3838, 3435, 3935, - 3837, 3435, 3935, - 3836, 3436, 3935, - 3836, 3437, 3934, - 3834, 3438, 3933, - 3833, 3440, 3932, - 3831, 3442, 3931, - 3828, 3445, 3930, - 3824, 3449, 3927, - 3819, 3455, 3924, - 3812, 3462, 3920, - 3803, 3471, 3914, - 3790, 3483, 3907, - 3772, 3499, 3897, - 3747, 3519, 3882, - 3712, 3545, 3863, - 3659, 3577, 3835, - 3578, 3617, 3795, - 3440, 3665, 3735, - 3149, 3723, 3640, - 0, 3790, 3472, - 0, 3867, 3056, - 4003, 3467, 4012, - 4003, 3467, 4012, - 4003, 3467, 4012, - 4003, 3467, 4012, - 4003, 3467, 4012, - 4003, 3467, 4012, - 4003, 3467, 4012, - 4002, 3467, 4012, - 4002, 3467, 4012, - 4002, 3468, 4011, - 4002, 3468, 4011, - 4002, 3468, 4011, - 4001, 3469, 4011, - 4001, 3470, 4010, - 4000, 3471, 4010, - 3999, 3473, 4009, - 3997, 3475, 4008, - 3995, 3478, 4006, - 3993, 3482, 4004, - 3989, 3487, 4002, - 3984, 3493, 3998, - 3978, 3502, 3994, - 3969, 3513, 3987, - 3957, 3528, 3979, - 3941, 3547, 3967, - 3918, 3571, 3950, - 3886, 3602, 3928, - 3838, 3640, 3895, - 3765, 3686, 3848, - 3646, 3741, 3776, - 3411, 3806, 3657, - 2348, 3880, 3426, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3508, 4095, - 4095, 3509, 4095, - 4095, 3509, 4095, - 4095, 3509, 4095, - 4095, 3510, 4095, - 4095, 3511, 4095, - 4095, 3512, 4095, - 4095, 3513, 4094, - 4095, 3515, 4093, - 4095, 3518, 4092, - 4095, 3522, 4091, - 4095, 3526, 4088, - 4095, 3532, 4086, - 4095, 3540, 4082, - 4095, 3551, 4076, - 4095, 3564, 4069, - 4095, 3582, 4060, - 4095, 3604, 4046, - 4077, 3633, 4028, - 4046, 3668, 4002, - 4002, 3712, 3965, - 3935, 3764, 3911, - 3826, 3826, 3826, - 3621, 3897, 3679, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3558, 4095, - 4095, 3559, 4095, - 4095, 3559, 4095, - 4095, 3560, 4095, - 4095, 3560, 4095, - 4095, 3561, 4095, - 4095, 3563, 4095, - 4095, 3564, 4095, - 4095, 3567, 4095, - 4095, 3570, 4095, - 4095, 3574, 4095, - 4095, 3580, 4095, - 4095, 3587, 4095, - 4095, 3596, 4095, - 4095, 3608, 4095, - 4095, 3624, 4095, - 4095, 3645, 4095, - 4095, 3671, 4095, - 4095, 3704, 4095, - 4095, 3744, 4086, - 4095, 3793, 4045, - 4093, 3851, 3983, - 3990, 3919, 3884, - 0, 3448, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3717, - 0, 3449, 3717, - 0, 3449, 3717, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3450, 3716, - 0, 3451, 3715, - 0, 3452, 3715, - 0, 3453, 3713, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3707, - 0, 3464, 3703, - 0, 3469, 3698, - 0, 3476, 3691, - 0, 3485, 3682, - 0, 3497, 3669, - 0, 3512, 3652, - 0, 3532, 3627, - 0, 3557, 3592, - 0, 3588, 3540, - 0, 3627, 3460, - 0, 3675, 3325, - 0, 3731, 3043, - 0, 3797, 0, - 0, 3873, 0, - 0, 3448, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3717, - 0, 3449, 3717, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3451, 3716, - 0, 3451, 3715, - 0, 3452, 3715, - 0, 3453, 3713, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3707, - 0, 3464, 3703, - 0, 3469, 3698, - 0, 3476, 3692, - 0, 3485, 3682, - 0, 3497, 3670, - 0, 3512, 3652, - 0, 3532, 3627, - 0, 3557, 3592, - 0, 3588, 3540, - 0, 3627, 3460, - 0, 3675, 3325, - 0, 3731, 3043, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3717, - 0, 3449, 3717, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3451, 3716, - 0, 3451, 3716, - 0, 3452, 3715, - 0, 3453, 3714, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3707, - 0, 3464, 3703, - 0, 3469, 3698, - 0, 3476, 3692, - 0, 3485, 3682, - 0, 3497, 3670, - 0, 3512, 3652, - 0, 3532, 3627, - 0, 3557, 3592, - 0, 3588, 3540, - 0, 3627, 3461, - 0, 3675, 3326, - 0, 3731, 3043, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3717, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3451, 3716, - 0, 3451, 3716, - 0, 3452, 3715, - 0, 3453, 3714, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3707, - 0, 3464, 3703, - 0, 3469, 3698, - 0, 3476, 3692, - 0, 3485, 3682, - 0, 3497, 3670, - 0, 3512, 3652, - 0, 3532, 3627, - 0, 3557, 3592, - 0, 3588, 3541, - 0, 3627, 3461, - 0, 3675, 3326, - 0, 3731, 3043, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3717, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3451, 3716, - 0, 3451, 3716, - 0, 3452, 3715, - 0, 3453, 3714, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3707, - 0, 3464, 3704, - 0, 3469, 3699, - 0, 3476, 3692, - 0, 3485, 3682, - 0, 3497, 3670, - 0, 3512, 3652, - 0, 3532, 3628, - 0, 3557, 3592, - 0, 3588, 3541, - 0, 3627, 3461, - 0, 3675, 3326, - 0, 3731, 3044, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3451, 3716, - 0, 3451, 3716, - 0, 3452, 3715, - 0, 3453, 3714, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3707, - 0, 3464, 3704, - 0, 3469, 3699, - 0, 3476, 3692, - 0, 3485, 3683, - 0, 3497, 3670, - 0, 3512, 3652, - 0, 3532, 3628, - 0, 3557, 3593, - 0, 3588, 3541, - 0, 3627, 3461, - 0, 3675, 3326, - 0, 3731, 3044, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3450, 3717, - 0, 3450, 3717, - 0, 3451, 3717, - 0, 3451, 3716, - 0, 3452, 3715, - 0, 3454, 3714, - 0, 3455, 3712, - 0, 3457, 3710, - 0, 3460, 3708, - 0, 3464, 3704, - 0, 3469, 3699, - 0, 3476, 3692, - 0, 3485, 3683, - 0, 3497, 3670, - 0, 3512, 3653, - 0, 3532, 3628, - 0, 3557, 3593, - 0, 3588, 3541, - 0, 3627, 3461, - 0, 3675, 3327, - 0, 3731, 3045, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3449, 3718, - 0, 3450, 3718, - 0, 3450, 3717, - 0, 3451, 3717, - 0, 3451, 3716, - 0, 3452, 3715, - 0, 3454, 3714, - 0, 3455, 3713, - 0, 3457, 3711, - 0, 3460, 3708, - 0, 3464, 3704, - 0, 3470, 3699, - 0, 3476, 3692, - 0, 3485, 3683, - 0, 3497, 3670, - 0, 3512, 3653, - 0, 3532, 3628, - 0, 3557, 3593, - 0, 3589, 3541, - 0, 3627, 3462, - 0, 3675, 3327, - 0, 3731, 3046, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3718, - 0, 3450, 3718, - 0, 3450, 3718, - 0, 3450, 3718, - 0, 3451, 3717, - 0, 3451, 3716, - 0, 3452, 3716, - 0, 3454, 3714, - 0, 3455, 3713, - 0, 3458, 3711, - 0, 3460, 3708, - 0, 3464, 3704, - 0, 3470, 3699, - 0, 3476, 3693, - 0, 3485, 3683, - 0, 3497, 3671, - 0, 3512, 3653, - 0, 3532, 3629, - 0, 3557, 3593, - 0, 3589, 3542, - 0, 3627, 3462, - 0, 3675, 3328, - 0, 3731, 3047, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3449, 3719, - 0, 3450, 3719, - 0, 3450, 3718, - 0, 3450, 3718, - 0, 3451, 3718, - 0, 3452, 3717, - 0, 3452, 3716, - 0, 3454, 3715, - 0, 3455, 3713, - 0, 3458, 3711, - 0, 3461, 3709, - 0, 3465, 3705, - 0, 3470, 3700, - 0, 3477, 3693, - 0, 3486, 3684, - 0, 3497, 3671, - 0, 3513, 3654, - 0, 3532, 3629, - 0, 3557, 3594, - 0, 3589, 3542, - 0, 3628, 3463, - 0, 3675, 3329, - 0, 3731, 3049, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3719, - 0, 3450, 3719, - 0, 3450, 3719, - 0, 3450, 3719, - 0, 3450, 3719, - 0, 3451, 3718, - 0, 3452, 3717, - 0, 3453, 3717, - 0, 3454, 3715, - 0, 3456, 3714, - 0, 3458, 3712, - 0, 3461, 3709, - 0, 3465, 3705, - 0, 3470, 3700, - 0, 3477, 3694, - 0, 3486, 3684, - 0, 3497, 3672, - 0, 3513, 3654, - 0, 3532, 3630, - 0, 3557, 3595, - 0, 3589, 3543, - 0, 3628, 3464, - 0, 3675, 3330, - 0, 3731, 3051, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3721, - 0, 3449, 3721, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3449, 3720, - 0, 3450, 3720, - 0, 3450, 3720, - 0, 3450, 3720, - 0, 3450, 3720, - 0, 3451, 3719, - 0, 3451, 3719, - 0, 3452, 3718, - 0, 3453, 3717, - 0, 3454, 3716, - 0, 3456, 3715, - 0, 3458, 3713, - 0, 3461, 3710, - 0, 3465, 3706, - 0, 3470, 3701, - 0, 3477, 3694, - 0, 3486, 3685, - 0, 3498, 3672, - 0, 3513, 3655, - 0, 3532, 3631, - 0, 3557, 3596, - 0, 3589, 3544, - 0, 3628, 3465, - 0, 3675, 3332, - 0, 3731, 3055, - 0, 3797, 0, - 0, 3873, 0, - 0, 3449, 3721, - 0, 3449, 3721, - 0, 3449, 3721, - 0, 3450, 3721, - 0, 3450, 3721, - 0, 3450, 3721, - 0, 3450, 3721, - 0, 3450, 3721, - 0, 3450, 3721, - 0, 3450, 3721, - 0, 3451, 3720, - 0, 3451, 3720, - 0, 3452, 3719, - 0, 3453, 3718, - 0, 3454, 3717, - 0, 3456, 3716, - 0, 3458, 3714, - 0, 3461, 3711, - 0, 3465, 3707, - 0, 3470, 3702, - 0, 3477, 3695, - 0, 3486, 3686, - 0, 3498, 3674, - 0, 3513, 3656, - 0, 3533, 3632, - 0, 3558, 3597, - 0, 3589, 3546, - 0, 3628, 3467, - 0, 3675, 3334, - 0, 3732, 3059, - 0, 3798, 0, - 0, 3873, 0, - 0, 3450, 3723, - 0, 3450, 3723, - 0, 3450, 3723, - 0, 3450, 3723, - 0, 3450, 3723, - 0, 3450, 3723, - 0, 3450, 3722, - 0, 3450, 3722, - 0, 3451, 3722, - 0, 3451, 3722, - 0, 3451, 3721, - 0, 3452, 3721, - 0, 3452, 3720, - 0, 3453, 3719, - 0, 3455, 3718, - 0, 3456, 3717, - 0, 3458, 3715, - 0, 3461, 3712, - 0, 3465, 3708, - 0, 3471, 3703, - 0, 3477, 3697, - 0, 3486, 3687, - 0, 3498, 3675, - 0, 3513, 3658, - 0, 3533, 3633, - 0, 3558, 3599, - 0, 3589, 3548, - 0, 3628, 3469, - 0, 3675, 3337, - 0, 3732, 3064, - 0, 3798, 0, - 0, 3873, 0, - 0, 3450, 3724, - 0, 3450, 3724, - 0, 3450, 3724, - 0, 3450, 3724, - 0, 3450, 3724, - 0, 3450, 3724, - 0, 3451, 3724, - 0, 3451, 3724, - 0, 3451, 3724, - 0, 3451, 3723, - 0, 3452, 3723, - 0, 3452, 3723, - 0, 3453, 3722, - 0, 3454, 3721, - 0, 3455, 3720, - 0, 3457, 3719, - 0, 3459, 3717, - 0, 3462, 3714, - 0, 3466, 3710, - 0, 3471, 3705, - 0, 3478, 3698, - 0, 3487, 3689, - 0, 3498, 3677, - 0, 3514, 3659, - 0, 3533, 3635, - 0, 3558, 3601, - 0, 3590, 3550, - 0, 3628, 3472, - 0, 3676, 3341, - 0, 3732, 3071, - 0, 3798, 0, - 0, 3873, 0, - 0, 3451, 3727, - 0, 3451, 3727, - 0, 3451, 3727, - 0, 3451, 3727, - 0, 3451, 3727, - 0, 3451, 3726, - 0, 3451, 3726, - 0, 3451, 3726, - 0, 3452, 3726, - 0, 3452, 3726, - 0, 3452, 3725, - 0, 3453, 3725, - 0, 3453, 3724, - 0, 3454, 3723, - 0, 3456, 3722, - 0, 3457, 3721, - 0, 3459, 3719, - 0, 3462, 3716, - 0, 3466, 3712, - 0, 3471, 3708, - 0, 3478, 3701, - 0, 3487, 3692, - 0, 3499, 3679, - 0, 3514, 3662, - 0, 3534, 3638, - 0, 3559, 3604, - 0, 3590, 3553, - 0, 3629, 3476, - 0, 3676, 3346, - 0, 3732, 3081, - 0, 3798, 0, - 0, 3873, 0, - 0, 3451, 3730, - 0, 3452, 3730, - 0, 3452, 3730, - 0, 3452, 3730, - 0, 3452, 3729, - 0, 3452, 3729, - 0, 3452, 3729, - 0, 3452, 3729, - 0, 3452, 3729, - 0, 3453, 3729, - 0, 3453, 3728, - 0, 3453, 3728, - 0, 3454, 3727, - 0, 3455, 3726, - 0, 3456, 3725, - 0, 3458, 3724, - 0, 3460, 3722, - 0, 3463, 3719, - 0, 3467, 3716, - 0, 3472, 3711, - 0, 3479, 3704, - 0, 3488, 3695, - 0, 3500, 3683, - 0, 3515, 3666, - 0, 3534, 3642, - 0, 3559, 3608, - 0, 3591, 3558, - 0, 3629, 3481, - 0, 3676, 3353, - 0, 3733, 3093, - 0, 3798, 0, - 0, 3874, 0, - 0, 3453, 3734, - 0, 3453, 3734, - 0, 3453, 3734, - 0, 3453, 3734, - 0, 3453, 3733, - 0, 3453, 3733, - 0, 3453, 3733, - 0, 3453, 3733, - 0, 3453, 3733, - 0, 3454, 3733, - 0, 3454, 3732, - 0, 3454, 3732, - 0, 3455, 3731, - 0, 3456, 3730, - 0, 3457, 3729, - 0, 3459, 3728, - 0, 3461, 3726, - 0, 3464, 3723, - 0, 3468, 3720, - 0, 3473, 3715, - 0, 3480, 3708, - 0, 3489, 3699, - 0, 3501, 3687, - 0, 3516, 3670, - 0, 3535, 3646, - 0, 3560, 3613, - 0, 3591, 3563, - 0, 3630, 3488, - 0, 3677, 3362, - 0, 3733, 3109, - 0, 3799, 370, - 0, 3874, 0, - 0, 3454, 3739, - 0, 3454, 3739, - 0, 3454, 3739, - 0, 3454, 3739, - 0, 3454, 3739, - 0, 3454, 3739, - 0, 3454, 3738, - 0, 3454, 3738, - 0, 3455, 3738, - 0, 3455, 3738, - 0, 3455, 3738, - 0, 3456, 3737, - 0, 3457, 3737, - 0, 3457, 3736, - 0, 3459, 3735, - 0, 3460, 3733, - 0, 3463, 3731, - 0, 3465, 3729, - 0, 3469, 3725, - 0, 3474, 3720, - 0, 3481, 3714, - 0, 3490, 3705, - 0, 3502, 3693, - 0, 3517, 3676, - 0, 3536, 3653, - 0, 3561, 3620, - 0, 3592, 3571, - 0, 3631, 3497, - 0, 3678, 3374, - 0, 3734, 3129, - 0, 3800, 1731, - 0, 3875, 0, - 0, 3456, 3746, - 0, 3456, 3746, - 0, 3456, 3746, - 0, 3456, 3746, - 0, 3456, 3746, - 0, 3456, 3745, - 0, 3456, 3745, - 0, 3456, 3745, - 0, 3456, 3745, - 0, 3457, 3745, - 0, 3457, 3744, - 0, 3458, 3744, - 0, 3458, 3743, - 0, 3459, 3743, - 0, 3460, 3742, - 0, 3462, 3740, - 0, 3464, 3738, - 0, 3467, 3736, - 0, 3471, 3732, - 0, 3476, 3727, - 0, 3483, 3721, - 0, 3492, 3712, - 0, 3503, 3700, - 0, 3518, 3684, - 0, 3538, 3661, - 0, 3563, 3629, - 0, 3594, 3581, - 0, 3632, 3508, - 0, 3679, 3389, - 0, 3735, 3155, - 0, 3800, 2103, - 0, 3875, 0, - 0, 3458, 3755, - 0, 3458, 3755, - 0, 3458, 3755, - 0, 3458, 3755, - 0, 3458, 3755, - 0, 3458, 3755, - 0, 3458, 3754, - 0, 3459, 3754, - 0, 3459, 3754, - 0, 3459, 3754, - 0, 3460, 3754, - 0, 3460, 3753, - 0, 3461, 3753, - 0, 3462, 3752, - 0, 3463, 3751, - 0, 3465, 3749, - 0, 3467, 3747, - 0, 3470, 3745, - 0, 3473, 3741, - 0, 3479, 3737, - 0, 3485, 3731, - 0, 3494, 3722, - 0, 3506, 3710, - 0, 3521, 3694, - 0, 3540, 3672, - 0, 3565, 3640, - 0, 3595, 3594, - 0, 3634, 3524, - 0, 3681, 3409, - 0, 3736, 3187, - 0, 3802, 2357, - 0, 3876, 0, - 0, 3461, 3767, - 0, 3461, 3767, - 0, 3461, 3767, - 0, 3461, 3767, - 0, 3461, 3767, - 0, 3462, 3766, - 0, 3462, 3766, - 0, 3462, 3766, - 0, 3462, 3766, - 0, 3462, 3766, - 0, 3463, 3765, - 0, 3463, 3765, - 0, 3464, 3764, - 0, 3465, 3764, - 0, 3466, 3763, - 0, 3468, 3761, - 0, 3470, 3759, - 0, 3473, 3757, - 0, 3477, 3754, - 0, 3482, 3749, - 0, 3488, 3743, - 0, 3497, 3735, - 0, 3508, 3723, - 0, 3523, 3708, - 0, 3543, 3686, - 0, 3567, 3655, - 0, 3598, 3611, - 0, 3636, 3543, - 0, 3682, 3434, - 0, 3738, 3227, - 0, 3803, 2563, - 0, 3878, 0, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3782, - 0, 3466, 3781, - 0, 3467, 3781, - 0, 3467, 3781, - 0, 3467, 3780, - 0, 3468, 3780, - 0, 3469, 3779, - 0, 3470, 3778, - 0, 3472, 3777, - 0, 3474, 3775, - 0, 3477, 3773, - 0, 3481, 3769, - 0, 3486, 3765, - 0, 3492, 3759, - 0, 3501, 3751, - 0, 3512, 3740, - 0, 3527, 3725, - 0, 3546, 3704, - 0, 3570, 3675, - 0, 3601, 3632, - 0, 3639, 3568, - 0, 3685, 3465, - 0, 3740, 3276, - 0, 3805, 2743, - 0, 3879, 0, - 0, 3471, 3802, - 0, 3471, 3802, - 0, 3471, 3802, - 0, 3471, 3802, - 0, 3471, 3802, - 0, 3471, 3802, - 0, 3472, 3802, - 0, 3472, 3801, - 0, 3472, 3801, - 0, 3472, 3801, - 0, 3473, 3801, - 0, 3473, 3800, - 0, 3474, 3800, - 0, 3475, 3799, - 0, 3476, 3798, - 0, 3477, 3797, - 0, 3480, 3795, - 0, 3482, 3793, - 0, 3486, 3790, - 0, 3491, 3786, - 0, 3498, 3780, - 0, 3506, 3772, - 0, 3517, 3762, - 0, 3532, 3748, - 0, 3551, 3728, - 0, 3575, 3700, - 0, 3605, 3660, - 0, 3643, 3599, - 0, 3689, 3504, - 0, 3743, 3334, - 0, 3808, 2908, - 0, 3882, 0, - 1996, 3479, 3827, - 1994, 3479, 3827, - 1992, 3479, 3827, - 1990, 3479, 3827, - 1986, 3479, 3827, - 1981, 3479, 3827, - 1974, 3479, 3827, - 1965, 3479, 3827, - 1953, 3479, 3826, - 1935, 3480, 3826, - 1911, 3480, 3826, - 1877, 3480, 3826, - 1826, 3481, 3825, - 1748, 3482, 3824, - 1616, 3483, 3824, - 1346, 3485, 3822, - 0, 3487, 3821, - 0, 3490, 3819, - 0, 3493, 3816, - 0, 3498, 3812, - 0, 3505, 3806, - 0, 3513, 3799, - 0, 3524, 3789, - 0, 3538, 3776, - 0, 3557, 3757, - 0, 3581, 3731, - 0, 3611, 3694, - 0, 3648, 3638, - 0, 3693, 3551, - 0, 3748, 3401, - 0, 3811, 3063, - 0, 3885, 0, - 2986, 3488, 3859, - 2986, 3488, 3859, - 2986, 3488, 3859, - 2986, 3488, 3859, - 2985, 3488, 3859, - 2985, 3489, 3858, - 2984, 3489, 3858, - 2983, 3489, 3858, - 2982, 3489, 3858, - 2980, 3489, 3858, - 2977, 3490, 3858, - 2974, 3490, 3857, - 2970, 3491, 3857, - 2964, 3492, 3856, - 2956, 3493, 3855, - 2945, 3494, 3854, - 2931, 3496, 3853, - 2910, 3499, 3851, - 2881, 3503, 3848, - 2839, 3507, 3844, - 2775, 3514, 3839, - 2674, 3522, 3833, - 2489, 3533, 3824, - 1982, 3547, 3811, - 0, 3565, 3794, - 0, 3589, 3770, - 0, 3618, 3736, - 0, 3655, 3685, - 0, 3699, 3608, - 0, 3753, 3478, - 0, 3816, 3212, - 0, 3889, 0, - 3342, 3501, 3898, - 3342, 3501, 3898, - 3342, 3501, 3898, - 3341, 3501, 3898, - 3341, 3501, 3898, - 3341, 3501, 3898, - 3341, 3501, 3898, - 3340, 3501, 3897, - 3340, 3502, 3897, - 3339, 3502, 3897, - 3338, 3502, 3897, - 3336, 3503, 3897, - 3334, 3503, 3896, - 3332, 3504, 3896, - 3328, 3505, 3895, - 3323, 3507, 3894, - 3317, 3509, 3892, - 3308, 3511, 3891, - 3296, 3515, 3888, - 3280, 3520, 3885, - 3257, 3526, 3880, - 3224, 3534, 3874, - 3177, 3544, 3866, - 3104, 3558, 3854, - 2984, 3576, 3839, - 2749, 3599, 3817, - 1669, 3628, 3786, - 0, 3663, 3741, - 0, 3707, 3674, - 0, 3760, 3564, - 0, 3822, 3356, - 0, 3894, 2681, - 3590, 3517, 3945, - 3590, 3517, 3945, - 3590, 3517, 3945, - 3589, 3517, 3945, - 3589, 3518, 3945, - 3589, 3518, 3945, - 3589, 3518, 3945, - 3589, 3518, 3945, - 3588, 3518, 3945, - 3588, 3518, 3945, - 3587, 3519, 3945, - 3586, 3519, 3944, - 3585, 3520, 3944, - 3584, 3520, 3943, - 3582, 3522, 3943, - 3579, 3523, 3942, - 3576, 3525, 3941, - 3571, 3527, 3939, - 3564, 3531, 3937, - 3555, 3535, 3934, - 3543, 3541, 3930, - 3525, 3549, 3924, - 3501, 3559, 3917, - 3467, 3573, 3907, - 3417, 3590, 3893, - 3340, 3612, 3873, - 3211, 3640, 3846, - 2949, 3675, 3807, - 0, 3718, 3749, - 0, 3769, 3658, - 0, 3830, 3497, - 0, 3901, 3116, - 3792, 3538, 4002, - 3792, 3538, 4002, - 3792, 3538, 4002, - 3792, 3539, 4002, - 3792, 3539, 4002, - 3792, 3539, 4002, - 3792, 3539, 4002, - 3792, 3539, 4002, - 3792, 3539, 4002, - 3791, 3539, 4002, - 3791, 3540, 4001, - 3790, 3540, 4001, - 3790, 3541, 4001, - 3789, 3541, 4000, - 3787, 3542, 4000, - 3786, 3544, 3999, - 3783, 3546, 3998, - 3780, 3548, 3996, - 3776, 3551, 3994, - 3770, 3556, 3992, - 3763, 3561, 3988, - 3752, 3569, 3983, - 3738, 3579, 3977, - 3718, 3591, 3968, - 3690, 3608, 3956, - 3649, 3629, 3939, - 3588, 3656, 3916, - 3492, 3690, 3882, - 3319, 3731, 3834, - 2882, 3782, 3759, - 0, 3841, 3636, - 0, 3910, 3389, - 3971, 3565, 4068, - 3971, 3565, 4068, - 3971, 3565, 4068, - 3971, 3565, 4068, - 3971, 3565, 4068, - 3971, 3565, 4068, - 3971, 3565, 4068, - 3971, 3566, 4068, - 3970, 3566, 4068, - 3970, 3566, 4068, - 3970, 3566, 4068, - 3970, 3567, 4067, - 3969, 3567, 4067, - 3968, 3568, 4067, - 3968, 3569, 4066, - 3966, 3570, 4066, - 3965, 3572, 4065, - 3963, 3574, 4063, - 3960, 3577, 4062, - 3956, 3581, 4059, - 3951, 3587, 4056, - 3944, 3594, 4052, - 3935, 3603, 4047, - 3922, 3615, 4039, - 3904, 3631, 4029, - 3879, 3651, 4014, - 3844, 3677, 3995, - 3791, 3709, 3967, - 3710, 3749, 3927, - 3572, 3797, 3867, - 3281, 3855, 3772, - 0, 3922, 3604, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3599, 4095, - 4095, 3600, 4095, - 4095, 3600, 4095, - 4095, 3601, 4095, - 4095, 3601, 4095, - 4095, 3602, 4095, - 4095, 3603, 4095, - 4095, 3605, 4095, - 4095, 3607, 4095, - 4095, 3610, 4095, - 4095, 3614, 4095, - 4095, 3619, 4095, - 4095, 3625, 4095, - 4095, 3634, 4095, - 4095, 3645, 4095, - 4090, 3660, 4095, - 4073, 3679, 4095, - 4050, 3703, 4083, - 4018, 3734, 4060, - 3970, 3772, 4027, - 3897, 3818, 3980, - 3778, 3873, 3908, - 3543, 3938, 3789, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3640, 4095, - 4095, 3641, 4095, - 4095, 3641, 4095, - 4095, 3641, 4095, - 4095, 3642, 4095, - 4095, 3642, 4095, - 4095, 3643, 4095, - 4095, 3644, 4095, - 4095, 3646, 4095, - 4095, 3648, 4095, - 4095, 3650, 4095, - 4095, 3654, 4095, - 4095, 3658, 4095, - 4095, 3664, 4095, - 4095, 3672, 4095, - 4095, 3683, 4095, - 4095, 3696, 4095, - 4095, 3714, 4095, - 4095, 3736, 4095, - 4095, 3765, 4095, - 4095, 3800, 4095, - 4095, 3844, 4095, - 4067, 3896, 4043, - 3958, 3958, 3958 -] + "Intervals": [0, 33, 66, 99, 132, 165, 198, 231, 264, 297, 330, 363, 396, 429, 462, 495, 528, 561, 594, 627, 660, 693, 726, 759, 792, 825, 858, 891, 924, 957, 990, 1023], + "Values": [0, 0, 0, +0, 0, 0, +0, 15, 0, +0, 104, 0, +0, 201, 0, +0, 305, 0, +0, 415, 0, +0, 530, 0, +0, 649, 0, +0, 771, 0, +0, 895, 0, +0, 1022, 0, +0, 1149, 0, +0, 1278, 0, +0, 1408, 0, +0, 1538, 0, +0, 1668, 0, +0, 1799, 0, +0, 1931, 0, +0, 2062, 0, +0, 2194, 0, +0, 2326, 0, +0, 2457, 0, +0, 2589, 0, +0, 2721, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3381, 0, +0, 3514, 0, +0, 3646, 0, +130, 0, 20, +28, 0, 0, +0, 33, 0, +0, 119, 0, +0, 213, 0, +0, 315, 0, +0, 423, 0, +0, 536, 0, +0, 654, 0, +0, 775, 0, +0, 898, 0, +0, 1024, 0, +0, 1151, 0, +0, 1279, 0, +0, 1408, 0, +0, 1538, 0, +0, 1669, 0, +0, 1800, 0, +0, 1931, 0, +0, 2062, 0, +0, 2194, 0, +0, 2326, 0, +0, 2458, 0, +0, 2589, 0, +0, 2721, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3381, 0, +0, 3514, 0, +0, 3646, 0, +342, 0, 170, +280, 0, 102, +183, 56, 0, +7, 139, 0, +0, 229, 0, +0, 328, 0, +0, 433, 0, +0, 544, 0, +0, 660, 0, +0, 779, 0, +0, 902, 0, +0, 1026, 0, +0, 1153, 0, +0, 1281, 0, +0, 1410, 0, +0, 1539, 0, +0, 1670, 0, +0, 1800, 0, +0, 1931, 0, +0, 2063, 0, +0, 2194, 0, +0, 2326, 0, +0, 2458, 0, +0, 2589, 0, +0, 2721, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3381, 0, +0, 3514, 0, +0, 3646, 0, +526, 0, 315, +486, 18, 266, +426, 86, 192, +331, 163, 68, +163, 250, 0, +0, 344, 0, +0, 446, 0, +0, 555, 0, +0, 668, 0, +0, 785, 0, +0, 906, 0, +0, 1030, 0, +0, 1156, 0, +0, 1283, 0, +0, 1411, 0, +0, 1540, 0, +0, 1670, 0, +0, 1801, 0, +0, 1932, 0, +0, 2063, 0, +0, 2194, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +693, 8, 457, +666, 60, 422, +626, 123, 370, +568, 195, 290, +475, 276, 155, +312, 366, 0, +0, 463, 0, +0, 568, 0, +0, 678, 0, +0, 794, 0, +0, 913, 0, +0, 1035, 0, +0, 1159, 0, +0, 1285, 0, +0, 1413, 0, +0, 1542, 0, +0, 1672, 0, +0, 1802, 0, +0, 1932, 0, +0, 2064, 0, +0, 2195, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +850, 65, 596, +831, 112, 570, +804, 168, 534, +765, 233, 479, +707, 308, 395, +616, 393, 250, +457, 485, 0, +82, 585, 0, +0, 692, 0, +0, 804, 0, +0, 921, 0, +0, 1041, 0, +0, 1164, 0, +0, 1289, 0, +0, 1416, 0, +0, 1544, 0, +0, 1673, 0, +0, 1803, 0, +0, 1933, 0, +0, 2064, 0, +0, 2195, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +999, 131, 733, +986, 172, 714, +967, 222, 688, +940, 280, 650, +901, 348, 594, +844, 426, 505, +755, 513, 352, +598, 608, 3, +235, 710, 0, +0, 818, 0, +0, 932, 0, +0, 1049, 0, +0, 1170, 0, +0, 1294, 0, +0, 1420, 0, +0, 1547, 0, +0, 1675, 0, +0, 1805, 0, +0, 1935, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1144, 207, 869, +1134, 242, 855, +1121, 285, 836, +1102, 336, 809, +1075, 397, 770, +1037, 468, 712, +980, 547, 621, +892, 636, 461, +737, 732, 82, +382, 836, 0, +0, 946, 0, +0, 1060, 0, +0, 1179, 0, +0, 1300, 0, +0, 1424, 0, +0, 1550, 0, +0, 1678, 0, +0, 1807, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1286, 293, 1004, +1278, 322, 994, +1268, 358, 980, +1255, 402, 960, +1236, 455, 932, +1210, 518, 893, +1172, 590, 833, +1115, 671, 740, +1027, 761, 574, +874, 859, 170, +525, 964, 0, +0, 1074, 0, +0, 1190, 0, +0, 1309, 0, +0, 1431, 0, +0, 1555, 0, +0, 1682, 0, +0, 1809, 0, +0, 1938, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1424, 386, 1138, +1419, 410, 1131, +1412, 440, 1120, +1402, 477, 1106, +1389, 523, 1086, +1370, 577, 1058, +1343, 641, 1018, +1306, 714, 958, +1250, 797, 862, +1162, 888, 692, +1010, 987, 267, +665, 1093, 0, +0, 1204, 0, +0, 1320, 0, +0, 1439, 0, +0, 1562, 0, +0, 1687, 0, +0, 1813, 0, +0, 1941, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1562, 487, 1272, +1558, 506, 1266, +1552, 531, 1258, +1545, 561, 1248, +1535, 599, 1234, +1522, 646, 1213, +1503, 701, 1185, +1477, 766, 1144, +1439, 840, 1084, +1383, 924, 987, +1296, 1016, 813, +1145, 1116, 370, +802, 1222, 0, +0, 1334, 0, +0, 1450, 0, +0, 1570, 0, +0, 1693, 0, +0, 1818, 0, +0, 1945, 0, +0, 2073, 0, +0, 2202, 0, +0, 2331, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1697, 595, 1405, +1695, 610, 1401, +1691, 629, 1395, +1685, 654, 1387, +1678, 685, 1377, +1668, 724, 1362, +1655, 771, 1342, +1636, 827, 1314, +1610, 893, 1273, +1572, 968, 1211, +1517, 1053, 1113, +1430, 1145, 937, +1279, 1246, 479, +939, 1352, 0, +0, 1465, 0, +0, 1581, 0, +0, 1701, 0, +0, 1824, 0, +0, 1950, 0, +0, 2076, 0, +0, 2204, 0, +0, 2334, 0, +0, 2463, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1832, 707, 1538, +1830, 719, 1535, +1827, 735, 1531, +1823, 755, 1525, +1818, 780, 1517, +1811, 811, 1507, +1801, 851, 1492, +1788, 898, 1472, +1769, 955, 1443, +1743, 1021, 1402, +1705, 1097, 1340, +1650, 1182, 1241, +1563, 1275, 1062, +1412, 1376, 594, +1074, 1483, 0, +0, 1596, 0, +0, 1712, 0, +0, 1833, 0, +0, 1956, 0, +0, 2081, 0, +0, 2208, 0, +0, 2336, 0, +0, 2466, 0, +0, 2595, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1966, 824, 1671, +1965, 834, 1668, +1963, 846, 1665, +1960, 861, 1661, +1956, 881, 1655, +1951, 907, 1647, +1943, 939, 1637, +1934, 978, 1622, +1920, 1026, 1602, +1902, 1084, 1573, +1875, 1150, 1531, +1838, 1227, 1469, +1782, 1312, 1370, +1696, 1406, 1190, +1545, 1507, 712, +1209, 1614, 0, +0, 1727, 0, +0, 1844, 0, +0, 1964, 0, +0, 2088, 0, +0, 2213, 0, +0, 2340, 0, +0, 2468, 0, +0, 2597, 0, +0, 2727, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +2100, 945, 1803, +2099, 952, 1802, +2097, 961, 1799, +2095, 973, 1796, +2092, 989, 1792, +2088, 1009, 1786, +2083, 1035, 1778, +2076, 1067, 1768, +2066, 1107, 1753, +2053, 1156, 1732, +2034, 1213, 1703, +2008, 1280, 1662, +1970, 1357, 1599, +1915, 1442, 1499, +1828, 1536, 1318, +1678, 1638, 834, +1342, 1745, 0, +0, 1858, 0, +0, 1976, 0, +0, 2096, 0, +0, 2220, 0, +0, 2345, 0, +0, 2472, 0, +0, 2600, 0, +0, 2730, 0, +0, 2859, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2233, 1068, 1936, +2232, 1074, 1935, +2231, 1081, 1933, +2230, 1090, 1930, +2227, 1102, 1927, +2225, 1118, 1923, +2221, 1139, 1917, +2215, 1164, 1909, +2208, 1197, 1899, +2198, 1237, 1884, +2185, 1286, 1863, +2166, 1343, 1834, +2140, 1411, 1793, +2103, 1488, 1730, +2047, 1573, 1629, +1961, 1668, 1447, +1811, 1769, 958, +1476, 1877, 0, +0, 1990, 0, +0, 2107, 0, +0, 2228, 0, +0, 2351, 0, +0, 2477, 0, +0, 2604, 0, +0, 2732, 0, +0, 2862, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2366, 1194, 2068, +2366, 1198, 2067, +2365, 1203, 2066, +2364, 1210, 2064, +2362, 1220, 2062, +2360, 1232, 2059, +2357, 1248, 2054, +2353, 1268, 2049, +2348, 1294, 2041, +2340, 1327, 2030, +2331, 1367, 2015, +2317, 1416, 1995, +2299, 1474, 1966, +2273, 1542, 1924, +2235, 1619, 1861, +2180, 1705, 1760, +2093, 1799, 1577, +1944, 1901, 1084, +1609, 2009, 0, +0, 2122, 0, +0, 2239, 0, +0, 2360, 0, +0, 2483, 0, +0, 2609, 0, +0, 2736, 0, +0, 2864, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2499, 1321, 2200, +2499, 1324, 2200, +2498, 1328, 2199, +2497, 1333, 2197, +2496, 1340, 2196, +2494, 1350, 2193, +2492, 1362, 2190, +2489, 1378, 2186, +2485, 1399, 2180, +2480, 1425, 2172, +2473, 1458, 2161, +2463, 1498, 2147, +2450, 1547, 2126, +2431, 1605, 2097, +2405, 1673, 2055, +2367, 1750, 1992, +2312, 1836, 1891, +2226, 1931, 1708, +2076, 2032, 1211, +1742, 2140, 0, +0, 2254, 0, +0, 2371, 0, +0, 2492, 0, +0, 2615, 0, +0, 2741, 0, +0, 2868, 0, +0, 2996, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2632, 1449, 2333, +2631, 1451, 2332, +2631, 1454, 2331, +2630, 1458, 2330, +2629, 1464, 2329, +2628, 1471, 2327, +2626, 1481, 2325, +2624, 1493, 2322, +2621, 1509, 2318, +2617, 1530, 2312, +2612, 1556, 2304, +2605, 1589, 2293, +2595, 1629, 2278, +2582, 1678, 2258, +2563, 1736, 2229, +2537, 1804, 2187, +2500, 1881, 2123, +2444, 1968, 2023, +2358, 2062, 1839, +2208, 2164, 1340, +1874, 2272, 0, +0, 2385, 0, +0, 2503, 0, +0, 2624, 0, +0, 2747, 0, +0, 2873, 0, +0, 3000, 0, +0, 3128, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2764, 1578, 2465, +2764, 1580, 2465, +2763, 1582, 2464, +2763, 1585, 2463, +2762, 1589, 2462, +2761, 1595, 2461, +2760, 1602, 2459, +2759, 1612, 2457, +2756, 1624, 2454, +2753, 1640, 2449, +2750, 1661, 2444, +2744, 1687, 2436, +2737, 1720, 2425, +2727, 1760, 2410, +2714, 1809, 2389, +2695, 1868, 2360, +2669, 1936, 2318, +2632, 2013, 2255, +2577, 2099, 2154, +2490, 2194, 1970, +2341, 2296, 1469, +2007, 2404, 0, +0, 2517, 0, +0, 2635, 0, +0, 2756, 0, +0, 2879, 0, +0, 3005, 0, +0, 3132, 0, +0, 3260, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1708, 2597, +2896, 1709, 2597, +2896, 1711, 2596, +2896, 1713, 2596, +2895, 1716, 2595, +2894, 1721, 2594, +2893, 1726, 2593, +2892, 1733, 2591, +2891, 1743, 2589, +2889, 1755, 2586, +2886, 1771, 2581, +2882, 1792, 2575, +2876, 1818, 2568, +2869, 1851, 2557, +2859, 1892, 2542, +2846, 1941, 2521, +2828, 1999, 2492, +2801, 2067, 2450, +2764, 2145, 2387, +2709, 2231, 2286, +2622, 2326, 2101, +2473, 2428, 1599, +2139, 2536, 0, +0, 2649, 0, +0, 2767, 0, +0, 2888, 0, +0, 3011, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3029, 1838, 2729, +3029, 1839, 2729, +3028, 1841, 2729, +3028, 1842, 2728, +3028, 1845, 2728, +3027, 1848, 2727, +3027, 1852, 2726, +3026, 1858, 2725, +3024, 1865, 2723, +3023, 1874, 2721, +3021, 1887, 2717, +3018, 1903, 2713, +3014, 1924, 2707, +3009, 1950, 2699, +3001, 1983, 2689, +2992, 2024, 2674, +2978, 2073, 2653, +2960, 2131, 2624, +2934, 2199, 2582, +2896, 2277, 2519, +2841, 2363, 2418, +2755, 2458, 2233, +2605, 2560, 1730, +2272, 2668, 0, +0, 2781, 0, +0, 2899, 0, +0, 3020, 0, +0, 3143, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3161, 1969, 2861, +3161, 1970, 2861, +3161, 1971, 2861, +3160, 1972, 2861, +3160, 1974, 2860, +3160, 1976, 2860, +3159, 1980, 2859, +3159, 1984, 2858, +3158, 1989, 2857, +3157, 1996, 2855, +3155, 2006, 2853, +3153, 2018, 2849, +3150, 2035, 2845, +3146, 2055, 2839, +3141, 2082, 2831, +3134, 2115, 2821, +3124, 2155, 2806, +3110, 2205, 2785, +3092, 2263, 2756, +3066, 2331, 2714, +3028, 2409, 2651, +2973, 2495, 2549, +2887, 2590, 2365, +2737, 2692, 1861, +2404, 2800, 0, +0, 2913, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3293, 2100, 2994, +3293, 2101, 2993, +3293, 2102, 2993, +3293, 2103, 2993, +3293, 2104, 2993, +3292, 2106, 2992, +3292, 2108, 2992, +3291, 2111, 2991, +3291, 2115, 2990, +3290, 2121, 2989, +3289, 2128, 2987, +3287, 2138, 2985, +3285, 2150, 2981, +3282, 2166, 2977, +3278, 2187, 2971, +3273, 2213, 2963, +3266, 2246, 2953, +3256, 2287, 2938, +3242, 2336, 2917, +3224, 2395, 2888, +3198, 2463, 2846, +3161, 2541, 2783, +3105, 2627, 2681, +3019, 2722, 2497, +2870, 2824, 1992, +2536, 2932, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3660, 0, +3425, 2232, 3126, +3425, 2232, 3126, +3425, 2233, 3125, +3425, 2233, 3125, +3425, 2234, 3125, +3425, 2236, 3125, +3424, 2238, 3124, +3424, 2240, 3124, +3424, 2243, 3123, +3423, 2247, 3122, +3422, 2253, 3121, +3421, 2260, 3119, +3419, 2270, 3117, +3417, 2282, 3113, +3414, 2298, 3109, +3410, 2319, 3103, +3405, 2345, 3095, +3398, 2378, 3085, +3388, 2419, 3070, +3375, 2468, 3049, +3356, 2527, 3020, +3330, 2595, 2978, +3293, 2673, 2915, +3237, 2759, 2813, +3151, 2854, 2629, +3002, 2956, 2124, +2668, 3064, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2363, 3258, +3557, 2364, 3258, +3557, 2364, 3258, +3557, 2365, 3258, +3557, 2365, 3257, +3557, 2366, 3257, +3557, 2368, 3257, +3557, 2370, 3256, +3556, 2372, 3256, +3556, 2375, 3255, +3555, 2379, 3254, +3554, 2385, 3253, +3553, 2392, 3251, +3551, 2402, 3249, +3549, 2414, 3245, +3546, 2430, 3241, +3542, 2451, 3235, +3537, 2477, 3227, +3530, 2510, 3217, +3520, 2551, 3202, +3507, 2600, 3181, +3488, 2659, 3152, +3462, 2727, 3110, +3425, 2805, 3047, +3369, 2891, 2945, +3283, 2986, 2760, +3134, 3088, 2255, +2800, 3196, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3690, 2495, 3390, +3690, 2495, 3390, +3690, 2496, 3390, +3689, 2496, 3390, +3689, 2497, 3390, +3689, 2497, 3389, +3689, 2498, 3389, +3689, 2500, 3389, +3689, 2501, 3388, +3688, 2504, 3388, +3688, 2507, 3387, +3687, 2511, 3386, +3686, 2517, 3385, +3685, 2524, 3383, +3683, 2534, 3381, +3681, 2546, 3378, +3678, 2562, 3373, +3674, 2583, 3367, +3669, 2609, 3360, +3662, 2642, 3349, +3652, 2683, 3334, +3639, 2732, 3313, +3620, 2791, 3284, +3594, 2859, 3242, +3557, 2937, 3179, +3502, 3023, 3077, +3415, 3118, 2892, +3266, 3220, 2387, +2933, 3328, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3822, 2627, 3522, +3822, 2627, 3522, +3822, 2627, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2629, 3522, +3821, 2629, 3521, +3821, 2630, 3521, +3821, 2632, 3521, +3821, 2633, 3521, +3820, 2636, 3520, +3820, 2639, 3519, +3819, 2643, 3518, +3818, 2649, 3517, +3817, 2656, 3515, +3816, 2666, 3513, +3813, 2678, 3510, +3810, 2694, 3505, +3807, 2715, 3499, +3801, 2741, 3492, +3794, 2774, 3481, +3784, 2815, 3466, +3771, 2864, 3445, +3752, 2923, 3416, +3726, 2991, 3374, +3689, 3069, 3311, +3634, 3155, 3209, +3547, 3250, 3024, +3398, 3352, 2519, +3065, 3460, 0, +0, 3574, 0, +0, 3691, 0, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3953, 2761, 3654, +3953, 2762, 3653, +3953, 2764, 3653, +3953, 2765, 3653, +3952, 2768, 3652, +3952, 2771, 3651, +3951, 2775, 3650, +3950, 2781, 3649, +3949, 2788, 3647, +3948, 2798, 3645, +3945, 2810, 3642, +3943, 2826, 3637, +3939, 2847, 3632, +3933, 2873, 3624, +3926, 2906, 3613, +3916, 2947, 3598, +3903, 2996, 3577, +3884, 3055, 3548, +3858, 3123, 3506, +3821, 3201, 3443, +3766, 3287, 3341, +3679, 3382, 3156, +3530, 3484, 2651, +3197, 3592, 0, +0, 3706, 0, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2893, 3786, +4085, 2894, 3785, +4085, 2896, 3785, +4085, 2897, 3785, +4085, 2900, 3784, +4084, 2903, 3783, +4083, 2907, 3782, +4083, 2913, 3781, +4081, 2920, 3779, +4080, 2930, 3777, +4078, 2942, 3774, +4075, 2958, 3769, +4071, 2979, 3764, +4065, 3005, 3756, +4058, 3038, 3745, +4049, 3079, 3730, +4035, 3128, 3709, +4017, 3187, 3680, +3991, 3255, 3638, +3953, 3333, 3575, +3898, 3419, 3473, +3812, 3514, 3289, +3662, 3616, 2783, +3329, 3725, 0, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3025, 3918, +4095, 3026, 3917, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3032, 3916, +4095, 3035, 3915, +4095, 3039, 3915, +4095, 3045, 3913, +4095, 3052, 3911, +4095, 3062, 3909, +4095, 3074, 3906, +4095, 3090, 3902, +4095, 3111, 3896, +4095, 3137, 3888, +4095, 3170, 3877, +4095, 3211, 3862, +4095, 3261, 3842, +4095, 3319, 3812, +4095, 3387, 3770, +4085, 3465, 3707, +4030, 3551, 3605, +3944, 3646, 3421, +3794, 3748, 2915, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3167, 4048, +4095, 3171, 4047, +4095, 3177, 4045, +4095, 3184, 4044, +4095, 3194, 4041, +4095, 3206, 4038, +4095, 3222, 4034, +4095, 3243, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3343, 3994, +4095, 3393, 3974, +4095, 3451, 3944, +4095, 3519, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 0, 0, +0, 0, 0, +0, 49, 0, +0, 132, 0, +0, 224, 0, +0, 324, 0, +0, 430, 0, +0, 542, 0, +0, 658, 0, +0, 778, 0, +0, 901, 0, +0, 1025, 0, +0, 1152, 0, +0, 1280, 0, +0, 1409, 0, +0, 1539, 0, +0, 1669, 0, +0, 1800, 0, +0, 1931, 0, +0, 2063, 0, +0, 2194, 0, +0, 2326, 0, +0, 2458, 0, +0, 2589, 0, +0, 2721, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3381, 0, +0, 3514, 0, +0, 3646, 0, +104, 0, 80, +0, 0, 0, +0, 66, 0, +0, 147, 0, +0, 236, 0, +0, 333, 0, +0, 438, 0, +0, 548, 0, +0, 662, 0, +0, 781, 0, +0, 903, 0, +0, 1028, 0, +0, 1154, 0, +0, 1281, 0, +0, 1410, 0, +0, 1540, 0, +0, 1670, 0, +0, 1800, 0, +0, 1931, 0, +0, 2063, 0, +0, 2194, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2721, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3381, 0, +0, 3514, 0, +0, 3646, 0, +326, 0, 214, +262, 20, 152, +160, 88, 54, +0, 165, 0, +0, 251, 0, +0, 346, 0, +0, 447, 0, +0, 555, 0, +0, 668, 0, +0, 786, 0, +0, 907, 0, +0, 1030, 0, +0, 1156, 0, +0, 1283, 0, +0, 1411, 0, +0, 1540, 0, +0, 1670, 0, +0, 1801, 0, +0, 1932, 0, +0, 2063, 0, +0, 2194, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +515, 0, 347, +474, 52, 302, +413, 116, 234, +315, 188, 122, +139, 271, 0, +0, 361, 0, +0, 460, 0, +0, 565, 0, +0, 676, 0, +0, 792, 0, +0, 911, 0, +0, 1034, 0, +0, 1158, 0, +0, 1285, 0, +0, 1413, 0, +0, 1542, 0, +0, 1671, 0, +0, 1802, 0, +0, 1932, 0, +0, 2063, 0, +0, 2195, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +686, 42, 481, +658, 92, 447, +618, 150, 399, +558, 218, 324, +463, 295, 200, +295, 382, 0, +0, 477, 0, +0, 579, 0, +0, 687, 0, +0, 800, 0, +0, 918, 0, +0, 1039, 0, +0, 1162, 0, +0, 1288, 0, +0, 1415, 0, +0, 1543, 0, +0, 1673, 0, +0, 1802, 0, +0, 1933, 0, +0, 2064, 0, +0, 2195, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +844, 96, 614, +825, 140, 589, +798, 192, 554, +758, 255, 502, +700, 327, 422, +607, 408, 287, +444, 498, 4, +53, 596, 0, +0, 700, 0, +0, 811, 0, +0, 926, 0, +0, 1045, 0, +0, 1167, 0, +0, 1291, 0, +0, 1418, 0, +0, 1545, 0, +0, 1674, 0, +0, 1804, 0, +0, 1934, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +996, 158, 746, +982, 197, 728, +963, 244, 702, +936, 300, 666, +897, 365, 611, +839, 440, 527, +748, 525, 382, +589, 617, 65, +214, 718, 0, +0, 824, 0, +0, 936, 0, +0, 1053, 0, +0, 1173, 0, +0, 1296, 0, +0, 1421, 0, +0, 1548, 0, +0, 1676, 0, +0, 1805, 0, +0, 1935, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1141, 230, 879, +1131, 263, 865, +1118, 304, 846, +1099, 354, 820, +1072, 412, 782, +1034, 481, 726, +976, 558, 638, +887, 645, 484, +730, 740, 135, +367, 842, 0, +0, 950, 0, +0, 1064, 0, +0, 1181, 0, +0, 1302, 0, +0, 1426, 0, +0, 1552, 0, +0, 1679, 0, +0, 1807, 0, +0, 1937, 0, +0, 2067, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1284, 312, 1011, +1276, 340, 1001, +1266, 374, 987, +1253, 417, 968, +1234, 468, 941, +1207, 529, 902, +1169, 600, 844, +1112, 679, 753, +1024, 768, 593, +869, 865, 214, +514, 968, 0, +0, 1078, 0, +0, 1192, 0, +0, 1311, 0, +0, 1432, 0, +0, 1557, 0, +0, 1683, 0, +0, 1810, 0, +0, 1939, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1423, 402, 1144, +1418, 425, 1136, +1410, 454, 1126, +1401, 490, 1112, +1387, 534, 1092, +1368, 587, 1064, +1342, 650, 1025, +1304, 722, 966, +1247, 803, 872, +1159, 893, 706, +1006, 991, 302, +657, 1096, 0, +0, 1206, 0, +0, 1322, 0, +0, 1441, 0, +0, 1563, 0, +0, 1687, 0, +0, 1814, 0, +0, 1941, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1561, 500, 1276, +1557, 518, 1270, +1551, 542, 1263, +1544, 572, 1252, +1534, 609, 1238, +1521, 655, 1218, +1502, 709, 1190, +1476, 773, 1150, +1438, 846, 1090, +1382, 929, 994, +1294, 1020, 824, +1142, 1119, 399, +797, 1225, 0, +0, 1336, 0, +0, 1452, 0, +0, 1571, 0, +0, 1694, 0, +0, 1819, 0, +0, 1945, 0, +0, 2073, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1697, 605, 1408, +1694, 619, 1404, +1690, 639, 1398, +1684, 663, 1391, +1677, 694, 1380, +1667, 732, 1366, +1654, 778, 1346, +1635, 833, 1317, +1609, 898, 1277, +1571, 973, 1216, +1515, 1056, 1119, +1428, 1148, 945, +1277, 1248, 502, +935, 1354, 0, +0, 1466, 0, +0, 1582, 0, +0, 1702, 0, +0, 1825, 0, +0, 1950, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1832, 715, 1540, +1830, 727, 1537, +1827, 742, 1533, +1823, 761, 1527, +1817, 786, 1519, +1810, 818, 1509, +1800, 856, 1494, +1787, 903, 1474, +1768, 959, 1446, +1742, 1025, 1405, +1704, 1100, 1343, +1649, 1185, 1245, +1562, 1277, 1069, +1411, 1378, 612, +1071, 1484, 0, +0, 1597, 0, +0, 1713, 0, +0, 1833, 0, +0, 1956, 0, +0, 2082, 0, +0, 2208, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1966, 830, 1672, +1964, 840, 1670, +1962, 851, 1667, +1959, 867, 1663, +1955, 887, 1657, +1950, 912, 1649, +1943, 943, 1639, +1933, 983, 1624, +1920, 1030, 1604, +1901, 1087, 1575, +1875, 1153, 1534, +1837, 1229, 1472, +1782, 1314, 1373, +1695, 1407, 1194, +1544, 1508, 726, +1206, 1615, 0, +0, 1728, 0, +0, 1845, 0, +0, 1965, 0, +0, 2088, 0, +0, 2213, 0, +0, 2340, 0, +0, 2468, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +2100, 950, 1805, +2099, 957, 1803, +2097, 966, 1801, +2095, 978, 1797, +2092, 993, 1793, +2088, 1013, 1787, +2083, 1039, 1780, +2075, 1071, 1769, +2066, 1110, 1754, +2052, 1159, 1734, +2034, 1216, 1705, +2007, 1282, 1663, +1970, 1359, 1601, +1914, 1444, 1502, +1828, 1538, 1322, +1678, 1639, 844, +1341, 1746, 0, +0, 1859, 0, +0, 1976, 0, +0, 2097, 0, +0, 2220, 0, +0, 2345, 0, +0, 2472, 0, +0, 2600, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2233, 1072, 1937, +2232, 1077, 1935, +2231, 1084, 1934, +2229, 1093, 1931, +2227, 1106, 1928, +2224, 1121, 1924, +2220, 1142, 1918, +2215, 1167, 1910, +2208, 1200, 1900, +2198, 1239, 1885, +2185, 1288, 1864, +2166, 1345, 1836, +2140, 1412, 1794, +2103, 1489, 1731, +2047, 1575, 1631, +1960, 1669, 1450, +1810, 1770, 966, +1475, 1878, 0, +0, 1990, 0, +0, 2108, 0, +0, 2228, 0, +0, 2352, 0, +0, 2477, 0, +0, 2604, 0, +0, 2732, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2366, 1196, 2069, +2365, 1200, 2068, +2365, 1206, 2067, +2363, 1213, 2065, +2362, 1222, 2063, +2360, 1234, 2059, +2357, 1250, 2055, +2353, 1271, 2049, +2347, 1297, 2041, +2340, 1329, 2031, +2330, 1369, 2016, +2317, 1418, 1995, +2298, 1475, 1966, +2272, 1543, 1925, +2235, 1620, 1862, +2180, 1706, 1762, +2093, 1800, 1579, +1943, 1901, 1090, +1608, 2009, 0, +0, 2122, 0, +0, 2239, 0, +0, 2360, 0, +0, 2483, 0, +0, 2609, 0, +0, 2736, 0, +0, 2864, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2499, 1323, 2201, +2498, 1326, 2200, +2498, 1330, 2199, +2497, 1335, 2198, +2496, 1342, 2196, +2494, 1352, 2194, +2492, 1364, 2191, +2489, 1380, 2186, +2485, 1400, 2181, +2480, 1426, 2173, +2473, 1459, 2162, +2463, 1499, 2147, +2449, 1548, 2127, +2431, 1606, 2098, +2405, 1674, 2056, +2367, 1751, 1993, +2312, 1837, 1892, +2225, 1931, 1709, +2076, 2033, 1216, +1741, 2141, 0, +0, 2254, 0, +0, 2371, 0, +0, 2492, 0, +0, 2615, 0, +0, 2741, 0, +0, 2868, 0, +0, 2996, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2631, 1450, 2333, +2631, 1453, 2333, +2631, 1456, 2332, +2630, 1460, 2331, +2629, 1465, 2330, +2628, 1473, 2328, +2626, 1482, 2325, +2624, 1494, 2322, +2621, 1510, 2318, +2617, 1531, 2312, +2612, 1557, 2304, +2605, 1590, 2294, +2595, 1630, 2279, +2582, 1679, 2258, +2563, 1737, 2229, +2537, 1805, 2187, +2500, 1882, 2124, +2444, 1968, 2023, +2358, 2063, 1840, +2208, 2164, 1343, +1874, 2272, 0, +0, 2386, 0, +0, 2503, 0, +0, 2624, 0, +0, 2747, 0, +0, 2873, 0, +0, 3000, 0, +0, 3128, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2764, 1579, 2465, +2764, 1581, 2465, +2763, 1583, 2464, +2763, 1586, 2464, +2762, 1590, 2463, +2761, 1596, 2461, +2760, 1603, 2460, +2758, 1613, 2457, +2756, 1625, 2454, +2753, 1641, 2450, +2749, 1662, 2444, +2744, 1688, 2436, +2737, 1721, 2425, +2727, 1761, 2410, +2714, 1810, 2390, +2695, 1868, 2361, +2669, 1936, 2319, +2632, 2013, 2256, +2576, 2100, 2155, +2490, 2194, 1971, +2341, 2296, 1472, +2006, 2404, 0, +0, 2518, 0, +0, 2635, 0, +0, 2756, 0, +0, 2879, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1709, 2597, +2896, 1710, 2597, +2896, 1712, 2597, +2895, 1714, 2596, +2895, 1717, 2595, +2894, 1721, 2594, +2893, 1727, 2593, +2892, 1734, 2591, +2891, 1744, 2589, +2888, 1756, 2586, +2886, 1772, 2581, +2882, 1793, 2576, +2876, 1819, 2568, +2869, 1852, 2557, +2859, 1892, 2542, +2846, 1942, 2522, +2827, 2000, 2492, +2801, 2068, 2450, +2764, 2145, 2387, +2709, 2232, 2286, +2622, 2326, 2102, +2473, 2428, 1601, +2139, 2536, 0, +0, 2650, 0, +0, 2767, 0, +0, 2888, 0, +0, 3011, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3029, 1839, 2729, +3029, 1840, 2729, +3028, 1841, 2729, +3028, 1843, 2729, +3028, 1845, 2728, +3027, 1849, 2727, +3026, 1853, 2726, +3026, 1858, 2725, +3024, 1865, 2723, +3023, 1875, 2721, +3021, 1887, 2718, +3018, 1904, 2713, +3014, 1924, 2708, +3009, 1950, 2700, +3001, 1983, 2689, +2992, 2024, 2674, +2978, 2073, 2653, +2960, 2132, 2624, +2934, 2199, 2582, +2896, 2277, 2519, +2841, 2363, 2418, +2754, 2458, 2234, +2605, 2560, 1732, +2271, 2668, 0, +0, 2781, 0, +0, 2899, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3161, 1970, 2862, +3161, 1970, 2861, +3161, 1971, 2861, +3160, 1973, 2861, +3160, 1975, 2860, +3160, 1977, 2860, +3159, 1980, 2859, +3159, 1984, 2858, +3158, 1990, 2857, +3157, 1997, 2855, +3155, 2006, 2853, +3153, 2019, 2850, +3150, 2035, 2845, +3146, 2056, 2839, +3141, 2082, 2832, +3133, 2115, 2821, +3124, 2156, 2806, +3110, 2205, 2785, +3092, 2263, 2756, +3066, 2331, 2714, +3028, 2409, 2651, +2973, 2495, 2550, +2887, 2590, 2365, +2737, 2692, 1862, +2404, 2800, 0, +0, 2914, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3293, 2101, 2994, +3293, 2101, 2994, +3293, 2102, 2993, +3293, 2103, 2993, +3293, 2104, 2993, +3292, 2106, 2992, +3292, 2109, 2992, +3291, 2112, 2991, +3291, 2116, 2990, +3290, 2121, 2989, +3289, 2129, 2987, +3287, 2138, 2985, +3285, 2151, 2982, +3282, 2167, 2977, +3278, 2187, 2971, +3273, 2214, 2963, +3266, 2247, 2953, +3256, 2287, 2938, +3242, 2337, 2917, +3224, 2395, 2888, +3198, 2463, 2846, +3160, 2541, 2783, +3105, 2627, 2681, +3019, 2722, 2497, +2870, 2824, 1993, +2536, 2932, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3660, 0, +3425, 2232, 3126, +3425, 2232, 3126, +3425, 2233, 3126, +3425, 2234, 3125, +3425, 2235, 3125, +3425, 2236, 3125, +3424, 2238, 3124, +3424, 2240, 3124, +3424, 2243, 3123, +3423, 2248, 3122, +3422, 2253, 3121, +3421, 2260, 3119, +3419, 2270, 3117, +3417, 2282, 3114, +3414, 2299, 3109, +3410, 2319, 3103, +3405, 2346, 3095, +3398, 2379, 3085, +3388, 2419, 3070, +3375, 2469, 3049, +3356, 2527, 3020, +3330, 2595, 2978, +3293, 2673, 2915, +3237, 2759, 2813, +3151, 2854, 2629, +3002, 2956, 2124, +2668, 3064, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2364, 3258, +3557, 2364, 3258, +3557, 2364, 3258, +3557, 2365, 3258, +3557, 2366, 3257, +3557, 2367, 3257, +3557, 2368, 3257, +3557, 2370, 3256, +3556, 2372, 3256, +3556, 2375, 3255, +3555, 2379, 3254, +3554, 2385, 3253, +3553, 2392, 3251, +3551, 2402, 3249, +3549, 2414, 3246, +3546, 2430, 3241, +3542, 2451, 3235, +3537, 2477, 3228, +3530, 2510, 3217, +3520, 2551, 3202, +3507, 2600, 3181, +3488, 2659, 3152, +3462, 2727, 3110, +3425, 2805, 3047, +3369, 2891, 2945, +3283, 2986, 2761, +3134, 3088, 2256, +2800, 3196, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3690, 2495, 3390, +3690, 2495, 3390, +3690, 2496, 3390, +3689, 2496, 3390, +3689, 2497, 3390, +3689, 2497, 3389, +3689, 2498, 3389, +3689, 2500, 3389, +3689, 2502, 3389, +3688, 2504, 3388, +3688, 2507, 3387, +3687, 2511, 3386, +3686, 2517, 3385, +3685, 2524, 3383, +3683, 2534, 3381, +3681, 2546, 3378, +3678, 2562, 3373, +3674, 2583, 3367, +3669, 2609, 3360, +3662, 2642, 3349, +3652, 2683, 3334, +3639, 2732, 3313, +3620, 2791, 3284, +3594, 2859, 3242, +3557, 2937, 3179, +3502, 3023, 3077, +3415, 3118, 2893, +3266, 3220, 2387, +2933, 3328, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3822, 2627, 3522, +3822, 2627, 3522, +3822, 2627, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3821, 2629, 3522, +3821, 2629, 3522, +3821, 2630, 3521, +3821, 2632, 3521, +3821, 2634, 3521, +3820, 2636, 3520, +3820, 2639, 3519, +3819, 2643, 3518, +3818, 2649, 3517, +3817, 2656, 3515, +3815, 2666, 3513, +3813, 2678, 3510, +3810, 2694, 3505, +3807, 2715, 3500, +3801, 2741, 3492, +3794, 2774, 3481, +3784, 2815, 3466, +3771, 2864, 3445, +3752, 2923, 3416, +3726, 2991, 3374, +3689, 3069, 3311, +3634, 3155, 3209, +3547, 3250, 3025, +3398, 3352, 2519, +3065, 3460, 0, +0, 3574, 0, +0, 3691, 0, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3953, 2761, 3654, +3953, 2762, 3653, +3953, 2764, 3653, +3953, 2766, 3653, +3952, 2768, 3652, +3952, 2771, 3651, +3951, 2775, 3650, +3950, 2781, 3649, +3949, 2788, 3647, +3948, 2798, 3645, +3945, 2810, 3642, +3943, 2826, 3637, +3939, 2847, 3632, +3933, 2873, 3624, +3926, 2906, 3613, +3916, 2947, 3598, +3903, 2996, 3577, +3884, 3055, 3548, +3858, 3123, 3506, +3821, 3201, 3443, +3766, 3287, 3341, +3679, 3382, 3157, +3530, 3484, 2651, +3197, 3592, 0, +0, 3706, 0, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2893, 3786, +4085, 2894, 3785, +4085, 2896, 3785, +4085, 2898, 3785, +4085, 2900, 3784, +4084, 2903, 3783, +4083, 2907, 3782, +4083, 2913, 3781, +4081, 2920, 3779, +4080, 2930, 3777, +4078, 2942, 3774, +4075, 2958, 3769, +4071, 2979, 3764, +4065, 3005, 3756, +4058, 3038, 3745, +4049, 3079, 3730, +4035, 3129, 3709, +4017, 3187, 3680, +3991, 3255, 3638, +3953, 3333, 3575, +3898, 3419, 3473, +3811, 3514, 3289, +3662, 3616, 2783, +3329, 3725, 0, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3032, 3916, +4095, 3035, 3916, +4095, 3039, 3915, +4095, 3045, 3913, +4095, 3052, 3911, +4095, 3062, 3909, +4095, 3074, 3906, +4095, 3090, 3902, +4095, 3111, 3896, +4095, 3137, 3888, +4095, 3171, 3877, +4095, 3211, 3862, +4095, 3261, 3842, +4095, 3319, 3812, +4095, 3387, 3770, +4085, 3465, 3707, +4030, 3551, 3605, +3944, 3646, 3421, +3794, 3748, 2915, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3167, 4048, +4095, 3171, 4047, +4095, 3177, 4045, +4095, 3184, 4044, +4095, 3194, 4041, +4095, 3206, 4038, +4095, 3222, 4034, +4095, 3243, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3343, 3994, +4095, 3393, 3974, +4095, 3451, 3944, +4095, 3519, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 0, 36, +0, 24, 0, +0, 91, 0, +0, 168, 0, +0, 254, 0, +0, 348, 0, +0, 449, 0, +0, 557, 0, +0, 669, 0, +0, 787, 0, +0, 907, 0, +0, 1031, 0, +0, 1156, 0, +0, 1283, 0, +0, 1411, 0, +0, 1541, 0, +0, 1671, 0, +0, 1801, 0, +0, 1932, 0, +0, 2063, 0, +0, 2195, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +67, 0, 149, +0, 42, 77, +0, 107, 0, +0, 181, 0, +0, 264, 0, +0, 356, 0, +0, 456, 0, +0, 562, 0, +0, 674, 0, +0, 790, 0, +0, 910, 0, +0, 1033, 0, +0, 1158, 0, +0, 1284, 0, +0, 1412, 0, +0, 1541, 0, +0, 1671, 0, +0, 1801, 0, +0, 1932, 0, +0, 2063, 0, +0, 2195, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2853, 0, +0, 2985, 0, +0, 3117, 0, +0, 3249, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +303, 13, 267, +236, 65, 212, +127, 127, 127, +0, 198, 0, +0, 279, 0, +0, 368, 0, +0, 465, 0, +0, 570, 0, +0, 680, 0, +0, 795, 0, +0, 913, 0, +0, 1035, 0, +0, 1160, 0, +0, 1286, 0, +0, 1413, 0, +0, 1542, 0, +0, 1672, 0, +0, 1802, 0, +0, 1933, 0, +0, 2064, 0, +0, 2195, 0, +0, 2326, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2985, 0, +0, 3117, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +500, 45, 387, +458, 94, 346, +394, 152, 284, +292, 220, 186, +105, 297, 8, +0, 383, 0, +0, 478, 0, +0, 579, 0, +0, 687, 0, +0, 801, 0, +0, 918, 0, +0, 1039, 0, +0, 1162, 0, +0, 1288, 0, +0, 1415, 0, +0, 1543, 0, +0, 1673, 0, +0, 1803, 0, +0, 1933, 0, +0, 2064, 0, +0, 2195, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +676, 85, 511, +647, 130, 480, +606, 184, 434, +545, 248, 366, +447, 321, 254, +271, 403, 43, +0, 494, 0, +0, 592, 0, +0, 697, 0, +0, 808, 0, +0, 924, 0, +0, 1044, 0, +0, 1166, 0, +0, 1291, 0, +0, 1417, 0, +0, 1545, 0, +0, 1674, 0, +0, 1803, 0, +0, 1934, 0, +0, 2064, 0, +0, 2196, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +837, 134, 636, +818, 175, 613, +790, 224, 579, +750, 282, 531, +690, 350, 456, +596, 428, 332, +427, 514, 85, +12, 609, 0, +0, 711, 0, +0, 819, 0, +0, 932, 0, +0, 1050, 0, +0, 1171, 0, +0, 1294, 0, +0, 1420, 0, +0, 1547, 0, +0, 1675, 0, +0, 1805, 0, +0, 1935, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +991, 192, 763, +977, 228, 746, +957, 272, 721, +930, 325, 686, +891, 387, 634, +832, 459, 554, +740, 540, 419, +577, 630, 136, +186, 728, 0, +0, 832, 0, +0, 943, 0, +0, 1058, 0, +0, 1177, 0, +0, 1299, 0, +0, 1423, 0, +0, 1550, 0, +0, 1677, 0, +0, 1806, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1138, 259, 892, +1128, 290, 878, +1114, 329, 860, +1095, 376, 834, +1068, 432, 798, +1029, 497, 743, +971, 572, 659, +880, 657, 514, +721, 749, 197, +347, 850, 0, +0, 956, 0, +0, 1068, 0, +0, 1185, 0, +0, 1305, 0, +0, 1428, 0, +0, 1553, 0, +0, 1680, 0, +0, 1808, 0, +0, 1937, 0, +0, 2067, 0, +0, 2198, 0, +0, 2328, 0, +0, 2460, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1281, 336, 1021, +1274, 362, 1011, +1264, 395, 997, +1250, 436, 978, +1231, 486, 952, +1204, 544, 914, +1166, 613, 858, +1109, 690, 770, +1019, 777, 616, +862, 872, 267, +499, 974, 0, +0, 1082, 0, +0, 1196, 0, +0, 1314, 0, +0, 1435, 0, +0, 1558, 0, +0, 1684, 0, +0, 1811, 0, +0, 1939, 0, +0, 2069, 0, +0, 2199, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1421, 422, 1151, +1416, 444, 1143, +1408, 472, 1133, +1398, 506, 1119, +1385, 549, 1100, +1366, 601, 1073, +1339, 661, 1034, +1301, 732, 976, +1245, 811, 885, +1156, 900, 725, +1001, 997, 346, +646, 1100, 0, +0, 1210, 0, +0, 1324, 0, +0, 1443, 0, +0, 1565, 0, +0, 1689, 0, +0, 1815, 0, +0, 1942, 0, +0, 2071, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1559, 516, 1281, +1555, 534, 1276, +1550, 557, 1268, +1543, 586, 1258, +1533, 622, 1244, +1519, 666, 1224, +1500, 719, 1197, +1474, 782, 1157, +1436, 854, 1098, +1380, 935, 1004, +1291, 1025, 838, +1138, 1123, 434, +789, 1228, 0, +0, 1339, 0, +0, 1454, 0, +0, 1573, 0, +0, 1695, 0, +0, 1820, 0, +0, 1946, 0, +0, 2074, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1696, 617, 1412, +1693, 632, 1408, +1689, 651, 1402, +1683, 674, 1395, +1676, 704, 1384, +1666, 741, 1370, +1653, 787, 1350, +1634, 841, 1322, +1608, 905, 1282, +1570, 978, 1222, +1514, 1061, 1126, +1426, 1152, 956, +1274, 1251, 531, +929, 1357, 0, +0, 1468, 0, +0, 1584, 0, +0, 1703, 0, +0, 1826, 0, +0, 1951, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1831, 725, 1543, +1829, 737, 1540, +1826, 752, 1536, +1822, 771, 1530, +1817, 795, 1523, +1809, 826, 1512, +1800, 864, 1498, +1786, 910, 1478, +1767, 965, 1449, +1741, 1030, 1409, +1703, 1105, 1348, +1648, 1188, 1251, +1560, 1280, 1077, +1409, 1380, 634, +1067, 1486, 0, +0, 1598, 0, +0, 1714, 0, +0, 1834, 0, +0, 1957, 0, +0, 2082, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1965, 838, 1675, +1964, 847, 1672, +1962, 859, 1669, +1959, 874, 1665, +1955, 894, 1659, +1949, 918, 1652, +1942, 950, 1641, +1932, 988, 1626, +1919, 1035, 1606, +1900, 1092, 1578, +1874, 1157, 1537, +1837, 1232, 1475, +1781, 1317, 1377, +1694, 1409, 1201, +1543, 1510, 744, +1203, 1617, 0, +0, 1729, 0, +0, 1845, 0, +0, 1966, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +2099, 956, 1806, +2098, 963, 1805, +2097, 972, 1802, +2094, 983, 1799, +2091, 999, 1795, +2087, 1019, 1789, +2082, 1044, 1781, +2075, 1076, 1771, +2065, 1115, 1756, +2052, 1162, 1736, +2033, 1219, 1707, +2007, 1285, 1666, +1969, 1361, 1604, +1914, 1446, 1505, +1827, 1539, 1326, +1676, 1640, 858, +1338, 1747, 0, +0, 1860, 0, +0, 1977, 0, +0, 2097, 0, +0, 2220, 0, +0, 2345, 0, +0, 2472, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2233, 1076, 1938, +2232, 1082, 1937, +2231, 1089, 1935, +2229, 1098, 1933, +2227, 1110, 1929, +2224, 1125, 1925, +2220, 1146, 1919, +2215, 1171, 1912, +2208, 1203, 1901, +2198, 1243, 1886, +2184, 1291, 1866, +2166, 1348, 1837, +2140, 1415, 1796, +2102, 1491, 1733, +2047, 1576, 1634, +1960, 1670, 1454, +1810, 1771, 976, +1473, 1878, 0, +0, 1991, 0, +0, 2108, 0, +0, 2229, 0, +0, 2352, 0, +0, 2477, 0, +0, 2604, 0, +0, 2732, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2366, 1200, 2070, +2365, 1204, 2069, +2364, 1209, 2068, +2363, 1216, 2066, +2361, 1226, 2063, +2359, 1238, 2060, +2356, 1253, 2056, +2352, 1274, 2050, +2347, 1299, 2042, +2340, 1332, 2032, +2330, 1371, 2017, +2317, 1420, 1997, +2298, 1477, 1968, +2272, 1544, 1926, +2235, 1621, 1863, +2179, 1707, 1763, +2092, 1801, 1582, +1943, 1902, 1098, +1607, 2010, 0, +0, 2123, 0, +0, 2240, 0, +0, 2360, 0, +0, 2484, 0, +0, 2609, 0, +0, 2736, 0, +0, 2864, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2499, 1325, 2202, +2498, 1328, 2201, +2498, 1332, 2200, +2497, 1338, 2199, +2495, 1345, 2197, +2494, 1354, 2195, +2492, 1367, 2191, +2489, 1382, 2187, +2485, 1403, 2181, +2480, 1429, 2174, +2472, 1461, 2163, +2463, 1501, 2148, +2449, 1550, 2128, +2431, 1608, 2099, +2404, 1675, 2057, +2367, 1752, 1994, +2312, 1838, 1894, +2225, 1932, 1711, +2075, 2033, 1222, +1740, 2141, 0, +0, 2254, 0, +0, 2371, 0, +0, 2492, 0, +0, 2616, 0, +0, 2741, 0, +0, 2868, 0, +0, 2996, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2631, 1452, 2334, +2631, 1455, 2333, +2630, 1458, 2332, +2630, 1462, 2331, +2629, 1467, 2330, +2628, 1474, 2328, +2626, 1484, 2326, +2624, 1496, 2323, +2621, 1512, 2319, +2617, 1533, 2313, +2612, 1559, 2305, +2605, 1591, 2294, +2595, 1631, 2279, +2581, 1680, 2259, +2563, 1738, 2230, +2537, 1806, 2188, +2499, 1883, 2125, +2444, 1969, 2024, +2357, 2063, 1842, +2208, 2165, 1348, +1873, 2273, 0, +0, 2386, 0, +0, 2503, 0, +0, 2624, 0, +0, 2748, 0, +0, 2873, 0, +0, 3000, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2764, 1581, 2466, +2764, 1582, 2465, +2763, 1585, 2465, +2763, 1588, 2464, +2762, 1592, 2463, +2761, 1597, 2462, +2760, 1605, 2460, +2758, 1614, 2458, +2756, 1626, 2454, +2753, 1642, 2450, +2749, 1663, 2444, +2744, 1689, 2436, +2737, 1722, 2426, +2727, 1762, 2411, +2714, 1811, 2390, +2695, 1869, 2361, +2669, 1937, 2319, +2632, 2014, 2256, +2576, 2100, 2155, +2490, 2195, 1972, +2340, 2297, 1475, +2006, 2405, 0, +0, 2518, 0, +0, 2635, 0, +0, 2756, 0, +0, 2880, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1710, 2598, +2896, 1711, 2597, +2896, 1713, 2597, +2895, 1715, 2596, +2895, 1718, 2596, +2894, 1723, 2595, +2893, 1728, 2593, +2892, 1735, 2592, +2891, 1745, 2589, +2888, 1757, 2586, +2885, 1773, 2582, +2882, 1794, 2576, +2876, 1820, 2568, +2869, 1853, 2557, +2859, 1893, 2542, +2846, 1942, 2522, +2827, 2001, 2493, +2801, 2068, 2451, +2764, 2146, 2388, +2709, 2232, 2287, +2622, 2326, 2103, +2473, 2428, 1604, +2139, 2536, 0, +0, 2650, 0, +0, 2767, 0, +0, 2888, 0, +0, 3012, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3029, 1840, 2730, +3028, 1841, 2729, +3028, 1842, 2729, +3028, 1844, 2729, +3028, 1846, 2728, +3027, 1849, 2727, +3026, 1854, 2726, +3026, 1859, 2725, +3024, 1866, 2723, +3023, 1876, 2721, +3021, 1888, 2718, +3018, 1904, 2714, +3014, 1925, 2708, +3008, 1951, 2700, +3001, 1984, 2689, +2992, 2025, 2674, +2978, 2074, 2654, +2960, 2132, 2625, +2933, 2200, 2582, +2896, 2277, 2519, +2841, 2364, 2418, +2754, 2458, 2234, +2605, 2560, 1733, +2271, 2668, 0, +0, 2782, 0, +0, 2899, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3161, 1970, 2862, +3161, 1971, 2862, +3161, 1972, 2861, +3160, 1973, 2861, +3160, 1975, 2861, +3160, 1978, 2860, +3159, 1981, 2859, +3159, 1985, 2858, +3158, 1990, 2857, +3156, 1998, 2855, +3155, 2007, 2853, +3153, 2020, 2850, +3150, 2036, 2845, +3146, 2056, 2840, +3141, 2083, 2832, +3133, 2115, 2821, +3124, 2156, 2806, +3110, 2205, 2785, +3092, 2264, 2756, +3066, 2332, 2714, +3028, 2409, 2651, +2973, 2495, 2550, +2887, 2590, 2366, +2737, 2692, 1864, +2403, 2800, 0, +0, 2914, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3293, 2101, 2994, +3293, 2102, 2994, +3293, 2103, 2993, +3293, 2104, 2993, +3293, 2105, 2993, +3292, 2107, 2993, +3292, 2109, 2992, +3291, 2112, 2991, +3291, 2116, 2990, +3290, 2122, 2989, +3289, 2129, 2987, +3287, 2139, 2985, +3285, 2151, 2982, +3282, 2167, 2977, +3278, 2188, 2972, +3273, 2214, 2964, +3266, 2247, 2953, +3256, 2288, 2938, +3242, 2337, 2917, +3224, 2395, 2888, +3198, 2463, 2846, +3160, 2541, 2783, +3105, 2627, 2682, +3019, 2722, 2497, +2869, 2824, 1994, +2536, 2932, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3660, 0, +3425, 2232, 3126, +3425, 2233, 3126, +3425, 2233, 3126, +3425, 2234, 3125, +3425, 2235, 3125, +3425, 2236, 3125, +3424, 2238, 3125, +3424, 2241, 3124, +3424, 2244, 3123, +3423, 2248, 3122, +3422, 2253, 3121, +3421, 2261, 3119, +3419, 2270, 3117, +3417, 2283, 3114, +3414, 2299, 3109, +3410, 2320, 3103, +3405, 2346, 3096, +3398, 2379, 3085, +3388, 2420, 3070, +3375, 2469, 3049, +3356, 2527, 3020, +3330, 2595, 2978, +3293, 2673, 2915, +3237, 2759, 2814, +3151, 2854, 2629, +3002, 2956, 2125, +2668, 3064, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2364, 3258, +3557, 2364, 3258, +3557, 2365, 3258, +3557, 2365, 3258, +3557, 2366, 3257, +3557, 2367, 3257, +3557, 2368, 3257, +3557, 2370, 3257, +3556, 2372, 3256, +3556, 2375, 3255, +3555, 2380, 3254, +3554, 2385, 3253, +3553, 2392, 3251, +3551, 2402, 3249, +3549, 2414, 3246, +3546, 2431, 3241, +3542, 2451, 3235, +3537, 2478, 3228, +3530, 2511, 3217, +3520, 2551, 3202, +3507, 2601, 3181, +3488, 2659, 3152, +3462, 2727, 3110, +3425, 2805, 3047, +3369, 2891, 2945, +3283, 2986, 2761, +3134, 3088, 2256, +2800, 3196, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3690, 2495, 3390, +3690, 2496, 3390, +3690, 2496, 3390, +3689, 2496, 3390, +3689, 2497, 3390, +3689, 2498, 3389, +3689, 2499, 3389, +3689, 2500, 3389, +3689, 2502, 3389, +3688, 2504, 3388, +3688, 2507, 3387, +3687, 2511, 3386, +3686, 2517, 3385, +3685, 2524, 3383, +3683, 2534, 3381, +3681, 2546, 3378, +3678, 2562, 3373, +3674, 2583, 3368, +3669, 2610, 3360, +3662, 2643, 3349, +3652, 2683, 3334, +3639, 2733, 3313, +3620, 2791, 3284, +3594, 2859, 3242, +3557, 2937, 3179, +3502, 3023, 3077, +3415, 3118, 2893, +3266, 3220, 2388, +2932, 3328, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3822, 2627, 3522, +3822, 2627, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3821, 2629, 3522, +3821, 2630, 3522, +3821, 2631, 3521, +3821, 2632, 3521, +3821, 2634, 3521, +3820, 2636, 3520, +3820, 2639, 3519, +3819, 2643, 3518, +3818, 2649, 3517, +3817, 2656, 3515, +3815, 2666, 3513, +3813, 2678, 3510, +3810, 2694, 3505, +3807, 2715, 3500, +3801, 2742, 3492, +3794, 2775, 3481, +3784, 2815, 3466, +3771, 2865, 3445, +3752, 2923, 3416, +3726, 2991, 3374, +3689, 3069, 3311, +3634, 3155, 3209, +3547, 3250, 3025, +3398, 3352, 2520, +3065, 3460, 0, +0, 3574, 0, +0, 3691, 0, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3953, 2762, 3654, +3953, 2763, 3653, +3953, 2764, 3653, +3953, 2766, 3653, +3952, 2768, 3652, +3952, 2771, 3651, +3951, 2775, 3650, +3950, 2781, 3649, +3949, 2788, 3647, +3948, 2798, 3645, +3945, 2810, 3642, +3943, 2826, 3637, +3939, 2847, 3632, +3933, 2873, 3624, +3926, 2907, 3613, +3916, 2947, 3598, +3903, 2997, 3577, +3884, 3055, 3548, +3858, 3123, 3506, +3821, 3201, 3443, +3766, 3287, 3341, +3679, 3382, 3157, +3530, 3484, 2651, +3197, 3592, 0, +0, 3706, 0, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2894, 3786, +4085, 2895, 3785, +4085, 2896, 3785, +4085, 2898, 3785, +4085, 2900, 3784, +4084, 2903, 3783, +4083, 2907, 3782, +4083, 2913, 3781, +4081, 2920, 3779, +4080, 2930, 3777, +4078, 2942, 3774, +4075, 2958, 3770, +4071, 2979, 3764, +4065, 3005, 3756, +4058, 3039, 3745, +4049, 3079, 3730, +4035, 3129, 3709, +4017, 3187, 3680, +3991, 3255, 3638, +3953, 3333, 3575, +3898, 3419, 3473, +3811, 3514, 3289, +3662, 3616, 2783, +3329, 3725, 0, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3032, 3916, +4095, 3035, 3916, +4095, 3039, 3915, +4095, 3045, 3913, +4095, 3052, 3911, +4095, 3062, 3909, +4095, 3074, 3906, +4095, 3090, 3902, +4095, 3111, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3211, 3862, +4095, 3261, 3842, +4095, 3319, 3812, +4095, 3387, 3770, +4085, 3465, 3707, +4030, 3551, 3606, +3944, 3646, 3421, +3794, 3748, 2915, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3167, 4048, +4095, 3171, 4047, +4095, 3177, 4045, +4095, 3184, 4044, +4095, 3194, 4041, +4095, 3206, 4038, +4095, 3222, 4034, +4095, 3243, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3343, 3994, +4095, 3393, 3974, +4095, 3451, 3944, +4095, 3519, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 33, 135, +0, 83, 61, +0, 142, 0, +0, 211, 0, +0, 290, 0, +0, 377, 0, +0, 473, 0, +0, 576, 0, +0, 684, 0, +0, 798, 0, +0, 916, 0, +0, 1037, 0, +0, 1161, 0, +0, 1287, 0, +0, 1414, 0, +0, 1543, 0, +0, 1672, 0, +0, 1802, 0, +0, 1933, 0, +0, 2064, 0, +0, 2195, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +11, 50, 228, +0, 99, 168, +0, 156, 74, +0, 223, 0, +0, 300, 0, +0, 386, 0, +0, 480, 0, +0, 581, 0, +0, 689, 0, +0, 802, 0, +0, 919, 0, +0, 1039, 0, +0, 1163, 0, +0, 1288, 0, +0, 1415, 0, +0, 1543, 0, +0, 1673, 0, +0, 1803, 0, +0, 1933, 0, +0, 2064, 0, +0, 2195, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +271, 73, 329, +199, 119, 281, +79, 174, 209, +0, 239, 91, +0, 313, 0, +0, 397, 0, +0, 489, 0, +0, 588, 0, +0, 694, 0, +0, 806, 0, +0, 922, 0, +0, 1042, 0, +0, 1165, 0, +0, 1290, 0, +0, 1416, 0, +0, 1544, 0, +0, 1673, 0, +0, 1803, 0, +0, 1934, 0, +0, 2064, 0, +0, 2195, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +480, 102, 436, +435, 145, 399, +368, 197, 344, +259, 259, 259, +54, 330, 113, +0, 411, 0, +0, 500, 0, +0, 597, 0, +0, 702, 0, +0, 812, 0, +0, 927, 0, +0, 1045, 0, +0, 1167, 0, +0, 1292, 0, +0, 1418, 0, +0, 1546, 0, +0, 1674, 0, +0, 1804, 0, +0, 1934, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2458, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +662, 137, 548, +632, 177, 519, +590, 226, 478, +526, 284, 416, +424, 352, 318, +237, 429, 140, +0, 515, 0, +0, 610, 0, +0, 711, 0, +0, 819, 0, +0, 933, 0, +0, 1050, 0, +0, 1171, 0, +0, 1294, 0, +0, 1420, 0, +0, 1547, 0, +0, 1675, 0, +0, 1805, 0, +0, 1935, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +828, 181, 665, +808, 217, 643, +779, 262, 612, +738, 316, 566, +677, 380, 498, +579, 453, 386, +403, 535, 175, +0, 626, 0, +0, 724, 0, +0, 830, 0, +0, 941, 0, +0, 1056, 0, +0, 1176, 0, +0, 1298, 0, +0, 1423, 0, +0, 1549, 0, +0, 1677, 0, +0, 1806, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +984, 233, 785, +970, 266, 768, +950, 307, 745, +922, 356, 712, +882, 414, 663, +822, 482, 588, +728, 560, 464, +559, 646, 217, +144, 741, 0, +0, 843, 0, +0, 951, 0, +0, 1064, 0, +0, 1182, 0, +0, 1303, 0, +0, 1426, 0, +0, 1552, 0, +0, 1679, 0, +0, 1807, 0, +0, 1937, 0, +0, 2067, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1133, 295, 908, +1123, 324, 895, +1109, 360, 878, +1089, 404, 853, +1062, 457, 818, +1023, 519, 766, +964, 591, 686, +872, 672, 551, +709, 762, 268, +318, 860, 0, +0, 964, 0, +0, 1075, 0, +0, 1190, 0, +0, 1309, 0, +0, 1431, 0, +0, 1555, 0, +0, 1682, 0, +0, 1809, 0, +0, 1938, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1277, 366, 1033, +1270, 391, 1024, +1260, 422, 1010, +1246, 461, 992, +1227, 508, 967, +1200, 564, 930, +1161, 629, 876, +1103, 705, 791, +1013, 789, 646, +853, 882, 329, +479, 982, 0, +0, 1088, 0, +0, 1201, 0, +0, 1317, 0, +0, 1437, 0, +0, 1560, 0, +0, 1685, 0, +0, 1812, 0, +0, 1940, 0, +0, 2069, 0, +0, 2199, 0, +0, 2330, 0, +0, 2460, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1418, 447, 1160, +1413, 468, 1153, +1406, 494, 1143, +1396, 528, 1129, +1382, 568, 1111, +1363, 618, 1084, +1336, 677, 1046, +1298, 745, 990, +1241, 822, 902, +1151, 909, 748, +994, 1004, 399, +631, 1106, 0, +0, 1214, 0, +0, 1328, 0, +0, 1446, 0, +0, 1567, 0, +0, 1690, 0, +0, 1816, 0, +0, 1943, 0, +0, 2072, 0, +0, 2201, 0, +0, 2331, 0, +0, 2461, 0, +0, 2592, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1557, 537, 1288, +1553, 554, 1283, +1548, 576, 1275, +1540, 604, 1265, +1531, 639, 1251, +1517, 681, 1232, +1498, 733, 1205, +1471, 793, 1166, +1433, 864, 1108, +1377, 944, 1017, +1288, 1032, 857, +1133, 1129, 478, +778, 1232, 0, +0, 1342, 0, +0, 1456, 0, +0, 1575, 0, +0, 1697, 0, +0, 1821, 0, +0, 1947, 0, +0, 2074, 0, +0, 2203, 0, +0, 2332, 0, +0, 2463, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1694, 634, 1417, +1691, 648, 1413, +1687, 666, 1408, +1682, 689, 1400, +1675, 718, 1390, +1665, 754, 1376, +1651, 798, 1356, +1632, 851, 1329, +1606, 914, 1289, +1568, 986, 1230, +1512, 1067, 1136, +1424, 1157, 970, +1270, 1255, 567, +921, 1360, 0, +0, 1471, 0, +0, 1586, 0, +0, 1705, 0, +0, 1827, 0, +0, 1952, 0, +0, 2078, 0, +0, 2206, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1830, 738, 1547, +1828, 750, 1544, +1825, 764, 1540, +1821, 783, 1534, +1815, 806, 1527, +1808, 836, 1516, +1798, 873, 1502, +1785, 919, 1482, +1766, 973, 1454, +1740, 1037, 1414, +1702, 1110, 1354, +1646, 1193, 1258, +1558, 1284, 1088, +1406, 1383, 663, +1061, 1489, 0, +0, 1600, 0, +0, 1716, 0, +0, 1836, 0, +0, 1958, 0, +0, 2083, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1965, 849, 1678, +1963, 857, 1675, +1961, 869, 1672, +1958, 884, 1668, +1954, 903, 1662, +1949, 927, 1655, +1941, 958, 1644, +1932, 996, 1630, +1918, 1042, 1610, +1899, 1097, 1582, +1873, 1162, 1541, +1835, 1237, 1480, +1780, 1320, 1383, +1692, 1412, 1209, +1541, 1512, 766, +1199, 1618, 0, +0, 1730, 0, +0, 1847, 0, +0, 1966, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +2099, 964, 1809, +2098, 970, 1807, +2096, 979, 1804, +2094, 991, 1801, +2091, 1006, 1797, +2087, 1026, 1791, +2082, 1051, 1784, +2074, 1082, 1773, +2065, 1120, 1759, +2051, 1167, 1738, +2032, 1224, 1710, +2006, 1289, 1669, +1969, 1364, 1607, +1913, 1449, 1509, +1826, 1542, 1333, +1675, 1642, 876, +1335, 1749, 0, +0, 1861, 0, +0, 1978, 0, +0, 2098, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2232, 1083, 1940, +2231, 1088, 1938, +2230, 1095, 1937, +2229, 1104, 1934, +2226, 1116, 1931, +2224, 1131, 1927, +2220, 1151, 1921, +2214, 1176, 1913, +2207, 1208, 1903, +2197, 1247, 1888, +2184, 1294, 1868, +2165, 1351, 1839, +2139, 1417, 1798, +2101, 1493, 1736, +2046, 1578, 1637, +1959, 1671, 1459, +1809, 1772, 990, +1470, 1879, 0, +0, 1992, 0, +0, 2109, 0, +0, 2229, 0, +0, 2352, 0, +0, 2478, 0, +0, 2604, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2366, 1204, 2071, +2365, 1208, 2070, +2364, 1214, 2069, +2363, 1221, 2067, +2361, 1230, 2065, +2359, 1242, 2062, +2356, 1258, 2057, +2352, 1278, 2052, +2347, 1303, 2044, +2340, 1335, 2033, +2330, 1375, 2018, +2316, 1423, 1998, +2298, 1480, 1969, +2272, 1547, 1928, +2234, 1623, 1865, +2179, 1708, 1766, +2092, 1802, 1586, +1942, 1903, 1108, +1605, 2010, 0, +0, 2123, 0, +0, 2240, 0, +0, 2361, 0, +0, 2484, 0, +0, 2609, 0, +0, 2736, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2498, 1329, 2203, +2498, 1332, 2202, +2497, 1336, 2201, +2496, 1341, 2200, +2495, 1348, 2198, +2494, 1358, 2196, +2491, 1370, 2192, +2488, 1385, 2188, +2485, 1406, 2182, +2479, 1431, 2175, +2472, 1464, 2164, +2462, 1504, 2149, +2449, 1552, 2129, +2430, 1609, 2100, +2404, 1677, 2058, +2367, 1753, 1995, +2311, 1839, 1896, +2225, 1933, 1714, +2075, 2034, 1230, +1739, 2142, 0, +0, 2255, 0, +0, 2372, 0, +0, 2492, 0, +0, 2616, 0, +0, 2741, 0, +0, 2868, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2631, 1455, 2334, +2631, 1457, 2334, +2630, 1460, 2333, +2630, 1464, 2332, +2629, 1470, 2331, +2628, 1477, 2329, +2626, 1486, 2327, +2624, 1499, 2324, +2621, 1514, 2319, +2617, 1535, 2313, +2612, 1561, 2306, +2604, 1593, 2295, +2595, 1633, 2280, +2581, 1682, 2260, +2563, 1740, 2231, +2537, 1807, 2189, +2499, 1884, 2126, +2444, 1970, 2026, +2357, 2064, 1844, +2207, 2165, 1354, +1872, 2273, 0, +0, 2386, 0, +0, 2504, 0, +0, 2624, 0, +0, 2748, 0, +0, 2873, 0, +0, 3000, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2764, 1583, 2466, +2763, 1584, 2466, +2763, 1587, 2465, +2763, 1590, 2464, +2762, 1594, 2464, +2761, 1599, 2462, +2760, 1607, 2460, +2758, 1616, 2458, +2756, 1628, 2455, +2753, 1644, 2451, +2749, 1665, 2445, +2744, 1691, 2437, +2737, 1723, 2426, +2727, 1764, 2411, +2714, 1812, 2391, +2695, 1870, 2362, +2669, 1938, 2320, +2631, 2015, 2257, +2576, 2101, 2156, +2490, 2195, 1974, +2340, 2297, 1480, +2005, 2405, 0, +0, 2518, 0, +0, 2635, 0, +0, 2756, 0, +0, 2880, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1711, 2598, +2896, 1713, 2598, +2896, 1714, 2597, +2895, 1717, 2597, +2895, 1720, 2596, +2894, 1724, 2595, +2893, 1730, 2594, +2892, 1737, 2592, +2890, 1746, 2590, +2888, 1759, 2586, +2885, 1775, 2582, +2881, 1795, 2576, +2876, 1821, 2568, +2869, 1854, 2558, +2859, 1894, 2543, +2846, 1943, 2522, +2827, 2001, 2493, +2801, 2069, 2451, +2764, 2146, 2388, +2708, 2232, 2288, +2622, 2327, 2104, +2472, 2429, 1608, +2138, 2537, 0, +0, 2650, 0, +0, 2767, 0, +0, 2888, 0, +0, 3012, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3029, 1841, 2730, +3028, 1842, 2730, +3028, 1843, 2729, +3028, 1845, 2729, +3028, 1847, 2728, +3027, 1851, 2728, +3026, 1855, 2727, +3025, 1860, 2725, +3024, 1867, 2724, +3023, 1877, 2721, +3020, 1889, 2718, +3018, 1905, 2714, +3014, 1926, 2708, +3008, 1952, 2700, +3001, 1985, 2689, +2991, 2025, 2675, +2978, 2074, 2654, +2959, 2133, 2625, +2933, 2200, 2583, +2896, 2278, 2520, +2841, 2364, 2419, +2754, 2459, 2235, +2605, 2560, 1736, +2271, 2668, 0, +0, 2782, 0, +0, 2899, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3161, 1971, 2862, +3161, 1972, 2862, +3161, 1973, 2862, +3160, 1974, 2861, +3160, 1976, 2861, +3160, 1978, 2860, +3159, 1981, 2860, +3159, 1986, 2859, +3158, 1991, 2857, +3156, 1998, 2856, +3155, 2008, 2853, +3153, 2020, 2850, +3150, 2036, 2846, +3146, 2057, 2840, +3141, 2083, 2832, +3133, 2116, 2821, +3124, 2157, 2806, +3110, 2206, 2786, +3092, 2264, 2757, +3066, 2332, 2715, +3028, 2409, 2651, +2973, 2496, 2550, +2886, 2590, 2366, +2737, 2692, 1866, +2403, 2800, 0, +0, 2914, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3293, 2102, 2994, +3293, 2102, 2994, +3293, 2103, 2994, +3293, 2104, 2993, +3292, 2105, 2993, +3292, 2107, 2993, +3292, 2110, 2992, +3291, 2113, 2991, +3291, 2117, 2990, +3290, 2122, 2989, +3289, 2130, 2987, +3287, 2139, 2985, +3285, 2152, 2982, +3282, 2168, 2978, +3278, 2188, 2972, +3273, 2215, 2964, +3266, 2248, 2953, +3256, 2288, 2938, +3242, 2337, 2918, +3224, 2396, 2888, +3198, 2464, 2846, +3160, 2541, 2783, +3105, 2628, 2682, +3019, 2722, 2498, +2869, 2824, 1996, +2536, 2932, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3660, 0, +3425, 2233, 3126, +3425, 2233, 3126, +3425, 2234, 3126, +3425, 2235, 3126, +3425, 2236, 3125, +3425, 2237, 3125, +3424, 2239, 3125, +3424, 2241, 3124, +3423, 2244, 3123, +3423, 2248, 3122, +3422, 2254, 3121, +3421, 2261, 3119, +3419, 2271, 3117, +3417, 2283, 3114, +3414, 2299, 3109, +3410, 2320, 3104, +3405, 2346, 3096, +3398, 2379, 3085, +3388, 2420, 3070, +3375, 2469, 3049, +3356, 2527, 3020, +3330, 2595, 2978, +3293, 2673, 2915, +3237, 2759, 2814, +3151, 2854, 2629, +3002, 2956, 2126, +2668, 3064, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2364, 3258, +3557, 2365, 3258, +3557, 2365, 3258, +3557, 2365, 3258, +3557, 2366, 3258, +3557, 2367, 3257, +3557, 2369, 3257, +3556, 2370, 3257, +3556, 2373, 3256, +3556, 2376, 3255, +3555, 2380, 3254, +3554, 2386, 3253, +3553, 2393, 3251, +3551, 2402, 3249, +3549, 2415, 3246, +3546, 2431, 3241, +3542, 2452, 3236, +3537, 2478, 3228, +3530, 2511, 3217, +3520, 2552, 3202, +3507, 2601, 3181, +3488, 2659, 3152, +3462, 2727, 3110, +3425, 2805, 3047, +3369, 2891, 2946, +3283, 2986, 2761, +3134, 3088, 2257, +2800, 3196, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3690, 2496, 3390, +3690, 2496, 3390, +3690, 2496, 3390, +3689, 2497, 3390, +3689, 2497, 3390, +3689, 2498, 3390, +3689, 2499, 3389, +3689, 2500, 3389, +3689, 2502, 3389, +3688, 2504, 3388, +3688, 2508, 3387, +3687, 2512, 3386, +3686, 2517, 3385, +3685, 2525, 3383, +3683, 2534, 3381, +3681, 2547, 3378, +3678, 2563, 3373, +3674, 2583, 3368, +3669, 2610, 3360, +3662, 2643, 3349, +3652, 2683, 3334, +3639, 2733, 3313, +3620, 2791, 3284, +3594, 2859, 3242, +3557, 2937, 3179, +3501, 3023, 3078, +3415, 3118, 2893, +3266, 3220, 2389, +2932, 3328, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3822, 2627, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3821, 2629, 3522, +3821, 2630, 3522, +3821, 2631, 3521, +3821, 2632, 3521, +3821, 2634, 3521, +3820, 2636, 3520, +3820, 2639, 3519, +3819, 2644, 3518, +3818, 2649, 3517, +3817, 2656, 3515, +3815, 2666, 3513, +3813, 2678, 3510, +3810, 2695, 3505, +3806, 2715, 3500, +3801, 2742, 3492, +3794, 2775, 3481, +3784, 2815, 3466, +3771, 2865, 3445, +3752, 2923, 3416, +3726, 2991, 3374, +3689, 3069, 3311, +3634, 3155, 3210, +3547, 3250, 3025, +3398, 3352, 2520, +3065, 3460, 0, +0, 3574, 0, +0, 3691, 0, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3953, 2762, 3654, +3953, 2763, 3653, +3953, 2764, 3653, +3953, 2766, 3653, +3952, 2768, 3652, +3952, 2771, 3651, +3951, 2775, 3650, +3950, 2781, 3649, +3949, 2788, 3647, +3948, 2798, 3645, +3945, 2810, 3642, +3943, 2826, 3637, +3939, 2847, 3632, +3933, 2874, 3624, +3926, 2907, 3613, +3916, 2947, 3598, +3903, 2997, 3577, +3884, 3055, 3548, +3858, 3123, 3506, +3821, 3201, 3443, +3766, 3287, 3342, +3679, 3382, 3157, +3530, 3484, 2652, +3197, 3593, 0, +0, 3706, 0, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2894, 3786, +4085, 2895, 3785, +4085, 2896, 3785, +4085, 2898, 3785, +4085, 2900, 3784, +4084, 2903, 3783, +4083, 2907, 3782, +4082, 2913, 3781, +4081, 2920, 3779, +4080, 2930, 3777, +4078, 2942, 3774, +4075, 2958, 3770, +4071, 2979, 3764, +4065, 3006, 3756, +4058, 3039, 3745, +4048, 3079, 3730, +4035, 3129, 3710, +4017, 3187, 3680, +3990, 3255, 3638, +3953, 3333, 3575, +3898, 3419, 3474, +3811, 3514, 3289, +3662, 3616, 2783, +3329, 3725, 0, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3032, 3916, +4095, 3035, 3916, +4095, 3039, 3915, +4095, 3045, 3913, +4095, 3052, 3911, +4095, 3062, 3909, +4095, 3074, 3906, +4095, 3090, 3902, +4095, 3111, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3211, 3862, +4095, 3261, 3842, +4095, 3319, 3812, +4095, 3387, 3770, +4085, 3465, 3707, +4030, 3552, 3606, +3944, 3646, 3421, +3794, 3748, 2915, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3167, 4048, +4095, 3171, 4047, +4095, 3177, 4045, +4095, 3184, 4044, +4095, 3194, 4041, +4095, 3206, 4038, +4095, 3222, 4034, +4095, 3243, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3343, 3994, +4095, 3393, 3974, +4095, 3451, 3944, +4095, 3519, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 108, 241, +0, 151, 183, +0, 203, 91, +0, 264, 0, +0, 334, 0, +0, 414, 0, +0, 503, 0, +0, 600, 0, +0, 704, 0, +0, 813, 0, +0, 928, 0, +0, 1046, 0, +0, 1168, 0, +0, 1292, 0, +0, 1418, 0, +0, 1546, 0, +0, 1674, 0, +0, 1804, 0, +0, 1934, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 123, 316, +0, 165, 267, +0, 215, 193, +0, 274, 69, +0, 343, 0, +0, 422, 0, +0, 509, 0, +0, 605, 0, +0, 708, 0, +0, 816, 0, +0, 930, 0, +0, 1048, 0, +0, 1170, 0, +0, 1293, 0, +0, 1419, 0, +0, 1546, 0, +0, 1675, 0, +0, 1804, 0, +0, 1934, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +225, 143, 400, +144, 182, 360, +6, 231, 300, +0, 288, 206, +0, 355, 37, +0, 432, 0, +0, 518, 0, +0, 612, 0, +0, 713, 0, +0, 821, 0, +0, 934, 0, +0, 1051, 0, +0, 1171, 0, +0, 1295, 0, +0, 1420, 0, +0, 1547, 0, +0, 1676, 0, +0, 1805, 0, +0, 1935, 0, +0, 2065, 0, +0, 2196, 0, +0, 2327, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +451, 167, 493, +403, 205, 461, +331, 251, 413, +211, 306, 341, +0, 371, 223, +0, 445, 0, +0, 529, 0, +0, 621, 0, +0, 720, 0, +0, 826, 0, +0, 938, 0, +0, 1054, 0, +0, 1174, 0, +0, 1297, 0, +0, 1422, 0, +0, 1548, 0, +0, 1676, 0, +0, 1805, 0, +0, 1935, 0, +0, 2066, 0, +0, 2196, 0, +0, 2328, 0, +0, 2459, 0, +0, 2590, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +643, 198, 593, +612, 234, 568, +567, 277, 531, +500, 329, 476, +391, 391, 391, +186, 462, 245, +0, 543, 0, +0, 632, 0, +0, 730, 0, +0, 834, 0, +0, 944, 0, +0, 1059, 0, +0, 1178, 0, +0, 1299, 0, +0, 1424, 0, +0, 1550, 0, +0, 1678, 0, +0, 1806, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +815, 237, 700, +794, 269, 680, +765, 310, 651, +722, 358, 610, +658, 417, 548, +556, 484, 450, +369, 561, 272, +0, 647, 0, +0, 742, 0, +0, 844, 0, +0, 952, 0, +0, 1065, 0, +0, 1182, 0, +0, 1303, 0, +0, 1426, 0, +0, 1552, 0, +0, 1679, 0, +0, 1808, 0, +0, 1937, 0, +0, 2067, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +974, 283, 813, +960, 313, 797, +940, 350, 775, +911, 395, 744, +870, 448, 699, +809, 512, 630, +711, 585, 518, +535, 667, 307, +81, 758, 0, +0, 856, 0, +0, 962, 0, +0, 1073, 0, +0, 1188, 0, +0, 1308, 0, +0, 1430, 0, +0, 1555, 0, +0, 1681, 0, +0, 1809, 0, +0, 1938, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1126, 339, 929, +1116, 365, 917, +1102, 398, 900, +1082, 439, 877, +1054, 488, 844, +1014, 546, 795, +954, 614, 720, +860, 692, 596, +691, 778, 349, +276, 873, 0, +0, 975, 0, +0, 1083, 0, +0, 1196, 0, +0, 1314, 0, +0, 1435, 0, +0, 1558, 0, +0, 1684, 0, +0, 1811, 0, +0, 1939, 0, +0, 2069, 0, +0, 2199, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1272, 404, 1049, +1265, 427, 1040, +1255, 456, 1027, +1241, 492, 1010, +1221, 536, 985, +1194, 589, 950, +1155, 651, 898, +1096, 723, 818, +1004, 804, 683, +841, 894, 400, +450, 992, 0, +0, 1096, 0, +0, 1207, 0, +0, 1322, 0, +0, 1441, 0, +0, 1563, 0, +0, 1688, 0, +0, 1814, 0, +0, 1942, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1415, 479, 1172, +1409, 499, 1165, +1402, 523, 1156, +1392, 554, 1143, +1378, 593, 1124, +1359, 640, 1099, +1332, 696, 1062, +1293, 762, 1008, +1235, 837, 923, +1145, 921, 778, +985, 1014, 461, +611, 1114, 0, +0, 1221, 0, +0, 1333, 0, +0, 1449, 0, +0, 1569, 0, +0, 1692, 0, +0, 1817, 0, +0, 1944, 0, +0, 2072, 0, +0, 2202, 0, +0, 2331, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1555, 563, 1298, +1551, 579, 1292, +1545, 600, 1285, +1538, 627, 1275, +1528, 660, 1262, +1514, 701, 1243, +1495, 750, 1216, +1468, 809, 1178, +1430, 877, 1122, +1373, 955, 1034, +1283, 1041, 880, +1127, 1136, 531, +763, 1238, 0, +0, 1347, 0, +0, 1460, 0, +0, 1578, 0, +0, 1699, 0, +0, 1822, 0, +0, 1948, 0, +0, 2075, 0, +0, 2204, 0, +0, 2333, 0, +0, 2463, 0, +0, 2593, 0, +0, 2724, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1692, 656, 1424, +1689, 669, 1420, +1685, 686, 1415, +1680, 708, 1408, +1673, 736, 1397, +1663, 771, 1384, +1649, 813, 1364, +1630, 865, 1337, +1604, 926, 1298, +1565, 996, 1240, +1509, 1076, 1149, +1420, 1164, 989, +1265, 1261, 610, +910, 1365, 0, +0, 1474, 0, +0, 1589, 0, +0, 1707, 0, +0, 1829, 0, +0, 1953, 0, +0, 2079, 0, +0, 2206, 0, +0, 2335, 0, +0, 2464, 0, +0, 2595, 0, +0, 2725, 0, +0, 2856, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1828, 756, 1553, +1826, 766, 1550, +1823, 780, 1545, +1819, 798, 1540, +1814, 821, 1532, +1807, 850, 1522, +1797, 886, 1508, +1783, 930, 1488, +1764, 983, 1461, +1738, 1046, 1421, +1700, 1118, 1362, +1644, 1199, 1268, +1556, 1289, 1103, +1402, 1387, 699, +1053, 1492, 0, +0, 1603, 0, +0, 1718, 0, +0, 1837, 0, +0, 1959, 0, +0, 2084, 0, +0, 2210, 0, +0, 2338, 0, +0, 2467, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1964, 862, 1682, +1962, 871, 1679, +1960, 882, 1676, +1957, 896, 1672, +1953, 915, 1667, +1948, 938, 1659, +1940, 968, 1649, +1930, 1006, 1634, +1917, 1051, 1614, +1898, 1105, 1586, +1872, 1169, 1546, +1834, 1243, 1486, +1778, 1325, 1391, +1690, 1416, 1220, +1538, 1515, 795, +1193, 1621, 0, +0, 1732, 0, +0, 1848, 0, +0, 1968, 0, +0, 2090, 0, +0, 2215, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +2098, 974, 1812, +2097, 981, 1810, +2095, 989, 1808, +2093, 1001, 1804, +2090, 1016, 1800, +2086, 1035, 1795, +2081, 1059, 1787, +2074, 1090, 1776, +2064, 1128, 1762, +2050, 1174, 1742, +2032, 1230, 1714, +2005, 1294, 1673, +1968, 1369, 1612, +1912, 1452, 1515, +1824, 1545, 1341, +1673, 1644, 898, +1331, 1751, 0, +0, 1862, 0, +0, 1979, 0, +0, 2099, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2232, 1091, 1942, +2231, 1096, 1941, +2230, 1103, 1939, +2228, 1111, 1937, +2226, 1123, 1933, +2223, 1138, 1929, +2219, 1158, 1924, +2214, 1183, 1916, +2206, 1214, 1905, +2197, 1253, 1891, +2183, 1300, 1870, +2165, 1356, 1842, +2138, 1421, 1801, +2101, 1497, 1739, +2045, 1581, 1641, +1958, 1674, 1465, +1807, 1774, 1008, +1467, 1881, 0, +0, 1993, 0, +0, 2110, 0, +0, 2230, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2365, 1211, 2073, +2364, 1215, 2072, +2364, 1220, 2071, +2362, 1227, 2069, +2361, 1236, 2066, +2359, 1248, 2063, +2356, 1263, 2059, +2352, 1283, 2053, +2346, 1308, 2046, +2339, 1340, 2035, +2329, 1379, 2020, +2316, 1427, 2000, +2297, 1483, 1971, +2271, 1550, 1930, +2234, 1625, 1868, +2178, 1710, 1769, +2091, 1804, 1591, +1941, 1904, 1122, +1603, 2011, 0, +0, 2124, 0, +0, 2241, 0, +0, 2361, 0, +0, 2484, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2498, 1334, 2204, +2498, 1337, 2203, +2497, 1341, 2202, +2496, 1346, 2201, +2495, 1353, 2199, +2493, 1362, 2197, +2491, 1374, 2194, +2488, 1390, 2189, +2484, 1410, 2184, +2479, 1435, 2176, +2472, 1467, 2165, +2462, 1507, 2150, +2449, 1555, 2130, +2430, 1612, 2101, +2404, 1679, 2060, +2366, 1755, 1997, +2311, 1840, 1898, +2224, 1934, 1718, +2074, 2035, 1241, +1737, 2142, 0, +0, 2255, 0, +0, 2372, 0, +0, 2493, 0, +0, 2616, 0, +0, 2741, 0, +0, 2868, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2631, 1459, 2335, +2631, 1461, 2335, +2630, 1464, 2334, +2629, 1468, 2333, +2628, 1473, 2332, +2627, 1480, 2330, +2626, 1490, 2328, +2624, 1502, 2324, +2621, 1518, 2320, +2617, 1538, 2314, +2611, 1564, 2307, +2604, 1596, 2296, +2594, 1636, 2281, +2581, 1684, 2261, +2562, 1742, 2232, +2536, 1809, 2190, +2499, 1885, 2128, +2443, 1971, 2028, +2357, 2065, 1846, +2207, 2166, 1362, +1871, 2274, 0, +0, 2387, 0, +0, 2504, 0, +0, 2625, 0, +0, 2748, 0, +0, 2873, 0, +0, 3000, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2764, 1585, 2467, +2763, 1587, 2466, +2763, 1589, 2466, +2762, 1593, 2465, +2762, 1597, 2464, +2761, 1602, 2463, +2760, 1609, 2461, +2758, 1618, 2459, +2756, 1631, 2456, +2753, 1647, 2451, +2749, 1667, 2446, +2744, 1693, 2438, +2737, 1725, 2427, +2727, 1765, 2412, +2713, 1814, 2392, +2695, 1872, 2363, +2669, 1939, 2321, +2631, 2016, 2258, +2576, 2102, 2158, +2489, 2196, 1976, +2340, 2297, 1486, +2004, 2405, 0, +0, 2518, 0, +0, 2636, 0, +0, 2756, 0, +0, 2880, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1713, 2599, +2896, 1715, 2598, +2896, 1717, 2598, +2895, 1719, 2597, +2895, 1722, 2597, +2894, 1726, 2596, +2893, 1731, 2594, +2892, 1739, 2593, +2890, 1748, 2590, +2888, 1760, 2587, +2885, 1776, 2583, +2881, 1797, 2577, +2876, 1823, 2569, +2869, 1855, 2558, +2859, 1896, 2544, +2846, 1944, 2523, +2827, 2002, 2494, +2801, 2070, 2452, +2764, 2147, 2389, +2708, 2233, 2289, +2622, 2327, 2106, +2472, 2429, 1612, +2137, 2537, 0, +0, 2650, 0, +0, 2767, 0, +0, 2888, 0, +0, 3012, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3028, 1843, 2730, +3028, 1844, 2730, +3028, 1845, 2730, +3028, 1847, 2729, +3027, 1849, 2729, +3027, 1852, 2728, +3026, 1856, 2727, +3025, 1862, 2726, +3024, 1869, 2724, +3023, 1878, 2722, +3020, 1891, 2719, +3017, 1907, 2714, +3014, 1927, 2708, +3008, 1953, 2701, +3001, 1986, 2690, +2991, 2026, 2675, +2978, 2075, 2654, +2959, 2133, 2625, +2933, 2201, 2583, +2896, 2278, 2520, +2840, 2364, 2420, +2754, 2459, 2236, +2605, 2561, 1740, +2270, 2669, 0, +0, 2782, 0, +0, 2899, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3161, 1972, 2862, +3161, 1973, 2862, +3160, 1974, 2862, +3160, 1975, 2862, +3160, 1977, 2861, +3160, 1980, 2861, +3159, 1983, 2860, +3158, 1987, 2859, +3158, 1992, 2858, +3156, 1999, 2856, +3155, 2009, 2853, +3153, 2021, 2850, +3150, 2037, 2846, +3146, 2058, 2840, +3140, 2084, 2832, +3133, 2117, 2821, +3124, 2157, 2807, +3110, 2206, 2786, +3092, 2265, 2757, +3065, 2333, 2715, +3028, 2410, 2652, +2973, 2496, 2551, +2886, 2591, 2367, +2737, 2692, 1868, +2403, 2801, 0, +0, 2914, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3293, 2103, 2994, +3293, 2103, 2994, +3293, 2104, 2994, +3293, 2105, 2994, +3292, 2106, 2993, +3292, 2108, 2993, +3292, 2110, 2992, +3291, 2114, 2992, +3291, 2118, 2991, +3290, 2123, 2989, +3289, 2130, 2988, +3287, 2140, 2985, +3285, 2152, 2982, +3282, 2168, 2978, +3278, 2189, 2972, +3273, 2215, 2964, +3265, 2248, 2953, +3256, 2289, 2938, +3242, 2338, 2918, +3224, 2396, 2889, +3198, 2464, 2847, +3160, 2541, 2784, +3105, 2628, 2682, +3019, 2722, 2498, +2869, 2824, 1998, +2535, 2932, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3660, 0, +3425, 2234, 3126, +3425, 2234, 3126, +3425, 2235, 3126, +3425, 2235, 3126, +3425, 2236, 3126, +3425, 2238, 3125, +3424, 2239, 3125, +3424, 2242, 3124, +3423, 2245, 3124, +3423, 2249, 3123, +3422, 2255, 3121, +3421, 2262, 3119, +3419, 2271, 3117, +3417, 2284, 3114, +3414, 2300, 3110, +3410, 2320, 3104, +3405, 2347, 3096, +3398, 2380, 3085, +3388, 2420, 3070, +3374, 2469, 3050, +3356, 2528, 3021, +3330, 2596, 2978, +3292, 2673, 2915, +3237, 2760, 2814, +3151, 2854, 2630, +3001, 2956, 2128, +2668, 3064, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2365, 3258, +3557, 2365, 3258, +3557, 2365, 3258, +3557, 2366, 3258, +3557, 2367, 3258, +3557, 2368, 3257, +3557, 2369, 3257, +3556, 2371, 3257, +3556, 2373, 3256, +3556, 2376, 3255, +3555, 2380, 3254, +3554, 2386, 3253, +3553, 2393, 3251, +3551, 2403, 3249, +3549, 2415, 3246, +3546, 2431, 3242, +3542, 2452, 3236, +3537, 2478, 3228, +3530, 2511, 3217, +3520, 2552, 3202, +3507, 2601, 3182, +3488, 2660, 3152, +3462, 2728, 3110, +3425, 2805, 3047, +3369, 2892, 2946, +3283, 2986, 2761, +3134, 3088, 2258, +2800, 3196, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3690, 2496, 3390, +3690, 2496, 3390, +3689, 2497, 3390, +3689, 2497, 3390, +3689, 2498, 3390, +3689, 2498, 3390, +3689, 2499, 3389, +3689, 2501, 3389, +3689, 2502, 3389, +3688, 2505, 3388, +3688, 2508, 3387, +3687, 2512, 3386, +3686, 2518, 3385, +3685, 2525, 3383, +3683, 2534, 3381, +3681, 2547, 3378, +3678, 2563, 3374, +3674, 2584, 3368, +3669, 2610, 3360, +3662, 2643, 3349, +3652, 2684, 3334, +3639, 2733, 3314, +3620, 2791, 3284, +3594, 2859, 3242, +3557, 2937, 3179, +3501, 3023, 3078, +3415, 3118, 2893, +3266, 3220, 2389, +2932, 3328, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2629, 3522, +3821, 2629, 3522, +3821, 2630, 3522, +3821, 2631, 3521, +3821, 2632, 3521, +3821, 2634, 3521, +3820, 2637, 3520, +3820, 2640, 3519, +3819, 2644, 3518, +3818, 2649, 3517, +3817, 2657, 3515, +3815, 2666, 3513, +3813, 2679, 3510, +3810, 2695, 3506, +3806, 2716, 3500, +3801, 2742, 3492, +3794, 2775, 3481, +3784, 2816, 3466, +3771, 2865, 3446, +3752, 2923, 3416, +3726, 2991, 3374, +3689, 3069, 3311, +3634, 3155, 3210, +3547, 3250, 3025, +3398, 3352, 2521, +3064, 3460, 0, +0, 3574, 0, +0, 3691, 0, +3954, 2759, 3654, +3954, 2759, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3954, 2761, 3654, +3953, 2762, 3654, +3953, 2763, 3653, +3953, 2764, 3653, +3953, 2766, 3653, +3952, 2768, 3652, +3952, 2772, 3651, +3951, 2776, 3650, +3950, 2781, 3649, +3949, 2788, 3647, +3948, 2798, 3645, +3945, 2811, 3642, +3943, 2827, 3638, +3939, 2847, 3632, +3933, 2874, 3624, +3926, 2907, 3613, +3916, 2947, 3598, +3903, 2997, 3578, +3884, 3055, 3548, +3858, 3123, 3506, +3821, 3201, 3443, +3766, 3287, 3342, +3679, 3382, 3157, +3530, 3484, 2652, +3197, 3593, 0, +0, 3706, 0, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2894, 3786, +4085, 2895, 3786, +4085, 2896, 3785, +4085, 2898, 3785, +4085, 2900, 3784, +4084, 2903, 3784, +4083, 2908, 3783, +4082, 2913, 3781, +4081, 2920, 3779, +4080, 2930, 3777, +4078, 2942, 3774, +4075, 2959, 3770, +4071, 2979, 3764, +4065, 3006, 3756, +4058, 3039, 3745, +4048, 3079, 3730, +4035, 3129, 3710, +4017, 3187, 3680, +3990, 3255, 3638, +3953, 3333, 3575, +3898, 3420, 3474, +3811, 3514, 3289, +3662, 3616, 2784, +3329, 3725, 0, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3032, 3916, +4095, 3035, 3916, +4095, 3040, 3915, +4095, 3045, 3913, +4095, 3052, 3912, +4095, 3062, 3909, +4095, 3074, 3906, +4095, 3091, 3902, +4095, 3111, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3211, 3862, +4095, 3261, 3842, +4095, 3319, 3812, +4095, 3387, 3770, +4085, 3465, 3707, +4030, 3552, 3606, +3944, 3646, 3421, +3794, 3748, 2916, +4095, 3155, 4051, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3167, 4048, +4095, 3172, 4047, +4095, 3177, 4045, +4095, 3184, 4044, +4095, 3194, 4041, +4095, 3206, 4038, +4095, 3223, 4034, +4095, 3243, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3343, 3994, +4095, 3393, 3974, +4095, 3451, 3945, +4095, 3519, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 193, 352, +0, 229, 307, +0, 273, 239, +0, 326, 129, +0, 388, 0, +0, 459, 0, +0, 540, 0, +0, 630, 0, +0, 728, 0, +0, 833, 0, +0, 943, 0, +0, 1058, 0, +0, 1177, 0, +0, 1299, 0, +0, 1423, 0, +0, 1550, 0, +0, 1677, 0, +0, 1806, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 205, 412, +0, 240, 373, +0, 283, 315, +0, 335, 223, +0, 396, 62, +0, 466, 0, +0, 546, 0, +0, 635, 0, +0, 732, 0, +0, 836, 0, +0, 945, 0, +0, 1060, 0, +0, 1178, 0, +0, 1300, 0, +0, 1424, 0, +0, 1550, 0, +0, 1678, 0, +0, 1807, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +154, 222, 481, +58, 255, 448, +0, 297, 399, +0, 347, 325, +0, 407, 201, +0, 476, 0, +0, 554, 0, +0, 641, 0, +0, 737, 0, +0, 840, 0, +0, 949, 0, +0, 1062, 0, +0, 1180, 0, +0, 1302, 0, +0, 1425, 0, +0, 1551, 0, +0, 1679, 0, +0, 1807, 0, +0, 1936, 0, +0, 2066, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +409, 242, 560, +357, 275, 532, +276, 315, 492, +138, 363, 433, +0, 420, 338, +0, 488, 170, +0, 564, 0, +0, 650, 0, +0, 744, 0, +0, 845, 0, +0, 953, 0, +0, 1066, 0, +0, 1183, 0, +0, 1304, 0, +0, 1427, 0, +0, 1552, 0, +0, 1679, 0, +0, 1808, 0, +0, 1937, 0, +0, 2067, 0, +0, 2197, 0, +0, 2328, 0, +0, 2459, 0, +0, 2591, 0, +0, 2722, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +616, 269, 648, +583, 299, 625, +535, 337, 593, +463, 383, 546, +343, 438, 474, +109, 503, 355, +0, 577, 124, +0, 661, 0, +0, 753, 0, +0, 852, 0, +0, 958, 0, +0, 1070, 0, +0, 1186, 0, +0, 1306, 0, +0, 1429, 0, +0, 1554, 0, +0, 1681, 0, +0, 1809, 0, +0, 1938, 0, +0, 2067, 0, +0, 2198, 0, +0, 2328, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +796, 302, 744, +775, 330, 726, +744, 366, 700, +700, 409, 663, +632, 461, 608, +523, 523, 523, +318, 594, 377, +0, 675, 54, +0, 764, 0, +0, 862, 0, +0, 966, 0, +0, 1076, 0, +0, 1191, 0, +0, 1310, 0, +0, 1432, 0, +0, 1556, 0, +0, 1682, 0, +0, 1810, 0, +0, 1938, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +962, 343, 847, +947, 369, 832, +926, 401, 812, +897, 442, 784, +854, 490, 742, +790, 549, 680, +688, 616, 582, +501, 693, 404, +0, 780, 0, +0, 874, 0, +0, 976, 0, +0, 1084, 0, +0, 1197, 0, +0, 1314, 0, +0, 1435, 0, +0, 1559, 0, +0, 1684, 0, +0, 1811, 0, +0, 1940, 0, +0, 2069, 0, +0, 2199, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1117, 392, 956, +1107, 415, 945, +1092, 445, 929, +1072, 482, 907, +1043, 527, 876, +1002, 581, 831, +941, 644, 762, +843, 717, 650, +667, 799, 439, +213, 890, 0, +0, 988, 0, +0, 1094, 0, +0, 1205, 0, +0, 1320, 0, +0, 1440, 0, +0, 1562, 0, +0, 1687, 0, +0, 1813, 0, +0, 1941, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1266, 450, 1070, +1258, 471, 1061, +1248, 497, 1049, +1234, 530, 1032, +1214, 571, 1009, +1186, 620, 976, +1146, 678, 927, +1086, 746, 852, +992, 824, 728, +824, 910, 481, +408, 1005, 0, +0, 1107, 0, +0, 1215, 0, +0, 1328, 0, +0, 1446, 0, +0, 1567, 0, +0, 1690, 0, +0, 1816, 0, +0, 1943, 0, +0, 2072, 0, +0, 2201, 0, +0, 2331, 0, +0, 2461, 0, +0, 2592, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1410, 519, 1188, +1405, 536, 1182, +1397, 559, 1172, +1387, 588, 1160, +1373, 624, 1142, +1353, 668, 1117, +1326, 721, 1082, +1287, 783, 1030, +1228, 855, 950, +1136, 936, 815, +973, 1026, 532, +582, 1124, 0, +0, 1229, 0, +0, 1339, 0, +0, 1454, 0, +0, 1573, 0, +0, 1695, 0, +0, 1820, 0, +0, 1946, 0, +0, 2074, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1551, 596, 1310, +1547, 611, 1305, +1542, 631, 1297, +1534, 655, 1288, +1524, 687, 1275, +1510, 725, 1256, +1491, 772, 1231, +1464, 828, 1194, +1425, 894, 1140, +1367, 969, 1055, +1277, 1053, 910, +1117, 1146, 593, +743, 1246, 0, +0, 1353, 0, +0, 1465, 0, +0, 1581, 0, +0, 1702, 0, +0, 1824, 0, +0, 1950, 0, +0, 2076, 0, +0, 2205, 0, +0, 2334, 0, +0, 2463, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1690, 683, 1434, +1687, 695, 1430, +1683, 711, 1424, +1677, 732, 1417, +1670, 759, 1407, +1660, 792, 1394, +1646, 833, 1375, +1627, 882, 1348, +1600, 941, 1310, +1562, 1009, 1254, +1505, 1087, 1166, +1415, 1173, 1013, +1259, 1268, 663, +895, 1370, 0, +0, 1479, 0, +0, 1592, 0, +0, 1710, 0, +0, 1831, 0, +0, 1954, 0, +0, 2080, 0, +0, 2207, 0, +0, 2336, 0, +0, 2465, 0, +0, 2595, 0, +0, 2726, 0, +0, 2856, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1826, 777, 1560, +1824, 788, 1557, +1821, 801, 1552, +1817, 818, 1547, +1812, 840, 1540, +1805, 868, 1530, +1795, 903, 1516, +1781, 945, 1496, +1762, 997, 1469, +1736, 1058, 1430, +1697, 1128, 1372, +1641, 1208, 1281, +1552, 1296, 1121, +1397, 1393, 742, +1042, 1497, 0, +0, 1606, 0, +0, 1721, 0, +0, 1839, 0, +0, 1961, 0, +0, 2085, 0, +0, 2211, 0, +0, 2338, 0, +0, 2467, 0, +0, 2597, 0, +0, 2727, 0, +0, 2857, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1962, 880, 1687, +1961, 888, 1685, +1958, 898, 1682, +1955, 912, 1678, +1951, 930, 1672, +1946, 953, 1664, +1939, 982, 1654, +1929, 1018, 1640, +1915, 1062, 1620, +1897, 1116, 1593, +1870, 1178, 1553, +1832, 1250, 1494, +1776, 1331, 1400, +1688, 1422, 1235, +1534, 1520, 831, +1185, 1624, 0, +0, 1735, 0, +0, 1850, 0, +0, 1969, 0, +0, 2091, 0, +0, 2216, 0, +0, 2342, 0, +0, 2470, 0, +0, 2599, 0, +0, 2728, 0, +0, 2859, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2097, 988, 1815, +2096, 994, 1814, +2094, 1003, 1811, +2092, 1014, 1808, +2089, 1028, 1804, +2085, 1047, 1799, +2080, 1071, 1791, +2072, 1100, 1781, +2063, 1138, 1766, +2049, 1183, 1746, +2030, 1237, 1719, +2004, 1301, 1678, +1966, 1375, 1618, +1910, 1457, 1523, +1822, 1548, 1352, +1670, 1647, 927, +1325, 1753, 0, +0, 1864, 0, +0, 1980, 0, +0, 2100, 0, +0, 2222, 0, +0, 2347, 0, +0, 2474, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2231, 1101, 1945, +2230, 1106, 1944, +2229, 1113, 1942, +2227, 1122, 1940, +2225, 1133, 1936, +2222, 1148, 1932, +2218, 1167, 1927, +2213, 1191, 1919, +2206, 1222, 1908, +2196, 1260, 1894, +2182, 1306, 1874, +2164, 1362, 1846, +2137, 1427, 1805, +2100, 1501, 1744, +2044, 1585, 1647, +1956, 1677, 1473, +1805, 1776, 1031, +1463, 1883, 0, +0, 1994, 0, +0, 2111, 0, +0, 2231, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2364, 1219, 2075, +2364, 1223, 2074, +2363, 1228, 2073, +2362, 1235, 2071, +2360, 1244, 2069, +2358, 1255, 2066, +2355, 1270, 2061, +2351, 1290, 2056, +2346, 1315, 2048, +2339, 1346, 2037, +2329, 1385, 2023, +2315, 1432, 2003, +2297, 1488, 1974, +2270, 1553, 1933, +2233, 1629, 1871, +2177, 1713, 1773, +2090, 1806, 1597, +1939, 1906, 1140, +1599, 2013, 0, +0, 2125, 0, +0, 2242, 0, +0, 2362, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2498, 1340, 2206, +2497, 1343, 2205, +2497, 1347, 2204, +2496, 1352, 2203, +2494, 1359, 2201, +2493, 1368, 2199, +2491, 1380, 2195, +2488, 1395, 2191, +2484, 1415, 2185, +2478, 1440, 2178, +2471, 1472, 2167, +2461, 1511, 2152, +2448, 1559, 2132, +2429, 1615, 2103, +2403, 1682, 2062, +2366, 1757, 2000, +2310, 1842, 1901, +2223, 1936, 1723, +2073, 2036, 1254, +1735, 2144, 0, +0, 2256, 0, +0, 2373, 0, +0, 2493, 0, +0, 2616, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2631, 1463, 2337, +2630, 1466, 2336, +2630, 1469, 2335, +2629, 1473, 2334, +2628, 1478, 2333, +2627, 1485, 2331, +2625, 1494, 2329, +2623, 1506, 2326, +2620, 1522, 2322, +2616, 1542, 2316, +2611, 1567, 2308, +2604, 1599, 2297, +2594, 1639, 2283, +2581, 1687, 2262, +2562, 1744, 2233, +2536, 1811, 2192, +2498, 1887, 2130, +2443, 1972, 2030, +2356, 2066, 1850, +2206, 2167, 1373, +1869, 2275, 0, +0, 2387, 0, +0, 2504, 0, +0, 2625, 0, +0, 2748, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2763, 1589, 2468, +2763, 1591, 2467, +2763, 1593, 2467, +2762, 1596, 2466, +2761, 1600, 2465, +2761, 1605, 2464, +2759, 1613, 2462, +2758, 1622, 2460, +2756, 1634, 2457, +2753, 1650, 2452, +2749, 1670, 2447, +2743, 1696, 2439, +2736, 1728, 2428, +2727, 1768, 2413, +2713, 1816, 2393, +2694, 1874, 2364, +2668, 1941, 2322, +2631, 2017, 2260, +2575, 2103, 2160, +2489, 2197, 1978, +2339, 2298, 1494, +2003, 2406, 0, +0, 2519, 0, +0, 2636, 0, +0, 2757, 0, +0, 2880, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1716, 2599, +2896, 1717, 2599, +2895, 1719, 2599, +2895, 1722, 2598, +2894, 1725, 2597, +2894, 1729, 2596, +2893, 1734, 2595, +2892, 1741, 2593, +2890, 1751, 2591, +2888, 1763, 2588, +2885, 1779, 2583, +2881, 1799, 2578, +2876, 1825, 2570, +2869, 1857, 2559, +2859, 1897, 2544, +2845, 1946, 2524, +2827, 2004, 2495, +2801, 2071, 2453, +2763, 2148, 2390, +2708, 2234, 2290, +2621, 2328, 2108, +2472, 2430, 1618, +2136, 2537, 0, +0, 2650, 0, +0, 2768, 0, +0, 2888, 0, +0, 3012, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3028, 1845, 2731, +3028, 1846, 2731, +3028, 1847, 2730, +3028, 1849, 2730, +3027, 1851, 2729, +3027, 1854, 2729, +3026, 1858, 2728, +3025, 1864, 2726, +3024, 1871, 2725, +3022, 1880, 2722, +3020, 1892, 2719, +3017, 1908, 2715, +3013, 1929, 2709, +3008, 1955, 2701, +3001, 1987, 2690, +2991, 2028, 2676, +2978, 2076, 2655, +2959, 2134, 2626, +2933, 2202, 2584, +2896, 2279, 2521, +2840, 2365, 2421, +2754, 2459, 2238, +2604, 2561, 1744, +2269, 2669, 0, +0, 2782, 0, +0, 2900, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3161, 1974, 2863, +3161, 1975, 2862, +3160, 1976, 2862, +3160, 1977, 2862, +3160, 1979, 2862, +3160, 1981, 2861, +3159, 1984, 2860, +3158, 1988, 2859, +3157, 1994, 2858, +3156, 2001, 2856, +3155, 2010, 2854, +3152, 2023, 2851, +3150, 2039, 2846, +3146, 2059, 2841, +3140, 2085, 2833, +3133, 2118, 2822, +3123, 2158, 2807, +3110, 2207, 2787, +3091, 2266, 2758, +3065, 2333, 2716, +3028, 2410, 2653, +2973, 2497, 2552, +2886, 2591, 2368, +2737, 2693, 1872, +2402, 2801, 0, +0, 2914, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3293, 2104, 2994, +3293, 2104, 2994, +3293, 2105, 2994, +3293, 2106, 2994, +3292, 2107, 2994, +3292, 2109, 2993, +3292, 2112, 2993, +3291, 2115, 2992, +3291, 2119, 2991, +3290, 2124, 2990, +3288, 2132, 2988, +3287, 2141, 2986, +3285, 2153, 2982, +3282, 2169, 2978, +3278, 2190, 2972, +3273, 2216, 2964, +3265, 2249, 2954, +3256, 2290, 2939, +3242, 2339, 2918, +3224, 2397, 2889, +3198, 2465, 2847, +3160, 2542, 2784, +3105, 2628, 2683, +3018, 2723, 2499, +2869, 2825, 2000, +2535, 2933, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3661, 0, +3425, 2234, 3126, +3425, 2235, 3126, +3425, 2235, 3126, +3425, 2236, 3126, +3425, 2237, 3126, +3425, 2238, 3125, +3424, 2240, 3125, +3424, 2243, 3124, +3423, 2246, 3124, +3423, 2250, 3123, +3422, 2255, 3121, +3421, 2263, 3120, +3419, 2272, 3117, +3417, 2284, 3114, +3414, 2301, 3110, +3410, 2321, 3104, +3405, 2347, 3096, +3398, 2380, 3085, +3388, 2421, 3071, +3374, 2470, 3050, +3356, 2528, 3021, +3330, 2596, 2979, +3292, 2674, 2916, +3237, 2760, 2815, +3151, 2855, 2631, +3001, 2956, 2130, +2667, 3065, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2365, 3258, +3557, 2366, 3258, +3557, 2366, 3258, +3557, 2367, 3258, +3557, 2367, 3258, +3557, 2368, 3258, +3557, 2370, 3257, +3556, 2371, 3257, +3556, 2374, 3256, +3556, 2377, 3256, +3555, 2381, 3255, +3554, 2387, 3253, +3553, 2394, 3252, +3551, 2403, 3249, +3549, 2416, 3246, +3546, 2432, 3242, +3542, 2453, 3236, +3537, 2479, 3228, +3530, 2512, 3217, +3520, 2552, 3202, +3507, 2602, 3182, +3488, 2660, 3153, +3462, 2728, 3111, +3425, 2805, 3047, +3369, 2892, 2946, +3283, 2986, 2762, +3134, 3088, 2260, +2800, 3197, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3690, 2497, 3390, +3690, 2497, 3390, +3689, 2497, 3390, +3689, 2498, 3390, +3689, 2498, 3390, +3689, 2499, 3390, +3689, 2500, 3390, +3689, 2501, 3389, +3689, 2503, 3389, +3688, 2505, 3388, +3688, 2508, 3388, +3687, 2513, 3387, +3686, 2518, 3385, +3685, 2525, 3384, +3683, 2535, 3381, +3681, 2547, 3378, +3678, 2563, 3374, +3674, 2584, 3368, +3669, 2610, 3360, +3662, 2643, 3349, +3652, 2684, 3334, +3639, 2733, 3314, +3620, 2792, 3285, +3594, 2860, 3242, +3557, 2937, 3179, +3501, 3024, 3078, +3415, 3118, 2894, +3266, 3220, 2391, +2932, 3329, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2628, 3522, +3822, 2629, 3522, +3822, 2629, 3522, +3821, 2630, 3522, +3821, 2630, 3522, +3821, 2631, 3522, +3821, 2633, 3521, +3821, 2635, 3521, +3820, 2637, 3520, +3820, 2640, 3520, +3819, 2644, 3519, +3818, 2650, 3517, +3817, 2657, 3515, +3815, 2667, 3513, +3813, 2679, 3510, +3810, 2695, 3506, +3806, 2716, 3500, +3801, 2742, 3492, +3794, 2775, 3481, +3784, 2816, 3466, +3771, 2865, 3446, +3752, 2924, 3416, +3726, 2992, 3374, +3689, 3069, 3311, +3634, 3156, 3210, +3547, 3250, 3025, +3398, 3352, 2521, +3064, 3461, 0, +0, 3574, 0, +0, 3692, 0, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3954, 2761, 3654, +3953, 2762, 3654, +3953, 2763, 3654, +3953, 2764, 3653, +3953, 2766, 3653, +3952, 2769, 3652, +3952, 2772, 3652, +3951, 2776, 3651, +3950, 2781, 3649, +3949, 2789, 3647, +3948, 2798, 3645, +3945, 2811, 3642, +3942, 2827, 3638, +3939, 2848, 3632, +3933, 2874, 3624, +3926, 2907, 3613, +3916, 2948, 3598, +3903, 2997, 3578, +3884, 3055, 3548, +3858, 3123, 3506, +3821, 3201, 3443, +3766, 3288, 3342, +3679, 3382, 3157, +3530, 3484, 2653, +3197, 3593, 0, +0, 3706, 0, +4086, 2891, 3786, +4086, 2891, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2893, 3786, +4086, 2894, 3786, +4085, 2895, 3786, +4085, 2896, 3785, +4085, 2898, 3785, +4085, 2900, 3784, +4084, 2904, 3784, +4083, 2908, 3783, +4082, 2913, 3781, +4081, 2921, 3780, +4080, 2930, 3777, +4078, 2943, 3774, +4075, 2959, 3770, +4071, 2980, 3764, +4065, 3006, 3756, +4058, 3039, 3745, +4048, 3080, 3730, +4035, 3129, 3710, +4017, 3187, 3680, +3990, 3255, 3638, +3953, 3333, 3575, +3898, 3420, 3474, +3811, 3514, 3289, +3662, 3616, 2784, +3329, 3725, 0, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3032, 3916, +4095, 3036, 3916, +4095, 3040, 3915, +4095, 3045, 3913, +4095, 3052, 3912, +4095, 3062, 3909, +4095, 3075, 3906, +4095, 3091, 3902, +4095, 3111, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3212, 3862, +4095, 3261, 3842, +4095, 3319, 3813, +4095, 3387, 3770, +4085, 3465, 3707, +4030, 3552, 3606, +3944, 3646, 3421, +3794, 3748, 2916, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3155, 4050, +4095, 3155, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3167, 4048, +4095, 3172, 4047, +4095, 3177, 4045, +4095, 3184, 4044, +4095, 3194, 4041, +4095, 3206, 4038, +4095, 3223, 4034, +4095, 3243, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3344, 3994, +4095, 3393, 3974, +4095, 3451, 3945, +4095, 3520, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 286, 468, +0, 316, 433, +0, 352, 383, +0, 397, 305, +0, 450, 175, +0, 514, 0, +0, 586, 0, +0, 668, 0, +0, 759, 0, +0, 857, 0, +0, 962, 0, +0, 1073, 0, +0, 1189, 0, +0, 1308, 0, +0, 1430, 0, +0, 1555, 0, +0, 1681, 0, +0, 1809, 0, +0, 1938, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 296, 515, +0, 325, 484, +0, 361, 439, +0, 405, 371, +0, 458, 261, +0, 520, 54, +0, 592, 0, +0, 673, 0, +0, 762, 0, +0, 860, 0, +0, 965, 0, +0, 1075, 0, +0, 1190, 0, +0, 1309, 0, +0, 1431, 0, +0, 1556, 0, +0, 1682, 0, +0, 1810, 0, +0, 1938, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +38, 310, 571, +0, 338, 544, +0, 372, 505, +0, 415, 447, +0, 467, 355, +0, 528, 195, +0, 599, 0, +0, 678, 0, +0, 767, 0, +0, 864, 0, +0, 968, 0, +0, 1077, 0, +0, 1192, 0, +0, 1311, 0, +0, 1432, 0, +0, 1556, 0, +0, 1682, 0, +0, 1810, 0, +0, 1939, 0, +0, 2068, 0, +0, 2198, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +347, 327, 637, +286, 354, 613, +190, 387, 580, +17, 429, 531, +0, 479, 457, +0, 539, 333, +0, 608, 87, +0, 686, 0, +0, 774, 0, +0, 869, 0, +0, 972, 0, +0, 1081, 0, +0, 1194, 0, +0, 1312, 0, +0, 1434, 0, +0, 1558, 0, +0, 1683, 0, +0, 1811, 0, +0, 1939, 0, +0, 2069, 0, +0, 2199, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +577, 349, 712, +541, 375, 692, +489, 407, 664, +408, 447, 624, +270, 495, 565, +0, 553, 470, +0, 620, 302, +0, 696, 0, +0, 782, 0, +0, 876, 0, +0, 977, 0, +0, 1085, 0, +0, 1198, 0, +0, 1315, 0, +0, 1436, 0, +0, 1559, 0, +0, 1684, 0, +0, 1812, 0, +0, 1940, 0, +0, 2069, 0, +0, 2199, 0, +0, 2329, 0, +0, 2460, 0, +0, 2591, 0, +0, 2723, 0, +0, 2854, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +771, 377, 796, +748, 401, 780, +715, 431, 757, +668, 469, 725, +595, 515, 678, +475, 571, 606, +241, 635, 487, +0, 709, 256, +0, 793, 0, +0, 885, 0, +0, 984, 0, +0, 1091, 0, +0, 1202, 0, +0, 1318, 0, +0, 1438, 0, +0, 1561, 0, +0, 1686, 0, +0, 1813, 0, +0, 1941, 0, +0, 2070, 0, +0, 2199, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +944, 411, 889, +928, 434, 876, +907, 462, 858, +876, 498, 832, +832, 541, 795, +764, 594, 740, +655, 655, 655, +450, 726, 509, +0, 807, 186, +0, 896, 0, +0, 994, 0, +0, 1098, 0, +0, 1208, 0, +0, 1323, 0, +0, 1442, 0, +0, 1564, 0, +0, 1688, 0, +0, 1814, 0, +0, 1942, 0, +0, 2071, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1105, 454, 990, +1094, 475, 979, +1079, 501, 965, +1058, 533, 944, +1029, 574, 916, +986, 623, 874, +922, 681, 813, +820, 748, 714, +633, 825, 536, +113, 912, 73, +0, 1006, 0, +0, 1108, 0, +0, 1216, 0, +0, 1329, 0, +0, 1446, 0, +0, 1567, 0, +0, 1691, 0, +0, 1816, 0, +0, 1943, 0, +0, 2072, 0, +0, 2201, 0, +0, 2331, 0, +0, 2461, 0, +0, 2592, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1257, 506, 1097, +1249, 524, 1088, +1239, 547, 1077, +1224, 577, 1061, +1204, 614, 1039, +1175, 659, 1008, +1134, 713, 963, +1073, 776, 894, +975, 849, 783, +799, 931, 571, +345, 1022, 0, +0, 1121, 0, +0, 1226, 0, +0, 1337, 0, +0, 1452, 0, +0, 1572, 0, +0, 1694, 0, +0, 1819, 0, +0, 1945, 0, +0, 2073, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1404, 566, 1209, +1398, 582, 1202, +1390, 603, 1193, +1380, 629, 1181, +1366, 662, 1165, +1346, 703, 1141, +1318, 752, 1108, +1278, 811, 1059, +1218, 878, 984, +1124, 956, 860, +956, 1042, 613, +540, 1137, 0, +0, 1239, 0, +0, 1347, 0, +0, 1461, 0, +0, 1578, 0, +0, 1699, 0, +0, 1823, 0, +0, 1948, 0, +0, 2075, 0, +0, 2204, 0, +0, 2333, 0, +0, 2463, 0, +0, 2593, 0, +0, 2724, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1546, 637, 1325, +1542, 651, 1320, +1537, 668, 1314, +1529, 691, 1304, +1519, 720, 1292, +1505, 756, 1274, +1486, 800, 1249, +1458, 853, 1214, +1419, 915, 1162, +1360, 987, 1082, +1268, 1068, 947, +1105, 1158, 665, +714, 1256, 0, +0, 1361, 0, +0, 1471, 0, +0, 1586, 0, +0, 1705, 0, +0, 1827, 0, +0, 1952, 0, +0, 2078, 0, +0, 2206, 0, +0, 2335, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1686, 717, 1446, +1683, 728, 1442, +1679, 743, 1437, +1674, 763, 1430, +1666, 787, 1420, +1656, 819, 1407, +1642, 857, 1388, +1623, 904, 1363, +1596, 960, 1326, +1557, 1026, 1272, +1500, 1101, 1187, +1409, 1185, 1042, +1250, 1278, 725, +875, 1378, 0, +0, 1485, 0, +0, 1597, 0, +0, 1713, 0, +0, 1834, 0, +0, 1957, 0, +0, 2082, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1824, 805, 1569, +1822, 815, 1566, +1819, 827, 1562, +1815, 843, 1556, +1809, 864, 1549, +1802, 891, 1539, +1792, 924, 1526, +1778, 965, 1507, +1759, 1014, 1480, +1732, 1073, 1442, +1694, 1141, 1386, +1637, 1219, 1298, +1547, 1305, 1145, +1391, 1400, 795, +1028, 1502, 0, +0, 1611, 0, +0, 1724, 0, +0, 1842, 0, +0, 1963, 0, +0, 2087, 0, +0, 2212, 0, +0, 2339, 0, +0, 2468, 0, +0, 2597, 0, +0, 2727, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1960, 902, 1694, +1959, 910, 1692, +1956, 920, 1689, +1953, 933, 1685, +1949, 950, 1679, +1944, 972, 1672, +1937, 1000, 1662, +1927, 1035, 1648, +1913, 1077, 1628, +1894, 1129, 1601, +1868, 1190, 1562, +1830, 1260, 1505, +1773, 1340, 1413, +1684, 1428, 1253, +1530, 1525, 875, +1174, 1629, 0, +0, 1738, 0, +0, 1853, 0, +0, 1971, 0, +0, 2093, 0, +0, 2217, 0, +0, 2343, 0, +0, 2471, 0, +0, 2599, 0, +0, 2729, 0, +0, 2859, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2095, 1005, 1821, +2094, 1012, 1819, +2093, 1020, 1817, +2090, 1030, 1814, +2087, 1044, 1810, +2084, 1062, 1804, +2078, 1085, 1797, +2071, 1114, 1786, +2061, 1150, 1772, +2047, 1195, 1753, +2029, 1248, 1725, +2002, 1310, 1685, +1964, 1382, 1626, +1908, 1464, 1533, +1820, 1554, 1367, +1667, 1652, 963, +1317, 1756, 0, +0, 1867, 0, +0, 1982, 0, +0, 2101, 0, +0, 2223, 0, +0, 2348, 0, +0, 2474, 0, +0, 2602, 0, +0, 2731, 0, +0, 2860, 0, +0, 2991, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2230, 1115, 1949, +2229, 1120, 1948, +2228, 1126, 1946, +2226, 1135, 1944, +2224, 1146, 1941, +2221, 1160, 1936, +2217, 1179, 1931, +2212, 1203, 1923, +2205, 1233, 1913, +2195, 1270, 1898, +2181, 1315, 1879, +2162, 1369, 1851, +2136, 1433, 1810, +2098, 1507, 1750, +2042, 1589, 1655, +1955, 1681, 1484, +1802, 1780, 1059, +1457, 1885, 0, +0, 1996, 0, +0, 2112, 0, +0, 2232, 0, +0, 2354, 0, +0, 2479, 0, +0, 2606, 0, +0, 2734, 0, +0, 2862, 0, +0, 2992, 0, +0, 3123, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2364, 1229, 2078, +2363, 1233, 2077, +2362, 1238, 2076, +2361, 1245, 2074, +2359, 1254, 2072, +2357, 1265, 2069, +2354, 1280, 2064, +2350, 1299, 2059, +2345, 1323, 2051, +2338, 1354, 2041, +2328, 1392, 2026, +2314, 1438, 2006, +2296, 1494, 1978, +2269, 1559, 1937, +2232, 1633, 1876, +2176, 1717, 1779, +2089, 1809, 1606, +1937, 1908, 1163, +1595, 2015, 0, +0, 2127, 0, +0, 2243, 0, +0, 2363, 0, +0, 2486, 0, +0, 2611, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2497, 1348, 2208, +2497, 1351, 2207, +2496, 1355, 2206, +2495, 1360, 2205, +2494, 1367, 2203, +2492, 1376, 2201, +2490, 1387, 2198, +2487, 1402, 2193, +2483, 1422, 2188, +2478, 1447, 2180, +2471, 1478, 2169, +2461, 1517, 2155, +2447, 1564, 2135, +2429, 1620, 2106, +2402, 1686, 2065, +2365, 1761, 2004, +2309, 1845, 1906, +2222, 1938, 1729, +2071, 2038, 1272, +1731, 2145, 0, +0, 2257, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2630, 1470, 2338, +2630, 1472, 2338, +2629, 1475, 2337, +2629, 1479, 2336, +2628, 1484, 2335, +2627, 1491, 2333, +2625, 1500, 2331, +2623, 1512, 2327, +2620, 1527, 2323, +2616, 1547, 2317, +2611, 1572, 2310, +2603, 1604, 2299, +2594, 1643, 2284, +2580, 1691, 2264, +2561, 1748, 2236, +2535, 1814, 2194, +2498, 1890, 2132, +2442, 1974, 2033, +2355, 2068, 1855, +2205, 2168, 1386, +1867, 2276, 0, +0, 2388, 0, +0, 2505, 0, +0, 2625, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2763, 1594, 2469, +2763, 1595, 2469, +2762, 1598, 2468, +2762, 1601, 2467, +2761, 1605, 2466, +2760, 1610, 2465, +2759, 1617, 2463, +2757, 1626, 2461, +2755, 1638, 2458, +2752, 1654, 2454, +2748, 1674, 2448, +2743, 1699, 2440, +2736, 1731, 2429, +2726, 1771, 2415, +2713, 1819, 2394, +2694, 1876, 2366, +2668, 1943, 2324, +2630, 2019, 2262, +2575, 2104, 2162, +2488, 2198, 1982, +2338, 2299, 1505, +2001, 2407, 0, +0, 2519, 0, +0, 2637, 0, +0, 2757, 0, +0, 2880, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2896, 1720, 2600, +2895, 1721, 2600, +2895, 1723, 2600, +2895, 1725, 2599, +2894, 1728, 2598, +2894, 1732, 2597, +2893, 1738, 2596, +2891, 1745, 2594, +2890, 1754, 2592, +2888, 1766, 2589, +2885, 1782, 2584, +2881, 1802, 2579, +2876, 1828, 2571, +2868, 1860, 2560, +2859, 1900, 2545, +2845, 1948, 2525, +2827, 2006, 2496, +2800, 2073, 2454, +2763, 2149, 2392, +2708, 2235, 2292, +2621, 2329, 2111, +2471, 2430, 1626, +2135, 2538, 0, +0, 2651, 0, +0, 2768, 0, +0, 2889, 0, +0, 3012, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3028, 1847, 2732, +3028, 1848, 2731, +3028, 1850, 2731, +3027, 1851, 2731, +3027, 1854, 2730, +3027, 1857, 2729, +3026, 1861, 2728, +3025, 1866, 2727, +3024, 1873, 2725, +3022, 1883, 2723, +3020, 1895, 2720, +3017, 1911, 2716, +3013, 1931, 2710, +3008, 1957, 2702, +3001, 1989, 2691, +2991, 2030, 2676, +2978, 2078, 2656, +2959, 2136, 2627, +2933, 2203, 2585, +2895, 2280, 2522, +2840, 2366, 2422, +2753, 2460, 2240, +2604, 2562, 1750, +2268, 2670, 0, +0, 2783, 0, +0, 2900, 0, +0, 3021, 0, +0, 3144, 0, +0, 3269, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +3160, 1976, 2863, +3160, 1977, 2863, +3160, 1978, 2863, +3160, 1979, 2862, +3160, 1981, 2862, +3159, 1983, 2862, +3159, 1986, 2861, +3158, 1990, 2860, +3157, 1996, 2858, +3156, 2003, 2857, +3154, 2012, 2854, +3152, 2025, 2851, +3149, 2040, 2847, +3146, 2061, 2841, +3140, 2087, 2833, +3133, 2120, 2822, +3123, 2160, 2808, +3110, 2209, 2787, +3091, 2267, 2758, +3065, 2334, 2716, +3028, 2411, 2653, +2972, 2497, 2553, +2886, 2592, 2370, +2736, 2693, 1876, +2401, 2801, 0, +0, 2914, 0, +0, 3032, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3529, 0, +0, 3657, 0, +3293, 2105, 2995, +3293, 2106, 2995, +3293, 2107, 2995, +3292, 2108, 2994, +3292, 2109, 2994, +3292, 2111, 2994, +3292, 2113, 2993, +3291, 2116, 2992, +3290, 2120, 2991, +3290, 2126, 2990, +3288, 2133, 2988, +3287, 2142, 2986, +3285, 2155, 2983, +3282, 2171, 2978, +3278, 2191, 2973, +3272, 2217, 2965, +3265, 2250, 2954, +3256, 2291, 2939, +3242, 2339, 2919, +3224, 2398, 2890, +3197, 2465, 2848, +3160, 2542, 2785, +3105, 2629, 2684, +3018, 2723, 2500, +2869, 2825, 2004, +2534, 2933, 0, +0, 3046, 0, +0, 3164, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3661, 0, +3425, 2236, 3127, +3425, 2236, 3127, +3425, 2237, 3126, +3425, 2237, 3126, +3425, 2238, 3126, +3424, 2240, 3126, +3424, 2241, 3125, +3424, 2244, 3125, +3423, 2247, 3124, +3423, 2251, 3123, +3422, 2256, 3122, +3421, 2264, 3120, +3419, 2273, 3118, +3417, 2286, 3114, +3414, 2302, 3110, +3410, 2322, 3104, +3405, 2348, 3096, +3397, 2381, 3086, +3388, 2422, 3071, +3374, 2471, 3050, +3356, 2529, 3021, +3330, 2597, 2979, +3292, 2674, 2916, +3237, 2760, 2815, +3150, 2855, 2631, +3001, 2957, 2132, +2667, 3065, 0, +0, 3178, 0, +0, 3296, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3557, 2366, 3259, +3557, 2367, 3258, +3557, 2367, 3258, +3557, 2367, 3258, +3557, 2368, 3258, +3557, 2369, 3258, +3557, 2371, 3258, +3556, 2372, 3257, +3556, 2375, 3257, +3555, 2378, 3256, +3555, 2382, 3255, +3554, 2387, 3254, +3553, 2395, 3252, +3551, 2404, 3249, +3549, 2417, 3246, +3546, 2433, 3242, +3542, 2453, 3236, +3537, 2480, 3228, +3530, 2512, 3217, +3520, 2553, 3203, +3506, 2602, 3182, +3488, 2660, 3153, +3462, 2728, 3111, +3424, 2806, 3048, +3369, 2892, 2947, +3283, 2987, 2763, +3133, 3089, 2262, +2799, 3197, 0, +0, 3310, 0, +0, 3428, 0, +0, 3548, 0, +0, 3672, 0, +3689, 2497, 3390, +3689, 2497, 3390, +3689, 2498, 3390, +3689, 2498, 3390, +3689, 2499, 3390, +3689, 2499, 3390, +3689, 2500, 3390, +3689, 2502, 3389, +3688, 2504, 3389, +3688, 2506, 3388, +3688, 2509, 3388, +3687, 2513, 3387, +3686, 2519, 3385, +3685, 2526, 3384, +3683, 2535, 3381, +3681, 2548, 3378, +3678, 2564, 3374, +3674, 2585, 3368, +3669, 2611, 3360, +3662, 2644, 3349, +3652, 2684, 3334, +3639, 2734, 3314, +3620, 2792, 3285, +3594, 2860, 3243, +3557, 2937, 3179, +3501, 3024, 3078, +3415, 3119, 2894, +3266, 3220, 2392, +2932, 3329, 0, +0, 3442, 0, +0, 3560, 0, +0, 3680, 0, +3822, 2628, 3522, +3822, 2629, 3522, +3822, 2629, 3522, +3822, 2629, 3522, +3821, 2630, 3522, +3821, 2630, 3522, +3821, 2631, 3522, +3821, 2632, 3522, +3821, 2633, 3521, +3821, 2635, 3521, +3820, 2637, 3520, +3820, 2641, 3520, +3819, 2645, 3519, +3818, 2650, 3517, +3817, 2657, 3516, +3815, 2667, 3513, +3813, 2679, 3510, +3810, 2696, 3506, +3806, 2716, 3500, +3801, 2743, 3492, +3794, 2775, 3481, +3784, 2816, 3466, +3771, 2865, 3446, +3752, 2924, 3417, +3726, 2992, 3375, +3689, 3069, 3311, +3633, 3156, 3210, +3547, 3250, 3026, +3398, 3352, 2523, +3064, 3461, 0, +0, 3574, 0, +0, 3692, 0, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2760, 3654, +3954, 2761, 3654, +3954, 2761, 3654, +3954, 2762, 3654, +3953, 2763, 3654, +3953, 2764, 3654, +3953, 2765, 3653, +3953, 2767, 3653, +3952, 2769, 3652, +3952, 2772, 3652, +3951, 2776, 3651, +3950, 2782, 3649, +3949, 2789, 3648, +3948, 2799, 3645, +3945, 2811, 3642, +3942, 2827, 3638, +3939, 2848, 3632, +3933, 2874, 3624, +3926, 2907, 3613, +3916, 2948, 3598, +3903, 2997, 3578, +3884, 3056, 3549, +3858, 3124, 3506, +3821, 3201, 3443, +3766, 3288, 3342, +3679, 3382, 3157, +3530, 3484, 2654, +3196, 3593, 0, +0, 3706, 0, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2893, 3786, +4086, 2894, 3786, +4086, 2894, 3786, +4085, 2895, 3786, +4085, 2897, 3785, +4085, 2898, 3785, +4085, 2901, 3784, +4084, 2904, 3784, +4083, 2908, 3783, +4082, 2914, 3781, +4081, 2921, 3780, +4080, 2930, 3777, +4077, 2943, 3774, +4075, 2959, 3770, +4071, 2980, 3764, +4065, 3006, 3756, +4058, 3039, 3745, +4048, 3080, 3730, +4035, 3129, 3710, +4017, 3188, 3681, +3990, 3256, 3638, +3953, 3333, 3575, +3898, 3420, 3474, +3811, 3514, 3289, +3662, 3616, 2785, +3329, 3725, 0, +4095, 3023, 3919, +4095, 3023, 3918, +4095, 3023, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3917, +4095, 3030, 3917, +4095, 3033, 3916, +4095, 3036, 3916, +4095, 3040, 3915, +4095, 3045, 3913, +4095, 3053, 3912, +4095, 3062, 3909, +4095, 3075, 3906, +4095, 3091, 3902, +4095, 3112, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3212, 3862, +4095, 3261, 3842, +4095, 3319, 3813, +4095, 3388, 3770, +4085, 3465, 3707, +4030, 3552, 3606, +3944, 3646, 3421, +3794, 3748, 2916, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4049, +4095, 3162, 4049, +4095, 3164, 4048, +4095, 3168, 4048, +4095, 3172, 4047, +4095, 3177, 4045, +4095, 3185, 4044, +4095, 3194, 4041, +4095, 3207, 4038, +4095, 3223, 4034, +4095, 3244, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3344, 3994, +4095, 3393, 3974, +4095, 3451, 3945, +4095, 3520, 3902, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3778, 3553, +0, 387, 587, +0, 410, 561, +0, 440, 523, +0, 477, 468, +0, 523, 381, +0, 577, 231, +0, 641, 0, +0, 714, 0, +0, 797, 0, +0, 888, 0, +0, 987, 0, +0, 1093, 0, +0, 1204, 0, +0, 1320, 0, +0, 1439, 0, +0, 1562, 0, +0, 1687, 0, +0, 1813, 0, +0, 1941, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 395, 624, +0, 418, 600, +0, 448, 565, +0, 484, 515, +0, 529, 437, +0, 583, 307, +0, 646, 42, +0, 718, 0, +0, 800, 0, +0, 891, 0, +0, 989, 0, +0, 1094, 0, +0, 1205, 0, +0, 1321, 0, +0, 1440, 0, +0, 1562, 0, +0, 1687, 0, +0, 1813, 0, +0, 1941, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 406, 669, +0, 428, 647, +0, 457, 616, +0, 493, 571, +0, 537, 503, +0, 590, 393, +0, 652, 186, +0, 724, 0, +0, 805, 0, +0, 894, 0, +0, 992, 0, +0, 1097, 0, +0, 1207, 0, +0, 1322, 0, +0, 1441, 0, +0, 1563, 0, +0, 1688, 0, +0, 1814, 0, +0, 1942, 0, +0, 2070, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +247, 420, 722, +170, 442, 703, +41, 470, 676, +0, 505, 637, +0, 547, 579, +0, 599, 487, +0, 660, 327, +0, 731, 0, +0, 811, 0, +0, 899, 0, +0, 996, 0, +0, 1100, 0, +0, 1210, 0, +0, 1324, 0, +0, 1443, 0, +0, 1564, 0, +0, 1688, 0, +0, 1815, 0, +0, 1942, 0, +0, 2071, 0, +0, 2200, 0, +0, 2330, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2986, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +519, 438, 786, +479, 459, 769, +418, 486, 745, +322, 520, 712, +149, 561, 663, +0, 611, 589, +0, 671, 465, +0, 740, 219, +0, 818, 0, +0, 906, 0, +0, 1001, 0, +0, 1104, 0, +0, 1213, 0, +0, 1327, 0, +0, 1445, 0, +0, 1566, 0, +0, 1690, 0, +0, 1815, 0, +0, 1943, 0, +0, 2071, 0, +0, 2201, 0, +0, 2331, 0, +0, 2461, 0, +0, 2592, 0, +0, 2723, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +734, 461, 858, +709, 481, 844, +673, 507, 824, +621, 539, 797, +540, 579, 756, +402, 627, 697, +110, 685, 602, +0, 752, 434, +0, 828, 18, +0, 914, 0, +0, 1008, 0, +0, 1109, 0, +0, 1217, 0, +0, 1330, 0, +0, 1447, 0, +0, 1568, 0, +0, 1691, 0, +0, 1817, 0, +0, 1944, 0, +0, 2072, 0, +0, 2201, 0, +0, 2331, 0, +0, 2462, 0, +0, 2592, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +919, 490, 940, +903, 509, 929, +880, 533, 912, +847, 563, 889, +800, 601, 857, +727, 647, 810, +607, 703, 738, +373, 767, 619, +0, 842, 388, +0, 925, 0, +0, 1017, 0, +0, 1116, 0, +0, 1223, 0, +0, 1334, 0, +0, 1451, 0, +0, 1570, 0, +0, 1693, 0, +0, 1818, 0, +0, 1945, 0, +0, 2073, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1087, 526, 1031, +1076, 544, 1021, +1061, 566, 1008, +1039, 594, 990, +1008, 630, 964, +964, 673, 927, +896, 726, 872, +787, 787, 787, +582, 859, 641, +0, 939, 318, +0, 1029, 0, +0, 1126, 0, +0, 1230, 0, +0, 1340, 0, +0, 1455, 0, +0, 1574, 0, +0, 1696, 0, +0, 1820, 0, +0, 1946, 0, +0, 2074, 0, +0, 2203, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1245, 570, 1130, +1237, 586, 1122, +1226, 607, 1111, +1211, 633, 1097, +1190, 665, 1076, +1161, 706, 1048, +1118, 755, 1006, +1055, 813, 945, +952, 880, 846, +765, 958, 669, +245, 1044, 205, +0, 1138, 0, +0, 1240, 0, +0, 1348, 0, +0, 1461, 0, +0, 1578, 0, +0, 1699, 0, +0, 1823, 0, +0, 1948, 0, +0, 2075, 0, +0, 2204, 0, +0, 2333, 0, +0, 2463, 0, +0, 2594, 0, +0, 2724, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1395, 623, 1235, +1389, 638, 1229, +1381, 656, 1220, +1371, 679, 1209, +1356, 709, 1193, +1336, 746, 1171, +1308, 791, 1140, +1267, 845, 1095, +1205, 908, 1026, +1107, 981, 915, +932, 1063, 703, +477, 1154, 0, +0, 1253, 0, +0, 1358, 0, +0, 1469, 0, +0, 1585, 0, +0, 1704, 0, +0, 1826, 0, +0, 1951, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1540, 686, 1346, +1536, 698, 1341, +1530, 715, 1334, +1522, 735, 1326, +1512, 762, 1313, +1498, 794, 1297, +1478, 835, 1273, +1450, 884, 1240, +1410, 943, 1191, +1351, 1011, 1116, +1256, 1088, 993, +1088, 1174, 745, +672, 1269, 0, +0, 1371, 0, +0, 1479, 0, +0, 1593, 0, +0, 1710, 0, +0, 1831, 0, +0, 1955, 0, +0, 2080, 0, +0, 2207, 0, +0, 2336, 0, +0, 2465, 0, +0, 2595, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1681, 758, 1461, +1678, 769, 1458, +1674, 783, 1453, +1669, 801, 1446, +1661, 823, 1436, +1651, 852, 1424, +1637, 888, 1406, +1618, 932, 1381, +1590, 985, 1346, +1551, 1047, 1295, +1492, 1119, 1215, +1400, 1200, 1079, +1237, 1290, 797, +846, 1388, 0, +0, 1493, 0, +0, 1603, 0, +0, 1718, 0, +0, 1837, 0, +0, 1959, 0, +0, 2084, 0, +0, 2210, 0, +0, 2338, 0, +0, 2467, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1820, 840, 1581, +1818, 849, 1578, +1815, 860, 1574, +1811, 875, 1569, +1806, 895, 1562, +1798, 920, 1552, +1788, 951, 1539, +1774, 989, 1521, +1755, 1036, 1495, +1728, 1092, 1458, +1689, 1158, 1404, +1632, 1233, 1319, +1541, 1317, 1174, +1382, 1410, 857, +1007, 1510, 0, +0, 1617, 0, +0, 1729, 0, +0, 1846, 0, +0, 1966, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1958, 930, 1703, +1956, 937, 1701, +1954, 947, 1698, +1951, 959, 1694, +1947, 976, 1689, +1941, 996, 1681, +1934, 1023, 1671, +1924, 1056, 1658, +1910, 1097, 1639, +1891, 1146, 1613, +1865, 1205, 1575, +1826, 1273, 1518, +1769, 1351, 1430, +1679, 1437, 1277, +1523, 1532, 927, +1160, 1635, 0, +0, 1743, 0, +0, 1856, 0, +0, 1974, 0, +0, 2095, 0, +0, 2219, 0, +0, 2344, 0, +0, 2471, 0, +0, 2600, 0, +0, 2729, 0, +0, 2859, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2094, 1028, 1828, +2092, 1034, 1826, +2091, 1042, 1824, +2088, 1052, 1821, +2086, 1065, 1817, +2082, 1082, 1811, +2076, 1104, 1804, +2069, 1132, 1794, +2059, 1167, 1780, +2045, 1210, 1761, +2026, 1261, 1733, +2000, 1322, 1695, +1962, 1392, 1637, +1905, 1472, 1545, +1816, 1561, 1385, +1662, 1657, 1007, +1307, 1761, 0, +0, 1870, 0, +0, 1985, 0, +0, 2103, 0, +0, 2225, 0, +0, 2349, 0, +0, 2475, 0, +0, 2603, 0, +0, 2731, 0, +0, 2861, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2228, 1133, 1954, +2228, 1138, 1953, +2226, 1144, 1951, +2225, 1152, 1949, +2223, 1163, 1946, +2220, 1176, 1942, +2216, 1194, 1936, +2210, 1217, 1929, +2203, 1246, 1918, +2193, 1282, 1904, +2180, 1327, 1885, +2161, 1380, 1857, +2134, 1442, 1817, +2096, 1514, 1758, +2040, 1596, 1665, +1952, 1686, 1499, +1799, 1784, 1095, +1449, 1888, 0, +0, 1999, 0, +0, 2114, 0, +0, 2233, 0, +0, 2356, 0, +0, 2480, 0, +0, 2606, 0, +0, 2734, 0, +0, 2863, 0, +0, 2992, 0, +0, 3123, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2363, 1243, 2082, +2362, 1247, 2081, +2361, 1252, 2080, +2360, 1258, 2078, +2358, 1267, 2076, +2356, 1278, 2073, +2353, 1292, 2068, +2349, 1311, 2063, +2344, 1335, 2055, +2337, 1365, 2045, +2327, 1402, 2031, +2313, 1447, 2011, +2294, 1502, 1983, +2268, 1565, 1942, +2230, 1639, 1882, +2174, 1721, 1787, +2087, 1813, 1617, +1934, 1912, 1191, +1589, 2017, 0, +0, 2129, 0, +0, 2244, 0, +0, 2364, 0, +0, 2486, 0, +0, 2611, 0, +0, 2738, 0, +0, 2866, 0, +0, 2995, 0, +0, 3124, 0, +0, 3255, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2496, 1359, 2211, +2496, 1362, 2210, +2495, 1365, 2209, +2494, 1370, 2208, +2493, 1377, 2206, +2491, 1386, 2204, +2489, 1397, 2201, +2486, 1412, 2196, +2482, 1431, 2191, +2477, 1455, 2183, +2470, 1486, 2173, +2460, 1524, 2158, +2446, 1570, 2138, +2428, 1626, 2110, +2402, 1691, 2069, +2364, 1765, 2008, +2308, 1849, 1911, +2221, 1941, 1738, +2069, 2041, 1295, +1727, 2147, 0, +0, 2259, 0, +0, 2375, 0, +0, 2495, 0, +0, 2618, 0, +0, 2743, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3648, 0, +2630, 1478, 2340, +2629, 1480, 2340, +2629, 1483, 2339, +2628, 1487, 2338, +2627, 1492, 2337, +2626, 1499, 2335, +2624, 1508, 2333, +2622, 1519, 2330, +2619, 1535, 2326, +2615, 1554, 2320, +2610, 1579, 2312, +2603, 1610, 2302, +2593, 1649, 2287, +2579, 1696, 2267, +2561, 1752, 2238, +2535, 1818, 2197, +2497, 1893, 2136, +2441, 1977, 2038, +2354, 2070, 1861, +2203, 2170, 1404, +1864, 2277, 0, +0, 2389, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +2763, 1600, 2471, +2762, 1602, 2470, +2762, 1604, 2470, +2761, 1607, 2469, +2761, 1611, 2468, +2760, 1616, 2467, +2759, 1623, 2465, +2757, 1632, 2463, +2755, 1644, 2460, +2752, 1659, 2455, +2748, 1679, 2450, +2743, 1704, 2442, +2735, 1736, 2431, +2726, 1775, 2417, +2712, 1823, 2396, +2694, 1880, 2368, +2667, 1946, 2326, +2630, 2022, 2264, +2574, 2107, 2165, +2487, 2200, 1987, +2337, 2301, 1518, +1999, 2408, 0, +0, 2520, 0, +0, 2637, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +2895, 1725, 2601, +2895, 1726, 2601, +2895, 1728, 2601, +2894, 1730, 2600, +2894, 1733, 2599, +2893, 1737, 2599, +2892, 1742, 2597, +2891, 1749, 2595, +2890, 1758, 2593, +2887, 1770, 2590, +2884, 1786, 2586, +2881, 1806, 2580, +2875, 1832, 2572, +2868, 1864, 2561, +2858, 1903, 2547, +2845, 1951, 2526, +2826, 2008, 2498, +2800, 2075, 2456, +2763, 2151, 2394, +2707, 2237, 2294, +2620, 2330, 2114, +2470, 2431, 1637, +2133, 2539, 0, +0, 2652, 0, +0, 2769, 0, +0, 2889, 0, +0, 3012, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3028, 1851, 2733, +3028, 1852, 2732, +3027, 1853, 2732, +3027, 1855, 2732, +3027, 1857, 2731, +3026, 1860, 2730, +3026, 1864, 2729, +3025, 1870, 2728, +3024, 1877, 2726, +3022, 1886, 2724, +3020, 1898, 2721, +3017, 1914, 2717, +3013, 1934, 2711, +3008, 1960, 2703, +3000, 1992, 2692, +2991, 2032, 2677, +2977, 2080, 2657, +2959, 2138, 2628, +2933, 2205, 2586, +2895, 2282, 2524, +2840, 2367, 2424, +2753, 2461, 2243, +2603, 2562, 1758, +2267, 2670, 0, +0, 2783, 0, +0, 2900, 0, +0, 3021, 0, +0, 3144, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +3160, 1979, 2864, +3160, 1979, 2864, +3160, 1980, 2863, +3160, 1982, 2863, +3160, 1983, 2863, +3159, 1986, 2862, +3159, 1989, 2861, +3158, 1993, 2861, +3157, 1998, 2859, +3156, 2005, 2857, +3154, 2015, 2855, +3152, 2027, 2852, +3149, 2043, 2848, +3145, 2063, 2842, +3140, 2089, 2834, +3133, 2122, 2823, +3123, 2162, 2809, +3110, 2210, 2788, +3091, 2268, 2759, +3065, 2335, 2717, +3028, 2412, 2654, +2972, 2498, 2554, +2886, 2592, 2372, +2736, 2694, 1882, +2401, 2802, 0, +0, 2915, 0, +0, 3032, 0, +0, 3153, 0, +0, 3276, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +3293, 2107, 2995, +3293, 2108, 2995, +3292, 2109, 2995, +3292, 2110, 2995, +3292, 2111, 2995, +3292, 2113, 2994, +3291, 2115, 2994, +3291, 2118, 2993, +3290, 2122, 2992, +3289, 2128, 2991, +3288, 2135, 2989, +3287, 2144, 2986, +3284, 2157, 2983, +3282, 2173, 2979, +3278, 2193, 2973, +3272, 2219, 2965, +3265, 2252, 2955, +3255, 2292, 2940, +3242, 2341, 2919, +3223, 2399, 2890, +3197, 2466, 2848, +3160, 2543, 2785, +3104, 2629, 2685, +3018, 2724, 2502, +2868, 2825, 2008, +2534, 2933, 0, +0, 3046, 0, +0, 3164, 0, +0, 3285, 0, +0, 3408, 0, +0, 3534, 0, +0, 3661, 0, +3425, 2237, 3127, +3425, 2238, 3127, +3425, 2238, 3127, +3425, 2239, 3127, +3425, 2240, 3126, +3424, 2241, 3126, +3424, 2243, 3126, +3424, 2245, 3125, +3423, 2248, 3124, +3423, 2252, 3123, +3422, 2258, 3122, +3420, 2265, 3120, +3419, 2275, 3118, +3417, 2287, 3115, +3414, 2303, 3111, +3410, 2323, 3105, +3405, 2350, 3097, +3397, 2382, 3086, +3388, 2423, 3071, +3374, 2472, 3051, +3356, 2530, 3022, +3330, 2597, 2980, +3292, 2675, 2917, +3237, 2761, 2816, +3150, 2855, 2633, +3001, 2957, 2136, +2666, 3065, 0, +0, 3178, 0, +0, 3296, 0, +0, 3417, 0, +0, 3540, 0, +0, 3666, 0, +3557, 2367, 3259, +3557, 2368, 3259, +3557, 2368, 3259, +3557, 2369, 3259, +3557, 2369, 3258, +3557, 2370, 3258, +3557, 2372, 3258, +3556, 2373, 3257, +3556, 2376, 3257, +3555, 2379, 3256, +3555, 2383, 3255, +3554, 2389, 3254, +3553, 2396, 3252, +3551, 2405, 3250, +3549, 2418, 3247, +3546, 2434, 3242, +3542, 2454, 3236, +3537, 2480, 3229, +3530, 2513, 3218, +3520, 2554, 3203, +3506, 2603, 3182, +3488, 2661, 3153, +3462, 2729, 3111, +3424, 2806, 3048, +3369, 2892, 2947, +3283, 2987, 2763, +3133, 3089, 2264, +2799, 3197, 0, +0, 3310, 0, +0, 3428, 0, +0, 3548, 0, +0, 3672, 0, +3689, 2498, 3391, +3689, 2498, 3391, +3689, 2499, 3391, +3689, 2499, 3390, +3689, 2500, 3390, +3689, 2500, 3390, +3689, 2501, 3390, +3689, 2503, 3390, +3688, 2504, 3389, +3688, 2507, 3389, +3688, 2510, 3388, +3687, 2514, 3387, +3686, 2520, 3386, +3685, 2527, 3384, +3683, 2536, 3382, +3681, 2549, 3378, +3678, 2565, 3374, +3674, 2585, 3368, +3669, 2612, 3360, +3662, 2644, 3350, +3652, 2685, 3335, +3639, 2734, 3314, +3620, 2792, 3285, +3594, 2860, 3243, +3557, 2938, 3180, +3501, 3024, 3079, +3415, 3119, 2895, +3265, 3221, 2394, +2932, 3329, 0, +0, 3442, 0, +0, 3560, 0, +0, 3681, 0, +3822, 2629, 3523, +3822, 2629, 3523, +3822, 2630, 3523, +3822, 2630, 3522, +3821, 2630, 3522, +3821, 2631, 3522, +3821, 2632, 3522, +3821, 2633, 3522, +3821, 2634, 3522, +3821, 2636, 3521, +3820, 2638, 3521, +3820, 2641, 3520, +3819, 2645, 3519, +3818, 2651, 3518, +3817, 2658, 3516, +3815, 2668, 3513, +3813, 2680, 3510, +3810, 2696, 3506, +3806, 2717, 3500, +3801, 2743, 3492, +3794, 2776, 3481, +3784, 2817, 3467, +3771, 2866, 3446, +3752, 2924, 3417, +3726, 2992, 3375, +3689, 3069, 3312, +3633, 3156, 3210, +3547, 3251, 3026, +3398, 3353, 2524, +3064, 3461, 0, +0, 3574, 0, +0, 3692, 0, +3954, 2760, 3655, +3954, 2761, 3655, +3954, 2761, 3654, +3954, 2761, 3654, +3954, 2761, 3654, +3954, 2762, 3654, +3953, 2762, 3654, +3953, 2763, 3654, +3953, 2764, 3654, +3953, 2765, 3653, +3953, 2767, 3653, +3952, 2769, 3652, +3952, 2773, 3652, +3951, 2777, 3651, +3950, 2782, 3649, +3949, 2790, 3648, +3947, 2799, 3645, +3945, 2812, 3642, +3942, 2828, 3638, +3939, 2848, 3632, +3933, 2875, 3624, +3926, 2908, 3613, +3916, 2948, 3598, +3903, 2997, 3578, +3884, 3056, 3549, +3858, 3124, 3507, +3821, 3201, 3443, +3766, 3288, 3342, +3679, 3383, 3158, +3530, 3485, 2655, +3196, 3593, 0, +0, 3706, 0, +4086, 2892, 3787, +4086, 2892, 3787, +4086, 2892, 3787, +4086, 2892, 3786, +4086, 2893, 3786, +4086, 2893, 3786, +4086, 2893, 3786, +4086, 2894, 3786, +4086, 2895, 3786, +4085, 2896, 3786, +4085, 2897, 3785, +4085, 2899, 3785, +4084, 2901, 3784, +4084, 2904, 3784, +4083, 2908, 3783, +4082, 2914, 3781, +4081, 2921, 3780, +4080, 2931, 3777, +4077, 2943, 3774, +4075, 2959, 3770, +4071, 2980, 3764, +4065, 3006, 3756, +4058, 3039, 3745, +4048, 3080, 3730, +4035, 3129, 3710, +4016, 3188, 3681, +3990, 3256, 3639, +3953, 3333, 3575, +3898, 3420, 3474, +3811, 3515, 3289, +3662, 3617, 2786, +3329, 3725, 0, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3024, 3918, +4095, 3024, 3918, +4095, 3025, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3029, 3917, +4095, 3030, 3917, +4095, 3033, 3916, +4095, 3036, 3916, +4095, 3040, 3915, +4095, 3046, 3913, +4095, 3053, 3912, +4095, 3062, 3909, +4095, 3075, 3906, +4095, 3091, 3902, +4095, 3112, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3212, 3862, +4095, 3261, 3842, +4095, 3320, 3813, +4095, 3388, 3771, +4085, 3465, 3707, +4030, 3552, 3606, +3943, 3647, 3421, +3794, 3749, 2917, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3155, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4050, +4095, 3156, 4050, +4095, 3157, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3161, 4049, +4095, 3162, 4049, +4095, 3165, 4048, +4095, 3168, 4048, +4095, 3172, 4047, +4095, 3177, 4045, +4095, 3185, 4044, +4095, 3194, 4041, +4095, 3207, 4038, +4095, 3223, 4034, +4095, 3244, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3344, 3994, +4095, 3393, 3974, +4095, 3452, 3945, +4095, 3520, 3903, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3779, 3553, +0, 494, 709, +0, 513, 690, +0, 537, 662, +0, 567, 621, +0, 604, 561, +0, 650, 466, +0, 705, 295, +0, 770, 0, +0, 843, 0, +0, 927, 0, +0, 1018, 0, +0, 1118, 0, +0, 1223, 0, +0, 1335, 0, +0, 1451, 0, +0, 1571, 0, +0, 1693, 0, +0, 1818, 0, +0, 1945, 0, +0, 2073, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 500, 738, +0, 519, 719, +0, 543, 693, +0, 572, 655, +0, 610, 600, +0, 655, 513, +0, 709, 363, +0, 773, 25, +0, 846, 0, +0, 929, 0, +0, 1020, 0, +0, 1119, 0, +0, 1225, 0, +0, 1336, 0, +0, 1452, 0, +0, 1571, 0, +0, 1694, 0, +0, 1819, 0, +0, 1945, 0, +0, 2073, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 509, 773, +0, 527, 756, +0, 550, 732, +0, 580, 697, +0, 616, 647, +0, 661, 569, +0, 715, 440, +0, 778, 174, +0, 850, 0, +0, 932, 0, +0, 1023, 0, +0, 1121, 0, +0, 1227, 0, +0, 1337, 0, +0, 1453, 0, +0, 1572, 0, +0, 1694, 0, +0, 1819, 0, +0, 1946, 0, +0, 2073, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +66, 520, 816, +0, 538, 801, +0, 561, 779, +0, 589, 748, +0, 625, 703, +0, 669, 635, +0, 722, 525, +0, 784, 318, +0, 856, 0, +0, 937, 0, +0, 1027, 0, +0, 1124, 0, +0, 1229, 0, +0, 1339, 0, +0, 1454, 0, +0, 1573, 0, +0, 1695, 0, +0, 1820, 0, +0, 1946, 0, +0, 2074, 0, +0, 2202, 0, +0, 2332, 0, +0, 2462, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3118, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +429, 534, 868, +379, 552, 854, +302, 574, 835, +173, 602, 808, +0, 637, 769, +0, 680, 711, +0, 731, 620, +0, 792, 459, +0, 863, 78, +0, 943, 0, +0, 1031, 0, +0, 1128, 0, +0, 1232, 0, +0, 1342, 0, +0, 1456, 0, +0, 1575, 0, +0, 1696, 0, +0, 1821, 0, +0, 1947, 0, +0, 2074, 0, +0, 2203, 0, +0, 2332, 0, +0, 2463, 0, +0, 2593, 0, +0, 2724, 0, +0, 2855, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +680, 553, 930, +652, 570, 918, +611, 591, 901, +550, 618, 878, +454, 652, 844, +281, 693, 796, +0, 743, 721, +0, 803, 597, +0, 872, 351, +0, 950, 0, +0, 1038, 0, +0, 1133, 0, +0, 1236, 0, +0, 1345, 0, +0, 1459, 0, +0, 1577, 0, +0, 1698, 0, +0, 1822, 0, +0, 1948, 0, +0, 2075, 0, +0, 2203, 0, +0, 2333, 0, +0, 2463, 0, +0, 2593, 0, +0, 2724, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +884, 577, 1001, +866, 593, 990, +841, 613, 976, +806, 639, 956, +753, 671, 929, +672, 711, 889, +534, 759, 829, +243, 817, 734, +0, 884, 566, +0, 960, 150, +0, 1046, 0, +0, 1140, 0, +0, 1241, 0, +0, 1349, 0, +0, 1462, 0, +0, 1579, 0, +0, 1700, 0, +0, 1823, 0, +0, 1949, 0, +0, 2076, 0, +0, 2204, 0, +0, 2333, 0, +0, 2463, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1063, 607, 1081, +1051, 622, 1072, +1035, 641, 1061, +1012, 665, 1044, +979, 696, 1022, +932, 733, 989, +859, 780, 942, +739, 835, 870, +505, 899, 751, +0, 974, 520, +0, 1057, 0, +0, 1149, 0, +0, 1249, 0, +0, 1355, 0, +0, 1466, 0, +0, 1583, 0, +0, 1702, 0, +0, 1825, 0, +0, 1950, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1228, 644, 1170, +1219, 658, 1163, +1208, 676, 1153, +1193, 698, 1140, +1171, 727, 1122, +1140, 762, 1096, +1096, 805, 1059, +1029, 858, 1005, +919, 919, 919, +715, 991, 773, +63, 1071, 450, +0, 1161, 0, +0, 1258, 0, +0, 1362, 0, +0, 1472, 0, +0, 1587, 0, +0, 1706, 0, +0, 1828, 0, +0, 1952, 0, +0, 2078, 0, +0, 2206, 0, +0, 2335, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1383, 690, 1267, +1377, 702, 1262, +1369, 718, 1254, +1358, 739, 1243, +1343, 765, 1229, +1322, 798, 1208, +1293, 838, 1180, +1250, 887, 1139, +1187, 945, 1077, +1084, 1013, 978, +897, 1090, 801, +377, 1176, 337, +0, 1270, 0, +0, 1372, 0, +0, 1480, 0, +0, 1593, 0, +0, 1711, 0, +0, 1831, 0, +0, 1955, 0, +0, 2080, 0, +0, 2208, 0, +0, 2336, 0, +0, 2465, 0, +0, 2595, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1531, 745, 1371, +1527, 756, 1367, +1521, 770, 1361, +1513, 788, 1352, +1503, 812, 1341, +1488, 841, 1325, +1468, 878, 1303, +1440, 923, 1272, +1399, 977, 1227, +1337, 1040, 1158, +1239, 1113, 1047, +1064, 1195, 835, +609, 1286, 120, +0, 1385, 0, +0, 1490, 0, +0, 1601, 0, +0, 1717, 0, +0, 1836, 0, +0, 1958, 0, +0, 2083, 0, +0, 2210, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1675, 809, 1481, +1672, 818, 1478, +1668, 831, 1473, +1662, 847, 1466, +1655, 867, 1458, +1644, 894, 1445, +1630, 927, 1429, +1610, 967, 1405, +1582, 1016, 1372, +1542, 1075, 1323, +1483, 1143, 1249, +1388, 1220, 1125, +1220, 1307, 878, +804, 1401, 0, +0, 1503, 0, +0, 1611, 0, +0, 1725, 0, +0, 1842, 0, +0, 1963, 0, +0, 2087, 0, +0, 2212, 0, +0, 2340, 0, +0, 2468, 0, +0, 2597, 0, +0, 2727, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1816, 882, 1596, +1813, 890, 1593, +1810, 901, 1590, +1806, 915, 1585, +1801, 933, 1578, +1793, 955, 1569, +1783, 984, 1556, +1769, 1020, 1538, +1750, 1064, 1514, +1722, 1117, 1478, +1683, 1179, 1427, +1625, 1251, 1347, +1532, 1333, 1212, +1369, 1422, 929, +978, 1520, 0, +0, 1625, 0, +0, 1735, 0, +0, 1850, 0, +0, 1969, 0, +0, 2092, 0, +0, 2216, 0, +0, 2342, 0, +0, 2470, 0, +0, 2599, 0, +0, 2728, 0, +0, 2859, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1954, 965, 1715, +1952, 972, 1713, +1950, 981, 1710, +1947, 992, 1706, +1943, 1007, 1701, +1938, 1027, 1694, +1930, 1052, 1684, +1920, 1083, 1671, +1906, 1121, 1653, +1887, 1168, 1627, +1860, 1224, 1590, +1821, 1290, 1536, +1764, 1365, 1452, +1673, 1449, 1307, +1514, 1542, 989, +1139, 1642, 0, +0, 1749, 0, +0, 1861, 0, +0, 1978, 0, +0, 2098, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +2091, 1056, 1837, +2090, 1062, 1835, +2088, 1069, 1833, +2086, 1079, 1830, +2083, 1091, 1826, +2079, 1108, 1821, +2073, 1129, 1813, +2066, 1155, 1803, +2056, 1188, 1790, +2042, 1229, 1771, +2023, 1278, 1745, +1997, 1337, 1707, +1958, 1405, 1650, +1901, 1483, 1562, +1812, 1570, 1409, +1655, 1664, 1059, +1292, 1767, 0, +0, 1875, 0, +0, 1988, 0, +0, 2106, 0, +0, 2227, 0, +0, 2351, 0, +0, 2476, 0, +0, 2604, 0, +0, 2732, 0, +0, 2861, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2227, 1156, 1961, +2226, 1160, 1960, +2224, 1166, 1958, +2223, 1174, 1956, +2221, 1184, 1953, +2218, 1197, 1949, +2214, 1214, 1943, +2208, 1236, 1936, +2201, 1264, 1926, +2191, 1299, 1912, +2177, 1342, 1893, +2158, 1393, 1866, +2132, 1454, 1827, +2094, 1524, 1769, +2037, 1604, 1678, +1948, 1693, 1517, +1794, 1789, 1139, +1439, 1893, 0, +0, 2002, 0, +0, 2117, 0, +0, 2235, 0, +0, 2357, 0, +0, 2481, 0, +0, 2607, 0, +0, 2735, 0, +0, 2863, 0, +0, 2993, 0, +0, 3123, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3647, 0, +2361, 1261, 2087, +2361, 1265, 2086, +2360, 1270, 2085, +2358, 1276, 2083, +2357, 1284, 2081, +2355, 1295, 2078, +2352, 1309, 2074, +2348, 1327, 2068, +2342, 1349, 2061, +2335, 1378, 2050, +2325, 1415, 2036, +2312, 1459, 2017, +2293, 1512, 1989, +2266, 1574, 1949, +2228, 1646, 1890, +2172, 1728, 1797, +2084, 1818, 1631, +1931, 1916, 1227, +1581, 2021, 0, +0, 2131, 0, +0, 2246, 0, +0, 2365, 0, +0, 2488, 0, +0, 2612, 0, +0, 2738, 0, +0, 2866, 0, +0, 2995, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2495, 1373, 2215, +2495, 1376, 2214, +2494, 1379, 2213, +2493, 1384, 2212, +2492, 1391, 2210, +2490, 1399, 2208, +2488, 1410, 2205, +2485, 1424, 2201, +2481, 1443, 2195, +2476, 1467, 2187, +2469, 1497, 2177, +2459, 1534, 2163, +2445, 1579, 2143, +2427, 1634, 2115, +2400, 1698, 2074, +2362, 1771, 2014, +2306, 1854, 1919, +2219, 1945, 1749, +2066, 2044, 1323, +1721, 2149, 0, +0, 2261, 0, +0, 2376, 0, +0, 2496, 0, +0, 2619, 0, +0, 2743, 0, +0, 2870, 0, +0, 2998, 0, +0, 3127, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3649, 0, +2629, 1489, 2343, +2628, 1491, 2343, +2628, 1494, 2342, +2627, 1497, 2341, +2626, 1503, 2340, +2625, 1509, 2338, +2623, 1518, 2336, +2621, 1529, 2333, +2618, 1544, 2329, +2614, 1563, 2323, +2609, 1588, 2315, +2602, 1618, 2305, +2592, 1656, 2290, +2579, 1703, 2270, +2560, 1758, 2242, +2534, 1823, 2201, +2496, 1897, 2140, +2440, 1981, 2043, +2353, 2073, 1870, +2201, 2173, 1427, +1859, 2279, 0, +0, 2391, 0, +0, 2507, 0, +0, 2627, 0, +0, 2750, 0, +0, 2875, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +2762, 1608, 2473, +2762, 1610, 2473, +2761, 1612, 2472, +2761, 1615, 2471, +2760, 1619, 2470, +2759, 1624, 2469, +2758, 1631, 2467, +2756, 1640, 2465, +2754, 1652, 2462, +2751, 1667, 2458, +2747, 1686, 2452, +2742, 1711, 2444, +2735, 1742, 2434, +2725, 1781, 2419, +2712, 1828, 2399, +2693, 1884, 2370, +2667, 1950, 2329, +2629, 2025, 2268, +2573, 2109, 2170, +2486, 2202, 1993, +2335, 2302, 1536, +1996, 2409, 0, +0, 2521, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +2895, 1731, 2603, +2895, 1732, 2603, +2894, 1734, 2602, +2894, 1736, 2602, +2893, 1739, 2601, +2893, 1743, 2600, +2892, 1748, 2599, +2891, 1755, 2597, +2889, 1764, 2595, +2887, 1776, 2592, +2884, 1791, 2587, +2880, 1811, 2582, +2875, 1836, 2574, +2868, 1868, 2563, +2858, 1907, 2549, +2844, 1955, 2528, +2826, 2012, 2500, +2800, 2078, 2458, +2762, 2154, 2396, +2706, 2239, 2298, +2619, 2332, 2119, +2469, 2433, 1651, +2131, 2540, 0, +0, 2652, 0, +0, 2769, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3028, 1856, 2734, +3027, 1857, 2734, +3027, 1858, 2733, +3027, 1860, 2733, +3027, 1862, 2732, +3026, 1865, 2732, +3025, 1869, 2731, +3024, 1874, 2729, +3023, 1881, 2728, +3022, 1890, 2725, +3019, 1902, 2722, +3017, 1918, 2718, +3013, 1938, 2712, +3007, 1964, 2704, +3000, 1996, 2694, +2990, 2035, 2679, +2977, 2083, 2658, +2958, 2140, 2630, +2932, 2207, 2588, +2895, 2283, 2526, +2839, 2369, 2426, +2752, 2462, 2246, +2602, 2563, 1769, +2265, 2671, 0, +0, 2784, 0, +0, 2901, 0, +0, 3021, 0, +0, 3144, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +3160, 1982, 2865, +3160, 1983, 2865, +3160, 1984, 2864, +3160, 1985, 2864, +3159, 1987, 2864, +3159, 1989, 2863, +3158, 1992, 2862, +3158, 1996, 2861, +3157, 2002, 2860, +3156, 2009, 2858, +3154, 2018, 2856, +3152, 2030, 2853, +3149, 2046, 2849, +3145, 2066, 2843, +3140, 2092, 2835, +3133, 2124, 2824, +3123, 2164, 2810, +3109, 2212, 2789, +3091, 2270, 2760, +3065, 2337, 2719, +3027, 2414, 2656, +2972, 2499, 2556, +2885, 2593, 2375, +2735, 2695, 1890, +2399, 2802, 0, +0, 2915, 0, +0, 3032, 0, +0, 3153, 0, +0, 3276, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +3292, 2110, 2996, +3292, 2111, 2996, +3292, 2111, 2996, +3292, 2112, 2996, +3292, 2114, 2995, +3292, 2116, 2995, +3291, 2118, 2994, +3291, 2121, 2994, +3290, 2125, 2993, +3289, 2130, 2991, +3288, 2138, 2990, +3286, 2147, 2987, +3284, 2159, 2984, +3281, 2175, 2980, +3277, 2195, 2974, +3272, 2221, 2966, +3265, 2254, 2955, +3255, 2294, 2941, +3242, 2342, 2920, +3223, 2400, 2891, +3197, 2467, 2849, +3160, 2544, 2787, +3104, 2630, 2686, +3018, 2724, 2504, +2868, 2826, 2015, +2533, 2934, 0, +0, 3047, 0, +0, 3164, 0, +0, 3285, 0, +0, 3408, 0, +0, 3534, 0, +0, 3661, 0, +3425, 2239, 3128, +3425, 2240, 3127, +3425, 2240, 3127, +3425, 2241, 3127, +3424, 2242, 3127, +3424, 2243, 3127, +3424, 2245, 3126, +3424, 2247, 3126, +3423, 2250, 3125, +3422, 2254, 3124, +3421, 2260, 3123, +3420, 2267, 3121, +3419, 2276, 3119, +3417, 2289, 3115, +3414, 2305, 3111, +3410, 2325, 3105, +3404, 2351, 3097, +3397, 2384, 3087, +3387, 2424, 3072, +3374, 2473, 3051, +3355, 2531, 3022, +3329, 2598, 2980, +3292, 2675, 2918, +3237, 2761, 2817, +3150, 2856, 2634, +3000, 2957, 2141, +2666, 3065, 0, +0, 3178, 0, +0, 3296, 0, +0, 3417, 0, +0, 3540, 0, +0, 3666, 0, +3557, 2369, 3259, +3557, 2369, 3259, +3557, 2370, 3259, +3557, 2370, 3259, +3557, 2371, 3259, +3557, 2372, 3259, +3556, 2373, 3258, +3556, 2375, 3258, +3556, 2377, 3257, +3555, 2380, 3257, +3555, 2385, 3256, +3554, 2390, 3254, +3553, 2397, 3252, +3551, 2407, 3250, +3549, 2419, 3247, +3546, 2435, 3243, +3542, 2456, 3237, +3537, 2482, 3229, +3529, 2514, 3218, +3520, 2555, 3203, +3506, 2604, 3183, +3488, 2662, 3154, +3462, 2729, 3112, +3424, 2807, 3049, +3369, 2893, 2948, +3282, 2987, 2765, +3133, 3089, 2268, +2799, 3197, 0, +0, 3310, 0, +0, 3428, 0, +0, 3549, 0, +0, 3672, 0, +3689, 2499, 3391, +3689, 2499, 3391, +3689, 2500, 3391, +3689, 2500, 3391, +3689, 2501, 3391, +3689, 2501, 3390, +3689, 2502, 3390, +3689, 2504, 3390, +3688, 2506, 3390, +3688, 2508, 3389, +3687, 2511, 3388, +3687, 2515, 3387, +3686, 2521, 3386, +3685, 2528, 3384, +3683, 2537, 3382, +3681, 2550, 3379, +3678, 2566, 3374, +3674, 2586, 3369, +3669, 2613, 3361, +3662, 2645, 3350, +3652, 2686, 3335, +3639, 2735, 3314, +3620, 2793, 3285, +3594, 2861, 3243, +3556, 2938, 3180, +3501, 3024, 3079, +3415, 3119, 2896, +3265, 3221, 2397, +2931, 3329, 0, +0, 3442, 0, +0, 3560, 0, +0, 3681, 0, +3822, 2630, 3523, +3822, 2630, 3523, +3821, 2630, 3523, +3821, 2631, 3523, +3821, 2631, 3523, +3821, 2632, 3522, +3821, 2632, 3522, +3821, 2633, 3522, +3821, 2635, 3522, +3821, 2637, 3521, +3820, 2639, 3521, +3820, 2642, 3520, +3819, 2646, 3519, +3818, 2652, 3518, +3817, 2659, 3516, +3815, 2668, 3514, +3813, 2681, 3510, +3810, 2697, 3506, +3806, 2717, 3500, +3801, 2744, 3492, +3794, 2777, 3482, +3784, 2817, 3467, +3771, 2866, 3446, +3752, 2925, 3417, +3726, 2992, 3375, +3689, 3070, 3312, +3633, 3156, 3211, +3547, 3251, 3027, +3398, 3353, 2526, +3064, 3461, 0, +0, 3574, 0, +0, 3692, 0, +3954, 2761, 3655, +3954, 2761, 3655, +3954, 2761, 3655, +3954, 2762, 3655, +3954, 2762, 3655, +3954, 2762, 3654, +3953, 2763, 3654, +3953, 2764, 3654, +3953, 2765, 3654, +3953, 2766, 3654, +3953, 2768, 3653, +3952, 2770, 3653, +3952, 2773, 3652, +3951, 2777, 3651, +3950, 2783, 3650, +3949, 2790, 3648, +3947, 2800, 3645, +3945, 2812, 3642, +3942, 2828, 3638, +3938, 2849, 3632, +3933, 2875, 3624, +3926, 2908, 3614, +3916, 2949, 3599, +3903, 2998, 3578, +3884, 3056, 3549, +3858, 3124, 3507, +3821, 3202, 3444, +3766, 3288, 3343, +3679, 3383, 3158, +3530, 3485, 2656, +3196, 3593, 0, +0, 3706, 0, +4086, 2892, 3787, +4086, 2893, 3787, +4086, 2893, 3787, +4086, 2893, 3787, +4086, 2893, 3787, +4086, 2893, 3786, +4086, 2894, 3786, +4086, 2894, 3786, +4085, 2895, 3786, +4085, 2896, 3786, +4085, 2897, 3786, +4085, 2899, 3785, +4084, 2902, 3785, +4084, 2905, 3784, +4083, 2909, 3783, +4082, 2914, 3782, +4081, 2922, 3780, +4080, 2931, 3777, +4077, 2944, 3774, +4075, 2960, 3770, +4071, 2980, 3764, +4065, 3007, 3756, +4058, 3040, 3745, +4048, 3080, 3731, +4035, 3130, 3710, +4016, 3188, 3681, +3990, 3256, 3639, +3953, 3333, 3575, +3898, 3420, 3474, +3811, 3515, 3290, +3662, 3617, 2787, +3328, 3725, 0, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3024, 3919, +4095, 3025, 3919, +4095, 3025, 3918, +4095, 3025, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3918, +4095, 3029, 3918, +4095, 3031, 3917, +4095, 3033, 3917, +4095, 3036, 3916, +4095, 3040, 3915, +4095, 3046, 3914, +4095, 3053, 3912, +4095, 3063, 3909, +4095, 3075, 3906, +4095, 3091, 3902, +4095, 3112, 3896, +4095, 3138, 3888, +4095, 3171, 3877, +4095, 3212, 3863, +4095, 3261, 3842, +4095, 3320, 3813, +4095, 3388, 3771, +4085, 3465, 3707, +4030, 3552, 3606, +3943, 3647, 3422, +3794, 3749, 2918, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3157, 4050, +4095, 3157, 4050, +4095, 3158, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3161, 4050, +4095, 3163, 4049, +4095, 3165, 4049, +4095, 3168, 4048, +4095, 3172, 4047, +4095, 3178, 4046, +4095, 3185, 4044, +4095, 3195, 4041, +4095, 3207, 4038, +4095, 3223, 4034, +4095, 3244, 4028, +4095, 3270, 4020, +4095, 3303, 4009, +4095, 3344, 3995, +4095, 3393, 3974, +4095, 3452, 3945, +4095, 3520, 3903, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3779, 3553, +0, 606, 834, +0, 621, 819, +0, 640, 798, +0, 664, 769, +0, 695, 726, +0, 733, 662, +0, 779, 559, +0, 834, 370, +0, 899, 0, +0, 973, 0, +0, 1057, 0, +0, 1149, 0, +0, 1248, 0, +0, 1355, 0, +0, 1466, 0, +0, 1583, 0, +0, 1702, 0, +0, 1825, 0, +0, 1950, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3250, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 611, 856, +0, 626, 842, +0, 645, 822, +0, 669, 794, +0, 699, 753, +0, 737, 693, +0, 782, 598, +0, 837, 427, +0, 902, 2, +0, 976, 0, +0, 1059, 0, +0, 1150, 0, +0, 1250, 0, +0, 1356, 0, +0, 1467, 0, +0, 1583, 0, +0, 1703, 0, +0, 1825, 0, +0, 1950, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 618, 883, +0, 632, 870, +0, 651, 851, +0, 675, 825, +0, 705, 788, +0, 742, 732, +0, 787, 645, +0, 841, 495, +0, 905, 157, +0, 979, 0, +0, 1061, 0, +0, 1152, 0, +0, 1251, 0, +0, 1357, 0, +0, 1468, 0, +0, 1584, 0, +0, 1703, 0, +0, 1826, 0, +0, 1951, 0, +0, 2077, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +0, 627, 918, +0, 641, 905, +0, 659, 888, +0, 682, 864, +0, 712, 829, +0, 748, 779, +0, 793, 702, +0, 847, 572, +0, 910, 306, +0, 983, 0, +0, 1064, 0, +0, 1155, 0, +0, 1253, 0, +0, 1359, 0, +0, 1469, 0, +0, 1585, 0, +0, 1704, 0, +0, 1827, 0, +0, 1951, 0, +0, 2078, 0, +0, 2205, 0, +0, 2334, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +271, 638, 960, +198, 652, 948, +78, 670, 933, +0, 693, 911, +0, 721, 880, +0, 757, 835, +0, 801, 768, +0, 854, 657, +0, 916, 450, +0, 988, 0, +0, 1069, 0, +0, 1159, 0, +0, 1256, 0, +0, 1361, 0, +0, 1471, 0, +0, 1586, 0, +0, 1705, 0, +0, 1827, 0, +0, 1952, 0, +0, 2078, 0, +0, 2206, 0, +0, 2335, 0, +0, 2464, 0, +0, 2594, 0, +0, 2725, 0, +0, 2856, 0, +0, 2987, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +595, 653, 1011, +561, 667, 1000, +511, 684, 986, +434, 706, 967, +305, 734, 940, +43, 769, 901, +0, 812, 843, +0, 863, 752, +0, 924, 591, +0, 995, 210, +0, 1075, 0, +0, 1164, 0, +0, 1260, 0, +0, 1364, 0, +0, 1474, 0, +0, 1588, 0, +0, 1707, 0, +0, 1829, 0, +0, 1953, 0, +0, 2079, 0, +0, 2206, 0, +0, 2335, 0, +0, 2464, 0, +0, 2595, 0, +0, 2725, 0, +0, 2856, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +832, 672, 1071, +812, 685, 1062, +784, 702, 1050, +743, 723, 1033, +682, 750, 1010, +586, 784, 976, +413, 825, 928, +0, 875, 853, +0, 935, 729, +0, 1004, 483, +0, 1082, 0, +0, 1170, 0, +0, 1265, 0, +0, 1368, 0, +0, 1477, 0, +0, 1591, 0, +0, 1709, 0, +0, 1830, 0, +0, 1954, 0, +0, 2080, 0, +0, 2207, 0, +0, 2335, 0, +0, 2465, 0, +0, 2595, 0, +0, 2725, 0, +0, 2856, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3382, 0, +0, 3514, 0, +0, 3646, 0, +1029, 697, 1140, +1016, 709, 1133, +998, 725, 1122, +973, 745, 1108, +938, 771, 1089, +885, 803, 1061, +804, 843, 1021, +666, 891, 961, +375, 949, 866, +0, 1016, 698, +0, 1093, 282, +0, 1178, 0, +0, 1272, 0, +0, 1374, 0, +0, 1481, 0, +0, 1594, 0, +0, 1711, 0, +0, 1832, 0, +0, 1955, 0, +0, 2081, 0, +0, 2208, 0, +0, 2336, 0, +0, 2465, 0, +0, 2595, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1204, 728, 1220, +1195, 739, 1213, +1183, 754, 1205, +1167, 773, 1193, +1144, 797, 1176, +1111, 828, 1154, +1064, 866, 1121, +991, 912, 1074, +872, 967, 1002, +637, 1032, 883, +0, 1106, 652, +0, 1189, 0, +0, 1281, 0, +0, 1381, 0, +0, 1487, 0, +0, 1599, 0, +0, 1715, 0, +0, 1835, 0, +0, 1957, 0, +0, 2082, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1366, 766, 1308, +1360, 777, 1302, +1352, 790, 1295, +1340, 808, 1286, +1325, 830, 1272, +1303, 859, 1254, +1272, 894, 1228, +1228, 938, 1191, +1161, 990, 1137, +1052, 1052, 1052, +847, 1123, 905, +195, 1203, 583, +0, 1293, 0, +0, 1390, 0, +0, 1494, 0, +0, 1604, 0, +0, 1719, 0, +0, 1838, 0, +0, 1960, 0, +0, 2084, 0, +0, 2210, 0, +0, 2338, 0, +0, 2467, 0, +0, 2596, 0, +0, 2727, 0, +0, 2857, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +1519, 813, 1404, +1515, 822, 1399, +1509, 834, 1394, +1501, 850, 1386, +1490, 871, 1375, +1475, 897, 1361, +1454, 930, 1341, +1425, 970, 1312, +1383, 1019, 1271, +1319, 1077, 1209, +1216, 1145, 1110, +1029, 1222, 933, +509, 1308, 469, +0, 1402, 0, +0, 1504, 0, +0, 1612, 0, +0, 1725, 0, +0, 1843, 0, +0, 1963, 0, +0, 2087, 0, +0, 2213, 0, +0, 2340, 0, +0, 2468, 0, +0, 2597, 0, +0, 2727, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1666, 868, 1507, +1663, 877, 1504, +1659, 888, 1499, +1653, 902, 1493, +1645, 920, 1484, +1635, 944, 1473, +1620, 973, 1457, +1600, 1010, 1435, +1572, 1055, 1404, +1531, 1109, 1359, +1469, 1172, 1290, +1372, 1245, 1179, +1196, 1327, 967, +741, 1418, 252, +0, 1517, 0, +0, 1622, 0, +0, 1733, 0, +0, 1849, 0, +0, 1968, 0, +0, 2091, 0, +0, 2215, 0, +0, 2342, 0, +0, 2470, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1809, 933, 1616, +1807, 941, 1613, +1804, 950, 1610, +1800, 963, 1605, +1794, 979, 1599, +1787, 999, 1590, +1776, 1026, 1578, +1762, 1059, 1561, +1742, 1099, 1537, +1715, 1148, 1504, +1675, 1207, 1455, +1615, 1275, 1381, +1520, 1352, 1257, +1352, 1439, 1010, +936, 1533, 0, +0, 1635, 0, +0, 1743, 0, +0, 1857, 0, +0, 1974, 0, +0, 2095, 0, +0, 2219, 0, +0, 2344, 0, +0, 2472, 0, +0, 2600, 0, +0, 2729, 0, +0, 2859, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1949, 1008, 1730, +1948, 1014, 1728, +1946, 1022, 1725, +1943, 1033, 1722, +1938, 1047, 1717, +1933, 1065, 1710, +1925, 1088, 1701, +1915, 1116, 1688, +1901, 1152, 1670, +1882, 1196, 1646, +1855, 1249, 1610, +1815, 1312, 1559, +1757, 1383, 1479, +1664, 1465, 1344, +1501, 1555, 1061, +1110, 1652, 0, +0, 1757, 0, +0, 1867, 0, +0, 1983, 0, +0, 2102, 0, +0, 2224, 0, +0, 2348, 0, +0, 2474, 0, +0, 2602, 0, +0, 2731, 0, +0, 2860, 0, +0, 2991, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2087, 1092, 1849, +2086, 1097, 1847, +2085, 1104, 1845, +2082, 1113, 1842, +2079, 1124, 1838, +2075, 1140, 1833, +2070, 1159, 1826, +2062, 1184, 1816, +2052, 1215, 1803, +2039, 1254, 1785, +2019, 1300, 1759, +1992, 1357, 1722, +1954, 1422, 1668, +1896, 1497, 1584, +1805, 1581, 1439, +1646, 1674, 1121, +1271, 1774, 0, +0, 1881, 0, +0, 1993, 0, +0, 2110, 0, +0, 2230, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2224, 1184, 1970, +2223, 1189, 1969, +2222, 1194, 1967, +2220, 1201, 1965, +2218, 1211, 1962, +2215, 1224, 1958, +2211, 1240, 1953, +2206, 1261, 1945, +2198, 1287, 1936, +2188, 1320, 1922, +2175, 1361, 1903, +2156, 1410, 1877, +2129, 1469, 1839, +2090, 1537, 1782, +2033, 1615, 1694, +1944, 1702, 1541, +1787, 1797, 1191, +1424, 1899, 0, +0, 2007, 0, +0, 2121, 0, +0, 2238, 0, +0, 2359, 0, +0, 2483, 0, +0, 2608, 0, +0, 2736, 0, +0, 2864, 0, +0, 2993, 0, +0, 3123, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2359, 1284, 2094, +2359, 1288, 2093, +2358, 1292, 2092, +2357, 1298, 2090, +2355, 1306, 2088, +2353, 1316, 2085, +2350, 1329, 2081, +2346, 1346, 2075, +2340, 1368, 2068, +2333, 1396, 2058, +2323, 1431, 2044, +2309, 1474, 2025, +2291, 1525, 1998, +2264, 1586, 1959, +2226, 1656, 1901, +2169, 1736, 1810, +2080, 1825, 1649, +1926, 1921, 1271, +1571, 2025, 0, +0, 2135, 0, +0, 2249, 0, +0, 2368, 0, +0, 2489, 0, +0, 2613, 0, +0, 2739, 0, +0, 2867, 0, +0, 2995, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2494, 1391, 2220, +2493, 1393, 2219, +2493, 1397, 2218, +2492, 1402, 2217, +2491, 1408, 2215, +2489, 1416, 2213, +2487, 1427, 2210, +2484, 1441, 2206, +2480, 1459, 2200, +2474, 1482, 2193, +2467, 1511, 2183, +2457, 1547, 2168, +2444, 1591, 2149, +2425, 1644, 2121, +2398, 1706, 2082, +2361, 1779, 2022, +2304, 1860, 1929, +2216, 1950, 1763, +2063, 2048, 1359, +1714, 2153, 0, +0, 2263, 0, +0, 2378, 0, +0, 2498, 0, +0, 2620, 0, +0, 2744, 0, +0, 2871, 0, +0, 2998, 0, +0, 3127, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +2628, 1503, 2347, +2627, 1505, 2347, +2627, 1508, 2346, +2626, 1511, 2345, +2625, 1516, 2344, +2624, 1523, 2342, +2622, 1531, 2340, +2620, 1542, 2337, +2617, 1557, 2333, +2613, 1575, 2327, +2608, 1599, 2319, +2601, 1629, 2309, +2591, 1666, 2295, +2577, 1711, 2275, +2559, 1766, 2247, +2532, 1830, 2207, +2495, 1903, 2146, +2438, 1986, 2051, +2351, 2077, 1881, +2199, 2176, 1456, +1853, 2281, 0, +0, 2393, 0, +0, 2509, 0, +0, 2628, 0, +0, 2751, 0, +0, 2875, 0, +0, 3002, 0, +0, 3130, 0, +0, 3259, 0, +0, 3388, 0, +0, 3519, 0, +0, 3650, 0, +2761, 1619, 2476, +2761, 1621, 2476, +2760, 1623, 2475, +2760, 1626, 2474, +2759, 1630, 2473, +2758, 1635, 2472, +2757, 1641, 2470, +2756, 1650, 2468, +2753, 1661, 2465, +2750, 1676, 2461, +2747, 1695, 2455, +2741, 1720, 2447, +2734, 1750, 2437, +2724, 1788, 2422, +2711, 1835, 2402, +2692, 1890, 2374, +2666, 1955, 2333, +2628, 2029, 2272, +2572, 2113, 2176, +2485, 2205, 2002, +2333, 2305, 1559, +1991, 2411, 0, +0, 2523, 0, +0, 2639, 0, +0, 2759, 0, +0, 2882, 0, +0, 3007, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3520, 0, +0, 3651, 0, +2894, 1739, 2605, +2894, 1740, 2605, +2894, 1742, 2605, +2893, 1744, 2604, +2893, 1747, 2603, +2892, 1751, 2602, +2891, 1756, 2601, +2890, 1763, 2599, +2888, 1772, 2597, +2886, 1784, 2594, +2883, 1799, 2590, +2879, 1818, 2584, +2874, 1843, 2576, +2867, 1874, 2566, +2857, 1913, 2551, +2844, 1960, 2531, +2825, 2016, 2502, +2799, 2082, 2461, +2761, 2157, 2400, +2705, 2241, 2302, +2618, 2334, 2125, +2468, 2434, 1668, +2128, 2541, 0, +0, 2653, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +3027, 1862, 2735, +3027, 1863, 2735, +3027, 1864, 2735, +3026, 1866, 2735, +3026, 1868, 2734, +3026, 1871, 2733, +3025, 1875, 2732, +3024, 1880, 2731, +3023, 1887, 2729, +3021, 1896, 2727, +3019, 1908, 2724, +3016, 1924, 2720, +3012, 1943, 2714, +3007, 1969, 2706, +3000, 2000, 2695, +2990, 2039, 2681, +2976, 2087, 2660, +2958, 2144, 2632, +2932, 2210, 2590, +2894, 2286, 2528, +2838, 2371, 2430, +2752, 2464, 2251, +2601, 2565, 1783, +2263, 2672, 0, +0, 2784, 0, +0, 2901, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +3160, 1987, 2866, +3160, 1988, 2866, +3159, 1989, 2866, +3159, 1990, 2865, +3159, 1992, 2865, +3159, 1994, 2864, +3158, 1997, 2864, +3157, 2001, 2863, +3157, 2006, 2861, +3155, 2013, 2860, +3154, 2023, 2857, +3152, 2035, 2854, +3149, 2050, 2850, +3145, 2070, 2844, +3139, 2096, 2836, +3132, 2128, 2826, +3122, 2167, 2811, +3109, 2215, 2791, +3090, 2272, 2762, +3064, 2339, 2720, +3027, 2415, 2658, +2971, 2501, 2558, +2884, 2594, 2378, +2734, 2696, 1901, +2397, 2803, 0, +0, 2916, 0, +0, 3033, 0, +0, 3153, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +3292, 2114, 2997, +3292, 2114, 2997, +3292, 2115, 2997, +3292, 2116, 2997, +3292, 2117, 2996, +3291, 2119, 2996, +3291, 2121, 2995, +3291, 2124, 2995, +3290, 2128, 2994, +3289, 2134, 2992, +3288, 2141, 2990, +3286, 2150, 2988, +3284, 2162, 2985, +3281, 2178, 2981, +3277, 2198, 2975, +3272, 2224, 2967, +3265, 2256, 2956, +3255, 2296, 2942, +3241, 2344, 2921, +3223, 2402, 2892, +3197, 2469, 2851, +3159, 2546, 2788, +3104, 2631, 2688, +3017, 2725, 2507, +2867, 2827, 2023, +2531, 2934, 0, +0, 3047, 0, +0, 3164, 0, +0, 3285, 0, +0, 3408, 0, +0, 3534, 0, +0, 3661, 0, +3425, 2242, 3128, +3425, 2242, 3128, +3425, 2243, 3128, +3424, 2244, 3128, +3424, 2245, 3128, +3424, 2246, 3127, +3424, 2248, 3127, +3423, 2250, 3126, +3423, 2253, 3126, +3422, 2257, 3125, +3421, 2262, 3123, +3420, 2270, 3122, +3418, 2279, 3119, +3416, 2291, 3116, +3413, 2307, 3112, +3410, 2327, 3106, +3404, 2353, 3098, +3397, 2386, 3087, +3387, 2426, 3073, +3374, 2474, 3052, +3355, 2532, 3023, +3329, 2600, 2981, +3292, 2676, 2919, +3236, 2762, 2818, +3150, 2856, 2636, +3000, 2958, 2147, +2665, 3066, 0, +0, 3179, 0, +0, 3296, 0, +0, 3417, 0, +0, 3540, 0, +0, 3666, 0, +3557, 2371, 3260, +3557, 2371, 3260, +3557, 2372, 3260, +3557, 2372, 3259, +3557, 2373, 3259, +3557, 2374, 3259, +3556, 2375, 3259, +3556, 2377, 3258, +3556, 2379, 3258, +3555, 2382, 3257, +3554, 2387, 3256, +3554, 2392, 3255, +3552, 2399, 3253, +3551, 2409, 3251, +3549, 2421, 3247, +3546, 2437, 3243, +3542, 2457, 3237, +3537, 2483, 3230, +3529, 2516, 3219, +3520, 2556, 3204, +3506, 2605, 3183, +3488, 2663, 3154, +3461, 2730, 3113, +3424, 2807, 3050, +3369, 2894, 2949, +3282, 2988, 2766, +3133, 3090, 2273, +2798, 3197, 0, +0, 3311, 0, +0, 3428, 0, +0, 3549, 0, +0, 3672, 0, +3689, 2501, 3391, +3689, 2501, 3391, +3689, 2501, 3391, +3689, 2502, 3391, +3689, 2502, 3391, +3689, 2503, 3391, +3689, 2504, 3391, +3689, 2505, 3390, +3688, 2507, 3390, +3688, 2509, 3389, +3687, 2513, 3389, +3687, 2517, 3388, +3686, 2522, 3386, +3685, 2529, 3385, +3683, 2539, 3382, +3681, 2551, 3379, +3678, 2567, 3375, +3674, 2588, 3369, +3669, 2614, 3361, +3662, 2646, 3350, +3652, 2687, 3336, +3638, 2736, 3315, +3620, 2794, 3286, +3594, 2862, 3244, +3556, 2939, 3181, +3501, 3025, 3080, +3414, 3119, 2897, +3265, 3221, 2400, +2931, 3329, 0, +0, 3442, 0, +0, 3560, 0, +0, 3681, 0, +3821, 2631, 3523, +3821, 2631, 3523, +3821, 2632, 3523, +3821, 2632, 3523, +3821, 2632, 3523, +3821, 2633, 3523, +3821, 2634, 3523, +3821, 2635, 3522, +3821, 2636, 3522, +3820, 2638, 3522, +3820, 2640, 3521, +3820, 2643, 3520, +3819, 2647, 3519, +3818, 2653, 3518, +3817, 2660, 3516, +3815, 2669, 3514, +3813, 2682, 3511, +3810, 2698, 3506, +3806, 2718, 3501, +3801, 2745, 3493, +3794, 2777, 3482, +3784, 2818, 3467, +3771, 2867, 3447, +3752, 2925, 3418, +3726, 2993, 3375, +3689, 3070, 3312, +3633, 3157, 3211, +3547, 3251, 3028, +3397, 3353, 2529, +3063, 3461, 0, +0, 3574, 0, +0, 3692, 0, +3954, 2762, 3655, +3954, 2762, 3655, +3954, 2762, 3655, +3954, 2762, 3655, +3954, 2763, 3655, +3953, 2763, 3655, +3953, 2764, 3655, +3953, 2765, 3654, +3953, 2766, 3654, +3953, 2767, 3654, +3953, 2769, 3653, +3952, 2771, 3653, +3952, 2774, 3652, +3951, 2778, 3651, +3950, 2784, 3650, +3949, 2791, 3648, +3947, 2800, 3646, +3945, 2813, 3643, +3942, 2829, 3638, +3938, 2850, 3632, +3933, 2876, 3625, +3926, 2909, 3614, +3916, 2949, 3599, +3903, 2998, 3578, +3884, 3057, 3549, +3858, 3125, 3507, +3821, 3202, 3444, +3765, 3288, 3343, +3679, 3383, 3159, +3530, 3485, 2658, +3196, 3593, 0, +0, 3706, 0, +4086, 2893, 3787, +4086, 2893, 3787, +4086, 2893, 3787, +4086, 2893, 3787, +4086, 2894, 3787, +4086, 2894, 3787, +4086, 2894, 3787, +4086, 2895, 3786, +4085, 2896, 3786, +4085, 2897, 3786, +4085, 2898, 3786, +4085, 2900, 3785, +4084, 2902, 3785, +4084, 2905, 3784, +4083, 2909, 3783, +4082, 2915, 3782, +4081, 2922, 3780, +4080, 2932, 3778, +4077, 2944, 3774, +4074, 2960, 3770, +4071, 2981, 3764, +4065, 3007, 3756, +4058, 3040, 3746, +4048, 3081, 3731, +4035, 3130, 3710, +4016, 3188, 3681, +3990, 3256, 3639, +3953, 3334, 3576, +3898, 3420, 3475, +3811, 3515, 3290, +3662, 3617, 2788, +3328, 3725, 0, +4095, 3024, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3026, 3918, +4095, 3026, 3918, +4095, 3027, 3918, +4095, 3028, 3918, +4095, 3030, 3918, +4095, 3031, 3917, +4095, 3034, 3917, +4095, 3037, 3916, +4095, 3041, 3915, +4095, 3046, 3914, +4095, 3054, 3912, +4095, 3063, 3910, +4095, 3076, 3906, +4095, 3092, 3902, +4095, 3113, 3896, +4095, 3139, 3888, +4095, 3172, 3878, +4095, 3212, 3863, +4095, 3262, 3842, +4095, 3320, 3813, +4095, 3388, 3771, +4085, 3466, 3708, +4030, 3552, 3606, +3943, 3647, 3422, +3794, 3749, 2919, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3156, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3158, 4050, +4095, 3158, 4050, +4095, 3159, 4050, +4095, 3160, 4050, +4095, 3161, 4050, +4095, 3163, 4049, +4095, 3165, 4049, +4095, 3168, 4048, +4095, 3173, 4047, +4095, 3178, 4046, +4095, 3185, 4044, +4095, 3195, 4041, +4095, 3207, 4038, +4095, 3224, 4034, +4095, 3244, 4028, +4095, 3271, 4020, +4095, 3304, 4009, +4095, 3344, 3995, +4095, 3393, 3974, +4095, 3452, 3945, +4095, 3520, 3903, +4095, 3597, 3839, +4095, 3684, 3738, +4076, 3779, 3554, +0, 723, 961, +0, 734, 949, +0, 749, 934, +0, 769, 912, +0, 793, 881, +0, 824, 837, +0, 862, 769, +0, 908, 660, +0, 964, 453, +0, 1029, 0, +0, 1104, 0, +0, 1187, 0, +0, 1280, 0, +0, 1380, 0, +0, 1486, 0, +0, 1598, 0, +0, 1714, 0, +0, 1834, 0, +0, 1957, 0, +0, 2082, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +0, 727, 977, +0, 738, 966, +0, 753, 951, +0, 772, 930, +0, 796, 901, +0, 827, 858, +0, 865, 794, +0, 911, 691, +0, 966, 502, +0, 1031, 0, +0, 1105, 0, +0, 1189, 0, +0, 1281, 0, +0, 1380, 0, +0, 1487, 0, +0, 1598, 0, +0, 1715, 0, +0, 1835, 0, +0, 1957, 0, +0, 2082, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +0, 732, 998, +0, 743, 988, +0, 758, 974, +0, 777, 954, +0, 801, 926, +0, 831, 886, +0, 869, 825, +0, 915, 730, +0, 969, 560, +0, 1034, 134, +0, 1108, 0, +0, 1191, 0, +0, 1282, 0, +0, 1382, 0, +0, 1488, 0, +0, 1599, 0, +0, 1715, 0, +0, 1835, 0, +0, 1958, 0, +0, 2082, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +0, 739, 1025, +0, 750, 1015, +0, 764, 1002, +0, 783, 983, +0, 807, 957, +0, 837, 920, +0, 874, 864, +0, 919, 777, +0, 973, 627, +0, 1037, 289, +0, 1111, 0, +0, 1193, 0, +0, 1284, 0, +0, 1383, 0, +0, 1489, 0, +0, 1600, 0, +0, 1716, 0, +0, 1836, 0, +0, 1958, 0, +0, 2083, 0, +0, 2209, 0, +0, 2337, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +0, 748, 1059, +0, 759, 1050, +0, 773, 1037, +0, 791, 1020, +0, 815, 996, +0, 844, 962, +0, 880, 911, +0, 925, 834, +0, 979, 704, +0, 1042, 438, +0, 1115, 0, +0, 1197, 0, +0, 1287, 0, +0, 1386, 0, +0, 1491, 0, +0, 1602, 0, +0, 1717, 0, +0, 1836, 0, +0, 1959, 0, +0, 2083, 0, +0, 2210, 0, +0, 2338, 0, +0, 2466, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3119, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +450, 760, 1100, +403, 770, 1092, +330, 784, 1080, +210, 802, 1065, +0, 825, 1043, +0, 853, 1012, +0, 889, 967, +0, 933, 900, +0, 986, 790, +0, 1048, 582, +0, 1120, 0, +0, 1201, 0, +0, 1291, 0, +0, 1388, 0, +0, 1493, 0, +0, 1603, 0, +0, 1718, 0, +0, 1837, 0, +0, 1960, 0, +0, 2084, 0, +0, 2210, 0, +0, 2338, 0, +0, 2467, 0, +0, 2596, 0, +0, 2726, 0, +0, 2857, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +751, 775, 1150, +727, 785, 1143, +693, 799, 1132, +643, 816, 1119, +566, 838, 1099, +437, 866, 1072, +175, 901, 1033, +0, 944, 975, +0, 995, 884, +0, 1056, 723, +0, 1127, 342, +0, 1207, 0, +0, 1296, 0, +0, 1392, 0, +0, 1496, 0, +0, 1606, 0, +0, 1720, 0, +0, 1839, 0, +0, 1961, 0, +0, 2085, 0, +0, 2211, 0, +0, 2338, 0, +0, 2467, 0, +0, 2597, 0, +0, 2727, 0, +0, 2857, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3514, 0, +0, 3646, 0, +978, 795, 1209, +964, 805, 1203, +944, 817, 1194, +916, 834, 1182, +875, 855, 1165, +814, 882, 1142, +718, 916, 1108, +545, 957, 1060, +108, 1008, 985, +0, 1067, 862, +0, 1136, 615, +0, 1215, 0, +0, 1302, 0, +0, 1397, 0, +0, 1500, 0, +0, 1609, 0, +0, 1723, 0, +0, 1841, 0, +0, 1962, 0, +0, 2086, 0, +0, 2212, 0, +0, 2339, 0, +0, 2468, 0, +0, 2597, 0, +0, 2727, 0, +0, 2858, 0, +0, 2988, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1170, 820, 1278, +1161, 829, 1273, +1148, 841, 1265, +1130, 857, 1255, +1105, 877, 1240, +1070, 903, 1221, +1017, 935, 1193, +936, 975, 1153, +798, 1023, 1093, +507, 1081, 998, +0, 1148, 830, +0, 1225, 414, +0, 1310, 0, +0, 1404, 0, +0, 1506, 0, +0, 1613, 0, +0, 1726, 0, +0, 1843, 0, +0, 1964, 0, +0, 2087, 0, +0, 2213, 0, +0, 2340, 0, +0, 2468, 0, +0, 2597, 0, +0, 2727, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1343, 851, 1356, +1336, 860, 1352, +1327, 871, 1345, +1316, 886, 1337, +1299, 905, 1325, +1276, 929, 1308, +1244, 960, 1286, +1196, 998, 1253, +1123, 1044, 1206, +1004, 1099, 1134, +769, 1164, 1015, +0, 1238, 784, +0, 1321, 0, +0, 1413, 0, +0, 1513, 0, +0, 1619, 0, +0, 1731, 0, +0, 1847, 0, +0, 1967, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +1502, 890, 1444, +1498, 898, 1440, +1492, 909, 1434, +1484, 922, 1427, +1472, 940, 1418, +1457, 962, 1404, +1435, 991, 1386, +1405, 1026, 1360, +1360, 1070, 1323, +1293, 1122, 1269, +1184, 1184, 1184, +979, 1255, 1037, +327, 1335, 715, +0, 1425, 0, +0, 1522, 0, +0, 1626, 0, +0, 1736, 0, +0, 1851, 0, +0, 1970, 0, +0, 2092, 0, +0, 2216, 0, +0, 2343, 0, +0, 2470, 0, +0, 2599, 0, +0, 2728, 0, +0, 2859, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1654, 938, 1539, +1651, 945, 1536, +1647, 954, 1532, +1641, 967, 1526, +1633, 982, 1518, +1622, 1003, 1507, +1607, 1029, 1493, +1586, 1062, 1473, +1557, 1102, 1444, +1515, 1151, 1403, +1451, 1209, 1341, +1349, 1277, 1243, +1161, 1354, 1065, +641, 1440, 601, +0, 1534, 0, +0, 1636, 0, +0, 1744, 0, +0, 1857, 0, +0, 1975, 0, +0, 2096, 0, +0, 2219, 0, +0, 2345, 0, +0, 2472, 0, +0, 2600, 0, +0, 2729, 0, +0, 2859, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1801, 994, 1642, +1798, 1000, 1639, +1795, 1009, 1636, +1791, 1020, 1631, +1785, 1034, 1625, +1778, 1052, 1617, +1767, 1076, 1605, +1752, 1105, 1589, +1732, 1142, 1567, +1704, 1187, 1536, +1663, 1241, 1491, +1601, 1304, 1423, +1504, 1377, 1311, +1328, 1459, 1099, +874, 1550, 384, +0, 1649, 0, +0, 1754, 0, +0, 1865, 0, +0, 1981, 0, +0, 2100, 0, +0, 2223, 0, +0, 2347, 0, +0, 2474, 0, +0, 2602, 0, +0, 2731, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1943, 1060, 1750, +1941, 1066, 1748, +1939, 1073, 1746, +1936, 1082, 1742, +1932, 1095, 1737, +1926, 1111, 1731, +1919, 1132, 1722, +1908, 1158, 1710, +1894, 1191, 1693, +1874, 1231, 1670, +1847, 1281, 1636, +1807, 1339, 1587, +1747, 1407, 1513, +1652, 1484, 1389, +1484, 1571, 1142, +1068, 1665, 0, +0, 1767, 0, +0, 1876, 0, +0, 1989, 0, +0, 2106, 0, +0, 2227, 0, +0, 2351, 0, +0, 2477, 0, +0, 2604, 0, +0, 2732, 0, +0, 2861, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +2083, 1136, 1864, +2082, 1140, 1862, +2080, 1146, 1860, +2078, 1155, 1858, +2075, 1165, 1854, +2071, 1179, 1849, +2065, 1197, 1842, +2058, 1220, 1833, +2047, 1249, 1820, +2033, 1284, 1802, +2014, 1328, 1778, +1987, 1381, 1743, +1947, 1444, 1691, +1889, 1516, 1611, +1796, 1597, 1476, +1633, 1687, 1193, +1242, 1784, 0, +0, 1889, 0, +0, 1999, 0, +0, 2115, 0, +0, 2234, 0, +0, 2356, 0, +0, 2480, 0, +0, 2606, 0, +0, 2734, 0, +0, 2863, 0, +0, 2993, 0, +0, 3123, 0, +0, 3253, 0, +0, 3385, 0, +0, 3516, 0, +0, 3647, 0, +2221, 1220, 1982, +2220, 1224, 1981, +2218, 1229, 1979, +2217, 1236, 1977, +2214, 1245, 1974, +2211, 1257, 1970, +2207, 1272, 1965, +2202, 1291, 1958, +2195, 1316, 1948, +2185, 1347, 1935, +2171, 1386, 1917, +2151, 1433, 1891, +2124, 1489, 1854, +2086, 1554, 1800, +2028, 1629, 1716, +1937, 1713, 1571, +1778, 1806, 1253, +1403, 1906, 0, +0, 2013, 0, +0, 2125, 0, +0, 2242, 0, +0, 2362, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2357, 1313, 2103, +2356, 1316, 2102, +2355, 1321, 2101, +2354, 1326, 2099, +2352, 1334, 2097, +2350, 1343, 2094, +2347, 1356, 2090, +2343, 1372, 2085, +2338, 1393, 2078, +2330, 1419, 2068, +2320, 1452, 2054, +2307, 1493, 2035, +2288, 1543, 2009, +2261, 1601, 1971, +2222, 1669, 1915, +2165, 1747, 1826, +2076, 1834, 1673, +1919, 1929, 1323, +1556, 2031, 0, +0, 2139, 0, +0, 2253, 0, +0, 2370, 0, +0, 2491, 0, +0, 2615, 0, +0, 2741, 0, +0, 2868, 0, +0, 2996, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2492, 1414, 2227, +2491, 1416, 2226, +2491, 1420, 2225, +2490, 1424, 2224, +2489, 1430, 2222, +2487, 1438, 2220, +2485, 1448, 2217, +2482, 1461, 2213, +2478, 1479, 2208, +2472, 1501, 2200, +2465, 1528, 2190, +2455, 1563, 2176, +2442, 1606, 2157, +2423, 1657, 2130, +2396, 1718, 2091, +2358, 1788, 2033, +2301, 1868, 1942, +2213, 1957, 1782, +2058, 2053, 1403, +1703, 2157, 0, +0, 2267, 0, +0, 2381, 0, +0, 2500, 0, +0, 2621, 0, +0, 2745, 0, +0, 2871, 0, +0, 2999, 0, +0, 3128, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +2626, 1521, 2353, +2626, 1523, 2352, +2625, 1526, 2351, +2625, 1529, 2350, +2624, 1534, 2349, +2623, 1540, 2347, +2621, 1548, 2345, +2619, 1559, 2342, +2616, 1573, 2338, +2612, 1591, 2332, +2607, 1614, 2325, +2599, 1643, 2315, +2589, 1679, 2301, +2576, 1723, 2281, +2557, 1776, 2253, +2531, 1839, 2214, +2493, 1911, 2154, +2436, 1992, 2061, +2348, 2082, 1895, +2195, 2180, 1491, +1846, 2285, 0, +0, 2395, 0, +0, 2511, 0, +0, 2630, 0, +0, 2752, 0, +0, 2876, 0, +0, 3003, 0, +0, 3130, 0, +0, 3259, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +2760, 1633, 2480, +2760, 1635, 2479, +2759, 1637, 2479, +2759, 1640, 2478, +2758, 1643, 2477, +2757, 1648, 2476, +2756, 1655, 2474, +2755, 1663, 2472, +2752, 1674, 2469, +2749, 1689, 2465, +2745, 1707, 2459, +2740, 1731, 2451, +2733, 1761, 2441, +2723, 1798, 2427, +2710, 1843, 2407, +2691, 1898, 2379, +2664, 1962, 2339, +2627, 2035, 2278, +2571, 2118, 2183, +2483, 2209, 2013, +2331, 2308, 1588, +1986, 2414, 0, +0, 2525, 0, +0, 2641, 0, +0, 2760, 0, +0, 2883, 0, +0, 3007, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +2893, 1750, 2608, +2893, 1751, 2608, +2893, 1753, 2608, +2893, 1755, 2607, +2892, 1758, 2606, +2891, 1762, 2605, +2891, 1767, 2604, +2889, 1773, 2602, +2888, 1782, 2600, +2886, 1793, 2597, +2883, 1808, 2593, +2879, 1827, 2587, +2873, 1852, 2579, +2866, 1882, 2569, +2856, 1920, 2554, +2843, 1967, 2534, +2824, 2022, 2506, +2798, 2087, 2465, +2760, 2161, 2404, +2704, 2245, 2308, +2617, 2337, 2134, +2465, 2437, 1691, +2123, 2543, 0, +0, 2655, 0, +0, 2771, 0, +0, 2891, 0, +0, 3014, 0, +0, 3139, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3652, 0, +3026, 1870, 2738, +3026, 1871, 2737, +3026, 1873, 2737, +3026, 1874, 2737, +3025, 1876, 2736, +3025, 1879, 2735, +3024, 1883, 2735, +3023, 1888, 2733, +3022, 1895, 2732, +3021, 1904, 2729, +3018, 1916, 2726, +3015, 1931, 2722, +3012, 1950, 2716, +3006, 1975, 2708, +2999, 2006, 2698, +2989, 2045, 2683, +2976, 2092, 2663, +2957, 2148, 2635, +2931, 2214, 2593, +2893, 2289, 2532, +2838, 2373, 2434, +2750, 2466, 2258, +2600, 2567, 1800, +2260, 2673, 0, +0, 2786, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +3159, 1993, 2868, +3159, 1994, 2868, +3159, 1995, 2867, +3159, 1996, 2867, +3159, 1998, 2867, +3158, 2000, 2866, +3158, 2003, 2865, +3157, 2007, 2864, +3156, 2012, 2863, +3155, 2019, 2861, +3153, 2028, 2859, +3151, 2040, 2856, +3148, 2056, 2852, +3144, 2075, 2846, +3139, 2101, 2838, +3132, 2132, 2827, +3122, 2172, 2813, +3109, 2219, 2793, +3090, 2276, 2764, +3064, 2342, 2723, +3026, 2418, 2661, +2971, 2503, 2562, +2884, 2596, 2383, +2733, 2697, 1915, +2395, 2804, 0, +0, 2917, 0, +0, 3033, 0, +0, 3154, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +3292, 2119, 2998, +3292, 2119, 2998, +3292, 2120, 2998, +3292, 2121, 2998, +3291, 2122, 2997, +3291, 2124, 2997, +3291, 2126, 2997, +3290, 2129, 2996, +3290, 2133, 2995, +3289, 2138, 2994, +3287, 2145, 2992, +3286, 2155, 2989, +3284, 2167, 2986, +3281, 2182, 2982, +3277, 2202, 2976, +3272, 2228, 2968, +3264, 2260, 2958, +3255, 2299, 2943, +3241, 2347, 2923, +3222, 2405, 2894, +3196, 2471, 2852, +3159, 2548, 2790, +3103, 2633, 2691, +3017, 2727, 2510, +2866, 2828, 2033, +2530, 2935, 0, +0, 3048, 0, +0, 3165, 0, +0, 3285, 0, +0, 3409, 0, +0, 3534, 0, +0, 3661, 0, +3424, 2246, 3129, +3424, 2246, 3129, +3424, 2246, 3129, +3424, 2247, 3129, +3424, 2248, 3129, +3424, 2249, 3128, +3424, 2251, 3128, +3423, 2253, 3127, +3423, 2257, 3127, +3422, 2261, 3126, +3421, 2266, 3124, +3420, 2273, 3123, +3418, 2282, 3120, +3416, 2294, 3117, +3413, 2310, 3113, +3409, 2330, 3107, +3404, 2356, 3099, +3397, 2388, 3088, +3387, 2428, 3074, +3374, 2477, 3053, +3355, 2534, 3024, +3329, 2601, 2983, +3291, 2678, 2920, +3236, 2763, 2820, +3149, 2857, 2639, +2999, 2959, 2155, +2663, 3066, 0, +0, 3179, 0, +0, 3297, 0, +0, 3417, 0, +0, 3540, 0, +0, 3666, 0, +3557, 2374, 3260, +3557, 2374, 3260, +3557, 2374, 3260, +3557, 2375, 3260, +3556, 2376, 3260, +3556, 2377, 3260, +3556, 2378, 3259, +3556, 2380, 3259, +3555, 2382, 3259, +3555, 2385, 3258, +3554, 2389, 3257, +3553, 2395, 3255, +3552, 2402, 3254, +3551, 2411, 3251, +3548, 2423, 3248, +3546, 2439, 3244, +3542, 2459, 3238, +3536, 2485, 3230, +3529, 2518, 3220, +3519, 2558, 3205, +3506, 2607, 3184, +3487, 2664, 3155, +3461, 2732, 3114, +3424, 2808, 3051, +3368, 2894, 2950, +3282, 2989, 2768, +3132, 3090, 2279, +2797, 3198, 0, +0, 3311, 0, +0, 3428, 0, +0, 3549, 0, +0, 3672, 0, +3689, 2503, 3392, +3689, 2503, 3392, +3689, 2503, 3392, +3689, 2504, 3392, +3689, 2504, 3392, +3689, 2505, 3391, +3689, 2506, 3391, +3688, 2507, 3391, +3688, 2509, 3390, +3688, 2511, 3390, +3687, 2515, 3389, +3687, 2519, 3388, +3686, 2524, 3387, +3684, 2531, 3385, +3683, 2541, 3383, +3681, 2553, 3380, +3678, 2569, 3375, +3674, 2589, 3369, +3669, 2615, 3362, +3661, 2648, 3351, +3652, 2688, 3336, +3638, 2737, 3316, +3620, 2795, 3287, +3594, 2863, 3245, +3556, 2940, 3182, +3501, 3026, 3081, +3414, 3120, 2898, +3265, 3222, 2405, +2930, 3330, 0, +0, 3443, 0, +0, 3560, 0, +0, 3681, 0, +3821, 2633, 3524, +3821, 2633, 3523, +3821, 2633, 3523, +3821, 2633, 3523, +3821, 2634, 3523, +3821, 2634, 3523, +3821, 2635, 3523, +3821, 2636, 3523, +3821, 2637, 3522, +3820, 2639, 3522, +3820, 2642, 3521, +3819, 2645, 3521, +3819, 2649, 3520, +3818, 2654, 3518, +3817, 2661, 3517, +3815, 2671, 3514, +3813, 2683, 3511, +3810, 2699, 3507, +3806, 2720, 3501, +3801, 2746, 3493, +3794, 2779, 3482, +3784, 2819, 3468, +3770, 2868, 3447, +3752, 2926, 3418, +3726, 2994, 3376, +3688, 3071, 3313, +3633, 3157, 3212, +3547, 3252, 3029, +3397, 3353, 2532, +3063, 3461, 0, +0, 3575, 0, +0, 3692, 0, +3954, 2763, 3655, +3954, 2763, 3655, +3954, 2763, 3655, +3954, 2764, 3655, +3953, 2764, 3655, +3953, 2764, 3655, +3953, 2765, 3655, +3953, 2766, 3655, +3953, 2767, 3654, +3953, 2768, 3654, +3953, 2770, 3654, +3952, 2772, 3653, +3952, 2775, 3652, +3951, 2779, 3651, +3950, 2785, 3650, +3949, 2792, 3648, +3947, 2802, 3646, +3945, 2814, 3643, +3942, 2830, 3639, +3938, 2851, 3633, +3933, 2877, 3625, +3926, 2910, 3614, +3916, 2950, 3599, +3903, 2999, 3579, +3884, 3057, 3550, +3858, 3125, 3508, +3821, 3202, 3444, +3765, 3289, 3344, +3679, 3383, 3160, +3529, 3485, 2661, +3195, 3593, 0, +0, 3706, 0, +4086, 2894, 3787, +4086, 2894, 3787, +4086, 2894, 3787, +4086, 2894, 3787, +4086, 2895, 3787, +4086, 2895, 3787, +4086, 2895, 3787, +4085, 2896, 3787, +4085, 2897, 3786, +4085, 2898, 3786, +4085, 2899, 3786, +4085, 2901, 3786, +4084, 2903, 3785, +4084, 2906, 3784, +4083, 2910, 3783, +4082, 2916, 3782, +4081, 2923, 3780, +4079, 2933, 3778, +4077, 2945, 3775, +4074, 2961, 3770, +4071, 2982, 3765, +4065, 3008, 3757, +4058, 3041, 3746, +4048, 3081, 3731, +4035, 3130, 3710, +4016, 3189, 3681, +3990, 3257, 3639, +3953, 3334, 3576, +3898, 3420, 3475, +3811, 3515, 3291, +3662, 3617, 2790, +3328, 3725, 0, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3025, 3919, +4095, 3026, 3919, +4095, 3026, 3919, +4095, 3026, 3919, +4095, 3027, 3919, +4095, 3027, 3919, +4095, 3028, 3918, +4095, 3029, 3918, +4095, 3030, 3918, +4095, 3032, 3917, +4095, 3034, 3917, +4095, 3037, 3916, +4095, 3042, 3915, +4095, 3047, 3914, +4095, 3054, 3912, +4095, 3064, 3910, +4095, 3076, 3906, +4095, 3092, 3902, +4095, 3113, 3896, +4095, 3139, 3888, +4095, 3172, 3878, +4095, 3213, 3863, +4095, 3262, 3842, +4095, 3320, 3813, +4095, 3388, 3771, +4085, 3466, 3708, +4030, 3552, 3607, +3943, 3647, 3422, +3794, 3749, 2920, +4095, 3156, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3159, 4050, +4095, 3159, 4050, +4095, 3160, 4050, +4095, 3162, 4050, +4095, 3163, 4049, +4095, 3166, 4049, +4095, 3169, 4048, +4095, 3173, 4047, +4095, 3179, 4046, +4095, 3186, 4044, +4095, 3195, 4042, +4095, 3208, 4038, +4095, 3224, 4034, +4095, 3245, 4028, +4095, 3271, 4020, +4095, 3304, 4010, +4095, 3345, 3995, +4095, 3394, 3974, +4095, 3452, 3945, +4095, 3520, 3903, +4095, 3598, 3840, +4095, 3684, 3738, +4075, 3779, 3554, +0, 843, 1089, +0, 852, 1080, +0, 864, 1068, +0, 879, 1052, +0, 898, 1030, +0, 923, 998, +0, 954, 952, +0, 992, 882, +0, 1039, 767, +0, 1094, 545, +0, 1160, 0, +0, 1234, 0, +0, 1318, 0, +0, 1411, 0, +0, 1511, 0, +0, 1617, 0, +0, 1729, 0, +0, 1846, 0, +0, 1966, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +0, 846, 1101, +0, 855, 1093, +0, 867, 1082, +0, 881, 1066, +0, 901, 1044, +0, 925, 1013, +0, 956, 969, +0, 994, 901, +0, 1041, 792, +0, 1096, 585, +0, 1161, 0, +0, 1236, 0, +0, 1319, 0, +0, 1412, 0, +0, 1512, 0, +0, 1618, 0, +0, 1730, 0, +0, 1846, 0, +0, 1966, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +0, 850, 1117, +0, 859, 1109, +0, 870, 1098, +0, 885, 1083, +0, 904, 1063, +0, 928, 1033, +0, 959, 990, +0, 997, 926, +0, 1043, 823, +0, 1098, 634, +0, 1163, 101, +0, 1237, 0, +0, 1321, 0, +0, 1413, 0, +0, 1513, 0, +0, 1619, 0, +0, 1730, 0, +0, 1847, 0, +0, 1967, 0, +0, 2089, 0, +0, 2214, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +0, 856, 1138, +0, 864, 1130, +0, 875, 1120, +0, 890, 1106, +0, 909, 1086, +0, 933, 1058, +0, 963, 1018, +0, 1001, 957, +0, 1047, 862, +0, 1101, 692, +0, 1166, 266, +0, 1240, 0, +0, 1323, 0, +0, 1414, 0, +0, 1514, 0, +0, 1620, 0, +0, 1731, 0, +0, 1847, 0, +0, 1967, 0, +0, 2090, 0, +0, 2215, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3251, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +0, 863, 1164, +0, 871, 1157, +0, 882, 1147, +0, 897, 1134, +0, 915, 1115, +0, 939, 1089, +0, 969, 1052, +0, 1006, 996, +0, 1051, 909, +0, 1106, 759, +0, 1169, 421, +0, 1243, 0, +0, 1325, 0, +0, 1417, 0, +0, 1515, 0, +0, 1621, 0, +0, 1732, 0, +0, 1848, 0, +0, 1968, 0, +0, 2090, 0, +0, 2215, 0, +0, 2341, 0, +0, 2469, 0, +0, 2598, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3646, 0, +133, 872, 1198, +32, 880, 1191, +0, 891, 1182, +0, 905, 1169, +0, 923, 1152, +0, 947, 1128, +0, 976, 1094, +0, 1013, 1043, +0, 1057, 966, +0, 1111, 836, +0, 1174, 570, +0, 1247, 0, +0, 1329, 0, +0, 1419, 0, +0, 1518, 0, +0, 1623, 0, +0, 1734, 0, +0, 1849, 0, +0, 1968, 0, +0, 2091, 0, +0, 2215, 0, +0, 2342, 0, +0, 2470, 0, +0, 2599, 0, +0, 2728, 0, +0, 2858, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +615, 884, 1238, +582, 892, 1232, +535, 902, 1224, +462, 916, 1213, +342, 934, 1197, +107, 957, 1175, +0, 986, 1144, +0, 1021, 1100, +0, 1065, 1032, +0, 1118, 922, +0, 1180, 714, +0, 1252, 39, +0, 1333, 0, +0, 1423, 0, +0, 1521, 0, +0, 1625, 0, +0, 1735, 0, +0, 1851, 0, +0, 1970, 0, +0, 2092, 0, +0, 2216, 0, +0, 2342, 0, +0, 2470, 0, +0, 2599, 0, +0, 2728, 0, +0, 2859, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +901, 899, 1288, +883, 907, 1282, +859, 917, 1275, +825, 931, 1265, +775, 948, 1251, +698, 970, 1231, +569, 998, 1204, +307, 1033, 1165, +0, 1076, 1107, +0, 1127, 1016, +0, 1188, 855, +0, 1259, 474, +0, 1339, 0, +0, 1428, 0, +0, 1524, 0, +0, 1628, 0, +0, 1738, 0, +0, 1852, 0, +0, 1971, 0, +0, 2093, 0, +0, 2217, 0, +0, 2343, 0, +0, 2470, 0, +0, 2599, 0, +0, 2729, 0, +0, 2859, 0, +0, 2989, 0, +0, 3120, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1121, 919, 1346, +1110, 927, 1341, +1096, 937, 1335, +1076, 949, 1326, +1048, 966, 1314, +1007, 987, 1297, +947, 1014, 1274, +850, 1048, 1241, +677, 1089, 1192, +240, 1140, 1117, +0, 1199, 994, +0, 1268, 747, +0, 1347, 0, +0, 1434, 0, +0, 1530, 0, +0, 1632, 0, +0, 1741, 0, +0, 1855, 0, +0, 1973, 0, +0, 2094, 0, +0, 2218, 0, +0, 2344, 0, +0, 2471, 0, +0, 2600, 0, +0, 2729, 0, +0, 2859, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1309, 945, 1414, +1302, 952, 1410, +1293, 961, 1405, +1280, 973, 1397, +1262, 989, 1387, +1237, 1009, 1372, +1202, 1035, 1353, +1149, 1067, 1325, +1068, 1107, 1285, +930, 1156, 1225, +639, 1213, 1130, +0, 1280, 962, +0, 1357, 546, +0, 1442, 0, +0, 1536, 0, +0, 1638, 0, +0, 1745, 0, +0, 1858, 0, +0, 1976, 0, +0, 2096, 0, +0, 2220, 0, +0, 2345, 0, +0, 2472, 0, +0, 2600, 0, +0, 2729, 0, +0, 2859, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +1479, 977, 1492, +1475, 983, 1488, +1468, 992, 1484, +1460, 1003, 1477, +1448, 1018, 1469, +1431, 1037, 1457, +1408, 1061, 1441, +1376, 1092, 1418, +1328, 1130, 1385, +1255, 1176, 1338, +1136, 1231, 1266, +901, 1296, 1148, +0, 1370, 916, +0, 1453, 0, +0, 1545, 0, +0, 1645, 0, +0, 1751, 0, +0, 1863, 0, +0, 1979, 0, +0, 2099, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1638, 1016, 1579, +1635, 1022, 1576, +1630, 1030, 1572, +1624, 1041, 1567, +1616, 1054, 1559, +1604, 1072, 1550, +1589, 1094, 1537, +1567, 1123, 1518, +1537, 1158, 1492, +1492, 1202, 1455, +1425, 1254, 1401, +1316, 1316, 1316, +1111, 1387, 1169, +459, 1468, 847, +0, 1557, 0, +0, 1654, 0, +0, 1758, 0, +0, 1869, 0, +0, 1983, 0, +0, 2102, 0, +0, 2224, 0, +0, 2348, 0, +0, 2475, 0, +0, 2602, 0, +0, 2731, 0, +0, 2861, 0, +0, 2991, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1789, 1064, 1673, +1786, 1070, 1671, +1783, 1077, 1668, +1779, 1086, 1664, +1773, 1099, 1658, +1765, 1115, 1650, +1754, 1135, 1640, +1739, 1161, 1625, +1719, 1194, 1605, +1689, 1234, 1576, +1647, 1283, 1535, +1583, 1341, 1473, +1481, 1409, 1375, +1293, 1486, 1197, +773, 1572, 733, +0, 1667, 0, +0, 1768, 0, +0, 1876, 0, +0, 1989, 0, +0, 2107, 0, +0, 2228, 0, +0, 2351, 0, +0, 2477, 0, +0, 2604, 0, +0, 2732, 0, +0, 2861, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1934, 1121, 1775, +1933, 1126, 1774, +1930, 1133, 1771, +1927, 1141, 1768, +1923, 1152, 1763, +1917, 1166, 1757, +1910, 1184, 1749, +1899, 1208, 1737, +1885, 1237, 1721, +1864, 1274, 1700, +1836, 1319, 1668, +1795, 1373, 1623, +1734, 1436, 1555, +1636, 1509, 1443, +1460, 1592, 1231, +1006, 1682, 516, +0, 1781, 0, +0, 1886, 0, +0, 1997, 0, +0, 2113, 0, +0, 2232, 0, +0, 2355, 0, +0, 2479, 0, +0, 2606, 0, +0, 2734, 0, +0, 2863, 0, +0, 2992, 0, +0, 3123, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +2076, 1188, 1884, +2075, 1192, 1882, +2074, 1198, 1880, +2071, 1205, 1878, +2068, 1214, 1874, +2064, 1227, 1869, +2058, 1243, 1863, +2051, 1264, 1854, +2041, 1290, 1842, +2026, 1323, 1825, +2007, 1363, 1802, +1979, 1413, 1768, +1939, 1471, 1720, +1879, 1539, 1645, +1784, 1616, 1521, +1616, 1703, 1274, +1200, 1798, 0, +0, 1899, 0, +0, 2008, 0, +0, 2121, 0, +0, 2239, 0, +0, 2359, 0, +0, 2483, 0, +0, 2609, 0, +0, 2736, 0, +0, 2864, 0, +0, 2993, 0, +0, 3123, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2216, 1264, 1997, +2215, 1268, 1996, +2214, 1272, 1995, +2212, 1279, 1992, +2210, 1287, 1990, +2207, 1297, 1986, +2203, 1311, 1981, +2197, 1329, 1974, +2190, 1352, 1965, +2179, 1381, 1952, +2165, 1417, 1935, +2146, 1461, 1910, +2119, 1513, 1875, +2079, 1576, 1823, +2021, 1648, 1743, +1928, 1729, 1608, +1765, 1819, 1325, +1374, 1916, 0, +0, 2021, 0, +0, 2132, 0, +0, 2247, 0, +0, 2366, 0, +0, 2488, 0, +0, 2612, 0, +0, 2739, 0, +0, 2866, 0, +0, 2995, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2353, 1349, 2115, +2353, 1352, 2114, +2352, 1356, 2113, +2350, 1361, 2111, +2349, 1368, 2109, +2347, 1377, 2106, +2344, 1389, 2102, +2340, 1404, 2097, +2334, 1423, 2090, +2327, 1448, 2080, +2317, 1479, 2067, +2303, 1518, 2049, +2284, 1565, 2023, +2257, 1621, 1987, +2218, 1686, 1932, +2160, 1761, 1848, +2069, 1846, 1703, +1910, 1938, 1386, +1535, 2039, 0, +0, 2145, 0, +0, 2257, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2489, 1443, 2236, +2489, 1445, 2235, +2488, 1449, 2234, +2487, 1453, 2233, +2486, 1458, 2231, +2484, 1466, 2229, +2482, 1475, 2226, +2479, 1488, 2222, +2475, 1504, 2217, +2470, 1525, 2210, +2462, 1551, 2200, +2452, 1584, 2186, +2439, 1625, 2167, +2420, 1675, 2141, +2393, 1733, 2103, +2355, 1802, 2047, +2297, 1879, 1958, +2208, 1966, 1805, +2051, 2061, 1456, +1688, 2163, 0, +0, 2271, 0, +0, 2385, 0, +0, 2502, 0, +0, 2623, 0, +0, 2747, 0, +0, 2873, 0, +0, 3000, 0, +0, 3128, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2624, 1544, 2359, +2624, 1546, 2359, +2624, 1549, 2358, +2623, 1552, 2357, +2622, 1556, 2356, +2621, 1562, 2354, +2619, 1570, 2352, +2617, 1580, 2349, +2614, 1593, 2345, +2610, 1611, 2340, +2605, 1633, 2332, +2597, 1661, 2322, +2587, 1695, 2308, +2574, 1738, 2289, +2555, 1789, 2262, +2528, 1850, 2223, +2490, 1921, 2165, +2433, 2000, 2074, +2345, 2089, 1914, +2190, 2186, 1535, +1835, 2289, 0, +0, 2399, 0, +0, 2513, 0, +0, 2632, 0, +0, 2753, 0, +0, 2877, 0, +0, 3004, 0, +0, 3131, 0, +0, 3260, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +2759, 1651, 2485, +2758, 1653, 2485, +2758, 1655, 2484, +2758, 1658, 2483, +2757, 1661, 2482, +2756, 1666, 2481, +2755, 1672, 2480, +2753, 1680, 2477, +2751, 1691, 2474, +2748, 1705, 2470, +2744, 1723, 2465, +2739, 1746, 2457, +2731, 1775, 2447, +2721, 1811, 2433, +2708, 1855, 2413, +2689, 1908, 2385, +2663, 1971, 2346, +2625, 2043, 2287, +2568, 2124, 2193, +2480, 2214, 2027, +2327, 2312, 1623, +1978, 2417, 0, +0, 2527, 0, +0, 2643, 0, +0, 2762, 0, +0, 2884, 0, +0, 3008, 0, +0, 3135, 0, +0, 3262, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +2892, 1764, 2612, +2892, 1765, 2612, +2892, 1767, 2612, +2892, 1769, 2611, +2891, 1772, 2610, +2890, 1775, 2609, +2889, 1780, 2608, +2888, 1787, 2606, +2887, 1795, 2604, +2884, 1806, 2601, +2882, 1821, 2597, +2878, 1839, 2591, +2872, 1863, 2584, +2865, 1893, 2573, +2855, 1930, 2559, +2842, 1976, 2539, +2823, 2030, 2511, +2797, 2094, 2471, +2759, 2167, 2411, +2703, 2250, 2315, +2615, 2341, 2145, +2463, 2440, 1720, +2118, 2546, 0, +0, 2657, 0, +0, 2773, 0, +0, 2892, 0, +0, 3015, 0, +0, 3140, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3653, 0, +3026, 1881, 2741, +3026, 1882, 2740, +3025, 1883, 2740, +3025, 1885, 2740, +3025, 1887, 2739, +3024, 1890, 2738, +3024, 1894, 2737, +3023, 1899, 2736, +3021, 1905, 2734, +3020, 1914, 2732, +3018, 1926, 2729, +3015, 1940, 2725, +3011, 1960, 2719, +3005, 1984, 2712, +2998, 2015, 2701, +2988, 2053, 2687, +2975, 2099, 2667, +2956, 2154, 2638, +2930, 2219, 2598, +2892, 2294, 2537, +2836, 2377, 2440, +2749, 2469, 2266, +2598, 2569, 1823, +2256, 2675, 0, +0, 2787, 0, +0, 2903, 0, +0, 3023, 0, +0, 3146, 0, +0, 3271, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +3159, 2002, 2870, +3159, 2002, 2870, +3158, 2003, 2870, +3158, 2005, 2869, +3158, 2006, 2869, +3158, 2008, 2868, +3157, 2011, 2868, +3156, 2015, 2867, +3156, 2020, 2865, +3154, 2027, 2864, +3153, 2036, 2861, +3151, 2048, 2858, +3148, 2063, 2854, +3144, 2082, 2848, +3138, 2107, 2840, +3131, 2139, 2830, +3121, 2177, 2815, +3108, 2224, 2795, +3089, 2280, 2767, +3063, 2346, 2726, +3025, 2421, 2664, +2970, 2506, 2566, +2883, 2598, 2390, +2732, 2699, 1933, +2392, 2805, 0, +0, 2918, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3403, 0, +0, 3529, 0, +0, 3658, 0, +3291, 2125, 3000, +3291, 2125, 3000, +3291, 2126, 3000, +3291, 2127, 2999, +3291, 2128, 2999, +3291, 2130, 2999, +3290, 2132, 2998, +3290, 2135, 2997, +3289, 2139, 2996, +3288, 2145, 2995, +3287, 2151, 2993, +3285, 2161, 2991, +3283, 2172, 2988, +3280, 2188, 2984, +3276, 2208, 2978, +3271, 2233, 2970, +3264, 2264, 2960, +3254, 2304, 2945, +3241, 2351, 2925, +3222, 2408, 2896, +3196, 2474, 2855, +3158, 2550, 2793, +3103, 2635, 2694, +3016, 2728, 2515, +2865, 2829, 2047, +2527, 2936, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3534, 0, +0, 3661, 0, +3424, 2250, 3130, +3424, 2251, 3130, +3424, 2251, 3130, +3424, 2252, 3130, +3424, 2253, 3130, +3423, 2254, 3130, +3423, 2256, 3129, +3423, 2258, 3129, +3422, 2261, 3128, +3422, 2265, 3127, +3421, 2271, 3126, +3420, 2278, 3124, +3418, 2287, 3122, +3416, 2299, 3118, +3413, 2314, 3114, +3409, 2334, 3108, +3404, 2360, 3101, +3396, 2392, 3090, +3387, 2431, 3075, +3373, 2479, 3055, +3355, 2537, 3026, +3328, 2603, 2984, +3291, 2680, 2922, +3235, 2765, 2823, +3149, 2859, 2643, +2999, 2960, 2165, +2662, 3067, 0, +0, 3180, 0, +0, 3297, 0, +0, 3418, 0, +0, 3541, 0, +0, 3666, 0, +3557, 2377, 3261, +3557, 2378, 3261, +3556, 2378, 3261, +3556, 2379, 3261, +3556, 2379, 3261, +3556, 2380, 3261, +3556, 2382, 3260, +3556, 2383, 3260, +3555, 2386, 3259, +3555, 2389, 3259, +3554, 2393, 3258, +3553, 2398, 3256, +3552, 2405, 3255, +3550, 2414, 3252, +3548, 2427, 3249, +3545, 2442, 3245, +3541, 2462, 3239, +3536, 2488, 3231, +3529, 2520, 3221, +3519, 2560, 3206, +3506, 2609, 3185, +3487, 2666, 3157, +3461, 2733, 3115, +3423, 2810, 3052, +3368, 2896, 2952, +3281, 2989, 2771, +3131, 3091, 2287, +2795, 3198, 0, +0, 3311, 0, +0, 3429, 0, +0, 3549, 0, +0, 3673, 0, +3689, 2506, 3393, +3689, 2506, 3393, +3689, 2506, 3392, +3689, 2506, 3392, +3689, 2507, 3392, +3689, 2508, 3392, +3688, 2509, 3392, +3688, 2510, 3392, +3688, 2512, 3391, +3688, 2514, 3391, +3687, 2517, 3390, +3686, 2521, 3389, +3686, 2527, 3388, +3684, 2534, 3386, +3683, 2543, 3383, +3681, 2555, 3380, +3678, 2571, 3376, +3674, 2592, 3370, +3668, 2617, 3362, +3661, 2650, 3352, +3651, 2690, 3337, +3638, 2739, 3316, +3619, 2796, 3287, +3593, 2864, 3246, +3556, 2941, 3183, +3500, 3026, 3083, +3414, 3121, 2900, +3264, 3222, 2411, +2929, 3330, 0, +0, 3443, 0, +0, 3560, 0, +0, 3681, 0, +3821, 2635, 3524, +3821, 2635, 3524, +3821, 2635, 3524, +3821, 2635, 3524, +3821, 2636, 3524, +3821, 2636, 3524, +3821, 2637, 3523, +3821, 2638, 3523, +3821, 2639, 3523, +3820, 2641, 3523, +3820, 2644, 3522, +3819, 2647, 3521, +3819, 2651, 3520, +3818, 2656, 3519, +3817, 2663, 3517, +3815, 2673, 3515, +3813, 2685, 3512, +3810, 2701, 3507, +3806, 2721, 3502, +3801, 2747, 3494, +3794, 2780, 3483, +3784, 2820, 3468, +3770, 2869, 3448, +3752, 2927, 3419, +3726, 2995, 3377, +3688, 3072, 3314, +3633, 3158, 3213, +3546, 3252, 3030, +3397, 3354, 2537, +3062, 3462, 0, +0, 3575, 0, +0, 3692, 0, +3953, 2765, 3656, +3953, 2765, 3656, +3953, 2765, 3656, +3953, 2765, 3656, +3953, 2765, 3655, +3953, 2766, 3655, +3953, 2766, 3655, +3953, 2767, 3655, +3953, 2768, 3655, +3953, 2770, 3655, +3952, 2771, 3654, +3952, 2774, 3654, +3952, 2777, 3653, +3951, 2781, 3652, +3950, 2786, 3651, +3949, 2793, 3649, +3947, 2803, 3646, +3945, 2815, 3643, +3942, 2831, 3639, +3938, 2852, 3633, +3933, 2878, 3625, +3926, 2911, 3615, +3916, 2951, 3600, +3903, 3000, 3579, +3884, 3058, 3550, +3858, 3126, 3508, +3821, 3203, 3445, +3765, 3289, 3344, +3679, 3384, 3161, +3529, 3485, 2664, +3195, 3593, 0, +0, 3707, 0, +4086, 2895, 3787, +4086, 2895, 3787, +4086, 2895, 3787, +4086, 2896, 3787, +4086, 2896, 3787, +4086, 2896, 3787, +4086, 2896, 3787, +4085, 2897, 3787, +4085, 2898, 3787, +4085, 2899, 3787, +4085, 2900, 3786, +4085, 2902, 3786, +4084, 2904, 3785, +4084, 2907, 3785, +4083, 2911, 3784, +4082, 2917, 3782, +4081, 2924, 3780, +4079, 2934, 3778, +4077, 2946, 3775, +4074, 2962, 3771, +4070, 2983, 3765, +4065, 3009, 3757, +4058, 3042, 3746, +4048, 3082, 3731, +4035, 3131, 3711, +4016, 3189, 3682, +3990, 3257, 3640, +3953, 3334, 3577, +3897, 3421, 3476, +3811, 3515, 3292, +3662, 3617, 2793, +3327, 3725, 0, +4095, 3026, 3919, +4095, 3026, 3919, +4095, 3026, 3919, +4095, 3026, 3919, +4095, 3026, 3919, +4095, 3027, 3919, +4095, 3027, 3919, +4095, 3027, 3919, +4095, 3028, 3919, +4095, 3029, 3919, +4095, 3030, 3918, +4095, 3031, 3918, +4095, 3033, 3918, +4095, 3035, 3917, +4095, 3038, 3916, +4095, 3042, 3915, +4095, 3048, 3914, +4095, 3055, 3912, +4095, 3065, 3910, +4095, 3077, 3907, +4095, 3093, 3902, +4095, 3114, 3897, +4095, 3140, 3889, +4095, 3173, 3878, +4095, 3213, 3863, +4095, 3263, 3843, +4095, 3321, 3813, +4095, 3389, 3771, +4085, 3466, 3708, +4030, 3552, 3607, +3943, 3647, 3423, +3794, 3749, 2922, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3157, 4051, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3159, 4051, +4095, 3159, 4051, +4095, 3160, 4050, +4095, 3161, 4050, +4095, 3162, 4050, +4095, 3164, 4049, +4095, 3166, 4049, +4095, 3170, 4048, +4095, 3174, 4047, +4095, 3179, 4046, +4095, 3186, 4044, +4095, 3196, 4042, +4095, 3208, 4039, +4095, 3224, 4034, +4095, 3245, 4028, +4095, 3271, 4021, +4095, 3304, 4010, +4095, 3345, 3995, +4095, 3394, 3974, +4095, 3453, 3945, +4095, 3520, 3903, +4095, 3598, 3840, +4095, 3684, 3739, +4075, 3779, 3555, +0, 966, 1218, +0, 973, 1211, +0, 982, 1202, +0, 994, 1191, +0, 1009, 1174, +0, 1028, 1151, +0, 1053, 1119, +0, 1084, 1071, +0, 1122, 999, +0, 1169, 879, +0, 1225, 645, +0, 1291, 0, +0, 1366, 0, +0, 1450, 0, +0, 1542, 0, +0, 1643, 0, +0, 1749, 0, +0, 1861, 0, +0, 1978, 0, +0, 2098, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3383, 0, +0, 3515, 0, +0, 3647, 0, +0, 969, 1227, +0, 975, 1221, +0, 984, 1212, +0, 996, 1201, +0, 1011, 1185, +0, 1030, 1162, +0, 1055, 1130, +0, 1086, 1084, +0, 1124, 1014, +0, 1171, 899, +0, 1226, 677, +0, 1292, 0, +0, 1367, 0, +0, 1451, 0, +0, 1543, 0, +0, 1643, 0, +0, 1750, 0, +0, 1862, 0, +0, 1978, 0, +0, 2098, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +0, 972, 1239, +0, 978, 1233, +0, 987, 1225, +0, 999, 1214, +0, 1014, 1198, +0, 1033, 1176, +0, 1057, 1146, +0, 1088, 1101, +0, 1126, 1033, +0, 1173, 924, +0, 1228, 717, +0, 1293, 53, +0, 1368, 0, +0, 1452, 0, +0, 1544, 0, +0, 1644, 0, +0, 1750, 0, +0, 1862, 0, +0, 1978, 0, +0, 2098, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +0, 976, 1255, +0, 982, 1249, +0, 991, 1241, +0, 1002, 1230, +0, 1017, 1215, +0, 1036, 1195, +0, 1061, 1165, +0, 1091, 1122, +0, 1129, 1058, +0, 1175, 955, +0, 1231, 766, +0, 1295, 233, +0, 1370, 0, +0, 1453, 0, +0, 1545, 0, +0, 1645, 0, +0, 1751, 0, +0, 1863, 0, +0, 1979, 0, +0, 2099, 0, +0, 2221, 0, +0, 2346, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +0, 981, 1276, +0, 988, 1270, +0, 996, 1263, +0, 1008, 1252, +0, 1022, 1238, +0, 1041, 1218, +0, 1065, 1190, +0, 1095, 1150, +0, 1133, 1090, +0, 1179, 994, +0, 1234, 824, +0, 1298, 398, +0, 1372, 0, +0, 1455, 0, +0, 1547, 0, +0, 1646, 0, +0, 1752, 0, +0, 1863, 0, +0, 1979, 0, +0, 2099, 0, +0, 2222, 0, +0, 2347, 0, +0, 2473, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +0, 988, 1302, +0, 995, 1297, +0, 1003, 1289, +0, 1014, 1280, +0, 1029, 1266, +0, 1047, 1247, +0, 1071, 1221, +0, 1101, 1184, +0, 1138, 1128, +0, 1183, 1041, +0, 1238, 891, +0, 1301, 553, +0, 1375, 0, +0, 1457, 0, +0, 1549, 0, +0, 1648, 0, +0, 1753, 0, +0, 1864, 0, +0, 1980, 0, +0, 2100, 0, +0, 2222, 0, +0, 2347, 0, +0, 2474, 0, +0, 2601, 0, +0, 2730, 0, +0, 2860, 0, +0, 2990, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +329, 998, 1335, +265, 1004, 1330, +164, 1012, 1323, +0, 1023, 1314, +0, 1037, 1301, +0, 1055, 1284, +0, 1079, 1260, +0, 1108, 1226, +0, 1145, 1175, +0, 1189, 1098, +0, 1243, 968, +0, 1306, 702, +0, 1379, 0, +0, 1461, 0, +0, 1551, 0, +0, 1650, 0, +0, 1755, 0, +0, 1866, 0, +0, 1981, 0, +0, 2101, 0, +0, 2223, 0, +0, 2347, 0, +0, 2474, 0, +0, 2602, 0, +0, 2731, 0, +0, 2860, 0, +0, 2991, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +770, 1010, 1375, +747, 1016, 1370, +715, 1024, 1364, +667, 1035, 1356, +594, 1048, 1345, +474, 1066, 1329, +239, 1089, 1307, +0, 1118, 1276, +0, 1154, 1232, +0, 1197, 1164, +0, 1250, 1054, +0, 1312, 846, +0, 1384, 171, +0, 1465, 0, +0, 1555, 0, +0, 1653, 0, +0, 1757, 0, +0, 1868, 0, +0, 1983, 0, +0, 2102, 0, +0, 2224, 0, +0, 2348, 0, +0, 2474, 0, +0, 2602, 0, +0, 2731, 0, +0, 2860, 0, +0, 2991, 0, +0, 3121, 0, +0, 3252, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1045, 1025, 1424, +1033, 1031, 1420, +1016, 1039, 1414, +992, 1049, 1407, +957, 1063, 1397, +907, 1080, 1383, +830, 1102, 1364, +702, 1130, 1336, +440, 1165, 1297, +0, 1208, 1239, +0, 1260, 1148, +0, 1321, 987, +0, 1391, 606, +0, 1471, 0, +0, 1560, 0, +0, 1657, 0, +0, 1760, 0, +0, 1870, 0, +0, 1985, 0, +0, 2103, 0, +0, 2225, 0, +0, 2349, 0, +0, 2475, 0, +0, 2603, 0, +0, 2731, 0, +0, 2861, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1261, 1046, 1482, +1253, 1051, 1478, +1242, 1059, 1473, +1228, 1069, 1467, +1208, 1082, 1458, +1180, 1098, 1446, +1139, 1119, 1429, +1079, 1146, 1406, +982, 1180, 1373, +810, 1222, 1324, +372, 1272, 1249, +0, 1331, 1126, +0, 1400, 879, +0, 1479, 0, +0, 1566, 0, +0, 1662, 0, +0, 1764, 0, +0, 1873, 0, +0, 1987, 0, +0, 2105, 0, +0, 2226, 0, +0, 2350, 0, +0, 2476, 0, +0, 2603, 0, +0, 2732, 0, +0, 2861, 0, +0, 2991, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1446, 1072, 1550, +1441, 1077, 1546, +1434, 1084, 1542, +1425, 1093, 1537, +1412, 1105, 1529, +1394, 1121, 1519, +1370, 1141, 1505, +1334, 1167, 1485, +1282, 1199, 1457, +1200, 1239, 1417, +1063, 1288, 1357, +771, 1345, 1263, +0, 1412, 1094, +0, 1489, 678, +0, 1575, 0, +0, 1668, 0, +0, 1770, 0, +0, 1877, 0, +0, 1990, 0, +0, 2108, 0, +0, 2228, 0, +0, 2352, 0, +0, 2477, 0, +0, 2604, 0, +0, 2732, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3515, 0, +0, 3647, 0, +1615, 1104, 1627, +1611, 1109, 1624, +1607, 1115, 1621, +1600, 1124, 1616, +1592, 1135, 1609, +1580, 1150, 1601, +1563, 1169, 1589, +1540, 1193, 1573, +1508, 1224, 1550, +1460, 1262, 1518, +1388, 1308, 1470, +1268, 1363, 1398, +1033, 1428, 1280, +0, 1502, 1048, +0, 1585, 57, +0, 1677, 0, +0, 1777, 0, +0, 1883, 0, +0, 1995, 0, +0, 2111, 0, +0, 2231, 0, +0, 2354, 0, +0, 2479, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +1772, 1144, 1713, +1770, 1148, 1711, +1767, 1154, 1708, +1762, 1162, 1704, +1756, 1173, 1699, +1748, 1186, 1692, +1737, 1204, 1682, +1721, 1226, 1669, +1699, 1255, 1650, +1669, 1290, 1624, +1624, 1334, 1588, +1557, 1386, 1533, +1448, 1448, 1448, +1243, 1519, 1301, +591, 1600, 979, +0, 1689, 0, +0, 1786, 0, +0, 1891, 0, +0, 2001, 0, +0, 2116, 0, +0, 2234, 0, +0, 2356, 0, +0, 2481, 0, +0, 2607, 0, +0, 2734, 0, +0, 2863, 0, +0, 2993, 0, +0, 3123, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3647, 0, +1923, 1192, 1807, +1921, 1196, 1805, +1919, 1202, 1803, +1915, 1209, 1800, +1911, 1218, 1796, +1905, 1231, 1790, +1897, 1247, 1782, +1886, 1267, 1772, +1871, 1293, 1757, +1851, 1326, 1737, +1821, 1366, 1708, +1779, 1415, 1667, +1715, 1473, 1605, +1613, 1541, 1507, +1426, 1618, 1329, +905, 1704, 865, +0, 1799, 0, +0, 1900, 0, +0, 2008, 0, +0, 2122, 0, +0, 2239, 0, +0, 2360, 0, +0, 2483, 0, +0, 2609, 0, +0, 2736, 0, +0, 2864, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2068, 1250, 1909, +2067, 1253, 1908, +2065, 1258, 1906, +2063, 1265, 1903, +2059, 1273, 1900, +2055, 1284, 1895, +2049, 1298, 1889, +2042, 1317, 1881, +2031, 1340, 1869, +2017, 1370, 1854, +1997, 1406, 1832, +1968, 1451, 1801, +1927, 1505, 1755, +1866, 1569, 1687, +1768, 1641, 1575, +1592, 1724, 1364, +1138, 1815, 648, +0, 1913, 0, +0, 2018, 0, +0, 2129, 0, +0, 2245, 0, +0, 2364, 0, +0, 2487, 0, +0, 2612, 0, +0, 2738, 0, +0, 2866, 0, +0, 2995, 0, +0, 3124, 0, +0, 3255, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +2210, 1317, 2017, +2209, 1320, 2016, +2207, 1324, 2014, +2206, 1330, 2012, +2203, 1337, 2010, +2200, 1347, 2006, +2196, 1359, 2001, +2191, 1375, 1995, +2183, 1396, 1986, +2173, 1422, 1974, +2158, 1455, 1957, +2139, 1496, 1934, +2111, 1545, 1900, +2071, 1603, 1852, +2011, 1671, 1777, +1916, 1749, 1653, +1748, 1835, 1406, +1333, 1930, 0, +0, 2032, 0, +0, 2140, 0, +0, 2253, 0, +0, 2371, 0, +0, 2492, 0, +0, 2615, 0, +0, 2741, 0, +0, 2868, 0, +0, 2996, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2349, 1394, 2130, +2348, 1396, 2129, +2347, 1400, 2128, +2346, 1404, 2127, +2344, 1411, 2125, +2342, 1419, 2122, +2339, 1429, 2118, +2335, 1443, 2113, +2329, 1461, 2106, +2322, 1484, 2097, +2312, 1513, 2084, +2298, 1549, 2067, +2278, 1593, 2042, +2251, 1646, 2007, +2211, 1708, 1955, +2153, 1780, 1875, +2061, 1861, 1740, +1898, 1951, 1457, +1507, 2049, 0, +0, 2153, 0, +0, 2264, 0, +0, 2379, 0, +0, 2498, 0, +0, 2620, 0, +0, 2744, 0, +0, 2871, 0, +0, 2998, 0, +0, 3127, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +2486, 1479, 2248, +2485, 1482, 2247, +2485, 1484, 2246, +2484, 1488, 2245, +2483, 1493, 2243, +2481, 1500, 2241, +2479, 1509, 2238, +2476, 1521, 2234, +2472, 1536, 2229, +2466, 1555, 2222, +2459, 1580, 2213, +2449, 1611, 2199, +2435, 1650, 2181, +2416, 1697, 2155, +2389, 1753, 2119, +2350, 1818, 2064, +2292, 1893, 1980, +2201, 1978, 1835, +2042, 2070, 1518, +1668, 2171, 0, +0, 2277, 0, +0, 2389, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +2622, 1573, 2368, +2621, 1575, 2368, +2621, 1578, 2367, +2620, 1581, 2366, +2619, 1585, 2365, +2618, 1590, 2363, +2616, 1598, 2361, +2614, 1607, 2358, +2611, 1620, 2354, +2607, 1636, 2349, +2602, 1657, 2342, +2595, 1683, 2332, +2585, 1716, 2318, +2571, 1757, 2299, +2552, 1807, 2273, +2525, 1865, 2235, +2487, 1934, 2179, +2430, 2011, 2091, +2340, 2098, 1937, +2183, 2193, 1588, +1820, 2295, 0, +0, 2403, 0, +0, 2517, 0, +0, 2634, 0, +0, 2755, 0, +0, 2879, 0, +0, 3005, 0, +0, 3132, 0, +0, 3260, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2757, 1675, 2492, +2756, 1676, 2491, +2756, 1678, 2491, +2756, 1681, 2490, +2755, 1684, 2489, +2754, 1688, 2488, +2753, 1694, 2486, +2751, 1702, 2484, +2749, 1712, 2481, +2746, 1726, 2477, +2742, 1743, 2472, +2737, 1765, 2464, +2729, 1793, 2454, +2719, 1827, 2440, +2706, 1870, 2421, +2687, 1922, 2394, +2660, 1982, 2355, +2622, 2053, 2297, +2566, 2132, 2206, +2477, 2221, 2046, +2322, 2318, 1667, +1967, 2421, 0, +0, 2531, 0, +0, 2645, 0, +0, 2764, 0, +0, 2885, 0, +0, 3010, 0, +0, 3136, 0, +0, 3263, 0, +0, 3392, 0, +0, 3521, 0, +0, 3651, 0, +2891, 1782, 2617, +2891, 1784, 2617, +2890, 1785, 2617, +2890, 1787, 2616, +2890, 1790, 2615, +2889, 1793, 2615, +2888, 1798, 2613, +2887, 1804, 2612, +2885, 1812, 2609, +2883, 1823, 2606, +2880, 1837, 2602, +2876, 1855, 2597, +2871, 1878, 2589, +2863, 1907, 2579, +2854, 1943, 2565, +2840, 1987, 2545, +2821, 2040, 2518, +2795, 2103, 2478, +2757, 2175, 2419, +2701, 2256, 2325, +2612, 2346, 2159, +2459, 2444, 1755, +2110, 2549, 0, +0, 2659, 0, +0, 2775, 0, +0, 2894, 0, +0, 3016, 0, +0, 3140, 0, +0, 3267, 0, +0, 3395, 0, +0, 3523, 0, +0, 3653, 0, +3025, 1895, 2745, +3024, 1896, 2744, +3024, 1897, 2744, +3024, 1899, 2744, +3024, 1901, 2743, +3023, 1904, 2742, +3022, 1908, 2741, +3022, 1912, 2740, +3020, 1919, 2738, +3019, 1927, 2736, +3017, 1938, 2733, +3014, 1953, 2729, +3010, 1971, 2723, +3004, 1995, 2716, +2997, 2025, 2705, +2987, 2062, 2691, +2974, 2108, 2671, +2955, 2162, 2643, +2929, 2226, 2603, +2891, 2299, 2543, +2835, 2382, 2447, +2747, 2473, 2277, +2595, 2572, 1852, +2250, 2678, 0, +0, 2789, 0, +0, 2905, 0, +0, 3024, 0, +0, 3147, 0, +0, 3272, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +3158, 2013, 2873, +3158, 2013, 2873, +3158, 2014, 2872, +3157, 2015, 2872, +3157, 2017, 2872, +3157, 2019, 2871, +3156, 2022, 2871, +3156, 2026, 2870, +3155, 2031, 2868, +3154, 2038, 2867, +3152, 2046, 2864, +3150, 2058, 2861, +3147, 2073, 2857, +3143, 2092, 2851, +3138, 2116, 2844, +3130, 2147, 2833, +3120, 2185, 2819, +3107, 2231, 2799, +3088, 2286, 2770, +3062, 2351, 2730, +3024, 2426, 2669, +2968, 2509, 2572, +2881, 2601, 2398, +2730, 2701, 1955, +2388, 2807, 0, +0, 2919, 0, +0, 3035, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +3291, 2133, 3002, +3291, 2134, 3002, +3291, 2135, 3002, +3291, 2135, 3002, +3290, 2137, 3001, +3290, 2138, 3001, +3290, 2141, 3000, +3289, 2143, 3000, +3288, 2147, 2999, +3288, 2153, 2997, +3286, 2159, 2996, +3285, 2168, 2993, +3283, 2180, 2990, +3280, 2195, 2986, +3276, 2215, 2980, +3270, 2239, 2973, +3263, 2271, 2962, +3253, 2309, 2947, +3240, 2356, 2927, +3221, 2412, 2899, +3195, 2478, 2858, +3157, 2553, 2796, +3102, 2638, 2698, +3015, 2730, 2522, +2864, 2831, 2065, +2524, 2938, 0, +0, 3050, 0, +0, 3166, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +3424, 2257, 3132, +3424, 2257, 3132, +3423, 2258, 3132, +3423, 2258, 3132, +3423, 2259, 3132, +3423, 2261, 3131, +3423, 2262, 3131, +3422, 2264, 3130, +3422, 2267, 3130, +3421, 2271, 3129, +3420, 2277, 3127, +3419, 2284, 3126, +3417, 2293, 3123, +3415, 2304, 3120, +3412, 2320, 3116, +3408, 2340, 3110, +3403, 2365, 3102, +3396, 2397, 3092, +3386, 2436, 3077, +3373, 2483, 3057, +3354, 2540, 3028, +3328, 2606, 2987, +3290, 2682, 2925, +3235, 2767, 2826, +3148, 2860, 2647, +2997, 2961, 2179, +2659, 3068, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3666, 0, +3556, 2382, 3263, +3556, 2382, 3263, +3556, 2383, 3262, +3556, 2383, 3262, +3556, 2384, 3262, +3556, 2385, 3262, +3556, 2386, 3262, +3555, 2388, 3261, +3555, 2390, 3261, +3554, 2393, 3260, +3554, 2397, 3259, +3553, 2403, 3258, +3552, 2410, 3256, +3550, 2419, 3254, +3548, 2431, 3250, +3545, 2446, 3246, +3541, 2466, 3240, +3536, 2492, 3233, +3529, 2524, 3222, +3519, 2564, 3207, +3505, 2612, 3187, +3487, 2669, 3158, +3461, 2736, 3117, +3423, 2812, 3054, +3368, 2897, 2955, +3281, 2991, 2775, +3131, 3092, 2297, +2794, 3199, 0, +0, 3312, 0, +0, 3429, 0, +0, 3550, 0, +0, 3673, 0, +3689, 2509, 3394, +3689, 2509, 3393, +3689, 2510, 3393, +3689, 2510, 3393, +3688, 2511, 3393, +3688, 2511, 3393, +3688, 2512, 3393, +3688, 2514, 3392, +3688, 2515, 3392, +3687, 2518, 3392, +3687, 2521, 3391, +3686, 2525, 3390, +3685, 2530, 3389, +3684, 2537, 3387, +3682, 2546, 3384, +3680, 2559, 3381, +3677, 2574, 3377, +3673, 2595, 3371, +3668, 2620, 3363, +3661, 2653, 3353, +3651, 2692, 3338, +3638, 2741, 3318, +3619, 2798, 3289, +3593, 2865, 3247, +3556, 2942, 3184, +3500, 3028, 3084, +3413, 3122, 2903, +3264, 3223, 2419, +2928, 3331, 0, +0, 3443, 0, +0, 3561, 0, +0, 3681, 0, +3821, 2637, 3525, +3821, 2638, 3525, +3821, 2638, 3525, +3821, 2638, 3525, +3821, 2639, 3524, +3821, 2639, 3524, +3821, 2640, 3524, +3821, 2641, 3524, +3820, 2642, 3524, +3820, 2644, 3523, +3820, 2646, 3523, +3819, 2649, 3522, +3818, 2653, 3521, +3818, 2659, 3520, +3816, 2666, 3518, +3815, 2675, 3516, +3813, 2687, 3512, +3810, 2703, 3508, +3806, 2724, 3502, +3801, 2750, 3494, +3793, 2782, 3484, +3784, 2822, 3469, +3770, 2871, 3448, +3752, 2929, 3420, +3725, 2996, 3378, +3688, 3073, 3315, +3633, 3159, 3215, +3546, 3253, 3032, +3396, 3354, 2543, +3061, 3462, 0, +0, 3575, 0, +0, 3692, 0, +3953, 2767, 3656, +3953, 2767, 3656, +3953, 2767, 3656, +3953, 2767, 3656, +3953, 2768, 3656, +3953, 2768, 3656, +3953, 2769, 3656, +3953, 2769, 3656, +3953, 2770, 3655, +3953, 2772, 3655, +3952, 2773, 3655, +3952, 2776, 3654, +3951, 2779, 3653, +3951, 2783, 3652, +3950, 2788, 3651, +3949, 2795, 3649, +3947, 2805, 3647, +3945, 2817, 3644, +3942, 2833, 3639, +3938, 2854, 3634, +3933, 2880, 3626, +3926, 2912, 3615, +3916, 2952, 3600, +3902, 3001, 3580, +3884, 3059, 3551, +3858, 3127, 3509, +3820, 3204, 3446, +3765, 3290, 3345, +3678, 3384, 3162, +3529, 3486, 2669, +3194, 3594, 0, +0, 3707, 0, +4086, 2897, 3788, +4086, 2897, 3788, +4086, 2897, 3788, +4086, 2897, 3788, +4086, 2897, 3788, +4085, 2898, 3788, +4085, 2898, 3787, +4085, 2899, 3787, +4085, 2899, 3787, +4085, 2900, 3787, +4085, 2902, 3787, +4085, 2903, 3786, +4084, 2906, 3786, +4084, 2909, 3785, +4083, 2913, 3784, +4082, 2918, 3783, +4081, 2926, 3781, +4079, 2935, 3779, +4077, 2947, 3775, +4074, 2963, 3771, +4070, 2984, 3765, +4065, 3010, 3757, +4058, 3043, 3747, +4048, 3083, 3732, +4035, 3132, 3711, +4016, 3190, 3682, +3990, 3258, 3640, +3953, 3335, 3577, +3897, 3421, 3476, +3811, 3516, 3293, +3661, 3617, 2796, +3327, 3725, 0, +4095, 3027, 3919, +4095, 3027, 3919, +4095, 3027, 3919, +4095, 3027, 3919, +4095, 3028, 3919, +4095, 3028, 3919, +4095, 3028, 3919, +4095, 3029, 3919, +4095, 3029, 3919, +4095, 3030, 3919, +4095, 3031, 3919, +4095, 3032, 3918, +4095, 3034, 3918, +4095, 3036, 3917, +4095, 3039, 3917, +4095, 3044, 3916, +4095, 3049, 3914, +4095, 3056, 3913, +4095, 3066, 3910, +4095, 3078, 3907, +4095, 3094, 3903, +4095, 3115, 3897, +4095, 3141, 3889, +4095, 3174, 3878, +4095, 3214, 3863, +4095, 3263, 3843, +4095, 3321, 3814, +4095, 3389, 3772, +4085, 3467, 3709, +4030, 3553, 3608, +3943, 3647, 3424, +3794, 3749, 2925, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3158, 4051, +4095, 3159, 4051, +4095, 3159, 4051, +4095, 3159, 4051, +4095, 3160, 4051, +4095, 3160, 4051, +4095, 3161, 4051, +4095, 3162, 4050, +4095, 3163, 4050, +4095, 3165, 4050, +4095, 3167, 4049, +4095, 3170, 4048, +4095, 3175, 4047, +4095, 3180, 4046, +4095, 3187, 4044, +4095, 3197, 4042, +4095, 3209, 4039, +4095, 3225, 4035, +4095, 3246, 4029, +4095, 3272, 4021, +4095, 3305, 4010, +4095, 3346, 3995, +4095, 3395, 3975, +4095, 3453, 3946, +4095, 3521, 3903, +4095, 3598, 3840, +4095, 3685, 3739, +4075, 3779, 3555, +0, 1092, 1347, +0, 1097, 1342, +0, 1104, 1336, +0, 1112, 1327, +0, 1124, 1315, +0, 1139, 1298, +0, 1159, 1275, +0, 1183, 1242, +0, 1215, 1193, +0, 1253, 1119, +0, 1300, 996, +0, 1356, 751, +0, 1422, 0, +0, 1497, 0, +0, 1581, 0, +0, 1674, 0, +0, 1774, 0, +0, 1881, 0, +0, 1993, 0, +0, 2110, 0, +0, 2230, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +0, 1093, 1354, +0, 1098, 1350, +0, 1105, 1343, +0, 1114, 1335, +0, 1126, 1323, +0, 1141, 1306, +0, 1160, 1283, +0, 1185, 1251, +0, 1216, 1203, +0, 1254, 1131, +0, 1301, 1011, +0, 1357, 777, +0, 1423, 0, +0, 1498, 0, +0, 1582, 0, +0, 1674, 0, +0, 1775, 0, +0, 1881, 0, +0, 1993, 0, +0, 2110, 0, +0, 2230, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +0, 1096, 1364, +0, 1101, 1359, +0, 1107, 1353, +0, 1116, 1344, +0, 1128, 1333, +0, 1143, 1317, +0, 1162, 1294, +0, 1187, 1262, +0, 1218, 1216, +0, 1256, 1146, +0, 1303, 1031, +0, 1359, 809, +0, 1424, 0, +0, 1499, 0, +0, 1583, 0, +0, 1675, 0, +0, 1775, 0, +0, 1882, 0, +0, 1994, 0, +0, 2110, 0, +0, 2230, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +0, 1099, 1376, +0, 1104, 1371, +0, 1110, 1365, +0, 1119, 1357, +0, 1131, 1346, +0, 1146, 1330, +0, 1165, 1308, +0, 1189, 1278, +0, 1220, 1233, +0, 1258, 1165, +0, 1305, 1056, +0, 1360, 850, +0, 1425, 185, +0, 1500, 0, +0, 1584, 0, +0, 1676, 0, +0, 1776, 0, +0, 1882, 0, +0, 1994, 0, +0, 2110, 0, +0, 2230, 0, +0, 2353, 0, +0, 2478, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +0, 1103, 1392, +0, 1108, 1387, +0, 1114, 1381, +0, 1123, 1373, +0, 1135, 1363, +0, 1149, 1348, +0, 1168, 1327, +0, 1193, 1297, +0, 1223, 1255, +0, 1261, 1190, +0, 1307, 1087, +0, 1363, 898, +0, 1427, 365, +0, 1502, 0, +0, 1585, 0, +0, 1677, 0, +0, 1777, 0, +0, 1883, 0, +0, 1995, 0, +0, 2111, 0, +0, 2231, 0, +0, 2354, 0, +0, 2479, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +0, 1108, 1412, +0, 1113, 1408, +0, 1120, 1402, +0, 1128, 1395, +0, 1140, 1384, +0, 1154, 1370, +0, 1173, 1350, +0, 1197, 1322, +0, 1227, 1282, +0, 1265, 1222, +0, 1311, 1126, +0, 1366, 956, +0, 1430, 530, +0, 1504, 0, +0, 1587, 0, +0, 1679, 0, +0, 1778, 0, +0, 1884, 0, +0, 1995, 0, +0, 2112, 0, +0, 2231, 0, +0, 2354, 0, +0, 2479, 0, +0, 2605, 0, +0, 2733, 0, +0, 2862, 0, +0, 2992, 0, +0, 3122, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +0, 1115, 1438, +0, 1120, 1434, +0, 1127, 1429, +0, 1135, 1421, +0, 1146, 1412, +0, 1161, 1398, +0, 1179, 1380, +0, 1203, 1353, +0, 1233, 1316, +0, 1270, 1260, +0, 1315, 1173, +0, 1370, 1023, +0, 1434, 686, +0, 1507, 0, +0, 1590, 0, +0, 1681, 0, +0, 1780, 0, +0, 1885, 0, +0, 1996, 0, +0, 2112, 0, +0, 2232, 0, +0, 2354, 0, +0, 2479, 0, +0, 2606, 0, +0, 2734, 0, +0, 2862, 0, +0, 2992, 0, +0, 3123, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +503, 1125, 1470, +461, 1130, 1467, +397, 1136, 1462, +296, 1144, 1455, +111, 1155, 1446, +0, 1169, 1433, +0, 1188, 1416, +0, 1211, 1392, +0, 1240, 1358, +0, 1277, 1307, +0, 1322, 1230, +0, 1375, 1100, +0, 1438, 834, +0, 1511, 0, +0, 1593, 0, +0, 1683, 0, +0, 1782, 0, +0, 1887, 0, +0, 1998, 0, +0, 2113, 0, +0, 2233, 0, +0, 2355, 0, +0, 2480, 0, +0, 2606, 0, +0, 2734, 0, +0, 2863, 0, +0, 2992, 0, +0, 3123, 0, +0, 3253, 0, +0, 3384, 0, +0, 3516, 0, +0, 3647, 0, +919, 1137, 1510, +902, 1142, 1507, +879, 1148, 1502, +847, 1156, 1496, +799, 1167, 1488, +726, 1180, 1477, +606, 1198, 1461, +371, 1221, 1439, +0, 1250, 1409, +0, 1286, 1364, +0, 1330, 1296, +0, 1382, 1186, +0, 1444, 978, +0, 1516, 303, +0, 1597, 0, +0, 1687, 0, +0, 1785, 0, +0, 1889, 0, +0, 2000, 0, +0, 2115, 0, +0, 2234, 0, +0, 2356, 0, +0, 2480, 0, +0, 2606, 0, +0, 2734, 0, +0, 2863, 0, +0, 2993, 0, +0, 3123, 0, +0, 3253, 0, +0, 3385, 0, +0, 3516, 0, +0, 3647, 0, +1186, 1153, 1559, +1177, 1158, 1556, +1165, 1164, 1552, +1148, 1171, 1546, +1124, 1182, 1539, +1090, 1195, 1529, +1039, 1212, 1515, +962, 1234, 1496, +834, 1262, 1468, +572, 1297, 1429, +0, 1340, 1371, +0, 1392, 1280, +0, 1453, 1119, +0, 1523, 738, +0, 1603, 0, +0, 1692, 0, +0, 1789, 0, +0, 1892, 0, +0, 2002, 0, +0, 2117, 0, +0, 2235, 0, +0, 2357, 0, +0, 2481, 0, +0, 2607, 0, +0, 2735, 0, +0, 2863, 0, +0, 2993, 0, +0, 3123, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3647, 0, +1398, 1174, 1617, +1393, 1178, 1614, +1385, 1184, 1610, +1375, 1191, 1606, +1360, 1201, 1599, +1340, 1214, 1590, +1312, 1230, 1578, +1271, 1251, 1561, +1211, 1278, 1538, +1114, 1312, 1505, +942, 1354, 1456, +504, 1404, 1382, +0, 1463, 1258, +0, 1532, 1012, +0, 1611, 0, +0, 1698, 0, +0, 1794, 0, +0, 1896, 0, +0, 2005, 0, +0, 2119, 0, +0, 2237, 0, +0, 2358, 0, +0, 2482, 0, +0, 2608, 0, +0, 2735, 0, +0, 2864, 0, +0, 2993, 0, +0, 3123, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3647, 0, +1582, 1200, 1684, +1579, 1204, 1682, +1573, 1209, 1679, +1567, 1216, 1674, +1557, 1225, 1669, +1544, 1237, 1661, +1527, 1253, 1651, +1502, 1273, 1637, +1466, 1299, 1617, +1414, 1331, 1589, +1332, 1371, 1549, +1195, 1420, 1489, +903, 1477, 1395, +0, 1544, 1226, +0, 1621, 810, +0, 1707, 0, +0, 1801, 0, +0, 1902, 0, +0, 2010, 0, +0, 2123, 0, +0, 2240, 0, +0, 2360, 0, +0, 2484, 0, +0, 2609, 0, +0, 2736, 0, +0, 2864, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +1750, 1232, 1761, +1747, 1236, 1759, +1744, 1241, 1756, +1739, 1248, 1753, +1732, 1256, 1748, +1724, 1268, 1742, +1712, 1282, 1733, +1695, 1301, 1721, +1672, 1326, 1705, +1640, 1356, 1682, +1592, 1394, 1650, +1520, 1440, 1602, +1400, 1495, 1530, +1165, 1560, 1412, +102, 1634, 1180, +0, 1718, 189, +0, 1809, 0, +0, 1909, 0, +0, 2015, 0, +0, 2127, 0, +0, 2243, 0, +0, 2363, 0, +0, 2486, 0, +0, 2611, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +1906, 1272, 1846, +1905, 1276, 1845, +1902, 1280, 1843, +1899, 1286, 1840, +1894, 1294, 1836, +1888, 1305, 1831, +1880, 1319, 1824, +1869, 1336, 1814, +1853, 1359, 1801, +1831, 1387, 1782, +1801, 1422, 1757, +1756, 1466, 1720, +1689, 1518, 1665, +1580, 1580, 1580, +1375, 1651, 1434, +723, 1732, 1111, +0, 1821, 0, +0, 1918, 0, +0, 2023, 0, +0, 2133, 0, +0, 2248, 0, +0, 2366, 0, +0, 2488, 0, +0, 2613, 0, +0, 2739, 0, +0, 2866, 0, +0, 2995, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2056, 1321, 1941, +2055, 1324, 1939, +2053, 1328, 1938, +2051, 1334, 1935, +2047, 1341, 1932, +2043, 1350, 1928, +2037, 1363, 1922, +2029, 1379, 1914, +2018, 1399, 1904, +2003, 1425, 1889, +1983, 1458, 1869, +1953, 1498, 1840, +1911, 1547, 1799, +1847, 1605, 1737, +1745, 1673, 1639, +1558, 1750, 1461, +1037, 1836, 997, +0, 1931, 0, +0, 2032, 0, +0, 2140, 0, +0, 2254, 0, +0, 2371, 0, +0, 2492, 0, +0, 2615, 0, +0, 2741, 0, +0, 2868, 0, +0, 2996, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +2201, 1379, 2042, +2200, 1382, 2041, +2199, 1386, 2040, +2197, 1390, 2038, +2195, 1397, 2035, +2191, 1405, 2032, +2187, 1416, 2027, +2182, 1430, 2021, +2174, 1449, 2013, +2163, 1472, 2001, +2149, 1502, 1986, +2129, 1538, 1964, +2100, 1583, 1933, +2059, 1637, 1887, +1998, 1701, 1819, +1900, 1774, 1707, +1724, 1856, 1496, +1270, 1947, 780, +0, 2045, 0, +0, 2151, 0, +0, 2262, 0, +0, 2377, 0, +0, 2497, 0, +0, 2619, 0, +0, 2744, 0, +0, 2870, 0, +0, 2998, 0, +0, 3127, 0, +0, 3256, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +2342, 1447, 2150, +2342, 1449, 2149, +2341, 1452, 2148, +2339, 1456, 2146, +2338, 1462, 2145, +2335, 1469, 2142, +2332, 1479, 2138, +2328, 1491, 2133, +2323, 1507, 2127, +2315, 1528, 2118, +2305, 1554, 2106, +2290, 1587, 2089, +2271, 1628, 2066, +2243, 1677, 2032, +2203, 1735, 1984, +2143, 1803, 1909, +2049, 1881, 1785, +1880, 1967, 1538, +1465, 2062, 3, +0, 2164, 0, +0, 2272, 0, +0, 2385, 0, +0, 2503, 0, +0, 2624, 0, +0, 2747, 0, +0, 2873, 0, +0, 3000, 0, +0, 3128, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2481, 1524, 2263, +2481, 1526, 2262, +2480, 1528, 2261, +2479, 1532, 2260, +2478, 1537, 2259, +2476, 1543, 2257, +2474, 1551, 2254, +2471, 1561, 2250, +2467, 1575, 2245, +2461, 1593, 2238, +2454, 1616, 2229, +2444, 1645, 2216, +2430, 1681, 2199, +2410, 1725, 2174, +2383, 1778, 2139, +2344, 1840, 2087, +2285, 1912, 2007, +2193, 1993, 1872, +2030, 2083, 1589, +1639, 2181, 0, +0, 2285, 0, +0, 2396, 0, +0, 2511, 0, +0, 2630, 0, +0, 2752, 0, +0, 2876, 0, +0, 3003, 0, +0, 3130, 0, +0, 3259, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +2618, 1610, 2380, +2618, 1611, 2380, +2617, 1614, 2379, +2617, 1617, 2378, +2616, 1620, 2377, +2615, 1626, 2375, +2613, 1632, 2373, +2611, 1641, 2370, +2608, 1653, 2367, +2604, 1668, 2361, +2598, 1687, 2354, +2591, 1712, 2345, +2581, 1743, 2331, +2567, 1782, 2313, +2548, 1829, 2287, +2521, 1885, 2251, +2482, 1950, 2197, +2424, 2026, 2112, +2333, 2110, 1967, +2174, 2202, 1650, +1800, 2303, 0, +0, 2409, 0, +0, 2522, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +2754, 1704, 2501, +2754, 1705, 2500, +2754, 1707, 2500, +2753, 1710, 2499, +2752, 1713, 2498, +2751, 1717, 2497, +2750, 1723, 2496, +2749, 1730, 2493, +2746, 1739, 2490, +2743, 1752, 2486, +2739, 1768, 2481, +2734, 1789, 2474, +2727, 1815, 2464, +2717, 1849, 2450, +2703, 1889, 2432, +2684, 1939, 2405, +2657, 1997, 2367, +2619, 2066, 2311, +2562, 2143, 2223, +2472, 2230, 2069, +2315, 2325, 1720, +1952, 2427, 0, +0, 2535, 0, +0, 2649, 0, +0, 2767, 0, +0, 2888, 0, +0, 3011, 0, +0, 3137, 0, +0, 3264, 0, +0, 3392, 0, +0, 3522, 0, +0, 3652, 0, +2889, 1806, 2624, +2889, 1807, 2624, +2889, 1808, 2624, +2888, 1810, 2623, +2888, 1813, 2622, +2887, 1816, 2621, +2886, 1821, 2620, +2885, 1826, 2619, +2883, 1834, 2616, +2881, 1844, 2613, +2878, 1858, 2609, +2874, 1875, 2604, +2869, 1897, 2596, +2861, 1925, 2586, +2852, 1959, 2572, +2838, 2002, 2553, +2819, 2054, 2526, +2792, 2114, 2487, +2754, 2185, 2429, +2698, 2265, 2338, +2609, 2353, 2178, +2454, 2450, 1799, +2099, 2553, 0, +0, 2663, 0, +0, 2777, 0, +0, 2896, 0, +0, 3018, 0, +0, 3142, 0, +0, 3268, 0, +0, 3395, 0, +0, 3524, 0, +0, 3653, 0, +3023, 1914, 2750, +3023, 1915, 2749, +3023, 1916, 2749, +3023, 1917, 2749, +3022, 1919, 2748, +3022, 1922, 2748, +3021, 1925, 2747, +3020, 1930, 2745, +3019, 1936, 2744, +3017, 1944, 2741, +3015, 1955, 2738, +3012, 1969, 2734, +3008, 1987, 2729, +3003, 2010, 2721, +2996, 2039, 2711, +2986, 2075, 2697, +2972, 2119, 2677, +2953, 2172, 2650, +2927, 2235, 2610, +2889, 2307, 2551, +2833, 2388, 2457, +2744, 2478, 2291, +2591, 2576, 1888, +2242, 2681, 0, +0, 2792, 0, +0, 2907, 0, +0, 3026, 0, +0, 3148, 0, +0, 3273, 0, +0, 3399, 0, +0, 3527, 0, +0, 3655, 0, +3157, 2027, 2877, +3157, 2028, 2877, +3157, 2028, 2876, +3156, 2030, 2876, +3156, 2031, 2876, +3156, 2033, 2875, +3155, 2036, 2874, +3155, 2040, 2874, +3154, 2045, 2872, +3152, 2051, 2871, +3151, 2059, 2868, +3149, 2071, 2865, +3146, 2085, 2861, +3142, 2104, 2855, +3136, 2127, 2848, +3129, 2157, 2837, +3119, 2194, 2823, +3106, 2240, 2803, +3087, 2294, 2775, +3061, 2358, 2735, +3023, 2431, 2675, +2967, 2514, 2579, +2879, 2605, 2409, +2727, 2704, 1984, +2382, 2810, 0, +0, 2921, 0, +0, 3037, 0, +0, 3157, 0, +0, 3279, 0, +0, 3404, 0, +0, 3530, 0, +0, 3658, 0, +3290, 2144, 3005, +3290, 2145, 3005, +3290, 2145, 3005, +3290, 2146, 3005, +3290, 2148, 3004, +3289, 2149, 3004, +3289, 2151, 3003, +3288, 2154, 3003, +3288, 2158, 3002, +3287, 2163, 3000, +3286, 2170, 2999, +3284, 2178, 2996, +3282, 2190, 2993, +3279, 2205, 2989, +3275, 2224, 2983, +3270, 2248, 2976, +3262, 2279, 2965, +3253, 2317, 2951, +3239, 2363, 2931, +3220, 2418, 2902, +3194, 2483, 2862, +3156, 2558, 2801, +3101, 2641, 2704, +3013, 2733, 2530, +2862, 2833, 2087, +2520, 2939, 0, +0, 3051, 0, +0, 3168, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +3423, 2265, 3134, +3423, 2265, 3134, +3423, 2266, 3134, +3423, 2267, 3134, +3423, 2268, 3134, +3422, 2269, 3133, +3422, 2270, 3133, +3422, 2273, 3132, +3421, 2276, 3132, +3421, 2279, 3131, +3420, 2285, 3130, +3418, 2291, 3128, +3417, 2300, 3125, +3415, 2312, 3122, +3412, 2327, 3118, +3408, 2347, 3112, +3403, 2371, 3105, +3395, 2403, 3094, +3386, 2441, 3080, +3372, 2488, 3059, +3353, 2545, 3031, +3327, 2610, 2990, +3290, 2685, 2928, +3234, 2770, 2830, +3147, 2863, 2654, +2996, 2963, 2197, +2656, 3070, 0, +0, 3182, 0, +0, 3298, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +3556, 2388, 3264, +3556, 2389, 3264, +3556, 2389, 3264, +3556, 2390, 3264, +3555, 2390, 3264, +3555, 2391, 3264, +3555, 2393, 3263, +3555, 2394, 3263, +3554, 2397, 3262, +3554, 2400, 3262, +3553, 2403, 3261, +3552, 2409, 3259, +3551, 2416, 3258, +3550, 2425, 3255, +3547, 2437, 3252, +3544, 2452, 3248, +3541, 2472, 3242, +3535, 2497, 3234, +3528, 2529, 3224, +3518, 2568, 3209, +3505, 2615, 3189, +3486, 2672, 3160, +3460, 2738, 3119, +3422, 2814, 3057, +3367, 2899, 2958, +3280, 2992, 2780, +3130, 3093, 2311, +2791, 3200, 0, +0, 3313, 0, +0, 3430, 0, +0, 3550, 0, +0, 3673, 0, +3688, 2514, 3395, +3688, 2514, 3395, +3688, 2515, 3395, +3688, 2515, 3395, +3688, 2515, 3394, +3688, 2516, 3394, +3688, 2517, 3394, +3688, 2518, 3394, +3687, 2520, 3393, +3687, 2522, 3393, +3686, 2525, 3392, +3686, 2529, 3391, +3685, 2535, 3390, +3684, 2542, 3388, +3682, 2551, 3386, +3680, 2563, 3383, +3677, 2579, 3378, +3673, 2599, 3373, +3668, 2624, 3365, +3661, 2656, 3354, +3651, 2696, 3339, +3637, 2744, 3319, +3619, 2801, 3290, +3593, 2868, 3249, +3555, 2944, 3186, +3500, 3029, 3087, +3413, 3123, 2907, +3263, 3224, 2429, +2926, 3331, 0, +0, 3444, 0, +0, 3561, 0, +0, 3682, 0, +3821, 2641, 3526, +3821, 2641, 3526, +3821, 2641, 3526, +3821, 2642, 3526, +3821, 2642, 3525, +3821, 2643, 3525, +3820, 2643, 3525, +3820, 2644, 3525, +3820, 2646, 3525, +3820, 2647, 3524, +3819, 2650, 3524, +3819, 2653, 3523, +3818, 2657, 3522, +3817, 2662, 3521, +3816, 2669, 3519, +3815, 2679, 3517, +3812, 2691, 3513, +3809, 2706, 3509, +3806, 2727, 3503, +3800, 2752, 3495, +3793, 2785, 3485, +3783, 2825, 3470, +3770, 2873, 3450, +3751, 2930, 3421, +3725, 2998, 3379, +3688, 3074, 3316, +3632, 3160, 3216, +3546, 3254, 3035, +3396, 3355, 2551, +3060, 3463, 0, +0, 3576, 0, +0, 3693, 0, +3953, 2769, 3657, +3953, 2770, 3657, +3953, 2770, 3657, +3953, 2770, 3657, +3953, 2770, 3657, +3953, 2771, 3657, +3953, 2771, 3656, +3953, 2772, 3656, +3953, 2773, 3656, +3952, 2774, 3656, +3952, 2776, 3655, +3952, 2778, 3655, +3951, 2781, 3654, +3951, 2785, 3653, +3950, 2791, 3652, +3948, 2798, 3650, +3947, 2807, 3648, +3945, 2820, 3644, +3942, 2835, 3640, +3938, 2856, 3634, +3933, 2882, 3627, +3925, 2914, 3616, +3916, 2954, 3601, +3902, 3003, 3581, +3884, 3061, 3552, +3858, 3128, 3510, +3820, 3205, 3447, +3765, 3291, 3347, +3678, 3385, 3165, +3528, 3486, 2675, +3193, 3594, 0, +0, 3707, 0, +4085, 2899, 3788, +4085, 2899, 3788, +4085, 2899, 3788, +4085, 2899, 3788, +4085, 2899, 3788, +4085, 2900, 3788, +4085, 2900, 3788, +4085, 2901, 3788, +4085, 2901, 3788, +4085, 2902, 3787, +4085, 2904, 3787, +4084, 2905, 3787, +4084, 2908, 3786, +4084, 2911, 3785, +4083, 2915, 3784, +4082, 2920, 3783, +4081, 2928, 3781, +4079, 2937, 3779, +4077, 2949, 3776, +4074, 2965, 3772, +4070, 2986, 3766, +4065, 3012, 3758, +4058, 3044, 3747, +4048, 3084, 3732, +4035, 3133, 3712, +4016, 3191, 3683, +3990, 3259, 3641, +3952, 3336, 3578, +3897, 3422, 3477, +3811, 3516, 3295, +3661, 3618, 2801, +3326, 3726, 0, +4095, 3029, 3920, +4095, 3029, 3920, +4095, 3029, 3920, +4095, 3029, 3920, +4095, 3029, 3920, +4095, 3029, 3920, +4095, 3030, 3920, +4095, 3030, 3920, +4095, 3031, 3919, +4095, 3031, 3919, +4095, 3032, 3919, +4095, 3034, 3919, +4095, 3035, 3918, +4095, 3038, 3918, +4095, 3041, 3917, +4095, 3045, 3916, +4095, 3050, 3915, +4095, 3058, 3913, +4095, 3067, 3911, +4095, 3079, 3907, +4095, 3095, 3903, +4095, 3116, 3897, +4095, 3142, 3889, +4095, 3175, 3879, +4095, 3215, 3864, +4095, 3264, 3843, +4095, 3322, 3814, +4095, 3390, 3772, +4085, 3467, 3709, +4029, 3553, 3609, +3943, 3648, 3425, +3793, 3750, 2928, +4095, 3159, 4052, +4095, 3159, 4052, +4095, 3159, 4052, +4095, 3159, 4052, +4095, 3160, 4052, +4095, 3160, 4051, +4095, 3160, 4051, +4095, 3160, 4051, +4095, 3161, 4051, +4095, 3161, 4051, +4095, 3162, 4051, +4095, 3163, 4051, +4095, 3164, 4050, +4095, 3166, 4050, +4095, 3168, 4049, +4095, 3171, 4049, +4095, 3176, 4048, +4095, 3181, 4046, +4095, 3188, 4045, +4095, 3198, 4042, +4095, 3210, 4039, +4095, 3226, 4035, +4095, 3247, 4029, +4095, 3273, 4021, +4095, 3306, 4010, +4095, 3346, 3996, +4095, 3395, 3975, +4095, 3454, 3946, +4095, 3521, 3904, +4095, 3599, 3841, +4095, 3685, 3740, +4075, 3780, 3556, +0, 1218, 1478, +0, 1222, 1474, +0, 1228, 1469, +0, 1234, 1463, +0, 1243, 1454, +0, 1255, 1441, +0, 1270, 1424, +0, 1290, 1401, +0, 1314, 1367, +0, 1346, 1318, +0, 1384, 1242, +0, 1431, 1116, +0, 1488, 863, +0, 1553, 0, +0, 1629, 0, +0, 1713, 0, +0, 1806, 0, +0, 1906, 0, +0, 2013, 0, +0, 2125, 0, +0, 2242, 0, +0, 2362, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1220, 1483, +0, 1224, 1479, +0, 1229, 1475, +0, 1236, 1468, +0, 1245, 1459, +0, 1256, 1447, +0, 1271, 1430, +0, 1291, 1407, +0, 1316, 1374, +0, 1347, 1325, +0, 1385, 1251, +0, 1432, 1128, +0, 1488, 883, +0, 1554, 0, +0, 1629, 0, +0, 1713, 0, +0, 1806, 0, +0, 1906, 0, +0, 2013, 0, +0, 2125, 0, +0, 2242, 0, +0, 2362, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1222, 1490, +0, 1225, 1486, +0, 1231, 1482, +0, 1237, 1475, +0, 1246, 1467, +0, 1258, 1455, +0, 1273, 1438, +0, 1292, 1415, +0, 1317, 1383, +0, 1348, 1335, +0, 1387, 1263, +0, 1433, 1143, +0, 1489, 909, +0, 1555, 0, +0, 1630, 0, +0, 1714, 0, +0, 1807, 0, +0, 1907, 0, +0, 2013, 0, +0, 2125, 0, +0, 2242, 0, +0, 2362, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1224, 1499, +0, 1228, 1496, +0, 1233, 1491, +0, 1240, 1485, +0, 1248, 1476, +0, 1260, 1465, +0, 1275, 1449, +0, 1294, 1426, +0, 1319, 1395, +0, 1350, 1348, +0, 1388, 1278, +0, 1435, 1163, +0, 1491, 942, +0, 1556, 111, +0, 1631, 0, +0, 1715, 0, +0, 1807, 0, +0, 1907, 0, +0, 2014, 0, +0, 2126, 0, +0, 2242, 0, +0, 2362, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1227, 1511, +0, 1231, 1508, +0, 1236, 1503, +0, 1243, 1497, +0, 1251, 1489, +0, 1263, 1478, +0, 1278, 1462, +0, 1297, 1441, +0, 1321, 1410, +0, 1352, 1365, +0, 1390, 1298, +0, 1437, 1188, +0, 1492, 982, +0, 1557, 317, +0, 1632, 0, +0, 1716, 0, +0, 1808, 0, +0, 1908, 0, +0, 2014, 0, +0, 2126, 0, +0, 2243, 0, +0, 2363, 0, +0, 2485, 0, +0, 2610, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1231, 1527, +0, 1235, 1524, +0, 1240, 1519, +0, 1247, 1514, +0, 1255, 1506, +0, 1267, 1495, +0, 1281, 1480, +0, 1300, 1459, +0, 1325, 1429, +0, 1355, 1387, +0, 1393, 1322, +0, 1439, 1219, +0, 1495, 1030, +0, 1559, 497, +0, 1634, 0, +0, 1717, 0, +0, 1809, 0, +0, 1909, 0, +0, 2015, 0, +0, 2127, 0, +0, 2243, 0, +0, 2363, 0, +0, 2486, 0, +0, 2611, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3254, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1237, 1547, +0, 1240, 1544, +0, 1245, 1540, +0, 1252, 1534, +0, 1260, 1527, +0, 1272, 1516, +0, 1286, 1502, +0, 1305, 1482, +0, 1329, 1454, +0, 1360, 1414, +0, 1397, 1354, +0, 1443, 1258, +0, 1498, 1088, +0, 1562, 662, +0, 1636, 0, +0, 1719, 0, +0, 1811, 0, +0, 1910, 0, +0, 2016, 0, +0, 2128, 0, +0, 2244, 0, +0, 2363, 0, +0, 2486, 0, +0, 2611, 0, +0, 2737, 0, +0, 2865, 0, +0, 2994, 0, +0, 3124, 0, +0, 3255, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +0, 1244, 1573, +0, 1248, 1570, +0, 1252, 1566, +0, 1259, 1561, +0, 1267, 1554, +0, 1278, 1544, +0, 1293, 1530, +0, 1311, 1512, +0, 1335, 1486, +0, 1365, 1448, +0, 1402, 1392, +0, 1448, 1306, +0, 1502, 1155, +0, 1566, 818, +0, 1639, 0, +0, 1722, 0, +0, 1813, 0, +0, 1912, 0, +0, 2017, 0, +0, 2129, 0, +0, 2244, 0, +0, 2364, 0, +0, 2486, 0, +0, 2611, 0, +0, 2738, 0, +0, 2866, 0, +0, 2995, 0, +0, 3124, 0, +0, 3255, 0, +0, 3385, 0, +0, 3516, 0, +0, 3648, 0, +664, 1253, 1605, +635, 1257, 1602, +593, 1262, 1599, +530, 1268, 1594, +428, 1276, 1587, +243, 1287, 1578, +0, 1301, 1566, +0, 1320, 1548, +0, 1343, 1524, +0, 1372, 1490, +0, 1409, 1440, +0, 1454, 1362, +0, 1507, 1232, +0, 1570, 966, +0, 1643, 0, +0, 1725, 0, +0, 1816, 0, +0, 1914, 0, +0, 2019, 0, +0, 2130, 0, +0, 2245, 0, +0, 2365, 0, +0, 2487, 0, +0, 2612, 0, +0, 2738, 0, +0, 2866, 0, +0, 2995, 0, +0, 3124, 0, +0, 3255, 0, +0, 3385, 0, +0, 3517, 0, +0, 3648, 0, +1063, 1266, 1645, +1051, 1269, 1642, +1034, 1274, 1639, +1011, 1280, 1635, +979, 1288, 1628, +931, 1299, 1620, +858, 1313, 1609, +738, 1330, 1593, +503, 1353, 1571, +0, 1382, 1541, +0, 1418, 1496, +0, 1462, 1428, +0, 1514, 1318, +0, 1577, 1110, +0, 1648, 435, +0, 1729, 0, +0, 1819, 0, +0, 1917, 0, +0, 2021, 0, +0, 2132, 0, +0, 2247, 0, +0, 2366, 0, +0, 2488, 0, +0, 2612, 0, +0, 2739, 0, +0, 2866, 0, +0, 2995, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +1325, 1282, 1693, +1318, 1285, 1691, +1309, 1290, 1688, +1297, 1296, 1684, +1280, 1303, 1678, +1256, 1314, 1671, +1222, 1327, 1661, +1172, 1344, 1647, +1095, 1366, 1628, +966, 1394, 1601, +704, 1429, 1562, +0, 1472, 1503, +0, 1524, 1412, +0, 1585, 1251, +0, 1655, 870, +0, 1735, 0, +0, 1824, 0, +0, 1921, 0, +0, 2024, 0, +0, 2134, 0, +0, 2249, 0, +0, 2367, 0, +0, 2489, 0, +0, 2613, 0, +0, 2739, 0, +0, 2867, 0, +0, 2995, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +1535, 1302, 1751, +1530, 1306, 1749, +1525, 1310, 1746, +1517, 1316, 1742, +1507, 1323, 1738, +1492, 1333, 1731, +1472, 1346, 1722, +1444, 1362, 1710, +1404, 1384, 1693, +1343, 1411, 1670, +1246, 1444, 1637, +1074, 1486, 1588, +636, 1536, 1514, +0, 1595, 1390, +0, 1664, 1144, +0, 1743, 0, +0, 1830, 0, +0, 1926, 0, +0, 2029, 0, +0, 2137, 0, +0, 2251, 0, +0, 2369, 0, +0, 2490, 0, +0, 2614, 0, +0, 2740, 0, +0, 2867, 0, +0, 2996, 0, +0, 3125, 0, +0, 3255, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +1717, 1329, 1818, +1714, 1332, 1816, +1711, 1336, 1814, +1706, 1341, 1811, +1699, 1348, 1806, +1689, 1357, 1801, +1676, 1370, 1793, +1659, 1385, 1783, +1634, 1406, 1769, +1598, 1431, 1749, +1546, 1464, 1721, +1465, 1503, 1681, +1327, 1552, 1621, +1035, 1609, 1527, +0, 1676, 1358, +0, 1753, 942, +0, 1839, 0, +0, 1933, 0, +0, 2034, 0, +0, 2142, 0, +0, 2255, 0, +0, 2372, 0, +0, 2492, 0, +0, 2616, 0, +0, 2741, 0, +0, 2868, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +1884, 1361, 1894, +1882, 1364, 1893, +1879, 1368, 1891, +1876, 1373, 1888, +1871, 1380, 1885, +1865, 1388, 1880, +1856, 1400, 1874, +1844, 1414, 1865, +1827, 1433, 1853, +1805, 1458, 1837, +1772, 1488, 1814, +1724, 1526, 1782, +1652, 1572, 1734, +1532, 1627, 1662, +1297, 1692, 1544, +234, 1766, 1313, +0, 1850, 322, +0, 1942, 0, +0, 2041, 0, +0, 2147, 0, +0, 2259, 0, +0, 2375, 0, +0, 2495, 0, +0, 2618, 0, +0, 2743, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3648, 0, +2040, 1402, 1980, +2038, 1405, 1979, +2037, 1408, 1977, +2034, 1413, 1975, +2031, 1419, 1972, +2026, 1427, 1968, +2020, 1437, 1963, +2012, 1451, 1956, +2001, 1468, 1946, +1985, 1491, 1933, +1964, 1519, 1914, +1933, 1555, 1889, +1888, 1598, 1852, +1821, 1650, 1797, +1712, 1712, 1712, +1507, 1783, 1566, +855, 1864, 1243, +0, 1953, 0, +0, 2051, 0, +0, 2155, 0, +0, 2265, 0, +0, 2380, 0, +0, 2499, 0, +0, 2620, 0, +0, 2745, 0, +0, 2871, 0, +0, 2999, 0, +0, 3127, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +2189, 1451, 2074, +2188, 1453, 2073, +2187, 1456, 2071, +2185, 1461, 2070, +2183, 1466, 2067, +2180, 1473, 2064, +2175, 1483, 2060, +2169, 1495, 2054, +2161, 1511, 2046, +2151, 1531, 2036, +2136, 1557, 2021, +2115, 1590, 2001, +2085, 1630, 1972, +2043, 1679, 1931, +1979, 1737, 1869, +1877, 1805, 1771, +1690, 1882, 1593, +1170, 1968, 1129, +0, 2063, 0, +0, 2165, 0, +0, 2273, 0, +0, 2386, 0, +0, 2503, 0, +0, 2624, 0, +0, 2747, 0, +0, 2873, 0, +0, 3000, 0, +0, 3128, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2334, 1509, 2175, +2333, 1511, 2174, +2332, 1514, 2173, +2331, 1518, 2172, +2329, 1522, 2170, +2327, 1529, 2167, +2324, 1537, 2164, +2319, 1548, 2159, +2314, 1562, 2153, +2306, 1581, 2145, +2295, 1604, 2134, +2281, 1634, 2118, +2261, 1671, 2096, +2232, 1716, 2065, +2191, 1769, 2019, +2130, 1833, 1951, +2032, 1906, 1839, +1856, 1988, 1628, +1402, 2079, 912, +0, 2177, 0, +0, 2283, 0, +0, 2394, 0, +0, 2509, 0, +0, 2629, 0, +0, 2751, 0, +0, 2876, 0, +0, 3002, 0, +0, 3130, 0, +0, 3259, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +2475, 1577, 2283, +2474, 1579, 2282, +2474, 1581, 2281, +2473, 1584, 2280, +2472, 1588, 2279, +2470, 1594, 2277, +2468, 1601, 2274, +2464, 1611, 2270, +2460, 1623, 2266, +2455, 1639, 2259, +2447, 1660, 2250, +2437, 1686, 2238, +2423, 1719, 2221, +2403, 1760, 2198, +2375, 1809, 2165, +2335, 1867, 2116, +2275, 1935, 2041, +2181, 2013, 1917, +2012, 2099, 1670, +1597, 2194, 135, +0, 2296, 0, +0, 2404, 0, +0, 2517, 0, +0, 2635, 0, +0, 2756, 0, +0, 2879, 0, +0, 3005, 0, +0, 3132, 0, +0, 3260, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2614, 1654, 2395, +2613, 1656, 2395, +2613, 1658, 2394, +2612, 1660, 2393, +2611, 1664, 2392, +2610, 1669, 2391, +2608, 1675, 2389, +2606, 1683, 2386, +2603, 1694, 2382, +2599, 1707, 2377, +2593, 1725, 2370, +2586, 1748, 2361, +2576, 1777, 2348, +2562, 1813, 2331, +2542, 1857, 2306, +2515, 1910, 2271, +2476, 1972, 2219, +2417, 2044, 2139, +2325, 2125, 2004, +2162, 2215, 1721, +1771, 2313, 0, +0, 2417, 0, +0, 2528, 0, +0, 2643, 0, +0, 2762, 0, +0, 2884, 0, +0, 3009, 0, +0, 3135, 0, +0, 3263, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +2751, 1741, 2513, +2750, 1742, 2512, +2750, 1744, 2512, +2750, 1746, 2511, +2749, 1749, 2510, +2748, 1753, 2509, +2747, 1758, 2507, +2745, 1764, 2505, +2743, 1773, 2502, +2740, 1785, 2499, +2736, 1800, 2493, +2730, 1819, 2486, +2723, 1844, 2477, +2713, 1875, 2464, +2699, 1914, 2445, +2680, 1961, 2420, +2653, 2017, 2383, +2614, 2083, 2329, +2556, 2158, 2244, +2466, 2242, 2099, +2306, 2335, 1782, +1932, 2435, 0, +0, 2542, 0, +0, 2654, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +2887, 1835, 2633, +2886, 1836, 2633, +2886, 1838, 2633, +2886, 1839, 2632, +2885, 1842, 2631, +2884, 1845, 2630, +2884, 1849, 2629, +2882, 1855, 2628, +2881, 1862, 2625, +2878, 1872, 2623, +2875, 1884, 2619, +2871, 1900, 2613, +2866, 1921, 2606, +2859, 1948, 2596, +2849, 1981, 2582, +2835, 2021, 2564, +2816, 2071, 2537, +2789, 2130, 2499, +2751, 2198, 2443, +2694, 2275, 2355, +2604, 2362, 2201, +2447, 2457, 1852, +2084, 2559, 0, +0, 2668, 0, +0, 2781, 0, +0, 2899, 0, +0, 3020, 0, +0, 3143, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +3021, 1937, 2757, +3021, 1938, 2756, +3021, 1939, 2756, +3021, 1940, 2756, +3020, 1942, 2755, +3020, 1945, 2754, +3019, 1948, 2754, +3018, 1953, 2752, +3017, 1959, 2751, +3015, 1966, 2748, +3013, 1977, 2745, +3010, 1990, 2741, +3006, 2007, 2736, +3001, 2029, 2728, +2994, 2057, 2718, +2984, 2092, 2705, +2970, 2134, 2685, +2951, 2186, 2658, +2924, 2247, 2619, +2886, 2317, 2561, +2830, 2397, 2470, +2741, 2485, 2310, +2586, 2582, 1931, +2231, 2685, 0, +0, 2795, 0, +0, 2910, 0, +0, 3028, 0, +0, 3150, 0, +0, 3274, 0, +0, 3400, 0, +0, 3527, 0, +0, 3656, 0, +3155, 2045, 2882, +3155, 2046, 2882, +3155, 2047, 2882, +3155, 2048, 2881, +3155, 2049, 2881, +3154, 2051, 2880, +3154, 2054, 2880, +3153, 2057, 2879, +3152, 2062, 2877, +3151, 2068, 2876, +3149, 2077, 2874, +3147, 2087, 2870, +3144, 2101, 2866, +3140, 2119, 2861, +3135, 2142, 2853, +3128, 2171, 2843, +3118, 2207, 2829, +3104, 2251, 2809, +3085, 2304, 2782, +3059, 2367, 2742, +3021, 2439, 2683, +2965, 2520, 2589, +2877, 2610, 2423, +2723, 2708, 2020, +2374, 2813, 0, +0, 2924, 0, +0, 3039, 0, +0, 3158, 0, +0, 3280, 0, +0, 3405, 0, +0, 3531, 0, +0, 3659, 0, +3289, 2158, 3009, +3289, 2159, 3009, +3289, 2160, 3009, +3289, 2160, 3009, +3288, 2162, 3008, +3288, 2163, 3008, +3288, 2165, 3007, +3287, 2168, 3007, +3287, 2172, 3006, +3286, 2177, 3004, +3285, 2183, 3003, +3283, 2192, 3000, +3281, 2203, 2997, +3278, 2217, 2993, +3274, 2236, 2988, +3269, 2259, 2980, +3261, 2289, 2969, +3251, 2326, 2955, +3238, 2372, 2935, +3219, 2426, 2907, +3193, 2490, 2867, +3155, 2563, 2807, +3099, 2646, 2711, +3011, 2737, 2541, +2859, 2836, 2116, +2514, 2942, 0, +0, 3053, 0, +0, 3169, 0, +0, 3289, 0, +0, 3411, 0, +0, 3536, 0, +0, 3662, 0, +3422, 2276, 3137, +3422, 2276, 3137, +3422, 2277, 3137, +3422, 2278, 3137, +3422, 2278, 3137, +3422, 2280, 3136, +3421, 2281, 3136, +3421, 2283, 3135, +3420, 2286, 3135, +3420, 2290, 3134, +3419, 2295, 3133, +3418, 2302, 3131, +3416, 2310, 3128, +3414, 2322, 3125, +3411, 2337, 3121, +3407, 2356, 3115, +3402, 2380, 3108, +3394, 2411, 3097, +3385, 2449, 3083, +3371, 2495, 3063, +3352, 2551, 3035, +3326, 2615, 2994, +3289, 2690, 2933, +3233, 2773, 2836, +3145, 2866, 2662, +2994, 2965, 2219, +2652, 3072, 0, +0, 3183, 0, +0, 3300, 0, +0, 3420, 0, +0, 3542, 0, +0, 3667, 0, +3555, 2397, 3267, +3555, 2397, 3266, +3555, 2398, 3266, +3555, 2398, 3266, +3555, 2399, 3266, +3555, 2400, 3266, +3555, 2401, 3266, +3554, 2403, 3265, +3554, 2405, 3265, +3553, 2408, 3264, +3553, 2412, 3263, +3552, 2417, 3262, +3551, 2423, 3260, +3549, 2432, 3258, +3547, 2444, 3254, +3544, 2459, 3250, +3540, 2479, 3245, +3535, 2504, 3237, +3527, 2535, 3226, +3518, 2573, 3212, +3504, 2621, 3191, +3485, 2677, 3163, +3459, 2742, 3122, +3422, 2818, 3060, +3366, 2902, 2962, +3279, 2995, 2786, +3128, 3095, 2329, +2788, 3202, 0, +0, 3314, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +3688, 2520, 3396, +3688, 2521, 3396, +3688, 2521, 3396, +3688, 2521, 3396, +3688, 2522, 3396, +3688, 2522, 3396, +3687, 2523, 3396, +3687, 2525, 3395, +3687, 2526, 3395, +3687, 2529, 3394, +3686, 2532, 3394, +3685, 2536, 3393, +3684, 2541, 3391, +3683, 2548, 3390, +3682, 2557, 3387, +3679, 2569, 3384, +3677, 2584, 3380, +3673, 2604, 3374, +3667, 2629, 3366, +3660, 2661, 3356, +3650, 2700, 3341, +3637, 2748, 3321, +3618, 2804, 3292, +3592, 2871, 3251, +3555, 2946, 3189, +3499, 3031, 3090, +3412, 3125, 2912, +3262, 3225, 2443, +2923, 3332, 0, +0, 3445, 0, +0, 3562, 0, +0, 3682, 0, +3820, 2646, 3527, +3820, 2646, 3527, +3820, 2646, 3527, +3820, 2647, 3527, +3820, 2647, 3527, +3820, 2648, 3527, +3820, 2648, 3526, +3820, 2649, 3526, +3820, 2651, 3526, +3819, 2652, 3525, +3819, 2654, 3525, +3819, 2658, 3524, +3818, 2662, 3523, +3817, 2667, 3522, +3816, 2674, 3520, +3814, 2683, 3518, +3812, 2695, 3515, +3809, 2711, 3510, +3805, 2731, 3505, +3800, 2756, 3497, +3793, 2788, 3486, +3783, 2828, 3471, +3769, 2876, 3451, +3751, 2933, 3422, +3725, 3000, 3381, +3687, 3076, 3318, +3632, 3161, 3219, +3545, 3255, 3039, +3395, 3356, 2562, +3058, 3463, 0, +0, 3576, 0, +0, 3693, 0, +3953, 2773, 3658, +3953, 2773, 3658, +3953, 2773, 3658, +3953, 2774, 3658, +3953, 2774, 3658, +3953, 2774, 3658, +3953, 2775, 3657, +3953, 2776, 3657, +3952, 2777, 3657, +3952, 2778, 3657, +3952, 2780, 3656, +3952, 2782, 3656, +3951, 2785, 3655, +3950, 2789, 3654, +3949, 2794, 3653, +3948, 2801, 3651, +3947, 2811, 3649, +3944, 2823, 3645, +3942, 2839, 3641, +3938, 2859, 3635, +3932, 2885, 3628, +3925, 2917, 3617, +3915, 2957, 3602, +3902, 3005, 3582, +3883, 3063, 3553, +3857, 3130, 3511, +3820, 3206, 3449, +3764, 3292, 3349, +3678, 3386, 3167, +3528, 3487, 2683, +3192, 3595, 0, +0, 3708, 0, +4085, 2901, 3789, +4085, 2902, 3789, +4085, 2902, 3789, +4085, 2902, 3789, +4085, 2902, 3789, +4085, 2902, 3789, +4085, 2903, 3789, +4085, 2903, 3789, +4085, 2904, 3788, +4085, 2905, 3788, +4085, 2906, 3788, +4084, 2908, 3787, +4084, 2910, 3787, +4083, 2913, 3786, +4083, 2918, 3785, +4082, 2923, 3784, +4081, 2930, 3782, +4079, 2939, 3780, +4077, 2952, 3777, +4074, 2968, 3772, +4070, 2988, 3767, +4065, 3014, 3759, +4058, 3046, 3748, +4048, 3086, 3733, +4034, 3135, 3713, +4016, 3193, 3684, +3990, 3260, 3642, +3952, 3337, 3579, +3897, 3423, 3479, +3810, 3517, 3297, +3660, 3618, 2807, +3325, 3726, 0, +4095, 3031, 3920, +4095, 3031, 3920, +4095, 3031, 3920, +4095, 3031, 3920, +4095, 3031, 3920, +4095, 3031, 3920, +4095, 3032, 3920, +4095, 3032, 3920, +4095, 3033, 3920, +4095, 3033, 3920, +4095, 3034, 3920, +4095, 3036, 3919, +4095, 3037, 3919, +4095, 3040, 3918, +4095, 3043, 3918, +4095, 3047, 3917, +4095, 3052, 3915, +4095, 3060, 3914, +4095, 3069, 3911, +4095, 3081, 3908, +4095, 3097, 3904, +4095, 3118, 3898, +4095, 3144, 3890, +4095, 3176, 3879, +4095, 3217, 3864, +4095, 3265, 3844, +4095, 3323, 3815, +4095, 3391, 3773, +4085, 3468, 3710, +4029, 3554, 3610, +3943, 3648, 3427, +3793, 3750, 2933, +4095, 3161, 4052, +4095, 3161, 4052, +4095, 3161, 4052, +4095, 3161, 4052, +4095, 3161, 4052, +4095, 3161, 4052, +4095, 3161, 4052, +4095, 3162, 4052, +4095, 3162, 4052, +4095, 3163, 4052, +4095, 3163, 4051, +4095, 3164, 4051, +4095, 3166, 4051, +4095, 3168, 4050, +4095, 3170, 4050, +4095, 3173, 4049, +4095, 3177, 4048, +4095, 3183, 4047, +4095, 3190, 4045, +4095, 3199, 4043, +4095, 3212, 4040, +4095, 3228, 4035, +4095, 3248, 4029, +4095, 3274, 4022, +4095, 3307, 4011, +4095, 3347, 3996, +4095, 3396, 3975, +4095, 3454, 3946, +4095, 3522, 3904, +4095, 3599, 3841, +4095, 3685, 3741, +4075, 3780, 3557, +0, 1347, 1608, +0, 1350, 1606, +0, 1354, 1602, +0, 1359, 1597, +0, 1365, 1590, +0, 1374, 1581, +0, 1386, 1569, +0, 1401, 1552, +0, 1421, 1528, +0, 1446, 1494, +0, 1477, 1444, +0, 1516, 1367, +0, 1563, 1239, +0, 1619, 979, +0, 1685, 0, +0, 1760, 0, +0, 1845, 0, +0, 1938, 0, +0, 2038, 0, +0, 2145, 0, +0, 2257, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +0, 1348, 1612, +0, 1351, 1610, +0, 1354, 1606, +0, 1360, 1601, +0, 1366, 1595, +0, 1375, 1586, +0, 1387, 1573, +0, 1402, 1557, +0, 1422, 1533, +0, 1447, 1499, +0, 1478, 1450, +0, 1516, 1374, +0, 1564, 1248, +0, 1620, 995, +0, 1685, 0, +0, 1761, 0, +0, 1845, 0, +0, 1938, 0, +0, 2038, 0, +0, 2145, 0, +0, 2257, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +0, 1349, 1618, +0, 1352, 1615, +0, 1356, 1611, +0, 1361, 1607, +0, 1368, 1600, +0, 1377, 1591, +0, 1388, 1579, +0, 1403, 1563, +0, 1423, 1539, +0, 1448, 1506, +0, 1479, 1457, +0, 1517, 1383, +0, 1564, 1260, +0, 1620, 1015, +0, 1686, 0, +0, 1761, 0, +0, 1845, 0, +0, 1938, 0, +0, 2038, 0, +0, 2145, 0, +0, 2257, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +0, 1351, 1625, +0, 1354, 1622, +0, 1358, 1619, +0, 1363, 1614, +0, 1369, 1607, +0, 1378, 1599, +0, 1390, 1587, +0, 1405, 1570, +0, 1424, 1548, +0, 1449, 1515, +0, 1480, 1467, +0, 1519, 1395, +0, 1565, 1275, +0, 1621, 1041, +0, 1687, 0, +0, 1762, 0, +0, 1846, 0, +0, 1939, 0, +0, 2039, 0, +0, 2145, 0, +0, 2258, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +0, 1353, 1634, +0, 1356, 1631, +0, 1360, 1628, +0, 1365, 1623, +0, 1372, 1617, +0, 1381, 1608, +0, 1392, 1597, +0, 1407, 1581, +0, 1426, 1558, +0, 1451, 1527, +0, 1482, 1480, +0, 1520, 1410, +0, 1567, 1295, +0, 1623, 1074, +0, 1688, 244, +0, 1763, 0, +0, 1847, 0, +0, 1939, 0, +0, 2039, 0, +0, 2146, 0, +0, 2258, 0, +0, 2374, 0, +0, 2494, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3386, 0, +0, 3517, 0, +0, 3648, 0, +0, 1356, 1646, +0, 1359, 1643, +0, 1363, 1640, +0, 1368, 1636, +0, 1375, 1629, +0, 1383, 1621, +0, 1395, 1610, +0, 1410, 1594, +0, 1429, 1573, +0, 1453, 1542, +0, 1484, 1497, +0, 1522, 1430, +0, 1569, 1320, +0, 1624, 1114, +0, 1690, 449, +0, 1764, 0, +0, 1848, 0, +0, 1940, 0, +0, 2040, 0, +0, 2146, 0, +0, 2258, 0, +0, 2375, 0, +0, 2495, 0, +0, 2617, 0, +0, 2742, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3648, 0, +0, 1360, 1662, +0, 1363, 1659, +0, 1367, 1656, +0, 1372, 1652, +0, 1379, 1646, +0, 1387, 1638, +0, 1399, 1627, +0, 1414, 1612, +0, 1433, 1591, +0, 1457, 1561, +0, 1487, 1519, +0, 1525, 1455, +0, 1572, 1351, +0, 1627, 1162, +0, 1692, 629, +0, 1766, 0, +0, 1849, 0, +0, 1941, 0, +0, 2041, 0, +0, 2147, 0, +0, 2259, 0, +0, 2375, 0, +0, 2495, 0, +0, 2618, 0, +0, 2743, 0, +0, 2869, 0, +0, 2997, 0, +0, 3126, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3648, 0, +0, 1366, 1682, +0, 1369, 1679, +0, 1373, 1676, +0, 1377, 1672, +0, 1384, 1666, +0, 1393, 1659, +0, 1404, 1648, +0, 1418, 1634, +0, 1437, 1614, +0, 1461, 1586, +0, 1492, 1546, +0, 1529, 1486, +0, 1575, 1390, +0, 1630, 1220, +0, 1694, 795, +0, 1768, 0, +0, 1851, 0, +0, 1943, 0, +0, 2042, 0, +0, 2148, 0, +0, 2260, 0, +0, 2376, 0, +0, 2495, 0, +0, 2618, 0, +0, 2743, 0, +0, 2870, 0, +0, 2998, 0, +0, 3127, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3649, 0, +0, 1373, 1707, +0, 1376, 1705, +0, 1380, 1702, +0, 1385, 1698, +0, 1391, 1693, +0, 1399, 1686, +0, 1411, 1676, +0, 1425, 1662, +0, 1444, 1644, +0, 1467, 1618, +0, 1497, 1580, +0, 1534, 1525, +0, 1580, 1438, +0, 1634, 1287, +0, 1698, 950, +0, 1771, 0, +0, 1854, 0, +0, 1945, 0, +0, 2044, 0, +0, 2149, 0, +0, 2261, 0, +0, 2377, 0, +0, 2496, 0, +0, 2619, 0, +0, 2743, 0, +0, 2870, 0, +0, 2998, 0, +0, 3127, 0, +0, 3256, 0, +0, 3387, 0, +0, 3517, 0, +0, 3649, 0, +817, 1383, 1739, +796, 1385, 1737, +767, 1389, 1734, +725, 1394, 1731, +662, 1400, 1726, +560, 1408, 1719, +375, 1419, 1710, +0, 1433, 1698, +0, 1452, 1680, +0, 1475, 1656, +0, 1504, 1622, +0, 1541, 1572, +0, 1586, 1494, +0, 1639, 1364, +0, 1702, 1098, +0, 1775, 0, +0, 1857, 0, +0, 1948, 0, +0, 2046, 0, +0, 2151, 0, +0, 2262, 0, +0, 2378, 0, +0, 2497, 0, +0, 2619, 0, +0, 2744, 0, +0, 2870, 0, +0, 2998, 0, +0, 3127, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +1204, 1395, 1779, +1195, 1398, 1777, +1183, 1401, 1775, +1166, 1406, 1771, +1143, 1412, 1767, +1111, 1420, 1761, +1063, 1431, 1752, +990, 1445, 1741, +870, 1462, 1725, +635, 1485, 1704, +0, 1514, 1673, +0, 1550, 1628, +0, 1594, 1560, +0, 1646, 1450, +0, 1709, 1243, +0, 1780, 567, +0, 1861, 0, +0, 1951, 0, +0, 2049, 0, +0, 2154, 0, +0, 2264, 0, +0, 2379, 0, +0, 2498, 0, +0, 2620, 0, +0, 2744, 0, +0, 2871, 0, +0, 2998, 0, +0, 3127, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +1462, 1411, 1827, +1457, 1414, 1825, +1450, 1417, 1823, +1441, 1422, 1820, +1429, 1428, 1816, +1412, 1436, 1811, +1388, 1446, 1803, +1354, 1459, 1793, +1304, 1476, 1779, +1227, 1498, 1760, +1098, 1526, 1733, +836, 1561, 1694, +0, 1604, 1636, +0, 1656, 1544, +0, 1717, 1383, +0, 1787, 1003, +0, 1867, 0, +0, 1956, 0, +0, 2053, 0, +0, 2157, 0, +0, 2266, 0, +0, 2381, 0, +0, 2499, 0, +0, 2621, 0, +0, 2745, 0, +0, 2871, 0, +0, 2999, 0, +0, 3128, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +1670, 1432, 1884, +1667, 1435, 1883, +1663, 1438, 1881, +1657, 1442, 1878, +1649, 1448, 1875, +1639, 1455, 1870, +1624, 1465, 1863, +1604, 1478, 1854, +1576, 1494, 1842, +1536, 1516, 1826, +1475, 1543, 1802, +1378, 1576, 1769, +1206, 1618, 1720, +769, 1668, 1646, +0, 1728, 1522, +0, 1797, 1276, +0, 1875, 0, +0, 1962, 0, +0, 2058, 0, +0, 2161, 0, +0, 2270, 0, +0, 2383, 0, +0, 2501, 0, +0, 2623, 0, +0, 2746, 0, +0, 2872, 0, +0, 3000, 0, +0, 3128, 0, +0, 3257, 0, +0, 3387, 0, +0, 3518, 0, +0, 3649, 0, +1851, 1458, 1951, +1849, 1461, 1950, +1847, 1464, 1948, +1843, 1468, 1946, +1838, 1473, 1943, +1831, 1480, 1939, +1821, 1490, 1933, +1809, 1502, 1925, +1791, 1517, 1915, +1766, 1538, 1901, +1730, 1563, 1881, +1678, 1596, 1853, +1597, 1636, 1813, +1459, 1684, 1753, +1167, 1741, 1659, +0, 1809, 1491, +0, 1885, 1074, +0, 1971, 0, +0, 2065, 0, +0, 2166, 0, +0, 2274, 0, +0, 2387, 0, +0, 2504, 0, +0, 2625, 0, +0, 2748, 0, +0, 2873, 0, +0, 3000, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +2017, 1491, 2027, +2016, 1494, 2026, +2014, 1496, 2025, +2011, 1500, 2023, +2008, 1505, 2020, +2003, 1512, 2017, +1997, 1520, 2012, +1988, 1532, 2006, +1976, 1547, 1997, +1960, 1566, 1985, +1937, 1590, 1969, +1904, 1620, 1946, +1856, 1658, 1914, +1784, 1704, 1867, +1664, 1759, 1794, +1430, 1824, 1676, +367, 1898, 1445, +0, 1982, 454, +0, 2074, 0, +0, 2173, 0, +0, 2279, 0, +0, 2391, 0, +0, 2507, 0, +0, 2627, 0, +0, 2750, 0, +0, 2875, 0, +0, 3002, 0, +0, 3130, 0, +0, 3259, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +2173, 1532, 2113, +2172, 1534, 2112, +2171, 1537, 2111, +2169, 1540, 2109, +2166, 1545, 2107, +2163, 1551, 2104, +2158, 1559, 2100, +2152, 1569, 2095, +2144, 1583, 2088, +2133, 1600, 2078, +2117, 1623, 2065, +2096, 1651, 2047, +2065, 1687, 2021, +2021, 1730, 1984, +1953, 1782, 1929, +1844, 1844, 1844, +1639, 1915, 1698, +988, 1996, 1375, +0, 2085, 0, +0, 2183, 0, +0, 2287, 0, +0, 2397, 0, +0, 2512, 0, +0, 2631, 0, +0, 2753, 0, +0, 2877, 0, +0, 3003, 0, +0, 3131, 0, +0, 3259, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +2322, 1581, 2206, +2321, 1583, 2206, +2320, 1585, 2205, +2319, 1588, 2204, +2317, 1593, 2202, +2315, 1598, 2199, +2312, 1605, 2196, +2307, 1615, 2192, +2301, 1627, 2186, +2293, 1643, 2179, +2283, 1663, 2168, +2268, 1690, 2153, +2247, 1722, 2133, +2218, 1763, 2105, +2175, 1811, 2063, +2111, 1870, 2001, +2009, 1937, 1903, +1822, 2014, 1725, +1302, 2100, 1261, +0, 2195, 0, +0, 2297, 0, +0, 2405, 0, +0, 2518, 0, +0, 2635, 0, +0, 2756, 0, +0, 2880, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2466, 1640, 2308, +2466, 1641, 2307, +2465, 1643, 2306, +2464, 1646, 2305, +2463, 1650, 2304, +2461, 1655, 2302, +2459, 1661, 2299, +2456, 1669, 2296, +2451, 1680, 2292, +2446, 1694, 2285, +2438, 1713, 2277, +2427, 1736, 2266, +2413, 1766, 2250, +2393, 1803, 2228, +2364, 1848, 2197, +2323, 1902, 2152, +2262, 1965, 2083, +2164, 2038, 1971, +1988, 2120, 1760, +1534, 2211, 1044, +0, 2309, 0, +0, 2415, 0, +0, 2526, 0, +0, 2641, 0, +0, 2761, 0, +0, 2883, 0, +0, 3008, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +2607, 1708, 2415, +2607, 1709, 2415, +2607, 1711, 2414, +2606, 1713, 2413, +2605, 1716, 2412, +2604, 1721, 2411, +2602, 1726, 2409, +2600, 1733, 2406, +2597, 1743, 2402, +2592, 1755, 2398, +2587, 1771, 2391, +2579, 1792, 2382, +2569, 1818, 2370, +2555, 1851, 2353, +2535, 1892, 2330, +2507, 1941, 2297, +2467, 1999, 2248, +2407, 2067, 2173, +2313, 2145, 2049, +2144, 2231, 1802, +1729, 2326, 267, +0, 2428, 0, +0, 2536, 0, +0, 2649, 0, +0, 2767, 0, +0, 2888, 0, +0, 3011, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +2746, 1785, 2528, +2746, 1786, 2528, +2745, 1788, 2527, +2745, 1790, 2526, +2744, 1793, 2526, +2743, 1796, 2524, +2742, 1801, 2523, +2740, 1807, 2521, +2738, 1815, 2518, +2735, 1826, 2514, +2731, 1839, 2509, +2726, 1857, 2502, +2718, 1880, 2493, +2708, 1909, 2480, +2694, 1945, 2463, +2674, 1989, 2438, +2647, 2042, 2403, +2608, 2104, 2351, +2549, 2176, 2271, +2457, 2257, 2136, +2294, 2347, 1853, +1903, 2445, 0, +0, 2549, 0, +0, 2660, 0, +0, 2775, 0, +0, 2894, 0, +0, 3016, 0, +0, 3141, 0, +0, 3267, 0, +0, 3395, 0, +0, 3523, 0, +0, 3653, 0, +2883, 1872, 2645, +2883, 1873, 2645, +2883, 1874, 2644, +2882, 1876, 2644, +2882, 1878, 2643, +2881, 1881, 2642, +2880, 1885, 2641, +2879, 1890, 2640, +2877, 1897, 2637, +2875, 1905, 2635, +2872, 1917, 2631, +2868, 1932, 2625, +2862, 1952, 2618, +2855, 1976, 2609, +2845, 2008, 2596, +2831, 2046, 2577, +2812, 2093, 2552, +2785, 2149, 2515, +2746, 2215, 2461, +2688, 2290, 2376, +2598, 2374, 2231, +2438, 2467, 1914, +2064, 2567, 0, +0, 2674, 0, +0, 2786, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3271, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +3019, 1967, 2766, +3019, 1967, 2765, +3018, 1968, 2765, +3018, 1970, 2765, +3018, 1971, 2764, +3017, 1974, 2763, +3017, 1977, 2763, +3016, 1981, 2761, +3014, 1987, 2760, +3013, 1994, 2758, +3011, 2004, 2755, +3008, 2016, 2751, +3004, 2032, 2745, +2998, 2053, 2738, +2991, 2080, 2728, +2981, 2113, 2715, +2967, 2154, 2696, +2948, 2203, 2669, +2921, 2262, 2631, +2883, 2330, 2575, +2826, 2408, 2487, +2736, 2494, 2334, +2580, 2589, 1984, +2216, 2691, 0, +0, 2800, 0, +0, 2913, 0, +0, 3031, 0, +0, 3152, 0, +0, 3275, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3154, 2069, 2889, +3153, 2069, 2889, +3153, 2070, 2888, +3153, 2071, 2888, +3153, 2072, 2888, +3152, 2074, 2887, +3152, 2077, 2887, +3151, 2080, 2886, +3150, 2085, 2884, +3149, 2091, 2883, +3147, 2098, 2881, +3145, 2109, 2878, +3142, 2122, 2873, +3138, 2139, 2868, +3133, 2161, 2861, +3126, 2189, 2850, +3116, 2224, 2837, +3102, 2266, 2817, +3083, 2318, 2790, +3057, 2379, 2751, +3018, 2449, 2693, +2962, 2529, 2602, +2873, 2617, 2442, +2718, 2714, 2063, +2363, 2818, 0, +0, 2927, 0, +0, 3042, 0, +0, 3160, 0, +0, 3282, 0, +0, 3406, 0, +0, 3532, 0, +0, 3659, 0, +3288, 2177, 3014, +3288, 2177, 3014, +3287, 2178, 3014, +3287, 2179, 3014, +3287, 2180, 3013, +3287, 2181, 3013, +3286, 2183, 3012, +3286, 2186, 3012, +3285, 2190, 3011, +3284, 2194, 3010, +3283, 2200, 3008, +3281, 2209, 3006, +3279, 2219, 3003, +3276, 2233, 2998, +3272, 2251, 2993, +3267, 2274, 2985, +3260, 2303, 2975, +3250, 2339, 2961, +3236, 2383, 2941, +3217, 2437, 2914, +3191, 2499, 2874, +3153, 2571, 2815, +3097, 2652, 2721, +3009, 2743, 2556, +2855, 2840, 2152, +2506, 2945, 0, +0, 3056, 0, +0, 3171, 0, +0, 3290, 0, +0, 3412, 0, +0, 3537, 0, +0, 3663, 0, +3421, 2290, 3141, +3421, 2291, 3141, +3421, 2291, 3141, +3421, 2292, 3141, +3421, 2293, 3141, +3421, 2294, 3140, +3420, 2295, 3140, +3420, 2297, 3139, +3419, 2300, 3139, +3419, 2304, 3138, +3418, 2309, 3136, +3417, 2315, 3135, +3415, 2324, 3132, +3413, 2335, 3129, +3410, 2349, 3125, +3406, 2368, 3120, +3401, 2392, 3112, +3393, 2421, 3102, +3384, 2459, 3087, +3370, 2504, 3067, +3351, 2558, 3039, +3325, 2622, 2999, +3287, 2696, 2939, +3231, 2778, 2844, +3143, 2869, 2673, +2991, 2968, 2248, +2646, 3074, 0, +0, 3185, 0, +0, 3301, 0, +0, 3421, 0, +0, 3543, 0, +0, 3668, 0, +3554, 2408, 3269, +3554, 2408, 3269, +3554, 2408, 3269, +3554, 2409, 3269, +3554, 2410, 3269, +3554, 2411, 3269, +3554, 2412, 3268, +3553, 2413, 3268, +3553, 2416, 3268, +3553, 2418, 3267, +3552, 2422, 3266, +3551, 2427, 3265, +3550, 2434, 3263, +3548, 2443, 3261, +3546, 2454, 3257, +3543, 2469, 3253, +3539, 2488, 3248, +3534, 2512, 3240, +3527, 2543, 3229, +3517, 2581, 3215, +3503, 2627, 3195, +3485, 2683, 3167, +3458, 2747, 3126, +3421, 2822, 3065, +3365, 2905, 2968, +3277, 2998, 2794, +3126, 3097, 2352, +2784, 3204, 0, +0, 3315, 0, +0, 3432, 0, +0, 3552, 0, +0, 3674, 0, +3687, 2529, 3399, +3687, 2529, 3399, +3687, 2529, 3399, +3687, 2530, 3398, +3687, 2530, 3398, +3687, 2531, 3398, +3687, 2532, 3398, +3687, 2533, 3398, +3686, 2535, 3397, +3686, 2537, 3397, +3685, 2540, 3396, +3685, 2544, 3395, +3684, 2549, 3394, +3683, 2556, 3392, +3681, 2565, 3390, +3679, 2576, 3387, +3676, 2591, 3382, +3672, 2611, 3377, +3667, 2636, 3369, +3660, 2667, 3358, +3650, 2706, 3344, +3636, 2753, 3324, +3618, 2809, 3295, +3591, 2874, 3254, +3554, 2950, 3192, +3498, 3034, 3094, +3411, 3127, 2918, +3260, 3227, 2461, +2920, 3334, 0, +0, 3446, 0, +0, 3563, 0, +0, 3683, 0, +3820, 2652, 3529, +3820, 2652, 3529, +3820, 2653, 3528, +3820, 2653, 3528, +3820, 2653, 3528, +3820, 2654, 3528, +3820, 2655, 3528, +3820, 2656, 3528, +3819, 2657, 3528, +3819, 2658, 3527, +3819, 2661, 3527, +3818, 2664, 3526, +3817, 2668, 3525, +3817, 2673, 3524, +3815, 2680, 3522, +3814, 2689, 3519, +3812, 2701, 3516, +3809, 2716, 3512, +3805, 2736, 3506, +3799, 2761, 3499, +3792, 2793, 3488, +3782, 2832, 3473, +3769, 2880, 3453, +3750, 2936, 3424, +3724, 3003, 3383, +3687, 3078, 3321, +3631, 3163, 3222, +3544, 3257, 3044, +3394, 3357, 2575, +3056, 3465, 0, +0, 3577, 0, +0, 3694, 0, +3953, 2778, 3659, +3953, 2778, 3659, +3953, 2778, 3659, +3953, 2778, 3659, +3952, 2779, 3659, +3952, 2779, 3659, +3952, 2780, 3659, +3952, 2780, 3658, +3952, 2781, 3658, +3952, 2783, 3658, +3952, 2784, 3658, +3951, 2787, 3657, +3951, 2790, 3656, +3950, 2794, 3655, +3949, 2799, 3654, +3948, 2806, 3652, +3946, 2815, 3650, +3944, 2827, 3647, +3941, 2843, 3642, +3937, 2863, 3637, +3932, 2888, 3629, +3925, 2920, 3618, +3915, 2960, 3604, +3902, 3008, 3583, +3883, 3065, 3554, +3857, 3132, 3513, +3819, 3208, 3450, +3764, 3293, 3351, +3677, 3387, 3171, +3527, 3488, 2694, +3190, 3596, 0, +0, 3708, 0, +4085, 2905, 3790, +4085, 2905, 3790, +4085, 2905, 3790, +4085, 2905, 3790, +4085, 2906, 3790, +4085, 2906, 3790, +4085, 2906, 3790, +4085, 2907, 3789, +4085, 2908, 3789, +4084, 2909, 3789, +4084, 2910, 3789, +4084, 2912, 3788, +4084, 2914, 3788, +4083, 2917, 3787, +4082, 2921, 3786, +4082, 2926, 3785, +4080, 2933, 3783, +4079, 2943, 3781, +4077, 2955, 3778, +4074, 2971, 3773, +4070, 2991, 3768, +4064, 3017, 3760, +4057, 3049, 3749, +4047, 3089, 3734, +4034, 3137, 3714, +4015, 3195, 3685, +3989, 3262, 3643, +3952, 3338, 3581, +3896, 3424, 3481, +3810, 3518, 3299, +3660, 3619, 2815, +3324, 3727, 0, +4095, 3033, 3921, +4095, 3034, 3921, +4095, 3034, 3921, +4095, 3034, 3921, +4095, 3034, 3921, +4095, 3034, 3921, +4095, 3034, 3921, +4095, 3035, 3921, +4095, 3035, 3921, +4095, 3036, 3920, +4095, 3037, 3920, +4095, 3038, 3920, +4095, 3040, 3920, +4095, 3042, 3919, +4095, 3046, 3918, +4095, 3050, 3917, +4095, 3055, 3916, +4095, 3062, 3914, +4095, 3072, 3912, +4095, 3084, 3909, +4095, 3100, 3904, +4095, 3120, 3899, +4095, 3146, 3891, +4095, 3178, 3880, +4095, 3218, 3865, +4095, 3267, 3845, +4095, 3325, 3816, +4095, 3392, 3774, +4084, 3469, 3711, +4029, 3555, 3611, +3942, 3649, 3429, +3793, 3751, 2939, +4095, 3163, 4053, +4095, 3163, 4052, +4095, 3163, 4052, +4095, 3163, 4052, +4095, 3163, 4052, +4095, 3163, 4052, +4095, 3164, 4052, +4095, 3164, 4052, +4095, 3164, 4052, +4095, 3165, 4052, +4095, 3166, 4052, +4095, 3167, 4052, +4095, 3168, 4051, +4095, 3170, 4051, +4095, 3172, 4050, +4095, 3175, 4050, +4095, 3179, 4049, +4095, 3185, 4047, +4095, 3192, 4046, +4095, 3201, 4043, +4095, 3213, 4040, +4095, 3229, 4036, +4095, 3250, 4030, +4095, 3276, 4022, +4095, 3308, 4011, +4095, 3349, 3997, +4095, 3397, 3976, +4095, 3455, 3947, +4095, 3523, 3905, +4095, 3600, 3842, +4095, 3686, 3742, +4075, 3780, 3559, +0, 1476, 1739, +0, 1478, 1737, +0, 1481, 1735, +0, 1485, 1731, +0, 1490, 1726, +0, 1497, 1719, +0, 1506, 1710, +0, 1518, 1698, +0, 1533, 1681, +0, 1552, 1657, +0, 1577, 1622, +0, 1609, 1572, +0, 1647, 1494, +0, 1695, 1365, +0, 1751, 1099, +0, 1817, 0, +0, 1892, 0, +0, 1976, 0, +0, 2069, 0, +0, 2170, 0, +0, 2277, 0, +0, 2389, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3518, 0, +0, 3649, 0, +0, 1477, 1742, +0, 1479, 1740, +0, 1482, 1738, +0, 1486, 1734, +0, 1491, 1729, +0, 1498, 1723, +0, 1507, 1713, +0, 1518, 1701, +0, 1533, 1684, +0, 1553, 1660, +0, 1578, 1626, +0, 1609, 1576, +0, 1648, 1500, +0, 1695, 1371, +0, 1751, 1111, +0, 1817, 0, +0, 1892, 0, +0, 1977, 0, +0, 2070, 0, +0, 2170, 0, +0, 2277, 0, +0, 2389, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1478, 1746, +0, 1480, 1744, +0, 1483, 1742, +0, 1487, 1738, +0, 1492, 1733, +0, 1499, 1727, +0, 1507, 1718, +0, 1519, 1706, +0, 1534, 1689, +0, 1554, 1665, +0, 1579, 1631, +0, 1610, 1582, +0, 1649, 1506, +0, 1696, 1380, +0, 1752, 1127, +0, 1818, 0, +0, 1893, 0, +0, 1977, 0, +0, 2070, 0, +0, 2170, 0, +0, 2277, 0, +0, 2389, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1479, 1752, +0, 1481, 1750, +0, 1484, 1747, +0, 1488, 1744, +0, 1493, 1739, +0, 1500, 1732, +0, 1509, 1723, +0, 1520, 1711, +0, 1535, 1695, +0, 1555, 1671, +0, 1580, 1638, +0, 1611, 1590, +0, 1650, 1515, +0, 1696, 1392, +0, 1753, 1147, +0, 1818, 0, +0, 1893, 0, +0, 1978, 0, +0, 2070, 0, +0, 2171, 0, +0, 2277, 0, +0, 2389, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1481, 1759, +0, 1483, 1757, +0, 1486, 1754, +0, 1490, 1751, +0, 1495, 1746, +0, 1502, 1740, +0, 1510, 1731, +0, 1522, 1719, +0, 1537, 1703, +0, 1556, 1680, +0, 1581, 1647, +0, 1612, 1600, +0, 1651, 1527, +0, 1698, 1407, +0, 1754, 1173, +0, 1819, 122, +0, 1894, 0, +0, 1978, 0, +0, 2071, 0, +0, 2171, 0, +0, 2278, 0, +0, 2390, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1483, 1768, +0, 1485, 1766, +0, 1488, 1763, +0, 1492, 1760, +0, 1497, 1755, +0, 1504, 1749, +0, 1513, 1741, +0, 1524, 1729, +0, 1539, 1713, +0, 1558, 1691, +0, 1583, 1659, +0, 1614, 1612, +0, 1652, 1542, +0, 1699, 1427, +0, 1755, 1206, +0, 1820, 376, +0, 1895, 0, +0, 1979, 0, +0, 2071, 0, +0, 2171, 0, +0, 2278, 0, +0, 2390, 0, +0, 2506, 0, +0, 2626, 0, +0, 2749, 0, +0, 2874, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1486, 1780, +0, 1488, 1778, +0, 1491, 1776, +0, 1495, 1772, +0, 1500, 1768, +0, 1507, 1762, +0, 1516, 1753, +0, 1527, 1742, +0, 1542, 1726, +0, 1561, 1705, +0, 1586, 1674, +0, 1616, 1629, +0, 1655, 1562, +0, 1701, 1452, +0, 1757, 1246, +0, 1822, 581, +0, 1896, 0, +0, 1980, 0, +0, 2072, 0, +0, 2172, 0, +0, 2279, 0, +0, 2390, 0, +0, 2507, 0, +0, 2627, 0, +0, 2750, 0, +0, 2875, 0, +0, 3001, 0, +0, 3129, 0, +0, 3258, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1490, 1795, +0, 1493, 1794, +0, 1495, 1791, +0, 1499, 1788, +0, 1504, 1784, +0, 1511, 1778, +0, 1519, 1770, +0, 1531, 1759, +0, 1546, 1744, +0, 1565, 1723, +0, 1589, 1694, +0, 1620, 1651, +0, 1657, 1587, +0, 1704, 1484, +0, 1759, 1294, +0, 1824, 762, +0, 1898, 0, +0, 1981, 0, +0, 2073, 0, +0, 2173, 0, +0, 2279, 0, +0, 2391, 0, +0, 2507, 0, +0, 2627, 0, +0, 2750, 0, +0, 2875, 0, +0, 3001, 0, +0, 3129, 0, +0, 3259, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1496, 1815, +0, 1498, 1814, +0, 1501, 1811, +0, 1505, 1808, +0, 1510, 1804, +0, 1516, 1799, +0, 1525, 1791, +0, 1536, 1781, +0, 1551, 1766, +0, 1569, 1746, +0, 1593, 1718, +0, 1624, 1678, +0, 1661, 1618, +0, 1707, 1522, +0, 1762, 1352, +0, 1826, 927, +0, 1900, 0, +0, 1983, 0, +0, 2075, 0, +0, 2174, 0, +0, 2280, 0, +0, 2392, 0, +0, 2508, 0, +0, 2628, 0, +0, 2750, 0, +0, 2875, 0, +0, 3002, 0, +0, 3130, 0, +0, 3259, 0, +0, 3388, 0, +0, 3519, 0, +0, 3649, 0, +0, 1503, 1841, +0, 1505, 1839, +0, 1508, 1837, +0, 1512, 1834, +0, 1517, 1830, +0, 1523, 1825, +0, 1532, 1818, +0, 1543, 1808, +0, 1557, 1795, +0, 1576, 1776, +0, 1599, 1750, +0, 1629, 1712, +0, 1666, 1657, +0, 1712, 1570, +0, 1766, 1419, +0, 1830, 1082, +0, 1903, 0, +0, 1986, 0, +0, 2077, 0, +0, 2176, 0, +0, 2282, 0, +0, 2393, 0, +0, 2509, 0, +0, 2628, 0, +0, 2751, 0, +0, 2875, 0, +0, 3002, 0, +0, 3130, 0, +0, 3259, 0, +0, 3388, 0, +0, 3519, 0, +0, 3650, 0, +964, 1513, 1873, +949, 1515, 1871, +928, 1518, 1869, +899, 1521, 1867, +857, 1526, 1863, +794, 1532, 1858, +692, 1541, 1851, +507, 1551, 1842, +0, 1566, 1830, +0, 1584, 1813, +0, 1607, 1788, +0, 1637, 1754, +0, 1673, 1704, +0, 1718, 1626, +0, 1771, 1496, +0, 1835, 1231, +0, 1907, 0, +0, 1989, 0, +0, 2080, 0, +0, 2178, 0, +0, 2283, 0, +0, 2394, 0, +0, 2510, 0, +0, 2629, 0, +0, 2751, 0, +0, 2876, 0, +0, 3002, 0, +0, 3130, 0, +0, 3259, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +1342, 1525, 1912, +1336, 1527, 1911, +1327, 1530, 1909, +1315, 1533, 1907, +1299, 1538, 1903, +1276, 1544, 1899, +1243, 1552, 1893, +1195, 1563, 1884, +1123, 1577, 1873, +1003, 1595, 1857, +767, 1617, 1836, +0, 1646, 1805, +0, 1682, 1760, +0, 1726, 1692, +0, 1779, 1582, +0, 1841, 1375, +0, 1912, 699, +0, 1994, 0, +0, 2083, 0, +0, 2181, 0, +0, 2286, 0, +0, 2396, 0, +0, 2511, 0, +0, 2630, 0, +0, 2752, 0, +0, 2877, 0, +0, 3003, 0, +0, 3130, 0, +0, 3259, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +1598, 1542, 1960, +1594, 1543, 1959, +1589, 1546, 1957, +1582, 1549, 1955, +1573, 1554, 1952, +1561, 1560, 1948, +1544, 1568, 1943, +1520, 1578, 1935, +1486, 1591, 1925, +1436, 1608, 1911, +1359, 1631, 1892, +1230, 1659, 1865, +968, 1693, 1826, +0, 1736, 1768, +0, 1788, 1676, +0, 1849, 1516, +0, 1919, 1135, +0, 1999, 0, +0, 2088, 0, +0, 2185, 0, +0, 2289, 0, +0, 2398, 0, +0, 2513, 0, +0, 2632, 0, +0, 2753, 0, +0, 2877, 0, +0, 3003, 0, +0, 3131, 0, +0, 3260, 0, +0, 3389, 0, +0, 3519, 0, +0, 3650, 0, +1804, 1562, 2017, +1802, 1564, 2016, +1799, 1567, 2015, +1795, 1570, 2013, +1789, 1574, 2010, +1781, 1580, 2007, +1771, 1587, 2002, +1756, 1597, 1995, +1737, 1610, 1987, +1708, 1626, 1974, +1668, 1648, 1958, +1607, 1675, 1934, +1511, 1708, 1901, +1338, 1750, 1852, +901, 1800, 1778, +0, 1860, 1654, +0, 1929, 1408, +0, 2007, 0, +0, 2095, 0, +0, 2190, 0, +0, 2293, 0, +0, 2402, 0, +0, 2515, 0, +0, 2633, 0, +0, 2755, 0, +0, 2878, 0, +0, 3004, 0, +0, 3132, 0, +0, 3260, 0, +0, 3389, 0, +0, 3520, 0, +0, 3650, 0, +1985, 1589, 2084, +1983, 1591, 2083, +1981, 1593, 2082, +1979, 1596, 2080, +1975, 1600, 2078, +1970, 1605, 2075, +1963, 1612, 2071, +1953, 1622, 2065, +1941, 1634, 2058, +1923, 1650, 2047, +1898, 1670, 2033, +1862, 1695, 2013, +1810, 1728, 1985, +1729, 1768, 1945, +1591, 1816, 1886, +1299, 1874, 1791, +0, 1941, 1623, +0, 2017, 1207, +0, 2103, 0, +0, 2197, 0, +0, 2298, 0, +0, 2406, 0, +0, 2519, 0, +0, 2636, 0, +0, 2757, 0, +0, 2880, 0, +0, 3005, 0, +0, 3132, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3650, 0, +2150, 1622, 2160, +2149, 1623, 2159, +2148, 1626, 2158, +2146, 1628, 2157, +2143, 1632, 2155, +2140, 1637, 2152, +2135, 1644, 2149, +2129, 1653, 2144, +2120, 1664, 2138, +2108, 1679, 2129, +2092, 1698, 2117, +2069, 1722, 2101, +2036, 1752, 2078, +1989, 1790, 2046, +1916, 1836, 1999, +1796, 1892, 1927, +1562, 1956, 1808, +499, 2030, 1577, +0, 2114, 586, +0, 2206, 0, +0, 2305, 0, +0, 2412, 0, +0, 2523, 0, +0, 2639, 0, +0, 2759, 0, +0, 2882, 0, +0, 3007, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3520, 0, +0, 3651, 0, +2306, 1663, 2246, +2305, 1664, 2245, +2304, 1666, 2244, +2303, 1669, 2243, +2301, 1672, 2241, +2298, 1677, 2239, +2295, 1683, 2236, +2291, 1691, 2232, +2284, 1701, 2227, +2276, 1715, 2220, +2265, 1732, 2210, +2249, 1755, 2197, +2228, 1783, 2179, +2197, 1819, 2153, +2153, 1862, 2116, +2085, 1915, 2061, +1976, 1976, 1976, +1771, 2047, 1830, +1120, 2128, 1507, +0, 2217, 0, +0, 2315, 0, +0, 2419, 0, +0, 2529, 0, +0, 2644, 0, +0, 2763, 0, +0, 2885, 0, +0, 3009, 0, +0, 3135, 0, +0, 3263, 0, +0, 3392, 0, +0, 3521, 0, +0, 3651, 0, +2455, 1712, 2339, +2454, 1713, 2339, +2453, 1715, 2338, +2452, 1717, 2337, +2451, 1721, 2336, +2449, 1725, 2334, +2447, 1730, 2332, +2444, 1737, 2328, +2439, 1747, 2324, +2434, 1759, 2318, +2426, 1775, 2311, +2415, 1796, 2300, +2400, 1822, 2285, +2379, 1854, 2265, +2350, 1895, 2237, +2307, 1944, 2195, +2243, 2002, 2134, +2141, 2069, 2035, +1954, 2146, 1857, +1434, 2233, 1394, +0, 2327, 0, +0, 2429, 0, +0, 2537, 0, +0, 2650, 0, +0, 2767, 0, +0, 2888, 0, +0, 3012, 0, +0, 3137, 0, +0, 3264, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +2599, 1771, 2440, +2598, 1772, 2440, +2598, 1773, 2439, +2597, 1775, 2438, +2596, 1778, 2437, +2595, 1782, 2436, +2593, 1787, 2434, +2591, 1793, 2432, +2588, 1801, 2428, +2584, 1812, 2424, +2578, 1827, 2418, +2570, 1845, 2409, +2560, 1868, 2398, +2545, 1898, 2382, +2525, 1935, 2360, +2496, 1980, 2329, +2455, 2034, 2284, +2394, 2097, 2215, +2296, 2170, 2104, +2120, 2252, 1892, +1666, 2343, 1176, +0, 2441, 0, +0, 2547, 0, +0, 2658, 0, +0, 2773, 0, +0, 2893, 0, +0, 3015, 0, +0, 3140, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3653, 0, +2740, 1839, 2548, +2740, 1840, 2547, +2739, 1841, 2547, +2739, 1843, 2546, +2738, 1845, 2545, +2737, 1848, 2544, +2736, 1853, 2543, +2734, 1858, 2541, +2732, 1865, 2538, +2729, 1875, 2535, +2725, 1887, 2530, +2719, 1903, 2523, +2711, 1924, 2514, +2701, 1950, 2502, +2687, 1983, 2486, +2667, 2024, 2462, +2639, 2073, 2429, +2599, 2132, 2380, +2539, 2199, 2305, +2445, 2277, 2181, +2277, 2363, 1934, +1861, 2458, 400, +0, 2560, 0, +0, 2668, 0, +0, 2781, 0, +0, 2899, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +2878, 1917, 2660, +2878, 1917, 2660, +2878, 1919, 2660, +2878, 1920, 2659, +2877, 1922, 2659, +2876, 1925, 2658, +2875, 1928, 2657, +2874, 1933, 2655, +2872, 1939, 2653, +2870, 1947, 2650, +2867, 1958, 2646, +2863, 1972, 2641, +2858, 1989, 2635, +2850, 2012, 2625, +2840, 2041, 2613, +2826, 2077, 2595, +2807, 2121, 2570, +2779, 2174, 2535, +2740, 2236, 2483, +2681, 2308, 2403, +2589, 2389, 2268, +2426, 2479, 1986, +2035, 2577, 0, +0, 2682, 0, +0, 2792, 0, +0, 2907, 0, +0, 3026, 0, +0, 3148, 0, +0, 3273, 0, +0, 3399, 0, +0, 3527, 0, +0, 3656, 0, +3015, 2003, 2777, +3015, 2004, 2777, +3015, 2005, 2777, +3015, 2006, 2776, +3014, 2008, 2776, +3014, 2010, 2775, +3013, 2013, 2774, +3012, 2017, 2773, +3011, 2022, 2772, +3009, 2029, 2770, +3007, 2038, 2767, +3004, 2049, 2763, +3000, 2064, 2758, +2995, 2084, 2751, +2987, 2108, 2741, +2977, 2140, 2728, +2963, 2178, 2709, +2944, 2225, 2684, +2917, 2281, 2647, +2878, 2347, 2593, +2821, 2422, 2508, +2730, 2506, 2363, +2570, 2599, 2046, +2196, 2699, 0, +0, 2806, 0, +0, 2918, 0, +0, 3034, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3529, 0, +0, 3658, 0, +3151, 2098, 2898, +3151, 2099, 2898, +3151, 2099, 2897, +3150, 2100, 2897, +3150, 2102, 2897, +3150, 2104, 2896, +3149, 2106, 2896, +3149, 2109, 2895, +3148, 2113, 2893, +3147, 2119, 2892, +3145, 2126, 2890, +3143, 2136, 2887, +3140, 2148, 2883, +3136, 2164, 2877, +3130, 2185, 2870, +3123, 2212, 2860, +3113, 2245, 2847, +3099, 2286, 2828, +3080, 2335, 2801, +3053, 2394, 2763, +3015, 2462, 2707, +2958, 2540, 2619, +2868, 2626, 2466, +2712, 2721, 2116, +2349, 2823, 0, +0, 2932, 0, +0, 3045, 0, +0, 3163, 0, +0, 3284, 0, +0, 3407, 0, +0, 3533, 0, +0, 3660, 0, +3286, 2200, 3021, +3286, 2201, 3021, +3286, 2201, 3021, +3285, 2202, 3021, +3285, 2203, 3020, +3285, 2205, 3020, +3284, 2206, 3019, +3284, 2209, 3019, +3283, 2212, 3018, +3282, 2217, 3016, +3281, 2223, 3015, +3280, 2231, 3013, +3277, 2241, 3010, +3274, 2254, 3006, +3270, 2271, 3000, +3265, 2293, 2993, +3258, 2321, 2983, +3248, 2356, 2969, +3234, 2398, 2949, +3215, 2450, 2922, +3189, 2511, 2883, +3151, 2581, 2825, +3094, 2661, 2734, +3005, 2749, 2574, +2850, 2846, 2196, +2495, 2950, 0, +0, 3059, 0, +0, 3174, 0, +0, 3292, 0, +0, 3414, 0, +0, 3538, 0, +0, 3664, 0, +3420, 2309, 3146, +3420, 2309, 3146, +3420, 2309, 3146, +3420, 2310, 3146, +3419, 2311, 3146, +3419, 2312, 3145, +3419, 2313, 3145, +3418, 2315, 3145, +3418, 2318, 3144, +3417, 2322, 3143, +3416, 2326, 3142, +3415, 2333, 3140, +3414, 2341, 3138, +3411, 2351, 3135, +3408, 2365, 3131, +3404, 2383, 3125, +3399, 2406, 3117, +3392, 2435, 3107, +3382, 2471, 3093, +3368, 2516, 3074, +3350, 2569, 3046, +3323, 2631, 3006, +3285, 2703, 2947, +3229, 2785, 2853, +3141, 2875, 2688, +2988, 2973, 2284, +2638, 3077, 0, +0, 3188, 0, +0, 3303, 0, +0, 3422, 0, +0, 3544, 0, +0, 3669, 0, +3553, 2422, 3273, +3553, 2422, 3273, +3553, 2423, 3273, +3553, 2423, 3273, +3553, 2424, 3273, +3553, 2425, 3273, +3553, 2426, 3272, +3552, 2427, 3272, +3552, 2430, 3271, +3552, 2432, 3271, +3551, 2436, 3270, +3550, 2441, 3269, +3549, 2447, 3267, +3547, 2456, 3265, +3545, 2467, 3261, +3542, 2481, 3257, +3538, 2500, 3252, +3533, 2524, 3244, +3525, 2554, 3234, +3516, 2591, 3219, +3502, 2636, 3200, +3483, 2690, 3172, +3457, 2754, 3131, +3419, 2828, 3071, +3363, 2910, 2976, +3275, 3002, 2805, +3123, 3100, 2380, +2778, 3206, 0, +0, 3317, 0, +0, 3433, 0, +0, 3553, 0, +0, 3675, 0, +3687, 2540, 3402, +3687, 2540, 3402, +3686, 2540, 3401, +3686, 2541, 3401, +3686, 2541, 3401, +3686, 2542, 3401, +3686, 2543, 3401, +3686, 2544, 3401, +3686, 2545, 3400, +3685, 2548, 3400, +3685, 2550, 3399, +3684, 2554, 3398, +3683, 2559, 3397, +3682, 2566, 3395, +3680, 2575, 3393, +3678, 2586, 3390, +3675, 2601, 3385, +3671, 2620, 3380, +3666, 2644, 3372, +3659, 2675, 3362, +3649, 2713, 3347, +3635, 2759, 3327, +3617, 2815, 3299, +3590, 2880, 3258, +3553, 2954, 3197, +3497, 3038, 3100, +3410, 3130, 2926, +3258, 3229, 2484, +2916, 3336, 0, +0, 3448, 0, +0, 3564, 0, +0, 3684, 0, +3819, 2661, 3531, +3819, 2661, 3531, +3819, 2661, 3531, +3819, 2661, 3531, +3819, 2662, 3531, +3819, 2662, 3530, +3819, 2663, 3530, +3819, 2664, 3530, +3819, 2665, 3530, +3818, 2667, 3529, +3818, 2669, 3529, +3818, 2672, 3528, +3817, 2676, 3527, +3816, 2681, 3526, +3815, 2688, 3524, +3813, 2697, 3522, +3811, 2708, 3519, +3808, 2723, 3514, +3804, 2743, 3509, +3799, 2768, 3501, +3792, 2799, 3490, +3782, 2838, 3476, +3768, 2885, 3456, +3750, 2941, 3427, +3723, 3007, 3386, +3686, 3082, 3325, +3630, 3166, 3227, +3543, 3259, 3050, +3392, 3359, 2593, +3052, 3466, 0, +0, 3578, 0, +0, 3695, 0, +3952, 2784, 3661, +3952, 2784, 3661, +3952, 2785, 3661, +3952, 2785, 3661, +3952, 2785, 3661, +3952, 2785, 3660, +3952, 2786, 3660, +3952, 2787, 3660, +3952, 2788, 3660, +3951, 2789, 3660, +3951, 2791, 3659, +3951, 2793, 3659, +3950, 2796, 3658, +3950, 2800, 3657, +3949, 2805, 3656, +3947, 2812, 3654, +3946, 2821, 3652, +3944, 2833, 3648, +3941, 2848, 3644, +3937, 2868, 3638, +3932, 2893, 3631, +3924, 2925, 3620, +3915, 2964, 3605, +3901, 3012, 3585, +3882, 3068, 3556, +3856, 3135, 3515, +3819, 3211, 3453, +3763, 3295, 3354, +3676, 3389, 3176, +3526, 3489, 2707, +3188, 3597, 0, +0, 3709, 0, +4085, 2910, 3791, +4085, 2910, 3791, +4085, 2910, 3791, +4085, 2910, 3791, +4085, 2911, 3791, +4085, 2911, 3791, +4085, 2911, 3791, +4084, 2912, 3791, +4084, 2912, 3791, +4084, 2913, 3790, +4084, 2915, 3790, +4084, 2916, 3790, +4083, 2919, 3789, +4083, 2922, 3788, +4082, 2926, 3787, +4081, 2931, 3786, +4080, 2938, 3784, +4078, 2947, 3782, +4076, 2959, 3779, +4073, 2975, 3775, +4069, 2995, 3769, +4064, 3020, 3761, +4057, 3052, 3750, +4047, 3092, 3736, +4034, 3140, 3715, +4015, 3197, 3686, +3989, 3264, 3645, +3951, 3340, 3583, +3896, 3425, 3483, +3809, 3519, 3303, +3659, 3620, 2826, +3322, 3728, 0, +4095, 3037, 3922, +4095, 3037, 3922, +4095, 3037, 3922, +4095, 3037, 3922, +4095, 3038, 3922, +4095, 3038, 3922, +4095, 3038, 3922, +4095, 3039, 3922, +4095, 3039, 3922, +4095, 3040, 3921, +4095, 3041, 3921, +4095, 3042, 3921, +4095, 3044, 3920, +4095, 3046, 3920, +4095, 3049, 3919, +4095, 3053, 3918, +4095, 3059, 3917, +4095, 3066, 3915, +4095, 3075, 3913, +4095, 3087, 3910, +4095, 3103, 3905, +4095, 3123, 3900, +4095, 3149, 3892, +4095, 3181, 3881, +4095, 3221, 3866, +4095, 3269, 3846, +4095, 3327, 3817, +4095, 3394, 3775, +4084, 3470, 3713, +4029, 3556, 3613, +3942, 3650, 3432, +3792, 3751, 2947, +4095, 3166, 4053, +4095, 3166, 4053, +4095, 3166, 4053, +4095, 3166, 4053, +4095, 3166, 4053, +4095, 3166, 4053, +4095, 3166, 4053, +4095, 3167, 4053, +4095, 3167, 4053, +4095, 3168, 4053, +4095, 3168, 4053, +4095, 3169, 4052, +4095, 3171, 4052, +4095, 3172, 4052, +4095, 3175, 4051, +4095, 3178, 4050, +4095, 3182, 4049, +4095, 3187, 4048, +4095, 3194, 4046, +4095, 3204, 4044, +4095, 3216, 4041, +4095, 3232, 4037, +4095, 3252, 4031, +4095, 3278, 4023, +4095, 3310, 4012, +4095, 3350, 3997, +4095, 3399, 3977, +4095, 3457, 3948, +4095, 3524, 3906, +4095, 3601, 3843, +4095, 3687, 3743, +4074, 3781, 3561, +0, 1606, 1871, +0, 1607, 1869, +0, 1610, 1867, +0, 1612, 1864, +0, 1616, 1861, +0, 1622, 1856, +0, 1628, 1849, +0, 1637, 1840, +0, 1649, 1827, +0, 1664, 1810, +0, 1684, 1786, +0, 1709, 1751, +0, 1740, 1701, +0, 1779, 1623, +0, 1826, 1491, +0, 1883, 1222, +0, 1949, 0, +0, 2024, 0, +0, 2108, 0, +0, 2201, 0, +0, 2302, 0, +0, 2409, 0, +0, 2521, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1606, 1873, +0, 1608, 1871, +0, 1610, 1869, +0, 1613, 1867, +0, 1617, 1863, +0, 1622, 1858, +0, 1629, 1851, +0, 1638, 1842, +0, 1650, 1830, +0, 1665, 1813, +0, 1684, 1789, +0, 1709, 1754, +0, 1741, 1704, +0, 1779, 1626, +0, 1827, 1497, +0, 1883, 1231, +0, 1949, 0, +0, 2024, 0, +0, 2109, 0, +0, 2202, 0, +0, 2302, 0, +0, 2409, 0, +0, 2521, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1607, 1876, +0, 1609, 1874, +0, 1611, 1872, +0, 1614, 1870, +0, 1618, 1866, +0, 1623, 1861, +0, 1630, 1855, +0, 1639, 1846, +0, 1650, 1833, +0, 1666, 1816, +0, 1685, 1792, +0, 1710, 1758, +0, 1741, 1708, +0, 1780, 1632, +0, 1827, 1503, +0, 1883, 1243, +0, 1949, 0, +0, 2024, 0, +0, 2109, 0, +0, 2202, 0, +0, 2302, 0, +0, 2409, 0, +0, 2521, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1608, 1880, +0, 1610, 1878, +0, 1612, 1876, +0, 1615, 1874, +0, 1619, 1870, +0, 1624, 1865, +0, 1631, 1859, +0, 1640, 1850, +0, 1651, 1838, +0, 1666, 1821, +0, 1686, 1797, +0, 1711, 1763, +0, 1742, 1714, +0, 1781, 1638, +0, 1828, 1512, +0, 1884, 1259, +0, 1950, 0, +0, 2025, 0, +0, 2109, 0, +0, 2202, 0, +0, 2302, 0, +0, 2409, 0, +0, 2521, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1609, 1885, +0, 1611, 1884, +0, 1613, 1882, +0, 1616, 1879, +0, 1620, 1876, +0, 1625, 1871, +0, 1632, 1864, +0, 1641, 1855, +0, 1652, 1843, +0, 1668, 1827, +0, 1687, 1803, +0, 1712, 1770, +0, 1743, 1722, +0, 1782, 1647, +0, 1829, 1524, +0, 1885, 1280, +0, 1950, 0, +0, 2025, 0, +0, 2110, 0, +0, 2202, 0, +0, 2303, 0, +0, 2409, 0, +0, 2522, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1611, 1892, +0, 1613, 1891, +0, 1615, 1889, +0, 1618, 1886, +0, 1622, 1883, +0, 1627, 1878, +0, 1634, 1872, +0, 1642, 1863, +0, 1654, 1851, +0, 1669, 1835, +0, 1689, 1812, +0, 1713, 1779, +0, 1744, 1732, +0, 1783, 1659, +0, 1830, 1540, +0, 1886, 1305, +0, 1951, 254, +0, 2026, 0, +0, 2110, 0, +0, 2203, 0, +0, 2303, 0, +0, 2410, 0, +0, 2522, 0, +0, 2638, 0, +0, 2758, 0, +0, 2881, 0, +0, 3006, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1614, 1901, +0, 1615, 1900, +0, 1617, 1898, +0, 1620, 1896, +0, 1624, 1892, +0, 1629, 1887, +0, 1636, 1881, +0, 1645, 1873, +0, 1656, 1861, +0, 1671, 1845, +0, 1691, 1823, +0, 1715, 1791, +0, 1746, 1745, +0, 1784, 1674, +0, 1831, 1559, +0, 1887, 1338, +0, 1952, 508, +0, 2027, 0, +0, 2111, 0, +0, 2203, 0, +0, 2304, 0, +0, 2410, 0, +0, 2522, 0, +0, 2639, 0, +0, 2759, 0, +0, 2881, 0, +0, 3007, 0, +0, 3133, 0, +0, 3261, 0, +0, 3390, 0, +0, 3520, 0, +0, 3651, 0, +0, 1617, 1913, +0, 1618, 1912, +0, 1620, 1910, +0, 1623, 1908, +0, 1627, 1904, +0, 1632, 1900, +0, 1639, 1894, +0, 1648, 1885, +0, 1659, 1874, +0, 1674, 1859, +0, 1693, 1837, +0, 1718, 1806, +0, 1748, 1761, +0, 1787, 1694, +0, 1833, 1584, +0, 1889, 1378, +0, 1954, 713, +0, 2028, 0, +0, 2112, 0, +0, 2204, 0, +0, 2304, 0, +0, 2411, 0, +0, 2522, 0, +0, 2639, 0, +0, 2759, 0, +0, 2882, 0, +0, 3007, 0, +0, 3133, 0, +0, 3261, 0, +0, 3391, 0, +0, 3520, 0, +0, 3651, 0, +0, 1621, 1929, +0, 1622, 1928, +0, 1625, 1926, +0, 1627, 1923, +0, 1631, 1920, +0, 1636, 1916, +0, 1643, 1910, +0, 1652, 1902, +0, 1663, 1891, +0, 1678, 1876, +0, 1697, 1855, +0, 1721, 1826, +0, 1752, 1783, +0, 1790, 1719, +0, 1836, 1616, +0, 1891, 1426, +0, 1956, 894, +0, 2030, 0, +0, 2113, 0, +0, 2206, 0, +0, 2305, 0, +0, 2411, 0, +0, 2523, 0, +0, 2639, 0, +0, 2759, 0, +0, 2882, 0, +0, 3007, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3520, 0, +0, 3651, 0, +0, 1626, 1949, +0, 1628, 1948, +0, 1630, 1946, +0, 1633, 1944, +0, 1637, 1940, +0, 1642, 1936, +0, 1648, 1931, +0, 1657, 1923, +0, 1668, 1913, +0, 1683, 1898, +0, 1701, 1878, +0, 1726, 1851, +0, 1756, 1810, +0, 1793, 1750, +0, 1839, 1655, +0, 1894, 1484, +0, 1958, 1059, +0, 2032, 0, +0, 2115, 0, +0, 2207, 0, +0, 2306, 0, +0, 2412, 0, +0, 2524, 0, +0, 2640, 0, +0, 2760, 0, +0, 2882, 0, +0, 3007, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3520, 0, +0, 3651, 0, +0, 1634, 1974, +0, 1635, 1973, +0, 1637, 1971, +0, 1640, 1969, +0, 1644, 1966, +0, 1649, 1962, +0, 1655, 1957, +0, 1664, 1950, +0, 1675, 1940, +0, 1689, 1927, +0, 1708, 1908, +0, 1731, 1882, +0, 1761, 1844, +0, 1798, 1789, +0, 1844, 1702, +0, 1898, 1552, +0, 1962, 1214, +0, 2035, 0, +0, 2118, 0, +0, 2209, 0, +0, 2308, 0, +0, 2414, 0, +0, 2525, 0, +0, 2641, 0, +0, 2760, 0, +0, 2883, 0, +0, 3008, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +1107, 1643, 2006, +1096, 1645, 2005, +1081, 1647, 2003, +1061, 1650, 2001, +1031, 1653, 1999, +989, 1658, 1995, +926, 1664, 1990, +824, 1673, 1983, +639, 1684, 1974, +132, 1698, 1962, +0, 1716, 1945, +0, 1739, 1921, +0, 1769, 1886, +0, 1805, 1836, +0, 1850, 1758, +0, 1904, 1628, +0, 1967, 1363, +0, 2039, 0, +0, 2121, 0, +0, 2212, 0, +0, 2310, 0, +0, 2415, 0, +0, 2526, 0, +0, 2642, 0, +0, 2761, 0, +0, 2883, 0, +0, 3008, 0, +0, 3134, 0, +0, 3262, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +1479, 1656, 2045, +1474, 1657, 2044, +1468, 1659, 2043, +1459, 1662, 2041, +1447, 1666, 2039, +1431, 1670, 2035, +1408, 1676, 2031, +1375, 1684, 2025, +1327, 1695, 2016, +1255, 1709, 2005, +1135, 1727, 1989, +899, 1749, 1968, +0, 1778, 1937, +0, 1814, 1892, +0, 1858, 1824, +0, 1911, 1714, +0, 1973, 1507, +0, 2045, 831, +0, 2126, 0, +0, 2215, 0, +0, 2313, 0, +0, 2418, 0, +0, 2528, 0, +0, 2643, 0, +0, 2762, 0, +0, 2884, 0, +0, 3009, 0, +0, 3135, 0, +0, 3263, 0, +0, 3391, 0, +0, 3521, 0, +0, 3651, 0, +1732, 1672, 2093, +1730, 1674, 2092, +1726, 1676, 2091, +1721, 1678, 2089, +1715, 1681, 2087, +1706, 1686, 2084, +1693, 1692, 2080, +1676, 1700, 2075, +1652, 1710, 2067, +1618, 1723, 2057, +1568, 1741, 2043, +1491, 1763, 2024, +1362, 1791, 1997, +1100, 1826, 1958, +0, 1868, 1900, +0, 1920, 1808, +0, 1981, 1648, +0, 2052, 1267, +0, 2132, 0, +0, 2220, 0, +0, 2317, 0, +0, 2421, 0, +0, 2530, 0, +0, 2645, 0, +0, 2764, 0, +0, 2885, 0, +0, 3009, 0, +0, 3136, 0, +0, 3263, 0, +0, 3392, 0, +0, 3521, 0, +0, 3651, 0, +1938, 1693, 2150, +1936, 1694, 2150, +1934, 1696, 2148, +1931, 1699, 2147, +1927, 1702, 2145, +1921, 1706, 2142, +1913, 1712, 2139, +1903, 1719, 2134, +1889, 1729, 2127, +1869, 1742, 2119, +1840, 1759, 2106, +1800, 1780, 2090, +1739, 1807, 2066, +1643, 1841, 2033, +1470, 1882, 1984, +1033, 1932, 1910, +0, 1992, 1786, +0, 2061, 1540, +0, 2139, 54, +0, 2227, 0, +0, 2322, 0, +0, 2425, 0, +0, 2534, 0, +0, 2648, 0, +0, 2766, 0, +0, 2887, 0, +0, 3011, 0, +0, 3136, 0, +0, 3264, 0, +0, 3392, 0, +0, 3522, 0, +0, 3652, 0, +2118, 1720, 2217, +2117, 1721, 2216, +2116, 1723, 2215, +2113, 1725, 2214, +2111, 1728, 2212, +2107, 1732, 2210, +2102, 1737, 2207, +2095, 1744, 2203, +2086, 1754, 2197, +2073, 1766, 2190, +2055, 1782, 2179, +2030, 1802, 2165, +1994, 1828, 2145, +1942, 1860, 2118, +1861, 1900, 2077, +1723, 1948, 2018, +1431, 2006, 1923, +0, 2073, 1755, +0, 2149, 1339, +0, 2235, 0, +0, 2329, 0, +0, 2430, 0, +0, 2538, 0, +0, 2651, 0, +0, 2768, 0, +0, 2889, 0, +0, 3012, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +2283, 1753, 2293, +2282, 1754, 2292, +2281, 1756, 2292, +2280, 1758, 2290, +2278, 1761, 2289, +2275, 1764, 2287, +2272, 1769, 2285, +2267, 1776, 2281, +2261, 1785, 2276, +2252, 1796, 2270, +2240, 1811, 2261, +2224, 1830, 2249, +2201, 1854, 2233, +2168, 1884, 2210, +2121, 1922, 2178, +2048, 1968, 2131, +1928, 2024, 2059, +1694, 2088, 1940, +631, 2163, 1709, +0, 2246, 718, +0, 2338, 0, +0, 2437, 0, +0, 2544, 0, +0, 2655, 0, +0, 2772, 0, +0, 2891, 0, +0, 3014, 0, +0, 3139, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3653, 0, +2439, 1794, 2378, +2438, 1795, 2378, +2437, 1796, 2377, +2436, 1798, 2376, +2435, 1801, 2375, +2433, 1804, 2373, +2430, 1809, 2371, +2427, 1815, 2368, +2423, 1823, 2364, +2417, 1833, 2359, +2408, 1847, 2352, +2397, 1864, 2342, +2382, 1887, 2329, +2360, 1915, 2311, +2329, 1951, 2285, +2285, 1994, 2248, +2217, 2047, 2193, +2108, 2108, 2108, +1903, 2180, 1962, +1252, 2260, 1639, +0, 2350, 0, +0, 2447, 0, +0, 2551, 0, +0, 2661, 0, +0, 2776, 0, +0, 2895, 0, +0, 3017, 0, +0, 3141, 0, +0, 3267, 0, +0, 3395, 0, +0, 3524, 0, +0, 3653, 0, +2587, 1843, 2472, +2587, 1844, 2471, +2586, 1845, 2471, +2585, 1847, 2470, +2584, 1850, 2469, +2583, 1853, 2468, +2581, 1857, 2466, +2579, 1862, 2464, +2576, 1869, 2460, +2571, 1879, 2456, +2566, 1891, 2451, +2558, 1907, 2443, +2547, 1928, 2432, +2532, 1954, 2418, +2511, 1986, 2397, +2482, 2027, 2369, +2439, 2076, 2327, +2375, 2134, 2266, +2273, 2201, 2167, +2086, 2279, 1990, +1566, 2365, 1526, +0, 2459, 0, +0, 2561, 0, +0, 2669, 0, +0, 2782, 0, +0, 2899, 0, +0, 3020, 0, +0, 3144, 0, +0, 3269, 0, +0, 3396, 0, +0, 3525, 0, +0, 3654, 0, +2731, 1902, 2573, +2731, 1903, 2572, +2731, 1904, 2572, +2730, 1906, 2571, +2729, 1908, 2570, +2728, 1910, 2569, +2727, 1914, 2568, +2725, 1919, 2566, +2723, 1925, 2564, +2720, 1933, 2560, +2716, 1944, 2556, +2710, 1959, 2550, +2702, 1977, 2541, +2692, 2000, 2530, +2677, 2030, 2514, +2657, 2067, 2492, +2629, 2112, 2461, +2588, 2166, 2416, +2526, 2229, 2347, +2428, 2302, 2236, +2252, 2384, 2024, +1798, 2475, 1309, +0, 2574, 0, +0, 2679, 0, +0, 2790, 0, +0, 2906, 0, +0, 3025, 0, +0, 3147, 0, +0, 3272, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +2872, 1970, 2680, +2872, 1971, 2680, +2872, 1972, 2679, +2871, 1973, 2679, +2871, 1975, 2678, +2870, 1977, 2677, +2869, 1981, 2676, +2868, 1985, 2675, +2866, 1990, 2673, +2864, 1998, 2670, +2861, 2007, 2667, +2857, 2019, 2662, +2851, 2036, 2655, +2843, 2056, 2646, +2833, 2083, 2634, +2819, 2115, 2618, +2799, 2156, 2594, +2771, 2205, 2561, +2731, 2264, 2512, +2672, 2332, 2437, +2577, 2409, 2314, +2409, 2495, 2066, +1993, 2590, 532, +0, 2692, 0, +0, 2800, 0, +0, 2914, 0, +0, 3031, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3528, 0, +0, 3657, 0, +3011, 2048, 2793, +3011, 2049, 2792, +3010, 2050, 2792, +3010, 2051, 2792, +3010, 2052, 2791, +3009, 2054, 2791, +3008, 2057, 2790, +3007, 2060, 2789, +3006, 2065, 2787, +3005, 2071, 2785, +3002, 2079, 2782, +2999, 2090, 2779, +2995, 2104, 2774, +2990, 2122, 2767, +2982, 2144, 2757, +2972, 2173, 2745, +2958, 2209, 2727, +2939, 2253, 2702, +2911, 2306, 2667, +2872, 2368, 2616, +2813, 2440, 2536, +2721, 2521, 2400, +2558, 2611, 2118, +2167, 2709, 0, +0, 2814, 0, +0, 2924, 0, +0, 3039, 0, +0, 3158, 0, +0, 3280, 0, +0, 3405, 0, +0, 3531, 0, +0, 3659, 0, +3148, 2135, 2910, +3147, 2135, 2909, +3147, 2136, 2909, +3147, 2137, 2909, +3147, 2138, 2909, +3146, 2140, 2908, +3146, 2142, 2907, +3145, 2145, 2907, +3144, 2149, 2905, +3143, 2154, 2904, +3141, 2161, 2902, +3139, 2170, 2899, +3136, 2181, 2895, +3132, 2196, 2890, +3127, 2216, 2883, +3119, 2241, 2873, +3109, 2272, 2860, +3095, 2310, 2842, +3076, 2357, 2816, +3049, 2413, 2779, +3010, 2479, 2725, +2953, 2554, 2640, +2862, 2638, 2495, +2703, 2731, 2178, +2328, 2831, 0, +0, 2938, 0, +0, 3050, 0, +0, 3167, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +3283, 2230, 3030, +3283, 2230, 3030, +3283, 2231, 3030, +3283, 2232, 3030, +3283, 2233, 3029, +3282, 2234, 3029, +3282, 2236, 3028, +3281, 2238, 3028, +3281, 2241, 3027, +3280, 2245, 3026, +3279, 2251, 3024, +3277, 2258, 3022, +3275, 2268, 3019, +3272, 2280, 3015, +3268, 2297, 3010, +3262, 2317, 3002, +3255, 2344, 2992, +3245, 2377, 2979, +3231, 2418, 2960, +3212, 2467, 2933, +3186, 2526, 2896, +3147, 2594, 2839, +3090, 2672, 2751, +3000, 2758, 2598, +2844, 2853, 2248, +2481, 2955, 0, +0, 3064, 0, +0, 3177, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3418, 2332, 3153, +3418, 2332, 3153, +3418, 2333, 3153, +3418, 2333, 3153, +3417, 2334, 3153, +3417, 2335, 3152, +3417, 2337, 3152, +3417, 2339, 3151, +3416, 2341, 3151, +3415, 2344, 3150, +3414, 2349, 3149, +3413, 2355, 3147, +3412, 2363, 3145, +3409, 2373, 3142, +3406, 2386, 3138, +3403, 2403, 3132, +3397, 2425, 3125, +3390, 2453, 3115, +3380, 2488, 3101, +3366, 2531, 3082, +3347, 2582, 3054, +3321, 2643, 3016, +3283, 2713, 2958, +3226, 2793, 2866, +3137, 2882, 2706, +2983, 2978, 2328, +2627, 3082, 0, +0, 3191, 0, +0, 3306, 0, +0, 3424, 0, +0, 3546, 0, +0, 3670, 0, +3552, 2440, 3279, +3552, 2441, 3278, +3552, 2441, 3278, +3552, 2441, 3278, +3552, 2442, 3278, +3551, 2443, 3278, +3551, 2444, 3278, +3551, 2446, 3277, +3551, 2448, 3277, +3550, 2450, 3276, +3549, 2454, 3275, +3549, 2458, 3274, +3547, 2465, 3272, +3546, 2473, 3270, +3543, 2484, 3267, +3541, 2497, 3263, +3537, 2515, 3257, +3531, 2538, 3250, +3524, 2567, 3239, +3514, 2603, 3225, +3500, 2648, 3206, +3482, 2701, 3178, +3455, 2763, 3138, +3417, 2835, 3079, +3361, 2917, 2986, +3273, 3007, 2820, +3120, 3105, 2416, +2770, 3209, 0, +0, 3320, 0, +0, 3435, 0, +0, 3554, 0, +0, 3676, 0, +3685, 2554, 3406, +3685, 2554, 3405, +3685, 2554, 3405, +3685, 2555, 3405, +3685, 2555, 3405, +3685, 2556, 3405, +3685, 2557, 3405, +3685, 2558, 3405, +3684, 2560, 3404, +3684, 2562, 3404, +3684, 2564, 3403, +3683, 2568, 3402, +3682, 2573, 3401, +3681, 2579, 3399, +3679, 2588, 3397, +3677, 2599, 3394, +3674, 2613, 3389, +3670, 2632, 3384, +3665, 2656, 3376, +3658, 2686, 3366, +3648, 2723, 3351, +3634, 2768, 3332, +3615, 2823, 3304, +3589, 2886, 3263, +3551, 2960, 3203, +3495, 3042, 3108, +3408, 3134, 2938, +3255, 3233, 2512, +2910, 3338, 0, +0, 3449, 0, +0, 3565, 0, +0, 3685, 0, +3819, 2672, 3534, +3819, 2672, 3534, +3819, 2672, 3534, +3819, 2672, 3534, +3818, 2673, 3533, +3818, 2673, 3533, +3818, 2674, 3533, +3818, 2675, 3533, +3818, 2676, 3533, +3818, 2678, 3532, +3817, 2680, 3532, +3817, 2683, 3531, +3816, 2686, 3530, +3815, 2691, 3529, +3814, 2698, 3527, +3812, 2707, 3525, +3810, 2718, 3522, +3807, 2733, 3517, +3803, 2752, 3512, +3798, 2776, 3504, +3791, 2807, 3494, +3781, 2845, 3479, +3767, 2891, 3459, +3749, 2947, 3431, +3722, 3012, 3390, +3685, 3086, 3329, +3629, 3170, 3232, +3542, 3262, 3059, +3390, 3362, 2616, +3048, 3468, 0, +0, 3580, 0, +0, 3696, 0, +3952, 2793, 3663, +3952, 2793, 3663, +3952, 2793, 3663, +3951, 2793, 3663, +3951, 2793, 3663, +3951, 2794, 3663, +3951, 2794, 3663, +3951, 2795, 3662, +3951, 2796, 3662, +3951, 2797, 3662, +3951, 2799, 3661, +3950, 2801, 3661, +3950, 2804, 3660, +3949, 2808, 3659, +3948, 2813, 3658, +3947, 2820, 3656, +3945, 2829, 3654, +3943, 2840, 3651, +3940, 2856, 3646, +3936, 2875, 3641, +3931, 2900, 3633, +3924, 2931, 3622, +3914, 2970, 3608, +3900, 3017, 3588, +3882, 3073, 3559, +3856, 3139, 3518, +3818, 3214, 3457, +3762, 3298, 3359, +3675, 3391, 3182, +3524, 3491, 2725, +3184, 3598, 0, +0, 3710, 0, +4084, 2916, 3793, +4084, 2916, 3793, +4084, 2916, 3793, +4084, 2917, 3793, +4084, 2917, 3793, +4084, 2917, 3793, +4084, 2918, 3793, +4084, 2918, 3792, +4084, 2919, 3792, +4084, 2920, 3792, +4083, 2921, 3792, +4083, 2923, 3791, +4083, 2925, 3791, +4082, 2928, 3790, +4082, 2932, 3789, +4081, 2937, 3788, +4080, 2944, 3786, +4078, 2953, 3784, +4076, 2965, 3781, +4073, 2980, 3776, +4069, 3000, 3771, +4064, 3025, 3763, +4056, 3057, 3752, +4047, 3096, 3738, +4033, 3144, 3717, +4015, 3201, 3689, +3988, 3267, 3647, +3951, 3343, 3585, +3895, 3428, 3486, +3808, 3521, 3308, +3658, 3622, 2839, +3320, 3729, 0, +4095, 3042, 3923, +4095, 3042, 3923, +4095, 3042, 3923, +4095, 3042, 3923, +4095, 3042, 3923, +4095, 3043, 3923, +4095, 3043, 3923, +4095, 3043, 3923, +4095, 3044, 3923, +4095, 3045, 3923, +4095, 3046, 3922, +4095, 3047, 3922, +4095, 3049, 3922, +4095, 3051, 3921, +4095, 3054, 3920, +4095, 3058, 3919, +4095, 3063, 3918, +4095, 3070, 3916, +4095, 3079, 3914, +4095, 3091, 3911, +4095, 3107, 3907, +4095, 3127, 3901, +4095, 3152, 3893, +4095, 3184, 3882, +4095, 3224, 3868, +4095, 3272, 3847, +4095, 3329, 3819, +4095, 3396, 3777, +4084, 3472, 3715, +4028, 3558, 3615, +3941, 3651, 3435, +3791, 3752, 2958, +4095, 3169, 4054, +4095, 3169, 4054, +4095, 3169, 4054, +4095, 3169, 4054, +4095, 3169, 4054, +4095, 3170, 4054, +4095, 3170, 4054, +4095, 3170, 4054, +4095, 3171, 4054, +4095, 3171, 4054, +4095, 3172, 4054, +4095, 3173, 4053, +4095, 3174, 4053, +4095, 3176, 4053, +4095, 3178, 4052, +4095, 3181, 4051, +4095, 3185, 4050, +4095, 3191, 4049, +4095, 3198, 4047, +4095, 3207, 4045, +4095, 3219, 4042, +4095, 3235, 4037, +4095, 3255, 4032, +4095, 3281, 4024, +4095, 3313, 4013, +4095, 3353, 3998, +4095, 3401, 3978, +4095, 3459, 3949, +4095, 3526, 3907, +4095, 3602, 3845, +4095, 3688, 3745, +4074, 3782, 3564, +0, 1736, 2002, +0, 1737, 2001, +0, 1739, 2000, +0, 1741, 1998, +0, 1744, 1995, +0, 1748, 1991, +0, 1753, 1986, +0, 1760, 1979, +0, 1769, 1970, +0, 1781, 1958, +0, 1796, 1940, +0, 1816, 1916, +0, 1841, 1881, +0, 1872, 1830, +0, 1911, 1752, +0, 1958, 1620, +0, 2015, 1347, +0, 2080, 0, +0, 2156, 0, +0, 2240, 0, +0, 2333, 0, +0, 2434, 0, +0, 2541, 0, +0, 2653, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +0, 1737, 2004, +0, 1738, 2003, +0, 1739, 2001, +0, 1742, 1999, +0, 1745, 1997, +0, 1749, 1993, +0, 1754, 1988, +0, 1761, 1981, +0, 1769, 1972, +0, 1781, 1960, +0, 1796, 1942, +0, 1816, 1918, +0, 1841, 1883, +0, 1872, 1833, +0, 1911, 1755, +0, 1958, 1624, +0, 2015, 1354, +0, 2081, 0, +0, 2156, 0, +0, 2241, 0, +0, 2333, 0, +0, 2434, 0, +0, 2541, 0, +0, 2653, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +0, 1737, 2006, +0, 1738, 2005, +0, 1740, 2004, +0, 1742, 2002, +0, 1745, 1999, +0, 1749, 1995, +0, 1754, 1990, +0, 1761, 1984, +0, 1770, 1974, +0, 1782, 1962, +0, 1797, 1945, +0, 1817, 1921, +0, 1841, 1886, +0, 1873, 1836, +0, 1912, 1759, +0, 1959, 1629, +0, 2015, 1363, +0, 2081, 0, +0, 2156, 0, +0, 2241, 0, +0, 2334, 0, +0, 2434, 0, +0, 2541, 0, +0, 2653, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +0, 1738, 2009, +0, 1739, 2008, +0, 1741, 2007, +0, 1743, 2005, +0, 1746, 2002, +0, 1750, 1998, +0, 1755, 1993, +0, 1762, 1987, +0, 1771, 1978, +0, 1782, 1965, +0, 1798, 1948, +0, 1817, 1924, +0, 1842, 1890, +0, 1873, 1840, +0, 1912, 1764, +0, 1959, 1636, +0, 2015, 1375, +0, 2081, 0, +0, 2157, 0, +0, 2241, 0, +0, 2334, 0, +0, 2434, 0, +0, 2541, 0, +0, 2653, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +0, 1739, 2013, +0, 1740, 2012, +0, 1742, 2011, +0, 1744, 2009, +0, 1747, 2006, +0, 1751, 2002, +0, 1756, 1997, +0, 1763, 1991, +0, 1772, 1982, +0, 1783, 1970, +0, 1798, 1953, +0, 1818, 1929, +0, 1843, 1895, +0, 1874, 1846, +0, 1913, 1771, +0, 1960, 1645, +0, 2016, 1391, +0, 2082, 0, +0, 2157, 0, +0, 2241, 0, +0, 2334, 0, +0, 2434, 0, +0, 2541, 0, +0, 2653, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +0, 1740, 2018, +0, 1741, 2017, +0, 1743, 2016, +0, 1745, 2014, +0, 1748, 2011, +0, 1752, 2008, +0, 1757, 2003, +0, 1764, 1996, +0, 1773, 1988, +0, 1785, 1975, +0, 1800, 1959, +0, 1819, 1935, +0, 1844, 1902, +0, 1875, 1854, +0, 1914, 1779, +0, 1961, 1656, +0, 2017, 1412, +0, 2082, 13, +0, 2157, 0, +0, 2242, 0, +0, 2334, 0, +0, 2435, 0, +0, 2541, 0, +0, 2654, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3138, 0, +0, 3265, 0, +0, 3393, 0, +0, 3522, 0, +0, 3652, 0, +0, 1742, 2025, +0, 1743, 2024, +0, 1745, 2023, +0, 1747, 2021, +0, 1750, 2018, +0, 1754, 2015, +0, 1759, 2010, +0, 1766, 2004, +0, 1775, 1995, +0, 1786, 1983, +0, 1801, 1967, +0, 1821, 1944, +0, 1845, 1911, +0, 1876, 1864, +0, 1915, 1791, +0, 1962, 1672, +0, 2018, 1438, +0, 2083, 386, +0, 2158, 0, +0, 2242, 0, +0, 2335, 0, +0, 2435, 0, +0, 2542, 0, +0, 2654, 0, +0, 2770, 0, +0, 2890, 0, +0, 3013, 0, +0, 3139, 0, +0, 3265, 0, +0, 3393, 0, +0, 3523, 0, +0, 3652, 0, +0, 1744, 2035, +0, 1746, 2033, +0, 1747, 2032, +0, 1749, 2030, +0, 1752, 2028, +0, 1756, 2024, +0, 1761, 2020, +0, 1768, 2013, +0, 1777, 2005, +0, 1788, 1993, +0, 1803, 1977, +0, 1823, 1955, +0, 1847, 1923, +0, 1878, 1877, +0, 1917, 1806, +0, 1963, 1691, +0, 2019, 1470, +0, 2084, 640, +0, 2159, 0, +0, 2243, 0, +0, 2336, 0, +0, 2436, 0, +0, 2542, 0, +0, 2654, 0, +0, 2771, 0, +0, 2891, 0, +0, 3014, 0, +0, 3139, 0, +0, 3265, 0, +0, 3393, 0, +0, 3523, 0, +0, 3652, 0, +0, 1748, 2046, +0, 1749, 2045, +0, 1750, 2044, +0, 1753, 2042, +0, 1755, 2040, +0, 1759, 2036, +0, 1764, 2032, +0, 1771, 2026, +0, 1780, 2018, +0, 1791, 2006, +0, 1806, 1991, +0, 1825, 1969, +0, 1850, 1938, +0, 1881, 1893, +0, 1919, 1826, +0, 1965, 1716, +0, 2021, 1510, +0, 2086, 846, +0, 2160, 0, +0, 2244, 0, +0, 2336, 0, +0, 2436, 0, +0, 2543, 0, +0, 2655, 0, +0, 2771, 0, +0, 2891, 0, +0, 3014, 0, +0, 3139, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3652, 0, +0, 1752, 2062, +0, 1753, 2061, +0, 1755, 2060, +0, 1757, 2058, +0, 1760, 2055, +0, 1763, 2052, +0, 1768, 2048, +0, 1775, 2042, +0, 1784, 2034, +0, 1795, 2023, +0, 1810, 2008, +0, 1829, 1987, +0, 1853, 1958, +0, 1884, 1915, +0, 1922, 1851, +0, 1968, 1748, +0, 2023, 1559, +0, 2088, 1026, +0, 2162, 0, +0, 2246, 0, +0, 2338, 0, +0, 2437, 0, +0, 2543, 0, +0, 2655, 0, +0, 2771, 0, +0, 2891, 0, +0, 3014, 0, +0, 3139, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3652, 0, +0, 1757, 2082, +0, 1759, 2081, +0, 1760, 2080, +0, 1762, 2078, +0, 1765, 2076, +0, 1769, 2073, +0, 1774, 2068, +0, 1780, 2063, +0, 1789, 2055, +0, 1800, 2045, +0, 1815, 2030, +0, 1834, 2011, +0, 1858, 1983, +0, 1888, 1942, +0, 1925, 1882, +0, 1971, 1787, +0, 2026, 1616, +0, 2090, 1191, +0, 2164, 0, +0, 2247, 0, +0, 2339, 0, +0, 2438, 0, +0, 2544, 0, +0, 2656, 0, +0, 2772, 0, +0, 2892, 0, +0, 3014, 0, +0, 3139, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3653, 0, +30, 1765, 2107, +0, 1766, 2106, +0, 1767, 2105, +0, 1770, 2103, +0, 1772, 2101, +0, 1776, 2098, +0, 1781, 2094, +0, 1787, 2089, +0, 1796, 2082, +0, 1807, 2072, +0, 1821, 2059, +0, 1840, 2040, +0, 1864, 2014, +0, 1893, 1976, +0, 1931, 1921, +0, 1976, 1834, +0, 2030, 1684, +0, 2094, 1346, +0, 2167, 0, +0, 2250, 0, +0, 2341, 0, +0, 2440, 0, +0, 2546, 0, +0, 2657, 0, +0, 2773, 0, +0, 2892, 0, +0, 3015, 0, +0, 3140, 0, +0, 3266, 0, +0, 3394, 0, +0, 3523, 0, +0, 3653, 0, +1247, 1774, 2139, +1239, 1775, 2138, +1228, 1777, 2137, +1213, 1779, 2136, +1193, 1782, 2133, +1163, 1785, 2131, +1121, 1790, 2127, +1058, 1796, 2122, +956, 1805, 2116, +771, 1816, 2106, +265, 1830, 2094, +0, 1848, 2077, +0, 1871, 2053, +0, 1901, 2018, +0, 1937, 1968, +0, 1982, 1890, +0, 2036, 1760, +0, 2099, 1495, +0, 2171, 0, +0, 2253, 0, +0, 2344, 0, +0, 2442, 0, +0, 2547, 0, +0, 2658, 0, +0, 2774, 0, +0, 2893, 0, +0, 3015, 0, +0, 3140, 0, +0, 3267, 0, +0, 3394, 0, +0, 3523, 0, +0, 3653, 0, +1614, 1787, 2178, +1611, 1788, 2178, +1606, 1790, 2177, +1600, 1792, 2175, +1591, 1794, 2173, +1579, 1798, 2171, +1563, 1802, 2167, +1540, 1808, 2163, +1507, 1817, 2157, +1459, 1827, 2149, +1387, 1841, 2137, +1267, 1859, 2122, +1031, 1881, 2100, +0, 1910, 2069, +0, 1946, 2024, +0, 1990, 1956, +0, 2043, 1846, +0, 2105, 1639, +0, 2177, 963, +0, 2258, 0, +0, 2348, 0, +0, 2445, 0, +0, 2550, 0, +0, 2660, 0, +0, 2775, 0, +0, 2894, 0, +0, 3016, 0, +0, 3141, 0, +0, 3267, 0, +0, 3395, 0, +0, 3523, 0, +0, 3653, 0, +1867, 1803, 2226, +1865, 1804, 2225, +1862, 1806, 2224, +1858, 1808, 2223, +1853, 1810, 2222, +1847, 1814, 2219, +1838, 1818, 2216, +1825, 1824, 2212, +1808, 1832, 2207, +1784, 1842, 2199, +1750, 1855, 2189, +1700, 1873, 2175, +1623, 1895, 2156, +1494, 1923, 2129, +1232, 1958, 2090, +0, 2000, 2032, +0, 2052, 1940, +0, 2113, 1780, +0, 2184, 1399, +0, 2264, 0, +0, 2352, 0, +0, 2449, 0, +0, 2553, 0, +0, 2663, 0, +0, 2777, 0, +0, 2896, 0, +0, 3017, 0, +0, 3142, 0, +0, 3268, 0, +0, 3395, 0, +0, 3524, 0, +0, 3653, 0, +2071, 1824, 2283, +2070, 1825, 2282, +2068, 1827, 2282, +2066, 1828, 2281, +2063, 1831, 2279, +2059, 1834, 2277, +2053, 1838, 2274, +2046, 1844, 2271, +2035, 1851, 2266, +2021, 1861, 2260, +2001, 1874, 2251, +1973, 1891, 2239, +1932, 1912, 2222, +1871, 1939, 2198, +1775, 1973, 2165, +1602, 2014, 2117, +1165, 2064, 2042, +0, 2124, 1918, +0, 2193, 1672, +0, 2271, 186, +0, 2359, 0, +0, 2454, 0, +0, 2557, 0, +0, 2666, 0, +0, 2780, 0, +0, 2898, 0, +0, 3019, 0, +0, 3143, 0, +0, 3268, 0, +0, 3396, 0, +0, 3524, 0, +0, 3654, 0, +2251, 1851, 2350, +2250, 1852, 2349, +2249, 1853, 2348, +2248, 1855, 2347, +2246, 1857, 2346, +2243, 1860, 2344, +2239, 1864, 2342, +2234, 1869, 2339, +2227, 1877, 2335, +2218, 1886, 2329, +2205, 1898, 2322, +2187, 1914, 2311, +2162, 1934, 2297, +2127, 1960, 2277, +2074, 1992, 2250, +1993, 2032, 2210, +1855, 2080, 2150, +1563, 2138, 2055, +0, 2205, 1887, +0, 2281, 1471, +0, 2367, 0, +0, 2461, 0, +0, 2562, 0, +0, 2670, 0, +0, 2783, 0, +0, 2900, 0, +0, 3021, 0, +0, 3144, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +2416, 1884, 2425, +2415, 1885, 2425, +2415, 1886, 2424, +2413, 1888, 2424, +2412, 1890, 2423, +2410, 1893, 2421, +2408, 1896, 2419, +2404, 1901, 2417, +2399, 1908, 2413, +2393, 1917, 2408, +2384, 1928, 2402, +2372, 1943, 2393, +2356, 1962, 2382, +2333, 1986, 2365, +2300, 2017, 2342, +2253, 2054, 2310, +2180, 2101, 2263, +2060, 2156, 2191, +1826, 2220, 2072, +763, 2295, 1841, +0, 2378, 850, +0, 2470, 0, +0, 2570, 0, +0, 2676, 0, +0, 2787, 0, +0, 2904, 0, +0, 3023, 0, +0, 3146, 0, +0, 3271, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +2571, 1925, 2511, +2571, 1926, 2510, +2570, 1927, 2510, +2569, 1928, 2509, +2568, 1930, 2508, +2567, 1933, 2507, +2565, 1936, 2505, +2563, 1941, 2503, +2559, 1947, 2500, +2555, 1955, 2496, +2549, 1965, 2491, +2540, 1979, 2484, +2529, 1997, 2474, +2514, 2019, 2461, +2492, 2048, 2443, +2461, 2083, 2417, +2417, 2126, 2380, +2350, 2179, 2326, +2240, 2240, 2240, +2036, 2312, 2094, +1384, 2392, 1771, +0, 2482, 0, +0, 2579, 0, +0, 2683, 0, +0, 2793, 0, +0, 2908, 0, +0, 3027, 0, +0, 3149, 0, +0, 3273, 0, +0, 3399, 0, +0, 3527, 0, +0, 3656, 0, +2720, 1975, 2604, +2719, 1975, 2604, +2719, 1976, 2603, +2718, 1978, 2603, +2718, 1979, 2602, +2717, 1982, 2601, +2715, 1985, 2600, +2713, 1989, 2598, +2711, 1994, 2596, +2708, 2002, 2593, +2704, 2011, 2588, +2698, 2023, 2583, +2690, 2039, 2575, +2679, 2060, 2564, +2664, 2086, 2550, +2643, 2119, 2529, +2614, 2159, 2501, +2571, 2208, 2460, +2508, 2266, 2398, +2405, 2333, 2299, +2218, 2411, 2122, +1698, 2497, 1658, +0, 2591, 0, +0, 2693, 0, +0, 2801, 0, +0, 2914, 0, +0, 3032, 0, +0, 3152, 0, +0, 3276, 0, +0, 3401, 0, +0, 3529, 0, +0, 3657, 0, +2864, 2033, 2705, +2863, 2034, 2705, +2863, 2035, 2704, +2863, 2036, 2704, +2862, 2038, 2703, +2861, 2040, 2703, +2860, 2042, 2702, +2859, 2046, 2700, +2857, 2051, 2698, +2855, 2057, 2696, +2852, 2066, 2692, +2848, 2076, 2688, +2842, 2091, 2682, +2834, 2109, 2673, +2824, 2133, 2662, +2809, 2162, 2646, +2789, 2199, 2624, +2761, 2244, 2593, +2720, 2298, 2548, +2658, 2361, 2479, +2560, 2434, 2368, +2385, 2516, 2156, +1930, 2607, 1441, +0, 2706, 0, +0, 2811, 0, +0, 2922, 0, +0, 3038, 0, +0, 3157, 0, +0, 3279, 0, +0, 3404, 0, +0, 3531, 0, +0, 3658, 0, +3004, 2102, 2812, +3004, 2102, 2812, +3004, 2103, 2812, +3004, 2104, 2811, +3003, 2105, 2811, +3003, 2107, 2810, +3002, 2110, 2810, +3001, 2113, 2808, +3000, 2117, 2807, +2998, 2122, 2805, +2996, 2130, 2802, +2993, 2139, 2799, +2989, 2152, 2794, +2983, 2168, 2787, +2976, 2188, 2779, +2965, 2215, 2766, +2951, 2248, 2750, +2931, 2288, 2726, +2903, 2337, 2693, +2863, 2396, 2644, +2804, 2464, 2570, +2709, 2541, 2446, +2541, 2628, 2199, +2125, 2722, 664, +0, 2824, 0, +0, 2932, 0, +0, 3046, 0, +0, 3163, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3660, 0, +3143, 2180, 2925, +3143, 2180, 2925, +3143, 2181, 2924, +3142, 2182, 2924, +3142, 2183, 2924, +3142, 2184, 2923, +3141, 2186, 2923, +3141, 2189, 2922, +3140, 2192, 2921, +3138, 2197, 2919, +3137, 2203, 2917, +3134, 2211, 2914, +3131, 2222, 2911, +3127, 2236, 2906, +3122, 2254, 2899, +3114, 2276, 2890, +3104, 2305, 2877, +3090, 2341, 2859, +3071, 2385, 2835, +3043, 2438, 2799, +3004, 2500, 2748, +2945, 2572, 2668, +2853, 2653, 2532, +2690, 2743, 2250, +2299, 2841, 0, +0, 2946, 0, +0, 3056, 0, +0, 3171, 0, +0, 3290, 0, +0, 3412, 0, +0, 3537, 0, +0, 3663, 0, +3280, 2267, 3042, +3280, 2267, 3042, +3280, 2267, 3041, +3279, 2268, 3041, +3279, 2269, 3041, +3279, 2270, 3041, +3278, 2272, 3040, +3278, 2274, 3039, +3277, 2277, 3039, +3276, 2281, 3037, +3275, 2286, 3036, +3273, 2293, 3034, +3271, 2302, 3031, +3268, 2313, 3027, +3264, 2328, 3022, +3259, 2348, 3015, +3251, 2373, 3005, +3241, 2404, 2992, +3227, 2442, 2974, +3208, 2489, 2948, +3181, 2545, 2911, +3142, 2611, 2857, +3085, 2686, 2773, +2994, 2770, 2628, +2835, 2863, 2310, +2460, 2963, 0, +0, 3070, 0, +0, 3182, 0, +0, 3299, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +3415, 2362, 3162, +3415, 2362, 3162, +3415, 2362, 3162, +3415, 2363, 3162, +3415, 2364, 3162, +3415, 2365, 3161, +3414, 2366, 3161, +3414, 2368, 3160, +3414, 2370, 3160, +3413, 2373, 3159, +3412, 2377, 3158, +3411, 2383, 3156, +3409, 2390, 3154, +3407, 2400, 3151, +3404, 2412, 3147, +3400, 2429, 3142, +3394, 2449, 3134, +3387, 2476, 3124, +3377, 2509, 3111, +3363, 2550, 3092, +3344, 2599, 3066, +3318, 2658, 3028, +3279, 2726, 2971, +3222, 2804, 2883, +3132, 2891, 2730, +2976, 2985, 2380, +2613, 3088, 0, +0, 3196, 0, +0, 3309, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3550, 2464, 3285, +3550, 2464, 3285, +3550, 2464, 3285, +3550, 2465, 3285, +3550, 2465, 3285, +3550, 2466, 3285, +3549, 2467, 3284, +3549, 2469, 3284, +3549, 2471, 3284, +3548, 2473, 3283, +3548, 2477, 3282, +3547, 2481, 3281, +3545, 2487, 3279, +3544, 2495, 3277, +3542, 2505, 3274, +3539, 2518, 3270, +3535, 2535, 3264, +3529, 2557, 3257, +3522, 2585, 3247, +3512, 2620, 3233, +3498, 2663, 3214, +3479, 2714, 3187, +3453, 2775, 3148, +3415, 2845, 3090, +3358, 2925, 2999, +3269, 3014, 2838, +3115, 3110, 2460, +2760, 3214, 0, +0, 3323, 0, +0, 3438, 0, +0, 3556, 0, +0, 3678, 0, +3684, 2572, 3411, +3684, 2572, 3411, +3684, 2573, 3411, +3684, 2573, 3410, +3684, 2574, 3410, +3684, 2574, 3410, +3684, 2575, 3410, +3683, 2576, 3410, +3683, 2578, 3409, +3683, 2580, 3409, +3682, 2582, 3408, +3682, 2586, 3407, +3681, 2591, 3406, +3679, 2597, 3404, +3678, 2605, 3402, +3676, 2616, 3399, +3673, 2630, 3395, +3669, 2647, 3389, +3663, 2670, 3382, +3656, 2699, 3371, +3646, 2736, 3357, +3633, 2780, 3338, +3614, 2833, 3310, +3587, 2895, 3270, +3549, 2967, 3211, +3493, 3049, 3118, +3405, 3139, 2952, +3252, 3237, 2548, +2902, 3342, 0, +0, 3452, 0, +0, 3567, 0, +0, 3686, 0, +3818, 2686, 3538, +3818, 2686, 3538, +3818, 2686, 3538, +3818, 2686, 3537, +3817, 2687, 3537, +3817, 2687, 3537, +3817, 2688, 3537, +3817, 2689, 3537, +3817, 2690, 3537, +3817, 2692, 3536, +3816, 2694, 3536, +3816, 2696, 3535, +3815, 2700, 3534, +3814, 2705, 3533, +3813, 2711, 3531, +3811, 2720, 3529, +3809, 2731, 3526, +3806, 2745, 3522, +3802, 2764, 3516, +3797, 2788, 3508, +3790, 2818, 3498, +3780, 2855, 3484, +3766, 2900, 3464, +3748, 2955, 3436, +3721, 3018, 3395, +3683, 3092, 3335, +3627, 3174, 3240, +3540, 3266, 3070, +3387, 3365, 2644, +3042, 3470, 0, +0, 3582, 0, +0, 3697, 0, +3951, 2804, 3666, +3951, 2804, 3666, +3951, 2804, 3666, +3951, 2804, 3666, +3951, 2804, 3666, +3951, 2805, 3666, +3951, 2805, 3665, +3950, 2806, 3665, +3950, 2807, 3665, +3950, 2808, 3665, +3950, 2810, 3664, +3949, 2812, 3664, +3949, 2815, 3663, +3948, 2818, 3662, +3947, 2823, 3661, +3946, 2830, 3659, +3944, 2839, 3657, +3942, 2850, 3654, +3939, 2865, 3650, +3935, 2884, 3644, +3930, 2909, 3636, +3923, 2939, 3626, +3913, 2977, 3611, +3900, 3024, 3591, +3881, 3079, 3563, +3855, 3144, 3522, +3817, 3218, 3461, +3761, 3302, 3364, +3674, 3394, 3191, +3522, 3494, 2748, +3180, 3600, 0, +0, 3712, 0, +4084, 2925, 3795, +4084, 2925, 3795, +4084, 2925, 3795, +4084, 2925, 3795, +4084, 2925, 3795, +4084, 2926, 3795, +4083, 2926, 3795, +4083, 2926, 3795, +4083, 2927, 3794, +4083, 2928, 3794, +4083, 2929, 3794, +4083, 2931, 3794, +4082, 2933, 3793, +4082, 2936, 3792, +4081, 2940, 3791, +4080, 2945, 3790, +4079, 2952, 3788, +4077, 2961, 3786, +4075, 2972, 3783, +4072, 2988, 3779, +4068, 3007, 3773, +4063, 3032, 3765, +4056, 3063, 3755, +4046, 3102, 3740, +4033, 3149, 3720, +4014, 3205, 3691, +3988, 3271, 3650, +3950, 3346, 3589, +3894, 3430, 3491, +3807, 3523, 3314, +3656, 3623, 2857, +3317, 3730, 0, +4095, 3048, 3925, +4095, 3048, 3925, +4095, 3048, 3925, +4095, 3049, 3925, +4095, 3049, 3925, +4095, 3049, 3925, +4095, 3049, 3925, +4095, 3050, 3925, +4095, 3050, 3924, +4095, 3051, 3924, +4095, 3052, 3924, +4095, 3053, 3924, +4095, 3055, 3923, +4095, 3057, 3923, +4095, 3060, 3922, +4095, 3064, 3921, +4095, 3069, 3920, +4095, 3076, 3918, +4095, 3085, 3916, +4095, 3097, 3913, +4095, 3112, 3908, +4095, 3132, 3903, +4095, 3157, 3895, +4095, 3189, 3884, +4095, 3228, 3870, +4095, 3276, 3849, +4095, 3333, 3821, +4095, 3399, 3779, +4083, 3475, 3717, +4027, 3560, 3619, +3940, 3653, 3440, +3790, 3754, 2972, +4095, 3174, 4055, +4095, 3174, 4055, +4095, 3174, 4055, +4095, 3174, 4055, +4095, 3174, 4055, +4095, 3174, 4055, +4095, 3175, 4055, +4095, 3175, 4055, +4095, 3175, 4055, +4095, 3176, 4055, +4095, 3177, 4055, +4095, 3178, 4055, +4095, 3179, 4054, +4095, 3181, 4054, +4095, 3183, 4053, +4095, 3186, 4053, +4095, 3190, 4052, +4095, 3195, 4050, +4095, 3202, 4049, +4095, 3211, 4046, +4095, 3223, 4043, +4095, 3239, 4039, +4095, 3259, 4033, +4095, 3285, 4025, +4095, 3317, 4015, +4095, 3356, 4000, +4095, 3404, 3979, +4095, 3461, 3951, +4095, 3528, 3909, +4095, 3604, 3847, +4095, 3690, 3747, +4073, 3783, 3567, +0, 1867, 2134, +0, 1868, 2133, +0, 1869, 2132, +0, 1871, 2130, +0, 1873, 2128, +0, 1876, 2126, +0, 1880, 2122, +0, 1885, 2117, +0, 1892, 2110, +0, 1901, 2101, +0, 1913, 2088, +0, 1928, 2071, +0, 1948, 2047, +0, 1973, 2012, +0, 2004, 1961, +0, 2043, 1882, +0, 2090, 1749, +0, 2146, 1473, +0, 2212, 0, +0, 2288, 0, +0, 2372, 0, +0, 2465, 0, +0, 2566, 0, +0, 2673, 0, +0, 2785, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +0, 1867, 2135, +0, 1868, 2134, +0, 1869, 2133, +0, 1871, 2132, +0, 1873, 2130, +0, 1876, 2127, +0, 1880, 2123, +0, 1885, 2118, +0, 1892, 2112, +0, 1901, 2102, +0, 1913, 2090, +0, 1928, 2072, +0, 1948, 2048, +0, 1973, 2013, +0, 2004, 1962, +0, 2043, 1884, +0, 2090, 1752, +0, 2147, 1479, +0, 2213, 0, +0, 2288, 0, +0, 2372, 0, +0, 2465, 0, +0, 2566, 0, +0, 2673, 0, +0, 2785, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3654, 0, +0, 1868, 2137, +0, 1869, 2136, +0, 1870, 2135, +0, 1872, 2133, +0, 1874, 2131, +0, 1877, 2129, +0, 1881, 2125, +0, 1886, 2120, +0, 1893, 2113, +0, 1902, 2104, +0, 1913, 2092, +0, 1929, 2074, +0, 1948, 2050, +0, 1973, 2016, +0, 2004, 1965, +0, 2043, 1887, +0, 2091, 1756, +0, 2147, 1486, +0, 2213, 0, +0, 2288, 0, +0, 2373, 0, +0, 2466, 0, +0, 2566, 0, +0, 2673, 0, +0, 2785, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +0, 1868, 2139, +0, 1869, 2138, +0, 1870, 2137, +0, 1872, 2136, +0, 1874, 2134, +0, 1877, 2131, +0, 1881, 2127, +0, 1886, 2122, +0, 1893, 2116, +0, 1902, 2107, +0, 1914, 2094, +0, 1929, 2077, +0, 1949, 2053, +0, 1974, 2019, +0, 2005, 1968, +0, 2044, 1891, +0, 2091, 1761, +0, 2147, 1495, +0, 2213, 0, +0, 2288, 0, +0, 2373, 0, +0, 2466, 0, +0, 2566, 0, +0, 2673, 0, +0, 2785, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +0, 1869, 2142, +0, 1870, 2141, +0, 1871, 2140, +0, 1873, 2139, +0, 1875, 2137, +0, 1878, 2134, +0, 1882, 2130, +0, 1887, 2125, +0, 1894, 2119, +0, 1903, 2110, +0, 1915, 2097, +0, 1930, 2080, +0, 1949, 2056, +0, 1974, 2022, +0, 2005, 1973, +0, 2044, 1896, +0, 2091, 1768, +0, 2148, 1508, +0, 2213, 0, +0, 2289, 0, +0, 2373, 0, +0, 2466, 0, +0, 2566, 0, +0, 2673, 0, +0, 2785, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +0, 1870, 2146, +0, 1871, 2145, +0, 1872, 2144, +0, 1874, 2143, +0, 1876, 2141, +0, 1879, 2138, +0, 1883, 2134, +0, 1888, 2130, +0, 1895, 2123, +0, 1904, 2114, +0, 1915, 2102, +0, 1931, 2085, +0, 1950, 2061, +0, 1975, 2028, +0, 2006, 1978, +0, 2045, 1903, +0, 2092, 1777, +0, 2148, 1523, +0, 2214, 0, +0, 2289, 0, +0, 2373, 0, +0, 2466, 0, +0, 2567, 0, +0, 2673, 0, +0, 2786, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3270, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +0, 1871, 2151, +0, 1872, 2151, +0, 1874, 2149, +0, 1875, 2148, +0, 1877, 2146, +0, 1880, 2143, +0, 1884, 2140, +0, 1889, 2135, +0, 1896, 2129, +0, 1905, 2120, +0, 1917, 2108, +0, 1932, 2091, +0, 1951, 2068, +0, 1976, 2034, +0, 2007, 1986, +0, 2046, 1912, +0, 2093, 1788, +0, 2149, 1544, +0, 2214, 145, +0, 2290, 0, +0, 2374, 0, +0, 2467, 0, +0, 2567, 0, +0, 2674, 0, +0, 2786, 0, +0, 2902, 0, +0, 3022, 0, +0, 3145, 0, +0, 3271, 0, +0, 3397, 0, +0, 3525, 0, +0, 3655, 0, +0, 1873, 2158, +0, 1874, 2157, +0, 1875, 2156, +0, 1877, 2155, +0, 1879, 2153, +0, 1882, 2150, +0, 1886, 2147, +0, 1891, 2142, +0, 1898, 2136, +0, 1907, 2127, +0, 1918, 2115, +0, 1933, 2099, +0, 1953, 2076, +0, 1977, 2043, +0, 2009, 1996, +0, 2047, 1923, +0, 2094, 1804, +0, 2150, 1570, +0, 2215, 518, +0, 2290, 0, +0, 2374, 0, +0, 2467, 0, +0, 2567, 0, +0, 2674, 0, +0, 2786, 0, +0, 2902, 0, +0, 3023, 0, +0, 3146, 0, +0, 3271, 0, +0, 3397, 0, +0, 3526, 0, +0, 3655, 0, +0, 1876, 2167, +0, 1876, 2167, +0, 1878, 2166, +0, 1879, 2164, +0, 1882, 2162, +0, 1884, 2160, +0, 1888, 2156, +0, 1893, 2152, +0, 1900, 2145, +0, 1909, 2137, +0, 1920, 2125, +0, 1935, 2109, +0, 1955, 2087, +0, 1979, 2055, +0, 2010, 2009, +0, 2049, 1938, +0, 2095, 1823, +0, 2151, 1602, +0, 2216, 772, +0, 2291, 0, +0, 2375, 0, +0, 2468, 0, +0, 2568, 0, +0, 2674, 0, +0, 2786, 0, +0, 2903, 0, +0, 3023, 0, +0, 3146, 0, +0, 3271, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +0, 1879, 2179, +0, 1880, 2179, +0, 1881, 2178, +0, 1883, 2176, +0, 1885, 2174, +0, 1888, 2172, +0, 1891, 2168, +0, 1896, 2164, +0, 1903, 2158, +0, 1912, 2150, +0, 1923, 2138, +0, 1938, 2123, +0, 1957, 2101, +0, 1982, 2070, +0, 2013, 2026, +0, 2051, 1958, +0, 2097, 1848, +0, 2153, 1642, +0, 2218, 978, +0, 2293, 0, +0, 2376, 0, +0, 2469, 0, +0, 2568, 0, +0, 2675, 0, +0, 2787, 0, +0, 2903, 0, +0, 3023, 0, +0, 3146, 0, +0, 3271, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +0, 1883, 2195, +0, 1884, 2194, +0, 1885, 2193, +0, 1887, 2192, +0, 1889, 2190, +0, 1892, 2188, +0, 1895, 2184, +0, 1900, 2180, +0, 1907, 2174, +0, 1916, 2166, +0, 1927, 2155, +0, 1942, 2140, +0, 1961, 2119, +0, 1985, 2090, +0, 2016, 2047, +0, 2054, 1983, +0, 2100, 1880, +0, 2155, 1691, +0, 2220, 1158, +0, 2294, 0, +0, 2378, 0, +0, 2470, 0, +0, 2569, 0, +0, 2676, 0, +0, 2787, 0, +0, 2904, 0, +0, 3023, 0, +0, 3146, 0, +0, 3271, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +0, 1889, 2215, +0, 1889, 2214, +0, 1891, 2213, +0, 1892, 2212, +0, 1894, 2210, +0, 1897, 2208, +0, 1901, 2205, +0, 1906, 2200, +0, 1912, 2195, +0, 1921, 2187, +0, 1932, 2177, +0, 1947, 2163, +0, 1966, 2143, +0, 1990, 2115, +0, 2020, 2074, +0, 2058, 2014, +0, 2103, 1919, +0, 2158, 1748, +0, 2223, 1323, +0, 2296, 0, +0, 2380, 0, +0, 2471, 0, +0, 2571, 0, +0, 2677, 0, +0, 2788, 0, +0, 2904, 0, +0, 3024, 0, +0, 3146, 0, +0, 3271, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +241, 1896, 2240, +162, 1897, 2239, +31, 1898, 2238, +0, 1900, 2237, +0, 1902, 2236, +0, 1904, 2233, +0, 1908, 2230, +0, 1913, 2227, +0, 1919, 2221, +0, 1928, 2214, +0, 1939, 2204, +0, 1953, 2191, +0, 1972, 2172, +0, 1996, 2146, +0, 2026, 2108, +0, 2063, 2053, +0, 2108, 1966, +0, 2162, 1816, +0, 2226, 1478, +0, 2299, 0, +0, 2382, 0, +0, 2473, 0, +0, 2572, 0, +0, 2678, 0, +0, 2789, 0, +0, 2905, 0, +0, 3024, 0, +0, 3147, 0, +0, 3272, 0, +0, 3398, 0, +0, 3526, 0, +0, 3655, 0, +1385, 1906, 2272, +1379, 1906, 2271, +1371, 1908, 2270, +1360, 1909, 2269, +1345, 1911, 2268, +1325, 1914, 2266, +1296, 1917, 2263, +1253, 1922, 2259, +1190, 1929, 2254, +1089, 1937, 2248, +903, 1948, 2239, +397, 1962, 2226, +0, 1980, 2209, +0, 2003, 2185, +0, 2033, 2150, +0, 2069, 2100, +0, 2114, 2023, +0, 2168, 1893, +0, 2231, 1627, +0, 2303, 0, +0, 2385, 0, +0, 2476, 0, +0, 2574, 0, +0, 2680, 0, +0, 2790, 0, +0, 2906, 0, +0, 3025, 0, +0, 3148, 0, +0, 3272, 0, +0, 3399, 0, +0, 3526, 0, +0, 3655, 0, +1749, 1918, 2311, +1747, 1919, 2310, +1743, 1920, 2310, +1738, 1922, 2309, +1732, 1924, 2307, +1723, 1926, 2305, +1711, 1930, 2303, +1695, 1934, 2300, +1672, 1941, 2295, +1639, 1949, 2289, +1592, 1959, 2281, +1519, 1973, 2269, +1399, 1991, 2254, +1164, 2014, 2232, +83, 2042, 2201, +0, 2078, 2156, +0, 2122, 2088, +0, 2175, 1978, +0, 2237, 1771, +0, 2309, 1096, +0, 2390, 0, +0, 2480, 0, +0, 2577, 0, +0, 2682, 0, +0, 2792, 0, +0, 2907, 0, +0, 3026, 0, +0, 3148, 0, +0, 3273, 0, +0, 3399, 0, +0, 3527, 0, +0, 3656, 0, +2000, 1935, 2359, +1999, 1935, 2358, +1997, 1936, 2358, +1994, 1938, 2357, +1990, 1940, 2355, +1985, 1942, 2354, +1979, 1946, 2351, +1970, 1950, 2348, +1957, 1956, 2344, +1940, 1964, 2339, +1916, 1974, 2331, +1882, 1988, 2321, +1832, 2005, 2307, +1755, 2027, 2288, +1626, 2055, 2261, +1364, 2090, 2222, +0, 2133, 2164, +0, 2184, 2073, +0, 2245, 1912, +0, 2316, 1531, +0, 2396, 0, +0, 2484, 0, +0, 2581, 0, +0, 2685, 0, +0, 2795, 0, +0, 2909, 0, +0, 3028, 0, +0, 3149, 0, +0, 3274, 0, +0, 3400, 0, +0, 3527, 0, +0, 3656, 0, +2205, 1955, 2416, +2204, 1956, 2415, +2202, 1957, 2415, +2201, 1959, 2414, +2198, 1960, 2413, +2195, 1963, 2411, +2191, 1966, 2409, +2185, 1970, 2407, +2178, 1976, 2403, +2167, 1984, 2398, +2153, 1993, 2392, +2133, 2006, 2383, +2105, 2023, 2371, +2064, 2044, 2354, +2003, 2071, 2331, +1907, 2105, 2297, +1734, 2146, 2249, +1297, 2196, 2174, +0, 2256, 2050, +0, 2325, 1804, +0, 2403, 318, +0, 2491, 0, +0, 2586, 0, +0, 2689, 0, +0, 2798, 0, +0, 2912, 0, +0, 3030, 0, +0, 3151, 0, +0, 3275, 0, +0, 3401, 0, +0, 3528, 0, +0, 3656, 0, +2384, 1982, 2482, +2383, 1983, 2482, +2382, 1984, 2481, +2381, 1985, 2480, +2380, 1987, 2479, +2378, 1989, 2478, +2375, 1992, 2476, +2371, 1996, 2474, +2366, 2002, 2471, +2359, 2009, 2467, +2350, 2018, 2461, +2337, 2030, 2454, +2319, 2046, 2443, +2294, 2066, 2429, +2259, 2092, 2410, +2206, 2124, 2382, +2125, 2164, 2342, +1987, 2212, 2282, +1696, 2270, 2187, +0, 2337, 2019, +0, 2414, 1603, +0, 2499, 0, +0, 2593, 0, +0, 2694, 0, +0, 2802, 0, +0, 2915, 0, +0, 3032, 0, +0, 3153, 0, +0, 3276, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +2549, 2015, 2558, +2548, 2016, 2558, +2547, 2017, 2557, +2547, 2018, 2557, +2546, 2020, 2556, +2544, 2022, 2555, +2542, 2025, 2553, +2540, 2029, 2551, +2536, 2034, 2549, +2531, 2040, 2545, +2525, 2049, 2541, +2516, 2060, 2534, +2504, 2075, 2526, +2488, 2094, 2514, +2465, 2118, 2497, +2432, 2149, 2475, +2385, 2187, 2442, +2312, 2233, 2395, +2192, 2288, 2323, +1958, 2352, 2204, +895, 2427, 1973, +0, 2510, 982, +0, 2602, 0, +0, 2702, 0, +0, 2808, 0, +0, 2919, 0, +0, 3036, 0, +0, 3156, 0, +0, 3278, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +2703, 2056, 2643, +2703, 2057, 2643, +2703, 2058, 2642, +2702, 2059, 2642, +2701, 2060, 2641, +2700, 2062, 2640, +2699, 2065, 2639, +2697, 2068, 2637, +2695, 2073, 2635, +2691, 2079, 2632, +2687, 2087, 2629, +2681, 2097, 2623, +2673, 2111, 2616, +2661, 2129, 2607, +2646, 2151, 2593, +2624, 2180, 2575, +2593, 2215, 2549, +2549, 2259, 2512, +2482, 2311, 2458, +2373, 2373, 2373, +2168, 2444, 2226, +1516, 2524, 1903, +0, 2614, 0, +0, 2711, 0, +0, 2815, 0, +0, 2925, 0, +0, 3040, 0, +0, 3159, 0, +0, 3281, 0, +0, 3405, 0, +0, 3531, 0, +0, 3659, 0, +2852, 2106, 2736, +2852, 2107, 2736, +2851, 2107, 2736, +2851, 2108, 2735, +2850, 2110, 2735, +2850, 2111, 2734, +2849, 2114, 2733, +2847, 2117, 2732, +2846, 2121, 2730, +2843, 2126, 2728, +2840, 2134, 2725, +2836, 2143, 2720, +2830, 2155, 2715, +2822, 2171, 2707, +2811, 2192, 2696, +2796, 2218, 2682, +2775, 2251, 2662, +2746, 2291, 2633, +2703, 2340, 2592, +2640, 2398, 2530, +2537, 2466, 2431, +2350, 2543, 2254, +1830, 2629, 1790, +0, 2723, 0, +0, 2825, 0, +0, 2933, 0, +0, 3046, 0, +0, 3164, 0, +0, 3284, 0, +0, 3408, 0, +0, 3533, 0, +0, 3661, 0, +2996, 2165, 2837, +2996, 2165, 2837, +2995, 2166, 2837, +2995, 2167, 2836, +2995, 2168, 2836, +2994, 2170, 2835, +2994, 2172, 2835, +2993, 2174, 2834, +2991, 2178, 2832, +2990, 2183, 2830, +2987, 2189, 2828, +2984, 2198, 2825, +2980, 2209, 2820, +2974, 2223, 2814, +2966, 2241, 2805, +2956, 2265, 2794, +2941, 2294, 2778, +2921, 2331, 2756, +2893, 2376, 2725, +2852, 2430, 2680, +2790, 2493, 2611, +2693, 2566, 2500, +2517, 2648, 2288, +2062, 2739, 1573, +0, 2838, 0, +0, 2943, 0, +0, 3054, 0, +0, 3170, 0, +0, 3289, 0, +0, 3412, 0, +0, 3536, 0, +0, 3663, 0, +3137, 2233, 2944, +3136, 2234, 2944, +3136, 2234, 2944, +3136, 2235, 2944, +3136, 2236, 2944, +3135, 2238, 2943, +3135, 2239, 2942, +3134, 2242, 2942, +3133, 2245, 2941, +3132, 2249, 2939, +3130, 2254, 2937, +3128, 2262, 2934, +3125, 2271, 2931, +3121, 2284, 2926, +3115, 2300, 2920, +3108, 2320, 2911, +3097, 2347, 2899, +3083, 2380, 2882, +3063, 2420, 2858, +3036, 2469, 2825, +2996, 2528, 2776, +2936, 2596, 2702, +2841, 2673, 2578, +2673, 2760, 2331, +2257, 2854, 796, +0, 2956, 0, +0, 3064, 0, +0, 3178, 0, +0, 3295, 0, +0, 3416, 0, +0, 3540, 0, +0, 3665, 0, +3275, 2311, 3057, +3275, 2312, 3057, +3275, 2312, 3057, +3275, 2313, 3057, +3275, 2314, 3056, +3274, 2315, 3056, +3274, 2316, 3055, +3273, 2318, 3055, +3273, 2321, 3054, +3272, 2324, 3053, +3270, 2329, 3051, +3269, 2335, 3049, +3267, 2343, 3046, +3263, 2354, 3043, +3259, 2368, 3038, +3254, 2386, 3031, +3246, 2409, 3022, +3236, 2437, 3009, +3222, 2473, 2991, +3203, 2517, 2967, +3175, 2570, 2931, +3136, 2633, 2880, +3078, 2704, 2800, +2985, 2786, 2665, +2822, 2875, 2382, +2431, 2973, 0, +0, 3078, 0, +0, 3188, 0, +0, 3303, 0, +0, 3422, 0, +0, 3545, 0, +0, 3669, 0, +3412, 2398, 3174, +3412, 2399, 3174, +3412, 2399, 3174, +3412, 2400, 3174, +3411, 2400, 3173, +3411, 2401, 3173, +3411, 2402, 3173, +3411, 2404, 3172, +3410, 2406, 3172, +3409, 2409, 3171, +3408, 2413, 3170, +3407, 2418, 3168, +3406, 2425, 3166, +3403, 2434, 3163, +3400, 2445, 3159, +3396, 2461, 3154, +3391, 2480, 3147, +3383, 2505, 3137, +3373, 2536, 3124, +3360, 2574, 3106, +3340, 2621, 3080, +3313, 2677, 3043, +3275, 2743, 2989, +3217, 2818, 2905, +3126, 2902, 2760, +2967, 2995, 2442, +2592, 3095, 0, +0, 3202, 0, +0, 3314, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +3547, 2493, 3294, +3547, 2494, 3294, +3547, 2494, 3294, +3547, 2494, 3294, +3547, 2495, 3294, +3547, 2496, 3294, +3547, 2497, 3293, +3547, 2498, 3293, +3546, 2500, 3293, +3546, 2502, 3292, +3545, 2505, 3291, +3544, 2510, 3290, +3543, 2515, 3288, +3541, 2522, 3286, +3539, 2532, 3283, +3536, 2545, 3279, +3532, 2561, 3274, +3527, 2582, 3266, +3519, 2608, 3257, +3509, 2641, 3243, +3496, 2682, 3224, +3476, 2731, 3198, +3450, 2790, 3160, +3411, 2858, 3103, +3354, 2936, 3015, +3265, 3023, 2862, +3108, 3118, 2512, +2745, 3220, 0, +0, 3328, 0, +0, 3442, 0, +0, 3559, 0, +0, 3680, 0, +3682, 2596, 3418, +3682, 2596, 3417, +3682, 2596, 3417, +3682, 2597, 3417, +3682, 2597, 3417, +3682, 2598, 3417, +3682, 2598, 3417, +3681, 2599, 3417, +3681, 2601, 3416, +3681, 2603, 3416, +3680, 2605, 3415, +3680, 2609, 3414, +3679, 2613, 3413, +3677, 2619, 3411, +3676, 2627, 3409, +3674, 2637, 3406, +3671, 2650, 3402, +3667, 2667, 3396, +3661, 2689, 3389, +3654, 2717, 3379, +3644, 2752, 3365, +3630, 2795, 3346, +3612, 2846, 3319, +3585, 2907, 3280, +3547, 2977, 3222, +3490, 3057, 3131, +3401, 3146, 2970, +3247, 3242, 2592, +2892, 3346, 0, +0, 3456, 0, +0, 3570, 0, +0, 3689, 0, +3816, 2704, 3543, +3816, 2704, 3543, +3816, 2705, 3543, +3816, 2705, 3543, +3816, 2705, 3543, +3816, 2706, 3542, +3816, 2706, 3542, +3816, 2707, 3542, +3815, 2708, 3542, +3815, 2710, 3541, +3815, 2712, 3541, +3814, 2714, 3540, +3814, 2718, 3539, +3813, 2723, 3538, +3811, 2729, 3536, +3810, 2737, 3534, +3808, 2748, 3531, +3805, 2762, 3527, +3801, 2780, 3521, +3795, 2803, 3514, +3788, 2832, 3504, +3778, 2868, 3489, +3765, 2912, 3470, +3746, 2965, 3442, +3719, 3027, 3403, +3681, 3099, 3343, +3625, 3181, 3250, +3537, 3271, 3084, +3384, 3369, 2680, +3034, 3474, 0, +0, 3584, 0, +0, 3699, 0, +3950, 2818, 3670, +3950, 2818, 3670, +3950, 2818, 3670, +3950, 2818, 3670, +3950, 2819, 3670, +3950, 2819, 3669, +3949, 2819, 3669, +3949, 2820, 3669, +3949, 2821, 3669, +3949, 2822, 3669, +3949, 2824, 3668, +3948, 2826, 3668, +3948, 2829, 3667, +3947, 2832, 3666, +3946, 2837, 3665, +3945, 2844, 3663, +3943, 2852, 3661, +3941, 2863, 3658, +3938, 2878, 3654, +3934, 2896, 3648, +3929, 2920, 3640, +3922, 2950, 3630, +3912, 2987, 3616, +3898, 3032, 3596, +3880, 3087, 3568, +3853, 3151, 3528, +3815, 3224, 3467, +3759, 3307, 3372, +3672, 3398, 3202, +3520, 3497, 2776, +3174, 3602, 0, +0, 3714, 0, +4083, 2936, 3798, +4083, 2936, 3798, +4083, 2936, 3798, +4083, 2936, 3798, +4083, 2936, 3798, +4083, 2936, 3798, +4083, 2937, 3798, +4083, 2937, 3798, +4082, 2938, 3797, +4082, 2939, 3797, +4082, 2940, 3797, +4082, 2942, 3796, +4081, 2944, 3796, +4081, 2947, 3795, +4080, 2951, 3794, +4079, 2956, 3793, +4078, 2962, 3791, +4077, 2971, 3789, +4074, 2982, 3786, +4071, 2997, 3782, +4068, 3016, 3776, +4062, 3041, 3768, +4055, 3071, 3758, +4045, 3109, 3743, +4032, 3156, 3723, +4013, 3211, 3695, +3987, 3276, 3654, +3949, 3350, 3593, +3893, 3434, 3496, +3806, 3526, 3323, +3654, 3626, 2880, +3312, 3732, 0, +4095, 3057, 3927, +4095, 3057, 3927, +4095, 3057, 3927, +4095, 3057, 3927, +4095, 3057, 3927, +4095, 3057, 3927, +4095, 3058, 3927, +4095, 3058, 3927, +4095, 3059, 3927, +4095, 3059, 3927, +4095, 3060, 3926, +4095, 3061, 3926, +4095, 3063, 3926, +4095, 3065, 3925, +4095, 3068, 3924, +4095, 3072, 3923, +4095, 3077, 3922, +4095, 3084, 3920, +4095, 3093, 3918, +4095, 3105, 3915, +4095, 3120, 3911, +4095, 3139, 3905, +4095, 3164, 3897, +4095, 3195, 3887, +4095, 3234, 3872, +4095, 3281, 3852, +4095, 3337, 3823, +4095, 3403, 3782, +4082, 3478, 3721, +4026, 3562, 3623, +3939, 3655, 3446, +3788, 3755, 2989, +4095, 3180, 4057, +4095, 3180, 4057, +4095, 3180, 4057, +4095, 3181, 4057, +4095, 3181, 4057, +4095, 3181, 4057, +4095, 3181, 4057, +4095, 3181, 4057, +4095, 3182, 4057, +4095, 3182, 4057, +4095, 3183, 4056, +4095, 3184, 4056, +4095, 3185, 4056, +4095, 3187, 4055, +4095, 3189, 4055, +4095, 3192, 4054, +4095, 3196, 4053, +4095, 3201, 4052, +4095, 3208, 4050, +4095, 3217, 4048, +4095, 3229, 4045, +4095, 3245, 4040, +4095, 3264, 4035, +4095, 3290, 4027, +4095, 3321, 4016, +4095, 3360, 4002, +4095, 3408, 3981, +4095, 3465, 3953, +4095, 3531, 3911, +4095, 3607, 3849, +4095, 3692, 3751, +4073, 3785, 3572, +0, 1998, 2266, +0, 1999, 2265, +0, 2000, 2264, +0, 2001, 2263, +0, 2003, 2262, +0, 2005, 2260, +0, 2008, 2257, +0, 2012, 2253, +0, 2017, 2248, +0, 2024, 2241, +0, 2033, 2232, +0, 2045, 2219, +0, 2060, 2202, +0, 2079, 2177, +0, 2104, 2143, +0, 2136, 2091, +0, 2175, 2012, +0, 2222, 1879, +0, 2278, 1601, +0, 2344, 0, +0, 2420, 0, +0, 2504, 0, +0, 2597, 0, +0, 2698, 0, +0, 2805, 0, +0, 2917, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +0, 1998, 2267, +0, 1999, 2266, +0, 2000, 2265, +0, 2001, 2264, +0, 2003, 2263, +0, 2005, 2260, +0, 2008, 2258, +0, 2012, 2254, +0, 2017, 2249, +0, 2024, 2242, +0, 2033, 2233, +0, 2045, 2220, +0, 2060, 2203, +0, 2080, 2179, +0, 2105, 2144, +0, 2136, 2093, +0, 2175, 2014, +0, 2222, 1881, +0, 2279, 1606, +0, 2344, 0, +0, 2420, 0, +0, 2504, 0, +0, 2597, 0, +0, 2698, 0, +0, 2805, 0, +0, 2917, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +0, 1999, 2268, +0, 1999, 2267, +0, 2000, 2266, +0, 2002, 2265, +0, 2003, 2264, +0, 2005, 2262, +0, 2008, 2259, +0, 2012, 2255, +0, 2017, 2250, +0, 2024, 2244, +0, 2033, 2234, +0, 2045, 2222, +0, 2060, 2204, +0, 2080, 2180, +0, 2105, 2145, +0, 2136, 2095, +0, 2175, 2016, +0, 2222, 1884, +0, 2279, 1611, +0, 2345, 0, +0, 2420, 0, +0, 2505, 0, +0, 2598, 0, +0, 2698, 0, +0, 2805, 0, +0, 2917, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +0, 1999, 2270, +0, 2000, 2269, +0, 2001, 2268, +0, 2002, 2267, +0, 2004, 2265, +0, 2006, 2263, +0, 2009, 2261, +0, 2013, 2257, +0, 2018, 2252, +0, 2025, 2245, +0, 2034, 2236, +0, 2045, 2224, +0, 2061, 2206, +0, 2080, 2182, +0, 2105, 2148, +0, 2137, 2097, +0, 2175, 2019, +0, 2223, 1888, +0, 2279, 1618, +0, 2345, 0, +0, 2420, 0, +0, 2505, 0, +0, 2598, 0, +0, 2698, 0, +0, 2805, 0, +0, 2917, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +0, 2000, 2272, +0, 2000, 2271, +0, 2001, 2270, +0, 2003, 2269, +0, 2004, 2268, +0, 2006, 2266, +0, 2009, 2263, +0, 2013, 2259, +0, 2018, 2254, +0, 2025, 2248, +0, 2034, 2239, +0, 2046, 2226, +0, 2061, 2209, +0, 2081, 2185, +0, 2106, 2151, +0, 2137, 2100, +0, 2176, 2023, +0, 2223, 1893, +0, 2279, 1627, +0, 2345, 0, +0, 2420, 0, +0, 2505, 0, +0, 2598, 0, +0, 2698, 0, +0, 2805, 0, +0, 2917, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3402, 0, +0, 3529, 0, +0, 3657, 0, +0, 2000, 2275, +0, 2001, 2274, +0, 2002, 2273, +0, 2003, 2272, +0, 2005, 2271, +0, 2007, 2269, +0, 2010, 2266, +0, 2014, 2262, +0, 2019, 2258, +0, 2026, 2251, +0, 2035, 2242, +0, 2047, 2230, +0, 2062, 2212, +0, 2081, 2189, +0, 2106, 2155, +0, 2138, 2105, +0, 2176, 2028, +0, 2223, 1900, +0, 2280, 1640, +0, 2345, 0, +0, 2421, 0, +0, 2505, 0, +0, 2598, 0, +0, 2698, 0, +0, 2805, 0, +0, 2917, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3403, 0, +0, 3529, 0, +0, 3658, 0, +0, 2001, 2279, +0, 2002, 2278, +0, 2003, 2277, +0, 2004, 2276, +0, 2006, 2275, +0, 2008, 2273, +0, 2011, 2270, +0, 2015, 2267, +0, 2020, 2262, +0, 2027, 2255, +0, 2036, 2246, +0, 2048, 2234, +0, 2063, 2217, +0, 2082, 2193, +0, 2107, 2160, +0, 2138, 2110, +0, 2177, 2035, +0, 2224, 1909, +0, 2280, 1655, +0, 2346, 0, +0, 2421, 0, +0, 2505, 0, +0, 2598, 0, +0, 2699, 0, +0, 2805, 0, +0, 2918, 0, +0, 3034, 0, +0, 3154, 0, +0, 3277, 0, +0, 3403, 0, +0, 3529, 0, +0, 3658, 0, +0, 2003, 2284, +0, 2003, 2283, +0, 2004, 2283, +0, 2006, 2282, +0, 2007, 2280, +0, 2009, 2278, +0, 2012, 2275, +0, 2016, 2272, +0, 2021, 2267, +0, 2028, 2261, +0, 2037, 2252, +0, 2049, 2240, +0, 2064, 2223, +0, 2083, 2200, +0, 2108, 2166, +0, 2139, 2118, +0, 2178, 2044, +0, 2225, 1921, +0, 2281, 1676, +0, 2347, 277, +0, 2422, 0, +0, 2506, 0, +0, 2599, 0, +0, 2699, 0, +0, 2806, 0, +0, 2918, 0, +0, 3034, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3529, 0, +0, 3658, 0, +0, 2005, 2291, +0, 2005, 2290, +0, 2006, 2290, +0, 2007, 2288, +0, 2009, 2287, +0, 2011, 2285, +0, 2014, 2283, +0, 2018, 2279, +0, 2023, 2274, +0, 2030, 2268, +0, 2039, 2259, +0, 2050, 2247, +0, 2065, 2231, +0, 2085, 2208, +0, 2110, 2175, +0, 2141, 2128, +0, 2179, 2055, +0, 2226, 1936, +0, 2282, 1702, +0, 2347, 650, +0, 2422, 0, +0, 2507, 0, +0, 2599, 0, +0, 2699, 0, +0, 2806, 0, +0, 2918, 0, +0, 3035, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +0, 2007, 2300, +0, 2008, 2299, +0, 2009, 2299, +0, 2010, 2298, +0, 2011, 2296, +0, 2014, 2294, +0, 2017, 2292, +0, 2020, 2288, +0, 2025, 2284, +0, 2032, 2277, +0, 2041, 2269, +0, 2053, 2257, +0, 2068, 2241, +0, 2087, 2219, +0, 2111, 2187, +0, 2142, 2141, +0, 2181, 2071, +0, 2227, 1955, +0, 2283, 1734, +0, 2349, 904, +0, 2423, 0, +0, 2507, 0, +0, 2600, 0, +0, 2700, 0, +0, 2806, 0, +0, 2918, 0, +0, 3035, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +0, 2010, 2312, +0, 2011, 2311, +0, 2012, 2311, +0, 2013, 2310, +0, 2015, 2308, +0, 2017, 2306, +0, 2020, 2304, +0, 2023, 2301, +0, 2029, 2296, +0, 2035, 2290, +0, 2044, 2282, +0, 2055, 2270, +0, 2070, 2255, +0, 2090, 2233, +0, 2114, 2202, +0, 2145, 2158, +0, 2183, 2090, +0, 2229, 1980, +0, 2285, 1774, +0, 2350, 1110, +0, 2425, 0, +0, 2508, 0, +0, 2601, 0, +0, 2700, 0, +0, 2807, 0, +0, 2919, 0, +0, 3035, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +0, 2014, 2327, +0, 2015, 2327, +0, 2016, 2326, +0, 2017, 2325, +0, 2019, 2324, +0, 2021, 2322, +0, 2024, 2320, +0, 2028, 2316, +0, 2033, 2312, +0, 2039, 2306, +0, 2048, 2298, +0, 2059, 2287, +0, 2074, 2272, +0, 2093, 2251, +0, 2117, 2222, +0, 2148, 2179, +0, 2186, 2115, +0, 2232, 2012, +0, 2287, 1823, +0, 2352, 1290, +0, 2426, 0, +0, 2510, 0, +0, 2602, 0, +0, 2701, 0, +0, 2808, 0, +0, 2919, 0, +0, 3036, 0, +0, 3155, 0, +0, 3278, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +0, 2020, 2347, +0, 2021, 2347, +0, 2022, 2346, +0, 2023, 2345, +0, 2024, 2344, +0, 2026, 2342, +0, 2029, 2340, +0, 2033, 2337, +0, 2038, 2333, +0, 2044, 2327, +0, 2053, 2319, +0, 2064, 2309, +0, 2079, 2295, +0, 2098, 2275, +0, 2122, 2247, +0, 2152, 2206, +0, 2190, 2146, +0, 2235, 2051, +0, 2290, 1881, +0, 2355, 1455, +0, 2429, 0, +0, 2512, 0, +0, 2603, 0, +0, 2703, 0, +0, 2809, 0, +0, 2920, 0, +0, 3036, 0, +0, 3156, 0, +0, 3279, 0, +0, 3403, 0, +0, 3530, 0, +0, 3658, 0, +423, 2027, 2373, +373, 2028, 2372, +295, 2029, 2371, +163, 2030, 2370, +0, 2032, 2369, +0, 2034, 2368, +0, 2036, 2365, +0, 2040, 2363, +0, 2045, 2359, +0, 2051, 2353, +0, 2060, 2346, +0, 2071, 2336, +0, 2085, 2323, +0, 2104, 2304, +0, 2128, 2278, +0, 2158, 2241, +0, 2195, 2185, +0, 2240, 2098, +0, 2294, 1948, +0, 2358, 1610, +0, 2432, 0, +0, 2514, 0, +0, 2605, 0, +0, 2704, 0, +0, 2810, 0, +0, 2921, 0, +0, 3037, 0, +0, 3157, 0, +0, 3279, 0, +0, 3404, 0, +0, 3530, 0, +0, 3658, 0, +1521, 2037, 2404, +1517, 2038, 2404, +1511, 2039, 2403, +1503, 2040, 2402, +1492, 2041, 2401, +1477, 2043, 2400, +1457, 2046, 2398, +1428, 2050, 2395, +1385, 2054, 2391, +1322, 2061, 2386, +1221, 2069, 2380, +1036, 2080, 2371, +529, 2094, 2358, +0, 2112, 2341, +0, 2135, 2317, +0, 2165, 2283, +0, 2201, 2232, +0, 2246, 2155, +0, 2300, 2025, +0, 2363, 1759, +0, 2436, 0, +0, 2518, 0, +0, 2608, 0, +0, 2707, 0, +0, 2812, 0, +0, 2923, 0, +0, 3038, 0, +0, 3157, 0, +0, 3280, 0, +0, 3404, 0, +0, 3531, 0, +0, 3659, 0, +1883, 2050, 2444, +1881, 2050, 2443, +1879, 2051, 2443, +1875, 2052, 2442, +1870, 2054, 2441, +1864, 2056, 2439, +1855, 2058, 2437, +1843, 2062, 2435, +1827, 2066, 2432, +1804, 2073, 2427, +1771, 2081, 2421, +1724, 2091, 2413, +1651, 2105, 2401, +1531, 2123, 2386, +1296, 2146, 2364, +216, 2174, 2333, +0, 2210, 2288, +0, 2254, 2221, +0, 2307, 2111, +0, 2369, 1903, +0, 2441, 1228, +0, 2522, 0, +0, 2612, 0, +0, 2709, 0, +0, 2814, 0, +0, 2924, 0, +0, 3039, 0, +0, 3158, 0, +0, 3280, 0, +0, 3405, 0, +0, 3531, 0, +0, 3659, 0, +2133, 2066, 2491, +2132, 2067, 2491, +2131, 2067, 2490, +2129, 2068, 2490, +2126, 2070, 2489, +2122, 2072, 2487, +2118, 2074, 2486, +2111, 2078, 2484, +2102, 2082, 2481, +2089, 2088, 2476, +2072, 2096, 2471, +2048, 2106, 2464, +2014, 2120, 2453, +1964, 2137, 2440, +1887, 2159, 2420, +1758, 2187, 2393, +1496, 2222, 2354, +0, 2265, 2296, +0, 2316, 2205, +0, 2377, 2044, +0, 2448, 1663, +0, 2528, 0, +0, 2617, 0, +0, 2713, 0, +0, 2817, 0, +0, 2927, 0, +0, 3041, 0, +0, 3160, 0, +0, 3282, 0, +0, 3406, 0, +0, 3532, 0, +0, 3659, 0, +2337, 2087, 2548, +2337, 2088, 2548, +2336, 2088, 2547, +2334, 2089, 2547, +2333, 2091, 2546, +2330, 2093, 2545, +2327, 2095, 2543, +2323, 2098, 2541, +2317, 2103, 2539, +2310, 2108, 2535, +2299, 2116, 2530, +2285, 2126, 2524, +2265, 2138, 2515, +2237, 2155, 2503, +2196, 2176, 2486, +2135, 2203, 2463, +2039, 2237, 2429, +1866, 2278, 2381, +1429, 2329, 2306, +0, 2388, 2182, +0, 2457, 1936, +0, 2536, 450, +0, 2623, 0, +0, 2718, 0, +0, 2821, 0, +0, 2930, 0, +0, 3044, 0, +0, 3162, 0, +0, 3283, 0, +0, 3407, 0, +0, 3533, 0, +0, 3660, 0, +2517, 2114, 2614, +2516, 2114, 2614, +2515, 2115, 2614, +2515, 2116, 2613, +2513, 2117, 2612, +2512, 2119, 2612, +2510, 2121, 2610, +2507, 2124, 2609, +2503, 2128, 2606, +2498, 2134, 2603, +2491, 2141, 2599, +2482, 2150, 2593, +2469, 2162, 2586, +2451, 2178, 2576, +2426, 2198, 2561, +2391, 2224, 2542, +2338, 2256, 2514, +2257, 2296, 2474, +2119, 2344, 2414, +1828, 2402, 2319, +0, 2469, 2151, +0, 2546, 1735, +0, 2631, 0, +0, 2725, 0, +0, 2827, 0, +0, 2934, 0, +0, 3047, 0, +0, 3164, 0, +0, 3285, 0, +0, 3408, 0, +0, 3534, 0, +0, 3661, 0, +2681, 2147, 2690, +2681, 2147, 2690, +2680, 2148, 2690, +2680, 2149, 2689, +2679, 2150, 2689, +2678, 2152, 2688, +2676, 2154, 2687, +2674, 2157, 2685, +2672, 2161, 2683, +2668, 2166, 2681, +2663, 2172, 2677, +2657, 2181, 2673, +2648, 2192, 2666, +2636, 2207, 2658, +2620, 2226, 2646, +2597, 2250, 2629, +2565, 2281, 2607, +2517, 2319, 2574, +2444, 2365, 2527, +2325, 2420, 2455, +2090, 2485, 2336, +1027, 2559, 2105, +0, 2642, 1114, +0, 2734, 0, +0, 2834, 0, +0, 2940, 0, +0, 3052, 0, +0, 3168, 0, +0, 3288, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +2836, 2188, 2775, +2836, 2189, 2775, +2835, 2189, 2775, +2835, 2190, 2774, +2834, 2191, 2774, +2833, 2193, 2773, +2832, 2194, 2772, +2831, 2197, 2771, +2829, 2201, 2770, +2827, 2205, 2767, +2823, 2211, 2765, +2819, 2219, 2761, +2813, 2230, 2755, +2805, 2243, 2748, +2793, 2261, 2739, +2778, 2283, 2725, +2756, 2312, 2707, +2726, 2347, 2681, +2681, 2391, 2644, +2614, 2443, 2590, +2505, 2505, 2505, +2300, 2576, 2358, +1648, 2656, 2036, +0, 2746, 0, +0, 2843, 0, +0, 2947, 0, +0, 3057, 0, +0, 3172, 0, +0, 3291, 0, +0, 3413, 0, +0, 3537, 0, +0, 3664, 0, +2984, 2238, 2869, +2984, 2238, 2868, +2984, 2239, 2868, +2983, 2239, 2868, +2983, 2240, 2868, +2983, 2242, 2867, +2982, 2244, 2866, +2981, 2246, 2865, +2979, 2249, 2864, +2978, 2253, 2862, +2975, 2259, 2860, +2972, 2266, 2857, +2968, 2275, 2853, +2962, 2287, 2847, +2954, 2303, 2839, +2943, 2324, 2828, +2928, 2350, 2814, +2907, 2383, 2794, +2878, 2423, 2765, +2836, 2472, 2724, +2772, 2530, 2662, +2669, 2598, 2563, +2482, 2675, 2386, +1962, 2761, 1922, +0, 2855, 0, +0, 2957, 0, +0, 3065, 0, +0, 3178, 0, +0, 3296, 0, +0, 3417, 0, +0, 3540, 0, +0, 3666, 0, +3128, 2297, 2969, +3128, 2297, 2969, +3128, 2298, 2969, +3128, 2298, 2969, +3127, 2299, 2969, +3127, 2300, 2968, +3126, 2302, 2968, +3126, 2304, 2967, +3125, 2307, 2966, +3123, 2310, 2964, +3122, 2315, 2962, +3119, 2321, 2960, +3116, 2330, 2957, +3112, 2341, 2952, +3106, 2355, 2946, +3099, 2373, 2938, +3088, 2397, 2926, +3073, 2426, 2910, +3053, 2463, 2888, +3025, 2508, 2857, +2984, 2562, 2812, +2922, 2625, 2744, +2825, 2698, 2632, +2649, 2780, 2420, +2195, 2871, 1705, +0, 2970, 0, +0, 3075, 0, +0, 3186, 0, +0, 3302, 0, +0, 3421, 0, +0, 3544, 0, +0, 3668, 0, +3269, 2365, 3077, +3269, 2366, 3077, +3269, 2366, 3076, +3268, 2367, 3076, +3268, 2367, 3076, +3268, 2368, 3076, +3268, 2370, 3075, +3267, 2371, 3075, +3266, 2374, 3074, +3265, 2377, 3073, +3264, 2381, 3071, +3262, 2387, 3069, +3260, 2394, 3067, +3257, 2403, 3063, +3253, 2416, 3058, +3247, 2432, 3052, +3240, 2453, 3043, +3229, 2479, 3031, +3215, 2512, 3014, +3195, 2552, 2990, +3168, 2601, 2957, +3128, 2660, 2908, +3068, 2728, 2834, +2973, 2805, 2710, +2805, 2892, 2463, +2389, 2986, 928, +0, 3088, 0, +0, 3197, 0, +0, 3310, 0, +0, 3427, 0, +0, 3548, 0, +0, 3672, 0, +3407, 2443, 3189, +3407, 2444, 3189, +3407, 2444, 3189, +3407, 2444, 3189, +3407, 2445, 3189, +3407, 2446, 3188, +3406, 2447, 3188, +3406, 2448, 3188, +3405, 2450, 3187, +3405, 2453, 3186, +3404, 2457, 3185, +3403, 2461, 3183, +3401, 2467, 3181, +3399, 2475, 3179, +3396, 2486, 3175, +3392, 2500, 3170, +3386, 2518, 3163, +3379, 2541, 3154, +3368, 2570, 3141, +3354, 2605, 3123, +3335, 2649, 3099, +3308, 2702, 3064, +3268, 2765, 3012, +3210, 2836, 2932, +3117, 2918, 2797, +2954, 3008, 2514, +2563, 3105, 0, +0, 3210, 0, +0, 3320, 0, +0, 3436, 0, +0, 3555, 0, +0, 3677, 0, +3544, 2530, 3306, +3544, 2530, 3306, +3544, 2531, 3306, +3544, 2531, 3306, +3544, 2532, 3306, +3544, 2532, 3305, +3543, 2533, 3305, +3543, 2534, 3305, +3543, 2536, 3304, +3542, 2538, 3304, +3541, 2541, 3303, +3541, 2545, 3302, +3539, 2550, 3300, +3538, 2557, 3298, +3535, 2566, 3295, +3532, 2578, 3291, +3528, 2593, 3286, +3523, 2612, 3279, +3516, 2637, 3269, +3505, 2668, 3256, +3492, 2707, 3238, +3472, 2754, 3212, +3445, 2810, 3175, +3407, 2875, 3121, +3349, 2950, 3037, +3258, 3034, 2892, +3099, 3127, 2574, +2724, 3227, 0, +0, 3334, 0, +0, 3446, 0, +0, 3563, 0, +0, 3683, 0, +3680, 2625, 3427, +3680, 2626, 3426, +3680, 2626, 3426, +3679, 2626, 3426, +3679, 2626, 3426, +3679, 2627, 3426, +3679, 2628, 3426, +3679, 2629, 3426, +3679, 2630, 3425, +3678, 2632, 3425, +3678, 2634, 3424, +3677, 2637, 3423, +3676, 2642, 3422, +3675, 2647, 3420, +3673, 2655, 3418, +3671, 2664, 3415, +3668, 2677, 3411, +3664, 2693, 3406, +3659, 2714, 3399, +3651, 2740, 3389, +3641, 2773, 3375, +3628, 2814, 3356, +3609, 2863, 3330, +3582, 2922, 3292, +3543, 2990, 3236, +3486, 3068, 3147, +3397, 3155, 2994, +3240, 3250, 2644, +2877, 3352, 0, +0, 3460, 0, +0, 3574, 0, +0, 3691, 0, +3814, 2728, 3550, +3814, 2728, 3550, +3814, 2728, 3550, +3814, 2728, 3550, +3814, 2729, 3549, +3814, 2729, 3549, +3814, 2730, 3549, +3814, 2730, 3549, +3814, 2732, 3549, +3813, 2733, 3548, +3813, 2735, 3548, +3812, 2737, 3547, +3812, 2741, 3546, +3811, 2745, 3545, +3810, 2751, 3543, +3808, 2759, 3541, +3806, 2769, 3538, +3803, 2782, 3534, +3799, 2800, 3528, +3793, 2822, 3521, +3786, 2849, 3511, +3776, 2884, 3497, +3763, 2927, 3478, +3744, 2978, 3451, +3717, 3039, 3412, +3679, 3109, 3354, +3622, 3189, 3263, +3534, 3278, 3102, +3379, 3374, 2724, +3024, 3478, 0, +0, 3588, 0, +0, 3702, 0, +3948, 2836, 3675, +3948, 2836, 3675, +3948, 2836, 3675, +3948, 2837, 3675, +3948, 2837, 3675, +3948, 2837, 3675, +3948, 2838, 3675, +3948, 2838, 3674, +3948, 2839, 3674, +3948, 2840, 3674, +3947, 2842, 3673, +3947, 2844, 3673, +3946, 2847, 3672, +3946, 2850, 3671, +3945, 2855, 3670, +3944, 2861, 3668, +3942, 2869, 3666, +3940, 2880, 3663, +3937, 2894, 3659, +3933, 2912, 3653, +3928, 2935, 3646, +3920, 2964, 3636, +3910, 3000, 3622, +3897, 3044, 3602, +3878, 3097, 3574, +3852, 3160, 3535, +3814, 3232, 3475, +3757, 3313, 3382, +3669, 3403, 3216, +3516, 3501, 2812, +3167, 3606, 0, +0, 3716, 0, +4082, 2950, 3802, +4082, 2950, 3802, +4082, 2950, 3802, +4082, 2950, 3802, +4082, 2950, 3802, +4082, 2951, 3802, +4082, 2951, 3802, +4082, 2952, 3801, +4081, 2952, 3801, +4081, 2953, 3801, +4081, 2954, 3801, +4081, 2956, 3800, +4080, 2958, 3800, +4080, 2961, 3799, +4079, 2964, 3798, +4078, 2969, 3797, +4077, 2976, 3795, +4075, 2984, 3793, +4073, 2995, 3790, +4070, 3010, 3786, +4066, 3028, 3780, +4061, 3052, 3772, +4054, 3082, 3762, +4044, 3119, 3748, +4030, 3164, 3728, +4012, 3219, 3700, +3985, 3283, 3660, +3948, 3356, 3599, +3892, 3439, 3504, +3804, 3530, 3334, +3652, 3629, 2909, +3307, 3735, 0, +4095, 3068, 3930, +4095, 3068, 3930, +4095, 3068, 3930, +4095, 3068, 3930, +4095, 3068, 3930, +4095, 3068, 3930, +4095, 3069, 3930, +4095, 3069, 3930, +4095, 3069, 3930, +4095, 3070, 3929, +4095, 3071, 3929, +4095, 3072, 3929, +4095, 3074, 3929, +4095, 3076, 3928, +4095, 3079, 3927, +4095, 3083, 3926, +4095, 3088, 3925, +4095, 3094, 3923, +4095, 3103, 3921, +4095, 3114, 3918, +4095, 3129, 3914, +4095, 3148, 3908, +4095, 3173, 3900, +4095, 3203, 3890, +4095, 3241, 3875, +4095, 3288, 3855, +4095, 3343, 3827, +4095, 3408, 3786, +4081, 3482, 3725, +4025, 3566, 3629, +3938, 3658, 3455, +3786, 3758, 3012, +4095, 3189, 4059, +4095, 3189, 4059, +4095, 3189, 4059, +4095, 3189, 4059, +4095, 3189, 4059, +4095, 3189, 4059, +4095, 3189, 4059, +4095, 3190, 4059, +4095, 3190, 4059, +4095, 3191, 4059, +4095, 3191, 4059, +4095, 3192, 4058, +4095, 3193, 4058, +4095, 3195, 4058, +4095, 3197, 4057, +4095, 3200, 4056, +4095, 3204, 4055, +4095, 3209, 4054, +4095, 3216, 4052, +4095, 3225, 4050, +4095, 3237, 4047, +4095, 3252, 4043, +4095, 3271, 4037, +4095, 3296, 4029, +4095, 3327, 4019, +4095, 3366, 4004, +4095, 3413, 3984, +4095, 3469, 3956, +4095, 3535, 3914, +4095, 3610, 3853, +4095, 3694, 3755, +4071, 3787, 3579, +0, 2129, 2398, +0, 2130, 2397, +0, 2131, 2396, +0, 2132, 2396, +0, 2133, 2394, +0, 2135, 2393, +0, 2137, 2391, +0, 2140, 2388, +0, 2144, 2384, +0, 2149, 2379, +0, 2156, 2373, +0, 2165, 2363, +0, 2176, 2351, +0, 2192, 2333, +0, 2211, 2309, +0, 2236, 2274, +0, 2268, 2222, +0, 2307, 2143, +0, 2354, 2009, +0, 2410, 1731, +0, 2476, 0, +0, 2552, 0, +0, 2636, 0, +0, 2729, 0, +0, 2830, 0, +0, 2937, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2130, 2398, +0, 2130, 2398, +0, 2131, 2397, +0, 2132, 2396, +0, 2133, 2395, +0, 2135, 2394, +0, 2137, 2392, +0, 2140, 2389, +0, 2144, 2385, +0, 2149, 2380, +0, 2156, 2373, +0, 2165, 2364, +0, 2177, 2352, +0, 2192, 2334, +0, 2212, 2310, +0, 2237, 2275, +0, 2268, 2223, +0, 2307, 2144, +0, 2354, 2011, +0, 2411, 1734, +0, 2476, 0, +0, 2552, 0, +0, 2636, 0, +0, 2729, 0, +0, 2830, 0, +0, 2937, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2130, 2399, +0, 2130, 2399, +0, 2131, 2398, +0, 2132, 2397, +0, 2133, 2396, +0, 2135, 2395, +0, 2137, 2393, +0, 2140, 2390, +0, 2144, 2386, +0, 2149, 2381, +0, 2156, 2374, +0, 2165, 2365, +0, 2177, 2353, +0, 2192, 2335, +0, 2212, 2311, +0, 2237, 2276, +0, 2268, 2225, +0, 2307, 2146, +0, 2354, 2013, +0, 2411, 1738, +0, 2477, 0, +0, 2552, 0, +0, 2637, 0, +0, 2730, 0, +0, 2830, 0, +0, 2937, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2130, 2400, +0, 2131, 2400, +0, 2131, 2399, +0, 2132, 2399, +0, 2134, 2397, +0, 2135, 2396, +0, 2138, 2394, +0, 2140, 2391, +0, 2144, 2387, +0, 2150, 2382, +0, 2156, 2376, +0, 2165, 2367, +0, 2177, 2354, +0, 2192, 2337, +0, 2212, 2312, +0, 2237, 2278, +0, 2268, 2227, +0, 2307, 2148, +0, 2354, 2016, +0, 2411, 1743, +0, 2477, 0, +0, 2552, 0, +0, 2637, 0, +0, 2730, 0, +0, 2830, 0, +0, 2937, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2131, 2402, +0, 2131, 2402, +0, 2132, 2401, +0, 2133, 2400, +0, 2134, 2399, +0, 2136, 2398, +0, 2138, 2396, +0, 2141, 2393, +0, 2145, 2389, +0, 2150, 2384, +0, 2157, 2377, +0, 2166, 2368, +0, 2177, 2356, +0, 2193, 2339, +0, 2212, 2314, +0, 2237, 2280, +0, 2269, 2229, +0, 2307, 2151, +0, 2355, 2020, +0, 2411, 1750, +0, 2477, 0, +0, 2552, 0, +0, 2637, 0, +0, 2730, 0, +0, 2830, 0, +0, 2937, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2131, 2404, +0, 2132, 2404, +0, 2132, 2403, +0, 2133, 2402, +0, 2135, 2401, +0, 2136, 2400, +0, 2139, 2398, +0, 2141, 2395, +0, 2145, 2391, +0, 2151, 2387, +0, 2157, 2380, +0, 2166, 2371, +0, 2178, 2358, +0, 2193, 2341, +0, 2213, 2317, +0, 2238, 2283, +0, 2269, 2232, +0, 2308, 2155, +0, 2355, 2025, +0, 2411, 1760, +0, 2477, 0, +0, 2553, 0, +0, 2637, 0, +0, 2730, 0, +0, 2830, 0, +0, 2937, 0, +0, 3049, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2132, 2407, +0, 2133, 2407, +0, 2133, 2406, +0, 2134, 2405, +0, 2135, 2404, +0, 2137, 2403, +0, 2139, 2401, +0, 2142, 2398, +0, 2146, 2395, +0, 2151, 2390, +0, 2158, 2383, +0, 2167, 2374, +0, 2179, 2362, +0, 2194, 2345, +0, 2213, 2321, +0, 2238, 2287, +0, 2270, 2237, +0, 2308, 2160, +0, 2356, 2032, +0, 2412, 1772, +0, 2478, 0, +0, 2553, 0, +0, 2637, 0, +0, 2730, 0, +0, 2830, 0, +0, 2937, 0, +0, 3050, 0, +0, 3166, 0, +0, 3286, 0, +0, 3409, 0, +0, 3535, 0, +0, 3661, 0, +0, 2133, 2411, +0, 2134, 2411, +0, 2134, 2410, +0, 2135, 2409, +0, 2136, 2408, +0, 2138, 2407, +0, 2140, 2405, +0, 2143, 2402, +0, 2147, 2399, +0, 2152, 2394, +0, 2159, 2387, +0, 2168, 2378, +0, 2180, 2366, +0, 2195, 2349, +0, 2214, 2325, +0, 2239, 2292, +0, 2270, 2242, +0, 2309, 2167, +0, 2356, 2041, +0, 2412, 1788, +0, 2478, 0, +0, 2553, 0, +0, 2638, 0, +0, 2730, 0, +0, 2831, 0, +0, 2937, 0, +0, 3050, 0, +0, 3166, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +0, 2134, 2417, +0, 2135, 2416, +0, 2136, 2416, +0, 2136, 2415, +0, 2138, 2414, +0, 2139, 2412, +0, 2142, 2410, +0, 2144, 2408, +0, 2148, 2404, +0, 2154, 2399, +0, 2160, 2393, +0, 2169, 2384, +0, 2181, 2372, +0, 2196, 2355, +0, 2215, 2332, +0, 2240, 2299, +0, 2271, 2250, +0, 2310, 2176, +0, 2357, 2053, +0, 2413, 1808, +0, 2479, 410, +0, 2554, 0, +0, 2638, 0, +0, 2731, 0, +0, 2831, 0, +0, 2938, 0, +0, 3050, 0, +0, 3166, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +0, 2136, 2424, +0, 2137, 2423, +0, 2137, 2422, +0, 2138, 2422, +0, 2140, 2421, +0, 2141, 2419, +0, 2143, 2417, +0, 2146, 2415, +0, 2150, 2411, +0, 2155, 2406, +0, 2162, 2400, +0, 2171, 2391, +0, 2182, 2379, +0, 2198, 2363, +0, 2217, 2340, +0, 2242, 2308, +0, 2273, 2260, +0, 2311, 2187, +0, 2358, 2068, +0, 2414, 1834, +0, 2479, 782, +0, 2554, 0, +0, 2639, 0, +0, 2731, 0, +0, 2831, 0, +0, 2938, 0, +0, 3050, 0, +0, 3167, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +0, 2139, 2433, +0, 2139, 2432, +0, 2140, 2432, +0, 2141, 2431, +0, 2142, 2430, +0, 2144, 2428, +0, 2146, 2426, +0, 2149, 2424, +0, 2152, 2420, +0, 2158, 2416, +0, 2164, 2410, +0, 2173, 2401, +0, 2185, 2389, +0, 2200, 2373, +0, 2219, 2351, +0, 2244, 2319, +0, 2274, 2273, +0, 2313, 2203, +0, 2360, 2088, +0, 2415, 1866, +0, 2481, 1036, +0, 2555, 0, +0, 2639, 0, +0, 2732, 0, +0, 2832, 0, +0, 2938, 0, +0, 3050, 0, +0, 3167, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +0, 2142, 2444, +0, 2142, 2444, +0, 2143, 2443, +0, 2144, 2443, +0, 2145, 2442, +0, 2147, 2440, +0, 2149, 2438, +0, 2152, 2436, +0, 2156, 2433, +0, 2161, 2428, +0, 2167, 2422, +0, 2176, 2414, +0, 2188, 2402, +0, 2202, 2387, +0, 2222, 2365, +0, 2246, 2334, +0, 2277, 2290, +0, 2315, 2222, +0, 2362, 2113, +0, 2417, 1906, +0, 2482, 1242, +0, 2557, 0, +0, 2640, 0, +0, 2733, 0, +0, 2833, 0, +0, 2939, 0, +0, 3051, 0, +0, 3167, 0, +0, 3287, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +0, 2146, 2460, +0, 2146, 2460, +0, 2147, 2459, +0, 2148, 2458, +0, 2149, 2457, +0, 2151, 2456, +0, 2153, 2454, +0, 2156, 2452, +0, 2160, 2448, +0, 2165, 2444, +0, 2171, 2438, +0, 2180, 2430, +0, 2191, 2419, +0, 2206, 2404, +0, 2225, 2383, +0, 2249, 2354, +0, 2280, 2311, +0, 2318, 2247, +0, 2364, 2144, +0, 2419, 1955, +0, 2484, 1422, +0, 2558, 0, +0, 2642, 0, +0, 2734, 0, +0, 2834, 0, +0, 2940, 0, +0, 3051, 0, +0, 3168, 0, +0, 3288, 0, +0, 3410, 0, +0, 3535, 0, +0, 3662, 0, +0, 2152, 2480, +0, 2152, 2479, +0, 2153, 2479, +0, 2154, 2478, +0, 2155, 2477, +0, 2156, 2476, +0, 2159, 2474, +0, 2161, 2472, +0, 2165, 2469, +0, 2170, 2465, +0, 2177, 2459, +0, 2185, 2451, +0, 2196, 2441, +0, 2211, 2427, +0, 2230, 2407, +0, 2254, 2379, +0, 2284, 2339, +0, 2322, 2278, +0, 2368, 2183, +0, 2422, 2013, +0, 2487, 1587, +0, 2561, 0, +0, 2644, 0, +0, 2735, 0, +0, 2835, 0, +0, 2941, 0, +0, 3052, 0, +0, 3168, 0, +0, 3288, 0, +0, 3411, 0, +0, 3536, 0, +0, 3662, 0, +590, 2159, 2505, +556, 2159, 2505, +505, 2160, 2504, +427, 2161, 2503, +295, 2162, 2503, +26, 2164, 2501, +0, 2166, 2500, +0, 2169, 2498, +0, 2172, 2495, +0, 2177, 2491, +0, 2184, 2485, +0, 2192, 2478, +0, 2203, 2468, +0, 2218, 2455, +0, 2236, 2436, +0, 2260, 2410, +0, 2290, 2373, +0, 2327, 2317, +0, 2372, 2230, +0, 2427, 2080, +0, 2490, 1742, +0, 2564, 0, +0, 2646, 0, +0, 2737, 0, +0, 2836, 0, +0, 2942, 0, +0, 3053, 0, +0, 3169, 0, +0, 3289, 0, +0, 3411, 0, +0, 3536, 0, +0, 3662, 0, +1656, 2169, 2537, +1653, 2169, 2536, +1649, 2170, 2536, +1643, 2171, 2535, +1635, 2172, 2534, +1624, 2173, 2533, +1610, 2175, 2532, +1589, 2178, 2530, +1560, 2182, 2527, +1518, 2186, 2523, +1454, 2193, 2518, +1353, 2201, 2512, +1168, 2212, 2503, +661, 2226, 2490, +0, 2244, 2473, +0, 2268, 2449, +0, 2297, 2415, +0, 2334, 2364, +0, 2378, 2287, +0, 2432, 2157, +0, 2495, 1891, +0, 2568, 0, +0, 2650, 0, +0, 2740, 0, +0, 2839, 0, +0, 2944, 0, +0, 3055, 0, +0, 3170, 0, +0, 3289, 0, +0, 3412, 0, +0, 3536, 0, +0, 3663, 0, +2017, 2181, 2576, +2015, 2182, 2576, +2013, 2182, 2575, +2011, 2183, 2575, +2007, 2184, 2574, +2002, 2186, 2573, +1996, 2188, 2571, +1987, 2190, 2570, +1975, 2194, 2567, +1959, 2199, 2564, +1936, 2205, 2559, +1903, 2213, 2553, +1856, 2223, 2545, +1783, 2237, 2533, +1663, 2255, 2518, +1428, 2278, 2496, +348, 2307, 2465, +0, 2342, 2420, +0, 2386, 2353, +0, 2439, 2243, +0, 2501, 2035, +0, 2573, 1360, +0, 2654, 0, +0, 2744, 0, +0, 2842, 0, +0, 2946, 0, +0, 3056, 0, +0, 3172, 0, +0, 3291, 0, +0, 3413, 0, +0, 3537, 0, +0, 3663, 0, +2266, 2198, 2624, +2266, 2198, 2623, +2264, 2199, 2623, +2263, 2200, 2622, +2261, 2201, 2622, +2258, 2202, 2621, +2255, 2204, 2620, +2250, 2206, 2618, +2243, 2210, 2616, +2234, 2214, 2613, +2222, 2220, 2609, +2204, 2228, 2603, +2180, 2238, 2596, +2146, 2252, 2586, +2096, 2269, 2572, +2019, 2291, 2552, +1890, 2319, 2525, +1628, 2354, 2486, +0, 2397, 2428, +0, 2448, 2337, +0, 2509, 2176, +0, 2580, 1795, +0, 2660, 0, +0, 2749, 0, +0, 2845, 0, +0, 2949, 0, +0, 3059, 0, +0, 3173, 0, +0, 3292, 0, +0, 3414, 0, +0, 3538, 0, +0, 3664, 0, +2470, 2219, 2680, +2469, 2219, 2680, +2469, 2220, 2680, +2468, 2220, 2679, +2466, 2221, 2679, +2465, 2223, 2678, +2462, 2225, 2677, +2459, 2227, 2675, +2455, 2230, 2673, +2450, 2235, 2671, +2442, 2240, 2667, +2431, 2248, 2662, +2417, 2258, 2656, +2397, 2270, 2647, +2369, 2287, 2635, +2328, 2308, 2618, +2267, 2335, 2595, +2171, 2369, 2561, +1998, 2410, 2513, +1561, 2461, 2438, +0, 2520, 2315, +0, 2589, 2068, +0, 2668, 582, +0, 2755, 0, +0, 2851, 0, +0, 2953, 0, +0, 3062, 0, +0, 3176, 0, +0, 3294, 0, +0, 3415, 0, +0, 3539, 0, +0, 3665, 0, +2649, 2245, 2747, +2649, 2246, 2746, +2648, 2246, 2746, +2648, 2247, 2746, +2647, 2248, 2745, +2646, 2249, 2745, +2644, 2251, 2744, +2642, 2253, 2742, +2639, 2256, 2741, +2635, 2260, 2738, +2630, 2266, 2735, +2623, 2273, 2731, +2614, 2282, 2726, +2601, 2294, 2718, +2583, 2310, 2708, +2558, 2330, 2693, +2523, 2356, 2674, +2470, 2388, 2646, +2389, 2428, 2606, +2251, 2476, 2546, +1960, 2534, 2451, +0, 2601, 2283, +0, 2678, 1867, +0, 2763, 0, +0, 2857, 0, +0, 2959, 0, +0, 3066, 0, +0, 3179, 0, +0, 3296, 0, +0, 3417, 0, +0, 3540, 0, +0, 3666, 0, +2813, 2279, 2823, +2813, 2279, 2822, +2813, 2280, 2822, +2812, 2280, 2822, +2812, 2281, 2821, +2811, 2282, 2821, +2810, 2284, 2820, +2808, 2286, 2819, +2806, 2289, 2817, +2804, 2293, 2816, +2800, 2298, 2813, +2796, 2304, 2809, +2789, 2313, 2805, +2780, 2324, 2798, +2769, 2339, 2790, +2752, 2358, 2778, +2729, 2382, 2762, +2697, 2413, 2739, +2649, 2451, 2706, +2576, 2497, 2659, +2457, 2552, 2587, +2222, 2617, 2468, +1159, 2691, 2237, +0, 2774, 1246, +0, 2866, 0, +0, 2966, 0, +0, 3072, 0, +0, 3184, 0, +0, 3300, 0, +0, 3420, 0, +0, 3542, 0, +0, 3667, 0, +2968, 2320, 2907, +2968, 2320, 2907, +2968, 2321, 2907, +2967, 2321, 2907, +2967, 2322, 2906, +2966, 2323, 2906, +2966, 2325, 2905, +2965, 2327, 2904, +2963, 2329, 2903, +2961, 2333, 2902, +2959, 2337, 2900, +2956, 2343, 2897, +2951, 2351, 2893, +2945, 2362, 2888, +2937, 2375, 2880, +2925, 2393, 2871, +2910, 2415, 2857, +2888, 2444, 2839, +2858, 2479, 2813, +2813, 2523, 2776, +2746, 2575, 2722, +2637, 2637, 2637, +2432, 2708, 2490, +1780, 2789, 2168, +0, 2878, 0, +0, 2975, 0, +0, 3079, 0, +0, 3190, 0, +0, 3304, 0, +0, 3423, 0, +0, 3545, 0, +0, 3669, 0, +3116, 2370, 3001, +3116, 2370, 3001, +3116, 2370, 3001, +3116, 2371, 3000, +3116, 2372, 3000, +3115, 2373, 3000, +3115, 2374, 2999, +3114, 2376, 2998, +3113, 2378, 2997, +3112, 2381, 2996, +3110, 2385, 2994, +3107, 2391, 2992, +3104, 2398, 2989, +3100, 2407, 2985, +3094, 2420, 2979, +3086, 2436, 2971, +3075, 2456, 2961, +3060, 2482, 2946, +3039, 2515, 2926, +3010, 2555, 2897, +2968, 2604, 2856, +2904, 2662, 2794, +2802, 2730, 2696, +2614, 2807, 2518, +2094, 2893, 2054, +0, 2987, 0, +0, 3089, 0, +0, 3197, 0, +0, 3310, 0, +0, 3428, 0, +0, 3549, 0, +0, 3672, 0, +3260, 2429, 3102, +3260, 2429, 3102, +3260, 2429, 3101, +3260, 2430, 3101, +3260, 2430, 3101, +3259, 2431, 3101, +3259, 2432, 3100, +3258, 2434, 3100, +3258, 2436, 3099, +3257, 2439, 3098, +3255, 2442, 3096, +3254, 2447, 3095, +3251, 2453, 3092, +3248, 2462, 3089, +3244, 2473, 3084, +3238, 2487, 3078, +3231, 2505, 3070, +3220, 2529, 3058, +3206, 2558, 3042, +3185, 2595, 3021, +3157, 2640, 2989, +3116, 2694, 2944, +3054, 2757, 2876, +2957, 2830, 2764, +2781, 2913, 2552, +2327, 3003, 1837, +0, 3102, 0, +0, 3207, 0, +0, 3318, 0, +0, 3434, 0, +0, 3553, 0, +0, 3676, 0, +3401, 2497, 3209, +3401, 2497, 3209, +3401, 2498, 3209, +3401, 2498, 3208, +3401, 2499, 3208, +3400, 2499, 3208, +3400, 2500, 3208, +3400, 2502, 3207, +3399, 2503, 3207, +3398, 2506, 3206, +3397, 2509, 3205, +3396, 2513, 3203, +3394, 2519, 3201, +3392, 2526, 3199, +3389, 2535, 3195, +3385, 2548, 3190, +3379, 2564, 3184, +3372, 2585, 3175, +3361, 2611, 3163, +3347, 2644, 3146, +3328, 2684, 3123, +3300, 2734, 3089, +3260, 2792, 3040, +3200, 2860, 2966, +3105, 2937, 2842, +2937, 3024, 2595, +2521, 3118, 1060, +0, 3220, 0, +0, 3329, 0, +0, 3442, 0, +0, 3560, 0, +0, 3680, 0, +3539, 2575, 3321, +3539, 2575, 3321, +3539, 2576, 3321, +3539, 2576, 3321, +3539, 2576, 3321, +3539, 2577, 3321, +3539, 2578, 3320, +3538, 2579, 3320, +3538, 2581, 3320, +3537, 2582, 3319, +3537, 2585, 3318, +3536, 2589, 3317, +3535, 2593, 3315, +3533, 2599, 3313, +3531, 2608, 3311, +3528, 2618, 3307, +3524, 2632, 3302, +3518, 2650, 3295, +3511, 2673, 3286, +3500, 2702, 3273, +3486, 2738, 3255, +3467, 2782, 3231, +3440, 2834, 3196, +3400, 2897, 3144, +3342, 2969, 3064, +3249, 3050, 2929, +3086, 3140, 2646, +2695, 3237, 0, +0, 3342, 0, +0, 3452, 0, +0, 3568, 0, +0, 3687, 0, +3676, 2662, 3438, +3676, 2662, 3438, +3676, 2663, 3438, +3676, 2663, 3438, +3676, 2663, 3438, +3676, 2664, 3438, +3676, 2664, 3438, +3675, 2665, 3437, +3675, 2667, 3437, +3675, 2668, 3436, +3674, 2670, 3436, +3674, 2673, 3435, +3673, 2677, 3434, +3671, 2682, 3432, +3670, 2689, 3430, +3668, 2698, 3427, +3665, 2710, 3423, +3661, 2725, 3418, +3655, 2744, 3411, +3648, 2769, 3401, +3638, 2800, 3388, +3624, 2839, 3370, +3605, 2886, 3344, +3578, 2942, 3308, +3539, 3007, 3253, +3481, 3082, 3169, +3390, 3167, 3024, +3231, 3259, 2706, +2856, 3359, 0, +0, 3466, 0, +0, 3578, 0, +0, 3695, 0, +3812, 2757, 3559, +3812, 2757, 3559, +3812, 2758, 3559, +3812, 2758, 3558, +3812, 2758, 3558, +3811, 2759, 3558, +3811, 2759, 3558, +3811, 2760, 3558, +3811, 2761, 3558, +3811, 2762, 3557, +3810, 2764, 3557, +3810, 2766, 3556, +3809, 2770, 3555, +3808, 2774, 3554, +3807, 2779, 3552, +3805, 2787, 3550, +3803, 2796, 3547, +3800, 2809, 3543, +3796, 2825, 3538, +3791, 2846, 3531, +3783, 2872, 3521, +3773, 2905, 3507, +3760, 2946, 3488, +3741, 2996, 3462, +3714, 3054, 3424, +3675, 3122, 3368, +3618, 3200, 3279, +3529, 3287, 3126, +3372, 3382, 2777, +3009, 3484, 0, +0, 3592, 0, +0, 3706, 0, +3946, 2860, 3682, +3946, 2860, 3682, +3946, 2860, 3682, +3946, 2860, 3682, +3946, 2860, 3682, +3946, 2861, 3682, +3946, 2861, 3681, +3946, 2862, 3681, +3946, 2863, 3681, +3946, 2864, 3681, +3945, 2865, 3680, +3945, 2867, 3680, +3944, 2869, 3679, +3944, 2873, 3678, +3943, 2877, 3677, +3942, 2883, 3675, +3940, 2891, 3673, +3938, 2901, 3670, +3935, 2914, 3666, +3931, 2932, 3661, +3926, 2954, 3653, +3918, 2981, 3643, +3908, 3016, 3629, +3895, 3059, 3610, +3876, 3110, 3583, +3849, 3171, 3544, +3811, 3242, 3486, +3754, 3321, 3395, +3666, 3410, 3235, +3511, 3507, 2856, +3156, 3610, 0, +0, 3720, 0, +4080, 2968, 3807, +4080, 2968, 3807, +4080, 2968, 3807, +4080, 2969, 3807, +4080, 2969, 3807, +4080, 2969, 3807, +4080, 2969, 3807, +4080, 2970, 3807, +4080, 2970, 3806, +4080, 2971, 3806, +4080, 2972, 3806, +4079, 2974, 3806, +4079, 2976, 3805, +4078, 2979, 3804, +4078, 2982, 3803, +4077, 2987, 3802, +4076, 2993, 3800, +4074, 3001, 3798, +4072, 3012, 3795, +4069, 3026, 3791, +4065, 3044, 3786, +4060, 3067, 3778, +4052, 3096, 3768, +4042, 3132, 3754, +4029, 3176, 3734, +4010, 3229, 3706, +3984, 3292, 3667, +3946, 3364, 3608, +3889, 3445, 3514, +3801, 3535, 3348, +3648, 3633, 2944, +3299, 3738, 0, +4095, 3082, 3934, +4095, 3082, 3934, +4095, 3082, 3934, +4095, 3082, 3934, +4095, 3082, 3934, +4095, 3082, 3934, +4095, 3083, 3934, +4095, 3083, 3934, +4095, 3084, 3934, +4095, 3084, 3933, +4095, 3085, 3933, +4095, 3086, 3933, +4095, 3088, 3932, +4095, 3090, 3932, +4095, 3093, 3931, +4095, 3096, 3930, +4095, 3101, 3929, +4095, 3108, 3927, +4095, 3116, 3925, +4095, 3127, 3922, +4095, 3142, 3918, +4095, 3160, 3912, +4095, 3184, 3905, +4095, 3214, 3894, +4095, 3251, 3880, +4095, 3297, 3860, +4095, 3351, 3832, +4095, 3415, 3792, +4080, 3488, 3732, +4024, 3571, 3636, +3936, 3662, 3466, +3784, 3761, 3041, +4095, 3200, 4062, +4095, 3200, 4062, +4095, 3200, 4062, +4095, 3200, 4062, +4095, 3200, 4062, +4095, 3200, 4062, +4095, 3200, 4062, +4095, 3201, 4062, +4095, 3201, 4062, +4095, 3202, 4062, +4095, 3202, 4062, +4095, 3203, 4061, +4095, 3204, 4061, +4095, 3206, 4061, +4095, 3208, 4060, +4095, 3211, 4059, +4095, 3215, 4058, +4095, 3220, 4057, +4095, 3226, 4055, +4095, 3235, 4053, +4095, 3247, 4050, +4095, 3261, 4046, +4095, 3280, 4040, +4095, 3305, 4032, +4095, 3335, 4022, +4095, 3374, 4008, +4095, 3420, 3988, +4095, 3475, 3959, +4095, 3540, 3918, +4095, 3614, 3858, +4095, 3698, 3761, +4070, 3790, 3587, +0, 2261, 2529, +0, 2261, 2529, +0, 2262, 2529, +0, 2263, 2528, +0, 2264, 2527, +0, 2265, 2526, +0, 2267, 2524, +0, 2269, 2522, +0, 2272, 2520, +0, 2276, 2516, +0, 2281, 2511, +0, 2288, 2504, +0, 2297, 2495, +0, 2308, 2482, +0, 2324, 2465, +0, 2343, 2440, +0, 2368, 2405, +0, 2400, 2354, +0, 2439, 2274, +0, 2486, 2140, +0, 2542, 1860, +0, 2608, 0, +0, 2684, 0, +0, 2768, 0, +0, 2861, 0, +0, 2962, 0, +0, 3069, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3667, 0, +0, 2261, 2530, +0, 2262, 2530, +0, 2262, 2529, +0, 2263, 2529, +0, 2264, 2528, +0, 2265, 2527, +0, 2267, 2525, +0, 2269, 2523, +0, 2272, 2520, +0, 2276, 2517, +0, 2281, 2512, +0, 2288, 2505, +0, 2297, 2495, +0, 2309, 2483, +0, 2324, 2465, +0, 2343, 2441, +0, 2368, 2406, +0, 2400, 2354, +0, 2439, 2275, +0, 2486, 2141, +0, 2543, 1863, +0, 2608, 0, +0, 2684, 0, +0, 2769, 0, +0, 2862, 0, +0, 2962, 0, +0, 3069, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3667, 0, +0, 2261, 2531, +0, 2262, 2530, +0, 2262, 2530, +0, 2263, 2529, +0, 2264, 2528, +0, 2265, 2527, +0, 2267, 2526, +0, 2269, 2524, +0, 2272, 2521, +0, 2276, 2517, +0, 2281, 2512, +0, 2288, 2505, +0, 2297, 2496, +0, 2309, 2484, +0, 2324, 2466, +0, 2344, 2442, +0, 2369, 2407, +0, 2400, 2355, +0, 2439, 2276, +0, 2486, 2143, +0, 2543, 1866, +0, 2609, 0, +0, 2684, 0, +0, 2769, 0, +0, 2862, 0, +0, 2962, 0, +0, 3069, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3667, 0, +0, 2262, 2532, +0, 2262, 2531, +0, 2263, 2531, +0, 2263, 2530, +0, 2264, 2529, +0, 2265, 2528, +0, 2267, 2527, +0, 2269, 2525, +0, 2272, 2522, +0, 2276, 2518, +0, 2281, 2513, +0, 2288, 2506, +0, 2297, 2497, +0, 2309, 2485, +0, 2324, 2467, +0, 2344, 2443, +0, 2369, 2408, +0, 2400, 2357, +0, 2439, 2278, +0, 2486, 2145, +0, 2543, 1870, +0, 2609, 0, +0, 2684, 0, +0, 2769, 0, +0, 2862, 0, +0, 2962, 0, +0, 3069, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3667, 0, +0, 2262, 2533, +0, 2262, 2533, +0, 2263, 2532, +0, 2264, 2531, +0, 2264, 2531, +0, 2266, 2529, +0, 2267, 2528, +0, 2270, 2526, +0, 2273, 2523, +0, 2276, 2520, +0, 2282, 2515, +0, 2288, 2508, +0, 2297, 2499, +0, 2309, 2486, +0, 2324, 2469, +0, 2344, 2444, +0, 2369, 2410, +0, 2400, 2359, +0, 2439, 2280, +0, 2487, 2148, +0, 2543, 1875, +0, 2609, 0, +0, 2684, 0, +0, 2769, 0, +0, 2862, 0, +0, 2962, 0, +0, 3069, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3667, 0, +0, 2262, 2535, +0, 2263, 2534, +0, 2263, 2534, +0, 2264, 2533, +0, 2265, 2532, +0, 2266, 2531, +0, 2268, 2530, +0, 2270, 2528, +0, 2273, 2525, +0, 2277, 2521, +0, 2282, 2516, +0, 2289, 2510, +0, 2298, 2500, +0, 2310, 2488, +0, 2325, 2471, +0, 2344, 2446, +0, 2369, 2412, +0, 2401, 2361, +0, 2440, 2283, +0, 2487, 2152, +0, 2543, 1882, +0, 2609, 0, +0, 2684, 0, +0, 2769, 0, +0, 2862, 0, +0, 2962, 0, +0, 3069, 0, +0, 3181, 0, +0, 3298, 0, +0, 3418, 0, +0, 3541, 0, +0, 3667, 0, +0, 2263, 2537, +0, 2263, 2537, +0, 2264, 2536, +0, 2265, 2535, +0, 2265, 2535, +0, 2267, 2533, +0, 2268, 2532, +0, 2271, 2530, +0, 2274, 2527, +0, 2277, 2524, +0, 2283, 2519, +0, 2289, 2512, +0, 2298, 2503, +0, 2310, 2490, +0, 2325, 2473, +0, 2345, 2449, +0, 2370, 2415, +0, 2401, 2364, +0, 2440, 2287, +0, 2487, 2157, +0, 2543, 1892, +0, 2609, 0, +0, 2685, 0, +0, 2769, 0, +0, 2862, 0, +0, 2962, 0, +0, 3069, 0, +0, 3182, 0, +0, 3298, 0, +0, 3418, 0, +0, 3542, 0, +0, 3667, 0, +0, 2264, 2540, +0, 2264, 2539, +0, 2265, 2539, +0, 2265, 2538, +0, 2266, 2538, +0, 2267, 2536, +0, 2269, 2535, +0, 2271, 2533, +0, 2274, 2530, +0, 2278, 2527, +0, 2283, 2522, +0, 2290, 2515, +0, 2299, 2506, +0, 2311, 2494, +0, 2326, 2477, +0, 2346, 2453, +0, 2370, 2419, +0, 2402, 2369, +0, 2440, 2292, +0, 2488, 2164, +0, 2544, 1904, +0, 2610, 0, +0, 2685, 0, +0, 2769, 0, +0, 2862, 0, +0, 2963, 0, +0, 3069, 0, +0, 3182, 0, +0, 3298, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +0, 2265, 2544, +0, 2265, 2543, +0, 2266, 2543, +0, 2266, 2542, +0, 2267, 2542, +0, 2268, 2540, +0, 2270, 2539, +0, 2272, 2537, +0, 2275, 2534, +0, 2279, 2531, +0, 2284, 2526, +0, 2291, 2519, +0, 2300, 2510, +0, 2312, 2498, +0, 2327, 2481, +0, 2346, 2458, +0, 2371, 2424, +0, 2402, 2375, +0, 2441, 2299, +0, 2488, 2173, +0, 2544, 1920, +0, 2610, 0, +0, 2685, 0, +0, 2770, 0, +0, 2862, 0, +0, 2963, 0, +0, 3070, 0, +0, 3182, 0, +0, 3298, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +0, 2266, 2549, +0, 2266, 2549, +0, 2267, 2548, +0, 2268, 2548, +0, 2269, 2547, +0, 2270, 2546, +0, 2271, 2544, +0, 2274, 2542, +0, 2277, 2540, +0, 2280, 2536, +0, 2286, 2531, +0, 2292, 2525, +0, 2301, 2516, +0, 2313, 2504, +0, 2328, 2487, +0, 2348, 2464, +0, 2372, 2431, +0, 2403, 2382, +0, 2442, 2308, +0, 2489, 2185, +0, 2545, 1940, +0, 2611, 542, +0, 2686, 0, +0, 2770, 0, +0, 2863, 0, +0, 2963, 0, +0, 3070, 0, +0, 3182, 0, +0, 3299, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +0, 2268, 2556, +0, 2268, 2556, +0, 2269, 2555, +0, 2269, 2555, +0, 2270, 2554, +0, 2272, 2553, +0, 2273, 2551, +0, 2275, 2549, +0, 2278, 2547, +0, 2282, 2543, +0, 2287, 2538, +0, 2294, 2532, +0, 2303, 2523, +0, 2315, 2512, +0, 2330, 2495, +0, 2349, 2472, +0, 2374, 2440, +0, 2405, 2392, +0, 2443, 2320, +0, 2490, 2200, +0, 2546, 1966, +0, 2612, 914, +0, 2687, 0, +0, 2771, 0, +0, 2863, 0, +0, 2963, 0, +0, 3070, 0, +0, 3182, 0, +0, 3299, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +0, 2270, 2565, +0, 2271, 2565, +0, 2271, 2564, +0, 2272, 2564, +0, 2273, 2563, +0, 2274, 2562, +0, 2276, 2560, +0, 2278, 2559, +0, 2281, 2556, +0, 2285, 2553, +0, 2290, 2548, +0, 2296, 2542, +0, 2305, 2533, +0, 2317, 2522, +0, 2332, 2505, +0, 2351, 2483, +0, 2376, 2451, +0, 2407, 2405, +0, 2445, 2335, +0, 2492, 2220, +0, 2547, 1998, +0, 2613, 1168, +0, 2688, 0, +0, 2772, 0, +0, 2864, 0, +0, 2964, 0, +0, 3071, 0, +0, 3183, 0, +0, 3299, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +0, 2273, 2577, +0, 2274, 2577, +0, 2274, 2576, +0, 2275, 2576, +0, 2276, 2575, +0, 2277, 2574, +0, 2279, 2572, +0, 2281, 2571, +0, 2284, 2568, +0, 2288, 2565, +0, 2293, 2560, +0, 2299, 2554, +0, 2308, 2546, +0, 2320, 2535, +0, 2335, 2519, +0, 2354, 2497, +0, 2378, 2467, +0, 2409, 2422, +0, 2447, 2354, +0, 2494, 2245, +0, 2549, 2038, +0, 2614, 1374, +0, 2689, 0, +0, 2773, 0, +0, 2865, 0, +0, 2965, 0, +0, 3071, 0, +0, 3183, 0, +0, 3299, 0, +0, 3419, 0, +0, 3542, 0, +0, 3667, 0, +0, 2278, 2592, +0, 2278, 2592, +0, 2279, 2592, +0, 2279, 2591, +0, 2280, 2590, +0, 2281, 2589, +0, 2283, 2588, +0, 2285, 2586, +0, 2288, 2584, +0, 2292, 2581, +0, 2297, 2576, +0, 2303, 2570, +0, 2312, 2562, +0, 2323, 2551, +0, 2338, 2536, +0, 2357, 2516, +0, 2382, 2486, +0, 2412, 2443, +0, 2450, 2379, +0, 2496, 2276, +0, 2551, 2087, +0, 2616, 1554, +0, 2690, 0, +0, 2774, 0, +0, 2866, 0, +0, 2966, 0, +0, 3072, 0, +0, 3184, 0, +0, 3300, 0, +0, 3420, 0, +0, 3542, 0, +0, 3667, 0, +0, 2283, 2612, +0, 2284, 2612, +0, 2284, 2611, +0, 2285, 2611, +0, 2286, 2610, +0, 2287, 2609, +0, 2289, 2608, +0, 2291, 2606, +0, 2293, 2604, +0, 2297, 2601, +0, 2302, 2597, +0, 2309, 2591, +0, 2317, 2584, +0, 2329, 2573, +0, 2343, 2559, +0, 2362, 2539, +0, 2386, 2511, +0, 2416, 2471, +0, 2454, 2410, +0, 2500, 2315, +0, 2555, 2145, +0, 2619, 1719, +0, 2693, 0, +0, 2776, 0, +0, 2868, 0, +0, 2967, 0, +0, 3073, 0, +0, 3184, 0, +0, 3300, 0, +0, 3420, 0, +0, 3543, 0, +0, 3668, 0, +746, 2291, 2637, +722, 2291, 2637, +688, 2292, 2637, +637, 2292, 2636, +559, 2293, 2636, +428, 2294, 2635, +158, 2296, 2633, +0, 2298, 2632, +0, 2301, 2630, +0, 2304, 2627, +0, 2309, 2623, +0, 2316, 2618, +0, 2324, 2610, +0, 2335, 2601, +0, 2350, 2587, +0, 2368, 2568, +0, 2392, 2542, +0, 2422, 2505, +0, 2459, 2449, +0, 2504, 2362, +0, 2559, 2212, +0, 2622, 1874, +0, 2696, 0, +0, 2778, 0, +0, 2870, 0, +0, 2969, 0, +0, 3074, 0, +0, 3185, 0, +0, 3301, 0, +0, 3421, 0, +0, 3543, 0, +0, 3668, 0, +1791, 2300, 2669, +1789, 2301, 2669, +1785, 2301, 2668, +1781, 2302, 2668, +1775, 2303, 2667, +1767, 2304, 2667, +1757, 2305, 2665, +1742, 2307, 2664, +1721, 2310, 2662, +1692, 2314, 2659, +1650, 2319, 2656, +1586, 2325, 2651, +1485, 2333, 2644, +1300, 2344, 2635, +793, 2358, 2622, +0, 2376, 2605, +0, 2400, 2581, +0, 2429, 2547, +0, 2466, 2496, +0, 2510, 2419, +0, 2564, 2289, +0, 2627, 2023, +0, 2700, 0, +0, 2782, 0, +0, 2872, 0, +0, 2971, 0, +0, 3076, 0, +0, 3187, 0, +0, 3302, 0, +0, 3422, 0, +0, 3544, 0, +0, 3668, 0, +2150, 2313, 2708, +2149, 2313, 2708, +2147, 2314, 2708, +2145, 2314, 2707, +2143, 2315, 2707, +2139, 2316, 2706, +2135, 2318, 2705, +2128, 2320, 2704, +2119, 2323, 2702, +2108, 2326, 2699, +2091, 2331, 2696, +2068, 2337, 2691, +2036, 2345, 2685, +1988, 2356, 2677, +1915, 2369, 2666, +1795, 2387, 2650, +1560, 2410, 2628, +480, 2439, 2597, +0, 2474, 2553, +0, 2518, 2485, +0, 2571, 2375, +0, 2633, 2167, +0, 2705, 1492, +0, 2786, 0, +0, 2876, 0, +0, 2974, 0, +0, 3078, 0, +0, 3189, 0, +0, 3304, 0, +0, 3423, 0, +0, 3545, 0, +0, 3669, 0, +2399, 2329, 2756, +2398, 2330, 2756, +2398, 2330, 2755, +2396, 2331, 2755, +2395, 2332, 2754, +2393, 2333, 2754, +2390, 2334, 2753, +2387, 2336, 2752, +2382, 2339, 2750, +2375, 2342, 2748, +2366, 2346, 2745, +2354, 2352, 2741, +2337, 2360, 2735, +2313, 2370, 2728, +2278, 2384, 2718, +2228, 2401, 2704, +2151, 2423, 2684, +2023, 2451, 2657, +1760, 2486, 2618, +0, 2529, 2560, +0, 2581, 2469, +0, 2642, 2308, +0, 2712, 1927, +0, 2792, 0, +0, 2881, 0, +0, 2978, 0, +0, 3081, 0, +0, 3191, 0, +0, 3306, 0, +0, 3424, 0, +0, 3546, 0, +0, 3670, 0, +2602, 2350, 2813, +2602, 2351, 2812, +2602, 2351, 2812, +2601, 2352, 2812, +2600, 2353, 2811, +2599, 2354, 2811, +2597, 2355, 2810, +2595, 2357, 2809, +2591, 2359, 2807, +2587, 2362, 2805, +2582, 2367, 2803, +2574, 2372, 2799, +2563, 2380, 2794, +2549, 2390, 2788, +2529, 2402, 2779, +2501, 2419, 2767, +2460, 2440, 2750, +2400, 2467, 2727, +2303, 2501, 2694, +2131, 2543, 2645, +1693, 2593, 2570, +0, 2652, 2447, +0, 2721, 2200, +0, 2800, 714, +0, 2887, 0, +0, 2983, 0, +0, 3085, 0, +0, 3194, 0, +0, 3308, 0, +0, 3426, 0, +0, 3547, 0, +0, 3671, 0, +2781, 2377, 2879, +2781, 2377, 2879, +2781, 2378, 2879, +2780, 2378, 2878, +2780, 2379, 2878, +2779, 2380, 2877, +2778, 2381, 2877, +2776, 2383, 2876, +2774, 2385, 2874, +2771, 2388, 2873, +2767, 2392, 2870, +2762, 2398, 2867, +2755, 2405, 2863, +2746, 2414, 2858, +2733, 2426, 2850, +2715, 2442, 2840, +2691, 2462, 2826, +2655, 2488, 2806, +2602, 2520, 2778, +2521, 2560, 2738, +2384, 2609, 2678, +2092, 2666, 2584, +0, 2733, 2415, +0, 2810, 1999, +0, 2895, 0, +0, 2989, 0, +0, 3091, 0, +0, 3198, 0, +0, 3311, 0, +0, 3429, 0, +0, 3549, 0, +0, 3673, 0, +2946, 2411, 2955, +2945, 2411, 2955, +2945, 2411, 2954, +2945, 2412, 2954, +2944, 2412, 2954, +2944, 2413, 2953, +2943, 2414, 2953, +2942, 2416, 2952, +2940, 2418, 2951, +2939, 2421, 2950, +2936, 2425, 2948, +2932, 2430, 2945, +2928, 2436, 2942, +2921, 2445, 2937, +2913, 2456, 2930, +2901, 2471, 2922, +2884, 2490, 2910, +2861, 2514, 2894, +2829, 2545, 2871, +2781, 2583, 2838, +2709, 2629, 2791, +2589, 2684, 2719, +2354, 2749, 2601, +1291, 2823, 2369, +0, 2906, 1378, +0, 2998, 0, +0, 3098, 0, +0, 3204, 0, +0, 3316, 0, +0, 3432, 0, +0, 3552, 0, +0, 3675, 0, +3100, 2452, 3040, +3100, 2452, 3040, +3100, 2452, 3039, +3100, 2453, 3039, +3099, 2453, 3039, +3099, 2454, 3039, +3098, 2455, 3038, +3098, 2457, 3037, +3097, 2459, 3037, +3095, 2461, 3035, +3093, 2465, 3034, +3091, 2469, 3032, +3088, 2475, 3029, +3083, 2483, 3025, +3077, 2494, 3020, +3069, 2507, 3013, +3058, 2525, 3003, +3042, 2547, 2990, +3020, 2576, 2971, +2990, 2611, 2945, +2945, 2655, 2909, +2878, 2707, 2854, +2769, 2769, 2769, +2564, 2840, 2622, +1912, 2921, 2300, +0, 3010, 0, +0, 3107, 0, +0, 3212, 0, +0, 3322, 0, +0, 3437, 0, +0, 3555, 0, +0, 3677, 0, +3249, 2501, 3133, +3248, 2502, 3133, +3248, 2502, 3133, +3248, 2502, 3133, +3248, 2503, 3132, +3248, 2504, 3132, +3247, 2505, 3132, +3247, 2506, 3131, +3246, 2508, 3130, +3245, 2510, 3129, +3244, 2513, 3128, +3242, 2517, 3126, +3239, 2523, 3124, +3236, 2530, 3121, +3232, 2539, 3117, +3226, 2552, 3111, +3218, 2568, 3103, +3207, 2588, 3093, +3192, 2614, 3078, +3172, 2647, 3058, +3142, 2687, 3029, +3100, 2736, 2988, +3036, 2794, 2926, +2934, 2862, 2828, +2746, 2939, 2650, +2226, 3025, 2186, +0, 3120, 0, +0, 3221, 0, +0, 3329, 0, +0, 3443, 0, +0, 3560, 0, +0, 3681, 0, +3392, 2560, 3234, +3392, 2561, 3234, +3392, 2561, 3234, +3392, 2561, 3233, +3392, 2562, 3233, +3392, 2562, 3233, +3391, 2563, 3233, +3391, 2564, 3232, +3391, 2566, 3232, +3390, 2568, 3231, +3389, 2571, 3230, +3388, 2574, 3229, +3386, 2579, 3227, +3383, 2586, 3224, +3380, 2594, 3221, +3376, 2605, 3216, +3370, 2619, 3210, +3363, 2637, 3202, +3352, 2661, 3190, +3338, 2691, 3175, +3317, 2727, 3153, +3289, 2772, 3121, +3248, 2826, 3076, +3187, 2890, 3008, +3089, 2962, 2896, +2913, 3045, 2685, +2459, 3135, 1969, +0, 3234, 0, +0, 3339, 0, +0, 3450, 0, +0, 3566, 0, +0, 3685, 0, +3533, 2629, 3341, +3533, 2629, 3341, +3533, 2629, 3341, +3533, 2630, 3341, +3533, 2630, 3341, +3533, 2631, 3340, +3532, 2631, 3340, +3532, 2632, 3340, +3532, 2634, 3339, +3531, 2636, 3339, +3530, 2638, 3338, +3530, 2641, 3337, +3528, 2645, 3335, +3527, 2651, 3333, +3524, 2658, 3331, +3521, 2668, 3327, +3517, 2680, 3322, +3512, 2696, 3316, +3504, 2717, 3307, +3494, 2743, 3295, +3479, 2776, 3278, +3460, 2817, 3255, +3432, 2866, 3221, +3392, 2924, 3173, +3332, 2992, 3098, +3237, 3069, 2974, +3069, 3156, 2727, +2654, 3251, 1192, +0, 3353, 0, +0, 3461, 0, +0, 3574, 0, +0, 3692, 0, +3672, 2707, 3453, +3672, 2707, 3453, +3671, 2707, 3453, +3671, 2708, 3453, +3671, 2708, 3453, +3671, 2709, 3453, +3671, 2709, 3453, +3671, 2710, 3453, +3671, 2711, 3452, +3670, 2713, 3452, +3670, 2715, 3451, +3669, 2717, 3450, +3668, 2721, 3449, +3667, 2725, 3448, +3665, 2732, 3446, +3663, 2740, 3443, +3660, 2750, 3439, +3656, 2764, 3434, +3650, 2782, 3427, +3643, 2805, 3418, +3633, 2834, 3405, +3619, 2870, 3388, +3599, 2914, 3363, +3572, 2967, 3328, +3532, 3029, 3276, +3474, 3101, 3196, +3382, 3182, 3061, +3218, 3272, 2778, +2827, 3370, 0, +0, 3474, 0, +0, 3585, 0, +0, 3700, 0, +3808, 2794, 3570, +3808, 2794, 3570, +3808, 2794, 3570, +3808, 2795, 3570, +3808, 2795, 3570, +3808, 2795, 3570, +3808, 2796, 3570, +3808, 2796, 3570, +3808, 2797, 3569, +3807, 2799, 3569, +3807, 2800, 3569, +3806, 2803, 3568, +3806, 2805, 3567, +3805, 2809, 3566, +3804, 2814, 3564, +3802, 2821, 3562, +3800, 2830, 3559, +3797, 2842, 3555, +3793, 2857, 3550, +3787, 2876, 3543, +3780, 2901, 3533, +3770, 2932, 3520, +3756, 2971, 3502, +3737, 3018, 3476, +3710, 3074, 3440, +3671, 3139, 3385, +3613, 3214, 3301, +3522, 3299, 3156, +3363, 3391, 2839, +2989, 3492, 0, +0, 3598, 0, +0, 3710, 0, +3944, 2889, 3691, +3944, 2889, 3691, +3944, 2890, 3691, +3944, 2890, 3691, +3944, 2890, 3691, +3944, 2890, 3691, +3944, 2891, 3690, +3943, 2891, 3690, +3943, 2892, 3690, +3943, 2893, 3690, +3943, 2894, 3689, +3942, 2896, 3689, +3942, 2898, 3688, +3941, 2902, 3687, +3940, 2906, 3686, +3939, 2911, 3684, +3937, 2919, 3682, +3935, 2928, 3679, +3932, 2941, 3675, +3928, 2957, 3670, +3923, 2978, 3663, +3916, 3004, 3653, +3906, 3037, 3639, +3892, 3078, 3620, +3873, 3128, 3594, +3846, 3186, 3556, +3808, 3255, 3500, +3750, 3332, 3412, +3661, 3419, 3258, +3504, 3514, 2909, +3141, 3616, 0, +0, 3724, 0, +4079, 2992, 3814, +4079, 2992, 3814, +4078, 2992, 3814, +4078, 2992, 3814, +4078, 2992, 3814, +4078, 2992, 3814, +4078, 2993, 3814, +4078, 2993, 3813, +4078, 2994, 3813, +4078, 2995, 3813, +4078, 2996, 3813, +4077, 2997, 3812, +4077, 2999, 3812, +4077, 3002, 3811, +4076, 3005, 3810, +4075, 3009, 3809, +4074, 3015, 3807, +4072, 3023, 3805, +4070, 3033, 3802, +4067, 3047, 3798, +4063, 3064, 3793, +4058, 3086, 3785, +4050, 3114, 3775, +4040, 3148, 3761, +4027, 3191, 3742, +4008, 3242, 3715, +3981, 3303, 3676, +3943, 3374, 3618, +3886, 3453, 3527, +3798, 3542, 3367, +3643, 3639, 2988, +3288, 3742, 0, +4095, 3100, 3939, +4095, 3100, 3939, +4095, 3100, 3939, +4095, 3101, 3939, +4095, 3101, 3939, +4095, 3101, 3939, +4095, 3101, 3939, +4095, 3101, 3939, +4095, 3102, 3939, +4095, 3103, 3939, +4095, 3103, 3938, +4095, 3105, 3938, +4095, 3106, 3938, +4095, 3108, 3937, +4095, 3111, 3936, +4095, 3114, 3936, +4095, 3119, 3934, +4095, 3125, 3933, +4095, 3133, 3930, +4095, 3144, 3927, +4095, 3158, 3923, +4095, 3176, 3918, +4095, 3199, 3910, +4095, 3228, 3900, +4095, 3264, 3886, +4095, 3308, 3866, +4095, 3361, 3839, +4095, 3424, 3799, +4078, 3496, 3740, +4021, 3577, 3646, +3933, 3667, 3480, +3780, 3765, 3076, +4095, 3214, 4066, +4095, 3214, 4066, +4095, 3214, 4066, +4095, 3214, 4066, +4095, 3214, 4066, +4095, 3214, 4066, +4095, 3215, 4066, +4095, 3215, 4066, +4095, 3215, 4066, +4095, 3216, 4066, +4095, 3216, 4066, +4095, 3217, 4065, +4095, 3218, 4065, +4095, 3220, 4065, +4095, 3222, 4064, +4095, 3225, 4063, +4095, 3229, 4062, +4095, 3233, 4061, +4095, 3240, 4059, +4095, 3248, 4057, +4095, 3259, 4054, +4095, 3274, 4050, +4095, 3292, 4044, +4095, 3316, 4037, +4095, 3346, 4026, +4095, 3383, 4012, +4095, 3429, 3992, +4095, 3483, 3964, +4095, 3547, 3924, +4095, 3620, 3864, +4095, 3703, 3768, +4068, 3794, 3598, +0, 2393, 2661, +0, 2393, 2661, +0, 2393, 2661, +0, 2394, 2660, +0, 2395, 2660, +0, 2396, 2659, +0, 2397, 2658, +0, 2399, 2656, +0, 2401, 2654, +0, 2404, 2651, +0, 2408, 2648, +0, 2413, 2643, +0, 2420, 2636, +0, 2429, 2627, +0, 2440, 2614, +0, 2456, 2596, +0, 2475, 2572, +0, 2500, 2537, +0, 2532, 2485, +0, 2571, 2406, +0, 2618, 2271, +0, 2674, 1991, +0, 2740, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3313, 0, +0, 3430, 0, +0, 3550, 0, +0, 3673, 0, +0, 2393, 2662, +0, 2393, 2662, +0, 2394, 2661, +0, 2394, 2661, +0, 2395, 2660, +0, 2396, 2659, +0, 2397, 2658, +0, 2399, 2657, +0, 2401, 2655, +0, 2404, 2652, +0, 2408, 2648, +0, 2413, 2643, +0, 2420, 2636, +0, 2429, 2627, +0, 2441, 2614, +0, 2456, 2597, +0, 2475, 2572, +0, 2500, 2537, +0, 2532, 2486, +0, 2571, 2406, +0, 2618, 2272, +0, 2675, 1992, +0, 2740, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3313, 0, +0, 3430, 0, +0, 3550, 0, +0, 3673, 0, +0, 2393, 2662, +0, 2393, 2662, +0, 2394, 2662, +0, 2394, 2661, +0, 2395, 2661, +0, 2396, 2660, +0, 2397, 2659, +0, 2399, 2657, +0, 2401, 2655, +0, 2404, 2652, +0, 2408, 2649, +0, 2413, 2644, +0, 2420, 2637, +0, 2429, 2628, +0, 2441, 2615, +0, 2456, 2597, +0, 2476, 2573, +0, 2501, 2538, +0, 2532, 2487, +0, 2571, 2407, +0, 2618, 2273, +0, 2675, 1995, +0, 2741, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3313, 0, +0, 3430, 0, +0, 3550, 0, +0, 3673, 0, +0, 2393, 2663, +0, 2393, 2663, +0, 2394, 2662, +0, 2394, 2662, +0, 2395, 2661, +0, 2396, 2661, +0, 2397, 2659, +0, 2399, 2658, +0, 2401, 2656, +0, 2404, 2653, +0, 2408, 2649, +0, 2413, 2644, +0, 2420, 2638, +0, 2429, 2628, +0, 2441, 2616, +0, 2456, 2598, +0, 2476, 2574, +0, 2501, 2539, +0, 2532, 2488, +0, 2571, 2408, +0, 2618, 2275, +0, 2675, 1998, +0, 2741, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3313, 0, +0, 3430, 0, +0, 3550, 0, +0, 3674, 0, +0, 2393, 2664, +0, 2394, 2664, +0, 2394, 2663, +0, 2395, 2663, +0, 2395, 2662, +0, 2396, 2661, +0, 2398, 2660, +0, 2399, 2659, +0, 2401, 2657, +0, 2404, 2654, +0, 2408, 2650, +0, 2413, 2645, +0, 2420, 2639, +0, 2429, 2629, +0, 2441, 2617, +0, 2456, 2599, +0, 2476, 2575, +0, 2501, 2540, +0, 2532, 2489, +0, 2571, 2410, +0, 2618, 2277, +0, 2675, 2002, +0, 2741, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3313, 0, +0, 3430, 0, +0, 3550, 0, +0, 3674, 0, +0, 2394, 2665, +0, 2394, 2665, +0, 2394, 2665, +0, 2395, 2664, +0, 2396, 2664, +0, 2397, 2663, +0, 2398, 2662, +0, 2399, 2660, +0, 2402, 2658, +0, 2405, 2655, +0, 2409, 2652, +0, 2414, 2647, +0, 2421, 2640, +0, 2430, 2631, +0, 2441, 2618, +0, 2457, 2601, +0, 2476, 2576, +0, 2501, 2542, +0, 2533, 2491, +0, 2571, 2412, +0, 2619, 2280, +0, 2675, 2007, +0, 2741, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3314, 0, +0, 3430, 0, +0, 3551, 0, +0, 3674, 0, +0, 2394, 2667, +0, 2394, 2667, +0, 2395, 2666, +0, 2395, 2666, +0, 2396, 2665, +0, 2397, 2664, +0, 2398, 2663, +0, 2400, 2662, +0, 2402, 2660, +0, 2405, 2657, +0, 2409, 2653, +0, 2414, 2648, +0, 2421, 2642, +0, 2430, 2633, +0, 2442, 2620, +0, 2457, 2603, +0, 2477, 2579, +0, 2501, 2544, +0, 2533, 2493, +0, 2572, 2415, +0, 2619, 2284, +0, 2675, 2014, +0, 2741, 0, +0, 2816, 0, +0, 2901, 0, +0, 2994, 0, +0, 3094, 0, +0, 3201, 0, +0, 3314, 0, +0, 3430, 0, +0, 3551, 0, +0, 3674, 0, +0, 2395, 2669, +0, 2395, 2669, +0, 2395, 2669, +0, 2396, 2668, +0, 2397, 2668, +0, 2398, 2667, +0, 2399, 2666, +0, 2400, 2664, +0, 2403, 2662, +0, 2406, 2659, +0, 2410, 2656, +0, 2415, 2651, +0, 2422, 2644, +0, 2430, 2635, +0, 2442, 2623, +0, 2457, 2605, +0, 2477, 2581, +0, 2502, 2547, +0, 2533, 2497, +0, 2572, 2419, +0, 2619, 2289, +0, 2676, 2024, +0, 2741, 0, +0, 2817, 0, +0, 2901, 0, +0, 2994, 0, +0, 3095, 0, +0, 3201, 0, +0, 3314, 0, +0, 3430, 0, +0, 3551, 0, +0, 3674, 0, +0, 2395, 2672, +0, 2396, 2672, +0, 2396, 2672, +0, 2397, 2671, +0, 2397, 2670, +0, 2398, 2670, +0, 2400, 2669, +0, 2401, 2667, +0, 2403, 2665, +0, 2406, 2662, +0, 2410, 2659, +0, 2415, 2654, +0, 2422, 2647, +0, 2431, 2638, +0, 2443, 2626, +0, 2458, 2609, +0, 2478, 2585, +0, 2503, 2551, +0, 2534, 2501, +0, 2573, 2424, +0, 2620, 2296, +0, 2676, 2036, +0, 2742, 0, +0, 2817, 0, +0, 2901, 0, +0, 2994, 0, +0, 3095, 0, +0, 3202, 0, +0, 3314, 0, +0, 3430, 0, +0, 3551, 0, +0, 3674, 0, +0, 2397, 2676, +0, 2397, 2676, +0, 2397, 2676, +0, 2398, 2675, +0, 2398, 2674, +0, 2399, 2674, +0, 2401, 2673, +0, 2402, 2671, +0, 2404, 2669, +0, 2407, 2666, +0, 2411, 2663, +0, 2416, 2658, +0, 2423, 2651, +0, 2432, 2642, +0, 2444, 2630, +0, 2459, 2613, +0, 2478, 2590, +0, 2503, 2556, +0, 2535, 2507, +0, 2573, 2431, +0, 2620, 2305, +0, 2677, 2052, +0, 2742, 0, +0, 2817, 0, +0, 2902, 0, +0, 2995, 0, +0, 3095, 0, +0, 3202, 0, +0, 3314, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +0, 2398, 2681, +0, 2398, 2681, +0, 2399, 2681, +0, 2399, 2680, +0, 2400, 2680, +0, 2401, 2679, +0, 2402, 2678, +0, 2404, 2676, +0, 2406, 2674, +0, 2409, 2672, +0, 2413, 2668, +0, 2418, 2663, +0, 2424, 2657, +0, 2433, 2648, +0, 2445, 2636, +0, 2460, 2619, +0, 2480, 2596, +0, 2504, 2563, +0, 2536, 2514, +0, 2574, 2440, +0, 2621, 2317, +0, 2677, 2072, +0, 2743, 674, +0, 2818, 0, +0, 2902, 0, +0, 2995, 0, +0, 3095, 0, +0, 3202, 0, +0, 3314, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +0, 2400, 2688, +0, 2400, 2688, +0, 2400, 2688, +0, 2401, 2687, +0, 2402, 2687, +0, 2402, 2686, +0, 2404, 2685, +0, 2405, 2683, +0, 2408, 2681, +0, 2410, 2679, +0, 2414, 2675, +0, 2419, 2671, +0, 2426, 2664, +0, 2435, 2656, +0, 2447, 2644, +0, 2462, 2627, +0, 2481, 2604, +0, 2506, 2572, +0, 2537, 2524, +0, 2575, 2452, +0, 2622, 2332, +0, 2678, 2098, +0, 2744, 1046, +0, 2819, 0, +0, 2903, 0, +0, 2995, 0, +0, 3096, 0, +0, 3202, 0, +0, 3314, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +0, 2402, 2697, +0, 2402, 2697, +0, 2403, 2697, +0, 2403, 2696, +0, 2404, 2696, +0, 2405, 2695, +0, 2406, 2694, +0, 2408, 2693, +0, 2410, 2691, +0, 2413, 2688, +0, 2417, 2685, +0, 2422, 2680, +0, 2428, 2674, +0, 2437, 2665, +0, 2449, 2654, +0, 2464, 2638, +0, 2483, 2615, +0, 2508, 2583, +0, 2539, 2537, +0, 2577, 2467, +0, 2624, 2352, +0, 2680, 2130, +0, 2745, 1300, +0, 2820, 0, +0, 2904, 0, +0, 2996, 0, +0, 3096, 0, +0, 3203, 0, +0, 3315, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +0, 2405, 2709, +0, 2406, 2709, +0, 2406, 2709, +0, 2406, 2708, +0, 2407, 2708, +0, 2408, 2707, +0, 2409, 2706, +0, 2411, 2705, +0, 2413, 2703, +0, 2416, 2700, +0, 2420, 2697, +0, 2425, 2692, +0, 2431, 2686, +0, 2440, 2678, +0, 2452, 2667, +0, 2467, 2651, +0, 2486, 2629, +0, 2510, 2599, +0, 2541, 2554, +0, 2579, 2486, +0, 2626, 2377, +0, 2681, 2170, +0, 2746, 1506, +0, 2821, 0, +0, 2905, 0, +0, 2997, 0, +0, 3097, 0, +0, 3203, 0, +0, 3315, 0, +0, 3431, 0, +0, 3551, 0, +0, 3674, 0, +0, 2410, 2725, +0, 2410, 2724, +0, 2410, 2724, +0, 2411, 2724, +0, 2411, 2723, +0, 2412, 2722, +0, 2413, 2721, +0, 2415, 2720, +0, 2417, 2718, +0, 2420, 2716, +0, 2424, 2713, +0, 2429, 2708, +0, 2435, 2702, +0, 2444, 2694, +0, 2456, 2684, +0, 2470, 2669, +0, 2489, 2648, +0, 2514, 2618, +0, 2544, 2575, +0, 2582, 2511, +0, 2628, 2408, +0, 2684, 2219, +0, 2748, 1686, +0, 2823, 0, +0, 2906, 0, +0, 2998, 0, +0, 3098, 0, +0, 3204, 0, +0, 3316, 0, +0, 3432, 0, +0, 3552, 0, +0, 3675, 0, +0, 2415, 2744, +0, 2415, 2744, +0, 2416, 2744, +0, 2416, 2744, +0, 2417, 2743, +0, 2418, 2742, +0, 2419, 2741, +0, 2421, 2740, +0, 2423, 2738, +0, 2426, 2736, +0, 2429, 2733, +0, 2434, 2729, +0, 2441, 2723, +0, 2449, 2716, +0, 2461, 2705, +0, 2475, 2691, +0, 2494, 2671, +0, 2518, 2643, +0, 2548, 2603, +0, 2586, 2543, +0, 2632, 2447, +0, 2687, 2277, +0, 2751, 1851, +0, 2825, 0, +0, 2908, 0, +0, 3000, 0, +0, 3099, 0, +0, 3205, 0, +0, 3316, 0, +0, 3432, 0, +0, 3552, 0, +0, 3675, 0, +896, 2423, 2770, +879, 2423, 2769, +854, 2423, 2769, +820, 2424, 2769, +769, 2424, 2768, +691, 2425, 2768, +560, 2426, 2767, +290, 2428, 2766, +0, 2430, 2764, +0, 2433, 2762, +0, 2436, 2759, +0, 2441, 2755, +0, 2448, 2750, +0, 2456, 2742, +0, 2467, 2733, +0, 2482, 2719, +0, 2500, 2701, +0, 2524, 2674, +0, 2554, 2637, +0, 2591, 2581, +0, 2636, 2494, +0, 2691, 2344, +0, 2755, 2007, +0, 2828, 0, +0, 2910, 0, +0, 3002, 0, +0, 3101, 0, +0, 3206, 0, +0, 3317, 0, +0, 3433, 0, +0, 3553, 0, +0, 3675, 0, +1925, 2432, 2801, +1923, 2432, 2801, +1921, 2433, 2801, +1917, 2433, 2801, +1913, 2434, 2800, +1907, 2435, 2799, +1899, 2436, 2799, +1889, 2438, 2798, +1874, 2440, 2796, +1853, 2442, 2794, +1824, 2446, 2791, +1782, 2451, 2788, +1718, 2457, 2783, +1617, 2465, 2776, +1432, 2476, 2767, +925, 2490, 2754, +0, 2508, 2737, +0, 2532, 2713, +0, 2561, 2679, +0, 2598, 2628, +0, 2642, 2551, +0, 2696, 2421, +0, 2759, 2155, +0, 2832, 0, +0, 2914, 0, +0, 3004, 0, +0, 3103, 0, +0, 3208, 0, +0, 3319, 0, +0, 3434, 0, +0, 3554, 0, +0, 3676, 0, +2283, 2445, 2841, +2282, 2445, 2840, +2281, 2445, 2840, +2279, 2446, 2840, +2278, 2447, 2839, +2275, 2447, 2839, +2271, 2449, 2838, +2267, 2450, 2837, +2260, 2452, 2836, +2252, 2455, 2834, +2240, 2458, 2831, +2223, 2463, 2828, +2200, 2469, 2823, +2168, 2477, 2817, +2120, 2488, 2809, +2047, 2501, 2798, +1927, 2519, 2782, +1692, 2542, 2760, +612, 2571, 2729, +0, 2607, 2685, +0, 2650, 2617, +0, 2703, 2507, +0, 2765, 2299, +0, 2837, 1624, +0, 2918, 0, +0, 3008, 0, +0, 3106, 0, +0, 3210, 0, +0, 3321, 0, +0, 3436, 0, +0, 3555, 0, +0, 3677, 0, +2532, 2461, 2888, +2531, 2462, 2888, +2531, 2462, 2888, +2530, 2462, 2887, +2529, 2463, 2887, +2527, 2464, 2887, +2525, 2465, 2886, +2522, 2466, 2885, +2519, 2468, 2884, +2514, 2471, 2882, +2507, 2474, 2880, +2498, 2479, 2877, +2486, 2484, 2873, +2469, 2492, 2867, +2445, 2503, 2860, +2411, 2516, 2850, +2360, 2533, 2836, +2283, 2555, 2817, +2155, 2583, 2789, +1893, 2618, 2750, +0, 2661, 2692, +0, 2713, 2601, +0, 2774, 2440, +0, 2844, 2059, +0, 2924, 0, +0, 3013, 0, +0, 3110, 0, +0, 3213, 0, +0, 3323, 0, +0, 3438, 0, +0, 3556, 0, +0, 3678, 0, +2735, 2482, 2945, +2735, 2483, 2945, +2734, 2483, 2945, +2734, 2483, 2944, +2733, 2484, 2944, +2732, 2485, 2944, +2731, 2486, 2943, +2729, 2487, 2942, +2727, 2489, 2941, +2724, 2491, 2940, +2719, 2495, 2938, +2714, 2499, 2935, +2706, 2504, 2931, +2696, 2512, 2927, +2681, 2522, 2920, +2661, 2535, 2911, +2633, 2551, 2899, +2592, 2572, 2882, +2532, 2599, 2859, +2435, 2633, 2826, +2263, 2675, 2777, +1825, 2725, 2702, +0, 2784, 2579, +0, 2853, 2332, +0, 2932, 847, +0, 3019, 0, +0, 3115, 0, +0, 3217, 0, +0, 3326, 0, +0, 3440, 0, +0, 3558, 0, +0, 3679, 0, +2914, 2509, 3011, +2913, 2509, 3011, +2913, 2510, 3011, +2913, 2510, 3011, +2912, 2510, 3010, +2912, 2511, 3010, +2911, 2512, 3009, +2910, 2513, 3009, +2908, 2515, 3008, +2906, 2517, 3007, +2903, 2521, 3005, +2900, 2525, 3003, +2894, 2530, 3000, +2888, 2537, 2995, +2878, 2546, 2990, +2865, 2558, 2982, +2848, 2574, 2972, +2823, 2594, 2958, +2787, 2620, 2938, +2735, 2652, 2910, +2653, 2692, 2870, +2516, 2741, 2810, +2224, 2798, 2716, +0, 2865, 2547, +0, 2942, 2131, +0, 3028, 0, +0, 3122, 0, +0, 3223, 0, +0, 3331, 0, +0, 3443, 0, +0, 3561, 0, +0, 3681, 0, +3078, 2542, 3087, +3078, 2543, 3087, +3077, 2543, 3087, +3077, 2543, 3087, +3077, 2544, 3086, +3076, 2544, 3086, +3076, 2545, 3086, +3075, 2547, 3085, +3074, 2548, 3084, +3073, 2550, 3083, +3071, 2553, 3082, +3068, 2557, 3080, +3064, 2562, 3077, +3060, 2569, 3074, +3053, 2577, 3069, +3045, 2589, 3063, +3033, 2603, 3054, +3016, 2622, 3042, +2993, 2647, 3026, +2961, 2677, 3003, +2913, 2715, 2971, +2841, 2761, 2923, +2721, 2816, 2851, +2486, 2881, 2733, +1423, 2955, 2501, +0, 3039, 1510, +0, 3130, 0, +0, 3230, 0, +0, 3336, 0, +0, 3448, 0, +0, 3564, 0, +0, 3684, 0, +3232, 2584, 3172, +3232, 2584, 3172, +3232, 2584, 3172, +3232, 2584, 3172, +3232, 2585, 3171, +3232, 2585, 3171, +3231, 2586, 3171, +3231, 2587, 3170, +3230, 2589, 3170, +3229, 2591, 3169, +3227, 2593, 3167, +3226, 2597, 3166, +3223, 2601, 3164, +3220, 2607, 3161, +3215, 2615, 3157, +3209, 2626, 3152, +3201, 2639, 3145, +3190, 2657, 3135, +3174, 2680, 3122, +3152, 2708, 3103, +3122, 2743, 3078, +3077, 2787, 3041, +3010, 2839, 2986, +2901, 2901, 2901, +2696, 2972, 2754, +2044, 3053, 2432, +0, 3142, 0, +0, 3239, 0, +0, 3344, 0, +0, 3454, 0, +0, 3569, 0, +0, 3687, 0, +3381, 2633, 3265, +3381, 2634, 3265, +3381, 2634, 3265, +3380, 2634, 3265, +3380, 2634, 3265, +3380, 2635, 3265, +3380, 2636, 3264, +3379, 2637, 3264, +3379, 2638, 3263, +3378, 2640, 3263, +3377, 2642, 3262, +3376, 2645, 3260, +3374, 2649, 3259, +3372, 2655, 3256, +3368, 2662, 3253, +3364, 2671, 3249, +3358, 2684, 3243, +3350, 2700, 3235, +3339, 2720, 3225, +3324, 2746, 3210, +3304, 2779, 3190, +3274, 2819, 3161, +3232, 2868, 3120, +3168, 2926, 3058, +3066, 2994, 2960, +2879, 3071, 2782, +2358, 3157, 2318, +0, 3252, 0, +0, 3353, 0, +0, 3461, 0, +0, 3575, 0, +0, 3692, 0, +3525, 2692, 3366, +3525, 2693, 3366, +3524, 2693, 3366, +3524, 2693, 3366, +3524, 2693, 3366, +3524, 2694, 3365, +3524, 2695, 3365, +3524, 2695, 3365, +3523, 2697, 3364, +3523, 2698, 3364, +3522, 2700, 3363, +3521, 2703, 3362, +3520, 2707, 3361, +3518, 2711, 3359, +3516, 2718, 3356, +3512, 2726, 3353, +3508, 2737, 3348, +3503, 2751, 3342, +3495, 2770, 3334, +3484, 2793, 3322, +3470, 2823, 3307, +3450, 2859, 3285, +3421, 2904, 3254, +3380, 2958, 3208, +3319, 3022, 3140, +3221, 3095, 3028, +3045, 3177, 2817, +2591, 3268, 2101, +0, 3366, 0, +0, 3471, 0, +0, 3582, 0, +0, 3698, 0, +3665, 2761, 3473, +3665, 2761, 3473, +3665, 2761, 3473, +3665, 2762, 3473, +3665, 2762, 3473, +3665, 2762, 3473, +3665, 2763, 3472, +3665, 2764, 3472, +3664, 2765, 3472, +3664, 2766, 3471, +3663, 2768, 3471, +3663, 2770, 3470, +3662, 2773, 3469, +3660, 2777, 3467, +3659, 2783, 3465, +3656, 2790, 3463, +3653, 2800, 3459, +3649, 2812, 3454, +3644, 2828, 3448, +3636, 2849, 3439, +3626, 2875, 3427, +3611, 2908, 3410, +3592, 2949, 3387, +3564, 2998, 3353, +3524, 3056, 3305, +3464, 3124, 3230, +3370, 3202, 3106, +3201, 3288, 2859, +2786, 3383, 1324, +0, 3485, 0, +0, 3593, 0, +0, 3706, 0, +3804, 2839, 3586, +3804, 2839, 3586, +3804, 2839, 3586, +3804, 2840, 3585, +3803, 2840, 3585, +3803, 2840, 3585, +3803, 2841, 3585, +3803, 2841, 3585, +3803, 2842, 3585, +3803, 2843, 3584, +3802, 2845, 3584, +3802, 2847, 3583, +3801, 2849, 3582, +3800, 2853, 3581, +3799, 2858, 3580, +3797, 2864, 3578, +3795, 2872, 3575, +3792, 2882, 3571, +3788, 2896, 3566, +3782, 2914, 3559, +3775, 2937, 3550, +3765, 2966, 3537, +3751, 3002, 3520, +3731, 3046, 3495, +3704, 3099, 3460, +3665, 3161, 3408, +3606, 3233, 3328, +3514, 3314, 3193, +3351, 3404, 2910, +2960, 3502, 0, +0, 3606, 0, +0, 3717, 0, +3940, 2926, 3703, +3940, 2926, 3702, +3940, 2926, 3702, +3940, 2926, 3702, +3940, 2927, 3702, +3940, 2927, 3702, +3940, 2927, 3702, +3940, 2928, 3702, +3940, 2929, 3702, +3940, 2930, 3702, +3939, 2931, 3701, +3939, 2932, 3701, +3938, 2935, 3700, +3938, 2938, 3699, +3937, 2941, 3698, +3936, 2947, 3696, +3934, 2953, 3694, +3932, 2962, 3691, +3929, 2974, 3687, +3925, 2989, 3682, +3919, 3008, 3675, +3912, 3033, 3666, +3902, 3064, 3652, +3888, 3103, 3634, +3869, 3150, 3608, +3842, 3206, 3572, +3803, 3271, 3517, +3745, 3347, 3433, +3654, 3431, 3288, +3495, 3523, 2971, +3121, 3624, 0, +0, 3730, 0, +4076, 3021, 3823, +4076, 3021, 3823, +4076, 3021, 3823, +4076, 3022, 3823, +4076, 3022, 3823, +4076, 3022, 3823, +4076, 3022, 3823, +4076, 3023, 3822, +4076, 3023, 3822, +4075, 3024, 3822, +4075, 3025, 3822, +4075, 3026, 3821, +4075, 3028, 3821, +4074, 3031, 3820, +4073, 3034, 3819, +4072, 3038, 3818, +4071, 3043, 3817, +4070, 3051, 3814, +4067, 3060, 3811, +4064, 3073, 3807, +4060, 3089, 3802, +4055, 3110, 3795, +4048, 3136, 3785, +4038, 3170, 3771, +4024, 3210, 3753, +4005, 3260, 3726, +3978, 3318, 3688, +3940, 3387, 3632, +3883, 3464, 3544, +3793, 3551, 3390, +3636, 3646, 3041, +3273, 3748, 0, +4095, 3124, 3946, +4095, 3124, 3946, +4095, 3124, 3946, +4095, 3124, 3946, +4095, 3124, 3946, +4095, 3124, 3946, +4095, 3125, 3946, +4095, 3125, 3946, +4095, 3125, 3946, +4095, 3126, 3945, +4095, 3127, 3945, +4095, 3128, 3945, +4095, 3129, 3945, +4095, 3131, 3944, +4095, 3134, 3943, +4095, 3137, 3942, +4095, 3142, 3941, +4095, 3147, 3940, +4095, 3155, 3937, +4095, 3165, 3934, +4095, 3179, 3930, +4095, 3196, 3925, +4095, 3218, 3917, +4095, 3246, 3907, +4095, 3280, 3893, +4095, 3323, 3874, +4095, 3375, 3847, +4095, 3435, 3808, +4075, 3506, 3750, +4019, 3586, 3659, +3930, 3674, 3499, +3775, 3771, 3120, +4095, 3232, 4071, +4095, 3232, 4071, +4095, 3232, 4071, +4095, 3232, 4071, +4095, 3233, 4071, +4095, 3233, 4071, +4095, 3233, 4071, +4095, 3233, 4071, +4095, 3234, 4071, +4095, 3234, 4071, +4095, 3235, 4071, +4095, 3236, 4070, +4095, 3237, 4070, +4095, 3238, 4070, +4095, 3240, 4069, +4095, 3243, 4069, +4095, 3246, 4068, +4095, 3251, 4066, +4095, 3257, 4065, +4095, 3265, 4062, +4095, 3276, 4059, +4095, 3290, 4055, +4095, 3308, 4050, +4095, 3331, 4042, +4095, 3360, 4032, +4095, 3396, 4018, +4095, 3440, 3998, +4095, 3493, 3971, +4095, 3556, 3931, +4095, 3628, 3872, +4095, 3709, 3778, +4065, 3799, 3612, +0, 2525, 2793, +0, 2525, 2793, +0, 2525, 2793, +0, 2525, 2793, +0, 2526, 2792, +0, 2527, 2792, +0, 2528, 2791, +0, 2529, 2790, +0, 2531, 2788, +0, 2533, 2786, +0, 2536, 2783, +0, 2540, 2779, +0, 2545, 2774, +0, 2552, 2768, +0, 2561, 2758, +0, 2572, 2746, +0, 2588, 2728, +0, 2607, 2704, +0, 2632, 2668, +0, 2664, 2617, +0, 2703, 2537, +0, 2750, 2402, +0, 2807, 2121, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3445, 0, +0, 3562, 0, +0, 3683, 0, +0, 2525, 2794, +0, 2525, 2794, +0, 2525, 2793, +0, 2526, 2793, +0, 2526, 2792, +0, 2527, 2792, +0, 2528, 2791, +0, 2529, 2790, +0, 2531, 2788, +0, 2533, 2786, +0, 2536, 2783, +0, 2540, 2780, +0, 2545, 2775, +0, 2552, 2768, +0, 2561, 2759, +0, 2573, 2746, +0, 2588, 2728, +0, 2607, 2704, +0, 2632, 2669, +0, 2664, 2617, +0, 2703, 2538, +0, 2750, 2403, +0, 2807, 2123, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2525, 2794, +0, 2525, 2794, +0, 2525, 2794, +0, 2526, 2793, +0, 2526, 2793, +0, 2527, 2792, +0, 2528, 2791, +0, 2529, 2790, +0, 2531, 2789, +0, 2533, 2787, +0, 2536, 2784, +0, 2540, 2780, +0, 2545, 2775, +0, 2552, 2768, +0, 2561, 2759, +0, 2573, 2746, +0, 2588, 2729, +0, 2608, 2704, +0, 2633, 2669, +0, 2664, 2618, +0, 2703, 2538, +0, 2750, 2404, +0, 2807, 2124, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2525, 2795, +0, 2525, 2794, +0, 2525, 2794, +0, 2526, 2794, +0, 2526, 2793, +0, 2527, 2793, +0, 2528, 2792, +0, 2529, 2791, +0, 2531, 2789, +0, 2533, 2787, +0, 2536, 2784, +0, 2540, 2781, +0, 2545, 2776, +0, 2552, 2769, +0, 2561, 2760, +0, 2573, 2747, +0, 2588, 2730, +0, 2608, 2705, +0, 2633, 2670, +0, 2664, 2619, +0, 2703, 2539, +0, 2750, 2405, +0, 2807, 2127, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2525, 2795, +0, 2525, 2795, +0, 2526, 2795, +0, 2526, 2795, +0, 2526, 2794, +0, 2527, 2793, +0, 2528, 2793, +0, 2529, 2791, +0, 2531, 2790, +0, 2533, 2788, +0, 2536, 2785, +0, 2540, 2781, +0, 2545, 2776, +0, 2552, 2770, +0, 2561, 2760, +0, 2573, 2748, +0, 2588, 2730, +0, 2608, 2706, +0, 2633, 2671, +0, 2664, 2620, +0, 2703, 2540, +0, 2750, 2407, +0, 2807, 2130, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2525, 2796, +0, 2526, 2796, +0, 2526, 2796, +0, 2526, 2795, +0, 2527, 2795, +0, 2527, 2794, +0, 2528, 2794, +0, 2530, 2792, +0, 2531, 2791, +0, 2533, 2789, +0, 2536, 2786, +0, 2540, 2782, +0, 2546, 2777, +0, 2552, 2771, +0, 2561, 2761, +0, 2573, 2749, +0, 2588, 2731, +0, 2608, 2707, +0, 2633, 2672, +0, 2664, 2621, +0, 2703, 2542, +0, 2751, 2409, +0, 2807, 2134, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2526, 2798, +0, 2526, 2797, +0, 2526, 2797, +0, 2527, 2797, +0, 2527, 2796, +0, 2528, 2796, +0, 2529, 2795, +0, 2530, 2794, +0, 2532, 2792, +0, 2534, 2790, +0, 2537, 2787, +0, 2541, 2784, +0, 2546, 2779, +0, 2553, 2772, +0, 2562, 2763, +0, 2573, 2750, +0, 2589, 2733, +0, 2608, 2709, +0, 2633, 2674, +0, 2665, 2623, +0, 2703, 2544, +0, 2751, 2412, +0, 2807, 2139, +0, 2873, 0, +0, 2948, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2526, 2799, +0, 2526, 2799, +0, 2527, 2799, +0, 2527, 2798, +0, 2527, 2798, +0, 2528, 2797, +0, 2529, 2797, +0, 2530, 2795, +0, 2532, 2794, +0, 2534, 2792, +0, 2537, 2789, +0, 2541, 2785, +0, 2546, 2780, +0, 2553, 2774, +0, 2562, 2765, +0, 2574, 2752, +0, 2589, 2735, +0, 2609, 2711, +0, 2634, 2676, +0, 2665, 2625, +0, 2704, 2547, +0, 2751, 2416, +0, 2807, 2146, +0, 2873, 0, +0, 2949, 0, +0, 3033, 0, +0, 3126, 0, +0, 3226, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2527, 2801, +0, 2527, 2801, +0, 2527, 2801, +0, 2528, 2801, +0, 2528, 2800, +0, 2529, 2800, +0, 2530, 2799, +0, 2531, 2798, +0, 2533, 2796, +0, 2535, 2794, +0, 2538, 2791, +0, 2542, 2788, +0, 2547, 2783, +0, 2554, 2776, +0, 2563, 2767, +0, 2574, 2755, +0, 2590, 2737, +0, 2609, 2713, +0, 2634, 2679, +0, 2665, 2629, +0, 2704, 2551, +0, 2751, 2421, +0, 2808, 2156, +0, 2873, 0, +0, 2949, 0, +0, 3033, 0, +0, 3126, 0, +0, 3227, 0, +0, 3333, 0, +0, 3446, 0, +0, 3562, 0, +0, 3683, 0, +0, 2527, 2804, +0, 2528, 2804, +0, 2528, 2804, +0, 2528, 2804, +0, 2529, 2803, +0, 2529, 2803, +0, 2530, 2802, +0, 2532, 2801, +0, 2533, 2799, +0, 2536, 2797, +0, 2538, 2794, +0, 2542, 2791, +0, 2548, 2786, +0, 2554, 2779, +0, 2563, 2770, +0, 2575, 2758, +0, 2590, 2741, +0, 2610, 2717, +0, 2635, 2683, +0, 2666, 2633, +0, 2705, 2556, +0, 2752, 2428, +0, 2808, 2168, +0, 2874, 0, +0, 2949, 0, +0, 3034, 0, +0, 3126, 0, +0, 3227, 0, +0, 3334, 0, +0, 3446, 0, +0, 3563, 0, +0, 3683, 0, +0, 2528, 2808, +0, 2529, 2808, +0, 2529, 2808, +0, 2529, 2808, +0, 2530, 2807, +0, 2531, 2807, +0, 2531, 2806, +0, 2533, 2805, +0, 2534, 2803, +0, 2537, 2801, +0, 2539, 2799, +0, 2543, 2795, +0, 2549, 2790, +0, 2555, 2783, +0, 2564, 2775, +0, 2576, 2762, +0, 2591, 2745, +0, 2611, 2722, +0, 2635, 2688, +0, 2667, 2639, +0, 2705, 2563, +0, 2752, 2437, +0, 2809, 2184, +0, 2874, 0, +0, 2949, 0, +0, 3034, 0, +0, 3127, 0, +0, 3227, 0, +0, 3334, 0, +0, 3446, 0, +0, 3563, 0, +0, 3683, 0, +0, 2530, 2814, +0, 2530, 2813, +0, 2530, 2813, +0, 2531, 2813, +0, 2531, 2812, +0, 2532, 2812, +0, 2533, 2811, +0, 2534, 2810, +0, 2536, 2808, +0, 2538, 2806, +0, 2541, 2804, +0, 2545, 2800, +0, 2550, 2795, +0, 2557, 2789, +0, 2565, 2780, +0, 2577, 2768, +0, 2592, 2751, +0, 2612, 2728, +0, 2636, 2695, +0, 2668, 2646, +0, 2706, 2572, +0, 2753, 2449, +0, 2809, 2204, +0, 2875, 806, +0, 2950, 0, +0, 3034, 0, +0, 3127, 0, +0, 3227, 0, +0, 3334, 0, +0, 3446, 0, +0, 3563, 0, +0, 3683, 0, +0, 2532, 2821, +0, 2532, 2820, +0, 2532, 2820, +0, 2532, 2820, +0, 2533, 2819, +0, 2534, 2819, +0, 2535, 2818, +0, 2536, 2817, +0, 2537, 2815, +0, 2540, 2814, +0, 2543, 2811, +0, 2546, 2807, +0, 2552, 2803, +0, 2558, 2796, +0, 2567, 2788, +0, 2579, 2776, +0, 2594, 2759, +0, 2613, 2736, +0, 2638, 2704, +0, 2669, 2656, +0, 2708, 2584, +0, 2754, 2464, +0, 2810, 2230, +0, 2876, 1179, +0, 2951, 0, +0, 3035, 0, +0, 3128, 0, +0, 3228, 0, +0, 3334, 0, +0, 3446, 0, +0, 3563, 0, +0, 3683, 0, +0, 2534, 2830, +0, 2534, 2829, +0, 2534, 2829, +0, 2535, 2829, +0, 2535, 2828, +0, 2536, 2828, +0, 2537, 2827, +0, 2538, 2826, +0, 2540, 2825, +0, 2542, 2823, +0, 2545, 2820, +0, 2549, 2817, +0, 2554, 2812, +0, 2561, 2806, +0, 2569, 2797, +0, 2581, 2786, +0, 2596, 2770, +0, 2615, 2747, +0, 2640, 2716, +0, 2671, 2669, +0, 2709, 2599, +0, 2756, 2484, +0, 2812, 2263, +0, 2877, 1432, +0, 2952, 0, +0, 3036, 0, +0, 3128, 0, +0, 3228, 0, +0, 3335, 0, +0, 3447, 0, +0, 3563, 0, +0, 3683, 0, +0, 2537, 2842, +0, 2537, 2841, +0, 2538, 2841, +0, 2538, 2841, +0, 2539, 2840, +0, 2539, 2840, +0, 2540, 2839, +0, 2541, 2838, +0, 2543, 2837, +0, 2545, 2835, +0, 2548, 2832, +0, 2552, 2829, +0, 2557, 2824, +0, 2564, 2818, +0, 2572, 2810, +0, 2584, 2799, +0, 2599, 2783, +0, 2618, 2761, +0, 2642, 2731, +0, 2673, 2686, +0, 2711, 2618, +0, 2758, 2509, +0, 2813, 2303, +0, 2878, 1638, +0, 2953, 0, +0, 3037, 0, +0, 3129, 0, +0, 3229, 0, +0, 3335, 0, +0, 3447, 0, +0, 3564, 0, +0, 3684, 0, +0, 2541, 2857, +0, 2542, 2857, +0, 2542, 2857, +0, 2542, 2856, +0, 2543, 2856, +0, 2543, 2855, +0, 2544, 2854, +0, 2546, 2854, +0, 2547, 2852, +0, 2549, 2850, +0, 2552, 2848, +0, 2556, 2845, +0, 2561, 2840, +0, 2568, 2835, +0, 2576, 2827, +0, 2588, 2816, +0, 2602, 2801, +0, 2621, 2780, +0, 2646, 2750, +0, 2676, 2708, +0, 2714, 2643, +0, 2760, 2540, +0, 2816, 2351, +0, 2880, 1818, +0, 2955, 0, +0, 3038, 0, +0, 3130, 0, +0, 3230, 0, +0, 3336, 0, +0, 3448, 0, +0, 3564, 0, +0, 3684, 0, +0, 2547, 2877, +0, 2547, 2877, +0, 2547, 2876, +0, 2548, 2876, +0, 2548, 2876, +0, 2549, 2875, +0, 2550, 2874, +0, 2551, 2873, +0, 2553, 2872, +0, 2555, 2870, +0, 2558, 2868, +0, 2561, 2865, +0, 2566, 2861, +0, 2573, 2855, +0, 2581, 2848, +0, 2593, 2837, +0, 2607, 2823, +0, 2626, 2803, +0, 2650, 2775, +0, 2680, 2735, +0, 2718, 2675, +0, 2764, 2579, +0, 2819, 2409, +0, 2883, 1983, +0, 2957, 0, +0, 3040, 0, +0, 3132, 0, +0, 3231, 0, +0, 3337, 0, +0, 3449, 0, +0, 3565, 0, +0, 3684, 0, +1040, 2554, 2902, +1028, 2555, 2902, +1011, 2555, 2902, +986, 2555, 2901, +952, 2556, 2901, +901, 2556, 2900, +823, 2557, 2900, +692, 2558, 2899, +422, 2560, 2898, +0, 2562, 2896, +0, 2565, 2894, +0, 2569, 2891, +0, 2573, 2887, +0, 2580, 2882, +0, 2588, 2875, +0, 2599, 2865, +0, 2614, 2851, +0, 2632, 2833, +0, 2656, 2806, +0, 2686, 2769, +0, 2723, 2713, +0, 2768, 2627, +0, 2823, 2476, +0, 2887, 2139, +0, 2960, 0, +0, 3043, 0, +0, 3134, 0, +0, 3233, 0, +0, 3338, 0, +0, 3450, 0, +0, 3565, 0, +0, 3685, 0, +2058, 2564, 2934, +2057, 2564, 2933, +2055, 2565, 2933, +2053, 2565, 2933, +2050, 2565, 2933, +2045, 2566, 2932, +2039, 2567, 2932, +2032, 2568, 2931, +2021, 2570, 2930, +2006, 2572, 2928, +1985, 2574, 2926, +1956, 2578, 2923, +1914, 2583, 2920, +1850, 2589, 2915, +1749, 2597, 2908, +1564, 2608, 2899, +1057, 2622, 2887, +0, 2641, 2869, +0, 2664, 2845, +0, 2693, 2811, +0, 2730, 2761, +0, 2775, 2683, +0, 2828, 2553, +0, 2891, 2287, +0, 2964, 0, +0, 3046, 0, +0, 3137, 0, +0, 3235, 0, +0, 3340, 0, +0, 3451, 0, +0, 3566, 0, +0, 3686, 0, +2415, 2577, 2973, +2415, 2577, 2973, +2414, 2577, 2972, +2413, 2578, 2972, +2412, 2578, 2972, +2410, 2579, 2971, +2407, 2580, 2971, +2404, 2581, 2970, +2399, 2582, 2969, +2392, 2584, 2968, +2384, 2587, 2966, +2372, 2590, 2963, +2355, 2595, 2960, +2332, 2601, 2956, +2300, 2609, 2949, +2252, 2620, 2941, +2179, 2633, 2930, +2059, 2651, 2914, +1824, 2674, 2892, +744, 2703, 2862, +0, 2739, 2817, +0, 2783, 2749, +0, 2835, 2639, +0, 2898, 2431, +0, 2969, 1756, +0, 3050, 0, +0, 3140, 0, +0, 3238, 0, +0, 3342, 0, +0, 3453, 0, +0, 3568, 0, +0, 3687, 0, +2664, 2593, 3020, +2664, 2593, 3020, +2663, 2594, 3020, +2663, 2594, 3020, +2662, 2594, 3020, +2661, 2595, 3019, +2659, 2596, 3019, +2657, 2597, 3018, +2654, 2598, 3017, +2651, 2600, 3016, +2646, 2603, 3014, +2639, 2606, 3012, +2630, 2611, 3009, +2618, 2617, 3005, +2601, 2624, 2999, +2577, 2635, 2992, +2543, 2648, 2982, +2493, 2665, 2968, +2416, 2687, 2949, +2287, 2715, 2922, +2025, 2750, 2883, +0, 2793, 2824, +0, 2845, 2733, +0, 2906, 2572, +0, 2976, 2191, +0, 3056, 0, +0, 3145, 0, +0, 3242, 0, +0, 3345, 0, +0, 3455, 0, +0, 3570, 0, +0, 3688, 0, +2867, 2614, 3077, +2867, 2614, 3077, +2867, 2615, 3077, +2866, 2615, 3077, +2866, 2615, 3076, +2865, 2616, 3076, +2864, 2617, 3076, +2863, 2618, 3075, +2861, 2619, 3074, +2859, 2621, 3073, +2856, 2623, 3072, +2851, 2627, 3070, +2846, 2631, 3067, +2838, 2637, 3063, +2828, 2644, 3059, +2813, 2654, 3052, +2793, 2667, 3043, +2765, 2683, 3031, +2724, 2705, 3014, +2664, 2731, 2991, +2567, 2765, 2958, +2395, 2807, 2909, +1957, 2857, 2835, +0, 2916, 2711, +0, 2985, 2465, +0, 3064, 979, +0, 3151, 0, +0, 3247, 0, +0, 3350, 0, +0, 3458, 0, +0, 3572, 0, +0, 3690, 0, +3046, 2641, 3143, +3046, 2641, 3143, +3046, 2641, 3143, +3045, 2642, 3143, +3045, 2642, 3143, +3044, 2643, 3142, +3044, 2643, 3142, +3043, 2644, 3142, +3042, 2646, 3141, +3040, 2647, 3140, +3038, 2650, 3139, +3035, 2653, 3137, +3032, 2657, 3135, +3027, 2662, 3132, +3020, 2669, 3127, +3010, 2678, 3122, +2997, 2691, 3114, +2980, 2706, 3104, +2955, 2727, 3090, +2919, 2752, 3070, +2867, 2785, 3042, +2786, 2824, 3002, +2648, 2873, 2942, +2356, 2930, 2848, +0, 2997, 2679, +0, 3074, 2263, +0, 3160, 0, +0, 3254, 0, +0, 3355, 0, +0, 3463, 0, +0, 3576, 0, +0, 3693, 0, +3210, 2674, 3219, +3210, 2674, 3219, +3210, 2675, 3219, +3210, 2675, 3219, +3209, 2675, 3219, +3209, 2676, 3218, +3209, 2677, 3218, +3208, 2677, 3218, +3207, 2679, 3217, +3206, 2680, 3216, +3205, 2682, 3215, +3203, 2685, 3214, +3200, 2689, 3212, +3197, 2694, 3209, +3192, 2701, 3206, +3185, 2709, 3201, +3177, 2721, 3195, +3165, 2735, 3186, +3148, 2754, 3174, +3126, 2779, 3158, +3093, 2809, 3135, +3045, 2847, 3103, +2973, 2893, 3055, +2853, 2948, 2983, +2618, 3013, 2865, +1555, 3087, 2634, +0, 3171, 1643, +0, 3263, 0, +0, 3362, 0, +0, 3468, 0, +0, 3580, 0, +0, 3696, 0, +3365, 2716, 3304, +3365, 2716, 3304, +3364, 2716, 3304, +3364, 2716, 3304, +3364, 2716, 3304, +3364, 2717, 3303, +3364, 2718, 3303, +3363, 2718, 3303, +3363, 2719, 3302, +3362, 2721, 3302, +3361, 2723, 3301, +3359, 2725, 3300, +3358, 2729, 3298, +3355, 2734, 3296, +3352, 2740, 3293, +3347, 2748, 3289, +3341, 2758, 3284, +3333, 2772, 3277, +3322, 2789, 3267, +3306, 2812, 3254, +3285, 2840, 3235, +3254, 2876, 3210, +3209, 2919, 3173, +3142, 2971, 3118, +3033, 3033, 3033, +2828, 3104, 2887, +2176, 3185, 2564, +0, 3274, 0, +0, 3372, 0, +0, 3476, 0, +0, 3586, 0, +0, 3701, 0, +3513, 2765, 3397, +3513, 2765, 3397, +3513, 2766, 3397, +3513, 2766, 3397, +3513, 2766, 3397, +3512, 2767, 3397, +3512, 2767, 3397, +3512, 2768, 3396, +3511, 2769, 3396, +3511, 2770, 3395, +3510, 2772, 3395, +3509, 2774, 3394, +3508, 2777, 3392, +3506, 2781, 3391, +3504, 2787, 3388, +3500, 2794, 3385, +3496, 2804, 3381, +3490, 2816, 3375, +3482, 2832, 3367, +3471, 2852, 3357, +3457, 2878, 3342, +3436, 2911, 3322, +3406, 2951, 3293, +3364, 3000, 3252, +3300, 3058, 3190, +3198, 3126, 3092, +3011, 3203, 2914, +2491, 3289, 2450, +0, 3384, 0, +0, 3486, 0, +0, 3594, 0, +0, 3707, 0, +3657, 2824, 3498, +3657, 2824, 3498, +3657, 2825, 3498, +3657, 2825, 3498, +3656, 2825, 3498, +3656, 2825, 3498, +3656, 2826, 3497, +3656, 2827, 3497, +3656, 2827, 3497, +3655, 2829, 3497, +3655, 2830, 3496, +3654, 2832, 3495, +3653, 2835, 3494, +3652, 2839, 3493, +3650, 2843, 3491, +3648, 2850, 3488, +3645, 2858, 3485, +3640, 2869, 3480, +3635, 2883, 3474, +3627, 2902, 3466, +3616, 2925, 3454, +3602, 2955, 3439, +3582, 2992, 3417, +3553, 3036, 3386, +3512, 3090, 3340, +3451, 3154, 3272, +3353, 3227, 3160, +3177, 3309, 2949, +2723, 3400, 2233, +0, 3498, 0, +0, 3604, 0, +0, 3715, 0, +3797, 2893, 3605, +3797, 2893, 3605, +3797, 2893, 3605, +3797, 2893, 3605, +3797, 2894, 3605, +3797, 2894, 3605, +3797, 2894, 3605, +3797, 2895, 3605, +3797, 2896, 3604, +3796, 2897, 3604, +3796, 2898, 3604, +3795, 2900, 3603, +3795, 2902, 3602, +3794, 2905, 3601, +3792, 2909, 3600, +3791, 2915, 3598, +3788, 2922, 3595, +3785, 2932, 3591, +3781, 2944, 3587, +3776, 2960, 3580, +3768, 2981, 3571, +3758, 3007, 3559, +3744, 3040, 3542, +3724, 3081, 3519, +3696, 3130, 3486, +3656, 3188, 3437, +3596, 3256, 3362, +3502, 3334, 3238, +3333, 3420, 2991, +2918, 3515, 1456, +0, 3617, 0, +0, 3725, 0, +3936, 2971, 3718, +3936, 2971, 3718, +3936, 2971, 3718, +3936, 2971, 3718, +3936, 2972, 3718, +3936, 2972, 3717, +3935, 2972, 3717, +3935, 2973, 3717, +3935, 2973, 3717, +3935, 2974, 3717, +3935, 2975, 3716, +3934, 2977, 3716, +3934, 2979, 3715, +3933, 2981, 3714, +3932, 2985, 3713, +3931, 2990, 3712, +3929, 2996, 3710, +3927, 3004, 3707, +3924, 3015, 3703, +3920, 3028, 3698, +3914, 3046, 3691, +3907, 3069, 3682, +3897, 3098, 3669, +3883, 3134, 3652, +3863, 3178, 3627, +3836, 3231, 3592, +3797, 3293, 3540, +3738, 3365, 3460, +3646, 3446, 3325, +3483, 3536, 3042, +3092, 3634, 0, +0, 3738, 0, +4073, 3058, 3835, +4073, 3058, 3835, +4072, 3058, 3835, +4072, 3058, 3835, +4072, 3059, 3834, +4072, 3059, 3834, +4072, 3059, 3834, +4072, 3059, 3834, +4072, 3060, 3834, +4072, 3061, 3834, +4072, 3062, 3834, +4071, 3063, 3833, +4071, 3064, 3833, +4071, 3067, 3832, +4070, 3070, 3831, +4069, 3073, 3830, +4068, 3079, 3828, +4066, 3085, 3826, +4064, 3094, 3823, +4061, 3106, 3820, +4057, 3121, 3814, +4051, 3140, 3807, +4044, 3165, 3798, +4034, 3196, 3784, +4020, 3235, 3766, +4001, 3282, 3741, +3974, 3338, 3704, +3935, 3404, 3650, +3877, 3479, 3565, +3787, 3563, 3420, +3627, 3656, 3103, +3253, 3756, 0, +4095, 3153, 3955, +4095, 3153, 3955, +4095, 3153, 3955, +4095, 3154, 3955, +4095, 3154, 3955, +4095, 3154, 3955, +4095, 3154, 3955, +4095, 3154, 3955, +4095, 3155, 3955, +4095, 3155, 3954, +4095, 3156, 3954, +4095, 3157, 3954, +4095, 3159, 3954, +4095, 3160, 3953, +4095, 3163, 3952, +4095, 3166, 3951, +4095, 3170, 3950, +4095, 3176, 3949, +4095, 3183, 3946, +4095, 3192, 3943, +4095, 3205, 3940, +4095, 3221, 3934, +4095, 3242, 3927, +4095, 3269, 3917, +4095, 3302, 3903, +4095, 3342, 3885, +4095, 3392, 3858, +4095, 3451, 3820, +4072, 3519, 3764, +4015, 3596, 3676, +3925, 3683, 3522, +3768, 3778, 3173, +4095, 3256, 4078, +4095, 3256, 4078, +4095, 3256, 4078, +4095, 3256, 4078, +4095, 3256, 4078, +4095, 3256, 4078, +4095, 3256, 4078, +4095, 3257, 4078, +4095, 3257, 4078, +4095, 3257, 4078, +4095, 3258, 4078, +4095, 3259, 4077, +4095, 3260, 4077, +4095, 3261, 4077, +4095, 3263, 4076, +4095, 3266, 4075, +4095, 3269, 4075, +4095, 3274, 4073, +4095, 3280, 4072, +4095, 3287, 4069, +4095, 3297, 4066, +4095, 3311, 4062, +4095, 3328, 4057, +4095, 3350, 4049, +4095, 3378, 4039, +4095, 3413, 4025, +4095, 3455, 4006, +4095, 3507, 3979, +4095, 3567, 3940, +4095, 3638, 3882, +4095, 3718, 3791, +4062, 3806, 3631, +0, 2656, 2925, +0, 2657, 2925, +0, 2657, 2925, +0, 2657, 2925, +0, 2658, 2924, +0, 2658, 2924, +0, 2659, 2923, +0, 2660, 2923, +0, 2661, 2921, +0, 2663, 2920, +0, 2665, 2918, +0, 2668, 2915, +0, 2672, 2911, +0, 2677, 2906, +0, 2684, 2899, +0, 2693, 2890, +0, 2705, 2878, +0, 2720, 2860, +0, 2739, 2835, +0, 2764, 2800, +0, 2796, 2749, +0, 2835, 2669, +0, 2882, 2534, +0, 2939, 2253, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2657, 2926, +0, 2657, 2926, +0, 2657, 2925, +0, 2657, 2925, +0, 2658, 2925, +0, 2658, 2924, +0, 2659, 2924, +0, 2660, 2923, +0, 2661, 2922, +0, 2663, 2920, +0, 2665, 2918, +0, 2668, 2915, +0, 2672, 2912, +0, 2677, 2907, +0, 2684, 2900, +0, 2693, 2890, +0, 2705, 2878, +0, 2720, 2860, +0, 2739, 2836, +0, 2765, 2801, +0, 2796, 2749, +0, 2835, 2669, +0, 2882, 2535, +0, 2939, 2254, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2657, 2926, +0, 2657, 2926, +0, 2657, 2926, +0, 2657, 2925, +0, 2658, 2925, +0, 2658, 2925, +0, 2659, 2924, +0, 2660, 2923, +0, 2661, 2922, +0, 2663, 2920, +0, 2665, 2918, +0, 2668, 2916, +0, 2672, 2912, +0, 2677, 2907, +0, 2684, 2900, +0, 2693, 2891, +0, 2705, 2878, +0, 2720, 2861, +0, 2740, 2836, +0, 2765, 2801, +0, 2796, 2749, +0, 2835, 2670, +0, 2882, 2535, +0, 2939, 2255, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2657, 2926, +0, 2657, 2926, +0, 2657, 2926, +0, 2657, 2926, +0, 2658, 2925, +0, 2658, 2925, +0, 2659, 2924, +0, 2660, 2923, +0, 2661, 2922, +0, 2663, 2921, +0, 2665, 2919, +0, 2668, 2916, +0, 2672, 2912, +0, 2677, 2907, +0, 2684, 2900, +0, 2693, 2891, +0, 2705, 2879, +0, 2720, 2861, +0, 2740, 2836, +0, 2765, 2801, +0, 2796, 2750, +0, 2835, 2670, +0, 2882, 2536, +0, 2939, 2257, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2657, 2927, +0, 2657, 2927, +0, 2657, 2927, +0, 2657, 2926, +0, 2658, 2926, +0, 2658, 2925, +0, 2659, 2925, +0, 2660, 2924, +0, 2661, 2923, +0, 2663, 2921, +0, 2665, 2919, +0, 2668, 2917, +0, 2672, 2913, +0, 2677, 2908, +0, 2684, 2901, +0, 2693, 2892, +0, 2705, 2879, +0, 2720, 2862, +0, 2740, 2837, +0, 2765, 2802, +0, 2796, 2751, +0, 2835, 2671, +0, 2882, 2537, +0, 2939, 2259, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2657, 2928, +0, 2657, 2927, +0, 2657, 2927, +0, 2658, 2927, +0, 2658, 2927, +0, 2659, 2926, +0, 2659, 2926, +0, 2660, 2925, +0, 2661, 2924, +0, 2663, 2922, +0, 2665, 2920, +0, 2668, 2917, +0, 2672, 2914, +0, 2677, 2909, +0, 2684, 2902, +0, 2693, 2893, +0, 2705, 2880, +0, 2720, 2862, +0, 2740, 2838, +0, 2765, 2803, +0, 2796, 2752, +0, 2835, 2673, +0, 2882, 2539, +0, 2939, 2262, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2657, 2929, +0, 2657, 2928, +0, 2658, 2928, +0, 2658, 2928, +0, 2658, 2928, +0, 2659, 2927, +0, 2660, 2926, +0, 2660, 2926, +0, 2662, 2925, +0, 2663, 2923, +0, 2666, 2921, +0, 2669, 2918, +0, 2672, 2915, +0, 2678, 2910, +0, 2684, 2903, +0, 2693, 2894, +0, 2705, 2881, +0, 2720, 2864, +0, 2740, 2839, +0, 2765, 2804, +0, 2796, 2753, +0, 2835, 2674, +0, 2883, 2541, +0, 2939, 2266, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2658, 2930, +0, 2658, 2930, +0, 2658, 2929, +0, 2658, 2929, +0, 2659, 2929, +0, 2659, 2928, +0, 2660, 2928, +0, 2661, 2927, +0, 2662, 2926, +0, 2664, 2924, +0, 2666, 2922, +0, 2669, 2919, +0, 2673, 2916, +0, 2678, 2911, +0, 2685, 2904, +0, 2694, 2895, +0, 2706, 2882, +0, 2721, 2865, +0, 2740, 2841, +0, 2765, 2806, +0, 2797, 2755, +0, 2836, 2676, +0, 2883, 2544, +0, 2939, 2271, +0, 3005, 0, +0, 3080, 0, +0, 3165, 0, +0, 3258, 0, +0, 3358, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2658, 2931, +0, 2658, 2931, +0, 2658, 2931, +0, 2659, 2931, +0, 2659, 2931, +0, 2660, 2930, +0, 2660, 2929, +0, 2661, 2929, +0, 2662, 2927, +0, 2664, 2926, +0, 2666, 2924, +0, 2669, 2921, +0, 2673, 2918, +0, 2678, 2913, +0, 2685, 2906, +0, 2694, 2897, +0, 2706, 2884, +0, 2721, 2867, +0, 2741, 2843, +0, 2766, 2808, +0, 2797, 2757, +0, 2836, 2679, +0, 2883, 2548, +0, 2939, 2279, +0, 3005, 0, +0, 3081, 0, +0, 3165, 0, +0, 3258, 0, +0, 3359, 0, +0, 3465, 0, +0, 3578, 0, +0, 3694, 0, +0, 2659, 2934, +0, 2659, 2934, +0, 2659, 2933, +0, 2659, 2933, +0, 2660, 2933, +0, 2660, 2932, +0, 2661, 2932, +0, 2662, 2931, +0, 2663, 2930, +0, 2665, 2928, +0, 2667, 2926, +0, 2670, 2924, +0, 2674, 2920, +0, 2679, 2915, +0, 2686, 2908, +0, 2695, 2899, +0, 2706, 2887, +0, 2722, 2870, +0, 2741, 2845, +0, 2766, 2811, +0, 2797, 2761, +0, 2836, 2683, +0, 2883, 2553, +0, 2940, 2288, +0, 3006, 0, +0, 3081, 0, +0, 3165, 0, +0, 3258, 0, +0, 3359, 0, +0, 3466, 0, +0, 3578, 0, +0, 3695, 0, +0, 2659, 2937, +0, 2659, 2937, +0, 2660, 2936, +0, 2660, 2936, +0, 2660, 2936, +0, 2661, 2935, +0, 2662, 2935, +0, 2663, 2934, +0, 2664, 2933, +0, 2665, 2931, +0, 2668, 2929, +0, 2671, 2927, +0, 2674, 2923, +0, 2680, 2918, +0, 2686, 2911, +0, 2695, 2902, +0, 2707, 2890, +0, 2722, 2873, +0, 2742, 2849, +0, 2767, 2815, +0, 2798, 2765, +0, 2837, 2688, +0, 2884, 2560, +0, 2940, 2300, +0, 3006, 0, +0, 3081, 0, +0, 3166, 0, +0, 3258, 0, +0, 3359, 0, +0, 3466, 0, +0, 3578, 0, +0, 3695, 0, +0, 2660, 2941, +0, 2660, 2941, +0, 2661, 2940, +0, 2661, 2940, +0, 2661, 2940, +0, 2662, 2939, +0, 2663, 2939, +0, 2664, 2938, +0, 2665, 2937, +0, 2666, 2935, +0, 2669, 2933, +0, 2672, 2931, +0, 2675, 2927, +0, 2681, 2922, +0, 2687, 2916, +0, 2696, 2907, +0, 2708, 2894, +0, 2723, 2877, +0, 2743, 2854, +0, 2768, 2820, +0, 2799, 2771, +0, 2837, 2695, +0, 2885, 2569, +0, 2941, 2316, +0, 3006, 0, +0, 3082, 0, +0, 3166, 0, +0, 3259, 0, +0, 3359, 0, +0, 3466, 0, +0, 3578, 0, +0, 3695, 0, +0, 2662, 2946, +0, 2662, 2946, +0, 2662, 2946, +0, 2662, 2945, +0, 2663, 2945, +0, 2663, 2945, +0, 2664, 2944, +0, 2665, 2943, +0, 2666, 2942, +0, 2668, 2941, +0, 2670, 2939, +0, 2673, 2936, +0, 2677, 2932, +0, 2682, 2928, +0, 2689, 2921, +0, 2698, 2912, +0, 2709, 2900, +0, 2724, 2883, +0, 2744, 2860, +0, 2769, 2827, +0, 2800, 2778, +0, 2838, 2704, +0, 2885, 2581, +0, 2941, 2336, +0, 3007, 938, +0, 3082, 0, +0, 3166, 0, +0, 3259, 0, +0, 3359, 0, +0, 3466, 0, +0, 3578, 0, +0, 3695, 0, +0, 2663, 2953, +0, 2664, 2953, +0, 2664, 2952, +0, 2664, 2952, +0, 2665, 2952, +0, 2665, 2951, +0, 2666, 2951, +0, 2667, 2950, +0, 2668, 2949, +0, 2670, 2948, +0, 2672, 2946, +0, 2675, 2943, +0, 2679, 2940, +0, 2684, 2935, +0, 2690, 2928, +0, 2699, 2920, +0, 2711, 2908, +0, 2726, 2891, +0, 2745, 2868, +0, 2770, 2836, +0, 2801, 2788, +0, 2840, 2716, +0, 2886, 2596, +0, 2942, 2362, +0, 3008, 1311, +0, 3083, 0, +0, 3167, 0, +0, 3260, 0, +0, 3360, 0, +0, 3466, 0, +0, 3579, 0, +0, 3695, 0, +0, 2666, 2962, +0, 2666, 2962, +0, 2666, 2962, +0, 2667, 2961, +0, 2667, 2961, +0, 2667, 2961, +0, 2668, 2960, +0, 2669, 2959, +0, 2670, 2958, +0, 2672, 2957, +0, 2674, 2955, +0, 2677, 2952, +0, 2681, 2949, +0, 2686, 2944, +0, 2693, 2938, +0, 2701, 2929, +0, 2713, 2918, +0, 2728, 2902, +0, 2747, 2879, +0, 2772, 2848, +0, 2803, 2801, +0, 2841, 2731, +0, 2888, 2616, +0, 2944, 2395, +0, 3009, 1565, +0, 3084, 0, +0, 3168, 0, +0, 3260, 0, +0, 3360, 0, +0, 3467, 0, +0, 3579, 0, +0, 3695, 0, +0, 2669, 2974, +0, 2669, 2974, +0, 2669, 2973, +0, 2670, 2973, +0, 2670, 2973, +0, 2671, 2972, +0, 2671, 2972, +0, 2672, 2971, +0, 2673, 2970, +0, 2675, 2969, +0, 2677, 2967, +0, 2680, 2964, +0, 2684, 2961, +0, 2689, 2957, +0, 2696, 2950, +0, 2704, 2942, +0, 2716, 2931, +0, 2731, 2915, +0, 2750, 2894, +0, 2774, 2863, +0, 2805, 2818, +0, 2843, 2751, +0, 2890, 2641, +0, 2945, 2435, +0, 3010, 1770, +0, 3085, 0, +0, 3169, 0, +0, 3261, 0, +0, 3361, 0, +0, 3467, 0, +0, 3579, 0, +0, 3696, 0, +0, 2673, 2989, +0, 2673, 2989, +0, 2674, 2989, +0, 2674, 2989, +0, 2674, 2988, +0, 2675, 2988, +0, 2676, 2987, +0, 2676, 2987, +0, 2678, 2986, +0, 2679, 2984, +0, 2681, 2982, +0, 2684, 2980, +0, 2688, 2977, +0, 2693, 2973, +0, 2700, 2967, +0, 2708, 2959, +0, 2720, 2948, +0, 2735, 2933, +0, 2754, 2912, +0, 2778, 2882, +0, 2808, 2840, +0, 2846, 2775, +0, 2893, 2672, +0, 2948, 2483, +0, 3013, 1950, +0, 3087, 0, +0, 3170, 0, +0, 3262, 0, +0, 3362, 0, +0, 3468, 0, +0, 3580, 0, +0, 3696, 0, +0, 2679, 3009, +0, 2679, 3009, +0, 2679, 3009, +0, 2680, 3008, +0, 2680, 3008, +0, 2680, 3008, +0, 2681, 3007, +0, 2682, 3007, +0, 2683, 3006, +0, 2685, 3004, +0, 2687, 3003, +0, 2690, 3000, +0, 2693, 2997, +0, 2698, 2993, +0, 2705, 2987, +0, 2714, 2980, +0, 2725, 2969, +0, 2739, 2955, +0, 2758, 2935, +0, 2782, 2907, +0, 2813, 2867, +0, 2850, 2807, +0, 2896, 2711, +0, 2951, 2541, +0, 3015, 2115, +0, 3089, 0, +0, 3172, 0, +0, 3264, 0, +0, 3363, 0, +0, 3469, 0, +0, 3581, 0, +0, 3697, 0, +1182, 2686, 3034, +1173, 2686, 3034, +1160, 2687, 3034, +1143, 2687, 3034, +1119, 2687, 3033, +1084, 2688, 3033, +1033, 2688, 3033, +955, 2689, 3032, +824, 2691, 3031, +554, 2692, 3030, +0, 2694, 3028, +0, 2697, 3026, +0, 2701, 3023, +0, 2706, 3019, +0, 2712, 3014, +0, 2720, 3007, +0, 2731, 2997, +0, 2746, 2983, +0, 2764, 2965, +0, 2788, 2939, +0, 2818, 2901, +0, 2855, 2846, +0, 2901, 2759, +0, 2955, 2608, +0, 3019, 2271, +0, 3092, 0, +0, 3175, 0, +0, 3266, 0, +0, 3365, 0, +0, 3470, 0, +0, 3582, 0, +0, 3697, 0, +2191, 2696, 3066, +2190, 2696, 3066, +2189, 2696, 3066, +2187, 2697, 3065, +2185, 2697, 3065, +2182, 2698, 3065, +2177, 2698, 3064, +2172, 2699, 3064, +2164, 2700, 3063, +2153, 2702, 3062, +2138, 2704, 3060, +2117, 2706, 3058, +2088, 2710, 3055, +2046, 2715, 3052, +1983, 2721, 3047, +1881, 2729, 3040, +1696, 2740, 3031, +1189, 2754, 3019, +0, 2773, 3001, +0, 2796, 2977, +0, 2825, 2943, +0, 2862, 2893, +0, 2907, 2815, +0, 2960, 2685, +0, 3023, 2419, +0, 3096, 0, +0, 3178, 0, +0, 3269, 0, +0, 3367, 0, +0, 3472, 0, +0, 3583, 0, +0, 3699, 0, +2548, 2709, 3105, +2548, 2709, 3105, +2547, 2709, 3105, +2546, 2709, 3105, +2545, 2710, 3104, +2544, 2710, 3104, +2542, 2711, 3104, +2539, 2712, 3103, +2536, 2713, 3102, +2531, 2714, 3101, +2524, 2716, 3100, +2516, 2719, 3098, +2504, 2722, 3095, +2487, 2727, 3092, +2464, 2733, 3088, +2432, 2741, 3082, +2384, 2752, 3073, +2311, 2766, 3062, +2191, 2783, 3046, +1956, 2806, 3025, +876, 2835, 2994, +0, 2871, 2949, +0, 2915, 2881, +0, 2967, 2771, +0, 3030, 2564, +0, 3101, 1888, +0, 3182, 0, +0, 3272, 0, +0, 3370, 0, +0, 3474, 0, +0, 3585, 0, +0, 3700, 0, +2796, 2725, 3153, +2796, 2725, 3152, +2796, 2725, 3152, +2795, 2726, 3152, +2795, 2726, 3152, +2794, 2726, 3152, +2793, 2727, 3151, +2791, 2728, 3151, +2789, 2729, 3150, +2787, 2730, 3149, +2783, 2732, 3148, +2778, 2735, 3146, +2771, 2738, 3144, +2762, 2743, 3141, +2750, 2749, 3137, +2733, 2756, 3131, +2709, 2767, 3124, +2675, 2780, 3114, +2625, 2797, 3100, +2548, 2819, 3081, +2419, 2847, 3054, +2157, 2882, 3015, +0, 2925, 2957, +0, 2977, 2865, +0, 3038, 2704, +0, 3108, 2323, +0, 3188, 0, +0, 3277, 0, +0, 3374, 0, +0, 3478, 0, +0, 3587, 0, +0, 3702, 0, +2999, 2746, 3209, +2999, 2746, 3209, +2999, 2746, 3209, +2999, 2747, 3209, +2998, 2747, 3209, +2998, 2747, 3209, +2997, 2748, 3208, +2996, 2749, 3208, +2995, 2750, 3207, +2993, 2751, 3206, +2991, 2753, 3205, +2988, 2755, 3204, +2984, 2759, 3202, +2978, 2763, 3199, +2970, 2769, 3196, +2960, 2776, 3191, +2945, 2786, 3184, +2925, 2799, 3175, +2897, 2815, 3163, +2857, 2837, 3147, +2796, 2864, 3123, +2699, 2897, 3090, +2527, 2939, 3041, +2089, 2989, 2967, +0, 3048, 2843, +0, 3118, 2597, +0, 3196, 1111, +0, 3283, 0, +0, 3379, 0, +0, 3482, 0, +0, 3590, 0, +0, 3704, 0, +3178, 2773, 3276, +3178, 2773, 3275, +3178, 2773, 3275, +3178, 2773, 3275, +3177, 2774, 3275, +3177, 2774, 3275, +3177, 2775, 3275, +3176, 2775, 3274, +3175, 2776, 3274, +3174, 2778, 3273, +3172, 2779, 3272, +3170, 2782, 3271, +3167, 2785, 3269, +3164, 2789, 3267, +3159, 2794, 3264, +3152, 2801, 3260, +3142, 2811, 3254, +3130, 2823, 3246, +3112, 2838, 3236, +3087, 2859, 3222, +3051, 2884, 3202, +2999, 2917, 3174, +2918, 2956, 3134, +2780, 3005, 3074, +2488, 3062, 2980, +0, 3130, 2811, +0, 3206, 2395, +0, 3292, 0, +0, 3386, 0, +0, 3487, 0, +0, 3595, 0, +0, 3708, 0, +3342, 2806, 3351, +3342, 2806, 3351, +3342, 2807, 3351, +3342, 2807, 3351, +3342, 2807, 3351, +3341, 2807, 3351, +3341, 2808, 3350, +3341, 2809, 3350, +3340, 2810, 3350, +3339, 2811, 3349, +3338, 2812, 3348, +3337, 2814, 3347, +3335, 2817, 3346, +3332, 2821, 3344, +3329, 2826, 3341, +3324, 2833, 3338, +3318, 2841, 3333, +3309, 2853, 3327, +3297, 2867, 3318, +3281, 2886, 3306, +3258, 2911, 3290, +3225, 2941, 3267, +3177, 2979, 3235, +3105, 3025, 3187, +2985, 3080, 3115, +2750, 3145, 2997, +1687, 3219, 2766, +0, 3303, 1775, +0, 3395, 0, +0, 3494, 0, +0, 3600, 0, +0, 3712, 0, +3497, 2847, 3436, +3497, 2848, 3436, +3497, 2848, 3436, +3497, 2848, 3436, +3496, 2848, 3436, +3496, 2849, 3436, +3496, 2849, 3436, +3496, 2850, 3435, +3495, 2850, 3435, +3495, 2852, 3434, +3494, 2853, 3434, +3493, 2855, 3433, +3492, 2858, 3432, +3490, 2861, 3430, +3487, 2866, 3428, +3484, 2872, 3425, +3479, 2880, 3421, +3473, 2890, 3416, +3465, 2904, 3409, +3454, 2921, 3399, +3438, 2944, 3386, +3417, 2972, 3368, +3386, 3008, 3342, +3341, 3051, 3305, +3274, 3103, 3250, +3165, 3165, 3165, +2960, 3236, 3019, +2308, 3317, 2696, +0, 3406, 0, +0, 3504, 0, +0, 3608, 0, +0, 3718, 0, +3645, 2897, 3529, +3645, 2897, 3529, +3645, 2898, 3529, +3645, 2898, 3529, +3645, 2898, 3529, +3645, 2898, 3529, +3644, 2899, 3529, +3644, 2899, 3529, +3644, 2900, 3528, +3644, 2901, 3528, +3643, 2902, 3527, +3642, 2904, 3527, +3641, 2906, 3526, +3640, 2909, 3524, +3638, 2914, 3523, +3636, 2919, 3520, +3633, 2926, 3517, +3628, 2936, 3513, +3622, 2948, 3507, +3614, 2964, 3500, +3604, 2984, 3489, +3589, 3011, 3474, +3568, 3043, 3454, +3539, 3084, 3426, +3496, 3132, 3384, +3432, 3191, 3322, +3330, 3258, 3224, +3143, 3335, 3046, +2623, 3421, 2582, +0, 3516, 0, +0, 3618, 0, +0, 3726, 0, +3789, 2956, 3630, +3789, 2956, 3630, +3789, 2957, 3630, +3789, 2957, 3630, +3789, 2957, 3630, +3789, 2957, 3630, +3788, 2958, 3630, +3788, 2958, 3630, +3788, 2959, 3629, +3788, 2960, 3629, +3787, 2961, 3629, +3787, 2962, 3628, +3786, 2964, 3627, +3785, 2967, 3626, +3784, 2971, 3625, +3782, 2976, 3623, +3780, 2982, 3620, +3777, 2990, 3617, +3772, 3001, 3613, +3767, 3015, 3606, +3759, 3034, 3598, +3748, 3057, 3587, +3734, 3087, 3571, +3714, 3124, 3549, +3685, 3169, 3518, +3644, 3222, 3473, +3583, 3286, 3404, +3485, 3359, 3292, +3309, 3441, 3081, +2855, 3532, 2365, +0, 3630, 0, +0, 3736, 0, +3929, 3025, 3737, +3929, 3025, 3737, +3929, 3025, 3737, +3929, 3025, 3737, +3929, 3026, 3737, +3929, 3026, 3737, +3929, 3026, 3737, +3929, 3026, 3737, +3929, 3027, 3737, +3929, 3028, 3736, +3928, 3029, 3736, +3928, 3030, 3736, +3927, 3032, 3735, +3927, 3034, 3734, +3926, 3037, 3733, +3925, 3042, 3732, +3923, 3047, 3730, +3921, 3054, 3727, +3918, 3064, 3723, +3913, 3076, 3719, +3908, 3092, 3712, +3900, 3113, 3703, +3890, 3139, 3691, +3876, 3172, 3674, +3856, 3213, 3651, +3828, 3262, 3618, +3788, 3320, 3569, +3728, 3388, 3494, +3634, 3466, 3370, +3465, 3552, 3123, +3050, 3647, 1588, +0, 3749, 0, +4068, 3103, 3850, +4068, 3103, 3850, +4068, 3103, 3850, +4068, 3103, 3850, +4068, 3104, 3850, +4068, 3104, 3850, +4068, 3104, 3850, +4068, 3104, 3849, +4067, 3105, 3849, +4067, 3105, 3849, +4067, 3106, 3849, +4067, 3107, 3849, +4066, 3109, 3848, +4066, 3111, 3847, +4065, 3114, 3847, +4064, 3117, 3845, +4063, 3122, 3844, +4061, 3128, 3842, +4059, 3136, 3839, +4056, 3147, 3835, +4052, 3160, 3830, +4046, 3178, 3823, +4039, 3201, 3814, +4029, 3230, 3801, +4015, 3266, 3784, +3995, 3310, 3759, +3968, 3363, 3724, +3929, 3425, 3672, +3870, 3497, 3592, +3778, 3578, 3457, +3615, 3668, 3174, +3224, 3766, 0, +4095, 3190, 3967, +4095, 3190, 3967, +4095, 3190, 3967, +4095, 3190, 3967, +4095, 3191, 3967, +4095, 3191, 3967, +4095, 3191, 3967, +4095, 3191, 3966, +4095, 3192, 3966, +4095, 3192, 3966, +4095, 3193, 3966, +4095, 3194, 3966, +4095, 3195, 3965, +4095, 3197, 3965, +4095, 3199, 3964, +4095, 3202, 3963, +4095, 3206, 3962, +4095, 3211, 3961, +4095, 3217, 3958, +4095, 3226, 3956, +4095, 3238, 3952, +4095, 3253, 3946, +4095, 3273, 3939, +4095, 3297, 3930, +4095, 3328, 3917, +4095, 3367, 3898, +4095, 3414, 3873, +4095, 3470, 3836, +4067, 3536, 3782, +4009, 3611, 3697, +3919, 3695, 3552, +3759, 3788, 3235, +4095, 3285, 4087, +4095, 3285, 4087, +4095, 3286, 4087, +4095, 3286, 4087, +4095, 3286, 4087, +4095, 3286, 4087, +4095, 3286, 4087, +4095, 3286, 4087, +4095, 3287, 4087, +4095, 3287, 4087, +4095, 3288, 4087, +4095, 3288, 4086, +4095, 3289, 4086, +4095, 3291, 4086, +4095, 3292, 4085, +4095, 3295, 4084, +4095, 3298, 4084, +4095, 3302, 4082, +4095, 3308, 4081, +4095, 3315, 4079, +4095, 3325, 4076, +4095, 3337, 4072, +4095, 3353, 4066, +4095, 3374, 4059, +4095, 3401, 4049, +4095, 3434, 4036, +4095, 3475, 4017, +4095, 3524, 3990, +4095, 3583, 3952, +4095, 3651, 3896, +4095, 3729, 3808, +4057, 3815, 3655, +0, 2788, 3057, +0, 2789, 3057, +0, 2789, 3057, +0, 2789, 3057, +0, 2789, 3057, +0, 2790, 3056, +0, 2790, 3056, +0, 2791, 3055, +0, 2792, 3054, +0, 2793, 3053, +0, 2795, 3052, +0, 2797, 3050, +0, 2800, 3047, +0, 2804, 3043, +0, 2809, 3038, +0, 2816, 3031, +0, 2825, 3022, +0, 2837, 3009, +0, 2852, 2992, +0, 2872, 2967, +0, 2897, 2932, +0, 2928, 2880, +0, 2967, 2801, +0, 3014, 2666, +0, 3071, 2384, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2788, 3058, +0, 2789, 3058, +0, 2789, 3057, +0, 2789, 3057, +0, 2789, 3057, +0, 2790, 3057, +0, 2790, 3056, +0, 2791, 3055, +0, 2792, 3055, +0, 2793, 3053, +0, 2795, 3052, +0, 2797, 3050, +0, 2800, 3047, +0, 2804, 3043, +0, 2809, 3038, +0, 2816, 3032, +0, 2825, 3022, +0, 2837, 3010, +0, 2852, 2992, +0, 2872, 2967, +0, 2897, 2932, +0, 2928, 2881, +0, 2967, 2801, +0, 3014, 2666, +0, 3071, 2385, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2788, 3058, +0, 2789, 3058, +0, 2789, 3058, +0, 2789, 3057, +0, 2789, 3057, +0, 2790, 3057, +0, 2790, 3056, +0, 2791, 3056, +0, 2792, 3055, +0, 2793, 3054, +0, 2795, 3052, +0, 2797, 3050, +0, 2800, 3047, +0, 2804, 3044, +0, 2809, 3039, +0, 2816, 3032, +0, 2825, 3023, +0, 2837, 3010, +0, 2852, 2992, +0, 2872, 2968, +0, 2897, 2933, +0, 2928, 2881, +0, 2967, 2801, +0, 3014, 2667, +0, 3071, 2386, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2789, 3058, +0, 2789, 3058, +0, 2789, 3058, +0, 2789, 3058, +0, 2789, 3057, +0, 2790, 3057, +0, 2790, 3057, +0, 2791, 3056, +0, 2792, 3055, +0, 2793, 3054, +0, 2795, 3052, +0, 2797, 3050, +0, 2800, 3048, +0, 2804, 3044, +0, 2809, 3039, +0, 2816, 3032, +0, 2825, 3023, +0, 2837, 3010, +0, 2852, 2993, +0, 2872, 2968, +0, 2897, 2933, +0, 2928, 2881, +0, 2967, 2802, +0, 3014, 2667, +0, 3071, 2387, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2789, 3059, +0, 2789, 3058, +0, 2789, 3058, +0, 2789, 3058, +0, 2789, 3058, +0, 2790, 3058, +0, 2790, 3057, +0, 2791, 3056, +0, 2792, 3056, +0, 2793, 3054, +0, 2795, 3053, +0, 2797, 3051, +0, 2800, 3048, +0, 2804, 3044, +0, 2809, 3039, +0, 2816, 3033, +0, 2825, 3023, +0, 2837, 3011, +0, 2852, 2993, +0, 2872, 2969, +0, 2897, 2934, +0, 2928, 2882, +0, 2967, 2802, +0, 3014, 2668, +0, 3071, 2389, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2789, 3059, +0, 2789, 3059, +0, 2789, 3059, +0, 2789, 3059, +0, 2790, 3058, +0, 2790, 3058, +0, 2791, 3058, +0, 2791, 3057, +0, 2792, 3056, +0, 2793, 3055, +0, 2795, 3053, +0, 2797, 3051, +0, 2800, 3049, +0, 2804, 3045, +0, 2809, 3040, +0, 2816, 3033, +0, 2825, 3024, +0, 2837, 3011, +0, 2852, 2994, +0, 2872, 2969, +0, 2897, 2934, +0, 2928, 2883, +0, 2967, 2803, +0, 3014, 2670, +0, 3071, 2391, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2789, 3060, +0, 2789, 3060, +0, 2789, 3060, +0, 2789, 3059, +0, 2790, 3059, +0, 2790, 3059, +0, 2791, 3058, +0, 2791, 3058, +0, 2792, 3057, +0, 2794, 3056, +0, 2795, 3054, +0, 2797, 3052, +0, 2800, 3049, +0, 2804, 3046, +0, 2810, 3041, +0, 2816, 3034, +0, 2825, 3025, +0, 2837, 3012, +0, 2852, 2995, +0, 2872, 2970, +0, 2897, 2935, +0, 2928, 2884, +0, 2967, 2805, +0, 3015, 2671, +0, 3071, 2394, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3490, 0, +0, 3597, 0, +0, 3710, 0, +0, 2789, 3061, +0, 2789, 3061, +0, 2789, 3061, +0, 2790, 3060, +0, 2790, 3060, +0, 2790, 3060, +0, 2791, 3059, +0, 2792, 3059, +0, 2793, 3058, +0, 2794, 3057, +0, 2795, 3055, +0, 2798, 3053, +0, 2801, 3050, +0, 2805, 3047, +0, 2810, 3042, +0, 2817, 3035, +0, 2826, 3026, +0, 2837, 3013, +0, 2853, 2996, +0, 2872, 2971, +0, 2897, 2936, +0, 2929, 2885, +0, 2967, 2806, +0, 3015, 2673, +0, 3071, 2398, +0, 3137, 0, +0, 3212, 0, +0, 3297, 0, +0, 3390, 0, +0, 3491, 0, +0, 3597, 0, +0, 3710, 0, +0, 2790, 3062, +0, 2790, 3062, +0, 2790, 3062, +0, 2790, 3062, +0, 2790, 3061, +0, 2791, 3061, +0, 2791, 3060, +0, 2792, 3060, +0, 2793, 3059, +0, 2794, 3058, +0, 2796, 3056, +0, 2798, 3054, +0, 2801, 3052, +0, 2805, 3048, +0, 2810, 3043, +0, 2817, 3036, +0, 2826, 3027, +0, 2838, 3014, +0, 2853, 2997, +0, 2872, 2973, +0, 2897, 2938, +0, 2929, 2887, +0, 2968, 2809, +0, 3015, 2676, +0, 3071, 2404, +0, 3137, 0, +0, 3213, 0, +0, 3297, 0, +0, 3390, 0, +0, 3491, 0, +0, 3598, 0, +0, 3710, 0, +0, 2790, 3064, +0, 2790, 3064, +0, 2790, 3063, +0, 2790, 3063, +0, 2791, 3063, +0, 2791, 3063, +0, 2792, 3062, +0, 2792, 3062, +0, 2793, 3061, +0, 2795, 3060, +0, 2796, 3058, +0, 2798, 3056, +0, 2801, 3053, +0, 2805, 3050, +0, 2810, 3045, +0, 2817, 3038, +0, 2826, 3029, +0, 2838, 3016, +0, 2853, 2999, +0, 2873, 2975, +0, 2898, 2940, +0, 2929, 2890, +0, 2968, 2811, +0, 3015, 2680, +0, 3072, 2411, +0, 3137, 0, +0, 3213, 0, +0, 3297, 0, +0, 3390, 0, +0, 3491, 0, +0, 3598, 0, +0, 3710, 0, +0, 2791, 3066, +0, 2791, 3066, +0, 2791, 3066, +0, 2791, 3065, +0, 2791, 3065, +0, 2792, 3065, +0, 2792, 3064, +0, 2793, 3064, +0, 2794, 3063, +0, 2795, 3062, +0, 2797, 3060, +0, 2799, 3058, +0, 2802, 3056, +0, 2806, 3052, +0, 2811, 3047, +0, 2818, 3040, +0, 2827, 3031, +0, 2838, 3019, +0, 2854, 3002, +0, 2873, 2978, +0, 2898, 2943, +0, 2930, 2893, +0, 2968, 2815, +0, 3016, 2685, +0, 3072, 2420, +0, 3138, 0, +0, 3213, 0, +0, 3297, 0, +0, 3390, 0, +0, 3491, 0, +0, 3598, 0, +0, 3710, 0, +0, 2791, 3069, +0, 2791, 3069, +0, 2792, 3069, +0, 2792, 3068, +0, 2792, 3068, +0, 2792, 3068, +0, 2793, 3067, +0, 2794, 3067, +0, 2795, 3066, +0, 2796, 3065, +0, 2798, 3063, +0, 2800, 3061, +0, 2803, 3059, +0, 2807, 3055, +0, 2812, 3050, +0, 2819, 3043, +0, 2827, 3034, +0, 2839, 3022, +0, 2854, 3005, +0, 2874, 2981, +0, 2899, 2947, +0, 2930, 2897, +0, 2969, 2821, +0, 3016, 2692, +0, 3072, 2432, +0, 3138, 0, +0, 3213, 0, +0, 3298, 0, +0, 3391, 0, +0, 3491, 0, +0, 3598, 0, +0, 3710, 0, +0, 2792, 3073, +0, 2792, 3073, +0, 2793, 3073, +0, 2793, 3072, +0, 2793, 3072, +0, 2793, 3072, +0, 2794, 3071, +0, 2795, 3071, +0, 2796, 3070, +0, 2797, 3069, +0, 2799, 3067, +0, 2801, 3065, +0, 2804, 3063, +0, 2808, 3059, +0, 2813, 3054, +0, 2819, 3048, +0, 2828, 3039, +0, 2840, 3026, +0, 2855, 3010, +0, 2875, 2986, +0, 2900, 2952, +0, 2931, 2903, +0, 2970, 2827, +0, 3017, 2701, +0, 3073, 2448, +0, 3138, 0, +0, 3214, 0, +0, 3298, 0, +0, 3391, 0, +0, 3491, 0, +0, 3598, 0, +0, 3710, 0, +0, 2794, 3078, +0, 2794, 3078, +0, 2794, 3078, +0, 2794, 3078, +0, 2794, 3077, +0, 2795, 3077, +0, 2795, 3077, +0, 2796, 3076, +0, 2797, 3075, +0, 2798, 3074, +0, 2800, 3073, +0, 2802, 3071, +0, 2805, 3068, +0, 2809, 3064, +0, 2814, 3060, +0, 2821, 3053, +0, 2830, 3044, +0, 2841, 3032, +0, 2856, 3016, +0, 2876, 2992, +0, 2901, 2959, +0, 2932, 2911, +0, 2970, 2836, +0, 3017, 2713, +0, 3074, 2468, +0, 3139, 1070, +0, 3214, 0, +0, 3298, 0, +0, 3391, 0, +0, 3491, 0, +0, 3598, 0, +0, 3710, 0, +0, 2795, 3085, +0, 2796, 3085, +0, 2796, 3085, +0, 2796, 3085, +0, 2796, 3084, +0, 2797, 3084, +0, 2797, 3084, +0, 2798, 3083, +0, 2799, 3082, +0, 2800, 3081, +0, 2802, 3080, +0, 2804, 3078, +0, 2807, 3075, +0, 2811, 3072, +0, 2816, 3067, +0, 2822, 3060, +0, 2831, 3052, +0, 2843, 3040, +0, 2858, 3023, +0, 2877, 3001, +0, 2902, 2968, +0, 2933, 2920, +0, 2972, 2848, +0, 3019, 2728, +0, 3075, 2494, +0, 3140, 1443, +0, 3215, 0, +0, 3299, 0, +0, 3392, 0, +0, 3492, 0, +0, 3599, 0, +0, 3711, 0, +0, 2798, 3094, +0, 2798, 3094, +0, 2798, 3094, +0, 2798, 3094, +0, 2799, 3093, +0, 2799, 3093, +0, 2800, 3093, +0, 2800, 3092, +0, 2801, 3091, +0, 2802, 3090, +0, 2804, 3089, +0, 2806, 3087, +0, 2809, 3084, +0, 2813, 3081, +0, 2818, 3076, +0, 2825, 3070, +0, 2834, 3062, +0, 2845, 3050, +0, 2860, 3034, +0, 2879, 3011, +0, 2904, 2980, +0, 2935, 2933, +0, 2973, 2863, +0, 3020, 2748, +0, 3076, 2527, +0, 3141, 1697, +0, 3216, 0, +0, 3300, 0, +0, 3392, 0, +0, 3492, 0, +0, 3599, 0, +0, 3711, 0, +0, 2801, 3106, +0, 2801, 3106, +0, 2801, 3106, +0, 2802, 3106, +0, 2802, 3105, +0, 2802, 3105, +0, 2803, 3105, +0, 2803, 3104, +0, 2804, 3103, +0, 2806, 3102, +0, 2807, 3101, +0, 2809, 3099, +0, 2812, 3096, +0, 2816, 3093, +0, 2821, 3089, +0, 2828, 3083, +0, 2837, 3074, +0, 2848, 3063, +0, 2863, 3047, +0, 2882, 3026, +0, 2907, 2995, +0, 2937, 2950, +0, 2976, 2883, +0, 3022, 2773, +0, 3078, 2567, +0, 3143, 1902, +0, 3217, 0, +0, 3301, 0, +0, 3393, 0, +0, 3493, 0, +0, 3599, 0, +0, 3711, 0, +0, 2805, 3121, +0, 2805, 3121, +0, 2806, 3121, +0, 2806, 3121, +0, 2806, 3121, +0, 2806, 3120, +0, 2807, 3120, +0, 2808, 3119, +0, 2809, 3119, +0, 2810, 3118, +0, 2811, 3116, +0, 2814, 3115, +0, 2816, 3112, +0, 2820, 3109, +0, 2825, 3105, +0, 2832, 3099, +0, 2840, 3091, +0, 2852, 3080, +0, 2867, 3065, +0, 2886, 3044, +0, 2910, 3014, +0, 2940, 2972, +0, 2978, 2908, +0, 3025, 2805, +0, 3080, 2615, +0, 3145, 2083, +0, 3219, 0, +0, 3302, 0, +0, 3394, 0, +0, 3494, 0, +0, 3600, 0, +0, 3712, 0, +0, 2811, 3141, +0, 2811, 3141, +0, 2811, 3141, +0, 2811, 3141, +0, 2812, 3141, +0, 2812, 3140, +0, 2813, 3140, +0, 2813, 3139, +0, 2814, 3139, +0, 2815, 3138, +0, 2817, 3136, +0, 2819, 3135, +0, 2822, 3132, +0, 2826, 3129, +0, 2831, 3125, +0, 2837, 3120, +0, 2846, 3112, +0, 2857, 3101, +0, 2872, 3087, +0, 2890, 3067, +0, 2914, 3039, +0, 2945, 2999, +0, 2982, 2939, +0, 3028, 2843, +0, 3083, 2673, +0, 3147, 2248, +0, 3221, 0, +0, 3304, 0, +0, 3396, 0, +0, 3495, 0, +0, 3601, 0, +0, 3713, 0, +1321, 2818, 3166, +1314, 2818, 3166, +1305, 2819, 3166, +1292, 2819, 3166, +1275, 2819, 3166, +1251, 2819, 3165, +1216, 2820, 3165, +1165, 2821, 3165, +1087, 2821, 3164, +956, 2823, 3163, +686, 2824, 3162, +0, 2826, 3160, +0, 2829, 3158, +0, 2833, 3155, +0, 2838, 3151, +0, 2844, 3146, +0, 2853, 3139, +0, 2864, 3129, +0, 2878, 3115, +0, 2897, 3097, +0, 2920, 3071, +0, 2950, 3033, +0, 2987, 2978, +0, 3033, 2891, +0, 3087, 2740, +0, 3151, 2403, +0, 3224, 0, +0, 3307, 0, +0, 3398, 0, +0, 3497, 0, +0, 3603, 0, +0, 3714, 0, +2324, 2828, 3198, +2323, 2828, 3198, +2322, 2828, 3198, +2321, 2828, 3198, +2319, 2829, 3197, +2317, 2829, 3197, +2314, 2830, 3197, +2309, 2830, 3196, +2304, 2831, 3196, +2296, 2832, 3195, +2285, 2834, 3194, +2270, 2836, 3192, +2249, 2839, 3190, +2220, 2842, 3188, +2178, 2847, 3184, +2115, 2853, 3179, +2013, 2862, 3172, +1828, 2872, 3163, +1321, 2887, 3151, +0, 2905, 3134, +0, 2928, 3109, +0, 2957, 3075, +0, 2994, 3025, +0, 3039, 2947, +0, 3092, 2817, +0, 3156, 2552, +0, 3228, 0, +0, 3310, 0, +0, 3401, 0, +0, 3499, 0, +0, 3604, 0, +0, 3715, 0, +2680, 2841, 3237, +2680, 2841, 3237, +2680, 2841, 3237, +2679, 2841, 3237, +2678, 2841, 3237, +2677, 2842, 3236, +2676, 2842, 3236, +2674, 2843, 3236, +2671, 2844, 3235, +2668, 2845, 3234, +2663, 2846, 3233, +2657, 2848, 3232, +2648, 2851, 3230, +2636, 2854, 3228, +2620, 2859, 3224, +2597, 2865, 3220, +2564, 2873, 3214, +2516, 2884, 3205, +2444, 2898, 3194, +2324, 2915, 3178, +2088, 2938, 3157, +1008, 2967, 3126, +0, 3003, 3081, +0, 3047, 3013, +0, 3100, 2903, +0, 3162, 2696, +0, 3233, 2020, +0, 3315, 0, +0, 3404, 0, +0, 3502, 0, +0, 3607, 0, +0, 3717, 0, +2929, 2857, 3285, +2929, 2857, 3285, +2928, 2857, 3285, +2928, 2858, 3284, +2927, 2858, 3284, +2927, 2858, 3284, +2926, 2859, 3284, +2925, 2859, 3283, +2923, 2860, 3283, +2921, 2861, 3282, +2919, 2863, 3281, +2915, 2864, 3280, +2910, 2867, 3278, +2903, 2870, 3276, +2894, 2875, 3273, +2882, 2881, 3269, +2865, 2889, 3264, +2841, 2899, 3256, +2807, 2912, 3246, +2757, 2929, 3232, +2680, 2952, 3213, +2551, 2980, 3186, +2289, 3014, 3147, +0, 3057, 3089, +0, 3109, 2997, +0, 3170, 2837, +0, 3240, 2456, +0, 3320, 0, +0, 3409, 0, +0, 3506, 0, +0, 3610, 0, +0, 3719, 0, +3132, 2878, 3341, +3132, 2878, 3341, +3131, 2878, 3341, +3131, 2879, 3341, +3131, 2879, 3341, +3130, 2879, 3341, +3130, 2880, 3341, +3129, 2880, 3340, +3128, 2881, 3340, +3127, 2882, 3339, +3125, 2883, 3338, +3123, 2885, 3337, +3120, 2888, 3336, +3116, 2891, 3334, +3110, 2895, 3331, +3102, 2901, 3328, +3092, 2908, 3323, +3077, 2918, 3316, +3057, 2931, 3307, +3029, 2947, 3295, +2989, 2969, 3279, +2928, 2996, 3255, +2832, 3029, 3222, +2659, 3071, 3173, +2222, 3121, 3099, +0, 3181, 2975, +0, 3250, 2729, +0, 3328, 1243, +0, 3415, 0, +0, 3511, 0, +0, 3614, 0, +0, 3723, 0, +3310, 2905, 3408, +3310, 2905, 3408, +3310, 2905, 3408, +3310, 2905, 3407, +3310, 2906, 3407, +3309, 2906, 3407, +3309, 2906, 3407, +3309, 2907, 3407, +3308, 2907, 3406, +3307, 2908, 3406, +3306, 2910, 3405, +3304, 2911, 3404, +3302, 2914, 3403, +3300, 2917, 3401, +3296, 2921, 3399, +3291, 2926, 3396, +3284, 2933, 3392, +3274, 2943, 3386, +3262, 2955, 3378, +3244, 2970, 3368, +3219, 2991, 3354, +3183, 3016, 3334, +3131, 3049, 3306, +3050, 3089, 3266, +2912, 3137, 3207, +2620, 3195, 3112, +0, 3262, 2944, +0, 3338, 2528, +0, 3424, 0, +0, 3518, 0, +0, 3619, 0, +0, 3727, 0, +3474, 2938, 3483, +3474, 2938, 3483, +3474, 2939, 3483, +3474, 2939, 3483, +3474, 2939, 3483, +3474, 2939, 3483, +3474, 2940, 3483, +3473, 2940, 3483, +3473, 2941, 3482, +3472, 2942, 3482, +3471, 2943, 3481, +3470, 2944, 3480, +3469, 2947, 3479, +3467, 2949, 3478, +3464, 2953, 3476, +3461, 2958, 3473, +3456, 2965, 3470, +3450, 2973, 3465, +3441, 2985, 3459, +3429, 3000, 3450, +3413, 3019, 3438, +3390, 3043, 3422, +3357, 3073, 3399, +3310, 3111, 3367, +3237, 3157, 3320, +3117, 3213, 3248, +2883, 3277, 3129, +1820, 3351, 2898, +0, 3435, 1907, +0, 3527, 0, +0, 3626, 0, +0, 3732, 0, +3629, 2980, 3568, +3629, 2980, 3568, +3629, 2980, 3568, +3629, 2980, 3568, +3629, 2980, 3568, +3629, 2980, 3568, +3628, 2981, 3568, +3628, 2981, 3568, +3628, 2982, 3567, +3627, 2983, 3567, +3627, 2984, 3566, +3626, 2985, 3566, +3625, 2987, 3565, +3624, 2990, 3564, +3622, 2993, 3562, +3619, 2998, 3560, +3616, 3004, 3557, +3612, 3012, 3553, +3605, 3022, 3548, +3597, 3036, 3541, +3586, 3053, 3531, +3570, 3076, 3518, +3549, 3104, 3500, +3518, 3140, 3474, +3474, 3183, 3437, +3406, 3235, 3382, +3297, 3297, 3297, +3092, 3368, 3151, +2441, 3449, 2828, +0, 3538, 0, +0, 3636, 0, +0, 3740, 0, +3777, 3029, 3662, +3777, 3029, 3662, +3777, 3030, 3662, +3777, 3030, 3661, +3777, 3030, 3661, +3777, 3030, 3661, +3777, 3030, 3661, +3777, 3031, 3661, +3776, 3031, 3661, +3776, 3032, 3660, +3776, 3033, 3660, +3775, 3034, 3660, +3774, 3036, 3659, +3773, 3038, 3658, +3772, 3042, 3657, +3770, 3046, 3655, +3768, 3051, 3652, +3765, 3058, 3649, +3760, 3068, 3645, +3754, 3080, 3639, +3747, 3096, 3632, +3736, 3117, 3621, +3721, 3143, 3606, +3700, 3175, 3586, +3671, 3216, 3558, +3628, 3265, 3516, +3564, 3323, 3455, +3462, 3390, 3356, +3275, 3467, 3178, +2755, 3554, 2715, +0, 3648, 0, +0, 3750, 0, +3921, 3088, 3762, +3921, 3088, 3762, +3921, 3089, 3762, +3921, 3089, 3762, +3921, 3089, 3762, +3921, 3089, 3762, +3921, 3089, 3762, +3921, 3090, 3762, +3920, 3090, 3762, +3920, 3091, 3761, +3920, 3092, 3761, +3919, 3093, 3761, +3919, 3094, 3760, +3918, 3096, 3759, +3917, 3099, 3758, +3916, 3103, 3757, +3914, 3108, 3755, +3912, 3114, 3753, +3909, 3122, 3749, +3905, 3133, 3745, +3899, 3148, 3738, +3891, 3166, 3730, +3881, 3189, 3719, +3866, 3219, 3703, +3846, 3256, 3681, +3817, 3301, 3650, +3776, 3355, 3605, +3715, 3418, 3536, +3617, 3491, 3424, +3441, 3573, 3213, +2987, 3664, 2497, +0, 3762, 0, +4062, 3157, 3869, +4062, 3157, 3869, +4062, 3157, 3869, +4062, 3157, 3869, +4062, 3157, 3869, +4061, 3158, 3869, +4061, 3158, 3869, +4061, 3158, 3869, +4061, 3159, 3869, +4061, 3159, 3869, +4061, 3160, 3869, +4060, 3161, 3868, +4060, 3162, 3868, +4060, 3164, 3867, +4059, 3166, 3866, +4058, 3169, 3865, +4057, 3174, 3864, +4055, 3179, 3862, +4053, 3186, 3859, +4050, 3196, 3856, +4045, 3208, 3851, +4040, 3224, 3844, +4032, 3245, 3835, +4022, 3271, 3823, +4008, 3304, 3806, +3988, 3345, 3783, +3960, 3394, 3750, +3920, 3452, 3701, +3860, 3520, 3626, +3766, 3598, 3502, +3598, 3684, 3255, +3182, 3779, 1720, +4095, 3235, 3982, +4095, 3235, 3982, +4095, 3235, 3982, +4095, 3235, 3982, +4095, 3235, 3982, +4095, 3236, 3982, +4095, 3236, 3982, +4095, 3236, 3982, +4095, 3236, 3982, +4095, 3237, 3981, +4095, 3238, 3981, +4095, 3238, 3981, +4095, 3239, 3981, +4095, 3241, 3980, +4095, 3243, 3979, +4095, 3246, 3979, +4095, 3249, 3978, +4095, 3254, 3976, +4095, 3260, 3974, +4095, 3268, 3971, +4095, 3279, 3967, +4095, 3293, 3962, +4095, 3310, 3956, +4095, 3333, 3946, +4095, 3362, 3934, +4095, 3398, 3916, +4095, 3442, 3891, +4095, 3495, 3856, +4061, 3557, 3804, +4002, 3629, 3724, +3910, 3710, 3589, +3747, 3800, 3306, +4095, 3322, 4095, +4095, 3322, 4095, +4095, 3322, 4095, +4095, 3322, 4095, +4095, 3322, 4095, +4095, 3323, 4095, +4095, 3323, 4095, +4095, 3323, 4095, +4095, 3323, 4095, +4095, 3324, 4095, +4095, 3324, 4095, +4095, 3325, 4095, +4095, 3326, 4095, +4095, 3327, 4095, +4095, 3329, 4095, +4095, 3331, 4095, +4095, 3334, 4095, +4095, 3338, 4094, +4095, 3343, 4093, +4095, 3350, 4090, +4095, 3358, 4088, +4095, 3370, 4084, +4095, 3385, 4079, +4095, 3405, 4071, +4095, 3429, 4062, +4095, 3461, 4049, +4095, 3499, 4030, +4095, 3546, 4005, +4095, 3602, 3968, +4095, 3668, 3914, +4095, 3743, 3829, +4051, 3827, 3684, +0, 2920, 3190, +0, 2920, 3189, +0, 2921, 3189, +0, 2921, 3189, +0, 2921, 3189, +0, 2921, 3189, +0, 2922, 3188, +0, 2922, 3188, +0, 2923, 3187, +0, 2924, 3186, +0, 2925, 3185, +0, 2927, 3184, +0, 2929, 3182, +0, 2932, 3179, +0, 2936, 3175, +0, 2941, 3170, +0, 2948, 3163, +0, 2957, 3154, +0, 2969, 3141, +0, 2984, 3124, +0, 3004, 3099, +0, 3029, 3064, +0, 3060, 3012, +0, 3099, 2932, +0, 3146, 2798, +0, 3203, 2515, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3622, 0, +0, 3729, 0, +0, 2920, 3190, +0, 2920, 3190, +0, 2921, 3189, +0, 2921, 3189, +0, 2921, 3189, +0, 2921, 3189, +0, 2922, 3189, +0, 2922, 3188, +0, 2923, 3187, +0, 2924, 3187, +0, 2925, 3185, +0, 2927, 3184, +0, 2929, 3182, +0, 2932, 3179, +0, 2936, 3175, +0, 2941, 3170, +0, 2948, 3163, +0, 2957, 3154, +0, 2969, 3142, +0, 2984, 3124, +0, 3004, 3099, +0, 3029, 3064, +0, 3060, 3013, +0, 3099, 2933, +0, 3146, 2798, +0, 3203, 2516, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3622, 0, +0, 3729, 0, +0, 2920, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3189, +0, 2921, 3189, +0, 2921, 3189, +0, 2922, 3189, +0, 2922, 3188, +0, 2923, 3188, +0, 2924, 3187, +0, 2925, 3186, +0, 2927, 3184, +0, 2929, 3182, +0, 2932, 3179, +0, 2936, 3176, +0, 2941, 3170, +0, 2948, 3164, +0, 2957, 3154, +0, 2969, 3142, +0, 2984, 3124, +0, 3004, 3100, +0, 3029, 3064, +0, 3060, 3013, +0, 3099, 2933, +0, 3146, 2798, +0, 3203, 2517, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3622, 0, +0, 3729, 0, +0, 2920, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3189, +0, 2922, 3189, +0, 2922, 3188, +0, 2923, 3188, +0, 2924, 3187, +0, 2925, 3186, +0, 2927, 3184, +0, 2929, 3182, +0, 2932, 3179, +0, 2936, 3176, +0, 2941, 3171, +0, 2948, 3164, +0, 2957, 3155, +0, 2969, 3142, +0, 2984, 3124, +0, 3004, 3100, +0, 3029, 3065, +0, 3060, 3013, +0, 3099, 2933, +0, 3146, 2799, +0, 3203, 2518, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3622, 0, +0, 3729, 0, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2921, 3190, +0, 2922, 3189, +0, 2922, 3189, +0, 2923, 3188, +0, 2924, 3187, +0, 2925, 3186, +0, 2927, 3185, +0, 2929, 3183, +0, 2932, 3180, +0, 2936, 3176, +0, 2941, 3171, +0, 2948, 3164, +0, 2957, 3155, +0, 2969, 3142, +0, 2984, 3125, +0, 3004, 3100, +0, 3029, 3065, +0, 3060, 3014, +0, 3099, 2934, +0, 3146, 2799, +0, 3203, 2519, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3622, 0, +0, 3729, 0, +0, 2921, 3191, +0, 2921, 3191, +0, 2921, 3191, +0, 2921, 3190, +0, 2921, 3190, +0, 2922, 3190, +0, 2922, 3190, +0, 2922, 3189, +0, 2923, 3188, +0, 2924, 3188, +0, 2925, 3187, +0, 2927, 3185, +0, 2929, 3183, +0, 2932, 3180, +0, 2936, 3176, +0, 2941, 3171, +0, 2948, 3165, +0, 2957, 3155, +0, 2969, 3143, +0, 2984, 3125, +0, 3004, 3101, +0, 3029, 3066, +0, 3060, 3014, +0, 3099, 2935, +0, 3146, 2800, +0, 3203, 2521, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3622, 0, +0, 3729, 0, +0, 2921, 3191, +0, 2921, 3191, +0, 2921, 3191, +0, 2921, 3191, +0, 2921, 3191, +0, 2922, 3190, +0, 2922, 3190, +0, 2923, 3190, +0, 2923, 3189, +0, 2924, 3188, +0, 2925, 3187, +0, 2927, 3186, +0, 2929, 3183, +0, 2932, 3181, +0, 2936, 3177, +0, 2941, 3172, +0, 2948, 3165, +0, 2957, 3156, +0, 2969, 3143, +0, 2984, 3126, +0, 3004, 3101, +0, 3029, 3066, +0, 3060, 3015, +0, 3099, 2936, +0, 3147, 2802, +0, 3203, 2523, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3623, 0, +0, 3729, 0, +0, 2921, 3192, +0, 2921, 3192, +0, 2921, 3192, +0, 2921, 3192, +0, 2922, 3191, +0, 2922, 3191, +0, 2922, 3191, +0, 2923, 3190, +0, 2923, 3190, +0, 2924, 3189, +0, 2926, 3188, +0, 2927, 3186, +0, 2930, 3184, +0, 2933, 3181, +0, 2936, 3178, +0, 2942, 3173, +0, 2948, 3166, +0, 2957, 3157, +0, 2969, 3144, +0, 2984, 3127, +0, 3004, 3102, +0, 3029, 3067, +0, 3061, 3016, +0, 3099, 2937, +0, 3147, 2803, +0, 3203, 2526, +0, 3269, 0, +0, 3344, 0, +0, 3429, 0, +0, 3522, 0, +0, 3623, 0, +0, 3730, 0, +0, 2921, 3193, +0, 2921, 3193, +0, 2921, 3193, +0, 2922, 3193, +0, 2922, 3192, +0, 2922, 3192, +0, 2922, 3192, +0, 2923, 3191, +0, 2924, 3191, +0, 2925, 3190, +0, 2926, 3189, +0, 2928, 3187, +0, 2930, 3185, +0, 2933, 3182, +0, 2937, 3179, +0, 2942, 3174, +0, 2949, 3167, +0, 2958, 3158, +0, 2969, 3145, +0, 2985, 3128, +0, 3004, 3103, +0, 3029, 3069, +0, 3061, 3017, +0, 3100, 2938, +0, 3147, 2806, +0, 3203, 2530, +0, 3269, 0, +0, 3345, 0, +0, 3429, 0, +0, 3522, 0, +0, 3623, 0, +0, 3730, 0, +0, 2922, 3194, +0, 2922, 3194, +0, 2922, 3194, +0, 2922, 3194, +0, 2922, 3194, +0, 2922, 3193, +0, 2923, 3193, +0, 2923, 3193, +0, 2924, 3192, +0, 2925, 3191, +0, 2926, 3190, +0, 2928, 3188, +0, 2930, 3186, +0, 2933, 3184, +0, 2937, 3180, +0, 2942, 3175, +0, 2949, 3168, +0, 2958, 3159, +0, 2970, 3147, +0, 2985, 3129, +0, 3005, 3105, +0, 3030, 3070, +0, 3061, 3019, +0, 3100, 2941, +0, 3147, 2808, +0, 3203, 2536, +0, 3269, 0, +0, 3345, 0, +0, 3429, 0, +0, 3522, 0, +0, 3623, 0, +0, 3730, 0, +0, 2922, 3196, +0, 2922, 3196, +0, 2922, 3196, +0, 2922, 3196, +0, 2923, 3195, +0, 2923, 3195, +0, 2923, 3195, +0, 2924, 3194, +0, 2924, 3194, +0, 2925, 3193, +0, 2927, 3192, +0, 2928, 3190, +0, 2931, 3188, +0, 2933, 3185, +0, 2937, 3182, +0, 2943, 3177, +0, 2949, 3170, +0, 2958, 3161, +0, 2970, 3148, +0, 2985, 3131, +0, 3005, 3107, +0, 3030, 3072, +0, 3061, 3022, +0, 3100, 2944, +0, 3147, 2812, +0, 3204, 2543, +0, 3269, 0, +0, 3345, 0, +0, 3429, 0, +0, 3522, 0, +0, 3623, 0, +0, 3730, 0, +0, 2923, 3198, +0, 2923, 3198, +0, 2923, 3198, +0, 2923, 3198, +0, 2923, 3198, +0, 2923, 3197, +0, 2924, 3197, +0, 2924, 3197, +0, 2925, 3196, +0, 2926, 3195, +0, 2927, 3194, +0, 2929, 3192, +0, 2931, 3190, +0, 2934, 3188, +0, 2938, 3184, +0, 2943, 3179, +0, 2950, 3172, +0, 2959, 3163, +0, 2971, 3151, +0, 2986, 3134, +0, 3005, 3110, +0, 3030, 3075, +0, 3062, 3025, +0, 3100, 2947, +0, 3148, 2818, +0, 3204, 2552, +0, 3270, 0, +0, 3345, 0, +0, 3430, 0, +0, 3522, 0, +0, 3623, 0, +0, 3730, 0, +0, 2923, 3201, +0, 2923, 3201, +0, 2924, 3201, +0, 2924, 3201, +0, 2924, 3201, +0, 2924, 3200, +0, 2925, 3200, +0, 2925, 3200, +0, 2926, 3199, +0, 2927, 3198, +0, 2928, 3197, +0, 2930, 3195, +0, 2932, 3193, +0, 2935, 3191, +0, 2939, 3187, +0, 2944, 3182, +0, 2951, 3176, +0, 2960, 3167, +0, 2971, 3154, +0, 2986, 3137, +0, 3006, 3113, +0, 3031, 3079, +0, 3062, 3029, +0, 3101, 2953, +0, 3148, 2824, +0, 3204, 2564, +0, 3270, 0, +0, 3345, 0, +0, 3430, 0, +0, 3523, 0, +0, 3623, 0, +0, 3730, 0, +0, 2924, 3205, +0, 2924, 3205, +0, 2925, 3205, +0, 2925, 3205, +0, 2925, 3205, +0, 2925, 3204, +0, 2926, 3204, +0, 2926, 3203, +0, 2927, 3203, +0, 2928, 3202, +0, 2929, 3201, +0, 2931, 3199, +0, 2933, 3197, +0, 2936, 3195, +0, 2940, 3191, +0, 2945, 3186, +0, 2952, 3180, +0, 2961, 3171, +0, 2972, 3159, +0, 2987, 3142, +0, 3007, 3118, +0, 3032, 3084, +0, 3063, 3035, +0, 3102, 2959, +0, 3149, 2833, +0, 3205, 2580, +0, 3271, 0, +0, 3346, 0, +0, 3430, 0, +0, 3523, 0, +0, 3623, 0, +0, 3730, 0, +0, 2926, 3210, +0, 2926, 3210, +0, 2926, 3210, +0, 2926, 3210, +0, 2926, 3210, +0, 2927, 3210, +0, 2927, 3209, +0, 2927, 3209, +0, 2928, 3208, +0, 2929, 3207, +0, 2930, 3206, +0, 2932, 3205, +0, 2934, 3203, +0, 2937, 3200, +0, 2941, 3197, +0, 2946, 3192, +0, 2953, 3185, +0, 2962, 3176, +0, 2973, 3164, +0, 2989, 3148, +0, 3008, 3124, +0, 3033, 3091, +0, 3064, 3043, +0, 3103, 2968, +0, 3150, 2845, +0, 3206, 2601, +0, 3271, 1202, +0, 3346, 0, +0, 3431, 0, +0, 3523, 0, +0, 3624, 0, +0, 3730, 0, +0, 2927, 3217, +0, 2928, 3217, +0, 2928, 3217, +0, 2928, 3217, +0, 2928, 3217, +0, 2928, 3216, +0, 2929, 3216, +0, 2929, 3216, +0, 2930, 3215, +0, 2931, 3214, +0, 2932, 3213, +0, 2934, 3212, +0, 2936, 3210, +0, 2939, 3207, +0, 2943, 3204, +0, 2948, 3199, +0, 2955, 3193, +0, 2963, 3184, +0, 2975, 3172, +0, 2990, 3156, +0, 3010, 3133, +0, 3034, 3100, +0, 3065, 3053, +0, 3104, 2980, +0, 3151, 2860, +0, 3207, 2626, +0, 3272, 1575, +0, 3347, 0, +0, 3431, 0, +0, 3524, 0, +0, 3624, 0, +0, 3731, 0, +0, 2930, 3226, +0, 2930, 3226, +0, 2930, 3226, +0, 2930, 3226, +0, 2930, 3226, +0, 2931, 3226, +0, 2931, 3225, +0, 2932, 3225, +0, 2932, 3224, +0, 2933, 3223, +0, 2934, 3222, +0, 2936, 3221, +0, 2938, 3219, +0, 2941, 3216, +0, 2945, 3213, +0, 2950, 3208, +0, 2957, 3202, +0, 2966, 3194, +0, 2977, 3182, +0, 2992, 3166, +0, 3012, 3144, +0, 3036, 3112, +0, 3067, 3066, +0, 3105, 2995, +0, 3152, 2880, +0, 3208, 2659, +0, 3273, 1829, +0, 3348, 0, +0, 3432, 0, +0, 3524, 0, +0, 3624, 0, +0, 3731, 0, +0, 2933, 3238, +0, 2933, 3238, +0, 2933, 3238, +0, 2933, 3238, +0, 2934, 3238, +0, 2934, 3237, +0, 2934, 3237, +0, 2935, 3237, +0, 2936, 3236, +0, 2936, 3235, +0, 2938, 3234, +0, 2939, 3233, +0, 2941, 3231, +0, 2944, 3229, +0, 2948, 3225, +0, 2953, 3221, +0, 2960, 3215, +0, 2969, 3206, +0, 2980, 3195, +0, 2995, 3179, +0, 3014, 3158, +0, 3039, 3127, +0, 3069, 3082, +0, 3108, 3015, +0, 3154, 2905, +0, 3210, 2699, +0, 3275, 2034, +0, 3349, 0, +0, 3433, 0, +0, 3525, 0, +0, 3625, 0, +0, 3732, 0, +0, 2937, 3254, +0, 2937, 3253, +0, 2938, 3253, +0, 2938, 3253, +0, 2938, 3253, +0, 2938, 3253, +0, 2939, 3252, +0, 2939, 3252, +0, 2940, 3252, +0, 2941, 3251, +0, 2942, 3250, +0, 2943, 3248, +0, 2946, 3247, +0, 2948, 3244, +0, 2952, 3241, +0, 2957, 3237, +0, 2964, 3231, +0, 2973, 3223, +0, 2984, 3212, +0, 2999, 3197, +0, 3018, 3176, +0, 3042, 3147, +0, 3073, 3104, +0, 3110, 3040, +0, 3157, 2937, +0, 3212, 2747, +0, 3277, 2215, +0, 3351, 0, +0, 3434, 0, +0, 3526, 0, +0, 3626, 0, +0, 3732, 0, +0, 2943, 3273, +0, 2943, 3273, +0, 2943, 3273, +0, 2943, 3273, +0, 2944, 3273, +0, 2944, 3273, +0, 2944, 3272, +0, 2945, 3272, +0, 2945, 3271, +0, 2946, 3271, +0, 2947, 3270, +0, 2949, 3268, +0, 2951, 3267, +0, 2954, 3264, +0, 2958, 3261, +0, 2963, 3257, +0, 2969, 3252, +0, 2978, 3244, +0, 2989, 3234, +0, 3004, 3219, +0, 3022, 3199, +0, 3046, 3171, +0, 3077, 3131, +0, 3114, 3071, +0, 3160, 2976, +0, 3215, 2805, +0, 3279, 2380, +0, 3353, 0, +0, 3436, 0, +0, 3528, 0, +0, 3627, 0, +0, 3733, 0, +1458, 2950, 3298, +1453, 2950, 3298, +1446, 2951, 3298, +1437, 2951, 3298, +1424, 2951, 3298, +1407, 2951, 3298, +1383, 2952, 3298, +1348, 2952, 3297, +1297, 2953, 3297, +1219, 2954, 3296, +1088, 2955, 3295, +818, 2956, 3294, +0, 2958, 3292, +0, 2961, 3290, +0, 2965, 3287, +0, 2970, 3283, +0, 2976, 3278, +0, 2985, 3271, +0, 2996, 3261, +0, 3010, 3248, +0, 3029, 3229, +0, 3052, 3203, +0, 3082, 3165, +0, 3119, 3110, +0, 3165, 3023, +0, 3219, 2873, +0, 3283, 2535, +0, 3356, 0, +0, 3439, 0, +0, 3530, 0, +0, 3629, 0, +0, 3735, 0, +2457, 2960, 3330, +2456, 2960, 3330, +2456, 2960, 3330, +2455, 2960, 3330, +2453, 2961, 3330, +2451, 2961, 3330, +2449, 2961, 3329, +2446, 2962, 3329, +2442, 2962, 3328, +2436, 2963, 3328, +2428, 2964, 3327, +2417, 2966, 3326, +2402, 2968, 3324, +2382, 2971, 3322, +2352, 2974, 3320, +2310, 2979, 3316, +2247, 2985, 3311, +2145, 2994, 3304, +1960, 3004, 3295, +1453, 3019, 3283, +0, 3037, 3266, +0, 3060, 3242, +0, 3090, 3207, +0, 3126, 3157, +0, 3171, 3079, +0, 3225, 2949, +0, 3288, 2684, +0, 3360, 0, +0, 3442, 0, +0, 3533, 0, +0, 3631, 0, +0, 3736, 0, +2813, 2973, 3369, +2813, 2973, 3369, +2812, 2973, 3369, +2812, 2973, 3369, +2811, 2973, 3369, +2810, 2974, 3369, +2809, 2974, 3369, +2808, 2974, 3368, +2806, 2975, 3368, +2803, 2976, 3367, +2800, 2977, 3366, +2795, 2978, 3365, +2789, 2980, 3364, +2780, 2983, 3362, +2768, 2987, 3360, +2752, 2991, 3356, +2729, 2997, 3352, +2696, 3005, 3346, +2648, 3016, 3337, +2576, 3030, 3326, +2456, 3048, 3310, +2220, 3070, 3289, +1140, 3099, 3258, +0, 3135, 3213, +0, 3179, 3145, +0, 3232, 3035, +0, 3294, 2828, +0, 3366, 2152, +0, 3447, 0, +0, 3536, 0, +0, 3634, 0, +0, 3739, 0, +3061, 2989, 3417, +3061, 2989, 3417, +3061, 2989, 3417, +3060, 2989, 3417, +3060, 2990, 3417, +3060, 2990, 3416, +3059, 2990, 3416, +3058, 2991, 3416, +3057, 2991, 3415, +3055, 2992, 3415, +3053, 2993, 3414, +3051, 2995, 3413, +3047, 2997, 3412, +3042, 2999, 3410, +3036, 3002, 3408, +3027, 3007, 3405, +3014, 3013, 3401, +2997, 3021, 3396, +2973, 3031, 3388, +2939, 3044, 3378, +2889, 3062, 3364, +2812, 3084, 3345, +2683, 3112, 3318, +2421, 3147, 3279, +0, 3189, 3221, +0, 3241, 3129, +0, 3302, 2969, +0, 3373, 2588, +0, 3452, 0, +0, 3541, 0, +0, 3638, 0, +0, 3742, 0, +3264, 3010, 3474, +3264, 3010, 3474, +3264, 3010, 3473, +3263, 3010, 3473, +3263, 3011, 3473, +3263, 3011, 3473, +3263, 3011, 3473, +3262, 3012, 3473, +3261, 3012, 3472, +3260, 3013, 3472, +3259, 3014, 3471, +3257, 3015, 3470, +3255, 3017, 3469, +3252, 3020, 3468, +3248, 3023, 3466, +3242, 3027, 3463, +3234, 3033, 3460, +3224, 3040, 3455, +3210, 3050, 3448, +3190, 3063, 3440, +3161, 3080, 3427, +3121, 3101, 3411, +3060, 3128, 3387, +2964, 3162, 3354, +2791, 3203, 3305, +2354, 3253, 3231, +0, 3313, 3107, +0, 3382, 2861, +0, 3460, 1375, +0, 3548, 0, +0, 3643, 0, +0, 3746, 0, +3442, 3037, 3540, +3442, 3037, 3540, +3442, 3037, 3540, +3442, 3037, 3540, +3442, 3037, 3540, +3442, 3038, 3539, +3442, 3038, 3539, +3441, 3038, 3539, +3441, 3039, 3539, +3440, 3040, 3538, +3439, 3041, 3538, +3438, 3042, 3537, +3437, 3044, 3536, +3434, 3046, 3535, +3432, 3049, 3533, +3428, 3053, 3531, +3423, 3058, 3528, +3416, 3065, 3524, +3407, 3075, 3518, +3394, 3087, 3511, +3376, 3103, 3500, +3351, 3123, 3486, +3315, 3149, 3466, +3263, 3181, 3438, +3182, 3221, 3398, +3044, 3269, 3339, +2752, 3327, 3244, +0, 3394, 3076, +0, 3470, 2660, +0, 3556, 0, +0, 3650, 0, +0, 3751, 0, +3606, 3070, 3616, +3606, 3070, 3616, +3606, 3071, 3616, +3606, 3071, 3615, +3606, 3071, 3615, +3606, 3071, 3615, +3606, 3071, 3615, +3606, 3072, 3615, +3605, 3072, 3615, +3605, 3073, 3614, +3604, 3074, 3614, +3603, 3075, 3613, +3602, 3077, 3613, +3601, 3079, 3611, +3599, 3082, 3610, +3596, 3085, 3608, +3593, 3090, 3605, +3588, 3097, 3602, +3582, 3106, 3597, +3573, 3117, 3591, +3561, 3132, 3582, +3545, 3151, 3570, +3522, 3175, 3554, +3489, 3205, 3531, +3442, 3243, 3499, +3369, 3289, 3452, +3249, 3345, 3380, +3015, 3409, 3261, +1952, 3483, 3030, +0, 3567, 2039, +0, 3659, 0, +0, 3758, 0, +3761, 3112, 3700, +3761, 3112, 3700, +3761, 3112, 3700, +3761, 3112, 3700, +3761, 3112, 3700, +3761, 3112, 3700, +3761, 3112, 3700, +3760, 3113, 3700, +3760, 3113, 3700, +3760, 3114, 3699, +3759, 3115, 3699, +3759, 3116, 3699, +3758, 3117, 3698, +3757, 3119, 3697, +3756, 3122, 3696, +3754, 3125, 3694, +3751, 3130, 3692, +3748, 3136, 3689, +3744, 3144, 3685, +3738, 3154, 3680, +3729, 3168, 3673, +3718, 3185, 3663, +3702, 3208, 3650, +3681, 3236, 3632, +3650, 3272, 3606, +3606, 3315, 3569, +3538, 3368, 3514, +3429, 3429, 3429, +3224, 3501, 3283, +2573, 3581, 2960, +0, 3671, 0, +0, 3768, 0, +3909, 3161, 3794, +3909, 3161, 3794, +3909, 3162, 3794, +3909, 3162, 3794, +3909, 3162, 3794, +3909, 3162, 3794, +3909, 3162, 3793, +3909, 3162, 3793, +3909, 3163, 3793, +3908, 3163, 3793, +3908, 3164, 3793, +3908, 3165, 3792, +3907, 3166, 3792, +3906, 3168, 3791, +3905, 3171, 3790, +3904, 3174, 3789, +3902, 3178, 3787, +3900, 3183, 3785, +3897, 3190, 3781, +3892, 3200, 3777, +3887, 3212, 3771, +3879, 3228, 3764, +3868, 3249, 3753, +3853, 3275, 3739, +3832, 3307, 3718, +3803, 3348, 3690, +3760, 3397, 3648, +3696, 3455, 3587, +3594, 3522, 3488, +3407, 3599, 3311, +2887, 3686, 2847, +0, 3780, 0, +4053, 3220, 3894, +4053, 3221, 3894, +4053, 3221, 3894, +4053, 3221, 3894, +4053, 3221, 3894, +4053, 3221, 3894, +4053, 3221, 3894, +4053, 3221, 3894, +4053, 3222, 3894, +4052, 3222, 3894, +4052, 3223, 3894, +4052, 3224, 3893, +4052, 3225, 3893, +4051, 3226, 3892, +4050, 3229, 3891, +4049, 3231, 3890, +4048, 3235, 3889, +4046, 3240, 3887, +4044, 3246, 3885, +4041, 3254, 3881, +4037, 3265, 3877, +4031, 3280, 3871, +4023, 3298, 3862, +4013, 3321, 3851, +3998, 3351, 3835, +3978, 3388, 3813, +3950, 3433, 3782, +3908, 3487, 3737, +3847, 3550, 3668, +3749, 3623, 3557, +3573, 3705, 3345, +3119, 3796, 2630, +4095, 3289, 4002, +4095, 3289, 4002, +4095, 3289, 4002, +4095, 3289, 4002, +4095, 3289, 4001, +4095, 3290, 4001, +4095, 3290, 4001, +4095, 3290, 4001, +4095, 3290, 4001, +4095, 3291, 4001, +4095, 3291, 4001, +4095, 3292, 4001, +4095, 3293, 4000, +4095, 3294, 4000, +4095, 3296, 3999, +4095, 3298, 3998, +4095, 3302, 3997, +4095, 3306, 3996, +4095, 3311, 3994, +4095, 3318, 3991, +4095, 3328, 3988, +4095, 3340, 3983, +4095, 3357, 3976, +4095, 3377, 3967, +4095, 3403, 3955, +4095, 3436, 3939, +4095, 3477, 3915, +4092, 3526, 3882, +4052, 3585, 3833, +3993, 3653, 3758, +3898, 3730, 3634, +3730, 3816, 3387, +4095, 3367, 4095, +4095, 3367, 4095, +4095, 3367, 4095, +4095, 3367, 4095, +4095, 3367, 4095, +4095, 3368, 4095, +4095, 3368, 4095, +4095, 3368, 4095, +4095, 3368, 4095, +4095, 3369, 4095, +4095, 3369, 4095, +4095, 3370, 4095, +4095, 3370, 4095, +4095, 3372, 4095, +4095, 3373, 4095, +4095, 3375, 4095, +4095, 3378, 4095, +4095, 3381, 4095, +4095, 3386, 4095, +4095, 3392, 4095, +4095, 3400, 4095, +4095, 3411, 4095, +4095, 3425, 4094, +4095, 3442, 4088, +4095, 3465, 4078, +4095, 3494, 4066, +4095, 3530, 4048, +4095, 3574, 4023, +4095, 3627, 3988, +4095, 3689, 3936, +4095, 3761, 3857, +4042, 3842, 3721, +0, 3052, 3322, +0, 3052, 3322, +0, 3053, 3321, +0, 3053, 3321, +0, 3053, 3321, +0, 3053, 3321, +0, 3053, 3321, +0, 3054, 3320, +0, 3054, 3320, +0, 3055, 3319, +0, 3056, 3318, +0, 3057, 3317, +0, 3059, 3316, +0, 3061, 3314, +0, 3064, 3311, +0, 3068, 3307, +0, 3073, 3302, +0, 3080, 3295, +0, 3089, 3286, +0, 3101, 3273, +0, 3116, 3256, +0, 3136, 3231, +0, 3161, 3196, +0, 3192, 3144, +0, 3231, 3064, +0, 3278, 2929, +0, 3335, 2647, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3052, 3322, +0, 3052, 3322, +0, 3053, 3322, +0, 3053, 3321, +0, 3053, 3321, +0, 3053, 3321, +0, 3053, 3321, +0, 3054, 3320, +0, 3054, 3320, +0, 3055, 3319, +0, 3056, 3319, +0, 3057, 3317, +0, 3059, 3316, +0, 3061, 3314, +0, 3064, 3311, +0, 3068, 3307, +0, 3073, 3302, +0, 3080, 3295, +0, 3089, 3286, +0, 3101, 3273, +0, 3116, 3256, +0, 3136, 3231, +0, 3161, 3196, +0, 3192, 3144, +0, 3231, 3065, +0, 3278, 2930, +0, 3335, 2648, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3052, 3322, +0, 3052, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3321, +0, 3053, 3321, +0, 3053, 3321, +0, 3054, 3321, +0, 3054, 3320, +0, 3055, 3319, +0, 3056, 3319, +0, 3057, 3318, +0, 3059, 3316, +0, 3061, 3314, +0, 3064, 3311, +0, 3068, 3307, +0, 3073, 3302, +0, 3080, 3296, +0, 3089, 3286, +0, 3101, 3274, +0, 3116, 3256, +0, 3136, 3231, +0, 3161, 3196, +0, 3192, 3145, +0, 3231, 3065, +0, 3278, 2930, +0, 3335, 2648, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3052, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3321, +0, 3053, 3321, +0, 3054, 3321, +0, 3054, 3320, +0, 3055, 3320, +0, 3056, 3319, +0, 3057, 3318, +0, 3059, 3316, +0, 3061, 3314, +0, 3064, 3311, +0, 3068, 3308, +0, 3073, 3303, +0, 3080, 3296, +0, 3089, 3286, +0, 3101, 3274, +0, 3116, 3256, +0, 3136, 3232, +0, 3161, 3197, +0, 3192, 3145, +0, 3231, 3065, +0, 3278, 2930, +0, 3335, 2649, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3321, +0, 3054, 3321, +0, 3054, 3321, +0, 3055, 3320, +0, 3056, 3319, +0, 3057, 3318, +0, 3059, 3316, +0, 3061, 3314, +0, 3064, 3312, +0, 3068, 3308, +0, 3073, 3303, +0, 3080, 3296, +0, 3089, 3287, +0, 3101, 3274, +0, 3116, 3256, +0, 3136, 3232, +0, 3161, 3197, +0, 3192, 3145, +0, 3231, 3065, +0, 3278, 2931, +0, 3335, 2650, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3053, 3323, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3053, 3322, +0, 3054, 3322, +0, 3054, 3321, +0, 3054, 3321, +0, 3055, 3320, +0, 3056, 3319, +0, 3057, 3318, +0, 3059, 3317, +0, 3061, 3315, +0, 3064, 3312, +0, 3068, 3308, +0, 3073, 3303, +0, 3080, 3296, +0, 3089, 3287, +0, 3101, 3274, +0, 3116, 3257, +0, 3136, 3232, +0, 3161, 3197, +0, 3192, 3146, +0, 3231, 3066, +0, 3279, 2932, +0, 3335, 2651, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3322, +0, 3054, 3322, +0, 3054, 3322, +0, 3055, 3321, +0, 3055, 3321, +0, 3056, 3320, +0, 3057, 3319, +0, 3059, 3317, +0, 3061, 3315, +0, 3064, 3312, +0, 3068, 3309, +0, 3073, 3304, +0, 3080, 3297, +0, 3089, 3287, +0, 3101, 3275, +0, 3116, 3257, +0, 3136, 3233, +0, 3161, 3198, +0, 3192, 3146, +0, 3231, 3067, +0, 3279, 2932, +0, 3335, 2653, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3053, 3323, +0, 3054, 3323, +0, 3054, 3322, +0, 3055, 3322, +0, 3055, 3321, +0, 3056, 3320, +0, 3058, 3319, +0, 3059, 3318, +0, 3061, 3316, +0, 3064, 3313, +0, 3068, 3309, +0, 3074, 3304, +0, 3080, 3297, +0, 3089, 3288, +0, 3101, 3275, +0, 3116, 3258, +0, 3136, 3233, +0, 3161, 3198, +0, 3192, 3147, +0, 3231, 3068, +0, 3279, 2934, +0, 3335, 2655, +0, 3401, 0, +0, 3476, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3053, 3324, +0, 3053, 3324, +0, 3053, 3324, +0, 3053, 3324, +0, 3053, 3324, +0, 3054, 3324, +0, 3054, 3323, +0, 3054, 3323, +0, 3055, 3322, +0, 3056, 3322, +0, 3057, 3321, +0, 3058, 3320, +0, 3059, 3318, +0, 3062, 3316, +0, 3065, 3314, +0, 3069, 3310, +0, 3074, 3305, +0, 3081, 3298, +0, 3090, 3289, +0, 3101, 3276, +0, 3117, 3259, +0, 3136, 3234, +0, 3161, 3199, +0, 3193, 3148, +0, 3231, 3069, +0, 3279, 2935, +0, 3335, 2658, +0, 3401, 0, +0, 3477, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3053, 3325, +0, 3053, 3325, +0, 3053, 3325, +0, 3054, 3325, +0, 3054, 3325, +0, 3054, 3325, +0, 3054, 3324, +0, 3055, 3324, +0, 3055, 3323, +0, 3056, 3323, +0, 3057, 3322, +0, 3058, 3321, +0, 3060, 3319, +0, 3062, 3317, +0, 3065, 3314, +0, 3069, 3311, +0, 3074, 3306, +0, 3081, 3299, +0, 3090, 3290, +0, 3102, 3277, +0, 3117, 3260, +0, 3136, 3235, +0, 3161, 3201, +0, 3193, 3149, +0, 3232, 3071, +0, 3279, 2938, +0, 3335, 2662, +0, 3401, 0, +0, 3477, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3054, 3326, +0, 3054, 3326, +0, 3054, 3326, +0, 3054, 3326, +0, 3054, 3326, +0, 3054, 3326, +0, 3055, 3326, +0, 3055, 3325, +0, 3055, 3325, +0, 3056, 3324, +0, 3057, 3323, +0, 3058, 3322, +0, 3060, 3321, +0, 3062, 3319, +0, 3065, 3316, +0, 3069, 3312, +0, 3074, 3307, +0, 3081, 3300, +0, 3090, 3291, +0, 3102, 3279, +0, 3117, 3261, +0, 3137, 3237, +0, 3162, 3202, +0, 3193, 3151, +0, 3232, 3073, +0, 3279, 2941, +0, 3335, 2668, +0, 3401, 0, +0, 3477, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3054, 3328, +0, 3054, 3328, +0, 3054, 3328, +0, 3054, 3328, +0, 3054, 3328, +0, 3055, 3327, +0, 3055, 3327, +0, 3055, 3327, +0, 3056, 3326, +0, 3057, 3326, +0, 3057, 3325, +0, 3059, 3324, +0, 3060, 3322, +0, 3063, 3320, +0, 3066, 3318, +0, 3069, 3314, +0, 3075, 3309, +0, 3081, 3302, +0, 3090, 3293, +0, 3102, 3281, +0, 3117, 3263, +0, 3137, 3239, +0, 3162, 3204, +0, 3193, 3154, +0, 3232, 3076, +0, 3279, 2944, +0, 3336, 2675, +0, 3402, 0, +0, 3477, 0, +0, 3561, 0, +0, 3654, 0, +0, 3755, 0, +0, 3055, 3330, +0, 3055, 3330, +0, 3055, 3330, +0, 3055, 3330, +0, 3055, 3330, +0, 3055, 3330, +0, 3056, 3329, +0, 3056, 3329, +0, 3056, 3329, +0, 3057, 3328, +0, 3058, 3327, +0, 3059, 3326, +0, 3061, 3325, +0, 3063, 3323, +0, 3066, 3320, +0, 3070, 3316, +0, 3075, 3311, +0, 3082, 3305, +0, 3091, 3295, +0, 3103, 3283, +0, 3118, 3266, +0, 3137, 3242, +0, 3162, 3207, +0, 3194, 3157, +0, 3233, 3080, +0, 3280, 2950, +0, 3336, 2684, +0, 3402, 0, +0, 3477, 0, +0, 3562, 0, +0, 3655, 0, +0, 3755, 0, +0, 3055, 3333, +0, 3055, 3333, +0, 3055, 3333, +0, 3056, 3333, +0, 3056, 3333, +0, 3056, 3333, +0, 3056, 3332, +0, 3057, 3332, +0, 3057, 3332, +0, 3058, 3331, +0, 3059, 3330, +0, 3060, 3329, +0, 3062, 3328, +0, 3064, 3326, +0, 3067, 3323, +0, 3071, 3319, +0, 3076, 3314, +0, 3083, 3308, +0, 3092, 3299, +0, 3103, 3286, +0, 3119, 3269, +0, 3138, 3245, +0, 3163, 3211, +0, 3194, 3161, +0, 3233, 3085, +0, 3280, 2957, +0, 3336, 2696, +0, 3402, 0, +0, 3477, 0, +0, 3562, 0, +0, 3655, 0, +0, 3755, 0, +0, 3056, 3337, +0, 3056, 3337, +0, 3056, 3337, +0, 3057, 3337, +0, 3057, 3337, +0, 3057, 3337, +0, 3057, 3336, +0, 3058, 3336, +0, 3058, 3336, +0, 3059, 3335, +0, 3060, 3334, +0, 3061, 3333, +0, 3063, 3332, +0, 3065, 3330, +0, 3068, 3327, +0, 3072, 3323, +0, 3077, 3318, +0, 3084, 3312, +0, 3093, 3303, +0, 3104, 3291, +0, 3119, 3274, +0, 3139, 3250, +0, 3164, 3216, +0, 3195, 3167, +0, 3234, 3092, +0, 3281, 2966, +0, 3337, 2712, +0, 3403, 0, +0, 3478, 0, +0, 3562, 0, +0, 3655, 0, +0, 3755, 0, +0, 3058, 3342, +0, 3058, 3342, +0, 3058, 3342, +0, 3058, 3342, +0, 3058, 3342, +0, 3058, 3342, +0, 3059, 3342, +0, 3059, 3341, +0, 3060, 3341, +0, 3060, 3340, +0, 3061, 3339, +0, 3062, 3338, +0, 3064, 3337, +0, 3066, 3335, +0, 3069, 3332, +0, 3073, 3329, +0, 3078, 3324, +0, 3085, 3317, +0, 3094, 3309, +0, 3106, 3296, +0, 3121, 3280, +0, 3140, 3256, +0, 3165, 3223, +0, 3196, 3175, +0, 3235, 3100, +0, 3282, 2977, +0, 3338, 2733, +0, 3403, 1334, +0, 3478, 0, +0, 3563, 0, +0, 3655, 0, +0, 3756, 0, +0, 3059, 3349, +0, 3060, 3349, +0, 3060, 3349, +0, 3060, 3349, +0, 3060, 3349, +0, 3060, 3349, +0, 3060, 3349, +0, 3061, 3348, +0, 3061, 3348, +0, 3062, 3347, +0, 3063, 3346, +0, 3064, 3345, +0, 3066, 3344, +0, 3068, 3342, +0, 3071, 3339, +0, 3075, 3336, +0, 3080, 3331, +0, 3087, 3325, +0, 3096, 3316, +0, 3107, 3304, +0, 3122, 3288, +0, 3142, 3265, +0, 3166, 3232, +0, 3197, 3185, +0, 3236, 3112, +0, 3283, 2993, +0, 3339, 2758, +0, 3404, 1707, +0, 3479, 0, +0, 3563, 0, +0, 3656, 0, +0, 3756, 0, +0, 3062, 3358, +0, 3062, 3358, +0, 3062, 3358, +0, 3062, 3358, +0, 3062, 3358, +0, 3063, 3358, +0, 3063, 3358, +0, 3063, 3357, +0, 3064, 3357, +0, 3064, 3356, +0, 3065, 3355, +0, 3067, 3354, +0, 3068, 3353, +0, 3070, 3351, +0, 3073, 3349, +0, 3077, 3345, +0, 3082, 3341, +0, 3089, 3334, +0, 3098, 3326, +0, 3109, 3314, +0, 3124, 3298, +0, 3144, 3276, +0, 3168, 3244, +0, 3199, 3198, +0, 3238, 3127, +0, 3284, 3012, +0, 3340, 2791, +0, 3405, 1961, +0, 3480, 0, +0, 3564, 0, +0, 3657, 0, +0, 3757, 0, +0, 3065, 3370, +0, 3065, 3370, +0, 3065, 3370, +0, 3065, 3370, +0, 3066, 3370, +0, 3066, 3370, +0, 3066, 3369, +0, 3066, 3369, +0, 3067, 3369, +0, 3068, 3368, +0, 3069, 3367, +0, 3070, 3366, +0, 3071, 3365, +0, 3074, 3363, +0, 3076, 3361, +0, 3080, 3357, +0, 3085, 3353, +0, 3092, 3347, +0, 3101, 3338, +0, 3112, 3327, +0, 3127, 3312, +0, 3146, 3290, +0, 3171, 3259, +0, 3202, 3214, +0, 3240, 3147, +0, 3286, 3037, +0, 3342, 2831, +0, 3407, 2166, +0, 3481, 0, +0, 3565, 0, +0, 3657, 0, +0, 3757, 0, +0, 3069, 3386, +0, 3069, 3386, +0, 3070, 3386, +0, 3070, 3385, +0, 3070, 3385, +0, 3070, 3385, +0, 3070, 3385, +0, 3071, 3385, +0, 3071, 3384, +0, 3072, 3384, +0, 3073, 3383, +0, 3074, 3382, +0, 3076, 3381, +0, 3078, 3379, +0, 3081, 3376, +0, 3084, 3373, +0, 3089, 3369, +0, 3096, 3363, +0, 3105, 3355, +0, 3116, 3344, +0, 3131, 3329, +0, 3150, 3308, +0, 3174, 3279, +0, 3205, 3236, +0, 3243, 3172, +0, 3289, 3069, +0, 3344, 2880, +0, 3409, 2347, +0, 3483, 0, +0, 3567, 0, +0, 3659, 0, +0, 3758, 0, +0, 3075, 3405, +0, 3075, 3405, +0, 3075, 3405, +0, 3075, 3405, +0, 3075, 3405, +0, 3076, 3405, +0, 3076, 3405, +0, 3076, 3404, +0, 3077, 3404, +0, 3077, 3404, +0, 3078, 3403, +0, 3080, 3402, +0, 3081, 3401, +0, 3083, 3399, +0, 3086, 3397, +0, 3090, 3393, +0, 3095, 3389, +0, 3101, 3384, +0, 3110, 3376, +0, 3121, 3366, +0, 3136, 3351, +0, 3155, 3332, +0, 3179, 3304, +0, 3209, 3263, +0, 3246, 3203, +0, 3292, 3108, +0, 3347, 2937, +0, 3411, 2512, +0, 3485, 0, +0, 3568, 0, +0, 3660, 0, +0, 3759, 0, +1593, 3082, 3431, +1590, 3082, 3431, +1585, 3083, 3431, +1578, 3083, 3430, +1569, 3083, 3430, +1556, 3083, 3430, +1539, 3083, 3430, +1515, 3084, 3430, +1480, 3084, 3429, +1429, 3085, 3429, +1351, 3086, 3428, +1220, 3087, 3427, +950, 3088, 3426, +0, 3090, 3424, +0, 3093, 3422, +0, 3097, 3419, +0, 3102, 3415, +0, 3108, 3410, +0, 3117, 3403, +0, 3128, 3393, +0, 3142, 3380, +0, 3161, 3361, +0, 3184, 3335, +0, 3214, 3297, +0, 3252, 3242, +0, 3297, 3155, +0, 3351, 3005, +0, 3415, 2667, +0, 3488, 0, +0, 3571, 0, +0, 3662, 0, +0, 3761, 0, +2589, 3092, 3462, +2589, 3092, 3462, +2588, 3092, 3462, +2588, 3092, 3462, +2587, 3092, 3462, +2585, 3093, 3462, +2584, 3093, 3462, +2581, 3093, 3461, +2578, 3094, 3461, +2574, 3094, 3461, +2568, 3095, 3460, +2560, 3096, 3459, +2549, 3098, 3458, +2534, 3100, 3456, +2514, 3103, 3454, +2484, 3106, 3452, +2442, 3111, 3448, +2379, 3117, 3443, +2277, 3126, 3436, +2092, 3137, 3427, +1586, 3151, 3415, +0, 3169, 3398, +0, 3192, 3374, +0, 3222, 3339, +0, 3258, 3289, +0, 3303, 3211, +0, 3357, 3081, +0, 3420, 2816, +0, 3492, 0, +0, 3574, 0, +0, 3665, 0, +0, 3763, 0, +2945, 3105, 3501, +2945, 3105, 3501, +2945, 3105, 3501, +2944, 3105, 3501, +2944, 3105, 3501, +2943, 3105, 3501, +2942, 3106, 3501, +2941, 3106, 3501, +2940, 3106, 3500, +2938, 3107, 3500, +2935, 3108, 3499, +2932, 3109, 3499, +2927, 3110, 3497, +2921, 3112, 3496, +2912, 3115, 3494, +2900, 3119, 3492, +2884, 3123, 3488, +2861, 3129, 3484, +2828, 3137, 3478, +2780, 3148, 3470, +2708, 3162, 3458, +2588, 3180, 3443, +2352, 3202, 3421, +1272, 3231, 3390, +0, 3267, 3345, +0, 3311, 3277, +0, 3364, 3167, +0, 3426, 2960, +0, 3498, 2284, +0, 3579, 0, +0, 3669, 0, +0, 3766, 0, +3193, 3121, 3549, +3193, 3121, 3549, +3193, 3121, 3549, +3193, 3121, 3549, +3192, 3122, 3549, +3192, 3122, 3549, +3192, 3122, 3548, +3191, 3122, 3548, +3190, 3123, 3548, +3189, 3123, 3548, +3188, 3124, 3547, +3186, 3125, 3546, +3183, 3127, 3545, +3179, 3129, 3544, +3174, 3131, 3543, +3168, 3135, 3540, +3159, 3139, 3537, +3146, 3145, 3533, +3129, 3153, 3528, +3105, 3163, 3520, +3071, 3176, 3510, +3021, 3194, 3496, +2944, 3216, 3477, +2815, 3244, 3450, +2553, 3279, 3411, +0, 3321, 3353, +0, 3373, 3261, +0, 3434, 3101, +0, 3505, 2720, +0, 3585, 0, +0, 3673, 0, +0, 3770, 0, +3396, 3142, 3606, +3396, 3142, 3606, +3396, 3142, 3606, +3396, 3142, 3606, +3396, 3143, 3605, +3395, 3143, 3605, +3395, 3143, 3605, +3395, 3143, 3605, +3394, 3144, 3605, +3393, 3144, 3604, +3392, 3145, 3604, +3391, 3146, 3603, +3389, 3148, 3603, +3387, 3149, 3601, +3384, 3152, 3600, +3380, 3155, 3598, +3374, 3159, 3595, +3367, 3165, 3592, +3356, 3172, 3587, +3342, 3182, 3581, +3322, 3195, 3572, +3294, 3212, 3560, +3253, 3233, 3543, +3192, 3260, 3519, +3096, 3294, 3486, +2923, 3335, 3437, +2486, 3385, 3363, +0, 3445, 3239, +0, 3514, 2993, +0, 3592, 1507, +0, 3680, 0, +0, 3775, 0, +3575, 3169, 3672, +3575, 3169, 3672, +3574, 3169, 3672, +3574, 3169, 3672, +3574, 3169, 3672, +3574, 3169, 3672, +3574, 3170, 3672, +3574, 3170, 3671, +3573, 3170, 3671, +3573, 3171, 3671, +3572, 3172, 3670, +3571, 3173, 3670, +3570, 3174, 3669, +3569, 3176, 3668, +3567, 3178, 3667, +3564, 3181, 3665, +3560, 3185, 3663, +3555, 3190, 3660, +3548, 3198, 3656, +3539, 3207, 3650, +3526, 3219, 3643, +3508, 3235, 3632, +3483, 3255, 3618, +3448, 3281, 3598, +3395, 3313, 3571, +3314, 3353, 3531, +3176, 3401, 3471, +2884, 3459, 3376, +0, 3526, 3208, +0, 3602, 2792, +0, 3688, 0, +0, 3782, 0, +3739, 3202, 3748, +3739, 3202, 3748, +3739, 3203, 3748, +3738, 3203, 3748, +3738, 3203, 3748, +3738, 3203, 3747, +3738, 3203, 3747, +3738, 3203, 3747, +3738, 3204, 3747, +3737, 3204, 3747, +3737, 3205, 3746, +3736, 3206, 3746, +3736, 3207, 3745, +3734, 3209, 3745, +3733, 3211, 3744, +3731, 3214, 3742, +3728, 3217, 3740, +3725, 3222, 3738, +3720, 3229, 3734, +3714, 3238, 3729, +3705, 3249, 3723, +3693, 3264, 3714, +3677, 3283, 3703, +3654, 3307, 3686, +3621, 3338, 3663, +3574, 3375, 3631, +3501, 3422, 3584, +3381, 3477, 3512, +3147, 3541, 3393, +2084, 3616, 3162, +0, 3699, 2171, +0, 3791, 0, +3893, 3244, 3833, +3893, 3244, 3833, +3893, 3244, 3833, +3893, 3244, 3832, +3893, 3244, 3832, +3893, 3244, 3832, +3893, 3244, 3832, +3893, 3244, 3832, +3893, 3245, 3832, +3892, 3245, 3832, +3892, 3246, 3832, +3892, 3247, 3831, +3891, 3248, 3831, +3890, 3249, 3830, +3889, 3251, 3829, +3888, 3254, 3828, +3886, 3257, 3826, +3884, 3262, 3824, +3880, 3268, 3821, +3876, 3276, 3817, +3870, 3286, 3812, +3861, 3300, 3805, +3850, 3318, 3795, +3835, 3340, 3782, +3813, 3368, 3764, +3782, 3404, 3738, +3738, 3447, 3701, +3670, 3500, 3646, +3561, 3561, 3561, +3357, 3633, 3415, +2705, 3713, 3092, +0, 3803, 0, +4041, 3293, 3926, +4041, 3293, 3926, +4041, 3294, 3926, +4041, 3294, 3926, +4041, 3294, 3926, +4041, 3294, 3926, +4041, 3294, 3926, +4041, 3294, 3926, +4041, 3295, 3925, +4041, 3295, 3925, +4041, 3296, 3925, +4040, 3296, 3925, +4040, 3297, 3924, +4039, 3299, 3924, +4039, 3300, 3923, +4038, 3303, 3922, +4036, 3306, 3921, +4034, 3310, 3919, +4032, 3315, 3917, +4029, 3322, 3914, +4025, 3332, 3909, +4019, 3344, 3904, +4011, 3360, 3896, +4000, 3381, 3885, +3985, 3407, 3871, +3964, 3440, 3850, +3935, 3480, 3822, +3892, 3529, 3781, +3829, 3587, 3719, +3726, 3654, 3620, +3539, 3732, 3443, +3019, 3818, 2979, +4095, 3353, 4027, +4095, 3353, 4027, +4095, 3353, 4027, +4095, 3353, 4027, +4095, 3353, 4026, +4095, 3353, 4026, +4095, 3353, 4026, +4095, 3353, 4026, +4095, 3354, 4026, +4095, 3354, 4026, +4095, 3354, 4026, +4095, 3355, 4026, +4095, 3356, 4025, +4095, 3357, 4025, +4095, 3359, 4024, +4095, 3361, 4024, +4095, 3363, 4023, +4095, 3367, 4021, +4095, 3372, 4019, +4095, 3378, 4017, +4095, 3387, 4013, +4095, 3397, 4009, +4095, 3412, 4003, +4095, 3430, 3994, +4095, 3454, 3983, +4095, 3483, 3967, +4095, 3520, 3945, +4082, 3565, 3914, +4041, 3619, 3869, +3979, 3682, 3800, +3881, 3755, 3689, +3706, 3837, 3477, +4095, 3421, 4095, +4095, 3421, 4095, +4095, 3421, 4095, +4095, 3421, 4095, +4095, 3421, 4095, +4095, 3421, 4095, +4095, 3422, 4095, +4095, 3422, 4095, +4095, 3422, 4095, +4095, 3422, 4095, +4095, 3423, 4095, +4095, 3423, 4095, +4095, 3424, 4095, +4095, 3425, 4095, +4095, 3426, 4095, +4095, 3428, 4095, +4095, 3431, 4095, +4095, 3434, 4095, +4095, 3438, 4095, +4095, 3443, 4095, +4095, 3451, 4095, +4095, 3460, 4095, +4095, 3473, 4095, +4095, 3489, 4095, +4095, 3509, 4095, +4095, 3536, 4087, +4095, 3568, 4071, +4095, 3609, 4047, +4095, 3658, 4014, +4095, 3717, 3965, +4095, 3785, 3891, +4030, 3862, 3767, +0, 3184, 3454, +0, 3184, 3454, +0, 3185, 3454, +0, 3185, 3453, +0, 3185, 3453, +0, 3185, 3453, +0, 3185, 3453, +0, 3185, 3453, +0, 3186, 3452, +0, 3186, 3452, +0, 3187, 3451, +0, 3188, 3450, +0, 3189, 3449, +0, 3191, 3448, +0, 3193, 3446, +0, 3196, 3443, +0, 3200, 3439, +0, 3205, 3434, +0, 3212, 3427, +0, 3221, 3418, +0, 3233, 3405, +0, 3248, 3388, +0, 3268, 3363, +0, 3293, 3328, +0, 3324, 3276, +0, 3363, 3196, +0, 3410, 3061, +0, 3467, 2779, +0, 3533, 0, +0, 3608, 0, +0, 3693, 0, +0, 3786, 0, +0, 3184, 3454, +0, 3184, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3453, +0, 3185, 3453, +0, 3185, 3453, +0, 3185, 3453, +0, 3186, 3452, +0, 3186, 3452, +0, 3187, 3451, +0, 3188, 3451, +0, 3189, 3449, +0, 3191, 3448, +0, 3193, 3446, +0, 3196, 3443, +0, 3200, 3439, +0, 3205, 3434, +0, 3212, 3427, +0, 3221, 3418, +0, 3233, 3405, +0, 3248, 3388, +0, 3268, 3363, +0, 3293, 3328, +0, 3324, 3276, +0, 3363, 3196, +0, 3410, 3061, +0, 3467, 2779, +0, 3533, 0, +0, 3608, 0, +0, 3693, 0, +0, 3786, 0, +0, 3184, 3454, +0, 3184, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3453, +0, 3185, 3453, +0, 3185, 3453, +0, 3186, 3453, +0, 3186, 3452, +0, 3187, 3451, +0, 3188, 3451, +0, 3189, 3449, +0, 3191, 3448, +0, 3193, 3446, +0, 3196, 3443, +0, 3200, 3439, +0, 3205, 3434, +0, 3212, 3428, +0, 3221, 3418, +0, 3233, 3406, +0, 3248, 3388, +0, 3268, 3363, +0, 3293, 3328, +0, 3324, 3277, +0, 3363, 3197, +0, 3411, 3062, +0, 3467, 2780, +0, 3533, 0, +0, 3608, 0, +0, 3693, 0, +0, 3786, 0, +0, 3184, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3453, +0, 3185, 3453, +0, 3186, 3453, +0, 3186, 3452, +0, 3187, 3452, +0, 3188, 3451, +0, 3189, 3450, +0, 3191, 3448, +0, 3193, 3446, +0, 3196, 3443, +0, 3200, 3440, +0, 3205, 3434, +0, 3212, 3428, +0, 3221, 3418, +0, 3233, 3406, +0, 3248, 3388, +0, 3268, 3364, +0, 3293, 3328, +0, 3324, 3277, +0, 3363, 3197, +0, 3411, 3062, +0, 3467, 2780, +0, 3533, 0, +0, 3608, 0, +0, 3693, 0, +0, 3786, 0, +0, 3184, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3453, +0, 3186, 3453, +0, 3186, 3453, +0, 3186, 3452, +0, 3187, 3452, +0, 3188, 3451, +0, 3189, 3450, +0, 3191, 3448, +0, 3193, 3446, +0, 3196, 3443, +0, 3200, 3440, +0, 3205, 3435, +0, 3212, 3428, +0, 3221, 3419, +0, 3233, 3406, +0, 3248, 3388, +0, 3268, 3364, +0, 3293, 3329, +0, 3324, 3277, +0, 3363, 3197, +0, 3411, 3062, +0, 3467, 2781, +0, 3533, 0, +0, 3608, 0, +0, 3693, 0, +0, 3786, 0, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3186, 3453, +0, 3186, 3453, +0, 3186, 3453, +0, 3187, 3452, +0, 3188, 3451, +0, 3189, 3450, +0, 3191, 3448, +0, 3193, 3446, +0, 3196, 3444, +0, 3200, 3440, +0, 3205, 3435, +0, 3212, 3428, +0, 3221, 3419, +0, 3233, 3406, +0, 3248, 3389, +0, 3268, 3364, +0, 3293, 3329, +0, 3324, 3277, +0, 3363, 3198, +0, 3411, 3063, +0, 3467, 2782, +0, 3533, 0, +0, 3608, 0, +0, 3693, 0, +0, 3786, 0, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3185, 3454, +0, 3186, 3454, +0, 3186, 3453, +0, 3187, 3453, +0, 3187, 3452, +0, 3188, 3451, +0, 3189, 3450, +0, 3191, 3449, +0, 3193, 3447, +0, 3196, 3444, +0, 3200, 3440, +0, 3205, 3435, +0, 3212, 3428, +0, 3221, 3419, +0, 3233, 3406, +0, 3248, 3389, +0, 3268, 3364, +0, 3293, 3329, +0, 3324, 3278, +0, 3363, 3198, +0, 3411, 3064, +0, 3467, 2783, +0, 3533, 0, +0, 3609, 0, +0, 3693, 0, +0, 3786, 0, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3454, +0, 3186, 3454, +0, 3186, 3454, +0, 3187, 3453, +0, 3187, 3453, +0, 3188, 3452, +0, 3190, 3451, +0, 3191, 3449, +0, 3193, 3447, +0, 3196, 3444, +0, 3200, 3441, +0, 3205, 3436, +0, 3212, 3429, +0, 3221, 3420, +0, 3233, 3407, +0, 3248, 3389, +0, 3268, 3365, +0, 3293, 3330, +0, 3324, 3278, +0, 3363, 3199, +0, 3411, 3065, +0, 3467, 2785, +0, 3533, 0, +0, 3609, 0, +0, 3693, 0, +0, 3786, 0, +0, 3185, 3456, +0, 3185, 3456, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3185, 3455, +0, 3186, 3455, +0, 3186, 3455, +0, 3186, 3454, +0, 3187, 3454, +0, 3187, 3453, +0, 3188, 3452, +0, 3190, 3451, +0, 3191, 3450, +0, 3194, 3448, +0, 3197, 3445, +0, 3200, 3441, +0, 3206, 3436, +0, 3212, 3429, +0, 3221, 3420, +0, 3233, 3407, +0, 3248, 3390, +0, 3268, 3365, +0, 3293, 3331, +0, 3325, 3279, +0, 3363, 3200, +0, 3411, 3066, +0, 3467, 2787, +0, 3533, 0, +0, 3609, 0, +0, 3693, 0, +0, 3786, 0, +0, 3185, 3456, +0, 3185, 3456, +0, 3185, 3456, +0, 3185, 3456, +0, 3185, 3456, +0, 3186, 3456, +0, 3186, 3456, +0, 3186, 3455, +0, 3186, 3455, +0, 3187, 3455, +0, 3188, 3454, +0, 3189, 3453, +0, 3190, 3452, +0, 3192, 3450, +0, 3194, 3448, +0, 3197, 3446, +0, 3201, 3442, +0, 3206, 3437, +0, 3213, 3430, +0, 3222, 3421, +0, 3233, 3408, +0, 3249, 3391, +0, 3268, 3366, +0, 3293, 3331, +0, 3325, 3280, +0, 3364, 3201, +0, 3411, 3067, +0, 3467, 2790, +0, 3533, 0, +0, 3609, 0, +0, 3693, 0, +0, 3786, 0, +0, 3185, 3457, +0, 3185, 3457, +0, 3185, 3457, +0, 3185, 3457, +0, 3186, 3457, +0, 3186, 3457, +0, 3186, 3457, +0, 3186, 3456, +0, 3187, 3456, +0, 3187, 3456, +0, 3188, 3455, +0, 3189, 3454, +0, 3190, 3453, +0, 3192, 3451, +0, 3194, 3449, +0, 3197, 3447, +0, 3201, 3443, +0, 3206, 3438, +0, 3213, 3431, +0, 3222, 3422, +0, 3234, 3409, +0, 3249, 3392, +0, 3268, 3368, +0, 3293, 3333, +0, 3325, 3282, +0, 3364, 3203, +0, 3411, 3070, +0, 3467, 2794, +0, 3533, 0, +0, 3609, 0, +0, 3693, 0, +0, 3786, 0, +0, 3186, 3459, +0, 3186, 3458, +0, 3186, 3458, +0, 3186, 3458, +0, 3186, 3458, +0, 3186, 3458, +0, 3186, 3458, +0, 3187, 3458, +0, 3187, 3457, +0, 3188, 3457, +0, 3188, 3456, +0, 3189, 3455, +0, 3190, 3454, +0, 3192, 3453, +0, 3194, 3451, +0, 3197, 3448, +0, 3201, 3444, +0, 3206, 3439, +0, 3213, 3432, +0, 3222, 3423, +0, 3234, 3411, +0, 3249, 3393, +0, 3269, 3369, +0, 3294, 3334, +0, 3325, 3283, +0, 3364, 3205, +0, 3411, 3073, +0, 3468, 2800, +0, 3533, 0, +0, 3609, 0, +0, 3693, 0, +0, 3786, 0, +0, 3186, 3460, +0, 3186, 3460, +0, 3186, 3460, +0, 3186, 3460, +0, 3186, 3460, +0, 3187, 3460, +0, 3187, 3460, +0, 3187, 3459, +0, 3187, 3459, +0, 3188, 3458, +0, 3189, 3458, +0, 3190, 3457, +0, 3191, 3456, +0, 3193, 3454, +0, 3195, 3452, +0, 3198, 3450, +0, 3202, 3446, +0, 3207, 3441, +0, 3214, 3434, +0, 3223, 3425, +0, 3234, 3413, +0, 3250, 3395, +0, 3269, 3371, +0, 3294, 3337, +0, 3325, 3286, +0, 3364, 3208, +0, 3411, 3077, +0, 3468, 2807, +0, 3534, 0, +0, 3609, 0, +0, 3694, 0, +0, 3787, 0, +0, 3187, 3462, +0, 3187, 3462, +0, 3187, 3462, +0, 3187, 3462, +0, 3187, 3462, +0, 3187, 3462, +0, 3187, 3462, +0, 3188, 3462, +0, 3188, 3461, +0, 3189, 3461, +0, 3189, 3460, +0, 3190, 3459, +0, 3191, 3458, +0, 3193, 3457, +0, 3195, 3455, +0, 3198, 3452, +0, 3202, 3448, +0, 3207, 3443, +0, 3214, 3437, +0, 3223, 3428, +0, 3235, 3415, +0, 3250, 3398, +0, 3270, 3374, +0, 3295, 3339, +0, 3326, 3289, +0, 3365, 3212, +0, 3412, 3082, +0, 3468, 2816, +0, 3534, 0, +0, 3609, 0, +0, 3694, 0, +0, 3787, 0, +0, 3187, 3465, +0, 3187, 3465, +0, 3187, 3465, +0, 3188, 3465, +0, 3188, 3465, +0, 3188, 3465, +0, 3188, 3465, +0, 3188, 3465, +0, 3189, 3464, +0, 3189, 3464, +0, 3190, 3463, +0, 3191, 3462, +0, 3192, 3461, +0, 3194, 3460, +0, 3196, 3458, +0, 3199, 3455, +0, 3203, 3451, +0, 3208, 3446, +0, 3215, 3440, +0, 3224, 3431, +0, 3235, 3418, +0, 3251, 3401, +0, 3270, 3377, +0, 3295, 3343, +0, 3326, 3293, +0, 3365, 3217, +0, 3412, 3089, +0, 3469, 2829, +0, 3534, 0, +0, 3610, 0, +0, 3694, 0, +0, 3787, 0, +0, 3188, 3469, +0, 3188, 3469, +0, 3188, 3469, +0, 3189, 3469, +0, 3189, 3469, +0, 3189, 3469, +0, 3189, 3469, +0, 3189, 3468, +0, 3190, 3468, +0, 3190, 3468, +0, 3191, 3467, +0, 3192, 3466, +0, 3193, 3465, +0, 3195, 3464, +0, 3197, 3462, +0, 3200, 3459, +0, 3204, 3455, +0, 3209, 3451, +0, 3216, 3444, +0, 3225, 3435, +0, 3236, 3423, +0, 3252, 3406, +0, 3271, 3382, +0, 3296, 3349, +0, 3327, 3299, +0, 3366, 3224, +0, 3413, 3098, +0, 3469, 2844, +0, 3535, 106, +0, 3610, 0, +0, 3694, 0, +0, 3787, 0, +0, 3190, 3475, +0, 3190, 3475, +0, 3190, 3474, +0, 3190, 3474, +0, 3190, 3474, +0, 3190, 3474, +0, 3190, 3474, +0, 3191, 3474, +0, 3191, 3473, +0, 3192, 3473, +0, 3192, 3472, +0, 3193, 3471, +0, 3195, 3470, +0, 3196, 3469, +0, 3198, 3467, +0, 3201, 3464, +0, 3205, 3461, +0, 3210, 3456, +0, 3217, 3449, +0, 3226, 3441, +0, 3238, 3429, +0, 3253, 3412, +0, 3272, 3389, +0, 3297, 3355, +0, 3328, 3307, +0, 3367, 3233, +0, 3414, 3109, +0, 3470, 2865, +0, 3535, 1466, +0, 3611, 0, +0, 3695, 0, +0, 3788, 0, +0, 3192, 3481, +0, 3192, 3481, +0, 3192, 3481, +0, 3192, 3481, +0, 3192, 3481, +0, 3192, 3481, +0, 3192, 3481, +0, 3193, 3481, +0, 3193, 3480, +0, 3193, 3480, +0, 3194, 3479, +0, 3195, 3478, +0, 3196, 3477, +0, 3198, 3476, +0, 3200, 3474, +0, 3203, 3471, +0, 3207, 3468, +0, 3212, 3463, +0, 3219, 3457, +0, 3228, 3448, +0, 3239, 3436, +0, 3254, 3420, +0, 3274, 3397, +0, 3298, 3364, +0, 3329, 3317, +0, 3368, 3244, +0, 3415, 3125, +0, 3471, 2891, +0, 3536, 1839, +0, 3611, 0, +0, 3695, 0, +0, 3788, 0, +0, 3194, 3491, +0, 3194, 3491, +0, 3194, 3490, +0, 3194, 3490, +0, 3194, 3490, +0, 3194, 3490, +0, 3195, 3490, +0, 3195, 3490, +0, 3195, 3489, +0, 3196, 3489, +0, 3197, 3488, +0, 3197, 3488, +0, 3199, 3487, +0, 3200, 3485, +0, 3202, 3483, +0, 3205, 3481, +0, 3209, 3477, +0, 3214, 3473, +0, 3221, 3466, +0, 3230, 3458, +0, 3241, 3446, +0, 3256, 3430, +0, 3276, 3408, +0, 3300, 3376, +0, 3331, 3330, +0, 3370, 3259, +0, 3416, 3144, +0, 3472, 2923, +0, 3537, 2093, +0, 3612, 0, +0, 3696, 0, +0, 3789, 0, +0, 3197, 3502, +0, 3197, 3502, +0, 3197, 3502, +0, 3197, 3502, +0, 3197, 3502, +0, 3198, 3502, +0, 3198, 3502, +0, 3198, 3502, +0, 3199, 3501, +0, 3199, 3501, +0, 3200, 3500, +0, 3201, 3500, +0, 3202, 3498, +0, 3203, 3497, +0, 3206, 3495, +0, 3209, 3493, +0, 3212, 3489, +0, 3217, 3485, +0, 3224, 3479, +0, 3233, 3471, +0, 3244, 3459, +0, 3259, 3444, +0, 3278, 3422, +0, 3303, 3391, +0, 3334, 3347, +0, 3372, 3279, +0, 3418, 3169, +0, 3474, 2963, +0, 3539, 2299, +0, 3613, 0, +0, 3697, 0, +0, 3790, 0, +0, 3201, 3518, +0, 3201, 3518, +0, 3202, 3518, +0, 3202, 3518, +0, 3202, 3518, +0, 3202, 3517, +0, 3202, 3517, +0, 3202, 3517, +0, 3203, 3517, +0, 3203, 3516, +0, 3204, 3516, +0, 3205, 3515, +0, 3206, 3514, +0, 3208, 3513, +0, 3210, 3511, +0, 3213, 3508, +0, 3216, 3505, +0, 3221, 3501, +0, 3228, 3495, +0, 3237, 3487, +0, 3248, 3476, +0, 3263, 3461, +0, 3282, 3440, +0, 3306, 3411, +0, 3337, 3368, +0, 3375, 3304, +0, 3421, 3201, +0, 3476, 3012, +0, 3541, 2479, +0, 3615, 0, +0, 3699, 0, +0, 3791, 0, +0, 3207, 3538, +0, 3207, 3538, +0, 3207, 3537, +0, 3207, 3537, +0, 3207, 3537, +0, 3207, 3537, +0, 3208, 3537, +0, 3208, 3537, +0, 3208, 3537, +0, 3209, 3536, +0, 3210, 3536, +0, 3210, 3535, +0, 3212, 3534, +0, 3213, 3533, +0, 3215, 3531, +0, 3218, 3529, +0, 3222, 3526, +0, 3227, 3521, +0, 3233, 3516, +0, 3242, 3508, +0, 3253, 3498, +0, 3268, 3483, +0, 3287, 3464, +0, 3311, 3436, +0, 3341, 3395, +0, 3379, 3335, +0, 3424, 3240, +0, 3479, 3069, +0, 3544, 2644, +0, 3617, 0, +0, 3701, 0, +0, 3792, 0, +1728, 3214, 3563, +1725, 3214, 3563, +1722, 3215, 3563, +1717, 3215, 3563, +1710, 3215, 3563, +1701, 3215, 3562, +1688, 3215, 3562, +1671, 3215, 3562, +1647, 3216, 3562, +1612, 3216, 3561, +1562, 3217, 3561, +1483, 3218, 3560, +1352, 3219, 3559, +1082, 3220, 3558, +0, 3223, 3557, +0, 3225, 3554, +0, 3229, 3551, +0, 3234, 3548, +0, 3240, 3542, +0, 3249, 3535, +0, 3260, 3525, +0, 3274, 3512, +0, 3293, 3493, +0, 3317, 3467, +0, 3346, 3429, +0, 3384, 3374, +0, 3429, 3287, +0, 3483, 3137, +0, 3547, 2799, +0, 3620, 0, +0, 3703, 0, +0, 3794, 0, +2722, 3224, 3594, +2721, 3224, 3594, +2721, 3224, 3594, +2720, 3224, 3594, +2720, 3224, 3594, +2719, 3225, 3594, +2717, 3225, 3594, +2716, 3225, 3594, +2713, 3225, 3593, +2710, 3226, 3593, +2706, 3227, 3593, +2700, 3227, 3592, +2692, 3229, 3591, +2681, 3230, 3590, +2666, 3232, 3589, +2646, 3235, 3587, +2617, 3238, 3584, +2574, 3243, 3580, +2511, 3250, 3575, +2410, 3258, 3569, +2224, 3269, 3559, +1718, 3283, 3547, +0, 3301, 3530, +0, 3324, 3506, +0, 3354, 3471, +0, 3390, 3421, +0, 3435, 3343, +0, 3489, 3214, +0, 3552, 2948, +0, 3624, 0, +0, 3706, 0, +0, 3797, 0, +3077, 3237, 3634, +3077, 3237, 3634, +3077, 3237, 3633, +3077, 3237, 3633, +3076, 3237, 3633, +3076, 3237, 3633, +3075, 3237, 3633, +3075, 3238, 3633, +3073, 3238, 3633, +3072, 3239, 3632, +3070, 3239, 3632, +3068, 3240, 3631, +3064, 3241, 3631, +3059, 3243, 3630, +3053, 3245, 3628, +3044, 3247, 3626, +3032, 3251, 3624, +3016, 3255, 3621, +2993, 3262, 3616, +2960, 3270, 3610, +2913, 3280, 3602, +2840, 3294, 3590, +2720, 3312, 3575, +2485, 3335, 3553, +1404, 3363, 3522, +0, 3399, 3477, +0, 3443, 3409, +0, 3496, 3299, +0, 3558, 3092, +0, 3630, 2417, +0, 3711, 0, +0, 3801, 0, +3325, 3253, 3681, +3325, 3253, 3681, +3325, 3253, 3681, +3325, 3253, 3681, +3325, 3254, 3681, +3325, 3254, 3681, +3324, 3254, 3681, +3324, 3254, 3681, +3323, 3254, 3680, +3322, 3255, 3680, +3321, 3255, 3680, +3320, 3256, 3679, +3318, 3257, 3678, +3315, 3259, 3678, +3311, 3261, 3676, +3306, 3263, 3675, +3300, 3267, 3672, +3291, 3271, 3669, +3278, 3277, 3665, +3261, 3285, 3660, +3237, 3295, 3652, +3203, 3308, 3642, +3153, 3326, 3628, +3076, 3348, 3609, +2947, 3376, 3582, +2685, 3411, 3543, +0, 3454, 3485, +0, 3505, 3394, +0, 3566, 3233, +0, 3637, 2852, +0, 3717, 0, +0, 3805, 0, +3528, 3274, 3738, +3528, 3274, 3738, +3528, 3274, 3738, +3528, 3274, 3738, +3528, 3275, 3738, +3528, 3275, 3738, +3527, 3275, 3737, +3527, 3275, 3737, +3527, 3275, 3737, +3526, 3276, 3737, +3525, 3276, 3737, +3525, 3277, 3736, +3523, 3278, 3735, +3522, 3280, 3735, +3519, 3281, 3734, +3516, 3284, 3732, +3512, 3287, 3730, +3506, 3291, 3728, +3499, 3297, 3724, +3488, 3305, 3719, +3474, 3314, 3713, +3454, 3327, 3704, +3426, 3344, 3692, +3385, 3365, 3675, +3324, 3392, 3652, +3228, 3426, 3618, +3055, 3467, 3570, +2618, 3517, 3495, +0, 3577, 3371, +0, 3646, 3125, +0, 3724, 1639, +0, 3812, 0, +3707, 3301, 3804, +3707, 3301, 3804, +3707, 3301, 3804, +3707, 3301, 3804, +3707, 3301, 3804, +3706, 3301, 3804, +3706, 3302, 3804, +3706, 3302, 3804, +3706, 3302, 3803, +3705, 3303, 3803, +3705, 3303, 3803, +3704, 3304, 3803, +3703, 3305, 3802, +3702, 3306, 3801, +3701, 3308, 3800, +3699, 3310, 3799, +3696, 3313, 3797, +3692, 3317, 3795, +3687, 3323, 3792, +3680, 3330, 3788, +3671, 3339, 3782, +3658, 3351, 3775, +3640, 3367, 3764, +3615, 3387, 3750, +3580, 3413, 3730, +3527, 3445, 3703, +3446, 3485, 3663, +3308, 3533, 3603, +3017, 3591, 3508, +0, 3658, 3340, +0, 3734, 2924, +0, 3820, 0, +3871, 3334, 3880, +3871, 3334, 3880, +3871, 3335, 3880, +3871, 3335, 3880, +3871, 3335, 3880, +3871, 3335, 3880, +3870, 3335, 3880, +3870, 3335, 3879, +3870, 3335, 3879, +3870, 3336, 3879, +3869, 3336, 3879, +3869, 3337, 3879, +3868, 3338, 3878, +3868, 3339, 3878, +3867, 3341, 3877, +3865, 3343, 3876, +3863, 3346, 3874, +3861, 3349, 3872, +3857, 3354, 3870, +3852, 3361, 3866, +3846, 3370, 3862, +3837, 3381, 3855, +3825, 3396, 3846, +3809, 3415, 3835, +3786, 3439, 3818, +3753, 3470, 3796, +3706, 3507, 3763, +3633, 3554, 3716, +3513, 3609, 3644, +3279, 3673, 3525, +2216, 3748, 3294, +0, 3831, 2303, +4025, 3376, 3965, +4025, 3376, 3965, +4025, 3376, 3965, +4025, 3376, 3965, +4025, 3376, 3965, +4025, 3376, 3965, +4025, 3376, 3964, +4025, 3376, 3964, +4025, 3377, 3964, +4025, 3377, 3964, +4024, 3377, 3964, +4024, 3378, 3964, +4024, 3379, 3963, +4023, 3380, 3963, +4022, 3381, 3962, +4021, 3383, 3961, +4020, 3386, 3960, +4018, 3389, 3958, +4016, 3394, 3956, +4012, 3400, 3953, +4008, 3408, 3950, +4002, 3418, 3944, +3993, 3432, 3937, +3982, 3450, 3928, +3967, 3472, 3914, +3945, 3501, 3896, +3914, 3536, 3870, +3870, 3579, 3833, +3803, 3632, 3779, +3693, 3693, 3693, +3489, 3765, 3547, +2837, 3845, 3224, +4095, 3425, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3426, 4058, +4095, 3427, 4057, +4095, 3427, 4057, +4095, 3428, 4057, +4095, 3428, 4057, +4095, 3429, 4056, +4095, 3431, 4056, +4095, 3432, 4055, +4095, 3435, 4054, +4095, 3438, 4053, +4095, 3442, 4051, +4095, 3447, 4049, +4095, 3455, 4046, +4095, 3464, 4041, +4095, 3476, 4036, +4095, 3492, 4028, +4095, 3513, 4017, +4095, 3539, 4003, +4095, 3572, 3982, +4067, 3612, 3954, +4024, 3661, 3913, +3961, 3719, 3851, +3858, 3787, 3752, +3671, 3864, 3575, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3485, 4095, +4095, 3486, 4095, +4095, 3486, 4095, +4095, 3486, 4095, +4095, 3487, 4095, +4095, 3488, 4095, +4095, 3489, 4095, +4095, 3491, 4095, +4095, 3493, 4095, +4095, 3495, 4095, +4095, 3499, 4095, +4095, 3504, 4095, +4095, 3510, 4095, +4095, 3519, 4095, +4095, 3530, 4095, +4095, 3544, 4095, +4095, 3562, 4095, +4095, 3586, 4095, +4095, 3615, 4095, +4095, 3652, 4077, +4095, 3697, 4046, +4095, 3751, 4001, +4095, 3814, 3932, +4014, 3887, 3821, +0, 3316, 3586, +0, 3316, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3585, +0, 3317, 3585, +0, 3317, 3585, +0, 3317, 3585, +0, 3318, 3584, +0, 3318, 3584, +0, 3319, 3583, +0, 3320, 3582, +0, 3321, 3581, +0, 3323, 3580, +0, 3325, 3578, +0, 3328, 3575, +0, 3332, 3571, +0, 3337, 3566, +0, 3344, 3559, +0, 3353, 3550, +0, 3365, 3537, +0, 3380, 3520, +0, 3400, 3495, +0, 3425, 3460, +0, 3456, 3408, +0, 3495, 3328, +0, 3543, 3193, +0, 3599, 2911, +0, 3665, 0, +0, 3740, 0, +0, 3825, 0, +0, 3316, 3586, +0, 3316, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3585, +0, 3317, 3585, +0, 3317, 3585, +0, 3317, 3585, +0, 3318, 3585, +0, 3318, 3584, +0, 3319, 3583, +0, 3320, 3583, +0, 3321, 3581, +0, 3323, 3580, +0, 3325, 3578, +0, 3328, 3575, +0, 3332, 3571, +0, 3337, 3566, +0, 3344, 3559, +0, 3353, 3550, +0, 3365, 3537, +0, 3380, 3520, +0, 3400, 3495, +0, 3425, 3460, +0, 3456, 3408, +0, 3495, 3328, +0, 3543, 3193, +0, 3599, 2911, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3316, 3586, +0, 3316, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3585, +0, 3317, 3585, +0, 3318, 3585, +0, 3318, 3585, +0, 3318, 3584, +0, 3319, 3583, +0, 3320, 3583, +0, 3321, 3581, +0, 3323, 3580, +0, 3325, 3578, +0, 3328, 3575, +0, 3332, 3571, +0, 3337, 3566, +0, 3344, 3560, +0, 3353, 3550, +0, 3365, 3538, +0, 3380, 3520, +0, 3400, 3495, +0, 3425, 3460, +0, 3456, 3408, +0, 3495, 3329, +0, 3543, 3194, +0, 3599, 2911, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3316, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3585, +0, 3317, 3585, +0, 3318, 3585, +0, 3318, 3585, +0, 3318, 3584, +0, 3319, 3584, +0, 3320, 3583, +0, 3321, 3582, +0, 3323, 3580, +0, 3325, 3578, +0, 3328, 3575, +0, 3332, 3571, +0, 3337, 3566, +0, 3344, 3560, +0, 3353, 3550, +0, 3365, 3538, +0, 3380, 3520, +0, 3400, 3495, +0, 3425, 3460, +0, 3456, 3409, +0, 3495, 3329, +0, 3543, 3194, +0, 3599, 2912, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3585, +0, 3318, 3585, +0, 3318, 3585, +0, 3318, 3584, +0, 3319, 3584, +0, 3320, 3583, +0, 3321, 3582, +0, 3323, 3580, +0, 3325, 3578, +0, 3328, 3575, +0, 3332, 3572, +0, 3337, 3567, +0, 3344, 3560, +0, 3353, 3551, +0, 3365, 3538, +0, 3380, 3520, +0, 3400, 3496, +0, 3425, 3460, +0, 3456, 3409, +0, 3495, 3329, +0, 3543, 3194, +0, 3599, 2912, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3318, 3585, +0, 3318, 3585, +0, 3319, 3584, +0, 3319, 3584, +0, 3320, 3583, +0, 3321, 3582, +0, 3323, 3580, +0, 3325, 3578, +0, 3328, 3576, +0, 3332, 3572, +0, 3337, 3567, +0, 3344, 3560, +0, 3353, 3551, +0, 3365, 3538, +0, 3380, 3520, +0, 3400, 3496, +0, 3425, 3461, +0, 3456, 3409, +0, 3495, 3329, +0, 3543, 3194, +0, 3599, 2913, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3318, 3586, +0, 3318, 3585, +0, 3319, 3585, +0, 3319, 3584, +0, 3320, 3583, +0, 3321, 3582, +0, 3323, 3581, +0, 3325, 3579, +0, 3328, 3576, +0, 3332, 3572, +0, 3337, 3567, +0, 3344, 3560, +0, 3353, 3551, +0, 3365, 3538, +0, 3380, 3521, +0, 3400, 3496, +0, 3425, 3461, +0, 3456, 3409, +0, 3495, 3330, +0, 3543, 3195, +0, 3599, 2914, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3586, +0, 3317, 3586, +0, 3317, 3586, +0, 3318, 3586, +0, 3318, 3585, +0, 3319, 3585, +0, 3319, 3584, +0, 3320, 3584, +0, 3322, 3582, +0, 3323, 3581, +0, 3325, 3579, +0, 3328, 3576, +0, 3332, 3572, +0, 3338, 3567, +0, 3344, 3561, +0, 3353, 3551, +0, 3365, 3539, +0, 3380, 3521, +0, 3400, 3496, +0, 3425, 3461, +0, 3456, 3410, +0, 3495, 3330, +0, 3543, 3196, +0, 3599, 2915, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3318, 3587, +0, 3318, 3586, +0, 3318, 3586, +0, 3319, 3585, +0, 3319, 3585, +0, 3320, 3584, +0, 3322, 3583, +0, 3323, 3581, +0, 3326, 3579, +0, 3328, 3576, +0, 3332, 3573, +0, 3338, 3568, +0, 3344, 3561, +0, 3353, 3552, +0, 3365, 3539, +0, 3380, 3521, +0, 3400, 3497, +0, 3425, 3462, +0, 3457, 3410, +0, 3495, 3331, +0, 3543, 3197, +0, 3599, 2917, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3587, +0, 3317, 3587, +0, 3317, 3587, +0, 3318, 3587, +0, 3318, 3587, +0, 3318, 3586, +0, 3319, 3586, +0, 3320, 3585, +0, 3321, 3584, +0, 3322, 3583, +0, 3323, 3582, +0, 3326, 3580, +0, 3329, 3577, +0, 3333, 3573, +0, 3338, 3568, +0, 3345, 3561, +0, 3354, 3552, +0, 3365, 3540, +0, 3381, 3522, +0, 3400, 3498, +0, 3425, 3463, +0, 3457, 3411, +0, 3496, 3332, +0, 3543, 3198, +0, 3599, 2919, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3588, +0, 3317, 3588, +0, 3318, 3588, +0, 3318, 3588, +0, 3318, 3587, +0, 3319, 3587, +0, 3319, 3587, +0, 3320, 3586, +0, 3321, 3585, +0, 3322, 3584, +0, 3324, 3583, +0, 3326, 3580, +0, 3329, 3578, +0, 3333, 3574, +0, 3338, 3569, +0, 3345, 3562, +0, 3354, 3553, +0, 3365, 3540, +0, 3381, 3523, +0, 3400, 3498, +0, 3425, 3464, +0, 3457, 3412, +0, 3496, 3333, +0, 3543, 3200, +0, 3599, 2922, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3317, 3589, +0, 3317, 3589, +0, 3317, 3589, +0, 3317, 3589, +0, 3318, 3589, +0, 3318, 3589, +0, 3318, 3589, +0, 3318, 3589, +0, 3318, 3588, +0, 3319, 3588, +0, 3319, 3588, +0, 3320, 3587, +0, 3321, 3586, +0, 3322, 3585, +0, 3324, 3583, +0, 3326, 3581, +0, 3329, 3579, +0, 3333, 3575, +0, 3338, 3570, +0, 3345, 3563, +0, 3354, 3554, +0, 3366, 3541, +0, 3381, 3524, +0, 3401, 3500, +0, 3426, 3465, +0, 3457, 3414, +0, 3496, 3335, +0, 3543, 3202, +0, 3600, 2927, +0, 3665, 0, +0, 3741, 0, +0, 3825, 0, +0, 3318, 3591, +0, 3318, 3591, +0, 3318, 3591, +0, 3318, 3590, +0, 3318, 3590, +0, 3318, 3590, +0, 3318, 3590, +0, 3318, 3590, +0, 3319, 3590, +0, 3319, 3589, +0, 3320, 3589, +0, 3320, 3588, +0, 3321, 3587, +0, 3323, 3586, +0, 3324, 3585, +0, 3326, 3583, +0, 3329, 3580, +0, 3333, 3576, +0, 3338, 3571, +0, 3345, 3565, +0, 3354, 3555, +0, 3366, 3543, +0, 3381, 3525, +0, 3401, 3501, +0, 3426, 3466, +0, 3457, 3415, +0, 3496, 3337, +0, 3543, 3205, +0, 3600, 2932, +0, 3666, 0, +0, 3741, 0, +0, 3826, 0, +0, 3318, 3592, +0, 3318, 3592, +0, 3318, 3592, +0, 3318, 3592, +0, 3318, 3592, +0, 3318, 3592, +0, 3319, 3592, +0, 3319, 3592, +0, 3319, 3591, +0, 3320, 3591, +0, 3320, 3591, +0, 3321, 3590, +0, 3322, 3589, +0, 3323, 3588, +0, 3325, 3586, +0, 3327, 3584, +0, 3330, 3582, +0, 3334, 3578, +0, 3339, 3573, +0, 3346, 3566, +0, 3355, 3557, +0, 3366, 3545, +0, 3382, 3527, +0, 3401, 3503, +0, 3426, 3469, +0, 3458, 3418, +0, 3496, 3340, +0, 3544, 3209, +0, 3600, 2939, +0, 3666, 0, +0, 3741, 0, +0, 3826, 0, +0, 3319, 3595, +0, 3319, 3595, +0, 3319, 3594, +0, 3319, 3594, +0, 3319, 3594, +0, 3319, 3594, +0, 3319, 3594, +0, 3319, 3594, +0, 3320, 3594, +0, 3320, 3593, +0, 3321, 3593, +0, 3321, 3592, +0, 3322, 3591, +0, 3324, 3590, +0, 3325, 3589, +0, 3327, 3587, +0, 3330, 3584, +0, 3334, 3580, +0, 3339, 3575, +0, 3346, 3569, +0, 3355, 3560, +0, 3367, 3547, +0, 3382, 3530, +0, 3402, 3506, +0, 3427, 3472, +0, 3458, 3421, +0, 3497, 3344, +0, 3544, 3214, +0, 3600, 2948, +0, 3666, 0, +0, 3741, 0, +0, 3826, 0, +0, 3319, 3598, +0, 3319, 3597, +0, 3320, 3597, +0, 3320, 3597, +0, 3320, 3597, +0, 3320, 3597, +0, 3320, 3597, +0, 3320, 3597, +0, 3320, 3597, +0, 3321, 3596, +0, 3321, 3596, +0, 3322, 3595, +0, 3323, 3594, +0, 3324, 3593, +0, 3326, 3592, +0, 3328, 3590, +0, 3331, 3587, +0, 3335, 3583, +0, 3340, 3579, +0, 3347, 3572, +0, 3356, 3563, +0, 3368, 3550, +0, 3383, 3533, +0, 3402, 3510, +0, 3427, 3475, +0, 3459, 3426, +0, 3497, 3349, +0, 3544, 3221, +0, 3601, 2961, +0, 3666, 0, +0, 3742, 0, +0, 3826, 0, +0, 3320, 3601, +0, 3320, 3601, +0, 3321, 3601, +0, 3321, 3601, +0, 3321, 3601, +0, 3321, 3601, +0, 3321, 3601, +0, 3321, 3601, +0, 3321, 3601, +0, 3322, 3600, +0, 3322, 3600, +0, 3323, 3599, +0, 3324, 3598, +0, 3325, 3597, +0, 3327, 3596, +0, 3329, 3594, +0, 3332, 3591, +0, 3336, 3587, +0, 3341, 3583, +0, 3348, 3576, +0, 3357, 3567, +0, 3368, 3555, +0, 3384, 3538, +0, 3403, 3514, +0, 3428, 3481, +0, 3459, 3431, +0, 3498, 3356, +0, 3545, 3230, +0, 3601, 2976, +0, 3667, 238, +0, 3742, 0, +0, 3826, 0, +0, 3322, 3607, +0, 3322, 3607, +0, 3322, 3607, +0, 3322, 3607, +0, 3322, 3606, +0, 3322, 3606, +0, 3322, 3606, +0, 3323, 3606, +0, 3323, 3606, +0, 3323, 3605, +0, 3324, 3605, +0, 3324, 3604, +0, 3325, 3604, +0, 3327, 3603, +0, 3328, 3601, +0, 3330, 3599, +0, 3333, 3596, +0, 3337, 3593, +0, 3342, 3588, +0, 3349, 3582, +0, 3358, 3573, +0, 3370, 3561, +0, 3385, 3544, +0, 3404, 3521, +0, 3429, 3487, +0, 3460, 3439, +0, 3499, 3365, +0, 3546, 3241, +0, 3602, 2997, +0, 3668, 1599, +0, 3743, 0, +0, 3827, 0, +0, 3324, 3614, +0, 3324, 3614, +0, 3324, 3614, +0, 3324, 3613, +0, 3324, 3613, +0, 3324, 3613, +0, 3324, 3613, +0, 3324, 3613, +0, 3325, 3613, +0, 3325, 3612, +0, 3326, 3612, +0, 3326, 3611, +0, 3327, 3611, +0, 3328, 3609, +0, 3330, 3608, +0, 3332, 3606, +0, 3335, 3603, +0, 3339, 3600, +0, 3344, 3595, +0, 3351, 3589, +0, 3360, 3580, +0, 3371, 3568, +0, 3386, 3552, +0, 3406, 3529, +0, 3431, 3496, +0, 3462, 3449, +0, 3500, 3376, +0, 3547, 3257, +0, 3603, 3023, +0, 3668, 1971, +0, 3743, 0, +0, 3827, 0, +0, 3326, 3623, +0, 3326, 3623, +0, 3326, 3623, +0, 3326, 3623, +0, 3326, 3622, +0, 3326, 3622, +0, 3327, 3622, +0, 3327, 3622, +0, 3327, 3622, +0, 3327, 3621, +0, 3328, 3621, +0, 3329, 3620, +0, 3330, 3620, +0, 3331, 3619, +0, 3332, 3617, +0, 3335, 3615, +0, 3337, 3613, +0, 3341, 3609, +0, 3346, 3605, +0, 3353, 3598, +0, 3362, 3590, +0, 3374, 3578, +0, 3388, 3562, +0, 3408, 3540, +0, 3432, 3508, +0, 3463, 3462, +0, 3502, 3392, +0, 3548, 3276, +0, 3604, 3055, +0, 3669, 2225, +0, 3744, 0, +0, 3828, 0, +0, 3329, 3635, +0, 3329, 3635, +0, 3329, 3634, +0, 3329, 3634, +0, 3329, 3634, +0, 3330, 3634, +0, 3330, 3634, +0, 3330, 3634, +0, 3330, 3634, +0, 3331, 3633, +0, 3331, 3633, +0, 3332, 3632, +0, 3333, 3632, +0, 3334, 3631, +0, 3336, 3629, +0, 3338, 3627, +0, 3341, 3625, +0, 3344, 3622, +0, 3349, 3617, +0, 3356, 3611, +0, 3365, 3603, +0, 3376, 3591, +0, 3391, 3576, +0, 3410, 3554, +0, 3435, 3523, +0, 3466, 3479, +0, 3504, 3411, +0, 3550, 3301, +0, 3606, 3095, +0, 3671, 2431, +0, 3746, 0, +0, 3829, 0, +0, 3333, 3650, +0, 3333, 3650, +0, 3334, 3650, +0, 3334, 3650, +0, 3334, 3650, +0, 3334, 3650, +0, 3334, 3649, +0, 3334, 3649, +0, 3334, 3649, +0, 3335, 3649, +0, 3335, 3648, +0, 3336, 3648, +0, 3337, 3647, +0, 3338, 3646, +0, 3340, 3645, +0, 3342, 3643, +0, 3345, 3641, +0, 3349, 3637, +0, 3354, 3633, +0, 3360, 3627, +0, 3369, 3619, +0, 3380, 3608, +0, 3395, 3593, +0, 3414, 3572, +0, 3438, 3543, +0, 3469, 3500, +0, 3507, 3436, +0, 3553, 3333, +0, 3608, 3144, +0, 3673, 2611, +0, 3747, 0, +0, 3831, 0, +0, 3339, 3670, +0, 3339, 3670, +0, 3339, 3670, +0, 3339, 3670, +0, 3339, 3670, +0, 3339, 3669, +0, 3340, 3669, +0, 3340, 3669, +0, 3340, 3669, +0, 3340, 3669, +0, 3341, 3668, +0, 3342, 3668, +0, 3343, 3667, +0, 3344, 3666, +0, 3345, 3665, +0, 3347, 3663, +0, 3350, 3661, +0, 3354, 3658, +0, 3359, 3654, +0, 3365, 3648, +0, 3374, 3640, +0, 3385, 3630, +0, 3400, 3616, +0, 3419, 3596, +0, 3443, 3568, +0, 3473, 3527, +0, 3511, 3467, +0, 3556, 3372, +0, 3611, 3202, +0, 3676, 2776, +0, 3750, 0, +0, 3833, 0, +1862, 3346, 3695, +1860, 3347, 3695, +1858, 3347, 3695, +1854, 3347, 3695, +1849, 3347, 3695, +1842, 3347, 3695, +1833, 3347, 3695, +1821, 3347, 3694, +1803, 3347, 3694, +1779, 3348, 3694, +1744, 3348, 3693, +1694, 3349, 3693, +1616, 3350, 3692, +1484, 3351, 3691, +1214, 3353, 3690, +0, 3355, 3689, +0, 3357, 3686, +0, 3361, 3684, +0, 3366, 3680, +0, 3372, 3674, +0, 3381, 3667, +0, 3392, 3657, +0, 3406, 3644, +0, 3425, 3625, +0, 3449, 3599, +0, 3479, 3562, +0, 3516, 3506, +0, 3561, 3419, +0, 3615, 3269, +0, 3679, 2931, +0, 3753, 0, +0, 3835, 0, +2854, 3356, 3727, +2854, 3356, 3727, +2853, 3356, 3726, +2853, 3356, 3726, +2853, 3356, 3726, +2852, 3357, 3726, +2851, 3357, 3726, +2849, 3357, 3726, +2848, 3357, 3726, +2845, 3358, 3726, +2842, 3358, 3725, +2838, 3359, 3725, +2832, 3360, 3724, +2824, 3361, 3723, +2813, 3362, 3722, +2798, 3364, 3721, +2778, 3367, 3719, +2749, 3371, 3716, +2706, 3375, 3712, +2643, 3382, 3707, +2542, 3390, 3701, +2357, 3401, 3692, +1850, 3415, 3679, +0, 3433, 3662, +0, 3456, 3638, +0, 3486, 3604, +0, 3522, 3553, +0, 3567, 3476, +0, 3621, 3346, +0, 3684, 3080, +0, 3757, 0, +0, 3838, 0, +3210, 3369, 3766, +3209, 3369, 3766, +3209, 3369, 3766, +3209, 3369, 3766, +3209, 3369, 3766, +3209, 3369, 3765, +3208, 3369, 3765, +3207, 3370, 3765, +3207, 3370, 3765, +3206, 3370, 3765, +3204, 3371, 3764, +3202, 3371, 3764, +3200, 3372, 3763, +3196, 3373, 3763, +3191, 3375, 3762, +3185, 3377, 3760, +3176, 3379, 3758, +3164, 3383, 3756, +3148, 3387, 3753, +3125, 3394, 3748, +3092, 3402, 3742, +3045, 3412, 3734, +2972, 3426, 3722, +2852, 3444, 3707, +2617, 3467, 3685, +1537, 3495, 3654, +0, 3531, 3609, +0, 3575, 3542, +0, 3628, 3431, +0, 3690, 3224, +0, 3762, 2549, +0, 3843, 0, +3457, 3385, 3813, +3457, 3385, 3813, +3457, 3385, 3813, +3457, 3385, 3813, +3457, 3385, 3813, +3457, 3386, 3813, +3457, 3386, 3813, +3456, 3386, 3813, +3456, 3386, 3813, +3455, 3387, 3812, +3454, 3387, 3812, +3453, 3388, 3812, +3452, 3388, 3811, +3450, 3389, 3811, +3447, 3391, 3810, +3443, 3393, 3808, +3439, 3395, 3807, +3432, 3399, 3805, +3423, 3403, 3802, +3410, 3409, 3797, +3393, 3417, 3792, +3369, 3427, 3785, +3335, 3441, 3774, +3285, 3458, 3761, +3208, 3480, 3741, +3079, 3508, 3714, +2817, 3543, 3675, +0, 3586, 3617, +0, 3637, 3526, +0, 3698, 3365, +0, 3769, 2984, +0, 3849, 0, +3660, 3406, 3870, +3660, 3406, 3870, +3660, 3406, 3870, +3660, 3406, 3870, +3660, 3407, 3870, +3660, 3407, 3870, +3660, 3407, 3870, +3660, 3407, 3870, +3659, 3407, 3869, +3659, 3408, 3869, +3658, 3408, 3869, +3658, 3409, 3869, +3657, 3409, 3868, +3655, 3410, 3868, +3654, 3412, 3867, +3651, 3414, 3866, +3648, 3416, 3864, +3644, 3419, 3862, +3638, 3424, 3860, +3631, 3429, 3856, +3620, 3437, 3851, +3606, 3446, 3845, +3586, 3459, 3836, +3558, 3476, 3824, +3517, 3497, 3807, +3456, 3524, 3784, +3360, 3558, 3750, +3187, 3599, 3702, +2750, 3650, 3627, +0, 3709, 3503, +0, 3778, 3257, +0, 3856, 1771, +3839, 3433, 3936, +3839, 3433, 3936, +3839, 3433, 3936, +3839, 3433, 3936, +3839, 3433, 3936, +3839, 3433, 3936, +3838, 3433, 3936, +3838, 3434, 3936, +3838, 3434, 3936, +3838, 3434, 3936, +3838, 3435, 3935, +3837, 3435, 3935, +3836, 3436, 3935, +3836, 3437, 3934, +3834, 3438, 3933, +3833, 3440, 3932, +3831, 3442, 3931, +3828, 3445, 3930, +3824, 3449, 3927, +3819, 3455, 3924, +3812, 3462, 3920, +3803, 3471, 3914, +3790, 3483, 3907, +3772, 3499, 3897, +3747, 3519, 3882, +3712, 3545, 3863, +3659, 3577, 3835, +3578, 3617, 3795, +3440, 3665, 3735, +3149, 3723, 3640, +0, 3790, 3472, +0, 3867, 3056, +4003, 3467, 4012, +4003, 3467, 4012, +4003, 3467, 4012, +4003, 3467, 4012, +4003, 3467, 4012, +4003, 3467, 4012, +4003, 3467, 4012, +4002, 3467, 4012, +4002, 3467, 4012, +4002, 3468, 4011, +4002, 3468, 4011, +4002, 3468, 4011, +4001, 3469, 4011, +4001, 3470, 4010, +4000, 3471, 4010, +3999, 3473, 4009, +3997, 3475, 4008, +3995, 3478, 4006, +3993, 3482, 4004, +3989, 3487, 4002, +3984, 3493, 3998, +3978, 3502, 3994, +3969, 3513, 3987, +3957, 3528, 3979, +3941, 3547, 3967, +3918, 3571, 3950, +3886, 3602, 3928, +3838, 3640, 3895, +3765, 3686, 3848, +3646, 3741, 3776, +3411, 3806, 3657, +2348, 3880, 3426, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3508, 4095, +4095, 3509, 4095, +4095, 3509, 4095, +4095, 3509, 4095, +4095, 3510, 4095, +4095, 3511, 4095, +4095, 3512, 4095, +4095, 3513, 4094, +4095, 3515, 4093, +4095, 3518, 4092, +4095, 3522, 4091, +4095, 3526, 4088, +4095, 3532, 4086, +4095, 3540, 4082, +4095, 3551, 4076, +4095, 3564, 4069, +4095, 3582, 4060, +4095, 3604, 4046, +4077, 3633, 4028, +4046, 3668, 4002, +4002, 3712, 3965, +3935, 3764, 3911, +3826, 3826, 3826, +3621, 3897, 3679, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3558, 4095, +4095, 3559, 4095, +4095, 3559, 4095, +4095, 3560, 4095, +4095, 3560, 4095, +4095, 3561, 4095, +4095, 3563, 4095, +4095, 3564, 4095, +4095, 3567, 4095, +4095, 3570, 4095, +4095, 3574, 4095, +4095, 3580, 4095, +4095, 3587, 4095, +4095, 3596, 4095, +4095, 3608, 4095, +4095, 3624, 4095, +4095, 3645, 4095, +4095, 3671, 4095, +4095, 3704, 4095, +4095, 3744, 4086, +4095, 3793, 4045, +4093, 3851, 3983, +3990, 3919, 3884, +0, 3448, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3717, +0, 3449, 3717, +0, 3449, 3717, +0, 3450, 3717, +0, 3450, 3717, +0, 3450, 3716, +0, 3451, 3715, +0, 3452, 3715, +0, 3453, 3713, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3707, +0, 3464, 3703, +0, 3469, 3698, +0, 3476, 3691, +0, 3485, 3682, +0, 3497, 3669, +0, 3512, 3652, +0, 3532, 3627, +0, 3557, 3592, +0, 3588, 3540, +0, 3627, 3460, +0, 3675, 3325, +0, 3731, 3043, +0, 3797, 0, +0, 3873, 0, +0, 3448, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3717, +0, 3449, 3717, +0, 3450, 3717, +0, 3450, 3717, +0, 3451, 3716, +0, 3451, 3715, +0, 3452, 3715, +0, 3453, 3713, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3707, +0, 3464, 3703, +0, 3469, 3698, +0, 3476, 3692, +0, 3485, 3682, +0, 3497, 3670, +0, 3512, 3652, +0, 3532, 3627, +0, 3557, 3592, +0, 3588, 3540, +0, 3627, 3460, +0, 3675, 3325, +0, 3731, 3043, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3717, +0, 3449, 3717, +0, 3450, 3717, +0, 3450, 3717, +0, 3451, 3716, +0, 3451, 3716, +0, 3452, 3715, +0, 3453, 3714, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3707, +0, 3464, 3703, +0, 3469, 3698, +0, 3476, 3692, +0, 3485, 3682, +0, 3497, 3670, +0, 3512, 3652, +0, 3532, 3627, +0, 3557, 3592, +0, 3588, 3540, +0, 3627, 3461, +0, 3675, 3326, +0, 3731, 3043, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3717, +0, 3450, 3717, +0, 3450, 3717, +0, 3451, 3716, +0, 3451, 3716, +0, 3452, 3715, +0, 3453, 3714, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3707, +0, 3464, 3703, +0, 3469, 3698, +0, 3476, 3692, +0, 3485, 3682, +0, 3497, 3670, +0, 3512, 3652, +0, 3532, 3627, +0, 3557, 3592, +0, 3588, 3541, +0, 3627, 3461, +0, 3675, 3326, +0, 3731, 3043, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3717, +0, 3450, 3717, +0, 3450, 3717, +0, 3451, 3716, +0, 3451, 3716, +0, 3452, 3715, +0, 3453, 3714, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3707, +0, 3464, 3704, +0, 3469, 3699, +0, 3476, 3692, +0, 3485, 3682, +0, 3497, 3670, +0, 3512, 3652, +0, 3532, 3628, +0, 3557, 3592, +0, 3588, 3541, +0, 3627, 3461, +0, 3675, 3326, +0, 3731, 3044, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3450, 3717, +0, 3450, 3717, +0, 3451, 3716, +0, 3451, 3716, +0, 3452, 3715, +0, 3453, 3714, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3707, +0, 3464, 3704, +0, 3469, 3699, +0, 3476, 3692, +0, 3485, 3683, +0, 3497, 3670, +0, 3512, 3652, +0, 3532, 3628, +0, 3557, 3593, +0, 3588, 3541, +0, 3627, 3461, +0, 3675, 3326, +0, 3731, 3044, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3450, 3717, +0, 3450, 3717, +0, 3451, 3717, +0, 3451, 3716, +0, 3452, 3715, +0, 3454, 3714, +0, 3455, 3712, +0, 3457, 3710, +0, 3460, 3708, +0, 3464, 3704, +0, 3469, 3699, +0, 3476, 3692, +0, 3485, 3683, +0, 3497, 3670, +0, 3512, 3653, +0, 3532, 3628, +0, 3557, 3593, +0, 3588, 3541, +0, 3627, 3461, +0, 3675, 3327, +0, 3731, 3045, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3449, 3718, +0, 3450, 3718, +0, 3450, 3717, +0, 3451, 3717, +0, 3451, 3716, +0, 3452, 3715, +0, 3454, 3714, +0, 3455, 3713, +0, 3457, 3711, +0, 3460, 3708, +0, 3464, 3704, +0, 3470, 3699, +0, 3476, 3692, +0, 3485, 3683, +0, 3497, 3670, +0, 3512, 3653, +0, 3532, 3628, +0, 3557, 3593, +0, 3589, 3541, +0, 3627, 3462, +0, 3675, 3327, +0, 3731, 3046, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3718, +0, 3450, 3718, +0, 3450, 3718, +0, 3450, 3718, +0, 3451, 3717, +0, 3451, 3716, +0, 3452, 3716, +0, 3454, 3714, +0, 3455, 3713, +0, 3458, 3711, +0, 3460, 3708, +0, 3464, 3704, +0, 3470, 3699, +0, 3476, 3693, +0, 3485, 3683, +0, 3497, 3671, +0, 3512, 3653, +0, 3532, 3629, +0, 3557, 3593, +0, 3589, 3542, +0, 3627, 3462, +0, 3675, 3328, +0, 3731, 3047, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3449, 3719, +0, 3450, 3719, +0, 3450, 3718, +0, 3450, 3718, +0, 3451, 3718, +0, 3452, 3717, +0, 3452, 3716, +0, 3454, 3715, +0, 3455, 3713, +0, 3458, 3711, +0, 3461, 3709, +0, 3465, 3705, +0, 3470, 3700, +0, 3477, 3693, +0, 3486, 3684, +0, 3497, 3671, +0, 3513, 3654, +0, 3532, 3629, +0, 3557, 3594, +0, 3589, 3542, +0, 3628, 3463, +0, 3675, 3329, +0, 3731, 3049, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3719, +0, 3450, 3719, +0, 3450, 3719, +0, 3450, 3719, +0, 3450, 3719, +0, 3451, 3718, +0, 3452, 3717, +0, 3453, 3717, +0, 3454, 3715, +0, 3456, 3714, +0, 3458, 3712, +0, 3461, 3709, +0, 3465, 3705, +0, 3470, 3700, +0, 3477, 3694, +0, 3486, 3684, +0, 3497, 3672, +0, 3513, 3654, +0, 3532, 3630, +0, 3557, 3595, +0, 3589, 3543, +0, 3628, 3464, +0, 3675, 3330, +0, 3731, 3051, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3721, +0, 3449, 3721, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3720, +0, 3449, 3720, +0, 3450, 3720, +0, 3450, 3720, +0, 3450, 3720, +0, 3450, 3720, +0, 3451, 3719, +0, 3451, 3719, +0, 3452, 3718, +0, 3453, 3717, +0, 3454, 3716, +0, 3456, 3715, +0, 3458, 3713, +0, 3461, 3710, +0, 3465, 3706, +0, 3470, 3701, +0, 3477, 3694, +0, 3486, 3685, +0, 3498, 3672, +0, 3513, 3655, +0, 3532, 3631, +0, 3557, 3596, +0, 3589, 3544, +0, 3628, 3465, +0, 3675, 3332, +0, 3731, 3055, +0, 3797, 0, +0, 3873, 0, +0, 3449, 3721, +0, 3449, 3721, +0, 3449, 3721, +0, 3450, 3721, +0, 3450, 3721, +0, 3450, 3721, +0, 3450, 3721, +0, 3450, 3721, +0, 3450, 3721, +0, 3450, 3721, +0, 3451, 3720, +0, 3451, 3720, +0, 3452, 3719, +0, 3453, 3718, +0, 3454, 3717, +0, 3456, 3716, +0, 3458, 3714, +0, 3461, 3711, +0, 3465, 3707, +0, 3470, 3702, +0, 3477, 3695, +0, 3486, 3686, +0, 3498, 3674, +0, 3513, 3656, +0, 3533, 3632, +0, 3558, 3597, +0, 3589, 3546, +0, 3628, 3467, +0, 3675, 3334, +0, 3732, 3059, +0, 3798, 0, +0, 3873, 0, +0, 3450, 3723, +0, 3450, 3723, +0, 3450, 3723, +0, 3450, 3723, +0, 3450, 3723, +0, 3450, 3723, +0, 3450, 3722, +0, 3450, 3722, +0, 3451, 3722, +0, 3451, 3722, +0, 3451, 3721, +0, 3452, 3721, +0, 3452, 3720, +0, 3453, 3719, +0, 3455, 3718, +0, 3456, 3717, +0, 3458, 3715, +0, 3461, 3712, +0, 3465, 3708, +0, 3471, 3703, +0, 3477, 3697, +0, 3486, 3687, +0, 3498, 3675, +0, 3513, 3658, +0, 3533, 3633, +0, 3558, 3599, +0, 3589, 3548, +0, 3628, 3469, +0, 3675, 3337, +0, 3732, 3064, +0, 3798, 0, +0, 3873, 0, +0, 3450, 3724, +0, 3450, 3724, +0, 3450, 3724, +0, 3450, 3724, +0, 3450, 3724, +0, 3450, 3724, +0, 3451, 3724, +0, 3451, 3724, +0, 3451, 3724, +0, 3451, 3723, +0, 3452, 3723, +0, 3452, 3723, +0, 3453, 3722, +0, 3454, 3721, +0, 3455, 3720, +0, 3457, 3719, +0, 3459, 3717, +0, 3462, 3714, +0, 3466, 3710, +0, 3471, 3705, +0, 3478, 3698, +0, 3487, 3689, +0, 3498, 3677, +0, 3514, 3659, +0, 3533, 3635, +0, 3558, 3601, +0, 3590, 3550, +0, 3628, 3472, +0, 3676, 3341, +0, 3732, 3071, +0, 3798, 0, +0, 3873, 0, +0, 3451, 3727, +0, 3451, 3727, +0, 3451, 3727, +0, 3451, 3727, +0, 3451, 3727, +0, 3451, 3726, +0, 3451, 3726, +0, 3451, 3726, +0, 3452, 3726, +0, 3452, 3726, +0, 3452, 3725, +0, 3453, 3725, +0, 3453, 3724, +0, 3454, 3723, +0, 3456, 3722, +0, 3457, 3721, +0, 3459, 3719, +0, 3462, 3716, +0, 3466, 3712, +0, 3471, 3708, +0, 3478, 3701, +0, 3487, 3692, +0, 3499, 3679, +0, 3514, 3662, +0, 3534, 3638, +0, 3559, 3604, +0, 3590, 3553, +0, 3629, 3476, +0, 3676, 3346, +0, 3732, 3081, +0, 3798, 0, +0, 3873, 0, +0, 3451, 3730, +0, 3452, 3730, +0, 3452, 3730, +0, 3452, 3730, +0, 3452, 3729, +0, 3452, 3729, +0, 3452, 3729, +0, 3452, 3729, +0, 3452, 3729, +0, 3453, 3729, +0, 3453, 3728, +0, 3453, 3728, +0, 3454, 3727, +0, 3455, 3726, +0, 3456, 3725, +0, 3458, 3724, +0, 3460, 3722, +0, 3463, 3719, +0, 3467, 3716, +0, 3472, 3711, +0, 3479, 3704, +0, 3488, 3695, +0, 3500, 3683, +0, 3515, 3666, +0, 3534, 3642, +0, 3559, 3608, +0, 3591, 3558, +0, 3629, 3481, +0, 3676, 3353, +0, 3733, 3093, +0, 3798, 0, +0, 3874, 0, +0, 3453, 3734, +0, 3453, 3734, +0, 3453, 3734, +0, 3453, 3734, +0, 3453, 3733, +0, 3453, 3733, +0, 3453, 3733, +0, 3453, 3733, +0, 3453, 3733, +0, 3454, 3733, +0, 3454, 3732, +0, 3454, 3732, +0, 3455, 3731, +0, 3456, 3730, +0, 3457, 3729, +0, 3459, 3728, +0, 3461, 3726, +0, 3464, 3723, +0, 3468, 3720, +0, 3473, 3715, +0, 3480, 3708, +0, 3489, 3699, +0, 3501, 3687, +0, 3516, 3670, +0, 3535, 3646, +0, 3560, 3613, +0, 3591, 3563, +0, 3630, 3488, +0, 3677, 3362, +0, 3733, 3109, +0, 3799, 370, +0, 3874, 0, +0, 3454, 3739, +0, 3454, 3739, +0, 3454, 3739, +0, 3454, 3739, +0, 3454, 3739, +0, 3454, 3739, +0, 3454, 3738, +0, 3454, 3738, +0, 3455, 3738, +0, 3455, 3738, +0, 3455, 3738, +0, 3456, 3737, +0, 3457, 3737, +0, 3457, 3736, +0, 3459, 3735, +0, 3460, 3733, +0, 3463, 3731, +0, 3465, 3729, +0, 3469, 3725, +0, 3474, 3720, +0, 3481, 3714, +0, 3490, 3705, +0, 3502, 3693, +0, 3517, 3676, +0, 3536, 3653, +0, 3561, 3620, +0, 3592, 3571, +0, 3631, 3497, +0, 3678, 3374, +0, 3734, 3129, +0, 3800, 1731, +0, 3875, 0, +0, 3456, 3746, +0, 3456, 3746, +0, 3456, 3746, +0, 3456, 3746, +0, 3456, 3746, +0, 3456, 3745, +0, 3456, 3745, +0, 3456, 3745, +0, 3456, 3745, +0, 3457, 3745, +0, 3457, 3744, +0, 3458, 3744, +0, 3458, 3743, +0, 3459, 3743, +0, 3460, 3742, +0, 3462, 3740, +0, 3464, 3738, +0, 3467, 3736, +0, 3471, 3732, +0, 3476, 3727, +0, 3483, 3721, +0, 3492, 3712, +0, 3503, 3700, +0, 3518, 3684, +0, 3538, 3661, +0, 3563, 3629, +0, 3594, 3581, +0, 3632, 3508, +0, 3679, 3389, +0, 3735, 3155, +0, 3800, 2103, +0, 3875, 0, +0, 3458, 3755, +0, 3458, 3755, +0, 3458, 3755, +0, 3458, 3755, +0, 3458, 3755, +0, 3458, 3755, +0, 3458, 3754, +0, 3459, 3754, +0, 3459, 3754, +0, 3459, 3754, +0, 3460, 3754, +0, 3460, 3753, +0, 3461, 3753, +0, 3462, 3752, +0, 3463, 3751, +0, 3465, 3749, +0, 3467, 3747, +0, 3470, 3745, +0, 3473, 3741, +0, 3479, 3737, +0, 3485, 3731, +0, 3494, 3722, +0, 3506, 3710, +0, 3521, 3694, +0, 3540, 3672, +0, 3565, 3640, +0, 3595, 3594, +0, 3634, 3524, +0, 3681, 3409, +0, 3736, 3187, +0, 3802, 2357, +0, 3876, 0, +0, 3461, 3767, +0, 3461, 3767, +0, 3461, 3767, +0, 3461, 3767, +0, 3461, 3767, +0, 3462, 3766, +0, 3462, 3766, +0, 3462, 3766, +0, 3462, 3766, +0, 3462, 3766, +0, 3463, 3765, +0, 3463, 3765, +0, 3464, 3764, +0, 3465, 3764, +0, 3466, 3763, +0, 3468, 3761, +0, 3470, 3759, +0, 3473, 3757, +0, 3477, 3754, +0, 3482, 3749, +0, 3488, 3743, +0, 3497, 3735, +0, 3508, 3723, +0, 3523, 3708, +0, 3543, 3686, +0, 3567, 3655, +0, 3598, 3611, +0, 3636, 3543, +0, 3682, 3434, +0, 3738, 3227, +0, 3803, 2563, +0, 3878, 0, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3782, +0, 3466, 3781, +0, 3467, 3781, +0, 3467, 3781, +0, 3467, 3780, +0, 3468, 3780, +0, 3469, 3779, +0, 3470, 3778, +0, 3472, 3777, +0, 3474, 3775, +0, 3477, 3773, +0, 3481, 3769, +0, 3486, 3765, +0, 3492, 3759, +0, 3501, 3751, +0, 3512, 3740, +0, 3527, 3725, +0, 3546, 3704, +0, 3570, 3675, +0, 3601, 3632, +0, 3639, 3568, +0, 3685, 3465, +0, 3740, 3276, +0, 3805, 2743, +0, 3879, 0, +0, 3471, 3802, +0, 3471, 3802, +0, 3471, 3802, +0, 3471, 3802, +0, 3471, 3802, +0, 3471, 3802, +0, 3472, 3802, +0, 3472, 3801, +0, 3472, 3801, +0, 3472, 3801, +0, 3473, 3801, +0, 3473, 3800, +0, 3474, 3800, +0, 3475, 3799, +0, 3476, 3798, +0, 3477, 3797, +0, 3480, 3795, +0, 3482, 3793, +0, 3486, 3790, +0, 3491, 3786, +0, 3498, 3780, +0, 3506, 3772, +0, 3517, 3762, +0, 3532, 3748, +0, 3551, 3728, +0, 3575, 3700, +0, 3605, 3660, +0, 3643, 3599, +0, 3689, 3504, +0, 3743, 3334, +0, 3808, 2908, +0, 3882, 0, +1996, 3479, 3827, +1994, 3479, 3827, +1992, 3479, 3827, +1990, 3479, 3827, +1986, 3479, 3827, +1981, 3479, 3827, +1974, 3479, 3827, +1965, 3479, 3827, +1953, 3479, 3826, +1935, 3480, 3826, +1911, 3480, 3826, +1877, 3480, 3826, +1826, 3481, 3825, +1748, 3482, 3824, +1616, 3483, 3824, +1346, 3485, 3822, +0, 3487, 3821, +0, 3490, 3819, +0, 3493, 3816, +0, 3498, 3812, +0, 3505, 3806, +0, 3513, 3799, +0, 3524, 3789, +0, 3538, 3776, +0, 3557, 3757, +0, 3581, 3731, +0, 3611, 3694, +0, 3648, 3638, +0, 3693, 3551, +0, 3748, 3401, +0, 3811, 3063, +0, 3885, 0, +2986, 3488, 3859, +2986, 3488, 3859, +2986, 3488, 3859, +2986, 3488, 3859, +2985, 3488, 3859, +2985, 3489, 3858, +2984, 3489, 3858, +2983, 3489, 3858, +2982, 3489, 3858, +2980, 3489, 3858, +2977, 3490, 3858, +2974, 3490, 3857, +2970, 3491, 3857, +2964, 3492, 3856, +2956, 3493, 3855, +2945, 3494, 3854, +2931, 3496, 3853, +2910, 3499, 3851, +2881, 3503, 3848, +2839, 3507, 3844, +2775, 3514, 3839, +2674, 3522, 3833, +2489, 3533, 3824, +1982, 3547, 3811, +0, 3565, 3794, +0, 3589, 3770, +0, 3618, 3736, +0, 3655, 3685, +0, 3699, 3608, +0, 3753, 3478, +0, 3816, 3212, +0, 3889, 0, +3342, 3501, 3898, +3342, 3501, 3898, +3342, 3501, 3898, +3341, 3501, 3898, +3341, 3501, 3898, +3341, 3501, 3898, +3341, 3501, 3898, +3340, 3501, 3897, +3340, 3502, 3897, +3339, 3502, 3897, +3338, 3502, 3897, +3336, 3503, 3897, +3334, 3503, 3896, +3332, 3504, 3896, +3328, 3505, 3895, +3323, 3507, 3894, +3317, 3509, 3892, +3308, 3511, 3891, +3296, 3515, 3888, +3280, 3520, 3885, +3257, 3526, 3880, +3224, 3534, 3874, +3177, 3544, 3866, +3104, 3558, 3854, +2984, 3576, 3839, +2749, 3599, 3817, +1669, 3628, 3786, +0, 3663, 3741, +0, 3707, 3674, +0, 3760, 3564, +0, 3822, 3356, +0, 3894, 2681, +3590, 3517, 3945, +3590, 3517, 3945, +3590, 3517, 3945, +3589, 3517, 3945, +3589, 3518, 3945, +3589, 3518, 3945, +3589, 3518, 3945, +3589, 3518, 3945, +3588, 3518, 3945, +3588, 3518, 3945, +3587, 3519, 3945, +3586, 3519, 3944, +3585, 3520, 3944, +3584, 3520, 3943, +3582, 3522, 3943, +3579, 3523, 3942, +3576, 3525, 3941, +3571, 3527, 3939, +3564, 3531, 3937, +3555, 3535, 3934, +3543, 3541, 3930, +3525, 3549, 3924, +3501, 3559, 3917, +3467, 3573, 3907, +3417, 3590, 3893, +3340, 3612, 3873, +3211, 3640, 3846, +2949, 3675, 3807, +0, 3718, 3749, +0, 3769, 3658, +0, 3830, 3497, +0, 3901, 3116, +3792, 3538, 4002, +3792, 3538, 4002, +3792, 3538, 4002, +3792, 3539, 4002, +3792, 3539, 4002, +3792, 3539, 4002, +3792, 3539, 4002, +3792, 3539, 4002, +3792, 3539, 4002, +3791, 3539, 4002, +3791, 3540, 4001, +3790, 3540, 4001, +3790, 3541, 4001, +3789, 3541, 4000, +3787, 3542, 4000, +3786, 3544, 3999, +3783, 3546, 3998, +3780, 3548, 3996, +3776, 3551, 3994, +3770, 3556, 3992, +3763, 3561, 3988, +3752, 3569, 3983, +3738, 3579, 3977, +3718, 3591, 3968, +3690, 3608, 3956, +3649, 3629, 3939, +3588, 3656, 3916, +3492, 3690, 3882, +3319, 3731, 3834, +2882, 3782, 3759, +0, 3841, 3636, +0, 3910, 3389, +3971, 3565, 4068, +3971, 3565, 4068, +3971, 3565, 4068, +3971, 3565, 4068, +3971, 3565, 4068, +3971, 3565, 4068, +3971, 3565, 4068, +3971, 3566, 4068, +3970, 3566, 4068, +3970, 3566, 4068, +3970, 3566, 4068, +3970, 3567, 4067, +3969, 3567, 4067, +3968, 3568, 4067, +3968, 3569, 4066, +3966, 3570, 4066, +3965, 3572, 4065, +3963, 3574, 4063, +3960, 3577, 4062, +3956, 3581, 4059, +3951, 3587, 4056, +3944, 3594, 4052, +3935, 3603, 4047, +3922, 3615, 4039, +3904, 3631, 4029, +3879, 3651, 4014, +3844, 3677, 3995, +3791, 3709, 3967, +3710, 3749, 3927, +3572, 3797, 3867, +3281, 3855, 3772, +0, 3922, 3604, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3599, 4095, +4095, 3600, 4095, +4095, 3600, 4095, +4095, 3601, 4095, +4095, 3601, 4095, +4095, 3602, 4095, +4095, 3603, 4095, +4095, 3605, 4095, +4095, 3607, 4095, +4095, 3610, 4095, +4095, 3614, 4095, +4095, 3619, 4095, +4095, 3625, 4095, +4095, 3634, 4095, +4095, 3645, 4095, +4090, 3660, 4095, +4073, 3679, 4095, +4050, 3703, 4083, +4018, 3734, 4060, +3970, 3772, 4027, +3897, 3818, 3980, +3778, 3873, 3908, +3543, 3938, 3789, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3640, 4095, +4095, 3641, 4095, +4095, 3641, 4095, +4095, 3641, 4095, +4095, 3642, 4095, +4095, 3642, 4095, +4095, 3643, 4095, +4095, 3644, 4095, +4095, 3646, 4095, +4095, 3648, 4095, +4095, 3650, 4095, +4095, 3654, 4095, +4095, 3658, 4095, +4095, 3664, 4095, +4095, 3672, 4095, +4095, 3683, 4095, +4095, 3696, 4095, +4095, 3714, 4095, +4095, 3736, 4095, +4095, 3765, 4095, +4095, 3800, 4095, +4095, 3844, 4095, +4067, 3896, 4043, +3958, 3958, 3958] } -} +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat index c655eb2e6c..56021c0801 100644 --- a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/CMD_ColorGradingTools.bat @@ -17,6 +17,13 @@ TITLE O3DE Color Grading CMD :: Use obvious color to prevent confusion (Grey with Yellow Text) COLOR 8E +echo. +echo _____________________________________________________________________ +echo. +echo ~ O3DE Color Grading Python CMD ... +echo _____________________________________________________________________ +echo. + %~d0 cd %~dp0 PUSHD %~dp0 @@ -27,16 +34,17 @@ SETLOCAL ENABLEDELAYEDEXPANSION IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat :: Initialize env +echo +echo ... calling Env_Core.bat CALL %~dp0\Env_Core.bat + +echo +echo ... calling Env_Python.bat CALL %~dp0\Env_Python.bat -CALL %~dp0\Env_Tools.bat -echo. -echo _____________________________________________________________________ -echo. -echo ~ O3DE Color Grading Python CMD ... -echo _____________________________________________________________________ -echo. +echo +echo ... calling Env_Tools.bat +CALL %~dp0\Env_Tools.bat :: Change to root dir CD /D .. diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat index 730170dce7..74d1e77247 100644 --- a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/Env_Core.bat @@ -93,9 +93,6 @@ popd set DCCSIG_PATH=%O3DE_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface echo DCCSIG_PATH = %DCCSIG_PATH% -:: Change to DCCsi root dir -CD /D %DCCSIG_PATH% - :: per-dcc sdk path set DCCSI_SDK_PATH=%DCCSIG_PATH%\SDK echo DCCSI_SDK_PATH = %DCCSI_SDK_PATH% diff --git a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template index 81a53393cf..973d6d5afd 100644 --- a/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template +++ b/Gems/Atom/Feature/Common/Tools/ColorGrading/cmdline/User_Env.bat.template @@ -26,7 +26,7 @@ SET DCCSI_GDEBUG=True SET DCCSI_DEV_MODE=True :: set the your user name here for windows path -SET TAG_USERNAME=< not set > +SET TAG_USERNAME=NOT_SET SET DCCSI_PY_REV=rev1 SET DCCSI_PY_PLATFORM=windows From 141cb55903a98ac1f52d9946cf612e9b5e945e51 Mon Sep 17 00:00:00 2001 From: bosnichd Date: Fri, 10 Sep 2021 13:12:45 -0600 Subject: [PATCH 043/274] Fix issue #4045 (#4053) * Remove unused Vulkan ShaderDescriptor class. Signed-off-by: bosnichd * Add missing dependency on Gem::Atom_RHI.Public Signed-off-by: bosnichd * Revert changes made to Gems/Atom/RHI/Vulkan/Code/* in https://github.com/o3de/o3de/pull/4021, and instead just check a trait to determine whether the RHI Vulkan targets have been defined else where. Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt maybe needs to be revisited at some point, but my changes are causing numerous issues on mac so this just restores the prior behavior for all platforms while also providing a mechanism for any platform to simply define exactly what Vulkan related targets it needs independently. Signed-off-by: bosnichd --- Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt | 9 +-- .../RHI.Reflect/Vulkan/ShaderDescriptor.h | 57 ------------------ .../ModuleStub_Unimplemented.cpp | 9 +-- .../Source/RHI.Reflect/ShaderDescriptor.cpp | 59 ------------------- .../RHI/Vulkan/Code/Source/RHI/ShaderModule.h | 2 - ...atom_rhi_vulkan_reflect_common_files.cmake | 2 - 6 files changed, 6 insertions(+), 132 deletions(-) delete mode 100644 Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/ShaderDescriptor.h delete mode 100644 Gems/Atom/RHI/Vulkan/Code/Source/RHI.Reflect/ShaderDescriptor.cpp diff --git a/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt b/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt index 5c74852f57..fb13d1fddb 100644 --- a/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt @@ -9,7 +9,11 @@ ly_get_list_relative_pal_filename(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME}) ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED +include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED / PAL_TRAIT_ATOM_RHI_VULKAN_TARGETS_ALREADY_DEFINED + +if(PAL_TRAIT_ATOM_RHI_VULKAN_TARGETS_ALREADY_DEFINED) + return() # Vulkan targets already defined in PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake +endif() if(NOT PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED) @@ -19,12 +23,9 @@ if(NOT PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED) NAMESPACE Gem FILES_CMAKE atom_rhi_vulkan_stub_module.cmake - atom_rhi_vulkan_reflect_common_files.cmake INCLUDE_DIRECTORIES PRIVATE - Include Source - ${pal_include_dir} Include/Atom/RHI.Loader/Glad BUILD_DEPENDENCIES PRIVATE diff --git a/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/ShaderDescriptor.h b/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/ShaderDescriptor.h deleted file mode 100644 index b432dcf0cb..0000000000 --- a/Gems/Atom/RHI/Vulkan/Code/Include/Atom/RHI.Reflect/Vulkan/ShaderDescriptor.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#pragma once - -#include -#include -#include -#include -#include - -namespace AZ -{ - class ReflectContext; - - namespace Vulkan - { - using ShaderByteCode = AZStd::vector; - - // TODO: remove this class after checking it is no longer necessary. - class ShaderDescriptor final - : public RHI::Object - { - using Base = RHI::Object; - public: - AZ_CLASS_ALLOCATOR(ShaderDescriptor, AZ::SystemAllocator, 0); - AZ_RTTI(ShaderDescriptor, "EB289A24-52DF-45E5-B3D0-C33B6DBAAAA7", Base); - - static void Reflect(AZ::ReflectContext* context); - - /// Clears all bytecodes and resets descriptor - void Clear(); - - /// Finalizes the descriptor and builds the hash value. - void Finalize(); - - /// Assigns bytecode to a specific shader stage. - void SetByteCode(RHI::ShaderStage shaderStage, const ShaderByteCode& bytecode); - - /// Returns whether bytecode exists for the given shader stage. - bool HasByteCode(RHI::ShaderStage shaderStage) const; - - /// Returns the bytecode for the given shader stage. - const ShaderByteCode& GetByteCode(RHI::ShaderStage shaderStage) const; - - private: - /// The set of shader bytecodes indexed by shader stage. - AZStd::array(RHI::ShaderStage::GraphicsCount)> m_byteCodesByStage; - size_t m_hash = 0; - }; - - } -} diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp index 44a8a26968..8c06700404 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/Platform/Common/Unimplemented/ModuleStub_Unimplemented.cpp @@ -5,8 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - -#include #include namespace AZ @@ -19,12 +17,7 @@ namespace AZ public: AZ_RTTI(PlatformModule, "{958CB096-796C-42C7-9B29-17C6FE792C30}", Module); - PlatformModule() - { - m_descriptors.insert(m_descriptors.end(), { - ReflectSystemComponent::CreateDescriptor() - }); - } + PlatformModule() = default; ~PlatformModule() override = default; AZ::ComponentTypeList GetRequiredSystemComponents() const override diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Reflect/ShaderDescriptor.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Reflect/ShaderDescriptor.cpp deleted file mode 100644 index b82d72a98c..0000000000 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Reflect/ShaderDescriptor.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ -#include -#include - -namespace AZ -{ - namespace Vulkan - { - void ShaderDescriptor::Reflect(AZ::ReflectContext* context) - { - if (SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("m_byteCodesByStage", &ShaderDescriptor::m_byteCodesByStage); - } - } - - void ShaderDescriptor::Clear() - { - m_hash = 0; - m_byteCodesByStage.fill(ShaderByteCode()); - } - - void ShaderDescriptor::Finalize() - { - AZ::Crc32 crc; - for (const ShaderByteCode& byteCode : m_byteCodesByStage) - { - if (!byteCode.empty()) - { - crc.Add(byteCode.data(), byteCode.size()); - } - } - m_hash = crc; - } - - void ShaderDescriptor::SetByteCode(RHI::ShaderStage shaderStage, const ShaderByteCode& bytecode) - { - m_byteCodesByStage[static_cast(shaderStage)] = bytecode; - } - - bool ShaderDescriptor::HasByteCode(RHI::ShaderStage shaderStage) const - { - return !(m_byteCodesByStage[static_cast(shaderStage)].empty()); - } - - const ShaderByteCode& ShaderDescriptor::GetByteCode(RHI::ShaderStage shaderStage) const - { - return m_byteCodesByStage[static_cast(shaderStage)]; - } - } -} diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderModule.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderModule.h index 244a1c1b82..74632e4539 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderModule.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderModule.h @@ -9,8 +9,6 @@ #include #include -#include -#include #include namespace AZ diff --git a/Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_reflect_common_files.cmake b/Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_reflect_common_files.cmake index 8965cd054d..92c22ddfc5 100644 --- a/Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_reflect_common_files.cmake +++ b/Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_reflect_common_files.cmake @@ -11,8 +11,6 @@ set(FILES Include/Atom/RHI.Reflect/Vulkan/BufferPoolDescriptor.h Source/RHI.Reflect/ImagePoolDescriptor.cpp Include/Atom/RHI.Reflect/Vulkan/ImagePoolDescriptor.h - Source/RHI.Reflect/ShaderDescriptor.cpp - Include/Atom/RHI.Reflect/Vulkan/ShaderDescriptor.h Source/RHI.Reflect/ShaderStageFunction.cpp Include/Atom/RHI.Reflect/Vulkan/ShaderStageFunction.h Source/RHI.Reflect/ReflectSystemComponent.cpp From 2629216e463aef01df4a1bdda5090443817e4374 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Fri, 10 Sep 2021 14:37:32 -0500 Subject: [PATCH 044/274] Optimize MemoryView::SetName (#4052) * Optimize MemoryView SetName Added a second version that uses wstring_view instead of string_view so that no temporaries need to be created when passing in a string literal that's already a wstring. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Changed to use SetPrivateData Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../Code/Source/Platform/Windows/RHI/DX12_Windows.h | 1 + .../Platform/Windows/platform_private_windows.cmake | 1 + .../DX12/Code/Source/RHI/MemoryPageAllocator.cpp | 2 +- Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp | 13 ++++++++++++- Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.h | 3 +++ .../RHI/DX12/Code/Source/RHI/RayTracingBlas.cpp | 4 ++-- .../DX12/Code/Source/RHI/RayTracingShaderTable.cpp | 2 +- .../RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp | 6 +++--- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h index 3f9079422c..85b782aa6b 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h @@ -19,6 +19,7 @@ #include #include +#include // This define is enabled if LY_PIX_ENABLED is enabled during configure. You can use LY_PIX_PATH to point where pix is downloaded. // Enabling this define will allow the runtime code to add PIX markers which will help with pix and renderdoc gpu captures diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows.cmake b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows.cmake index d792c3d2aa..c94b2a020e 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows.cmake +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/platform_private_windows.cmake @@ -10,4 +10,5 @@ set(LY_BUILD_DEPENDENCIES PRIVATE d3d12 dxgi + dxguid ) diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryPageAllocator.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryPageAllocator.cpp index 5692befedf..2715b7063b 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryPageAllocator.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryPageAllocator.cpp @@ -51,7 +51,7 @@ namespace AZ if (memoryView.IsValid()) { heapMemoryUsage.m_residentInBytes += m_descriptor.m_pageSizeInBytes; - memoryView.SetName("BufferPage"); + memoryView.SetName(L"BufferPage"); } else { diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp index c9d932afb1..6389076408 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -95,7 +96,17 @@ namespace AZ { AZStd::wstring wname; AZStd::to_wstring(wname, name); - m_memoryAllocation.m_memory->SetName(wname.data()); + m_memoryAllocation.m_memory->SetPrivateData( + WKPDID_D3DDebugObjectNameW, aznumeric_cast(wname.size() * sizeof(wchar_t)), wname.data()); + } + } + + void MemoryView::SetName(const AZStd::wstring_view& name) + { + if (m_memoryAllocation.m_memory) + { + m_memoryAllocation.m_memory->SetPrivateData( + WKPDID_D3DDebugObjectNameW, aznumeric_cast(name.size() * sizeof(wchar_t)), name.data()); } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.h index a5162d53de..f418af6058 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/MemoryView.h @@ -77,6 +77,9 @@ namespace AZ /// Sets the name of the ID3D12Resource. void SetName(const AZStd::string_view& name); + /// Sets the name of the ID3D12Resource. + void SetName(const AZStd::wstring_view& name); + private: void Construct(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingBlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingBlas.cpp index 917e1a4d98..0f651f9be3 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingBlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingBlas.cpp @@ -83,7 +83,7 @@ namespace AZ AZ_Assert(resultCode == RHI::ResultCode::Success, "failed to create BLAS scratch buffer"); MemoryView& scratchMemoryView = static_cast(buffers.m_scratchBuffer.get())->GetMemoryView(); - scratchMemoryView.SetName("BLAS Scratch"); + scratchMemoryView.SetName(L"BLAS Scratch"); // create BLAS buffer buffers.m_blasBuffer = RHI::Factory::Get().CreateBuffer(); @@ -98,7 +98,7 @@ namespace AZ AZ_Assert(resultCode == RHI::ResultCode::Success, "failed to create BLAS buffer"); MemoryView& blasMemoryView = static_cast(buffers.m_blasBuffer.get())->GetMemoryView(); - blasMemoryView.SetName("BLAS"); + blasMemoryView.SetName(L"BLAS"); #endif return RHI::ResultCode::Success; } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp index 21e7dbc82e..0a9ea63d2f 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingShaderTable.cpp @@ -72,7 +72,7 @@ namespace AZ AZ_Assert(resultCode == RHI::ResultCode::Success, "failed to create shader table buffer"); MemoryView& shaderTableMemoryView = static_cast(shaderTableBuffer.get())->GetMemoryView(); - shaderTableMemoryView.SetName("RayTracingShaderTable"); + shaderTableMemoryView.SetName(L"RayTracingShaderTable"); // copy records RHI::BufferMapResponse mapResponse; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp index 8c4f63aacc..52e4aa4881 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp @@ -66,7 +66,7 @@ namespace AZ AZ_Assert(resultCode == RHI::ResultCode::Success, "failed to create TLAS instances buffer"); MemoryView& tlasInstancesMemoryView = static_cast(buffers.m_tlasInstancesBuffer.get())->GetMemoryView(); - tlasInstancesMemoryView.SetName("TLAS Instance"); + tlasInstancesMemoryView.SetName(L"TLAS Instance"); RHI::BufferMapResponse mapResponse; resultCode = bufferPools.GetTlasInstancesBufferPool()->MapBuffer(RHI::BufferMapRequest(*buffers.m_tlasInstancesBuffer, 0, instanceDescsSizeInBytes), mapResponse); @@ -130,7 +130,7 @@ namespace AZ AZ_Assert(resultCode == RHI::ResultCode::Success, "failed to create TLAS scratch buffer"); MemoryView& scratchMemoryView = static_cast(buffers.m_scratchBuffer.get())->GetMemoryView(); - scratchMemoryView.SetName("TLAS Scratch"); + scratchMemoryView.SetName(L"TLAS Scratch"); // create TLAS buffer buffers.m_tlasBuffer = RHI::Factory::Get().CreateBuffer(); @@ -145,7 +145,7 @@ namespace AZ AZ_Assert(resultCode == RHI::ResultCode::Success, "failed to create TLAS buffer"); MemoryView& tlasMemoryView = static_cast(buffers.m_tlasBuffer.get())->GetMemoryView(); - tlasMemoryView.SetName("TLAS"); + tlasMemoryView.SetName(L"TLAS"); #endif return RHI::ResultCode::Success; } From 3535d6b6b34f8fb342414031fe3256abee10305f Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Fri, 10 Sep 2021 12:56:41 -0700 Subject: [PATCH 045/274] [AWS Automation] Stack tear down mechanism for the deployment on Jenkins (#3656) Make awsi_test_profile_vs2019 a nonblocking step to make sure that resources are cleaned up even though automation tests failed Signed-off-by: Junbo Liang --- .../Gem/PythonTests/AWS/README.md | 22 +++-- .../aws_metrics_automation_test.py | 8 +- .../build/Platform/Windows/build_config.json | 14 ++- .../Windows/destroy_cdk_applications.cmd | 92 +++++++++++++++++++ 4 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 scripts/build/Platform/Windows/destroy_cdk_applications.cmd diff --git a/AutomatedTesting/Gem/PythonTests/AWS/README.md b/AutomatedTesting/Gem/PythonTests/AWS/README.md index 8b5e65d6d7..1429fc487f 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/README.md +++ b/AutomatedTesting/Gem/PythonTests/AWS/README.md @@ -8,19 +8,21 @@ ## Deploy CDK Applications 1. Go to the AWS IAM console and create an IAM role called o3de-automation-tests which adds your own account as as a trusted entity and uses the "AdministratorAccess" permissions policy. 2. Copy {engine_root}\scripts\build\Platform\Windows\deploy_cdk_applications.cmd to your engine root folder. -3. Open a Command Prompt window at the engine root and set the following environment variables: - Set O3DE_AWS_PROJECT_NAME=AWSAUTO - Set O3DE_AWS_DEPLOY_REGION=us-east-1 - Set ASSUME_ROLE_ARN="arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests" - Set COMMIT_ID=HEAD -4. Deploy the CDK applications for AWS gems by running deploy_cdk_applications.cmd in the same Command Prompt window. -5. Edit AWS\common\constants.py to replace the assume role ARN with your own: - arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests +3. Open a new Command Prompt window at the engine root and set the following environment variables: + Set O3DE_AWS_PROJECT_NAME=AWSAUTO + Set O3DE_AWS_DEPLOY_REGION=us-east-1 + Set ASSUME_ROLE_ARN="arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests" + Set COMMIT_ID=HEAD +4. In the same Command Prompt window, Deploy the CDK applications for AWS gems by running deploy_cdk_applications.cmd. ## Run Automation Tests ### CLI -Open a Command Prompt window at the engine root and run the following CLI command: +In the same Command Prompt window, run the following CLI command: python\python.cmd -m pytest {path_to_the_test_file} --build-directory {directory_to_the_profile_build} ### Pycharm -You can also run any specific automation test directly from Pycharm by providing the "--build-directory" argument in the Run Configuration. \ No newline at end of file +You can also run any specific automation test directly from Pycharm by providing the "--build-directory" argument in the Run Configuration. + +## Destroy CDK Applications +1. Copy {engine_root}\scripts\build\Platform\Windows\destroy_cdk_applications.cmd to your engine root folder. +2. In the same Command Prompt window, destroy the CDK applications for AWS gems by running destroy_cdk_applications.cmd. \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py index 1fb35cb9e8..a0a53f92b5 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py +++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py @@ -167,10 +167,6 @@ class TestAWSMetricsWindows(object): args=(aws_metrics_utils, resource_mappings, True)) kinesis_analytics_application_thread.start() - # Clear the analytics bucket objects before sending new metrics. - aws_metrics_utils.empty_bucket( - resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName')) - log_monitor = setup(launcher, asset_processor) # Kinesis analytics application needs to be in the running state before we start the game launcher. @@ -205,6 +201,10 @@ class TestAWSMetricsWindows(object): for thread in operational_threads: thread.join() + # Clear the analytics bucket objects so that the S3 bucket can be destroyed during tear down. + aws_metrics_utils.empty_bucket( + resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName')) + def test_unauthorized_user_request_rejected(self, level: str, launcher: pytest.fixture, diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 689ba6935d..02bd01038a 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -220,13 +220,17 @@ ], "steps": [ "awsi_deployment", - "awsi_test_profile_vs2019" + "awsi_test_profile_vs2019", + "awsi_destruction" ] }, "awsi_test_profile_vs2019": { "TAGS": [ "weekly-build-metrics" ], + "PIPELINE_ENV": { + "NONBLOCKING_STEP": "True" + }, "COMMAND": "build_test_windows.cmd", "PARAMETERS": { "CONFIGURATION": "profile", @@ -411,5 +415,13 @@ }, "COMMAND": "deploy_cdk_applications.cmd", "PARAMETERS": {} + }, + "awsi_destruction": { + "TAGS": [], + "PIPELINE_ENV": { + "NONBLOCKING_STEP": "True" + }, + "COMMAND": "destroy_cdk_applications.cmd", + "PARAMETERS": {} } } diff --git a/scripts/build/Platform/Windows/destroy_cdk_applications.cmd b/scripts/build/Platform/Windows/destroy_cdk_applications.cmd new file mode 100644 index 0000000000..dacc9d327a --- /dev/null +++ b/scripts/build/Platform/Windows/destroy_cdk_applications.cmd @@ -0,0 +1,92 @@ +@ECHO OFF +REM +REM Copyright (c) Contributors to the Open 3D Engine Project. +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM +REM + +REM Destroy the CDK applcations for AWS gems (Windows only) +REM Prerequisites: +REM 1) Node.js is installed +REM 2) Node.js version >= 10.13.0, except for versions 13.0.0 - 13.6.0. A version in active long-term support is recommended. +SETLOCAL EnableDelayedExpansion + +SET SOURCE_DIRECTORY=%CD% +SET PATH=%SOURCE_DIRECTORY%\python;%PATH% +SET GEM_DIRECTORY=%SOURCE_DIRECTORY%\Gems + +REM Create and activate a virtualenv for the CDK destruction +CALL python -m venv .env +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to create a virtualenv for the CDK destruction + exit /b 1 +) +CALL .env\Scripts\activate.bat +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to activate the virtualenv for the CDK destruction + exit /b 1 +) + +ECHO [cdk_installation] Install the latest version of CDK +CALL npm uninstall -g aws-cdk +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to uninstall the current version of CDK + exit /b 1 +) +CALL npm install -g aws-cdk@latest +IF ERRORLEVEL 1 ( + ECHO [cdk_bootstrap] Failed to install the latest version of CDK + exit /b 1 +) + +REM Set temporary AWS credentials from the assume role +FOR /f "tokens=1,2,3" %%a IN ('CALL aws sts assume-role --query Credentials.[SecretAccessKey^,SessionToken^,AccessKeyId] --output text --role-arn %ASSUME_ROLE_ARN% --role-session-name o3de-Automation-session') DO ( + SET AWS_SECRET_ACCESS_KEY=%%a + SET AWS_SESSION_TOKEN=%%b + SET AWS_ACCESS_KEY_ID=%%c +) +FOR /F "tokens=4 delims=:" %%a IN ("%ASSUME_ROLE_ARN%") DO SET O3DE_AWS_DEPLOY_ACCOUNT=%%a + +SET ERROR_EXISTS=0 +CALL :DestroyCDKApplication AWSCore,ERROR_EXISTS +CALL :DestroyCDKApplication AWSClientAuth,ERROR_EXISTS +CALL :DestroyCDKApplication AWSMetrics,ERROR_EXISTS + +IF %ERROR_EXISTS% EQU 1 ( + EXIT /b 1 +) + +EXIT /b 0 + +:DestroyCDKApplication +REM Destroy the CDK application for a specific AWS gem +SET GEM_NAME=%~1 +ECHO [cdk_destruction] Destroy the CDK application for the %GEM_NAME% gem +PUSHD %GEM_DIRECTORY%\%GEM_NAME%\cdk + +REM Revert the CDK application code to a stable state using the provided commit ID +CALL git checkout %COMMIT_ID% -- . +IF ERRORLEVEL 1 ( + ECHO [git_checkout] Failed to checkout the CDK application for the %GEM_NAME% gem using commit ID %COMMIT_ID% + POPD + SET %~2=1 +) + +REM Install required packages for the CDK application +CALL python -m pip install -r requirements.txt +IF ERRORLEVEL 1 ( + ECHO [cdk_destruction] Failed to install required packages for the %GEM_NAME% gem + POPD + SET %~2=1 +) + +REM Destroy the CDK application +CALL cdk destroy --all -f +IF ERRORLEVEL 1 ( + ECHO [cdk_destruction] Failed to destroy the CDK application for the %GEM_NAME% gem + POPD + SET %~2=1 +) +POPD From 5bf749dcacab59b4c5a536fd9c2f68c33611c5ee Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 10 Sep 2021 14:10:49 -0700 Subject: [PATCH 046/274] fix infinite loop due to thin triangles (#4027) * fix infinite loop due to thin triangles Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> * check exact triangles size Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Code/Source/Shape/ShapeGeometryUtil.cpp | 11 ++++--- .../Code/Tests/ShapeGeometryUtilTest.cpp | 33 +++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp b/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp index 3b54447fdd..e8bf3748fa 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/ShapeGeometryUtil.cpp @@ -152,17 +152,18 @@ namespace LmbrCentral const AZ::Vector2 edgeAfter = next - curr; const float triangleArea = Wedge(edgeBefore, edgeAfter); + const float tolerance = 0.001f; const bool interiorVertex = triangleArea <= 0.0f; - // if triangle is not an 'ear', continue. - if (!interiorVertex) + // if triangle is not an 'ear' and we have other vertices, continue. + if (!interiorVertex && vertices.size() > 3) { continue; } - // check no other vertices are inside the triangle formed - // by these three vertices, if so, continue to next vertex. - if (vertices.size() > 3) + // check if this is a large enough triangle, that there are no other vertices + // inside the triangle formed, otherwise, continue to next vertex. + if (vertices.size() > 3 && !AZ::IsClose(triangleArea, 0.f, tolerance)) { bool pointInside = false; for (size_t j = (nextIndex + 1) % vertices.size(); j != prevIndex; j = (j + 1) % vertices.size()) diff --git a/Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp b/Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp index 390b30abe3..77e4974db1 100644 --- a/Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp @@ -94,6 +94,39 @@ namespace UnitTest EXPECT_TRUE(triangles.size() == 18); } + // thin + TEST_F(ShapeGeometryUtilTest, GenerateTrianglesThin) + { + // given a series of vertices that are known to cause an infinite loop in the past + // due to numerical precision issues with very thin triangles + AZStd::vector triangles = + LmbrCentral::GenerateTriangles( + { + AZ::Vector2( 2.00000000f, -1.50087357f), + AZ::Vector2( 2.00000000f, -1.24706364f), + AZ::Vector2( 1.99930608f, -0.999682188f), + AZ::Vector2( 1.99859631f, -0.746669292f), + AZ::Vector2( 1.99789453f, -0.496492654f), + AZ::Vector2( 1.89999998f, 34.4000015f), + AZ::Vector2( 1.95483327f, 0.787139893f), + AZ::Vector2( 1.95505607f, 0.650562286f), + AZ::Vector2( 1.95553458f, 0.357242584f), + AZ::Vector2( 1.95596826f, 0.0913925171f), + AZ::Vector2( 1.95620418f, -0.0532035828f), + AZ::Vector2( 1.95642424f, -0.188129425f), + AZ::Vector2( 1.95684254f, -0.444545746f), + AZ::Vector2( 1.95693028f, -0.498298645f), + AZ::Vector2( 1.95734584f, -0.753005981f), + AZ::Vector2( 1.95775008f, -1.00079727f), + AZ::Vector2( 1.95814919f, -1.24542999f), + AZ::Vector2( 1.95856297f, -1.49910200f) + } + ); + + // expect the algorithm completes and produces triangles (num verts - 2) * 3 + EXPECT_TRUE(triangles.size() == 48); + } + // test double to record if DrawTrianglesIndexed or DrawLines are called class DebugShapeDebugDisplayRequests : public AzFramework::DebugDisplayRequests { From 72cd282ad2f21aa479d764115040bb92a883e366 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Fri, 10 Sep 2021 15:16:33 -0700 Subject: [PATCH 047/274] Avoid redefining `PRI` macros on Linux (#4055) * Avoid redefining `PRI` macros on Linux The fixed width 64-bit integer types are defined differently per platform. Some platforms define it as "long", others define it as "long long". For consistency, `AZ::u64` or `AZ::s64` is always defined to "long long". However, this causes problems for formatting those types, because on platforms where `uint64_t` is a `long`, `PRIu64` gives the wrong format string for `AZ::u64`. Previously this was fixed by redefining the `PRI` macros so that they work for `AZ::u64`, but that breaks the ability to format `uint64_t`. We could add an AZ-specific version of the `PRI` macros for 64-bit integer types, but we don't really need to, since they are `long long` on every platform we support. * Use `%ll` for `AZ::u64` * Use `PRIu64` for `uint64_t` Signed-off-by: Chris Burel * Avoid redefining `PRI` macros in CryCommon Signed-off-by: Chris Burel --- .../UnixLike/AzCore/PlatformIncl_UnixLike.h | 13 ------------- Code/Legacy/CryCommon/platform.h | 15 ++------------- Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp | 11 ++--------- Code/Legacy/CrySystem/XML/xml.cpp | 11 ++--------- .../native/AssetManager/SourceFileRelocator.cpp | 4 ++-- .../native/utilities/assetUtils.cpp | 6 +++--- Gems/AudioSystem/Code/Source/Engine/ATL.cpp | 6 +++--- .../Code/Source/Engine/ATLAudioObject.cpp | 2 +- .../Builders/SliceBuilder/SliceBuilderWorker.cpp | 2 +- .../Code/Source/AreaSystemComponent.cpp | 4 ++-- 10 files changed, 18 insertions(+), 56 deletions(-) diff --git a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/PlatformIncl_UnixLike.h b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/PlatformIncl_UnixLike.h index 451ba1763a..63e8a4ce70 100644 --- a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/PlatformIncl_UnixLike.h +++ b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/PlatformIncl_UnixLike.h @@ -9,16 +9,3 @@ #pragma once #include - -#define __STDC_FORMAT_MACROS -#include - -// types like AZ::u64 require an usigned long long, but inttypes.h has it as unsigned long -#undef PRIX64 -#undef PRIx64 -#undef PRId64 -#undef PRIu64 -#define PRIX64 "llX" -#define PRIx64 "llx" -#define PRId64 "lld" -#define PRIu64 "llu" diff --git a/Code/Legacy/CryCommon/platform.h b/Code/Legacy/CryCommon/platform.h index 37f0636c3a..2baddaafd5 100644 --- a/Code/Legacy/CryCommon/platform.h +++ b/Code/Legacy/CryCommon/platform.h @@ -51,20 +51,9 @@ #undef AZ_RESTRICTED_SECTION_IMPLEMENTED #elif defined(LINUX) || defined(APPLE) #define __STDC_FORMAT_MACROS - #include - #if defined(APPLE) || defined(LINUX64) - // int64 is not the same type as the operating system's int64_t - #undef PRIX64 - #undef PRIx64 - #undef PRId64 - #undef PRIu64 - #define PRIX64 "llX" - #define PRIx64 "llx" - #define PRId64 "lld" - #define PRIu64 "llu" - #endif + #include #else - #include + #include #endif #if !defined(PRISIZE_T) diff --git a/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp b/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp index ec154b31e8..a13759e82b 100644 --- a/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp +++ b/Code/Legacy/CrySystem/XML/XMLBinaryNode.cpp @@ -125,7 +125,7 @@ bool CBinaryXmlNode::getAttr(const char* key, int64& value) const const char* svalue = GetValue(key); if (svalue) { - azsscanf(svalue, "%" PRId64, &value); + value = strtoll(svalue, nullptr, 10); return true; } return false; @@ -137,14 +137,7 @@ bool CBinaryXmlNode::getAttr(const char* key, uint64& value, bool useHexFormat) const char* svalue = GetValue(key); if (svalue) { - if (useHexFormat) - { - azsscanf(svalue, "%" PRIX64, &value); - } - else - { - azsscanf(svalue, "%" PRIu64, &value); - } + value = strtoull(svalue, nullptr, useHexFormat ? 16 : 10); return true; } return false; diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp index b1f18142f1..826e74b758 100644 --- a/Code/Legacy/CrySystem/XML/xml.cpp +++ b/Code/Legacy/CrySystem/XML/xml.cpp @@ -400,7 +400,7 @@ bool CXmlNode::getAttr(const char* key, int64& value) const const char* svalue = GetValue(key); if (svalue) { - azsscanf(svalue, "%" PRId64, &value); + value = strtoll(key, nullptr, 10); return true; } return false; @@ -412,14 +412,7 @@ bool CXmlNode::getAttr(const char* key, uint64& value, bool useHexFormat) const const char* svalue = GetValue(key); if (svalue) { - if (useHexFormat) - { - azsscanf(svalue, "%" PRIX64, &value); - } - else - { - azsscanf(svalue, "%" PRIu64, &value); - } + value = strtoull(key, nullptr, useHexFormat ? 16 : 10); return true; } return false; diff --git a/Code/Tools/AssetProcessor/native/AssetManager/SourceFileRelocator.cpp b/Code/Tools/AssetProcessor/native/AssetManager/SourceFileRelocator.cpp index 64e176ffe4..04de6c64f3 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/SourceFileRelocator.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/SourceFileRelocator.cpp @@ -699,7 +699,7 @@ Please note that only those seed files will get updated that are active for your if (isMove) { report.append(AZStd::string::format( - "SOURCEID: %" PRId64 ", CURRENT PATH: %s, NEW PATH: %s, CURRENT GUID: %s, NEW GUID: %s\n", + "SOURCEID: %lld, CURRENT PATH: %s, NEW PATH: %s, CURRENT GUID: %s, NEW GUID: %s\n", relocationInfo.m_sourceEntry.m_sourceID, relocationInfo.m_oldRelativePath.c_str(), relocationInfo.m_newRelativePath.c_str(), @@ -709,7 +709,7 @@ Please note that only those seed files will get updated that are active for your else { report.append(AZStd::string::format( - "SOURCEID: %" PRId64 ", CURRENT PATH: %s, CURRENT GUID: %s\n", + "SOURCEID: %lld, CURRENT PATH: %s, CURRENT GUID: %s\n", relocationInfo.m_sourceEntry.m_sourceID, relocationInfo.m_oldRelativePath.c_str(), relocationInfo.m_sourceEntry.m_sourceGuid.ToString().c_str())); diff --git a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp index 85801bdf8a..c0e907f2d5 100644 --- a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp @@ -1018,7 +1018,7 @@ namespace AssetUtilities AZStd::string ComputeJobLogFileName(const AzToolsFramework::AssetSystem::JobInfo& jobInfo) { - return AZStd::string::format("%s-%u-%" PRIu64 ".log", jobInfo.m_sourceFile.c_str(), jobInfo.GetHash(), jobInfo.m_jobRunKey); + return AZStd::string::format("%s-%u-%llu.log", jobInfo.m_sourceFile.c_str(), jobInfo.GetHash(), jobInfo.m_jobRunKey); } AZStd::string ComputeJobLogFileName(const AssetBuilderSDK::CreateJobsRequest& createJobsRequest) @@ -1287,13 +1287,13 @@ namespace AssetUtilities // so we add the size of it too. // its also possible that it moved to a different file with the same modtime/hash AND size, // but with a different name. So we add that too. - return AZStd::string::format("%" PRIX64 ":%" PRIu64 ":%s", fileIdentifier, fileStateInfo.m_fileSize, nameToUse.c_str()); + return AZStd::string::format("%llX:%llu:%s", fileIdentifier, fileStateInfo.m_fileSize, nameToUse.c_str()); } } AZStd::string ComputeJobLogFileName(const AssetProcessor::JobEntry& jobEntry) { - return AZStd::string::format("%s-%u-%" PRIu64 ".log", jobEntry.m_databaseSourceName.toUtf8().constData(), jobEntry.GetHash(), jobEntry.m_jobRunKey); + return AZStd::string::format("%s-%u-%llu.log", jobEntry.m_databaseSourceName.toUtf8().constData(), jobEntry.GetHash(), jobEntry.m_jobRunKey); } bool CreateTempRootFolder(QString startFolder, QDir& tempRoot) diff --git a/Gems/AudioSystem/Code/Source/Engine/ATL.cpp b/Gems/AudioSystem/Code/Source/Engine/ATL.cpp index e43f7beba7..6a842785fa 100644 --- a/Gems/AudioSystem/Code/Source/Engine/ATL.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/ATL.cpp @@ -2144,7 +2144,7 @@ namespace Audio { if (bytes < (1 << 10)) { - azsnprintf(buffer, bufLength, "%" PRIu64 " B", bytes); + azsnprintf(buffer, bufLength, "%llu B", bytes); } else if (bytes < (1 << 20)) { @@ -2261,10 +2261,10 @@ namespace Audio auxGeom.Draw2dLabel(fPosX + xTablePositions[4], posY + lineHeight, textSize, color, false, "%s", buffer); auxGeom.Draw2dLabel(fPosX + xTablePositions[5], posY, textSize, color, false, "Total Allocs"); - auxGeom.Draw2dLabel(fPosX + xTablePositions[5], posY + lineHeight, textSize, color, false, "%" PRIu64, totalAllocs); + auxGeom.Draw2dLabel(fPosX + xTablePositions[5], posY + lineHeight, textSize, color, false, "%llu", totalAllocs); auxGeom.Draw2dLabel(fPosX + xTablePositions[6], posY, textSize, color, false, "Total Frees"); - auxGeom.Draw2dLabel(fPosX + xTablePositions[6], posY + lineHeight, textSize, color, false, "%" PRIu64, totalFrees); + auxGeom.Draw2dLabel(fPosX + xTablePositions[6], posY + lineHeight, textSize, color, false, "%llu", totalFrees); } else { diff --git a/Gems/AudioSystem/Code/Source/Engine/ATLAudioObject.cpp b/Gems/AudioSystem/Code/Source/Engine/ATLAudioObject.cpp index c8548efa04..6e229c7c0e 100644 --- a/Gems/AudioSystem/Code/Source/Engine/ATLAudioObject.cpp +++ b/Gems/AudioSystem/Code/Source/Engine/ATLAudioObject.cpp @@ -762,7 +762,7 @@ namespace Audio AZStd::string eventsString; for (auto activeEvent : m_cActiveEvents) { - eventsString = AZStd::string::format("%s%" PRIu64 "%s", eventsString.c_str(), activeEvent, sSeparator); + eventsString = AZStd::string::format("%s%llu%s", eventsString.c_str(), activeEvent, sSeparator); } return eventsString; diff --git a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp index 79cf3ac282..d917a3b600 100644 --- a/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp +++ b/Gems/LmbrCentral/Code/Source/Builders/SliceBuilder/SliceBuilderWorker.cpp @@ -211,7 +211,7 @@ namespace SliceBuilder jobDescriptor.SetPlatformIdentifier(info.m_identifier.c_str()); jobDescriptor.m_additionalFingerprintInfo = AZStd::string(compilerVersion) - .append(AZStd::string::format("|%" PRIu64, static_cast(sourceSliceTypeFingerprint))); + .append(AZStd::string::format("|%zu", sourceSliceTypeFingerprint)); for (const auto& sourceDependency : sourceFileDependencies) { diff --git a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp index 4ffed260de..6684aef913 100644 --- a/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp +++ b/Gems/Vegetation/Code/Source/AreaSystemComponent.cpp @@ -211,7 +211,7 @@ namespace Vegetation { return AZ::Failure( AZStd::string::format("The combination of View Area Grid Size and Sector Point Density will create %" PRId64 " instances. Only a max of %" PRId64 " instances is allowed.", - static_cast(totalInstances), static_cast(s_maxVegetationInstances))); + totalInstances, s_maxVegetationInstances)); } return AZ::Success(); @@ -235,7 +235,7 @@ namespace Vegetation { return AZ::Failure( AZStd::string::format("The combination of View Area Grid Size and Sector Point Density will create %" PRId64 " instances. Only a max of %" PRId64 " instances is allowed.", - static_cast(totalInstances), static_cast(s_maxVegetationInstances))); + totalInstances, s_maxVegetationInstances)); } const float instancesPerMeter = static_cast(sectorDensity) / static_cast(m_sectorSizeInMeters); From 8554cea0adb039e9b7c43579f7b4a4324eb6c7f3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:14:58 -0700 Subject: [PATCH 048/274] better organization of the warning Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Platform/Common/Clang/Configurations_clang.cmake | 12 +++++++++++- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 9 ++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cmake/Platform/Common/Clang/Configurations_clang.cmake b/cmake/Platform/Common/Clang/Configurations_clang.cmake index 41949678be..5c24161a19 100644 --- a/cmake/Platform/Common/Clang/Configurations_clang.cmake +++ b/cmake/Platform/Common/Clang/Configurations_clang.cmake @@ -16,13 +16,23 @@ ly_append_configurations_options( -Wall -Werror - # Disabled warnings (please do not disable any others without first consulting ly-warnings) + ################### + # Disabled warnings (please do not disable any others without first consulting sig-build) + ################### + # -Wno-inconsistent-missing-override # unfortunately there is no warning in MSVC to detect missing overrides, + # MSVC's static analyzer can, but that is a different run that most developers are not ware of. A pass was + # done to fix all hits. Leaving this disabled until there is a matching warning in MSVC. + -Wrange-loop-analysis -Wno-unknown-warning-option # used as a way to mark warnings that are MSVC only -Wno-parentheses -Wno-reorder -Wno-switch -Wno-undefined-var-template + + ################### + # Enabled warnings (that are disabled by default) + ################### COMPILATION_DEBUG -O0 # No optimization diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index bac6cd6aa1..8885624a81 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -35,10 +35,14 @@ ly_append_configurations_options( /WX # Warnings as errors /permissive- # Conformance with standard - # Disabling some warnings + ################### + # Disabled warnings (please do not disable any others without first consulting sig-build) + ################### /wd4201 # nonstandard extension used: nameless struct/union. This actually became part of the C++11 std, MS has an open issue: https://developercommunity.visualstudio.com/t/warning-level-4-generates-a-bogus-warning-c4201-no/103064 - # Enabling warnings that are disabled by default from /W4 + ################### + # Enabled warnings (that are disabled by default from /W4) + ################### # https://docs.microsoft.com/en-us/cpp/preprocessor/compiler-warnings-that-are-off-by-default?view=vs-2019 /we4263 # 'function': member function does not override any base class virtual member function /we4264 # 'virtual_function': no override available for virtual member function from base 'class'; function is hidden @@ -54,7 +58,6 @@ ly_append_configurations_options( /we5032 # detected #pragma warning(push) with no corresponding #pragma warning(pop) /we5233 # explicit lambda capture 'identifier' is not used - /Zc:forScope # Force Conformance in for Loop Scope /diagnostics:caret # Compiler diagnostic options: includes the column where the issue was found and places a caret (^) under the location in the line of code where the issue was detected. /Zc:__cplusplus From 7f157f152dffe29c61309241b822226242724659 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:15:16 -0700 Subject: [PATCH 049/274] Code/Editor Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/2DViewport.h | 34 +-- Code/Editor/ActionManager.h | 2 +- Code/Editor/AnimationContext.h | 2 +- Code/Editor/BaseLibrary.h | 34 +-- Code/Editor/BaseLibraryManager.h | 84 ++--- Code/Editor/Controls/ColorGradientCtrl.h | 2 +- Code/Editor/Controls/FolderTreeCtrl.h | 2 +- .../ReflectedVarWrapper.h | 2 +- Code/Editor/Controls/SplineCtrlEx.h | 22 +- Code/Editor/Controls/TimelineCtrl.h | 4 +- Code/Editor/EditorToolsApplication.h | 2 +- Code/Editor/Export/ExportManager.h | 30 +- Code/Editor/IEditorImpl.h | 286 +++++++++--------- Code/Editor/LevelTreeModel.h | 2 +- Code/Editor/Objects/AxisGizmo.h | 18 +- Code/Editor/Objects/BaseObject.h | 2 +- Code/Editor/Objects/EntityObject.h | 54 ++-- Code/Editor/Objects/GizmoManager.h | 8 +- Code/Editor/Objects/LineGizmo.h | 8 +- Code/Editor/Objects/ObjectManager.h | 148 ++++----- .../Objects/ComponentEntityObject.h | 4 +- .../SandboxIntegration.h | 2 +- .../ComponentPalette/FavoriteComponentList.h | 2 +- .../UI/Outliner/OutlinerListModel.hxx | 2 +- Code/Editor/PreferencesStdPages.h | 12 +- Code/Editor/QtViewPane.h | 8 +- Code/Editor/SelectSequenceDialog.h | 2 +- Code/Editor/ToolbarCustomizationDialog.h | 2 +- Code/Editor/TopRendererWnd.h | 10 +- .../TrackView/SequenceBatchRenderDialog.h | 2 +- Code/Editor/TrackView/TrackViewCurveEditor.h | 10 +- Code/Editor/TrackView/TrackViewDialog.h | 12 +- Code/Editor/TrackView/TrackViewSequence.h | 32 +- .../TrackView/TrackViewSequenceManager.h | 4 +- Code/Editor/TrackView/TrackViewSplineCtrl.h | 10 +- Code/Editor/Util/ColumnGroupTreeView.h | 2 +- Code/Editor/Util/Variable.h | 84 ++--- Code/Editor/Viewport.h | 104 +++---- Code/Editor/ViewportTitleDlg.h | 2 +- 39 files changed, 526 insertions(+), 526 deletions(-) diff --git a/Code/Editor/2DViewport.h b/Code/Editor/2DViewport.h index 4ffda18514..007c1a47d3 100644 --- a/Code/Editor/2DViewport.h +++ b/Code/Editor/2DViewport.h @@ -35,32 +35,32 @@ public: Q2DViewport(QWidget* parent = nullptr); virtual ~Q2DViewport(); - virtual void SetType(EViewportType type); - virtual EViewportType GetType() const { return m_viewType; } - virtual float GetAspectRatio() const { return 1.0f; }; + void SetType(EViewportType type) override; + EViewportType GetType() const override { return m_viewType; } + float GetAspectRatio() const override { return 1.0f; }; - virtual void ResetContent(); - virtual void UpdateContent(int flags); + void ResetContent() override; + void UpdateContent(int flags) override; public slots: // Called every frame to update viewport. - virtual void Update(); + void Update() override; public: //! Map world space position to viewport position. - virtual QPoint WorldToView(const Vec3& wp) const; + QPoint WorldToView(const Vec3& wp) const override; - virtual QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const; //Eric@conffx + QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const override; //Eric@conffx //! Map viewport position to world space position. - virtual Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; + Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; //! Map viewport position to world space ray from camera. - virtual void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const; + void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override; void OnTitleMenu(QMenu* menu) override; - virtual bool HitTest(const QPoint& point, HitContext& hitInfo) override; - virtual bool IsBoundsVisible(const AABB& box) const; + bool HitTest(const QPoint& point, HitContext& hitInfo) override; + bool IsBoundsVisible(const AABB& box) const override; // ovverided from CViewport. float GetScreenScaleFactor(const Vec3& worldPoint) const override; @@ -111,8 +111,8 @@ protected: virtual void SetZoom(float fZoomFactor, const QPoint& center); // overrides from CViewport. - virtual void MakeConstructionPlane(int axis); - virtual const Matrix34& GetConstructionMatrix(RefCoordSys coordSys); + void MakeConstructionPlane(int axis) override; + const Matrix34& GetConstructionMatrix(RefCoordSys coordSys) override; //! Calculate view transformation matrix. virtual void CalculateViewTM(); @@ -146,9 +146,9 @@ protected: void showEvent(QShowEvent* event) override; void paintEvent(QPaintEvent* event) override; int OnCreate(); - void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point); - void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point); - void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt); + void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; + void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; + void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt) override; void OnDestroy(); protected: diff --git a/Code/Editor/ActionManager.h b/Code/Editor/ActionManager.h index 2481b7e3ef..8879bdc1fb 100644 --- a/Code/Editor/ActionManager.h +++ b/Code/Editor/ActionManager.h @@ -353,7 +353,7 @@ public: m_actionHandlers[id] = std::bind(method, object, id); } - bool eventFilter(QObject* watched, QEvent* event); + bool eventFilter(QObject* watched, QEvent* event) override; // returns false if the action was already inserted, indicating that the action should not be processed again bool InsertActionExecuting(int id); diff --git a/Code/Editor/AnimationContext.h b/Code/Editor/AnimationContext.h index 98c951eda7..62ffa26634 100644 --- a/Code/Editor/AnimationContext.h +++ b/Code/Editor/AnimationContext.h @@ -197,7 +197,7 @@ private: virtual void OnSequenceRemoved(CTrackViewSequence* pSequence) override; - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); + virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override; void AnimateActiveSequence(); diff --git a/Code/Editor/BaseLibrary.h b/Code/Editor/BaseLibrary.h index 6c807df56b..55079d3fde 100644 --- a/Code/Editor/BaseLibrary.h +++ b/Code/Editor/BaseLibrary.h @@ -40,57 +40,57 @@ public: //! Set library name. virtual void SetName(const QString& name); //! Get library name. - const QString& GetName() const; + const QString& GetName() const override; //! Set new filename for this library. virtual bool SetFilename(const QString& filename, [[maybe_unused]] bool checkForUnique = true) { m_filename = filename.toLower(); return true; }; - const QString& GetFilename() const { return m_filename; }; + const QString& GetFilename() const override { return m_filename; }; - virtual bool Save() = 0; - virtual bool Load(const QString& filename) = 0; - virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0; + bool Save() override = 0; + bool Load(const QString& filename) override = 0; + void Serialize(XmlNodeRef& node, bool bLoading) override = 0; //! Mark library as modified. - void SetModified(bool bModified = true); + void SetModified(bool bModified = true) override; //! Check if library was modified. - bool IsModified() const { return m_bModified; }; + bool IsModified() const override { return m_bModified; }; ////////////////////////////////////////////////////////////////////////// // Working with items. ////////////////////////////////////////////////////////////////////////// //! Add a new prototype to library. - void AddItem(IDataBaseItem* item, bool bRegister = true); + void AddItem(IDataBaseItem* item, bool bRegister = true) override; //! Get number of known prototypes. - int GetItemCount() const { return static_cast(m_items.size()); } + int GetItemCount() const override { return static_cast(m_items.size()); } //! Get prototype by index. - IDataBaseItem* GetItem(int index); + IDataBaseItem* GetItem(int index) override; //! Delete item by pointer of item. - void RemoveItem(IDataBaseItem* item); + void RemoveItem(IDataBaseItem* item) override; //! Delete all items from library. - void RemoveAllItems(); + void RemoveAllItems() override; //! Find library item by name. //! Using linear search. - IDataBaseItem* FindItem(const QString& name); + IDataBaseItem* FindItem(const QString& name) override; //! Check if this library is local level library. - bool IsLevelLibrary() const { return m_bLevelLib; }; + bool IsLevelLibrary() const override { return m_bLevelLib; }; //! Set library to be level library. - void SetLevelLibrary(bool bEnable) { m_bLevelLib = bEnable; }; + void SetLevelLibrary(bool bEnable) override { m_bLevelLib = bEnable; }; ////////////////////////////////////////////////////////////////////////// //! Return manager for this library. - IBaseLibraryManager* GetManager(); + IBaseLibraryManager* GetManager() override; // Saves the library with the main tag defined by the parameter name bool SaveLibrary(const char* name, bool saveEmptyLibrary = false); //CONFETTI BEGIN // Used to change the library item order - virtual void ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) override; + void ChangeItemOrder(CBaseLibraryItem* item, unsigned int newLocation) override; //CONFETTI END signals: diff --git a/Code/Editor/BaseLibraryManager.h b/Code/Editor/BaseLibraryManager.h index 6f0b905760..118c7ef1f0 100644 --- a/Code/Editor/BaseLibraryManager.h +++ b/Code/Editor/BaseLibraryManager.h @@ -35,112 +35,112 @@ public: ~CBaseLibraryManager(); //! Clear all libraries. - virtual void ClearAll() override; + void ClearAll() override; ////////////////////////////////////////////////////////////////////////// // IDocListener implementation. ////////////////////////////////////////////////////////////////////////// - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override; + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; ////////////////////////////////////////////////////////////////////////// // Library items. ////////////////////////////////////////////////////////////////////////// //! Make a new item in specified library. - virtual IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) override; + IDataBaseItem* CreateItem(IDataBaseLibrary* pLibrary) override; //! Delete item from library and manager. - virtual void DeleteItem(IDataBaseItem* pItem) override; + void DeleteItem(IDataBaseItem* pItem) override; //! Find Item by its GUID. - virtual IDataBaseItem* FindItem(REFGUID guid) const; - virtual IDataBaseItem* FindItemByName(const QString& fullItemName); - virtual IDataBaseItem* LoadItemByName(const QString& fullItemName); + IDataBaseItem* FindItem(REFGUID guid) const override; + IDataBaseItem* FindItemByName(const QString& fullItemName) override; + IDataBaseItem* LoadItemByName(const QString& fullItemName) override; virtual IDataBaseItem* FindItemByName(const char* fullItemName); virtual IDataBaseItem* LoadItemByName(const char* fullItemName); - virtual IDataBaseItemEnumerator* GetItemEnumerator() override; + IDataBaseItemEnumerator* GetItemEnumerator() override; ////////////////////////////////////////////////////////////////////////// // Set item currently selected. - virtual void SetSelectedItem(IDataBaseItem* pItem) override; + void SetSelectedItem(IDataBaseItem* pItem) override; // Get currently selected item. - virtual IDataBaseItem* GetSelectedItem() const override; - virtual IDataBaseItem* GetSelectedParentItem() const override; + IDataBaseItem* GetSelectedItem() const override; + IDataBaseItem* GetSelectedParentItem() const override; ////////////////////////////////////////////////////////////////////////// // Libraries. ////////////////////////////////////////////////////////////////////////// //! Add Item library. - virtual IDataBaseLibrary* AddLibrary(const QString& library, bool bIsLevelLibrary = false, bool bIsLoading = true) override; - virtual void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) override; + IDataBaseLibrary* AddLibrary(const QString& library, bool bIsLevelLibrary = false, bool bIsLoading = true) override; + void DeleteLibrary(const QString& library, bool forceDeleteLevel = false) override; //! Get number of libraries. - virtual int GetLibraryCount() const override { return static_cast(m_libs.size()); }; + int GetLibraryCount() const override { return static_cast(m_libs.size()); }; //! Get number of modified libraries. - virtual int GetModifiedLibraryCount() const override; + int GetModifiedLibraryCount() const override; //! Get Item library by index. - virtual IDataBaseLibrary* GetLibrary(int index) const override; + IDataBaseLibrary* GetLibrary(int index) const override; //! Get Level Item library. - virtual IDataBaseLibrary* GetLevelLibrary() const override; + IDataBaseLibrary* GetLevelLibrary() const override; //! Find Items Library by name. - virtual IDataBaseLibrary* FindLibrary(const QString& library) override; + IDataBaseLibrary* FindLibrary(const QString& library) override; //! Find Items Library's index by name. int FindLibraryIndex(const QString& library) override; //! Load Items library. - virtual IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) override; + IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false) override; //! Save all modified libraries. - virtual void SaveAllLibs() override; + void SaveAllLibs() override; //! Serialize property manager. - virtual void Serialize(XmlNodeRef& node, bool bLoading) override; + void Serialize(XmlNodeRef& node, bool bLoading) override; //! Export items to game. - virtual void Export([[maybe_unused]] XmlNodeRef& node) override {}; + void Export([[maybe_unused]] XmlNodeRef& node) override {}; //! Returns unique name base on input name. - virtual QString MakeUniqueItemName(const QString& name, const QString& libName = "") override; - virtual QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) override; + QString MakeUniqueItemName(const QString& name, const QString& libName = "") override; + QString MakeFullItemName(IDataBaseLibrary* pLibrary, const QString& group, const QString& itemName) override; //! Root node where this library will be saved. - virtual QString GetRootNodeName() override = 0; + QString GetRootNodeName() override = 0; //! Path to libraries in this manager. - virtual QString GetLibsPath() override = 0; + QString GetLibsPath() override = 0; ////////////////////////////////////////////////////////////////////////// //! Validate library items for errors. - virtual void Validate() override; + void Validate() override; ////////////////////////////////////////////////////////////////////////// - virtual void GatherUsedResources(CUsedResources& resources) override; + void GatherUsedResources(CUsedResources& resources) override; - virtual void AddListener(IDataBaseManagerListener* pListener) override; - virtual void RemoveListener(IDataBaseManagerListener* pListener) override; + void AddListener(IDataBaseManagerListener* pListener) override; + void RemoveListener(IDataBaseManagerListener* pListener) override; ////////////////////////////////////////////////////////////////////////// - virtual void RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) override; - virtual void RegisterItem(CBaseLibraryItem* pItem) override; - virtual void UnregisterItem(CBaseLibraryItem* pItem) override; + void RegisterItem(CBaseLibraryItem* pItem, REFGUID newGuid) override; + void RegisterItem(CBaseLibraryItem* pItem) override; + void UnregisterItem(CBaseLibraryItem* pItem) override; // Only Used internally. - virtual void OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) override; + void OnRenameItem(CBaseLibraryItem* pItem, const QString& oldName) override; // Called by items to indicated that they have been modified. // Sends item changed event to listeners. - virtual void OnItemChanged(IDataBaseItem* pItem) override; - virtual void OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) override; + void OnItemChanged(IDataBaseItem* pItem) override; + void OnUpdateProperties(IDataBaseItem* pItem, bool bRefresh) override; QString MakeFilename(const QString& library); - virtual bool IsUniqueFilename(const QString& library) override; + bool IsUniqueFilename(const QString& library) override; //CONFETTI BEGIN // Used to change the library item order - virtual void ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) override; + void ChangeLibraryOrder(IDataBaseLibrary* lib, unsigned int newLocation) override; - virtual bool SetLibraryName(CBaseLibrary* lib, const QString& name) override; + bool SetLibraryName(CBaseLibrary* lib, const QString& name) override; protected: void SplitFullItemName(const QString& fullItemName, QString& libraryName, QString& itemName); @@ -199,8 +199,8 @@ public: m_pMap = pMap; m_iterator = m_pMap->begin(); } - virtual void Release() { delete this; }; - virtual IDataBaseItem* GetFirst() + void Release() override { delete this; }; + IDataBaseItem* GetFirst() override { m_iterator = m_pMap->begin(); if (m_iterator == m_pMap->end()) @@ -209,7 +209,7 @@ public: } return m_iterator->second; } - virtual IDataBaseItem* GetNext() + IDataBaseItem* GetNext() override { if (m_iterator != m_pMap->end()) { diff --git a/Code/Editor/Controls/ColorGradientCtrl.h b/Code/Editor/Controls/ColorGradientCtrl.h index a3f95fcd8c..bb1a83b0c1 100644 --- a/Code/Editor/Controls/ColorGradientCtrl.h +++ b/Code/Editor/Controls/ColorGradientCtrl.h @@ -81,7 +81,7 @@ protected: HIT_SPLINE, }; - void paintEvent(QPaintEvent* e); + void paintEvent(QPaintEvent* e) override; void resizeEvent(QResizeEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; diff --git a/Code/Editor/Controls/FolderTreeCtrl.h b/Code/Editor/Controls/FolderTreeCtrl.h index 48eff10a92..f74cca6143 100644 --- a/Code/Editor/Controls/FolderTreeCtrl.h +++ b/Code/Editor/Controls/FolderTreeCtrl.h @@ -83,7 +83,7 @@ protected Q_SLOTS: void OnIndexDoubleClicked(const QModelIndex& index); protected: - virtual void OnFileMonitorChange(const SFileChangeInfo& rChange); + void OnFileMonitorChange(const SFileChangeInfo& rChange) override; void contextMenuEvent(QContextMenuEvent* e) override; void InitTree(); diff --git a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h index 9c49f1ae1a..4bcd6dcaa3 100644 --- a/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h +++ b/Code/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.h @@ -123,7 +123,7 @@ public: void SetVariable(IVariable* pVariable) override; void SyncReflectedVarToIVar(IVariable* pVariable) override; void SyncIVarToReflectedVar(IVariable* pVariable) override; - virtual void OnVariableChange(IVariable* var); + void OnVariableChange(IVariable* var) override; CReflectedVar* GetReflectedVar() override { return m_reflectedVar.data(); } protected: diff --git a/Code/Editor/Controls/SplineCtrlEx.h b/Code/Editor/Controls/SplineCtrlEx.h index 711cbcf8d4..9bf412f056 100644 --- a/Code/Editor/Controls/SplineCtrlEx.h +++ b/Code/Editor/Controls/SplineCtrlEx.h @@ -159,15 +159,15 @@ public: ////////////////////////////////////////////////////////////////////////// // IKeyTimeSet Implementation - virtual int GetKeyTimeCount() const; - virtual float GetKeyTime(int index) const; - virtual void MoveKeyTimes(int numChanges, int* indices, float scale, float offset, bool copyKeys); - virtual bool GetKeyTimeSelected(int index) const; - virtual void SetKeyTimeSelected(int index, bool selected); - virtual int GetKeyCount(int index) const; - virtual int GetKeyCountBound() const; - virtual void BeginEdittingKeyTimes(); - virtual void EndEdittingKeyTimes(); + int GetKeyTimeCount() const override; + float GetKeyTime(int index) const override; + void MoveKeyTimes(int numChanges, int* indices, float scale, float offset, bool copyKeys) override; + bool GetKeyTimeSelected(int index) const override; + void SetKeyTimeSelected(int index, bool selected) override; + int GetKeyCount(int index) const override; + int GetKeyCountBound() const override; + void BeginEdittingKeyTimes() override; + void EndEdittingKeyTimes() override; void SetEditLock(bool bLock) { m_bEditLock = bLock; } @@ -361,8 +361,8 @@ public: SplineWidget(QWidget* parent); virtual ~SplineWidget(); - void update() { QWidget::update(); } - void update(const QRect& rect) { QWidget::update(rect); } + void update() override { QWidget::update(); } + void update(const QRect& rect) override { QWidget::update(rect); } QPoint mapFromGlobal(const QPoint& point) const override { return QWidget::mapFromGlobal(point); } diff --git a/Code/Editor/Controls/TimelineCtrl.h b/Code/Editor/Controls/TimelineCtrl.h index f87bdf3410..7e1fc6fcb2 100644 --- a/Code/Editor/Controls/TimelineCtrl.h +++ b/Code/Editor/Controls/TimelineCtrl.h @@ -56,7 +56,7 @@ public: void setGeometry(const QRect& r) override { QWidget::setGeometry(r); } void SetTimeRange(const Range& r) { m_timeRange = r; } - void SetTimeMarker(float fTime); + void SetTimeMarker(float fTime) override; float GetTimeMarker() const { return m_fTimeMarker; } void SetZoom(float fZoom); @@ -113,7 +113,7 @@ protected: void OnLButtonUp(const QPoint& point, Qt::KeyboardModifiers modifiers); void OnRButtonDown(const QPoint& point, Qt::KeyboardModifiers modifiers); void OnRButtonUp(const QPoint& point, Qt::KeyboardModifiers modifiers); - void keyPressEvent(QKeyEvent* event); + void keyPressEvent(QKeyEvent* event) override; // Drawing functions float ClientToTime(int x); diff --git a/Code/Editor/EditorToolsApplication.h b/Code/Editor/EditorToolsApplication.h index 93916cfc8c..422772cbc4 100644 --- a/Code/Editor/EditorToolsApplication.h +++ b/Code/Editor/EditorToolsApplication.h @@ -28,7 +28,7 @@ namespace EditorInternal void RegisterCoreComponents() override; - AZ::ComponentTypeList GetRequiredSystemComponents() const; + AZ::ComponentTypeList GetRequiredSystemComponents() const override; void StartCommon(AZ::Entity* systemEntity) override; diff --git a/Code/Editor/Export/ExportManager.h b/Code/Editor/Export/ExportManager.h index 4417a0ae89..14318be957 100644 --- a/Code/Editor/Export/ExportManager.h +++ b/Code/Editor/Export/ExportManager.h @@ -36,8 +36,8 @@ namespace Export public: CMesh(); - virtual int GetFaceCount() const { return static_cast(m_faces.size()); } - virtual const Face* GetFaceBuffer() const { return m_faces.size() ? &m_faces[0] : 0; } + int GetFaceCount() const override { return static_cast(m_faces.size()); } + const Face* GetFaceBuffer() const override { return !m_faces.empty() ? &m_faces[0] : nullptr; } private: std::vector m_faces; @@ -54,13 +54,13 @@ namespace Export CObject(const char* pName); int GetVertexCount() const override { return static_cast(m_vertices.size()); } - const Vector3D* GetVertexBuffer() const override { return m_vertices.size() ? &m_vertices[0] : nullptr; } + const Vector3D* GetVertexBuffer() const override { return !m_vertices.empty() ? &m_vertices[0] : nullptr; } int GetNormalCount() const override { return static_cast(m_normals.size()); } - const Vector3D* GetNormalBuffer() const override { return m_normals.size() ? &m_normals[0] : nullptr; } + const Vector3D* GetNormalBuffer() const override { return !m_normals.empty() ? &m_normals[0] : nullptr; } int GetTexCoordCount() const override { return static_cast(m_texCoords.size()); } - const UV* GetTexCoordBuffer() const override { return m_texCoords.size() ? &m_texCoords[0] : nullptr; } + const UV* GetTexCoordBuffer() const override { return !m_texCoords.empty() ? &m_texCoords[0] : nullptr; } int GetMeshCount() const override { return static_cast(m_meshes.size()); } Mesh* GetMesh(int index) const override { return m_meshes[index]; } @@ -68,9 +68,9 @@ namespace Export size_t MeshHash() const override{return m_MeshHash; } void SetMaterialName(const char* pName); - virtual int GetEntityAnimationDataCount() const {return static_cast(m_entityAnimData.size()); } - virtual const EntityAnimData* GetEntityAnimationData(int index) const {return &m_entityAnimData[index]; } - virtual void SetEntityAnimationData(EntityAnimData entityData){ m_entityAnimData.push_back(entityData); }; + int GetEntityAnimationDataCount() const override {return static_cast(m_entityAnimData.size()); } + const EntityAnimData* GetEntityAnimationData(int index) const override {return &m_entityAnimData[index]; } + void SetEntityAnimationData(EntityAnimData entityData) override{ m_entityAnimData.push_back(entityData); }; void SetLastPtr(CBaseObject* pObject){m_pLastObject = pObject; }; CBaseObject* GetLastObjectPtr(){return m_pLastObject; }; @@ -94,9 +94,9 @@ namespace Export public: virtual ~CData() = default; - virtual int GetObjectCount() const { return static_cast(m_objects.size()); } - virtual Object* GetObject(int index) const { return m_objects[index]; } - virtual Object* AddObject(const char* objectName); + int GetObjectCount() const override { return static_cast(m_objects.size()); } + Object* GetObject(int index) const override { return m_objects[index]; } + Object* AddObject(const char* objectName) override; void Clear(); private: @@ -119,7 +119,7 @@ public: //! Register exporter //! return true if succeed, otherwise false - virtual bool RegisterExporter(IExporter* pExporter); + bool RegisterExporter(IExporter* pExporter) override; //! Export specified geometry //! return true if succeed, otherwise false @@ -141,15 +141,15 @@ public: //! Exports the stat obj to the obj file specified //! returns true if succeeded, otherwise false - virtual bool ExportSingleStatObj(IStatObj* pStatObj, const char* filename); + bool ExportSingleStatObj(IStatObj* pStatObj, const char* filename) override; void SetBakedKeysSequenceExport(bool bBaked){m_bBakedKeysSequenceExport = bBaked; }; void SaveNodeKeysTimeToXML(); private: - void AddMesh(Export::CObject* pObj, const IIndexedMesh* pIndMesh, Matrix34A* pTm = 0); - bool AddStatObj(Export::CObject* pObj, IStatObj* pStatObj, Matrix34A* pTm = 0); + void AddMesh(Export::CObject* pObj, const IIndexedMesh* pIndMesh, Matrix34A* pTm = nullptr); + bool AddStatObj(Export::CObject* pObj, IStatObj* pStatObj, Matrix34A* pTm = nullptr); bool AddMeshes(Export::CObject* pObj); bool AddObject(CBaseObject* pBaseObj); void SolveHierarchy(); diff --git a/Code/Editor/IEditorImpl.h b/Code/Editor/IEditorImpl.h index 762dd1db11..26701edec2 100644 --- a/Code/Editor/IEditorImpl.h +++ b/Code/Editor/IEditorImpl.h @@ -79,70 +79,70 @@ public: void SetGameEngine(CGameEngine* ge); - void DeleteThis() { delete this; }; - IEditorClassFactory* GetClassFactory(); - CEditorCommandManager* GetCommandManager() { return m_pCommandManager; }; - ICommandManager* GetICommandManager() { return m_pCommandManager; } - void ExecuteCommand(const char* sCommand, ...); - void ExecuteCommand(const QString& command); - void SetDocument(CCryEditDoc* pDoc); - CCryEditDoc* GetDocument() const; + void DeleteThis() override { delete this; }; + IEditorClassFactory* GetClassFactory() override; + CEditorCommandManager* GetCommandManager() override { return m_pCommandManager; }; + ICommandManager* GetICommandManager() override { return m_pCommandManager; } + void ExecuteCommand(const char* sCommand, ...) override; + void ExecuteCommand(const QString& command) override; + void SetDocument(CCryEditDoc* pDoc) override; + CCryEditDoc* GetDocument() const override; bool IsLevelLoaded() const override; - void SetModifiedFlag(bool modified = true); - void SetModifiedModule(EModifiedModule eModifiedModule, bool boSet = true); - bool IsLevelExported() const; - bool SetLevelExported(bool boExported = true); + void SetModifiedFlag(bool modified = true) override; + void SetModifiedModule(EModifiedModule eModifiedModule, bool boSet = true) override; + bool IsLevelExported() const override; + bool SetLevelExported(bool boExported = true) override; void InitFinished(); - bool IsModified(); - bool IsInitialized() const{ return m_bInitialized; } - bool SaveDocument(); - ISystem* GetSystem(); - void WriteToConsole(const char* string) { CLogFile::WriteLine(string); }; - void WriteToConsole(const QString& string) { CLogFile::WriteLine(string); }; + bool IsModified() override; + bool IsInitialized() const override{ return m_bInitialized; } + bool SaveDocument() override; + ISystem* GetSystem() override; + void WriteToConsole(const char* string) override { CLogFile::WriteLine(string); }; + void WriteToConsole(const QString& string) override { CLogFile::WriteLine(string); }; // Change the message in the status bar - void SetStatusText(const QString& pszString); - virtual IMainStatusBar* GetMainStatusBar() override; - bool ShowConsole([[maybe_unused]] bool show) + void SetStatusText(const QString& pszString) override; + IMainStatusBar* GetMainStatusBar() override; + bool ShowConsole([[maybe_unused]] bool show) override { //if (AfxGetMainWnd())return ((CMainFrame *) (AfxGetMainWnd()))->ShowConsole(show); return false; } - void SetConsoleVar(const char* var, float value); - float GetConsoleVar(const char* var); + void SetConsoleVar(const char* var, float value) override; + float GetConsoleVar(const char* var) override; //! Query main window of the editor QMainWindow* GetEditorMainWindow() const override { return MainWindow::instance(); }; - QString GetPrimaryCDFolder(); + QString GetPrimaryCDFolder() override; QString GetLevelName() override; - QString GetLevelFolder(); - QString GetLevelDataFolder(); - QString GetSearchPath(EEditorPathName path); - QString GetResolvedUserFolder(); - bool ExecuteConsoleApp(const QString& CommandLine, QString& OutputText, bool bNoTimeOut = false, bool bShowWindow = false); - virtual bool IsInGameMode() override; - virtual void SetInGameMode(bool inGame) override; - virtual bool IsInSimulationMode() override; - virtual bool IsInTestMode() override; - virtual bool IsInPreviewMode() override; - virtual bool IsInConsolewMode() override; - virtual bool IsInLevelLoadTestMode() override; - virtual bool IsInMatEditMode() override { return m_bMatEditMode; } + QString GetLevelFolder() override; + QString GetLevelDataFolder() override; + QString GetSearchPath(EEditorPathName path) override; + QString GetResolvedUserFolder() override; + bool ExecuteConsoleApp(const QString& CommandLine, QString& OutputText, bool bNoTimeOut = false, bool bShowWindow = false) override; + bool IsInGameMode() override; + void SetInGameMode(bool inGame) override; + bool IsInSimulationMode() override; + bool IsInTestMode() override; + bool IsInPreviewMode() override; + bool IsInConsolewMode() override; + bool IsInLevelLoadTestMode() override; + bool IsInMatEditMode() override { return m_bMatEditMode; } //! Enables/Disable updates of editor. - void EnableUpdate(bool enable) { m_bUpdates = enable; }; + void EnableUpdate(bool enable) override { m_bUpdates = enable; }; //! Enable/Disable accelerator table, (Enabled by default). - void EnableAcceleratos(bool bEnable); - CGameEngine* GetGameEngine() { return m_pGameEngine; }; - CDisplaySettings* GetDisplaySettings() { return m_pDisplaySettings; }; - const SGizmoParameters& GetGlobalGizmoParameters(); - CBaseObject* NewObject(const char* typeName, const char* fileName = "", const char* name = "", float x = 0.0f, float y = 0.0f, float z = 0.0f, bool modifyDoc = true); - void DeleteObject(CBaseObject* obj); - CBaseObject* CloneObject(CBaseObject* obj); - IObjectManager* GetObjectManager(); + void EnableAcceleratos(bool bEnable) override; + CGameEngine* GetGameEngine() override { return m_pGameEngine; }; + CDisplaySettings* GetDisplaySettings() override { return m_pDisplaySettings; }; + const SGizmoParameters& GetGlobalGizmoParameters() override; + CBaseObject* NewObject(const char* typeName, const char* fileName = "", const char* name = "", float x = 0.0f, float y = 0.0f, float z = 0.0f, bool modifyDoc = true) override; + void DeleteObject(CBaseObject* obj) override; + CBaseObject* CloneObject(CBaseObject* obj) override; + IObjectManager* GetObjectManager() override; // This will return a null pointer if CrySystem is not loaded before // Global Sandbox Settings are loaded from the registry before CrySystem // At that stage GetSettingsManager will return null and xml node in @@ -150,27 +150,27 @@ public: // After m_IEditor is created and CrySystem loaded, it is possible // to feed memory node with all necessary data needed for export // (gSettings.Load() and CXTPDockingPaneManager/CXTPDockingPaneLayout Sandbox layout management) - CSettingsManager* GetSettingsManager(); - CSelectionGroup* GetSelection(); - int ClearSelection(); - CBaseObject* GetSelectedObject(); - void SelectObject(CBaseObject* obj); - void LockSelection(bool bLock); - bool IsSelectionLocked(); + CSettingsManager* GetSettingsManager() override; + CSelectionGroup* GetSelection() override; + int ClearSelection() override; + CBaseObject* GetSelectedObject() override; + void SelectObject(CBaseObject* obj) override; + void LockSelection(bool bLock) override; + bool IsSelectionLocked() override; - IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType); - CMusicManager* GetMusicManager() { return m_pMusicManager; }; + IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) override; + CMusicManager* GetMusicManager() override { return m_pMusicManager; }; IEditorFileMonitor* GetFileMonitor() override; void RegisterEventLoopHook(IEventLoopHook* pHook) override; void UnregisterEventLoopHook(IEventLoopHook* pHook) override; - IIconManager* GetIconManager(); - float GetTerrainElevation(float x, float y); - Editor::EditorQtApplication* GetEditorQtApplication() { return m_QtApplication; } + IIconManager* GetIconManager() override; + float GetTerrainElevation(float x, float y) override; + Editor::EditorQtApplication* GetEditorQtApplication() override { return m_QtApplication; } const QColor& GetColorByName(const QString& name) override; ////////////////////////////////////////////////////////////////////////// - IMovieSystem* GetMovieSystem() + IMovieSystem* GetMovieSystem() override { if (m_pSystem) { @@ -179,37 +179,37 @@ public: return nullptr; }; - CPluginManager* GetPluginManager() { return m_pPluginManager; } - CViewManager* GetViewManager(); - CViewport* GetActiveView(); - void SetActiveView(CViewport* viewport); + CPluginManager* GetPluginManager() override { return m_pPluginManager; } + CViewManager* GetViewManager() override; + CViewport* GetActiveView() override; + void SetActiveView(CViewport* viewport) override; - CLevelIndependentFileMan* GetLevelIndependentFileMan() { return m_pLevelIndependentFileMan; } + CLevelIndependentFileMan* GetLevelIndependentFileMan() override { return m_pLevelIndependentFileMan; } - void UpdateViews(int flags, const AABB* updateRegion); - void ResetViews(); - void ReloadTrackView(); - Vec3 GetMarkerPosition() { return m_marker; }; - void SetMarkerPosition(const Vec3& pos) { m_marker = pos; }; - void SetSelectedRegion(const AABB& box); - void GetSelectedRegion(AABB& box); + void UpdateViews(int flags, const AABB* updateRegion) override; + void ResetViews() override; + void ReloadTrackView() override; + Vec3 GetMarkerPosition() override { return m_marker; }; + void SetMarkerPosition(const Vec3& pos) override { m_marker = pos; }; + void SetSelectedRegion(const AABB& box) override; + void GetSelectedRegion(AABB& box) override; bool AddToolbarItem(uint8 iId, IUIEvent* pIHandler); - void SetDataModified(); - void SetOperationMode(EOperationMode mode); - EOperationMode GetOperationMode(); - - ITransformManipulator* ShowTransformManipulator(bool bShow); - ITransformManipulator* GetTransformManipulator(); - void SetAxisConstraints(AxisConstrains axis); - AxisConstrains GetAxisConstrains(); - void SetAxisVectorLock(bool bAxisVectorLock) { m_bAxisVectorLock = bAxisVectorLock; } - bool IsAxisVectorLocked() { return m_bAxisVectorLock; } - void SetTerrainAxisIgnoreObjects(bool bIgnore); - bool IsTerrainAxisIgnoreObjects(); - void SetReferenceCoordSys(RefCoordSys refCoords); - RefCoordSys GetReferenceCoordSys(); - XmlNodeRef FindTemplate(const QString& templateName); - void AddTemplate(const QString& templateName, XmlNodeRef& tmpl); + void SetDataModified() override; + void SetOperationMode(EOperationMode mode) override; + EOperationMode GetOperationMode() override; + + ITransformManipulator* ShowTransformManipulator(bool bShow) override; + ITransformManipulator* GetTransformManipulator() override; + void SetAxisConstraints(AxisConstrains axis) override; + AxisConstrains GetAxisConstrains() override; + void SetAxisVectorLock(bool bAxisVectorLock) override { m_bAxisVectorLock = bAxisVectorLock; } + bool IsAxisVectorLocked() override { return m_bAxisVectorLock; } + void SetTerrainAxisIgnoreObjects(bool bIgnore) override; + bool IsTerrainAxisIgnoreObjects() override; + void SetReferenceCoordSys(RefCoordSys refCoords) override; + RefCoordSys GetReferenceCoordSys() override; + XmlNodeRef FindTemplate(const QString& templateName) override; + void AddTemplate(const QString& templateName, XmlNodeRef& tmpl) override; const QtViewPane* OpenView(QString sViewClassName, bool reuseOpened = true) override; @@ -220,87 +220,87 @@ public: */ QWidget* FindView(QString viewClassName) override; - bool CloseView(const char* sViewClassName); - bool SetViewFocus(const char* sViewClassName); + bool CloseView(const char* sViewClassName) override; + bool SetViewFocus(const char* sViewClassName) override; - virtual QWidget* OpenWinWidget(WinWidgetId openId) override; - virtual WinWidget::WinWidgetManager* GetWinWidgetManager() const override; + QWidget* OpenWinWidget(WinWidgetId openId) override; + WinWidget::WinWidgetManager* GetWinWidgetManager() const override; // close ALL panels related to classId, used when unloading plugins. - void CloseView(const GUID& classId); + void CloseView(const GUID& classId) override; bool SelectColor(QColor &color, QWidget *parent = 0) override; void Update(); - SFileVersion GetFileVersion() { return m_fileVersion; }; - SFileVersion GetProductVersion() { return m_productVersion; }; + SFileVersion GetFileVersion() override { return m_fileVersion; }; + SFileVersion GetProductVersion() override { return m_productVersion; }; //! Get shader enumerator. - CUndoManager* GetUndoManager() { return m_pUndoManager; }; - void BeginUndo(); - void RestoreUndo(bool undo); - void AcceptUndo(const QString& name); - void CancelUndo(); - void SuperBeginUndo(); - void SuperAcceptUndo(const QString& name); - void SuperCancelUndo(); - void SuspendUndo(); - void ResumeUndo(); - void Undo(); - void Redo(); - bool IsUndoRecording(); - bool IsUndoSuspended(); - void RecordUndo(IUndoObject* obj); - bool FlushUndo(bool isShowMessage = false); - bool ClearLastUndoSteps(int steps); - bool ClearRedoStack(); + CUndoManager* GetUndoManager() override { return m_pUndoManager; }; + void BeginUndo() override; + void RestoreUndo(bool undo) override; + void AcceptUndo(const QString& name) override; + void CancelUndo() override; + void SuperBeginUndo() override; + void SuperAcceptUndo(const QString& name) override; + void SuperCancelUndo() override; + void SuspendUndo() override; + void ResumeUndo() override; + void Undo() override; + void Redo() override; + bool IsUndoRecording() override; + bool IsUndoSuspended() override; + void RecordUndo(IUndoObject* obj) override; + bool FlushUndo(bool isShowMessage = false) override; + bool ClearLastUndoSteps(int steps) override; + bool ClearRedoStack() override; //! Retrieve current animation context. - CAnimationContext* GetAnimation(); + CAnimationContext* GetAnimation() override; CTrackViewSequenceManager* GetSequenceManager() override; ITrackViewSequenceManager* GetSequenceManagerInterface() override; - CToolBoxManager* GetToolBoxManager() { return m_pToolBoxManager; }; - IErrorReport* GetErrorReport() { return m_pErrorReport; } - IErrorReport* GetLastLoadedLevelErrorReport() { return m_pLasLoadedLevelErrorReport; } + CToolBoxManager* GetToolBoxManager() override { return m_pToolBoxManager; }; + IErrorReport* GetErrorReport() override { return m_pErrorReport; } + IErrorReport* GetLastLoadedLevelErrorReport() override { return m_pLasLoadedLevelErrorReport; } void StartLevelErrorReportRecording() override; - void CommitLevelErrorReport() {SAFE_DELETE(m_pLasLoadedLevelErrorReport); m_pLasLoadedLevelErrorReport = new CErrorReport(*m_pErrorReport); } - virtual IFileUtil* GetFileUtil() override { return m_pFileUtil; } - void Notify(EEditorNotifyEvent event); - void NotifyExcept(EEditorNotifyEvent event, IEditorNotifyListener* listener); - void RegisterNotifyListener(IEditorNotifyListener* listener); - void UnregisterNotifyListener(IEditorNotifyListener* listener); + void CommitLevelErrorReport() override {SAFE_DELETE(m_pLasLoadedLevelErrorReport); m_pLasLoadedLevelErrorReport = new CErrorReport(*m_pErrorReport); } + IFileUtil* GetFileUtil() override { return m_pFileUtil; } + void Notify(EEditorNotifyEvent event) override; + void NotifyExcept(EEditorNotifyEvent event, IEditorNotifyListener* listener) override; + void RegisterNotifyListener(IEditorNotifyListener* listener) override; + void UnregisterNotifyListener(IEditorNotifyListener* listener) override; //! Register document notifications listener. - void RegisterDocListener(IDocListener* listener); + void RegisterDocListener(IDocListener* listener) override; //! Unregister document notifications listener. - void UnregisterDocListener(IDocListener* listener); + void UnregisterDocListener(IDocListener* listener) override; //! Retrieve interface to the source control. - ISourceControl* GetSourceControl(); + ISourceControl* GetSourceControl() override; //! Retrieve true if source control is provided and enabled in settings bool IsSourceControlAvailable() override; //! Only returns true if source control is both available AND currently connected and functioning bool IsSourceControlConnected() override; //! Setup Material Editor mode void SetMatEditMode(bool bIsMatEditMode); - CUIEnumsDatabase* GetUIEnumsDatabase() { return m_pUIEnumsDatabase; }; - void AddUIEnums(); - void ReduceMemory(); + CUIEnumsDatabase* GetUIEnumsDatabase() override { return m_pUIEnumsDatabase; }; + void AddUIEnums() override; + void ReduceMemory() override; // Get Export manager - IExportManager* GetExportManager(); + IExportManager* GetExportManager() override; // Set current configuration spec of the editor. - void SetEditorConfigSpec(ESystemConfigSpec spec, ESystemConfigPlatform platform); - ESystemConfigSpec GetEditorConfigSpec() const; - ESystemConfigPlatform GetEditorConfigPlatform() const; - void ReloadTemplates(); + void SetEditorConfigSpec(ESystemConfigSpec spec, ESystemConfigPlatform platform) override; + ESystemConfigSpec GetEditorConfigSpec() const override; + ESystemConfigPlatform GetEditorConfigPlatform() const override; + void ReloadTemplates() override; void AddErrorMessage(const QString& text, const QString& caption); - virtual void ShowStatusText(bool bEnable); + void ShowStatusText(bool bEnable) override; void OnObjectContextMenuOpened(QMenu* pMenu, const CBaseObject* pObject); - virtual void RegisterObjectContextMenuExtension(TContextMenuExtensionFunc func) override; - - virtual SSystemGlobalEnvironment* GetEnv() override; - virtual IBaseLibraryManager* GetMaterialManagerLibrary() override; // Vladimir@Conffx - virtual IEditorMaterialManager* GetIEditorMaterialManager() override; // Vladimir@Conffx - virtual IImageUtil* GetImageUtil() override; // Vladimir@conffx - virtual SEditorSettings* GetEditorSettings() override; - virtual IEditorPanelUtils* GetEditorPanelUtils() override; - virtual ILogFile* GetLogFile() override { return m_pLogFile; } + void RegisterObjectContextMenuExtension(TContextMenuExtensionFunc func) override; + + SSystemGlobalEnvironment* GetEnv() override; + IBaseLibraryManager* GetMaterialManagerLibrary() override; // Vladimir@Conffx + IEditorMaterialManager* GetIEditorMaterialManager() override; // Vladimir@Conffx + IImageUtil* GetImageUtil() override; // Vladimir@conffx + SEditorSettings* GetEditorSettings() override; + IEditorPanelUtils* GetEditorPanelUtils() override; + ILogFile* GetLogFile() override { return m_pLogFile; } void UnloadPlugins() override; void LoadPlugins() override; diff --git a/Code/Editor/LevelTreeModel.h b/Code/Editor/LevelTreeModel.h index 4f0e36a311..7cc5cf5496 100644 --- a/Code/Editor/LevelTreeModel.h +++ b/Code/Editor/LevelTreeModel.h @@ -23,7 +23,7 @@ class LevelTreeModelFilter Q_OBJECT public: explicit LevelTreeModelFilter(QObject* parent = nullptr); - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; void setFilterText(const QString&); QVariant data(const QModelIndex& index, int role) const override; private: diff --git a/Code/Editor/Objects/AxisGizmo.h b/Code/Editor/Objects/AxisGizmo.h index dfd35388b6..bab667a629 100644 --- a/Code/Editor/Objects/AxisGizmo.h +++ b/Code/Editor/Objects/AxisGizmo.h @@ -35,21 +35,21 @@ public: ////////////////////////////////////////////////////////////////////////// // Ovverides from CGizmo ////////////////////////////////////////////////////////////////////////// - virtual void GetWorldBounds(AABB& bbox); - virtual void Display(DisplayContext& dc); - virtual bool HitTest(HitContext& hc); - virtual const Matrix34& GetMatrix() const; + void GetWorldBounds(AABB& bbox) override; + void Display(DisplayContext& dc) override; + bool HitTest(HitContext& hc) override; + const Matrix34& GetMatrix() const override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // ITransformManipulator implementation. ////////////////////////////////////////////////////////////////////////// - virtual Matrix34 GetTransformation(RefCoordSys coordSys, IDisplayViewport* view = nullptr) const; - virtual void SetTransformation(RefCoordSys coordSys, const Matrix34& tm); - virtual bool HitTestManipulator(HitContext& hc); - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int nFlags); - virtual void SetAlwaysUseLocal(bool on) + Matrix34 GetTransformation(RefCoordSys coordSys, IDisplayViewport* view = nullptr) const override; + void SetTransformation(RefCoordSys coordSys, const Matrix34& tm) override; + bool HitTestManipulator(HitContext& hc) override; + bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int nFlags) override; + void SetAlwaysUseLocal(bool on) override { m_bAlwaysUseLocal = on; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Objects/BaseObject.h b/Code/Editor/Objects/BaseObject.h index 0b37a3b852..3865696ecb 100644 --- a/Code/Editor/Objects/BaseObject.h +++ b/Code/Editor/Objects/BaseObject.h @@ -712,7 +712,7 @@ protected: // May be overridden in derived classes to handle helpers scaling. ////////////////////////////////////////////////////////////////////////// virtual void SetHelperScale([[maybe_unused]] float scale) {}; - virtual float GetHelperScale() { return 1; }; + virtual float GetHelperScale() { return 1.0f; }; void SetNameInternal(const QString& name) { m_name = name; } diff --git a/Code/Editor/Objects/EntityObject.h b/Code/Editor/Objects/EntityObject.h index 6150685c45..dcc6ff7b22 100644 --- a/Code/Editor/Objects/EntityObject.h +++ b/Code/Editor/Objects/EntityObject.h @@ -82,14 +82,14 @@ public: // Overrides from CBaseObject. ////////////////////////////////////////////////////////////////////////// //! Return type name of Entity. - QString GetTypeDescription() const { return GetEntityClass(); }; + QString GetTypeDescription() const override { return GetEntityClass(); }; ////////////////////////////////////////////////////////////////////////// - bool IsSameClass(CBaseObject* obj); + bool IsSameClass(CBaseObject* obj) override; - virtual bool Init(IEditor* ie, CBaseObject* prev, const QString& file); - virtual void InitVariables(); - virtual void Done(); + bool Init(IEditor* ie, CBaseObject* prev, const QString& file) override; + void InitVariables() override; + void Done() override; void DrawExtraLightInfo (DisplayContext& disp); @@ -102,30 +102,30 @@ public: void SetEntityPropertyFloat(const char* name, float value); void SetEntityPropertyString(const char* name, const QString& value); - virtual int MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - virtual void OnContextMenu(QMenu* menu); + int MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) override; + void OnContextMenu(QMenu* menu) override; - void SetName(const QString& name); - void SetSelected(bool bSelect); + void SetName(const QString& name) override; + void SetSelected(bool bSelect) override; - virtual void GetLocalBounds(AABB& box); + void GetLocalBounds(AABB& box) override; - virtual bool HitTest(HitContext& hc); - virtual bool HitHelperTest(HitContext& hc); - virtual bool HitTestRect(HitContext& hc); - void UpdateVisibility(bool bVisible); - bool ConvertFromObject(CBaseObject* object); + bool HitTest(HitContext& hc) override; + bool HitHelperTest(HitContext& hc) override; + bool HitTestRect(HitContext& hc) override; + void UpdateVisibility(bool bVisible) override; + bool ConvertFromObject(CBaseObject* object) override; using CBaseObject::Serialize; void Serialize(CObjectArchive& ar) override; - virtual void PostLoad(CObjectArchive& ar); + void PostLoad(CObjectArchive& ar) override; - XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode); + XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode) override; ////////////////////////////////////////////////////////////////////////// - void OnEvent(ObjectEvent event); + void OnEvent(ObjectEvent event) override; - virtual void SetTransformDelegate(ITransformDelegate* pTransformDelegate) override; + void SetTransformDelegate(ITransformDelegate* pTransformDelegate) override; // Set attach flags and target enum EAttachmentType @@ -140,15 +140,15 @@ public: EAttachmentType GetAttachType() const { return m_attachmentType; } QString GetAttachTarget() const { return m_attachmentTarget; } - virtual void SetHelperScale(float scale); - virtual float GetHelperScale(); + void SetHelperScale(float scale) override; + float GetHelperScale() override; - virtual void GatherUsedResources(CUsedResources& resources); - virtual bool IsSimilarObject(CBaseObject* pObject); + void GatherUsedResources(CUsedResources& resources) override; + bool IsSimilarObject(CBaseObject* pObject) override; - virtual bool HasMeasurementAxis() const { return false; } + bool HasMeasurementAxis() const override { return false; } - virtual bool IsIsolated() const { return false; } + bool IsIsolated() const override { return false; } ////////////////////////////////////////////////////////////////////////// // END CBaseObject @@ -233,7 +233,7 @@ protected: ////////////////////////////////////////////////////////////////////////// //! Must be called after cloning the object on clone of object. //! This will make sure object references are cloned correctly. - virtual void PostClone(CBaseObject* pFromObject, CObjectCloneContext& ctx); + void PostClone(CBaseObject* pFromObject, CObjectCloneContext& ctx) override; //! Draw default object items. void DrawProjectorPyramid(DisplayContext& dc, float dist); @@ -265,7 +265,7 @@ public: } protected: - void DeleteThis() { delete this; }; + void DeleteThis() override { delete this; }; ////////////////////////////////////////////////////////////////////////// // Radius callbacks. diff --git a/Code/Editor/Objects/GizmoManager.h b/Code/Editor/Objects/GizmoManager.h index c3a71ad81b..efc3e99205 100644 --- a/Code/Editor/Objects/GizmoManager.h +++ b/Code/Editor/Objects/GizmoManager.h @@ -23,14 +23,14 @@ class CGizmoManager : public IGizmoManager { public: - void AddGizmo(CGizmo* gizmo); - void RemoveGizmo(CGizmo* gizmo); + void AddGizmo(CGizmo* gizmo) override; + void RemoveGizmo(CGizmo* gizmo) override; int GetGizmoCount() const override; CGizmo* GetGizmoByIndex(int nIndex) const override; - void Display(DisplayContext& dc); - bool HitTest(HitContext& hc); + void Display(DisplayContext& dc) override; + bool HitTest(HitContext& hc) override; void DeleteAllTransformManipulators(); diff --git a/Code/Editor/Objects/LineGizmo.h b/Code/Editor/Objects/LineGizmo.h index af3b38b199..e50f044f3c 100644 --- a/Code/Editor/Objects/LineGizmo.h +++ b/Code/Editor/Objects/LineGizmo.h @@ -30,10 +30,10 @@ public: ////////////////////////////////////////////////////////////////////////// // Ovverides from CGizmo ////////////////////////////////////////////////////////////////////////// - virtual void SetName(const char* sName); - virtual void GetWorldBounds(AABB& bbox); - virtual void Display(DisplayContext& dc); - virtual bool HitTest(HitContext& hc); + void SetName(const char* sName) override; + void GetWorldBounds(AABB& bbox) override; + void Display(DisplayContext& dc) override; + bool HitTest(HitContext& hc) override; ////////////////////////////////////////////////////////////////////////// void SetObjects(CBaseObject* pObject1, CBaseObject* pObject2, const QString& boneName = ""); diff --git a/Code/Editor/Objects/ObjectManager.h b/Code/Editor/Objects/ObjectManager.h index de0a4ce849..4ffa5e9a07 100644 --- a/Code/Editor/Objects/ObjectManager.h +++ b/Code/Editor/Objects/ObjectManager.h @@ -103,142 +103,142 @@ public: void RegisterObjectClasses(); - CBaseObject* NewObject(CObjectClassDesc* cls, CBaseObject* prev = 0, const QString& file = "", const char* newObjectName = nullptr); - CBaseObject* NewObject(const QString& typeName, CBaseObject* prev = 0, const QString& file = "", const char* newEntityName = nullptr); + CBaseObject* NewObject(CObjectClassDesc* cls, CBaseObject* prev = 0, const QString& file = "", const char* newObjectName = nullptr) override; + CBaseObject* NewObject(const QString& typeName, CBaseObject* prev = 0, const QString& file = "", const char* newEntityName = nullptr) override; - void DeleteObject(CBaseObject* obj); - void DeleteSelection(CSelectionGroup* pSelection); - void DeleteAllObjects(); - CBaseObject* CloneObject(CBaseObject* obj); + void DeleteObject(CBaseObject* obj) override; + void DeleteSelection(CSelectionGroup* pSelection) override; + void DeleteAllObjects() override; + CBaseObject* CloneObject(CBaseObject* obj) override; - void BeginEditParams(CBaseObject* obj, int flags); - void EndEditParams(int flags = 0); + void BeginEditParams(CBaseObject* obj, int flags) override; + void EndEditParams(int flags = 0) override; // Hides all transform manipulators. void HideTransformManipulators(); //! Get number of objects manager by ObjectManager (not contain sub objects of groups). - int GetObjectCount() const; + int GetObjectCount() const override; //! Get array of objects, managed by manager (not contain sub objects of groups). //! @param layer if 0 get objects for all layers, or layer to get objects from. - void GetObjects(CBaseObjectsArray& objects) const; + void GetObjects(CBaseObjectsArray& objects) const override; //! Get array of objects that pass the filter. //! @param filter The filter functor, return true if you want to get the certain obj, return false if want to skip it. - void GetObjects(CBaseObjectsArray& objects, BaseObjectFilterFunctor const& filter) const; + void GetObjects(CBaseObjectsArray& objects, BaseObjectFilterFunctor const& filter) const override; //! Update objects. void Update(); //! Display objects on display context. - void Display(DisplayContext& dc); + void Display(DisplayContext& dc) override; //! Called when selecting without selection helpers - this is needed since //! the visible object cache is normally not updated when not displaying helpers. - void ForceUpdateVisibleObjectCache(DisplayContext& dc); + void ForceUpdateVisibleObjectCache(DisplayContext& dc) override; //! Check intersection with objects. //! Find intersection with nearest to ray origin object hit by ray. //! If distance tollerance is specified certain relaxation applied on collision test. //! @return true if hit any object, and fills hitInfo structure. - bool HitTest(HitContext& hitInfo); + bool HitTest(HitContext& hitInfo) override; //! Check intersection with an object. //! @return true if hit, and fills hitInfo structure. - bool HitTestObject(CBaseObject* obj, HitContext& hc); + bool HitTestObject(CBaseObject* obj, HitContext& hc) override; //! Send event to all objects. //! Will cause OnEvent handler to be called on all objects. - void SendEvent(ObjectEvent event); + void SendEvent(ObjectEvent event) override; //! Send event to all objects within given bounding box. //! Will cause OnEvent handler to be called on objects within bounding box. - void SendEvent(ObjectEvent event, const AABB& bounds); + void SendEvent(ObjectEvent event, const AABB& bounds) override; ////////////////////////////////////////////////////////////////////////// //! Find object by ID. - CBaseObject* FindObject(REFGUID guid) const; + CBaseObject* FindObject(REFGUID guid) const override; ////////////////////////////////////////////////////////////////////////// //! Find object by name. - CBaseObject* FindObject(const QString& sName) const; + CBaseObject* FindObject(const QString& sName) const override; ////////////////////////////////////////////////////////////////////////// //! Find objects of given type. void FindObjectsOfType(const QMetaObject* pClass, std::vector& result) override; void FindObjectsOfType(ObjectType type, std::vector& result) override; ////////////////////////////////////////////////////////////////////////// //! Find objects which intersect with a given AABB. - virtual void FindObjectsInAABB(const AABB& aabb, std::vector& result) const; + void FindObjectsInAABB(const AABB& aabb, std::vector& result) const override; ////////////////////////////////////////////////////////////////////////// // Operations on objects. ////////////////////////////////////////////////////////////////////////// //! Makes object visible or invisible. - void HideObject(CBaseObject* obj, bool hide); + void HideObject(CBaseObject* obj, bool hide) override; //! Shows the last hidden object based on hidden ID - void ShowLastHiddenObject(); + void ShowLastHiddenObject() override; //! Freeze object, making it unselectable. - void FreezeObject(CBaseObject* obj, bool freeze); + void FreezeObject(CBaseObject* obj, bool freeze) override; //! Unhide all hidden objects. - void UnhideAll(); + void UnhideAll() override; //! Unfreeze all frozen objects. - void UnfreezeAll(); + void UnfreezeAll() override; ////////////////////////////////////////////////////////////////////////// // Object Selection. ////////////////////////////////////////////////////////////////////////// - bool SelectObject(CBaseObject* obj, bool bUseMask = true); - void UnselectObject(CBaseObject* obj); + bool SelectObject(CBaseObject* obj, bool bUseMask = true) override; + void UnselectObject(CBaseObject* obj) override; //! Select objects within specified distance from given position. //! Return number of selected objects. - int SelectObjects(const AABB& box, bool bUnselect = false); + int SelectObjects(const AABB& box, bool bUnselect = false) override; - virtual void SelectEntities(std::set& s); + void SelectEntities(std::set& s) override; - int MoveObjects(const AABB& box, const Vec3& offset, ImageRotationDegrees rotation, bool bIsCopy = false); + int MoveObjects(const AABB& box, const Vec3& offset, ImageRotationDegrees rotation, bool bIsCopy = false) override; //! Selects/Unselects all objects within 2d rectangle in given viewport. - void SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect); - void FindObjectsInRect(CViewport* view, const QRect& rect, std::vector& guids); + void SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect) override; + void FindObjectsInRect(CViewport* view, const QRect& rect, std::vector& guids) override; //! Clear default selection set. //! @Return number of objects removed from selection. - int ClearSelection(); + int ClearSelection() override; //! Deselect all current selected objects and selects object that were unselected. //! @Return number of selected objects. - int InvertSelection(); + int InvertSelection() override; //! Get current selection. - CSelectionGroup* GetSelection() const { return m_currSelection; }; + CSelectionGroup* GetSelection() const override { return m_currSelection; }; //! Get named selection. - CSelectionGroup* GetSelection(const QString& name) const; + CSelectionGroup* GetSelection(const QString& name) const override; // Get selection group names - void GetNameSelectionStrings(QStringList& names); + void GetNameSelectionStrings(QStringList& names) override; //! Change name of current selection group. //! And store it in list. - void NameSelection(const QString& name); + void NameSelection(const QString& name) override; //! Set one of name selections as current selection. - void SetSelection(const QString& name); - void RemoveSelection(const QString& name); + void SetSelection(const QString& name) override; + void RemoveSelection(const QString& name) override; bool IsObjectDeletionAllowed(CBaseObject* pObject); //! Delete all objects in selection group. - void DeleteSelection(); + void DeleteSelection() override; - uint32 ForceID() const{return m_ForceID; } - void ForceID(uint32 FID){m_ForceID = FID; } + uint32 ForceID() const override{return m_ForceID; } + void ForceID(uint32 FID) override{m_ForceID = FID; } //! Generates uniq name base on type name of object. - QString GenerateUniqueObjectName(const QString& typeName); + QString GenerateUniqueObjectName(const QString& typeName) override; //! Register object name in object manager, needed for generating uniq names. - void RegisterObjectName(const QString& name); + void RegisterObjectName(const QString& name) override; //! Decrease name number and remove if it was last in object manager, needed for generating uniq names. void UpdateRegisterObjectName(const QString& name); //! Enable/Disable generating of unique object names (Enabled by default). //! Return previous value. - bool EnableUniqObjectNames(bool bEnable); + bool EnableUniqObjectNames(bool bEnable) override; //! Register XML template of runtime class. void RegisterClassTemplate(const XmlNodeRef& templ); @@ -249,25 +249,25 @@ public: void RegisterCVars(); //! Find object class by name. - CObjectClassDesc* FindClass(const QString& className); - void GetClassCategories(QStringList& categories); + CObjectClassDesc* FindClass(const QString& className) override; + void GetClassCategories(QStringList& categories) override; void GetClassCategoryToolClassNamePairs(std::vector< std::pair >& categoryToolClassNamePairs) override; - void GetClassTypes(const QString& category, QStringList& types); + void GetClassTypes(const QString& category, QStringList& types) override; //! Export objects to xml. //! When onlyShared is true ony objects with shared flags exported, overwise only not shared object exported. - void Export(const QString& levelPath, XmlNodeRef& rootNode, bool onlyShared); - void ExportEntities(XmlNodeRef& rootNode); + void Export(const QString& levelPath, XmlNodeRef& rootNode, bool onlyShared) override; + void ExportEntities(XmlNodeRef& rootNode) override; //! Serialize Objects in manager to specified XML Node. //! @param flags Can be one of SerializeFlags. - void Serialize(XmlNodeRef& rootNode, bool bLoading, int flags = SERIALIZE_ALL); + void Serialize(XmlNodeRef& rootNode, bool bLoading, int flags = SERIALIZE_ALL) override; - void SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading); + void SerializeNameSelection(XmlNodeRef& rootNode, bool bLoading) override; //! Load objects from object archive. //! @param bSelect if set newly loaded object will be selected. - void LoadObjects(CObjectArchive& ar, bool bSelect); + void LoadObjects(CObjectArchive& ar, bool bSelect) override; //! Delete from Object manager all objects without SHARED flag. void DeleteNotSharedObjects(); @@ -276,57 +276,57 @@ public: bool AddObject(CBaseObject* obj); void RemoveObject(CBaseObject* obj); - void ChangeObjectId(REFGUID oldId, REFGUID newId); - bool IsDuplicateObjectName(const QString& newName) const + void ChangeObjectId(REFGUID oldId, REFGUID newId) override; + bool IsDuplicateObjectName(const QString& newName) const override { return FindObject(newName) ? true : false; } - void ShowDuplicationMsgWarning(CBaseObject* obj, const QString& newName, bool bShowMsgBox) const; - void ChangeObjectName(CBaseObject* obj, const QString& newName); + void ShowDuplicationMsgWarning(CBaseObject* obj, const QString& newName, bool bShowMsgBox) const override; + void ChangeObjectName(CBaseObject* obj, const QString& newName) override; //! Convert object of one type to object of another type. //! Original object is deleted. - bool ConvertToType(CBaseObject* pObject, const QString& typeName); + bool ConvertToType(CBaseObject* pObject, const QString& typeName) override; //! Set new selection callback. //! @return previous selection callback. - IObjectSelectCallback* SetSelectCallback(IObjectSelectCallback* callback); + IObjectSelectCallback* SetSelectCallback(IObjectSelectCallback* callback) override; // Enables/Disables creating of game objects. - void SetCreateGameObject(bool enable) { m_createGameObjects = enable; }; + void SetCreateGameObject(bool enable) override { m_createGameObjects = enable; }; //! Return true if objects loaded from xml should immidiatly create game objects associated with them. - bool IsCreateGameObjects() const { return m_createGameObjects; }; + bool IsCreateGameObjects() const override { return m_createGameObjects; }; ////////////////////////////////////////////////////////////////////////// //! Get access to gizmo manager. - IGizmoManager* GetGizmoManager(); + IGizmoManager* GetGizmoManager() override; ////////////////////////////////////////////////////////////////////////// //! Invalidate visibily settings of objects. - void InvalidateVisibleList(); + void InvalidateVisibleList() override; ////////////////////////////////////////////////////////////////////////// // ObjectManager notification Callbacks. ////////////////////////////////////////////////////////////////////////// - void AddObjectEventListener(EventListener* listener); - void RemoveObjectEventListener(EventListener* listener); + void AddObjectEventListener(EventListener* listener) override; + void RemoveObjectEventListener(EventListener* listener) override; ////////////////////////////////////////////////////////////////////////// // Used to indicate starting and ending of objects loading. ////////////////////////////////////////////////////////////////////////// - void StartObjectsLoading(int numObjects); - void EndObjectsLoading(); + void StartObjectsLoading(int numObjects) override; + void EndObjectsLoading() override; ////////////////////////////////////////////////////////////////////////// // Gathers all resources used by all objects. - void GatherUsedResources(CUsedResources& resources); + void GatherUsedResources(CUsedResources& resources) override; - virtual bool IsLightClass(CBaseObject* pObject); + bool IsLightClass(CBaseObject* pObject) override; - virtual void FindAndRenameProperty2(const char* property2Name, const QString& oldValue, const QString& newValue); - virtual void FindAndRenameProperty2If(const char* property2Name, const QString& oldValue, const QString& newValue, const char* otherProperty2Name, const QString& otherValue); + virtual void FindAndRenameProperty2(const char* property2Name, const QString& oldValue, const QString& newValue) override; + virtual void FindAndRenameProperty2If(const char* property2Name, const QString& oldValue, const QString& newValue, const char* otherProperty2Name, const QString& otherValue) override; - bool IsReloading() const { return m_bInReloading; } + bool IsReloading() const override { return m_bInReloading; } void SetSkipUpdate(bool bSkipUpdate) override { m_bSkipObjectUpdate = bSkipUpdate; } void SetExportingLevel(bool bExporting) override { m_bLevelExporting = bExporting; } @@ -341,7 +341,7 @@ private: @param objectNode Xml node to serialize object info from. @param pUndoObject Pointer to deleted object for undo. */ - CBaseObject* NewObject(CObjectArchive& archive, CBaseObject* pUndoObject, bool bMakeNewId); + CBaseObject* NewObject(CObjectArchive& archive, CBaseObject* pUndoObject, bool bMakeNewId) override; //! Update visibility of all objects. void UpdateVisibilityList(); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h index 23151eb05c..bb19f4d77e 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h @@ -86,7 +86,7 @@ public: // Always returns false as Component entity highlighting (accenting) is taken care of elsewhere bool IsHighlighted() { return false; } // Component entity highlighting (accenting) is taken care of elsewhere - void DrawHighlight(DisplayContext& /*dc*/) {}; + void DrawHighlight(DisplayContext& /*dc*/) override {}; // Don't auto-clone children. Cloning happens in groups with reference fixups, // and individually selected objercts should be cloned as individuals. @@ -164,7 +164,7 @@ protected: float GetRadius(); - void DeleteThis() { delete this; }; + void DeleteThis() override { delete this; }; bool IsNonLayerAncestorSelected() const; bool IsLayer() const; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index f2764681b2..617c5cb2c8 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -182,7 +182,7 @@ private: ////////////////////////////////////////////////////////////////////////// // AzToolsFramework::EditorContextMenu::Bus::Handler overrides void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; - int GetMenuPosition() const; + int GetMenuPosition() const override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/FavoriteComponentList.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/FavoriteComponentList.h index 5f704237ab..2bd2d83e04 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/FavoriteComponentList.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/FavoriteComponentList.h @@ -102,7 +102,7 @@ protected: void AddFavorites(const AZStd::vector& classDataContainer) override; ////////////////////////////////////////////////////////////////////////// - void rowsInserted(const QModelIndex& parent, int start, int end); + void rowsInserted(const QModelIndex& parent, int start, int end) override; // Context menu handlers void ShowContextMenu(const QPoint&); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.hxx b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.hxx index 346a5e938a..8acb2f1a72 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.hxx +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.hxx @@ -255,7 +255,7 @@ protected: bool DropMimeDataAssets(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); bool CanDropMimeDataAssets(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const; - QMap itemData(const QModelIndex &index) const; + QMap itemData(const QModelIndex &index) const override; QVariant dataForAll(const QModelIndex& index, int role) const; QVariant dataForName(const QModelIndex& index, int role) const; QVariant dataForVisibility(const QModelIndex& index, int role) const; diff --git a/Code/Editor/PreferencesStdPages.h b/Code/Editor/PreferencesStdPages.h index f4a6e0b783..8a182bde55 100644 --- a/Code/Editor/PreferencesStdPages.h +++ b/Code/Editor/PreferencesStdPages.h @@ -28,16 +28,16 @@ public: ////////////////////////////////////////////////////////////////////////// // IUnkown implementation. - virtual HRESULT STDMETHODCALLTYPE QueryInterface(const IID& riid, void** ppvObj); - virtual ULONG STDMETHODCALLTYPE AddRef(); - virtual ULONG STDMETHODCALLTYPE Release(); + HRESULT STDMETHODCALLTYPE QueryInterface(const IID& riid, void** ppvObj) override; + ULONG STDMETHODCALLTYPE AddRef() override; + ULONG STDMETHODCALLTYPE Release() override; ////////////////////////////////////////////////////////////////////////// - virtual REFGUID ClassID(); + REFGUID ClassID() override; ////////////////////////////////////////////////////////////////////////// - virtual int GetPagesCount(); - virtual IPreferencesPage* CreateEditorPreferencesPage(int index) override; + int GetPagesCount() override; + IPreferencesPage* CreateEditorPreferencesPage(int index) override; }; #endif // CRYINCLUDE_EDITOR_PREFERENCESSTDPAGES_H diff --git a/Code/Editor/QtViewPane.h b/Code/Editor/QtViewPane.h index 09fc215833..194dd8919a 100644 --- a/Code/Editor/QtViewPane.h +++ b/Code/Editor/QtViewPane.h @@ -123,18 +123,18 @@ public: { } - virtual ESystemClassID SystemClassID() { return m_classId; }; + ESystemClassID SystemClassID() override { return m_classId; }; static const GUID& GetClassID() { return TWidget::GetClassID(); } - virtual const GUID& ClassID() + const GUID& ClassID() override { return GetClassID(); } - virtual QString ClassName() { return m_name; }; - virtual QString Category() { return m_category; }; + QString ClassName() override { return m_name; }; + QString Category() override { return m_category; }; QObject* CreateQObject() const override { return new TWidget(); }; QString GetPaneTitle() override { return m_name; }; diff --git a/Code/Editor/SelectSequenceDialog.h b/Code/Editor/SelectSequenceDialog.h index 5531949c1a..960da7ebe3 100644 --- a/Code/Editor/SelectSequenceDialog.h +++ b/Code/Editor/SelectSequenceDialog.h @@ -30,7 +30,7 @@ protected: void OnInitDialog() override; // Derived Dialogs should override this - virtual void GetItems(std::vector& outItems); + void GetItems(std::vector& outItems) override; }; #endif // CRYINCLUDE_EDITOR_SELECTSEQUENCEDIALOG_H diff --git a/Code/Editor/ToolbarCustomizationDialog.h b/Code/Editor/ToolbarCustomizationDialog.h index 7063c2b792..0e64bfbb5b 100644 --- a/Code/Editor/ToolbarCustomizationDialog.h +++ b/Code/Editor/ToolbarCustomizationDialog.h @@ -39,7 +39,7 @@ public: protected: void dragMoveEvent(QDragMoveEvent* ev) override; void dragEnterEvent(QDragEnterEvent* ev) override; - void dropEvent(QDropEvent* ev); + void dropEvent(QDropEvent* ev) override; private: void OnTabChanged(int index); diff --git a/Code/Editor/TopRendererWnd.h b/Code/Editor/TopRendererWnd.h index 3a5c1026bc..c5bc7a31f2 100644 --- a/Code/Editor/TopRendererWnd.h +++ b/Code/Editor/TopRendererWnd.h @@ -35,11 +35,11 @@ public: /** Get type of this viewport. */ - virtual EViewportType GetType() const { return ET_ViewportMap; } - virtual void SetType(EViewportType type); + EViewportType GetType() const override { return ET_ViewportMap; } + void SetType(EViewportType type) override; - virtual void ResetContent(); - virtual void UpdateContent(int flags); + void ResetContent() override; + void UpdateContent(int flags) override; //! Map viewport position to world space position. virtual Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; @@ -52,7 +52,7 @@ public: protected: // Draw everything. - virtual void Draw(DisplayContext& dc); + void Draw(DisplayContext& dc) override; private: bool m_bContentsUpdated; diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.h b/Code/Editor/TrackView/SequenceBatchRenderDialog.h index 5d8934f783..9be10c22af 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.h +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.h @@ -187,7 +187,7 @@ protected: int m_customFPS; void InitializeContext(); - virtual void OnMovieEvent(IMovieListener::EMovieEvent event, IAnimSequence* pSequence); + void OnMovieEvent(IMovieListener::EMovieEvent event, IAnimSequence* pSequence) override; void CaptureItemStart(); diff --git a/Code/Editor/TrackView/TrackViewCurveEditor.h b/Code/Editor/TrackView/TrackViewCurveEditor.h index b2e019899b..1af55a9e0c 100644 --- a/Code/Editor/TrackView/TrackViewCurveEditor.h +++ b/Code/Editor/TrackView/TrackViewCurveEditor.h @@ -50,8 +50,8 @@ public: void SetPlayCallback(const std::function& callback); // IAnimationContextListener - virtual void OnSequenceChanged(CTrackViewSequence* pNewSequence); - virtual void OnTimeChanged(float newTime); + void OnSequenceChanged(CTrackViewSequence* pNewSequence) override; + void OnTimeChanged(float newTime) override; protected: void showEvent(QShowEvent* event) override; @@ -65,7 +65,7 @@ private: void OnSplineTimeMarkerChange(); // IEditorNotifyListener - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override; + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; //ITrackViewSequenceListener void OnKeysChanged(CTrackViewSequence* pSequence) override; @@ -109,8 +109,8 @@ public: float GetFPS() const { return m_widget->GetFPS(); } void SetTickDisplayMode(ETVTickMode mode) { m_widget->SetTickDisplayMode(mode); } - virtual void OnSequenceChanged(CTrackViewSequence* pNewSequence) { m_widget->OnSequenceChanged(pNewSequence); } - virtual void OnTimeChanged(float newTime) { m_widget->OnTimeChanged(newTime); } + void OnSequenceChanged(CTrackViewSequence* pNewSequence) override { m_widget->OnSequenceChanged(pNewSequence); } + void OnTimeChanged(float newTime) override { m_widget->OnTimeChanged(newTime); } // ITrackViewSequenceListener delegation to m_widget void OnKeysChanged(CTrackViewSequence* pSequence) override { m_widget->OnKeysChanged(pSequence); } diff --git a/Code/Editor/TrackView/TrackViewDialog.h b/Code/Editor/TrackView/TrackViewDialog.h index f6c1126713..c66f31e1f7 100644 --- a/Code/Editor/TrackView/TrackViewDialog.h +++ b/Code/Editor/TrackView/TrackViewDialog.h @@ -69,10 +69,10 @@ public: void UpdateSequenceLockStatus(); // IAnimationContextListener - virtual void OnSequenceChanged(CTrackViewSequence* pNewSequence) override; + void OnSequenceChanged(CTrackViewSequence* pNewSequence) override; // ITrackViewSequenceListener - virtual void OnSequenceSettingsChanged(CTrackViewSequence* pSequence) override; + void OnSequenceSettingsChanged(CTrackViewSequence* pSequence) override; void UpdateDopeSheetTime(CTrackViewSequence* pSequence); @@ -197,8 +197,8 @@ private: bool processRawInput(MSG* pMsg); #endif - virtual void OnNodeSelectionChanged(CTrackViewSequence* pSequence) override; - virtual void OnNodeRenamed(CTrackViewNode* pNode, const char* pOldName) override; + void OnNodeSelectionChanged(CTrackViewSequence* pSequence) override; + void OnNodeRenamed(CTrackViewNode* pNode, const char* pOldName) override; void OnSequenceAdded(CTrackViewSequence* pSequence) override; void OnSequenceRemoved(CTrackViewSequence* pSequence) override; @@ -209,8 +209,8 @@ private: void AddDialogListeners(); void RemoveDialogListeners(); - virtual void BeginUndoTransaction(); - virtual void EndUndoTransaction(); + void BeginUndoTransaction() override; + void EndUndoTransaction() override; void SaveCurrentSequenceToFBX(); void SaveSequenceTimingToXML(); diff --git a/Code/Editor/TrackView/TrackViewSequence.h b/Code/Editor/TrackView/TrackViewSequence.h index 69858adf8f..a392ad00f9 100644 --- a/Code/Editor/TrackView/TrackViewSequence.h +++ b/Code/Editor/TrackView/TrackViewSequence.h @@ -100,16 +100,16 @@ public: void Load() override; // ITrackViewNode - virtual ETrackViewNodeType GetNodeType() const override { return eTVNT_Sequence; } + ETrackViewNodeType GetNodeType() const override { return eTVNT_Sequence; } - virtual AZStd::string GetName() const override { return m_pAnimSequence->GetName(); } - virtual bool SetName(const char* pName) override; - virtual bool CanBeRenamed() const override { return true; } + AZStd::string GetName() const override { return m_pAnimSequence->GetName(); } + bool SetName(const char* pName) override; + bool CanBeRenamed() const override { return true; } // Binding/Unbinding - virtual void BindToEditorObjects() override; - virtual void UnBindFromEditorObjects() override; - virtual bool IsBoundToEditorObjects() const override; + void BindToEditorObjects() override; + void UnBindFromEditorObjects() override; + bool IsBoundToEditorObjects() const override; // Time range void SetTimeRange(Range timeRange); @@ -136,10 +136,10 @@ public: uint32 GetCryMovieId() const { return m_pAnimSequence->GetId(); } // Rendering - virtual void Render(const SAnimContext& animContext) override; + void Render(const SAnimContext& animContext) override; // Playback control - virtual void Animate(const SAnimContext& animContext) override; + void Animate(const SAnimContext& animContext) override; void Resume() { m_pAnimSequence->Resume(); } void Pause() { m_pAnimSequence->Pause(); } void StillUpdate() { m_pAnimSequence->StillUpdate(); } @@ -162,7 +162,7 @@ public: void TimeChanged(float newTime) { m_pAnimSequence->TimeChanged(newTime); } // Check if it's a group node - virtual bool IsGroupNode() const override { return true; } + bool IsGroupNode() const override { return true; } // Track Events (TODO: Undo?) int GetTrackEventsCount() const { return m_pAnimSequence->GetTrackEventsCount(); } @@ -195,7 +195,7 @@ public: bool IsActiveSequence() const; // The root sequence node is always an active director - virtual bool IsActiveDirector() const override { return true; } + bool IsActiveDirector() const override { return true; } // Copy keys to clipboard (in XML form) void CopyKeysToClipboard(const bool bOnlySelectedKeys, const bool bOnlyFromSelectedTracks); @@ -306,15 +306,15 @@ private: // Called when an animation updates needs to be schedules void ForceAnimation(); - virtual void CopyKeysToClipboard(XmlNodeRef& xmlNode, const bool bOnlySelectedKeys, const bool bOnlyFromSelectedTracks) override; + void CopyKeysToClipboard(XmlNodeRef& xmlNode, const bool bOnlySelectedKeys, const bool bOnlyFromSelectedTracks) override; std::deque GetMatchingTracks(CTrackViewAnimNode* pAnimNode, XmlNodeRef trackNode); void GetMatchedPasteLocationsRec(std::vector& locations, CTrackViewNode* pCurrentNode, XmlNodeRef clipboardNode); - virtual void BeginUndoTransaction(); - virtual void EndUndoTransaction(); - virtual void BeginRestoreTransaction(); - virtual void EndRestoreTransaction(); + void BeginUndoTransaction() override; + void EndUndoTransaction() override; + void BeginRestoreTransaction() override; + void EndRestoreTransaction() override; // For record mode on AZ::Entities - connect (or disconnect) to buses for notification of property changes void ConnectToBusesForRecording(const AZ::EntityId& entityIdForBus, bool enableConnection); diff --git a/Code/Editor/TrackView/TrackViewSequenceManager.h b/Code/Editor/TrackView/TrackViewSequenceManager.h index 21c10f009a..1474323dc6 100644 --- a/Code/Editor/TrackView/TrackViewSequenceManager.h +++ b/Code/Editor/TrackView/TrackViewSequenceManager.h @@ -27,7 +27,7 @@ public: CTrackViewSequenceManager(); ~CTrackViewSequenceManager(); - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; unsigned int GetCount() const { return static_cast(m_sequences.size()); } @@ -65,7 +65,7 @@ private: void OnSequenceAdded(CTrackViewSequence* pSequence); void OnSequenceRemoved(CTrackViewSequence* pSequence); - virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event); + void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) override; // AZ::EntitySystemBus void OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) override; diff --git a/Code/Editor/TrackView/TrackViewSplineCtrl.h b/Code/Editor/TrackView/TrackViewSplineCtrl.h index 2f4c790627..7c5a13cdb6 100644 --- a/Code/Editor/TrackView/TrackViewSplineCtrl.h +++ b/Code/Editor/TrackView/TrackViewSplineCtrl.h @@ -28,7 +28,7 @@ public: CTrackViewSplineCtrl(QWidget* parent); virtual ~CTrackViewSplineCtrl(); - virtual void ClearSelection(); + void ClearSelection() override; void AddSpline(ISplineInterpolator* pSpline, CTrackViewTrack* pTrack, const QColor& color); void AddSpline(ISplineInterpolator * pSpline, CTrackViewTrack * pTrack, QColor anColorArray[4]); @@ -53,12 +53,12 @@ protected: void wheelEvent(QWheelEvent* event) override; private: - virtual void SelectKey(ISplineInterpolator* pSpline, int nKey, int nDimension, bool bSelect) override; - virtual void SelectRectangle(const QRect& rc, bool bSelect) override; + void SelectKey(ISplineInterpolator* pSpline, int nKey, int nDimension, bool bSelect) override; + void SelectRectangle(const QRect& rc, bool bSelect) override; std::vector m_tracks; - virtual bool GetTangentHandlePts(QPoint& inTangentPt, QPoint& pt, QPoint& outTangentPt, + bool GetTangentHandlePts(QPoint& inTangentPt, QPoint& pt, QPoint& outTangentPt, int nSpline, int nKey, int nDimension) override; void ComputeIncomingTangentAndEaseTo(float& ds, float& easeTo, QPoint inTangentPt, int nSpline, int nKey, int nDimension); @@ -67,7 +67,7 @@ private: void AdjustTCB(float d_tension, float d_continuity, float d_bias); void MoveSelectedTangentHandleTo(const QPoint& point); - virtual ISplineCtrlUndo* CreateSplineCtrlUndoObject(std::vector& splineContainer); + virtual ISplineCtrlUndo* CreateSplineCtrlUndoObject(std::vector& splineContainer) override; bool m_bKeysFreeze; bool m_bTangentsFreeze; diff --git a/Code/Editor/Util/ColumnGroupTreeView.h b/Code/Editor/Util/ColumnGroupTreeView.h index 3c7dea91c3..eda5f8e9c9 100644 --- a/Code/Editor/Util/ColumnGroupTreeView.h +++ b/Code/Editor/Util/ColumnGroupTreeView.h @@ -44,7 +44,7 @@ public slots: QVector Groups() const; protected: - void paintEvent(QPaintEvent* event) + void paintEvent(QPaintEvent* event) override { if (model() && model()->rowCount() > 0) { diff --git a/Code/Editor/Util/Variable.h b/Code/Editor/Util/Variable.h index 0965756488..639161775c 100644 --- a/Code/Editor/Util/Variable.h +++ b/Code/Editor/Util/Variable.h @@ -399,7 +399,7 @@ public: //! Get name of parameter. QString GetDescription() const override { return m_description; }; - EType GetType() const { return IVariable::UNKNOWN; }; + EType GetType() const override { return IVariable::UNKNOWN; }; int GetSize() const override { return sizeof(*this); }; unsigned char GetDataType() const override { return m_dataType; }; @@ -409,8 +409,8 @@ public: int GetFlags() const override { return m_flags; } void SetFlagRecursive(EFlags flag) override { m_flags |= flag; } - void SetUserData(const QVariant &data){ m_userData = data; }; - QVariant GetUserData() const { return m_userData; } + void SetUserData(const QVariant &data) override { m_userData = data; }; + QVariant GetUserData() const override { return m_userData; } ////////////////////////////////////////////////////////////////////////// // Set methods. @@ -1114,44 +1114,44 @@ public: } //! Get name of parameter. - virtual EType GetType() const { return (EType)var_type::type_traits::type(); }; - virtual int GetSize() const { return sizeof(T); }; + EType GetType() const override { return (EType)var_type::type_traits::type(); }; + int GetSize() const override { return sizeof(T); }; ////////////////////////////////////////////////////////////////////////// // Set methods. ////////////////////////////////////////////////////////////////////////// - virtual void Set(int value) { SetValue(value); } - virtual void Set(bool value) { SetValue(value); } - virtual void Set(float value) { SetValue(value); } - virtual void Set(double value) { SetValue(value); } - virtual void Set(const Vec2& value) { SetValue(value); } - virtual void Set(const Vec3& value) { SetValue(value); } - virtual void Set(const Vec4& value) { SetValue(value); } - virtual void Set(const Ang3& value) { SetValue(value); } - virtual void Set(const Quat& value) { SetValue(value); } - virtual void Set(const QString& value) { SetValue(value); } - virtual void Set(const char* value) { SetValue(QString(value)); } + void Set(int value) override { SetValue(value); } + void Set(bool value) override { SetValue(value); } + void Set(float value) override { SetValue(value); } + void Set(double value) override { SetValue(value); } + void Set(const Vec2& value) override { SetValue(value); } + void Set(const Vec3& value) override { SetValue(value); } + void Set(const Vec4& value) override { SetValue(value); } + void Set(const Ang3& value) override { SetValue(value); } + void Set(const Quat& value) override { SetValue(value); } + void Set(const QString& value) override { SetValue(value); } + void Set(const char* value) override { SetValue(QString(value)); } ////////////////////////////////////////////////////////////////////////// // Get methods. ////////////////////////////////////////////////////////////////////////// - virtual void Get(int& value) const { GetValue(value); } - virtual void Get(bool& value) const { GetValue(value); } - virtual void Get(float& value) const { GetValue(value); } - virtual void Get(double& value) const { GetValue(value); } - virtual void Get(Vec2& value) const { GetValue(value); } - virtual void Get(Vec3& value) const { GetValue(value); } - virtual void Get(Vec4& value) const { GetValue(value); } - virtual void Get(Quat& value) const { GetValue(value); } - virtual void Get(QString& value) const { GetValue(value); } - virtual bool HasDefaultValue() const + void Get(int& value) const override { GetValue(value); } + void Get(bool& value) const override { GetValue(value); } + void Get(float& value) const override { GetValue(value); } + void Get(double& value) const override { GetValue(value); } + void Get(Vec2& value) const override { GetValue(value); } + void Get(Vec3& value) const override { GetValue(value); } + void Get(Vec4& value) const override { GetValue(value); } + void Get(Quat& value) const override { GetValue(value); } + void Get(QString& value) const override { GetValue(value); } + bool HasDefaultValue() const override { T defval; var_type::init(defval); return m_valueDef == defval; } - virtual void ResetToDefault() + void ResetToDefault() override { T defval; var_type::init(defval); @@ -1161,7 +1161,7 @@ public: ////////////////////////////////////////////////////////////////////////// // Limits. ////////////////////////////////////////////////////////////////////////// - virtual void SetLimits(float fMin, float fMax, float fStep = 0.f, bool bHardMin = true, bool bHardMax = true) + void SetLimits(float fMin, float fMax, float fStep = 0.f, bool bHardMin = true, bool bHardMax = true) override { m_valueMin = fMin; m_valueMax = fMax; @@ -1173,7 +1173,7 @@ public: m_customLimits = true; } - virtual void GetLimits(float& fMin, float& fMax, float& fStep, bool& bHardMin, bool& bHardMax) + void GetLimits(float& fMin, float& fMax, float& fStep, bool& bHardMin, bool& bHardMax) override { if (!m_customLimits && var_type::type_traits::supports_range()) { @@ -1201,7 +1201,7 @@ public: m_customLimits = false; } - virtual bool HasCustomLimits() + bool HasCustomLimits() override { return m_customLimits; } @@ -1219,14 +1219,14 @@ public: void operator=(const T& value) { SetValue(value); } ////////////////////////////////////////////////////////////////////////// - IVariable* Clone([[maybe_unused]] bool bRecursive) const + IVariable* Clone([[maybe_unused]] bool bRecursive) const override { Self* var = new Self(*this); return var; } ////////////////////////////////////////////////////////////////////////// - void CopyValue(IVariable* fromVar) + void CopyValue(IVariable* fromVar) override { assert(fromVar); T val; @@ -1670,7 +1670,7 @@ struct CSmartVariableBase return *pV; } // Cast to CVariableBase& VarType& operator*() const { return *pVar; } - VarType* operator->(void) const { return pVar; } + VarType* operator->() const { return pVar; } VarType* GetVar() const { return pVar; }; @@ -1732,7 +1732,7 @@ struct CSmartVariableArray } VarType& operator*() const { return *pVar; } - VarType* operator->(void) const { return pVar; } + VarType* operator->() const { return pVar; } VarType* GetVar() const { return pVar; }; @@ -1754,35 +1754,35 @@ public: // Dtor. virtual ~CVarBlock() {} //! Add variable to block. - virtual void AddVariable(IVariable* var); + void AddVariable(IVariable* var) override; //! Remove variable from block - virtual bool DeleteVariable(IVariable* var, bool bRecursive = false); + bool DeleteVariable(IVariable* var, bool bRecursive = false) override; void AddVariable(IVariable* pVar, const char* varName, unsigned char dataType = IVariable::DT_SIMPLE); // This used from smart variable pointer. void AddVariable(CVariableBase& var, const char* varName, unsigned char dataType = IVariable::DT_SIMPLE); //! Returns number of variables in block. - virtual int GetNumVariables() const { return static_cast(m_vars.size()); } + int GetNumVariables() const override { return static_cast(m_vars.size()); } //! Get pointer to stored variable by index. - virtual IVariable* GetVariable(int index) const + IVariable* GetVariable(int index) const override { assert(index >= 0 && index < m_vars.size()); return m_vars[index]; } // Clear all vars from VarBlock. - virtual void DeleteAllVariables() { m_vars.clear(); }; + void DeleteAllVariables() override { m_vars.clear(); }; //! Return true if variable block is empty (Does not have any vars). - virtual bool IsEmpty() const { return m_vars.empty(); } + bool IsEmpty() const override { return m_vars.empty(); } // Returns true if var block contains specified variable. - virtual bool IsContainsVariable(IVariable* pVar, bool bRecursive = true) const; + bool IsContainsVariable(IVariable* pVar, bool bRecursive = true) const override; //! Find variable by name. - virtual IVariable* FindVariable(const char* name, bool bRecursive = true, bool bHumanName = false) const; + IVariable* FindVariable(const char* name, bool bRecursive = true, bool bHumanName = false) const override; ////////////////////////////////////////////////////////////////////////// //! Clone var block. diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index e54eca6083..e1cd822404 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -172,7 +172,7 @@ public: //! Get current view matrix. //! This is a matrix that transforms from world space to view space. - virtual const Matrix34& GetViewTM() const + const Matrix34& GetViewTM() const override { AZ_Error("CryLegacy", false, "QtViewport::GetViewTM not implemented"); static const Matrix34 m; @@ -182,7 +182,7 @@ public: ////////////////////////////////////////////////////////////////////////// //! Get current screen matrix. //! Screen matrix transform from World space to Screen space. - virtual const Matrix34& GetScreenTM() const + const Matrix34& GetScreenTM() const override { return m_screenTM; } @@ -190,9 +190,9 @@ public: virtual Vec3 MapViewToCP(const QPoint& point) = 0; //! Map viewport position to world space position. - virtual Vec3 ViewToWorld(const QPoint& vp, bool* pCollideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const = 0; + Vec3 ViewToWorld(const QPoint& vp, bool* pCollideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override = 0; //! Convert point on screen to world ray. - virtual void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const = 0; + void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override = 0; //! Get normal for viewport position virtual Vec3 ViewToWorldNormal(const QPoint& vp, bool onlyTerrain, bool bTestRenderMesh = false) = 0; @@ -261,7 +261,7 @@ public: virtual void SetCursorString(const QString& str) = 0; virtual void SetFocus() = 0; - virtual void Invalidate(bool bErase = 1) = 0; + virtual void Invalidate(bool bErase = true) = 0; // Is overridden by RenderViewport virtual void SetFOV([[maybe_unused]] float fov) {} @@ -280,7 +280,7 @@ public: virtual void PreWidgetRendering() {} virtual void PostWidgetRendering() {} - virtual CViewport *asCViewport() { return this; } + CViewport *asCViewport() override { return this; } protected: CLayoutViewPane* m_viewPane = nullptr; @@ -342,7 +342,7 @@ public: void SetActiveWindow() override { activateWindow(); } //! Called while window is idle. - virtual void Update(); + void Update() override; /** Set name of this viewport. */ @@ -350,24 +350,24 @@ public: /** Get name of viewport */ - QString GetName() const; + QString GetName() const override; - virtual void SetFocus() { setFocus(); } - virtual void Invalidate([[maybe_unused]] bool bErase = 1) { update(); } + void SetFocus() override { setFocus(); } + void Invalidate([[maybe_unused]] bool bErase = 1) override { update(); } // Is overridden by RenderViewport - virtual void SetFOV([[maybe_unused]] float fov) {} - virtual float GetFOV() const; + void SetFOV([[maybe_unused]] float fov) override {} + float GetFOV() const override; // Must be overridden in derived classes. // Returns: // e.g. 4.0/3.0 - virtual float GetAspectRatio() const = 0; - virtual void GetDimensions(int* pWidth, int* pHeight) const; - virtual void ScreenToClient(QPoint& pPoint) const override; + float GetAspectRatio() const override = 0; + void GetDimensions(int* pWidth, int* pHeight) const override; + void ScreenToClient(QPoint& pPoint) const override; - virtual void ResetContent(); - virtual void UpdateContent(int flags); + void ResetContent() override; + void UpdateContent(int flags) override; //! Set current zoom factor for this viewport. virtual void SetZoomFactor(float fZoomFactor); @@ -379,10 +379,10 @@ public: virtual void OnDeactivate(); //! Map world space position to viewport position. - virtual QPoint WorldToView(const Vec3& wp) const override; + QPoint WorldToView(const Vec3& wp) const override; //! Map world space position to 3D viewport position. - virtual Vec3 WorldToView3D(const Vec3& wp, int nFlags = 0) const; + Vec3 WorldToView3D(const Vec3& wp, int nFlags = 0) const override; //! Map viewport position to world space position. virtual Vec3 ViewToWorld(const QPoint& vp, bool* pCollideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; @@ -398,17 +398,17 @@ public: //! This method return a vector (p2-p1) in world space alligned to construction plane and restriction axises. //! p1 and p2 must be given in world space and lie on construction plane. using CViewport::GetCPVector; - virtual Vec3 GetCPVector(const Vec3& p1, const Vec3& p2, int axis); + Vec3 GetCPVector(const Vec3& p1, const Vec3& p2, int axis) override; //! Snap any given 3D world position to grid lines if snap is enabled. Vec3 SnapToGrid(const Vec3& vec) override; - virtual float GetGridStep() const; + float GetGridStep() const override; //! Returns the screen scale factor for a point given in world coordinates. //! This factor gives the width in world-space units at the point's distance of the viewport. - virtual float GetScreenScaleFactor([[maybe_unused]] const Vec3& worldPoint) const { return 1; }; + float GetScreenScaleFactor([[maybe_unused]] const Vec3& worldPoint) const override { return 1; }; - void SetAxisConstrain(int axis); + void SetAxisConstrain(int axis) override; /// Take raw input and create a final mouse interaction. /// @attention Do not map **point** from widget to viewport explicitly, @@ -420,7 +420,7 @@ public: // Selection. ////////////////////////////////////////////////////////////////////////// //! Resets current selection region. - virtual void ResetSelectionRegion(); + void ResetSelectionRegion() override; //! Set 2D selection rectangle. void SetSelectionRectangle(const QRect& rect) override; @@ -429,12 +429,12 @@ public: //! Called when dragging selection rectangle. void OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect = false) override; //! Get selection procision tolerance. - float GetSelectionTolerance() const { return m_selectionTolerance; } + float GetSelectionTolerance() const override { return m_selectionTolerance; } //! Center viewport on selection. void CenterOnSelection() override {} void CenterOnAABB([[maybe_unused]] const AABB& aabb) override {} - virtual void CenterOnSliceInstance() {} + void CenterOnSliceInstance() override {} //! Performs hit testing of 2d point in view to find which object hit. bool HitTest(const QPoint& point, HitContext& hitInfo) override; @@ -447,10 +447,10 @@ public: float GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const override; // Access to the member m_bAdvancedSelectMode so interested modules can know its value. - bool GetAdvancedSelectModeFlag(); + bool GetAdvancedSelectModeFlag() override; - virtual void GetPerpendicularAxis(EAxis* pAxis, bool* pIs2D) const; - virtual const ::Plane* GetConstructionPlane() const { return &m_constructionPlane; } + void GetPerpendicularAxis(EAxis* pAxis, bool* pIs2D) const override; + const ::Plane* GetConstructionPlane() const override { return &m_constructionPlane; } ////////////////////////////////////////////////////////////////////////// @@ -458,7 +458,7 @@ public: //! Set construction plane from given position construction matrix refrence coord system and axis settings. ////////////////////////////////////////////////////////////////////////// void MakeConstructionPlane(int axis) override; - virtual void SetConstructionMatrix(RefCoordSys coordSys, const Matrix34& xform); + void SetConstructionMatrix(RefCoordSys coordSys, const Matrix34& xform) override; virtual const Matrix34& GetConstructionMatrix(RefCoordSys coordSys); // Set simple construction plane origin. void SetConstructionOrigin(const Vec3& worldPos); @@ -468,11 +468,11 @@ public: ////////////////////////////////////////////////////////////////////////// // Undo for viewpot operations. - void BeginUndo(); - void AcceptUndo(const QString& undoDescription); - void CancelUndo(); - void RestoreUndo(); - bool IsUndoRecording() const; + void BeginUndo() override; + void AcceptUndo(const QString& undoDescription) override; + void CancelUndo() override; + void RestoreUndo() override; + bool IsUndoRecording() const override; ////////////////////////////////////////////////////////////////////////// //! Get prefered original size for this viewport. @@ -480,39 +480,39 @@ public: virtual QSize GetIdealSize() const; //! Check if world space bounding box is visible in this view. - virtual bool IsBoundsVisible(const AABB& box) const; + bool IsBoundsVisible(const AABB& box) const override; ////////////////////////////////////////////////////////////////////////// - void SetCursor(const QCursor& cursor) + void SetCursor(const QCursor& cursor) override { setCursor(cursor); } // Set`s current cursor string. void SetCurrentCursor(const QCursor& hCursor, const QString& cursorString); - virtual void SetCurrentCursor(EStdCursor stdCursor, const QString& cursorString); - void SetCurrentCursor(EStdCursor stdCursor); - virtual void SetCursorString(const QString& cursorString); - void ResetCursor(); - void SetSupplementaryCursorStr(const QString& str); + void SetCurrentCursor(EStdCursor stdCursor, const QString& cursorString) override; + void SetCurrentCursor(EStdCursor stdCursor) override; + void SetCursorString(const QString& cursorString) override; + void ResetCursor() override; + void SetSupplementaryCursorStr(const QString& str) override; ////////////////////////////////////////////////////////////////////////// // Return visble objects cache. - CBaseObjectsCache* GetVisibleObjectsCache() { return m_pVisibleObjectsCache; }; + CBaseObjectsCache* GetVisibleObjectsCache() override { return m_pVisibleObjectsCache; }; - void RegisterRenderListener(IRenderListener* piListener); - bool UnregisterRenderListener(IRenderListener* piListener); - bool IsRenderListenerRegistered(IRenderListener* piListener); + void RegisterRenderListener(IRenderListener* piListener) override; + bool UnregisterRenderListener(IRenderListener* piListener) override; + bool IsRenderListenerRegistered(IRenderListener* piListener) override; - void AddPostRenderer(IPostRenderer* pPostRenderer); - bool RemovePostRenderer(IPostRenderer* pPostRenderer); + void AddPostRenderer(IPostRenderer* pPostRenderer) override; + bool RemovePostRenderer(IPostRenderer* pPostRenderer) override; void CaptureMouse() override { m_mouseCaptured = true; QWidget::grabMouse(); } void ReleaseMouse() override { m_mouseCaptured = false; QWidget::releaseMouse(); } - virtual void setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir); - virtual void setHitcontext(QPoint& vp, Vec3& raySrc, Vec3& rayDir); + void setRay(QPoint& vp, Vec3& raySrc, Vec3& rayDir) override; + void setHitcontext(QPoint& vp, Vec3& raySrc, Vec3& rayDir) override; QPoint m_vp; AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING Vec3 m_raySrc; @@ -576,8 +576,8 @@ protected: //Child classes can override these to provide extra logic that wraps //widget rendering. Needed by the RenderViewport to handle raycasts //from screen-space to world-space. - virtual void PreWidgetRendering() {} - virtual void PostWidgetRendering() {} + void PreWidgetRendering() override {} + void PostWidgetRendering() override {} AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AzToolsFramework::ViewportUi::ViewportUiManager m_viewportUi; diff --git a/Code/Editor/ViewportTitleDlg.h b/Code/Editor/ViewportTitleDlg.h index 5acb04ca99..4a2a454907 100644 --- a/Code/Editor/ViewportTitleDlg.h +++ b/Code/Editor/ViewportTitleDlg.h @@ -77,7 +77,7 @@ Q_SIGNALS: protected: virtual void OnInitDialog(); - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override; void OnMaximize(); From 7484f3adff36c81ecdd86ea62063720280243b33 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:15:33 -0700 Subject: [PATCH 050/274] Code/Tools/SceneAPI Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestNameHandler.h | 2 +- .../SceneAPI/SceneUI/RowWidgets/NodeListSelectionHandler.h | 2 +- Code/Tools/SceneAPI/SceneUI/RowWidgets/TransformRowHandler.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestNameHandler.h b/Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestNameHandler.h index 8c73b5fe17..fbfd553caa 100644 --- a/Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestNameHandler.h +++ b/Code/Tools/SceneAPI/SceneUI/RowWidgets/ManifestNameHandler.h @@ -34,7 +34,7 @@ namespace AZ QWidget* CreateGUI(QWidget* parent) override; u32 GetHandlerName() const override; - bool AutoDelete() const; + bool AutoDelete() const override; void ConsumeAttribute(ManifestNameWidget* widget, u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; diff --git a/Code/Tools/SceneAPI/SceneUI/RowWidgets/NodeListSelectionHandler.h b/Code/Tools/SceneAPI/SceneUI/RowWidgets/NodeListSelectionHandler.h index 3b8f028be8..8717e23ac4 100644 --- a/Code/Tools/SceneAPI/SceneUI/RowWidgets/NodeListSelectionHandler.h +++ b/Code/Tools/SceneAPI/SceneUI/RowWidgets/NodeListSelectionHandler.h @@ -57,7 +57,7 @@ namespace AZ QWidget* CreateGUI(QWidget* parent) override; u32 GetHandlerName() const override; - bool AutoDelete() const; + bool AutoDelete() const override; void ConsumeAttribute(NodeListSelectionWidget* widget, u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; diff --git a/Code/Tools/SceneAPI/SceneUI/RowWidgets/TransformRowHandler.h b/Code/Tools/SceneAPI/SceneUI/RowWidgets/TransformRowHandler.h index 664fea9f85..0fd9aede88 100644 --- a/Code/Tools/SceneAPI/SceneUI/RowWidgets/TransformRowHandler.h +++ b/Code/Tools/SceneAPI/SceneUI/RowWidgets/TransformRowHandler.h @@ -33,7 +33,7 @@ namespace AZ QWidget* CreateGUI(QWidget* parent) override; u32 GetHandlerName() const override; - bool AutoDelete() const; + bool AutoDelete() const override; bool IsDefaultHandler() const override; From 7755c39d09063872fb6867f4d3910bfb82952770 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:15:55 -0700 Subject: [PATCH 051/274] Code/Tools/Standalone Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Standalone/Source/LUA/LUAEditorContext.h | 130 +++++++++--------- .../Source/LUA/LUAEditorMainWindow.hxx | 36 ++--- .../Standalone/Source/LUA/LUAEditorView.hxx | 10 +- .../Source/StandaloneToolsApplication.h | 2 +- .../Source/Telemetry/TelemetryComponent.h | 4 +- 5 files changed, 91 insertions(+), 91 deletions(-) diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorContext.h b/Code/Tools/Standalone/Source/LUA/LUAEditorContext.h index fc0e78089d..f844eaf395 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorContext.h +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorContext.h @@ -84,22 +84,22 @@ namespace LUAEditor ////////////////////////////////////////////////////////////////////////// // AZ::Component - virtual void Init(); - virtual void Activate(); - virtual void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; ////////////////////////////////////////////////////////////////////////// static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); ////////////////////////////////////////////////////////////////////////// // EditorFramework::CoreMessageBus::Handler - virtual void RunAsAnotherInstance(); + void RunAsAnotherInstance() override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // AzToolsFramework::AssetSystemInfoBus::Handler - virtual void AssetCompilationSuccess(const AZStd::string& assetPath) override; - virtual void AssetCompilationFailed(const AZStd::string& assetPath) override; + void AssetCompilationSuccess(const AZStd::string& assetPath) override; + void AssetCompilationFailed(const AZStd::string& assetPath) override; ////////////////////////////////////////////////////////////////////////// @@ -111,110 +111,110 @@ namespace LUAEditor ////////////////////////////////////////////////////////////////////////// // ContextInterface Messages // it is an error to call GetDocumentData when the data is not yet ready. - virtual void ShowLUAEditorView(); + void ShowLUAEditorView() override; // this occurs from time to time, generally triggered when some external event occurs // that makes it suspect that its document statuses might be invalid: ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// //Context_DocumentManagement Messages - virtual void OnNewDocument(const AZStd::string& assetId); - virtual void OnLoadDocument(const AZStd::string& assetId, bool errorOnNotFound); - virtual void OnCloseDocument(const AZStd::string& assetId); - virtual void OnSaveDocument(const AZStd::string& assetId, bool bCloseAfterSaved, bool bSaveAs); - virtual bool OnSaveDocumentAs(const AZStd::string& assetId, bool bCloseAfterSaved); - virtual void NotifyDocumentModified(const AZStd::string& assetId, bool modified); - virtual void DocumentCheckOutRequested(const AZStd::string& assetId); - virtual void RefreshAllDocumentPerforceStat(); - virtual void OnReloadDocument(const AZStd::string assetId); - - virtual void UpdateDocumentData(const AZStd::string& assetId, const char* dataPtr, const AZStd::size_t dataLength); - virtual void GetDocumentData(const AZStd::string& assetId, const char** dataPtr, AZStd::size_t& dataLength); + void OnNewDocument(const AZStd::string& assetId) override; + void OnLoadDocument(const AZStd::string& assetId, bool errorOnNotFound) override; + void OnCloseDocument(const AZStd::string& assetId) override; + void OnSaveDocument(const AZStd::string& assetId, bool bCloseAfterSaved, bool bSaveAs) override; + bool OnSaveDocumentAs(const AZStd::string& assetId, bool bCloseAfterSaved) override; + void NotifyDocumentModified(const AZStd::string& assetId, bool modified) override; + void DocumentCheckOutRequested(const AZStd::string& assetId) override; + void RefreshAllDocumentPerforceStat() override; + void OnReloadDocument(const AZStd::string assetId) override; + + void UpdateDocumentData(const AZStd::string& assetId, const char* dataPtr, const AZStd::size_t dataLength) override; + void GetDocumentData(const AZStd::string& assetId, const char** dataPtr, AZStd::size_t& dataLength) override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Target Manager ////////////////////////////////////////////////////////////////////////// - virtual void DesiredTargetConnected(bool connected); - virtual void DesiredTargetChanged(AZ::u32 newTargetID, AZ::u32 oldTargetID); + void DesiredTargetConnected(bool connected) override; + void DesiredTargetChanged(AZ::u32 newTargetID, AZ::u32 oldTargetID) override; ////////////////////////////////////////////////////////////////////////// //Context_DebuggerManagement Messages ////////////////////////////////////////////////////////////////////////// - void ExecuteScriptBlob(const AZStd::string& fromAssetId, bool executeLocal); - virtual void SynchronizeBreakpoints(); - virtual void CreateBreakpoint(const AZStd::string& fromAssetId, int lineNumber); - virtual void MoveBreakpoint(const AZ::Uuid& breakpointUID, int lineNumber); - virtual void DeleteBreakpoint(const AZ::Uuid& breakpointUID); - virtual void CleanUpBreakpoints(); + void ExecuteScriptBlob(const AZStd::string& fromAssetId, bool executeLocal) override; + void SynchronizeBreakpoints() override; + void CreateBreakpoint(const AZStd::string& fromAssetId, int lineNumber) override; + void MoveBreakpoint(const AZ::Uuid& breakpointUID, int lineNumber) override; + void DeleteBreakpoint(const AZ::Uuid& breakpointUID) override; + void CleanUpBreakpoints() override; // These come from the VM - virtual void OnDebuggerAttached(); - virtual void OnDebuggerRefused(); - virtual void OnDebuggerDetached(); - virtual void OnBreakpointHit(const AZStd::string& assetIdString, int lineNumber); - virtual void OnBreakpointAdded(const AZStd::string& assetIdString, int lineNumber); - virtual void OnBreakpointRemoved(const AZStd::string& assetIdString, int lineNumber); - virtual void OnReceivedAvailableContexts(const AZStd::vector& contexts); - virtual void OnReceivedRegisteredClasses(const AzFramework::ScriptUserClassList& classes); - virtual void OnReceivedRegisteredEBuses(const AzFramework::ScriptUserEBusList& ebuses); - virtual void OnReceivedRegisteredGlobals(const AzFramework::ScriptUserMethodList& methods, const AzFramework::ScriptUserPropertyList& properties); - virtual void OnReceivedLocalVariables(const AZStd::vector& vars); - virtual void OnReceivedCallstack(const AZStd::vector& callstack); - virtual void OnReceivedValueState(const AZ::ScriptContextDebug::DebugValue& value); - virtual void OnSetValueResult(const AZStd::string& name, bool success); - virtual void OnExecutionResumed(); - virtual void OnExecuteScriptResult(bool success); + void OnDebuggerAttached() override; + void OnDebuggerRefused() override; + void OnDebuggerDetached() override; + void OnBreakpointHit(const AZStd::string& assetIdString, int lineNumber) override; + void OnBreakpointAdded(const AZStd::string& assetIdString, int lineNumber) override; + void OnBreakpointRemoved(const AZStd::string& assetIdString, int lineNumber) override; + void OnReceivedAvailableContexts(const AZStd::vector& contexts) override; + void OnReceivedRegisteredClasses(const AzFramework::ScriptUserClassList& classes) override; + void OnReceivedRegisteredEBuses(const AzFramework::ScriptUserEBusList& ebuses) override; + void OnReceivedRegisteredGlobals(const AzFramework::ScriptUserMethodList& methods, const AzFramework::ScriptUserPropertyList& properties) override; + void OnReceivedLocalVariables(const AZStd::vector& vars) override; + void OnReceivedCallstack(const AZStd::vector& callstack) override; + void OnReceivedValueState(const AZ::ScriptContextDebug::DebugValue& value) override; + void OnSetValueResult(const AZStd::string& name, bool success) override; + void OnExecutionResumed() override; + void OnExecuteScriptResult(bool success) override; ////////////////////////////////////////////////////////////////////////// //BreakpointTracker Messages ////////////////////////////////////////////////////////////////////////// - virtual const BreakpointMap* RequestBreakpoints(); - virtual void RequestEditorFocus(const AZStd::string& assetIdString, int lineNumber); - virtual void RequestDeleteBreakpoint(const AZStd::string& assetIdString, int lineNumber); + const BreakpointMap* RequestBreakpoints() override; + void RequestEditorFocus(const AZStd::string& assetIdString, int lineNumber) override; + void RequestDeleteBreakpoint(const AZStd::string& assetIdString, int lineNumber) override; ////////////////////////////////////////////////////////////////////////// //StackTracker Messages ////////////////////////////////////////////////////////////////////////// - virtual void RequestStackClicked(const AZStd::string& stackString, int lineNumber); + void RequestStackClicked(const AZStd::string& stackString, int lineNumber) override; ////////////////////////////////////////////////////////////////////////// //TargetContextTracker Messages ////////////////////////////////////////////////////////////////////////// - virtual const AZStd::vector RequestTargetContexts(); - virtual const AZStd::string RequestCurrentTargetContext(); - virtual void SetCurrentTargetContext(AZStd::string& contextName); + virtual const AZStd::vector RequestTargetContexts() override; + const AZStd::string RequestCurrentTargetContext() override; + void SetCurrentTargetContext(AZStd::string& contextName) override; ////////////////////////////////////////////////////////////////////////// //Watch window messages ////////////////////////////////////////////////////////////////////////// - virtual void RequestWatchedVariable(const AZStd::string& varName); + void RequestWatchedVariable(const AZStd::string& varName) override; ////////////////////////////////////////////////////////////////////////// //Debug Request messages ////////////////////////////////////////////////////////////////////////// - virtual void RequestDetachDebugger(); - virtual void RequestAttachDebugger(); + void RequestDetachDebugger() override; + void RequestAttachDebugger() override; ////////////////////////////////////////////////////////////////////////// // AzToolsFramework CoreMessages - virtual void OnRestoreState(); // sent when everything is registered up and ready to go, this is what bootstraps stuff to get going. - virtual bool OnGetPermissionToShutDown(); - virtual bool CheckOkayToShutDown(); - virtual void OnSaveState(); // sent to everything when the app is about to shut down - do what you need to do. - virtual void OnDestroyState(); - virtual void ApplicationDeactivated(); - virtual void ApplicationActivated(); - virtual void ApplicationShow(AZ::Uuid id); - virtual void ApplicationHide(AZ::Uuid id); - virtual void ApplicationCensus(); + void OnRestoreState() override; // sent when everything is registered up and ready to go, this is what bootstraps stuff to get going. + bool OnGetPermissionToShutDown() override; + bool CheckOkayToShutDown() override; + void OnSaveState() override; // sent to everything when the app is about to shut down - do what you need to do. + void OnDestroyState() override; + void ApplicationDeactivated() override; + void ApplicationActivated() override; + void ApplicationShow(AZ::Uuid id) override; + void ApplicationHide(AZ::Uuid id) override; + void ApplicationCensus() override; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // HighlightedWords - virtual const HighlightedWords::LUAKeywordsType* GetLUAKeywords() { return &m_LUAKeywords; } - virtual const HighlightedWords::LUAKeywordsType* GetLUALibraryFunctions() { return &m_LUALibraryFunctions; } + const HighlightedWords::LUAKeywordsType* GetLUAKeywords() override { return &m_LUAKeywords; } + const HighlightedWords::LUAKeywordsType* GetLUALibraryFunctions() override { return &m_LUALibraryFunctions; } // internal data structure for the LUA debugger class/member/property reference panel // this is what we serialize and work with diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.hxx b/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.hxx index c01893909b..1b23504fed 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.hxx +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.hxx @@ -86,14 +86,14 @@ namespace LUAEditor public: AZ_CLASS_ALLOCATOR(LUAEditorMainWindow,AZ::SystemAllocator,0); LUAEditorMainWindow(QStandardItemModel* dataModel, bool connectedState, QWidget* parent = NULL, Qt::WindowFlags flags = Qt::WindowFlags()); - virtual ~LUAEditorMainWindow(void); + virtual ~LUAEditorMainWindow(); bool OnGetPermissionToShutDown(); ////////////////////////////////////////////////////////////////////////// // Qt Events private: - virtual void closeEvent(QCloseEvent* event); + void closeEvent(QCloseEvent* event) override; Ui::LUAEditorMainWindow* m_gui; AzToolsFramework::TargetSelectorButtonAction* m_pTargetButton; @@ -204,7 +204,7 @@ namespace LUAEditor AZStd::string m_lastOpenFilePath; AZStd::vector m_dProcessFindListClicked; - void OnDataLoadedAndSet(const DocumentInfo& info, LUAViewWidget* pLUAViewWidget); + void OnDataLoadedAndSet(const DocumentInfo& info, LUAViewWidget* pLUAViewWidget) override; AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_filterModel; QSharedPointer CreateFilter(); @@ -243,18 +243,18 @@ namespace LUAEditor // LUAEditorMainWindow Messages. public: virtual void OnCloseView(const AZStd::string& assetId); - virtual void OnFocusInEvent(const AZStd::string& assetId); - virtual void OnFocusOutEvent(const AZStd::string& assetId); - virtual void OnRequestCheckOut(const AZStd::string& assetId); - virtual void OnConnectedToTarget(); - virtual void OnDisconnectedFromTarget(); - virtual void OnConnectedToDebugger(); - virtual void OnDisconnectedFromDebugger(); + void OnFocusInEvent(const AZStd::string& assetId) override; + void OnFocusOutEvent(const AZStd::string& assetId) override; + void OnRequestCheckOut(const AZStd::string& assetId) override; + void OnConnectedToTarget() override; + void OnDisconnectedFromTarget() override; + void OnConnectedToDebugger() override; + void OnDisconnectedFromDebugger() override; void Repaint() override; ////////////////////////////////////////////////////////////////////////// - virtual void dragEnterEvent(QDragEnterEvent *pEvent); - virtual void dropEvent(QDropEvent *pEvent); + void dragEnterEvent(QDragEnterEvent *pEvent) override; + void dropEvent(QDropEvent *pEvent) override; void IgnoreFocusEvents(bool ignore) { m_bIgnoreFocusRequests = ignore; } @@ -327,7 +327,7 @@ namespace LUAEditor // support for windows-ish Ctrl+Tab cycling through documents via the above Tab actions typedef AZStd::list TrackedLUACtrlTabOrder; TrackedLUACtrlTabOrder m_CtrlTabOrder; - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject *obj, QEvent *event) override; AZStd::string m_StoredTabAssetId; bool m_bIgnoreFocusRequests; @@ -338,10 +338,10 @@ namespace LUAEditor ////////////////////////////////////////////////////////////////////////// //Debugger Messages, from the LUAEditor::LUABreakpointTrackerMessages::Bus - virtual void BreakpointsUpdate(const LUAEditor::BreakpointMap& uniqueBreakpoints); - virtual void BreakpointHit(const LUAEditor::Breakpoint& breakpoint); - virtual void BreakpointResume(); - virtual void OnExecuteScriptResult(bool success); + void BreakpointsUpdate(const LUAEditor::BreakpointMap& uniqueBreakpoints) override; + void BreakpointHit(const LUAEditor::Breakpoint& breakpoint) override; + void BreakpointResume() override; + void OnExecuteScriptResult(bool success) override; ////////////////////////////////////////////////////////////////////////// // track activity and synchronize the appropriate widgets' states to match @@ -433,7 +433,7 @@ namespace LUAEditor bool m_bAutoReloadUnmodifiedFiles = false; LUAEditorMainWindowSavedState() {} - void Init(const QByteArray& windowState,const QByteArray& windowGeom) + void Init(const QByteArray& windowState,const QByteArray& windowGeom) override { AzToolsFramework::MainWindowSavedState::Init(windowState, windowGeom); } diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorView.hxx b/Code/Tools/Standalone/Source/LUA/LUAEditorView.hxx index 70e4ba625f..ada99929aa 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorView.hxx +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorView.hxx @@ -73,7 +73,7 @@ namespace LUAEditor LUADockWidget* luaDockWidget(){ return m_pLUADockWidget;} void SetLuaDockWidget(LUADockWidget* pLUADockWidget){m_pLUADockWidget = pLUADockWidget;} - virtual void dropEvent(QDropEvent *e); + void dropEvent(QDropEvent *e) override; // point a little arrow at this line. -1 means remove it. void UpdateCurrentExecutingLine(int lineNumber); @@ -83,9 +83,9 @@ namespace LUAEditor ////////////////////////////////////////////////////////////////////////// //Debugger Messages, from the LUAEditor::LUABreakpointTrackerMessages::Bus - virtual void BreakpointsUpdate(const LUAEditor::BreakpointMap& uniqueBreakpoints); - virtual void BreakpointHit(const LUAEditor::Breakpoint& breakpoint); - virtual void BreakpointResume(); + void BreakpointsUpdate(const LUAEditor::BreakpointMap& uniqueBreakpoints) override; + void BreakpointHit(const LUAEditor::Breakpoint& breakpoint) override; + void BreakpointResume() override; void BreakpointToggle(int line); @@ -153,7 +153,7 @@ namespace LUAEditor void RegainFocus(); private: - virtual void keyPressEvent(QKeyEvent *ev); + void keyPressEvent(QKeyEvent *ev) override; int CalcDocPosition(int line, int column); template //callabe must take a const QTextCursor& as a parameter void UpdateCursor(Callable callable); diff --git a/Code/Tools/Standalone/Source/StandaloneToolsApplication.h b/Code/Tools/Standalone/Source/StandaloneToolsApplication.h index 82028d7b9f..4ca45b8669 100644 --- a/Code/Tools/Standalone/Source/StandaloneToolsApplication.h +++ b/Code/Tools/Standalone/Source/StandaloneToolsApplication.h @@ -42,7 +42,7 @@ namespace StandaloneTools bool LaunchDiscoveryService(); // AZ::UserSettingsFileLocatorBus::Handler - AZStd::string ResolveFilePath(AZ::u32 /*providerId*/); + AZStd::string ResolveFilePath(AZ::u32 /*providerId*/) override; ////////////////////////////////////////////////////////////////////////// }; } diff --git a/Code/Tools/Standalone/Source/Telemetry/TelemetryComponent.h b/Code/Tools/Standalone/Source/Telemetry/TelemetryComponent.h index a715466cdb..f924908ea2 100644 --- a/Code/Tools/Standalone/Source/Telemetry/TelemetryComponent.h +++ b/Code/Tools/Standalone/Source/Telemetry/TelemetryComponent.h @@ -26,8 +26,8 @@ namespace Telemetry ////////////////// // AZ::Component - void Activate(); - void Deactivate(); + void Activate() override; + void Deactivate() override; static void Reflect(AZ::ReflectContext* context); ////////////////// From a7780b6dbedac5c479389c24b403e5904bde7f3b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:16:11 -0700 Subject: [PATCH 052/274] Gems/Atom* Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Editor/MipmapSettingWidget.h | 2 +- .../Code/Source/Editor/TexturePreviewWidget.h | 2 +- .../Source/Editor/TexturePropertyEditor.h | 2 +- .../StartParamFunctionsOverrideImpl.inl | 19 +++++++++++++++++++ .../Source/Checkerboard/CheckerboardPass.h | 2 +- .../Common/Code/Source/ImGui/ImGuiPass.h | 2 +- .../Source/PostProcess/Bloom/BloomSettings.h | 2 +- .../Source/PostProcess/PostProcessSettings.h | 2 +- .../Source/PostProcess/Ssao/SsaoSettings.h | 2 +- .../Source/ScreenSpace/DeferredFogSettings.h | 18 +++++++++--------- .../Shadows/ProjectedShadowFeatureProcessor.h | 2 +- .../atom_feature_common_public_files.cmake | 1 + .../RHI.Builders/ShaderPlatformInterface.h | 2 +- Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h | 18 +++++++++--------- .../MaterialPropertySerializerTests.cpp | 4 ++-- .../Viewport/RenderViewportWidget.h | 2 +- .../Source/Animation/AttachmentComponent.h | 2 +- .../CoreLights/SimplePointLightDelegate.h | 3 +-- .../CoreLights/SimpleSpotLightDelegate.h | 2 +- .../Source/Mesh/MeshComponentController.h | 17 +++++++---------- .../Code/Source/AtomActorInstance.h | 4 ++-- 21 files changed, 63 insertions(+), 47 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/StartParamFunctionsOverrideImpl.inl diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/MipmapSettingWidget.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/MipmapSettingWidget.h index 9ea7f9c6ae..27efdb084b 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/MipmapSettingWidget.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/MipmapSettingWidget.h @@ -47,7 +47,7 @@ namespace ImageProcessingAtomEditor protected: //////////////////////////////////////////////////////////////////////// //EditorInternalNotificationBus - void OnEditorSettingsChanged(bool needRefresh, const AZStd::string& platform); + void OnEditorSettingsChanged(bool needRefresh, const AZStd::string& platform) override; //////////////////////////////////////////////////////////////////////// private: diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePreviewWidget.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePreviewWidget.h index db3c95c142..d97698cc63 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePreviewWidget.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePreviewWidget.h @@ -70,7 +70,7 @@ namespace ImageProcessingAtomEditor protected: //////////////////////////////////////////////////////////////////////// //EditorInternalNotificationBus - void OnEditorSettingsChanged(bool needRefresh, const AZStd::string& platform); + void OnEditorSettingsChanged(bool needRefresh, const AZStd::string& platform) override; //////////////////////////////////////////////////////////////////////// void resizeEvent(QResizeEvent* event) override; bool eventFilter(QObject* obj, QEvent* event) override; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePropertyEditor.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePropertyEditor.h index 988561f3ce..83bcec9c83 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePropertyEditor.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePropertyEditor.h @@ -52,7 +52,7 @@ namespace ImageProcessingAtomEditor //////////////////////////////////////////////////////////////////////// //EditorInternalNotificationBus - void OnEditorSettingsChanged(bool needRefresh, const AZStd::string& platform); + void OnEditorSettingsChanged(bool needRefresh, const AZStd::string& platform) override; //////////////////////////////////////////////////////////////////////// bool event(QEvent* event) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/StartParamFunctionsOverrideImpl.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/StartParamFunctionsOverrideImpl.inl new file mode 100644 index 0000000000..37a853c94c --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ParamMacros/StartParamFunctionsOverrideImpl.inl @@ -0,0 +1,19 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +// Auto-generates override function declarations for getters and setters of specified parameters and overrides + +#define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) \ + ValueType Get##Name() const override { return MemberName; } \ + void Set##Name(ValueType val) override { MemberName = val; } \ + +#define AZ_GFX_COMMON_OVERRIDE(ValueType, Name, MemberName, OverrideValueType) \ + OverrideValueType Get##Name##Override() const override { return MemberName##Override; } \ + void Set##Name##Override(OverrideValueType val) override { MemberName##Override = val; } \ + +#include diff --git a/Gems/Atom/Feature/Common/Code/Source/Checkerboard/CheckerboardPass.h b/Gems/Atom/Feature/Common/Code/Source/Checkerboard/CheckerboardPass.h index 3ef4e5f851..5db9a7e487 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Checkerboard/CheckerboardPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/Checkerboard/CheckerboardPass.h @@ -35,7 +35,7 @@ namespace AZ protected: // Pass overrides... - void FrameBeginInternal(FramePrepareParams params); + void FrameBeginInternal(FramePrepareParams params) override; void BuildInternal() override; void FrameEndInternal() override; diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.h b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.h index 0bde3edb4f..018d2d46b7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.h @@ -77,7 +77,7 @@ namespace AZ void RenderImguiDrawData(const ImDrawData& drawData); // TickBus::Handler overrides... - void OnTick(float deltaTime, AZ::ScriptTimePoint timePoint); + void OnTick(float deltaTime, AZ::ScriptTimePoint timePoint) override; // AzFramework::InputTextEventListener overrides... bool OnInputTextEventFiltered(const AZStd::string& textUTF8) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/Bloom/BloomSettings.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/Bloom/BloomSettings.h index 1c245732aa..a433305d92 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/Bloom/BloomSettings.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/Bloom/BloomSettings.h @@ -47,7 +47,7 @@ namespace AZ void ApplySettingsTo(BloomSettings* target, float alpha) const; // Generate getters and setters. -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h index 2bb1eee277..515326e357 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h @@ -52,7 +52,7 @@ namespace AZ #undef POST_PROCESS_MEMBER // Auto-gen getter and setter functions for post process members... -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/Ssao/SsaoSettings.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/Ssao/SsaoSettings.h index f49b8151b1..4b3eb6e535 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/Ssao/SsaoSettings.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/Ssao/SsaoSettings.h @@ -47,7 +47,7 @@ namespace AZ void ApplySettingsTo(SsaoSettings* target, float alpha) const; // Generate getters and setters. -#include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogSettings.h b/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogSettings.h index 57d1dd24b5..85ced5496b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogSettings.h +++ b/Gems/Atom/Feature/Common/Code/Source/ScreenSpace/DeferredFogSettings.h @@ -56,7 +56,7 @@ namespace AZ ~DeferredFogSettings() = default; // DeferredFogSettingsInterface overrides... - void OnSettingsChanged(); + void OnSettingsChanged() override; bool GetSettingsNeedUpdate() { return m_needUpdate; @@ -66,35 +66,35 @@ namespace AZ m_needUpdate = needUpdate; } - void SetEnabled(bool value); - virtual bool GetEnabled() const override + void SetEnabled(bool value) override; + bool GetEnabled() const override { return m_enabled; } - virtual void SetInitialized(bool isInitialized) override + void SetInitialized(bool isInitialized) override { m_isInitialized = isInitialized; } - virtual bool IsInitialized() override + bool IsInitialized() override { return m_isInitialized; } - virtual void SetUseNoiseTextureShaderOption(bool value) override + void SetUseNoiseTextureShaderOption(bool value) override { m_useNoiseTextureShaderOption = value; } - virtual bool GetUseNoiseTextureShaderOption() override + bool GetUseNoiseTextureShaderOption() override { return m_useNoiseTextureShaderOption; } - virtual void SetEnableFogLayerShaderOption(bool value) override + void SetEnableFogLayerShaderOption(bool value) override { m_enableFogLayerShaderOption = value; } - virtual bool GetEnableFogLayerShaderOption() override + bool GetEnableFogLayerShaderOption() override { return m_enableFogLayerShaderOption; } diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index 8beed800b6..cd74ba3797 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -48,7 +48,7 @@ namespace AZ::Render void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override; void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; void SetShadowBias(ShadowId id, float bias) override; - void SetPcfMethod(ShadowId id, PcfMethod method); + void SetPcfMethod(ShadowId id, PcfMethod method) override; void SetEsmExponent(ShadowId id, float exponent); void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override; diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake index 886a9f0f22..89febbcf3d 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake @@ -39,6 +39,7 @@ set(FILES Include/Atom/Feature/ParamMacros/StartParamCopySettingsTo.inl Include/Atom/Feature/ParamMacros/StartParamFunctions.inl Include/Atom/Feature/ParamMacros/StartParamFunctionsOverride.inl + Include/Atom/Feature/ParamMacros/StartParamFunctionsOverrideImpl.inl Include/Atom/Feature/ParamMacros/StartParamFunctionsVirtual.inl Include/Atom/Feature/ParamMacros/StartParamMembers.inl Include/Atom/Feature/ParamMacros/StartParamSerializeContext.inl diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.h b/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.h index 0a03211ca6..a9176ac750 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.h +++ b/Gems/Atom/RHI/Null/Code/Source/RHI.Builders/ShaderPlatformInterface.h @@ -34,7 +34,7 @@ namespace AZ const AssetBuilderSDK::PlatformInfo& platform, const AZStd::string& shaderSourcePath, const AZStd::string& functionName, RHI::ShaderHardwareStage shaderStage, const AZStd::string& tempFolderPath, StageDescriptor& outputDescriptor, const RHI::ShaderCompilerArguments& shaderCompilerArguments) const override; - AZStd::string GetAzslCompilerWarningParameters(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const; + AZStd::string GetAzslCompilerWarningParameters(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const override; bool BuildHasDebugInfo(const RHI::ShaderCompilerArguments& shaderCompilerArguments) const override; const char* GetAzslHeader(const AssetBuilderSDK::PlatformInfo& platform) const override; bool BuildPipelineLayoutDescriptor( diff --git a/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h b/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h index c3768c1ce6..2ed2875cad 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h +++ b/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h @@ -69,8 +69,8 @@ namespace UnitTest void FillFormatsCapabilitiesInternal([[maybe_unused]] FormatCapabilitiesList& formatsCapabilities) override {} AZ::RHI::ResultCode InitializeLimits() override { return AZ::RHI::ResultCode::Success; } void PreShutdown() override {} - AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::ImageDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; }; - AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::BufferDescriptor& descriptor) { return AZ::RHI::ResourceMemoryRequirements{}; }; + AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::ImageDescriptor& descriptor) override { return AZ::RHI::ResourceMemoryRequirements{}; }; + AZ::RHI::ResourceMemoryRequirements GetResourceMemoryRequirements([[maybe_unused]] const AZ::RHI::BufferDescriptor& descriptor) override { return AZ::RHI::ResourceMemoryRequirements{}; }; void ObjectCollectionNotify(AZ::RHI::ObjectCollectorNotifyFunction notifyFunction) override {} }; @@ -228,12 +228,12 @@ namespace UnitTest AZ_CLASS_ALLOCATOR(Fence, AZ::SystemAllocator, 0); private: - virtual AZ::RHI::ResultCode InitInternal(AZ::RHI::Device&, AZ::RHI::FenceState) override { return AZ::RHI::ResultCode::Success; } - virtual void ShutdownInternal() override {} - virtual void SignalOnCpuInternal() override {} - virtual void WaitOnCpuInternal() const override {}; - virtual void ResetInternal() override {} - virtual AZ::RHI::FenceState GetFenceStateInternal() const override { return AZ::RHI::FenceState::Reset; } + AZ::RHI::ResultCode InitInternal(AZ::RHI::Device&, AZ::RHI::FenceState) override { return AZ::RHI::ResultCode::Success; } + void ShutdownInternal() override {} + void SignalOnCpuInternal() override {} + void WaitOnCpuInternal() const override {}; + void ResetInternal() override {} + AZ::RHI::FenceState GetFenceStateInternal() const override { return AZ::RHI::FenceState::Reset; } }; class ShaderResourceGroupPool @@ -276,7 +276,7 @@ namespace UnitTest AZ_CLASS_ALLOCATOR(ShaderStageFunction, AZ::SystemAllocator, 0); private: - virtual AZ::RHI::ResultCode FinalizeInternal() { return AZ::RHI::ResultCode::Success; } + AZ::RHI::ResultCode FinalizeInternal() override { return AZ::RHI::ResultCode::Success; } }; class PipelineState diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp index 5386af1cfa..ce842d385d 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialPropertySerializerTests.cpp @@ -21,14 +21,14 @@ namespace JsonSerializationTests public JsonSerializerConformityTestDescriptor { public: - void Reflect(AZStd::unique_ptr& context) + void Reflect(AZStd::unique_ptr& context) override { AZ::RPI::MaterialTypeSourceData::Reflect(context.get()); AZ::RPI::MaterialPropertyDescriptor::Reflect(context.get()); AZ::RPI::ReflectMaterialDynamicMetadata(context.get()); } - void Reflect(AZStd::unique_ptr& context) + void Reflect(AZStd::unique_ptr& context) override { AZ::RPI::MaterialTypeSourceData::Reflect(context.get()); } 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 4210c82921..071bc5c997 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -113,7 +113,7 @@ namespace AtomToolsFramework void ToggleFullScreenState() override; float GetDpiScaleFactor() const override; uint32_t GetSyncInterval() const override; - uint32_t GetDisplayRefreshRate() const; + uint32_t GetDisplayRefreshRate() const override; protected: // AzFramework::InputChannelEventListener ... diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h index 3e8feb2182..bd7c52c851 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h @@ -75,7 +75,7 @@ namespace AZ //////////////////////////////////////////////////////////////////////// // AttachmentComponentRequests - void Reattach(bool detachFirst); + void Reattach(bool detachFirst) override; void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override; void Detach() override; void SetAttachmentOffset(const AZ::Transform& offset) override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h index ef6c0b9da8..c239055be8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimplePointLightDelegate.h @@ -31,8 +31,7 @@ namespace AZ float GetEffectiveSolidAngle() const override { return PhotometricValue::OmnidirectionalSteradians; } private: - virtual void HandleShapeChanged(); - + void HandleShapeChanged() override; }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h index 6b2b9bf4bb..7f9c4abc0f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SimpleSpotLightDelegate.h @@ -34,7 +34,7 @@ namespace AZ void SetShutterAngles(float innerAngleDegrees, float outerAngleDegrees) override; private: - virtual void HandleShapeChanged(); + void HandleShapeChanged() override; }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 2c7cc78979..6b0731fbf7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -30,9 +30,6 @@ namespace AZ { namespace Render { - - - //! A configuration structure for the MeshComponentController class MeshComponentConfig final : public AZ::ComponentConfig @@ -107,14 +104,14 @@ namespace AZ void SetLodType(RPI::Cullable::LodType lodType) override; RPI::Cullable::LodType GetLodType() const override; - virtual void SetLodOverride(RPI::Cullable::LodOverride lodOverride); - virtual RPI::Cullable::LodOverride GetLodOverride() const; + void SetLodOverride(RPI::Cullable::LodOverride lodOverride) override; + RPI::Cullable::LodOverride GetLodOverride() const override; - virtual void SetMinimumScreenCoverage(float minimumScreenCoverage); - virtual float GetMinimumScreenCoverage() const; + void SetMinimumScreenCoverage(float minimumScreenCoverage) override; + float GetMinimumScreenCoverage() const override; - virtual void SetQualityDecayRate(float qualityDecayRate); - virtual float GetQualityDecayRate() const; + void SetQualityDecayRate(float qualityDecayRate) override; + float GetQualityDecayRate() const override; void SetVisibility(bool visible) override; bool GetVisibility() const override; @@ -130,7 +127,7 @@ namespace AZ void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; // MaterialReceiverRequestBus::Handler overrides ... - virtual MaterialAssignmentId FindMaterialAssignmentId( + MaterialAssignmentId FindMaterialAssignmentId( const MaterialAssignmentLodIndex lod, const AZStd::string& label) const override; RPI::ModelMaterialSlotMap GetModelMaterialSlots() const override; MaterialAssignmentMap GetMaterialAssignments() const override; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index a74cc46e65..5ddab8bc61 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -88,7 +88,7 @@ namespace AZ void UpdateBounds() override; void DebugDraw(const DebugOptions& debugOptions) override; void SetMaterials(const EMotionFX::Integration::ActorAsset::MaterialList& materialPerLOD) override { AZ_UNUSED(materialPerLOD); }; - void SetSkinningMethod(EMotionFX::Integration::SkinningMethod emfxSkinningMethod); + void SetSkinningMethod(EMotionFX::Integration::SkinningMethod emfxSkinningMethod) override; SkinningMethod GetAtomSkinningMethod() const; void SetIsVisible(bool isVisible) override; @@ -120,7 +120,7 @@ namespace AZ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MaterialReceiverRequestBus::Handler overrides... - virtual MaterialAssignmentId FindMaterialAssignmentId( + MaterialAssignmentId FindMaterialAssignmentId( const MaterialAssignmentLodIndex lod, const AZStd::string& label) const override; RPI::ModelMaterialSlotMap GetModelMaterialSlots() const override; MaterialAssignmentMap GetMaterialAssignments() const override; From b8d0bffdd04998092cd955c6447ea81452b3ced1 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:16:39 -0700 Subject: [PATCH 053/274] Gems/AudioSystem Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.h | 4 ++-- .../Code/Source/Editor/ATLControlsResourceDialog.h | 2 +- .../Code/Source/Editor/AudioControlsEditorWindow.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.h b/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.h index 1bb6cef3de..3942a6b18a 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.h +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsPanel.h @@ -73,11 +73,11 @@ namespace AudioControls void HandleExternalDropEvent(QDropEvent* pDropEvent); // ------------- IATLControlModelListener ---------------- - virtual void OnControlAdded(CATLControl* pControl) override; + void OnControlAdded(CATLControl* pControl) override; // ------------------------------------------------------- // ------------------ QWidget ---------------------------- - bool eventFilter(QObject* pObject, QEvent* pEvent); + bool eventFilter(QObject* pObject, QEvent* pEvent) override; // ------------------------------------------------------- private slots: diff --git a/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.h b/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.h index 10186f9c74..daa8c195c3 100644 --- a/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.h +++ b/Gems/AudioSystem/Code/Source/Editor/ATLControlsResourceDialog.h @@ -63,7 +63,7 @@ namespace AudioControls QString GetWindowTitle(EACEControlType type) const; // ------------------ QWidget ---------------------------- - bool eventFilter(QObject* pObject, QEvent* pEvent); + bool eventFilter(QObject* pObject, QEvent* pEvent) override; // ------------------------------------------------------- // Filtering diff --git a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h index bfa08828ac..abe5fd4511 100644 --- a/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h +++ b/Gems/AudioSystem/Code/Source/Editor/AudioControlsEditorWindow.h @@ -63,8 +63,8 @@ namespace AudioControls void Update(); protected: - void keyPressEvent(QKeyEvent* pEvent); - void closeEvent(QCloseEvent* pEvent); + void keyPressEvent(QKeyEvent* pEvent) override; + void closeEvent(QCloseEvent* pEvent) override; private: void UpdateAudioSystemData(); From 48652dcac7c38d55539e30cdf0e518f90130dc3b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:17:50 -0700 Subject: [PATCH 054/274] Gems/EditorPythonBindings Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/EditorPythonBindings/Code/Tests/PythonAssetTypesTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EditorPythonBindings/Code/Tests/PythonAssetTypesTests.cpp b/Gems/EditorPythonBindings/Code/Tests/PythonAssetTypesTests.cpp index 78ac2a0a45..9940a01b7a 100644 --- a/Gems/EditorPythonBindings/Code/Tests/PythonAssetTypesTests.cpp +++ b/Gems/EditorPythonBindings/Code/Tests/PythonAssetTypesTests.cpp @@ -116,7 +116,7 @@ namespace UnitTest return AZ::Data::AssetType("{7FD86523-3903-4037-BCD1-542027BFC553}"); } - virtual const char* GetFileFilter() const + const char* GetFileFilter() const override { return nullptr; } From 0800e95aa77b19ebf4294a4459d618f9708a1de3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:18:05 -0700 Subject: [PATCH 055/274] Gems/EMotionFX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../EMStudioSDK/Source/MainWindow.h | 2 +- .../Source/RenderPlugin/RenderPlugin.h | 2 +- .../Source/RenderPlugin/RenderWidget.h | 4 ++-- .../Source/OpenGLRender/GLWidget.h | 18 +++++++++--------- .../Source/OpenGLRender/OpenGLRenderPlugin.h | 6 +++--- .../Source/AnimGraph/AnimGraphItemDelegate.h | 2 +- .../Source/AnimGraph/AttributesWindow.h | 2 +- .../Source/AnimGraph/BlendTreeVisualNode.h | 4 ++-- .../Source/TimeView/TrackHeaderWidget.h | 4 ++-- .../Integration/System/SystemComponent.h | 2 +- .../Tests/AnimGraphTransitionCommandTests.cpp | 4 ++-- .../Code/Tests/MotionEventTrackTests.cpp | 2 +- 12 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h index 318838b2b1..a11f11c6a8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h @@ -290,7 +290,7 @@ namespace EMStudio /// CommandManagerCallback implementation void OnPreExecuteCommand(MCore::CommandGroup* group, MCore::Command* command, const MCore::CommandLine& commandLine) override; void OnPostExecuteCommand(MCore::CommandGroup* /*group*/, MCore::Command* /*command*/, const MCore::CommandLine& /*commandLine*/, bool /*wasSuccess*/, const AZStd::string& /*outResult*/) override { } - void OnPreUndoCommand(MCore::Command* command, const MCore::CommandLine& commandLine); + void OnPreUndoCommand(MCore::Command* command, const MCore::CommandLine& commandLine) override; void OnPreExecuteCommandGroup(MCore::CommandGroup* /*group*/, bool /*undo*/) override { } void OnPostExecuteCommandGroup(MCore::CommandGroup* /*group*/, bool /*wasSuccess*/) override { } void OnAddCommandToHistory(size_t /*historyIndex*/, MCore::CommandGroup* /*group*/, MCore::Command* /*command*/, const MCore::CommandLine& /*commandLine*/) override { } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index 01678e024d..6e4a68fa6f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -95,7 +95,7 @@ namespace EMStudio virtual bool CreateEMStudioActor(EMotionFX::Actor* actor) = 0; // SkeletonOutlinerNotificationBus - void ZoomToJoints(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& joints); + void ZoomToJoints(EMotionFX::ActorInstance* actorInstance, const AZStd::vector& joints) override; // ActorNotificationBus void OnActorReady(EMotionFX::Actor* actor) override; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h index d4906355da..01644362de 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h @@ -81,8 +81,8 @@ namespace EMStudio // overloaded const AZStd::vector GetHandledEventTypes() const override { return { EMotionFX::EVENT_TYPE_ON_DRAW_LINE, EMotionFX::EVENT_TYPE_ON_DRAW_TRIANGLE, EMotionFX::EVENT_TYPE_ON_DRAW_TRIANGLES }; } - MCORE_INLINE void OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) { m_widget->AddTriangle(posA, posB, posC, normalA, normalB, normalC, color); } - MCORE_INLINE void OnDrawTriangles() { m_widget->RenderTriangles(); } + MCORE_INLINE void OnDrawTriangle(const AZ::Vector3& posA, const AZ::Vector3& posB, const AZ::Vector3& posC, const AZ::Vector3& normalA, const AZ::Vector3& normalB, const AZ::Vector3& normalC, uint32 color) override { m_widget->AddTriangle(posA, posB, posC, normalA, normalB, normalC, color); } + MCORE_INLINE void OnDrawTriangles() override { m_widget->RenderTriangles(); } private: RenderWidget* m_widget; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h index 685ff4ef88..f821a7710e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h @@ -53,7 +53,7 @@ namespace EMStudio void initializeGL() override; void paintGL() override; - void resizeGL(int width, int height); + void resizeGL(int width, int height) override; private slots: void CloneSelectedActorInstances() { CommandSystem::CloneSelectedActorInstances(); } @@ -64,16 +64,16 @@ namespace EMStudio void ResetToBindPose() { CommandSystem::ResetToBindPose(); } protected: - void mouseMoveEvent(QMouseEvent* event) { RenderWidget::OnMouseMoveEvent(this, event); } - void mousePressEvent(QMouseEvent* event) { RenderWidget::OnMousePressEvent(this, event); } - void mouseReleaseEvent(QMouseEvent* event) { RenderWidget::OnMouseReleaseEvent(this, event); } - void wheelEvent(QWheelEvent* event) { RenderWidget::OnWheelEvent(this, event); } + void mouseMoveEvent(QMouseEvent* event) override { RenderWidget::OnMouseMoveEvent(this, event); } + void mousePressEvent(QMouseEvent* event) override { RenderWidget::OnMousePressEvent(this, event); } + void mouseReleaseEvent(QMouseEvent* event) override { RenderWidget::OnMouseReleaseEvent(this, event); } + void wheelEvent(QWheelEvent* event) override { RenderWidget::OnWheelEvent(this, event); } - void focusInEvent(QFocusEvent* event); - void focusOutEvent(QFocusEvent* event); + void focusInEvent(QFocusEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; - void Render(); - void Update() { update(); } + void Render() override; + void Update() override { update(); } void RenderBorder(const MCore::RGBAColor& color); RenderGL::GBuffer m_gBuffer; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h index 1203d7e381..ba2bb0f462 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/OpenGLRenderPlugin.h @@ -43,8 +43,8 @@ namespace EMStudio bool GetIsVertical() const override { return false; } // overloaded main init function - bool Init(); - EMStudioPlugin* Clone() { return new OpenGLRenderPlugin(); } + bool Init() override; + EMStudioPlugin* Clone() override { return new OpenGLRenderPlugin(); } // overloaded functions void CreateRenderWidget(RenderViewWidget* renderViewWidget, RenderWidget** outRenderWidget, QWidget** outWidget) override; @@ -57,7 +57,7 @@ namespace EMStudio RenderGL::GraphicsManager* m_graphicsManager; // shared OpenGL engine object // overloaded emstudio actor create function which creates an OpenGL render actor internally - bool CreateEMStudioActor(EMotionFX::Actor* actor); + bool CreateEMStudioActor(EMotionFX::Actor* actor) override; void RenderActorInstance(EMotionFX::ActorInstance* actorInstance, float timePassedInSeconds) override; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphItemDelegate.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphItemDelegate.h index 4066601cf5..c2c7499727 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphItemDelegate.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphItemDelegate.h @@ -28,7 +28,7 @@ namespace EMStudio void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override; - void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; signals: void linkActivated(const QString& link); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h index 38bceb4426..b19304b898 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AttributesWindow.h @@ -152,7 +152,7 @@ namespace EMStudio void OnDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles); private: AddConditionButton* m_addConditionButton = nullptr; - void contextMenuEvent(QContextMenuEvent* event); + void contextMenuEvent(QContextMenuEvent* event) override; void PasteTransition(bool pasteTransitionProperties, bool pasteConditions); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.h index a72985cae6..ef87fc9a00 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendTreeVisualNode.h @@ -34,11 +34,11 @@ namespace EMStudio ~BlendTreeVisualNode(); void Sync() override; - uint32 GetType() const { return BlendTreeVisualNode::TYPE_ID; } + uint32 GetType() const override { return BlendTreeVisualNode::TYPE_ID; } void Render(QPainter& painter, QPen* pen, bool renderShadow) override; - int32 CalcRequiredHeight() const; + int32 CalcRequiredHeight() const override; private: QColor GetPortColor(const EMotionFX::AnimGraphNode::Port& port) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h index b794f248f6..2839e52e11 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/TimeView/TrackHeaderWidget.h @@ -70,8 +70,8 @@ namespace EMStudio void NameEdited(const QString& text); void EnabledCheckBoxChanged(int state); - void keyPressEvent(QKeyEvent* event); - void keyReleaseEvent(QKeyEvent* event); + void keyPressEvent(QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; }; /** diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h index 7d0c3f4725..a716f0aa9b 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h @@ -110,7 +110,7 @@ namespace EMotionFX #if defined (EMOTIONFXANIMATION_EDITOR) void UpdateAnimationEditorPlugins(float delta); void NotifyRegisterViews() override; - bool IsSystemActive(EditorAnimationSystemRequests::AnimationSystem systemType); + bool IsSystemActive(EditorAnimationSystemRequests::AnimationSystem systemType) override; ////////////////////////////////////////////////////////////////////////////////////// // AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphTransitionCommandTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphTransitionCommandTests.cpp index 49d53f1f91..bb13744b46 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphTransitionCommandTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphTransitionCommandTests.cpp @@ -62,14 +62,14 @@ namespace EMotionFX m_motionNodeAnimGraph->InitAfterLoading(); } - void SetUp() + void SetUp() override { AnimGraphFixture::SetUp(); m_animGraphInstance->Destroy(); m_animGraphInstance = m_motionNodeAnimGraph->GetAnimGraphInstance(m_actorInstance, m_motionSet); } - void TearDown() + void TearDown() override { AnimGraphFixture::TearDown(); } diff --git a/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp b/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp index 30ab36e35a..08d67b8bee 100644 --- a/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionEventTrackTests.cpp @@ -122,7 +122,7 @@ namespace EMotionFX { } - virtual const AZStd::vector GetHandledEventTypes() const + const AZStd::vector GetHandledEventTypes() const override { return { EVENT_TYPE_ON_EVENT }; } From 545beaab7d7489a41a240d57c1255e9d3b749824 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:18:22 -0700 Subject: [PATCH 056/274] Gems/GameStateSamples Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/GameStateSamples/Code/Source/GameStateSamplesModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/GameStateSamples/Code/Source/GameStateSamplesModule.cpp b/Gems/GameStateSamples/Code/Source/GameStateSamplesModule.cpp index f175619bf4..a83a5abdd1 100644 --- a/Gems/GameStateSamples/Code/Source/GameStateSamplesModule.cpp +++ b/Gems/GameStateSamples/Code/Source/GameStateSamplesModule.cpp @@ -84,7 +84,7 @@ namespace GameStateSamples } protected: - void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& systemInitParams) + void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& systemInitParams) override { CryHooksModule::OnCrySystemInitialized(system, systemInitParams); From 35a7ad612b1943474e40eb426adddfdea038666d Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:18:37 -0700 Subject: [PATCH 057/274] Gems/GradientSignal Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../GradientSignal/Editor/EditorGradientComponentBase.h | 2 +- .../GradientSignal/Code/Source/UI/GradientPreviewDataWidget.h | 2 +- Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Editor/EditorGradientComponentBase.h b/Gems/GradientSignal/Code/Include/GradientSignal/Editor/EditorGradientComponentBase.h index 1eac48a109..2083837934 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Editor/EditorGradientComponentBase.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Editor/EditorGradientComponentBase.h @@ -92,7 +92,7 @@ namespace GradientSignal using BaseClassType::m_component; using BaseClassType::m_configuration; - virtual AZ::u32 ConfigurationChanged(); + AZ::u32 ConfigurationChanged() override; // This is used by the preview so we can pass an invalid entity Id if our component is disabled AZ::EntityId GetGradientEntityId() const; diff --git a/Gems/GradientSignal/Code/Source/UI/GradientPreviewDataWidget.h b/Gems/GradientSignal/Code/Source/UI/GradientPreviewDataWidget.h index 3aa5987924..7fc3a53463 100644 --- a/Gems/GradientSignal/Code/Source/UI/GradientPreviewDataWidget.h +++ b/Gems/GradientSignal/Code/Source/UI/GradientPreviewDataWidget.h @@ -66,7 +66,7 @@ namespace GradientSignal AZ::u32 GetHandlerName() const override; bool ReadValueIntoGUI(size_t index, GradientPreviewDataWidget* GUI, void* value, const AZ::Uuid& propertyType) override; - void ConsumeAttribute(GradientPreviewDataWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName); + void ConsumeAttribute(GradientPreviewDataWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; QWidget* CreateGUI(QWidget* pParent) override; void PreventRefresh(QWidget* widget, bool shouldPrevent) override; diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h index cf3843ce4a..9c0d8be588 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestMocks.h @@ -174,8 +174,8 @@ namespace UnitTest } AZ::EntityId GetPreviewEntity() const override { return m_id; } - virtual AZ::Aabb GetPreviewBounds() const { return m_previewBounds; } - virtual bool GetConstrainToShape() const { return m_constrainToShape; } + AZ::Aabb GetPreviewBounds() const override { return m_previewBounds; } + bool GetConstrainToShape() const override { return m_constrainToShape; } protected: AZ::EntityId m_id; From fa1d1bd2fc4ba1cd7183d66d9849dcba1092d04b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:19:06 -0700 Subject: [PATCH 058/274] Gems/GraphCanvas Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Include/GraphCanvas/Widgets/RootGraphicsItem.h | 10 +++++----- .../BookmarkAnchor/BookmarkAnchorVisualComponent.h | 2 +- .../Connections/ConnectionLayerControllerComponent.h | 2 +- .../Code/Source/Components/GeometryComponent.h | 2 +- .../NodePropertyDisplays/StringNodePropertyDisplay.h | 2 +- .../NodePropertyDisplays/VectorNodePropertyDisplay.h | 2 +- .../Nodes/Comment/CommentNodeFrameComponent.h | 2 +- .../Nodes/Comment/CommentNodeLayoutComponent.h | 8 ++++---- .../Nodes/Comment/CommentNodeTextComponent.h | 2 +- .../Nodes/Comment/CommentTextGraphicsWidget.h | 2 +- .../Nodes/General/GeneralNodeFrameComponent.h | 2 +- .../Nodes/General/GeneralSlotLayoutComponent.h | 4 ++-- .../Nodes/Group/CollapsedNodeGroupComponent.h | 4 ++-- .../Components/Nodes/Group/NodeGroupFrameComponent.h | 10 +++++----- .../Components/Nodes/Group/NodeGroupLayoutComponent.h | 8 ++++---- .../Code/Source/Components/Nodes/NodeComponent.h | 2 +- .../Nodes/Wrapper/WrapperNodeLayoutComponent.h | 6 +++--- .../Source/Components/Slots/Data/DataSlotComponent.h | 6 +++--- .../Slots/Default/DefaultSlotLayoutComponent.h | 2 +- .../Slots/Execution/ExecutionSlotLayoutComponent.h | 8 ++++---- .../Components/Slots/Extender/ExtenderSlotComponent.h | 6 +++--- .../Slots/Extender/ExtenderSlotLayoutComponent.h | 8 ++++---- .../Components/Slots/Property/PropertySlotComponent.h | 8 ++++---- .../Slots/Property/PropertySlotLayoutComponent.h | 2 +- .../Code/Source/Components/Slots/SlotComponent.h | 2 +- .../Code/Source/Components/Slots/SlotLayoutComponent.h | 8 ++++---- .../Code/Source/Components/Slots/SlotLayoutItem.h | 4 ++-- .../Code/Source/Widgets/NodePropertyDisplayWidget.h | 4 ++-- .../GraphCanvas/Components/GraphCanvasPropertyBus.h | 8 ++++---- .../GraphicsItems/GlowOutlineGraphicsItem.h | 4 ++-- .../GraphCanvas/Styling/SelectorImplementations.h | 2 +- .../Code/StaticLib/GraphCanvas/Styling/Style.cpp | 8 ++++---- .../GraphCanvas/Types/SceneMemberComponentSaveData.h | 2 +- .../StateControllers/PrioritizedStateController.h | 4 ++-- .../Utils/StateControllers/StackStateController.h | 4 ++-- .../GraphCanvas/Widgets/Bookmarks/BookmarkDockWidget.h | 2 +- .../GraphCanvas/Widgets/Bookmarks/BookmarkTableModel.h | 4 ++-- .../GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h | 4 ++-- .../GraphCanvasGraphicsView/GraphCanvasGraphicsView.h | 4 ++-- .../TreeItems/IconDecoratedNodePaletteTreeItem.h | 4 ++-- .../NodePalette/TreeItems/NodePaletteTreeItem.h | 2 +- 41 files changed, 90 insertions(+), 90 deletions(-) diff --git a/Gems/GraphCanvas/Code/Include/GraphCanvas/Widgets/RootGraphicsItem.h b/Gems/GraphCanvas/Code/Include/GraphCanvas/Widgets/RootGraphicsItem.h index cd7283c53c..e7c884da92 100644 --- a/Gems/GraphCanvas/Code/Include/GraphCanvas/Widgets/RootGraphicsItem.h +++ b/Gems/GraphCanvas/Code/Include/GraphCanvas/Widgets/RootGraphicsItem.h @@ -163,14 +163,14 @@ namespace GraphCanvas } // StateController - void OnStateChanged([[maybe_unused]] const RootGraphicsItemDisplayState& displayState) + void OnStateChanged([[maybe_unused]] const RootGraphicsItemDisplayState& displayState) override { UpdateActualDisplayState(); } //// // TickBus - void OnTick(float delta, AZ::ScriptTimePoint) + void OnTick(float delta, AZ::ScriptTimePoint) override { m_currentAnimationTime += delta; @@ -191,7 +191,7 @@ namespace GraphCanvas //// // RootGraphicsItemRequestBus - void AnimatePositionTo(const QPointF& scenePoint, const AZStd::chrono::milliseconds& duration) + void AnimatePositionTo(const QPointF& scenePoint, const AZStd::chrono::milliseconds& duration) override { if (!IsAnimating()) { @@ -231,7 +231,7 @@ namespace GraphCanvas GeometryRequestBus::Event(GetEntityId(), &GeometryRequests::SetAnimationTarget, m_targetPoint); } - void CancelAnimation() + void CancelAnimation() override { m_currentAnimationTime = m_animationDuration; CleanUpAnimation(); @@ -315,7 +315,7 @@ namespace GraphCanvas } } - RootGraphicsItemEnabledState GetEnabledState() const + RootGraphicsItemEnabledState GetEnabledState() const override { return m_enabledState; } diff --git a/Gems/GraphCanvas/Code/Source/Components/BookmarkAnchor/BookmarkAnchorVisualComponent.h b/Gems/GraphCanvas/Code/Source/Components/BookmarkAnchor/BookmarkAnchorVisualComponent.h index 2e2d9b9ab0..7e7ac6489f 100644 --- a/Gems/GraphCanvas/Code/Source/Components/BookmarkAnchor/BookmarkAnchorVisualComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/BookmarkAnchor/BookmarkAnchorVisualComponent.h @@ -57,7 +57,7 @@ namespace GraphCanvas //// // StyleNotificationBus - void OnStyleChanged(); + void OnStyleChanged() override; //// // GeometryNotificationBus diff --git a/Gems/GraphCanvas/Code/Source/Components/Connections/ConnectionLayerControllerComponent.h b/Gems/GraphCanvas/Code/Source/Components/Connections/ConnectionLayerControllerComponent.h index f991409b17..2532492d64 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Connections/ConnectionLayerControllerComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Connections/ConnectionLayerControllerComponent.h @@ -39,7 +39,7 @@ namespace GraphCanvas //// // LayerControllerNotificationBus - void OnOffsetsChanged(int selectionOffset, int groupOffset); + void OnOffsetsChanged(int selectionOffset, int groupOffset) override; //// private: diff --git a/Gems/GraphCanvas/Code/Source/Components/GeometryComponent.h b/Gems/GraphCanvas/Code/Source/Components/GeometryComponent.h index 1c7bf39445..61b66bcbf9 100644 --- a/Gems/GraphCanvas/Code/Source/Components/GeometryComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/GeometryComponent.h @@ -69,7 +69,7 @@ namespace GraphCanvas void SetIsPositionAnimating(bool animating) override; - void SetAnimationTarget(const AZ::Vector2& targetPoint); + void SetAnimationTarget(const AZ::Vector2& targetPoint) override; //// // VisualNotificationBus diff --git a/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/StringNodePropertyDisplay.h b/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/StringNodePropertyDisplay.h index ac179832d3..1e50262194 100644 --- a/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/StringNodePropertyDisplay.h +++ b/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/StringNodePropertyDisplay.h @@ -81,7 +81,7 @@ namespace GraphCanvas //// // AZ::SystemTickBus::Handler - void OnSystemTick(); + void OnSystemTick() override; //// private: diff --git a/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/VectorNodePropertyDisplay.h b/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/VectorNodePropertyDisplay.h index e0c50821a8..9c12dae08e 100644 --- a/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/VectorNodePropertyDisplay.h +++ b/Gems/GraphCanvas/Code/Source/Components/NodePropertyDisplays/VectorNodePropertyDisplay.h @@ -95,7 +95,7 @@ namespace GraphCanvas //// // DataSlotNotifications - void OnDragDropStateStateChanged(const DragDropState& dragState); + void OnDragDropStateStateChanged(const DragDropState& dragState) override; //// private: diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeFrameComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeFrameComponent.h index 0c85f366ed..9baeccb78f 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeFrameComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeFrameComponent.h @@ -65,7 +65,7 @@ namespace GraphCanvas //// // NodeNotifications - void OnNodeActivated(); + void OnNodeActivated() override; //// private: diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeLayoutComponent.h index 057261743f..8e2692ce0e 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeLayoutComponent.h @@ -50,9 +50,9 @@ namespace GraphCanvas required.push_back(AZ_CRC("GraphCanvas_StyledGraphicItemService", 0xeae4cdf4)); } - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // EntityBus @@ -64,7 +64,7 @@ namespace GraphCanvas //// // NodeNotification - void OnNodeActivated(); + void OnNodeActivated() override; //// protected: diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeTextComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeTextComponent.h index 36ddfeafe5..fa047d56a2 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeTextComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentNodeTextComponent.h @@ -82,7 +82,7 @@ namespace GraphCanvas //// // NodeNotification - void OnAddedToScene(const AZ::EntityId&); + void OnAddedToScene(const AZ::EntityId&) override; //// // CommentRequestBus diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentTextGraphicsWidget.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentTextGraphicsWidget.h index 1f6a4ce9a7..390fb1ef9e 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentTextGraphicsWidget.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Comment/CommentTextGraphicsWidget.h @@ -163,7 +163,7 @@ namespace GraphCanvas void SubmitValue(); void UpdateSizePolicies(); - bool sceneEventFilter(QGraphicsItem*, QEvent* event); + bool sceneEventFilter(QGraphicsItem*, QEvent* event) override; const AZ::EntityId& GetEntityId() const { return m_entityId; } void SetupProxyWidget(); diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralNodeFrameComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralNodeFrameComponent.h index f38157e82e..123f21f13d 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralNodeFrameComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralNodeFrameComponent.h @@ -68,7 +68,7 @@ namespace GraphCanvas //// // NodeNotifications - void OnNodeActivated(); + void OnNodeActivated() override; void OnNodeWrapped(const AZ::EntityId& wrappingNode) override; void OnNodeUnwrapped(const AZ::EntityId& wrappingNode) override; diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralSlotLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralSlotLayoutComponent.h index c9290021c9..397aea5a38 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralSlotLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/General/GeneralSlotLayoutComponent.h @@ -158,7 +158,7 @@ namespace GraphCanvas //// // SceneMemberNotificationBus - void OnSceneSet(const AZ::EntityId& sceneId); + void OnSceneSet(const AZ::EntityId& sceneId) override; //// // SlotLayoutRequestBus @@ -168,7 +168,7 @@ namespace GraphCanvas bool IsSlotGroupVisible(SlotGroup group) const override; void SetSlotGroupVisible(SlotGroup group, bool visible) override; - void ClearSlotGroup(SlotGroup group); + void ClearSlotGroup(SlotGroup group) override; //// // StyleNotificationBus diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/CollapsedNodeGroupComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/CollapsedNodeGroupComponent.h index 17ef858b52..fd9706f7ea 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/CollapsedNodeGroupComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/CollapsedNodeGroupComponent.h @@ -94,7 +94,7 @@ namespace GraphCanvas //// // GeometryNotifications - void OnBoundsChanged(); + void OnBoundsChanged() override; void OnPositionChanged(const AZ::EntityId& targetEntity, const AZ::Vector2& position) override; //// @@ -117,7 +117,7 @@ namespace GraphCanvas AZ::EntityId GetSourceGroup() const override; - AZStd::vector< Endpoint > GetRedirectedEndpoints() const; + AZStd::vector< Endpoint > GetRedirectedEndpoints() const override; void ForceEndpointRedirection(const AZStd::vector< Endpoint >& endpoints) override; //// diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.h index 4f791d913d..cc54866ccb 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupFrameComponent.h @@ -239,7 +239,7 @@ namespace GraphCanvas //// // SystemTickBus - void OnSystemTick(); + void OnSystemTick() override; //// // VisualNotificationBus @@ -446,13 +446,13 @@ namespace GraphCanvas //// // CommentNotificationBus - void OnEditBegin(); - void OnEditEnd(); + void OnEditBegin() override; + void OnEditEnd() override; void OnCommentSizeChanged(const QSizeF& oldSize, const QSizeF& newSize) override; - void OnCommentFontReloadBegin(); - void OnCommentFontReloadEnd(); + void OnCommentFontReloadBegin() override; + void OnCommentFontReloadEnd() override; //// // QGraphicsItem diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupLayoutComponent.h index ec3bbdda28..5685702051 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Group/NodeGroupLayoutComponent.h @@ -61,13 +61,13 @@ namespace GraphCanvas //// // AZ::Component - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // NodeNotification - void OnNodeActivated(); + void OnNodeActivated() override; //// void UpdateLayoutParameters(); diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/NodeComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/NodeComponent.h index 996ba2e8c9..4e2052555f 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/NodeComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/NodeComponent.h @@ -109,7 +109,7 @@ namespace GraphCanvas void SetTranslationKeyedTooltip(const TranslationKeyedString& tooltip) override; const AZStd::string GetTooltip() const override { return m_configuration.GetTooltip(); } - void SetShowInOutliner(bool showInOutliner) { m_configuration.SetShowInOutliner(showInOutliner); } + void SetShowInOutliner(bool showInOutliner) override { m_configuration.SetShowInOutliner(showInOutliner); } bool ShowInOutliner() const override { return m_configuration.GetShowInOutliner(); } void AddSlot(const AZ::EntityId& slotId) override; diff --git a/Gems/GraphCanvas/Code/Source/Components/Nodes/Wrapper/WrapperNodeLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Nodes/Wrapper/WrapperNodeLayoutComponent.h index 4fa98dbadd..0423f061f6 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Nodes/Wrapper/WrapperNodeLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Nodes/Wrapper/WrapperNodeLayoutComponent.h @@ -155,9 +155,9 @@ namespace GraphCanvas required.push_back(AZ_CRC("GraphCanvas_StyledGraphicItemService", 0xeae4cdf4)); } - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // WrapperNodeRequestBus diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h index d6c6b71771..fb76c2c80e 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h @@ -29,9 +29,9 @@ namespace GraphCanvas ~DataSlotComponent(); // Component - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // SlotRequestBus diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Default/DefaultSlotLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Default/DefaultSlotLayoutComponent.h index 7d963af0bf..c1b6b5b0ac 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Default/DefaultSlotLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Default/DefaultSlotLayoutComponent.h @@ -43,7 +43,7 @@ namespace GraphCanvas //// // StyleNotificationBus - void OnStyleChanged(); + void OnStyleChanged() override; //// private: diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Execution/ExecutionSlotLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Execution/ExecutionSlotLayoutComponent.h index 812bef7187..5df2b9f68c 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Execution/ExecutionSlotLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Execution/ExecutionSlotLayoutComponent.h @@ -51,7 +51,7 @@ namespace GraphCanvas //// // StyleNotificationBus - void OnStyleChanged(); + void OnStyleChanged() override; //// private: @@ -88,9 +88,9 @@ namespace GraphCanvas ExecutionSlotLayoutComponent(); ~ExecutionSlotLayoutComponent() override = default; - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; private: ExecutionSlotLayout* m_layout; diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotComponent.h index 5ca93d5c26..b37704156d 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotComponent.h @@ -40,9 +40,9 @@ namespace GraphCanvas ~ExtenderSlotComponent(); // Component - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // SceneMemberNotifications diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotLayoutComponent.h index de8e95d7ff..ed477d40cf 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Extender/ExtenderSlotLayoutComponent.h @@ -53,7 +53,7 @@ namespace GraphCanvas //// // StyleNotificationBus - void OnStyleChanged(); + void OnStyleChanged() override; //// private: @@ -82,9 +82,9 @@ namespace GraphCanvas ExtenderSlotLayoutComponent(); ~ExtenderSlotLayoutComponent() override = default; - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; private: diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotComponent.h index 309e4bb762..65e537458b 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotComponent.h @@ -27,9 +27,9 @@ namespace GraphCanvas ~PropertySlotComponent(); // Component - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // Slot RequestBus @@ -38,7 +38,7 @@ namespace GraphCanvas //// // PropertySlotBus - const AZ::Crc32& GetPropertyId() const; + const AZ::Crc32& GetPropertyId() const override; //// private: diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotLayoutComponent.h index 9b63882ec8..0891f51f06 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Property/PropertySlotLayoutComponent.h @@ -49,7 +49,7 @@ namespace GraphCanvas // SlotNotificationBus void OnRegisteredToNode(const AZ::EntityId& nodeId) override; - void OnTooltipChanged(const TranslationKeyedString& tooltip); + void OnTooltipChanged(const TranslationKeyedString& tooltip) override; //// // StyleNotificationBus diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/SlotComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/SlotComponent.h index 319ffd7216..5afa3fbc14 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/SlotComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/SlotComponent.h @@ -72,7 +72,7 @@ namespace GraphCanvas const AZ::EntityId& GetNode() const override; void SetNode(const AZ::EntityId&) override; - Endpoint GetEndpoint() const; + Endpoint GetEndpoint() const override; const AZStd::string GetName() const override { return m_slotConfiguration.m_name.GetDisplayString(); } void SetName(const AZStd::string& name) override; diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutComponent.h index 87917cbe29..d73018f40b 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutComponent.h @@ -52,16 +52,16 @@ namespace GraphCanvas required.push_back(AZ_CRC("GraphCanvas_SlotService", 0x701eaf6b)); } - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // VisualRequestBus QGraphicsItem* AsGraphicsItem() override; QGraphicsLayoutItem* AsGraphicsLayoutItem() override; - bool Contains(const AZ::Vector2& position) const; + bool Contains(const AZ::Vector2& position) const override; void SetVisible(bool visible) override; bool IsVisible() const override; //// diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutItem.h b/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutItem.h index ee97284be8..98134a7362 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutItem.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/SlotLayoutItem.h @@ -38,7 +38,7 @@ namespace GraphCanvas protected: // QGraphicsItem - void mousePressEvent(QGraphicsSceneMouseEvent* event) + void mousePressEvent(QGraphicsSceneMouseEvent* event) override { bool result = false; VisualNotificationBus::EventResult(result, GetEntityId(), &VisualNotifications::OnMousePress, GetEntityId(), event); @@ -48,7 +48,7 @@ namespace GraphCanvas } } - void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) + void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override { bool result = false; VisualNotificationBus::EventResult(result, GetEntityId(), &VisualNotifications::OnMouseRelease, GetEntityId(), event); diff --git a/Gems/GraphCanvas/Code/Source/Widgets/NodePropertyDisplayWidget.h b/Gems/GraphCanvas/Code/Source/Widgets/NodePropertyDisplayWidget.h index dbd8a983cf..955ec490d6 100644 --- a/Gems/GraphCanvas/Code/Source/Widgets/NodePropertyDisplayWidget.h +++ b/Gems/GraphCanvas/Code/Source/Widgets/NodePropertyDisplayWidget.h @@ -45,7 +45,7 @@ namespace GraphCanvas //// // RootGraphicsItemNotificationBus - void OnDisplayStateChanged(RootGraphicsItemDisplayState oldState, RootGraphicsItemDisplayState newState); + void OnDisplayStateChanged(RootGraphicsItemDisplayState oldState, RootGraphicsItemDisplayState newState) override; //// // NodePropertiesRequestBus @@ -56,7 +56,7 @@ namespace GraphCanvas //// // NodePropertyRequestBus - void SetDisabled(bool disabled); + void SetDisabled(bool disabled) override; void SetNodePropertyDisplay(NodePropertyDisplay* nodePropertyDisplay) override; NodePropertyDisplay* GetNodePropertyDisplay() const override; diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/GraphCanvasPropertyBus.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/GraphCanvasPropertyBus.h index 6dda23692b..2a26fc3fe0 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/GraphCanvasPropertyBus.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/GraphCanvasPropertyBus.h @@ -57,12 +57,12 @@ namespace GraphCanvas GraphCanvasPropertyBus::MultiHandler::BusDisconnect(); } - void AddBusId(const AZ::EntityId& busId) override final + void AddBusId(const AZ::EntityId& busId) final { GraphCanvasPropertyBus::MultiHandler::BusConnect(busId); } - void RemoveBusId(const AZ::EntityId& busId) override final + void RemoveBusId(const AZ::EntityId& busId) final { GraphCanvasPropertyBus::MultiHandler::BusDisconnect(busId); } @@ -86,12 +86,12 @@ namespace GraphCanvas void Init() override {}; - void Activate() + void Activate() override { GraphCanvasPropertyBusHandler::OnActivate(GetEntityId()); } - void Deactivate() + void Deactivate() override { GraphCanvasPropertyBusHandler::OnDeactivate(); } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/GraphicsItems/GlowOutlineGraphicsItem.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/GraphicsItems/GlowOutlineGraphicsItem.h index d54c34f8f0..05302ee889 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/GraphicsItems/GlowOutlineGraphicsItem.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/GraphicsItems/GlowOutlineGraphicsItem.h @@ -77,7 +77,7 @@ namespace GraphCanvas //// // SystemTick - void OnSystemTick(); + void OnSystemTick() override; //// // TickBus @@ -86,7 +86,7 @@ namespace GraphCanvas // GeometryNotificationBus::Handler void OnPositionChanged(const AZ::EntityId& /*targetEntity*/, const AZ::Vector2& /*position*/) override; - void OnBoundsChanged(); + void OnBoundsChanged() override; //// // ViewNotificationBus diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h index 86b2cafdc9..1c65bf1915 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h @@ -37,7 +37,7 @@ namespace GraphCanvas return 0; } - bool Matches([[maybe_unused]] const AZ::EntityId& object) const + bool Matches([[maybe_unused]] const AZ::EntityId& object) const override { return false; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Style.cpp b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Style.cpp index 166a333d24..048bdf1736 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Style.cpp +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/Style.cpp @@ -129,7 +129,7 @@ namespace : public AZ::SerializeContext::IDataSerializer { /// Store the class data into a binary buffer - virtual size_t Save(const void* classPtr, AZ::IO::GenericStream& stream, bool isDataBigEndian /*= false*/) + size_t Save(const void* classPtr, AZ::IO::GenericStream& stream, bool isDataBigEndian /*= false*/) override { auto variant = reinterpret_cast(classPtr); @@ -142,7 +142,7 @@ namespace } /// Convert binary data to text - virtual size_t DataToText(AZ::IO::GenericStream& in, AZ::IO::GenericStream& out, bool isDataBigEndian /*= false*/) + size_t DataToText(AZ::IO::GenericStream& in, AZ::IO::GenericStream& out, bool isDataBigEndian /*= false*/) override { (void)isDataBigEndian; @@ -152,7 +152,7 @@ namespace } /// Convert text data to binary, to support loading old version formats. We must respect text version if the text->binary format has changed! - virtual size_t TextToData(const char* text, unsigned int textVersion, AZ::IO::GenericStream& stream, bool isDataBigEndian = false) + size_t TextToData(const char* text, unsigned int textVersion, AZ::IO::GenericStream& stream, bool isDataBigEndian = false) override { (void)textVersion; (void)isDataBigEndian; @@ -164,7 +164,7 @@ namespace } /// Load the class data from a stream. - virtual bool Load(void* classPtr, AZ::IO::GenericStream& in, unsigned int, bool isDataBigEndian = false) + bool Load(void* classPtr, AZ::IO::GenericStream& in, unsigned int, bool isDataBigEndian = false) override { QByteArray buffer = ReadAll(in); QDataStream qtStream(&buffer, QIODevice::ReadOnly); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Types/SceneMemberComponentSaveData.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Types/SceneMemberComponentSaveData.h index 4c07c82aef..b30857d71f 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Types/SceneMemberComponentSaveData.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Types/SceneMemberComponentSaveData.h @@ -43,7 +43,7 @@ namespace GraphCanvas } // SceneMemberNotificationBus::Handler - void OnSceneSet(const AZ::EntityId& graphId) + void OnSceneSet(const AZ::EntityId& graphId) override { const AZ::EntityId* ownerId = SceneMemberNotificationBus::GetCurrentBusId(); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/PrioritizedStateController.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/PrioritizedStateController.h index 1e31cc6c8a..583e755dfa 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/PrioritizedStateController.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/PrioritizedStateController.h @@ -45,7 +45,7 @@ namespace GraphCanvas m_valueSet.clear(); } - bool HasState() const + bool HasState() const override { return !m_valueSet.empty(); } @@ -85,7 +85,7 @@ namespace GraphCanvas return releasedValue; } - const T& GetCalculatedState() const + const T& GetCalculatedState() const override { auto valueIter = m_valueSet.begin(); return (*valueIter); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StackStateController.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StackStateController.h index d77cd43861..948e286f77 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StackStateController.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Utils/StateControllers/StackStateController.h @@ -43,7 +43,7 @@ namespace GraphCanvas m_states.clear(); } - bool HasState() const + bool HasState() const override { return !m_states.empty(); } @@ -79,7 +79,7 @@ namespace GraphCanvas return releasedValue; } - const T& GetCalculatedState() const + const T& GetCalculatedState() const override { return m_states.back().second; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkDockWidget.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkDockWidget.h index 0326a5e5a0..74207315e1 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkDockWidget.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkDockWidget.h @@ -57,7 +57,7 @@ namespace GraphCanvas //// // GraphCanvas::SceneNotifications - void OnSelectionChanged(); + void OnSelectionChanged() override; //// public Q_SLOTS: diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkTableModel.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkTableModel.h index 2e14011d47..a1c5e15a3b 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkTableModel.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/Bookmarks/BookmarkTableModel.h @@ -79,7 +79,7 @@ namespace GraphCanvas // QAbstractTableModel int rowCount(const QModelIndex& parent = QModelIndex()) const override; - int columnCount(const QModelIndex& index = QModelIndex()) const; + int columnCount(const QModelIndex& index = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; @@ -125,7 +125,7 @@ namespace GraphCanvas BookmarkTableSortProxyModel(BookmarkTableSourceModel* sourceModel); ~BookmarkTableSortProxyModel() override = default; - bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const; + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; void SetFilter(const QString& filter); void ClearFilter(); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h index 4eeb98b23a..1f78a109a9 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/ComboBox/ComboBoxItemModels.h @@ -415,7 +415,7 @@ namespace GraphCanvas return index(nextRow, GetSortColumn()); } - void OnDropDownAboutToShow() + void OnDropDownAboutToShow() override { beginResetModel(); setSourceModel(m_modelInterface->GetDropDownItemModel()); @@ -424,7 +424,7 @@ namespace GraphCanvas invalidate(); } - void OnDropDownHidden() + void OnDropDownHidden() override { beginResetModel(); setSourceModel(nullptr); diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasGraphicsView/GraphCanvasGraphicsView.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasGraphicsView/GraphCanvasGraphicsView.h index 7dd8a01dc3..70b3e16166 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasGraphicsView/GraphCanvasGraphicsView.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/GraphCanvasGraphicsView/GraphCanvasGraphicsView.h @@ -129,7 +129,7 @@ namespace GraphCanvas ToastId ShowToastAtCursor(const ToastConfiguration& toastConfiguration) override; ToastId ShowToastAtPoint(const QPoint& screenPosition, const QPointF& anchorPoint, const ToastConfiguration& toastConfiguration) override; - bool IsShowing() const; + bool IsShowing() const override; //// // TickBus @@ -159,7 +159,7 @@ namespace GraphCanvas void wheelEvent(QWheelEvent* event) override; - void focusOutEvent(QFocusEvent* event); + void focusOutEvent(QFocusEvent* event) override; void resizeEvent(QResizeEvent* event) override; void moveEvent(QMoveEvent* event) override; diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/IconDecoratedNodePaletteTreeItem.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/IconDecoratedNodePaletteTreeItem.h index b214f00416..cfb4fe477a 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/IconDecoratedNodePaletteTreeItem.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/IconDecoratedNodePaletteTreeItem.h @@ -27,8 +27,8 @@ namespace GraphCanvas void AddIconColorPalette(const AZStd::string& colorPalette); - void OnStylesUnloaded(); - void OnStylesLoaded(); + void OnStylesUnloaded() override; + void OnStylesLoaded() override; protected: diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h index fdeb20dadf..fcb4d79077 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/NodePalette/TreeItems/NodePaletteTreeItem.h @@ -95,7 +95,7 @@ namespace GraphCanvas const EditorId& GetEditorId() const; // Child Overrides - virtual bool LessThan(const GraphCanvasTreeItem* graphItem) const; + bool LessThan(const GraphCanvasTreeItem* graphItem) const override; virtual QVariant OnData(const QModelIndex& index, int role) const; virtual Qt::ItemFlags OnFlags() const; From 32b4958778cdd4d372b9c351712600ecdc3c1f03 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:19:32 -0700 Subject: [PATCH 059/274] Code/Framework/AzToolsFramework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Core/EditorFrameworkApplication.h | 38 +++++++++---------- .../UI/Outliner/EntityOutlinerListModel.hxx | 2 +- .../PropertyEditor/EntityPropertyEditor.hxx | 8 ++-- .../PropertyEditor/MultiLineTextEditHandler.h | 2 +- .../UI/PropertyEditor/PropertyEditorAPI.h | 4 +- .../ViewportUi/ViewportUiManager.h | 2 +- .../SliceStabilityTestFramework.h | 2 +- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.h index bcd9d23203..99235c420c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.h @@ -63,23 +63,23 @@ namespace LegacyFramework // ------------------------------------------------------------------ // implementation of FrameworkApplicationMessages::Handler - virtual bool IsRunningInGUIMode() { return m_desc.m_enableGUI; } - virtual bool RequiresGameProject() { return m_desc.m_enableProjectManager; } - virtual bool ShouldRunAssetProcessor() { return m_desc.m_shouldRunAssetProcessor; } - virtual void* GetMainModule(); - virtual const char* GetApplicationName(); - virtual const char* GetApplicationModule(); - virtual const char* GetApplicationDirectory(); - virtual const AzFramework::CommandLine* GetCommandLineParser(); - virtual void TeardownApplicationComponent(); - virtual void RunAssetProcessor() override; + bool IsRunningInGUIMode() override { return m_desc.m_enableGUI; } + bool RequiresGameProject() override { return m_desc.m_enableProjectManager; } + bool ShouldRunAssetProcessor() override { return m_desc.m_shouldRunAssetProcessor; } + void* GetMainModule() override; + const char* GetApplicationName() override; + const char* GetApplicationModule() override; + const char* GetApplicationDirectory() override; + const AzFramework::CommandLine* GetCommandLineParser() override; + void TeardownApplicationComponent() override; + void RunAssetProcessor() override; // ------------------------------------------------------------------ void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override; // ------------------------------------------------------------------ // implementation of CoreMessageBus::Handler - virtual void OnProjectSet(const char* /*pathToProject*/); + void OnProjectSet(const char* /*pathToProject*/) override; // ------------------------------------------------------------------ // This is called during the bootstrap and makes all the components we should have for SYSTEM minimal functionality. @@ -114,17 +114,17 @@ namespace LegacyFramework * ComponentApplication::RegisterCoreComponents and then register the application * specific core components. */ - virtual void RegisterCoreComponents(); + void RegisterCoreComponents() override; AZ::Entity* m_ptrSystemEntity; - virtual int GetDesiredExitCode() override { return m_desiredExitCode; } - virtual void SetDesiredExitCode(int code) override { m_desiredExitCode = code; } - virtual bool GetAbortRequested() override { return m_abortRequested; } - virtual void SetAbortRequested() override { m_abortRequested = true; } - virtual AZStd::string GetApplicationGlobalStoragePath() override; - virtual bool IsPrimary() override { return m_isPrimary; } + int GetDesiredExitCode() override { return m_desiredExitCode; } + void SetDesiredExitCode(int code) override { m_desiredExitCode = code; } + bool GetAbortRequested() override { return m_abortRequested; } + void SetAbortRequested() override { m_abortRequested = true; } + AZStd::string GetApplicationGlobalStoragePath() override; + bool IsPrimary() override { return m_isPrimary; } - virtual bool IsAppConfigWritable() override; + bool IsAppConfigWritable() override; AZ::Entity* m_applicationEntity; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx index a6ac859971..25e4276dd4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.hxx @@ -230,7 +230,7 @@ namespace AzToolsFramework bool DropMimeDataAssets(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); bool CanDropMimeDataAssets(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const; - QMap itemData(const QModelIndex& index) const; + QMap itemData(const QModelIndex& index) const override; QVariant dataForAll(const QModelIndex& index, int role) const; QVariant dataForName(const QModelIndex& index, int role) const; QVariant dataForVisibility(const QModelIndex& index, int role) const; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index 3ff69f80e0..83b275b81a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -139,8 +139,8 @@ namespace AzToolsFramework EntityPropertyEditor(QWidget* pParent = NULL, Qt::WindowFlags flags = Qt::WindowFlags(), bool isLevelEntityEditor = false); virtual ~EntityPropertyEditor(); - virtual void BeforeUndoRedo(); - virtual void AfterUndoRedo(); + void BeforeUndoRedo() override; + void AfterUndoRedo() override; static void Reflect(AZ::ReflectContext* context); @@ -249,8 +249,8 @@ namespace AzToolsFramework bool IsEntitySelected(const AZ::EntityId& id) const; bool IsSingleEntitySelected(const AZ::EntityId& id) const; - virtual void GotSceneSourceControlStatus(AzToolsFramework::SourceControlFileInfo& fileInfo); - virtual void PerformActionsBasedOnSceneStatus(bool sceneIsNew, bool readOnly); + void GotSceneSourceControlStatus(AzToolsFramework::SourceControlFileInfo& fileInfo) override; + void PerformActionsBasedOnSceneStatus(bool sceneIsNew, bool readOnly) override; // enable/disable editor void EnableEditor(bool enabled); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/MultiLineTextEditHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/MultiLineTextEditHandler.h index 88a3d89f9f..c4a8980d29 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/MultiLineTextEditHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/MultiLineTextEditHandler.h @@ -41,7 +41,7 @@ namespace AzToolsFramework QWidget* CreateGUI(QWidget* parent) override; AZ::u32 GetHandlerName() const override; - bool AutoDelete() const; + bool AutoDelete() const override; void ConsumeAttribute(GrowTextEdit* widget, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; void WriteGUIValuesIntoProperty(size_t index, GrowTextEdit* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h index 6d3ccd45bd..f5529eec15 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h @@ -130,8 +130,8 @@ namespace AzToolsFramework } QWidget* GetFirstInTabOrder(WidgetType* widget) override { return widget; } - virtual QWidget* GetLastInTabOrder(WidgetType* widget) { return widget; } - virtual void UpdateWidgetInternalTabbing(WidgetType* /*widget*/) { } + QWidget* GetLastInTabOrder(WidgetType* widget) override { return widget; } + void UpdateWidgetInternalTabbing(WidgetType* /*widget*/) override {} QWidget* CreateGUI(QWidget *pParent) override = 0; protected: diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h index 137ee7b2c0..c5ecf7aee6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h @@ -40,7 +40,7 @@ namespace AzToolsFramework::ViewportUi void RegisterSwitcherEventHandler(SwitcherId switcherId, AZ::Event::Handler& handler) override; void RemoveCluster(ClusterId clusterId) override; void RemoveSwitcher(SwitcherId switcherId) override; - void SetClusterVisible(ClusterId clusterId, bool visible); + void SetClusterVisible(ClusterId clusterId, bool visible) override; void SetSwitcherVisible(SwitcherId switcherId, bool visible); void SetClusterGroupVisible(const AZStd::vector& clusterGroup, bool visible) override; const TextFieldId CreateTextField( diff --git a/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h b/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h index 64dd8636a7..93e86374db 100644 --- a/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h +++ b/Code/Framework/AzToolsFramework/Tests/SliceStabilityTests/SliceStabilityTestFramework.h @@ -137,7 +137,7 @@ namespace UnitTest void CreateEditorRepresentation(AZ::Entity* entity) override; void BrowseForAssets(AzToolsFramework::AssetBrowser::AssetSelectionModel& selection) override { AZ_UNUSED(selection); } int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override { AZ_UNUSED(entityIconPath); return 0; } - bool DisplayHelpersVisible() { return false; } + bool DisplayHelpersVisible() override { return false; } /* * AssetSystemRequestBus From 287d2a0fe74d972604a7e3cc4b76229ac8b3979b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:19:52 -0700 Subject: [PATCH 060/274] Code/Framework/AzManipulatorTestFramework Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Include/AzManipulatorTestFramework/ViewportInteraction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h index 8b6ea5c59b..1bc329d404 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h @@ -40,7 +40,7 @@ namespace AzManipulatorTestFramework // ViewportInteractionRequestBus overrides ... AzFramework::CameraState GetCameraState() override; - AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition); + AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) override; AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override; AZStd::optional ViewportScreenToWorldRay( const AzFramework::ScreenPoint& screenPosition) override; From d046389a30ab9696428dc56eb8b9922bbc6ed66a Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:20:14 -0700 Subject: [PATCH 061/274] Code/Tools/AssetProcessor Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Tools/AssetProcessor/AssetBuilder/TraceMessageHook.h | 4 ++-- .../AssetProcessor/native/AssetManager/AssetCatalog.h | 8 ++++---- .../native/resourcecompiler/rcjoblistmodel.h | 2 +- .../assetBuilderSDK/SerializationDependenciesTests.cpp | 2 +- .../native/unittests/AssetRequestHandlerUnitTests.cpp | 4 ++-- .../native/unittests/UtilitiesUnitTests.cpp | 2 +- .../native/utilities/ApplicationManagerBase.h | 2 +- .../AssetProcessor/native/utilities/AssetServerHandler.h | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Code/Tools/AssetProcessor/AssetBuilder/TraceMessageHook.h b/Code/Tools/AssetProcessor/AssetBuilder/TraceMessageHook.h index 7774816cb2..dcb186b81a 100644 --- a/Code/Tools/AssetProcessor/AssetBuilder/TraceMessageHook.h +++ b/Code/Tools/AssetProcessor/AssetBuilder/TraceMessageHook.h @@ -26,8 +26,8 @@ namespace AssetBuilder void EnableDebugMode(bool enable); bool OnAssert(const char* message) override; - bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message); - bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message); + bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; bool OnException(const char* message) override; bool OnPrintf(const char* window, const char* message) override; bool OnOutput(const char* window, const char* message) override; diff --git a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h index 6d25b654c5..84e96bcf3e 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.h @@ -122,8 +122,8 @@ namespace AssetProcessor ////////////////////////////////////////////////////////////////////////// // AzToolsFramework::ToolsAssetSystemBus::Handler - void RegisterSourceAssetType(const AZ::Data::AssetType& assetType, const char* assetFileFilter); - void UnregisterSourceAssetType(const AZ::Data::AssetType& assetType); + void RegisterSourceAssetType(const AZ::Data::AssetType& assetType, const char* assetFileFilter) override; + void UnregisterSourceAssetType(const AZ::Data::AssetType& assetType) override; ////////////////////////////////////////////////////////////////////////// //! given some absolute path, please respond with its relative product path. For now, this will be a @@ -163,9 +163,9 @@ namespace AssetProcessor AZ::Outcome, AZStd::string> GetAllProductDependenciesFilter( const AZ::Data::AssetId& id, const AZStd::unordered_set& exclusionList, - const AZStd::vector& wildcardPatternExclusionList); + const AZStd::vector& wildcardPatternExclusionList) override; - bool DoesAssetIdMatchWildcardPattern(const AZ::Data::AssetId& assetId, const AZStd::string& wildcardPattern); + bool DoesAssetIdMatchWildcardPattern(const AZ::Data::AssetId& assetId, const AZStd::string& wildcardPattern) override; void AddAssetDependencies( const AZ::Data::AssetId& searchAssetId, diff --git a/Code/Tools/AssetProcessor/native/resourcecompiler/rcjoblistmodel.h b/Code/Tools/AssetProcessor/native/resourcecompiler/rcjoblistmodel.h index 97a59c90ea..5c055087a8 100644 --- a/Code/Tools/AssetProcessor/native/resourcecompiler/rcjoblistmodel.h +++ b/Code/Tools/AssetProcessor/native/resourcecompiler/rcjoblistmodel.h @@ -67,7 +67,7 @@ namespace AssetProcessor int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - QVariant data(const QModelIndex& index, int role) const; + QVariant data(const QModelIndex& index, int role) const override; void markAsProcessing(RCJob* rcJob); void markAsStarted(RCJob* rcJob); diff --git a/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/SerializationDependenciesTests.cpp b/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/SerializationDependenciesTests.cpp index cb7b1b5c4d..86c363075d 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/SerializationDependenciesTests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetBuilderSDK/SerializationDependenciesTests.cpp @@ -95,7 +95,7 @@ namespace SerializationDependencyTests // Use an arbitrary ID for the asset type. return AZ::Data::AssetType("{03FD33E2-DA2F-4021-A266-0DC9714FF84D}"); } - virtual const char* GetFileFilter() const + const char* GetFileFilter() const override { return nullptr; } diff --git a/Code/Tools/AssetProcessor/native/unittests/AssetRequestHandlerUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/AssetRequestHandlerUnitTests.cpp index 010d1cc069..8b0ee56c32 100644 --- a/Code/Tools/AssetProcessor/native/unittests/AssetRequestHandlerUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/AssetRequestHandlerUnitTests.cpp @@ -49,13 +49,13 @@ namespace bool m_deleteFenceFileResult = false; protected: - virtual QString CreateFenceFile(unsigned int fenceId) + QString CreateFenceFile(unsigned int fenceId) override { m_numTimesCreateFenceFileCalled++; m_fenceId = fenceId; return m_fenceFileName; } - virtual bool DeleteFenceFile(QString fenceFileName) + bool DeleteFenceFile(QString fenceFileName) override { m_numTimesDeleteFenceFileCalled++; return m_deleteFenceFileResult; diff --git a/Code/Tools/AssetProcessor/native/unittests/UtilitiesUnitTests.cpp b/Code/Tools/AssetProcessor/native/unittests/UtilitiesUnitTests.cpp index bbeafda342..9f2d855811 100644 --- a/Code/Tools/AssetProcessor/native/unittests/UtilitiesUnitTests.cpp +++ b/Code/Tools/AssetProcessor/native/unittests/UtilitiesUnitTests.cpp @@ -543,7 +543,7 @@ public: Q_EMIT UnitTestPassed(); } - bool OnPreAssert(const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + bool OnPreAssert(const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override { m_assertTriggered = true; return true; diff --git a/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h b/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h index 7e6347b4d1..886880df3a 100644 --- a/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h +++ b/Code/Tools/AssetProcessor/native/utilities/ApplicationManagerBase.h @@ -114,7 +114,7 @@ public: void Rescan(); - bool IsAssetProcessorManagerIdle() const; + bool IsAssetProcessorManagerIdle() const override; bool CheckFullIdle(); Q_SIGNALS: void CheckAssetProcessorManagerIdleState(); diff --git a/Code/Tools/AssetProcessor/native/utilities/AssetServerHandler.h b/Code/Tools/AssetProcessor/native/utilities/AssetServerHandler.h index 840c3e6f5b..04f00e6dff 100644 --- a/Code/Tools/AssetProcessor/native/utilities/AssetServerHandler.h +++ b/Code/Tools/AssetProcessor/native/utilities/AssetServerHandler.h @@ -22,7 +22,7 @@ namespace AssetProcessor virtual ~AssetServerHandler(); ////////////////////////////////////////////////////////////////////////// // AssetServerBus::Handler overrides - bool IsServerAddressValid(); + bool IsServerAddressValid() override; //! StoreJobResult will store all the files in the the temp folder provided by AP to a zip file on the network drive //! whose file name will be based on the server key bool StoreJobResult(const AssetProcessor::BuilderParams& builderParams, AZStd::vector& sourceFileList) override; From 8f0f462f077becb521b47f81368b804ccab70d13 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:20:34 -0700 Subject: [PATCH 062/274] Code/Tools/SceneAPI Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../SceneAPI/SceneCore/Tests/Containers/SceneGraphTests.cpp | 2 +- Code/Tools/SceneAPI/SceneData/Groups/AnimationGroup.h | 2 +- Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.h | 4 ++-- Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.h | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneGraphTests.cpp b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneGraphTests.cpp index 87e2cbdbde..f51304c000 100644 --- a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneGraphTests.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneGraphTests.cpp @@ -108,7 +108,7 @@ namespace AZ BusDisconnect(); } - bool OnPreAssert(const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + bool OnPreAssert(const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override { m_assertTriggered = true; return true; diff --git a/Code/Tools/SceneAPI/SceneData/Groups/AnimationGroup.h b/Code/Tools/SceneAPI/SceneData/Groups/AnimationGroup.h index c26dc7563e..f5d9239865 100644 --- a/Code/Tools/SceneAPI/SceneData/Groups/AnimationGroup.h +++ b/Code/Tools/SceneAPI/SceneData/Groups/AnimationGroup.h @@ -38,7 +38,7 @@ namespace AZ void OverrideId(const Uuid& id); Containers::RuleContainer& GetRuleContainer() override; - const Containers::RuleContainer& GetRuleContainerConst() const; + const Containers::RuleContainer& GetRuleContainerConst() const override; const AZStd::string& GetSelectedRootBone() const override; uint32_t GetStartFrame() const override; diff --git a/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.h b/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.h index 7c6ed2dc57..3318f89b8d 100644 --- a/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.h +++ b/Code/Tools/SceneAPI/SceneData/Groups/SkeletonGroup.h @@ -39,8 +39,8 @@ namespace AZ const Uuid& GetId() const override; void OverrideId(const Uuid& id); - Containers::RuleContainer& GetRuleContainer(); - const Containers::RuleContainer& GetRuleContainerConst() const; + Containers::RuleContainer& GetRuleContainer() override; + const Containers::RuleContainer& GetRuleContainerConst() const override; const AZStd::string& GetSelectedRootBone() const override; void SetSelectedRootBone(const AZStd::string& selectedRootBone) override; diff --git a/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.h b/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.h index 6708654463..010091e3eb 100644 --- a/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.h +++ b/Code/Tools/SceneAPI/SceneData/Groups/SkinGroup.h @@ -46,8 +46,8 @@ namespace AZ const Uuid& GetId() const override; void OverrideId(const Uuid& id); - Containers::RuleContainer& GetRuleContainer(); - const Containers::RuleContainer& GetRuleContainerConst() const; + Containers::RuleContainer& GetRuleContainer() override; + const Containers::RuleContainer& GetRuleContainerConst() const override; DataTypes::ISceneNodeSelectionList& GetSceneNodeSelectionList() override; const DataTypes::ISceneNodeSelectionList& GetSceneNodeSelectionList() const override; From c7a234473853878896f72e92415cc65eb83d0f95 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:21:01 -0700 Subject: [PATCH 063/274] Code/Tools/DeltaCataloger Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Tools/DeltaCataloger/Tests/tests_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/DeltaCataloger/Tests/tests_main.cpp b/Code/Tools/DeltaCataloger/Tests/tests_main.cpp index 34dd6dbddb..1a3b86d34b 100644 --- a/Code/Tools/DeltaCataloger/Tests/tests_main.cpp +++ b/Code/Tools/DeltaCataloger/Tests/tests_main.cpp @@ -84,7 +84,7 @@ protected: } - bool OnPreError([[maybe_unused]] const char* window, [[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) + bool OnPreError([[maybe_unused]] const char* window, [[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override { return true; } From a55dfece641b020a067737d9a643e03df6f55b0c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:21:16 -0700 Subject: [PATCH 064/274] Gems/GraphModel Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Include/GraphModel/Integration/GraphController.h | 6 +++--- Gems/GraphModel/Code/Tests/MockGraphCanvas.h | 6 +++--- Gems/GraphModel/Code/Tests/TestEnvironment.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gems/GraphModel/Code/Include/GraphModel/Integration/GraphController.h b/Gems/GraphModel/Code/Include/GraphModel/Integration/GraphController.h index a8051e16e4..3705b91b15 100644 --- a/Gems/GraphModel/Code/Include/GraphModel/Integration/GraphController.h +++ b/Gems/GraphModel/Code/Include/GraphModel/Integration/GraphController.h @@ -78,8 +78,8 @@ namespace GraphModelIntegration GraphModel::NodePtrList GetSelectedNodes() override; void SetSelected(GraphModel::NodePtrList nodes, bool selected) override; void ClearSelection() override; - void EnableNode(GraphModel::NodePtr node); - void DisableNode(GraphModel::NodePtr node); + void EnableNode(GraphModel::NodePtr node) override; + void DisableNode(GraphModel::NodePtr node) override; void CenterOnNodes(GraphModel::NodePtrList nodes) override; AZ::Vector2 GetMajorPitch() const override; @@ -166,7 +166,7 @@ namespace GraphModelIntegration void EnableNodes(const AZStd::unordered_set& nodeIds) override; void DisableNodes(const AZStd::unordered_set& nodeIds) override; - AZStd::string GetDataTypeString(const AZ::Uuid& typeId); + AZStd::string GetDataTypeString(const AZ::Uuid& typeId) override; //! This is where we find all of the graph metadata (like node positions, comments, etc) and store it in the node graph for serialization // CJS TODO: Use this instead of the above undo functions diff --git a/Gems/GraphModel/Code/Tests/MockGraphCanvas.h b/Gems/GraphModel/Code/Tests/MockGraphCanvas.h index e66a47a79c..774e6aab9f 100644 --- a/Gems/GraphModel/Code/Tests/MockGraphCanvas.h +++ b/Gems/GraphModel/Code/Tests/MockGraphCanvas.h @@ -137,8 +137,8 @@ namespace MockGraphCanvasServices ~MockExtenderSlotComponent() = default; // Component overrides ... - void Activate(); - void Deactivate(); + void Activate() override; + void Deactivate() override; //// // ExtenderSlotComponent overrides ... @@ -177,7 +177,7 @@ namespace MockGraphCanvasServices void SetTooltip(const AZStd::string& tooltip) override; void SetTranslationKeyedTooltip(const GraphCanvas::TranslationKeyedString& tooltip) override; const AZStd::string GetTooltip() const override; - void SetShowInOutliner(bool showInOutliner); + void SetShowInOutliner(bool showInOutliner) override; bool ShowInOutliner() const override; void AddSlot(const AZ::EntityId& slotId) override; void RemoveSlot(const AZ::EntityId& slotId) override; diff --git a/Gems/GraphModel/Code/Tests/TestEnvironment.h b/Gems/GraphModel/Code/Tests/TestEnvironment.h index 908a4990e1..a9b2a548f4 100644 --- a/Gems/GraphModel/Code/Tests/TestEnvironment.h +++ b/Gems/GraphModel/Code/Tests/TestEnvironment.h @@ -87,7 +87,7 @@ namespace GraphModelIntegrationTest const char* GetTitle() const override; protected: - void RegisterSlots(); + void RegisterSlots() override; AZStd::shared_ptr m_graphContext = nullptr; }; @@ -108,7 +108,7 @@ namespace GraphModelIntegrationTest const char* GetTitle() const override; protected: - void RegisterSlots(); + void RegisterSlots() override; AZStd::shared_ptr m_graphContext = nullptr; }; @@ -129,7 +129,7 @@ namespace GraphModelIntegrationTest const char* GetTitle() const override; protected: - void RegisterSlots(); + void RegisterSlots() override; AZStd::shared_ptr m_graphContext = nullptr; }; From d92dd162d049af6d3a21b72b5362bc78a7c2dff5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:21:32 -0700 Subject: [PATCH 065/274] Gems/ImGui Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/ImGui/Code/Source/ImGuiManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/ImGui/Code/Source/ImGuiManager.h b/Gems/ImGui/Code/Source/ImGuiManager.h index 52862205a5..c4fa5169f7 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.h +++ b/Gems/ImGui/Code/Source/ImGuiManager.h @@ -48,8 +48,8 @@ namespace ImGui void SetClientMenuBarState(DisplayState state) override { m_clientMenuBarState = state; } bool IsControllerSupportModeEnabled(ImGuiControllerModeFlags::FlagType controllerMode) const override; void EnableControllerSupportMode(ImGuiControllerModeFlags::FlagType controllerMode, bool enable) override; - void SetControllerMouseSensitivity(float sensitivity) { m_controllerMouseSensitivity = sensitivity; } - float GetControllerMouseSensitivity() const { return m_controllerMouseSensitivity; } + void SetControllerMouseSensitivity(float sensitivity) override { m_controllerMouseSensitivity = sensitivity; } + float GetControllerMouseSensitivity() const override { return m_controllerMouseSensitivity; } bool GetEnableDiscreteInputMode() const override { return m_enableDiscreteInputMode; } void SetEnableDiscreteInputMode(bool enabled) override { m_enableDiscreteInputMode = enabled; } ImGuiResolutionMode GetResolutionMode() const override { return m_resolutionMode; } From a9a295275098651a56a2ff7cbbcd9b337554960c Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:21:46 -0700 Subject: [PATCH 066/274] Gems/LmbrCentral Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Ai/NavigationComponent.h | 8 ++++---- .../Source/Audio/AudioSystemComponent.cpp | 4 ++-- .../EditorRandomTimedSpawnerComponent.h | 2 +- .../Source/Scripting/SimpleStateComponent.cpp | 2 +- .../Builders/CopyDependencyBuilderTest.cpp | 20 +++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.h b/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.h index 17a5183dfe..3c6ce745ca 100644 --- a/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.h +++ b/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.h @@ -168,9 +168,9 @@ namespace LmbrCentral { public: - bool IsPathIntersectingObstacles(const NavigationMeshID /*meshID*/, const Vec3& /*start*/, const Vec3& /*end*/, float /*radius*/) const { return false; } - bool IsPointInsideObstacles(const Vec3& /*position*/) const { return false; } - bool IsLineSegmentIntersectingObstaclesOrCloseToThem(const Lineseg& /*linesegToTest*/, float /*maxDistanceToConsiderClose*/) const { return false; } + bool IsPathIntersectingObstacles(const NavigationMeshID /*meshID*/, const Vec3& /*start*/, const Vec3& /*end*/, float /*radius*/) const override { return false; } + bool IsPointInsideObstacles(const Vec3& /*position*/) const override { return false; } + bool IsLineSegmentIntersectingObstaclesOrCloseToThem(const Lineseg& /*linesegToTest*/, float /*maxDistanceToConsiderClose*/) const override { return false; } }; NullPathObstacles m_pathObstacles; @@ -344,7 +344,7 @@ namespace LmbrCentral bool GetValidPositionNearby(const Vec3&, Vec3&) const override { return false; } bool GetTeleportPosition(Vec3&) const override { return false; } class IPathFollower* GetPathFollower() const override { return nullptr; } - bool IsPointValidForAgent(const Vec3&, AZ::u32) const { return true; }; + bool IsPointValidForAgent(const Vec3&, AZ::u32) const override { return true; }; //// ~IAIPathAgent }; } // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Audio/AudioSystemComponent.cpp b/Gems/LmbrCentral/Code/Source/Audio/AudioSystemComponent.cpp index cd4cff09ae..0c3531902f 100644 --- a/Gems/LmbrCentral/Code/Source/Audio/AudioSystemComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Audio/AudioSystemComponent.cpp @@ -35,12 +35,12 @@ namespace LmbrCentral OnGameUnpaused ); - void OnGamePaused() + void OnGamePaused() override { Call(FN_OnGamePaused); } - void OnGameUnpaused() + void OnGameUnpaused() override { Call(FN_OnGameUnpaused); } diff --git a/Gems/LmbrCentral/Code/Source/Scripting/EditorRandomTimedSpawnerComponent.h b/Gems/LmbrCentral/Code/Source/Scripting/EditorRandomTimedSpawnerComponent.h index d55463abd8..cc8a1a3a9e 100644 --- a/Gems/LmbrCentral/Code/Source/Scripting/EditorRandomTimedSpawnerComponent.h +++ b/Gems/LmbrCentral/Code/Source/Scripting/EditorRandomTimedSpawnerComponent.h @@ -57,7 +57,7 @@ namespace LmbrCentral void SetSpawnDelayVariation(double spawnDelayVariation) override { m_config.m_spawnDelayVariation = spawnDelayVariation; } double GetSpawnDelayVariation() override { return m_config.m_spawnDelayVariation; } - void BuildGameEntity(AZ::Entity* gameEntity); + void BuildGameEntity(AZ::Entity* gameEntity) override; private: //Reflected members diff --git a/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp b/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp index ad60e86834..e278f18e8b 100644 --- a/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp @@ -29,7 +29,7 @@ namespace LmbrCentral AZ_EBUS_BEHAVIOR_BINDER(BehaviorSimpleStateComponentNotificationBusHandler, "{F935125C-AE4E-48C1-BB60-24A0559BC4D2}", AZ::SystemAllocator, OnStateChanged); - void OnStateChanged(const char* oldState, const char* newState) + void OnStateChanged(const char* oldState, const char* newState) override { Call(FN_OnStateChanged, oldState, newState); } diff --git a/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp b/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp index 08eb7df669..65847a7fef 100644 --- a/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/Builders/CopyDependencyBuilderTest.cpp @@ -213,18 +213,18 @@ namespace UnitTest // AzToolsFramework::AssetSystem::AssetSystemRequestBus::Handler overrides const char* GetAbsoluteDevGameFolderPath() override { return ""; } const char* GetAbsoluteDevRootFolderPath() override { return ""; } - bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) { return true; } + bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) override { return true; } bool GenerateRelativeSourcePath( [[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath, - [[maybe_unused]] AZStd::string& watchFolder) { return true; } - bool GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) { return true; } - bool GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType, [[maybe_unused]] const AZStd::string& platformName, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& rootFilePath) { return true; } - bool GetSourceInfoBySourcePath([[maybe_unused]] const char* sourcePath, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } - bool GetSourceInfoBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) { return true; } - bool GetScanFolders([[maybe_unused]] AZStd::vector& scanFolders) { return true; } - bool IsAssetPlatformEnabled([[maybe_unused]] const char* platform) { return true; } - int GetPendingAssetsForPlatform([[maybe_unused]] const char* platform) { return 0; } - bool GetAssetsProducedBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZStd::vector& productsAssetInfo) { return true; } + [[maybe_unused]] AZStd::string& watchFolder) override { return true; } + bool GetFullSourcePathFromRelativeProductPath([[maybe_unused]] const AZStd::string& relPath, [[maybe_unused]] AZStd::string& fullSourcePath) override { return true; } + bool GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& assetId, [[maybe_unused]] const AZ::Data::AssetType& assetType, [[maybe_unused]] const AZStd::string& platformName, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& rootFilePath) override { return true; } + bool GetSourceInfoBySourcePath([[maybe_unused]] const char* sourcePath, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) override { return true; } + bool GetSourceInfoBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZ::Data::AssetInfo& assetInfo, [[maybe_unused]] AZStd::string& watchFolder) override { return true; } + bool GetScanFolders([[maybe_unused]] AZStd::vector& scanFolders) override { return true; } + bool IsAssetPlatformEnabled([[maybe_unused]] const char* platform) override { return true; } + int GetPendingAssetsForPlatform([[maybe_unused]] const char* platform) override { return 0; } + bool GetAssetsProducedBySourceUUID([[maybe_unused]] const AZ::Uuid& sourceUuid, [[maybe_unused]] AZStd::vector& productsAssetInfo) override { return true; } bool GetAssetSafeFolders(AZStd::vector& assetSafeFolders) override { char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; From 6e51bbcd53844894c2504d3eb73d199e2298b9c5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:22:04 -0700 Subject: [PATCH 067/274] Gems/LyShine Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Editor/Animation/AnimationContext.h | 8 +- .../Animation/Controls/UiSplineCtrlEx.h | 4 +- .../Animation/Controls/UiTimelineCtrl.h | 4 +- .../Animation/UiAVTrackEventKeyUIControls.h | 4 +- .../Editor/Animation/UiAnimViewCurveEditor.h | 8 +- .../Code/Editor/Animation/UiAnimViewDialog.h | 10 +- .../Animation/UiAnimViewDopeSheetBase.h | 2 +- .../Editor/Animation/UiAnimViewSequence.h | 10 +- .../Animation/UiAnimViewSequenceManager.h | 2 +- .../Editor/Animation/UiAnimViewSplineCtrl.h | 4 +- Gems/LyShine/Code/Source/Animation/AnimNode.h | 40 +++--- .../Code/Source/Animation/AnimSequence.h | 106 +++++++------- .../Code/Source/Animation/AnimSplineTrack.h | 118 +++++++-------- .../LyShine/Code/Source/Animation/AnimTrack.h | 116 +++++++-------- .../Code/Source/Animation/AzEntityNode.h | 42 +++--- .../Source/Animation/CompoundSplineTrack.h | 136 +++++++++--------- .../Code/Source/Animation/TrackEventTrack.h | 6 +- .../Code/Source/Animation/UiAnimationSystem.h | 116 +++++++-------- .../Code/Source/LyShineSystemComponent.h | 4 +- .../Code/Source/UiLayoutFitterComponent.h | 2 +- .../Code/Source/UiScrollBarComponent.h | 2 +- .../Code/Source/UiTooltipDisplayComponent.h | 2 +- 22 files changed, 373 insertions(+), 373 deletions(-) diff --git a/Gems/LyShine/Code/Editor/Animation/AnimationContext.h b/Gems/LyShine/Code/Editor/Animation/AnimationContext.h index 9534902f99..cb45fb9653 100644 --- a/Gems/LyShine/Code/Editor/Animation/AnimationContext.h +++ b/Gems/LyShine/Code/Editor/Animation/AnimationContext.h @@ -167,12 +167,12 @@ public: void UpdateTimeRange(); private: - virtual void BeginUndoTransaction() override; - virtual void EndUndoTransaction() override; + void BeginUndoTransaction() override; + void EndUndoTransaction() override; - virtual void OnSequenceRemoved(CUiAnimViewSequence* pSequence) override; + void OnSequenceRemoved(CUiAnimViewSequence* pSequence) override; - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; void AnimateActiveSequence(); diff --git a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h index 1bbcf8eea7..05b86bd380 100644 --- a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h +++ b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.h @@ -345,8 +345,8 @@ public: SplineWidget(QWidget* parent); virtual ~SplineWidget(); - void update() { QWidget::update(); } - void update(const QRect& rect) { QWidget::update(rect); } + void update() override { QWidget::update(); } + void update(const QRect& rect) override { QWidget::update(rect); } QPoint mapFromGlobal(const QPoint& point) const override { return QWidget::mapFromGlobal(point); } diff --git a/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.h b/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.h index 701d187ddc..ed0d8ce02d 100644 --- a/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.h +++ b/Gems/LyShine/Code/Editor/Animation/Controls/UiTimelineCtrl.h @@ -54,7 +54,7 @@ public: void setGeometry(const QRect& r) override { QWidget::setGeometry(r); } void SetTimeRange(const Range& r) { m_timeRange = r; } - void SetTimeMarker(float fTime); + void SetTimeMarker(float fTime) override; float GetTimeMarker() const { return m_fTimeMarker; } void SetZoom(float fZoom); @@ -111,7 +111,7 @@ protected: void OnLButtonUp(const QPoint& point, Qt::KeyboardModifiers modifiers); void OnRButtonDown(const QPoint& point, Qt::KeyboardModifiers modifiers); void OnRButtonUp(const QPoint& point, Qt::KeyboardModifiers modifiers); - void keyPressEvent(QKeyEvent* event); + void keyPressEvent(QKeyEvent* event) override; // Drawing functions float ClientToTime(int x); diff --git a/Gems/LyShine/Code/Editor/Animation/UiAVTrackEventKeyUIControls.h b/Gems/LyShine/Code/Editor/Animation/UiAVTrackEventKeyUIControls.h index df3b7fa24f..ed47e6a160 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAVTrackEventKeyUIControls.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAVTrackEventKeyUIControls.h @@ -17,13 +17,13 @@ public: CSmartVariableEnum mv_event; CSmartVariable mv_value; - virtual void OnCreateVars(); + void OnCreateVars() override; bool SupportTrackType(const CUiAnimParamType& paramType, EUiAnimCurveType trackType, EUiAnimValue valueType) const override; bool OnKeySelectionChange(CUiAnimViewKeyBundle& selectedKeys) override; void OnUIChange(IVariable* pVar, CUiAnimViewKeyBundle& keys) override; - virtual unsigned int GetPriority() const { return 1; } + unsigned int GetPriority() const override { return 1; } static const GUID& GetClassID() { diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.h index edde246e1c..863e8c1cdd 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewCurveEditor.h @@ -49,8 +49,8 @@ public: void SetPlayCallback(const std::function& callback); // IUiAnimationContextListener - virtual void OnSequenceChanged(CUiAnimViewSequence* pNewSequence); - virtual void OnTimeChanged(float newTime); + void OnSequenceChanged(CUiAnimViewSequence* pNewSequence) override; + void OnTimeChanged(float newTime) override; protected: void showEvent(QShowEvent* event) override; @@ -112,8 +112,8 @@ public: float GetFPS() const { return m_widget->GetFPS(); } void SetTickDisplayMode(EUiAVTickMode mode) { m_widget->SetTickDisplayMode(mode); } - virtual void OnSequenceChanged(CUiAnimViewSequence* pNewSequence) { m_widget->OnSequenceChanged(pNewSequence); } - virtual void OnTimeChanged(float newTime) { m_widget->OnTimeChanged(newTime); } + void OnSequenceChanged(CUiAnimViewSequence* pNewSequence) override { m_widget->OnSequenceChanged(pNewSequence); } + void OnTimeChanged(float newTime) override { m_widget->OnTimeChanged(newTime); } virtual void OnKeysChanged(CUiAnimViewSequence* pSequence) override { m_widget->OnKeysChanged(pSequence); } virtual void OnKeySelectionChanged(CUiAnimViewSequence* pSequence) override { m_widget->OnKeySelectionChanged(pSequence); } diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.h index a7ecbd3499..4671612695 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDialog.h @@ -70,7 +70,7 @@ public: // UiEditorAnimationStateInterface UiEditorAnimationStateInterface::UiEditorAnimationEditState GetCurrentEditState() override; - void RestoreCurrentEditState(const UiEditorAnimationStateInterface::UiEditorAnimationEditState& animEditState); + void RestoreCurrentEditState(const UiEditorAnimationStateInterface::UiEditorAnimationEditState& animEditState) override; // ~UiEditorAnimationStateInterface // UiEditorAnimListenerInterface @@ -167,11 +167,11 @@ private: virtual void OnNodeSelectionChanged(CUiAnimViewSequence* pSequence) override; virtual void OnNodeRenamed(CUiAnimViewNode* pNode, const char* pOldName) override; - virtual void OnSequenceAdded(CUiAnimViewSequence* pSequence); - virtual void OnSequenceRemoved(CUiAnimViewSequence* pSequence); + void OnSequenceAdded(CUiAnimViewSequence* pSequence) override; + void OnSequenceRemoved(CUiAnimViewSequence* pSequence) override; - virtual void BeginUndoTransaction(); - virtual void EndUndoTransaction(); + void BeginUndoTransaction() override; + void EndUndoTransaction() override; void SaveSequenceTimingToXML(); // Instance diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.h index ff1984184f..504c39e630 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewDopeSheetBase.h @@ -87,7 +87,7 @@ public: void SetEditLock(bool bLock) { m_bEditLock = bLock; } // IUiAnimationContextListener - virtual void OnTimeChanged(float newTime); + void OnTimeChanged(float newTime) override; float TickSnap(float time) const; diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.h index 3aa8d74563..494cebd573 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequence.h @@ -234,17 +234,17 @@ private: // Called when an animation updates needs to be schedules void ForceAnimation(); - virtual void CopyKeysToClipboard(XmlNodeRef& xmlNode, const bool bOnlySelectedKeys, const bool bOnlyFromSelectedTracks) override; + void CopyKeysToClipboard(XmlNodeRef& xmlNode, const bool bOnlySelectedKeys, const bool bOnlyFromSelectedTracks) override; void UpdateLightAnimationRefs(const char* pOldName, const char* pNewName); std::deque GetMatchingTracks(CUiAnimViewAnimNode* pAnimNode, XmlNodeRef trackNode); void GetMatchedPasteLocationsRec(std::vector& locations, CUiAnimViewNode* pCurrentNode, XmlNodeRef clipboardNode); - virtual void BeginUndoTransaction(); - virtual void EndUndoTransaction(); - virtual void BeginRestoreTransaction(); - virtual void EndRestoreTransaction(); + void BeginUndoTransaction() override; + void EndUndoTransaction() override; + void BeginRestoreTransaction() override; + void EndRestoreTransaction() override; // Current time when animated float m_time; diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.h index f29f0e58e1..1fe9d96f85 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.h @@ -35,7 +35,7 @@ public: CUiAnimViewSequenceManager(); ~CUiAnimViewSequenceManager(); - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); + void OnEditorNotifyEvent(EEditorNotifyEvent event) override; unsigned int GetCount() const { return static_cast(m_sequences.size()); } diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.h b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.h index 8dd0ec0c79..45b3816f29 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.h +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSplineCtrl.h @@ -26,7 +26,7 @@ public: CUiAnimViewSplineCtrl(QWidget* parent); virtual ~CUiAnimViewSplineCtrl(); - virtual void ClearSelection(); + void ClearSelection() override; void AddSpline(ISplineInterpolator* pSpline, CUiAnimViewTrack* pTrack, const QColor& color); void AddSpline(ISplineInterpolator * pSpline, CUiAnimViewTrack * pTrack, QColor anColorArray[4]); @@ -64,7 +64,7 @@ private: void AdjustTCB(float d_tension, float d_continuity, float d_bias); void MoveSelectedTangentHandleTo(const QPoint& point); - virtual ISplineCtrlUndo* CreateSplineCtrlUndoObject(std::vector& splineContainer); + ISplineCtrlUndo* CreateSplineCtrlUndoObject(std::vector& splineContainer) override; bool m_bKeysFreeze; bool m_bTangentsFreeze; diff --git a/Gems/LyShine/Code/Source/Animation/AnimNode.h b/Gems/LyShine/Code/Source/Animation/AnimNode.h index 6ac198a5c7..0076276204 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimNode.h +++ b/Gems/LyShine/Code/Source/Animation/AnimNode.h @@ -64,10 +64,10 @@ public: // Return Animation Sequence that owns this node. IUiAnimSequence* GetSequence() const override { return m_pSequence; }; - void SetFlags(int flags); - int GetFlags() const; + void SetFlags(int flags) override; + int GetFlags() const override; - IUiAnimationSystem* GetUiAnimationSystem() const { return m_pSequence->GetUiAnimationSystem(); }; + IUiAnimationSystem* GetUiAnimationSystem() const override { return m_pSequence->GetUiAnimationSystem(); }; virtual void OnStart() {} void OnReset() override {} @@ -80,23 +80,23 @@ public: virtual Matrix34 GetReferenceMatrix() const; ////////////////////////////////////////////////////////////////////////// - bool IsParamValid(const CUiAnimParamType& paramType) const; + bool IsParamValid(const CUiAnimParamType& paramType) const override; AZStd::string GetParamName(const CUiAnimParamType& param) const override; - virtual EUiAnimValue GetParamValueType(const CUiAnimParamType& paramType) const; - virtual IUiAnimNode::ESupportedParamFlags GetParamFlags(const CUiAnimParamType& paramType) const; - virtual unsigned int GetParamCount() const { return 0; }; + EUiAnimValue GetParamValueType(const CUiAnimParamType& paramType) const override; + IUiAnimNode::ESupportedParamFlags GetParamFlags(const CUiAnimParamType& paramType) const override; + unsigned int GetParamCount() const override { return 0; }; - bool SetParamValue(float time, CUiAnimParamType param, float val); - bool SetParamValue(float time, CUiAnimParamType param, const Vec3& val); - bool SetParamValue(float time, CUiAnimParamType param, const Vec4& val); - bool GetParamValue(float time, CUiAnimParamType param, float& val); - bool GetParamValue(float time, CUiAnimParamType param, Vec3& val); - bool GetParamValue(float time, CUiAnimParamType param, Vec4& val); + bool SetParamValue(float time, CUiAnimParamType param, float val) override; + bool SetParamValue(float time, CUiAnimParamType param, const Vec3& val) override; + bool SetParamValue(float time, CUiAnimParamType param, const Vec4& val) override; + bool GetParamValue(float time, CUiAnimParamType param, float& val) override; + bool GetParamValue(float time, CUiAnimParamType param, Vec3& val) override; + bool GetParamValue(float time, CUiAnimParamType param, Vec4& val) override; void SetTarget([[maybe_unused]] IUiAnimNode* node) {}; IUiAnimNode* GetTarget() const { return 0; }; - void StillUpdate() {} + void StillUpdate() override {} void Animate(SUiAnimContext& ec) override; virtual void PrecacheStatic([[maybe_unused]] float startTime) {} @@ -109,7 +109,7 @@ public: IUiAnimNodeOwner* GetNodeOwner() override { return m_pOwner; }; // Called by sequence when needs to activate a node. - virtual void Activate(bool bActivate); + void Activate(bool bActivate) override; ////////////////////////////////////////////////////////////////////////// void SetParent(IUiAnimNode* pParent) override; @@ -132,7 +132,7 @@ public: IUiAnimTrack* GetTrackForAzField([[maybe_unused]] const UiAnimParamData& param) const override { return nullptr; } IUiAnimTrack* CreateTrackForAzField([[maybe_unused]] const UiAnimParamData& param) override { return nullptr; } - virtual void SetTrack(const CUiAnimParamType& paramType, IUiAnimTrack* track); + void SetTrack(const CUiAnimParamType& paramType, IUiAnimTrack* track) override; IUiAnimTrack* CreateTrack(const CUiAnimParamType& paramType) override; void SetTimeRange(Range timeRange) override; void AddTrack(IUiAnimTrack* track) override; @@ -147,7 +147,7 @@ public: void SetId(int id) { m_id = id; } const char* GetNameFast() const { return m_name.c_str(); } - virtual void Render(){} + void Render() override{} static void Reflect(AZ::SerializeContext* serializeContext); @@ -168,7 +168,7 @@ protected: // sets track animNode pointer to this node and sorts tracks void RegisterTrack(IUiAnimTrack* track); - virtual bool NeedToRender() const { return false; } + bool NeedToRender() const override { return false; } protected: int m_refCount; @@ -199,7 +199,7 @@ class CUiAnimNodeGroup public: CUiAnimNodeGroup(const int id) : CUiAnimNode(id, eUiAnimNodeType_Group) { SetFlags(GetFlags() | eUiAnimNodeFlags_CanChangeName); } - EUiAnimNodeType GetType() const { return eUiAnimNodeType_Group; } + EUiAnimNodeType GetType() const override { return eUiAnimNodeType_Group; } - virtual CUiAnimParamType GetParamType([[maybe_unused]] unsigned int nIndex) const { return eUiAnimParamType_Invalid; } + CUiAnimParamType GetParamType([[maybe_unused]] unsigned int nIndex) const override { return eUiAnimParamType_Invalid; } }; diff --git a/Gems/LyShine/Code/Source/Animation/AnimSequence.h b/Gems/LyShine/Code/Source/Animation/AnimSequence.h index e4026ce250..1451770b4e 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimSequence.h +++ b/Gems/LyShine/Code/Source/Animation/AnimSequence.h @@ -34,95 +34,95 @@ public: // Animation system. IUiAnimationSystem* GetUiAnimationSystem() const override { return m_pUiAnimationSystem; }; - void SetName(const char* name); - const char* GetName() const; - uint32 GetId() const { return m_id; } + void SetName(const char* name) override; + const char* GetName() const override; + uint32 GetId() const override { return m_id; } float GetTime() const { return m_time; } - virtual void SetOwner(IUiAnimSequenceOwner* pOwner) { m_pOwner = pOwner; } - virtual IUiAnimSequenceOwner* GetOwner() const { return m_pOwner; } + void SetOwner(IUiAnimSequenceOwner* pOwner) override { m_pOwner = pOwner; } + IUiAnimSequenceOwner* GetOwner() const override { return m_pOwner; } - virtual void SetActiveDirector(IUiAnimNode* pDirectorNode); - virtual IUiAnimNode* GetActiveDirector() const; + void SetActiveDirector(IUiAnimNode* pDirectorNode) override; + IUiAnimNode* GetActiveDirector() const override; - virtual void SetFlags(int flags); - virtual int GetFlags() const; - virtual int GetCutSceneFlags(const bool localFlags = false) const; + void SetFlags(int flags) override; + int GetFlags() const override; + int GetCutSceneFlags(const bool localFlags = false) const override; - virtual void SetParentSequence(IUiAnimSequence* pParentSequence); - virtual const IUiAnimSequence* GetParentSequence() const; - virtual bool IsAncestorOf(const IUiAnimSequence* pSequence) const; + void SetParentSequence(IUiAnimSequence* pParentSequence) override; + const IUiAnimSequence* GetParentSequence() const override; + bool IsAncestorOf(const IUiAnimSequence* pSequence) const override; - void SetTimeRange(Range timeRange); - Range GetTimeRange() { return m_timeRange; }; + void SetTimeRange(Range timeRange) override; + Range GetTimeRange() override { return m_timeRange; }; - void AdjustKeysToTimeRange(const Range& timeRange); + void AdjustKeysToTimeRange(const Range& timeRange) override; //! Return number of animation nodes in sequence. - int GetNodeCount() const; + int GetNodeCount() const override; //! Get specified animation node. - IUiAnimNode* GetNode(int index) const; + IUiAnimNode* GetNode(int index) const override; - IUiAnimNode* FindNodeByName(const char* sNodeName, const IUiAnimNode* pParentDirector); + IUiAnimNode* FindNodeByName(const char* sNodeName, const IUiAnimNode* pParentDirector) override; IUiAnimNode* FindNodeById(int nNodeId); - virtual void ReorderNode(IUiAnimNode* node, IUiAnimNode* pPivotNode, bool next); + void ReorderNode(IUiAnimNode* node, IUiAnimNode* pPivotNode, bool next) override; - void Reset(bool bSeekToStart); - void ResetHard(); - void Pause(); - void Resume(); - bool IsPaused() const; + void Reset(bool bSeekToStart) override; + void ResetHard() override; + void Pause() override; + void Resume() override; + bool IsPaused() const override; virtual void OnStart(); virtual void OnStop(); void OnLoop() override; //! Add animation node to sequence. - bool AddNode(IUiAnimNode* node); - IUiAnimNode* CreateNode(EUiAnimNodeType nodeType); - IUiAnimNode* CreateNode(XmlNodeRef node); - void RemoveNode(IUiAnimNode* node); + bool AddNode(IUiAnimNode* node) override; + IUiAnimNode* CreateNode(EUiAnimNodeType nodeType) override; + IUiAnimNode* CreateNode(XmlNodeRef node) override; + void RemoveNode(IUiAnimNode* node) override; //! Add scene node to sequence. - void RemoveAll(); + void RemoveAll() override; - virtual void Activate(); - virtual bool IsActivated() const { return m_bActive; } - virtual void Deactivate(); + void Activate() override; + bool IsActivated() const override { return m_bActive; } + void Deactivate() override; - virtual void PrecacheData(float startTime); + void PrecacheData(float startTime) override; void PrecacheStatic(const float startTime); void PrecacheDynamic(float time); - void StillUpdate(); - void Animate(const SUiAnimContext& ec); - void Render(); + void StillUpdate() override; + void Animate(const SUiAnimContext& ec) override; + void Render() override; - void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true, uint32 overrideId = 0, bool bResetLightAnimSet = false); - void InitPostLoad(IUiAnimationSystem* pUiAnimationSystem, bool remapIds, LyShine::EntityIdMap* entityIdMap); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true, uint32 overrideId = 0, bool bResetLightAnimSet = false) override; + void InitPostLoad(IUiAnimationSystem* pUiAnimationSystem, bool remapIds, LyShine::EntityIdMap* entityIdMap) override; - void CopyNodes(XmlNodeRef& xmlNode, IUiAnimNode** pSelectedNodes, uint32 count); - void PasteNodes(const XmlNodeRef& xmlNode, IUiAnimNode* pParent); + void CopyNodes(XmlNodeRef& xmlNode, IUiAnimNode** pSelectedNodes, uint32 count) override; + void PasteNodes(const XmlNodeRef& xmlNode, IUiAnimNode* pParent) override; //! Add/remove track events in sequence - virtual bool AddTrackEvent(const char* szEvent); - virtual bool RemoveTrackEvent(const char* szEvent); - virtual bool RenameTrackEvent(const char* szEvent, const char* szNewEvent); - virtual bool MoveUpTrackEvent(const char* szEvent); - virtual bool MoveDownTrackEvent(const char* szEvent); - virtual void ClearTrackEvents(); + bool AddTrackEvent(const char* szEvent) override; + bool RemoveTrackEvent(const char* szEvent) override; + bool RenameTrackEvent(const char* szEvent, const char* szNewEvent) override; + bool MoveUpTrackEvent(const char* szEvent) override; + bool MoveDownTrackEvent(const char* szEvent) override; + void ClearTrackEvents() override; //! Get the track events in the sequence - virtual int GetTrackEventsCount() const; - virtual char const* GetTrackEvent(int iIndex) const; - virtual IUiAnimStringTable* GetTrackEventStringTable() { return m_pEventStrings.get(); } + int GetTrackEventsCount() const override; + char const* GetTrackEvent(int iIndex) const override; + IUiAnimStringTable* GetTrackEventStringTable() override { return m_pEventStrings.get(); } //! Call to trigger a track event - virtual void TriggerTrackEvent(const char* event, const char* param = NULL); + void TriggerTrackEvent(const char* event, const char* param = NULL) override; //! Track event listener - virtual void AddTrackEventListener(IUiTrackEventListener* pListener); - virtual void RemoveTrackEventListener(IUiTrackEventListener* pListener); + void AddTrackEventListener(IUiTrackEventListener* pListener) override; + void RemoveTrackEventListener(IUiTrackEventListener* pListener) override; static void Reflect(AZ::SerializeContext* serializeContext); diff --git a/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h b/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h index 0bc625155a..bf49546916 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h +++ b/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h @@ -45,23 +45,23 @@ public: void release() override; ////////////////////////////////////////////////////////////////////////// - virtual int GetSubTrackCount() const { return 0; }; - virtual IUiAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const { return 0; }; + int GetSubTrackCount() const override { return 0; }; + IUiAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const override { return 0; }; AZStd::string GetSubTrackName([[maybe_unused]] int nIndex) const override { return AZStd::string(); }; - virtual void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) { assert(0); } + void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) override { assert(0); } - virtual const CUiAnimParamType& GetParameterType() const { return m_nParamType; }; - virtual void SetParameterType(CUiAnimParamType type) { m_nParamType = type; }; + const CUiAnimParamType& GetParameterType() const override { return m_nParamType; }; + void SetParameterType(CUiAnimParamType type) override { m_nParamType = type; }; - virtual const UiAnimParamData& GetParamData() const { return m_componentParamData; } - virtual void SetParamData(const UiAnimParamData& param) { m_componentParamData = param; } + const UiAnimParamData& GetParamData() const override { return m_componentParamData; } + void SetParamData(const UiAnimParamData& param) override { m_componentParamData = param; } - virtual void GetKeyValueRange(float& fMin, float& fMax) const { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; - virtual void SetKeyValueRange(float fMin, float fMax){ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; + void GetKeyValueRange(float& fMin, float& fMax) const override { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; + void SetKeyValueRange(float fMin, float fMax) override{ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; - ISplineInterpolator* GetSpline() const { return m_spline.get(); }; + ISplineInterpolator* GetSpline() const override { return m_spline.get(); }; - virtual bool IsKeySelected(int key) const + bool IsKeySelected(int key) const override { if (GetSpline() && GetSpline()->IsKeySelectedAtAnyDimension(key)) { @@ -70,7 +70,7 @@ public: return false; } - virtual void SelectKey(int key, bool select) + void SelectKey(int key, bool select) override { if (GetSpline()) { @@ -78,22 +78,22 @@ public: } } - int GetNumKeys() const + int GetNumKeys() const override { return m_spline->num_keys(); } - void SetNumKeys(int numKeys) + void SetNumKeys(int numKeys) override { m_spline->resize(numKeys); } - bool HasKeys() const + bool HasKeys() const override { return GetNumKeys() != 0; } - void RemoveKey(int num) + void RemoveKey(int num) override { if (m_spline && m_spline->num_keys() > num) { @@ -105,7 +105,7 @@ public: } } - void GetKey(int index, IKey* key) const + void GetKey(int index, IKey* key) const override { assert(index >= 0 && index < GetNumKeys()); assert(key != 0); @@ -123,7 +123,7 @@ public: tcbkey->SetValue(k.value); } - void SetKey(int index, IKey* key) + void SetKey(int index, IKey* key) override { assert(index >= 0 && index < GetNumKeys()); assert(key != 0); @@ -140,76 +140,76 @@ public: Invalidate(); } - float GetKeyTime(int index) const + float GetKeyTime(int index) const override { assert(index >= 0 && index < GetNumKeys()); return m_spline->time(index); } - void SetKeyTime(int index, float time) + void SetKeyTime(int index, float time) override { assert(index >= 0 && index < GetNumKeys()); m_spline->SetKeyTime(index, time); Invalidate(); } - int GetKeyFlags(int index) + int GetKeyFlags(int index) override { assert(index >= 0 && index < GetNumKeys()); return m_spline->key(index).flags; } - void SetKeyFlags(int index, int flags) + void SetKeyFlags(int index, int flags) override { assert(index >= 0 && index < GetNumKeys()); m_spline->key(index).flags = flags; } - virtual EUiAnimCurveType GetCurveType() { assert(0); return eUiAnimCurveType_Unknown; } - virtual EUiAnimValue GetValueType() { assert(0); return eUiAnimValue_Unknown; } + EUiAnimCurveType GetCurveType() override { assert(0); return eUiAnimCurveType_Unknown; } + EUiAnimValue GetValueType() override { assert(0); return eUiAnimValue_Unknown; } - virtual void GetValue(float time, float& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector2& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector3& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector4& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Color& value) { assert(0); } + void GetValue(float time, float& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector2& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector3& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector4& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Color& value) override { assert(0); } - virtual void SetValue(float time, const float& value, bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector2& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector3& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector4& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Color& value, [[maybe_unused]] bool bDefault = false) { assert(0); } + void SetValue(float time, const float& value, bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector2& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector3& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector4& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Color& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } - virtual void OffsetKeyPosition([[maybe_unused]] const Vec3& value) { assert(0); }; + void OffsetKeyPosition([[maybe_unused]] const Vec3& value) override { assert(0); }; - bool Serialize(IUiAnimationSystem* uiAnimationSystem, XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); - bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected, float fTimeOffset); + bool Serialize(IUiAnimationSystem* uiAnimationSystem, XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; + bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected, float fTimeOffset) override; - void GetKeyInfo(int key, const char*& description, float& duration) + void GetKeyInfo(int key, const char*& description, float& duration) override { description = 0; duration = 0; } //! Sort keys in track (after time of keys was modified). - void SortKeys() + void SortKeys() override { m_spline->sort_keys(); }; //! Get track flags. - int GetFlags() { return m_flags; } + int GetFlags() override { return m_flags; } //! Check if track is masked by mask - virtual bool IsMasked([[maybe_unused]] const uint32 mask) const { return false; } + bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; } //! Set track flags. - void SetFlags(int flags) + void SetFlags(int flags) override { m_flags = flags; if (m_flags & eUiAnimTrackFlags_Loop) @@ -231,12 +231,12 @@ public: m_spline->flag_set(Spline::MODIFIED); }; - void SetTimeRange(const Range& timeRange) + void SetTimeRange(const Range& timeRange) override { m_spline->SetRange(timeRange.start, timeRange.end); } - int FindKey(float time) + int FindKey(float time) override { // Find key with given time. int num = m_spline->num_keys(); @@ -252,7 +252,7 @@ public: } //! Create key at given time, and return its index. - int CreateKey(float time) + int CreateKey(float time) override { ValueType value; @@ -272,12 +272,12 @@ public: return m_spline->InsertKey(time, tmp); } - int CloneKey(int srcKey) + int CloneKey(int srcKey) override { return CopyKey(this, srcKey); } - int CopyKey(IUiAnimTrack* pFromTrack, int nFromKey) + int CopyKey(IUiAnimTrack* pFromTrack, int nFromKey) override { ITcbKey key; pFromTrack->GetKey(nFromKey, &key); @@ -326,16 +326,16 @@ public: m_defaultValue = value; } - virtual ColorB GetCustomColor() const + ColorB GetCustomColor() const override { return m_customColor; } - virtual void SetCustomColor(ColorB color) + void SetCustomColor(ColorB color) override { m_customColor = color; m_bCustomColorSet = true; } - virtual bool HasCustomColor() const + bool HasCustomColor() const override { return m_bCustomColorSet; } - virtual void ClearCustomColor() + void ClearCustomColor() override { m_bCustomColorSet = false; } static void Reflect(AZ::SerializeContext* serializeContext) {} diff --git a/Gems/LyShine/Code/Source/Animation/AnimTrack.h b/Gems/LyShine/Code/Source/Animation/AnimTrack.h index 9645572e3e..1ab5c26ab0 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimTrack.h +++ b/Gems/LyShine/Code/Source/Animation/AnimTrack.h @@ -27,19 +27,19 @@ public: TUiAnimTrack(); - virtual EUiAnimCurveType GetCurveType() { return eUiAnimCurveType_Unknown; }; - virtual EUiAnimValue GetValueType() { return eUiAnimValue_Unknown; } + EUiAnimCurveType GetCurveType() override { return eUiAnimCurveType_Unknown; }; + EUiAnimValue GetValueType() override { return eUiAnimValue_Unknown; } - virtual int GetSubTrackCount() const { return 0; }; - virtual IUiAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const { return 0; }; + int GetSubTrackCount() const override { return 0; }; + IUiAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const override { return 0; }; AZStd::string GetSubTrackName([[maybe_unused]] int nIndex) const override { return AZStd::string(); }; - virtual void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) { assert(0); } + void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) override { assert(0); } - virtual const CUiAnimParamType& GetParameterType() const { return m_nParamType; }; - virtual void SetParameterType(CUiAnimParamType type) { m_nParamType = type; }; + const CUiAnimParamType& GetParameterType() const override { return m_nParamType; }; + void SetParameterType(CUiAnimParamType type) override { m_nParamType = type; }; - virtual const UiAnimParamData& GetParamData() const { return m_componentParamData; } - virtual void SetParamData(const UiAnimParamData& param) { m_componentParamData = param; } + const UiAnimParamData& GetParamData() const override { return m_componentParamData; } + void SetParamData(const UiAnimParamData& param) override { m_componentParamData = param; } ////////////////////////////////////////////////////////////////////////// // for intrusive_ptr support @@ -47,7 +47,7 @@ public: void release() override; ////////////////////////////////////////////////////////////////////////// - virtual bool IsKeySelected(int key) const + bool IsKeySelected(int key) const override { AZ_Assert(key >= 0 && key < (int)m_keys.size(), "Key index is out of range"); if (m_keys[key].flags & AKEY_SELECTED) @@ -57,7 +57,7 @@ public: return false; } - virtual void SelectKey(int key, bool select) + void SelectKey(int key, bool select) override { AZ_Assert(key >= 0 && key < (int)m_keys.size(), "Key index is out of range"); if (select) @@ -71,100 +71,100 @@ public: } //! Return number of keys in track. - virtual int GetNumKeys() const { return static_cast(m_keys.size()); }; + int GetNumKeys() const override { return static_cast(m_keys.size()); }; //! Return true if keys exists in this track - virtual bool HasKeys() const { return !m_keys.empty(); } + bool HasKeys() const override { return !m_keys.empty(); } //! Set number of keys in track. //! If needed adds empty keys at end or remove keys from end. - virtual void SetNumKeys(int numKeys) { m_keys.resize(numKeys); }; + void SetNumKeys(int numKeys) override { m_keys.resize(numKeys); }; //! Remove specified key. - virtual void RemoveKey(int num); + void RemoveKey(int num) override; - int CreateKey(float time); - int CloneKey(int fromKey); - int CopyKey(IUiAnimTrack* pFromTrack, int nFromKey); + int CreateKey(float time) override; + int CloneKey(int fromKey) override; + int CopyKey(IUiAnimTrack* pFromTrack, int nFromKey) override; //! Get key at specified location. //! @param key Must be valid pointer to compatible key structure, to be filled with specified key location. - virtual void GetKey(int index, IKey* key) const; + void GetKey(int index, IKey* key) const override; //! Get time of specified key. //! @return key time. - virtual float GetKeyTime(int index) const; + float GetKeyTime(int index) const override; //! Find key at given time. //! @return Index of found key, or -1 if key with this time not found. - virtual int FindKey(float time); + int FindKey(float time) override; //! Get flags of specified key. //! @return key time. - virtual int GetKeyFlags(int index); + int GetKeyFlags(int index) override; //! Set key at specified location. //! @param key Must be valid pointer to compatible key structure. - virtual void SetKey(int index, IKey* key); + void SetKey(int index, IKey* key) override; //! Set time of specified key. - virtual void SetKeyTime(int index, float time); + void SetKeyTime(int index, float time) override; //! Set flags of specified key. - virtual void SetKeyFlags(int index, int flags); + void SetKeyFlags(int index, int flags) override; //! Sort keys in track (after time of keys was modified). - virtual void SortKeys(); + void SortKeys() override; //! Get track flags. - virtual int GetFlags() { return m_flags; } + int GetFlags() override { return m_flags; } //! Check if track is masked - virtual bool IsMasked([[maybe_unused]] const uint32 mask) const { return false; } + bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; } //! Set track flags. - virtual void SetFlags(int flags) { m_flags = flags; } + void SetFlags(int flags) override { m_flags = flags; } ////////////////////////////////////////////////////////////////////////// // Get track value at specified time. // Interpolates keys if needed. ////////////////////////////////////////////////////////////////////////// - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] float& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector2& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector3& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector4& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Color& value) { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] float& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector2& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector3& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Vector4& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] AZ::Color& value) override { assert(0); }; ////////////////////////////////////////////////////////////////////////// // Set track value at specified time. // Adds new keys if required. ////////////////////////////////////////////////////////////////////////// - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const float& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector2& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector3& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector4& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Color& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - - virtual void OffsetKeyPosition([[maybe_unused]] const Vec3& value) { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const float& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector2& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector3& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Vector4& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const AZ::Color& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + + void OffsetKeyPosition([[maybe_unused]] const Vec3& value) override { assert(0); }; /** Assign active time range for this track. */ - virtual void SetTimeRange(const Range& timeRange) { m_timeRange = timeRange; }; + void SetTimeRange(const Range& timeRange) override { m_timeRange = timeRange; }; /** Serialize this animation track to XML. Do not override this method, prefer to override SerializeKey. */ - virtual bool Serialize(IUiAnimationSystem* uiAnimationSystem, XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true); + bool Serialize(IUiAnimationSystem* uiAnimationSystem, XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true) override; - virtual bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0); + bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0) override; /** Serialize single key of this track. @@ -181,21 +181,21 @@ public: int GetActiveKey(float time, KeyType* key); #ifdef UI_ANIMATION_SYSTEM_SUPPORT_EDITING - virtual ColorB GetCustomColor() const + ColorB GetCustomColor() const override { return m_customColor; } - virtual void SetCustomColor(ColorB color) + void SetCustomColor(ColorB color) override { m_customColor = color; m_bCustomColorSet = true; } - virtual bool HasCustomColor() const + bool HasCustomColor() const override { return m_bCustomColorSet; } - virtual void ClearCustomColor() + void ClearCustomColor() override { m_bCustomColorSet = false; } #endif - virtual void GetKeyValueRange(float& fMin, float& fMax) const { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; - virtual void SetKeyValueRange(float fMin, float fMax){ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; + void GetKeyValueRange(float& fMin, float& fMax) const override { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; + void SetKeyValueRange(float fMin, float fMax) override{ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; static void Reflect(AZ::SerializeContext* serializeContext) {} diff --git a/Gems/LyShine/Code/Source/Animation/AzEntityNode.h b/Gems/LyShine/Code/Source/Animation/AzEntityNode.h index 9771ac7be3..f3a0fd641f 100644 --- a/Gems/LyShine/Code/Source/Animation/AzEntityNode.h +++ b/Gems/LyShine/Code/Source/Animation/AzEntityNode.h @@ -37,24 +37,24 @@ public: void EnableEntityPhysics(bool bEnable); - virtual EUiAnimNodeType GetType() const { return eUiAnimNodeType_AzEntity; } + EUiAnimNodeType GetType() const override { return eUiAnimNodeType_AzEntity; } - virtual void AddTrack(IUiAnimTrack* track); + void AddTrack(IUiAnimTrack* track) override; ////////////////////////////////////////////////////////////////////////// // Overrides from CUiAnimNode ////////////////////////////////////////////////////////////////////////// // UiAnimNodeInterface - virtual AZ::EntityId GetAzEntityId() override { return m_entityId; }; - virtual void SetAzEntity(AZ::Entity* entity) override { m_entityId = entity->GetId(); } + AZ::EntityId GetAzEntityId() override { return m_entityId; }; + void SetAzEntity(AZ::Entity* entity) override { m_entityId = entity->GetId(); } // ~UiAnimNodeInterface - virtual void StillUpdate(); - virtual void Animate(SUiAnimContext& ec); + void StillUpdate() override; + void Animate(SUiAnimContext& ec) override; - virtual void CreateDefaultTracks(); + void CreateDefaultTracks() override; bool SetParamValueAz(float time, const UiAnimParamData& param, float value) override; bool SetParamValueAz(float time, const UiAnimParamData& param, bool value) override; @@ -67,30 +67,30 @@ public: bool GetParamValueAz(float time, const UiAnimParamData& param, float& value) override; - virtual void PrecacheStatic(float startTime) override; - virtual void PrecacheDynamic(float time) override; + void PrecacheStatic(float startTime) override; + void PrecacheDynamic(float time) override; Vec3 GetPos() { return m_pos; }; Quat GetRotate() { return m_rotate; }; Vec3 GetScale() { return m_scale; }; - virtual void Activate(bool bActivate); + void Activate(bool bActivate) override; IUiAnimTrack* GetTrackForAzField(const UiAnimParamData& param) const override; IUiAnimTrack* CreateTrackForAzField(const UiAnimParamData& param) override; ////////////////////////////////////////////////////////////////////////// - void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); - virtual void InitPostLoad(IUiAnimSequence* pSequence, bool remapIds, LyShine::EntityIdMap* entityIdMap); - void OnReset(); - void OnResetHard(); - void OnStart(); - void OnPause(); - void OnStop(); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; + void InitPostLoad(IUiAnimSequence* pSequence, bool remapIds, LyShine::EntityIdMap* entityIdMap) override; + void OnReset() override; + void OnResetHard() override; + void OnStart() override; + void OnPause() override; + void OnStop() override; ////////////////////////////////////////////////////////////////////////// - virtual unsigned int GetParamCount() const; - virtual CUiAnimParamType GetParamType(unsigned int nIndex) const; + unsigned int GetParamCount() const override; + CUiAnimParamType GetParamType(unsigned int nIndex) const override; AZStd::string GetParamName(const CUiAnimParamType& param) const override; AZStd::string GetParamNameForTrack(const CUiAnimParamType& param, const IUiAnimTrack* track) const override; @@ -100,7 +100,7 @@ public: static void Reflect(AZ::SerializeContext* serializeContext); protected: - virtual bool GetParamInfoFromType(const CUiAnimParamType& paramId, SParamInfo& info) const; + bool GetParamInfoFromType(const CUiAnimParamType& paramId, SParamInfo& info) const override; //! Given the class data definition and a track for a field within it, //! compute the offset for the field and set it in the track @@ -115,7 +115,7 @@ protected: void ReleaseSounds(); // functions involved in the process to parse and store lua animated properties - virtual void UpdateDynamicParams(); + void UpdateDynamicParams() override; virtual void UpdateDynamicParams_Editor(); virtual void UpdateDynamicParams_PureGame(); diff --git a/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h b/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h index 127b6593fb..83a1f82588 100644 --- a/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h +++ b/Gems/LyShine/Code/Source/Animation/CompoundSplineTrack.h @@ -26,8 +26,8 @@ public: UiCompoundSplineTrack(int nDims, EUiAnimValue inValueType, CUiAnimParamType subTrackParamTypes[MAX_SUBTRACKS]); UiCompoundSplineTrack(); - void add_ref() { ++m_refCount; } - void release() + void add_ref() override { ++m_refCount; } + void release() override { if (--m_refCount <= 0) { @@ -35,107 +35,107 @@ public: } } - virtual int GetSubTrackCount() const { return m_nDimensions; }; - virtual IUiAnimTrack* GetSubTrack(int nIndex) const; + int GetSubTrackCount() const override { return m_nDimensions; }; + IUiAnimTrack* GetSubTrack(int nIndex) const override; AZStd::string GetSubTrackName(int nIndex) const override; - virtual void SetSubTrackName(int nIndex, const char* name); - - virtual EUiAnimCurveType GetCurveType() { return eUiAnimCurveType_BezierFloat; }; - virtual EUiAnimValue GetValueType() { return m_valueType; }; - - virtual const CUiAnimParamType& GetParameterType() const { return m_nParamType; }; - virtual void SetParameterType(CUiAnimParamType type) { m_nParamType = type; } - - virtual const UiAnimParamData& GetParamData() const { return m_componentParamData; } - virtual void SetParamData(const UiAnimParamData& param) { m_componentParamData = param; } - - virtual int GetNumKeys() const; - virtual void SetNumKeys([[maybe_unused]] int numKeys) { assert(0); }; - virtual bool HasKeys() const; - virtual void RemoveKey(int num); - - virtual void GetKeyInfo(int key, const char*& description, float& duration); - virtual int CreateKey([[maybe_unused]] float time) { assert(0); return 0; }; - virtual int CloneKey([[maybe_unused]] int fromKey) { assert(0); return 0; }; - virtual int CopyKey([[maybe_unused]] IUiAnimTrack* pFromTrack, [[maybe_unused]] int nFromKey) { assert(0); return 0; }; - virtual void GetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) const { assert(0); }; - virtual float GetKeyTime(int index) const; - virtual int FindKey([[maybe_unused]] float time) { assert(0); return 0; }; - virtual int GetKeyFlags([[maybe_unused]] int index) { assert(0); return 0; }; - virtual void SetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) { assert(0); }; - virtual void SetKeyTime(int index, float time); - virtual void SetKeyFlags([[maybe_unused]] int index, [[maybe_unused]] int flags) { assert(0); }; - virtual void SortKeys() { assert(0); }; - - virtual bool IsKeySelected(int key) const; - virtual void SelectKey(int key, bool select); - - virtual int GetFlags() { return m_flags; }; - virtual bool IsMasked([[maybe_unused]] const uint32 mask) const { return false; } - virtual void SetFlags(int flags) { m_flags = flags; }; + void SetSubTrackName(int nIndex, const char* name) override; + + EUiAnimCurveType GetCurveType() override { return eUiAnimCurveType_BezierFloat; }; + EUiAnimValue GetValueType() override { return m_valueType; }; + + const CUiAnimParamType& GetParameterType() const override { return m_nParamType; }; + void SetParameterType(CUiAnimParamType type) override { m_nParamType = type; } + + const UiAnimParamData& GetParamData() const override { return m_componentParamData; } + void SetParamData(const UiAnimParamData& param) override { m_componentParamData = param; } + + int GetNumKeys() const override; + void SetNumKeys([[maybe_unused]] int numKeys) override { assert(0); }; + bool HasKeys() const override; + void RemoveKey(int num) override; + + void GetKeyInfo(int key, const char*& description, float& duration) override; + int CreateKey([[maybe_unused]] float time) override { assert(0); return 0; }; + int CloneKey([[maybe_unused]] int fromKey) override { assert(0); return 0; }; + int CopyKey([[maybe_unused]] IUiAnimTrack* pFromTrack, [[maybe_unused]] int nFromKey) override { assert(0); return 0; }; + void GetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) const override { assert(0); }; + float GetKeyTime(int index) const override; + int FindKey([[maybe_unused]] float time) override { assert(0); return 0; }; + int GetKeyFlags([[maybe_unused]] int index) override { assert(0); return 0; }; + void SetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) override { assert(0); }; + void SetKeyTime(int index, float time) override; + void SetKeyFlags([[maybe_unused]] int index, [[maybe_unused]] int flags) override { assert(0); }; + void SortKeys() override { assert(0); }; + + bool IsKeySelected(int key) const override; + void SelectKey(int key, bool select) override; + + int GetFlags() override { return m_flags; }; + bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; } + void SetFlags(int flags) override { m_flags = flags; }; ////////////////////////////////////////////////////////////////////////// // Get track value at specified time. // Interpolates keys if needed. ////////////////////////////////////////////////////////////////////////// - virtual void GetValue(float time, float& value); - virtual void GetValue(float time, Vec3& value); - virtual void GetValue(float time, Vec4& value); - virtual void GetValue(float time, Quat& value); - virtual void GetValue(float time, AZ::Vector2& value); - virtual void GetValue(float time, AZ::Vector3& value); - virtual void GetValue(float time, AZ::Vector4& value); - virtual void GetValue(float time, AZ::Color& value); - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) { assert(0); }; + void GetValue(float time, float& value) override; + void GetValue(float time, Vec3& value) override; + void GetValue(float time, Vec4& value) override; + void GetValue(float time, Quat& value) override; + void GetValue(float time, AZ::Vector2& value) override; + void GetValue(float time, AZ::Vector3& value) override; + void GetValue(float time, AZ::Vector4& value) override; + void GetValue(float time, AZ::Color& value) override; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); }; ////////////////////////////////////////////////////////////////////////// // Set track value at specified time. // Adds new keys if required. ////////////////////////////////////////////////////////////////////////// - virtual void SetValue(float time, const float& value, bool bDefault = false); - virtual void SetValue(float time, const Vec3& value, bool bDefault = false); - void SetValue(float time, const Vec4& value, bool bDefault = false); - virtual void SetValue(float time, const Quat& value, bool bDefault = false); - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue(float time, const AZ::Vector2& value, bool bDefault = false); - virtual void SetValue(float time, const AZ::Vector3& value, bool bDefault = false); - virtual void SetValue(float time, const AZ::Vector4& value, bool bDefault = false); - virtual void SetValue(float time, const AZ::Color& value, bool bDefault = false); + void SetValue(float time, const float& value, bool bDefault = false) override; + void SetValue(float time, const Vec3& value, bool bDefault = false) override; + void SetValue(float time, const Vec4& value, bool bDefault = false) override; + void SetValue(float time, const Quat& value, bool bDefault = false) override; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue(float time, const AZ::Vector2& value, bool bDefault = false) override; + void SetValue(float time, const AZ::Vector3& value, bool bDefault = false) override; + void SetValue(float time, const AZ::Vector4& value, bool bDefault = false) override; + void SetValue(float time, const AZ::Color& value, bool bDefault = false) override; - virtual void OffsetKeyPosition(const Vec3& value); + void OffsetKeyPosition(const Vec3& value) override; - virtual void SetTimeRange(const Range& timeRange); + void SetTimeRange(const Range& timeRange) override; - virtual bool Serialize(IUiAnimationSystem* uiAnimationSystem, XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true); + bool Serialize(IUiAnimationSystem* uiAnimationSystem, XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true) override; - virtual bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0); + bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0) override; - virtual int NextKeyByTime(int key) const; + int NextKeyByTime(int key) const override; void SetSubTrackName(const int i, const AZStd::string& name) { assert (i < MAX_SUBTRACKS); m_subTrackNames[i] = name; } #ifdef UI_ANIMATION_SYSTEM_SUPPORT_EDITING - virtual ColorB GetCustomColor() const + ColorB GetCustomColor() const override { return m_customColor; } - virtual void SetCustomColor(ColorB color) + void SetCustomColor(ColorB color) override { m_customColor = color; m_bCustomColorSet = true; } - virtual bool HasCustomColor() const + bool HasCustomColor() const override { return m_bCustomColorSet; } - virtual void ClearCustomColor() + void ClearCustomColor() override { m_bCustomColorSet = false; } #endif - virtual void GetKeyValueRange(float& fMin, float& fMax) const + void GetKeyValueRange(float& fMin, float& fMax) const override { if (GetSubTrackCount() > 0) { m_subTracks[0]->GetKeyValueRange(fMin, fMax); } }; - virtual void SetKeyValueRange(float fMin, float fMax) + void SetKeyValueRange(float fMin, float fMax) override { for (int i = 0; i < m_nDimensions; ++i) { diff --git a/Gems/LyShine/Code/Source/Animation/TrackEventTrack.h b/Gems/LyShine/Code/Source/Animation/TrackEventTrack.h index 5896b19a2a..c7499c15d0 100644 --- a/Gems/LyShine/Code/Source/Animation/TrackEventTrack.h +++ b/Gems/LyShine/Code/Source/Animation/TrackEventTrack.h @@ -66,9 +66,9 @@ public: ////////////////////////////////////////////////////////////////////////// // Overrides of IAnimTrack. ////////////////////////////////////////////////////////////////////////// - void GetKeyInfo(int key, const char*& description, float& duration); - void SerializeKey(IEventKey& key, XmlNodeRef& keyNode, bool bLoading); - void SetKey(int index, IKey* key); + void GetKeyInfo(int key, const char*& description, float& duration) override; + void SerializeKey(IEventKey& key, XmlNodeRef& keyNode, bool bLoading) override; + void SetKey(int index, IKey* key) override; void InitPostLoad(IUiAnimSequence* sequence) override; static void Reflect(AZ::SerializeContext* serializeContext); diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h index c1dbdcfcda..c270d9ca60 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h @@ -44,94 +44,94 @@ public: ~UiAnimationSystem(); - void Release() { delete this; }; + void Release() override { delete this; }; - bool Load(const char* pszFile, const char* pszMission); + bool Load(const char* pszFile, const char* pszMission) override; - ISystem* GetSystem() { return m_pSystem; } + ISystem* GetSystem() override { return m_pSystem; } - IUiAnimTrack* CreateTrack(EUiAnimCurveType type); + IUiAnimTrack* CreateTrack(EUiAnimCurveType type) override; - IUiAnimSequence* CreateSequence(const char* sequence, bool bLoad = false, uint32 id = 0); + IUiAnimSequence* CreateSequence(const char* sequence, bool bLoad = false, uint32 id = 0) override; IUiAnimSequence* LoadSequence(const char* pszFilePath); - IUiAnimSequence* LoadSequence(XmlNodeRef& xmlNode, bool bLoadEmpty = true); - - void AddSequence(IUiAnimSequence* pSequence); - void RemoveSequence(IUiAnimSequence* pSequence); - IUiAnimSequence* FindSequence(const char* sequence) const; - IUiAnimSequence* FindSequenceById(uint32 id) const; - IUiAnimSequence* GetSequence(int i) const; - int GetNumSequences() const; - IUiAnimSequence* GetPlayingSequence(int i) const; - int GetNumPlayingSequences() const; - bool IsCutScenePlaying() const; - - uint32 GrabNextSequenceId() + IUiAnimSequence* LoadSequence(XmlNodeRef& xmlNode, bool bLoadEmpty = true) override; + + void AddSequence(IUiAnimSequence* pSequence) override; + void RemoveSequence(IUiAnimSequence* pSequence) override; + IUiAnimSequence* FindSequence(const char* sequence) const override; + IUiAnimSequence* FindSequenceById(uint32 id) const override; + IUiAnimSequence* GetSequence(int i) const override; + int GetNumSequences() const override; + IUiAnimSequence* GetPlayingSequence(int i) const override; + int GetNumPlayingSequences() const override; + bool IsCutScenePlaying() const override; + + uint32 GrabNextSequenceId() override { return m_nextSequenceId++; } - int OnSequenceRenamed(const char* before, const char* after); - int OnCameraRenamed(const char* before, const char* after); + int OnSequenceRenamed(const char* before, const char* after) override; + int OnCameraRenamed(const char* before, const char* after) override; - bool AddUiAnimationListener(IUiAnimSequence* pSequence, IUiAnimationListener* pListener); - bool RemoveUiAnimationListener(IUiAnimSequence* pSequence, IUiAnimationListener* pListener); + bool AddUiAnimationListener(IUiAnimSequence* pSequence, IUiAnimationListener* pListener) override; + bool RemoveUiAnimationListener(IUiAnimSequence* pSequence, IUiAnimationListener* pListener) override; - void RemoveAllSequences(); + void RemoveAllSequences() override; ////////////////////////////////////////////////////////////////////////// // Sequence playback. ////////////////////////////////////////////////////////////////////////// void PlaySequence(const char* sequence, IUiAnimSequence* parentSeq = NULL, bool bResetFX = true, - bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX); + bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX) override; void PlaySequence(IUiAnimSequence* seq, IUiAnimSequence* parentSeq = NULL, bool bResetFX = true, - bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX); - void PlayOnLoadSequences(); + bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX) override; + void PlayOnLoadSequences() override; - bool StopSequence(const char* sequence); - bool StopSequence(IUiAnimSequence* seq); - bool AbortSequence(IUiAnimSequence* seq, bool bLeaveTime = false); + bool StopSequence(const char* sequence) override; + bool StopSequence(IUiAnimSequence* seq) override; + bool AbortSequence(IUiAnimSequence* seq, bool bLeaveTime = false) override; - void StopAllSequences(); - void StopAllCutScenes(); + void StopAllSequences() override; + void StopAllCutScenes() override; void Pause(bool bPause); - void Reset(bool bPlayOnReset, bool bSeekToStart); - void StillUpdate(); - void PreUpdate(const float dt); - void PostUpdate(const float dt); - void Render(); + void Reset(bool bPlayOnReset, bool bSeekToStart) override; + void StillUpdate() override; + void PreUpdate(const float dt) override; + void PostUpdate(const float dt) override; + void Render() override; - bool IsPlaying(IUiAnimSequence* seq) const; + bool IsPlaying(IUiAnimSequence* seq) const override; - void Pause(); - void Resume(); + void Pause() override; + void Resume() override; - void SetRecording(bool recording) { m_bRecording = recording; }; - bool IsRecording() const { return m_bRecording; }; + void SetRecording(bool recording) override { m_bRecording = recording; }; + bool IsRecording() const override { return m_bRecording; }; - void SetCallback(IUiAnimationCallback* pCallback) { m_pCallback = pCallback; } - IUiAnimationCallback* GetCallback() { return m_pCallback; } + void SetCallback(IUiAnimationCallback* pCallback) override { m_pCallback = pCallback; } + IUiAnimationCallback* GetCallback() override { return m_pCallback; } void Callback(IUiAnimationCallback::ECallbackReason Reason, IUiAnimNode* pNode); - void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bRemoveOldNodes = false, bool bLoadEmpty = true); - void InitPostLoad(bool remapIds, LyShine::EntityIdMap* entityIdMap); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bRemoveOldNodes = false, bool bLoadEmpty = true) override; + void InitPostLoad(bool remapIds, LyShine::EntityIdMap* entityIdMap) override; - void SetSequenceStopBehavior(ESequenceStopBehavior behavior); - IUiAnimationSystem::ESequenceStopBehavior GetSequenceStopBehavior(); + void SetSequenceStopBehavior(ESequenceStopBehavior behavior) override; + IUiAnimationSystem::ESequenceStopBehavior GetSequenceStopBehavior() override; - float GetPlayingTime(IUiAnimSequence* pSeq); - bool SetPlayingTime(IUiAnimSequence* pSeq, float fTime); + float GetPlayingTime(IUiAnimSequence* pSeq) override; + bool SetPlayingTime(IUiAnimSequence* pSeq, float fTime) override; - float GetPlayingSpeed(IUiAnimSequence* pSeq); - bool SetPlayingSpeed(IUiAnimSequence* pSeq, float fTime); + float GetPlayingSpeed(IUiAnimSequence* pSeq) override; + bool SetPlayingSpeed(IUiAnimSequence* pSeq, float fTime) override; - bool GetStartEndTime(IUiAnimSequence* pSeq, float& fStartTime, float& fEndTime); - bool SetStartEndTime(IUiAnimSequence* pSeq, const float fStartTime, const float fEndTime); + bool GetStartEndTime(IUiAnimSequence* pSeq, float& fStartTime, float& fEndTime) override; + bool SetStartEndTime(IUiAnimSequence* pSeq, const float fStartTime, const float fEndTime) override; - void GoToFrame(const char* seqName, float targetFrame); + void GoToFrame(const char* seqName, float targetFrame) override; void SerializeNodeType(EUiAnimNodeType& animNodeType, XmlNodeRef& xmlNode, bool bLoading, const uint version, int flags); - virtual void SerializeParamType(CUiAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version); - virtual void SerializeParamData(UiAnimParamData& animParamData, XmlNodeRef& xmlNode, bool bLoading); + void SerializeParamType(CUiAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version) override; + void SerializeParamData(UiAnimParamData& animParamData, XmlNodeRef& xmlNode, bool bLoading) override; static const char* GetParamTypeName(const CUiAnimParamType& animParamType); @@ -156,8 +156,8 @@ private: void UpdateInternal(const float dt, const bool bPreUpdate); #ifdef UI_ANIMATION_SYSTEM_SUPPORT_EDITING - virtual EUiAnimNodeType GetNodeTypeFromString(const char* pString) const; - virtual CUiAnimParamType GetParamTypeFromString(const char* pString) const; + EUiAnimNodeType GetNodeTypeFromString(const char* pString) const override; + CUiAnimParamType GetParamTypeFromString(const char* pString) const override; #endif ISystem* m_pSystem; diff --git a/Gems/LyShine/Code/Source/LyShineSystemComponent.h b/Gems/LyShine/Code/Source/LyShineSystemComponent.h index 3d5e81f7c5..5b4086007b 100644 --- a/Gems/LyShine/Code/Source/LyShineSystemComponent.h +++ b/Gems/LyShine/Code/Source/LyShineSystemComponent.h @@ -65,7 +65,7 @@ namespace LyShine // UiSystemBus interface implementation void RegisterComponentTypeForMenuOrdering(const AZ::Uuid& typeUuid) override; const AZStd::vector* GetComponentTypesForMenuOrdering() override; - const AZStd::list* GetLyShineComponentDescriptors(); + const AZStd::list* GetLyShineComponentDescriptors() override; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -89,7 +89,7 @@ namespace LyShine // CrySystemEventBus /////////////////////////////////////////////////////// void OnCrySystemInitialized(ISystem& system, const SSystemInitParams&) override; - virtual void OnCrySystemShutdown(ISystem&) override; + void OnCrySystemShutdown(ISystem&) override; //////////////////////////////////////////////////////////////////////////// void BroadcastCursorImagePathname(); diff --git a/Gems/LyShine/Code/Source/UiLayoutFitterComponent.h b/Gems/LyShine/Code/Source/UiLayoutFitterComponent.h index d8ca9462bc..c5ceef4a74 100644 --- a/Gems/LyShine/Code/Source/UiLayoutFitterComponent.h +++ b/Gems/LyShine/Code/Source/UiLayoutFitterComponent.h @@ -72,7 +72,7 @@ protected: // member functions // ~AZ::Component // UiLayoutControllerInterface - unsigned int GetPriority() const; + unsigned int GetPriority() const override; // ~UiLayoutControllerInterface AZ_DISABLE_COPY_MOVE(UiLayoutFitterComponent); diff --git a/Gems/LyShine/Code/Source/UiScrollBarComponent.h b/Gems/LyShine/Code/Source/UiScrollBarComponent.h index 78bfa708c7..ba7abdf5e5 100644 --- a/Gems/LyShine/Code/Source/UiScrollBarComponent.h +++ b/Gems/LyShine/Code/Source/UiScrollBarComponent.h @@ -53,7 +53,7 @@ public: // member functions // UiScrollerInterface Orientation GetOrientation() override; - void SetOrientation(Orientation orientation); + void SetOrientation(Orientation orientation) override; AZ::EntityId GetScrollableEntity() override; void SetScrollableEntity(AZ::EntityId entityId) override; float GetValue() override; diff --git a/Gems/LyShine/Code/Source/UiTooltipDisplayComponent.h b/Gems/LyShine/Code/Source/UiTooltipDisplayComponent.h index 7aa0c0f618..d1fd53ec28 100644 --- a/Gems/LyShine/Code/Source/UiTooltipDisplayComponent.h +++ b/Gems/LyShine/Code/Source/UiTooltipDisplayComponent.h @@ -70,7 +70,7 @@ public: // member functions // ~UiInitializationInterface //! IUiAnimationListener - void OnUiAnimationEvent(EUiAnimationEvent uiAnimationEvent, IUiAnimSequence* pAnimSequence); + void OnUiAnimationEvent(EUiAnimationEvent uiAnimationEvent, IUiAnimSequence* pAnimSequence) override; // ~IUiAnimationListener State GetState(); From bd7bd3648b736e2c0ad85c7ad006ee45455b842b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:22:23 -0700 Subject: [PATCH 068/274] Gems/Maestro Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Cinematics/AnimAZEntityNode.h | 2 +- .../Source/Cinematics/AnimComponentNode.h | 2 +- .../Maestro/Code/Source/Cinematics/AnimNode.h | 32 ++-- .../Code/Source/Cinematics/AnimPostFXNode.h | 14 +- .../Source/Cinematics/AnimScreenFaderNode.h | 20 +-- .../Code/Source/Cinematics/AnimSequence.h | 98 ++++++------- .../Code/Source/Cinematics/AnimSplineTrack.h | 110 +++++++------- .../Code/Source/Cinematics/AnimTrack.h | 104 ++++++------- .../Code/Source/Cinematics/BoolTrack.h | 10 +- .../Maestro/Code/Source/Cinematics/CVarNode.h | 16 +- .../Source/Cinematics/CompoundSplineTrack.h | 118 +++++++-------- .../Code/Source/Cinematics/EventTrack.h | 6 +- .../Code/Source/Cinematics/MaterialNode.h | 10 +- Gems/Maestro/Code/Source/Cinematics/Movie.h | 138 +++++++++--------- .../Code/Source/Cinematics/SceneNode.cpp | 4 +- .../Code/Source/Cinematics/SceneNode.h | 20 +-- .../Code/Source/Cinematics/ScreenFaderTrack.h | 4 +- .../Code/Source/Cinematics/SoundTrack.h | 6 +- .../Code/Source/Cinematics/TrackEventTrack.h | 6 +- .../Components/EditorSequenceComponent.h | 2 +- 20 files changed, 361 insertions(+), 361 deletions(-) diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h index f5af0a7ab8..68399aa53e 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h @@ -63,7 +63,7 @@ public: Vec3 GetScale() override; ////////////////////////////////////////////////////////////////////////// - void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; // this is an unfortunate hold-over from legacy entities - used when a SceneNode overrides the camera animation so // we must disable the transform and camera components from updating animation on this entity because the SceneNode diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h index 43f49e8b80..6f4fe4cdd6 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h @@ -86,7 +86,7 @@ public: // EditorSequenceAgentComponentNotificationBus::Handler Interface void OnSequenceAgentConnected() override; - void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; const AZ::Uuid& GetComponentTypeId() const { return m_componentTypeId; } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimNode.h index 7c56d8f641..d0f22599e8 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimNode.h @@ -46,7 +46,7 @@ public: ////////////////////////////////////////////////////////////////////////// void SetName(const char* name) override { m_name = name; }; - const char* GetName() { return m_name.c_str(); }; + const char* GetName() override { return m_name.c_str(); }; void SetSequence(IAnimSequence* sequence) override { m_pSequence = sequence; } // Return Animation Sequence that owns this node. @@ -60,7 +60,7 @@ public: int GetFlags() const override; bool AreFlagsSetOnNodeOrAnyParent(EAnimNodeFlags flagsToCheck) const override; - IMovieSystem* GetMovieSystem() const { return gEnv->pMovieSystem; }; + IMovieSystem* GetMovieSystem() const override { return gEnv->pMovieSystem; }; virtual void OnStart() {} void OnReset() override {} @@ -85,23 +85,23 @@ public: virtual Matrix34 GetReferenceMatrix() const; ////////////////////////////////////////////////////////////////////////// - bool IsParamValid(const CAnimParamType& paramType) const; + bool IsParamValid(const CAnimParamType& paramType) const override; AZStd::string GetParamName(const CAnimParamType& param) const override; - virtual AnimValueType GetParamValueType(const CAnimParamType& paramType) const; - virtual IAnimNode::ESupportedParamFlags GetParamFlags(const CAnimParamType& paramType) const; - virtual unsigned int GetParamCount() const { return 0; }; + AnimValueType GetParamValueType(const CAnimParamType& paramType) const override; + IAnimNode::ESupportedParamFlags GetParamFlags(const CAnimParamType& paramType) const override; + unsigned int GetParamCount() const override { return 0; }; - bool SetParamValue(float time, CAnimParamType param, float val); - bool SetParamValue(float time, CAnimParamType param, const Vec3& val); - bool SetParamValue(float time, CAnimParamType param, const Vec4& val); - bool GetParamValue(float time, CAnimParamType param, float& val); - bool GetParamValue(float time, CAnimParamType param, Vec3& val); - bool GetParamValue(float time, CAnimParamType param, Vec4& val); + bool SetParamValue(float time, CAnimParamType param, float val) override; + bool SetParamValue(float time, CAnimParamType param, const Vec3& val) override; + bool SetParamValue(float time, CAnimParamType param, const Vec4& val) override; + bool GetParamValue(float time, CAnimParamType param, float& val) override; + bool GetParamValue(float time, CAnimParamType param, Vec3& val) override; + bool GetParamValue(float time, CAnimParamType param, Vec4& val) override; void SetTarget([[maybe_unused]] IAnimNode* node) {}; IAnimNode* GetTarget() const { return 0; }; - void StillUpdate() {} + void StillUpdate() override {} void Animate(SAnimContext& ec) override; virtual void PrecacheStatic([[maybe_unused]] float startTime) {} @@ -114,7 +114,7 @@ public: IAnimNodeOwner* GetNodeOwner() override { return m_pOwner; }; // Called by sequence when needs to activate a node. - virtual void Activate(bool bActivate); + void Activate(bool bActivate) override; ////////////////////////////////////////////////////////////////////////// void SetParent(IAnimNode* parent) override; @@ -149,7 +149,7 @@ public: void SetId(int id) { m_id = id; } const char* GetNameFast() const { return m_name.c_str(); } - virtual void Render(){} + void Render() override{} void UpdateDynamicParams() final; @@ -177,7 +177,7 @@ protected: CMovieSystem* GetCMovieSystem() const { return (CMovieSystem*)gEnv->pMovieSystem; } - virtual bool NeedToRender() const { return false; } + bool NeedToRender() const override { return false; } // nodes which support sounds should override this to reset their start/stop sound states virtual void ResetSounds() {} diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h index 6ce44607aa..25c4c89b94 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h @@ -37,32 +37,32 @@ public: //----------------------------------------------------------------------------- //! - virtual void SerializeAnims(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); + void SerializeAnims(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; //----------------------------------------------------------------------------- //! - virtual unsigned int GetParamCount() const; - virtual CAnimParamType GetParamType(unsigned int nIndex) const; + unsigned int GetParamCount() const override; + CAnimParamType GetParamType(unsigned int nIndex) const override; //----------------------------------------------------------------------------- //! //----------------------------------------------------------------------------- //! - virtual void CreateDefaultTracks(); + void CreateDefaultTracks() override; - virtual void OnReset(); + void OnReset() override; //----------------------------------------------------------------------------- //! - virtual void Animate(SAnimContext& ac); + void Animate(SAnimContext& ac) override; void InitPostLoad(IAnimSequence* sequence) override; static void Reflect(AZ::ReflectContext* context); protected: - virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; + bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const override; typedef std::map< AnimNodeType, _smart_ptr > FxNodeDescriptionMap; static StaticInstance s_fxNodeDescriptions; diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h index 1e16cc5fb0..8f4b0de4fb 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h @@ -32,32 +32,32 @@ public: //----------------------------------------------------------------------------- //! Overrides from CAnimNode - virtual void Animate(SAnimContext& ac); + void Animate(SAnimContext& ac) override; - virtual void CreateDefaultTracks(); + void CreateDefaultTracks() override; - virtual void OnReset(); + void OnReset() override; - virtual void Activate(bool bActivate); + void Activate(bool bActivate) override; - virtual void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; //----------------------------------------------------------------------------- //! Overrides from IAnimNode - virtual unsigned int GetParamCount() const; - virtual CAnimParamType GetParamType(unsigned int nIndex) const; + unsigned int GetParamCount() const override; + CAnimParamType GetParamType(unsigned int nIndex) const override; void SetFlags(int flags) override; - virtual void Render(); + void Render() override; bool IsAnyTextureVisible() const; static void Reflect(AZ::ReflectContext* context); protected: - virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; + bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const override; - virtual bool NeedToRender() const { return true; } + bool NeedToRender() const override { return true; } private: CAnimScreenFaderNode(const CAnimScreenFaderNode&); diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h index 0a1d4a931c..f824cf519d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.h @@ -40,48 +40,48 @@ public: // Movie system. IMovieSystem* GetMovieSystem() const { return m_pMovieSystem; }; - void SetName(const char* name); - const char* GetName() const; - uint32 GetId() const { return m_id; } + void SetName(const char* name) override; + const char* GetName() const override; + uint32 GetId() const override { return m_id; } void ResetId() override; float GetTime() const { return m_time; } void SetLegacySequenceObject(IAnimLegacySequenceObject* legacySequenceObject) override { m_legacySequenceObject = legacySequenceObject; } - virtual IAnimLegacySequenceObject* GetLegacySequenceObject() const override { return m_legacySequenceObject; } + IAnimLegacySequenceObject* GetLegacySequenceObject() const override { return m_legacySequenceObject; } void SetSequenceEntityId(const AZ::EntityId& sequenceEntityId) override; const AZ::EntityId& GetSequenceEntityId() const override { return m_sequenceEntityId; } - virtual void SetActiveDirector(IAnimNode* pDirectorNode); - virtual IAnimNode* GetActiveDirector() const; + void SetActiveDirector(IAnimNode* pDirectorNode) override; + IAnimNode* GetActiveDirector() const override; - virtual void SetFlags(int flags); - virtual int GetFlags() const; - virtual int GetCutSceneFlags(const bool localFlags = false) const; + void SetFlags(int flags) override; + int GetFlags() const override; + int GetCutSceneFlags(const bool localFlags = false) const override; - virtual void SetParentSequence(IAnimSequence* pParentSequence); - virtual const IAnimSequence* GetParentSequence() const; - virtual bool IsAncestorOf(const IAnimSequence* pSequence) const; + void SetParentSequence(IAnimSequence* pParentSequence) override; + const IAnimSequence* GetParentSequence() const override; + bool IsAncestorOf(const IAnimSequence* pSequence) const override; - void SetTimeRange(Range timeRange); - Range GetTimeRange() { return m_timeRange; }; + void SetTimeRange(Range timeRange) override; + Range GetTimeRange() override { return m_timeRange; }; - void AdjustKeysToTimeRange(const Range& timeRange); + void AdjustKeysToTimeRange(const Range& timeRange) override; //! Return number of animation nodes in sequence. - int GetNodeCount() const; + int GetNodeCount() const override; //! Get specified animation node. - IAnimNode* GetNode(int index) const; + IAnimNode* GetNode(int index) const override; - IAnimNode* FindNodeByName(const char* sNodeName, const IAnimNode* pParentDirector); + IAnimNode* FindNodeByName(const char* sNodeName, const IAnimNode* pParentDirector) override; IAnimNode* FindNodeById(int nNodeId); - virtual void ReorderNode(IAnimNode* node, IAnimNode* pPivotNode, bool next); + void ReorderNode(IAnimNode* node, IAnimNode* pPivotNode, bool next) override; - void Reset(bool bSeekToStart); - void ResetHard(); - void Pause(); - void Resume(); - bool IsPaused() const; + void Reset(bool bSeekToStart) override; + void ResetHard() override; + void Pause() override; + void Resume() override; + bool IsPaused() const override; virtual void OnStart(); virtual void OnStop(); @@ -90,49 +90,49 @@ public: void TimeChanged(float newTime) override; //! Add animation node to sequence. - bool AddNode(IAnimNode* node); - IAnimNode* CreateNode(AnimNodeType nodeType); - IAnimNode* CreateNode(XmlNodeRef node); + bool AddNode(IAnimNode* node) override; + IAnimNode* CreateNode(AnimNodeType nodeType) override; + IAnimNode* CreateNode(XmlNodeRef node) override; void RemoveNode(IAnimNode* node, bool removeChildRelationships=true) override; //! Add scene node to sequence. - void RemoveAll(); + void RemoveAll() override; - virtual void Activate(); - virtual bool IsActivated() const { return m_bActive; } - virtual void Deactivate(); + void Activate() override; + bool IsActivated() const override { return m_bActive; } + void Deactivate() override; - virtual void PrecacheData(float startTime); + void PrecacheData(float startTime) override; void PrecacheStatic(const float startTime); void PrecacheDynamic(float time); - void StillUpdate(); - void Animate(const SAnimContext& ec); - void Render(); + void StillUpdate() override; + void Animate(const SAnimContext& ec) override; + void Render() override; void InitPostLoad() override; - void CopyNodes(XmlNodeRef& xmlNode, IAnimNode** pSelectedNodes, uint32 count); - void PasteNodes(const XmlNodeRef& xmlNode, IAnimNode* pParent); + void CopyNodes(XmlNodeRef& xmlNode, IAnimNode** pSelectedNodes, uint32 count) override; + void PasteNodes(const XmlNodeRef& xmlNode, IAnimNode* pParent) override; //! Add/remove track events in sequence - virtual bool AddTrackEvent(const char* szEvent); - virtual bool RemoveTrackEvent(const char* szEvent); - virtual bool RenameTrackEvent(const char* szEvent, const char* szNewEvent); - virtual bool MoveUpTrackEvent(const char* szEvent); - virtual bool MoveDownTrackEvent(const char* szEvent); - virtual void ClearTrackEvents(); + bool AddTrackEvent(const char* szEvent) override; + bool RemoveTrackEvent(const char* szEvent) override; + bool RenameTrackEvent(const char* szEvent, const char* szNewEvent) override; + bool MoveUpTrackEvent(const char* szEvent) override; + bool MoveDownTrackEvent(const char* szEvent) override; + void ClearTrackEvents() override; //! Get the track events in the sequence - virtual int GetTrackEventsCount() const; - virtual char const* GetTrackEvent(int iIndex) const; - virtual IAnimStringTable* GetTrackEventStringTable() { return m_pEventStrings.get(); } + int GetTrackEventsCount() const override; + char const* GetTrackEvent(int iIndex) const override; + IAnimStringTable* GetTrackEventStringTable() override { return m_pEventStrings.get(); } //! Call to trigger a track event - virtual void TriggerTrackEvent(const char* event, const char* param = NULL); + void TriggerTrackEvent(const char* event, const char* param = NULL) override; //! Track event listener - virtual void AddTrackEventListener(ITrackEventListener* pListener); - virtual void RemoveTrackEventListener(ITrackEventListener* pListener); + void AddTrackEventListener(ITrackEventListener* pListener) override; + void RemoveTrackEventListener(ITrackEventListener* pListener) override; SequenceType GetSequenceType() const override { return m_sequenceType; } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h index 46dcb63daa..d6f969b21d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h @@ -52,24 +52,24 @@ public: ////////////////////////////////////////////////////////////////////////// - virtual int GetSubTrackCount() const { return 0; }; - virtual IAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const { return 0; }; - AZStd::string GetSubTrackName([[maybe_unused]] int nIndex) const { return AZStd::string(); }; - virtual void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) { assert(0); } + int GetSubTrackCount() const override { return 0; }; + IAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const override { return 0; }; + AZStd::string GetSubTrackName([[maybe_unused]] int nIndex) const override { return AZStd::string(); }; + void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) override { assert(0); } void SetNode(IAnimNode* node) override { m_node = node; } // Return Animation Node that owns this Track. IAnimNode* GetNode() override { return m_node; } - virtual const CAnimParamType& GetParameterType() const { return m_nParamType; }; - virtual void SetParameterType(CAnimParamType type) { m_nParamType = type; }; + const CAnimParamType& GetParameterType() const override { return m_nParamType; }; + void SetParameterType(CAnimParamType type) override { m_nParamType = type; }; - virtual void GetKeyValueRange(float& fMin, float& fMax) const { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; - virtual void SetKeyValueRange(float fMin, float fMax){ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; + void GetKeyValueRange(float& fMin, float& fMax) const override { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; + void SetKeyValueRange(float fMin, float fMax) override{ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; - ISplineInterpolator* GetSpline() const { return m_spline.get(); }; + ISplineInterpolator* GetSpline() const override { return m_spline.get(); }; - virtual bool IsKeySelected(int key) const + bool IsKeySelected(int key) const override { if (GetSpline() && GetSpline()->IsKeySelectedAtAnyDimension(key)) { @@ -78,7 +78,7 @@ public: return false; } - virtual void SelectKey(int key, bool select) + void SelectKey(int key, bool select) override { if (GetSpline()) { @@ -86,22 +86,22 @@ public: } } - int GetNumKeys() const + int GetNumKeys() const override { return m_spline->num_keys(); } - void SetNumKeys(int numKeys) + void SetNumKeys(int numKeys) override { m_spline->resize(numKeys); } - bool HasKeys() const + bool HasKeys() const override { return GetNumKeys() != 0; } - void RemoveKey(int num) + void RemoveKey(int num) override { if (m_spline && m_spline->num_keys() > num) { @@ -113,7 +113,7 @@ public: } } - void GetKey(int index, IKey* key) const + void GetKey(int index, IKey* key) const override { assert(index >= 0 && index < GetNumKeys()); assert(key != 0); @@ -131,7 +131,7 @@ public: tcbkey->SetValue(k.value); } - void SetKey(int index, IKey* key) + void SetKey(int index, IKey* key) override { assert(index >= 0 && index < GetNumKeys()); assert(key != 0); @@ -148,71 +148,71 @@ public: Invalidate(); } - float GetKeyTime(int index) const + float GetKeyTime(int index) const override { assert(index >= 0 && index < GetNumKeys()); return m_spline->time(index); } - void SetKeyTime(int index, float time) + void SetKeyTime(int index, float time) override { assert(index >= 0 && index < GetNumKeys()); m_spline->SetKeyTime(index, time); Invalidate(); } - int GetKeyFlags(int index) + int GetKeyFlags(int index) override { assert(index >= 0 && index < GetNumKeys()); return m_spline->key(index).flags; } - void SetKeyFlags(int index, int flags) + void SetKeyFlags(int index, int flags) override { assert(index >= 0 && index < GetNumKeys()); m_spline->key(index).flags = flags; } - virtual EAnimCurveType GetCurveType() { assert(0); return eAnimCurveType_Unknown; } - virtual AnimValueType GetValueType() { assert(0); return static_cast(0xFFFFFFFF); } + EAnimCurveType GetCurveType() override { assert(0); return eAnimCurveType_Unknown; } + AnimValueType GetValueType() override { assert(0); return static_cast(0xFFFFFFFF); } - virtual void GetValue(float time, float& value, bool applyMultiplier = false) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value, [[maybe_unused]] bool applyMultiplier = false) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value, [[maybe_unused]] bool applyMultiplier = false) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) { assert(0); } - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends& value) { assert(0); } + void GetValue(float time, float& value, bool applyMultiplier = false) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends& value) override { assert(0); } - virtual void SetValue(float time, const float& value, bool bDefault = false, bool applyMultiplier = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) { assert(0); } - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends& value, [[maybe_unused]] bool bDefault = false) { assert(0); } + void SetValue(float time, const float& value, bool bDefault = false, bool applyMultiplier = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } - virtual void OffsetKeyPosition([[maybe_unused]] const Vec3& value) { assert(0); }; - virtual void UpdateKeyDataAfterParentChanged([[maybe_unused]] const AZ::Transform& oldParentWorldTM, [[maybe_unused]] const AZ::Transform& newParentWorldTM) { assert(0); }; + void OffsetKeyPosition([[maybe_unused]] const Vec3& value) override { assert(0); }; + void UpdateKeyDataAfterParentChanged([[maybe_unused]] const AZ::Transform& oldParentWorldTM, [[maybe_unused]] const AZ::Transform& newParentWorldTM) override { assert(0); }; - bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); - bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected, float fTimeOffset); + bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; + bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected, float fTimeOffset) override; - void GetKeyInfo(int key, const char*& description, float& duration) + void GetKeyInfo(int key, const char*& description, float& duration) override { description = 0; duration = 0; } //! Sort keys in track (after time of keys was modified). - void SortKeys() + void SortKeys() override { m_spline->sort_keys(); }; //! Get track flags. - int GetFlags() { return m_flags; }; + int GetFlags() override { return m_flags; }; //! Check if track is masked by mask - virtual bool IsMasked([[maybe_unused]] const uint32 mask) const { return false; } + bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; } //! Set track flags. - void SetFlags(int flags) + void SetFlags(int flags) override { m_flags = flags; if (m_flags & eAnimTrackFlags_Loop) @@ -234,12 +234,12 @@ public: m_spline->flag_set(Spline::MODIFIED); }; - void SetTimeRange(const Range& timeRange) + void SetTimeRange(const Range& timeRange) override { m_spline->SetRange(timeRange.start, timeRange.end); } - int FindKey(float time) + int FindKey(float time) override { // Find key with given time. int num = m_spline->num_keys(); @@ -255,7 +255,7 @@ public: } //! Create key at given time, and return its index. - int CreateKey(float time) + int CreateKey(float time) override { ValueType value; @@ -275,12 +275,12 @@ public: return m_spline->InsertKey(time, tmp); } - int CloneKey(int srcKey) + int CloneKey(int srcKey) override { return CopyKey(this, srcKey); } - int CopyKey(IAnimTrack* pFromTrack, int nFromKey) + int CopyKey(IAnimTrack* pFromTrack, int nFromKey) override { ITcbKey key; pFromTrack->GetKey(nFromKey, &key); @@ -329,16 +329,16 @@ public: m_defaultValue = value; } - virtual ColorB GetCustomColor() const + ColorB GetCustomColor() const override { return m_customColor; } - virtual void SetCustomColor(ColorB color) + void SetCustomColor(ColorB color) override { m_customColor = color; m_bCustomColorSet = true; } - virtual bool HasCustomColor() const + bool HasCustomColor() const override { return m_bCustomColorSet; } - virtual void ClearCustomColor() + void ClearCustomColor() override { m_bCustomColorSet = false; } void SetMultiplier(float trackMultiplier) override @@ -346,12 +346,12 @@ public: m_trackMultiplier = trackMultiplier; } - void SetExpanded([[maybe_unused]] bool expanded) + void SetExpanded([[maybe_unused]] bool expanded) override { AZ_Assert(false, "Not expected to be used."); } - bool GetExpanded() const + bool GetExpanded() const override { return false; } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h b/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h index e16f64c7c1..e39ae3e2ee 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h @@ -28,20 +28,20 @@ public: TAnimTrack(); - virtual EAnimCurveType GetCurveType() { return eAnimCurveType_Unknown; }; - virtual AnimValueType GetValueType() { return kAnimValueUnknown; } + EAnimCurveType GetCurveType() override { return eAnimCurveType_Unknown; }; + AnimValueType GetValueType() override { return kAnimValueUnknown; } void SetNode(IAnimNode* node) override { m_node = node; } // Return Animation Node that owns this Track. IAnimNode* GetNode() override { return m_node; } - virtual int GetSubTrackCount() const { return 0; }; - virtual IAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const { return 0; }; + int GetSubTrackCount() const override { return 0; }; + IAnimTrack* GetSubTrack([[maybe_unused]] int nIndex) const override { return 0; }; AZStd::string GetSubTrackName([[maybe_unused]] int nIndex) const override { return AZStd::string(); }; - virtual void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) { assert(0); } + void SetSubTrackName([[maybe_unused]] int nIndex, [[maybe_unused]] const char* name) override { assert(0); } - virtual const CAnimParamType& GetParameterType() const { return m_nParamType; }; - virtual void SetParameterType(CAnimParamType type) { m_nParamType = type; }; + const CAnimParamType& GetParameterType() const override { return m_nParamType; }; + void SetParameterType(CAnimParamType type) override { m_nParamType = type; }; ////////////////////////////////////////////////////////////////////////// // for intrusive_ptr support @@ -49,7 +49,7 @@ public: void release() override; ////////////////////////////////////////////////////////////////////////// - virtual bool IsKeySelected(int key) const + bool IsKeySelected(int key) const override { AZ_Assert(key >= 0 && key < (int)m_keys.size(), "Key index is out of range"); if (m_keys[key].flags & AKEY_SELECTED) @@ -59,7 +59,7 @@ public: return false; } - virtual void SelectKey(int key, bool select) + void SelectKey(int key, bool select) override { AZ_Assert(key >= 0 && key < (int)m_keys.size(), "Key index is out of range"); if (select) @@ -96,59 +96,59 @@ public: } //! Return number of keys in track. - virtual int GetNumKeys() const { return static_cast(m_keys.size()); }; + int GetNumKeys() const override { return static_cast(m_keys.size()); }; //! Return true if keys exists in this track - virtual bool HasKeys() const { return !m_keys.empty(); } + bool HasKeys() const override { return !m_keys.empty(); } //! Set number of keys in track. //! If needed adds empty keys at end or remove keys from end. - virtual void SetNumKeys(int numKeys) { m_keys.resize(numKeys); }; + void SetNumKeys(int numKeys) override { m_keys.resize(numKeys); }; //! Remove specified key. - virtual void RemoveKey(int num); + void RemoveKey(int num) override; - int CreateKey(float time); - int CloneKey(int fromKey); - int CopyKey(IAnimTrack* pFromTrack, int nFromKey); + int CreateKey(float time) override; + int CloneKey(int fromKey) override; + int CopyKey(IAnimTrack* pFromTrack, int nFromKey) override; //! Get key at specified location. //! @param key Must be valid pointer to compatible key structure, to be filled with specified key location. - virtual void GetKey(int index, IKey* key) const; + void GetKey(int index, IKey* key) const override; //! Get time of specified key. //! @return key time. - virtual float GetKeyTime(int index) const; + float GetKeyTime(int index) const override; //! Find key at given time. //! @return Index of found key, or -1 if key with this time not found. - virtual int FindKey(float time); + int FindKey(float time) override; //! Get flags of specified key. //! @return key time. - virtual int GetKeyFlags(int index); + int GetKeyFlags(int index) override; //! Set key at specified location. //! @param key Must be valid pointer to compatible key structure. - virtual void SetKey(int index, IKey* key); + void SetKey(int index, IKey* key) override; //! Set time of specified key. - virtual void SetKeyTime(int index, float time); + void SetKeyTime(int index, float time) override; //! Set flags of specified key. - virtual void SetKeyFlags(int index, int flags); + void SetKeyFlags(int index, int flags) override; //! Sort keys in track (after time of keys was modified). - virtual void SortKeys(); + void SortKeys() override; //! Get track flags. - virtual int GetFlags() { return m_flags; }; + int GetFlags() override { return m_flags; }; //! Check if track is masked - virtual bool IsMasked([[maybe_unused]] const uint32 mask) const { return false; } + bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; } //! Set track flags. - virtual void SetFlags(int flags) + void SetFlags(int flags) override { m_flags = flags; } @@ -157,37 +157,37 @@ public: // Get track value at specified time. // Interpolates keys if needed. ////////////////////////////////////////////////////////////////////////// - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] float& value, [[maybe_unused]] bool applyMultiplier = false) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value, [[maybe_unused]] bool applyMultiplier = false) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value, [[maybe_unused]] bool applyMultiplier = false) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends& value) { assert(0); } + void GetValue([[maybe_unused]] float time, [[maybe_unused]] float& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec3& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Vec4& value, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Quat& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends& value) override { assert(0); } ////////////////////////////////////////////////////////////////////////// // Set track value at specified time. // Adds new keys if required. ////////////////////////////////////////////////////////////////////////// - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const float& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends& value, [[maybe_unused]] bool bDefault = false) { assert(0); } + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const float& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec3& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Vec4& value, [[maybe_unused]] bool bDefault = false, [[maybe_unused]] bool applyMultiplier = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Quat& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } - virtual void OffsetKeyPosition([[maybe_unused]] const Vec3& value) { assert(0); }; - virtual void UpdateKeyDataAfterParentChanged([[maybe_unused]] const AZ::Transform& oldParentWorldTM, [[maybe_unused]] const AZ::Transform& newParentWorldTM) { assert(0); }; + void OffsetKeyPosition([[maybe_unused]] const Vec3& value) override { assert(0); }; + void UpdateKeyDataAfterParentChanged([[maybe_unused]] const AZ::Transform& oldParentWorldTM, [[maybe_unused]] const AZ::Transform& newParentWorldTM) override { assert(0); }; /** Assign active time range for this track. */ - virtual void SetTimeRange(const Range& timeRange) { m_timeRange = timeRange; }; + void SetTimeRange(const Range& timeRange) override { m_timeRange = timeRange; }; /** Serialize this animation track to XML. Do not override this method, prefer to override SerializeKey. */ - virtual bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true); + bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true) override; - virtual bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0); + bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0) override; /** Serialize single key of this track. @@ -204,33 +204,33 @@ public: int GetActiveKey(float time, KeyType* key); #ifdef MOVIESYSTEM_SUPPORT_EDITING - virtual ColorB GetCustomColor() const + ColorB GetCustomColor() const override { return m_customColor; } - virtual void SetCustomColor(ColorB color) + void SetCustomColor(ColorB color) override { m_customColor = color; m_bCustomColorSet = true; } - virtual bool HasCustomColor() const + bool HasCustomColor() const override { return m_bCustomColorSet; } - virtual void ClearCustomColor() + void ClearCustomColor() override { m_bCustomColorSet = false; } #endif - virtual void GetKeyValueRange(float& fMin, float& fMax) const { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; - virtual void SetKeyValueRange(float fMin, float fMax){ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; + void GetKeyValueRange(float& fMin, float& fMax) const override { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; + void SetKeyValueRange(float fMin, float fMax) override{ m_fMinKeyValue = fMin; m_fMaxKeyValue = fMax; }; void SetMultiplier(float trackMultiplier) override { m_trackMultiplier = trackMultiplier; } - void SetExpanded([[maybe_unused]] bool expanded) + void SetExpanded([[maybe_unused]] bool expanded) override { AZ_Assert(false, "Not expected to be used."); } - bool GetExpanded() const + bool GetExpanded() const override { return false; } diff --git a/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h b/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h index edee77437c..a24f695b56 100644 --- a/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h @@ -28,14 +28,14 @@ public: CBoolTrack(); - virtual AnimValueType GetValueType(); + AnimValueType GetValueType() override; - virtual void GetValue(float time, bool& value); - virtual void SetValue(float time, const bool& value, bool bDefault = false); + void GetValue(float time, bool& value) override; + void SetValue(float time, const bool& value, bool bDefault = false) override; - void SerializeKey([[maybe_unused]] IBoolKey& key, [[maybe_unused]] XmlNodeRef& keyNode, [[maybe_unused]] bool bLoading) {}; - void GetKeyInfo(int key, const char*& description, float& duration); + void SerializeKey([[maybe_unused]] IBoolKey& key, [[maybe_unused]] XmlNodeRef& keyNode, [[maybe_unused]] bool bLoading) override {}; + void GetKeyInfo(int key, const char*& description, float& duration) override; void SetDefaultValue(const bool bDefaultValue); diff --git a/Gems/Maestro/Code/Source/Cinematics/CVarNode.h b/Gems/Maestro/Code/Source/Cinematics/CVarNode.h index 5068140f11..af5ce43b2f 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CVarNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/CVarNode.h @@ -26,21 +26,21 @@ public: ////////////////////////////////////////////////////////////////////////// // Overrides from CAnimNode ////////////////////////////////////////////////////////////////////////// - void SetName(const char* name); - void Animate(SAnimContext& ec); - void CreateDefaultTracks(); - void OnReset(); - void OnResume(); + void SetName(const char* name) override; + void Animate(SAnimContext& ec) override; + void CreateDefaultTracks() override; + void OnReset() override; + void OnResume() override; - virtual unsigned int GetParamCount() const; - virtual CAnimParamType GetParamType(unsigned int nIndex) const; + unsigned int GetParamCount() const override; + CAnimParamType GetParamType(unsigned int nIndex) const override; int GetDefaultKeyTangentFlags() const override; static void Reflect(AZ::ReflectContext* context); protected: - virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; + bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const override; private: float m_value; diff --git a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h index 443bad584b..4d7065a06d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h @@ -36,41 +36,41 @@ public: // Return Animation Node that owns this Track. IAnimNode* GetNode() override { return m_node; } - virtual int GetSubTrackCount() const { return m_nDimensions; }; - virtual IAnimTrack* GetSubTrack(int nIndex) const; - AZStd::string GetSubTrackName(int nIndex) const; - virtual void SetSubTrackName(int nIndex, const char* name); - - virtual EAnimCurveType GetCurveType() { return eAnimCurveType_BezierFloat; }; - virtual AnimValueType GetValueType() { return m_valueType; }; - - virtual const CAnimParamType& GetParameterType() const { return m_nParamType; }; - virtual void SetParameterType(CAnimParamType type) { m_nParamType = type; } - - virtual int GetNumKeys() const; - virtual void SetNumKeys([[maybe_unused]] int numKeys) { assert(0); }; - virtual bool HasKeys() const; - virtual void RemoveKey(int num); - - virtual void GetKeyInfo(int key, const char*& description, float& duration); - virtual int CreateKey([[maybe_unused]] float time) { assert(0); return 0; }; - virtual int CloneKey([[maybe_unused]] int fromKey) { assert(0); return 0; }; - virtual int CopyKey([[maybe_unused]] IAnimTrack* pFromTrack, [[maybe_unused]] int nFromKey) { assert(0); return 0; }; - virtual void GetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) const { assert(0); }; - virtual float GetKeyTime(int index) const; - virtual int FindKey([[maybe_unused]] float time) { assert(0); return 0; }; - virtual int GetKeyFlags([[maybe_unused]] int index) { assert(0); return 0; }; - virtual void SetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) { assert(0); }; - virtual void SetKeyTime(int index, float time); - virtual void SetKeyFlags([[maybe_unused]] int index, [[maybe_unused]] int flags) { assert(0); }; - virtual void SortKeys() { assert(0); }; - - virtual bool IsKeySelected(int key) const; - virtual void SelectKey(int key, bool select); - - virtual int GetFlags() { return m_flags; }; - virtual bool IsMasked([[maybe_unused]] const uint32 mask) const { return false; } - virtual void SetFlags(int flags) + int GetSubTrackCount() const override { return m_nDimensions; }; + IAnimTrack* GetSubTrack(int nIndex) const override; + AZStd::string GetSubTrackName(int nIndex) const override; + void SetSubTrackName(int nIndex, const char* name) override; + + EAnimCurveType GetCurveType() override { return eAnimCurveType_BezierFloat; }; + AnimValueType GetValueType() override { return m_valueType; }; + + const CAnimParamType& GetParameterType() const override { return m_nParamType; }; + void SetParameterType(CAnimParamType type) override { m_nParamType = type; } + + int GetNumKeys() const override; + void SetNumKeys([[maybe_unused]] int numKeys) override { assert(0); }; + bool HasKeys() const override; + void RemoveKey(int num) override; + + void GetKeyInfo(int key, const char*& description, float& duration) override; + int CreateKey([[maybe_unused]] float time) override { assert(0); return 0; }; + int CloneKey([[maybe_unused]] int fromKey) override { assert(0); return 0; }; + int CopyKey([[maybe_unused]] IAnimTrack* pFromTrack, [[maybe_unused]] int nFromKey) override { assert(0); return 0; }; + void GetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) const override { assert(0); }; + float GetKeyTime(int index) const override; + int FindKey([[maybe_unused]] float time) override { assert(0); return 0; }; + int GetKeyFlags([[maybe_unused]] int index) override { assert(0); return 0; }; + void SetKey([[maybe_unused]] int index, [[maybe_unused]] IKey* key) override { assert(0); }; + void SetKeyTime(int index, float time) override; + void SetKeyFlags([[maybe_unused]] int index, [[maybe_unused]] int flags) override { assert(0); }; + void SortKeys() override { assert(0); }; + + bool IsKeySelected(int key) const override; + void SelectKey(int key, bool select) override; + + int GetFlags() override { return m_flags; }; + bool IsMasked([[maybe_unused]] const uint32 mask) const override { return false; } + void SetFlags(int flags) override { m_flags = flags; } @@ -79,59 +79,59 @@ public: // Get track value at specified time. // Interpolates keys if needed. ////////////////////////////////////////////////////////////////////////// - virtual void GetValue(float time, float& value, bool applyMultiplier = false); - virtual void GetValue(float time, Vec3& value, bool applyMultiplier = false); - virtual void GetValue(float time, Vec4& value, bool applyMultiplier = false); - virtual void GetValue(float time, Quat& value); - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) { assert(0); }; - virtual void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends& value) { assert(0); } + void GetValue(float time, float& value, bool applyMultiplier = false) override; + void GetValue(float time, Vec3& value, bool applyMultiplier = false) override; + void GetValue(float time, Vec4& value, bool applyMultiplier = false) override; + void GetValue(float time, Quat& value) override; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] bool& value) override { assert(0); }; + void GetValue([[maybe_unused]] float time, [[maybe_unused]] Maestro::AssetBlends& value) override { assert(0); } ////////////////////////////////////////////////////////////////////////// // Set track value at specified time. // Adds new keys if required. ////////////////////////////////////////////////////////////////////////// - virtual void SetValue(float time, const float& value, bool bDefault = false, bool applyMultiplier = false); - virtual void SetValue(float time, const Vec3& value, bool bDefault = false, bool applyMultiplier = false); - void SetValue(float time, const Vec4& value, bool bDefault = false, bool applyMultiplier = false); - virtual void SetValue(float time, const Quat& value, bool bDefault = false); - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) { assert(0); }; - virtual void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends& value, [[maybe_unused]] bool bDefault = false) { assert(0); } + void SetValue(float time, const float& value, bool bDefault = false, bool applyMultiplier = false) override; + void SetValue(float time, const Vec3& value, bool bDefault = false, bool applyMultiplier = false) override; + void SetValue(float time, const Vec4& value, bool bDefault = false, bool applyMultiplier = false) override; + void SetValue(float time, const Quat& value, bool bDefault = false) override; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const bool& value, [[maybe_unused]] bool bDefault = false) override { assert(0); }; + void SetValue([[maybe_unused]] float time, [[maybe_unused]] const Maestro::AssetBlends& value, [[maybe_unused]] bool bDefault = false) override { assert(0); } - virtual void OffsetKeyPosition(const Vec3& value); - virtual void UpdateKeyDataAfterParentChanged(const AZ::Transform& oldParentWorldTM, const AZ::Transform& newParentWorldTM); + void OffsetKeyPosition(const Vec3& value) override; + void UpdateKeyDataAfterParentChanged(const AZ::Transform& oldParentWorldTM, const AZ::Transform& newParentWorldTM) override; - virtual void SetTimeRange(const Range& timeRange); + void SetTimeRange(const Range& timeRange) override; - virtual bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true); + bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true) override; - virtual bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0); + bool SerializeSelection(XmlNodeRef& xmlNode, bool bLoading, bool bCopySelected = false, float fTimeOffset = 0) override; - virtual int NextKeyByTime(int key) const; + int NextKeyByTime(int key) const override; void SetSubTrackName(const int i, const AZStd::string& name) { assert (i < MAX_SUBTRACKS); m_subTrackNames[i] = name; } #ifdef MOVIESYSTEM_SUPPORT_EDITING - virtual ColorB GetCustomColor() const + ColorB GetCustomColor() const override { return m_customColor; } - virtual void SetCustomColor(ColorB color) + void SetCustomColor(ColorB color) override { m_customColor = color; m_bCustomColorSet = true; } - virtual bool HasCustomColor() const + bool HasCustomColor() const override { return m_bCustomColorSet; } - virtual void ClearCustomColor() + void ClearCustomColor() override { m_bCustomColorSet = false; } #endif - virtual void GetKeyValueRange(float& fMin, float& fMax) const + void GetKeyValueRange(float& fMin, float& fMax) const override { if (GetSubTrackCount() > 0) { m_subTracks[0]->GetKeyValueRange(fMin, fMax); } }; - virtual void SetKeyValueRange(float fMin, float fMax) + void SetKeyValueRange(float fMin, float fMax) override { for (int i = 0; i < m_nDimensions; ++i) { diff --git a/Gems/Maestro/Code/Source/Cinematics/EventTrack.h b/Gems/Maestro/Code/Source/Cinematics/EventTrack.h index afe7eb6602..6430119e5e 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/EventTrack.h @@ -33,9 +33,9 @@ public: ////////////////////////////////////////////////////////////////////////// // Overrides of IAnimTrack. ////////////////////////////////////////////////////////////////////////// - void GetKeyInfo(int key, const char*& description, float& duration); - void SerializeKey(IEventKey& key, XmlNodeRef& keyNode, bool bLoading); - void SetKey(int index, IKey* key); + void GetKeyInfo(int key, const char*& description, float& duration) override; + void SerializeKey(IEventKey& key, XmlNodeRef& keyNode, bool bLoading) override; + void SetKey(int index, IKey* key) override; void InitPostLoad(IAnimSequence* sequence) override; static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h index fcc308e5c8..5878ee0269 100644 --- a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h @@ -26,19 +26,19 @@ public: CAnimMaterialNode(const int id); static void Initialize(); - virtual void SetName(const char* name); + void SetName(const char* name) override; ////////////////////////////////////////////////////////////////////////// // Overrides from CAnimNode ////////////////////////////////////////////////////////////////////////// - void Animate(SAnimContext& ec); + void Animate(SAnimContext& ec) override; void AddTrack(IAnimTrack* track) override; ////////////////////////////////////////////////////////////////////////// // Supported tracks description. ////////////////////////////////////////////////////////////////////////// - virtual unsigned int GetParamCount() const; - virtual CAnimParamType GetParamType(unsigned int nIndex) const; + unsigned int GetParamCount() const override; + CAnimParamType GetParamType(unsigned int nIndex) const override; AZStd::string GetParamName(const CAnimParamType& paramType) const override; virtual void GetKeyValueRange(float& fMin, float& fMax) const { fMin = m_fMinKeyValue; fMax = m_fMaxKeyValue; }; @@ -49,7 +49,7 @@ public: static void Reflect(AZ::ReflectContext* context); protected: - virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; + bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const override; void UpdateDynamicParamsInternal() override; private: diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.h b/Gems/Maestro/Code/Source/Cinematics/Movie.h index 8ab888178d..15295da353 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.h +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.h @@ -42,7 +42,7 @@ class CLightAnimWrapper { public: // ILightAnimWrapper interface - virtual bool Resolve(); + bool Resolve() override; public: static CLightAnimWrapper* Create(const char* name); @@ -80,116 +80,116 @@ public: CMovieSystem(ISystem* system); CMovieSystem(); - void Release() { delete this; }; + void Release() override { delete this; }; - void SetUser(IMovieUser* pUser) { m_pUser = pUser; } - IMovieUser* GetUser() { return m_pUser; } + void SetUser(IMovieUser* pUser) override { m_pUser = pUser; } + IMovieUser* GetUser() override { return m_pUser; } - ISystem* GetSystem() { return m_pSystem; } + ISystem* GetSystem() override { return m_pSystem; } - IAnimSequence* CreateSequence(const char* sequence, bool bLoad = false, uint32 id = 0, SequenceType = kSequenceTypeDefault, AZ::EntityId entityId = AZ::EntityId()); + IAnimSequence* CreateSequence(const char* sequence, bool bLoad = false, uint32 id = 0, SequenceType = kSequenceTypeDefault, AZ::EntityId entityId = AZ::EntityId()) override; - void AddSequence(IAnimSequence* pSequence); - void RemoveSequence(IAnimSequence* pSequence); + void AddSequence(IAnimSequence* pSequence) override; + void RemoveSequence(IAnimSequence* pSequence) override; IAnimSequence* FindLegacySequenceByName(const char* sequence) const override; IAnimSequence* FindSequence(const AZ::EntityId& componentEntitySequenceId) const override; IAnimSequence* FindSequenceById(uint32 id) const override; - IAnimSequence* GetSequence(int i) const; - int GetNumSequences() const; - IAnimSequence* GetPlayingSequence(int i) const; - int GetNumPlayingSequences() const; - bool IsCutScenePlaying() const; + IAnimSequence* GetSequence(int i) const override; + int GetNumSequences() const override; + IAnimSequence* GetPlayingSequence(int i) const override; + int GetNumPlayingSequences() const override; + bool IsCutScenePlaying() const override; uint32 GrabNextSequenceId() override { return m_nextSequenceId++; } void OnSetSequenceId(uint32 sequenceId) override; - int OnSequenceRenamed(const char* before, const char* after); - int OnCameraRenamed(const char* before, const char* after); + int OnSequenceRenamed(const char* before, const char* after) override; + int OnCameraRenamed(const char* before, const char* after) override; - bool AddMovieListener(IAnimSequence* pSequence, IMovieListener* pListener); - bool RemoveMovieListener(IAnimSequence* pSequence, IMovieListener* pListener); + bool AddMovieListener(IAnimSequence* pSequence, IMovieListener* pListener) override; + bool RemoveMovieListener(IAnimSequence* pSequence, IMovieListener* pListener) override; - void RemoveAllSequences(); + void RemoveAllSequences() override; ////////////////////////////////////////////////////////////////////////// // Sequence playback. ////////////////////////////////////////////////////////////////////////// void PlaySequence(const char* sequence, IAnimSequence* parentSeq = NULL, bool bResetFX = true, - bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX); + bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX) override; void PlaySequence(IAnimSequence* seq, IAnimSequence* parentSeq = NULL, bool bResetFX = true, - bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX); - void PlayOnLoadSequences(); + bool bTrackedSequence = false, float startTime = -FLT_MAX, float endTime = -FLT_MAX) override; + void PlayOnLoadSequences() override; - bool StopSequence(const char* sequence); - bool StopSequence(IAnimSequence* seq); - bool AbortSequence(IAnimSequence* seq, bool bLeaveTime = false); + bool StopSequence(const char* sequence) override; + bool StopSequence(IAnimSequence* seq) override; + bool AbortSequence(IAnimSequence* seq, bool bLeaveTime = false) override; - void StopAllSequences(); - void StopAllCutScenes(); + void StopAllSequences() override; + void StopAllCutScenes() override; void Pause(bool bPause); - void Reset(bool bPlayOnReset, bool bSeekToStart); - void StillUpdate(); - void PreUpdate(const float dt); - void PostUpdate(const float dt); - void Render(); + void Reset(bool bPlayOnReset, bool bSeekToStart) override; + void StillUpdate() override; + void PreUpdate(const float dt) override; + void PostUpdate(const float dt) override; + void Render() override; - void EnableFixedStepForCapture(float step); - void DisableFixedStepForCapture(); - void StartCapture(const ICaptureKey& key, int frame); - void EndCapture(); - void ControlCapture(); - bool IsCapturing() const; + void EnableFixedStepForCapture(float step) override; + void DisableFixedStepForCapture() override; + void StartCapture(const ICaptureKey& key, int frame) override; + void EndCapture() override; + void ControlCapture() override; + bool IsCapturing() const override; - bool IsPlaying(IAnimSequence* seq) const; + bool IsPlaying(IAnimSequence* seq) const override; - void Pause(); - void Resume(); + void Pause() override; + void Resume() override; - virtual void PauseCutScenes(); - virtual void ResumeCutScenes(); + void PauseCutScenes() override; + void ResumeCutScenes() override; - void SetRecording(bool recording) { m_bRecording = recording; }; - bool IsRecording() const { return m_bRecording; }; + void SetRecording(bool recording) override { m_bRecording = recording; }; + bool IsRecording() const override { return m_bRecording; }; - void EnableCameraShake(bool bEnabled){ m_bEnableCameraShake = bEnabled; }; + void EnableCameraShake(bool bEnabled) override{ m_bEnableCameraShake = bEnabled; }; - void SetCallback(IMovieCallback* pCallback) { m_pCallback = pCallback; } - IMovieCallback* GetCallback() { return m_pCallback; } + void SetCallback(IMovieCallback* pCallback) override { m_pCallback = pCallback; } + IMovieCallback* GetCallback() override { return m_pCallback; } void Callback(IMovieCallback::ECallbackReason Reason, IAnimNode* pNode); - const SCameraParams& GetCameraParams() const { return m_ActiveCameraParams; } - void SetCameraParams(const SCameraParams& Params); + const SCameraParams& GetCameraParams() const override { return m_ActiveCameraParams; } + void SetCameraParams(const SCameraParams& Params) override; - void SendGlobalEvent(const char* pszEvent); - void SetSequenceStopBehavior(ESequenceStopBehavior behavior); - IMovieSystem::ESequenceStopBehavior GetSequenceStopBehavior(); + void SendGlobalEvent(const char* pszEvent) override; + void SetSequenceStopBehavior(ESequenceStopBehavior behavior) override; + IMovieSystem::ESequenceStopBehavior GetSequenceStopBehavior() override; - float GetPlayingTime(IAnimSequence* pSeq); - bool SetPlayingTime(IAnimSequence* pSeq, float fTime); + float GetPlayingTime(IAnimSequence* pSeq) override; + bool SetPlayingTime(IAnimSequence* pSeq, float fTime) override; - float GetPlayingSpeed(IAnimSequence* pSeq); - bool SetPlayingSpeed(IAnimSequence* pSeq, float fTime); + float GetPlayingSpeed(IAnimSequence* pSeq) override; + bool SetPlayingSpeed(IAnimSequence* pSeq, float fTime) override; - bool GetStartEndTime(IAnimSequence* pSeq, float& fStartTime, float& fEndTime); - bool SetStartEndTime(IAnimSequence* pSeq, const float fStartTime, const float fEndTime); + bool GetStartEndTime(IAnimSequence* pSeq, float& fStartTime, float& fEndTime) override; + bool SetStartEndTime(IAnimSequence* pSeq, const float fStartTime, const float fEndTime) override; - void GoToFrame(const char* seqName, float targetFrame); + void GoToFrame(const char* seqName, float targetFrame) override; - const char* GetOverrideCamName() const + const char* GetOverrideCamName() const override { return m_mov_overrideCam->GetString(); } - virtual bool IsPhysicsEventsEnabled() const { return m_bPhysicsEventsEnabled; } - virtual void EnablePhysicsEvents(bool enable) { m_bPhysicsEventsEnabled = enable; } + bool IsPhysicsEventsEnabled() const override { return m_bPhysicsEventsEnabled; } + void EnablePhysicsEvents(bool enable) override { m_bPhysicsEventsEnabled = enable; } - virtual void EnableBatchRenderMode(bool bOn) { m_bBatchRenderMode = bOn; } - virtual bool IsInBatchRenderMode() const { return m_bBatchRenderMode; } + void EnableBatchRenderMode(bool bOn) override { m_bBatchRenderMode = bOn; } + bool IsInBatchRenderMode() const override { return m_bBatchRenderMode; } void SerializeNodeType(AnimNodeType& animNodeType, XmlNodeRef& xmlNode, bool bLoading, const uint version, int flags) override; - virtual void LoadParamTypeFromXml(CAnimParamType& animParamType, const XmlNodeRef& xmlNode, const uint version) override; - virtual void SaveParamTypeToXml(const CAnimParamType& animParamType, XmlNodeRef& xmlNode) override; - virtual void SerializeParamType(CAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version); + void LoadParamTypeFromXml(CAnimParamType& animParamType, const XmlNodeRef& xmlNode, const uint version) override; + void SaveParamTypeToXml(const CAnimParamType& animParamType, XmlNodeRef& xmlNode) override; + void SerializeParamType(CAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version) override; static const char* GetParamTypeName(const CAnimParamType& animParamType); @@ -226,8 +226,8 @@ private: void UpdateInternal(const float dt, const bool bPreUpdate); #ifdef MOVIESYSTEM_SUPPORT_EDITING - virtual AnimNodeType GetNodeTypeFromString(const char* pString) const; - virtual CAnimParamType GetParamTypeFromString(const char* pString) const; + AnimNodeType GetNodeTypeFromString(const char* pString) const override; + CAnimParamType GetParamTypeFromString(const char* pString) const override; #endif ISystem* m_pSystem; diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp index 10014a8700..b93215d397 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp @@ -89,13 +89,13 @@ namespace { AZ::Quaternion quat = LYQuaternionToAZQuaternion(localRotation); AZ::TransformBus::Event(m_cameraEntityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, quat); } - float GetFoV() const + float GetFoV() const override { float retFoV = DEFAULT_FOV; Camera::CameraRequestBus::EventResult(retFoV, m_cameraEntityId, &Camera::CameraComponentRequests::GetFovDegrees); return retFoV; } - float GetNearZ() const + float GetNearZ() const override { float retNearZ = DEFAULT_NEAR; Camera::CameraRequestBus::EventResult(retNearZ, m_cameraEntityId, &Camera::CameraComponentRequests::GetNearClipDistance); diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.h b/Gems/Maestro/Code/Source/Cinematics/SceneNode.h index d4d0410728..c577839fce 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.h @@ -65,12 +65,12 @@ public: ////////////////////////////////////////////////////////////////////////// // Overrides from CAnimNode ////////////////////////////////////////////////////////////////////////// - void Animate(SAnimContext& ec); - void CreateDefaultTracks(); + void Animate(SAnimContext& ec) override; + void CreateDefaultTracks() override; - virtual void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks); + void Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) override; - virtual void Activate(bool bActivate); + void Activate(bool bActivate) override; // overridden from IAnimNode/CAnimNode void OnStart() override; @@ -80,11 +80,11 @@ public: void OnLoop() override; ////////////////////////////////////////////////////////////////////////// - virtual unsigned int GetParamCount() const; - virtual CAnimParamType GetParamType(unsigned int nIndex) const; + unsigned int GetParamCount() const override; + CAnimParamType GetParamType(unsigned int nIndex) const override; - virtual void PrecacheStatic(float startTime) override; - virtual void PrecacheDynamic(float time) override; + void PrecacheStatic(float startTime) override; + void PrecacheDynamic(float time) override; static void Reflect(AZ::ReflectContext* context); @@ -92,7 +92,7 @@ public: static IAnimSequence* GetSequenceFromSequenceKey(const ISequenceKey& sequenceKey); protected: - virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; + bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const override; void ResetSounds() override; void ReleaseSounds(); // Stops audio @@ -111,7 +111,7 @@ private: void InterpolateCameras(SCameraParams& retInterpolatedCameraParams, ISceneCamera* firstCamera, ISelectKey& firstKey, ISelectKey& secondKey, float time); - virtual void InitializeTrackDefaultValue(IAnimTrack* pTrack, const CAnimParamType& paramType) override; + void InitializeTrackDefaultValue(IAnimTrack* pTrack, const CAnimParamType& paramType) override; // Cached parameters of node at given time. float m_time = 0.0f; diff --git a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h index 410dd41e2c..b5cb81dbc6 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h @@ -30,8 +30,8 @@ public: //----------------------------------------------------------------------------- //! IAnimTrack Method Overriding. //----------------------------------------------------------------------------- - virtual void GetKeyInfo(int key, const char*& description, float& duration); - virtual void SerializeKey(IScreenFaderKey& key, XmlNodeRef& keyNode, bool bLoading); + void GetKeyInfo(int key, const char*& description, float& duration) override; + void SerializeKey(IScreenFaderKey& key, XmlNodeRef& keyNode, bool bLoading) override; void SetFlags(int flags) override; void PreloadTextures(); diff --git a/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h b/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h index c55b2de520..435eccfb0b 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h @@ -29,11 +29,11 @@ public: AZ_CLASS_ALLOCATOR(CSoundTrack, AZ::SystemAllocator, 0); AZ_RTTI(CSoundTrack, "{B87D8805-F583-4154-B554-45518BC487F4}", IAnimTrack); - void GetKeyInfo(int key, const char*& description, float& duration); - void SerializeKey(ISoundKey& key, XmlNodeRef& keyNode, bool bLoading); + void GetKeyInfo(int key, const char*& description, float& duration) override; + void SerializeKey(ISoundKey& key, XmlNodeRef& keyNode, bool bLoading) override; //! Check if track is masked - virtual bool IsMasked(const uint32 mask) const { return (mask & eTrackMask_MaskSound) != 0; } + bool IsMasked(const uint32 mask) const override { return (mask & eTrackMask_MaskSound) != 0; } bool UsesMute() const override { return true; } diff --git a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h index 13a6549220..b0a7de63a7 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h @@ -70,9 +70,9 @@ public: ////////////////////////////////////////////////////////////////////////// // Overrides of IAnimTrack. ////////////////////////////////////////////////////////////////////////// - void GetKeyInfo(int key, const char*& description, float& duration); - void SerializeKey(IEventKey& key, XmlNodeRef& keyNode, bool bLoading); - void SetKey(int index, IKey* key); + void GetKeyInfo(int key, const char*& description, float& duration) override; + void SerializeKey(IEventKey& key, XmlNodeRef& keyNode, bool bLoading) override; + void SetKey(int index, IKey* key) override; void InitPostLoad(IAnimSequence* sequence) override; static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h b/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h index 83caaeea19..76b21faff4 100644 --- a/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h +++ b/Gems/Maestro/Code/Source/Components/EditorSequenceComponent.h @@ -78,7 +78,7 @@ namespace Maestro ////////////////////////////////////////////////////////////////////////// // TickBus - used to refresh property displays when values are animated - virtual void OnTick(float deltaTime, AZ::ScriptTimePoint time); + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; ////////////////////////////////////////////////////////////////////////// // TODO - this should be on a Bus, right? From 61247f8019b99248a0be9cf47632686294828b2b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:22:37 -0700 Subject: [PATCH 069/274] Gems/PhysX Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/PhysX/Code/Source/EditorColliderComponent.h | 2 +- Gems/PhysX/Code/Source/EditorShapeColliderComponent.h | 2 +- .../PhysXCharacters/Components/CharacterControllerComponent.h | 2 +- Gems/PhysX/Code/Source/Pipeline/HeightFieldAssetHandler.h | 2 +- Gems/PhysX/Code/Source/Pipeline/MeshAssetHandler.h | 2 +- Gems/PhysX/Code/Tests/TestColliderComponent.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index 50cf9d0c8b..1331fd08b6 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -144,7 +144,7 @@ namespace PhysX void OnDeselected() override; // DisplayCallback - void Display(AzFramework::DebugDisplayRequests& debugDisplay) const; + void Display(AzFramework::DebugDisplayRequests& debugDisplay) const override; void DisplayMeshCollider(AzFramework::DebugDisplayRequests& debugDisplay) const; void DisplayUnscaledPrimitiveCollider(AzFramework::DebugDisplayRequests& debugDisplay) const; void DisplayScaledPrimitiveCollider(AzFramework::DebugDisplayRequests& debugDisplay) const; diff --git a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.h b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.h index 47da6eb772..792d3c4327 100644 --- a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.h @@ -129,7 +129,7 @@ namespace PhysX void OnShapeChanged(LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons changeReason) override; // DisplayCallback - void Display(AzFramework::DebugDisplayRequests& debugDisplay) const; + void Display(AzFramework::DebugDisplayRequests& debugDisplay) const override; // ColliderShapeRequestBus AZ::Aabb GetColliderShapeAabb() override; diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h index a5b64c9c76..02de77568e 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h @@ -108,7 +108,7 @@ namespace PhysX // CharacterControllerRequestBus void Resize(float height) override; float GetHeight() override; - void SetHeight(float height); + void SetHeight(float height) override; float GetRadius() override; void SetRadius(float radius) override; float GetHalfSideExtent() override; diff --git a/Gems/PhysX/Code/Source/Pipeline/HeightFieldAssetHandler.h b/Gems/PhysX/Code/Source/Pipeline/HeightFieldAssetHandler.h index eb99a7e306..b1f55027b8 100644 --- a/Gems/PhysX/Code/Source/Pipeline/HeightFieldAssetHandler.h +++ b/Gems/PhysX/Code/Source/Pipeline/HeightFieldAssetHandler.h @@ -52,7 +52,7 @@ namespace PhysX // AZ::AssetTypeInfoBus AZ::Data::AssetType GetAssetType() const override; void GetAssetTypeExtensions(AZStd::vector& extensions) override; - const char* GetAssetTypeDisplayName() const; + const char* GetAssetTypeDisplayName() const override; const char* GetBrowserIcon() const override; const char* GetGroup() const override; AZ::Uuid GetComponentTypeId() const override; diff --git a/Gems/PhysX/Code/Source/Pipeline/MeshAssetHandler.h b/Gems/PhysX/Code/Source/Pipeline/MeshAssetHandler.h index ccaddc0c86..0cb8a58b65 100644 --- a/Gems/PhysX/Code/Source/Pipeline/MeshAssetHandler.h +++ b/Gems/PhysX/Code/Source/Pipeline/MeshAssetHandler.h @@ -48,7 +48,7 @@ namespace PhysX // AZ::AssetTypeInfoBus AZ::Data::AssetType GetAssetType() const override; void GetAssetTypeExtensions(AZStd::vector& extensions) override; - const char* GetAssetTypeDisplayName() const; + const char* GetAssetTypeDisplayName() const override; const char* GetBrowserIcon() const override; const char* GetGroup() const override; AZ::Uuid GetComponentTypeId() const override; diff --git a/Gems/PhysX/Code/Tests/TestColliderComponent.h b/Gems/PhysX/Code/Tests/TestColliderComponent.h index 4df96a9ff1..91d3f16122 100644 --- a/Gems/PhysX/Code/Tests/TestColliderComponent.h +++ b/Gems/PhysX/Code/Tests/TestColliderComponent.h @@ -49,7 +49,7 @@ namespace UnitTest m_componentModeDelegate.Disconnect(); } - void SetColliderOffset(const AZ::Vector3& offset) { m_offset = offset; } + void SetColliderOffset(const AZ::Vector3& offset) override { m_offset = offset; } AZ::Vector3 GetColliderOffset() override { return m_offset; } void SetColliderRotation(const AZ::Quaternion& rotation) override { m_rotation = rotation; } AZ::Quaternion GetColliderRotation() override { return m_rotation; } From 5cb3ccfbada02b5a2a3dd94d0fe467cc6210d753 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:23:21 -0700 Subject: [PATCH 070/274] Gems/PythonAssetBuilder Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../PythonAssetBuilder/Code/Tests/PythonBuilderTestShared.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/PythonAssetBuilder/Code/Tests/PythonBuilderTestShared.h b/Gems/PythonAssetBuilder/Code/Tests/PythonBuilderTestShared.h index 3a16e28ee0..eb01d5011b 100644 --- a/Gems/PythonAssetBuilder/Code/Tests/PythonBuilderTestShared.h +++ b/Gems/PythonAssetBuilder/Code/Tests/PythonBuilderTestShared.h @@ -37,7 +37,7 @@ namespace UnitTest return response; } - AssetBuilderSDK::ProcessJobResponse OnProcessJobRequest(const AssetBuilderSDK::ProcessJobRequest& request) + AssetBuilderSDK::ProcessJobResponse OnProcessJobRequest(const AssetBuilderSDK::ProcessJobRequest& request) override { if (request.m_sourceFileUUID.IsNull()) { @@ -49,12 +49,12 @@ namespace UnitTest return response; } - void OnShutdown() + void OnShutdown() override { ++m_onShutdownCount; } - void OnCancel() + void OnCancel() override { ++m_onCancelCount; } From e317585e60534cb5669edb74e060576c1d7fe658 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:23:35 -0700 Subject: [PATCH 071/274] Gems/SceneLoggingExample Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../SceneLoggingExample/Code/Behaviors/LoggingGroupBehavior.h | 4 ++-- .../Code/Processors/LoadingTrackingProcessor.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/SceneLoggingExample/Code/Behaviors/LoggingGroupBehavior.h b/Gems/SceneLoggingExample/Code/Behaviors/LoggingGroupBehavior.h index ae1989a284..a3ed7c1b20 100644 --- a/Gems/SceneLoggingExample/Code/Behaviors/LoggingGroupBehavior.h +++ b/Gems/SceneLoggingExample/Code/Behaviors/LoggingGroupBehavior.h @@ -28,8 +28,8 @@ namespace SceneLoggingExample ~LoggingGroupBehavior() override = default; - void Activate(); - void Deactivate(); + void Activate() override; + void Deactivate() override; static void Reflect(AZ::ReflectContext* context); void GetCategoryAssignments(CategoryRegistrationList& categories, const AZ::SceneAPI::Containers::Scene& scene) override; diff --git a/Gems/SceneLoggingExample/Code/Processors/LoadingTrackingProcessor.h b/Gems/SceneLoggingExample/Code/Processors/LoadingTrackingProcessor.h index d6480b7dcd..959098cb97 100644 --- a/Gems/SceneLoggingExample/Code/Processors/LoadingTrackingProcessor.h +++ b/Gems/SceneLoggingExample/Code/Processors/LoadingTrackingProcessor.h @@ -34,7 +34,7 @@ namespace SceneLoggingExample RequestingApplication requester) override; AZ::SceneAPI::Events::LoadingResult LoadAsset(AZ::SceneAPI::Containers::Scene& scene, const AZStd::string& path, const AZ::Uuid& guid, RequestingApplication requester) override; - void FinalizeAssetLoading(AZ::SceneAPI::Containers::Scene& scene, RequestingApplication requester); + void FinalizeAssetLoading(AZ::SceneAPI::Containers::Scene& scene, RequestingApplication requester) override; AZ::SceneAPI::Events::ProcessingResult UpdateManifest(AZ::SceneAPI::Containers::Scene& scene, ManifestAction action, RequestingApplication requester) override; From 1d53200eda77a0aa8db7edd65ed4f9bab3fd26e5 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:23:49 -0700 Subject: [PATCH 072/274] Gems/SceneProcessing Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Config/SettingsObjects/FileSoftNameSetting.h | 2 +- .../Code/Source/Config/Widgets/GraphTypeSelector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/SceneProcessing/Code/Source/Config/SettingsObjects/FileSoftNameSetting.h b/Gems/SceneProcessing/Code/Source/Config/SettingsObjects/FileSoftNameSetting.h index d6dcdb9de9..15c407a0cb 100644 --- a/Gems/SceneProcessing/Code/Source/Config/SettingsObjects/FileSoftNameSetting.h +++ b/Gems/SceneProcessing/Code/Source/Config/SettingsObjects/FileSoftNameSetting.h @@ -68,7 +68,7 @@ namespace AZ const char* virtualType, bool inclusive, std::initializer_list graphTypes); ~FileSoftNameSetting() override = default; - bool IsVirtualType(const SceneAPI::Containers::Scene& scene, SceneAPI::Containers::SceneGraph::NodeIndex node) const; + bool IsVirtualType(const SceneAPI::Containers::Scene& scene, SceneAPI::Containers::SceneGraph::NodeIndex node) const override; static void Reflect(AZ::ReflectContext* context); diff --git a/Gems/SceneProcessing/Code/Source/Config/Widgets/GraphTypeSelector.h b/Gems/SceneProcessing/Code/Source/Config/Widgets/GraphTypeSelector.h index 19ab410384..813f791310 100644 --- a/Gems/SceneProcessing/Code/Source/Config/Widgets/GraphTypeSelector.h +++ b/Gems/SceneProcessing/Code/Source/Config/Widgets/GraphTypeSelector.h @@ -32,7 +32,7 @@ namespace AZ QWidget* CreateGUI(QWidget* parent) override; u32 GetHandlerName() const override; - bool AutoDelete() const; + bool AutoDelete() const override; bool IsDefaultHandler() const override; From 711b332ebe1fe84270afc660f8f2bc5d61761d87 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:24:15 -0700 Subject: [PATCH 073/274] Gems/ScriptCanvas* Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Editor/Assets/ScriptCanvasAssetTracker.h | 2 +- .../Framework/ScriptCanvasTraceUtilities.h | 18 +++++++++--------- .../Components/DynamicSlotComponent.h | 6 +++--- .../GraphCanvas/Components/MappingComponent.h | 8 ++++---- .../NodeDescriptors/NodeDescriptorComponent.h | 6 +++--- ...EventReceiverEventNodeDescriptorComponent.h | 2 +- .../VariableNodeDescriptorComponent.h | 2 +- .../ScriptCanvasColorDataInterface.h | 2 +- .../ScriptCanvasVariableDataInterface.h | 14 +++++++------- .../ScriptCanvasVectorDataInterface.h | 2 +- ...ptCanvasEnumComboBoxPropertyDataInterface.h | 2 +- .../ScriptCanvasPropertyDataInterface.h | 2 +- .../ScriptCanvas/Assets/ScriptCanvasAsset.h | 4 ++-- .../ScriptCanvas/Components/EditorGraph.h | 6 +++--- .../ScriptCanvas/Components/GraphUpgrade.h | 2 +- Gems/ScriptCanvas/Code/Editor/Settings.h | 2 +- .../View/EditCtrls/GenericLineEditCtrl.h | 2 +- .../ScriptCanvas/Code/Editor/SystemComponent.h | 4 ++-- .../Code/Editor/View/Widgets/CanvasWidget.h | 2 +- .../LoggingAssetDataAggregator.h | 18 +++++++++--------- .../LiveLoggingDataAggregator.h | 4 ++-- .../LiveLoggingWindowSession.h | 4 ++-- .../LoggingPanel/LoggingDataAggregator.h | 2 +- .../LoggingPanel/LoggingWindowTreeItems.h | 2 +- .../FunctionNodePaletteTreeItemTypes.h | 4 ++-- .../ScriptEventsNodePaletteTreeItemTypes.h | 4 ++-- .../SpecializedNodePaletteTreeItemTypes.h | 4 ++-- .../VariablePanel/GraphVariablesTableView.h | 2 +- .../Code/Editor/View/Windows/MainWindow.h | 14 +++++++------- .../Code/Include/ScriptCanvas/Core/Graph.h | 6 +++--- .../DataValidation/InvalidVariableTypeEvent.h | 8 ++++---- .../DataValidation/ScopedDataConnectionEvent.h | 8 ++++---- .../ScriptEventVersionMismatch.h | 8 ++++---- .../DataValidation/UnknownEndpointEvent.h | 2 +- .../ExecutionValidation/UnusedNodeEvent.h | 2 +- .../ParsingValidation/ParsingValidations.h | 2 +- .../Internal/Nodes/StringFormatted.h | 4 +--- .../Libraries/Core/EBusEventHandler.h | 4 ++-- .../ScriptCanvas/Libraries/Core/Method.h | 2 +- .../ScriptCanvas/Libraries/Logic/Cycle.h | 4 ++-- .../ScriptCanvas/Libraries/Logic/IsNull.h | 2 +- .../Libraries/Logic/OrderedSequencer.h | 4 ++-- .../Libraries/Logic/TargetedSequencer.h | 4 ++-- .../Libraries/Logic/WeightedRandomSequencer.h | 2 +- .../Include/ScriptCanvas/SystemComponent.h | 2 +- .../Code/scriptcanvasgem_debugger_files.cmake | 1 + .../CreateElementsActions.h | 6 +++--- .../ScriptCanvasActions/ElementInteractions.h | 8 ++++---- .../ScriptCanvasActions/VariableActions.h | 4 ++-- .../EditorAutomationStates/EditorViewStates.h | 2 +- .../Include/ScriptCanvasDeveloperEditor/Mock.h | 2 +- .../ScriptCanvasDeveloperEditor/WrapperMock.h | 2 +- .../Editor/Source/EditorAutomationTestDialog.h | 2 +- .../EditorAutomationTests/GraphCreationTests.h | 4 ++-- .../Framework/ScriptCanvasTestUtilities.h | 2 +- .../Code/Source/ScriptCanvasTestBus.cpp | 2 +- .../Code/Tests/ScriptCanvas_MethodOverload.cpp | 2 +- 57 files changed, 123 insertions(+), 124 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetTracker.h b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetTracker.h index 6101f292a1..4850e669ff 100644 --- a/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetTracker.h +++ b/Gems/ScriptCanvas/Code/Editor/Assets/ScriptCanvasAssetTracker.h @@ -86,7 +86,7 @@ namespace ScriptCanvasEditor void UpdateFileState(AZ::Data::AssetId assetId, Tracker::ScriptCanvasFileState state) override; AssetTrackerRequests::AssetList GetUnsavedAssets() override; - AssetTrackerRequests::AssetList GetAssets(); + AssetTrackerRequests::AssetList GetAssets() override; AssetTrackerRequests::AssetList GetAssetsIf(AZStd::function pred = []() { return true; }) override; AZ::EntityId GetSceneEntityIdFromEditorEntityId(AZ::Data::AssetId assetId, AZ::EntityId editorEntityId) override; diff --git a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasTraceUtilities.h b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasTraceUtilities.h index e9a850a2a4..a87f4450c2 100644 --- a/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasTraceUtilities.h +++ b/Gems/ScriptCanvas/Code/Editor/Framework/ScriptCanvasTraceUtilities.h @@ -128,15 +128,15 @@ namespace ScriptCanvasEditor } } - bool OnPreAssert(const char*, int, const char*, const char*) { return suppressPreAssert; } - bool OnAssert(const char*) { return suppressAssert; } - bool OnException(const char*) { return suppressException; } - bool OnPreError(const char*, const char*, int, const char*, const char*) { return suppressPreError; } - bool OnError(const char*, const char*) { return suppressError; } - bool OnPreWarning(const char*, const char*, int, const char*, const char*) { return suppressPreWarning; } - bool OnWarning(const char*, const char*) { return suppressWarning; } - bool OnPrintf(const char*, const char*) { return suppressPrintf; } - bool OnOutput(const char*, const char*) { return suppressAllOutput; } + bool OnPreAssert(const char*, int, const char*, const char*) override { return suppressPreAssert; } + bool OnAssert(const char*) override { return suppressAssert; } + bool OnException(const char*) override { return suppressException; } + bool OnPreError(const char*, const char*, int, const char*, const char*) override { return suppressPreError; } + bool OnError(const char*, const char*) override { return suppressError; } + bool OnPreWarning(const char*, const char*, int, const char*, const char*) override { return suppressPreWarning; } + bool OnWarning(const char*, const char*) override { return suppressWarning; } + bool OnPrintf(const char*, const char*) override { return suppressPrintf; } + bool OnOutput(const char*, const char*) override { return suppressAllOutput; } void SuppressPreAssert(bool suppress) override { suppressPreAssert = suppress; } void SuppressAssert(bool suppress)override { suppressAssert = suppress; } diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/DynamicSlotComponent.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/DynamicSlotComponent.h index 5f1372d8c3..a30e6c999f 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/DynamicSlotComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/DynamicSlotComponent.h @@ -33,9 +33,9 @@ namespace ScriptCanvasEditor ~DynamicSlotComponent() override = default; // AZ::Component - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // GraphCanvas::SceneMemberNotificationBus diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/MappingComponent.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/MappingComponent.h index f5345f8bc8..fdc5ebc9fa 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/MappingComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/MappingComponent.h @@ -31,8 +31,8 @@ namespace ScriptCanvasEditor SceneMemberMappingComponent(const AZ::EntityId& sourceId); ~SceneMemberMappingComponent() = default; - void Activate(); - void Deactivate(); + void Activate() override; + void Deactivate() override; // SceneMemberMappingConfigurationRequestBus void ConfigureMapping(const AZ::EntityId& scriptCanvasMemberId) override; @@ -68,8 +68,8 @@ namespace ScriptCanvasEditor SlotMappingComponent(const AZ::EntityId& sourceId); ~SlotMappingComponent() = default; - void Activate(); - void Deactivate(); + void Activate() override; + void Deactivate() override; // GraphCanvas::NodeNotificationBus void OnAddedToScene(const AZ::EntityId&) override; diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h index c885c26624..1c42d1bdb0 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/NodeDescriptorComponent.h @@ -33,9 +33,9 @@ namespace ScriptCanvasEditor ~NodeDescriptorComponent() override = default; // Component - void Init(); - void Activate(); - void Deactivate(); + void Init() override; + void Activate() override; + void Deactivate() override; //// // NodeDescriptorBus::Handler diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/ScriptEventReceiverEventNodeDescriptorComponent.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/ScriptEventReceiverEventNodeDescriptorComponent.h index 7a991fc791..4a75432ad9 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/ScriptEventReceiverEventNodeDescriptorComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/ScriptEventReceiverEventNodeDescriptorComponent.h @@ -74,7 +74,7 @@ namespace ScriptCanvasEditor //// // ScriptEventReceiveNodeDescriptorNotifications - void OnScriptEventReloaded(const AZ::Data::Asset& asset); + void OnScriptEventReloaded(const AZ::Data::Asset& asset) override; //// protected: diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h index 9a14a7ca23..be5eacc397 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/Components/NodeDescriptors/VariableNodeDescriptorComponent.h @@ -52,7 +52,7 @@ namespace ScriptCanvasEditor //// // VariableNodeDescriptorBus - ScriptCanvas::VariableId GetVariableId() const; + ScriptCanvas::VariableId GetVariableId() const override; //// protected: diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasColorDataInterface.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasColorDataInterface.h index b7db5a4e08..37d5ba0181 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasColorDataInterface.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasColorDataInterface.h @@ -131,7 +131,7 @@ namespace ScriptCanvasEditor return "vectorized"; } - virtual AZStd::string GetElementStyle(int index) const + AZStd::string GetElementStyle(int index) const override { return AZStd::string::format("vector_%i", index); } diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVariableDataInterface.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVariableDataInterface.h index 7b93dc3a71..29dc17deca 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVariableDataInterface.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVariableDataInterface.h @@ -88,12 +88,12 @@ namespace ScriptCanvasEditor //// // GeneralEditorNotifications - void OnUndoRedoBegin() + void OnUndoRedoBegin() override { ScriptCanvas::GraphVariableManagerNotificationBus::Handler::BusDisconnect(); } - void OnUndoRedoEnd() + void OnUndoRedoEnd() override { FinalizeActivation(); } @@ -250,7 +250,7 @@ namespace ScriptCanvasEditor } // SystemTickBus - void OnSystemTick() + void OnSystemTick() override { AZ::SystemTickBus::Handler::BusDisconnect(); AssignIndex(m_variableTypeModel.GetDefaultIndex()); @@ -440,7 +440,7 @@ namespace ScriptCanvasEditor } // SystemTickBus - void OnSystemTick() + void OnSystemTick() override { AZ::SystemTickBus::Handler::BusDisconnect(); AssignIndex(m_variableTypeModel.GetDefaultIndex()); @@ -449,7 +449,7 @@ namespace ScriptCanvasEditor //// // NodeNotificationBus - void OnSlotDisplayTypeChanged(const ScriptCanvas::SlotId& slotId, [[maybe_unused]] const ScriptCanvas::Data::Type& slotType) + void OnSlotDisplayTypeChanged(const ScriptCanvas::SlotId& slotId, [[maybe_unused]] const ScriptCanvas::Data::Type& slotType) override { if (slotId == GetSlotId()) { @@ -482,7 +482,7 @@ namespace ScriptCanvasEditor //// // EndpointNotificationBus - void OnEndpointReferenceChanged(const ScriptCanvas::VariableId& variableId) + void OnEndpointReferenceChanged(const ScriptCanvas::VariableId& variableId) override { ScriptCanvas::VariableNotificationBus::Handler::BusDisconnect(); ScriptCanvas::VariableNotificationBus::Handler::BusConnect(ScriptCanvas::GraphScopedVariableId(GetScriptCanvasId(), variableId)); @@ -490,7 +490,7 @@ namespace ScriptCanvasEditor SignalValueChanged(); } - void OnSlotRecreated() + void OnSlotRecreated() override { ScriptCanvas::Slot* slot = GetSlot(); diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVectorDataInterface.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVectorDataInterface.h index 717022c19d..6d76d5504a 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVectorDataInterface.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/DataInterfaces/ScriptCanvasVectorDataInterface.h @@ -103,7 +103,7 @@ namespace ScriptCanvasEditor return "???"; } - AZStd::string GetStyle() const + AZStd::string GetStyle() const override { return "vectorized"; } diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasEnumComboBoxPropertyDataInterface.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasEnumComboBoxPropertyDataInterface.h index 6faac13659..c283fc8802 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasEnumComboBoxPropertyDataInterface.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasEnumComboBoxPropertyDataInterface.h @@ -50,7 +50,7 @@ namespace ScriptCanvasEditor return m_comboBoxModel.GetIndexForValue(dataValue); } - QString GetDisplayString() const + QString GetDisplayString() const override { int32_t dataValue = GetValue(); return m_comboBoxModel.GetNameForValue(dataValue); diff --git a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasPropertyDataInterface.h b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasPropertyDataInterface.h index 768773e676..f69315bc86 100644 --- a/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasPropertyDataInterface.h +++ b/Gems/ScriptCanvas/Code/Editor/GraphCanvas/PropertyInterfaces/ScriptCanvasPropertyDataInterface.h @@ -177,7 +177,7 @@ namespace ScriptCanvasEditor return m_comboBoxModel.GetIndexForValue(dataValue); } - QString GetDisplayString() const + QString GetDisplayString() const override { DataType dataValue = this->GetValue(); return m_comboBoxModel.GetNameForValue(dataValue); diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAsset.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAsset.h index 9942e349c5..fdc8cbc1d8 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAsset.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Assets/ScriptCanvasAsset.h @@ -81,8 +81,8 @@ namespace ScriptCanvasEditor ScriptCanvas::Graph* GetScriptCanvasGraph() const; using Description = ScriptCanvasAssetDescription; - ScriptCanvas::ScriptCanvasData& GetScriptCanvasData(); - const ScriptCanvas::ScriptCanvasData& GetScriptCanvasData() const; + ScriptCanvas::ScriptCanvasData& GetScriptCanvasData() override; + const ScriptCanvas::ScriptCanvasData& GetScriptCanvasData() const override; }; } diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h index cb6689091b..6f73e84493 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h @@ -248,8 +248,8 @@ namespace ScriptCanvasEditor GraphCanvas::GraphId GetGraphCanvasGraphId() const override; - AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* > GetGraphCanvasSaveData(); - void UpdateGraphCanvasSaveData(const AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* >& saveData); + AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* > GetGraphCanvasSaveData() override; + void UpdateGraphCanvasSaveData(const AZStd::unordered_map< AZ::EntityId, GraphCanvas::EntitySaveDataContainer* >& saveData) override; NodeIdPair CreateCustomNode(const AZ::Uuid& typeId, const AZ::Vector2& position) override; @@ -325,7 +325,7 @@ namespace ScriptCanvasEditor } protected: - void PostRestore(const UndoData& restoredData); + void PostRestore(const UndoData& restoredData) override; void UnregisterToast(const GraphCanvas::ToastId& toastId); diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h index 89ee0f3b55..fb6e109156 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h @@ -82,7 +82,7 @@ namespace ScriptCanvasEditor StateMachine* GetStateMachine() override { return m_stateMachine; } - virtual int GetStateId() const { return Traits::StateID(); } + int GetStateId() const override { return Traits::StateID(); } static int StateID() { return Traits::StateID(); } diff --git a/Gems/ScriptCanvas/Code/Editor/Settings.h b/Gems/ScriptCanvas/Code/Editor/Settings.h index b282e114ac..7eff40ec43 100644 --- a/Gems/ScriptCanvas/Code/Editor/Settings.h +++ b/Gems/ScriptCanvas/Code/Editor/Settings.h @@ -40,7 +40,7 @@ namespace ScriptCanvasEditor ScriptCanvasConstructPresets(); ~ScriptCanvasConstructPresets() override = default; - void InitializeConstructType(GraphCanvas::ConstructType constructType); + void InitializeConstructType(GraphCanvas::ConstructType constructType) override; }; class EditorWorkspace diff --git a/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h b/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h index 9b83819860..950fa8ef2e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h +++ b/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h @@ -59,7 +59,7 @@ namespace ScriptCanvasEditor void onChildLineEditValueChange(const QString& value); protected: - virtual void focusInEvent(QFocusEvent* e); + void focusInEvent(QFocusEvent* e) override; private: QLineEdit* m_pLineEdit; diff --git a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h index ba850401d6..3e18262c98 100644 --- a/Gems/ScriptCanvas/Code/Editor/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Editor/SystemComponent.h @@ -65,7 +65,7 @@ namespace ScriptCanvasEditor //////////////////////////////////////////////////////////////////////// // SystemRequestBus::Handler... void AddAsyncJob(AZStd::function&& jobFunc) override; - void GetEditorCreatableTypes(AZStd::unordered_set& outCreatableTypes); + void GetEditorCreatableTypes(AZStd::unordered_set& outCreatableTypes) override; void CreateEditorComponentsOnEntity(AZ::Entity* entity, const AZ::Data::AssetType& assetType) override; //////////////////////////////////////////////////////////////////////// @@ -110,7 +110,7 @@ namespace ScriptCanvasEditor //////////////////////////////////////////////////////////////////////// // IUpgradeRequests... - void ClearGraphsThatNeedUpgrade() + void ClearGraphsThatNeedUpgrade() override { m_assetsThatNeedManualUpgrade.clear(); } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.h index 2ebc71f785..9abb41aacc 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/CanvasWidget.h @@ -61,7 +61,7 @@ namespace ScriptCanvasEditor protected: - void resizeEvent(QResizeEvent *ev); + void resizeEvent(QResizeEvent *ev) override; void OnClicked(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/AssetWindowSession/LoggingAssetDataAggregator.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/AssetWindowSession/LoggingAssetDataAggregator.h index ae92586c4d..71efcbb017 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/AssetWindowSession/LoggingAssetDataAggregator.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/AssetWindowSession/LoggingAssetDataAggregator.h @@ -27,15 +27,15 @@ namespace ScriptCanvasEditor bool IsCapturingData() const override { return false; } protected: - void Visit(ScriptCanvas::AnnotateNodeSignal&); - void Visit(ScriptCanvas::ExecutionThreadEnd&); - void Visit(ScriptCanvas::ExecutionThreadBeginning&); - void Visit(ScriptCanvas::GraphActivation&); - void Visit(ScriptCanvas::GraphDeactivation&); - void Visit(ScriptCanvas::NodeStateChange&); - void Visit(ScriptCanvas::InputSignal&); - void Visit(ScriptCanvas::OutputSignal&); - void Visit(ScriptCanvas::VariableChange&); + void Visit(ScriptCanvas::AnnotateNodeSignal&) override; + void Visit(ScriptCanvas::ExecutionThreadEnd&) override; + void Visit(ScriptCanvas::ExecutionThreadBeginning&) override; + void Visit(ScriptCanvas::GraphActivation&) override; + void Visit(ScriptCanvas::GraphDeactivation&) override; + void Visit(ScriptCanvas::NodeStateChange&) override; + void Visit(ScriptCanvas::InputSignal&) override; + void Visit(ScriptCanvas::OutputSignal&) override; + void Visit(ScriptCanvas::VariableChange&) override; private: diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h index d26939a217..8efeba4613 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingDataAggregator.h @@ -38,8 +38,8 @@ namespace ScriptCanvasEditor void OnCurrentTargetChanged() override; //// - bool CanCaptureData() const; - bool IsCapturingData() const; + bool CanCaptureData() const override; + bool IsCapturingData() const override; void StartCaptureData(); void StopCaptureData(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h index ba2e5b4a56..3fa0cf8d01 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LiveWindowSession/LiveLoggingWindowSession.h @@ -97,8 +97,8 @@ namespace ScriptCanvasEditor //// // AzToolsFramework::EditorEntityContextNotificationBus::Handler - void OnStartPlayInEditorBegin(); - void OnStopPlayInEditor(); + void OnStartPlayInEditorBegin() override; + void OnStopPlayInEditor() override; //// // ScriptCavnas::Debugger::ServiceNotificationsBus diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingDataAggregator.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingDataAggregator.h index 0e4d35e270..9892245fa4 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingDataAggregator.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingDataAggregator.h @@ -88,7 +88,7 @@ namespace ScriptCanvasEditor AZ::NamedEntityId FindNamedEntityId(const AZ::EntityId& entityId) override; //// - virtual bool IsCapturingData() const = 0; + bool IsCapturingData() const override = 0; virtual bool CanCaptureData() const = 0; // Should be bus methods, but don't want to copy data diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingWindowTreeItems.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingWindowTreeItems.h index 751c1c30b7..862b231f3a 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingWindowTreeItems.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/LoggingPanel/LoggingWindowTreeItems.h @@ -115,7 +115,7 @@ namespace ScriptCanvasEditor protected: - bool OnMatchesFilter([[maybe_unused]] const DebugLogFilter& treeFilter) { return true; } + bool OnMatchesFilter([[maybe_unused]] const DebugLogFilter& treeFilter) override { return true; } UpdatePolicy m_updatePolicy; QTimer m_additionTimer; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.h index b03efa5813..479fed1097 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.h @@ -59,8 +59,8 @@ namespace ScriptCanvasEditor FunctionPaletteTreeItem(const char* name, const ScriptCanvas::Grammar::FunctionSourceId& sourceId, AZ::Data::Asset asset); ~FunctionPaletteTreeItem() = default; - GraphCanvas::GraphCanvasMimeEvent* CreateMimeEvent() const; - QVariant OnData(const QModelIndex& index, int role) const; + GraphCanvas::GraphCanvasMimeEvent* CreateMimeEvent() const override; + QVariant OnData(const QModelIndex& index, int role) const override; ScriptCanvas::Grammar::FunctionSourceId GetFunctionSourceId() const; AZ::Data::AssetId GetSourceAssetId() const; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h index c3b37369ca..f47a224564 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/ScriptEventsNodePaletteTreeItemTypes.h @@ -232,8 +232,8 @@ namespace ScriptCanvasEditor ScriptEventsEventNodePaletteTreeItem(const AZ::Data::AssetId& m_assetId, const ScriptEvents::Method& methodDefinition, const ScriptCanvas::EBusEventId& eventId); ~ScriptEventsEventNodePaletteTreeItem() = default; - GraphCanvas::GraphCanvasMimeEvent* CreateMimeEvent() const; - QVariant OnData(const QModelIndex& index, int role) const; + GraphCanvas::GraphCanvasMimeEvent* CreateMimeEvent() const override; + QVariant OnData(const QModelIndex& index, int role) const override; ScriptCanvas::EBusBusId GetBusIdentifier() const; ScriptCanvas::EBusEventId GetEventIdentifier() const; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/SpecializedNodePaletteTreeItemTypes.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/SpecializedNodePaletteTreeItemTypes.h index cfc056e705..244e2bf645 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/SpecializedNodePaletteTreeItemTypes.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/SpecializedNodePaletteTreeItemTypes.h @@ -25,7 +25,7 @@ namespace ScriptCanvasEditor CreateCommentNodeMimeEvent() = default; ~CreateCommentNodeMimeEvent() = default; - NodeIdPair ConstructNode(const AZ::EntityId& sceneId, const AZ::Vector2& scenePosition); + NodeIdPair ConstructNode(const AZ::EntityId& sceneId, const AZ::Vector2& scenePosition) override; bool ExecuteEvent(const AZ::Vector2& mousePosition, AZ::Vector2& sceneDropPosition, const AZ::EntityId& sceneId) override; }; @@ -54,7 +54,7 @@ namespace ScriptCanvasEditor CreateNodeGroupMimeEvent() = default; ~CreateNodeGroupMimeEvent() = default; - NodeIdPair ConstructNode(const GraphCanvas::GraphId& sceneId, const AZ::Vector2& scenePosition); + NodeIdPair ConstructNode(const GraphCanvas::GraphId& sceneId, const AZ::Vector2& scenePosition) override; bool ExecuteEvent(const AZ::Vector2& mousePosition, AZ::Vector2& sceneDropPosition, const GraphCanvas::GraphId& sceneId) override; }; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h index 27923fbe63..962aadb8c8 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/GraphVariablesTableView.h @@ -160,7 +160,7 @@ namespace ScriptCanvasEditor //// // GraphCanvas::SceneNotifications - void OnSelectionChanged(); + void OnSelectionChanged() override; //// void ApplyPreferenceSort(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h index d11d2f0052..ba5ff7f97f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.h @@ -272,7 +272,7 @@ namespace ScriptCanvasEditor private: // UIRequestBus QMainWindow* GetMainWindow() override { return qobject_cast(this); } - void OpenValidationPanel(); + void OpenValidationPanel() override; // // Undo Handlers @@ -299,9 +299,9 @@ namespace ScriptCanvasEditor bool ContainsGraph(const GraphCanvas::GraphId& graphId) const override; bool CloseGraph(const GraphCanvas::GraphId& graphId) override; - void CustomizeConnectionEntity(AZ::Entity* connectionEntity); + void CustomizeConnectionEntity(AZ::Entity* connectionEntity) override; - void ShowAssetPresetsMenu(GraphCanvas::ConstructType constructType); + void ShowAssetPresetsMenu(GraphCanvas::ConstructType constructType) override; GraphCanvas::ContextMenuAction::SceneReaction ShowSceneContextMenuWithGroup(const QPoint& screenPoint, const QPointF& scenePoint, AZ::EntityId groupTarget) override; @@ -327,8 +327,8 @@ namespace ScriptCanvasEditor //// //! ScriptCanvas::BatchOperationsNotificationBus - void OnCommandStarted(AZ::Crc32 commandTag); - void OnCommandFinished(AZ::Crc32 commandTag); + void OnCommandStarted(AZ::Crc32 commandTag) override; + void OnCommandFinished(AZ::Crc32 commandTag) override; // File menu void OnFileNew(); @@ -427,7 +427,7 @@ namespace ScriptCanvasEditor QVariant GetTabData(const AZ::Data::AssetId& assetId); //! GeneralRequestBus - AZ::Outcome OpenScriptCanvasAssetId(const AZ::Data::AssetId& assetId); + AZ::Outcome OpenScriptCanvasAssetId(const AZ::Data::AssetId& assetId) override; AZ::Outcome OpenScriptCanvasAsset(AZ::Data::AssetId scriptCanvasAssetId, int tabIndex = -1) override; AZ::Outcome OpenScriptCanvasAsset(const ScriptCanvasMemoryAsset& scriptCanvasAsset, int tabIndex = -1); int CloseScriptCanvasAsset(const AZ::Data::AssetId& assetId) override; @@ -497,7 +497,7 @@ namespace ScriptCanvasEditor float GetEdgePanningScrollSpeed() const override; GraphCanvas::EditorConstructPresets* GetConstructPresets() const override; - const GraphCanvas::ConstructTypePresetBucket* GetConstructTypePresetBucket(GraphCanvas::ConstructType constructType) const; + const GraphCanvas::ConstructTypePresetBucket* GetConstructTypePresetBucket(GraphCanvas::ConstructType constructType) const override; GraphCanvas::Styling::ConnectionCurveType GetConnectionCurveType() const override; GraphCanvas::Styling::ConnectionCurveType GetDataConnectionCurveType() const override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h index bb1ea21f30..46e8a103bb 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h @@ -109,11 +109,11 @@ namespace ScriptCanvas //! NOTE: There can be multiple Graph components on the same entity so calling FindComponent may not not return this GraphComponent AZ::Entity* GetGraphEntity() const override { return GetEntity(); } - Graph* GetGraph() { return this; } + Graph* GetGraph() override { return this; } GraphData* GetGraphData() override { return &m_graphData; } const GraphData* GetGraphDataConst() const override { return &m_graphData; } - const VariableData* GetVariableDataConst() const { return const_cast(this)->GetVariableData(); } + const VariableData* GetVariableDataConst() const override { return const_cast(this)->GetVariableData(); } bool AddGraphData(const GraphData&) override; void RemoveGraphData(const GraphData&) override; @@ -131,7 +131,7 @@ namespace ScriptCanvas /////////////////////////////////////////////////////////// // StatusRequestBus - void ValidateGraph(ValidationResults& validationEvents); + void ValidateGraph(ValidationResults& validationEvents) override; void ReportValidationResults(ValidationResults&) override { } //// diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidVariableTypeEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidVariableTypeEvent.h index 85ce975968..602e6626a1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidVariableTypeEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidVariableTypeEvent.h @@ -31,12 +31,12 @@ namespace ScriptCanvas SetDescription(AZStd::string::format("Variable with id %s has an invalid type.", variableId.ToString().c_str())); } - bool CanAutoFix() const + bool CanAutoFix() const override { return true; } - AZStd::string GetIdentifier() const + AZStd::string GetIdentifier() const override { return DataValidationIds::InvalidVariableTypeId; } @@ -46,12 +46,12 @@ namespace ScriptCanvas return m_variableId; } - AZ::Crc32 GetIdCrc() const + AZ::Crc32 GetIdCrc() const override { return DataValidationIds::InvalidVariableTypeCrc; } - AZStd::string_view GetTooltip() const + AZStd::string_view GetTooltip() const override { return "Invalid type for variable, auto fixing will remove all invalid variable nodes."; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScopedDataConnectionEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScopedDataConnectionEvent.h index 09c372da9a..0b2150448b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScopedDataConnectionEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScopedDataConnectionEvent.h @@ -59,17 +59,17 @@ namespace ScriptCanvas , targetNode.GetNodeName().data())); } - bool CanAutoFix() const + bool CanAutoFix() const override { return false; } - AZStd::string GetIdentifier() const + AZStd::string GetIdentifier() const override { return DataValidationIds::ScopedDataConnectionId; } - AZ::Crc32 GetIdCrc() const + AZ::Crc32 GetIdCrc() const override { return DataValidationIds::ScopedDataConnectionCrc; } @@ -79,7 +79,7 @@ namespace ScriptCanvas return m_connectionId; } - AZStd::string_view GetTooltip() const + AZStd::string_view GetTooltip() const override { return "Out of Scope Data Connection"; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScriptEventVersionMismatch.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScriptEventVersionMismatch.h index b23c241967..c0443f9cc2 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScriptEventVersionMismatch.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScriptEventVersionMismatch.h @@ -37,17 +37,17 @@ namespace ScriptCanvas SetDescription("The Script Event asset this node uses has changed. This node is no longer valid. You can fix this by deleting this node, re-adding it and reconnecting it."); } - bool CanAutoFix() const + bool CanAutoFix() const override { return false; } - AZStd::string GetIdentifier() const + AZStd::string GetIdentifier() const override { return DataValidationIds::ScriptEventVersionMismatchId; } - AZ::Crc32 GetIdCrc() const + AZ::Crc32 GetIdCrc() const override { return DataValidationIds::ScriptEventVersionMismatchCrc; } @@ -57,7 +57,7 @@ namespace ScriptCanvas return m_definition; } - AZStd::string_view GetTooltip() const + AZStd::string_view GetTooltip() const override { return "The Script Event asset has changed, you can fix this problem by deleting the out of date node and re-adding it to your graph."; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/UnknownEndpointEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/UnknownEndpointEvent.h index b654448dc6..36f12527a2 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/UnknownEndpointEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/UnknownEndpointEvent.h @@ -86,7 +86,7 @@ namespace ScriptCanvas return DataValidationIds::UnknownSourceEndpointCrc; } - AZStd::string_view GetTooltip() const + AZStd::string_view GetTooltip() const override { return "Unknown Source Endpoint"; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ExecutionValidation/UnusedNodeEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ExecutionValidation/UnusedNodeEvent.h index a49998e555..d2c028985f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ExecutionValidation/UnusedNodeEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ExecutionValidation/UnusedNodeEvent.h @@ -60,7 +60,7 @@ namespace ScriptCanvas } // HighlightEntityEffect - AZ::EntityId GetHighlightTarget() const + AZ::EntityId GetHighlightTarget() const override { return m_nodeId; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ParsingValidation/ParsingValidations.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ParsingValidation/ParsingValidations.h index ac8f41862e..a862cca2eb 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ParsingValidation/ParsingValidations.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Debugger/ValidationEvents/ParsingValidation/ParsingValidations.h @@ -43,7 +43,7 @@ namespace ScriptCanvas } // HighlightEntityEffect - AZ::EntityId GetHighlightTarget() const + AZ::EntityId GetHighlightTarget() const override { return m_nodeId; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodes/StringFormatted.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodes/StringFormatted.h index 205ae4ea60..2a327bd37d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodes/StringFormatted.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodes/StringFormatted.h @@ -40,7 +40,7 @@ namespace ScriptCanvas return true; } - AZ::Outcome GetDependencies() const + AZ::Outcome GetDependencies() const override { return AZ::Success(DependencyReport{}); } @@ -49,8 +49,6 @@ namespace ScriptCanvas AZ_INLINE const NamedSlotIdMap& GetNamedSlotIdMap() const { return m_formatSlotMap; } AZ_INLINE const int GetPostDecimalPrecision() const { return m_numericPrecision; } - - protected: // This is a map that binds the index into m_unresolvedString to the SlotId that needs to be checked for a valid datum. diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h index c6d4a8b512..05419f3ec3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h @@ -102,7 +102,7 @@ namespace ScriptCanvas AZ::Outcome GetFunctionCallName(const Slot* /*slot*/) const override; bool IsEBusAddressed() const override; - AZStd::optional GetEventIndex(AZStd::string eventName) const; + AZStd::optional GetEventIndex(AZStd::string eventName) const override; const EBusEventEntry* FindEvent(const AZStd::string& name) const; AZStd::string GetEBusName() const override; bool IsAutoConnected() const override; @@ -138,7 +138,7 @@ namespace ScriptCanvas void SetAutoConnectToGraphOwner(bool enabled); - void OnDeserialize(); + void OnDeserialize() override; #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// void OnWriteEnd(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h index 5584212048..1f1daddc71 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h @@ -107,7 +107,7 @@ namespace ScriptCanvas SlotId GetBusSlotId() const; - void OnDeserialize(); + void OnDeserialize() override; #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// void OnWriteEnd(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/Cycle.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/Cycle.h index 17c203626f..7edd83794a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/Cycle.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/Cycle.h @@ -36,9 +36,9 @@ namespace ScriptCanvas void OnConfigured() override; void ConfigureVisualExtensions() override; - bool CanDeleteSlot(const SlotId& slotId) const; + bool CanDeleteSlot(const SlotId& slotId) const override; - SlotId HandleExtension(AZ::Crc32 extensionId); + SlotId HandleExtension(AZ::Crc32 extensionId) override; AZ::Outcome GetDependencies() const override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/IsNull.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/IsNull.h index 71ea8870c2..24bcd8e5e5 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/IsNull.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/IsNull.h @@ -29,7 +29,7 @@ namespace ScriptCanvas IsNull(); - AZ::Outcome GetDependencies() const; + AZ::Outcome GetDependencies() const override; bool IsIfBranch() const override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/OrderedSequencer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/OrderedSequencer.h index 10517502a5..0547f59db0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/OrderedSequencer.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/OrderedSequencer.h @@ -30,13 +30,13 @@ namespace ScriptCanvas OrderedSequencer(); - bool CanDeleteSlot(const SlotId& slotId) const; + bool CanDeleteSlot(const SlotId& slotId) const override; AZ::Outcome GetDependencies() const override; ConstSlotsOutcome GetSlotsInExecutionThreadByTypeImpl(const Slot& executionSlot, CombinedSlotType targetSlotType, const Slot* /*executionChildSlot*/) const override; - SlotId HandleExtension(AZ::Crc32 extensionId); + SlotId HandleExtension(AZ::Crc32 extensionId) override; void OnInit() override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/TargetedSequencer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/TargetedSequencer.h index a2c4d93ef8..f4f590751a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/TargetedSequencer.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/TargetedSequencer.h @@ -33,9 +33,9 @@ namespace ScriptCanvas void OnConfigured() override; void ConfigureVisualExtensions() override; - bool CanDeleteSlot(const SlotId& slotId) const; + bool CanDeleteSlot(const SlotId& slotId) const override; - SlotId HandleExtension(AZ::Crc32 extensionId); + SlotId HandleExtension(AZ::Crc32 extensionId) override; // Script Canvas Translation... bool IsSwitchStatement() const override { return true; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/WeightedRandomSequencer.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/WeightedRandomSequencer.h index f9cbaac652..b51327b65d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/WeightedRandomSequencer.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Logic/WeightedRandomSequencer.h @@ -39,7 +39,7 @@ namespace ScriptCanvas void OnInit() override; void ConfigureVisualExtensions() override; - bool OnValidateNode(ValidationResults& validationResults); + bool OnValidateNode(ValidationResults& validationResults) override; SlotId HandleExtension(AZ::Crc32 extensionId) override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h index f208e3b9d4..7dbde3224e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h @@ -74,7 +74,7 @@ namespace ScriptCanvas ScriptCanvasId FindScriptCanvasId(AZ::Entity* graphEntity) override; ScriptCanvas::Node* GetNode(const AZ::EntityId&, const AZ::Uuid&) override; ScriptCanvas::Node* CreateNodeOnEntity(const AZ::EntityId& entityId, ScriptCanvasId scriptCanvasId, const AZ::Uuid& nodeType) override; - SystemComponentConfiguration GetSystemComponentConfiguration() + SystemComponentConfiguration GetSystemComponentConfiguration() override { SystemComponentConfiguration configuration; configuration.m_maxIterationsForInfiniteLoopDetection = m_infiniteLoopDetectionMaxIterations; diff --git a/Gems/ScriptCanvas/Code/scriptcanvasgem_debugger_files.cmake b/Gems/ScriptCanvas/Code/scriptcanvasgem_debugger_files.cmake index 38182dc251..0a68a9b175 100644 --- a/Gems/ScriptCanvas/Code/scriptcanvasgem_debugger_files.cmake +++ b/Gems/ScriptCanvas/Code/scriptcanvasgem_debugger_files.cmake @@ -35,6 +35,7 @@ set(FILES Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/DynamicDataTypeEvent.h Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidExpressionEvent.h Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidRandomSignalEvent.h + Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/InvalidVariableTypeEvent.h Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/ScopedDataConnectionEvent.h Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/SlotReferenceEvent.h Include/ScriptCanvas/Debugger/ValidationEvents/DataValidation/UnknownEndpointEvent.h diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.h index d2f1feb0d1..c9eda4c0bc 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/CreateElementsActions.h @@ -139,7 +139,7 @@ namespace ScriptCanvasDeveloper protected: - void OnActionsComplete(); + void OnActionsComplete() override; private: @@ -222,7 +222,7 @@ namespace ScriptCanvasDeveloper CreateGroupAction(GraphCanvas::EditorId editorGraph, GraphCanvas::GraphId graphId, CreationType creationType = CreationType::Hotkey); ~CreateGroupAction() override = default; - void SetupAction(); + void SetupAction() override; // GraphCanvas::SceneNotificationBus::Handler void OnNodeAdded(const AZ::EntityId& groupId, bool isPaste = false) override; @@ -236,7 +236,7 @@ namespace ScriptCanvasDeveloper void SetupToolbarAction(); void SetupHotkeyAction(); - void OnActionsComplete(); + void OnActionsComplete() override; private: diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.h index 4a83ab2637..b7498ff56e 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/ElementInteractions.h @@ -32,7 +32,7 @@ namespace ScriptCanvasDeveloper bool IsMissingPrecondition() override; EditorAutomationAction* GenerateMissingPreconditionAction() override; - void SetupAction(); + void SetupAction() override; private: @@ -66,9 +66,9 @@ namespace ScriptCanvasDeveloper ActionReport GenerateReport() const override; // SceneNotificaitonBus - void OnNodeRemoved(const AZ::EntityId& nodeId); + void OnNodeRemoved(const AZ::EntityId& nodeId) override; - void OnConnectionRemoved(const AZ::EntityId& connectionId); + void OnConnectionRemoved(const AZ::EntityId& connectionId) override; //// protected: @@ -98,7 +98,7 @@ namespace ScriptCanvasDeveloper MouseToNodePropertyEditorAction(GraphCanvas::SlotId slotId); ~MouseToNodePropertyEditorAction() override = default; - void SetupAction(); + void SetupAction() override; private: diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.h index 2ce49ba3ed..a8d7165feb 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationActions/ScriptCanvasActions/VariableActions.h @@ -96,7 +96,7 @@ namespace ScriptCanvasDeveloper bool IsMissingPrecondition() override; EditorAutomationAction* GenerateMissingPreconditionAction() override; - void SetupAction(); + void SetupAction() override; // GraphCanvas::SceneNotificationBus void OnNodeAdded(const AZ::EntityId& nodeId, bool isPaste) override; @@ -146,7 +146,7 @@ namespace ScriptCanvasDeveloper ShowGraphVariablesAction() = default; ~ShowGraphVariablesAction() override = default; - void SetupAction(); + void SetupAction() override; ActionReport GenerateReport() const override; }; diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/EditorViewStates.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/EditorViewStates.h index fa7db8ce9f..daba20b8c8 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/EditorViewStates.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/EditorViewStates.h @@ -70,7 +70,7 @@ namespace ScriptCanvasDeveloper FindViewCenterState(AutomationStateModelId outputId); ~FindViewCenterState() override = default; - void OnCustomAction(); + void OnCustomAction() override; private: diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/Mock.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/Mock.h index 221aa501a9..41eddbfc02 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/Mock.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/Mock.h @@ -118,7 +118,7 @@ namespace ScriptCanvasDeveloper private: //// ScriptCanvasEditor::EditorGraphNotificationBus - void OnGraphCanvasNodeDisplayed(AZ::EntityId graphCanvasEntityId); + void OnGraphCanvasNodeDisplayed(AZ::EntityId graphCanvasEntityId) override; //// AZStd::string m_nodeTitle; diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/WrapperMock.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/WrapperMock.h index 4ffafbd2a5..4b0155ec29 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/WrapperMock.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/WrapperMock.h @@ -52,7 +52,7 @@ namespace ScriptCanvasDeveloper void OnActionNameChanged(); - void OnClear(); + void OnClear() override; void OnNodeDisplayed(const GraphCanvas::NodeId& graphCanvasNodeId) override; private: diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTestDialog.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTestDialog.h index 84597a991c..865738eadc 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTestDialog.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTestDialog.h @@ -101,7 +101,7 @@ namespace ScriptCanvasDeveloper void RunTest(QModelIndex index); // SystemTickBus - void OnSystemTick(); + void OnSystemTick() override; //// // EditorAutomationTestDialogRequestBus::Handler diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GraphCreationTests.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GraphCreationTests.h index c09f219da0..c02d5cf081 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GraphCreationTests.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/EditorAutomationTests/GraphCreationTests.h @@ -55,8 +55,8 @@ namespace ScriptCanvasDeveloper protected: - void OnSetupStateActions(EditorAutomationActionRunner& actionRunner); - void OnStateActionsComplete(); + void OnSetupStateActions(EditorAutomationActionRunner& actionRunner) override; + void OnStateActionsComplete() override; private: diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h index 56ecdc33a1..8272e647a3 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestUtilities.h @@ -548,7 +548,7 @@ namespace ScriptCanvasTests bool DestroyEntityById(AZ::EntityId entityId) override; AZ::Entity* CloneEntity(const AZ::Entity& sourceEntity) override; void ResetContext() override; - AZ::EntityId FindLoadedEntityIdMapping(const AZ::EntityId& staticId) const; + AZ::EntityId FindLoadedEntityIdMapping(const AZ::EntityId& staticId) const override; //// void AddEntity(AZ::EntityId entityId); diff --git a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp index 7ab7fa2540..c8db1169ed 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp @@ -237,7 +237,7 @@ namespace ScriptCanvasTesting return result; } - void Void(AZStd::string_view value) + void Void(AZStd::string_view value) override { Call(FN_Void, value); } diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_MethodOverload.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_MethodOverload.cpp index 13f6657d62..d7e5bbfb02 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_MethodOverload.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_MethodOverload.cpp @@ -99,7 +99,7 @@ public: } } - void ConfigureSlots() + void ConfigureSlots() override { ScriptCanvas::SlotExecution::Ins ins; { From 629d836142cf6c31c9db04db6d7d50a70c210873 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:24:32 -0700 Subject: [PATCH 074/274] Gems/Script* Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Editor/ScriptEventsSystemEditorComponent.h | 2 +- .../Code/Source/ScriptedEntityTweenerModule.cpp | 2 +- .../Code/Source/ScriptedEntityTweenerSystemComponent.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptEvents/Code/Source/Editor/ScriptEventsSystemEditorComponent.h b/Gems/ScriptEvents/Code/Source/Editor/ScriptEventsSystemEditorComponent.h index 4365873b3a..9463b2a047 100644 --- a/Gems/ScriptEvents/Code/Source/Editor/ScriptEventsSystemEditorComponent.h +++ b/Gems/ScriptEvents/Code/Source/Editor/ScriptEventsSystemEditorComponent.h @@ -46,7 +46,7 @@ namespace ScriptEventsEditor // AssetEditorValidationRequestBus::Handler AZ::Outcome IsAssetDataValid(const AZ::Data::Asset& asset) override; - void PreAssetSave(AZ::Data::Asset asset); + void PreAssetSave(AZ::Data::Asset asset) override; void BeforePropertyEdit(AzToolsFramework::InstanceDataNode* node, AZ::Data::Asset asset) override; void SetSaveAsBinary(bool saveAsBinary) { m_saveAsBinary = saveAsBinary; } diff --git a/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerModule.cpp b/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerModule.cpp index 8d5057e17f..20f59b94a9 100644 --- a/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerModule.cpp +++ b/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerModule.cpp @@ -39,7 +39,7 @@ namespace ScriptedEntityTweener }; } - void OnSystemEvent(ESystemEvent systemEvent, UINT_PTR wparam, UINT_PTR lparam) + void OnSystemEvent(ESystemEvent systemEvent, UINT_PTR wparam, UINT_PTR lparam) override { CryHooksModule::OnSystemEvent(systemEvent, wparam, lparam); diff --git a/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerSystemComponent.cpp b/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerSystemComponent.cpp index f1f4977164..67a5038aec 100644 --- a/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerSystemComponent.cpp +++ b/Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweenerSystemComponent.cpp @@ -47,7 +47,7 @@ namespace ScriptedEntityTweener Call(FN_RemoveCallback, callbackId); } - void OnTimelineAnimationStart(int timelineId, const AZ::Uuid& uuid, const AZStd::string& componentName, const AZStd::string& propertyName) + void OnTimelineAnimationStart(int timelineId, const AZ::Uuid& uuid, const AZStd::string& componentName, const AZStd::string& propertyName) override { Call(FN_OnTimelineAnimationStart, timelineId, uuid, componentName, propertyName); } From df1a6e6af9a8642107c1b9fe65e04417f15a73b0 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:26:22 -0700 Subject: [PATCH 075/274] Gems/SurfaceData Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Components/SurfaceDataShapeComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h index 31b960c2b6..f2c478ed27 100644 --- a/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h +++ b/Gems/SurfaceData/Code/Source/Components/SurfaceDataShapeComponent.h @@ -64,7 +64,7 @@ namespace SurfaceData ////////////////////////////////////////////////////////////////////////// // SurfaceDataProviderRequestBus - void GetSurfacePoints(const AZ::Vector3& inPosition, SurfacePointList& surfacePointList) const; + void GetSurfacePoints(const AZ::Vector3& inPosition, SurfacePointList& surfacePointList) const override; ////////////////////////////////////////////////////////////////////////// // SurfaceDataModifierRequestBus From de02f9bb553efa038f1a167f13c06e58daf0714b Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:26:35 -0700 Subject: [PATCH 076/274] Gems/Twitch Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/Twitch/Code/Source/TwitchReflection.cpp | 54 ++++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Gems/Twitch/Code/Source/TwitchReflection.cpp b/Gems/Twitch/Code/Source/TwitchReflection.cpp index 618fb6814a..510d1d94f5 100644 --- a/Gems/Twitch/Code/Source/TwitchReflection.cpp +++ b/Gems/Twitch/Code/Source/TwitchReflection.cpp @@ -595,137 +595,137 @@ namespace Twitch StartChannelCommercial, ResetChannelStreamKey); - void UserIDNotify(const StringValue& userID) + void UserIDNotify(const StringValue& userID) override { Call(FN_UserIDNotify, userID); } - void OAuthTokenNotify(const StringValue& token) + void OAuthTokenNotify(const StringValue& token) override { Call(FN_OAuthTokenNotify, token); } - void GetUser(const UserInfoValue& result) + void GetUser(const UserInfoValue& result) override { Call(FN_GetUser, result); } - void ResetFriendsNotificationCountNotify(const Int64Value& result) + void ResetFriendsNotificationCountNotify(const Int64Value& result) override { Call(FN_ResetFriendsNotificationCountNotify, result); } - void GetFriendNotificationCount(const Int64Value& result) + void GetFriendNotificationCount(const Int64Value& result) override { Call(FN_GetFriendNotificationCount, result); } - void GetFriendRecommendations(const FriendRecommendationValue& result) + void GetFriendRecommendations(const FriendRecommendationValue& result) override { Call(FN_GetFriendRecommendations, result); } - void GetFriends(const GetFriendValue& result) + void GetFriends(const GetFriendValue& result) override { Call(FN_GetFriends, result); } - void GetFriendStatus(const FriendStatusValue& result) + void GetFriendStatus(const FriendStatusValue& result) override { Call(FN_GetFriendStatus, result); } - void AcceptFriendRequest(const Int64Value& result) + void AcceptFriendRequest(const Int64Value& result) override { Call(FN_AcceptFriendRequest, result); } - void GetFriendRequests(const FriendRequestValue& result) + void GetFriendRequests(const FriendRequestValue& result) override { Call(FN_GetFriendRequests, result); } - void CreateFriendRequest(const Int64Value& result) + void CreateFriendRequest(const Int64Value& result) override { Call(FN_CreateFriendRequest, result); } - void DeclineFriendRequest(const Int64Value& result) + void DeclineFriendRequest(const Int64Value& result) override { Call(FN_DeclineFriendRequest, result); } - void UpdatePresenceStatus(const Int64Value& result) + void UpdatePresenceStatus(const Int64Value& result) override { Call(FN_UpdatePresenceStatus, result); } - void GetPresenceStatusofFriends(const PresenceStatusValue& result) + void GetPresenceStatusofFriends(const PresenceStatusValue& result) override { Call(FN_GetPresenceStatusofFriends, result); } - void GetPresenceSettings(const PresenceSettingsValue& result) + void GetPresenceSettings(const PresenceSettingsValue& result) override { Call(FN_GetPresenceSettings, result); } - void UpdatePresenceSettings(const PresenceSettingsValue& result) + void UpdatePresenceSettings(const PresenceSettingsValue& result) override { Call(FN_UpdatePresenceSettings, result); } - void GetChannelbyID(const ChannelInfoValue& result) + void GetChannelbyID(const ChannelInfoValue& result) override { Call(FN_GetChannelbyID, result); } - void GetChannel(const ChannelInfoValue& result) + void GetChannel(const ChannelInfoValue& result) override { Call(FN_GetChannel, result); } - void UpdateChannel(const ChannelInfoValue& result) + void UpdateChannel(const ChannelInfoValue& result) override { Call(FN_UpdateChannel, result); } - void GetChannelEditors(const UserInfoListValue& result) + void GetChannelEditors(const UserInfoListValue& result) override { Call(FN_GetChannelEditors, result); } - void GetChannelFollowers(const FollowerResultValue& result) + void GetChannelFollowers(const FollowerResultValue& result) override { Call(FN_GetChannelFollowers, result); } - void GetChannelTeams(const ChannelTeamValue& result) + void GetChannelTeams(const ChannelTeamValue& result) override { Call(FN_GetChannelTeams, result); } - void GetChannelSubscribers(const SubscriberValue& result) + void GetChannelSubscribers(const SubscriberValue& result) override { Call(FN_GetChannelSubscribers, result); } - void CheckChannelSubscriptionbyUser(const SubscriberbyUserValue& result) + void CheckChannelSubscriptionbyUser(const SubscriberbyUserValue& result) override { Call(FN_CheckChannelSubscriptionbyUser, result); } - void GetChannelVideos(const VideoReturnValue& result) + void GetChannelVideos(const VideoReturnValue& result) override { Call(FN_GetChannelVideos, result); } - void StartChannelCommercial(const StartChannelCommercialValue& result) + void StartChannelCommercial(const StartChannelCommercialValue& result) override { Call(FN_StartChannelCommercial, result); } - void ResetChannelStreamKey(const ChannelInfoValue& result) + void ResetChannelStreamKey(const ChannelInfoValue& result) override { Call(FN_ResetChannelStreamKey, result); } From 5ce7b76ca5d46facdb9c7e6e619ea86e5bada849 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 20:26:50 -0700 Subject: [PATCH 077/274] Gems/Vegetation Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Include/Vegetation/Editor/EditorAreaComponentBase.h | 2 +- Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp | 2 +- Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp | 2 +- Gems/Vegetation/Code/Tests/VegetationMocks.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/Vegetation/Code/Include/Vegetation/Editor/EditorAreaComponentBase.h b/Gems/Vegetation/Code/Include/Vegetation/Editor/EditorAreaComponentBase.h index 60ef04b46e..87a1546ad0 100644 --- a/Gems/Vegetation/Code/Include/Vegetation/Editor/EditorAreaComponentBase.h +++ b/Gems/Vegetation/Code/Include/Vegetation/Editor/EditorAreaComponentBase.h @@ -63,7 +63,7 @@ namespace Vegetation AZ::Aabb GetPreviewBounds() const override; bool GetConstrainToShape() const override; - GradientSignal::GradientPreviewContextPriority GetPreviewContextPriority() const; + GradientSignal::GradientPreviewContextPriority GetPreviewContextPriority() const override; ////////////////////////////////////////////////////////////////////////// // AzToolsFramework::EntitySelectionEvents::Bus::Handler diff --git a/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp b/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp index 01a2e059e6..9838a7b6a1 100644 --- a/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp +++ b/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp @@ -191,7 +191,7 @@ namespace UnitTest AZ::Data::AssetHandler::LoadResult LoadAssetData( const AZ::Data::Asset& asset, AZStd::shared_ptr stream, - [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) + [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) override { MockAssetData* temp = reinterpret_cast(asset.GetData()); temp->SetStatus(AZ::Data::AssetData::AssetStatus::Ready); diff --git a/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp b/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp index ed48aec134..b0d88f2d63 100644 --- a/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp +++ b/Gems/Vegetation/Code/Tests/PrefabInstanceSpawnerTests.cpp @@ -185,7 +185,7 @@ namespace UnitTest AZ::Data::AssetHandler::LoadResult LoadAssetData( const AZ::Data::Asset& asset, AZStd::shared_ptr stream, - [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) + [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) override { MockAssetData* temp = reinterpret_cast(asset.GetData()); temp->SetStatus(AZ::Data::AssetData::AssetStatus::Ready); diff --git a/Gems/Vegetation/Code/Tests/VegetationMocks.h b/Gems/Vegetation/Code/Tests/VegetationMocks.h index 97eaa50b69..ee620c81a2 100644 --- a/Gems/Vegetation/Code/Tests/VegetationMocks.h +++ b/Gems/Vegetation/Code/Tests/VegetationMocks.h @@ -268,7 +268,7 @@ namespace UnitTest } } - void GetSystemConfig(AZ::ComponentConfig* config) const + void GetSystemConfig(AZ::ComponentConfig* config) const override { if (azrtti_typeid(m_areaSystemConfig) == azrtti_typeid(*config)) { From 5815b48a0050a05a2415898ea14f8740916db45a Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 10 Sep 2021 21:16:03 -0700 Subject: [PATCH 078/274] disabling the warning after merge Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/Clang/Configurations_clang.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Platform/Common/Clang/Configurations_clang.cmake b/cmake/Platform/Common/Clang/Configurations_clang.cmake index 5c24161a19..86f4faccfb 100644 --- a/cmake/Platform/Common/Clang/Configurations_clang.cmake +++ b/cmake/Platform/Common/Clang/Configurations_clang.cmake @@ -19,9 +19,9 @@ ly_append_configurations_options( ################### # Disabled warnings (please do not disable any others without first consulting sig-build) ################### - # -Wno-inconsistent-missing-override # unfortunately there is no warning in MSVC to detect missing overrides, - # MSVC's static analyzer can, but that is a different run that most developers are not ware of. A pass was - # done to fix all hits. Leaving this disabled until there is a matching warning in MSVC. + -Wno-inconsistent-missing-override # unfortunately there is no warning in MSVC to detect missing overrides, + # MSVC's static analyzer can, but that is a different run that most developers are not ware of. A pass + # was done to fix all hits. Leaving this disabled until there is a matching warning in MSVC. -Wrange-loop-analysis -Wno-unknown-warning-option # used as a way to mark warnings that are MSVC only From 51ce59e24099f2d32b8bfa203289df4ca1e0c1b2 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Mon, 13 Sep 2021 08:25:38 +0200 Subject: [PATCH 079/274] EMotion FX: Resetting the anim graph while in the middle of selecting transitions for interruption crashes the Editor (#4026) Signed-off-by: Benjamin Jillich --- .../Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp index ce114a498e..c49f5de085 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/AnimGraphTransitionHandler.cpp @@ -24,7 +24,6 @@ #include #include - namespace EMotionFX { AZ_CLASS_ALLOCATOR_IMPL(AnimGraphTransitionIdPicker, AZ::SystemAllocator, 0) @@ -126,8 +125,13 @@ namespace EMotionFX } } - void AnimGraphTransitionIdPicker::OnAboutToBeRemoved(const QModelIndex &parent, int first, int last) + void AnimGraphTransitionIdPicker::OnAboutToBeRemoved(const QModelIndex& parent, int first, int last) { + if (!parent.isValid()) + { + return; + } + EMStudio::EMStudioPlugin* plugin = EMStudio::GetPluginManager()->FindActivePlugin(EMStudio::AnimGraphPlugin::CLASS_ID); EMStudio::AnimGraphPlugin* animGraphPlugin = static_cast(plugin); if (animGraphPlugin) From 28d45891f29210cca73aed56f5996fa4e0bb9caf Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Mon, 13 Sep 2021 09:36:34 +0100 Subject: [PATCH 080/274] Remove redundant API calls from EditorViewportWidget and use new WorldToScreen call (#4022) * remove redundant API calls from EditorViewportWidget and use new WorldToScreen call Signed-off-by: hultonha * remove additional pre/post widget render calls that are no longer required Signed-off-by: hultonha --- Code/Editor/EditorViewportWidget.cpp | 64 +++++-------------- Code/Editor/EditorViewportWidget.h | 5 +- Code/Editor/IEditorImpl.cpp | 7 -- Code/Editor/Viewport.cpp | 27 -------- Code/Editor/Viewport.h | 16 +---- .../Manipulators/EditorVertexSelection.cpp | 7 +- .../Viewport/ViewportMessages.h | 27 -------- .../ViewportSelection/EditorHelpers.cpp | 7 +- .../ViewportSelection/EditorSelectionUtil.cpp | 12 ---- .../ViewportSelection/EditorSelectionUtil.h | 3 - .../EditorTransformComponentSelection.cpp | 15 +---- .../Editor/EditorViewportEntityPicker.cpp | 38 +++++------ 12 files changed, 42 insertions(+), 186 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 736bbe5feb..61c7355273 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -295,28 +295,17 @@ void EditorViewportWidget::mousePressEvent(QMouseEvent* event) QtViewport::mousePressEvent(event); } -AzToolsFramework::ViewportInteraction::MousePick EditorViewportWidget::BuildMousePickInternal(const QPoint& point) const +AzToolsFramework::ViewportInteraction::MousePick EditorViewportWidget::BuildMousePick(const QPoint& point) const { - using namespace AzToolsFramework::ViewportInteraction; - - MousePick mousePick; - mousePick.m_screenCoordinates = ScreenPointFromQPoint(point); - const auto& ray = m_renderViewport->ViewportScreenToWorldRay(mousePick.m_screenCoordinates); - if (ray.has_value()) + AzToolsFramework::ViewportInteraction::MousePick mousePick; + mousePick.m_screenCoordinates = AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(point); + if (const auto& ray = m_renderViewport->ViewportScreenToWorldRay(mousePick.m_screenCoordinates); + ray.has_value()) { mousePick.m_rayOrigin = ray.value().origin; mousePick.m_rayDirection = ray.value().direction; } - return mousePick; -} - -AzToolsFramework::ViewportInteraction::MousePick EditorViewportWidget::BuildMousePick(const QPoint& point) -{ - using namespace AzToolsFramework::ViewportInteraction; - PreWidgetRendering(); - const MousePick mousePick = BuildMousePickInternal(point); - PostWidgetRendering(); return mousePick; } @@ -325,9 +314,7 @@ AzToolsFramework::ViewportInteraction::MouseInteraction EditorViewportWidget::Bu const AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers, const AzToolsFramework::ViewportInteraction::MousePick& mousePick) const { - using namespace AzToolsFramework::ViewportInteraction; - - MouseInteraction mouse; + AzToolsFramework::ViewportInteraction::MouseInteraction mouse; mouse.m_interactionId.m_cameraId = m_viewEntityId; mouse.m_interactionId.m_viewportId = GetViewportId(); mouse.m_mouseButtons = buttons; @@ -339,11 +326,11 @@ AzToolsFramework::ViewportInteraction::MouseInteraction EditorViewportWidget::Bu AzToolsFramework::ViewportInteraction::MouseInteraction EditorViewportWidget::BuildMouseInteraction( const Qt::MouseButtons buttons, const Qt::KeyboardModifiers modifiers, const QPoint& point) { - using namespace AzToolsFramework::ViewportInteraction; + namespace AztfVi = AzToolsFramework::ViewportInteraction; return BuildMouseInteractionInternal( - BuildMouseButtons(buttons), - BuildKeyboardModifiers(modifiers), + AztfVi::BuildMouseButtons(buttons), + AztfVi::BuildKeyboardModifiers(modifiers), BuildMousePick(WidgetToViewport(point))); } @@ -721,8 +708,6 @@ void EditorViewportWidget::OnBeginPrepareRender() return; } - PreWidgetRendering(); - RenderAll(); // Draw 2D helpers. @@ -748,8 +733,6 @@ void EditorViewportWidget::OnBeginPrepareRender() m_debugDisplay->SetState(prevState); m_debugDisplay->DepthTestOn(); - - PostWidgetRendering(); } ////////////////////////////////////////////////////////////////////////// @@ -769,15 +752,15 @@ void EditorViewportWidget::RenderAll() if (m_manipulatorManager != nullptr) { - using namespace AzToolsFramework::ViewportInteraction; + namespace AztfVi = AzToolsFramework::ViewportInteraction; m_debugDisplay->DepthTestOff(); m_manipulatorManager->DrawManipulators( *m_debugDisplay, GetCameraState(), BuildMouseInteractionInternal( - MouseButtons(TranslateMouseButtons(QGuiApplication::mouseButtons())), - BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()), - BuildMousePickInternal(WidgetToViewport(mapFromGlobal(QCursor::pos()))))); + AztfVi::MouseButtons(AztfVi::TranslateMouseButtons(QGuiApplication::mouseButtons())), + AztfVi::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()), + BuildMousePick(WidgetToViewport(mapFromGlobal(QCursor::pos()))))); m_debugDisplay->DepthTestOn(); } } @@ -950,8 +933,6 @@ AZ::Vector3 EditorViewportWidget::PickTerrain(const AzFramework::ScreenPoint& po AZ::EntityId EditorViewportWidget::PickEntity(const AzFramework::ScreenPoint& point) { - PreWidgetRendering(); - AZ::EntityId entityId; HitContext hitInfo; hitInfo.view = this; @@ -964,8 +945,6 @@ AZ::EntityId EditorViewportWidget::PickEntity(const AzFramework::ScreenPoint& po } } - PostWidgetRendering(); - return entityId; } @@ -999,28 +978,17 @@ QWidget* EditorViewportWidget::GetWidgetForViewportContextMenu() return this; } -void EditorViewportWidget::BeginWidgetContext() -{ - PreWidgetRendering(); -} - -void EditorViewportWidget::EndWidgetContext() -{ - PostWidgetRendering(); -} - bool EditorViewportWidget::ShowingWorldSpace() { - using namespace AzToolsFramework::ViewportInteraction; - return BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()).Shift(); + return AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()).Shift(); } void EditorViewportWidget::SetViewportId(int id) { CViewport::SetViewportId(id); - // Clear the cached debugdisplay pointer. we're about to delete that render viewport, and deleting the render - // viewport invalidates the debugdisplay. + // Clear the cached DebugDisplay pointer. we're about to delete that render viewport, and deleting the render + // viewport invalidates the DebugDisplay. m_debugDisplay = nullptr; // First delete any existing layout diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index dff0adb55a..426b7c5ad1 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -211,8 +211,6 @@ private: float TerrainHeight(const AZ::Vector2& position) override; bool ShowingWorldSpace() override; QWidget* GetWidgetForViewportContextMenu() override; - void BeginWidgetContext() override; - void EndWidgetContext() override; // EditorEntityViewportInteractionRequestBus overrides ... void FindVisibleEntities(AZStd::vector& visibleEntities) override; @@ -271,7 +269,7 @@ private: // note: The argument passed to parameter **point**, originating // from a Qt event, must first be passed to WidgetToViewport before being // passed to BuildMousePick. - AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(const QPoint& point); + AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(const QPoint& point) const; bool CheckRespondToInput() const; @@ -281,7 +279,6 @@ private: void PushDisableRendering(); void PopDisableRendering(); bool IsRenderingDisabled() const; - AzToolsFramework::ViewportInteraction::MousePick BuildMousePickInternal(const QPoint& point) const; void RestoreViewportAfterGameMode(); diff --git a/Code/Editor/IEditorImpl.cpp b/Code/Editor/IEditorImpl.cpp index 51ef0dedc3..66c64d5bef 100644 --- a/Code/Editor/IEditorImpl.cpp +++ b/Code/Editor/IEditorImpl.cpp @@ -632,14 +632,7 @@ void CEditorImpl::SetReferenceCoordSys(RefCoordSys refCoords) CViewport* pViewport = GetActiveView(); if (pViewport) { - //Pre and Post widget rendering calls are made here to make sure that the proper camera state is set. - //MakeConstructionPlane will make a call to ViewToWorldRay which needs the correct camera state - //in the CRenderViewport to be set. - pViewport->PreWidgetRendering(); - pViewport->MakeConstructionPlane(GetIEditor()->GetAxisConstrains()); - - pViewport->PostWidgetRendering(); } Notify(eNotify_OnRefCoordSysChange); diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 9c6088e340..2d41538d92 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -43,12 +43,7 @@ void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) { context.m_hitLocation = AZ::Vector3::CreateZero(); - - PreWidgetRendering(); // required so that the current render cam is set. - context.m_hitLocation = GetHitLocation(pt); - - PostWidgetRendering(); } @@ -1352,28 +1347,6 @@ bool QtViewport::MouseCallback(EMouseEvent event, const QPoint& point, Qt::Keybo return true; } - // RAII wrapper for Pre / PostWidgetRendering calls. - // It also tracks the times a mouse callback potentially created a new viewport context. - struct ScopedProcessingMouseCallback - { - explicit ScopedProcessingMouseCallback(QtViewport* viewport) - : m_viewport(viewport) - { - m_viewport->m_processingMouseCallbacksCounter++; - m_viewport->PreWidgetRendering(); - } - - ~ScopedProcessingMouseCallback() - { - m_viewport->PostWidgetRendering(); - m_viewport->m_processingMouseCallbacksCounter--; - } - - QtViewport* m_viewport; - }; - - ScopedProcessingMouseCallback scopedProcessingMouseCallback(this); - ////////////////////////////////////////////////////////////////////////// // Hit test gizmo objects. ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Viewport.h b/Code/Editor/Viewport.h index 6b5bfb5c34..74897508f0 100644 --- a/Code/Editor/Viewport.h +++ b/Code/Editor/Viewport.h @@ -274,12 +274,6 @@ public: void SetViewPane(CLayoutViewPane* viewPane) { m_viewPane = viewPane; } - //Child classes can override these to provide extra logic that wraps - //widget rendering. Needed by the RenderViewport to handle raycasts - //from screen-space to world-space. - virtual void PreWidgetRendering() {} - virtual void PostWidgetRendering() {} - virtual CViewport *asCViewport() { return this; } protected: @@ -289,7 +283,7 @@ protected: // Screen Matrix Matrix34 m_screenTM; int m_nCurViewportID; - // Final game view matrix before drpping back to editor + // Final game view matrix before dropping back to editor Matrix34 m_gameTM; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING @@ -427,7 +421,7 @@ public: QRect GetSelectionRectangle() const override { return m_selectedRect; }; //! Called when dragging selection rectangle. void OnDragSelectRectangle(const QRect& rect, bool bNormalizeRect = false) override; - //! Get selection procision tolerance. + //! Get selection precision tolerance. float GetSelectionTolerance() const { return m_selectionTolerance; } //! Center viewport on selection. void CenterOnSelection() override {} @@ -572,12 +566,6 @@ protected: void dragLeaveEvent(QDragLeaveEvent* event) override; void dropEvent(QDropEvent* event) override; - //Child classes can override these to provide extra logic that wraps - //widget rendering. Needed by the RenderViewport to handle raycasts - //from screen-space to world-space. - virtual void PreWidgetRendering() {} - virtual void PostWidgetRendering() {} - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING AzToolsFramework::ViewportUi::ViewportUiManager m_viewportUi; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp index af5a9004e3..7b2ce53613 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -363,9 +364,7 @@ namespace AzToolsFramework boxSelectData.m_activeSelection = boxSelectData.m_startSelection; } - // set the widget context before calls to ViewportWorldToScreen so we are not - // going to constantly be pushing/popping the widget context - ViewportInteraction::WidgetContextGuard widgetContextGuard(viewportId); + const AzFramework::CameraState cameraState = GetCameraState(viewportId); // box select active (clicking and dragging) if (editorBoxSelect.BoxRegion()) @@ -385,7 +384,7 @@ namespace AzToolsFramework found, fixedVertices, &AZ::FixedVerticesRequestBus::Handler::GetVertex, vertexIndex, localVertex); const AZ::Vector3 worldVertex = worldFromLocal.TransformPoint(AZ::AdaptVertexOut(localVertex)); - const AzFramework::ScreenPoint screenPosition = GetScreenPosition(viewportId, worldVertex); + const AzFramework::ScreenPoint screenPosition = AzFramework::WorldToScreen(worldVertex, cameraState); // check if a vertex is inside the box select region if (editorBoxSelect.BoxRegion()->contains(ViewportInteraction::QPointFromScreenPoint(screenPosition))) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 942fee1a49..fa4d8dfe11 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -254,11 +254,6 @@ namespace AzToolsFramework virtual bool ShowingWorldSpace() = 0; //! Return the widget to use as the parent for the viewport context menu. virtual QWidget* GetWidgetForViewportContextMenu() = 0; - //! Set the render context for the viewport. - virtual void BeginWidgetContext() = 0; - //! End the render context for the viewport. - //! Return to previous context before Begin was called. - virtual void EndWidgetContext() = 0; protected: ~MainEditorViewportInteractionRequests() = default; @@ -297,28 +292,6 @@ namespace AzToolsFramework //! Type to inherit to implement MainEditorViewportInteractionRequests. using ViewportMouseCursorRequestBus = AZ::EBus; - - //! A helper to wrap Begin/EndWidgetContext. - class WidgetContextGuard - { - public: - explicit WidgetContextGuard(const int viewportId) - : m_viewportId(viewportId) - { - MainEditorViewportInteractionRequestBus::Event( - viewportId, &MainEditorViewportInteractionRequestBus::Events::BeginWidgetContext); - } - - ~WidgetContextGuard() - { - MainEditorViewportInteractionRequestBus::Event( - m_viewportId, &MainEditorViewportInteractionRequestBus::Events::EndWidgetContext); - } - - private: - int m_viewportId; //!< The viewport id the widget context is being set on. - }; - } // namespace ViewportInteraction //! Utility function to return EntityContextId. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp index 7abff230e3..25b10463dc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -118,10 +119,6 @@ namespace AzToolsFramework const int viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId; - // set the widget context before calls to ViewportWorldToScreen so we are not - // going to constantly be pushing/popping the widget context - ViewportInteraction::WidgetContextGuard widgetContextGuard(viewportId); - const bool helpersVisible = HelpersVisible(); // selecting new entities @@ -145,7 +142,7 @@ namespace AzToolsFramework const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex); // selecting based on 2d icon - should only do it when visible and not selected - const AzFramework::ScreenPoint screenPosition = GetScreenPosition(viewportId, entityPosition); + const AzFramework::ScreenPoint screenPosition = AzFramework::WorldToScreen(entityPosition, cameraState); const float distSqFromCamera = cameraState.m_position.GetDistanceSq(entityPosition); const auto iconRange = static_cast(GetIconScale(distSqFromCamera) * s_iconSize * 0.5f); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp index f4b68b5970..a5ef66e7a3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.cpp @@ -48,18 +48,6 @@ namespace AzToolsFramework return AZ::GetMax(projectedCameraDistance, cameraState.m_nearClip) / apparentDistance; } - AzFramework::ScreenPoint GetScreenPosition(const int viewportId, const AZ::Vector3& worldTranslation) - { - AZ_PROFILE_FUNCTION(AzToolsFramework); - - auto screenPosition = AzFramework::ScreenPoint(0, 0); - ViewportInteraction::ViewportInteractionRequestBus::EventResult( - screenPosition, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ViewportWorldToScreen, - worldTranslation); - - return screenPosition; - } - bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance) { AZ_PROFILE_FUNCTION(AzToolsFramework); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h index ec9bde9f9c..d58549b329 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorSelectionUtil.h @@ -39,9 +39,6 @@ namespace AzToolsFramework //! Calculate scale factor based on distance from camera float CalculateScreenToWorldMultiplier(const AZ::Vector3& worldPosition, const AzFramework::CameraState& cameraState); - //! Map from world space to screen space. - AzFramework::ScreenPoint GetScreenPosition(int viewportId, const AZ::Vector3& worldTranslation); - //! Given a mouse interaction, determine if the pick ray from its position //! in screen space intersected an aabb in world space. bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index afcade944a..6442559ede 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -412,10 +412,7 @@ namespace AzToolsFramework potentialSelectedEntityIds.clear(); } - // set the widget context before calls to ViewportWorldToScreen so we are not - // going to constantly be pushing/popping the widget context - ViewportInteraction::WidgetContextGuard widgetContextGuard(viewportId); - + const AzFramework::CameraState cameraState = GetCameraState(viewportId); for (size_t entityCacheIndex = 0; entityCacheIndex < entityDataCache.VisibleEntityDataCount(); ++entityCacheIndex) { if (entityDataCache.IsVisibleEntityLocked(entityCacheIndex) || !entityDataCache.IsVisibleEntityVisible(entityCacheIndex)) @@ -426,7 +423,7 @@ namespace AzToolsFramework const AZ::EntityId entityId = entityDataCache.GetVisibleEntityId(entityCacheIndex); const AZ::Vector3& entityPosition = entityDataCache.GetVisibleEntityPosition(entityCacheIndex); - const AzFramework::ScreenPoint screenPosition = GetScreenPosition(viewportId, entityPosition); + const AzFramework::ScreenPoint screenPosition = AzFramework::WorldToScreen(entityPosition, cameraState); if (currentKeyboardModifiers.Ctrl()) { @@ -1779,13 +1776,7 @@ namespace AzToolsFramework CheckDirtyEntityIds(); - const int viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId; - - const AzFramework::CameraState cameraState = GetCameraState(viewportId); - - // set the widget context before calls to ViewportWorldToScreen so we are not - // going to constantly be pushing/popping the widget context - ViewportInteraction::WidgetContextGuard widgetContextGuard(viewportId); + const AzFramework::CameraState cameraState = GetCameraState(mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId); m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction); diff --git a/Gems/PhysX/Code/Editor/EditorViewportEntityPicker.cpp b/Gems/PhysX/Code/Editor/EditorViewportEntityPicker.cpp index 605e6f213f..7f46f961f2 100644 --- a/Gems/PhysX/Code/Editor/EditorViewportEntityPicker.cpp +++ b/Gems/PhysX/Code/Editor/EditorViewportEntityPicker.cpp @@ -6,12 +6,12 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #include #include #include #include #include - #include namespace PhysX @@ -28,17 +28,13 @@ namespace PhysX } AZ::EntityId EditorViewportEntityPicker::PickEntity( - [[maybe_unused]] const AzFramework::CameraState& cameraState - , const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction - , AZ::Vector3& pickPosition - , AZ::Aabb& pickAabb) - { + [[maybe_unused]] const AzFramework::CameraState& cameraState, + const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction, + AZ::Vector3& pickPosition, + AZ::Aabb& pickAabb) + { const int viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId; - // set the widget context before calls to ViewportWorldToScreen so we are not - // going to constantly be pushing/popping the widget context - AzToolsFramework::ViewportInteraction::WidgetContextGuard widgetContextGuard(viewportId); - // selecting new entities AZ::EntityId entityIdUnderCursor; pickPosition = AZ::Vector3::CreateZero(); @@ -48,31 +44,29 @@ namespace PhysX { const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex); - if (m_entityDataCache->IsVisibleEntityLocked(entityCacheIndex) - || !m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex)) + if (m_entityDataCache->IsVisibleEntityLocked(entityCacheIndex) || !m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex)) { continue; } // Ignore the case where the mouse hovers over an icon. Proceed to check for intersection with entity's AABB. - if (const AZ::Aabb aabb = AzToolsFramework::CalculateEditorEntitySelectionBounds( - entityId, AzFramework::ViewportInfo{viewportId}); + if (const AZ::Aabb aabb = + AzToolsFramework::CalculateEditorEntitySelectionBounds(entityId, AzFramework::ViewportInfo{ viewportId }); aabb.IsValid()) { const float pickRayLength = 1000.0f; - const AZ::Vector3 rayScaledDir = - mouseInteraction.m_mouseInteraction.m_mousePick.m_rayDirection * pickRayLength; + const AZ::Vector3 rayScaledDir = mouseInteraction.m_mouseInteraction.m_mousePick.m_rayDirection * pickRayLength; AZ::Vector3 startNormal; float t, end; int intersectResult = AZ::Intersect::IntersectRayAABB( - mouseInteraction.m_mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, - rayScaledDir.GetReciprocal(), aabb, t, end, startNormal); + mouseInteraction.m_mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, + startNormal); if (intersectResult > 0) { entityIdUnderCursor = entityId; - pickPosition = mouseInteraction.m_mouseInteraction.m_mousePick.m_rayOrigin - + (mouseInteraction.m_mouseInteraction.m_mousePick.m_rayDirection * pickRayLength * t); + pickPosition = mouseInteraction.m_mouseInteraction.m_mousePick.m_rayOrigin + + (mouseInteraction.m_mouseInteraction.m_mousePick.m_rayDirection * pickRayLength * t); pickAabb = aabb; } } @@ -82,10 +76,8 @@ namespace PhysX } void EditorViewportEntityPicker::DisplayViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) + const AzFramework::ViewportInfo& viewportInfo, [[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay) { - AZ_UNUSED(debugDisplay); m_entityDataCache->CalculateVisibleEntityDatas(viewportInfo); } } // namespace PhysX From 1f66e8a76054a7a136e13fcf1b2cd126c73c1d8a Mon Sep 17 00:00:00 2001 From: pereslav Date: Mon, 13 Sep 2021 13:35:35 +0100 Subject: [PATCH 081/274] PR feedback addressing Signed-off-by: pereslav --- .../NetworkEntity/NetworkEntityManager.cpp | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 88f0b221ec..4e0818323e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -470,14 +470,21 @@ namespace Multiplayer AzFramework::EntitySpawnTicket NetworkEntityManager::RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable) { const AzFramework::Spawnable::EntityList& entityList = rootSpawnable->GetEntities(); - if (entityList.size() == 0) + if (entityList.empty()) { - AZ_Assert(false, "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()) + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()); return {}; } // The first entity in every spawnable is the root one const AZ::Entity* rootEntity = (entityList.begin())->get(); + if(!rootEntity) + { + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); + return {}; + } const auto* holderComponent = rootEntity->FindComponent(); if(!holderComponent) @@ -493,17 +500,19 @@ namespace Multiplayer AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_priority = AzFramework::SpawnablePriority_High; + AZ::Name netSpawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); + // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [spawnableAssetId = netSpawnableAsset.GetId()](AzFramework::EntitySpawnTicket::Id, + optionalArgs.m_preInsertionCallback = [netSpawnableName = netSpawnableName](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { - for (uint32_t netEntityIndex = 0; netEntityIndex < entities.size(); netEntityIndex++) + for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); + netEntityIndex < entitiesSize; netEntityIndex++) { AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); - AZ::Name spawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(spawnableAssetId); PrefabEntityId prefabEntityId; - prefabEntityId.m_prefabName = spawnableName; + prefabEntityId.m_prefabName = netSpawnableName; prefabEntityId.m_entityOffset = netEntityIndex; AZ::Interface::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority); } From 7a58b72f1509ba46a4b854bff4070c2cd4929182 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Mon, 13 Sep 2021 15:19:46 +0100 Subject: [PATCH 082/274] Add remaining integration tests for viewport selection (box select) (#4075) * updates to viewport box select tests Signed-off-by: hultonha * add interface for querying keyboard modifiers Signed-off-by: hultonha * remove redundant casts Signed-off-by: hultonha * update formatting options for trace functions in ActionDispatcher Signed-off-by: hultonha * remove redundant GetKeyboardModifiers call Signed-off-by: hultonha * update how trace/log functions have been fixed to output during tests Signed-off-by: hultonha --- Code/Editor/EditorViewportWidget.cpp | 10 +- Code/Editor/EditorViewportWidget.h | 6 +- .../ActionDispatcher.h | 99 +++++---- .../ImmediateModeActionDispatcher.h | 13 +- .../Source/ImmediateModeActionDispatcher.cpp | 6 +- .../Manipulators/EditorVertexSelection.cpp | 3 +- .../Viewport/ViewportMessages.h | 23 ++ .../ViewportSelection/EditorBoxSelect.cpp | 10 +- .../ViewportSelection/EditorBoxSelect.h | 2 +- .../EditorDefaultSelection.cpp | 4 +- .../EditorTransformComponentSelection.cpp | 21 +- .../EditorTransformComponentSelection.h | 22 +- ...EditorTransformComponentSelectionTests.cpp | 204 ++++++++++-------- .../Source/EditorWhiteBoxComponentMode.cpp | 3 +- .../Code/Tests/WhiteBoxComponentTest.cpp | 2 +- 15 files changed, 256 insertions(+), 172 deletions(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 61c7355273..851d2c5b6f 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -758,8 +758,7 @@ void EditorViewportWidget::RenderAll() m_manipulatorManager->DrawManipulators( *m_debugDisplay, GetCameraState(), BuildMouseInteractionInternal( - AztfVi::MouseButtons(AztfVi::TranslateMouseButtons(QGuiApplication::mouseButtons())), - AztfVi::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()), + AztfVi::MouseButtons(AztfVi::TranslateMouseButtons(QGuiApplication::mouseButtons())), QueryKeyboardModifiers(), BuildMousePick(WidgetToViewport(mapFromGlobal(QCursor::pos()))))); m_debugDisplay->DepthTestOn(); } @@ -980,7 +979,12 @@ QWidget* EditorViewportWidget::GetWidgetForViewportContextMenu() bool EditorViewportWidget::ShowingWorldSpace() { - return AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()).Shift(); + return QueryKeyboardModifiers().Shift(); +} + +AzToolsFramework::ViewportInteraction::KeyboardModifiers EditorViewportWidget::QueryKeyboardModifiers() +{ + return AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()); } void EditorViewportWidget::SetViewportId(int id) diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index 426b7c5ad1..825d21a034 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -92,6 +92,7 @@ class SANDBOX_API EditorViewportWidget final , private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler , private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler , private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler + , private AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler , private AzFramework::AssetCatalogEventBus::Handler , private AZ::RPI::SceneNotificationBus::Handler { @@ -205,7 +206,7 @@ private: bool IsViewportInputFrozen() override; void FreezeViewportInput(bool freeze) override; - // AzToolsFramework::MainEditorViewportInteractionRequestBus + // AzToolsFramework::MainEditorViewportInteractionRequestBus overrides ... AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override; AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override; float TerrainHeight(const AZ::Vector2& position) override; @@ -215,6 +216,9 @@ private: // EditorEntityViewportInteractionRequestBus overrides ... void FindVisibleEntities(AZStd::vector& visibleEntities) override; + // EditorModifierKeyRequestBus overrides ... + AzToolsFramework::ViewportInteraction::KeyboardModifiers QueryKeyboardModifiers() override; + // Camera::EditorCameraRequestBus overrides ... void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h index 6ae09340e3..1b555a4a81 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h @@ -8,15 +8,15 @@ #pragma once -#include +#include #include #include -#include +#include namespace AzManipulatorTestFramework { //! Base class for derived immediate and retained action dispatchers. - template + template class ActionDispatcher { public: @@ -31,7 +31,7 @@ namespace AzManipulatorTestFramework //! Enable/disable action logging. DerivedDispatcherT* LogActions(bool logging); //! Output a trace debug message. - template + template DerivedDispatcherT* Trace(const char* format, const Args&... args); //! Set the camera state. DerivedDispatcherT* CameraState(const AzFramework::CameraState& cameraState); @@ -60,8 +60,9 @@ namespace AzManipulatorTestFramework //! Break out to the debugger mid action sequence (note: do not leave uses in production code). DerivedDispatcherT* DebugBreak(); //! Enter component mode for the specified component type. - template + template DerivedDispatcherT* EnterComponentMode(); + protected: // Actions to be implemented by derived immediate and retained action dispatchers. virtual void EnableSnapToGridImpl() = 0; @@ -79,32 +80,50 @@ namespace AzManipulatorTestFramework virtual void SetSelectedEntityImpl(AZ::EntityId entity) = 0; virtual void SetSelectedEntitiesImpl(const AzToolsFramework::EntityIdList& entities) = 0; virtual void EnterComponentModeImpl(const AZ::Uuid& uuid) = 0; - template + template void Log(const char* format, const Args&... args); bool m_logging = false; + private: const char* KeyboardModifierString(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier); + static void DebugPrint(const char* format, ...); }; - template + template + void ActionDispatcher::DebugPrint(const char* format, ...) + { + va_list args; + va_start(args, format); + + vprintf(format, args); + printf("\n"); + + va_end(args); + } + + template template void ActionDispatcher::Log(const char* format, const Args&... args) { if (m_logging) { - AZ_Printf("ActionDispatcher", format, args...); + DebugPrint(format, args...); } } - template + template template DerivedDispatcherT* ActionDispatcher::Trace(const char* format, const Args&... args) { - Log(format, args...); + if (m_logging) + { + DebugPrint(format, args...); + } + return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::EnableSnapToGrid() { Log("Enabling SnapToGrid"); @@ -112,7 +131,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::DisableSnapToGrid() { Log("Disabling SnapToGrid"); @@ -120,15 +139,15 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::GridSize(float size) { - Log("GridSize: %f", size); + Log("GridSize: %.3f", size); GridSizeImpl(size); return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::LogActions(bool logging) { m_logging = logging; @@ -136,17 +155,16 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::CameraState(const AzFramework::CameraState& cameraState) { - Log("Camera state: p(%f, %f, %f) d(%f, %f, %f)", - float(cameraState.m_position.GetX()), float(cameraState.m_position.GetY()), float(cameraState.m_position.GetZ()), - float(cameraState.m_forward.GetX()), float(cameraState.m_forward.GetY()), float(cameraState.m_forward.GetZ())); + Log("Camera state: p(%.3f, %.3f, %.3f) d(%.3f, %.3f, %.3f)", cameraState.m_position.GetX(), cameraState.m_position.GetY(), + cameraState.m_position.GetZ(), cameraState.m_forward.GetX(), cameraState.m_forward.GetY(), cameraState.m_forward.GetZ()); CameraStateImpl(cameraState); return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::MouseLButtonDown() { Log("%s", "Mouse left button down"); @@ -154,14 +172,15 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::MouseLButtonUp() { Log("%s", "Mouse left button up"); MouseLButtonUpImpl(); return static_cast(this); } - template + + template const char* ActionDispatcher::KeyboardModifierString( const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) { @@ -176,11 +195,12 @@ namespace AzManipulatorTestFramework return "Shift"; case KeyboardModifier::None: return "None"; - default: return "Unknown modifier"; + default: + return "Unknown modifier"; } } - template + template DerivedDispatcherT* ActionDispatcher::KeyboardModifierDown( const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) { @@ -189,7 +209,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::KeyboardModifierUp( const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) { @@ -198,7 +218,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::MousePosition(const AzFramework::ScreenPoint& position) { Log("Mouse position: (%i, %i)", position.m_x, position.m_y); @@ -206,7 +226,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::ExpectManipulatorBeingInteracted() { Log("Expecting manipulator interacting"); @@ -214,7 +234,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::ExpectManipulatorNotBeingInteracted() { Log("Not expecting manipulator interacting"); @@ -222,27 +242,24 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template - DerivedDispatcherT* ActionDispatcher::SetEntityWorldTransform( - AZ::EntityId entityId, const AZ::Transform& transform) + template + DerivedDispatcherT* ActionDispatcher::SetEntityWorldTransform(AZ::EntityId entityId, const AZ::Transform& transform) { Log("Setting entity world transform: %s", AZ::ToString(transform).c_str()); SetEntityWorldTransformImpl(entityId, transform); return static_cast(this); } - template - DerivedDispatcherT* ActionDispatcher::SetSelectedEntity( - AZ::EntityId entity) + template + DerivedDispatcherT* ActionDispatcher::SetSelectedEntity(AZ::EntityId entity) { Log("Selecting entity: %u", static_cast(entity)); SetSelectedEntityImpl(entity); return static_cast(this); } - template - DerivedDispatcherT* ActionDispatcher::SetSelectedEntities( - const AzToolsFramework::EntityIdList& entities) + template + DerivedDispatcherT* ActionDispatcher::SetSelectedEntities(const AzToolsFramework::EntityIdList& entities) { for (const auto& entity : entities) { @@ -252,7 +269,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::EnterComponentMode(const AZ::Uuid& uuid) { Log("Entering component mode: %s", uuid.ToString().c_str()); @@ -260,7 +277,7 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template + template DerivedDispatcherT* ActionDispatcher::DebugBreak() { Log("Breaking to debugger"); @@ -268,8 +285,8 @@ namespace AzManipulatorTestFramework return static_cast(this); } - template - template + template + template DerivedDispatcherT* ActionDispatcher::EnterComponentMode() { EnterComponentMode(AZ::AzTypeInfo::Uuid()); diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h index 89be56bab7..7a4773a37c 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h @@ -10,11 +10,14 @@ #include #include +#include namespace AzManipulatorTestFramework { //! Dispatches actions immediately to the manipulators. - class ImmediateModeActionDispatcher : public ActionDispatcher + class ImmediateModeActionDispatcher + : public ActionDispatcher + , public AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler { using KeyboardModifier = AzToolsFramework::ViewportInteraction::KeyboardModifier; using KeyboardModifiers = AzToolsFramework::ViewportInteraction::KeyboardModifiers; @@ -44,8 +47,8 @@ namespace AzManipulatorTestFramework //! Execute an arbitrary section of code inline in the action dispatcher. ImmediateModeActionDispatcher* ExecuteBlock(const AZStd::function& blockFn); - //! Get the current state of the keyboard modifiers. - KeyboardModifiers GetKeyboardModifiers() const; + // EditorModifierKeyRequestBus overrides ... + KeyboardModifiers QueryKeyboardModifiers() override; protected: // ActionDispatcher ... @@ -94,11 +97,11 @@ namespace AzManipulatorTestFramework inline ImmediateModeActionDispatcher* ImmediateModeActionDispatcher::GetKeyboardModifiers(KeyboardModifiers& keyboardModifiers) { - keyboardModifiers = GetKeyboardModifiers(); + keyboardModifiers = QueryKeyboardModifiers(); return this; } - inline AzToolsFramework::ViewportInteraction::KeyboardModifiers ImmediateModeActionDispatcher::GetKeyboardModifiers() const + inline AzToolsFramework::ViewportInteraction::KeyboardModifiers ImmediateModeActionDispatcher::QueryKeyboardModifiers() { return GetMouseInteractionEvent()->m_mouseInteraction.m_keyboardModifiers; } diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp index 4a6ed6a771..895899cf3f 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp @@ -32,9 +32,13 @@ namespace AzManipulatorTestFramework ImmediateModeActionDispatcher::ImmediateModeActionDispatcher(ManipulatorViewportInteraction& viewportManipulatorInteraction) : m_viewportManipulatorInteraction(viewportManipulatorInteraction) { + AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusConnect(); } - ImmediateModeActionDispatcher::~ImmediateModeActionDispatcher() = default; + ImmediateModeActionDispatcher::~ImmediateModeActionDispatcher() + { + AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusDisconnect(); + } void ImmediateModeActionDispatcher::MouseMoveAfterButton() { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp index 7b2ce53613..00f5b1ac47 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp @@ -657,8 +657,7 @@ namespace AzToolsFramework m_editorBoxSelect.InstallDisplayScene( [this, vertexBoxSelectData](const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& /*debugDisplay*/) { - const auto keyboardModifiers = ViewportInteraction::KeyboardModifiers( - ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers())); + const auto keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers(); // when modifiers change ensure we refresh box selection for immediate update if (keyboardModifiers != m_editorBoxSelect.PreviousModifiers()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index fa4d8dfe11..c90c506a05 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -275,6 +275,29 @@ namespace AzToolsFramework using EditorEntityViewportInteractionRequestBus = AZ::EBus; + //! An interface to query editor modifier keys. + class EditorModifierKeyRequests : public AZ::EBusTraits + { + public: + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + + //! Returns the current state of the keyboard modifier keys. + virtual KeyboardModifiers QueryKeyboardModifiers() = 0; + + protected: + ~EditorModifierKeyRequests() = default; + }; + + using EditorModifierKeyRequestBus = AZ::EBus; + + inline KeyboardModifiers QueryKeyboardModifiers() + { + KeyboardModifiers keyboardModifiers; + EditorModifierKeyRequestBus::BroadcastResult(keyboardModifiers, &EditorModifierKeyRequestBus::Events::QueryKeyboardModifiers); + return keyboardModifiers; + } + //! Viewport requests for managing the viewport cursor state. class ViewportMouseCursorRequests { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp index eafd37f199..a1b653225b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp @@ -19,6 +19,13 @@ namespace AzToolsFramework static const AZ::Color s_boxSelectColor = AZ::Color(1.0f, 1.0f, 1.0f, 0.4f); static const float s_boxSelectLineWidth = 2.0f; + EditorBoxSelect::EditorBoxSelect() + { + // discard double click interval as box select is only interested in 'move' detection + // note: this also simplifies integration tests that do not have delays between presses + m_clickDetector.SetDoubleClickInterval(0.0f); + } + void EditorBoxSelect::HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -95,8 +102,7 @@ namespace AzToolsFramework debugDisplay.DepthTestOn(); - m_previousModifiers = ViewportInteraction::KeyboardModifiers( - ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers())); + m_previousModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers(); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h index f1c59f9fd8..3a638b80b6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h @@ -29,7 +29,7 @@ namespace AzToolsFramework class EditorBoxSelect { public: - EditorBoxSelect() = default; + EditorBoxSelect(); //! Return if a box select action is currently taking place. bool Active() const { return m_boxSelectRegion.has_value(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp index d7dd008c9e..7903668409 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp @@ -293,8 +293,8 @@ namespace AzToolsFramework } // poll and set the keyboard modifiers to ensure the mouse interaction is up to date - m_currentInteraction.m_keyboardModifiers = - AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()); + m_currentInteraction.m_keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers(); + // draw the manipulators const AzFramework::CameraState cameraState = GetCameraState(viewportInfo.m_viewportId); debugDisplay.DepthTestOff(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 6442559ede..3db8492d70 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -399,16 +399,18 @@ namespace AzToolsFramework // modifier has changed - swapped from additive to subtractive box select (or vice versa) if (previousKeyboardModifiers != currentKeyboardModifiers) { - for (AZ::EntityId entityId : potentialDeselectedEntityIds) + for (const AZ::EntityId& entityId : potentialDeselectedEntityIds) { editorTransformComponentSelection.AddEntityToSelection(entityId); } + potentialDeselectedEntityIds.clear(); - for (AZ::EntityId entityId : potentialSelectedEntityIds) + for (const AZ::EntityId& entityId : potentialSelectedEntityIds) { editorTransformComponentSelection.RemoveEntityFromSelection(entityId); } + potentialSelectedEntityIds.clear(); } @@ -1162,15 +1164,13 @@ namespace AzToolsFramework m_boxSelect.InstallDisplayScene( [this, entityBoxSelectData](const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { - const auto modifiers = ViewportInteraction::KeyboardModifiers( - ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers())); - - if (m_boxSelect.PreviousModifiers() != modifiers) + if (const auto keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers(); + m_boxSelect.PreviousModifiers() != keyboardModifiers) { EntityBoxSelectUpdateGeneral( m_boxSelect.BoxRegion(), *this, m_selectedEntityIds, entityBoxSelectData->m_selectedEntityIdsBeforeBoxSelect, entityBoxSelectData->m_potentialSelectedEntityIds, entityBoxSelectData->m_potentialDeselectedEntityIds, - *m_entityDataCache, viewportInfo.m_viewportId, modifiers, m_boxSelect.PreviousModifiers()); + *m_entityDataCache, viewportInfo.m_viewportId, keyboardModifiers, m_boxSelect.PreviousModifiers()); } debugDisplay.DepthTestOff(); @@ -3324,16 +3324,15 @@ namespace AzToolsFramework CheckDirtyEntityIds(); - const auto modifiers = - ViewportInteraction::KeyboardModifiers(ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers())); + const auto keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers(); m_cursorState.Update(); HandleAccents( - !m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor, modifiers.Ctrl(), m_hoveredEntityId, + !m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor, keyboardModifiers.Ctrl(), m_hoveredEntityId, ViewportInteraction::BuildMouseButtons(QGuiApplication::mouseButtons()), m_boxSelect.Active()); - const ReferenceFrame referenceFrame = m_spaceCluster.m_spaceLock.value_or(ReferenceFrameFromModifiers(modifiers)); + const ReferenceFrame referenceFrame = m_spaceCluster.m_spaceLock.value_or(ReferenceFrameFromModifiers(keyboardModifiers)); UpdateSpaceCluster(referenceFrame); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index f528a11688..35d3587d0b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -235,7 +235,7 @@ namespace AzToolsFramework // can be returned to its previous state after an undo/redo operation void CreateEntityManipulatorDeselectCommand(ScopedUndoBatch& undoBatch); - // EditorTransformComponentSelectionRequestBus ... + // EditorTransformComponentSelectionRequestBus overrides ... Mode GetTransformMode() override; void SetTransformMode(Mode mode) override; void RefreshManipulators(RefreshType refreshType) override; @@ -252,34 +252,34 @@ namespace AzToolsFramework void CopyScaleToSelectedEntitiesIndividualWorld(float scale) override; void SnapSelectedEntitiesToWorldGrid(float gridSize) override; - // EditorManipulatorCommandUndoRedoRequestBus ... + // EditorManipulatorCommandUndoRedoRequestBus overrides ... void UndoRedoEntityManipulatorCommand(AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override; - // EditorContextMenuBus... + // EditorContextMenuBus overrides ... void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; int GetMenuPosition() const override; AZStd::string GetMenuIdentifier() const override; - // EditorEventsBus ... + // EditorEventsBus overrides ... void OnEscape() override; - // ToolsApplicationNotificationBus ... + // ToolsApplicationNotificationBus overrides ... void BeforeEntitySelectionChanged() override; void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override; - // TransformNotificationBus ... + // TransformNotificationBus overrides ... void OnTransformChanged(const AZ::Transform& localTM, const AZ::Transform& worldTM) override; - // Camera::EditorCameraNotificationBus ... + // Camera::EditorCameraNotificationBus overrides ... void OnViewportViewEntityChanged(const AZ::EntityId& newViewId) override; - // EditorContextVisibilityNotificationBus ... + // EditorContextVisibilityNotificationBus overrides ... void OnEntityVisibilityChanged(bool visibility) override; - // EditorContextLockComponentNotificationBus ... + // EditorContextLockComponentNotificationBus overrides ... void OnEntityLockChanged(bool locked) override; - // EditorComponentModeNotificationBus ... + // EditorComponentModeNotificationBus overrides ... void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; void LeftComponentMode(const AZStd::vector& componentModeTypes) override; @@ -301,7 +301,7 @@ namespace AzToolsFramework //! Responsible for keeping the space cluster in sync with the current reference frame. void UpdateSpaceCluster(ReferenceFrame referenceFrame); - //! Hides/Shows all viewportUi toolbars. + //! Hides/Shows all viewportUi tool bars. void SetAllViewportUiVisible(bool visible); AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any). diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index dc6e38ecd5..8a958af567 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -238,10 +238,32 @@ namespace UnitTest m_entityId3 = createEntityWithBoundsFn("Entity3"); } - public: + void PositionEntities() + { + // the initial starting position of the entities + AZ::TransformBus::Event( + m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(m_entity1WorldTranslation)); + AZ::TransformBus::Event( + m_entityId2, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(m_entity2WorldTranslation)); + AZ::TransformBus::Event( + m_entityId3, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(m_entity3WorldTranslation)); + } + + static void PositionCamera(AzFramework::CameraState& cameraState) + { + // initial camera position (looking down the negative x-axis) + AzFramework::SetCameraTransform( + cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + } + AZ::EntityId m_entityId1; AZ::EntityId m_entityId2; AZ::EntityId m_entityId3; + AZ::Vector3 m_entity1WorldTranslation = AZ::Vector3(5.0f, 15.0f, 10.0f); + AZ::Vector3 m_entity2WorldTranslation = AZ::Vector3(5.0f, 14.0f, 10.0f); + AZ::Vector3 m_entity3WorldTranslation = AZ::Vector3(5.0f, 16.0f, 10.0f); }; void ArrangeIndividualRotatedEntitySelection(const AzToolsFramework::EntityIdList& entityIds, const AZ::Quaternion& orientation) @@ -596,25 +618,18 @@ namespace UnitTest { AzToolsFramework::ed_viewportStickySelect = true; - // the initial starting position of the entity - const auto initialTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)); - AZ::TransformBus::Event(m_entityId1, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorld); - - // initial camera position (looking down the negative x-axis) - AzFramework::SetCameraTransform( - m_cameraState, - AZ::Transform::CreateFromQuaternionAndTranslation( - AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + PositionEntities(); + PositionCamera(m_cameraState); using ::testing::Eq; auto selectedEntitiesBefore = SelectedEntities(); EXPECT_TRUE(selectedEntitiesBefore.empty()); // calculate the position in screen space of the initial entity position - const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState); + const auto entity1ScreenPosition = AzFramework::WorldToScreen(m_entity1WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(initialPositionScreen)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); // entity is selected auto selectedEntitiesAfter = SelectedEntities(); @@ -626,19 +641,12 @@ namespace UnitTest { AzToolsFramework::ed_viewportStickySelect = true; - // the initial starting position of the entity - AZ::TransformBus::Event( - m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); + PositionEntities(); + PositionCamera(m_cameraState); // position in space above the entity const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f); - // initial camera position (looking down the negative x-axis) - AzFramework::SetCameraTransform( - m_cameraState, - AZ::Transform::CreateFromQuaternionAndTranslation( - AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); - AzToolsFramework::SelectEntity(m_entityId1); // calculate the position in screen space of the initial position of the entity @@ -660,30 +668,16 @@ namespace UnitTest { AzToolsFramework::ed_viewportStickySelect = true; - // the initial starting position of the entity - AZ::TransformBus::Event( - m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); - - const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f)); - AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity); - - // initial camera position (looking down the negative x-axis) - AzFramework::SetCameraTransform( - m_cameraState, - AZ::Transform::CreateFromQuaternionAndTranslation( - AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + PositionEntities(); + PositionCamera(m_cameraState); AzToolsFramework::SelectEntity(m_entityId1); // calculate the position in screen space of the second entity - const auto initialPositionScreenSecondEntity = - AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState); + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState) - ->MousePosition(initialPositionScreenSecondEntity) - ->MouseLButtonDown() - ->MouseLButtonUp(); + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); // entity selection was not changed using ::testing::Eq; @@ -698,28 +692,17 @@ namespace UnitTest { AzToolsFramework::ed_viewportStickySelect = true; - // the initial starting position of the entity - AZ::TransformBus::Event( - m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); - - const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f)); - AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity); - - // initial camera position (looking down the negative x-axis) - AzFramework::SetCameraTransform( - m_cameraState, - AZ::Transform::CreateFromQuaternionAndTranslation( - AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + PositionEntities(); + PositionCamera(m_cameraState); AzToolsFramework::SelectEntity(m_entityId1); // calculate the position in screen space of the second entity - const auto initialPositionScreenSecondEntity = - AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState); + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport m_actionDispatcher->CameraState(m_cameraState) - ->MousePosition(initialPositionScreenSecondEntity) + ->MousePosition(entity2ScreenPosition) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() ->MouseLButtonUp(); @@ -736,28 +719,17 @@ namespace UnitTest { AzToolsFramework::ed_viewportStickySelect = true; - // the initial starting position of the entity - AZ::TransformBus::Event( - m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); - - const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f)); - AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity); - - // initial camera position (looking down the negative x-axis) - AzFramework::SetCameraTransform( - m_cameraState, - AZ::Transform::CreateFromQuaternionAndTranslation( - AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + PositionEntities(); + PositionCamera(m_cameraState); AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2 }); // calculate the position in screen space of the second entity - const auto initialPositionScreenSecondEntity = - AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState); + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport m_actionDispatcher->CameraState(m_cameraState) - ->MousePosition(initialPositionScreenSecondEntity) + ->MousePosition(entity2ScreenPosition) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() ->MouseLButtonUp(); @@ -768,39 +740,26 @@ namespace UnitTest EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1)); } - TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, DISABLED_BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) { AzToolsFramework::ed_viewportStickySelect = true; - // the initial starting position of the entities - AZ::TransformBus::Event( - m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f))); - AZ::TransformBus::Event( - m_entityId2, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 14.0f, 10.0f))); - AZ::TransformBus::Event( - m_entityId3, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 16.0f, 10.0f))); - - // initial camera position (looking down the negative x-axis) - AzFramework::SetCameraTransform( - m_cameraState, - AZ::Transform::CreateFromQuaternionAndTranslation( - AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f))); + PositionEntities(); + PositionCamera(m_cameraState); using ::testing::Eq; auto selectedEntitiesBefore = SelectedEntities(); EXPECT_THAT(selectedEntitiesBefore.size(), Eq(0)); // calculate the position in screen space of where to begin and end the box select action - const auto beginningPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState); - const auto middlePositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 15.0f, 10.0f), m_cameraState); - const auto endingPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); + const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState); + const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); // perform a box select in the viewport m_actionDispatcher->CameraState(m_cameraState) - ->MousePosition(beginningPositionWorldBoxSelectStart) + ->MousePosition(beginningPositionWorldBoxSelect) ->MouseLButtonDown() - ->MousePosition(middlePositionWorldBoxSelectStart) - ->MousePosition(endingPositionWorldBoxSelectStart) + ->MousePosition(endingPositionWorldBoxSelect) ->MouseLButtonUp(); // entities are selected @@ -809,6 +768,73 @@ namespace UnitTest EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3)); } + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithSelectionAppendsEntitiesToSelection) + { + AzToolsFramework::ed_viewportStickySelect = true; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntity(m_entityId1); + + using ::testing::UnorderedElementsAre; + auto selectedEntitiesBefore = SelectedEntities(); + EXPECT_THAT(selectedEntitiesBefore, UnorderedElementsAre(m_entityId1)); + + // calculate the position in screen space of where to begin and end the box select action + const auto beginningPositionWorldBoxSelect1 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 14.5f, 10.5f), m_cameraState); + const auto endingPositionWorldBoxSelect1 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 9.5f), m_cameraState); + const auto beginningPositionWorldBoxSelect2 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 15.5f, 10.5f), m_cameraState); + const auto endingPositionWorldBoxSelect2 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); + + // perform a box select in the viewport (going left and right) + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(beginningPositionWorldBoxSelect1) + ->MouseLButtonDown() + ->MousePosition(endingPositionWorldBoxSelect1) + ->MouseLButtonUp() + ->MousePosition(beginningPositionWorldBoxSelect2) + ->MouseLButtonDown() + ->MousePosition(endingPositionWorldBoxSelect2) + ->MouseLButtonUp(); + + // entities are selected + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + BoxSelectHoldingCtrlWithSelectionRemovesEntitiesFromSelection) + { + AzToolsFramework::ed_viewportStickySelect = true; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2, m_entityId3 }); + + using ::testing::UnorderedElementsAre; + auto selectedEntitiesBefore = SelectedEntities(); + EXPECT_THAT(selectedEntitiesBefore, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3)); + + // calculate the position in screen space of where to begin and end the box select action + const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState); + const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); + + // perform a box select in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(beginningPositionWorldBoxSelect) + ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) + ->MouseLButtonDown() + ->MousePosition(endingPositionWorldBoxSelect) + ->MouseLButtonUp(); + + // entities are selected + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_TRUE(selectedEntitiesAfter.empty()); + } + using EditorTransformComponentSelectionManipulatorTestFixture = IndirectCallManipulatorViewportInteractionFixtureMixin; diff --git a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponentMode.cpp b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponentMode.cpp index 13dc29599d..4bca7a9c96 100644 --- a/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponentMode.cpp +++ b/Gems/WhiteBox/Code/Source/EditorWhiteBoxComponentMode.cpp @@ -52,8 +52,7 @@ namespace WhiteBox // default behavior for querying modifier keys (ask the QApplication) m_keyboardMofifierQueryFn = []() { - namespace vi = AzToolsFramework::ViewportInteraction; - return vi::KeyboardModifiers(vi::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers())); + return AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers(); }; m_worldFromLocal = AzToolsFramework::WorldFromLocalWithUniformScale(entityComponentIdPair.GetEntityId()); diff --git a/Gems/WhiteBox/Code/Tests/WhiteBoxComponentTest.cpp b/Gems/WhiteBox/Code/Tests/WhiteBoxComponentTest.cpp index e2549a6126..0e93f38195 100644 --- a/Gems/WhiteBox/Code/Tests/WhiteBoxComponentTest.cpp +++ b/Gems/WhiteBox/Code/Tests/WhiteBoxComponentTest.cpp @@ -301,7 +301,7 @@ namespace UnitTest &WhiteBox::EditorWhiteBoxComponentModeRequestBus::Events::OverrideKeyboardModifierQuery, [this]() { - return m_actionDispatcher->GetKeyboardModifiers(); + return m_actionDispatcher->QueryKeyboardModifiers(); }); AzFramework::SetCameraTransform( From 6628f5bad176151eef37290c9919b3e4bf39385f Mon Sep 17 00:00:00 2001 From: moraaar Date: Mon, 13 Sep 2021 15:22:00 +0100 Subject: [PATCH 083/274] Marking script canvas failing tests as xfail until they can be reworked to make them pass. (#4077) Signed-off-by: moraaar --- .../Gem/PythonTests/scripting/CMakeLists.txt | 2 ++ .../Gem/PythonTests/scripting/TestSuite_Periodic.py | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt index 25988216b2..ed61dfaf33 100644 --- a/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/scripting/CMakeLists.txt @@ -28,5 +28,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) Legacy::Editor AZ::AssetProcessor AutomatedTesting.Assets + COMPONENT + ScriptCanvas ) endif() diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py index 642818281b..0862e03a79 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py @@ -37,6 +37,7 @@ class TestAutomation(TestAutomationBase): from . import Pane_HappyPath_ResizesProperly as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptCanvas_TwoComponents_InteractSuccessfully(self, request, workspace, editor, launcher_platform, level): def teardown(): @@ -46,6 +47,7 @@ class TestAutomation(TestAutomationBase): from . import ScriptCanvas_TwoComponents_InteractSuccessfully as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptCanvas_ChangingAssets_ComponentStable(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -63,6 +65,7 @@ class TestAutomation(TestAutomationBase): from . import NodePalette_HappyPath_CanSelectNode as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptCanvasComponent_OnEntityActivatedDeactivated_PrintMessage(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -76,6 +79,7 @@ class TestAutomation(TestAutomationBase): from . import NodePalette_HappyPath_ClearSelection as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptCanvas_TwoEntities_UseSimultaneously(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -139,6 +143,7 @@ class TestAutomation(TestAutomationBase): from . import Pane_Default_RetainOnSCRestart as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptEvents_HappyPath_SendReceiveAcrossMultiple(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -148,6 +153,7 @@ class TestAutomation(TestAutomationBase): from . import ScriptEvents_HappyPath_SendReceiveAcrossMultiple as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptEvents_Default_SendReceiveSuccessfully(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -157,6 +163,7 @@ class TestAutomation(TestAutomationBase): from . import ScriptEvents_Default_SendReceiveSuccessfully as test_module self._run_test(request, workspace, editor, test_module) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_ScriptEvents_ReturnSetType_Successfully(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -204,6 +211,7 @@ class TestScriptCanvasTests(object): The following tests use hydra_test_utils.py to launch the editor and validate the results. """ + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") def test_FileMenu_Default_NewAndOpen(self, request, editor, launcher_platform): expected_lines = [ "File->New action working as expected: True", @@ -213,6 +221,7 @@ class TestScriptCanvasTests(object): request, TEST_DIRECTORY, editor, "FileMenu_Default_NewAndOpen.py", expected_lines, auto_test_mode=False, timeout=60, ) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") def test_NewScriptEventButton_HappyPath_ContainsSCCategory(self, request, editor, launcher_platform): expected_lines = [ "New Script event action found: True", @@ -295,6 +304,7 @@ class TestScriptCanvasTests(object): timeout=60, ) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") def test_ScriptEvent_AddRemoveMethod_UpdatesInSC(self, request, workspace, editor, launcher_platform): def teardown(): file_system.delete( @@ -322,6 +332,7 @@ class TestScriptCanvasTests(object): timeout=60, ) + @pytest.mark.xfail(reason="Test fails to find expected lines, it needs to be fixed.") def test_ScriptEvents_AllParamDatatypes_CreationSuccess(self, request, workspace, editor, launcher_platform): def teardown(): file_system.delete( From 9b0e3f26b14e6573ad0877a63ef9e9d66879cefb Mon Sep 17 00:00:00 2001 From: pereslav Date: Mon, 13 Sep 2021 16:30:42 +0100 Subject: [PATCH 084/274] PR feedback addressing 2 Signed-off-by: pereslav --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 4e0818323e..793acc17ff 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -500,10 +500,11 @@ namespace Multiplayer AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_priority = AzFramework::SpawnablePriority_High; - AZ::Name netSpawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); + const AZ::Name netSpawnableName = + AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [netSpawnableName = netSpawnableName](AzFramework::EntitySpawnTicket::Id, + optionalArgs.m_preInsertionCallback = [netSpawnableName](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); From 9c07078ee859d65f46e1775f1eb9b06f5f3425ec Mon Sep 17 00:00:00 2001 From: sphrose <82213493+sphrose@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:58:20 +0100 Subject: [PATCH 085/274] Change shape type in test mock plus bugfix. (#4073) Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> --- Gems/Terrain/Code/Tests/TerrainMocks.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Terrain/Code/Tests/TerrainMocks.h b/Gems/Terrain/Code/Tests/TerrainMocks.h index 5f90cafd69..674104e26b 100644 --- a/Gems/Terrain/Code/Tests/TerrainMocks.h +++ b/Gems/Terrain/Code/Tests/TerrainMocks.h @@ -46,6 +46,7 @@ namespace UnitTest { provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); provided.push_back(AZ_CRC("BoxShapeService", 0x946a0032)); + provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); } static void GetIncompatibleServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& incompatible) @@ -74,7 +75,7 @@ namespace UnitTest Terrain::TerrainSystemServiceRequestBus::Handler::BusDisconnect(); } - void SetWorldBounds(const AZ::Aabb& worldBounds) override + void SetWorldBounds([[maybe_unused]] const AZ::Aabb& worldBounds) override { } From 4c1c2d6f6bc8e66ff90432e77861844aabf4099d Mon Sep 17 00:00:00 2001 From: "rgba16f [Amazon]" <82187279+rgba16f@users.noreply.github.com> Date: Mon, 13 Sep 2021 11:19:20 -0500 Subject: [PATCH 086/274] update freetype library revision used (#4065) * Update freetype linux package revision * Update mac & ios revisions of the freetype library * Update Mac freetype to use rev 16 * update linux to use freetype rev 16 * Update Android & Mac to use freetype rev 16 Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake | 2 +- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index f22de7e4c8..0d9be5bb49 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -16,7 +16,7 @@ ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zst ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) # platform-specific: -ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-android TARGETS freetype PACKAGE_HASH 74dd75382688323c3a2a5090f473840b5d7e9d2aed1a4fcdff05ed2a09a664f2) +ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-android TARGETS freetype PACKAGE_HASH df9e4d559ea0f03b0666b48c79813b1cd4d9624429148a249865de9f5c2c11cd) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-android TARGETS tiff PACKAGE_HASH a9b30a1980946390c2fad0ed94562476a1d7ba8c1f36934ae140a89c54a8efd0) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-android TARGETS AWSNativeSDK PACKAGE_HASH 1624ba9aaf03d001ed0ffc57d2f945ff82590e75a7ea868de35043cf673e82fb) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index c9315336b9..2f0669f635 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -25,7 +25,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) -ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) +ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 4d62f6a7bf..1799fde7b9 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -27,7 +27,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-mac TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 3f77367dbb0342136ec4ebbd44bc1fedf7198089a0f83c5631248530769b2be6) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) -ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) +ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-mac TARGETS freetype PACKAGE_HASH f159b346ac3251fb29cb8dd5f805c99b0015ed7fdb3887f656945ca701a61d0d) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-mac TARGETS AWSNativeSDK PACKAGE_HASH ffb890bd9cf23afb429b9214ad9bac1bf04696f07a0ebb93c42058c482ab2f01) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 64cbfa05dd..e0b77fb0fa 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -28,7 +28,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-windows TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 803e10b94006b834cbbdd30f562a8ddf04174c2cb6956c8399ec164ef8418d1f) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817) -ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) +ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-windows TARGETS freetype PACKAGE_HASH 9809255f1c59b07875097aa8d8c6c21c97c47a31fb35e30f2bb93188e99a85ff) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-windows TARGETS AWSNativeSDK PACKAGE_HASH a900e80f7259e43aed5c847afee2599ada37f29db70505481397675bcbb6c76c) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index 69576bb665..ea51158f4a 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -17,7 +17,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS gla ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) # platform-specific: -ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) +ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-ios TARGETS freetype PACKAGE_HASH 3ac3c35e056ae4baec2e40caa023d76a7a3320895ef172b6655e9261b0dc2e29) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-ios TARGETS AWSNativeSDK PACKAGE_HASH 1246219a213ccfff76b526011febf521586d44dbc1753e474f8fb5fd861654a4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) From 1e3c8edc401ffa6a19ea09ef500c2c11f41b996a Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:04:20 +0100 Subject: [PATCH 087/274] Remove viewport freeze request bus (#4089) Signed-off-by: hultonha --- Code/Editor/CryEditPy.cpp | 4 ---- Code/Editor/EditorViewportWidget.cpp | 22 ------------------- Code/Editor/EditorViewportWidget.h | 8 ------- .../Viewport/ViewportMessages.h | 18 --------------- 4 files changed, 52 deletions(-) diff --git a/Code/Editor/CryEditPy.cpp b/Code/Editor/CryEditPy.cpp index 7a407aac37..1b38fe23b8 100644 --- a/Code/Editor/CryEditPy.cpp +++ b/Code/Editor/CryEditPy.cpp @@ -77,10 +77,6 @@ namespace // This closes the current document (level) currentLevel->OnNewDocument(); - // Then we freeze the viewport's input - AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Broadcast( - &AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Events::FreezeViewportInput, true); - // Then we need to tell the game engine there is no level to render anymore if (GetIEditor()->GetGameEngine()) { diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 851d2c5b6f..7631ac6237 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -669,16 +669,6 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) case eNotify_OnEndSceneSave: PopDisableRendering(); break; - - case eNotify_OnBeginLoad: // disables viewport input when starting to load an existing level - case eNotify_OnBeginCreate: // disables viewport input when starting to create a new level - m_freezeViewportInput = true; - break; - - case eNotify_OnEndLoad: // enables viewport input when finished loading an existing level - case eNotify_OnEndCreate: // enables viewport input when finished creating a new level - m_freezeViewportInput = false; - break; } } @@ -962,16 +952,6 @@ AzFramework::ScreenPoint EditorViewportWidget::ViewportWorldToScreen(const AZ::V return m_renderViewport->ViewportWorldToScreen(worldPosition); } -bool EditorViewportWidget::IsViewportInputFrozen() -{ - return m_freezeViewportInput; -} - -void EditorViewportWidget::FreezeViewportInput(bool freeze) -{ - m_freezeViewportInput = freeze; -} - QWidget* EditorViewportWidget::GetWidgetForViewportContextMenu() { return this; @@ -1057,7 +1037,6 @@ void EditorViewportWidget::SetViewportId(int id) void EditorViewportWidget::ConnectViewportInteractionRequestBus() { - AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusConnect(GetViewportId()); AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); m_viewportUi.ConnectViewportUiBus(GetViewportId()); @@ -1072,7 +1051,6 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus() m_viewportUi.DisconnectViewportUiBus(); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect(); - AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusDisconnect(); } namespace AZ::ViewportHelpers diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index 825d21a034..c4a8e9fcca 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -89,7 +89,6 @@ class SANDBOX_API EditorViewportWidget final , private Camera::EditorCameraRequestBus::Handler , private Camera::CameraNotificationBus::Handler , private AzFramework::InputSystemCursorConstraintRequestBus::Handler - , private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler , private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler , private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler , private AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler @@ -202,10 +201,6 @@ private: // AzFramework::InputSystemCursorConstraintRequestBus overrides ... void* GetSystemCursorConstraintWindow() const override; - // AzToolsFramework::ViewportFreezeRequestBus overrides ... - bool IsViewportInputFrozen() override; - void FreezeViewportInput(bool freeze) override; - // AzToolsFramework::MainEditorViewportInteractionRequestBus overrides ... AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override; AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override; @@ -387,9 +382,6 @@ private: // Unclear if it's still necessary. QSet m_keyDown; - // State for ViewportFreezeRequestBus, currently does nothing - bool m_freezeViewportInput = false; - // This widget holds a reference to the manipulator manage because its responsible for drawing manipulators AZStd::shared_ptr m_manipulatorManager; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index c90c506a05..8bddeb7a44 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -221,24 +221,6 @@ namespace AzToolsFramework using ViewportSettingsNotificationBus = AZ::EBus; - //! Requests to freeze the Viewport Input - //! Added to prevent a bug with the legacy CryEngine Viewport code that would - //! keep doing raycast tests even when no level is loaded, causing a crash. - class ViewportFreezeRequests - { - public: - //! Return if Viewport Input is frozen - virtual bool IsViewportInputFrozen() = 0; - //! Sets the Viewport Input freeze state - virtual void FreezeViewportInput(bool freeze) = 0; - - protected: - ~ViewportFreezeRequests() = default; - }; - - //! Type to inherit to implement ViewportFreezeRequests. - using ViewportFreezeRequestBus = AZ::EBus; - //! Viewport requests that are only guaranteed to be serviced by the Main Editor viewport. class MainEditorViewportInteractionRequests { From 32e6473de2d6db4b7c4725a86baeaff5ee068752 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 13 Sep 2021 10:41:53 -0700 Subject: [PATCH 088/274] [development] Update RapidXML package info (#4057) Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake | 2 +- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index 0d9be5bb49..119fc324c6 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -9,7 +9,7 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) -ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) +ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 2f0669f635..f66f762f7a 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -12,7 +12,7 @@ ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) -ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) +ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 1799fde7b9..ebc5de729a 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -12,7 +12,7 @@ ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) -ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) +ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index e0b77fb0fa..05368d1f6a 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -12,7 +12,7 @@ ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) -ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) +ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index ea51158f4a..2f12d7f81e 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -9,7 +9,7 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) -ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) +ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) From de3d2a2b693be2d9f1769fb7247282b4281e3ab3 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 13 Sep 2021 11:15:23 -0700 Subject: [PATCH 089/274] Detects that binary dir and install prefix are not the same (#4091) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/OutputDirectory.cmake | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/OutputDirectory.cmake b/cmake/OutputDirectory.cmake index a75b47e818..6906f76de5 100644 --- a/cmake/OutputDirectory.cmake +++ b/cmake/OutputDirectory.cmake @@ -14,6 +14,16 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Build dir # We install outside of the binary dir because our install support muliple platforms to # be installed together. We also have an exclusion rule in the AP that filters out the # "install" folder to avoid the AP picking it up +unset(define_with_force) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install CACHE PATH "Install directory" FORCE) + set(define_with_force FORCE) +endif() +set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install CACHE PATH "Install directory" ${define_with_force}) + +cmake_path(ABSOLUTE_PATH CMAKE_BINARY_DIR NORMALIZE OUTPUT_VARIABLE cmake_binary_dir_normalized) +cmake_path(ABSOLUTE_PATH CMAKE_INSTALL_PREFIX NORMALIZE OUTPUT_VARIABLE cmake_install_prefix_normalized) +cmake_path(COMPARE ${cmake_binary_dir_normalized} EQUAL ${cmake_install_prefix_normalized} are_paths_equal) +if(are_paths_equal) + message(FATAL_ERROR "Binary dir is the same path as install prefix, indicate a different install prefix with " + "CMAKE_INSTALL_PREFIX or a different binary dir with -B ") endif() From 6103c9c63cca0889243b8e49729bfbbfc304cfa4 Mon Sep 17 00:00:00 2001 From: Nicholas Lawson <70027408+lawsonamzn@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:35:29 -0700 Subject: [PATCH 090/274] Updates libtiff for all platforms (#4068) The new libtiff is uniform, and static, across all platforms. It includes zlib support and uses our own zlib. Signed-off-by: lawsonamzn <70027408+lawsonamzn@users.noreply.github.com> --- cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake | 2 +- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index 119fc324c6..47c3c66463 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -16,8 +16,8 @@ ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zst ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) # platform-specific: +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-android TARGETS tiff PACKAGE_HASH 252b99e5886ec59fdccf38603c1399dd3fc02d878641aba35a7f8d2504065a06) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-android TARGETS freetype PACKAGE_HASH df9e4d559ea0f03b0666b48c79813b1cd4d9624429148a249865de9f5c2c11cd) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-android TARGETS tiff PACKAGE_HASH a9b30a1980946390c2fad0ed94562476a1d7ba8c1f36934ae140a89c54a8efd0) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-android TARGETS AWSNativeSDK PACKAGE_HASH 1624ba9aaf03d001ed0ffc57d2f945ff82590e75a7ea868de35043cf673e82fb) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-android TARGETS PhysX PACKAGE_HASH b8cb6aa46b2a21671f6cb1f6a78713a3ba88824d0447560ff5ce6c01014b9f43) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index f66f762f7a..429665f04a 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -25,8 +25,8 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-linux TARGETS tiff PACKAGE_HASH 19791da0a370470a6c187199f97c2c46efcc2d89146e2013775fb3600fd7317d) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-linux TARGETS PhysX PACKAGE_HASH a110249cbef4f266b0002c4ee9a71f59f373040cefbe6b82f1e1510c811edde6) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index ebc5de729a..4900a9d77e 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -27,8 +27,8 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-mac TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 3f77367dbb0342136ec4ebbd44bc1fedf7198089a0f83c5631248530769b2be6) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-mac TARGETS tiff PACKAGE_HASH b6f3040319f5bfe465d7e3f9b12ceed0dc951e66e05562beaac1c8da3b1b5d3f) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-mac TARGETS freetype PACKAGE_HASH f159b346ac3251fb29cb8dd5f805c99b0015ed7fdb3887f656945ca701a61d0d) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-mac TARGETS AWSNativeSDK PACKAGE_HASH ffb890bd9cf23afb429b9214ad9bac1bf04696f07a0ebb93c42058c482ab2f01) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 05368d1f6a..3855b7d712 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -28,8 +28,8 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-windows TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 803e10b94006b834cbbdd30f562a8ddf04174c2cb6956c8399ec164ef8418d1f) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-windows TARGETS tiff PACKAGE_HASH ff03464ca460fc34a8406b2a0c548ad221b10e40480b0abb954f1e649c20bad0) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-windows TARGETS freetype PACKAGE_HASH 9809255f1c59b07875097aa8d8c6c21c97c47a31fb35e30f2bb93188e99a85ff) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-windows TARGETS AWSNativeSDK PACKAGE_HASH a900e80f7259e43aed5c847afee2599ada37f29db70505481397675bcbb6c76c) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-windows TARGETS PhysX PACKAGE_HASH 0c5ffbd9fa588e5cf7643721a7cfe74d0fe448bf82252d39b3a96d06dfca2298) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index 2f12d7f81e..25fbaf830f 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -17,8 +17,8 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS gla ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) # platform-specific: +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-ios TARGETS tiff PACKAGE_HASH d864beb0c955a55f28c2a993843afb2ecf6e01519ddfc857cedf34fc5db68d49) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-ios TARGETS freetype PACKAGE_HASH 3ac3c35e056ae4baec2e40caa023d76a7a3320895ef172b6655e9261b0dc2e29) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-ios TARGETS AWSNativeSDK PACKAGE_HASH 1246219a213ccfff76b526011febf521586d44dbc1753e474f8fb5fd861654a4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-ios TARGETS PhysX PACKAGE_HASH b1bbc1fc068d2c6e1eb18eecd4e8b776adc516833e8da3dcb1970cef2a8f0cbd) From aa6c03888051eb90999428936efa7c5d28455ba0 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:51:50 -0400 Subject: [PATCH 091/274] Hierarchical components, phase 1, unittests Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Multiplayer/Components/NetBindComponent.h | 2 + .../Components/NetworkHierarchyBus.h | 46 + .../NetworkHierarchyChildComponent.h | 66 + .../NetworkHierarchyRootComponent.h | 76 ++ .../Components/NetworkTransformComponent.h | 4 + ...kHierarchyChildComponent.AutoComponent.xml | 14 + ...rkHierarchyRootComponent.AutoComponent.xml | 14 + .../NetworkHierarchyChildComponent.cpp | 134 ++ .../NetworkHierarchyRootComponent.cpp | 277 ++++ .../Components/NetworkTransformComponent.cpp | 43 +- .../Code/Source/MultiplayerGem.cpp | 6 +- .../EntityReplicationManager.cpp | 26 +- .../EntityReplication/EntityReplicator.cpp | 96 +- .../EntityReplication/EntityReplicator.h | 4 +- .../Code/Tests/ClientHierarchyTests.cpp | 379 ++++++ .../Code/Tests/CommonHierarchySetup.h | 387 ++++++ Gems/Multiplayer/Code/Tests/MockInterfaces.h | 166 +++ .../Code/Tests/ServerHierarchyTests.cpp | 1145 +++++++++++++++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 42 +- .../Code/multiplayer_tests_files.cmake | 4 + 20 files changed, 2886 insertions(+), 45 deletions(-) create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp create mode 100644 Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp create mode 100644 Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h create mode 100644 Gems/Multiplayer/Code/Tests/MockInterfaces.h create mode 100644 Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index 65bac09726..855d109145 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -199,6 +199,8 @@ namespace Multiplayer friend class NetworkEntityManager; friend class EntityReplicationManager; + + friend class HierarchyTests; }; bool NetworkRoleHasController(NetEntityRole networkRole); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h new file mode 100644 index 0000000000..72dff65401 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace Multiplayer +{ + class NetworkHierarchyNotifications + : public AZ::ComponentBus + { + public: + //! Called when a hierarchy has been updated (a child added or removed, etc.) + virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {} + + //! Called when an entity has left a hierarchy + virtual void OnLeavingNetworkHierarchy() {} + }; + + typedef AZ::EBus NetworkHierarchyNotificationBus; + + class NetworkHierarchyRequests + : public AZ::ComponentBus + { + public: + //! @returns hierarchical entities, the first element is the top level root + virtual AZStd::vector GetHierarchicalEntities() const = 0; + + //! @returns the top level root of a hierarchy, or nullptr if this entity is not in a hierarchy + virtual AZ::Entity* GetHierarchicalRoot() const = 0; + + //! @return true if this entity is a child entity within a hierarchy + virtual bool IsHierarchicalChild() const = 0; + + //! @return true if this entity is the top level root of a hierarchy + virtual bool IsHierarchicalRoot() const = 0; + }; + + typedef AZ::EBus NetworkHierarchyRequestBus; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h new file mode 100644 index 0000000000..27f794ec21 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +namespace Multiplayer +{ + class NetworkHierarchyRootComponent; + + //! @class NetworkHierarchyChildComponent + //! @brief Component that declares network dependency on the parent of this entity + /* + * The parent of this entity should have @NetworkHierarchyChildComponent (or @NetworkHierarchyRootComponent). + * A network hierarchy is a collection of entities with one @NetworkHierarchyRootComponent at the top parent + * and one or more @NetworkHierarchyChildComponent on its child entities. + */ + class NetworkHierarchyChildComponent final + : public NetworkHierarchyChildComponentBase + , public NetworkHierarchyRequestBus::Handler + { + friend class NetworkHierarchyRootComponent; + + public: + AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyChildComponent, s_networkHierarchyChildComponentConcreteUuid, Multiplayer::NetworkHierarchyChildComponentBase); + + static void Reflect(AZ::ReflectContext* context); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + NetworkHierarchyChildComponent(); + + //! @{ + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + //! @} + + //! NetworkHierarchyRequestBus overrides + //! @{ + bool IsHierarchicalChild() const override; + bool IsHierarchicalRoot() const override { return false; } + AZ::Entity* GetHierarchicalRoot() const override; + AZStd::vector GetHierarchicalEntities() const override; + //! @} + + protected: + //! Used by @NetworkHierarchyRootComponent + void SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot); + + private: + const NetworkHierarchyRootComponent* m_hierarchyRootComponent = nullptr; + + AZ::Event::Handler m_hierarchyRootNetIdChanged; + void OnHierarchyRootNetIdChanged(NetEntityId rootNetId); + }; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h new file mode 100644 index 0000000000..48c003d9e7 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace Multiplayer +{ + //! @class NetworkHierarchyRootComponent + //! @brief Component that declares the top level entity of a network hierarchy. + /* + * Call @GetHierarchyChildren to get the list of hierarchical entities. + * A network hierarchy is meant to be a small group of entities. You can control the maximum supported size of + * a network hierarchy by modifying CVar @bg_hierarchyEntityMaxLimit. + * + * A root component marks either a top most root of a hierarchy, or an inner root of an attach hierarchy. + */ + class NetworkHierarchyRootComponent final + : public NetworkHierarchyRootComponentBase + , public NetworkHierarchyRequestBus::Handler + , protected AZ::TransformNotificationBus::MultiHandler + { + public: + AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase); + + static void Reflect(AZ::ReflectContext* context); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + //! NetworkHierarchyRootComponentBase overrides. + //! @{ + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + //! @} + + //! NetworkHierarchyRequestBus overrides. + //! @{ + bool IsHierarchicalRoot() const override; + bool IsHierarchicalChild() const override; + AZStd::vector GetHierarchicalEntities() const override; + AZ::Entity* GetHierarchicalRoot() const override; + //! @} + + protected: + //! AZ::TransformNotificationBus::Handler overrides. + //! @{ + void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent) override; + void OnChildAdded(AZ::EntityId child) override; + void OnChildRemoved(AZ::EntityId childRemovedId) override; + //! @} + + void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); + + private: + AZ::Entity* m_higherRootEntity = nullptr; + AZStd::vector m_hierarchicalEntities; + + void RebuildHierarchy(); + + //! @returns false if the maximum supported hierarchy size has been reached + bool RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount); + //! @returns false if the maximum supported hierarchy size has been reached + bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); + }; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index 914aeaadd3..969b59a672 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -36,6 +36,7 @@ namespace Multiplayer void OnTranslationChangedEvent(const AZ::Vector3& translation); void OnScaleChangedEvent(float scale); void OnResetCountChangedEvent(); + void OnParentIdChangedEvent(NetEntityId newParent); void UpdateTargetHostFrameId(); @@ -46,6 +47,7 @@ namespace Multiplayer AZ::Event::Handler m_translationEventHandler; AZ::Event::Handler m_scaleEventHandler; AZ::Event::Handler m_resetCountEventHandler; + AZ::Event::Handler m_parentIdChangedEventHandler; EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; EntityCorrectionEvent::Handler m_entityCorrectionEventHandler; @@ -64,7 +66,9 @@ namespace Multiplayer private: void OnTransformChangedEvent(const AZ::Transform& worldTm); + void OnParentIdChangedEvent(AZ::EntityId oldParent, AZ::EntityId newParent); AZ::TransformChangedEvent::Handler m_transformChangedHandler; + AZ::ParentChangedEvent::Handler m_parentIdChangedHandler; }; } diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml new file mode 100644 index 0000000000..46523d3724 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml new file mode 100644 index 0000000000..0f33e1f642 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp new file mode 100644 index 0000000000..c644b832a0 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + void NetworkHierarchyChildComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "Network Hierarchy Child", "declares a network dependency on the root of this hierarchy") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ; + } + } + NetworkHierarchyChildComponentBase::Reflect(context); + } + + void NetworkHierarchyChildComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("NetworkTransformComponent")); + } + + void NetworkHierarchyChildComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent")); + } + + void NetworkHierarchyChildComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent")); + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); + } + + NetworkHierarchyChildComponent::NetworkHierarchyChildComponent() + : m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); }) + { + + } + + void NetworkHierarchyChildComponent::OnInit() + { + } + + void NetworkHierarchyChildComponent::OnActivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) + { + HierarchyRootAddEvent(m_hierarchyRootNetIdChanged); + NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); + } + + void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) + { + NetworkHierarchyRequestBus::Handler::BusDisconnect(); + } + + bool NetworkHierarchyChildComponent::IsHierarchicalChild() const + { + if (GetHierarchyRoot() != InvalidNetEntityId) + { + return true; + } + + return false; + } + + AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const + { + return m_hierarchyRootComponent ? m_hierarchyRootComponent->GetEntity() : nullptr; + } + + AZStd::vector NetworkHierarchyChildComponent::GetHierarchicalEntities() const + { + if (m_hierarchyRootComponent) + { + return m_hierarchyRootComponent->GetHierarchicalEntities(); + } + + return {}; + } + + void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot) + { + m_hierarchyRootComponent = hierarchyRoot; + if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) + { + NetworkHierarchyChildComponentController* controller = static_cast(GetController()); + if (hierarchyRoot) + { + const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetEntityId()); + controller->SetHierarchyRoot(netRootId); + + NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyUpdated, hierarchyRoot->GetEntityId()); + } + else + { + controller->SetHierarchyRoot(InvalidNetEntityId); + NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnLeavingNetworkHierarchy); + } + } + } + + void NetworkHierarchyChildComponent::OnHierarchyRootNetIdChanged(NetEntityId rootNetId) + { + const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId); + if (rootHandle.Exists()) + { + m_hierarchyRootComponent = rootHandle.FindComponent(); + } + else + { + m_hierarchyRootComponent = nullptr; + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp new file mode 100644 index 0000000000..2fa960ed2a --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -0,0 +1,277 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +AZ_CVAR(uint32_t, bg_hierarchyEntityMaxLimit, 16, nullptr, AZ::ConsoleFunctorFlags::Null, + "Maximum allowed size of network entity hierarchies, including top level entity."); + +namespace Multiplayer +{ + void NetworkHierarchyRootComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "Network Hierarchy Root", "marks the entity as the root of an entity hierarchy") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ; + } + } + NetworkHierarchyRootComponentBase::Reflect(context); + } + + void NetworkHierarchyRootComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("NetworkTransformComponent")); + } + + void NetworkHierarchyRootComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); + } + + void NetworkHierarchyRootComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent")); + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); + } + + void NetworkHierarchyRootComponent::OnInit() + { + } + + void NetworkHierarchyRootComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + m_hierarchicalEntities.push_back(GetEntity()); + + NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); + AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + } + + void NetworkHierarchyRootComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); + NetworkHierarchyRequestBus::Handler::BusDisconnect(); + + for (const AZ::Entity* childEntity : m_hierarchicalEntities) + { + auto* hierarchyChildComponent = childEntity->FindComponent(); + auto* hierarchyRootComponent = childEntity->FindComponent(); + + if (hierarchyChildComponent) + { + hierarchyChildComponent->SetTopLevelHierarchyRootComponent(nullptr); + } + if (hierarchyRootComponent) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr); + } + } + + m_hierarchicalEntities.clear(); + m_higherRootEntity = nullptr; + } + + bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const + { + if (GetHierarchyRoot() != InvalidNetEntityId) + { + return false; + } + + return true; + } + + bool NetworkHierarchyRootComponent::IsHierarchicalChild() const + { + return !IsHierarchicalRoot(); + } + + AZStd::vector NetworkHierarchyRootComponent::GetHierarchicalEntities() const + { + return m_hierarchicalEntities; + } + + AZ::Entity* NetworkHierarchyRootComponent::GetHierarchicalRoot() const + { + if (m_higherRootEntity) + { + return m_higherRootEntity; + } + + return GetEntity(); + } + + void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) + { + const AZ::EntityId entityBusId = *AZ::TransformNotificationBus::GetCurrentBusId(); + if (GetEntityId() != entityBusId) + { + return; // ignore parent changes of child entities + } + + if (AZ::Entity* parentEntity = AZ::Interface::Get()->FindEntity(newParent)) + { + if (parentEntity->FindComponent()) + { + m_higherRootEntity = parentEntity; + m_hierarchicalEntities.clear(); + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); + + // Should still listen for its events, such as when this root detaches + AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + } + } + else + { + // detached from parent + RebuildHierarchy(); + } + } + + void NetworkHierarchyRootComponent::OnChildAdded([[maybe_unused]] AZ::EntityId child) + { + // Parent-child notifications from TransformNotificationBus are not reliable enough to avoid duplicate notifications, + // so we will rebuild from scratch to avoid duplicate entries in @m_hierarchicalEntities. + RebuildHierarchy(); + } + + void NetworkHierarchyRootComponent::RebuildHierarchy() + { + m_hierarchicalEntities.clear(); + m_hierarchicalEntities.push_back(GetEntity()); // add the root itself + + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); + AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + + uint32_t currentEntityCount = aznumeric_cast(m_hierarchicalEntities.size()); + RecursiveAttachHierarchicalEntities(GetEntityId(), currentEntityCount); + } + + bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount) + { + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, underEntity, &AZ::TransformBus::Events::GetChildren); + + for (const AZ::EntityId newChildId : allChildren) + { + if (!RecursiveAttachHierarchicalChild(newChildId, currentEntityCount)) + { + return false; + } + } + + return true; + } + + bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount) + { + if (currentEntityCount >= bg_hierarchyEntityMaxLimit) + { + AZLOG_WARN("Entity %s is trying to build a network hierarchy that is too large. bg_hierarchyEntityMaxLimit is currently set to (%u)", + GetEntity()->GetName().c_str(), static_cast(bg_hierarchyEntityMaxLimit)); + return false; + } + + if (AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entity)) + { + auto* hierarchyChildComponent = childEntity->FindComponent(); + auto* hierarchyRootComponent = childEntity->FindComponent(); + + if (hierarchyChildComponent || hierarchyRootComponent) + { + AZ::TransformNotificationBus::MultiHandler::BusConnect(entity); + m_hierarchicalEntities.push_back(childEntity); + ++currentEntityCount; + + if (hierarchyChildComponent) + { + hierarchyChildComponent->SetTopLevelHierarchyRootComponent(this); + } + else if (hierarchyRootComponent) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(GetEntity()); + } + + if (!RecursiveAttachHierarchicalEntities(entity, currentEntityCount)) + { + return false; + } + } + } + + return true; + } + + void NetworkHierarchyRootComponent::OnChildRemoved(AZ::EntityId childRemovedId) + { + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, childRemovedId, &AZ::TransformBus::Events::GetEntityAndAllDescendants); + + for (AZ::EntityId childId : allChildren) + { + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(childId); + + const AZ::Entity* childEntity = nullptr; + + AZStd::erase_if(m_hierarchicalEntities, [childId, &childEntity](const AZ::Entity* entity) + { + if (entity->GetId() == childId) + { + childEntity = entity; + return true; + } + + return false; + }); + + if (childEntity) + { + if (NetworkHierarchyChildComponent* childComponent = childEntity->FindComponent()) + { + childComponent->SetTopLevelHierarchyRootComponent(nullptr); + } + } + } + } + + void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) + { + m_higherRootEntity = hierarchyRoot; + if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) + { + NetworkHierarchyChildComponentController* controller = static_cast(GetController()); + if (hierarchyRoot) + { + const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetId()); + controller->SetHierarchyRoot(netRootId); + } + else + { + controller->SetHierarchyRoot(InvalidNetEntityId); + } + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index fa08794c4d..a37b6b52ed 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -30,6 +30,7 @@ namespace Multiplayer , m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) , m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); }) , m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); }) + , m_parentIdChangedEventHandler([this](NetEntityId newParent) { OnParentIdChangedEvent(newParent); }) , m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); }) , m_entityCorrectionEventHandler([this]() { OnCorrection(); }) { @@ -47,8 +48,12 @@ namespace Multiplayer TranslationAddEvent(m_translationEventHandler); ScaleAddEvent(m_scaleEventHandler); ResetCountAddEvent(m_resetCountEventHandler); - GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); - GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); + ParentEntityIdAddEvent(m_parentIdChangedEventHandler); + if (GetNetBindComponent()) + { + GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); + GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); + } // When coming into relevance, reset all blending factors so we don't interpolate to our start position OnResetCountChangedEvent(); @@ -82,15 +87,33 @@ namespace Multiplayer void NetworkTransformComponent::OnResetCountChangedEvent() { + OnParentIdChangedEvent(GetParentEntityId()); + m_targetTransform.SetRotation(GetRotation()); m_targetTransform.SetTranslation(GetTranslation()); m_targetTransform.SetUniformScale(GetScale()); m_previousTransform = m_targetTransform; } + void NetworkTransformComponent::OnParentIdChangedEvent([[maybe_unused]] NetEntityId newParent) + { + const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(newParent); + if (rootHandle.Exists()) + { + const AZ::EntityId parentEntityId = rootHandle.GetEntity()->GetId(); + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + if (transformComponent->GetParentId() != parentEntityId) + { + transformComponent->SetParent(parentEntityId); + } + } + } + } + void NetworkTransformComponent::UpdateTargetHostFrameId() { - HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId(); + const HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId(); if (currentHostFrameId > m_targetHostFrameId) { m_targetHostFrameId = currentHostFrameId; @@ -137,6 +160,7 @@ namespace Multiplayer NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) , m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformChangedEvent(worldTm); }) + , m_parentIdChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId newParent) { OnParentIdChangedEvent(oldParent, newParent); }) { ; } @@ -145,6 +169,9 @@ namespace Multiplayer { GetParent().GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler); OnTransformChangedEvent(GetParent().GetTransformComponent()->GetWorldTM()); + + GetParent().GetTransformComponent()->BindParentChangedEventHandler(m_parentIdChangedHandler); + OnParentIdChangedEvent(AZ::EntityId(), GetParent().GetTransformComponent()->GetParentId()); } void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) @@ -158,4 +185,14 @@ namespace Multiplayer SetTranslation(worldTm.GetTranslation()); SetScale(worldTm.GetUniformScale()); } + + void NetworkTransformComponentController::OnParentIdChangedEvent([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) + { + AZ::Entity* parentEntity = AZ::Interface::Get()->FindEntity(newParent); + if (parentEntity) + { + const ConstNetworkEntityHandle parentHandle(parentEntity, GetNetworkEntityTracker()); + SetParentEntityId(parentHandle.GetNetEntityId()); + } + } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 1ad7be1a0a..849dc15e10 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -6,13 +6,15 @@ * */ +#include +#include +#include +#include #include #include #include #include #include -#include -#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index 482d3a1ee8..b45c05cda7 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -75,6 +75,8 @@ namespace Multiplayer void EntityReplicationManager::ActivatePendingEntities() { + AZStd::vector notReadyEntities; + const AZ::TimeMs endTimeMs = AZ::GetElapsedTimeMs() + m_entityActivationTimeSliceMs; while (!m_entitiesPendingActivation.empty()) { @@ -83,7 +85,14 @@ namespace Multiplayer EntityReplicator* entityReplicator = GetEntityReplicator(entityId); if (entityReplicator && !entityReplicator->IsMarkedForRemoval()) { - entityReplicator->ActivateNetworkEntity(); + if (entityReplicator->IsReadyToActivate()) + { + entityReplicator->ActivateNetworkEntity(); + } + else + { + notReadyEntities.push_back(entityId); + } } if (m_entityActivationTimeSliceMs > AZ::TimeMs{ 0 } && AZ::GetElapsedTimeMs() > endTimeMs) { @@ -91,6 +100,11 @@ namespace Multiplayer break; } } + + for (NetEntityId netEntityId : notReadyEntities) + { + m_entitiesPendingActivation.push_back(netEntityId); + } } void EntityReplicationManager::SendUpdates(AZ::TimeMs hostTimeMs) @@ -249,15 +263,15 @@ namespace Multiplayer void EntityReplicationManager::SendEntityUpdates(AZ::TimeMs hostTimeMs) { EntityReplicatorList toSendList = GenerateEntityUpdateList(); - + AZLOG(NET_ReplicationInfo, "Sending %zd updates from %d to %d", toSendList.size(), (uint8_t)GetNetworkEntityManager()->GetHostId(), (uint8_t)GetRemoteHostId()); - + // prep a replication record for send, at this point, everything needs to be sent for (EntityReplicator* replicator : toSendList) { replicator->GetPropertyPublisher()->PrepareSerialization(); } - + // While our to send list is not empty, build up another packet to send do { @@ -524,7 +538,7 @@ namespace Multiplayer bool EntityReplicationManager::HandlePropertyChangeMessage ( - AzNetworking::IConnection* invokingConnection, + AzNetworking::IConnection* invokingConnection, EntityReplicator* entityReplicator, AzNetworking::PacketId packetId, NetEntityId netEntityId, @@ -1137,7 +1151,7 @@ namespace Multiplayer AzNetworking::TrackChangedSerializer outputSerializer(message.m_propertyUpdateData.GetBuffer(), static_cast(message.m_propertyUpdateData.GetSize())); if (!HandlePropertyChangeMessage ( - invokingConnection, + invokingConnection, replicator, AzNetworking::InvalidPacketId, message.m_entityId, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index 14df1bb028..ad8c883f34 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -6,23 +6,25 @@ * */ -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include #include #include @@ -30,6 +32,8 @@ #include +AZ_CVAR(bool, bg_debugHierarchyActivation, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Helpful messages when debugging network hierarchy behavior"); + namespace Multiplayer { EntityReplicator::EntityReplicator @@ -48,7 +52,7 @@ namespace Multiplayer , m_onForwardRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); }) , m_onSendAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); }) , m_onForwardAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); }) - , m_onEntityStopHandler([this](const ConstNetworkEntityHandle &) { OnEntityRemovedEvent(); }) + , m_onEntityStopHandler([this](const ConstNetworkEntityHandle&) { OnEntityRemovedEvent(); }) , m_proxyRemovalEvent([this] { OnProxyRemovalTimedEvent(); }, AZ::Name("ProxyRemovalTimedEvent")) { if (auto localEnt = m_entityHandle.GetEntity()) @@ -119,12 +123,12 @@ namespace Multiplayer { m_replicationManager.AddReplicatorToPendingSend(*this); m_propertyPublisher = AZStd::make_unique - ( - GetRemoteNetworkRole(), - !RemoteManagerOwnsEntityLifetime() ? PropertyPublisher::OwnsLifetime::True : PropertyPublisher::OwnsLifetime::False, - m_netBindComponent, - *m_connection - ); + ( + GetRemoteNetworkRole(), + !RemoteManagerOwnsEntityLifetime() ? PropertyPublisher::OwnsLifetime::True : PropertyPublisher::OwnsLifetime::False, + m_netBindComponent, + *m_connection + ); m_netBindComponent->AddEntityDirtiedEventHandler(m_onEntityDirtiedHandler); } else @@ -279,7 +283,7 @@ namespace Multiplayer AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent"); bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority) - && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); + && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client; bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous; if (isAuthority || isClient || isAutonomous) @@ -306,9 +310,9 @@ namespace Multiplayer bool EntityReplicator::RemoteManagerOwnsEntityLifetime() const { bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server) - && (GetRemoteNetworkRole() == NetEntityRole::Authority); + && (GetRemoteNetworkRole() == NetEntityRole::Authority); bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client) - || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); + || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); return isServer || isClient; } @@ -405,6 +409,62 @@ namespace Multiplayer return m_replicationManager.GetResendTimeoutTimeMs(); } + bool EntityReplicator::IsReadyToActivate() const + { + const AZ::Entity* entity = m_entityHandle.GetEntity(); + AZ_Assert(entity, "Entity replicator entity unexpectedly missing"); + + const NetworkHierarchyChildComponent* hierarchyChildComponent = entity->FindComponent(); + const NetworkHierarchyRootComponent* hierarchyRootComponent = nullptr; + + if (hierarchyChildComponent == nullptr) + { + // child and root hierarchy components are mutually exclusive + hierarchyRootComponent = entity->FindComponent(); + } + + if ((hierarchyChildComponent && hierarchyChildComponent->IsHierarchicalChild()) + || (hierarchyRootComponent && hierarchyRootComponent->IsHierarchicalChild())) + { + // if hierarchy is enabled for the entity, check if the parent is available + if (const NetworkTransformComponent* networkTransform = entity->FindComponent()) + { + const NetEntityId parentId = networkTransform->GetParentEntityId(); + /* + * For root entities attached to a level, a network parent won't be set. + * In this case, this entity is the root entity of the hierarchy and it will be activated first. + */ + if (parentId != InvalidNetEntityId) + { + ConstNetworkEntityHandle parentHandle = GetNetworkEntityManager()->GetEntity(parentId); + + const AZ::Entity* parentEntity = parentHandle.GetEntity(); + if (parentEntity && parentEntity->GetState() == AZ::Entity::State::Active) + { + if (bg_debugHierarchyActivation) + { + AZLOG_DEBUG( + "Entity %s asking for activation - granted", + entity->GetName().c_str()); + } + return true; + } + + if (bg_debugHierarchyActivation) + { + AZLOG_DEBUG( + "Entity %s asking for activation - waiting on the parent %u", + entity->GetName().c_str(), + aznumeric_cast(parentId)); + } + return false; + } + } + } + + return true; + } + NetworkEntityUpdateMessage EntityReplicator::GenerateUpdatePacket() { if (IsMarkedForRemoval() && OwnsReplicatorLifetime()) // TODO: clean this up diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h index ec4bd8c4f5..e4dc62bc26 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h @@ -36,7 +36,7 @@ namespace Multiplayer { public: EntityReplicator(EntityReplicationManager& replicationManager, AzNetworking::IConnection* connection, NetEntityRole remoteNetworkRole, const ConstNetworkEntityHandle& entityHandle); - virtual ~EntityReplicator(); + ~EntityReplicator() override; NetEntityRole GetBoundLocalNetworkRole() const; NetEntityRole GetRemoteNetworkRole() const; @@ -62,6 +62,8 @@ namespace Multiplayer bool IsDeletionAcknowledged() const; bool WasMigrated() const; void SetWasMigrated(bool wasMigrated); + // If an entity is part of a network hierarchy then it is only ready to activate when its direct parent entity is active. + bool IsReadyToActivate() const; NetworkEntityUpdateMessage GenerateUpdatePacket(); diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp new file mode 100644 index 0000000000..d1b01a279c --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -0,0 +1,379 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using namespace testing; + using namespace ::UnitTest; + + /* + * Test NetBindComponent activation. This must work before more complicated tests. + */ + TEST_F(HierarchyTests, On_Client_NetBindComponent_Activate) + { + AZ::Entity entity; + entity.CreateComponent(); + SetupEntity(entity, NetEntityId{ 1 }, NetEntityRole::Client); + entity.Activate(); + + StopEntity(entity); + + entity.Deactivate(); + } + + /* + * Hierarchy test - a child entity on a client delaying activation until its hierarchical parent has been activated + */ + TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_BeforeParent) + { + // Create a child entity that will be tested for activation inside a hierarchy + AZ::Entity childEntity; + CreateEntityWithChildHierarchy(childEntity); + SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); + // child entity is not activated on purpose here, we are about to test conditional activation check + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + entityReplicator.Initialize(childHandle); + + // Entity replicator should not be ready to activate the entity because its parent does not exist + EXPECT_EQ(entityReplicator.IsReadyToActivate(), false); + } + + TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_Inner_Root_Before_Top_Root) + { + // Create a child entity that will be tested for activation inside a hierarchy + AZ::Entity innerRootEntity; + CreateEntityWithRootHierarchy(innerRootEntity); + SetupEntity(innerRootEntity, NetEntityId{ 2 }, NetEntityRole::Client); + // child entity is not activated on purpose here, we are about to test conditional activation check + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(innerRootEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(innerRootEntity, NetEntityId{ 1 }); + + // Create an entity replicator for the child entity + const NetworkEntityHandle innerRootHandle(&innerRootEntity, m_networkEntityTracker.get()); + EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, innerRootHandle); + entityReplicator.Initialize(innerRootHandle); + + // Entity replicator should not be ready to activate the entity because its parent does not exist + EXPECT_EQ(entityReplicator.IsReadyToActivate(), false); + } + + TEST_F(HierarchyTests, On_Client_Not_In_Hierarchy_EntityReplicator_Ignores_Parent) + { + // Create a child entity that will be tested for activation inside a hierarchy + AZ::Entity childEntity; + CreateEntityWithChildHierarchy(childEntity); + SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); + // child entity is not activated on purpose here, we are about to test conditional activation check + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, InvalidNetEntityId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + entityReplicator.Initialize(childHandle); + + // Entity replicator should not be ready to activate the entity because its parent does not exist + EXPECT_EQ(entityReplicator.IsReadyToActivate(), true); + } + + /* + * Hierarchy test - a child entity on a client allowing activation when its hierarchical parent is active + */ + TEST_F(HierarchyTests, On_Client_EntityReplicator_Activates_AfterParent) + { + AZ::Entity childEntity; + CreateEntityWithChildHierarchy(childEntity); + SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + EntityReplicator childEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + childEntityReplicator.Initialize(childHandle); + + // Now let's create a parent entity and activate it + AZ::Entity parentEntity; + CreateEntityWithRootHierarchy(parentEntity); + SetupEntity(parentEntity, NetEntityId{ 1 }, NetEntityRole::Client); + + // Create an entity replicator for the parent entity + const NetworkEntityHandle parentHandle(&parentEntity, m_networkEntityTracker.get()); + ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Return(parentHandle)); + EntityReplicator parentEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, parentHandle); + parentEntityReplicator.Initialize(parentHandle); + + parentEntity.Activate(); + + // The child should be ready to be activated + EXPECT_EQ(childEntityReplicator.IsReadyToActivate(), true); + + StopEntity(parentEntity); + + parentEntity.Deactivate(); + } + + /* + * Parent -> Child + */ + class ClientSimpleHierarchyTests : public HierarchyTests + { + public: + static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + + CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + // now the two entities are under one hierarchy + } + + void TearDown() override + { + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + void CreateSimpleHierarchy(EntityInfo& root, EntityInfo& child) + { + PopulateHierarchicalEntity(root); + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Client); + + PopulateHierarchicalEntity(child); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Client); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + SetHierarchyRootFieldOnNetworkHierarchyChild(child.m_entity, root.m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + child.m_replicator->Initialize(childHandle); + + // Create an entity replicator for the root entity + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + } + + void SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(const AZ::Entity& entity, NetEntityId value) + { + /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; + constexpr int inHierarchyBit = 0 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::hierarchyRoot_DirtyFlag*/; + + ReplicationRecord currentRecord(NetEntityRole::Client); + currentRecord.m_authorityToClient.AddBits(totalBits); + currentRecord.m_authorityToClient.SetBit(inHierarchyBit, true); + + constexpr uint32_t bufferSize = 100; + AZStd::array buffer = {}; + NetworkInputSerializer inSerializer(buffer.begin(), bufferSize); + inSerializer.Serialize(reinterpret_cast(value), + "hierarchyRoot", /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + AZStd::numeric_limits::min(), AZStd::numeric_limits::max()); + + NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + + ReplicationRecord notifyRecord = currentRecord; + + entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + + entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + }; + + TEST_F(ClientSimpleHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_rootEntity.get() + ); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 2) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + } + } + + TEST_F(ClientSimpleHierarchyTests, Client_Detaches_Child_When_Server_Detaches) + { + // simulate server detaching child entity + SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + nullptr + ); + } + + /* + * Parent -> Child + */ + class ClientDeepHierarchyTests : public ClientSimpleHierarchyTests + { + public: + static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + + void SetUp() override + { + ClientSimpleHierarchyTests::SetUp(); + + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchyOnClient(*m_childOfChildEntityInfo); + + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + } + + void TearDown() override + { + m_childOfChildEntityInfo.reset(); + StopAndDeleteEntity(m_childOfChildEntity); + + ClientSimpleHierarchyTests::TearDown(); + } + + void CreateDeepHierarchyOnClient(EntityInfo& childOfChild) + { + PopulateHierarchicalEntity(childOfChild); + SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Client); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childEntityInfo->m_netId); + SetHierarchyRootFieldOnNetworkHierarchyChild(childOfChild.m_entity, m_rootEntityInfo->m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childOfChildHandle); + childOfChild.m_replicator->Initialize(childOfChildHandle); + + childOfChild.m_entity.Activate(); + } + + AZStd::unique_ptr m_childOfChildEntity; + AZStd::unique_ptr m_childOfChildEntityInfo; + }; + + TEST_F(ClientDeepHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_rootEntity.get() + ); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + } + } +} diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h new file mode 100644 index 0000000000..89d0d32428 --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -0,0 +1,387 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using namespace testing; + using namespace ::UnitTest; + + class HierarchyTests + : public AllocatorsFixture + { + public: + void SetUp() override + { + SetupAllocator(); + AZ::NameDictionary::Create(); + + m_mockComponentApplicationRequests = AZStd::make_unique>(); + AZ::Interface::Register(m_mockComponentApplicationRequests.get()); + + ON_CALL(*m_mockComponentApplicationRequests, AddEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::AddEntity)); + ON_CALL(*m_mockComponentApplicationRequests, FindEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::FindEntity)); + + // register components involved in testing + m_serializeContext = AZStd::make_unique(); + + m_transformDescriptor.reset(AzFramework::TransformComponent::CreateDescriptor()); + m_transformDescriptor->Reflect(m_serializeContext.get()); + + m_netBindDescriptor.reset(NetBindComponent::CreateDescriptor()); + m_netBindDescriptor->Reflect(m_serializeContext.get()); + + m_hierarchyRootDescriptor.reset(NetworkHierarchyRootComponent::CreateDescriptor()); + m_hierarchyRootDescriptor->Reflect(m_serializeContext.get()); + + m_hierarchyChildDescriptor.reset(NetworkHierarchyChildComponent::CreateDescriptor()); + m_hierarchyChildDescriptor->Reflect(m_serializeContext.get()); + + m_netTransformDescriptor.reset(NetworkTransformComponent::CreateDescriptor()); + m_netTransformDescriptor->Reflect(m_serializeContext.get()); + + m_mockMultiplayer = AZStd::make_unique>(); + AZ::Interface::Register(m_mockMultiplayer.get()); + + EXPECT_NE(AZ::Interface::Get(), nullptr); + + // Create space for replication stats + // Without Multiplayer::RegisterMultiplayerComponents() the stats go to invalid id, which is fine for unit tests + GetMultiplayer()->GetStats().ReserveComponentStats(Multiplayer::InvalidNetComponentId, 50, 0); + + m_mockNetworkEntityManager = AZStd::make_unique>(); + + ON_CALL(*m_mockNetworkEntityManager, AddEntityToEntityMap(_, _)).WillByDefault(Invoke(this, &HierarchyTests::AddEntityToEntityMap)); + ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::GetEntity)); + ON_CALL(*m_mockNetworkEntityManager, GetNetEntityIdById(_)).WillByDefault(Invoke(this, &HierarchyTests::GetNetEntityIdById)); + + m_mockTime = AZStd::make_unique>(); + AZ::Interface::Register(m_mockTime.get()); + + m_mockNetworkTime = AZStd::make_unique>(); + AZ::Interface::Register(m_mockNetworkTime.get()); + + ON_CALL(*m_mockMultiplayer, GetNetworkEntityManager()).WillByDefault(Return(m_mockNetworkEntityManager.get())); + EXPECT_NE(AZ::Interface::Get()->GetNetworkEntityManager(), nullptr); + + const IpAddress address("localhost", 1, ProtocolType::Udp); + m_mockConnection = AZStd::make_unique>(ConnectionId{ 1 }, address, ConnectionRole::Connector); + m_mockConnectionListener = AZStd::make_unique(); + + m_networkEntityTracker = AZStd::make_unique(); + ON_CALL(*m_mockNetworkEntityManager, GetNetworkEntityTracker()).WillByDefault(Return(m_networkEntityTracker.get())); + + m_networkEntityAuthorityTracker = AZStd::make_unique(*m_mockNetworkEntityManager); + ON_CALL(*m_mockNetworkEntityManager, GetNetworkEntityAuthorityTracker()).WillByDefault(Return(m_networkEntityAuthorityTracker.get())); + + m_entityReplicationManager = AZStd::make_unique(*m_mockConnection, *m_mockConnectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer); + + m_console.reset(aznew AZ::Console()); + AZ::Interface::Register(m_console.get()); + m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead()); + + m_multiplayerComponentRegistry = AZStd::make_unique(); + ON_CALL(*m_mockNetworkEntityManager, GetMultiplayerComponentRegistry()).WillByDefault(Return(m_multiplayerComponentRegistry.get())); + RegisterMultiplayerComponents(); + } + + void TearDown() override + { + m_multiplayerComponentRegistry.reset(); + + AZ::Interface::Unregister(m_console.get()); + m_console.reset(); + + m_networkEntityMap.clear(); + m_entities.clear(); + + m_entityReplicationManager.reset(); + + m_mockConnection.reset(); + m_mockConnectionListener.reset(); + m_networkEntityTracker.reset(); + m_networkEntityAuthorityTracker.reset(); + + AZ::Interface::Unregister(m_mockNetworkTime.get()); + AZ::Interface::Unregister(m_mockTime.get()); + AZ::Interface::Unregister(m_mockMultiplayer.get()); + AZ::Interface::Unregister(m_mockComponentApplicationRequests.get()); + + m_mockTime.reset(); + + m_mockNetworkEntityManager.reset(); + m_mockMultiplayer.reset(); + + m_transformDescriptor.reset(); + m_netTransformDescriptor.reset(); + m_hierarchyRootDescriptor.reset(); + m_hierarchyChildDescriptor.reset(); + m_netBindDescriptor.reset(); + m_serializeContext.reset(); + m_mockComponentApplicationRequests.reset(); + + AZ::NameDictionary::Destroy(); + TeardownAllocator(); + } + + AZStd::unique_ptr m_console; + + AZStd::unique_ptr> m_mockComponentApplicationRequests; + AZStd::unique_ptr m_serializeContext; + AZStd::unique_ptr m_transformDescriptor; + AZStd::unique_ptr m_netBindDescriptor; + AZStd::unique_ptr m_hierarchyRootDescriptor; + AZStd::unique_ptr m_hierarchyChildDescriptor; + AZStd::unique_ptr m_netTransformDescriptor; + + AZStd::unique_ptr> m_mockMultiplayer; + AZStd::unique_ptr m_mockNetworkEntityManager; + AZStd::unique_ptr> m_mockTime; + AZStd::unique_ptr> m_mockNetworkTime; + + AZStd::unique_ptr> m_mockConnection; + AZStd::unique_ptr m_mockConnectionListener; + AZStd::unique_ptr m_networkEntityTracker; + AZStd::unique_ptr m_networkEntityAuthorityTracker; + + AZStd::unique_ptr m_entityReplicationManager; + + AZStd::unique_ptr m_multiplayerComponentRegistry;; + + mutable AZStd::map m_networkEntityMap; + + NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) + { + m_networkEntityMap[netEntityId] = entity; + return NetworkEntityHandle(entity, netEntityId, m_networkEntityTracker.get()); + } + + ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const + { + AZ::Entity* entity = m_networkEntityMap[netEntityId]; + return ConstNetworkEntityHandle(entity, m_networkEntityTracker.get()); + } + + NetEntityId GetNetEntityIdById(const AZ::EntityId& entityId) const + { + for (const auto& pair : m_networkEntityMap) + { + if (pair.second->GetId() == entityId) + { + return pair.first; + } + } + + return InvalidNetEntityId; + } + + AZStd::map m_entities; + + bool AddEntity(AZ::Entity* entity) + { + m_entities[entity->GetId()] = entity; + return true; + } + + AZ::Entity* FindEntity(AZ::EntityId entityId) + { + const auto iterator = m_entities.find(entityId); + if (iterator != m_entities.end()) + { + return iterator->second; + } + + return nullptr; + } + + void SetupEntity(AZ::Entity& entity, NetEntityId netId, NetEntityRole role) + { + const auto netBindComponent = entity.FindComponent(); + EXPECT_NE(netBindComponent, nullptr); + netBindComponent->PreInit(&entity, PrefabEntityId{ AZ::Name("test"), 1 }, netId, role); + entity.Init(); + } + + void StopEntity(const AZ::Entity& entity) + { + const auto netBindComponent = entity.FindComponent(); + EXPECT_NE(netBindComponent, nullptr); + netBindComponent->StopEntity(); + } + + void StopAndDeleteEntity(AZStd::unique_ptr& entity) + { + if (entity) + { + StopEntity(*entity); + entity->Deactivate(); + entity.reset(); + } + } + + void CreateEntityWithRootHierarchy(AZ::Entity& rootEntity) + { + rootEntity.CreateComponent(); + rootEntity.CreateComponent(); + rootEntity.CreateComponent(); + rootEntity.CreateComponent(); + } + + void CreateEntityWithChildHierarchy(AZ::Entity& childEntity) + { + childEntity.CreateComponent(); + childEntity.CreateComponent(); + childEntity.CreateComponent(); + childEntity.CreateComponent(); + } + + void SetParentIdOnNetworkTransform(const AZ::Entity& entity, NetEntityId netParentId) + { + /* Derived from NetworkTransformComponent.AutoComponent.xml */ + constexpr int totalBits = 6 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::Count*/; + constexpr int parentIdBit = 4 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::parentEntityId_DirtyFlag*/; + + ReplicationRecord currentRecord; + currentRecord.m_authorityToClient.AddBits(totalBits); + currentRecord.m_authorityToClient.SetBit(parentIdBit, true); + + constexpr uint32_t bufferSize = 100; + AZStd::array buffer = {}; + NetworkInputSerializer inSerializer(buffer.begin(), bufferSize); + inSerializer.Serialize(reinterpret_cast(netParentId), + "parentEntityId", /* Derived from NetworkTransformComponent.AutoComponent.xml */ + AZStd::numeric_limits::min(), AZStd::numeric_limits::max()); + + NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + + entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + // now the parent id is in the component + } + + template + void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZ::Entity& entity, NetEntityId value) + { + /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; + constexpr int inHierarchyBit = 0 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::hierarchyRoot_DirtyFlag*/; + + ReplicationRecord currentRecord; + currentRecord.m_authorityToClient.AddBits(totalBits); + currentRecord.m_authorityToClient.SetBit(inHierarchyBit, true); + + constexpr uint32_t bufferSize = 100; + AZStd::array buffer = {}; + NetworkInputSerializer inSerializer(buffer.begin(), bufferSize); + inSerializer.Serialize(reinterpret_cast(value), + "hierarchyRoot", /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + AZStd::numeric_limits::min(), AZStd::numeric_limits::max()); + + NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + + entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + // now the parent id is in the component + } + + struct EntityInfo + { + enum class Role + { + Root, + Child, + None + }; + + EntityInfo(AZ::Entity& entity, NetEntityId netId, Role role) + : m_entity(entity) + , m_netId(netId) + , m_role(role) + { + } + + AZ::Entity& m_entity; + NetEntityId m_netId; + AZStd::unique_ptr m_replicator; + Role m_role = Role::None; + }; + + void PopulateHierarchicalEntity(const EntityInfo& entityInfo) + { + entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity.CreateComponent(); + switch (entityInfo.m_role) + { + case EntityInfo::Role::Root: + entityInfo.m_entity.CreateComponent(); + break; + case EntityInfo::Role::Child: + entityInfo.m_entity.CreateComponent(); + break; + case EntityInfo::Role::None: + break; + } + } + + void CreateDeepHierarchy(EntityInfo& root, EntityInfo& child, EntityInfo& childOfChild) + { + PopulateHierarchicalEntity(root); + PopulateHierarchicalEntity(child); + PopulateHierarchicalEntity(childOfChild); + + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Authority); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); + SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Authority); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); + childOfChild.m_replicator->Initialize(childOfChildHandle); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); + child.m_replicator->Initialize(childHandle); + + // Create an entity replicator for the root entity + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + childOfChild.m_entity.Activate(); + } + }; +} diff --git a/Gems/Multiplayer/Code/Tests/MockInterfaces.h b/Gems/Multiplayer/Code/Tests/MockInterfaces.h new file mode 100644 index 0000000000..375fe2c5ba --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/MockInterfaces.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace UnitTest +{ + class MockMultiplayer : public Multiplayer::IMultiplayer + { + public: + MOCK_CONST_METHOD0(GetCurrentBlendFactor, float ()); + MOCK_CONST_METHOD0(GetAgentType, Multiplayer::MultiplayerAgentType()); + MOCK_METHOD1(InitializeMultiplayer, void(Multiplayer::MultiplayerAgentType)); + MOCK_METHOD2(StartHosting, bool(uint16_t, bool)); + MOCK_METHOD2(Connect, bool(AZStd::string, uint16_t)); + MOCK_METHOD1(Terminate, void(AzNetworking::DisconnectReason)); + MOCK_METHOD1(AddClientDisconnectedHandler, void(AZ::Event<>::Handler&)); + MOCK_METHOD1(AddConnectionAcquiredHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddSessionInitHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddSessionShutdownHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(SendReadyForEntityUpdates, void(bool)); + MOCK_CONST_METHOD0(GetCurrentHostTimeMs, AZ::TimeMs()); + MOCK_METHOD0(GetNetworkTime, Multiplayer::INetworkTime* ()); + MOCK_METHOD0(GetNetworkEntityManager, Multiplayer::INetworkEntityManager* ()); + MOCK_METHOD1(SetFilterEntityManager, void(Multiplayer::IFilterEntityManager*)); + MOCK_METHOD0(GetFilterEntityManager, Multiplayer::IFilterEntityManager* ()); + }; + + class MockNetworkEntityManager : public Multiplayer::INetworkEntityManager + { + public: + MOCK_METHOD4(CreateEntitiesImmediate, EntityList (const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityRole, const AZ::Transform&, Multiplayer::AutoActivate)); + MOCK_CONST_METHOD1(GetNetEntityIdById, Multiplayer::NetEntityId (const AZ::EntityId&)); + MOCK_METHOD0(GetNetworkEntityTracker, Multiplayer::NetworkEntityTracker* ()); + MOCK_METHOD0(GetNetworkEntityAuthorityTracker, Multiplayer::NetworkEntityAuthorityTracker* ()); + MOCK_METHOD0(GetMultiplayerComponentRegistry, Multiplayer::MultiplayerComponentRegistry* ()); + MOCK_CONST_METHOD0(GetHostId, Multiplayer::HostId()); + MOCK_METHOD3(CreateEntitiesImmediate, EntityList(const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityRole, const AZ:: + Transform&)); + MOCK_METHOD5(CreateEntitiesImmediate, EntityList(const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityId, Multiplayer:: + NetEntityRole, Multiplayer::AutoActivate, const AZ::Transform&)); + MOCK_METHOD3(SetupNetEntity, void(AZ::Entity*, Multiplayer::PrefabEntityId, Multiplayer::NetEntityRole)); + MOCK_CONST_METHOD1(GetEntity, Multiplayer::ConstNetworkEntityHandle(Multiplayer::NetEntityId)); + MOCK_CONST_METHOD0(GetEntityCount, uint32_t()); + MOCK_METHOD2(AddEntityToEntityMap, Multiplayer::NetworkEntityHandle(Multiplayer::NetEntityId, AZ::Entity*)); + MOCK_METHOD1(MarkForRemoval, void(const Multiplayer::ConstNetworkEntityHandle&)); + MOCK_CONST_METHOD1(IsMarkedForRemoval, bool(const Multiplayer::ConstNetworkEntityHandle&)); + MOCK_METHOD1(ClearEntityFromRemovalList, void(const Multiplayer::ConstNetworkEntityHandle&)); + MOCK_METHOD0(ClearAllEntities, void()); + MOCK_METHOD1(AddEntityMarkedDirtyHandler, void(AZ::Event<>::Handler&)); + MOCK_METHOD1(AddEntityNotifyChangesHandler, void(AZ::Event<>::Handler&)); + MOCK_METHOD1(AddEntityExitDomainHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddControllersActivatedHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddControllersDeactivatedHandler, void(AZ::Event::Handler&)); + MOCK_METHOD0(NotifyEntitiesDirtied, void()); + MOCK_METHOD0(NotifyEntitiesChanged, void()); + MOCK_METHOD2(NotifyControllersActivated, void(const Multiplayer::ConstNetworkEntityHandle&, Multiplayer::EntityIsMigrating)); + MOCK_METHOD2(NotifyControllersDeactivated, void(const Multiplayer::ConstNetworkEntityHandle&, Multiplayer::EntityIsMigrating)); + MOCK_METHOD1(HandleLocalRpcMessage, void(Multiplayer::NetworkEntityRpcMessage&)); + }; + + class MockConnectionListener : public AzNetworking::IConnectionListener + { + public: + MOCK_METHOD3(ValidateConnect, ConnectResult(const IpAddress&, const IPacketHeader&, ISerializer&)); + MOCK_METHOD1(OnConnect, void(IConnection*)); + MOCK_METHOD3(OnPacketReceived, PacketDispatchResult (IConnection*, const IPacketHeader&, ISerializer&)); + MOCK_METHOD2(OnPacketLost, void(IConnection*, PacketId)); + MOCK_METHOD3(OnDisconnect, void(IConnection*, DisconnectReason, TerminationEndpoint)); + }; + + class MockTime : public AZ::ITime + { + public: + MOCK_CONST_METHOD0(GetElapsedTimeMs, AZ::TimeMs()); + }; + + class MockNetworkTime : public Multiplayer::INetworkTime + { + public: + MOCK_METHOD2(ForceSetTime, void (Multiplayer::HostFrameId, AZ::TimeMs)); + MOCK_CONST_METHOD0(GetHostBlendFactor, float ()); + MOCK_METHOD1(AlterBlendFactor, void (float)); + MOCK_CONST_METHOD0(IsTimeRewound, bool()); + MOCK_CONST_METHOD0(GetHostFrameId, Multiplayer::HostFrameId()); + MOCK_CONST_METHOD0(GetUnalteredHostFrameId, Multiplayer::HostFrameId()); + MOCK_METHOD0(IncrementHostFrameId, void()); + MOCK_CONST_METHOD0(GetHostTimeMs, AZ::TimeMs()); + MOCK_CONST_METHOD0(GetRewindingConnectionId, AzNetworking::ConnectionId()); + MOCK_CONST_METHOD1(GetHostFrameIdForRewindingConnection, Multiplayer::HostFrameId(AzNetworking::ConnectionId)); + MOCK_METHOD3(AlterTime, void(Multiplayer::HostFrameId, AZ::TimeMs, AzNetworking::ConnectionId)); + MOCK_METHOD1(SyncEntitiesToRewindState, void(const AZ::Aabb&)); + MOCK_METHOD0(ClearRewoundEntities, void()); + }; + + class MockComponentApplicationRequests : public AZ::ComponentApplicationRequests + { + public: + MOCK_METHOD1(RegisterComponentDescriptor, void(const AZ::ComponentDescriptor*)); + MOCK_METHOD1(UnregisterComponentDescriptor, void(const AZ::ComponentDescriptor*)); + MOCK_METHOD0(GetApplication, AZ::ComponentApplication* ()); + MOCK_METHOD1(RegisterEntityAddedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(RegisterEntityRemovedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(RegisterEntityActivatedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(RegisterEntityDeactivatedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(SignalEntityActivated, void(AZ::Entity*)); + MOCK_METHOD1(SignalEntityDeactivated, void(AZ::Entity*)); + MOCK_METHOD1(AddEntity, bool(AZ::Entity*)); + MOCK_METHOD1(RemoveEntity, bool(AZ::Entity*)); + MOCK_METHOD1(DeleteEntity, bool(const AZ::EntityId&)); + MOCK_METHOD1(FindEntity, AZ::Entity* (const AZ::EntityId&)); + MOCK_METHOD1(GetEntityName, AZStd::string(const AZ::EntityId&)); + MOCK_METHOD1(EnumerateEntities, void(const EntityCallback&)); + MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ()); + MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ()); + MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ()); + MOCK_CONST_METHOD0(GetAppRoot, const char* ()); + MOCK_CONST_METHOD0(GetEngineRoot, const char* ()); + MOCK_CONST_METHOD0(GetExecutableFolder, const char* ()); + MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ()); + MOCK_METHOD1(ResolveModulePath, void(AZ::OSString&)); + MOCK_METHOD0(GetAzCommandLine, AZ::CommandLine* ()); + MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&)); + }; + + class MockSerializer : public ISerializer + { + public: + MOCK_CONST_METHOD0(IsValid, bool ()); + MOCK_CONST_METHOD0(GetSerializerMode, SerializerMode ()); + MOCK_METHOD2(Serialize, bool (bool&, const char*)); + MOCK_METHOD4(Serialize, bool (char&, const char*, char, char)); + MOCK_METHOD4(Serialize, bool (int8_t&, const char*, int8_t, int8_t)); + MOCK_METHOD4(Serialize, bool (int16_t&, const char*, int16_t, int16_t)); + MOCK_METHOD4(Serialize, bool (int32_t&, const char*, int32_t, int32_t)); + MOCK_METHOD4(Serialize, bool (int64_t&, const char*, int64_t, int64_t)); + MOCK_METHOD4(Serialize, bool (uint8_t&, const char*, uint8_t, uint8_t)); + MOCK_METHOD4(Serialize, bool (uint16_t&, const char*, uint16_t, uint16_t)); + MOCK_METHOD4(Serialize, bool (uint32_t&, const char*, uint32_t, uint32_t)); + MOCK_METHOD4(Serialize, bool (uint64_t&, const char*, uint64_t, uint64_t)); + MOCK_METHOD4(Serialize, bool (float&, const char*, float, float)); + MOCK_METHOD4(Serialize, bool (double&, const char*, double, double)); + MOCK_METHOD5(SerializeBytes, bool (uint8_t*, uint32_t, bool, uint32_t&, const char*)); + MOCK_METHOD2(BeginObject, bool (const char*, const char*)); + MOCK_METHOD2(EndObject, bool (const char*, const char*)); + MOCK_CONST_METHOD0(GetBuffer, const uint8_t* ()); + MOCK_CONST_METHOD0(GetCapacity, uint32_t ()); + MOCK_CONST_METHOD0(GetSize, uint32_t ()); + MOCK_METHOD0(ClearTrackedChangesFlag, void ()); + MOCK_CONST_METHOD0(GetTrackedChangesFlag, bool ()); + }; +} + diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp new file mode 100644 index 0000000000..ae2d8b162d --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -0,0 +1,1145 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using namespace testing; + using namespace ::UnitTest; + + /* + * Parent -> Child + */ + class ServerSimpleHierarchyTests : public HierarchyTests + { + public: + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); + + CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + // now the two entities are under one hierarchy + } + + void TearDown() override + { + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + void CreateSimpleHierarchy(EntityInfo& root, EntityInfo& child) + { + PopulateHierarchicalEntity(root); + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Authority); + + PopulateHierarchicalEntity(child); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); + + //// we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + //SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); + child.m_replicator->Initialize(childHandle); + + // Create an entity replicator for the root entity + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + }; + + TEST_F(ServerSimpleHierarchyTests, Server_Sets_Appropriate_Network_Fields_For_Clients) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + NetEntityId{ 1 } + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Is_Top_Level_Root) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->IsHierarchicalChild(), + false + ); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Set) + { + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + NetEntityId{ 1 } + ); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Cleared_On_Detach) + { + // now detach the child + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_Reference) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_References_Removed_On_Detach) + { + // now detach the child + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Deactivates_Child_Has_No_References_To_Root) + { + StopEntity(*m_rootEntity); + m_rootEntity->Deactivate(); + m_rootEntity.reset(); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Deactivates_Root_Has_No_References_To_Child) + { + StopEntity(*m_childEntity); + m_childEntity->Deactivate(); + m_childEntity.reset(); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + /* + * Parent -> Child -> ChildOfChild + */ + class ServerDeepHierarchyTests : public HierarchyTests + { + public: + static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo.reset(); + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childOfChildEntity); + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + AZStd::unique_ptr m_childOfChildEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_childOfChildEntityInfo; + }; + + TEST_F(ServerDeepHierarchyTests, Root_Is_Top_Level_Root) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->IsHierarchicalChild(), + false + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_Child_References) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + } + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_Child_Of_Child_Reference_Removed_On_Detach) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_Removed_On_Detach_Of_Mid_Child) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Mid_Child_Added_With_Child) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Child_Of_Child_Added) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Points_To_Root_After_Attach) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, All_New_Children_Point_To_Root_If_Mid_Child_Added_With_Child) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Children_Clear_Reference_To_Root_After_Mid_Child_Detached) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Clears_Reference_To_Root_After_Detached) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Deactivates_Children_Have_No_References_To_Root) + { + StopAndDeleteEntity(m_rootEntity); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Deactivates_Root_Removes_References_To_It) + { + StopAndDeleteEntity(m_childOfChildEntity); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerDeepHierarchyTests, Testing_Limiting_Hierarchy_Maximum_Size) + { + uint32_t currentMaxLimit = 0; + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); + + // remake the hierarchy + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + + m_console->PerformCommand((AZStd::string("bg_hierarchyEntityMaxLimit ") + AZStd::to_string(currentMaxLimit)).c_str()); + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + } + + /* + * Parent -> Child -> Child Of Child + * -> Child2 -> Child Of Child2 + * -> Child2 Of Child2 + */ + class ServerBranchedHierarchyTests : public HierarchyTests + { + public: + static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + static const NetEntityId Child2NetEntityId = NetEntityId{ 4 }; + static const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 5 }; + static const NetEntityId Child2OfChild2NetEntityId = NetEntityId{ 6 }; + + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + m_child2Entity = AZStd::make_unique(AZ::EntityId(4), "child2"); + m_childOfChild2Entity = AZStd::make_unique(AZ::EntityId(5), "child of child2"); + m_child2OfChild2Entity = AZStd::make_unique(AZ::EntityId(6), "child2 of child2"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_child2EntityInfo = AZStd::make_unique(*m_child2Entity.get(), Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChild2EntityInfo = AZStd::make_unique(*m_childOfChild2Entity.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); + m_child2OfChild2EntityInfo = AZStd::make_unique(*m_child2OfChild2Entity.get(), Child2OfChild2NetEntityId, EntityInfo::Role::Child); + + CreateBranchedHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo, + *m_child2EntityInfo, *m_childOfChild2EntityInfo, *m_child2OfChild2EntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_child2OfChild2EntityInfo.reset(); + m_childOfChild2EntityInfo.reset(); + m_child2EntityInfo.reset(); + m_childOfChildEntityInfo.reset(); + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_child2OfChild2Entity); + StopAndDeleteEntity(m_childOfChild2Entity); + StopAndDeleteEntity(m_child2Entity); + StopAndDeleteEntity(m_childOfChildEntity); + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + + void CreateBranchedHierarchy(EntityInfo& root, EntityInfo& child, EntityInfo& childOfChild, + EntityInfo& child2, EntityInfo& childOfChild2, EntityInfo& child2OfChild2) + { + PopulateHierarchicalEntity(root); + PopulateHierarchicalEntity(child); + PopulateHierarchicalEntity(childOfChild); + PopulateHierarchicalEntity(child2); + PopulateHierarchicalEntity(childOfChild2); + PopulateHierarchicalEntity(child2OfChild2); + + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Authority); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); + SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Authority); + SetupEntity(child2.m_entity, child2.m_netId, NetEntityRole::Authority); + SetupEntity(childOfChild2.m_entity, childOfChild2.m_netId, NetEntityRole::Authority); + SetupEntity(child2OfChild2.m_entity, child2OfChild2.m_netId, NetEntityRole::Authority); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); + SetParentIdOnNetworkTransform(child2.m_entity, root.m_netId); + SetParentIdOnNetworkTransform(childOfChild2.m_entity, child2.m_netId); + SetParentIdOnNetworkTransform(child2OfChild2.m_entity, child2.m_netId); + + // Create entity replicators + const NetworkEntityHandle childOfChild2Handle(&childOfChild2.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChild2Handle); + childOfChild.m_replicator->Initialize(childOfChild2Handle); + + const NetworkEntityHandle child2OfChild2Handle(&child2OfChild2.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2OfChild2Handle); + childOfChild.m_replicator->Initialize(child2OfChild2Handle); + + const NetworkEntityHandle child2Handle(&child2.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2Handle); + child.m_replicator->Initialize(child2Handle); + + const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); + childOfChild.m_replicator->Initialize(childOfChildHandle); + + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); + child.m_replicator->Initialize(childHandle); + + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + childOfChild.m_entity.Activate(); + child2.m_entity.Activate(); + childOfChild2.m_entity.Activate(); + child2OfChild2.m_entity.Activate(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + AZStd::unique_ptr m_childOfChildEntity; + AZStd::unique_ptr m_child2Entity; + AZStd::unique_ptr m_childOfChild2Entity; + AZStd::unique_ptr m_child2OfChild2Entity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_child2EntityInfo; + AZStd::unique_ptr m_childOfChild2EntityInfo; + AZStd::unique_ptr m_child2OfChild2EntityInfo; + }; + + TEST_F(ServerBranchedHierarchyTests, Sanity_Check) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 6) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], + m_child2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[4], + m_child2OfChild2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[5], + m_childOfChild2Entity.get() + ); + } + } + + TEST_F(ServerBranchedHierarchyTests, Detach_Child_While_Child2_Remains_Attached) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 4 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 4) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_child2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_child2OfChild2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], + m_childOfChild2Entity.get() + ); + } + + EXPECT_EQ( + m_child2Entity->FindComponent()->GetHierarchicalRoot(), + m_rootEntity.get() + ); + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + nullptr + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchicalRoot(), + nullptr + ); + } + + TEST_F(ServerBranchedHierarchyTests, Detach_Child_Then_Attach_To_Child2) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childEntity->FindComponent()->SetParent(m_child2Entity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + /* + * Sets up 2 deep hierarchies. + */ + class ServerHierarchyOfHierarchyTests : public ServerDeepHierarchyTests + { + public: + static const NetEntityId Root2NetEntityId = NetEntityId{ 4 }; + static const NetEntityId Child2NetEntityId = NetEntityId{ 5 }; + static const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 6 }; + + void SetUp() override + { + ServerDeepHierarchyTests::SetUp(); + + m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); + m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); + m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + + m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), Root2NetEntityId, EntityInfo::Role::Root); + m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); + + m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo2.reset(); + m_childEntityInfo2.reset(); + m_rootEntityInfo2.reset(); + + StopAndDeleteEntity(m_childOfChildEntity2); + StopAndDeleteEntity(m_childEntity2); + StopAndDeleteEntity(m_rootEntity2); + + ServerDeepHierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity2; + AZStd::unique_ptr m_childEntity2; + AZStd::unique_ptr m_childOfChildEntity2; + + AZStd::unique_ptr m_rootEntityInfo2; + AZStd::unique_ptr m_childEntityInfo2; + AZStd::unique_ptr m_childOfChildEntityInfo2; + }; + + TEST_F(ServerHierarchyOfHierarchyTests, Hierarchies_Are_Not_Related) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + } + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + + if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity2.get() + ); + } + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Is_Not_Top_Level_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->IsHierarchicalChild(), + false + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child_Of_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child_Of_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Doesnt_Keep_Child_References) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 0 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Top_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity2.get() + ); + } + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Stress_Test_Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) + { + for (int i = 0; i < 100; ++i) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + } + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_Of_Child_In_Inner_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 5 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Attachment_Of_Child_Of_Child_In_Inner_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + // re-connect + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Of_Child_Changed_Hierarchies) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + + // connect to a different hierarchy + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_In_Inner_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 4 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Changed_Hierarchies) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + + // connect to a different hierarchy + m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_No_Child_References_After_All_Children_Moved_To_Another_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Child_Deactivated_Top_Root_Has_No_Child_Reference_To_It) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + StopAndDeleteEntity(m_childEntity2); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 4 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Testing_Limiting_Hierarchy_Maximum_Size) + { + uint32_t currentMaxLimit = 0; + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); + + // remake the top level hierarchy + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + + m_console->PerformCommand((AZStd::string("bg_hierarchyEntityMaxLimit ") + AZStd::to_string(currentMaxLimit)).c_str()); + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + } + + /* + * Parent -> Child -> ChildOfChild (not marked as in a hierarchy) + */ + class ServerMixedDeepHierarchyTests : public HierarchyTests + { + public: + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), NetEntityId{ 3 }, EntityInfo::Role::None); + + CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo.reset(); + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childOfChildEntity); + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + AZStd::unique_ptr m_childOfChildEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_childOfChildEntityInfo; + }; + + TEST_F(ServerMixedDeepHierarchyTests, Top_Root_Ignores_Non_Hierarchical_Entities) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerMixedDeepHierarchyTests, Detaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerMixedDeepHierarchyTests, Attaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChildEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + /* + * 1st hierarchy: Parent -> Child -> ChildOfChild (not marked as in a hierarchy) + * 2nd hierarchy: Parent2 -> Child2 (not marked as in a hierarchy) -> ChildOfChild2 + */ + class ServerMixedHierarchyOfHierarchyTests : public ServerMixedDeepHierarchyTests + { + public: + void SetUp() override + { + ServerMixedDeepHierarchyTests::SetUp(); + + m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); + m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); + m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + + m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), NetEntityId{ 4 }, EntityInfo::Role::Root); + m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), NetEntityId{ 5 }, EntityInfo::Role::None); + m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), NetEntityId{ 6 }, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); + + m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo2.reset(); + m_childEntityInfo2.reset(); + m_rootEntityInfo2.reset(); + + + StopAndDeleteEntity(m_childOfChildEntity2); + StopAndDeleteEntity(m_childEntity2); + StopAndDeleteEntity(m_rootEntity2); + + ServerMixedDeepHierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity2; + AZStd::unique_ptr m_childEntity2; + AZStd::unique_ptr m_childOfChildEntity2; + + AZStd::unique_ptr m_rootEntityInfo2; + AZStd::unique_ptr m_childEntityInfo2; + AZStd::unique_ptr m_childOfChildEntityInfo2; + }; + + TEST_F(ServerMixedHierarchyOfHierarchyTests, Sanity_Check_Ingore_Children_Without_Hierarchy_Components) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerMixedHierarchyOfHierarchyTests, Adding_Mixed_Hierarchy_Ingores_Children_Without_Hierarchy_Components) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerMixedHierarchyOfHierarchyTests, Attaching_Hierarchy_To_Non_Hierarchical_Entity_Does_Not_Merge_Hierarchies) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + false + ); + } +} diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 0b2adb1530..6475155f40 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -15,20 +15,28 @@ set(FILES Include/Multiplayer/MultiplayerTypes.h Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h Include/Multiplayer/Components/MultiplayerComponent.h - Include/Multiplayer/Components/MultiplayerController.h Include/Multiplayer/Components/MultiplayerComponentRegistry.h + Include/Multiplayer/Components/MultiplayerController.h Include/Multiplayer/Components/NetBindComponent.h + Include/Multiplayer/Components/NetworkHierarchyChildComponent.h + Include/Multiplayer/Components/NetworkHierarchyRootComponent.h + Include/Multiplayer/Components/NetworkHierarchyBus.h Include/Multiplayer/Components/NetworkTransformComponent.h Include/Multiplayer/ConnectionData/IConnectionData.h Include/Multiplayer/EntityDomains/IEntityDomain.h - Include/Multiplayer/NetworkEntity/INetworkEntityManager.h + Include/Multiplayer/IMultiplayer.h + Include/Multiplayer/IMultiplayerTools.h Include/Multiplayer/INetworkSpawnableLibrary.h + Include/Multiplayer/MultiplayerConstants.h + Include/Multiplayer/MultiplayerStats.h + Include/Multiplayer/MultiplayerTypes.h + Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h Include/Multiplayer/NetworkEntity/IFilterEntityManager.h - Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h - Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h + Include/Multiplayer/NetworkEntity/INetworkEntityManager.h Include/Multiplayer/NetworkEntity/NetworkEntityHandle.h Include/Multiplayer/NetworkEntity/NetworkEntityHandle.inl - Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h + Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h + Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h Include/Multiplayer/NetworkInput/NetworkInput.h Include/Multiplayer/NetworkTime/INetworkTime.h @@ -40,23 +48,24 @@ set(FILES Include/Multiplayer/NetworkTime/RewindableObject.inl Include/Multiplayer/Physics/PhysicsUtils.h Include/Multiplayer/ReplicationWindows/IReplicationWindow.h - Source/MultiplayerSystemComponent.cpp - Source/MultiplayerSystemComponent.h - Source/MultiplayerStats.cpp - Source/AutoGen/AutoComponent_Header.jinja - Source/AutoGen/AutoComponent_Source.jinja - Source/AutoGen/AutoComponent_Common.jinja Source/AutoGen/AutoComponentTypes_Header.jinja Source/AutoGen/AutoComponentTypes_Source.jinja + Source/AutoGen/AutoComponent_Common.jinja + Source/AutoGen/AutoComponent_Header.jinja + Source/AutoGen/AutoComponent_Source.jinja Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml Source/AutoGen/Multiplayer.AutoPackets.xml Source/AutoGen/MultiplayerEditor.AutoPackets.xml Source/AutoGen/NetworkTransformComponent.AutoComponent.xml + Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml + Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml Source/Components/LocalPredictionPlayerInputComponent.cpp Source/Components/MultiplayerComponent.cpp - Source/Components/MultiplayerController.cpp Source/Components/MultiplayerComponentRegistry.cpp + Source/Components/MultiplayerController.cpp Source/Components/NetBindComponent.cpp + Source/Components/NetworkHierarchyChildComponent.cpp + Source/Components/NetworkHierarchyRootComponent.cpp Source/Components/NetworkTransformComponent.cpp Source/ConnectionData/ClientToServerConnectionData.cpp Source/ConnectionData/ClientToServerConnectionData.h @@ -68,6 +77,9 @@ set(FILES Source/Editor/MultiplayerEditorConnection.h Source/EntityDomains/FullOwnershipEntityDomain.cpp Source/EntityDomains/FullOwnershipEntityDomain.h + Source/MultiplayerStats.cpp + Source/MultiplayerSystemComponent.cpp + Source/MultiplayerSystemComponent.h Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp Source/NetworkEntity/EntityReplication/EntityReplicationManager.h Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -83,13 +95,13 @@ set(FILES Source/NetworkEntity/NetworkEntityHandle.cpp Source/NetworkEntity/NetworkEntityManager.cpp Source/NetworkEntity/NetworkEntityManager.h - Source/NetworkEntity/NetworkSpawnableLibrary.cpp - Source/NetworkEntity/NetworkSpawnableLibrary.h Source/NetworkEntity/NetworkEntityRpcMessage.cpp Source/NetworkEntity/NetworkEntityTracker.cpp Source/NetworkEntity/NetworkEntityTracker.h Source/NetworkEntity/NetworkEntityTracker.inl Source/NetworkEntity/NetworkEntityUpdateMessage.cpp + Source/NetworkEntity/NetworkSpawnableLibrary.cpp + Source/NetworkEntity/NetworkSpawnableLibrary.h Source/NetworkInput/NetworkInput.cpp Source/NetworkInput/NetworkInputArray.cpp Source/NetworkInput/NetworkInputArray.h @@ -101,11 +113,11 @@ set(FILES Source/NetworkInput/NetworkInputMigrationVector.h Source/NetworkTime/NetworkTime.cpp Source/NetworkTime/NetworkTime.h + Source/Physics/PhysicsUtils.cpp Source/Pipeline/NetBindMarkerComponent.cpp Source/Pipeline/NetBindMarkerComponent.h Source/Pipeline/NetworkSpawnableHolderComponent.cpp Source/Pipeline/NetworkSpawnableHolderComponent.h - Source/Physics/PhysicsUtils.cpp Source/ReplicationWindows/NullReplicationWindow.cpp Source/ReplicationWindows/NullReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp diff --git a/Gems/Multiplayer/Code/multiplayer_tests_files.cmake b/Gems/Multiplayer/Code/multiplayer_tests_files.cmake index f385a21600..3f4fcc9efa 100644 --- a/Gems/Multiplayer/Code/multiplayer_tests_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_tests_files.cmake @@ -8,6 +8,10 @@ set(FILES Tests/Main.cpp + Tests/MockInterfaces.h + Tests/ClientHierarchyTests.cpp + Tests/ServerHierarchyTests.cpp + Tests/CommonHierarchySetup.h Tests/IMultiplayerConnectionMock.h Tests/MultiplayerSystemTests.cpp Tests/RewindableContainerTests.cpp From 880e3c99beac237775f84574f080b046c5838e25 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 13 Sep 2021 14:07:28 -0700 Subject: [PATCH 092/274] PR comments Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/TrackView/TrackViewNode.h | 8 ++++---- Code/Editor/TrackView/TrackViewSplineCtrl.h | 2 +- .../Tests/IO/Streamer/StorageDriveTests_Windows.cpp | 2 ++ Code/Legacy/CrySystem/Timer.h | 2 +- Code/Legacy/CrySystem/ViewSystem/View.h | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Code/Editor/TrackView/TrackViewNode.h b/Code/Editor/TrackView/TrackViewNode.h index a3918d61a4..80ca7b9d49 100644 --- a/Code/Editor/TrackView/TrackViewNode.h +++ b/Code/Editor/TrackView/TrackViewNode.h @@ -119,12 +119,12 @@ public: : m_bAllOfSameType(true) {} virtual ~CTrackViewKeyBundle() = default; - virtual bool AreAllKeysOfSameType() const override { return m_bAllOfSameType; } + bool AreAllKeysOfSameType() const override { return m_bAllOfSameType; } - virtual unsigned int GetKeyCount() const override { return static_cast(m_keys.size()); } - virtual CTrackViewKeyHandle GetKey(unsigned int index) override { return m_keys[index]; } + unsigned int GetKeyCount() const override { return static_cast(m_keys.size()); } + CTrackViewKeyHandle GetKey(unsigned int index) override { return m_keys[index]; } - virtual void SelectKeys(const bool bSelected) override; + void SelectKeys(const bool bSelected) override; CTrackViewKeyHandle GetSingleSelectedKey(); diff --git a/Code/Editor/TrackView/TrackViewSplineCtrl.h b/Code/Editor/TrackView/TrackViewSplineCtrl.h index 7c5a13cdb6..7cf12fb750 100644 --- a/Code/Editor/TrackView/TrackViewSplineCtrl.h +++ b/Code/Editor/TrackView/TrackViewSplineCtrl.h @@ -67,7 +67,7 @@ private: void AdjustTCB(float d_tension, float d_continuity, float d_bias); void MoveSelectedTangentHandleTo(const QPoint& point); - virtual ISplineCtrlUndo* CreateSplineCtrlUndoObject(std::vector& splineContainer) override; + ISplineCtrlUndo* CreateSplineCtrlUndoObject(std::vector& splineContainer) override; bool m_bKeysFreeze; bool m_bTangentsFreeze; diff --git a/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp b/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp index 51fa68cc2b..22fb6379d2 100644 --- a/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp +++ b/Code/Framework/AzCore/Tests/Platform/Windows/Tests/IO/Streamer/StorageDriveTests_Windows.cpp @@ -1163,12 +1163,14 @@ namespace Benchmark m_absolutePath.swap(temp); delete m_streamer; + m_streamer = nullptr; SystemFile::Delete(TestFileName); AZ::IO::FileIOBase::SetInstance(nullptr); AZ::IO::FileIOBase::SetInstance(m_previousFileIO); delete m_fileIO; + m_fileIO = nullptr; } public: constexpr static const char* TestFileName = "StreamerBenchmark.bin"; diff --git a/Code/Legacy/CrySystem/Timer.h b/Code/Legacy/CrySystem/Timer.h index c988c1fa38..69fd2357e0 100644 --- a/Code/Legacy/CrySystem/Timer.h +++ b/Code/Legacy/CrySystem/Timer.h @@ -21,7 +21,7 @@ public: // constructor CTimer(); // destructor - ~CTimer() = default;; + ~CTimer() = default; bool Init(); diff --git a/Code/Legacy/CrySystem/ViewSystem/View.h b/Code/Legacy/CrySystem/ViewSystem/View.h index d1fc905eef..001bf694fd 100644 --- a/Code/Legacy/CrySystem/ViewSystem/View.h +++ b/Code/Legacy/CrySystem/ViewSystem/View.h @@ -26,7 +26,7 @@ class CView public: CView(ISystem* pSystem); - virtual ~CView(); + ~CView() override; //shaking struct SShake From 2b7caa685b8989f6772bca93ad3d6e5eb99aa5cd Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Mon, 13 Sep 2021 14:23:00 -0700 Subject: [PATCH 093/274] Introduce default font size. This fixes sizing and spacing for text rendered via a painter with not font specified. (#4069) Also removed some qss for windows that have been removed. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- Code/Editor/Style/Editor.qss | 90 ------------------- .../Components/StyleManager.cpp | 4 + 2 files changed, 4 insertions(+), 90 deletions(-) diff --git a/Code/Editor/Style/Editor.qss b/Code/Editor/Style/Editor.qss index 302b7703a5..5eb280260e 100644 --- a/Code/Editor/Style/Editor.qss +++ b/Code/Editor/Style/Editor.qss @@ -191,94 +191,4 @@ ConsoleTextEdit:focus, border-width: 0px; border-color: #e9e9e9; border-style: solid; -} - -/* Welcome Screen styling */ - -WelcomeScreenDialog QLabel -{ - font-size: 12px; - color: #FFFFFF; - line-height: 20px; - background-color: transparent; - margin: 0; -} - -WelcomeScreenDialog QLabel#currentProjectLabel -{ - margin-top: 10px; -} - -WelcomeScreenDialog QPushButton -{ - font-size: 14px; - line-height: 16px; -} - -WelcomeScreenDialog QWidget#articleViewContainerRoot -{ - background: #444444; -} - -WelcomeScreenDialog QWidget#levelViewFTUEContainer -{ - background: #282828; -} - -QTableWidget#recentLevelTable::item { - background-color: rgb(64,64,64); - margin-bottom: 4px; - margin-top: 4px; -} - -/* Particle Editor */ - -#NumParticlesLabel -{ - margin-top: 6px; -} - -#LibrarySearchIcon -{ - max-width: 16px; - max-height: 16px; - qproperty-iconSize: 16px 16px; -} - - -#ClosePrefabDialog, #SavePrefabDialog -{ - min-width : 640px; -} - -#SaveDependentPrefabsCard -{ - margin: 0px 15px 10px 15px; -} - -#PrefabSavedMessageFrame{ - border: 1px solid green; - margin: 10px 15px 10px 15px; - border-radius: 2px; - padding: 5px 2px 5px 2px; -} - -#ClosePrefabDialog #PrefabSaveWarningFrame -{ - border: 1px solid orange; - margin: 10px 15px 10px 15px; - border-radius: 2px; - padding: 5px 2px 5px 2px; - color : white; -} - -#SavePrefabDialog #FooterSeparatorLine -{ - color: gray; -} - -#SavePrefabDialog #PrefabSavePreferenceHint -{ - font: italic; - color: #999999; } \ No newline at end of file diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.cpp index c7ec4d4c7a..8f659afb7e 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/StyleManager.cpp @@ -169,6 +169,10 @@ namespace AzQtComponents initializeSearchPaths(application, engineRootPath); initializeFonts(); + QFont defaultFont("Open Sans"); + defaultFont.setPixelSize(12); + QApplication::setFont(defaultFont); + m_titleBarOverdrawHandler = TitleBarOverdrawHandler::createHandler(application, this); // The window decoration wrappers require the titlebar overdraw handler From 850d401bb3de889a9bd2e4337abef4d7156f6175 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Mon, 13 Sep 2021 14:55:55 -0700 Subject: [PATCH 094/274] PerScreenDpi | Moving windows between screens with different scale changes the window size (#4064) * Fix window size when dropped on a screen with a different scale setting compared to the one it was dragged from. Note that this fixes a bug that could only be reproduced with the PerScreenDpiAware setting activated - current editor uses SystemDpiAware. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix loss of precision warning. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzQtComponents/Components/FancyDocking.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp index d73ebbec28..f60a98f392 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp @@ -2461,6 +2461,18 @@ namespace AzQtComponents placeholderRect.translate(0, -margins.bottom()); } + // Also adjust the placeholderRect by the relative dpi change from the original screen, since setGeometry uses the screen's + // virtualGeometry! + QScreen* fromScreen = dock->screen(); + QScreen* toScreen = Utilities::ScreenAtPoint(placeholderRect.topLeft()); + + if (fromScreen != toScreen) + { + qreal factorRatio = QHighDpiScaling::factor(fromScreen) / QHighDpiScaling::factor(toScreen); + placeholderRect.setWidth(aznumeric_cast(aznumeric_cast(placeholderRect.width()) * factorRatio)); + placeholderRect.setHeight(aznumeric_cast(aznumeric_cast(placeholderRect.height()) * factorRatio)); + } + // Place the floating dock widget makeDockWidgetFloating(dock, placeholderRect); clearDraggingState(); From 28ca59ae6112c99f5f142d8d5a2e284ec3e10a4e Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Mon, 13 Sep 2021 15:00:42 -0700 Subject: [PATCH 095/274] Moving NetworkHitVolumesComponent and NetworkRigidBodyComponent to the MultiplayerGem Signed-off-by: Gene Walters --- Gems/Multiplayer/Code/CMakeLists.txt | 2 + .../Components/NetworkHitVolumesComponent.h | 89 +++++++ .../Components/NetworkRigidBodyComponent.h | 68 ++++++ .../AutoGen/AutoComponentTypes_Source.jinja | 2 +- ...tworkHitVolumesComponent.AutoComponent.xml | 12 + ...etworkRigidBodyComponent.AutoComponent.xml | 18 ++ .../Components/NetworkHitVolumesComponent.cpp | 222 ++++++++++++++++++ .../Components/NetworkRigidBodyComponent.cpp | 147 ++++++++++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 6 + 9 files changed, 565 insertions(+), 1 deletion(-) create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkRigidBodyComponent.h create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkHitVolumesComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkRigidBodyComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkRigidBodyComponent.cpp diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index e8b38c8799..256f1bceeb 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -25,6 +25,8 @@ ly_add_target( AZ::AzCore AZ::AzFramework AZ::AzNetworking + PRIVATE + Gem::EMotionFXStaticLib AUTOGEN_RULES *.AutoPackets.xml,AutoPackets_Header.jinja,$path/$fileprefix.AutoPackets.h *.AutoPackets.xml,AutoPackets_Inline.jinja,$path/$fileprefix.AutoPackets.inl diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h new file mode 100644 index 0000000000..74f6dcc571 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include + +namespace Physics +{ + class CharacterRequests; + class CharacterHitDetectionConfiguration; +} + +namespace Multiplayer +{ + class NetworkHitVolumesComponent + : public NetworkHitVolumesComponentBase + , private EMotionFX::Integration::ActorComponentNotificationBus::Handler + { + public: + struct AnimatedHitVolume final + { + AnimatedHitVolume + ( + AzNetworking::ConnectionId connectionId, + Physics::CharacterRequests* character, + const char* hitVolumeName, + const Physics::ColliderConfiguration* colliderConfig, + const Physics::ShapeConfiguration* shapeConfig, + const uint32_t jointIndex + ); + + ~AnimatedHitVolume() = default; + + void UpdateTransform(const AZ::Transform& transform); + void SyncToCurrentTransform(); + + Multiplayer::RewindableObject m_transform; + AZStd::shared_ptr m_physicsShape; + + // Cached so we don't have to do subsequent lookups by name + const Physics::ColliderConfiguration* m_colliderConfig = nullptr; + const Physics::ShapeConfiguration* m_shapeConfig = nullptr; + AZ::Transform m_colliderOffSetTransform; + const AZ::u32 m_jointIndex = 0; + }; + + AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHitVolumesComponent, s_networkHitVolumesComponentConcreteUuid, Multiplayer::NetworkHitVolumesComponentBase); + + static void Reflect(AZ::ReflectContext* context); + + NetworkHitVolumesComponent(); + + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnPreRender(float deltaTime, float blendFactor); + void OnTransformUpdate(const AZ::Transform& transform); + void OnSyncRewind(); + + void CreateHitVolumes(); + void DestroyHitVolumes(); + + //! ActorComponentNotificationBus::Handler + //! @{ + void OnActorInstanceCreated(EMotionFX::ActorInstance* actorInstance) override; + void OnActorInstanceDestroyed(EMotionFX::ActorInstance* actorInstance) override; + //! @} + + Physics::CharacterRequests* m_physicsCharacter = nullptr; + EMotionFX::Integration::ActorComponentRequests* m_actorComponent = nullptr; + const Physics::CharacterColliderConfiguration* m_hitDetectionConfig = nullptr; + + AZStd::vector m_animatedHitVolumes; + + Multiplayer::EntitySyncRewindEvent::Handler m_syncRewindHandler; + Multiplayer::EntityPreRenderEvent::Handler m_preRenderHandler; + AZ::TransformChangedEvent::Handler m_transformChangedHandler; + }; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkRigidBodyComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkRigidBodyComponent.h new file mode 100644 index 0000000000..19379fc959 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkRigidBodyComponent.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include + +namespace Physics +{ + class RigidBodyRequests; +} + +namespace Multiplayer +{ + //! Bus for requests to the network rigid body component. + class NetworkRigidBodyRequests : public AZ::ComponentBus + { + }; + using NetworkRigidBodyRequestBus = AZ::EBus; + + class NetworkRigidBodyComponent final + : public NetworkRigidBodyComponentBase + , private NetworkRigidBodyRequestBus::Handler + { + friend class NetworkRigidBodyComponentController; + + public: + AZ_MULTIPLAYER_COMPONENT( + Multiplayer::NetworkRigidBodyComponent, s_networkRigidBodyComponentConcreteUuid, Multiplayer::NetworkRigidBodyComponentBase); + + static void Reflect(AZ::ReflectContext* context); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); + + NetworkRigidBodyComponent(); + + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnTransformUpdate(const AZ::Transform& worldTm); + void OnSyncRewind(); + + Multiplayer::EntitySyncRewindEvent::Handler m_syncRewindHandler; + AZ::TransformChangedEvent::Handler m_transformChangedHandler; + Physics::RigidBodyRequests* m_physicsRigidBodyComponent = nullptr; + Multiplayer::RewindableObject m_transform; + }; + + class NetworkRigidBodyComponentController + : public NetworkRigidBodyComponentControllerBase + { + public: + NetworkRigidBodyComponentController(NetworkRigidBodyComponent& parent); + + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + void HandleSendApplyImpulse(AzNetworking::IConnection* invokingConnection, const AZ::Vector3& impulse, const AZ::Vector3& worldPoint) override; + }; +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja index 7bb4bdcc2c..c551c8bc20 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponentTypes_Source.jinja @@ -14,7 +14,7 @@ {% set Namespace = dataFiles[0].attrib['Namespace'] %} {% for Component in dataFiles %} {% if Component.attrib['Namespace'] != Namespace %} -#error "mismatched component namespaces detected in declared multiplayer components, expected {{ Namespace }} but found {{ Component.attrib['Namespace'] }}" +#error "mismatched component namespaces detected in declared multiplayer components, expected {{ Namespace }} but {{ Component.attrib['Name'] }} is using {{ Component.attrib['Namespace'] }} namespace." {% endif %} {% endfor %} namespace {{ Namespace }} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkHitVolumesComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHitVolumesComponent.AutoComponent.xml new file mode 100644 index 0000000000..d3c31a5bc0 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHitVolumesComponent.AutoComponent.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkRigidBodyComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkRigidBodyComponent.AutoComponent.xml new file mode 100644 index 0000000000..b6cdfca9c2 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkRigidBodyComponent.AutoComponent.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp new file mode 100644 index 0000000000..e95afbdc86 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + AZ_CVAR(bool, bg_DrawArticulatedHitVolumes, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enables debug draw of articulated hit volumes"); + AZ_CVAR(float, bg_DrawDebugHitVolumeLifetime, 0.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The lifetime for hit volume draw-debug shapes"); + + AZ_CVAR(float, bg_RewindPositionTolerance, 0.0001f, nullptr, AZ::ConsoleFunctorFlags::Null, "Don't sync the physx entity if the square of delta position is less than this value"); + AZ_CVAR(float, bg_RewindOrientationTolerance, 0.001f, nullptr, AZ::ConsoleFunctorFlags::Null, "Don't sync the physx entity if the square of delta orientation is less than this value"); + + NetworkHitVolumesComponent::AnimatedHitVolume::AnimatedHitVolume + ( + AzNetworking::ConnectionId connectionId, + Physics::CharacterRequests* character, + const char* hitVolumeName, + const Physics::ColliderConfiguration* colliderConfig, + const Physics::ShapeConfiguration* shapeConfig, + const uint32_t jointIndex + ) + : m_colliderConfig(colliderConfig) + , m_shapeConfig(shapeConfig) + , m_jointIndex(jointIndex) + { + m_transform.SetOwningConnectionId(connectionId); + + m_colliderOffSetTransform = AZ::Transform::CreateFromQuaternionAndTranslation(m_colliderConfig->m_rotation, m_colliderConfig->m_position); + + if (m_colliderConfig->m_isExclusive) + { + Physics::SystemRequestBus::BroadcastResult(m_physicsShape, &Physics::SystemRequests::CreateShape, *m_colliderConfig, *m_shapeConfig); + } + else + { + Physics::ColliderConfiguration colliderConfiguration = *m_colliderConfig; + colliderConfiguration.m_isExclusive = true; + colliderConfiguration.m_isSimulated = false; + colliderConfiguration.m_isInSceneQueries = true; + Physics::SystemRequestBus::BroadcastResult(m_physicsShape, &Physics::SystemRequests::CreateShape, colliderConfiguration, *m_shapeConfig); + } + + if (m_physicsShape) + { + m_physicsShape->SetName(hitVolumeName); + character->GetCharacter()->AttachShape(m_physicsShape); + } + } + + void NetworkHitVolumesComponent::AnimatedHitVolume::UpdateTransform(const AZ::Transform& transform) + { + m_transform = transform; + m_physicsShape->SetLocalPose(transform.GetTranslation(), transform.GetRotation()); + } + + void NetworkHitVolumesComponent::AnimatedHitVolume::SyncToCurrentTransform() + { + AZ::Transform rewoundTransform; + const AZ::Transform& targetTransform = m_transform.Get(); + const float blendFactor = Multiplayer::GetNetworkTime()->GetHostBlendFactor(); + if (blendFactor < 1.f) + { + // If a blend factor was supplied, interpolate the transform appropriately + const AZ::Transform& previousTransform = m_transform.GetPrevious(); + rewoundTransform.SetRotation(previousTransform.GetRotation().Slerp(targetTransform.GetRotation(), blendFactor)); + rewoundTransform.SetTranslation(previousTransform.GetTranslation().Lerp(targetTransform.GetTranslation(), blendFactor)); + rewoundTransform.SetUniformScale(AZ::Lerp(previousTransform.GetUniformScale(), targetTransform.GetUniformScale(), blendFactor)); + } + else + { + rewoundTransform = m_transform.Get(); + } + + const AZ::Transform physicsTransform = AZ::Transform::CreateFromQuaternionAndTranslation(m_physicsShape->GetLocalPose().second, m_physicsShape->GetLocalPose().first); + + // Don't call SetLocalPose unless the transforms are actually different + const AZ::Vector3 positionDelta = physicsTransform.GetTranslation() - rewoundTransform.GetTranslation(); + const AZ::Quaternion orientationDelta = physicsTransform.GetRotation() - rewoundTransform.GetRotation(); + + if ((positionDelta.GetLengthSq() >= bg_RewindPositionTolerance) || (orientationDelta.GetLengthSq() >= bg_RewindOrientationTolerance)) + { + m_physicsShape->SetLocalPose(rewoundTransform.GetTranslation(), rewoundTransform.GetRotation()); + } + } + + void NetworkHitVolumesComponent::NetworkHitVolumesComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + } + NetworkHitVolumesComponentBase::Reflect(context); + } + + NetworkHitVolumesComponent::NetworkHitVolumesComponent() + : m_syncRewindHandler([this]() { OnSyncRewind(); }) + , m_preRenderHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); }) + , m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformUpdate(worldTm); }) + { + ; + } + + void NetworkHitVolumesComponent::OnInit() + { + ; + } + + void NetworkHitVolumesComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + EMotionFX::Integration::ActorComponentNotificationBus::Handler::BusConnect(GetEntityId()); + GetNetBindComponent()->AddEntitySyncRewindEventHandler(m_syncRewindHandler); + m_physicsCharacter = Physics::CharacterRequestBus::FindFirstHandler(GetEntityId()); + GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler); + OnTransformUpdate(GetTransformComponent()->GetWorldTM()); + } + + void NetworkHitVolumesComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + DestroyHitVolumes(); + EMotionFX::Integration::ActorComponentNotificationBus::Handler::BusDisconnect(); + } + + void NetworkHitVolumesComponent::OnPreRender([[maybe_unused]] float deltaTime, [[maybe_unused]] float blendFactor) + { + if (m_animatedHitVolumes.size() <= 0) + { + CreateHitVolumes(); + } + + AZ::Vector3 position, scale; + AZ::Quaternion rotation; + for (AnimatedHitVolume& hitVolume : m_animatedHitVolumes) + { + m_actorComponent->GetJointTransformComponents(hitVolume.m_jointIndex, EMotionFX::Integration::Space::ModelSpace, position, rotation, scale); + hitVolume.UpdateTransform(AZ::Transform::CreateFromQuaternionAndTranslation(rotation, position) * hitVolume.m_colliderOffSetTransform); + } + } + + void NetworkHitVolumesComponent::OnTransformUpdate([[maybe_unused]] const AZ::Transform& transform) + { + OnSyncRewind(); + } + + void NetworkHitVolumesComponent::OnSyncRewind() + { + if (m_physicsCharacter && m_physicsCharacter->GetCharacter()) + { + uint32_t frameId = static_cast(Multiplayer::GetNetworkTime()->GetHostFrameId()); + m_physicsCharacter->GetCharacter()->SetFrameId(frameId); + } + + for (AnimatedHitVolume& hitVolume : m_animatedHitVolumes) + { + hitVolume.SyncToCurrentTransform(); + } + } + + void NetworkHitVolumesComponent::CreateHitVolumes() + { + if (m_physicsCharacter == nullptr || m_actorComponent == nullptr) + { + return; + } + + const Physics::AnimationConfiguration* physicsConfig = m_actorComponent->GetPhysicsConfig(); + if (physicsConfig == nullptr) + { + return; + } + + m_hitDetectionConfig = &physicsConfig->m_hitDetectionConfig; + const AzNetworking::ConnectionId owningConnectionId = GetNetBindComponent()->GetOwningConnectionId(); + + m_animatedHitVolumes.reserve(m_hitDetectionConfig->m_nodes.size()); + for (const Physics::CharacterColliderNodeConfiguration& nodeConfig : m_hitDetectionConfig->m_nodes) + { + const AZStd::size_t jointIndex = m_actorComponent->GetJointIndexByName(nodeConfig.m_name.c_str()); + if (jointIndex == EMotionFX::Integration::ActorComponentRequests::s_invalidJointIndex) + { + continue; + } + + for (const AzPhysics::ShapeColliderPair& coliderPair : nodeConfig.m_shapes) + { + const Physics::ColliderConfiguration* colliderConfig = coliderPair.first.get(); + Physics::ShapeConfiguration* shapeConfig = coliderPair.second.get(); + m_animatedHitVolumes.emplace_back(owningConnectionId, m_physicsCharacter, nodeConfig.m_name.c_str(), colliderConfig, shapeConfig, aznumeric_cast(jointIndex)); + } + } + } + + void NetworkHitVolumesComponent::DestroyHitVolumes() + { + m_animatedHitVolumes.clear(); + } + + void NetworkHitVolumesComponent::OnActorInstanceCreated([[maybe_unused]] EMotionFX::ActorInstance* actorInstance) + { + m_actorComponent = EMotionFX::Integration::ActorComponentRequestBus::FindFirstHandler(GetEntity()->GetId()); + } + + void NetworkHitVolumesComponent::OnActorInstanceDestroyed([[maybe_unused]] EMotionFX::ActorInstance* actorInstance) + { + m_actorComponent = nullptr; + } +} diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkRigidBodyComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkRigidBodyComponent.cpp new file mode 100644 index 0000000000..bcf855d834 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkRigidBodyComponent.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +namespace Multiplayer +{ + AZ_CVAR_EXTERNED(float, bg_RewindPositionTolerance); + AZ_CVAR_EXTERNED(float, bg_RewindOrientationTolerance); + + void NetworkRigidBodyComponent::NetworkRigidBodyComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class()->Version(1); + } + NetworkRigidBodyComponentBase::Reflect(context); + } + + void NetworkRigidBodyComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("NetworkRigidBodyService")); + } + + void NetworkRigidBodyComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("PhysXRigidBodyService")); + } + + void NetworkRigidBodyComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) + { + dependent.push_back(AZ_CRC_CE("TransformService")); + dependent.push_back(AZ_CRC_CE("PhysXRigidBodyService")); + } + + NetworkRigidBodyComponent::NetworkRigidBodyComponent() + : m_syncRewindHandler([this](){ OnSyncRewind(); }) + , m_transformChangedHandler([this]([[maybe_unused]] const AZ::Transform& localTm, const AZ::Transform& worldTm){ OnTransformUpdate(worldTm); }) + { + } + + void NetworkRigidBodyComponent::OnInit() + { + } + + void NetworkRigidBodyComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + NetworkRigidBodyRequestBus::Handler::BusConnect(GetEntityId()); + + GetNetBindComponent()->AddEntitySyncRewindEventHandler(m_syncRewindHandler); + GetEntity()->FindComponent()->BindTransformChangedEventHandler(m_transformChangedHandler); + + m_physicsRigidBodyComponent = + Physics::RigidBodyRequestBus::FindFirstHandler(GetEntity()->GetId()); + AZ_Assert(m_physicsRigidBodyComponent, "PhysX Rigid Body Component is required on entity %s", GetEntity()->GetName().c_str()); + + if (!HasController()) + { + m_physicsRigidBodyComponent->SetKinematic(true); + } + } + + void NetworkRigidBodyComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + NetworkRigidBodyRequestBus::Handler::BusDisconnect(); + } + + void NetworkRigidBodyComponent::OnTransformUpdate(const AZ::Transform& worldTm) + { + m_transform = worldTm; + + if (!HasController()) + { + m_physicsRigidBodyComponent->SetKinematicTarget(worldTm); + } + } + + void NetworkRigidBodyComponent::OnSyncRewind() + { + uint32_t frameId = static_cast(Multiplayer::GetNetworkTime()->GetHostFrameId()); + + AzPhysics::RigidBody* rigidBody = m_physicsRigidBodyComponent->GetRigidBody(); + rigidBody->SetFrameId(frameId); + + AZ::Transform rewoundTransform; + const AZ::Transform& targetTransform = m_transform.Get(); + const float blendFactor = Multiplayer::GetNetworkTime()->GetHostBlendFactor(); + if (blendFactor < 1.f) + { + // If a blend factor was supplied, interpolate the transform appropriately + const AZ::Transform& previousTransform = m_transform.GetPrevious(); + rewoundTransform.SetRotation(previousTransform.GetRotation().Slerp(targetTransform.GetRotation(), blendFactor)); + rewoundTransform.SetTranslation(previousTransform.GetTranslation().Lerp(targetTransform.GetTranslation(), blendFactor)); + rewoundTransform.SetUniformScale(AZ::Lerp(previousTransform.GetUniformScale(), targetTransform.GetUniformScale(), blendFactor)); + } + else + { + rewoundTransform = m_transform.Get(); + } + const AZ::Transform& physicsTransform = rigidBody->GetTransform(); + + // Don't call SetLocalPose unless the transforms are actually different + const AZ::Vector3 positionDelta = physicsTransform.GetTranslation() - rewoundTransform.GetTranslation(); + const AZ::Quaternion orientationDelta = physicsTransform.GetRotation() - rewoundTransform.GetRotation(); + + if ((positionDelta.GetLengthSq() >= bg_RewindPositionTolerance) || + (orientationDelta.GetLengthSq() >= bg_RewindOrientationTolerance)) + { + rigidBody->SetTransform(rewoundTransform); + } + } + + NetworkRigidBodyComponentController::NetworkRigidBodyComponentController(NetworkRigidBodyComponent& parent) + : NetworkRigidBodyComponentControllerBase(parent) + { + ; + } + + void NetworkRigidBodyComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkRigidBodyComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkRigidBodyComponentController::HandleSendApplyImpulse + ( + [[maybe_unused]] AzNetworking::IConnection* invokingConnection, + const AZ::Vector3& impulse, + const AZ::Vector3& worldPoint + ) + { + AzPhysics::RigidBody* rigidBody = GetParent().m_physicsRigidBodyComponent->GetRigidBody(); + rigidBody->ApplyLinearImpulseAtWorldPoint(impulse, worldPoint); + } +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 0b2adb1530..ca5a52579c 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -18,6 +18,8 @@ set(FILES Include/Multiplayer/Components/MultiplayerController.h Include/Multiplayer/Components/MultiplayerComponentRegistry.h Include/Multiplayer/Components/NetBindComponent.h + Include/Multiplayer/Components/NetworkHitVolumesComponent.h + Include/Multiplayer/Components/NetworkRigidBodyComponent.h Include/Multiplayer/Components/NetworkTransformComponent.h Include/Multiplayer/ConnectionData/IConnectionData.h Include/Multiplayer/EntityDomains/IEntityDomain.h @@ -51,12 +53,16 @@ set(FILES Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml Source/AutoGen/Multiplayer.AutoPackets.xml Source/AutoGen/MultiplayerEditor.AutoPackets.xml + Source/AutoGen/NetworkHitVolumesComponent.AutoComponent.xml + Source/AutoGen/NetworkRigidBodyComponent.AutoComponent.xml Source/AutoGen/NetworkTransformComponent.AutoComponent.xml Source/Components/LocalPredictionPlayerInputComponent.cpp Source/Components/MultiplayerComponent.cpp Source/Components/MultiplayerController.cpp Source/Components/MultiplayerComponentRegistry.cpp Source/Components/NetBindComponent.cpp + Source/Components/NetworkHitVolumesComponent.cpp + Source/Components/NetworkRigidBodyComponent.cpp Source/Components/NetworkTransformComponent.cpp Source/ConnectionData/ClientToServerConnectionData.cpp Source/ConnectionData/ClientToServerConnectionData.h From 2a10c400a7ac5b94c7eb86ce542e489f1b8a2609 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:28:52 -0400 Subject: [PATCH 096/274] Comments cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Multiplayer/Components/NetworkHierarchyRootComponent.h | 2 +- .../Code/Source/Components/NetworkHierarchyChildComponent.cpp | 2 +- .../Code/Source/Components/NetworkHierarchyRootComponent.cpp | 2 +- Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp | 4 ++-- Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp | 3 --- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 48c003d9e7..6192d41ad6 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -18,7 +18,7 @@ namespace Multiplayer //! @class NetworkHierarchyRootComponent //! @brief Component that declares the top level entity of a network hierarchy. /* - * Call @GetHierarchyChildren to get the list of hierarchical entities. + * Call @GetHierarchicalEntities to get the list of hierarchical entities. * A network hierarchy is meant to be a small group of entities. You can control the maximum supported size of * a network hierarchy by modifying CVar @bg_hierarchyEntityMaxLimit. * diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index c644b832a0..c04fc2cf3b 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -26,7 +26,7 @@ namespace Multiplayer if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Network Hierarchy Child", "declares a network dependency on the root of this hierarchy") + "Network Hierarchy Child", "Declares a network dependency on the root of this hierarchy.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index 2fa960ed2a..d20aa8d898 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -32,7 +32,7 @@ namespace Multiplayer if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Network Hierarchy Root", "marks the entity as the root of an entity hierarchy") + "Network Hierarchy Root", "Marks the entity as the root of an entity hierarchy.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index d1b01a279c..23de4d2f04 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -287,8 +287,8 @@ namespace Multiplayer ); } - /* - * Parent -> Child + /* + * Parent -> Child -> ChildOfChild */ class ClientDeepHierarchyTests : public ClientSimpleHierarchyTests { diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index ae2d8b162d..d119ade937 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -66,9 +66,6 @@ namespace Multiplayer PopulateHierarchicalEntity(child); SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); - //// we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) - //SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); - // Create an entity replicator for the child entity const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); From 853cffbf7bcfde4ebdb9cab4fd4bc1cd2fa6f2c1 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:37:05 -0400 Subject: [PATCH 097/274] Comment cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Include/Multiplayer/Components/NetworkHierarchyBus.h | 2 +- .../Multiplayer/Components/NetworkHierarchyChildComponent.h | 3 ++- .../Code/Source/Components/NetworkHierarchyChildComponent.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h index 72dff65401..d644d6eb5a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -20,7 +20,7 @@ namespace Multiplayer virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {} //! Called when an entity has left a hierarchy - virtual void OnLeavingNetworkHierarchy() {} + virtual void OnNetworkHierarchyLeave() {} }; typedef AZ::EBus NetworkHierarchyNotificationBus; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index 27f794ec21..cfc3803d28 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -39,13 +39,14 @@ namespace Multiplayer NetworkHierarchyChildComponent(); + //! NetworkHierarchyChildComponentBase overrides. //! @{ void OnInit() override; void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; //! @} - //! NetworkHierarchyRequestBus overrides + //! NetworkHierarchyRequestBus overrides. //! @{ bool IsHierarchicalChild() const override; bool IsHierarchicalRoot() const override { return false; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index c04fc2cf3b..cbdf214dfc 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -114,7 +114,7 @@ namespace Multiplayer else { controller->SetHierarchyRoot(InvalidNetEntityId); - NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnLeavingNetworkHierarchy); + NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyLeave); } } } From 05e464b31bd8b99d7757874ef1e01c70089adeae Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:45:22 -0400 Subject: [PATCH 098/274] Improving comments Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyRootComponent.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 6192d41ad6..4be8b24d8a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -67,10 +67,19 @@ namespace Multiplayer AZStd::vector m_hierarchicalEntities; void RebuildHierarchy(); - - //! @returns false if the maximum supported hierarchy size has been reached + + //! @param underEntity Walk the child entities that belong to @underEntity and consider adding them to the hierarchy + //! @param currentEntityCount The total number of entities in the hierarchy prior to calling this method, + //! used to avoid adding too many entities to the hierarchy while walking recursively the relevant entities. + //! @currentEntityCount will be modified to reflect the total entity count upon completion of this method. + //! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise bool RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount); - //! @returns false if the maximum supported hierarchy size has been reached + + //! @param entity Add the child entity and any of its relevant children to the hierarchy + //! @param currentEntityCount The total number of entities in the hierarchy prior to calling this method, + //! used to avoid adding too many entities to the hierarchy while walking recursively the relevant entities. + //! @currentEntityCount will be modified to reflect the total entity count upon completion of this method. + //! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); }; } From 0d8b0fe496a3b62bba714acc32add2befcee3321 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:51:39 -0400 Subject: [PATCH 099/274] Fixes for clang builds Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Source/Components/NetworkHierarchyRootComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index d20aa8d898..5f546298cb 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -175,7 +175,7 @@ namespace Multiplayer AZStd::vector allChildren; AZ::TransformBus::EventResult(allChildren, underEntity, &AZ::TransformBus::Events::GetChildren); - for (const AZ::EntityId newChildId : allChildren) + for (const AZ::EntityId& newChildId : allChildren) { if (!RecursiveAttachHierarchicalChild(newChildId, currentEntityCount)) { From b2963f2bc1018e3bf0be54b2a31e9582a81d36c0 Mon Sep 17 00:00:00 2001 From: srikappa-amzn <82230713+srikappa-amzn@users.noreply.github.com> Date: Mon, 13 Sep 2021 15:55:28 -0700 Subject: [PATCH 100/274] Renamed AtomMaxFileSize to DefaultMaxFileSize (#4067) Signed-off-by: srikappa-amzn --- .../Asset/Shader/Code/Source/Editor/AzslCompiler.cpp | 4 ++-- .../Shader/Code/Source/Editor/ShaderAssetBuilder.cpp | 2 +- .../Shader/Code/Source/Editor/ShaderBuilderUtility.cpp | 8 ++++---- .../Code/Source/Editor/ShaderVariantAssetBuilder.cpp | 10 +++++----- .../RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h | 4 ++-- .../Source/RPI.Builders/Material/MaterialBuilder.cpp | 4 ++-- .../RPI.Edit/Material/MaterialSourceDataSerializer.cpp | 2 +- .../Code/Source/RPI.Edit/Material/MaterialUtils.cpp | 2 +- .../Editor/AssetCollectionAsyncLoaderTestComponent.cpp | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp index a82c731d7b..79a39ff793 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslCompiler.cpp @@ -1150,7 +1150,7 @@ namespace AZ return BuildResult::CompilationFailed; } - auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (readJsonResult.IsSuccess()) { @@ -1171,7 +1171,7 @@ namespace AZ AZStd::string outputFile = m_inputFilePath; AzFramework::StringFunc::Path::ReplaceExtension(outputFile, outputExtension); - auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto readJsonResult = JsonSerializationUtils::ReadJsonFile(outputFile, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (readJsonResult.IsSuccess()) { diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 6b673759cf..6673da2be3 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -556,7 +556,7 @@ namespace AZ shaderAssetCreator.SetRenderStates(renderStates); } - Outcome hlslSourceCodeOutcome = Utils::ReadFile(hlslFullPath, AZ::RPI::JsonUtils::AtomMaxFileSize); + Outcome hlslSourceCodeOutcome = Utils::ReadFile(hlslFullPath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!hlslSourceCodeOutcome.IsSuccess()) { AZ_Error( diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index 9c616569bd..e47dd55a97 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -52,7 +52,7 @@ namespace AZ { RPI::ShaderSourceData shaderSourceData; - auto document = JsonSerializationUtils::ReadJsonFile(fullPathToJsonFile, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto document = JsonSerializationUtils::ReadJsonFile(fullPathToJsonFile, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!document.IsSuccess()) { @@ -128,7 +128,7 @@ namespace AZ AZStd::unordered_map> outcomes; for (int i : indicesOfInterest) { - outcomes[i] = JsonSerializationUtils::ReadJsonFile(pathOfJsonFiles[i], AZ::RPI::JsonUtils::AtomMaxFileSize); + outcomes[i] = JsonSerializationUtils::ReadJsonFile(pathOfJsonFiles[i], AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!outcomes[i].IsSuccess()) { AZ_Error(builderName, false, "%s", outcomes[i].GetError().c_str()); @@ -623,7 +623,7 @@ namespace AZ StructData inputStruct; inputStruct.m_id = ""; - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToIaJson, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToIaJson, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderBuilderUtilityName, false, "%s", jsonOutcome.GetError().c_str()); @@ -716,7 +716,7 @@ namespace AZ StructData outputStruct; outputStruct.m_id = ""; - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToOmJson, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(pathToOmJson, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderBuilderUtilityName, false, "%s", jsonOutcome.GetError().c_str()); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 5a552a2702..7c5be89508 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -478,7 +478,7 @@ namespace AZ RPI::Ptr shaderOptionGroupLayout = RPI::ShaderOptionGroupLayout::Create(); // The shader options define what options are available, what are the allowed values/range // for each option and what is its default value. - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(optionsGroupJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(optionsGroupJsonPath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -509,7 +509,7 @@ namespace AZ } auto functionsJsonPath = functionsJsonPathOutcome.TakeValue(); - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(functionsJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(functionsJsonPath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -541,7 +541,7 @@ namespace AZ } auto srgJsonPath = srgJsonPathOutcome.TakeValue(); - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(srgJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(srgJsonPath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -598,7 +598,7 @@ namespace AZ } auto bindingsJsonPath = bindingsJsonPathOutcome.TakeValue(); - auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(bindingsJsonPath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto jsonOutcome = JsonSerializationUtils::ReadJsonFile(bindingsJsonPath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!jsonOutcome.IsSuccess()) { AZ_Error(ShaderVariantAssetBuilderName, false, "%s", jsonOutcome.GetError().c_str()); @@ -630,7 +630,7 @@ namespace AZ } hlslSourcePath = hlslSourcePathOutcome.TakeValue(); - Outcome hlslSourceOutcome = Utils::ReadFile(hlslSourcePath, AZ::RPI::JsonUtils::AtomMaxFileSize); + Outcome hlslSourceOutcome = Utils::ReadFile(hlslSourcePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!hlslSourceOutcome.IsSuccess()) { AZ_Error( diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 913a9702b1..4715acd64c 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -22,7 +22,7 @@ namespace AZ { //! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary. //! If you need to work with larger files, please use AZ::IO directly instead of these utility functions. - inline constexpr size_t AtomMaxFileSize = 1024 * 1024; + inline constexpr size_t DefaultMaxFileSize = 1024 * 1024; // Declarations... @@ -43,7 +43,7 @@ namespace AZ { objectData = ObjectType(); - auto loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(path, AtomMaxFileSize); + auto loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(path, DefaultMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error("AZ::RPI::JsonUtils", false, "%s", loadOutcome.GetError().c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 62e078c628..5ddeb08ef8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -152,7 +152,7 @@ namespace AZ AZStd::string fullSourcePath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullSourcePath, true); - auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error(MaterialBuilderName, false, "%s", loadOutcome.GetError().c_str()); @@ -299,7 +299,7 @@ namespace AZ AZStd::string fullSourcePath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullSourcePath, true); - auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto loadOutcome = JsonSerializationUtils::ReadJsonFile(fullSourcePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error(MaterialBuilderName, false, "Failed to load material file: %s", loadOutcome.GetError().c_str()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp index 6f68115ccb..5e4af07aae 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialSourceDataSerializer.cpp @@ -68,7 +68,7 @@ namespace AZ { AZStd::string materialTypePath = AssetUtils::ResolvePathReference(jsonFileLoadContext->GetFilePath(), materialSourceData->m_materialType); - auto materialTypeJson = JsonSerializationUtils::ReadJsonFile(materialTypePath, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto materialTypeJson = JsonSerializationUtils::ReadJsonFile(materialTypePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!materialTypeJson.IsSuccess()) { AZStd::string failureMessage; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp index 80b292ea9b..62f4f02e3c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Material/MaterialUtils.cpp @@ -65,7 +65,7 @@ namespace AZ AZ::Outcome loadOutcome; if (document == nullptr) { - loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(filePath, AZ::RPI::JsonUtils::AtomMaxFileSize); + loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(filePath, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error("AZ::RPI::JsonUtils", false, "%s", loadOutcome.GetError().c_str()); diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp index 8270901b6b..92e09bf4b1 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp @@ -115,7 +115,7 @@ namespace AZ { rapidjson::Document jsonDoc; - auto readJsonResult = JsonSerializationUtils::ReadJsonFile(pathToAssetListJson, AZ::RPI::JsonUtils::AtomMaxFileSize); + auto readJsonResult = JsonSerializationUtils::ReadJsonFile(pathToAssetListJson, AZ::RPI::JsonUtils::DefaultMaxFileSize); if (!readJsonResult.IsSuccess()) { From 2c55ea574da185ea14aefec1b9b801c073fece1b Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:56:00 -0700 Subject: [PATCH 101/274] Added a new ScopedValue utility class that simply sets a value when it goes out of scope. This is particularly handy for flags that track whether the callstack is inside a particular scope, like a m_isInitializing flag. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../AtomCore/AtomCore/Utils/ScopedValue.h | 36 ++++++++++++++++++ .../AtomCore/AtomCore/atomcore_files.cmake | 1 + .../AtomCore/Tests/ScopedValueTest.cpp | 37 +++++++++++++++++++ .../AtomCore/Tests/atomcore_tests_files.cmake | 1 + 4 files changed, 75 insertions(+) create mode 100644 Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h create mode 100644 Code/Framework/AtomCore/Tests/ScopedValueTest.cpp diff --git a/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h b/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h new file mode 100644 index 0000000000..8cb985cffe --- /dev/null +++ b/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include + +namespace AZ +{ + //! Sets a variable upon construction and again when the object goes out of scope. + template + class ScopedValue + { + private: + T* m_ptr; + T m_finalValue; + + public: + ScopedValue(T* ptr, T initialValue, T finalValue) + { + m_ptr = ptr; + *m_ptr = initialValue; + m_finalValue = finalValue; + } + + ~ScopedValue() + { + *m_ptr = m_finalValue; + } + }; + +} // namespace AZ diff --git a/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake b/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake index c90263468f..9167c1e645 100644 --- a/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake +++ b/Code/Framework/AtomCore/AtomCore/atomcore_files.cmake @@ -19,4 +19,5 @@ set(FILES std/containers/vector_set.h std/containers/vector_set_base.h std/parallel/concurrency_checker.h + Utils/ScopedValue.h ) diff --git a/Code/Framework/AtomCore/Tests/ScopedValueTest.cpp b/Code/Framework/AtomCore/Tests/ScopedValueTest.cpp new file mode 100644 index 0000000000..9578cb2329 --- /dev/null +++ b/Code/Framework/AtomCore/Tests/ScopedValueTest.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +namespace UnitTest +{ + TEST(ScopedValueTest, TestBoolValue) + { + bool localValue = false; + + { + AZ::ScopedValue scopedValue(&localValue, true, false); + EXPECT_EQ(true, localValue); + } + + EXPECT_EQ(false, localValue); + } + + TEST(ScopedValueTest, TestIntValue) + { + int localValue = 0; + + { + AZ::ScopedValue scopedValue(&localValue, 1, 2); + EXPECT_EQ(1, localValue); + } + + EXPECT_EQ(2, localValue); + } +} diff --git a/Code/Framework/AtomCore/Tests/atomcore_tests_files.cmake b/Code/Framework/AtomCore/Tests/atomcore_tests_files.cmake index 0f5fcb441d..4522a4b7b6 100644 --- a/Code/Framework/AtomCore/Tests/atomcore_tests_files.cmake +++ b/Code/Framework/AtomCore/Tests/atomcore_tests_files.cmake @@ -12,5 +12,6 @@ set(FILES InstanceDatabase.cpp lru_cache.cpp Main.cpp + ScopedValueTest.cpp vector_set.cpp ) From f75fa435f9fbb2ae272875e80fb40bb39dd7a938 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 13 Sep 2021 17:00:58 -0700 Subject: [PATCH 102/274] Made a couple imporvements to material_find_overrides_demo.lua: - Made the target material slot name configurable through an exposed component property. - Fixed a timing issue where the assignmentId was invalid if FindMaterialAssignmentId is called too early. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Scripts/material_find_overrides_demo.lua | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua b/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua index 41df35e355..4a1b8c8f06 100644 --- a/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua +++ b/Gems/Atom/Feature/Common/Assets/Scripts/material_find_overrides_demo.lua @@ -22,6 +22,7 @@ local FindMaterialAssignmentTest = "materials/presets/macbeth/12_orange_yellow_srgb.tif.streamingimage", "materials/presets/macbeth/17_magenta_srgb.tif.streamingimage" }, + MaterialSlotFilter = "" }, } @@ -50,18 +51,6 @@ function FindMaterialAssignmentTest:OnActivate() self.colors = {} self.lerpDirs = {} - self.assignmentIds = - { - MaterialComponentRequestBus.Event.FindMaterialAssignmentId(self.entityId, -1, "lambert"), - } - - for index = 1, #self.assignmentIds do - local id = self.assignmentIds[index] - if (id ~= nil) then - self.colors[index] = randomColor() - self.lerpDirs[index] = randomDir() - end - end self.tickBusHandler = TickBus.Connect(self); end @@ -144,10 +133,33 @@ function FindMaterialAssignmentTest:lerpColors(deltaTime) end function FindMaterialAssignmentTest:OnTick(deltaTime, timePoint) + + + if(nil == self.assignmentIds) then + + local originalAssignments = MaterialComponentRequestBus.Event.GetOriginalMaterialAssignments(self.entityId) + if(nil == originalAssignments or #originalAssignments <= 1) then -- There is always 1 entry for the default assignment; a loaded model will have at least 2 assignments + return + end + + self.assignmentIds = + { + MaterialComponentRequestBus.Event.FindMaterialAssignmentId(self.entityId, -1, self.Properties.MaterialSlotFilter), + } + + for index = 1, #self.assignmentIds do + local id = self.assignmentIds[index] + if (id ~= nil) then + self.colors[index] = randomColor() + self.lerpDirs[index] = randomDir() + end + end + end + self.timer = self.timer + deltaTime self.totalTime = self.totalTime + deltaTime self:lerpColors(deltaTime) - + if (self.timer > self.timeUpdate and self.totalTime < self.totalTimeMax) then self.timer = self.timer - self.timeUpdate self:UpdateProperties() @@ -155,6 +167,7 @@ function FindMaterialAssignmentTest:OnTick(deltaTime, timePoint) self:ClearProperties() self.tickBusHandler:Disconnect(self); end + end -return FindMaterialAssignmentTest \ No newline at end of file +return FindMaterialAssignmentTest From 0d0b6c80330d2804d494d1944713db596c584f14 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Mon, 13 Sep 2021 17:04:47 -0700 Subject: [PATCH 103/274] Add support for nvme volumes Signed-off-by: brianherrera --- scripts/build/bootstrap/incremental_build_util.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index 10543d5951..101e31b5db 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -320,10 +320,14 @@ def mount_volume_to_device(created): time.sleep(1) else: - subprocess.call(['file', '-s', '/dev/xvdf']) + device_name = '/dev/xvdf' + nvme_device_name = '/dev/nvme1n1' + if os.path.exists(nvme_device_name): + device_name = nvme_device_name + subprocess.call(['file', '-s', device_name]) if created: - subprocess.call(['mkfs', '-t', 'ext4', '/dev/xvdf']) - subprocess.call(['mount', '/dev/xvdf', MOUNT_PATH]) + subprocess.call(['mkfs', '-t', 'ext4', device_name]) + subprocess.call(['mount', device_name, MOUNT_PATH]) def attach_volume_to_ec2_instance(volume, volume_id, instance_id, timeout_duration=DEFAULT_TIMEOUT): @@ -515,4 +519,4 @@ def main(action, snapshot_hint, repository_name, project, pipeline, branch, plat if __name__ == "__main__": args = parse_args() ret = main(args.action, args.snapshot_hint, args.repository_name, args.project, args.pipeline, args.branch, args.platform, args.build_type, args.disk_size, args.disk_type) - sys.exit(ret) \ No newline at end of file + sys.exit(ret) From 51f101748dda11a34a5308d3e27055e06507c069 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Mon, 13 Sep 2021 17:05:11 -0700 Subject: [PATCH 104/274] These changes make material system report warnings when gameplay scripts attempt to change PSO-impacting material properties at runtime. So far the material system has always allowed any properties to be changed at runtime, including those that affect Pipeline State Objects (PSOs), as this is supported on several platforms. But some platforms require that Pipeline State Objects be pre-compiled and shipped with the game. At some point we will need to add new restrictions that limit what material properties can be changed at runtime. In the meantime, these warnings should alert users to avoid this, as the functionality likely won't be supported in the future. - Made the Material and LuaMaterialFunctor classes configurable to report errors or warnings when material properties modify Pipeline State Objects. This is controlled by a new "MaterialPropertyPsoHandling" enum. - Made the EditorMaterialComponent override PSO handling as Enabled, to prevent warnings when the user is editing material instance property overrides. This requried a new MaterialComponentNotificationBus bus message "OnMaterialInstanceCreated". - Removed unnecessary GetMaterialPropertyDependencies member from material functor context classes, as this is already available as part of the functor itself. - Made Material::SetPropertyValue return early when the property value hadn't actually changed. Besides being more efficientn, this prevents unnecessary spamming of the new warning. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI.Public/Material/Material.h | 20 +++- .../RPI.Reflect/Material/LuaMaterialFunctor.h | 22 +++- .../RPI.Reflect/Material/MaterialFunctor.h | 34 +++++- .../Source/RPI.Public/Material/Material.cpp | 28 ++++- .../Material/LuaMaterialFunctor.cpp | 109 ++++++++++++++---- .../RPI.Reflect/Material/MaterialFunctor.cpp | 4 +- .../Code/Source/Document/MaterialDocument.cpp | 4 + .../Material/MaterialComponentBus.h | 9 +- .../Material/EditorMaterialComponent.cpp | 14 ++- .../Source/Material/EditorMaterialComponent.h | 1 + .../Material/MaterialComponentController.cpp | 5 + 11 files changed, 214 insertions(+), 36 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h index 59c5d571fc..3976ef989b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Material/Material.h @@ -74,6 +74,7 @@ namespace AZ MaterialPropertyIndex FindPropertyIndex(const Name& name) const; //! Sets the value of a material property. The template data type must match the property's data type. + //! @return true if property value was changed template bool SetPropertyValue(MaterialPropertyIndex index, const Type& value); @@ -81,12 +82,15 @@ namespace AZ template const Type& GetPropertyValue(MaterialPropertyIndex index) const; - //! Gets flags indicating which properties have been modified. - const MaterialPropertyFlags& GetPropertyDirtyFlags() const; - + //! Sets the value of a material property. The @value data type must match the property's data type. + //! @return true if property value was changed bool SetPropertyValue(MaterialPropertyIndex index, const MaterialPropertyValue& value); + const MaterialPropertyValue& GetPropertyValue(MaterialPropertyIndex index) const; const AZStd::vector& GetPropertyValues() const; + + //! Gets flags indicating which properties have been modified. + const MaterialPropertyFlags& GetPropertyDirtyFlags() const; //! Gets the material properties layout. RHI::ConstPtr GetMaterialPropertiesLayout() const; @@ -111,6 +115,12 @@ namespace AZ //! @param return the number of shader options that were updated, or Failure if the material owns the indicated shader option. AZ::Outcome SetSystemShaderOption(const Name& shaderOptionName, RPI::ShaderOptionValue value); + //! Override the material's default PSO handling setting. + //! This is normally used in tools like Asset Processor or Material Editor to allow changes that impact + //! Pipeline State Objects which is not allowed at runtime. See MaterialPropertyPsoHandling for more details. + //! Do not set this in the shipping runtime unless you know what you are doing. + void SetPsoHandlingOverride(MaterialPropertyPsoHandling psoHandlingOverride); + const RHI::ShaderResourceGroup* GetRHIShaderResourceGroup() const; const Data::Asset& GetAsset() const; @@ -189,6 +199,10 @@ namespace AZ //! Records the m_currentChangeId when the material was last compiled. ChangeId m_compiledChangeId = DEFAULT_CHANGE_ID; + + bool m_isInitializing = false; + + MaterialPropertyPsoHandling m_psoHandling = MaterialPropertyPsoHandling::Warning; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h index 026e9f7f18..5f4dce40e5 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/LuaMaterialFunctor.h @@ -83,14 +83,19 @@ namespace AZ AZ_TYPE_INFO(AZ::RPI::LuaMaterialFunctorCommonContext, "{2CCCB9A9-AD4F-447C-B587-E7A91CEA8088}"); explicit LuaMaterialFunctorCommonContext(MaterialFunctor::RuntimeContext* runtimeContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix); explicit LuaMaterialFunctorCommonContext(MaterialFunctor::EditorContext* editorContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix); + + //! Returns false if PSO changes are not allowed, and may report errors or warnings + bool CheckPsoChangesAllowed(); protected: @@ -100,6 +105,12 @@ namespace AZ MaterialPropertyIndex GetMaterialPropertyIndex(const char* name, const char* functionName) const; const MaterialPropertyValue& GetMaterialPropertyValue(MaterialPropertyIndex propertyIndex) const; + + MaterialPropertyPsoHandling GetMaterialPropertyPsoHandling() const; + + RHI::ConstPtr GetMaterialPropertiesLayout() const; + + AZStd::string GetMaterialPropertyDependenciesString() const; // These are prefix strings that will be applied to every name lookup in the lua functor. // This allows the lua script to be reused in different contexts. @@ -112,6 +123,8 @@ namespace AZ // Only one of these will be valid MaterialFunctor::RuntimeContext* m_runtimeContextImpl = nullptr; MaterialFunctor::EditorContext* m_editorContextImpl = nullptr; + const MaterialPropertyFlags* m_materialPropertyDependencies = nullptr; + bool m_psoChangesReported = false; //!< errors/warnings about PSO changes will only be reported once per execution of the functor }; //! Wraps RHI::RenderStates for LuaMaterialFunctor access @@ -241,7 +254,11 @@ namespace AZ static void Reflect(BehaviorContext* behaviorContext); - explicit LuaMaterialFunctorShaderItem(ShaderCollection::Item* shaderItem) : m_shaderItem(shaderItem) {} + LuaMaterialFunctorShaderItem() : + m_context(nullptr), m_shaderItem(nullptr) {} + + explicit LuaMaterialFunctorShaderItem(LuaMaterialFunctorCommonContext* context, ShaderCollection::Item* shaderItem) : + m_context(context), m_shaderItem(shaderItem) {} LuaMaterialFunctorRenderStates GetRenderStatesOverride(); void SetEnabled(bool enable); @@ -253,6 +270,7 @@ namespace AZ private: void SetShaderOptionValue(const Name& name, AZStd::function setValueCommand); + LuaMaterialFunctorCommonContext* m_context = nullptr; ShaderCollection::Item* m_shaderItem = nullptr; }; @@ -265,6 +283,7 @@ namespace AZ static void Reflect(BehaviorContext* behaviorContext); explicit LuaMaterialFunctorRuntimeContext(MaterialFunctor::RuntimeContext* runtimeContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix); @@ -304,6 +323,7 @@ namespace AZ static void Reflect(BehaviorContext* behaviorContext); explicit LuaMaterialFunctorEditorContext(MaterialFunctor::EditorContext* editorContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h index 682183f70c..09d10bf538 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialFunctor.h @@ -28,6 +28,24 @@ namespace AZ class MaterialPropertiesLayout; using MaterialPropertyFlags = AZStd::bitset; + + //! Indicates how the material system should respond to any material property changes that + //! impact Pipeline State Object configuration. This is significant because some platforms + //! require that PSOs be pre-compiled and shipped with the game. + enum class MaterialPropertyPsoHandling + { + //! PSO-impacting property changes are not allowed, are ignored, and will report an error. + //! This should be used at runtime. It is recommended to do this on all platforms, not just the restricted ones, + //! to encourage best-practices. However, if a game project is not shipping on any restricted platforms, + //! then the team could decide to allow PSO changes. + Error, + + //! PSO-impacting property changes are allowed, but produce a warning message. + Warning, + + //! PSO-impacting property changes are allowed. This can be used during asset processing, in developer tools, or on platforms that don't restrict PSO changes. + Allowed + }; //! MaterialFunctor objects provide custom logic and calculations to configure shaders, render states, //! editor metadata, and more. @@ -81,6 +99,8 @@ namespace AZ const MaterialPropertyValue& GetMaterialPropertyValue(const MaterialPropertyIndex& index) const; const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const { return m_materialPropertiesLayout.get(); } + + MaterialPropertyPsoHandling GetMaterialPropertyPsoHandling() const { return m_psoHandling; } //! Set the value of a shader option //! @param shaderIndex the index of a shader in the material's ShaderCollection @@ -126,16 +146,18 @@ namespace AZ RHI::ConstPtr materialPropertiesLayout, ShaderCollection* shaderCollection, ShaderResourceGroup* shaderResourceGroup, - const MaterialPropertyFlags* materialPropertyDependencies + const MaterialPropertyFlags* materialPropertyDependencies, + MaterialPropertyPsoHandling psoHandling ); private: bool SetShaderOptionValue(ShaderCollection::Item& shaderItem, ShaderOptionIndex optionIndex, ShaderOptionValue value); const AZStd::vector& m_materialPropertyValues; RHI::ConstPtr m_materialPropertiesLayout; - ShaderCollection* m_shaderCollection; - ShaderResourceGroup* m_shaderResourceGroup; + ShaderCollection* m_shaderCollection; + ShaderResourceGroup* m_shaderResourceGroup; const MaterialPropertyFlags* m_materialPropertyDependencies = nullptr; + MaterialPropertyPsoHandling m_psoHandling = MaterialPropertyPsoHandling::Error; }; class EditorContext @@ -144,7 +166,7 @@ namespace AZ public: const MaterialPropertyDynamicMetadata* GetMaterialPropertyMetadata(const Name& propertyName) const; const MaterialPropertyDynamicMetadata* GetMaterialPropertyMetadata(const MaterialPropertyIndex& index) const; - + const MaterialPropertyGroupDynamicMetadata* GetMaterialPropertyGroupMetadata(const Name& propertyName) const; //! Get the property value. The type must be one of those in MaterialPropertyValue. @@ -158,6 +180,8 @@ namespace AZ const MaterialPropertyValue& GetMaterialPropertyValue(const MaterialPropertyIndex& index) const; const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const { return m_materialPropertiesLayout.get(); } + + MaterialPropertyPsoHandling GetMaterialPropertyPsoHandling() const { return MaterialPropertyPsoHandling::Allowed; } //! Set the visibility dynamic metadata of a material property. bool SetMaterialPropertyVisibility(const Name& propertyName, MaterialPropertyVisibility visibility); @@ -177,7 +201,7 @@ namespace AZ bool SetMaterialPropertySoftMaxValue(const Name& propertyName, const MaterialPropertyValue& max); bool SetMaterialPropertySoftMaxValue(const MaterialPropertyIndex& index, const MaterialPropertyValue& max); - + bool SetMaterialPropertyGroupVisibility(const Name& propertyGroupName, MaterialPropertyGroupVisibility visibility); // [GFX TODO][ATOM-4168] Replace the workaround for unlink-able RPI.Public classes in MaterialFunctor diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index 3b82114a69..2dcaa70deb 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -20,6 +20,7 @@ #include #include +#include namespace AZ { @@ -58,6 +59,8 @@ namespace AZ { AZ_TRACE_METHOD(); + ScopedValue isInitializing(&m_isInitializing, true, false); + m_materialAsset = { &materialAsset, AZ::Data::AssetLoadBehavior::PreLoad }; // Cache off pointers to some key data structures from the material type... @@ -198,6 +201,11 @@ namespace AZ return AZ::Success(appliedCount); } + void Material::SetPsoHandlingOverride(MaterialPropertyPsoHandling psoHandlingOverride) + { + m_psoHandling = psoHandlingOverride; + } + const RHI::ShaderResourceGroup* Material::GetRHIShaderResourceGroup() const { return m_rhiShaderResourceGroup; @@ -310,6 +318,16 @@ namespace AZ if (NeedsCompile() && CanCompile()) { + // On some platforms, PipelineStateObjects must be pre-compiled and shipped with the game; they cannot be compiled at runtime. So at some + // point the material system needs to be smart about when it allows PSO changes and when it doesn't. There is a task scheduled to + // thoroughly address this in 2022, but for now we just report a warning to alert users who are using the engine in a way that might + // not be supported for much longer. PSO changes should only be allowed in developer tools (though we could also expose a way for users to + // enable dynamic PSO changes if their project only targets platforms that support this). + // PSO modifications are allowed during initialization because that's using the stored asset data, which the asset system can + // access to pre-compile the necessary PSOs. + MaterialPropertyPsoHandling psoHandling = m_isInitializing ? MaterialPropertyPsoHandling::Allowed : m_psoHandling; + + AZ_PROFILE_BEGIN(RPI, "Material::Compile() Processing Functors"); for (const Ptr& functor : m_materialAsset->GetMaterialFunctors()) { @@ -325,7 +343,8 @@ namespace AZ m_layout, &m_shaderCollection, m_shaderResourceGroup.get(), - &materialPropertyDependencies + &materialPropertyDependencies, + psoHandling ); @@ -484,6 +503,13 @@ namespace AZ } MaterialPropertyValue& savedPropertyValue = m_propertyValues[index.GetIndex()]; + + // If the property value didn't actually change, don't waste time running functors and compiling the changes + if (savedPropertyValue == value) + { + return false; + } + savedPropertyValue = value; m_propertyDirtyFlags.set(index.GetIndex()); m_propertyOverrideFlags.set(index.GetIndex()); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp index 77902093f0..9338d52cb2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/LuaMaterialFunctor.cpp @@ -128,7 +128,7 @@ namespace AZ if (m_scriptStatus == ScriptStatus::Ready) { - LuaMaterialFunctorRuntimeContext luaContext{&context, m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix}; + LuaMaterialFunctorRuntimeContext luaContext{&context, &GetMaterialPropertyDependencies(), m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix}; AZ::ScriptDataContext call; if (m_scriptContext->Call("Process", call)) { @@ -146,7 +146,7 @@ namespace AZ if (m_scriptStatus == ScriptStatus::Ready) { - LuaMaterialFunctorEditorContext luaContext{&context, m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix}; + LuaMaterialFunctorEditorContext luaContext{&context, &GetMaterialPropertyDependencies(), m_propertyNamePrefix, m_srgNamePrefix, m_optionsNamePrefix}; AZ::ScriptDataContext call; if (m_scriptContext->Call("ProcessEditor", call)) { @@ -157,10 +157,12 @@ namespace AZ } LuaMaterialFunctorCommonContext::LuaMaterialFunctorCommonContext(MaterialFunctor::RuntimeContext* runtimeContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix) : m_runtimeContextImpl(runtimeContextImpl) + , m_materialPropertyDependencies(materialPropertyDependencies) , m_propertyNamePrefix(propertyNamePrefix) , m_srgNamePrefix(srgNamePrefix) , m_optionsNamePrefix(optionsNamePrefix) @@ -168,35 +170,97 @@ namespace AZ } LuaMaterialFunctorCommonContext::LuaMaterialFunctorCommonContext(MaterialFunctor::EditorContext* editorContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix) : m_editorContextImpl(editorContextImpl) + , m_materialPropertyDependencies(materialPropertyDependencies) , m_propertyNamePrefix(propertyNamePrefix) , m_srgNamePrefix(srgNamePrefix) , m_optionsNamePrefix(optionsNamePrefix) { } - - MaterialPropertyIndex LuaMaterialFunctorCommonContext::GetMaterialPropertyIndex(const char* name, const char* functionName) const + + MaterialPropertyPsoHandling LuaMaterialFunctorCommonContext::GetMaterialPropertyPsoHandling() const { - MaterialPropertyIndex propertyIndex; - - Name propertyFullName{m_propertyNamePrefix + name}; - if (m_runtimeContextImpl) { - propertyIndex = m_runtimeContextImpl->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyFullName); + return m_runtimeContextImpl->GetMaterialPropertyPsoHandling(); } - else if (m_editorContextImpl) + else { - propertyIndex = m_editorContextImpl->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyFullName); + return m_editorContextImpl->GetMaterialPropertyPsoHandling(); + } + } + + RHI::ConstPtr LuaMaterialFunctorCommonContext::GetMaterialPropertiesLayout() const + { + if (m_runtimeContextImpl) + { + return m_runtimeContextImpl->GetMaterialPropertiesLayout(); } else { - AZ_Assert(false, "Context not initialized properly"); + return m_editorContextImpl->GetMaterialPropertiesLayout(); + } + } + + AZStd::string LuaMaterialFunctorCommonContext::GetMaterialPropertyDependenciesString() const + { + AZStd::vector propertyList; + for (size_t i = 0; i < m_materialPropertyDependencies->size(); ++i) + { + if ((*m_materialPropertyDependencies)[i]) + { + propertyList.push_back(GetMaterialPropertiesLayout()->GetPropertyDescriptor(MaterialPropertyIndex{i})->GetName().GetStringView()); + } } + AZStd::string propertyListString; + AzFramework::StringFunc::Join(propertyListString, propertyList.begin(), propertyList.end(), ", "); + + return propertyListString; + } + + bool LuaMaterialFunctorCommonContext::CheckPsoChangesAllowed() + { + if (GetMaterialPropertyPsoHandling() == MaterialPropertyPsoHandling::Error) + { + if (!m_psoChangesReported) + { + LuaMaterialFunctorUtilities::Script_Error( + AZStd::string::format( + "The following material properties must not be changed at runtime because they impact Pipeline State Objects: %s", GetMaterialPropertyDependenciesString().c_str())); + + m_psoChangesReported = true; + } + + return false; + } + else if (GetMaterialPropertyPsoHandling() == MaterialPropertyPsoHandling::Warning) + { + if (!m_psoChangesReported) + { + LuaMaterialFunctorUtilities::Script_Warning( + AZStd::string::format( + "The following material properties should not be changed at runtime because they impact Pipeline State Objects: %s", GetMaterialPropertyDependenciesString().c_str())); + + m_psoChangesReported = true; + } + } + + return true; + } + + MaterialPropertyIndex LuaMaterialFunctorCommonContext::GetMaterialPropertyIndex(const char* name, const char* functionName) const + { + MaterialPropertyIndex propertyIndex; + + Name propertyFullName{m_propertyNamePrefix + name}; + + propertyIndex = GetMaterialPropertiesLayout()->FindPropertyIndex(propertyFullName); + if (!propertyIndex.IsValid()) { LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("%s() could not find property '%s'", functionName, propertyFullName.GetCStr())); @@ -297,10 +361,11 @@ namespace AZ } LuaMaterialFunctorRuntimeContext::LuaMaterialFunctorRuntimeContext(MaterialFunctor::RuntimeContext* runtimeContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix) - : LuaMaterialFunctorCommonContext(runtimeContextImpl, propertyNamePrefix, srgNamePrefix, optionsNamePrefix) + : LuaMaterialFunctorCommonContext(runtimeContextImpl, materialPropertyDependencies, propertyNamePrefix, srgNamePrefix, optionsNamePrefix) , m_runtimeContextImpl(runtimeContextImpl) { } @@ -331,7 +396,7 @@ namespace AZ if (!shaderItem.MaterialOwnsShaderOption(optionIndex)) { - LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("Shader option '%s' is not owned by this material.", fullOptionName.GetCStr()).c_str()); + LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("Shader option '%s' is not owned by this material.", fullOptionName.GetCStr())); break; } @@ -398,12 +463,12 @@ namespace AZ { if (index < GetShaderCount()) { - return LuaMaterialFunctorShaderItem{&(*m_runtimeContextImpl->m_shaderCollection)[index]}; + return LuaMaterialFunctorShaderItem{this, &(*m_runtimeContextImpl->m_shaderCollection)[index]}; } else { LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format("GetShader(%zu) is invalid.", index)); - return LuaMaterialFunctorShaderItem{nullptr}; + return {}; } } @@ -412,13 +477,13 @@ namespace AZ const AZ::Name tag{shaderTag}; if (m_runtimeContextImpl->m_shaderCollection->HasShaderTag(tag)) { - return LuaMaterialFunctorShaderItem{&(*m_runtimeContextImpl->m_shaderCollection)[tag]}; + return LuaMaterialFunctorShaderItem{this, &(*m_runtimeContextImpl->m_shaderCollection)[tag]}; } else { LuaMaterialFunctorUtilities::Script_Error(AZStd::string::format( "GetShaderByTag('%s') is invalid: Could not find a shader with the tag '%s'.", tag.GetCStr(), tag.GetCStr())); - return LuaMaterialFunctorShaderItem{nullptr}; + return {}; } } @@ -459,10 +524,11 @@ namespace AZ } LuaMaterialFunctorEditorContext::LuaMaterialFunctorEditorContext(MaterialFunctor::EditorContext* editorContextImpl, + const MaterialPropertyFlags* materialPropertyDependencies, const AZStd::string& propertyNamePrefix, const AZStd::string& srgNamePrefix, const AZStd::string& optionsNamePrefix) - : LuaMaterialFunctorCommonContext(editorContextImpl, propertyNamePrefix, srgNamePrefix, optionsNamePrefix) + : LuaMaterialFunctorCommonContext(editorContextImpl, materialPropertyDependencies, propertyNamePrefix, srgNamePrefix, optionsNamePrefix) , m_editorContextImpl(editorContextImpl) { } @@ -595,7 +661,7 @@ namespace AZ LuaMaterialFunctorRenderStates LuaMaterialFunctorShaderItem::GetRenderStatesOverride() { - if (m_shaderItem) + if (m_context->CheckPsoChangesAllowed() && m_shaderItem) { return LuaMaterialFunctorRenderStates{m_shaderItem->GetRenderStatesOverlay()}; } @@ -638,8 +704,7 @@ namespace AZ { LuaMaterialFunctorUtilities::Script_Error( AZStd::string::format( - "Shader option '%s' is not owned by the shader '%s'.", name.GetCStr(), m_shaderItem->GetShaderTag().GetCStr()) - .c_str()); + "Shader option '%s' is not owned by the shader '%s'.", name.GetCStr(), m_shaderItem->GetShaderTag().GetCStr())); return; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp index d08fa3e58e..0f70d0af35 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialFunctor.cpp @@ -35,13 +35,15 @@ namespace AZ RHI::ConstPtr materialPropertiesLayout, ShaderCollection* shaderCollection, ShaderResourceGroup* shaderResourceGroup, - const MaterialPropertyFlags* materialPropertyDependencies + const MaterialPropertyFlags* materialPropertyDependencies, + MaterialPropertyPsoHandling psoHandling ) : m_materialPropertyValues(propertyValues) , m_materialPropertiesLayout(materialPropertiesLayout) , m_shaderCollection(shaderCollection) , m_shaderResourceGroup(shaderResourceGroup) , m_materialPropertyDependencies(materialPropertyDependencies) + , m_psoHandling(psoHandling) {} bool MaterialFunctor::RuntimeContext::SetShaderOptionValue(ShaderCollection::Item& shaderItem, ShaderOptionIndex optionIndex, ShaderOptionValue value) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 11834beb73..d032f35e38 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -763,6 +763,10 @@ namespace MaterialEditor return false; } + // Pipeline State Object changes are always allowed in the material editor because it only runs on developer systems + // where such changes are supported at runtime. + m_materialInstance->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed); + // Populate the property map from a combination of source data and assets // Assets must still be used for now because they contain the final accumulated value after all other materials // in the hierarchy are applied diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 01c87fa2fb..1ed8469749 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -105,8 +105,15 @@ namespace AZ : public ComponentBus { public: - virtual void OnMaterialsUpdated([[maybe_unused]] const MaterialAssignmentMap& materials) {} + + //! This message is sent every time a material property is updated. virtual void OnMaterialsEdited([[maybe_unused]] const MaterialAssignmentMap& materials) {} + + //! This message is sent when one or more material property changes have been applied, at most once per frame. + virtual void OnMaterialsUpdated([[maybe_unused]] const MaterialAssignmentMap& materials) {} + + //! This message is sent when the component has created the material instance to be used for rendering. + virtual void OnMaterialInstanceCreated([[maybe_unused]] const MaterialAssignment& materialAssignment) {} }; using MaterialComponentNotificationBus = EBus; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index a4e058561e..4249ed0c3b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -257,6 +257,16 @@ namespace AZ &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); } + + void EditorMaterialComponent::OnMaterialInstanceCreated(const MaterialAssignment& materialAssignment) + { + // PSO-impacting property changes are allowed in the editor + // because the saved slice data can be analyzed to pre-compile the necessary PSOs. + if (materialAssignment.m_materialInstance) + { + materialAssignment.m_materialInstance->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed); + } + } void EditorMaterialComponent::UpdateConfiguration(const MaterialComponentConfig& config) { @@ -280,19 +290,19 @@ namespace AZ { continue; } + + MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; // Only material slots with a valid asset IDs or property overrides will be copied // to minimize the amount of data stored in the controller and game component if (materialSlot->m_materialAsset.GetId().IsValid()) { - MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; materialAssignment.m_materialAsset = materialSlot->m_materialAsset; materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; } else if (!materialSlot->m_propertyOverrides.empty() || !materialSlot->m_matModUvOverrides.empty()) { - MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; materialAssignment.m_materialAsset = materialSlot->m_defaultMaterialAsset; materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h index 88ffef9366..0c468b10a6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h @@ -51,6 +51,7 @@ namespace AZ //! MaterialComponentNotificationBus::Handler overrides... void OnMaterialsEdited(const MaterialAssignmentMap& materials) override; + void OnMaterialInstanceCreated(const MaterialAssignment& materialAssignment) override; // Apply a material component configuration to the active controller void UpdateConfiguration(const MaterialComponentConfig& config); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index 6e1e710282..97e8301bc9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -249,6 +249,7 @@ namespace AZ for (auto& materialPair : m_configuration.m_materials) { materialPair.second.RebuildInstance(); + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialPair.second); QueuePropertyChanges(materialPair.first); } QueueMaterialUpdateNotification(); @@ -364,6 +365,7 @@ namespace AZ { materialAssignment.m_propertyOverrides[AZ::Name(propertyName)] = value; materialAssignment.RebuildInstance(); + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialAssignment); QueueMaterialUpdateNotification(); } else @@ -561,6 +563,7 @@ namespace AZ if (materialIt->second.m_propertyOverrides.empty()) { materialIt->second.RebuildInstance(); + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialIt->second); QueueMaterialUpdateNotification(); } @@ -581,6 +584,7 @@ namespace AZ { materialIt->second.m_propertyOverrides = {}; materialIt->second.RebuildInstance(); + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialIt->second); QueueMaterialUpdateNotification(); MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } @@ -595,6 +599,7 @@ namespace AZ { materialPair.second.m_propertyOverrides = {}; materialPair.second.RebuildInstance(); + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialPair.second); QueueMaterialUpdateNotification(); cleared = true; } From 088511577b9a4ae6169d72411c36992a4a572cc0 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 20:33:32 -0400 Subject: [PATCH 105/274] Fix for clan compiler Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp | 4 ++-- Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 23de4d2f04..29d4f7f809 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -148,8 +148,8 @@ namespace Multiplayer class ClientSimpleHierarchyTests : public HierarchyTests { public: - static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; - static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; void SetUp() override { diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index d119ade937..708a39d439 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -176,9 +176,9 @@ namespace Multiplayer class ServerDeepHierarchyTests : public HierarchyTests { public: - static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; - static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; - static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; void SetUp() override { From 4db353eb22e9a74cb1a3b3616206ef8876d1842f Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Mon, 13 Sep 2021 17:38:58 -0700 Subject: [PATCH 106/274] PR comments Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../Code/Source/Shadows/ProjectedShadowFeatureProcessor.h | 3 ++- Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp | 2 +- Gems/LyShine/Code/Source/Animation/AnimSequence.h | 4 ++-- Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index cd74ba3797..eca8b91f1d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -49,7 +49,6 @@ namespace AZ::Render void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; void SetShadowBias(ShadowId id, float bias) override; void SetPcfMethod(ShadowId id, PcfMethod method) override; - void SetEsmExponent(ShadowId id, float exponent); void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override; void SetPredictionSampleCount(ShadowId id, uint16_t count) override; @@ -57,6 +56,8 @@ namespace AZ::Render void SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) override; const ProjectedShadowDescriptor& GetShadowProperties(ShadowId id) override; + void SetEsmExponent(ShadowId id, float exponent); + private: // GPU data stored in m_projectedShadows. diff --git a/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp b/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp index 86f97b96e9..f7476c0bc4 100644 --- a/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Image/StreamingImageTests.cpp @@ -53,7 +53,7 @@ namespace AZ : public UnitTest::AssetTester { public: - ImageMipChainAssetTester() {} + ImageMipChainAssetTester() = default; ~ImageMipChainAssetTester() override = default; void SetAssetReady(Data::Asset& asset) override diff --git a/Gems/LyShine/Code/Source/Animation/AnimSequence.h b/Gems/LyShine/Code/Source/Animation/AnimSequence.h index 1451770b4e..5441dc3860 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimSequence.h +++ b/Gems/LyShine/Code/Source/Animation/AnimSequence.h @@ -118,7 +118,7 @@ public: IUiAnimStringTable* GetTrackEventStringTable() override { return m_pEventStrings.get(); } //! Call to trigger a track event - void TriggerTrackEvent(const char* event, const char* param = NULL) override; + void TriggerTrackEvent(const char* event, const char* param = nullptr) override; //! Track event listener void AddTrackEventListener(IUiTrackEventListener* pListener) override; @@ -130,7 +130,7 @@ private: void ComputeTimeRange(); void CopyNodeChildren(XmlNodeRef& xmlNode, IUiAnimNode* pAnimNode); void NotifyTrackEvent(IUiTrackEventListener::ETrackEventReason reason, - const char* event, const char* param = NULL); + const char* event, const char* param = nullptr); // Create a new animation node. IUiAnimNode* CreateNodeInternal(EUiAnimNodeType nodeType, uint32 nNodeId = -1); diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp index df714d7143..de8a9d2146 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXJointBenchmarks.cpp @@ -183,7 +183,6 @@ namespace PhysX::Benchmarks class PhysXJointBenchmarkFixture : public PhysXBaseBenchmarkFixture { - public: void internalSetUp() { PhysXBaseBenchmarkFixture::SetUpInternal(); @@ -194,7 +193,6 @@ namespace PhysX::Benchmarks PhysXBaseBenchmarkFixture::TearDownInternal(); } - protected: public: void SetUp(const benchmark::State&) override { From db63dcbcd9c6b1758870ed20f91e869394e06ae8 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Sep 2021 17:57:42 -0700 Subject: [PATCH 107/274] Refresh rate driven rendering tick logic (#3375) * Implement sync interval and refresh rate API for RenderViewportWidget Signed-off-by: nvsickle * Measure actual frame timings in the viewport info overlay. Takes the median of the sum of (frame end - frame begin) to provide more a more representative view of when frames begin and end. Note: Until VSync is internally supported by the event loop, this will produce nearly identical frame timings as the frame will spend as much time as needed synchronously waiting on a vblank. Signed-off-by: nvsickle * Make frame timing per-pipeline, wire up refresh rate info to ViewportContext Signed-off-by: nvsickle * POC: Frame limit pipeline rendering Signed-off-by: nvsickle * Switch Editor tick to every 0ms to allow better tick accumulation behavior Signed-off-by: nvsickle * Move RPISystemComponent to the tick bus, remove tick accumulation logic Signed-off-by: nvsickle * Add `AddToRenderTickAtInterval` to RenderPipeline API This allows a pipeline to update at a set cadence, instead of rendering every frame or being directly told when to tick. Signed-off-by: nvsickle * Make ViewportContext enforce a target framerate -Adds GetFpsLimit/SetFpsLimit for actively limiting FPS -Calculates a render tick interval based on vsync and the vps limit and updates the current pipeline Signed-off-by: nvsickle * Add r_fps_limit and ed_inactive_viewport_fps_limit cvars Signed-off-by: nvsickle * Quick null check from a crash I bumped into Signed-off-by: nvsickle * Fix off-by-one on FPS calculation (shouldn't include the not-yet-rendered frame) Signed-off-by: nvsickle * Clarify frame time begin initialization Signed-off-by: nvsickle * Fix TrackView export. Signed-off-by: nvsickle * Address some reviewer feedback, revert RPISystem API change, fix CPU profiler. Signed-off-by: nvsickle * Add g_simulation_tick_rate Signed-off-by: nvsickle * Address review feedback, make frame limit updates event driven Signed-off-by: nvsickle * Remove timestamp update from ComponentApplication::Tick Signed-off-by: nvsickle --- Code/Editor/Core/QtEditorApplication.cpp | 2 +- .../TrackView/SequenceBatchRenderDialog.cpp | 10 + .../AzCore/Component/ComponentApplication.cpp | 19 ++ .../AzCore/AzCore/Component/TickBus.h | 2 + .../Atom/Bootstrap/BootstrapNotificationBus.h | 3 +- .../Atom/Bootstrap/BootstrapRequestBus.h | 2 + .../Code/Source/BootstrapSystemComponent.cpp | 39 +-- .../Code/Source/BootstrapSystemComponent.h | 2 + .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 2 +- .../Include/Atom/RPI.Public/RenderPipeline.h | 43 +++- .../Code/Include/Atom/RPI.Public/SceneBus.h | 3 + .../Include/Atom/RPI.Public/ViewportContext.h | 49 +++- .../Atom/RPI.Public/ViewportContextBus.h | 8 +- .../Source/RPI.Private/RPISystemComponent.cpp | 18 +- .../Source/RPI.Private/RPISystemComponent.h | 7 +- .../RPI/Code/Source/RPI.Public/Pass/Pass.cpp | 7 +- .../Code/Source/RPI.Public/RenderPipeline.cpp | 44 +++- .../Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 21 +- Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp | 5 +- .../Source/RPI.Public/ViewportContext.cpp | 142 +++++++++-- .../Viewport/RenderViewportWidget.h | 24 ++ .../RenderViewportWidgetNotificationBus.h | 35 +++ .../Source/Viewport/RenderViewportWidget.cpp | 223 ++++++++++++++---- .../Code/atomtoolsframework_files.cmake | 1 + ...AtomViewportDisplayInfoSystemComponent.cpp | 31 ++- .../AtomViewportDisplayInfoSystemComponent.h | 15 +- 26 files changed, 633 insertions(+), 124 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h diff --git a/Code/Editor/Core/QtEditorApplication.cpp b/Code/Editor/Core/QtEditorApplication.cpp index a4aab24be4..66ed42af8f 100644 --- a/Code/Editor/Core/QtEditorApplication.cpp +++ b/Code/Editor/Core/QtEditorApplication.cpp @@ -44,7 +44,7 @@ enum { // in milliseconds GameModeIdleFrequency = 0, - EditorModeIdleFrequency = 1, + EditorModeIdleFrequency = 0, InactiveModeFrequency = 10, UninitializedFrequency = 9999, }; diff --git a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp index b510315995..6b3f1c2633 100644 --- a/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp +++ b/Code/Editor/TrackView/SequenceBatchRenderDialog.cpp @@ -36,6 +36,9 @@ #include "CryEdit.h" #include "Viewport.h" +// Atom Renderer +#include + AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING @@ -1234,6 +1237,13 @@ void CSequenceBatchRenderDialog::OnKickIdleTimout() { componentApplication->TickSystem(); } + + // Directly tick the renderer, as it's no longer part of the system tick + if (auto rpiSystem = AZ::RPI::RPISystemInterface::Get()) + { + rpiSystem->SimulationTick(); + rpiSystem->RenderTick(); + } } } diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index c76156c006..04a76b0f8e 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -74,6 +74,8 @@ #include #include +AZ_CVAR(float, g_simulation_tick_rate, 0, nullptr, AZ::ConsoleFunctorFlags::Null, "The rate at which the game simulation tick loop runs, or 0 for as fast as possible"); + static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments) { if (arguments.empty()) @@ -1392,6 +1394,23 @@ namespace AZ AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick"); EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now)); } + + // If tick rate limiting is on, ensure (1 / g_simulation_tick_rate) ms has elapsed since the last frame, + // sleeping if there's still time remaining. + if (g_simulation_tick_rate > 0.f) + { + now = AZStd::chrono::system_clock::now(); + + // Work in microsecond durations here as that's the native measurement time for time_point + constexpr float microsecondsPerSecond = 1000.f * 1000.f; + const AZStd::chrono::microseconds timeBudgetPerTick(static_cast(microsecondsPerSecond / g_simulation_tick_rate)); + AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now; + + if (timeUntilNextTick.count() > 0) + { + AZStd::this_thread::sleep_for(timeUntilNextTick); + } + } } } diff --git a/Code/Framework/AzCore/AzCore/Component/TickBus.h b/Code/Framework/AzCore/AzCore/Component/TickBus.h index e65efb93f2..966a3c303e 100644 --- a/Code/Framework/AzCore/AzCore/Component/TickBus.h +++ b/Code/Framework/AzCore/AzCore/Component/TickBus.h @@ -46,6 +46,8 @@ namespace AZ TICK_PRE_RENDER = 750, ///< Suggested tick handler position to update render-related data. + TICK_RENDER = 800, ///< Suggested tick handler position for rendering. + TICK_DEFAULT = 1000, ///< Default tick handler position when the handler is constructed. TICK_UI = 2000, ///< Suggested tick handler position for UI components. diff --git a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h index e40bf39923..f4ce51fc02 100644 --- a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h +++ b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapNotificationBus.h @@ -56,7 +56,8 @@ namespace AZ ////////////////////////////////////////////////////////////////////////// - virtual void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) = 0; + virtual void OnBootstrapSceneReady([[maybe_unused]]AZ::RPI::Scene* bootstrapScene){} + virtual void OnFrameRateLimitChanged([[maybe_unused]]float fpsLimit){} }; using NotificationBus = AZ::EBus; } // namespace Bootstrap diff --git a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h index 21cc91420b..fbf3bad935 100644 --- a/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h +++ b/Gems/Atom/Bootstrap/Code/Include/Atom/Bootstrap/BootstrapRequestBus.h @@ -23,6 +23,8 @@ namespace AZ::Render::Bootstrap virtual AZ::RPI::ScenePtr GetOrCreateAtomSceneFromAzScene(AzFramework::Scene* scene) = 0; virtual bool EnsureDefaultRenderPipelineInstalledForScene(AZ::RPI::ScenePtr scene, AZ::RPI::ViewportContextPtr viewportContext) = 0; + virtual float GetFrameRateLimit() const = 0; + virtual void SetFrameRateLimit(float fpsLimit) = 0; protected: ~Request() = default; diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index d837988cfb..97faa7380f 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -41,7 +41,14 @@ #include #include +static void OnFrameRateLimitChanged(const float& fpsLimit) +{ + AZ::Render::Bootstrap::RequestBus::Broadcast( + &AZ::Render::Bootstrap::RequestBus::Events::SetFrameRateLimit, fpsLimit); +} + AZ_CVAR(AZ::CVarFixedString, r_default_pipeline_name, AZ_TRAIT_BOOTSTRAPSYSTEMCOMPONENT_PIPELINE_NAME, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Default Render pipeline name"); +AZ_CVAR(float, r_fps_limit, 0, OnFrameRateLimitChanged, AZ::ConsoleFunctorFlags::Null, "The maximum framerate to render at, or 0 for unlimited"); namespace AZ { @@ -342,6 +349,22 @@ namespace AZ return true; } + float BootstrapSystemComponent::GetFrameRateLimit() const + { + return r_fps_limit; + } + + void BootstrapSystemComponent::SetFrameRateLimit(float fpsLimit) + { + r_fps_limit = fpsLimit; + if (m_viewportContext) + { + m_viewportContext->SetFpsLimit(r_fps_limit); + } + Render::Bootstrap::NotificationBus::Broadcast( + &Render::Bootstrap::NotificationBus::Events::OnFrameRateLimitChanged, fpsLimit); + } + void BootstrapSystemComponent::CreateDefaultRenderPipeline() { EnsureDefaultRenderPipelineInstalledForScene(m_defaultScene, m_viewportContext); @@ -381,23 +404,11 @@ namespace AZ } void BootstrapSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time) - { - // Temp: When running in the launcher without the legacy renderer - // we need to call RenderTick on the viewport context each frame. - if (m_viewportContext) - { - AZ::ApplicationTypeQuery appType; - ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType); - if (appType.IsGame()) - { - m_viewportContext->RenderTick(); - } - } - } + { } int BootstrapSystemComponent::GetTickOrder() { - return TICK_LAST; + return TICK_PRE_RENDER; } void BootstrapSystemComponent::OnWindowClosed() diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h index 566d19b1a4..438c6cb236 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.h @@ -69,6 +69,8 @@ namespace AZ // Render::Bootstrap::RequestBus::Handler overrides ... AZ::RPI::ScenePtr GetOrCreateAtomSceneFromAzScene(AzFramework::Scene* scene) override; bool EnsureDefaultRenderPipelineInstalledForScene(AZ::RPI::ScenePtr scene, AZ::RPI::ViewportContextPtr viewportContext) override; + float GetFrameRateLimit() const override; + void SetFrameRateLimit(float fpsLimit) override; protected: // Component overrides ... diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index 8099fc3a32..e16b89b5cd 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -144,7 +144,7 @@ namespace AZ // Try to lock here, the shutdownMutex will only be contested when the CpuProfiler is shutting down. if (m_shutdownMutex.try_lock_shared()) { - if (m_enabled) + if (m_enabled && ms_threadLocalStorage != nullptr) { ms_threadLocalStorage->RegionStackPopBack(); } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h index 90389687de..cc25aa17c4 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h @@ -161,19 +161,25 @@ namespace AZ //! Add this RenderPipeline to RPI system's RenderTick and it will be rendered whenever //! the RPI system's RenderTick is called. - //! The RenderPipeline is rendered per RenderTick by default unless AddToRenderTickOnce() was called. + //! The RenderPipeline is rendered per RenderTick by default. void AddToRenderTick(); + //! Add this RenderPipeline to RPI system's RenderTick and it will be rendered every RenderTick + //! after the specified interval has elapsed since the last rendered frame. + //! @param renderInterval The desired time between rendered frames, in seconds. + void AddToRenderTickAtInterval(AZStd::chrono::duration renderInterval); + //! Disable render for this RenderPipeline void RemoveFromRenderTick(); ~RenderPipeline(); - + enum class RenderMode : uint8_t { - RenderEveryTick, // Render at each RPI system render tick - RenderOnce, // Render once in next RPI system render tick - NoRender // Render disabled. + RenderEveryTick, //!< Render at each RPI system render tick. + RenderAtTargetRate, //!< Render on RPI system render tick after a target refresh rate interval has passed. + RenderOnce, //!< Render once in next RPI system render tick. + NoRender //!< Render disabled. }; //! Get current render mode @@ -185,6 +191,12 @@ namespace AZ //! Get draw filter mask RHI::DrawFilterMask GetDrawFilterMask() const; + using FrameNotificationEvent = AZ::Event<>; + //! Notifies a listener when a frame is about to be prepared for render, before SRGs are bound. + void ConnectPrepareFrameHandler(FrameNotificationEvent::Handler& handler); + //! Notifies a listener when the rendering of a frame has finished + void ConnectEndFrameHandler(FrameNotificationEvent::Handler& handler); + private: RenderPipeline() = default; @@ -202,8 +214,11 @@ namespace AZ void OnAddedToScene(Scene* scene); void OnRemovedFromScene(Scene* scene); + // Called before this pipeline is about to be rendered and before SRGs are bound. + void OnPrepareFrame(); + // Called when this pipeline is about to be rendered - void OnStartFrame(const TickTimeInfo& tick); + void OnStartFrame(); // Called when the rendering of current frame is finished. void OnFrameEnd(); @@ -228,8 +243,14 @@ namespace AZ PipelineViewMap m_pipelineViewsByTag; - /// The system time when the last time this pipeline render was started - float m_lastRenderStartTime = 0; + // The system time when the last time this pipeline render was started + AZStd::chrono::system_clock::time_point m_lastRenderStartTime; + + // The current system time, as of OnPrepareFrame's execution. + AZStd::chrono::system_clock::time_point m_lastRenderRequestTime; + + // The target time between renders when m_renderMode is RenderMode::RenderAtTargetRate + AZStd::chrono::duration m_targetRefreshRate; // RenderPipeline's name id, it will be used to identify the render pipeline when it's added to a Scene RenderPipelineId m_nameId; @@ -259,7 +280,11 @@ namespace AZ RHI::DrawFilterTag m_drawFilterTag; // A mask to filter draw items submitted by passes of this render pipeline. // This mask is created from the value of m_drawFilterTag. - RHI::DrawFilterMask m_drawFilterMask = 0; + RHI::DrawFilterMask m_drawFilterMask = 0; + + // Events for notification on render state + FrameNotificationEvent m_prepareFrameEvent; + FrameNotificationEvent m_endFrameEvent; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h index ca531d2de6..748c470edf 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/SceneBus.h @@ -67,6 +67,9 @@ namespace AZ //! Notifies when the PrepareRender phase is ending virtual void OnEndPrepareRender() {} + + //! Notifies when the render tick for a given frame has finished. + virtual void OnFrameEnd() {} }; using SceneNotificationBus = AZ::EBus; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h index 966e6b3016..feed24a80d 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContext.h @@ -51,9 +51,21 @@ namespace AZ //! Sets the root scene associated with this viewport. //! This does not provide a default render pipeline, one must be provided to enable rendering. void SetRenderScene(ScenePtr scene); - //! Runs one simulation and render tick and renders a frame to this viewport's window. - //! @note This is likely to be replaced by a tick management system in the RPI. - void RenderTick(); + + //! Gets the maximum frame rate this viewport context's pipeline can render at, 0 for unlimited. + //! The target framerate for the pipeline will be determined by this frame limit and the + //! vsync settings for the current window. + float GetFpsLimit() const; + + //! Sets the maximum frame rate this viewport context's pipeline can render at, 0 for unlimited. + //! The target framerate for the pipeline will be determined by this frame limit and the + //! vsync settings for the current window. + void SetFpsLimit(float fpsLimit); + + //! Gets the target frame rate for this viewport context. + //! This returns the lowest of either the current VSync refresh rate + //! or 0 for an unlimited frame rate (if there's no FPS limit and vsync is off). + float GetTargetFrameRate() const; //! Gets the current name of this ViewportContext. //! This name is used to tie this ViewportContext to its View stack, and ViewportContexts may be @@ -74,19 +86,28 @@ namespace AZ //! \see AzFramework::WindowRequests::GetDpiScaleFactor float GetDpiScalingFactor() const; + //! Gets the current vsync interval, as a divisor of the current refresh rate. + //! A value of 0 indicates that vsync is disabled. + uint32_t GetVsyncInterval() const; + + //! Gets the current display refresh rate, in frames per second. + uint32_t GetRefreshRate() const; + // SceneNotificationBus interface overrides... //! Ensures our default view remains set when our scene's render pipelines are modified. void OnRenderPipelineAdded(RenderPipelinePtr pipeline) override; //! Ensures our default view remains set when our scene's render pipelines are modified. void OnRenderPipelineRemoved(RenderPipeline* pipeline) override; - //! OnBeginPrepareRender is forwarded to our RenderTick notification to allow subscribers to do rendering. - void OnBeginPrepareRender() override; // WindowNotificationBus interface overrides... //! Used to fire a notification when our window resizes. void OnWindowResized(uint32_t width, uint32_t height) override; //! Used to fire a notification when our window DPI changes. void OnDpiScaleFactorChanged(float dpiScaleFactor) override; + //! Used to fire a notification when our vsync interval changes. + void OnVsyncIntervalChanged(uint32_t interval) override; + //! Used to fire a notification when our refresh rate changes. + void OnRefreshRateChanged(uint32_t refreshRate) override; using SizeChangedEvent = AZ::Event; //! Notifies consumers when the viewport size has changed. @@ -98,6 +119,12 @@ namespace AZ //! Alternatively, connect to ViewportContextNotificationsBus and listen to ViewportContextNotifications::OnViewportDpiScalingChanged. void ConnectDpiScalingFactorChangedHandler(ScalarChangedEvent::Handler& handler); + using UintChangedEvent = AZ::Event; + //! Notifies consumers when the vsync interval has changed. + void ConnectVsyncIntervalChangedHandler(UintChangedEvent::Handler& handler); + //! Notifies consumers when the refresh rate has changed. + void ConnectRefreshRateChangedHandler(UintChangedEvent::Handler& handler); + using MatrixChangedEvent = AZ::Event; //! Notifies consumers when the view matrix has changed. void ConnectViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler); @@ -139,15 +166,24 @@ namespace AZ void SetDefaultView(ViewPtr view); // Ensures our render pipeline's default camera matches ours. void UpdatePipelineView(); + // Ensures our render pipeline refresh rate matches our refresh rate. + void UpdatePipelineRefreshRate(); + // Resets the current pipeline reference and ensures pipeline events are disconnected. + void ResetCurrentPipeline(); ScenePtr m_rootScene; WindowContextSharedPtr m_windowContext; ViewPtr m_defaultView; AzFramework::WindowSize m_viewportSize; float m_viewportDpiScaleFactor = 1.0f; + uint32_t m_vsyncInterval = 1; + uint32_t m_refreshRate = 60; + float m_fpsLimit = 0.f; SizeChangedEvent m_sizeChangedEvent; ScalarChangedEvent m_dpiScalingFactorChangedEvent; + UintChangedEvent m_vsyncIntervalChangedEvent; + UintChangedEvent m_refreshRateChangedEvent; MatrixChangedEvent m_viewMatrixChangedEvent; MatrixChangedEvent::Handler m_onViewMatrixChangedHandler; MatrixChangedEvent m_projectionMatrixChangedEvent; @@ -157,6 +193,9 @@ namespace AZ ViewChangedEvent m_defaultViewChangedEvent; ViewportIdEvent m_aboutToBeDestroyedEvent; + AZ::Event<>::Handler m_prepareFrameHandler; + AZ::Event<>::Handler m_endFrameHandler; + ViewportContextManager* m_manager; RenderPipelinePtr m_currentPipeline; Name m_name; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h index 0b53172ba2..fa13a3987a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/ViewportContextBus.h @@ -110,11 +110,13 @@ namespace AZ virtual void OnViewportSizeChanged(AzFramework::WindowSize size){AZ_UNUSED(size);} //! Called when the window DPI scaling changes for a given viewport context. virtual void OnViewportDpiScalingChanged(float dpiScale){AZ_UNUSED(dpiScale);} - //! Called when the active view for a given viewport context name changes. + //! Called when the active view changes for a given viewport context. virtual void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view){AZ_UNUSED(view);} //! Called when the viewport is to be rendered. - //! Add draws to this functions if they only need to be rendered to this viewport. - virtual void OnRenderTick(){}; + //! Add draws to this function if they only need to be rendered to this viewport. + virtual void OnRenderTick(){} + //! Called when the viewport finishes rendering a frame. + virtual void OnFrameEnd(){} protected: ~ViewportContextNotifications() = default; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp index 2567d221e5..789d43712e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.cpp @@ -14,6 +14,9 @@ #include #include +#include +#include +#include #include #include @@ -93,20 +96,29 @@ namespace AZ } m_rpiSystem.Initialize(m_rpiDescriptor); - AZ::SystemTickBus::Handler::BusConnect(); + AZ::TickBus::Handler::BusConnect(); } void RPISystemComponent::Deactivate() { - AZ::SystemTickBus::Handler::BusDisconnect(); + AZ::TickBus::Handler::BusDisconnect(); m_rpiSystem.Shutdown(); } - void RPISystemComponent::OnSystemTick() + void RPISystemComponent::OnTick([[maybe_unused]]float deltaTime, [[maybe_unused]]ScriptTimePoint time) { + if (deltaTime == 0.f) + { + return; + } + m_rpiSystem.SimulationTick(); m_rpiSystem.RenderTick(); } + int RPISystemComponent::GetTickOrder() + { + return AZ::ComponentTickBus::TICK_RENDER; + } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h index e0a128c3f1..7933e1581c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h +++ b/Gems/Atom/RPI/Code/Source/RPI.Private/RPISystemComponent.h @@ -32,7 +32,7 @@ namespace AZ */ class RPISystemComponent final : public AZ::Component - , public AZ::SystemTickBus::Handler + , private AZ::TickBus::Handler { public: AZ_COMPONENT(RPISystemComponent, "{83E301F3-7A0C-4099-B530-9342B91B1BC0}"); @@ -50,8 +50,9 @@ namespace AZ private: RPISystemComponent(const RPISystemComponent&) = delete; - // SystemTickBus overrides... - void OnSystemTick() override; + // TickBus overrides... + void OnTick(float deltaTime, ScriptTimePoint time) override; + int GetTickOrder() override; RPISystem m_rpiSystem; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index a8d94e9a91..c5e871697b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -93,8 +93,11 @@ namespace AZ void Pass::SetEnabled(bool enabled) { - m_flags.m_enabled = enabled; - OnHierarchyChange(); + if (m_flags.m_enabled != enabled) + { + m_flags.m_enabled = enabled; + OnHierarchyChange(); + } } bool Pass::IsEnabled() const diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp index 6d974a074f..7f0ab9c8aa 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp @@ -301,6 +301,26 @@ namespace AZ m_drawFilterMask = 0; } + void RenderPipeline::OnPrepareFrame() + { + m_lastRenderRequestTime = AZStd::chrono::system_clock::now(); + + // If we're attempting to render at a target interval, check to see if we're within + // 1ms of that interval, enabling rendering only if we are. + if (m_renderMode == RenderMode::RenderAtTargetRate) + { + constexpr AZStd::chrono::duration updateThresholdMs(0.001f); + const bool shouldRender = + m_lastRenderRequestTime - m_lastRenderStartTime + updateThresholdMs >= m_targetRefreshRate; + m_rootPass->SetEnabled(shouldRender); + } + + if (NeedsRender()) + { + m_prepareFrameEvent.Signal(); + } + } + void RenderPipeline::OnPassModified() { if (m_needsPassRecreate) @@ -375,11 +395,11 @@ namespace AZ m_scene->RemoveRenderPipeline(m_nameId); } - void RenderPipeline::OnStartFrame(const TickTimeInfo& tick) + void RenderPipeline::OnStartFrame() { AZ_PROFILE_FUNCTION(RPI); - m_lastRenderStartTime = tick.m_currentGameTime; + m_lastRenderStartTime = m_lastRenderRequestTime; OnPassModified(); @@ -407,6 +427,7 @@ namespace AZ { RemoveFromRenderTick(); } + m_endFrameEvent.Signal(); } void RenderPipeline::CollectPersistentViews(AZStd::map& outViewMasks) const @@ -489,6 +510,13 @@ namespace AZ m_renderMode = RenderMode::RenderEveryTick; } + void RenderPipeline::AddToRenderTickAtInterval(AZStd::chrono::duration renderInterval) + { + m_rootPass->SetEnabled(false); + m_renderMode = RenderMode::RenderAtTargetRate; + m_targetRefreshRate = renderInterval; + } + void RenderPipeline::RemoveFromRenderTick() { m_renderMode = RenderMode::NoRender; @@ -502,7 +530,7 @@ namespace AZ bool RenderPipeline::NeedsRender() const { - return m_renderMode != RenderMode::NoRender; + return m_rootPass->IsEnabled(); } RHI::DrawFilterTag RenderPipeline::GetDrawFilterTag() const @@ -515,6 +543,16 @@ namespace AZ return m_drawFilterMask; } + void RenderPipeline::ConnectPrepareFrameHandler(FrameNotificationEvent::Handler& handler) + { + handler.Connect(m_prepareFrameEvent); + } + + void RenderPipeline::ConnectEndFrameHandler(FrameNotificationEvent::Handler& handler) + { + handler.Connect(m_endFrameEvent); + } + void RenderPipeline::SetDrawFilterTag(RHI::DrawFilterTag tag) { m_drawFilterTag = tag; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index 0b0481b960..9fa49f7f2a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -420,7 +420,7 @@ namespace AZ } } - void Scene::PrepareRender(const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy) + void Scene::PrepareRender([[maybe_unused]]const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy) { AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: PrepareRender"); @@ -432,20 +432,27 @@ namespace AZ SceneNotificationBus::Event(GetId(), &SceneNotification::OnBeginPrepareRender); - // Get active pipelines which need to be rendered and notify them frame started + // Get active pipelines which need to be rendered and notify them of an impending frame. AZStd::vector activePipelines; { - AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene: OnStartFrame"); + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene: OnPrepareFrame"); for (auto& pipeline : m_pipelines) { + pipeline->OnPrepareFrame(); if (pipeline->NeedsRender()) { activePipelines.push_back(pipeline); - pipeline->OnStartFrame(tickInfo); } } } + // Get active pipelines which need to be rendered and notify them frame started + for (const auto& pipeline : activePipelines) + { + AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene: OnStartFrame"); + pipeline->OnStartFrame(); + } + // Return if there is no active render pipeline if (activePipelines.empty()) { @@ -587,10 +594,12 @@ namespace AZ void Scene::OnFrameEnd() { AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: OnFrameEnd"); + bool didRender = false; for (auto& pipeline : m_pipelines) { if (pipeline->NeedsRender()) { + didRender = true; pipeline->OnFrameEnd(); } } @@ -598,6 +607,10 @@ namespace AZ { fp->OnRenderEnd(); } + if (didRender) + { + SceneNotificationBus::Event(GetId(), &SceneNotification::OnFrameEnd); + } } void Scene::UpdateSrgs() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp index b07728938f..bdb3ea8899 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/View.cpp @@ -241,7 +241,10 @@ namespace AZ { AZ_PROFILE_FUNCTION(RPI); m_drawListContext.FinalizeLists(); - SortFinalizedDrawLists(); + if (m_passesByDrawList) + { + SortFinalizedDrawLists(); + } } void View::SortFinalizedDrawLists() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp index 77114e5cf5..3dcbae2fb9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/ViewportContext.cpp @@ -25,14 +25,13 @@ namespace AZ , m_viewportSize(1, 1) { m_windowContext->Initialize(device, nativeWindow); - AzFramework::WindowRequestBus::EventResult( - m_viewportSize, - nativeWindow, - &AzFramework::WindowRequestBus::Events::GetClientAreaSize); - AzFramework::WindowRequestBus::EventResult( - m_viewportDpiScaleFactor, - nativeWindow, - &AzFramework::WindowRequestBus::Events::GetDpiScaleFactor); + AzFramework::WindowRequestBus::Event(nativeWindow, [this](AzFramework::WindowRequestBus::Events* window) + { + m_viewportSize = window->GetClientAreaSize(); + m_viewportDpiScaleFactor = window->GetDpiScaleFactor(); + m_vsyncInterval = window->GetSyncInterval(); + m_refreshRate = window->GetDisplayRefreshRate(); + }); AzFramework::WindowNotificationBus::Handler::BusConnect(nativeWindow); AzFramework::ViewportRequestBus::Handler::BusConnect(id); @@ -46,6 +45,20 @@ namespace AZ m_viewMatrixChangedEvent.Signal(matrix); }); + m_prepareFrameHandler = RenderPipeline::FrameNotificationEvent::Handler( + [this]() + { + ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnRenderTick); + ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnRenderTick); + }); + + m_endFrameHandler = RenderPipeline::FrameNotificationEvent::Handler( + [this]() + { + ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnFrameEnd); + ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnFrameEnd); + }); + SetRenderScene(renderScene); } @@ -111,26 +124,38 @@ namespace AZ { SceneNotificationBus::Handler::BusConnect(m_rootScene->GetId()); } - m_currentPipeline.reset(); + ResetCurrentPipeline(); UpdatePipelineView(); + UpdatePipelineRefreshRate(); } m_sceneChangedEvent.Signal(scene); } - void ViewportContext::RenderTick() + float ViewportContext::GetFpsLimit() const { - // add the current pipeline to next render tick if it's not already added. - if (m_currentPipeline && m_currentPipeline->GetRenderMode() != RenderPipeline::RenderMode::RenderOnce) - { - m_currentPipeline->AddToRenderTickOnce(); - } + return m_fpsLimit; + } + + void ViewportContext::SetFpsLimit(float fpsLimit) + { + m_fpsLimit = fpsLimit; + UpdatePipelineRefreshRate(); } - void ViewportContext::OnBeginPrepareRender() + float ViewportContext::GetTargetFrameRate() const { - ViewportContextNotificationBus::Event(GetName(), &ViewportContextNotificationBus::Events::OnRenderTick); - ViewportContextIdNotificationBus::Event(GetId(), &ViewportContextIdNotificationBus::Events::OnRenderTick); + float targetFrameRate = GetFpsLimit(); + const AZ::u32 vsyncInterval = GetVsyncInterval(); + if (vsyncInterval != 0) + { + const float vsyncFrameRate = static_cast(GetRefreshRate()) / static_cast(vsyncInterval); + if (targetFrameRate == 0.f || vsyncFrameRate < targetFrameRate) + { + targetFrameRate = vsyncFrameRate; + } + } + return targetFrameRate; } AZ::Name ViewportContext::GetName() const @@ -158,6 +183,16 @@ namespace AZ return m_viewportDpiScaleFactor; } + uint32_t ViewportContext::GetVsyncInterval() const + { + return m_vsyncInterval; + } + + uint32_t ViewportContext::GetRefreshRate() const + { + return m_refreshRate; + } + void ViewportContext::ConnectSizeChangedHandler(SizeChangedEvent::Handler& handler) { handler.Connect(m_sizeChangedEvent); @@ -168,6 +203,16 @@ namespace AZ handler.Connect(m_dpiScalingFactorChangedEvent); } + void ViewportContext::ConnectVsyncIntervalChangedHandler(UintChangedEvent::Handler& handler) + { + handler.Connect(m_vsyncIntervalChangedEvent); + } + + void ViewportContext::ConnectRefreshRateChangedHandler(UintChangedEvent::Handler& handler) + { + handler.Connect(m_refreshRateChangedEvent); + } + void ViewportContext::ConnectViewMatrixChangedHandler(MatrixChangedEvent::Handler& handler) { handler.Connect(m_viewMatrixChangedEvent); @@ -263,12 +308,43 @@ namespace AZ m_currentPipelineChangedEvent.Signal(m_currentPipeline); } - if (auto pipeline = GetCurrentPipeline()) + if (m_currentPipeline) { - pipeline->SetDefaultView(m_defaultView); + if (!m_prepareFrameHandler.IsConnected()) + { + m_currentPipeline->ConnectPrepareFrameHandler(m_prepareFrameHandler); + m_currentPipeline->ConnectEndFrameHandler(m_endFrameHandler); + } + m_currentPipeline->SetDefaultView(m_defaultView); + } + } + + void ViewportContext::UpdatePipelineRefreshRate() + { + if (!m_currentPipeline) + { + return; + } + + const float refreshRate = GetTargetFrameRate(); + // If we have a truly unlimited framerate, just render every tick + if (refreshRate == 0.f) + { + m_currentPipeline->AddToRenderTick(); + } + else + { + m_currentPipeline->AddToRenderTickAtInterval(AZStd::chrono::duration(1.f / refreshRate)); } } + void ViewportContext::ResetCurrentPipeline() + { + m_prepareFrameHandler.Disconnect(); + m_endFrameHandler.Disconnect(); + m_currentPipeline.reset(); + } + RenderPipelinePtr ViewportContext::GetCurrentPipeline() { return m_currentPipeline; @@ -281,8 +357,9 @@ namespace AZ // in the event prioritization is added later if (pipeline->GetWindowHandle() == m_windowContext->GetWindowHandle()) { - m_currentPipeline.reset(); + ResetCurrentPipeline(); UpdatePipelineView(); + UpdatePipelineRefreshRate(); } } @@ -290,8 +367,9 @@ namespace AZ { if (m_currentPipeline.get() == pipeline) { - m_currentPipeline.reset(); + ResetCurrentPipeline(); UpdatePipelineView(); + UpdatePipelineRefreshRate(); } } @@ -305,10 +383,30 @@ namespace AZ } } + void ViewportContext::OnRefreshRateChanged(uint32_t refreshRate) + { + if (m_refreshRate != refreshRate) + { + m_refreshRate = refreshRate; + m_refreshRateChangedEvent.Signal(m_refreshRate); + UpdatePipelineRefreshRate(); + } + } + void ViewportContext::OnDpiScaleFactorChanged(float dpiScaleFactor) { m_viewportDpiScaleFactor = dpiScaleFactor; m_dpiScalingFactorChangedEvent.Signal(dpiScaleFactor); } + + void ViewportContext::OnVsyncIntervalChanged(uint32_t interval) + { + if (m_vsyncInterval != interval) + { + m_vsyncInterval = interval; + m_vsyncIntervalChangedEvent.Signal(m_vsyncInterval); + UpdatePipelineRefreshRate(); + } + } } // namespace RPI } // namespace AZ 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 4210c82921..60ddf33cf7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,8 @@ #include #include #include +#include +#include namespace AtomToolsFramework { @@ -35,6 +38,8 @@ namespace AtomToolsFramework , public AzFramework::WindowRequestBus::Handler , protected AzFramework::InputChannelEventListener , protected AZ::TickBus::Handler + , protected AZ::Render::Bootstrap::NotificationBus::Handler + , protected AtomToolsFramework::RenderViewportWidgetNotificationBus::Handler { public: //! Creates a RenderViewportWidget. @@ -121,6 +126,7 @@ namespace AtomToolsFramework // AZ::TickBus::Handler ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + int GetTickOrder() override; // QWidget ... void resizeEvent(QResizeEvent *event) override; @@ -128,9 +134,21 @@ namespace AtomToolsFramework void enterEvent(QEvent* event) override; void leaveEvent(QEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override; + void focusInEvent(QFocusEvent* event) override; + + // AZ::Render::Bootstrap::NotificationBus::Handler ... + void OnFrameRateLimitChanged(float fpsLimit) override; + + // AtomToolsFramework::RenderViewportWidgetNotificationBus::Handler ... + void OnInactiveViewportFrameRateChanged(float fpsLimit) override; private: + AzFramework::NativeWindowHandle GetNativeWindowHandle() const; + void UpdateFrameRate(); + + void SetScreen(QScreen* screen); void SendWindowResizeEvent(); + void NotifyUpdateRefreshRate(); // The underlying ViewportContext, our entry-point to the Atom RPI. AZ::RPI::ViewportContextPtr m_viewportContext; @@ -153,5 +171,11 @@ namespace AtomToolsFramework AZ::ScriptTimePoint m_time; // Maps our internal Qt events into AzFramework InputChannels for our ViewportControllerList. AzToolsFramework::QtEventToAzInputMapper* m_inputChannelMapper = nullptr; + // Stores our current screen, used for tracking the current refresh rate. + QScreen* m_screen = nullptr; + // Stores the last RenderViewportWidget that has received user focus. + // This is used for optional framerate throtting for "inactive" viewports via the + // ed_inactive_viewport_fps_limit CVAR. + AZ::EnvironmentVariable m_lastFocusedViewport; }; } //namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h new file mode 100644 index 0000000000..0563bd6bf2 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace AtomToolsFramework +{ + //! Provides an interface for providing notifications specific to RenderViewportWidget. + //! @note Most behaviors in RenderViewportWidget are handled by its underyling + //! ViewportContext, this bus is specifically for functionality exclusive to the + //! Qt layer provided by RenderViewportWidget. + class RenderViewportWidgetNotifications : public AZ::EBusTraits + { + public: + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + + //! Triggered when the idle frame rate limit for inactive viewports changed. + //! Controlled by the ed_inactive_viewport_fps_limit CVAR. + //! Active viewports are controlled by the r_fps_limit CVAR. + virtual void OnInactiveViewportFrameRateChanged([[maybe_unused]]float fpsLimit){} + + protected: + ~RenderViewportWidgetNotifications() = default; + }; + + using RenderViewportWidgetNotificationBus = AZ::EBus; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 027ac80151..4446e11231 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -6,23 +6,42 @@ * */ -#include +#include +#include +#include #include #include -#include +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include #include -#include +#include #include +#include +#include +#include + +static void OnInactiveViewportFrameRateChanged(const float& fpsLimit) +{ + AtomToolsFramework::RenderViewportWidgetNotificationBus::Broadcast( + &AtomToolsFramework::RenderViewportWidgetNotificationBus::Events::OnInactiveViewportFrameRateChanged, fpsLimit); +} + +AZ_CVAR( + float, + ed_inactive_viewport_fps_limit, + 0, + OnInactiveViewportFrameRateChanged, + AZ::ConsoleFunctorFlags::Null, + "The maximum framerate to render viewports that don't have focus at"); + +static constexpr const char* LastFocusedViewportVariableName = "AtomToolsFramework::RenderViewportWidget::LastFocusedViewport"; namespace AtomToolsFramework { @@ -30,6 +49,12 @@ namespace AtomToolsFramework : QWidget(parent) , AzFramework::InputChannelEventListener(AzFramework::InputChannelEventListener::GetPriorityDefault()) { + m_lastFocusedViewport = AZ::Environment::FindVariable(LastFocusedViewportVariableName); + if (!m_lastFocusedViewport) + { + m_lastFocusedViewport = AZ::Environment::CreateVariable(LastFocusedViewportVariableName, nullptr); + } + if (shouldInitializeViewportContext) { InitializeViewportContext(); @@ -38,13 +63,24 @@ namespace AtomToolsFramework setUpdatesEnabled(false); setFocusPolicy(Qt::FocusPolicy::WheelFocus); setMouseTracking(true); + + // Wait a frame for our window handle to be constructed, then wire up our screen change signals. + QTimer::singleShot( + 0, + [this]() + { + QObject::connect(windowHandle(), &QWindow::screenChanged, this, &RenderViewportWidget::SetScreen); + }); + SetScreen(screen()); } bool RenderViewportWidget::InitializeViewportContext(AzFramework::ViewportId id) { if (m_viewportContext != nullptr) { - AZ_Assert(id == AzFramework::InvalidViewportId || m_viewportContext->GetId() == id, "Attempted to reinitialize RenderViewportWidget with a different ID"); + AZ_Assert( + id == AzFramework::InvalidViewportId || m_viewportContext->GetId() == id, + "Attempted to reinitialize RenderViewportWidget with a different ID"); return true; } @@ -59,7 +95,7 @@ namespace AtomToolsFramework // Before we do anything else, we must create a ViewportContext which will give us a ViewportId if we didn't manually specify one. AZ::RPI::ViewportContextRequestsInterface::CreationParameters params; params.device = AZ::RHI::RHISystemInterface::Get()->GetDevice(); - params.windowHandle = reinterpret_cast(winId()); + params.windowHandle = GetNativeWindowHandle(); params.id = id; AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle); m_viewportContext = viewportContextManager->CreateViewportContext(AZ::Name(), params); @@ -80,29 +116,46 @@ namespace AtomToolsFramework AzFramework::InputChannelEventListener::Connect(); AZ::TickBus::Handler::BusConnect(); AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle); + AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); + AtomToolsFramework::RenderViewportWidgetNotificationBus::Handler::BusConnect(); m_inputChannelMapper = new AzToolsFramework::QtEventToAzInputMapper(this, id); // Forward input events to our controller list. - QObject::connect(m_inputChannelMapper, &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, this, + QObject::connect( + m_inputChannelMapper, &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, this, [this](const AzFramework::InputChannel* inputChannel, QEvent* event) - { - AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); - if (m_controllerList->HandleInputChannelEvent(AzFramework::ViewportControllerInputEvent{GetId(), windowId, *inputChannel})) { - // If the controller handled the input event, mark the event as accepted so it doesn't continue to propagate. - if (event) + const AzFramework::NativeWindowHandle windowId = GetNativeWindowHandle(); + if (m_controllerList->HandleInputChannelEvent( + AzFramework::ViewportControllerInputEvent{ GetId(), windowId, *inputChannel })) { - event->setAccepted(true); + // If the controller handled the input event, mark the event as accepted so it doesn't continue to propagate. + if (event) + { + event->setAccepted(true); + } } - } - }); + }); + + // Update our target frame rate. If we're the only viewport, become active. + if (m_lastFocusedViewport.Get() == nullptr) + { + m_lastFocusedViewport.Set(this); + } + UpdateFrameRate(); + return true; } RenderViewportWidget::~RenderViewportWidget() { + if (m_lastFocusedViewport.Get() == this) + { + m_lastFocusedViewport.Set(nullptr); + } + AzFramework::WindowRequestBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); AzFramework::InputChannelEventListener::Disconnect(); @@ -181,17 +234,22 @@ namespace AtomToolsFramework bool shouldConsumeEvent = true; - AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); - const bool eventHandled = m_controllerList->HandleInputChannelEvent({GetId(), windowId, inputChannel}); + const bool eventHandled = m_controllerList->HandleInputChannelEvent({ GetId(), GetNativeWindowHandle(), inputChannel }); - // If our controllers handled the event and it's one we can safely consume (i.e. it's not an Ended event that other viewports might need), consume it. + // If our controllers handled the event and it's one we can safely consume (i.e. it's not an Ended event that other viewports might + // need), consume it. return eventHandled && shouldConsumeEvent; } - void RenderViewportWidget::OnTick([[maybe_unused]]float deltaTime, AZ::ScriptTimePoint time) + void RenderViewportWidget::OnTick([[maybe_unused]] float deltaTime, AZ::ScriptTimePoint time) { m_time = time; - m_controllerList->UpdateViewport({GetId(), AzFramework::FloatSeconds(deltaTime), m_time}); + m_controllerList->UpdateViewport({ GetId(), AzFramework::FloatSeconds(deltaTime), m_time }); + } + + int RenderViewportWidget::GetTickOrder() + { + return AZ::ComponentTickBus::TICK_PRE_RENDER; } void RenderViewportWidget::resizeEvent([[maybe_unused]] QResizeEvent* event) @@ -236,6 +294,75 @@ namespace AtomToolsFramework m_mousePosition = event->localPos(); } + void RenderViewportWidget::focusInEvent([[maybe_unused]] QFocusEvent* event) + { + RenderViewportWidget* lastFocusedViewport = m_lastFocusedViewport.Get(); + if (lastFocusedViewport == this) + { + return; + } + + RenderViewportWidget* previousFocusWidget = lastFocusedViewport; + m_lastFocusedViewport.Set(this); + + // Ensure this viewport and whatever viewport last had focus (if any) respect + // the active / inactive viewport frame rate settings. + UpdateFrameRate(); + if (previousFocusWidget != nullptr) + { + previousFocusWidget->UpdateFrameRate(); + } + } + + void RenderViewportWidget::OnFrameRateLimitChanged([[maybe_unused]] float fpsLimit) + { + UpdateFrameRate(); + } + + void RenderViewportWidget::OnInactiveViewportFrameRateChanged([[maybe_unused]] float fpsLimit) + { + UpdateFrameRate(); + } + + AzFramework::NativeWindowHandle RenderViewportWidget::GetNativeWindowHandle() const + { + return reinterpret_cast(winId()); + } + + void RenderViewportWidget::UpdateFrameRate() + { + if (ed_inactive_viewport_fps_limit > 0.f && m_lastFocusedViewport.Get() != this) + { + m_viewportContext->SetFpsLimit(ed_inactive_viewport_fps_limit); + } + else + { + float fpsLimit = 0.f; + AZ::Render::Bootstrap::RequestBus::BroadcastResult(fpsLimit, &AZ::Render::Bootstrap::RequestBus::Events::GetFrameRateLimit); + m_viewportContext->SetFpsLimit(fpsLimit); + } + } + + void RenderViewportWidget::SetScreen(QScreen* screen) + { + if (m_screen != screen) + { + if (m_screen) + { + QObject::disconnect(m_screen, &QScreen::refreshRateChanged, this, &RenderViewportWidget::NotifyUpdateRefreshRate); + } + + if (screen) + { + QObject::connect(m_screen, &QScreen::refreshRateChanged, this, &RenderViewportWidget::NotifyUpdateRefreshRate); + } + + NotifyUpdateRefreshRate(); + + m_screen = screen; + } + } + void RenderViewportWidget::SendWindowResizeEvent() { // Scale the size by the DPI of the platform to @@ -243,11 +370,17 @@ namespace AtomToolsFramework const QSize uiWindowSize = size(); const QSize windowSize = uiWindowSize * devicePixelRatioF(); - const AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); - AzFramework::WindowNotificationBus::Event(windowId, &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); + AzFramework::WindowNotificationBus::Event( + GetNativeWindowHandle(), &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); m_windowResizedEvent = false; } + void RenderViewportWidget::NotifyUpdateRefreshRate() + { + AzFramework::WindowNotificationBus::Event( + GetNativeWindowHandle(), &AzFramework::WindowNotificationBus::Events::OnRefreshRateChanged, GetDisplayRefreshRate()); + } + AZ::Name RenderViewportWidget::GetCurrentContextName() const { return m_viewportContext->GetName(); @@ -303,9 +436,7 @@ namespace AtomToolsFramework // Build camera state from Atom camera transforms AzFramework::CameraState cameraState = AzFramework::CreateCameraFromWorldFromViewMatrix( - currentView->GetViewToWorldMatrix(), - AZ::Vector2{aznumeric_cast(width()), aznumeric_cast(height())} - ); + currentView->GetViewToWorldMatrix(), AZ::Vector2{ aznumeric_cast(width()), aznumeric_cast(height()) }); AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, currentView->GetViewToClipMatrix()); // Convert from Z-up @@ -317,8 +448,7 @@ namespace AtomToolsFramework AzFramework::ScreenPoint RenderViewportWidget::ViewportWorldToScreen(const AZ::Vector3& worldPosition) { - if (AZ::RPI::ViewPtr currentView = m_viewportContext->GetDefaultView(); - currentView == nullptr) + if (AZ::RPI::ViewPtr currentView = m_viewportContext->GetDefaultView(); currentView == nullptr) { return AzFramework::ScreenPoint(0, 0); } @@ -331,12 +461,10 @@ namespace AtomToolsFramework const auto& cameraProjection = m_viewportContext->GetCameraProjectionMatrix(); const auto& cameraView = m_viewportContext->GetCameraViewMatrix(); - const AZ::Vector4 normalizedScreenPosition { - screenPosition.m_x * 2.f / width() - 1.0f, - (height() - screenPosition.m_y) * 2.f / height() - 1.0f, - 1.f - depth, // [GFX TODO] [ATOM-1501] Currently we always assume reverse depth - 1.f - }; + const AZ::Vector4 normalizedScreenPosition{ screenPosition.m_x * 2.f / width() - 1.0f, + (height() - screenPosition.m_y) * 2.f / height() - 1.0f, + 1.f - depth, // [GFX TODO] [ATOM-1501] Currently we always assume reverse depth + 1.f }; AZ::Matrix4x4 worldFromScreen = cameraProjection * cameraView; worldFromScreen.InvertFull(); @@ -365,7 +493,7 @@ namespace AtomToolsFramework AZ::Vector3 rayDirection = pos1.value() - pos0.value(); rayDirection.Normalize(); - return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{rayOrigin, rayDirection}; + return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{ rayOrigin, rayDirection }; } float RenderViewportWidget::DeviceScalingFactor() @@ -395,12 +523,12 @@ namespace AtomToolsFramework AzFramework::WindowSize RenderViewportWidget::GetClientAreaSize() const { - return AzFramework::WindowSize{aznumeric_cast(width()), aznumeric_cast(height())}; + return AzFramework::WindowSize{ aznumeric_cast(width()), aznumeric_cast(height()) }; } void RenderViewportWidget::ResizeClientArea(AzFramework::WindowSize clientAreaSize) { - const QSize targetSize = QSize{aznumeric_cast(clientAreaSize.m_width), aznumeric_cast(clientAreaSize.m_height)}; + const QSize targetSize = QSize{ aznumeric_cast(clientAreaSize.m_width), aznumeric_cast(clientAreaSize.m_height) }; resize(targetSize); } @@ -410,7 +538,7 @@ namespace AtomToolsFramework return false; } - void RenderViewportWidget::SetFullScreenState([[maybe_unused]]bool fullScreenState) + void RenderViewportWidget::SetFullScreenState([[maybe_unused]] bool fullScreenState) { // The RenderViewportWidget does not currently support full screen. } @@ -433,11 +561,20 @@ namespace AtomToolsFramework uint32_t RenderViewportWidget::GetDisplayRefreshRate() const { - return 60; + return static_cast(screen()->refreshRate()); } uint32_t RenderViewportWidget::GetSyncInterval() const { - return 1; + uint32_t interval = 1; + + // Get vsync_interval from AzFramework::NativeWindow, which owns it. + // NativeWindow also handles broadcasting OnVsyncIntervalChanged to all + // WindowNotificationBus listeners. + if (auto console = AZ::Interface::Get()) + { + console->GetCvarValue("vsync_interval", interval); + } + return interval; } -} //namespace AtomToolsFramework +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 3d4bb82eec..a24b45179f 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -28,6 +28,7 @@ set(FILES Include/AtomToolsFramework/Util/MaterialPropertyUtil.h Include/AtomToolsFramework/Util/Util.h Include/AtomToolsFramework/Viewport/RenderViewportWidget.h + Include/AtomToolsFramework/Viewport/RenderViewportWidgetNotificationBus.h Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h Include/AtomToolsFramework/Window/AtomToolsMainWindow.h diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp index 7d659ebb7a..bf356fa4b5 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.cpp @@ -183,6 +183,15 @@ namespace AZ::Render DrawFramerate(); } + void AtomViewportDisplayInfoSystemComponent::OnFrameEnd() + { + auto currentTime = AZStd::chrono::system_clock::now(); + if (!m_fpsHistory.empty()) + { + m_fpsHistory.back().m_endFrameTime = currentTime; + } + } + AtomBridge::ViewportInfoDisplayState AtomViewportDisplayInfoSystemComponent::GetDisplayState() const { return aznumeric_cast(r_displayInfo.operator int()); @@ -248,11 +257,11 @@ namespace AZ::Render void AtomViewportDisplayInfoSystemComponent::UpdateFramerate() { auto currentTime = AZStd::chrono::system_clock::now(); - while (!m_fpsHistory.empty() && (currentTime - m_fpsHistory.front()) > m_fpsInterval) + while (!m_fpsHistory.empty() && (currentTime - m_fpsHistory.front().m_beginFrameTime) > m_fpsInterval) { m_fpsHistory.pop_front(); } - m_fpsHistory.push_back(currentTime); + m_fpsHistory.push_back(FrameTimingInfo(currentTime)); } void AtomViewportDisplayInfoSystemComponent::DrawFramerate() @@ -261,25 +270,31 @@ namespace AZ::Render double minFPS = DBL_MAX; double maxFPS = 0; AZStd::chrono::duration deltaTime; + AZStd::chrono::milliseconds totalFrameMS(0); for (const auto& time : m_fpsHistory) { if (lastTime.has_value()) { - deltaTime = time - lastTime.value(); + deltaTime = time.m_beginFrameTime - lastTime.value(); double fps = AZStd::chrono::seconds(1) / deltaTime; minFPS = AZStd::min(minFPS, fps); maxFPS = AZStd::max(maxFPS, fps); } - lastTime = time; + lastTime = time.m_beginFrameTime; + + if (time.m_endFrameTime.has_value()) + { + totalFrameMS += time.m_endFrameTime.value() - time.m_beginFrameTime; + } } double averageFPS = 0; double averageFrameMs = 0; if (m_fpsHistory.size() > 1) { - deltaTime = m_fpsHistory.back() - m_fpsHistory.front(); - averageFPS = AZStd::chrono::seconds(m_fpsHistory.size()) / deltaTime; - averageFrameMs = 1000.0f/averageFPS; + deltaTime = m_fpsHistory.back().m_beginFrameTime - m_fpsHistory.front().m_beginFrameTime; + averageFPS = AZStd::chrono::seconds(m_fpsHistory.size() - 1) / deltaTime; + averageFrameMs = aznumeric_cast(totalFrameMS.count()) / (m_fpsHistory.size() - 1); } const double frameIntervalSeconds = m_fpsInterval.count(); @@ -288,7 +303,7 @@ namespace AZ::Render AZStd::string::format( "FPS %.1f [%.0f..%.0f], %.1fms/frame, avg over %.1fs", averageFPS, - minFPS, + minFPS == DBL_MAX ? 0.0 : minFPS, maxFPS, averageFrameMs, frameIntervalSeconds), diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h index 1d53e188d0..689cfdb43b 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/Code/Source/AtomViewportDisplayInfoSystemComponent.h @@ -45,6 +45,7 @@ namespace AZ // AZ::RPI::ViewportContextNotificationBus::Handler overrides... void OnRenderTick() override; + void OnFrameEnd() override; // AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Handler overrides... AtomBridge::ViewportInfoDisplayState GetDisplayState() const override; @@ -61,6 +62,8 @@ namespace AZ void DrawPassInfo(); void DrawFramerate(); + void UpdateScene(AZ::RPI::ScenePtr scene); + static constexpr float BaseFontSize = 0.7f; AZStd::string m_rendererDescription; @@ -68,7 +71,17 @@ namespace AZ AzFramework::FontDrawInterface* m_fontDrawInterface = nullptr; float m_lineSpacing; AZStd::chrono::duration m_fpsInterval = AZStd::chrono::seconds(1); - AZStd::deque m_fpsHistory; + struct FrameTimingInfo + { + AZStd::chrono::system_clock::time_point m_beginFrameTime; + AZStd::optional m_endFrameTime; + + explicit FrameTimingInfo(AZStd::chrono::system_clock::time_point beginFrameTime) + : m_beginFrameTime(beginFrameTime) + { + } + }; + AZStd::deque m_fpsHistory; AZStd::optional m_lastMemoryUpdate; bool m_updateRootPassQuery = true; }; From 9d2352c3b74e3cf03127b09a184c66ad9d0b1170 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Tue, 14 Sep 2021 13:24:01 +0100 Subject: [PATCH 108/274] Update the viewport interaction model to support single click select (#4094) * add support for single click select Signed-off-by: hultonha * remove redundant profile macro Signed-off-by: hultonha * updates following review feedback Signed-off-by: hultonha * fix behaviour for fallthrough to match previous code Signed-off-by: hultonha --- Code/Editor/EditorViewportWidget.cpp | 2 + .../ActionDispatcher.h | 15 +- .../ImmediateModeActionDispatcher.h | 1 + .../RetainedModeActionDispatcher.h | 55 --- .../Source/ImmediateModeActionDispatcher.cpp | 12 +- .../Source/RetainedModeActionDispatcher.cpp | 129 ------- .../azmanipulatortestframework_files.cmake | 2 - .../EditorTransformComponentSelection.cpp | 353 ++++++++++-------- .../EditorTransformComponentSelection.h | 6 + ...EditorTransformComponentSelectionTests.cpp | 170 ++++++++- 10 files changed, 393 insertions(+), 352 deletions(-) delete mode 100644 Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/RetainedModeActionDispatcher.h delete mode 100644 Code/Framework/AzManipulatorTestFramework/Source/RetainedModeActionDispatcher.cpp diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 7631ac6237..f009fe7602 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1039,6 +1039,7 @@ void EditorViewportWidget::ConnectViewportInteractionRequestBus() { AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); + AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusConnect(); m_viewportUi.ConnectViewportUiBus(GetViewportId()); AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect(); @@ -1049,6 +1050,7 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus() AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect(); m_viewportUi.DisconnectViewportUiBus(); + AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect(); } diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h index 1b555a4a81..6bd72f5101 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h @@ -39,6 +39,8 @@ namespace AzManipulatorTestFramework DerivedDispatcherT* MouseLButtonDown(); //! Set the left mouse button up. DerivedDispatcherT* MouseLButtonUp(); + //! Send a double click event. + DerivedDispatcherT* MouseLButtonDoubleClick(); //! Set the keyboard modifier button down. DerivedDispatcherT* KeyboardModifierDown(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier); //! Set the keyboard modifier button up. @@ -71,6 +73,7 @@ namespace AzManipulatorTestFramework virtual void CameraStateImpl(const AzFramework::CameraState& cameraState) = 0; virtual void MouseLButtonDownImpl() = 0; virtual void MouseLButtonUpImpl() = 0; + virtual void MouseLButtonDoubleClickImpl() = 0; virtual void MousePositionImpl(const AzFramework::ScreenPoint& position) = 0; virtual void KeyboardModifierDownImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) = 0; virtual void KeyboardModifierUpImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) = 0; @@ -167,7 +170,7 @@ namespace AzManipulatorTestFramework template DerivedDispatcherT* ActionDispatcher::MouseLButtonDown() { - Log("%s", "Mouse left button down"); + Log("Mouse left button down"); MouseLButtonDownImpl(); return static_cast(this); } @@ -175,11 +178,19 @@ namespace AzManipulatorTestFramework template DerivedDispatcherT* ActionDispatcher::MouseLButtonUp() { - Log("%s", "Mouse left button up"); + Log("Mouse left button up"); MouseLButtonUpImpl(); return static_cast(this); } + template + DerivedDispatcherT* ActionDispatcher::MouseLButtonDoubleClick() + { + Log("Mouse left button double click"); + MouseLButtonDoubleClickImpl(); + return static_cast(this); + } + template const char* ActionDispatcher::KeyboardModifierString( const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h index 7a4773a37c..9e11a7543c 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h @@ -58,6 +58,7 @@ namespace AzManipulatorTestFramework void CameraStateImpl(const AzFramework::CameraState& cameraState) override; void MouseLButtonDownImpl() override; void MouseLButtonUpImpl() override; + void MouseLButtonDoubleClickImpl() override; void MousePositionImpl(const AzFramework::ScreenPoint& position) override; void KeyboardModifierDownImpl(const KeyboardModifier& keyModifier) override; void KeyboardModifierUpImpl(const KeyboardModifier& keyModifier) override; diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/RetainedModeActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/RetainedModeActionDispatcher.h deleted file mode 100644 index d9aceedf8a..0000000000 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/RetainedModeActionDispatcher.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace AzManipulatorTestFramework -{ - //! Buffers actions to be dispatched upon a call to Execute(). - class RetainedModeActionDispatcher - : public ActionDispatcher - { - public: - explicit RetainedModeActionDispatcher(ManipulatorViewportInteraction& viewportManipulatorInteraction); - //! Execute the sequence of actions and lock the dispatcher from adding further actions. - RetainedModeActionDispatcher* Execute(); - //! Reset the sequence of actions and unlock the dispatcher from adding further actions. - RetainedModeActionDispatcher* ResetSequence(); - - protected: - // ActionDispatcher ... - void EnableSnapToGridImpl() override; - void DisableSnapToGridImpl() override; - void GridSizeImpl(float size) override; - void CameraStateImpl(const AzFramework::CameraState& cameraState) override; - void MouseLButtonDownImpl() override; - void MouseLButtonUpImpl() override; - void MousePositionImpl(const AzFramework::ScreenPoint& position) override; - void KeyboardModifierDownImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) override; - void KeyboardModifierUpImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) override; - void ExpectManipulatorBeingInteractedImpl() override; - void ExpectManipulatorNotBeingInteractedImpl() override; - void SetEntityWorldTransformImpl(AZ::EntityId entityId, const AZ::Transform& transform) override; - void SetSelectedEntityImpl(AZ::EntityId entity) override; - void SetSelectedEntitiesImpl(const AzToolsFramework::EntityIdList& entities) override; - void EnterComponentModeImpl(const AZ::Uuid& uuid) override; - - private: - using Action = AZStd::function; - void AddActionToSequence(Action&& action); - ImmediateModeActionDispatcher m_dispatcher; - AZStd::list m_actions; - bool m_locked = false; - }; -} // namespace AzManipulatorTestFramework diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp index 895899cf3f..23cc2a21f5 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp @@ -83,7 +83,17 @@ namespace AzManipulatorTestFramework void ImmediateModeActionDispatcher::MouseLButtonUpImpl() { GetMouseInteractionEvent()->m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::Up; - m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*GetMouseInteractionEvent()); + m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event); + ToggleOff(GetMouseInteractionEvent()->m_mouseInteraction.m_mouseButtons.m_mouseButtons, MouseButton::Left); + // the mouse position will be the same as the previous event, thus the delta will be 0 + MouseMoveAfterButton(); + } + + void ImmediateModeActionDispatcher::MouseLButtonDoubleClickImpl() + { + GetMouseInteractionEvent()->m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::DoubleClick; + ToggleOn(GetMouseInteractionEvent()->m_mouseInteraction.m_mouseButtons.m_mouseButtons, MouseButton::Left); + m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event); ToggleOff(GetMouseInteractionEvent()->m_mouseInteraction.m_mouseButtons.m_mouseButtons, MouseButton::Left); // the mouse position will be the same as the previous event, thus the delta will be 0 MouseMoveAfterButton(); diff --git a/Code/Framework/AzManipulatorTestFramework/Source/RetainedModeActionDispatcher.cpp b/Code/Framework/AzManipulatorTestFramework/Source/RetainedModeActionDispatcher.cpp deleted file mode 100644 index 34ae4aaf4a..0000000000 --- a/Code/Framework/AzManipulatorTestFramework/Source/RetainedModeActionDispatcher.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#include - -namespace AzManipulatorTestFramework -{ - using KeyboardModifier = AzToolsFramework::ViewportInteraction::KeyboardModifier; - - RetainedModeActionDispatcher::RetainedModeActionDispatcher( - ManipulatorViewportInteraction& viewportManipulatorInteraction) - : m_dispatcher(viewportManipulatorInteraction) - { - } - - void RetainedModeActionDispatcher::AddActionToSequence(Action&& action) - { - if (m_locked) - { - const char* error = "Couldn't add action to sequence, dispatcher is locked (you must call ResetSequence() \ - before adding actions to this dispatcher)"; - Log("%s", error); - AZ_Assert(false, "Error: %s", error); - } - - m_actions.emplace_back(action); - } - - void RetainedModeActionDispatcher::EnableSnapToGridImpl() - { - AddActionToSequence([=]() { m_dispatcher.EnableSnapToGrid(); }); - } - - void RetainedModeActionDispatcher::DisableSnapToGridImpl() - { - AddActionToSequence([=]() { m_dispatcher.DisableSnapToGrid(); }); - } - - void RetainedModeActionDispatcher::GridSizeImpl(float size) - { - AddActionToSequence([=]() { m_dispatcher.GridSize(size); }); - } - - void RetainedModeActionDispatcher::CameraStateImpl(const AzFramework::CameraState& cameraState) - { - AddActionToSequence([=]() { m_dispatcher.CameraState(cameraState); }); - } - - void RetainedModeActionDispatcher::MouseLButtonDownImpl() - { - AddActionToSequence([=]() { m_dispatcher.MouseLButtonDown(); }); - } - - void RetainedModeActionDispatcher::MouseLButtonUpImpl() - { - AddActionToSequence([=]() { m_dispatcher.MouseLButtonUp(); }); - } - - void RetainedModeActionDispatcher::MousePositionImpl(const AzFramework::ScreenPoint& position) - { - AddActionToSequence([=]() { m_dispatcher.MousePosition(position); }); - } - - void RetainedModeActionDispatcher::KeyboardModifierDownImpl(const KeyboardModifier& keyModifier) - { - AddActionToSequence([=]() { m_dispatcher.KeyboardModifierDown(keyModifier); }); - } - - void RetainedModeActionDispatcher::KeyboardModifierUpImpl(const KeyboardModifier& keyModifier) - { - AddActionToSequence([=]() { m_dispatcher.KeyboardModifierUp(keyModifier); }); - } - - void RetainedModeActionDispatcher::ExpectManipulatorBeingInteractedImpl() - { - AddActionToSequence([=]() { m_dispatcher.ExpectManipulatorBeingInteracted(); }); - } - - void RetainedModeActionDispatcher::ExpectManipulatorNotBeingInteractedImpl() - { - AddActionToSequence([=]() { m_dispatcher.ExpectManipulatorNotBeingInteracted(); }); - } - - void RetainedModeActionDispatcher::SetEntityWorldTransformImpl(AZ::EntityId entityId, const AZ::Transform& transform) - { - AddActionToSequence([=]() { m_dispatcher.SetEntityWorldTransform(entityId, transform); }); - } - - void RetainedModeActionDispatcher::SetSelectedEntityImpl(AZ::EntityId entity) - { - AddActionToSequence([=]() { m_dispatcher.SetSelectedEntity(entity); }); - } - - void RetainedModeActionDispatcher::SetSelectedEntitiesImpl(const AzToolsFramework::EntityIdList& entities) - { - AddActionToSequence([=]() { m_dispatcher.SetSelectedEntities(entities); }); - } - - void RetainedModeActionDispatcher::EnterComponentModeImpl(const AZ::Uuid& uuid) - { - AddActionToSequence([=]() { m_dispatcher.EnterComponentMode(uuid); }); - } - - RetainedModeActionDispatcher* RetainedModeActionDispatcher::ResetSequence() - { - Log("%s", "Resetting the action sequence"); - m_actions.clear(); - m_dispatcher.ResetEvent(); - m_locked = false; - return this; - } - - RetainedModeActionDispatcher* RetainedModeActionDispatcher::Execute() - { - Log("Executing %u actions", m_actions.size()); - for (auto& action : m_actions) - { - action(); - } - m_dispatcher.ResetEvent(); - m_locked = true; - return this; - } -} // namespace AzManipulatorTestFramework diff --git a/Code/Framework/AzManipulatorTestFramework/azmanipulatortestframework_files.cmake b/Code/Framework/AzManipulatorTestFramework/azmanipulatortestframework_files.cmake index 3fe9f4266c..9f480a3e2a 100644 --- a/Code/Framework/AzManipulatorTestFramework/azmanipulatortestframework_files.cmake +++ b/Code/Framework/AzManipulatorTestFramework/azmanipulatortestframework_files.cmake @@ -14,12 +14,10 @@ set(FILES Include/AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h Include/AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h - Include/AzManipulatorTestFramework/RetainedModeActionDispatcher.h Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h Source/ViewportInteraction.cpp Source/DirectManipulatorViewportInteraction.cpp Source/IndirectManipulatorViewportInteraction.cpp Source/ImmediateModeActionDispatcher.cpp - Source/RetainedModeActionDispatcher.cpp Source/AzManipulatorTestFrameworkUtils.cpp ) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 3db8492d70..5a7b097e29 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1770,6 +1770,12 @@ namespace AzToolsFramework return false; } + void EditorTransformComponentSelection::ChangeSelectedEntity(const AZ::EntityId entityId) + { + DeselectEntities(); + SelectDeselect(entityId); + } + bool EditorTransformComponentSelection::HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -1821,202 +1827,239 @@ namespace AzToolsFramework return true; } - // double click to deselect all - if (Input::DeselectAll(mouseInteraction)) + if (ed_viewportStickySelect) { - // note: even if m_selectedEntityIds is technically empty, we - // may still have an entity selected that was clicked in the - // entity outliner - we still want to make sure the deselect all - // action clears the selection - DeselectEntities(); - return false; + // double click to deselect all + if (Input::DeselectAll(mouseInteraction)) + { + // note: even if m_selectedEntityIds is technically empty, we + // may still have an entity selected that was clicked in the + // entity outliner - we still want to make sure the deselect all + // action clears the selection + DeselectEntities(); + return false; + } } - if (!m_selectedEntityIds.empty()) + // select/deselect (add/remove) entities with ctrl held + if (Input::AdditiveIndividualSelect(clickOutcome, mouseInteraction)) { - // select/deselect (add/remove) entities with ctrl held - if (Input::AdditiveIndividualSelect(clickOutcome, mouseInteraction)) + if (SelectDeselect(entityIdUnderCursor)) { - if (SelectDeselect(entityIdUnderCursor)) + if (m_selectedEntityIds.empty()) { - if (m_selectedEntityIds.empty()) - { - m_pivotOverrideFrame.Reset(); - } - - return false; + m_pivotOverrideFrame.Reset(); } + + return false; } + } + if (!m_selectedEntityIds.empty()) + { // group copying/alignment to specific entity - 'ditto' position/orientation for group - if (Input::GroupDitto(mouseInteraction)) + if (Input::GroupDitto(mouseInteraction) && PerformGroupDitto(entityIdUnderCursor)) { - if (entityIdUnderCursor.IsValid()) - { - AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(worldFromLocal, entityIdUnderCursor, &AZ::TransformBus::Events::GetWorldTM); - - switch (m_mode) - { - case Mode::Rotation: - CopyOrientationToSelectedEntitiesGroup(QuaternionFromTransformNoScaling(worldFromLocal)); - break; - case Mode::Scale: - CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetUniformScale()); - break; - case Mode::Translation: - CopyTranslationToSelectedEntitiesGroup(worldFromLocal.GetTranslation()); - break; - default: - // do nothing - break; - } - - return false; - } + return false; } // individual copying/alignment to specific entity - 'ditto' position/orientation for individual - if (Input::IndividualDitto(mouseInteraction)) + if (Input::IndividualDitto(mouseInteraction) && PerformIndividualDitto(entityIdUnderCursor)) { - if (entityIdUnderCursor.IsValid()) - { - AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(worldFromLocal, entityIdUnderCursor, &AZ::TransformBus::Events::GetWorldTM); - - switch (m_mode) - { - case Mode::Rotation: - CopyOrientationToSelectedEntitiesIndividual(QuaternionFromTransformNoScaling(worldFromLocal)); - break; - case Mode::Scale: - CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetUniformScale()); - break; - case Mode::Translation: - CopyTranslationToSelectedEntitiesIndividual(worldFromLocal.GetTranslation()); - break; - default: - // do nothing - break; - } - - return false; - } + return false; } // try snapping to the terrain (if in Translation mode) and entity wasn't picked if (Input::SnapTerrain(mouseInteraction)) { - for (AZ::EntityId entityId : m_selectedEntityIds) - { - ScopedUndoBatch::MarkEntityDirty(entityId); - } - - if (m_mode == Mode::Translation) - { - const AZ::Vector3 finalSurfacePosition = PickTerrainPosition(mouseInteraction.m_mouseInteraction); - - // handle modifier alternatives - if (Input::IndividualDitto(mouseInteraction)) - { - CopyTranslationToSelectedEntitiesIndividual(finalSurfacePosition); - } - else if (Input::GroupDitto(mouseInteraction)) - { - CopyTranslationToSelectedEntitiesGroup(finalSurfacePosition); - } - } - else if (m_mode == Mode::Rotation) - { - // handle modifier alternatives - if (Input::IndividualDitto(mouseInteraction)) - { - CopyOrientationToSelectedEntitiesIndividual(AZ::Quaternion::CreateIdentity()); - } - else if (Input::GroupDitto(mouseInteraction)) - { - CopyOrientationToSelectedEntitiesGroup(AZ::Quaternion::CreateIdentity()); - } - } - + PerformSnapToTerrain(mouseInteraction); return false; } // set manipulator pivot override translation or orientation (update manipulators) if (Input::ManipulatorDitto(mouseInteraction)) { - if (m_entityIdManipulators.m_manipulators) - { - ScopedUndoBatch undoBatch(s_dittoManipulatorUndoRedoDesc); - - auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + PerformManipulatorDitto(entityIdUnderCursor); + return false; + } - if (entityIdUnderCursor.IsValid()) - { - AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(worldFromLocal, entityIdUnderCursor, &AZ::TransformBus::Events::GetWorldTM); + if (ed_viewportStickySelect) + { + return false; + } + } - // set orientation/translation to match picked entity - switch (m_mode) - { - case Mode::Rotation: - OverrideManipulatorOrientation(QuaternionFromTransformNoScaling(worldFromLocal)); - break; - case Mode::Translation: - OverrideManipulatorTranslation(worldFromLocal.GetTranslation()); - break; - case Mode::Scale: - // do nothing - break; - default: - break; - } + // standard toggle selection + if (Input::IndividualSelect(clickOutcome)) + { + if (!ed_viewportStickySelect) + { + ChangeSelectedEntity(entityIdUnderCursor); + } + else + { + SelectDeselect(entityIdUnderCursor); + } + } - // only update pivot override when in translation or rotation mode - switch (m_mode) - { - case Mode::Rotation: - m_pivotOverrideFrame.m_pickTypes |= OptionalFrame::PickType::Orientation; - [[fallthrough]]; - case Mode::Translation: - m_pivotOverrideFrame.m_pickTypes |= OptionalFrame::PickType::Translation; - m_pivotOverrideFrame.m_pickedEntityIdOverride = entityIdUnderCursor; - break; - case Mode::Scale: - // do nothing - break; - default: - break; - } - } - else - { - // match the same behavior as if we pressed Ctrl+R to reset the manipulator - DelegateClearManipulatorOverride(); - } + return false; + } - manipulatorCommand->SetManipulatorAfter(EntityManipulatorCommand::State( - BuildPivotOverride(m_pivotOverrideFrame.HasTranslationOverride(), m_pivotOverrideFrame.HasOrientationOverride()), - m_entityIdManipulators.m_manipulators->GetLocalTransform(), entityIdUnderCursor)); + bool EditorTransformComponentSelection::PerformGroupDitto(const AZ::EntityId entityId) + { + if (entityId.IsValid()) + { + AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM); - manipulatorCommand->SetParent(undoBatch.GetUndoBatch()); - manipulatorCommand.release(); - } + switch (m_mode) + { + case Mode::Rotation: + CopyOrientationToSelectedEntitiesGroup(QuaternionFromTransformNoScaling(worldFromLocal)); + break; + case Mode::Scale: + CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetUniformScale()); + break; + case Mode::Translation: + CopyTranslationToSelectedEntitiesGroup(worldFromLocal.GetTranslation()); + break; + default: + // do nothing + break; } - return false; + return true; } - // standard toggle selection - if (Input::IndividualSelect(clickOutcome)) + return false; + } + + bool EditorTransformComponentSelection::PerformIndividualDitto(const AZ::EntityId entityId) + { + if (entityId.IsValid()) { - SelectDeselect(entityIdUnderCursor); + AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM); + + switch (m_mode) + { + case Mode::Rotation: + CopyOrientationToSelectedEntitiesIndividual(QuaternionFromTransformNoScaling(worldFromLocal)); + break; + case Mode::Scale: + CopyScaleToSelectedEntitiesIndividualWorld(worldFromLocal.GetUniformScale()); + break; + case Mode::Translation: + CopyTranslationToSelectedEntitiesIndividual(worldFromLocal.GetTranslation()); + break; + default: + // do nothing + break; + } + + return true; } return false; } + void EditorTransformComponentSelection::PerformSnapToTerrain(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) + { + for (AZ::EntityId entityId : m_selectedEntityIds) + { + ScopedUndoBatch::MarkEntityDirty(entityId); + } + + if (m_mode == Mode::Translation) + { + const AZ::Vector3 finalSurfacePosition = PickTerrainPosition(mouseInteraction.m_mouseInteraction); + + // handle modifier alternatives + if (Input::IndividualDitto(mouseInteraction)) + { + CopyTranslationToSelectedEntitiesIndividual(finalSurfacePosition); + } + else if (Input::GroupDitto(mouseInteraction)) + { + CopyTranslationToSelectedEntitiesGroup(finalSurfacePosition); + } + } + else if (m_mode == Mode::Rotation) + { + // handle modifier alternatives + if (Input::IndividualDitto(mouseInteraction)) + { + CopyOrientationToSelectedEntitiesIndividual(AZ::Quaternion::CreateIdentity()); + } + else if (Input::GroupDitto(mouseInteraction)) + { + CopyOrientationToSelectedEntitiesGroup(AZ::Quaternion::CreateIdentity()); + } + } + } + + void EditorTransformComponentSelection::PerformManipulatorDitto(const AZ::EntityId entityId) + { + if (m_entityIdManipulators.m_manipulators) + { + ScopedUndoBatch undoBatch(s_dittoManipulatorUndoRedoDesc); + + auto manipulatorCommand = + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + + if (entityId.IsValid()) + { + AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM); + + // set orientation/translation to match picked entity + switch (m_mode) + { + case Mode::Rotation: + OverrideManipulatorOrientation(QuaternionFromTransformNoScaling(worldFromLocal)); + break; + case Mode::Translation: + OverrideManipulatorTranslation(worldFromLocal.GetTranslation()); + break; + case Mode::Scale: + // do nothing + break; + default: + break; + } + + // only update pivot override when in translation or rotation mode + switch (m_mode) + { + case Mode::Rotation: + m_pivotOverrideFrame.m_pickTypes |= OptionalFrame::PickType::Orientation; + [[fallthrough]]; + case Mode::Translation: + m_pivotOverrideFrame.m_pickTypes |= OptionalFrame::PickType::Translation; + m_pivotOverrideFrame.m_pickedEntityIdOverride = entityId; + break; + case Mode::Scale: + // do nothing + break; + default: + break; + } + } + else + { + // match the same behavior as if we pressed Ctrl+R to reset the manipulator + DelegateClearManipulatorOverride(); + } + + manipulatorCommand->SetManipulatorAfter(EntityManipulatorCommand::State( + BuildPivotOverride(m_pivotOverrideFrame.HasTranslationOverride(), m_pivotOverrideFrame.HasOrientationOverride()), + m_entityIdManipulators.m_manipulators->GetLocalTransform(), entityId)); + + manipulatorCommand->SetParent(undoBatch.GetUndoBatch()); + manipulatorCommand.release(); + } + } + template static void AddAction( AZStd::vector>& actions, diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index 35d3587d0b..478c0b775e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -207,6 +207,7 @@ namespace AzToolsFramework void SetSelectedEntities(const EntityIdList& entityIds); void DeselectEntities(); bool SelectDeselect(AZ::EntityId entityId); + void ChangeSelectedEntity(AZ::EntityId entityId); void RefreshSelectedEntityIds(); void RefreshSelectedEntityIds(const EntityIdList& selectedEntityIds); @@ -298,6 +299,11 @@ namespace AzToolsFramework void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation); void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Quaternion& localRotation); + bool PerformGroupDitto(AZ::EntityId entityId); + bool PerformIndividualDitto(AZ::EntityId entityId); + void PerformManipulatorDitto(AZ::EntityId entityId); + void PerformSnapToTerrain(const ViewportInteraction::MouseInteractionEvent& mouseInteraction); + //! Responsible for keeping the space cluster in sync with the current reference frame. void UpdateSpaceCluster(ReferenceFrame referenceFrame); diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index 8a958af567..241ee3f576 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -614,7 +614,7 @@ namespace UnitTest using EditorTransformComponentSelectionViewportPickingManipulatorTestFixture = IndirectCallManipulatorViewportInteractionFixtureMixin; - TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickWithNoSelectionWillSelectEntity) + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickySingleClickWithNoSelectionWillSelectEntity) { AzToolsFramework::ed_viewportStickySelect = true; @@ -637,19 +637,44 @@ namespace UnitTest EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1)); } - TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickOffEntityWithSelectionWillNotDeselectEntity) + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickWithNoSelectionWillSelectEntity) + { + AzToolsFramework::ed_viewportStickySelect = false; + + PositionEntities(); + PositionCamera(m_cameraState); + + using ::testing::Eq; + auto selectedEntitiesBefore = SelectedEntities(); + EXPECT_TRUE(selectedEntitiesBefore.empty()); + + // calculate the position in screen space of the initial entity position + const auto entity1ScreenPosition = AzFramework::WorldToScreen(m_entity1WorldTranslation, m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + + // entity is selected + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1)); + EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + StickySingleClickOffEntityWithSelectionWillNotDeselectEntity) { AzToolsFramework::ed_viewportStickySelect = true; PositionEntities(); PositionCamera(m_cameraState); - // position in space above the entity + // position in space above the entities const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f); AzToolsFramework::SelectEntity(m_entityId1); - // calculate the position in screen space of the initial position of the entity + // calculate the screen space position of the click const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); // click the empty space in the viewport @@ -662,9 +687,32 @@ namespace UnitTest EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1)); } + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickOffEntityWithSelectionWillDeselectEntity) + { + AzToolsFramework::ed_viewportStickySelect = false; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntity(m_entityId1); + + // position in space above the entities + const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f); + // calculate the screen space position of the click + const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); + + // click the empty space in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDown()->MouseLButtonUp(); + + // entity was deselected + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_TRUE(selectedEntitiesAfter.empty()); + } + TEST_F( EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, - SingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity) + StickySingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity) { AzToolsFramework::ed_viewportStickySelect = true; @@ -688,7 +736,31 @@ namespace UnitTest TEST_F( EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, - CtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection) + UnstickySingleClickOnNewEntityWithSelectionWillChangeSelectedEntity) + { + AzToolsFramework::ed_viewportStickySelect = false; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntity(m_entityId1); + + // calculate the position in screen space of the second entity + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + + // entity selection was changed + using ::testing::Eq; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1)); + EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId2)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + StickyCtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection) { AzToolsFramework::ed_viewportStickySelect = true; @@ -715,7 +787,34 @@ namespace UnitTest TEST_F( EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, - CtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection) + UnstickyCtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection) + { + AzToolsFramework::ed_viewportStickySelect = false; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntity(m_entityId1); + + // calculate the position in screen space of the second entity + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(entity2ScreenPosition) + ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) + ->MouseLButtonDown() + ->MouseLButtonUp(); + + // entity selection was changed (one entity selected to two) + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + StickyCtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection) { AzToolsFramework::ed_viewportStickySelect = true; @@ -740,7 +839,36 @@ namespace UnitTest EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1)); } - TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + UnstickyCtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection) + { + AzToolsFramework::ed_viewportStickySelect = false; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2 }); + + // calculate the position in screen space of the second entity + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); + + // click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState) + ->MousePosition(entity2ScreenPosition) + ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) + ->MouseLButtonDown() + ->MouseLButtonUp(); + + // entity selection was changed (entity2 was deselected) + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1)); + } + + TEST_F( + EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, + BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) { AzToolsFramework::ed_viewportStickySelect = true; @@ -835,6 +963,32 @@ namespace UnitTest EXPECT_TRUE(selectedEntitiesAfter.empty()); } + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickyDoubleClickWithSelectionWillDeselectEntities) + { + AzToolsFramework::ed_viewportStickySelect = true; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2, m_entityId3 }); + + using ::testing::UnorderedElementsAre; + auto selectedEntitiesBefore = SelectedEntities(); + EXPECT_THAT(selectedEntitiesBefore, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3)); + + // position in space above the entities + const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f); + // calculate the screen space position of the click + const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); + + // double click to deselect entities + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDoubleClick(); + + // no entities are selected + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_TRUE(selectedEntitiesAfter.empty()); + } + using EditorTransformComponentSelectionManipulatorTestFixture = IndirectCallManipulatorViewportInteractionFixtureMixin; From fcd5b3f184af27c4514a4f6eab2c6d912ae1d1e9 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 14 Sep 2021 11:50:51 -0400 Subject: [PATCH 109/274] Converted to use AZ::Events for hiearchy notifications. Added unittests. Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyBus.h | 22 +++++++------- .../NetworkHierarchyChildComponent.h | 5 ++++ .../NetworkHierarchyRootComponent.h | 5 ++++ .../NetworkHierarchyChildComponent.cpp | 17 +++++++++-- .../NetworkHierarchyRootComponent.cpp | 14 +++++++++ .../Components/NetworkTransformComponent.cpp | 23 +++++++++++---- .../EntityReplication/EntityReplicator.cpp | 28 +++++++++--------- .../Code/Tests/ClientHierarchyTests.cpp | 25 +++++++++++++++- .../Code/Tests/CommonHierarchySetup.h | 29 +++++++++++++++++-- 9 files changed, 131 insertions(+), 37 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h index d644d6eb5a..1401856afe 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -12,18 +12,8 @@ namespace Multiplayer { - class NetworkHierarchyNotifications - : public AZ::ComponentBus - { - public: - //! Called when a hierarchy has been updated (a child added or removed, etc.) - virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {} - - //! Called when an entity has left a hierarchy - virtual void OnNetworkHierarchyLeave() {} - }; - - typedef AZ::EBus NetworkHierarchyNotificationBus; + using NetworkHierarchyChangedEvent = AZ::Event; + using NetworkHierarchyLeaveEvent = AZ::Event<>; class NetworkHierarchyRequests : public AZ::ComponentBus @@ -40,6 +30,14 @@ namespace Multiplayer //! @return true if this entity is the top level root of a hierarchy virtual bool IsHierarchicalRoot() const = 0; + + //! Binds the provided NetworkHierarchyChangedEvent handler to a Network Hierarchy component. + //! @param handler the handler to invoke when the entity's network hierarchy has been modified. + virtual void BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) = 0; + + //! Binds the provided NetworkHierarchyLeaveEvent handler to a Network Hierarchy component. + //! @param handler the handler to invoke when the entity left its network hierarchy. + virtual void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) = 0; }; typedef AZ::EBus NetworkHierarchyRequestBus; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index cfc3803d28..93ce3e25d0 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -52,6 +52,8 @@ namespace Multiplayer bool IsHierarchicalRoot() const override { return false; } AZ::Entity* GetHierarchicalRoot() const override; AZStd::vector GetHierarchicalEntities() const override; + void BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) override; + void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override; //! @} protected: @@ -63,5 +65,8 @@ namespace Multiplayer AZ::Event::Handler m_hierarchyRootNetIdChanged; void OnHierarchyRootNetIdChanged(NetEntityId rootNetId); + + NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; + NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 4be8b24d8a..228f953a32 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -50,6 +50,8 @@ namespace Multiplayer bool IsHierarchicalChild() const override; AZStd::vector GetHierarchicalEntities() const override; AZ::Entity* GetHierarchicalRoot() const override; + void BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) override; + void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override; //! @} protected: @@ -63,6 +65,9 @@ namespace Multiplayer void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); private: + NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; + NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; + AZ::Entity* m_higherRootEntity = nullptr; AZStd::vector m_hierarchicalEntities; diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index cbdf214dfc..93574ec5b4 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -98,6 +98,16 @@ namespace Multiplayer return {}; } + void NetworkHierarchyChildComponent::BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyChangedEvent); + } + + void NetworkHierarchyChildComponent::BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyLeaveEvent); + } + void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot) { m_hierarchyRootComponent = hierarchyRoot; @@ -109,12 +119,13 @@ namespace Multiplayer const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetEntityId()); controller->SetHierarchyRoot(netRootId); - NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyUpdated, hierarchyRoot->GetEntityId()); + m_networkHierarchyChangedEvent.Signal(hierarchyRoot->GetEntityId()); } else { controller->SetHierarchyRoot(InvalidNetEntityId); - NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyLeave); + + m_networkHierarchyLeaveEvent.Signal(); } } } @@ -125,10 +136,12 @@ namespace Multiplayer if (rootHandle.Exists()) { m_hierarchyRootComponent = rootHandle.FindComponent(); + m_networkHierarchyChangedEvent.Signal(m_hierarchyRootComponent->GetEntityId()); } else { m_hierarchyRootComponent = nullptr; + m_networkHierarchyLeaveEvent.Signal(); } } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index 5f546298cb..ced2c79bce 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -124,6 +124,16 @@ namespace Multiplayer return GetEntity(); } + void NetworkHierarchyRootComponent::BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyChangedEvent); + } + + void NetworkHierarchyRootComponent::BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyLeaveEvent); + } + void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) { const AZ::EntityId entityBusId = *AZ::TransformNotificationBus::GetCurrentBusId(); @@ -168,6 +178,8 @@ namespace Multiplayer uint32_t currentEntityCount = aznumeric_cast(m_hierarchicalEntities.size()); RecursiveAttachHierarchicalEntities(GetEntityId(), currentEntityCount); + + m_networkHierarchyChangedEvent.Signal(GetEntityId()); } bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount) @@ -255,6 +267,8 @@ namespace Multiplayer } } } + + m_networkHierarchyChangedEvent.Signal(GetEntityId()); } void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index a37b6b52ed..8461f950fd 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -97,15 +97,28 @@ namespace Multiplayer void NetworkTransformComponent::OnParentIdChangedEvent([[maybe_unused]] NetEntityId newParent) { - const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(newParent); - if (rootHandle.Exists()) + if (newParent == InvalidNetEntityId) { - const AZ::EntityId parentEntityId = rootHandle.GetEntity()->GetId(); if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) { - if (transformComponent->GetParentId() != parentEntityId) + if (transformComponent->GetParentId() != AZ::EntityId()) { - transformComponent->SetParent(parentEntityId); + transformComponent->SetParent(AZ::EntityId()); + } + } + } + else + { + const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(newParent); + if (rootHandle.Exists()) + { + const AZ::EntityId parentEntityId = rootHandle.GetEntity()->GetId(); + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + if (transformComponent->GetParentId() != parentEntityId) + { + transformComponent->SetParent(parentEntityId); + } } } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index ad8c883f34..bd98d15923 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -32,8 +32,6 @@ #include -AZ_CVAR(bool, bg_debugHierarchyActivation, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Helpful messages when debugging network hierarchy behavior"); - namespace Multiplayer { EntityReplicator::EntityReplicator @@ -441,22 +439,22 @@ namespace Multiplayer const AZ::Entity* parentEntity = parentHandle.GetEntity(); if (parentEntity && parentEntity->GetState() == AZ::Entity::State::Active) { - if (bg_debugHierarchyActivation) - { - AZLOG_DEBUG( - "Entity %s asking for activation - granted", - entity->GetName().c_str()); - } + AZLOG + ( + NET_HierarchyActivationInfo, + "Hierchical entity %s asking for activation - granted", + entity->GetName().c_str() + ); return true; } - if (bg_debugHierarchyActivation) - { - AZLOG_DEBUG( - "Entity %s asking for activation - waiting on the parent %u", - entity->GetName().c_str(), - aznumeric_cast(parentId)); - } + AZLOG + ( + NET_HierarchyActivationInfo, + "Hierchical entity %s asking for activation - waiting on the parent %u", + entity->GetName().c_str(), + aznumeric_cast(parentId) + ); return false; } } diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 29d4f7f809..1483f32023 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -226,7 +226,6 @@ namespace Multiplayer ReplicationRecord notifyRecord = currentRecord; entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); } @@ -287,6 +286,30 @@ namespace Multiplayer ); } + TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Updated_Event_On_Child_Detached_On_Server) + { + MockNetworkHierarchyCallbackHandler mock; + EXPECT_CALL(mock, OnNetworkHierarchyUpdated(m_rootEntity->GetId())); + + m_rootEntity->FindComponent()->BindNetworkHierarchyChangedEventHandler(mock.m_changedHandler); + + // simulate server detaching a child entity + SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + } + + TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Leave_Event_On_Child_Detached_On_Server) + { + MockNetworkHierarchyCallbackHandler mock; + EXPECT_CALL(mock, OnNetworkHierarchyLeave); + + m_childEntity->FindComponent()->BindNetworkHierarchyLeaveEventHandler(mock.m_leaveHandler); + + // simulate server detaching a child entity + SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + } + /* * Parent -> Child -> ChildOfChild */ diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h index 89d0d32428..d4f9d218e2 100644 --- a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -35,6 +35,29 @@ namespace Multiplayer using namespace testing; using namespace ::UnitTest; + class NetworkHierarchyCallbacks + { + public: + virtual void OnNetworkHierarchyLeave() = 0; + virtual void OnNetworkHierarchyUpdated(const AZ::EntityId& hierarchyRootId) = 0; + }; + + class MockNetworkHierarchyCallbackHandler : public NetworkHierarchyCallbacks + { + public: + MockNetworkHierarchyCallbackHandler() + : m_leaveHandler([this]() { OnNetworkHierarchyLeave(); }) + , m_changedHandler([this](const AZ::EntityId& rootId) { OnNetworkHierarchyUpdated(rootId); }) + { + } + + NetworkHierarchyLeaveEvent::Handler m_leaveHandler; + NetworkHierarchyChangedEvent::Handler m_changedHandler; + + MOCK_METHOD0(OnNetworkHierarchyLeave, void()); + MOCK_METHOD1(OnNetworkHierarchyUpdated, void(const AZ::EntityId&)); + }; + class HierarchyTests : public AllocatorsFixture { @@ -282,8 +305,9 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + ReplicationRecord notifyRecord = currentRecord; entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - // now the parent id is in the component + entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); } template @@ -306,8 +330,9 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + ReplicationRecord notifyRecord = currentRecord; entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - // now the parent id is in the component + entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); } struct EntityInfo From 3973e1d3e5d9febff33ce3b473532bdf861c72c8 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Tue, 14 Sep 2021 09:14:55 -0700 Subject: [PATCH 110/274] Moved NetworkCharacterComponent out of MPSample and into MP gem Signed-off-by: Gene Walters --- Gems/Multiplayer/Code/CMakeLists.txt | 1 + .../Components/NetworkCharacterComponent.h | 69 ++++++ ...etworkCharacterComponent.AutoComponent.xml | 12 + .../Components/NetworkCharacterComponent.cpp | 214 ++++++++++++++++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 3 + 5 files changed, 299 insertions(+) create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkCharacterComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index 256f1bceeb..49b404fb1c 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -27,6 +27,7 @@ ly_add_target( AZ::AzNetworking PRIVATE Gem::EMotionFXStaticLib + Gem::PhysX.Static AUTOGEN_RULES *.AutoPackets.xml,AutoPackets_Header.jinja,$path/$fileprefix.AutoPackets.h *.AutoPackets.xml,AutoPackets_Inline.jinja,$path/$fileprefix.AutoPackets.inl diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h new file mode 100644 index 0000000000..8939284d17 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include + +namespace Physics +{ + class Character; +} + +namespace Multiplayer +{ + class NetworkCharacterComponent + : public NetworkCharacterComponentBase + , private PhysX::CharacterGameplayRequestBus::Handler + { + friend class NetworkCharacterComponentController; + + public: + AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkCharacterComponent, s_networkCharacterComponentConcreteUuid, Multiplayer::NetworkCharacterComponentBase) + + static void Reflect(AZ::ReflectContext* context); + + NetworkCharacterComponent(); + + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("NetworkRigidBodyService")); + } + + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + private: + void OnTranslationChangedEvent(const AZ::Vector3& translation); + void OnSyncRewind(); + + // CharacterGameplayRequestBus + bool IsOnGround() const override; + float GetGravityMultiplier() const override { return {}; } + void SetGravityMultiplier([[maybe_unused]] float gravityMultiplier) override {} + AZ::Vector3 GetFallingVelocity() const override { return {}; } + void SetFallingVelocity([[maybe_unused]] const AZ::Vector3& fallingVelocity) override {} + + Physics::Character* m_physicsCharacter = nullptr; + Multiplayer::EntitySyncRewindEvent::Handler m_syncRewindHandler = Multiplayer::EntitySyncRewindEvent::Handler([this]() { OnSyncRewind(); }); + AZ::Event::Handler m_translationEventHandler; + }; + + class NetworkCharacterComponentController + : public NetworkCharacterComponentControllerBase + { + public: + NetworkCharacterComponentController(NetworkCharacterComponent& parent); + + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + + AZ::Vector3 TryMoveWithVelocity(const AZ::Vector3& velocity, float deltaTime); + }; +} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkCharacterComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkCharacterComponent.AutoComponent.xml new file mode 100644 index 0000000000..83e15800e0 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkCharacterComponent.AutoComponent.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp new file mode 100644 index 0000000000..31be4a490d --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + + bool CollisionLayerBasedControllerFilter(const physx::PxController& controllerA, const physx::PxController& controllerB) + { + PHYSX_SCENE_READ_LOCK(controllerA.getActor()->getScene()); + physx::PxRigidDynamic* actorA = controllerA.getActor(); + physx::PxRigidDynamic* actorB = controllerB.getActor(); + + if (actorA && actorA->getNbShapes() > 0 && actorB && actorB->getNbShapes() > 0) + { + physx::PxShape* shapeA = nullptr; + actorA->getShapes(&shapeA, 1, 0); + physx::PxFilterData filterDataA = shapeA->getSimulationFilterData(); + physx::PxShape* shapeB = nullptr; + actorB->getShapes(&shapeB, 1, 0); + physx::PxFilterData filterDataB = shapeB->getSimulationFilterData(); + return PhysX::Utils::Collision::ShouldCollide(filterDataA, filterDataB); + } + + return true; + } + + physx::PxQueryHitType::Enum CollisionLayerBasedObjectPreFilter( + const physx::PxFilterData& filterData, + const physx::PxShape* shape, + const physx::PxRigidActor* actor, + [[maybe_unused]] physx::PxHitFlags& queryFlags) + { + // non-kinematic dynamic bodies should not impede the movement of the character + if (actor->getConcreteType() == physx::PxConcreteType::eRIGID_DYNAMIC) + { + const physx::PxRigidDynamic* rigidDynamic = static_cast(actor); + + bool isKinematic = (rigidDynamic->getRigidBodyFlags() & physx::PxRigidBodyFlag::eKINEMATIC); + if (isKinematic) + { + const PhysX::ActorData* actorData = PhysX::Utils::GetUserData(rigidDynamic); + if (actorData) + { + const AZ::EntityId entityId = actorData->GetEntityId(); + + if (Multiplayer::NetworkRigidBodyRequestBus::FindFirstHandler(entityId) != nullptr) + { + // Network rigid bodies are kinematic on the client but dynamic on the server, + // hence filtering treats these actors as dynamic to support client prediction and avoid desyncs + isKinematic = false; + } + } + } + + if (!isKinematic) + { + return physx::PxQueryHitType::eNONE; + } + } + + // all other cases should be determined by collision filters + if (PhysX::Utils::Collision::ShouldCollide(filterData, shape->getSimulationFilterData())) + { + return physx::PxQueryHitType::eBLOCK; + } + + return physx::PxQueryHitType::eNONE; + } + + void NetworkCharacterComponent::NetworkCharacterComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + } + NetworkCharacterComponentBase::Reflect(context); + } + + NetworkCharacterComponent::NetworkCharacterComponent() + : m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) + { + ; + } + + void NetworkCharacterComponent::OnInit() + { + ; + } + + void NetworkCharacterComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + Physics::CharacterRequests* characterRequests = Physics::CharacterRequestBus::FindFirstHandler(GetEntityId()); + m_physicsCharacter = (characterRequests != nullptr) ? characterRequests->GetCharacter() : nullptr; + GetNetBindComponent()->AddEntitySyncRewindEventHandler(m_syncRewindHandler); + + if (m_physicsCharacter) + { + auto controller = static_cast(m_physicsCharacter); + controller->SetFilterFlags(physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC | physx::PxQueryFlag::ePREFILTER); + if (auto callbackManager = controller->GetCallbackManager()) + { + callbackManager->SetControllerFilter(CollisionLayerBasedControllerFilter); + callbackManager->SetObjectPreFilter(CollisionLayerBasedObjectPreFilter); + } + } + + if (!HasController()) + { + GetNetworkTransformComponent()->TranslationAddEvent(m_translationEventHandler); + } + } + + void NetworkCharacterComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkCharacterComponent::OnTranslationChangedEvent([[maybe_unused]] const AZ::Vector3& translation) + { + OnSyncRewind(); + } + + void NetworkCharacterComponent::OnSyncRewind() + { + if (m_physicsCharacter == nullptr) + { + return; + } + + const AZ::Vector3 currPosition = m_physicsCharacter->GetBasePosition(); + if (!currPosition.IsClose(GetNetworkTransformComponent()->GetTranslation())) + { + uint32_t frameId = static_cast(Multiplayer::GetNetworkTime()->GetHostFrameId()); + m_physicsCharacter->SetFrameId(frameId); + //m_physicsCharacter->SetBasePosition(GetNetworkTransformComponent()->GetTranslation()); + } + } + + bool NetworkCharacterComponent::IsOnGround() const + { + auto pxController = static_cast(m_physicsCharacter->GetNativePointer()); + if (!pxController) + { + return true; + } + + physx::PxControllerState state; + pxController->getState(state); + return state.touchedActor != nullptr || (state.collisionFlags & physx::PxControllerCollisionFlag::eCOLLISION_DOWN) != 0; + } + + NetworkCharacterComponentController::NetworkCharacterComponentController(NetworkCharacterComponent& parent) + : NetworkCharacterComponentControllerBase(parent) + { + ; + } + + void NetworkCharacterComponentController::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + void NetworkCharacterComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + ; + } + + AZ::Vector3 NetworkCharacterComponentController::TryMoveWithVelocity(const AZ::Vector3& velocity, [[maybe_unused]] float deltaTime) + { + // Ensure any entities that we might interact with are properly synchronized to their rewind state + if (IsAuthority()) + { + const AZ::Aabb entityStartBounds = AZ::Interface::Get()->GetEntityLocalBoundsUnion(GetEntity()->GetId()); + const AZ::Aabb entityFinalBounds = entityStartBounds.GetTranslated(velocity); + AZ::Aabb entitySweptBounds = entityStartBounds; + entitySweptBounds.AddAabb(entityFinalBounds); + Multiplayer::GetNetworkTime()->SyncEntitiesToRewindState(entitySweptBounds); + } + + if ((GetParent().m_physicsCharacter == nullptr) || (velocity.GetLengthSq() <= 0.0f)) + { + return GetEntity()->GetTransform()->GetWorldTranslation(); + } + GetParent().m_physicsCharacter->AddVelocity(velocity); + GetParent().m_physicsCharacter->ApplyRequestedVelocity(deltaTime); + GetEntity()->GetTransform()->SetWorldTranslation(GetParent().m_physicsCharacter->GetBasePosition()); + AZLOG + ( + NET_Movement, + "Moved to position %f x %f x %f", + GetParent().m_physicsCharacter->GetBasePosition().GetX(), + GetParent().m_physicsCharacter->GetBasePosition().GetY(), + GetParent().m_physicsCharacter->GetBasePosition().GetZ() + ); + return GetEntity()->GetTransform()->GetWorldTranslation(); + } +} diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index ca5a52579c..54311a0abc 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -18,6 +18,7 @@ set(FILES Include/Multiplayer/Components/MultiplayerController.h Include/Multiplayer/Components/MultiplayerComponentRegistry.h Include/Multiplayer/Components/NetBindComponent.h + Include/Multiplayer/Components/NetworkCharacterComponent.h Include/Multiplayer/Components/NetworkHitVolumesComponent.h Include/Multiplayer/Components/NetworkRigidBodyComponent.h Include/Multiplayer/Components/NetworkTransformComponent.h @@ -53,6 +54,7 @@ set(FILES Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml Source/AutoGen/Multiplayer.AutoPackets.xml Source/AutoGen/MultiplayerEditor.AutoPackets.xml + Source/AutoGen/NetworkCharacterComponent.AutoComponent.xml Source/AutoGen/NetworkHitVolumesComponent.AutoComponent.xml Source/AutoGen/NetworkRigidBodyComponent.AutoComponent.xml Source/AutoGen/NetworkTransformComponent.AutoComponent.xml @@ -61,6 +63,7 @@ set(FILES Source/Components/MultiplayerController.cpp Source/Components/MultiplayerComponentRegistry.cpp Source/Components/NetBindComponent.cpp + Source/Components/NetworkCharacterComponent.cpp Source/Components/NetworkHitVolumesComponent.cpp Source/Components/NetworkRigidBodyComponent.cpp Source/Components/NetworkTransformComponent.cpp From 988a6b7443c0d6dd69e0765bc57429a950c01972 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 14 Sep 2021 10:29:20 -0700 Subject: [PATCH 111/274] PR comments Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/std/string/regex.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/string/regex.h b/Code/Framework/AzCore/AzCore/std/string/regex.h index e20f67905c..3d4a2a0b38 100644 --- a/Code/Framework/AzCore/AzCore/std/string/regex.h +++ b/Code/Framework/AzCore/AzCore/std/string/regex.h @@ -215,6 +215,7 @@ namespace AZStd struct ErrorSink { + virtual ~ErrorSink() = default; virtual void RegexError(regex_constants::error_type code) = 0; }; } @@ -1079,7 +1080,7 @@ namespace AZStd NodeBase* m_next; NodeBase* m_previous; - virtual ~NodeBase() { } + virtual ~NodeBase() = default; }; inline void DestroyNode(NodeBase* node, NodeBase* end = nullptr) @@ -1758,7 +1759,7 @@ namespace AZStd return (*this); } - virtual ~basic_regex() + ~basic_regex() override { // destroy the object Clear(); } @@ -2916,7 +2917,7 @@ namespace AZStd } template - inline NodeBase* Builder::BeginGroup(void) + inline NodeBase* Builder::BeginGroup() { // add group node return (NewNode(NT_group)); } @@ -3026,7 +3027,7 @@ namespace AZStd } template - inline RootNode* Builder::EndPattern(void) + inline RootNode* Builder::EndPattern() { // wrap up NewNode(NT_end); return m_root; From a91ea7d549eaefe55b1ffa08ecc0167d866fa576 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Tue, 14 Sep 2021 13:04:52 -0500 Subject: [PATCH 112/274] Removed unused EngineJson.cmake file (#4107) Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- cmake/EngineJson.cmake | 45 ----------------------------------------- cmake/cmake_files.cmake | 2 +- 2 files changed, 1 insertion(+), 46 deletions(-) delete mode 100644 cmake/EngineJson.cmake diff --git a/cmake/EngineJson.cmake b/cmake/EngineJson.cmake deleted file mode 100644 index f175ff5a8b..0000000000 --- a/cmake/EngineJson.cmake +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# -# This file is copied during engine registration. Edits to this file will be lost next -# time a registration happens. - -include_guard() - -set(LY_EXTERNAL_SUBDIRS "" CACHE STRING "Additional list of subdirectory to recurse into via the cmake `add_subdirectory()` command. \ - The subdirectories are included after the restricted platform folders have been visited by a call to `add_subdirectory(restricted/\${restricted_platform})`") - -#! read_engine_external_subdirs -# Read the external subdirectories from the engine.json file -# External subdirectories are any folders with CMakeLists.txt in them -# This could be regular subdirectories, Gems(contains an additional gem.json), -# Restricted folders(contains an additional restricted.json), etc... -# \arg:output_external_subdirs name of output variable to store external subdirectories into -function(read_engine_external_subdirs output_external_subdirs) - ly_file_read(${LY_ROOT_FOLDER}/engine.json engine_json_data) - string(JSON external_subdirs_count ERROR_VARIABLE engine_json_error - LENGTH ${engine_json_data} "external_subdirectories") - if(engine_json_error) - message(FATAL_ERROR "Error querying number of elements in JSON array \"external_subdirectories\": ${engine_json_error}") - endif() - - if(external_subdirs_count GREATER 0) - math(EXPR external_subdir_range "${external_subdirs_count}-1") - # Convert the paths the relative paths to absolute paths using the engine root - # as the base directory - foreach(external_subdir_index RANGE ${external_subdir_range}) - string(JSON external_subdir ERROR_VARIABLE engine_json_error - GET ${engine_json_data} "external_subdirectories" "${external_subdir_index}") - if(engine_json_error) - message(FATAL_ERROR "Error reading field at index ${external_subdir_index} in \"external_subdirectories\" JSON array: ${engine_json_error}") - endif() - file(REAL_PATH ${external_subdir} real_external_subdir BASE_DIRECTORY ${CMAKE_SOURCE_DIR}) - list(APPEND external_subdirs ${real_external_subdir}) - endforeach() - endif() - set(${output_external_subdirs} ${external_subdirs} PARENT_SCOPE) -endfunction() diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index aa275b634a..caeab9d12e 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -15,7 +15,6 @@ set(FILES Configurations.cmake Dependencies.cmake Deployment.cmake - EngineJson.cmake FileUtil.cmake Findo3de.cmake Gems.cmake @@ -28,6 +27,7 @@ set(FILES LYPython.cmake LYWrappers.cmake Monolithic.cmake + O3DEJson.cmake OutputDirectory.cmake Packaging.cmake PAL.cmake From 73b04d7e34f1049f5d535e6bb7e7045c9ea41f9d Mon Sep 17 00:00:00 2001 From: Gene Walters <32776221+AMZN-Gene@users.noreply.github.com> Date: Tue, 14 Sep 2021 12:01:32 -0700 Subject: [PATCH 113/274] Network Input Exposed to Script (#3990) * NetworkInput now has new attribute called ExposeToScript. NetworkInput with this attribute set to True will be exposed to behavior context. Also added a CreateFromValues for the NetworkInput where scripters can create an instance of the MyComponentNetworkInput class which will eventually be passed around CreateInput and ProcessInput events. Signed-off-by: Gene Walters * Adding Create Input event handler. SC can now receive the event to create input, and send it over the network Signed-off-by: Gene Walters * Auto-component controller will now generate CreateInput/ProcessInput methods if they have input exposed to script, not ready for use yet, just stubbed in Signed-off-by: Gene Walters * Reducing code replication by putting common network input variables into AutoComponent_Common.jinja Signed-off-by: Gene Walters * Fix minor comment typo in the CreateInput method Signed-off-by: Gene Walters * Small fix. Changing ebus call from MyComponentNameCreateInput to just CreateInput. It's part of the MyComponentRequestBus so adding the component name before CreateInput is noisy Signed-off-by: Gene Walters * Cleaning with jinja a bit using macro calls to iterate over scriptable netinputs Signed-off-by: Gene Walters * ProcessInput will now be triggered in script Signed-off-by: Gene Walters * ProcessInput event is sent to script. Script can now create and process input. Tested locally with a simple script. Signed-off-by: Gene Walters * Created a seperate CreateInputFromScript and ProcessInputFromScript. Developers no longer need to remember to call the BaseClass::CreateInput and ProcessInput since CreateInputFromScript will automatically be called beforehand. Signed-off-by: Gene Walters --- .../Components/MultiplayerController.h | 12 +++ .../Source/AutoGen/AutoComponent_Common.jinja | 60 +++++++++++++- .../Source/AutoGen/AutoComponent_Header.jinja | 56 ++++++++++++- .../Source/AutoGen/AutoComponent_Source.jinja | 82 +++++++++++++++++-- .../Source/Components/NetBindComponent.cpp | 2 + 5 files changed, 204 insertions(+), 8 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h index 2467b0566d..545706db4b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/MultiplayerController.h @@ -89,11 +89,23 @@ namespace Multiplayer //! @param deltaTime amount of time to integrate the provided inputs over virtual void ProcessInput(NetworkInput& networkInput, float deltaTime) = 0; + //! Similar to ProcessInput, do not call directly. + //! This only needs to be overridden in components which allow NetworkInput to be processed by script. + //! @param networkInput input structure to process + //! @param deltaTime amount of time to integrate the provided inputs over + virtual void ProcessInputFromScript([[maybe_unused]] NetworkInput& networkInput, [[maybe_unused]] float deltaTime){} + //! Only valid on a client, should never be invoked on the server. //! @param networkInput input structure to process //! @param deltaTime amount of time to integrate the provided inputs over virtual void CreateInput(NetworkInput& networkInput, float deltaTime) = 0; + //! Similar to CreateInput, should never be invoked on the server. + //! This only needs to be overridden in components which allow NetworkInput creation to be handled by scripts. + //! @param networkInput input structure to process + //! @param deltaTime amount of time to integrate the provided inputs over + virtual void CreateInputFromScript([[maybe_unused]]NetworkInput& networkInput, [[maybe_unused]] float deltaTime) {} + template const ComponentType* FindComponent() const; diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja index 811039feda..5bf0a4823f 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Common.jinja @@ -252,7 +252,44 @@ void Signal{{ PropertyName }}({{ ', '.join(paramDefines) }}); {# #} -{%- macro EmitDerivedClassesComment(dataFileNames, Component, ComponentName, ComponentNameBase, ComponentDerived, ControllerName, ControllerNameBase, ControllerDerived, NetworkInputCount) -%} +{% macro GetNetworkInputCount(Component) -%} +{{ Component.findall('NetworkInput') | len }} +{%- endmacro -%} +{# + +#} +{% macro ParseNetworkInputsExposedToScript(Component) -%} +{% set NetworkInputsExposedToScript = namespace(value=0) %} +{% for netInput in Component.findall('NetworkInput') %} +{% if ('ExposeToScript' in netInput.attrib) and (netInput.attrib['ExposeToScript'] |booleanTrue) %} +{{ caller(netInput) -}} +{% endif %} +{% endfor %} +{%- endmacro -%} +{# + +#} +{% macro GetNetworkInputsExposedToScriptCount(Component) -%} +{% set NetworkInputsExposedToScript = namespace(value=0) %} +{% call (netInput) ParseNetworkInputsExposedToScript(Component) %} +{% set NetworkInputsExposedToScript.value = NetworkInputsExposedToScript.value + 1 %} +{% endcall %} +{{ NetworkInputsExposedToScript.value }} +{%- endmacro -%} +{# + +#} +{% macro GetCommaSeparatedParamListOfScriptableNetworkInputs(Component) -%} +{% set parameters = [] %} +{% call (netInput) ParseNetworkInputsExposedToScript(Component) %} +{% set parameters = parameters.append(netInput.attrib['Type'] + ' ' + LowerFirst(netInput.attrib['Name'])) %} +{% endcall %} +{{ parameters | join(', ') }} +{%- endmacro -%} +{# + +#} +{%- macro EmitDerivedClassesComment(dataFileNames, Component, ComponentName, ComponentNameBase, ComponentDerived, ControllerName, ControllerNameBase, ControllerDerived) -%} {% if ComponentDerived or ControllerDerived %} /* /// You may use the classes below as a basis for your new derived classes. Derived classes must be marked in {{ (dataFileNames[0] | basename) }} @@ -293,7 +330,16 @@ namespace {{ Component.attrib['Namespace'] }} void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; +{% set NetworkInputCount = GetNetworkInputCount(Component) | int %} {% if NetworkInputCount > 0 %} + + //! Common input creation logic for the NetworkInput. + //! Fill out the input struct and the MultiplayerInputDriver will send the input data over the network + //! to ensure it's processed. + //! @param input input structure which to store input data for sending to the authority + //! @param deltaTime amount of time to integrate the provided inputs over + void CreateInput(Multiplayer::NetworkInput& input, float deltaTime) override; + //! Common input processing logic for the NetworkInput. //! @param input input structure to process //! @param deltaTime amount of time to integrate the provided inputs over @@ -366,6 +412,18 @@ namespace {{ Component.attrib['Namespace'] }} { } {% if NetworkInputCount > 0 %} +{% set net_input_parameters_name = [] %} +{% call (netInput) ParseNetworkInputsExposedToScript(Component) %} +{% set net_input_parameters_name = net_input_parameters_name.append(LowerFirst(netInput.attrib['Name'])) %} +{% endcall %} + + void {{ ControllerName }}::CreateInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) + { +{% if (GetNetworkInputsExposedToScriptCount(Component) | int) > 0 %} + // Remember the following NetworkInputs have been exposed to script: {{ net_input_parameters_name|join(', ') }}. + // If a script is handling these inputs they will have already be filled out by now. +{% endif %} + } void {{ ControllerName }}::ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) { diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja index 8cde9613b7..0f62da11f3 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja @@ -230,7 +230,8 @@ AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] } {% if ControllerDerived %} {% set ControllerBaseName = ControllerName + "Base" %} {% endif %} -{% set NetworkInputCount = Component.findall('NetworkInput') | len %} +{% set NetworkInputCount = AutoComponentMacros.GetNetworkInputCount(Component) | int %} +{% set NetworkInputsExposedToScriptCount = AutoComponentMacros.GetNetworkInputsExposedToScriptCount(Component) | int %} {% set NetworkPropertyCount = Component.findall('NetworkProperty') | len %} {% set RpcCount = Component.findall('RemoteProcedure') | len %} #include "AutoComponentTypes.h" @@ -250,6 +251,10 @@ AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] } {% call(Include) AutoComponentMacros.ParseIncludes(Component) %} #include <{{ Include.attrib['File'] }}> {% endcall %} +{% if NetworkInputsExposedToScriptCount > 0 %} +#include +{% endif %} + {% for Service in Component.iter('ComponentRelation') %} {% if Service.attrib['Constraint'] != 'Incompatible' %} @@ -263,7 +268,7 @@ namespace {{ Service.attrib['Namespace'] }} {% endif %} {% endfor %} -{{ AutoComponentMacros.EmitDerivedClassesComment(dataFileNames, Component, ComponentName, ComponentBaseName, ComponentDerived, ControllerName, ControllerBaseName, ControllerDerived, NetworkInputCount) }} +{{ AutoComponentMacros.EmitDerivedClassesComment(dataFileNames, Component, ComponentName, ComponentBaseName, ComponentDerived, ControllerName, ControllerBaseName, ControllerDerived) }} namespace {{ Component.attrib['Namespace'] }} { //! Forward declarations @@ -337,6 +342,13 @@ namespace {{ Component.attrib['Namespace'] }} : public Multiplayer::IMultiplayerComponentInput { public: +{% if NetworkInputsExposedToScriptCount > 0 %} + AZ_TYPE_INFO({{ ComponentName }}NetworkInput, "{{ (ComponentName ~ "NetworkInput") | createHashGuid }}") + {{ ComponentName }}NetworkInput() = default; + {{ ComponentName }}NetworkInput({{ AutoComponentMacros.GetCommaSeparatedParamListOfScriptableNetworkInputs(Component) }}); + static void Reflect(AZ::ReflectContext* context); + +{% endif%} Multiplayer::NetComponentId GetNetComponentId() const override; bool Serialize(AzNetworking::ISerializer& serializer) override; Multiplayer::IMultiplayerComponentInput& operator =(const Multiplayer::IMultiplayerComponentInput& rhs) override; @@ -348,7 +360,41 @@ namespace {{ Component.attrib['Namespace'] }} static Multiplayer::NetComponentId s_netComponentId; friend void RegisterMultiplayerComponents(); }; +{% if NetworkInputsExposedToScriptCount > 0 %} + + class {{ ComponentName }}Requests + : public AZ::ComponentBus + { + public: + AZ_RTTI({{ ComponentName }}Requests, "{{ (ComponentName ~ "Requests") | createHashGuid }}") + + virtual {{ ComponentName }}NetworkInput CreateInput(float deltaTime) = 0; + virtual void ProcessInput({{ ComponentName }}NetworkInput* networkInput, float deltaTime) = 0; + }; + + using {{ ComponentName }}RequestBus = AZ::EBus<{{ ComponentName }}Requests>; + + class {{ ComponentName }}BusHandler final + : public {{ ComponentName }}RequestBus::Handler + , public AZ::BehaviorEBusHandler + { + public: + AZ_EBUS_BEHAVIOR_BINDER({{ ComponentName }}BusHandler, "{{ (ComponentName ~ "BusHandler") | createHashGuid }}", AZ::SystemAllocator, CreateInput, ProcessInput) + + {{ ComponentName }}NetworkInput CreateInput(float deltaTime) override + { + {{ ComponentName }}NetworkInput result; + CallResult(result, FN_CreateInput, deltaTime); + return result; + } + + void ProcessInput({{ ComponentName }}NetworkInput* networkInput, float deltaTime) override + { + Call(FN_ProcessInput, networkInput, deltaTime); + } + }; +{% endif %} {% endif %} class {{ ControllerBaseName }}{% if not ControllerDerived %} final{% endif %}{{ "" }} : public Multiplayer::MultiplayerController @@ -373,8 +419,14 @@ namespace {{ Component.attrib['Namespace'] }} //! MultiplayerController interface //! @{ Multiplayer::MultiplayerController::InputPriorityOrder GetInputOrder() const override { return Multiplayer::MultiplayerController::InputPriorityOrder::Default; } + +{% if NetworkInputsExposedToScriptCount > 0 %} + void CreateInputFromScript([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) final; + void ProcessInputFromScript([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) final; +{% endif %} void CreateInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) override {} void ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) override {} + //! @} {{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Server', false)|indent(8) -}} diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index d8e729afd6..e57e8dad2f 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1152,7 +1152,8 @@ m_{{ LowerFirst(Property.attrib['Name']) }} = m_{{ LowerFirst(Property.attrib['N {% else %} {% set ControllerBaseName = ControllerName %} {% endif %} -{% set NetworkInputCount = Component.findall('NetworkInput') | len %} +{% set NetworkInputCount = AutoComponentMacros.GetNetworkInputCount(Component) | int %} +{% set NetworkInputsExposedToScriptCount = AutoComponentMacros.GetNetworkInputsExposedToScriptCount(Component) | int %} {% set NetworkPropertyCount = Component.findall('NetworkProperty') | len %} {% set RpcCount = Component.findall('RemoteProcedure') | len %} #include "{{ includeFile }}" @@ -1299,6 +1300,56 @@ namespace {{ Component.attrib['Namespace'] }} } {% if NetworkInputCount > 0 %} +{% set ScriptableNetworkInputParamNames = [] %} +{% call(netInput) AutoComponentMacros.ParseNetworkInputsExposedToScript(Component) %} +{% set ScriptableNetworkInputParamNames = ScriptableNetworkInputParamNames.append(LowerFirst(netInput.attrib['Name'])) %} +{% endcall %} +{% if NetworkInputsExposedToScriptCount > 0 %} + {{ ComponentName }}NetworkInput Construct{{ ComponentName }}NetworkInput({{ AutoComponentMacros.GetCommaSeparatedParamListOfScriptableNetworkInputs(Component) }}) + { + return {{ ComponentName }}NetworkInput({{ ScriptableNetworkInputParamNames|join(', ') }}); + } + + {{ ComponentName }}NetworkInput::{{ ComponentName }}NetworkInput({{ AutoComponentMacros.GetCommaSeparatedParamListOfScriptableNetworkInputs(Component) }}) + : {% for param_name in ScriptableNetworkInputParamNames %}m_{{ LowerFirst(param_name) }}({{ LowerFirst(param_name) }}){% if not loop.last %}, {% endif %}{% endfor -%}{} + + void {{ ComponentName }}NetworkInput::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class<{{ ComponentName }}NetworkInput>() + ->Version(1) + ; + } + + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class<{{ ComponentName }}NetworkInput>("{{ ComponentName }}NetworkInput") + ->Attribute(AZ::Script::Attributes::Module, "{{ LowerFirst(Component.attrib['Namespace']) }}") + ->Attribute(AZ::Script::Attributes::Category, "{{ UpperFirst(Component.attrib['Namespace']) }}") +{% set ScriptableNetInputNames = [] %} +{% call (netInput) AutoComponentMacros.ParseNetworkInputsExposedToScript(Component) %} +{% set ScriptableNetInputNames = ScriptableNetInputNames.append(netInput.attrib['Name']) %} +{% endcall %} + ->Method("CreateFromValues", &Construct{{ ComponentName }}NetworkInput, { { {% for param_name in ScriptableNetInputNames %}{"{{ LowerFirst(param_name) }}"}{% if not loop.last %}, {% endif %}{% endfor -%} } }) + +{% for param_name in ScriptableNetInputNames %} + ->Property("{{ param_name }}", BehaviorValueProperty(&{{ ComponentName }}NetworkInput::m_{{ LowerFirst(param_name) }})) +{% endfor %} + ; + + behaviorContext->EBus<{{ ComponentName }}RequestBus>("{{ ComponentName }}BusHandler") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Module, "{{ LowerFirst(Component.attrib['Namespace']) }}") + ->Attribute(AZ::Script::Attributes::Category, "{{ UpperFirst(Component.attrib['Namespace']) }}") + ->Handler<{{ ComponentName }}BusHandler>() + ; + } + } +{% endif %} + Multiplayer::NetComponentId {{ ComponentName }}NetworkInput::GetNetComponentId() const { return {{ ComponentName }}NetworkInput::s_netComponentId; @@ -1347,6 +1398,26 @@ namespace {{ Component.attrib['Namespace'] }} {% endif %} } +{% if NetworkInputsExposedToScriptCount > 0 %} + void {{ ControllerBaseName }}::CreateInputFromScript([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) + { + {{ ComponentName }}NetworkInput result; + {{ ComponentName }}RequestBus::EventResult(result, GetEntity()->GetId(), &{{ ComponentName }}RequestBus::Events::CreateInput, deltaTime); + + // Inputs for your own component always exist + {{ ComponentName }}NetworkInput* {{ LowerFirst(ComponentName) }}Input = input.FindComponentInput<{{ ComponentName }}NetworkInput>(); +{% call(netInput) AutoComponentMacros.ParseNetworkInputsExposedToScript(Component) %} + {{ LowerFirst(ComponentName) }}Input->m_{{ LowerFirst(netInput.attrib['Name']) }} = result.m_{{ LowerFirst(netInput.attrib['Name']) }}; +{% endcall %} + } + + void {{ ControllerBaseName }}::ProcessInputFromScript([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) + { + {{ ComponentName }}NetworkInput* {{ LowerFirst(ComponentName) }}Input = input.FindComponentInput<{{ ComponentName }}NetworkInput>(); + {{ ComponentName }}RequestBus::Event(GetEntity()->GetId(), &{{ ComponentName }}RequestBus::Events::ProcessInput, {{ LowerFirst(ComponentName) }}Input, deltaTime); + } +{% endif %} + const {{ ComponentName }}& {{ ControllerBaseName }}::GetParent() const { return static_cast(GetOwner()); @@ -1399,6 +1470,9 @@ namespace {{ Component.attrib['Namespace'] }} } ReflectToEditContext(context); ReflectToBehaviorContext(context); +{% if NetworkInputsExposedToScriptCount > 0 %} + {{ ComponentName }}NetworkInput::Reflect(context); +{% endif %} } void {{ ComponentBaseName }}::ReflectToEditContext(AZ::ReflectContext* context) @@ -1448,8 +1522,8 @@ namespace {{ Component.attrib['Namespace'] }} {{ DefineNetworkPropertyBehaviorReflection(Component, 'Authority', 'Server', ComponentName) | indent(16) -}} {{ DefineNetworkPropertyBehaviorReflection(Component, 'Authority', 'Client', ComponentName) | indent(16) -}} {{ DefineNetworkPropertyBehaviorReflection(Component, 'Authority', 'Autonomous', ComponentName) | indent(16) -}} - {{ DefineNetworkPropertyBehaviorReflection(Component, 'Autonomous', 'Authority', ComponentName) | indent(16) -}} - + {{ DefineNetworkPropertyBehaviorReflection(Component, 'Autonomous', 'Authority', ComponentName) | indent(16) }} + // Reflect RPCs {{ ReflectRpcInvocations(Component, ComponentName, 'Server', 'Authority')|indent(4) -}} {{ ReflectRpcInvocations(Component, ComponentName, 'Autonomous', 'Authority')|indent(4) -}} @@ -1459,7 +1533,6 @@ namespace {{ Component.attrib['Namespace'] }} {{ ReflectRpcEvents(Component, ComponentName, 'Autonomous', 'Authority')|indent(4) -}} {{ ReflectRpcEvents(Component, ComponentName, 'Authority', 'Autonomous')|indent(4) -}} {{ ReflectRpcEvents(Component, ComponentName, 'Authority', 'Client')|indent(4) -}} - {{- DefineArchetypePropertyBehaviorReflection(Component, ComponentName) | indent(16) }} ; } @@ -1508,7 +1581,6 @@ namespace {{ Component.attrib['Namespace'] }} } {{ ComponentBaseName }}::{{ ComponentBaseName }}() = default; - {{ ComponentBaseName }}::~{{ ComponentBaseName }}() = default; void {{ ComponentBaseName }}::Init() diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index d8e8a765ce..43577525c0 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -278,6 +278,7 @@ namespace Multiplayer AZ_Assert(IsNetEntityRoleAutonomous(), "Incorrect network role for input creation"); for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) { + multiplayerComponent->GetController()->CreateInputFromScript(networkInput, deltaTime); multiplayerComponent->GetController()->CreateInput(networkInput, deltaTime); } } @@ -289,6 +290,7 @@ namespace Multiplayer AZ_Assert((NetworkRoleHasController(m_netEntityRole)), "Incorrect network role for input processing"); for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector) { + multiplayerComponent->GetController()->ProcessInputFromScript(networkInput, deltaTime); multiplayerComponent->GetController()->ProcessInput(networkInput, deltaTime); } m_isProcessingInput = false; From ae735ad3381d0d51c3b11647c5828d8c5504ec7f Mon Sep 17 00:00:00 2001 From: Jonny Gallowy Date: Tue, 14 Sep 2021 14:26:50 -0500 Subject: [PATCH 114/274] new postfx layer categories and ordering values Signed-off-by: Jonny Gallowy --- .../PostProcess/default.postfxlayercategories | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/PostProcess/default.postfxlayercategories b/Gems/AtomLyIntegration/CommonFeatures/Assets/PostProcess/default.postfxlayercategories index 33adccfd33..d6bffb0e6a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/PostProcess/default.postfxlayercategories +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/PostProcess/default.postfxlayercategories @@ -1,17 +1,30 @@ + - - + + - - + + + + + + + + + + - + + + + + From c0426ba465dfd002a7cfded7b15ad953a1ec56d0 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 14 Sep 2021 12:35:56 -0700 Subject: [PATCH 115/274] PerScreenDpi | QLabels incorrectly handle scale for icons (#4070) * Fixes to icon generation. Generating a pixmap out of a size won't take the screen scaling factor into account, resulting in blurry results. Note that this is not a catchall solution, every case needs to be addressed manually. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * HighDpi fixes for startup splashscreen and About dialog Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Add helper function to generate appropriate pixmaps for a screen based on its dpi settings. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- Code/Editor/AboutDialog.cpp | 10 ++++-- Code/Editor/StartupLogoDialog.cpp | 17 +++++----- .../WelcomeScreen/WelcomeScreenDialog.cpp | 6 +++- .../Utilities/PixmapScaleUtilities.cpp | 31 +++++++++++++++++++ .../Utilities/PixmapScaleUtilities.h | 19 ++++++++++++ .../AzQtComponents/azqtcomponents_files.cmake | 2 ++ .../EditorEntityUiHandlerBase.cpp | 4 +-- .../EditorEntityUiHandlerBase.h | 2 +- .../UI/Layer/LayerUiHandler.cpp | 4 +-- .../UI/Layer/LayerUiHandler.h | 2 +- .../UI/Outliner/EntityOutlinerListModel.cpp | 14 ++++----- .../UI/Prefab/LevelRootUiHandler.cpp | 4 +-- .../UI/Prefab/LevelRootUiHandler.h | 2 +- .../UI/Prefab/PrefabUiHandler.cpp | 6 ++-- .../UI/Prefab/PrefabUiHandler.h | 2 +- 15 files changed, 94 insertions(+), 31 deletions(-) create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h diff --git a/Code/Editor/AboutDialog.cpp b/Code/Editor/AboutDialog.cpp index f8abe67376..2c76526731 100644 --- a/Code/Editor/AboutDialog.cpp +++ b/Code/Editor/AboutDialog.cpp @@ -20,6 +20,7 @@ // AzCore #include // for aznumeric_cast +#include AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include @@ -46,8 +47,13 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice, CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }"); // Prepare background image - QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")); - m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi( + QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")), + screen(), + QSize(m_enforcedWidth, m_enforcedHeight), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation + ); // Draw the Open 3D Engine logo from svg m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); diff --git a/Code/Editor/StartupLogoDialog.cpp b/Code/Editor/StartupLogoDialog.cpp index d9625aff1a..ab251b1564 100644 --- a/Code/Editor/StartupLogoDialog.cpp +++ b/Code/Editor/StartupLogoDialog.cpp @@ -9,11 +9,11 @@ // Description : implementation file - #include "EditorDefs.h" - #include "StartupLogoDialog.h" +#include + // Qt #include #include @@ -22,8 +22,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - ///////////////////////////////////////////////////////////////////////////// // CStartupLogoDialog dialog @@ -36,13 +34,16 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy m_ui->setupUi(this); s_pLogoWindow = this; - - m_backgroundImage = QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")); setFixedSize(QSize(600, 300)); // Prepare background image - QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")); - m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi( + QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")), + screen(), + QSize(m_enforcedWidth, m_enforcedHeight), + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation + ); // Draw the Open 3D Engine logo from svg m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg")); diff --git a/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp b/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp index 0f73023acf..17f576b5ee 100644 --- a/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp +++ b/Code/Editor/WelcomeScreen/WelcomeScreenDialog.cpp @@ -34,6 +34,7 @@ // AzQtComponents #include #include +#include // Editor #include "Settings.h" @@ -79,8 +80,11 @@ WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent) { projectPreviewPath = ":/WelcomeScreenDialog/DefaultProjectImage.png"; } + ui->activeProjectIcon->setPixmap( - QPixmap(projectPreviewPath).scaled( + AzQtComponents::ScalePixmapForScreenDpi( + QPixmap(projectPreviewPath), + screen(), ui->activeProjectIcon->size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp new file mode 100644 index 0000000000..fa32b708d7 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include + +namespace AzQtComponents +{ + QPixmap ScalePixmapForScreenDpi( + QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode) + { + qreal screenDpiFactor = QHighDpiScaling::factor(screen); + pixmap.setDevicePixelRatio(screenDpiFactor); + + QPixmap scaledPixmap; + + size.setWidth(aznumeric_cast(aznumeric_cast(size.width()) * screenDpiFactor)); + size.setHeight(aznumeric_cast(aznumeric_cast(size.height()) * screenDpiFactor)); + + scaledPixmap = pixmap.scaled(size, aspectRatioMode, transformationMode); + + return scaledPixmap; + } +} diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h new file mode 100644 index 0000000000..4b083855d5 --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Utilities/PixmapScaleUtilities.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include +#include + +namespace AzQtComponents +{ + AZ_QT_COMPONENTS_API QPixmap ScalePixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode); +}; // namespace AzQtComponents diff --git a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake index c214b81405..8219ab04b2 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake @@ -276,6 +276,8 @@ set(FILES Utilities/HandleDpiAwareness.cpp Utilities/HandleDpiAwareness.h Utilities/MouseHider.h + Utilities/PixmapScaleUtilities.cpp + Utilities/PixmapScaleUtilities.h Utilities/QtPluginPaths.cpp Utilities/QtPluginPaths.h Utilities/QtWindowUtilities.cpp diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp index f0462532e6..a0da20ebf0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp @@ -47,9 +47,9 @@ namespace AzToolsFramework return QString(); } - QPixmap EditorEntityUiHandlerBase::GenerateItemIcon(AZ::EntityId /*entityId*/) const + QIcon EditorEntityUiHandlerBase::GenerateItemIcon(AZ::EntityId /*entityId*/) const { - return QPixmap(); + return QIcon(); } bool EditorEntityUiHandlerBase::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h index e7008b7abf..c37b099272 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h @@ -40,7 +40,7 @@ namespace AzToolsFramework //! Returns the item tooltip text to display in the Outliner. virtual QString GenerateItemTooltip(AZ::EntityId entityId) const; //! Returns the item icon pixmap to display in the Outliner. - virtual QPixmap GenerateItemIcon(AZ::EntityId entityId) const; + virtual QIcon GenerateItemIcon(AZ::EntityId entityId) const; //! Returns whether the element's lock and visibility state should be accessible in the Outliner virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const; //! Returns whether the element's name should be editable diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.cpp index b0eee96abc..8a001bc04f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.cpp @@ -66,9 +66,9 @@ namespace AzToolsFramework return result; } - QPixmap LayerUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const + QIcon LayerUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const { - return QPixmap(m_layerIconPath); + return QIcon(m_layerIconPath); } void LayerUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.h index 56b62832ce..b1af9d694e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Layer/LayerUiHandler.h @@ -24,7 +24,7 @@ namespace AzToolsFramework // EditorEntityUiHandler... QString GenerateItemInfoString(AZ::EntityId entityId) const override; - QPixmap GenerateItemIcon(AZ::EntityId entityId) const override; + QIcon GenerateItemIcon(AZ::EntityId entityId) const override; void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QModelIndex& descendantIndex) const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index b9180f8ef6..d9f3ff8bb8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -280,17 +280,17 @@ namespace AzToolsFramework QVariant EntityOutlinerListModel::GetEntityIcon(const AZ::EntityId& id) const { auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(id); - QPixmap pixmap; + QIcon icon; // Retrieve the icon from the handler if (entityUiHandler != nullptr) { - pixmap = entityUiHandler->GenerateItemIcon(id); + icon = entityUiHandler->GenerateItemIcon(id); } - if (!pixmap.isNull()) + if (!icon.isNull()) { - return QIcon(pixmap); + return icon; } // If no icon was returned by the handler, use the default one. @@ -299,7 +299,7 @@ namespace AzToolsFramework if (isEditorOnly) { - return QIcon(QPixmap(QString(":/Icons/Entity_Editor_Only.svg"))); + return QIcon(QString(":/Icons/Entity_Editor_Only.svg")); } AZ::Entity* entity = nullptr; @@ -308,10 +308,10 @@ namespace AzToolsFramework if (!isInitiallyActive) { - return QIcon(QPixmap(QString(":/Icons/Entity_Not_Active.svg"))); + return QIcon(QString(":/Icons/Entity_Not_Active.svg")); } - return QIcon(QPixmap(QString(":/Icons/Entity.svg"))); + return QIcon(QString(":/Icons/Entity.svg")); } QVariant EntityOutlinerListModel::GetEntityTooltip(const AZ::EntityId& id) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp index 73a28a3edc..c75f6aa86d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp @@ -41,9 +41,9 @@ namespace AzToolsFramework } } - QPixmap LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const + QIcon LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const { - return QPixmap(m_levelRootIconPath); + return QIcon(m_levelRootIconPath); } QString LevelRootUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h index 29bb5a7d49..6eeccfe88d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h @@ -29,7 +29,7 @@ namespace AzToolsFramework ~LevelRootUiHandler() override = default; // EditorEntityUiHandler... - QPixmap GenerateItemIcon(AZ::EntityId entityId) const override; + QIcon GenerateItemIcon(AZ::EntityId entityId) const override; QString GenerateItemInfoString(AZ::EntityId entityId) const override; bool CanToggleLockVisibility(AZ::EntityId entityId) const override; bool CanRename(AZ::EntityId entityId) const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp index 1a9632b0e1..fda56b79f1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp @@ -81,14 +81,14 @@ namespace AzToolsFramework return tooltip; } - QPixmap PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const + QIcon PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const { if (m_prefabEditInterface->IsOwningPrefabBeingEdited(entityId)) { - return QPixmap(m_prefabEditIconPath); + return QIcon(m_prefabEditIconPath); } - return QPixmap(m_prefabIconPath); + return QIcon(m_prefabIconPath); } void PrefabUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h index 0d73fba049..d900fae427 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h @@ -31,7 +31,7 @@ namespace AzToolsFramework // EditorEntityUiHandler... QString GenerateItemInfoString(AZ::EntityId entityId) const override; QString GenerateItemTooltip(AZ::EntityId entityId) const override; - QPixmap GenerateItemIcon(AZ::EntityId entityId) const override; + QIcon GenerateItemIcon(AZ::EntityId entityId) const override; void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QModelIndex& descendantIndex) const override; From 2382b5cbd3bcf53f83807b0160c897b5c8a6fb9a Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Tue, 14 Sep 2021 12:42:16 -0700 Subject: [PATCH 116/274] Linux fix launch project manager from editor (#4105) Signed-off-by: Steve Pham --- .../Process/ProcessWatcher_Linux.cpp | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessWatcher_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessWatcher_Linux.cpp index 2d29fac73d..d2cd681012 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessWatcher_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Process/ProcessWatcher_Linux.cpp @@ -263,21 +263,29 @@ namespace AzFramework } commandAndArgs[commandTokens.size()] = nullptr; + AZStd::vector> environmentVariablesManaged; + AZStd::vector environmentVariablesVector; char** environmentVariables = nullptr; - int numEnvironmentVars = 0; if (processLaunchInfo.m_environmentVariables) { - numEnvironmentVars = processLaunchInfo.m_environmentVariables->size(); - // Adding one more as exec expects the array to have a nullptr as the last element - environmentVariables = new char*[numEnvironmentVars + 1]; - for (int i = 0; i < numEnvironmentVars; i++) + for (const auto& envVarString : *processLaunchInfo.m_environmentVariables) { - const AZStd::string& envVarString = processLaunchInfo.m_environmentVariables->at(i); - environmentVariables[i] = new char[envVarString.size() + 1]; - environmentVariables[i][0] = '\0'; - azstrcat(environmentVariables[i], envVarString.size(), envVarString.c_str()); + auto& environmentVariable = environmentVariablesManaged.emplace_back(AZStd::make_unique(envVarString.size() + 1)); + environmentVariable[0] = '\0'; + azstrcat(environmentVariable.get(), envVarString.size() + 1, envVarString.c_str()); + environmentVariablesVector.emplace_back(environmentVariable.get()); } - environmentVariables[numEnvironmentVars] = nullptr; + // Adding one more as exec expects the array to have a nullptr as the last element + environmentVariablesVector.emplace_back(nullptr); + environmentVariables = environmentVariablesVector.data(); + } + else + { + // If no environment variables were specified, then use the current process's environment variables + // and pass it along for the execute . + extern char **environ; // Defined in unistd.h + environmentVariables = ::environ; + AZ_Assert(environmentVariables, "Environment variables for current process not available\n"); } pid_t child_pid = fork(); @@ -290,15 +298,6 @@ namespace AzFramework // Close these handles as they are only to be used by the child process processData.m_startupInfo.CloseAllHandles(); - if (processLaunchInfo.m_environmentVariables) - { - for (int i = 0; i < numEnvironmentVars; i++) - { - delete [] environmentVariables[i]; - } - delete [] environmentVariables; - } - for (int i = 0; i < commandTokens.size(); i++) { delete [] commandAndArgs[i]; From e356003fb558374b6f1a2598cfe03a3fd3a49385 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 14 Sep 2021 14:10:17 -0700 Subject: [PATCH 117/274] Fixes for VS < 17 and Android Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h | 8 ++++---- Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h | 8 ++++---- cmake/Platform/Common/MSVC/Configurations_msvc.cmake | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h b/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h index bf49546916..414b1cb3cb 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h +++ b/Gems/LyShine/Code/Source/Animation/AnimSplineTrack.h @@ -326,16 +326,16 @@ public: m_defaultValue = value; } - ColorB GetCustomColor() const override + ColorB GetCustomColor() const { return m_customColor; } - void SetCustomColor(ColorB color) override + void SetCustomColor(ColorB color) { m_customColor = color; m_bCustomColorSet = true; } - bool HasCustomColor() const override + bool HasCustomColor() const { return m_bCustomColorSet; } - void ClearCustomColor() override + void ClearCustomColor() { m_bCustomColorSet = false; } static void Reflect(AZ::SerializeContext* serializeContext) {} diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h index d6f969b21d..6388c9709e 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h @@ -329,16 +329,16 @@ public: m_defaultValue = value; } - ColorB GetCustomColor() const override + ColorB GetCustomColor() const { return m_customColor; } - void SetCustomColor(ColorB color) override + void SetCustomColor(ColorB color) { m_customColor = color; m_bCustomColorSet = true; } - bool HasCustomColor() const override + bool HasCustomColor() const { return m_bCustomColorSet; } - void ClearCustomColor() override + void ClearCustomColor() { m_bCustomColorSet = false; } void SetMultiplier(float trackMultiplier) override diff --git a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake index 8885624a81..a4d8533626 100644 --- a/cmake/Platform/Common/MSVC/Configurations_msvc.cmake +++ b/cmake/Platform/Common/MSVC/Configurations_msvc.cmake @@ -141,7 +141,6 @@ endif() ly_set(LY_CXX_SYSTEM_INCLUDE_CONFIGURATION_FLAG /experimental:external # Turns on "external" headers feature for MSVC compilers /external:W0 # Set warning level in external headers to 0. This is used to suppress warnings 3rdParty libraries which uses the "system_includes" option in their json configuration - /analyze:external- # disable analysis on external headers ) if(NOT CMAKE_INCLUDE_SYSTEM_FLAG_CXX) ly_set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX /external:I) From 4e8d4c0c512b33ebb8697a72ebe30e55f32f1ef2 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Tue, 14 Sep 2021 16:15:46 -0500 Subject: [PATCH 118/274] Added a max_size function to all AZStd container style allocator functions (#4106) * Added a max_size function to all AZStd container style allocator functions The max_size functions returns the maximum value that a single contiguous allocation value returns Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the BestFitExternalMapSchema and MallocSchema GetMaxContiguousAllocationSize function Those functions now return a Max allocation size of AZ_CORE_MAX_ALLOCATOR size to indicate the maximum size for a single allocation Changed the IAllocatorAllocator::GetMaxContiguousAllocationSize function from a pure virtual function to regular virtual function Removed the left over String.cpp test to validate that the issue with the allocator::max_size() function was occuring Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AzCore/AzCore/EBus/Environment.h | 2 +- .../AzCore/Memory/AllocatorOverrideShim.cpp | 5 ++ .../AzCore/Memory/AllocatorOverrideShim.h | 1 + .../Memory/BestFitExternalMapAllocator.cpp | 5 ++ .../Memory/BestFitExternalMapAllocator.h | 1 + .../Memory/BestFitExternalMapSchema.cpp | 6 ++ .../AzCore/Memory/BestFitExternalMapSchema.h | 1 + .../AzCore/AzCore/Memory/HeapSchema.cpp | 5 ++ .../AzCore/AzCore/Memory/HeapSchema.h | 1 + .../AzCore/AzCore/Memory/HphaSchema.cpp | 11 ++++ .../AzCore/AzCore/Memory/HphaSchema.h | 1 + .../AzCore/AzCore/Memory/IAllocator.h | 2 + .../AzCore/AzCore/Memory/MallocSchema.cpp | 5 ++ .../AzCore/AzCore/Memory/MallocSchema.h | 1 + Code/Framework/AzCore/AzCore/Memory/Memory.h | 11 +++- .../AzCore/AzCore/Memory/OSAllocator.h | 1 + .../Memory/OverrunDetectionAllocator.cpp | 11 ++++ .../AzCore/Memory/OverrunDetectionAllocator.h | 1 + .../AzCore/AzCore/Memory/PoolSchema.cpp | 10 +++ .../AzCore/AzCore/Memory/PoolSchema.h | 2 + .../AzCore/Memory/SimpleSchemaAllocator.h | 5 ++ .../AzCore/AzCore/Memory/SystemAllocator.h | 1 + .../AzCore/AzCore/Module/Environment.cpp | 2 +- .../AzCore/AzCore/Script/ScriptContext.cpp | 4 +- .../AzCore/AzCore/UnitTest/TestTypes.h | 5 +- .../Framework/AzCore/AzCore/std/allocator.cpp | 10 +-- Code/Framework/AzCore/AzCore/std/allocator.h | 9 +-- .../AzCore/AzCore/std/allocator_ref.h | 2 +- .../AzCore/AzCore/std/allocator_stack.h | 2 +- .../AzCore/AzCore/std/allocator_static.h | 4 +- .../AzCore/AzCore/std/containers/deque.h | 7 +-- .../AzCore/std/containers/forward_list.h | 2 +- .../AzCore/AzCore/std/containers/list.h | 8 +-- .../AzCore/AzCore/std/containers/rbtree.h | 2 +- .../AzCore/std/containers/ring_buffer.h | 10 ++- .../AzCore/AzCore/std/containers/vector.h | 3 +- .../parallel/allocator_concurrent_static.h | 4 +- .../AzCore/AzCore/std/string/string.h | 4 +- .../AzCore/Tests/AZStd/Allocators.cpp | 63 ++++++++++--------- .../Tests/AZStd/ConcurrentAllocators.cpp | 14 ++--- Code/Framework/AzCore/Tests/Memory.cpp | 2 + .../Code/MCore/Source/StaticAllocator.cpp | 2 +- .../Code/MCore/Source/StaticAllocator.h | 2 +- 43 files changed, 166 insertions(+), 84 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/EBus/Environment.h b/Code/Framework/AzCore/AzCore/EBus/Environment.h index e5cec765be..93a0f714f9 100644 --- a/Code/Framework/AzCore/AzCore/EBus/Environment.h +++ b/Code/Framework/AzCore/AzCore/EBus/Environment.h @@ -96,7 +96,7 @@ namespace AZ const char* get_name() const { return m_name; } void set_name(const char* name) { m_name = name; } - size_type get_max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; } + constexpr size_type max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; } size_type get_allocated_size() const { return 0; } bool is_lock_free() { return false; } diff --git a/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.cpp b/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.cpp index 69fbe2a519..154d59edd3 100644 --- a/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.cpp @@ -216,6 +216,11 @@ namespace AZ return m_source->GetMaxAllocationSize(); } + auto AllocatorOverrideShim::GetMaxContiguousAllocationSize() const -> size_type + { + return m_source->GetMaxContiguousAllocationSize(); + } + IAllocatorAllocate* AllocatorOverrideShim::GetSubAllocator() { return m_source->GetSubAllocator(); diff --git a/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.h b/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.h index ae3859a938..3b45b9953e 100644 --- a/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.h +++ b/Code/Framework/AzCore/AzCore/Memory/AllocatorOverrideShim.h @@ -52,6 +52,7 @@ namespace AZ size_type NumAllocatedBytes() const override; size_type Capacity() const override; size_type GetMaxAllocationSize() const override; + size_type GetMaxContiguousAllocationSize() const override; IAllocatorAllocate* GetSubAllocator() override; private: diff --git a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.cpp b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.cpp index cf26c8f723..ca414df4b5 100644 --- a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.cpp @@ -188,6 +188,11 @@ BestFitExternalMapAllocator::GetMaxAllocationSize() const return m_schema->GetMaxAllocationSize(); } +auto BestFitExternalMapAllocator::GetMaxContiguousAllocationSize() const -> size_type +{ + return m_schema->GetMaxContiguousAllocationSize(); +} + //========================================================================= // GetSubAllocator // [1/28/2011] diff --git a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.h b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.h index 474619ad9f..17425625b7 100644 --- a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapAllocator.h @@ -63,6 +63,7 @@ namespace AZ size_type NumAllocatedBytes() const override; size_type Capacity() const override; size_type GetMaxAllocationSize() const override; + size_type GetMaxContiguousAllocationSize() const override; IAllocatorAllocate* GetSubAllocator() override; ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.cpp index d94d1dfe35..715ecd221e 100644 --- a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.cpp @@ -136,6 +136,12 @@ BestFitExternalMapSchema::GetMaxAllocationSize() const return 0; } +auto BestFitExternalMapSchema::GetMaxContiguousAllocationSize() const -> size_type +{ + // Return the maximum size of any single allocation + return AZ_CORE_MAX_ALLOCATOR_SIZE; +} + //========================================================================= // GarbageCollect // [1/28/2011] diff --git a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.h b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.h index 221407421f..eaab614593 100644 --- a/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/BestFitExternalMapSchema.h @@ -57,6 +57,7 @@ namespace AZ AZ_FORCE_INLINE size_type NumAllocatedBytes() const { return m_used; } AZ_FORCE_INLINE size_type Capacity() const { return m_desc.m_memoryBlockByteSize; } size_type GetMaxAllocationSize() const; + size_type GetMaxContiguousAllocationSize() const; AZ_FORCE_INLINE IAllocatorAllocate* GetSubAllocator() const { return m_desc.m_mapAllocator; } /** diff --git a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp index 50e6a47630..aceafa1b28 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.cpp @@ -244,6 +244,11 @@ namespace AZ return maxChunk; } + auto HeapSchema::GetMaxContiguousAllocationSize() const -> size_type + { + return MAX_REQUEST; + } + AZ_FORCE_INLINE HeapSchema::size_type HeapSchema::ChunckSize(pointer_type ptr) { diff --git a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h index af3e2d9986..f6c6f98315 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/HeapSchema.h @@ -57,6 +57,7 @@ namespace AZ virtual size_type NumAllocatedBytes() const { return m_used; } virtual size_type Capacity() const { return m_capacity; } virtual size_type GetMaxAllocationSize() const; + size_type GetMaxContiguousAllocationSize() const override; virtual IAllocatorAllocate* GetSubAllocator() { return m_subAllocator; } virtual void GarbageCollect() {} diff --git a/Code/Framework/AzCore/AzCore/Memory/HphaSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/HphaSchema.cpp index f5df0dfe96..6af8f201c2 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HphaSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/HphaSchema.cpp @@ -1069,6 +1069,7 @@ namespace AZ { /// returns allocation size for the pointer if it belongs to the allocator. result is undefined if the pointer doesn't belong to the allocator. size_t AllocationSize(void* ptr); size_t GetMaxAllocationSize() const; + size_t GetMaxContiguousAllocationSize() const; size_t GetUnAllocatedMemory(bool isPrint) const; void* SystemAlloc(size_t size, size_t align); @@ -2301,6 +2302,11 @@ namespace AZ { return maxSize; } + size_t HpAllocator::GetMaxContiguousAllocationSize() const + { + return AZ_CORE_MAX_ALLOCATOR_SIZE; + } + //========================================================================= // GetUnAllocatedMemory // [9/30/2013] @@ -2677,6 +2683,11 @@ namespace AZ { return m_allocator->GetMaxAllocationSize(); } + auto HphaSchema::GetMaxContiguousAllocationSize() const -> size_type + { + return m_allocator->GetMaxContiguousAllocationSize(); + } + //========================================================================= // GetUnAllocatedMemory // [9/30/2013] diff --git a/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h b/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h index fc10bcd768..0f84ca1e68 100644 --- a/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/HphaSchema.h @@ -66,6 +66,7 @@ namespace AZ virtual size_type NumAllocatedBytes() const; virtual size_type Capacity() const; virtual size_type GetMaxAllocationSize() const; + size_type GetMaxContiguousAllocationSize() const override; virtual size_type GetUnAllocatedMemory(bool isPrint = false) const; virtual IAllocatorAllocate* GetSubAllocator() { return m_desc.m_subAllocator; } diff --git a/Code/Framework/AzCore/AzCore/Memory/IAllocator.h b/Code/Framework/AzCore/AzCore/Memory/IAllocator.h index 02f08fe77f..1aa4cf70f5 100644 --- a/Code/Framework/AzCore/AzCore/Memory/IAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/IAllocator.h @@ -62,6 +62,8 @@ namespace AZ virtual size_type Capacity() const = 0; /// Returns max allocation size if possible. If not returned value is 0 virtual size_type GetMaxAllocationSize() const { return 0; } + /// Returns the maximum contiguous allocation size of a single allocation + virtual size_type GetMaxContiguousAllocationSize() const { return 0; } /** * Returns memory allocated by the allocator and available to the user for allocations. * IMPORTANT: this is not the overhead memory this is just the memory that is allocated, but not used. Example: the pool allocators diff --git a/Code/Framework/AzCore/AzCore/Memory/MallocSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/MallocSchema.cpp index 581b6f2d57..76a71e0f08 100644 --- a/Code/Framework/AzCore/AzCore/Memory/MallocSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/MallocSchema.cpp @@ -144,6 +144,11 @@ AZ::MallocSchema::size_type AZ::MallocSchema::GetMaxAllocationSize() const return 0xFFFFFFFFull; } +AZ::MallocSchema::size_type AZ::MallocSchema::GetMaxContiguousAllocationSize() const +{ + return AZ_CORE_MAX_ALLOCATOR_SIZE; +} + AZ::IAllocatorAllocate* AZ::MallocSchema::GetSubAllocator() { return nullptr; diff --git a/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h b/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h index 3a363cb069..cbf928e189 100644 --- a/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/MallocSchema.h @@ -50,6 +50,7 @@ namespace AZ virtual size_type NumAllocatedBytes() const override; virtual size_type Capacity() const override; virtual size_type GetMaxAllocationSize() const override; + virtual size_type GetMaxContiguousAllocationSize() const override; virtual IAllocatorAllocate* GetSubAllocator() override; virtual void GarbageCollect() override; diff --git a/Code/Framework/AzCore/AzCore/Memory/Memory.h b/Code/Framework/AzCore/AzCore/Memory/Memory.h index af175c7a64..d09003f3f0 100644 --- a/Code/Framework/AzCore/AzCore/Memory/Memory.h +++ b/Code/Framework/AzCore/AzCore/Memory/Memory.h @@ -839,6 +839,11 @@ namespace AZ return AZ::AllocatorInstance::Get().GetMaxAllocationSize(); } + size_type GetMaxContiguousAllocationSize() const override + { + return AZ::AllocatorInstance::Get().GetMaxContiguousAllocationSize(); + } + size_type GetUnAllocatedMemory(bool isPrint = false) const override { return AZ::AllocatorInstance::Get().GetUnAllocatedMemory(isPrint); @@ -896,7 +901,7 @@ namespace AZ } AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - size_type get_max_size() const { return AllocatorInstance::Get().GetMaxAllocationSize(); } + size_type max_size() const { return AllocatorInstance::Get().GetMaxContiguousAllocationSize(); } size_type get_allocated_size() const { return AllocatorInstance::Get().NumAllocatedBytes(); } AZ_FORCE_INLINE bool is_lock_free() { return AllocatorInstance::Get().is_lock_free(); } @@ -954,7 +959,7 @@ namespace AZ } AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - size_type get_max_size() const { return m_allocator->GetMaxAllocationSize(); } + size_type max_size() const { return m_allocator->GetMaxContiguousAllocationSize(); } size_type get_allocated_size() const { return m_allocator->NumAllocatedBytes(); } AZ_FORCE_INLINE bool operator==(const AZStdIAllocator& rhs) const { return m_allocator == rhs.m_allocator; } @@ -1006,7 +1011,7 @@ namespace AZ } constexpr const char* get_name() const { return m_name; } void set_name(const char* name) { m_name = name; } - size_type get_max_size() const { return m_allocatorFunctor().GetMaxAllocationSize(); } + size_type max_size() const { return m_allocatorFunctor().GetMaxContiguousAllocationSize(); } size_type get_allocated_size() const { return m_allocatorFunctor().NumAllocatedBytes(); } constexpr bool operator==(const AZStdFunctorAllocator& rhs) const { return m_allocatorFunctor == rhs.m_allocatorFunctor; } diff --git a/Code/Framework/AzCore/AzCore/Memory/OSAllocator.h b/Code/Framework/AzCore/AzCore/Memory/OSAllocator.h index 6154e97f38..b327cf6349 100644 --- a/Code/Framework/AzCore/AzCore/Memory/OSAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/OSAllocator.h @@ -61,6 +61,7 @@ namespace AZ size_type NumAllocatedBytes() const override { return m_custom ? m_custom->NumAllocatedBytes() : m_numAllocatedBytes; } size_type Capacity() const override { return m_custom ? m_custom->Capacity() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited size_type GetMaxAllocationSize() const override { return m_custom ? m_custom->GetMaxAllocationSize() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited + size_type GetMaxContiguousAllocationSize() const override { return m_custom ? m_custom->GetMaxContiguousAllocationSize() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited IAllocatorAllocate* GetSubAllocator() override { return m_custom ? m_custom : NULL; } protected: diff --git a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp index 35ad19dd9e..ed5e0febc2 100644 --- a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.cpp @@ -232,6 +232,7 @@ namespace AZ size_type NumAllocatedBytes() const; size_type Capacity() const; size_type GetMaxAllocationSize() const; + size_type GetMaxContiguousAllocationSize() const; IAllocatorAllocate* GetSubAllocator(); void GarbageCollect(); @@ -674,6 +675,11 @@ AZ::OverrunDetectionSchema::size_type AZ::OverrunDetectionSchemaImpl::GetMaxAllo return 0; } +auto AZ::OverrunDetectionSchemaImpl::GetMaxContiguousAllocationSize() const -> size_type +{ + return 0; +} + AZ::IAllocatorAllocate* AZ::OverrunDetectionSchemaImpl::GetSubAllocator() { return nullptr; @@ -799,6 +805,11 @@ AZ::OverrunDetectionSchema::size_type AZ::OverrunDetectionSchema::GetMaxAllocati return m_impl->GetMaxAllocationSize(); } +auto AZ::OverrunDetectionSchema::GetMaxContiguousAllocationSize() const -> size_type +{ + return m_impl->GetMaxContiguousAllocationSize(); +} + AZ::IAllocatorAllocate* AZ::OverrunDetectionSchema::GetSubAllocator() { return m_impl->GetSubAllocator(); diff --git a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h index 669fda8a04..3dffdfad56 100644 --- a/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/OverrunDetectionAllocator.h @@ -86,6 +86,7 @@ namespace AZ virtual size_type NumAllocatedBytes() const override; virtual size_type Capacity() const override; virtual size_type GetMaxAllocationSize() const override; + size_type GetMaxContiguousAllocationSize() const override; virtual IAllocatorAllocate* GetSubAllocator() override; virtual void GarbageCollect() override; diff --git a/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp b/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp index 3e71f530a0..0bef6b7d28 100644 --- a/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp +++ b/Code/Framework/AzCore/AzCore/Memory/PoolSchema.cpp @@ -707,6 +707,11 @@ PoolSchema::GarbageCollect() //m_impl->GarbageCollect(); } +auto PoolSchema::GetMaxContiguousAllocationSize() const -> size_type +{ + return m_impl->m_allocator.m_maxAllocationSize; +} + //========================================================================= // NumAllocatedBytes // [11/1/2010] @@ -1052,6 +1057,11 @@ ThreadPoolSchema::GarbageCollect() m_impl->GarbageCollect(); } +auto ThreadPoolSchema::GetMaxContiguousAllocationSize() const -> size_type +{ + return m_impl->m_maxAllocationSize; +} + //========================================================================= // NumAllocatedBytes // [11/1/2010] diff --git a/Code/Framework/AzCore/AzCore/Memory/PoolSchema.h b/Code/Framework/AzCore/AzCore/Memory/PoolSchema.h index d9c89d28bd..cfc5e3ea07 100644 --- a/Code/Framework/AzCore/AzCore/Memory/PoolSchema.h +++ b/Code/Framework/AzCore/AzCore/Memory/PoolSchema.h @@ -70,6 +70,7 @@ namespace AZ /// Return unused memory to the OS. Don't call this too often because you will force unnecessary allocations. void GarbageCollect() override; + size_type GetMaxContiguousAllocationSize() const override; size_type NumAllocatedBytes() const override; size_type Capacity() const override; IAllocatorAllocate* GetSubAllocator() override; @@ -115,6 +116,7 @@ namespace AZ /// Return unused memory to the OS. Don't call this too often because you will force unnecessary allocations. void GarbageCollect() override; + size_type GetMaxContiguousAllocationSize() const override; size_type NumAllocatedBytes() const override; size_type Capacity() const override; IAllocatorAllocate* GetSubAllocator() override; diff --git a/Code/Framework/AzCore/AzCore/Memory/SimpleSchemaAllocator.h b/Code/Framework/AzCore/AzCore/Memory/SimpleSchemaAllocator.h index e9d001aec3..5fbc890203 100644 --- a/Code/Framework/AzCore/AzCore/Memory/SimpleSchemaAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/SimpleSchemaAllocator.h @@ -179,6 +179,11 @@ namespace AZ return m_schema->GetMaxAllocationSize(); } + size_type GetMaxContiguousAllocationSize() const override + { + return m_schema->GetMaxContiguousAllocationSize(); + } + size_type GetUnAllocatedMemory(bool isPrint = false) const override { return m_schema->GetUnAllocatedMemory(isPrint); diff --git a/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.h b/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.h index 9fd5734dbb..c02ada5843 100644 --- a/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/SystemAllocator.h @@ -103,6 +103,7 @@ namespace AZ size_type Capacity() const override { return m_allocator->Capacity(); } /// Keep in mind this operation will execute GarbageCollect to make sure it returns, max allocation. This function WILL be slow. size_type GetMaxAllocationSize() const override { return m_allocator->GetMaxAllocationSize(); } + size_type GetMaxContiguousAllocationSize() const override { return m_allocator->GetMaxContiguousAllocationSize(); } size_type GetUnAllocatedMemory(bool isPrint = false) const override { return m_allocator->GetUnAllocatedMemory(isPrint); } IAllocatorAllocate* GetSubAllocator() override { return m_isCustom ? m_allocator : m_allocator->GetSubAllocator(); } diff --git a/Code/Framework/AzCore/AzCore/Module/Environment.cpp b/Code/Framework/AzCore/AzCore/Module/Environment.cpp index c07b7444d4..71da948a35 100644 --- a/Code/Framework/AzCore/AzCore/Module/Environment.cpp +++ b/Code/Framework/AzCore/AzCore/Module/Environment.cpp @@ -61,7 +61,7 @@ namespace AZ const char* get_name() const { return m_name; } void set_name(const char* name) { m_name = name; } - size_type get_max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; } + constexpr size_type max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; } size_type get_allocated_size() const { return 0; } bool is_lock_free() { return false; } diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp index 5a35603d0a..b03d413507 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp @@ -2306,7 +2306,7 @@ LUA_API const Node* lua_getDummyNode() else // even references are stored by value as we need to convert from lua native type, i.e. there is not real reference for NativeTypes (numbers, strings, etc.) { bool usedBackupAlloc = false; - if (backupAllocator != nullptr && sizeof(T) > tempAllocator.get_max_size()) + if (backupAllocator != nullptr && sizeof(T) > AZStd::allocator_traits::max_size(tempAllocator)) { value.m_value = backupAllocator->allocate(sizeof(T), AZStd::alignment_of::value, 0); usedBackupAlloc = true; @@ -2340,7 +2340,7 @@ LUA_API const Node* lua_getDummyNode() else // it's a value type { bool usedBackupAlloc = false; - if (backupAllocator != nullptr && valueClass->m_size > tempAllocator.get_max_size()) + if (backupAllocator != nullptr && valueClass->m_size > AZStd::allocator_traits::max_size(tempAllocator)) { value.m_value = backupAllocator->allocate(valueClass->m_size, valueClass->m_alignment, 0); usedBackupAlloc = true; diff --git a/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h b/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h index c3e3f5210a..d9e3dfad1e 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h @@ -45,7 +45,7 @@ namespace UnitTest virtual ~AllocatorsBase() = default; - void SetupAllocator() + void SetupAllocator(const AZ::SystemAllocator::Descriptor& allocatorDesc = {}) { m_drillerManager = AZ::Debug::DrillerManager::Create(); m_drillerManager->Register(aznew AZ::Debug::MemoryDriller); @@ -54,7 +54,7 @@ namespace UnitTest // Only create the SystemAllocator if it s not ready if (!AZ::AllocatorInstance::IsReady()) { - AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(allocatorDesc); m_ownsAllocator = true; } } @@ -85,6 +85,7 @@ namespace UnitTest { public: ScopedAllocatorSetupFixture() { SetupAllocator(); } + explicit ScopedAllocatorSetupFixture(const AZ::SystemAllocator::Descriptor& allocatorDesc) { SetupAllocator(allocatorDesc); } ~ScopedAllocatorSetupFixture() { TeardownAllocator(); } }; diff --git a/Code/Framework/AzCore/AzCore/std/allocator.cpp b/Code/Framework/AzCore/AzCore/std/allocator.cpp index 0aaad5a5a8..fdf1903882 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator.cpp +++ b/Code/Framework/AzCore/AzCore/std/allocator.cpp @@ -40,15 +40,11 @@ namespace AZStd return AZ::AllocatorInstance::Get().Resize(ptr, newSize); } - //========================================================================= - // get_max_size - // [1/1/2008] - //========================================================================= - allocator::size_type - allocator::get_max_size() const + auto allocator::max_size() const -> size_type { - return AZ::AllocatorInstance::Get().GetMaxAllocationSize(); + return AZ::AllocatorInstance::Get().GetMaxContiguousAllocationSize(); } + //========================================================================= // get_allocated_size // [1/1/2008] diff --git a/Code/Framework/AzCore/AzCore/std/allocator.h b/Code/Framework/AzCore/AzCore/std/allocator.h index 0fee5481e2..225350e883 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator.h +++ b/Code/Framework/AzCore/AzCore/std/allocator.h @@ -49,8 +49,8 @@ namespace AZStd * const char* get_name() const; * void set_name(const char* name); * - * // Returns maximum size we can allocate from this allocator. - * size_type get_max_size() const; + * // Returns theoretical maximum size of a single contiguous allocation from this allocator. + * size_type max_size() const; * size_type get_allocated_size() const; * }; * @@ -100,7 +100,8 @@ namespace AZStd pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0); void deallocate(pointer_type ptr, size_type byteSize, size_type alignment); size_type resize(pointer_type ptr, size_type newSize); - size_type get_max_size() const; + // max_size actually returns the true maximum size of a single allocation + size_type max_size() const; size_type get_allocated_size() const; AZ_FORCE_INLINE bool is_lock_free() { return false; } @@ -157,7 +158,7 @@ namespace AZStd AZ_FORCE_INLINE const char* get_name() const; AZ_FORCE_INLINE void set_name(const char* name); - AZ_FORCE_INLINE size_type get_max_size() const; + AZ_FORCE_INLINE size_type max_size() const; AZ_FORCE_INLINE bool is_lock_free(); AZ_FORCE_INLINE bool is_stale_read_allowed(); diff --git a/Code/Framework/AzCore/AzCore/std/allocator_ref.h b/Code/Framework/AzCore/AzCore/std/allocator_ref.h index 659ee0cc8f..62a3cf68de 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator_ref.h +++ b/Code/Framework/AzCore/AzCore/std/allocator_ref.h @@ -41,7 +41,7 @@ namespace AZStd AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - AZ_FORCE_INLINE size_type get_max_size() const { return m_allocator->get_max_size(); } + constexpr size_type max_size() const { return m_allocator->max_size(); } AZ_FORCE_INLINE size_type get_allocated_size() const { return m_allocator->get_allocated_size(); } diff --git a/Code/Framework/AzCore/AzCore/std/allocator_stack.h b/Code/Framework/AzCore/AzCore/std/allocator_stack.h index 202e62bd0f..d8546bfd18 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator_stack.h +++ b/Code/Framework/AzCore/AzCore/std/allocator_stack.h @@ -59,7 +59,7 @@ namespace AZStd AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - AZ_FORCE_INLINE size_type get_max_size() const { return m_size - (m_freeData - m_data); } + constexpr size_type max_size() const { return m_size; } AZ_FORCE_INLINE size_type get_allocated_size() const { return m_freeData - m_data; } pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0) diff --git a/Code/Framework/AzCore/AzCore/std/allocator_static.h b/Code/Framework/AzCore/AzCore/std/allocator_static.h index 0c079eaa9d..7f793c6d6b 100644 --- a/Code/Framework/AzCore/AzCore/std/allocator_static.h +++ b/Code/Framework/AzCore/AzCore/std/allocator_static.h @@ -63,7 +63,7 @@ namespace AZStd AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - AZ_FORCE_INLINE size_type get_max_size() const { return Size - (m_freeData - reinterpret_cast(&m_data)); } + constexpr size_type max_size() const { return Size; } AZ_FORCE_INLINE size_type get_allocated_size() const { return m_freeData - reinterpret_cast(&m_data); } pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0) @@ -190,7 +190,7 @@ namespace AZStd AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - AZ_FORCE_INLINE size_type get_max_size() const { return (NumNodes - m_numOfAllocatedNodes) * sizeof(Node); } + constexpr size_type max_size() const { return NumNodes * sizeof(Node); } AZ_FORCE_INLINE size_type get_allocated_size() const { return m_numOfAllocatedNodes * sizeof(Node); } inline Node* allocate() diff --git a/Code/Framework/AzCore/AzCore/std/containers/deque.h b/Code/Framework/AzCore/AzCore/std/containers/deque.h index 215845a8f4..db585e0ec9 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/deque.h +++ b/Code/Framework/AzCore/AzCore/std/containers/deque.h @@ -6,11 +6,10 @@ * */ #pragma once -#ifndef AZSTD_DEQUE_H -#define AZSTD_DEQUE_H 1 #include +#include #include #include #include @@ -350,7 +349,7 @@ namespace AZStd } AZ_FORCE_INLINE size_type size() const { return m_size; } - AZ_FORCE_INLINE size_type max_size() const { return m_allocator.get_max_size() / sizeof(block_node_type); } + AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits::max_size(m_allocator) / sizeof(block_node_type); } AZ_FORCE_INLINE bool empty() const { return m_size == 0; } AZ_FORCE_INLINE const_reference at(size_type offset) const { return *const_iterator(AZSTD_CHECKED_ITERATOR_2(const_iterator_impl, m_firstOffset + offset, this)); } @@ -1243,5 +1242,3 @@ namespace AZStd return removedCount; } } - -#endif // AZSTD_DEQUE_H diff --git a/Code/Framework/AzCore/AzCore/std/containers/forward_list.h b/Code/Framework/AzCore/AzCore/std/containers/forward_list.h index c311991ee3..407d65ffa9 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/forward_list.h +++ b/Code/Framework/AzCore/AzCore/std/containers/forward_list.h @@ -286,7 +286,7 @@ namespace AZStd } AZ_FORCE_INLINE size_type size() const { return m_numElements; } - AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); } + AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits::max_size(m_allocator) / sizeof(node_type); } AZ_FORCE_INLINE bool empty() const { return (m_numElements == 0); } AZ_FORCE_INLINE iterator begin() { return iterator(AZSTD_CHECKED_ITERATOR(iterator_impl, m_head.m_next)); } diff --git a/Code/Framework/AzCore/AzCore/std/containers/list.h b/Code/Framework/AzCore/AzCore/std/containers/list.h index 124d8b7d7c..60d2977749 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/list.h +++ b/Code/Framework/AzCore/AzCore/std/containers/list.h @@ -5,11 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZSTD_LIST_H -#define AZSTD_LIST_H 1 + #pragma once #include +#include #include #include #include @@ -316,7 +316,7 @@ namespace AZStd } AZ_FORCE_INLINE size_type size() const { return m_numElements; } - AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); } + AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits::max_size(m_allocator) / sizeof(node_type); } AZ_FORCE_INLINE bool empty() const { return (m_numElements == 0); } AZ_FORCE_INLINE iterator begin() { return iterator(AZSTD_CHECKED_ITERATOR(iterator_impl, m_head.m_next)); } @@ -1346,5 +1346,3 @@ namespace AZStd return container.remove_if(predicate); } } - -#endif // AZSTD_LIST_H diff --git a/Code/Framework/AzCore/AzCore/std/containers/rbtree.h b/Code/Framework/AzCore/AzCore/std/containers/rbtree.h index c8f0883eaf..fd268f4936 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/rbtree.h +++ b/Code/Framework/AzCore/AzCore/std/containers/rbtree.h @@ -484,7 +484,7 @@ namespace AZStd AZ_FORCE_INLINE bool empty() const { return m_numElements == 0; } AZ_FORCE_INLINE size_type size() const { return m_numElements; } - AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); } + AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits::max_size(m_allocator) / sizeof(node_type); } rbtree(this_type&& rhs) : m_numElements(0) // it will be set during swap diff --git a/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h b/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h index 7e84124958..d8c3c6ecda 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h +++ b/Code/Framework/AzCore/AzCore/std/containers/ring_buffer.h @@ -5,10 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZSTD_RINGBUFFER_H -#define AZSTD_RINGBUFFER_H 1 + +#pragma once #include +#include #include #include #include @@ -416,7 +417,7 @@ namespace AZStd } AZ_FORCE_INLINE size_type size() const { return m_size; } - AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); } + AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits::max_size(m_allocator) / sizeof(node_type); } AZ_FORCE_INLINE bool empty() const { return m_size == 0; } AZ_FORCE_INLINE bool full() const { return size_type(m_end - m_buff) == m_size; } AZ_FORCE_INLINE size_type free() const { return size_type(m_end - m_buff) - m_size; } @@ -1240,6 +1241,3 @@ namespace AZStd lhs.swap(rhs); } } - -#endif // AZSTD_RINGBUFFER_H -#pragma once diff --git a/Code/Framework/AzCore/AzCore/std/containers/vector.h b/Code/Framework/AzCore/AzCore/std/containers/vector.h index bf02527d77..48de12a5b4 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/vector.h +++ b/Code/Framework/AzCore/AzCore/std/containers/vector.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -431,7 +432,7 @@ namespace AZStd } AZ_FORCE_INLINE size_type size() const { return m_last - m_start; } - AZ_FORCE_INLINE size_type max_size() const { return m_allocator.get_max_size() / sizeof(node_type); } + AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits::max_size(m_allocator) / sizeof(node_type); } AZ_FORCE_INLINE bool empty() const { return m_start == m_last; } void reserve(size_type numElements) diff --git a/Code/Framework/AzCore/AzCore/std/parallel/allocator_concurrent_static.h b/Code/Framework/AzCore/AzCore/std/parallel/allocator_concurrent_static.h index 72c687beab..b9cd5207dd 100644 --- a/Code/Framework/AzCore/AzCore/std/parallel/allocator_concurrent_static.h +++ b/Code/Framework/AzCore/AzCore/std/parallel/allocator_concurrent_static.h @@ -22,7 +22,7 @@ namespace AZStd * Internally the buffer is allocated using aligned_storage. * \note only allocate/deallocate are thread safe. * reset, leak_before_destroy and comparison operators are not thread safe. - * get_max_size and get_allocated_size are thread safe but the returned value is not perfectly in + * get_allocated_size is thread safe but the returned value is not perfectly in * sync on the actual number of allocations (the number of allocations is incremented before the * allocation happens and decremented after the allocation happens, trying to give a conservative * number) @@ -71,7 +71,7 @@ namespace AZStd AZ_FORCE_INLINE const char* get_name() const { return m_name; } AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; } - AZ_FORCE_INLINE size_type get_max_size() const { return (NumNodes - m_numOfAllocatedNodes.load(AZStd::memory_order_relaxed)) * sizeof(Node); } + constexpr size_type max_size() const { return NumNodes * sizeof(Node); } AZ_FORCE_INLINE size_type get_allocated_size() const { return m_numOfAllocatedNodes.load(AZStd::memory_order_relaxed) * sizeof(Node); } inline Node* allocate() diff --git a/Code/Framework/AzCore/AzCore/std/string/string.h b/Code/Framework/AzCore/AzCore/std/string/string.h index ad3546ab09..c02c6805a1 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string.h +++ b/Code/Framework/AzCore/AzCore/std/string/string.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -862,8 +863,7 @@ namespace AZStd inline size_type max_size() const { // return maximum possible length of sequence - size_type num = m_allocator.get_max_size(); - return (num <= 1 ? 1 : num - 1); + return AZStd::allocator_traits::max_size(m_allocator) / sizeof(value_type); } inline void resize(size_type newSize) diff --git a/Code/Framework/AzCore/Tests/AZStd/Allocators.cpp b/Code/Framework/AzCore/Tests/AZStd/Allocators.cpp index 6b82c642d5..8b5d1494fc 100644 --- a/Code/Framework/AzCore/Tests/AZStd/Allocators.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/Allocators.cpp @@ -122,8 +122,15 @@ namespace UnitTest TEST_F(AllocatorDefaultTest, AllocatorTraitsMaxSizeCompilesWithoutErrors) { - using AZStdAllocatorTraits = AZStd::allocator_traits; - AZStd::allocator testAllocator("trait allocator"); + struct AllocatorWithGetMaxSize + : AZStd::allocator + { + using AZStd::allocator::allocator; + size_t get_max_size() { return max_size(); } + }; + + using AZStdAllocatorTraits = AZStd::allocator_traits; + AllocatorWithGetMaxSize testAllocator("trait allocator"); typename AZStdAllocatorTraits::size_type maxSize = AZStdAllocatorTraits::max_size(testAllocator); EXPECT_EQ(testAllocator.get_max_size(), maxSize); } @@ -149,32 +156,32 @@ namespace UnitTest myalloc.set_name(newName); AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0); - AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize)); + EXPECT_EQ(bufferSize, myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); buffer_alloc_type::pointer_type data = myalloc.allocate(100, 1); AZ_TEST_ASSERT(data != nullptr); - AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100); + EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100); myalloc.deallocate(data, 100, 1); // we can free the last allocation only - AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize); + EXPECT_EQ(bufferSize, myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); data = myalloc.allocate(100, 1); myalloc.allocate(3, 1); myalloc.deallocate(data); // can't free allocation which is not the last. - AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 103); + EXPECT_EQ(bufferSize - 103, myalloc.max_size() - myalloc.get_allocated_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 103); myalloc.reset(); - AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize)); + EXPECT_EQ(bufferSize, myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); data = myalloc.allocate(50, 64); AZ_TEST_ASSERT(data != nullptr); AZ_TEST_ASSERT(((AZStd::size_t)data & 63) == 0); - AZ_TEST_ASSERT(myalloc.get_max_size() <= bufferSize - 50); + EXPECT_LE(myalloc.max_size() - myalloc.get_allocated_size(), bufferSize - 50); AZ_TEST_ASSERT(myalloc.get_allocated_size() >= 50); buffer_alloc_type myalloc2; @@ -194,28 +201,28 @@ namespace UnitTest myalloc.set_name(newName); AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0); - AZ_TEST_ASSERT(myalloc.get_max_size() == sizeof(int) * numNodes); + EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); int* data = reinterpret_cast(myalloc.allocate(sizeof(int), 1)); AZ_TEST_ASSERT(data != nullptr); - AZ_TEST_ASSERT(myalloc.get_max_size() == (numNodes - 1) * sizeof(int)); + EXPECT_EQ((numNodes - 1) * sizeof(int), myalloc.max_size() - myalloc.get_allocated_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == sizeof(int)); myalloc.deallocate(data, sizeof(int), 1); - AZ_TEST_ASSERT(myalloc.get_max_size() == sizeof(int) * numNodes); + EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); for (int i = 0; i < numNodes; ++i) { data = reinterpret_cast(myalloc.allocate(sizeof(int), 1)); AZ_TEST_ASSERT(data != nullptr); - AZ_TEST_ASSERT(myalloc.get_max_size() == (numNodes - (i + 1)) * sizeof(int)); + EXPECT_EQ((numNodes - (i + 1)) * sizeof(int), myalloc.max_size() - myalloc.get_allocated_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == (i + 1) * sizeof(int)); } myalloc.reset(); - AZ_TEST_ASSERT(myalloc.get_max_size() == numNodes * sizeof(int)); + EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); AZ_TEST_ASSERT(myalloc == myalloc); @@ -233,7 +240,7 @@ namespace UnitTest AZ_TEST_ASSERT(aligned_data != nullptr); AZ_TEST_ASSERT(((AZStd::size_t)aligned_data & (dataAlignment - 1)) == 0); - AZ_TEST_ASSERT(myaligned_pool.get_max_size() == (numNodes - 1) * sizeof(aligned_int_type)); + EXPECT_EQ((numNodes - 1) * sizeof(aligned_int_type), myaligned_pool.max_size() - myaligned_pool.get_allocated_size()); AZ_TEST_ASSERT(myaligned_pool.get_allocated_size() == sizeof(aligned_int_type)); myaligned_pool.deallocate(aligned_data, sizeof(aligned_int_type), dataAlignment); // Make sure we free what we have allocated. @@ -268,32 +275,32 @@ namespace UnitTest ref_allocator_type::pointer_type data1 = ref_allocator1.allocate(10, 1); AZ_TEST_ASSERT(data1 != nullptr); - AZ_TEST_ASSERT(ref_allocator1.get_max_size() == bufferSize - 10); + EXPECT_EQ(bufferSize - 10, ref_allocator1.max_size() - ref_allocator1.get_allocated_size()); AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() == 10); - AZ_TEST_ASSERT(shared_allocator.get_max_size() == bufferSize - 10); + EXPECT_EQ(bufferSize - 10, shared_allocator.max_size() - shared_allocator.get_allocated_size()); AZ_TEST_ASSERT(shared_allocator.get_allocated_size() == 10); ref_allocator_type::pointer_type data2 = ref_allocator2.allocate(10, 1); AZ_TEST_ASSERT(data2 != nullptr); - AZ_TEST_ASSERT(ref_allocator2.get_max_size() <= bufferSize - 20); + EXPECT_LE(ref_allocator2.max_size() - ref_allocator2.get_allocated_size(), bufferSize - 20); AZ_TEST_ASSERT(ref_allocator2.get_allocated_size() >= 20); - AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 20); + EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 20); AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 20); shared_allocator.reset(); data1 = ref_allocator1.allocate(10, 32); AZ_TEST_ASSERT(data1 != nullptr); - AZ_TEST_ASSERT(ref_allocator1.get_max_size() <= bufferSize - 10); + EXPECT_LE(ref_allocator1.max_size() - ref_allocator1.get_allocated_size(), bufferSize - 10); AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() >= 10); - AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 10); + EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 10); AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 10); data2 = ref_allocator2.allocate(10, 32); AZ_TEST_ASSERT(data2 != nullptr); - AZ_TEST_ASSERT(ref_allocator1.get_max_size() <= bufferSize - 20); + EXPECT_LE(ref_allocator1.max_size() - ref_allocator1.get_allocated_size(), bufferSize - 20); AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() >= 20); - AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 20); + EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 20); AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 20); AZ_TEST_ASSERT(ref_allocator1 == ref_allocator2); @@ -312,31 +319,31 @@ namespace UnitTest myalloc.set_name(newName); AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0); - AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize)); + EXPECT_EQ(bufferSize, myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); stack_allocator::pointer_type data = myalloc.allocate(100, 1); AZ_TEST_ASSERT(data != nullptr); - AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100); + EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100); myalloc.deallocate(data, 100, 1); // this allocator doesn't free data - AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100); + EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100); myalloc.reset(); - AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize)); + EXPECT_EQ(bufferSize, myalloc.max_size()); AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0); data = myalloc.allocate(50, 64); AZ_TEST_ASSERT(data != nullptr); AZ_TEST_ASSERT(((AZStd::size_t)data & 63) == 0); - AZ_TEST_ASSERT(myalloc.get_max_size() <= bufferSize - 50); + EXPECT_LE(myalloc.max_size() - myalloc.get_allocated_size(), bufferSize - 50); AZ_TEST_ASSERT(myalloc.get_allocated_size() >= 50); AZ_STACK_ALLOCATOR(myalloc2, 200); // test the macro declaration - AZ_TEST_ASSERT(myalloc2.get_max_size() == 200); + EXPECT_EQ(200, myalloc2.max_size() ); AZ_TEST_ASSERT(myalloc == myalloc); AZ_TEST_ASSERT((myalloc2 != myalloc)); diff --git a/Code/Framework/AzCore/Tests/AZStd/ConcurrentAllocators.cpp b/Code/Framework/AzCore/Tests/AZStd/ConcurrentAllocators.cpp index 5be17a75e2..86ac22bfc9 100644 --- a/Code/Framework/AzCore/Tests/AZStd/ConcurrentAllocators.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/ConcurrentAllocators.cpp @@ -49,7 +49,7 @@ namespace UnitTest const char newName[] = "My new test allocator"; myalloc.set_name(newName); EXPECT_EQ(0, strcmp(myalloc.get_name(), newName)); - EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.get_max_size()); + EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.max_size()); } } @@ -61,10 +61,10 @@ namespace UnitTest typename TestFixture::allocator_type::pointer_type data = myalloc.allocate(); EXPECT_NE(nullptr, data); EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_allocated_size()); - EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (s_allocatorCapacity - 1), myalloc.get_max_size()); + EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (s_allocatorCapacity - 1), myalloc.max_size() - myalloc.get_allocated_size()); myalloc.deallocate(data); EXPECT_EQ(0, myalloc.get_allocated_size()); - EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.get_max_size()); + EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.max_size()); } TYPED_TEST(ConcurrentAllocatorTestFixture, MultipleAllocateDeallocate) @@ -84,19 +84,19 @@ namespace UnitTest EXPECT_EQ(dataSize, dataSet.size()); dataSet.clear(); EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * dataSize, myalloc.get_allocated_size()); - EXPECT_EQ((s_allocatorCapacity - dataSize) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size()); + EXPECT_EQ((s_allocatorCapacity - dataSize) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size() - myalloc.get_allocated_size()); for (size_t i = 0; i < dataSize; i += 2) { myalloc.deallocate(data[i]); } EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (dataSize / 2), myalloc.get_allocated_size()); - EXPECT_EQ((s_allocatorCapacity - dataSize / 2) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size()); + EXPECT_EQ((s_allocatorCapacity - dataSize / 2) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size() - myalloc.get_allocated_size()); for (size_t i = 1; i < dataSize; i += 2) { myalloc.deallocate(data[i]); } EXPECT_EQ(0, myalloc.get_allocated_size()); - EXPECT_EQ(s_allocatorCapacity * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size()); + EXPECT_EQ(s_allocatorCapacity * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size()); } TYPED_TEST(ConcurrentAllocatorTestFixture, ConcurrentAllocateoDeallocate) @@ -159,7 +159,7 @@ namespace UnitTest EXPECT_NE(nullptr, aligned_data); EXPECT_EQ(0, ((AZStd::size_t)aligned_data & (dataAlignment - 1))); - EXPECT_EQ((s_allocatorCapacity - 1) * sizeof(aligned_int_type), myaligned_pool.get_max_size()); + EXPECT_EQ((s_allocatorCapacity - 1) * sizeof(aligned_int_type), myaligned_pool.max_size() - myaligned_pool.get_allocated_size()); EXPECT_EQ(sizeof(aligned_int_type), myaligned_pool.get_allocated_size()); myaligned_pool.deallocate(aligned_data, sizeof(aligned_int_type), dataAlignment); // Make sure we free what we have allocated. diff --git a/Code/Framework/AzCore/Tests/Memory.cpp b/Code/Framework/AzCore/Tests/Memory.cpp index 611af827d2..eb854050b6 100644 --- a/Code/Framework/AzCore/Tests/Memory.cpp +++ b/Code/Framework/AzCore/Tests/Memory.cpp @@ -1179,6 +1179,8 @@ namespace UnitTest size_type Capacity() const override { return 1 * 1024 * 1024 * 1024; } /// Returns max allocation size if possible. If not returned value is 0 size_type GetMaxAllocationSize() const override { return 1 * 1024 * 1024 * 1024; } + /// Returns max allocation size of a single contiguous allocation + size_type GetMaxContiguousAllocationSize() const override { return 1 * 1024 * 1024 * 1024; } /// Returns a pointer to a sub-allocator or NULL. IAllocatorAllocate* GetSubAllocator() override { return NULL; } }; diff --git a/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.cpp b/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.cpp index dfb397a02c..35faa74b19 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.cpp @@ -39,7 +39,7 @@ namespace MCore return 0; } - StaticAllocator::size_type StaticAllocator::get_max_size() const + StaticAllocator::size_type StaticAllocator::max_size() const { return 0; } diff --git a/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.h b/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.h index d3b1c68855..50d8dac04c 100644 --- a/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.h +++ b/Gems/EMotionFX/Code/MCore/Source/StaticAllocator.h @@ -22,7 +22,7 @@ namespace MCore StaticAllocator::size_type resize(pointer_type ptr, size_type newSize); - StaticAllocator::size_type get_max_size() const; + StaticAllocator::size_type max_size() const; StaticAllocator::size_type get_allocated_size() const; }; From 2c066a81daec45277246757ec8be7fd5dfc068e4 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 14 Sep 2021 15:11:11 -0700 Subject: [PATCH 119/274] Adds support for creating an SDK layout from a Monolithic build (#4097) Adds support for creating an SDK layout from a Monolithic build and have the same install prefix used between monolithic and non-monolithic Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/Install_common.cmake | 96 +++++++++++++++------- cmake/Platform/Mac/Install_mac.cmake | 10 +-- cmake/install/ConfigurationTypes.cmake | 11 ++- cmake/install/InstalledTarget.in | 2 +- 4 files changed, 82 insertions(+), 37 deletions(-) diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 86f46a6e0b..fdd3256d78 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -23,12 +23,12 @@ ly_set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME Core) cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory) cmake_path(RELATIVE_PATH CMAKE_LIBRARY_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE library_output_directory) -# Anywhere CMAKE_INSTALL_PREFIX is used, it has to be escaped so it is baked into the cmake_install.cmake script instead -# of baking the path. This is needed so `cmake --install --prefix ` works regardless of the CMAKE_INSTALL_PREFIX -# used to generate the solution. -# CMAKE_INSTALL_PREFIX is still used when building the INSTALL target -set(install_output_folder "\${CMAKE_INSTALL_PREFIX}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$") +if(LY_MONOLITHIC_GAME) + set(LY_BUILD_PERMUTATION Monolithic) +else() + set(LY_BUILD_PERMUTATION Default) +endif() #! ly_setup_target: Setup the data needed to re-create the cmake target commands for a single target function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_target_source_dir) @@ -91,6 +91,10 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar cmake_path(RELATIVE_PATH target_library_output_directory BASE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} OUTPUT_VARIABLE target_library_output_subdirectory) endif() + cmake_path(APPEND archive_output_directory "${PAL_PLATFORM_NAME}/$/${LY_BUILD_PERMUTATION}") + cmake_path(APPEND library_output_directory "${PAL_PLATFORM_NAME}/$/${LY_BUILD_PERMUTATION}") + cmake_path(APPEND runtime_output_directory "${PAL_PLATFORM_NAME}/$/${LY_BUILD_PERMUTATION}") + if(COMMAND ly_install_target_override) # Mac needs special handling because of a cmake issue ly_install_target_override(TARGET ${TARGET_NAME} @@ -104,18 +108,18 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar install( TARGETS ${TARGET_NAME} ARCHIVE - DESTINATION ${archive_output_directory}/${PAL_PLATFORM_NAME}/$ + DESTINATION ${archive_output_directory} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} LIBRARY - DESTINATION ${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory} + DESTINATION ${library_output_directory}/${target_library_output_subdirectory} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} RUNTIME - DESTINATION ${runtime_output_directory}/${PAL_PLATFORM_NAME}/$/${target_runtime_output_subdirectory} + DESTINATION ${runtime_output_directory}/${target_runtime_output_subdirectory} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} ) endif() - # CMakeLists.txt file + # CMakeLists.txt related files string(REGEX MATCH "(.*)::(.*)$" match ${ALIAS_TARGET_NAME}) if(match) set(NAMESPACE_PLACEHOLDER "NAMESPACE ${CMAKE_MATCH_1}") @@ -140,7 +144,7 @@ function(ly_setup_target OUTPUT_CONFIGURED_TARGET ALIAS_TARGET_NAME absolute_tar if(TARGET_TYPE_PLACEHOLDER IN_LIST GEM_LIBRARY_TYPES) get_target_property(gem_module ${TARGET_NAME} GEM_MODULE) if(gem_module) - set(TARGET_TYPE_PLACEHOLDER "GEM_MODULE") + string(PREPEND TARGET_TYPE_PLACEHOLDER "GEM_") endif() endif() @@ -222,32 +226,32 @@ set_target_properties(${RUN_TARGET_NAME} PROPERTIES ) endif() - # Config file + # Config files set(target_file_contents "# Generated by O3DE install\n\n") if(NOT target_type STREQUAL INTERFACE_LIBRARY) unset(target_location) set(runtime_types EXECUTABLE APPLICATION) if(target_type IN_LIST runtime_types) - set(target_location "\${LY_ROOT_FOLDER}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$/${target_runtime_output_subdirectory}/$") + set(target_location "\${LY_ROOT_FOLDER}/${runtime_output_directory}/${target_runtime_output_subdirectory}/$") elseif(target_type STREQUAL MODULE_LIBRARY) - set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$") + set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${target_library_output_subdirectory}/$") elseif(target_type STREQUAL SHARED_LIBRARY) string(APPEND target_file_contents "set_property(TARGET ${NAME_PLACEHOLDER} APPEND_STRING PROPERTY IMPORTED_IMPLIB - $<$$:\"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\"$ + $<$$:\"\${LY_ROOT_FOLDER}/${archive_output_directory}/$\"$ ) ") string(APPEND target_file_contents "set_property(TARGET ${NAME_PLACEHOLDER} PROPERTY IMPORTED_IMPLIB_$> - \"\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$\" + \"\${LY_ROOT_FOLDER}/${archive_output_directory}/$\" ) ") - set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${PAL_PLATFORM_NAME}/$/${target_library_output_subdirectory}/$") + set(target_location "\${LY_ROOT_FOLDER}/${library_output_directory}/${target_library_output_subdirectory}/$") else() # STATIC_LIBRARY, OBJECT_LIBRARY, INTERFACE_LIBRARY - set(target_location "\${LY_ROOT_FOLDER}/${archive_output_directory}/${PAL_PLATFORM_NAME}/$/$") + set(target_location "\${LY_ROOT_FOLDER}/${archive_output_directory}/$") endif() if(target_location) @@ -265,9 +269,9 @@ set_property(TARGET ${NAME_PLACEHOLDER} endif() set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) - file(GENERATE OUTPUT "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" CONTENT "${target_file_contents}") - install(FILES "${target_install_source_dir}/${NAME_PLACEHOLDER}_$.cmake" - DESTINATION ${relative_target_source_dir} + file(GENERATE OUTPUT "${target_install_source_dir}/Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION}/${NAME_PLACEHOLDER}_$.cmake" CONTENT "${target_file_contents}") + install(FILES "${target_install_source_dir}/Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION}/${NAME_PLACEHOLDER}_$.cmake" + DESTINATION ${relative_target_source_dir}/Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} ) @@ -299,16 +303,44 @@ function(ly_setup_subdirectory absolute_target_source_dir) string(APPEND all_configured_targets "${configured_target}") endforeach() + # Initialize the target install source directory to path underneath the current binary directory + set(target_install_source_dir "${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}") + + ly_file_read(${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) + + # 1. Create the base CMakeLists.txt that will just include a cmake file per platform + file(CONFIGURE OUTPUT "${target_install_source_dir}/CMakeLists.txt" CONTENT [[ +@cmake_copyright_comment@ +include(Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +]] @ONLY) + install(FILES "${target_install_source_dir}/CMakeLists.txt" + DESTINATION ${relative_target_source_dir} + COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} + ) + + # 2. For this platform file, create a Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake file + # that will include different configuration permutations (e.g. monolithic vs non-monolithic) + file(CONFIGURE OUTPUT "${target_install_source_dir}/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake" CONTENT [[ +@cmake_copyright_comment@ +if(LY_MONOLITHIC_GAME) + include(Platform/${PAL_PLATFORM_NAME}/Monolithic/permutation.cmake) +else() + include(Platform/${PAL_PLATFORM_NAME}/Default/permutation.cmake) +endif() +]]) + install(FILES "${target_install_source_dir}/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake" + DESTINATION ${relative_target_source_dir}/Platform/${PAL_PLATFORM_NAME} + COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} + ) + + # 3. For this configuration permutation, generate a Platform/${PAL_PLATFORM_NAME}/${permutation}/permutation.cmake + # that will declare the target and configure it ly_setup_subdirectory_create_alias("${absolute_target_source_dir}" CREATE_ALIASES_PLACEHOLDER) ly_setup_subdirectory_set_gem_variant_to_load("${absolute_target_source_dir}" GEM_VARIANT_TO_LOAD_PLACEHOLDER) ly_setup_subdirectory_enable_gems("${absolute_target_source_dir}" ENABLE_GEMS_PLACEHOLDER) - ly_file_read(${LY_ROOT_FOLDER}/cmake/install/Copyright.in cmake_copyright_comment) - - # Initialize the target install source directory to path underneath the current binary directory - set(target_install_source_dir ${CMAKE_CURRENT_BINARY_DIR}/install/${relative_target_source_dir}) # Write out all the aggregated ly_add_target function calls and the final ly_create_alias() calls to the target CMakeLists.txt - file(WRITE ${target_install_source_dir}/CMakeLists.txt + file(WRITE "${target_install_source_dir}/Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION}/permutation.cmake" "${cmake_copyright_comment}" "${all_configured_targets}" "\n" @@ -316,9 +348,8 @@ function(ly_setup_subdirectory absolute_target_source_dir) "${GEM_VARIANT_TO_LOAD_PLACEHOLDER}" "${ENABLE_GEMS_PLACEHOLDER}" ) - - install(FILES "${target_install_source_dir}/CMakeLists.txt" - DESTINATION ${relative_target_source_dir} + install(FILES "${target_install_source_dir}/Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION}/permutation.cmake" + DESTINATION ${relative_target_source_dir}//Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} ) @@ -362,10 +393,10 @@ function(ly_setup_cmake_install) # Inject code that will generate each ConfigurationType_.cmake file set(install_configuration_type_template [=[ configure_file(@LY_ROOT_FOLDER@/cmake/install/ConfigurationType_config.cmake.in - ${CMAKE_INSTALL_PREFIX}/cmake/ConfigurationTypes_${CMAKE_INSTALL_CONFIG_NAME}.cmake + ${CMAKE_INSTALL_PREFIX}/cmake/Platform/@PAL_PLATFORM_NAME@/@LY_BUILD_PERMUTATION@/ConfigurationTypes_${CMAKE_INSTALL_CONFIG_NAME}.cmake @ONLY ) - message(STATUS "Generated ${CMAKE_INSTALL_PREFIX}/cmake/ConfigurationTypes_${CMAKE_INSTALL_CONFIG_NAME}.cmake") + message(STATUS "Generated ${CMAKE_INSTALL_PREFIX}/cmake/Platform/@PAL_PLATFORM_NAME@/@LY_BUILD_PERMUTATION@/ConfigurationTypes_${CMAKE_INSTALL_CONFIG_NAME}.cmake") ]=]) string(CONFIGURE "${install_configuration_type_template}" install_configuration_type @ONLY) install(CODE "${install_configuration_type}" @@ -493,6 +524,11 @@ endfunction()" endif() # runtime dependencies that need to be copied to the output + # Anywhere CMAKE_INSTALL_PREFIX is used, it has to be escaped so it is baked into the cmake_install.cmake script instead + # of baking the path. This is needed so `cmake --install --prefix ` works regardless of the CMAKE_INSTALL_PREFIX + # used to generate the solution. + # CMAKE_INSTALL_PREFIX is still used when building the INSTALL target + set(install_output_folder "\${CMAKE_INSTALL_PREFIX}/${runtime_output_directory}/${PAL_PLATFORM_NAME}/$/${LY_BUILD_PERMUTATION}") set(target_file_dir "${install_output_folder}/${target_runtime_output_subdirectory}") ly_get_runtime_dependencies(runtime_dependencies ${target}) foreach(runtime_dependency ${runtime_dependencies}) diff --git a/cmake/Platform/Mac/Install_mac.cmake b/cmake/Platform/Mac/Install_mac.cmake index f3c2b31b31..8f07b1bfde 100644 --- a/cmake/Platform/Mac/Install_mac.cmake +++ b/cmake/Platform/Mac/Install_mac.cmake @@ -54,19 +54,19 @@ function(ly_install_target_override) install( TARGETS ${ly_platform_install_target_TARGET} ARCHIVE - DESTINATION ${ly_platform_install_target_ARCHIVE_DIR}/${PAL_PLATFORM_NAME}/$ + DESTINATION ${ly_platform_install_target_ARCHIVE_DIR} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} LIBRARY - DESTINATION ${ly_platform_install_target_LIBRARY_DIR}/${PAL_PLATFORM_NAME}/$/${ly_platform_install_target_LIBRARY_SUBDIR} + DESTINATION ${ly_platform_install_target_LIBRARY_DIR}/${ly_platform_install_target_LIBRARY_SUBDIR} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} RUNTIME - DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${PAL_PLATFORM_NAME}/$/${ly_platform_install_target_RUNTIME_SUBDIR} + DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${ly_platform_install_target_RUNTIME_SUBDIR} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} BUNDLE - DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${PAL_PLATFORM_NAME}/$/${ly_platform_install_target_RUNTIME_SUBDIR} + DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${ly_platform_install_target_RUNTIME_SUBDIR} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} RESOURCE - DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${PAL_PLATFORM_NAME}/$/${ly_platform_install_target_RUNTIME_SUBDIR}/ + DESTINATION ${ly_platform_install_target_RUNTIME_DIR}/${ly_platform_install_target_RUNTIME_SUBDIR} COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME} ) diff --git a/cmake/install/ConfigurationTypes.cmake b/cmake/install/ConfigurationTypes.cmake index 709f3e71ab..ce0fbd7963 100644 --- a/cmake/install/ConfigurationTypes.cmake +++ b/cmake/install/ConfigurationTypes.cmake @@ -15,7 +15,16 @@ include_guard(GLOBAL) set(CMAKE_CONFIGURATION_TYPES "" CACHE STRING "" FORCE) # For the SDK case, we want to only define the confiuguration types that have been added to the SDK -file(GLOB configuration_type_files "cmake/ConfigurationTypes_*.cmake") +# We need to redeclare LY_BUILD_PERMUTATION because Configurations is one of the first things included by the +# root CMakeLists.txt. Even LY_MONOLITHIC_GAME is declared after, but since is a passed cache variable, and +# default is the same as undeclared, we can use it at this point. +if(LY_MONOLITHIC_GAME) + set(LY_BUILD_PERMUTATION Monolithic) +else() + set(LY_BUILD_PERMUTATION Default) +endif() + +file(GLOB configuration_type_files "cmake/Platform/${PAL_PLATFORM_NAME}/${LY_BUILD_PERMUTATION}/ConfigurationTypes_*.cmake") foreach(configuration_type_file ${configuration_type_files}) include(${configuration_type_file}) endforeach() diff --git a/cmake/install/InstalledTarget.in b/cmake/install/InstalledTarget.in index 2095211bb2..5022a108e8 100644 --- a/cmake/install/InstalledTarget.in +++ b/cmake/install/InstalledTarget.in @@ -23,5 +23,5 @@ ly_add_target( set(configs @CMAKE_CONFIGURATION_TYPES@) foreach(config ${configs}) - include("@NAME_PLACEHOLDER@_${config}.cmake" OPTIONAL) + include("Platform/@PAL_PLATFORM_NAME@/@LY_BUILD_PERMUTATION@/@NAME_PLACEHOLDER@_${config}.cmake" OPTIONAL) endforeach() From 603e33d7f774f17c61da0335a3c8077b11b526b1 Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Tue, 14 Sep 2021 16:10:06 -0700 Subject: [PATCH 120/274] Removing the boundary search method. (#4024) * Removing the boundary search method. Bicubic is now the default and only PCF filtering method * Removing padding (based upon feedback) * Removing PCF method from py auto testing Signed-off-by: mrieggeramzn --- ...dra_AtomEditorComponents_LightComponent.py | 2 - .../atom_renderer/test_Atom_MainSuite.py | 2 - .../Shadow/DirectionalLightShadow.azsli | 96 +++------------- .../Features/Shadow/ProjectedShadow.azsli | 105 +++--------------- .../CoreLights/ViewSrg.azsli | 4 +- ...irectionalLightFeatureProcessorInterface.h | 9 -- .../DiskLightFeatureProcessorInterface.h | 4 - .../PointLightFeatureProcessorInterface.h | 5 - .../Atom/Feature/CoreLights/ShadowConstants.h | 8 -- ...ProjectedShadowFeatureProcessorInterface.h | 4 - .../DirectionalLightFeatureProcessor.cpp | 23 ---- .../DirectionalLightFeatureProcessor.h | 4 - .../CoreLights/DiskLightFeatureProcessor.cpp | 10 -- .../CoreLights/DiskLightFeatureProcessor.h | 2 - .../CoreLights/PointLightFeatureProcessor.cpp | 10 -- .../CoreLights/PointLightFeatureProcessor.h | 2 - .../ProjectedShadowFeatureProcessor.cpp | 24 +--- .../Shadows/ProjectedShadowFeatureProcessor.h | 5 +- .../CommonFeatures/CoreLights/AreaLightBus.h | 13 --- .../CoreLights/AreaLightComponentConfig.h | 8 -- .../CoreLights/DirectionalLightBus.h | 16 --- .../DirectionalLightComponentConfig.h | 8 -- .../CoreLights/AreaLightComponentConfig.cpp | 24 ---- .../AreaLightComponentController.cpp | 36 ------ .../CoreLights/AreaLightComponentController.h | 4 - .../DirectionalLightComponentConfig.cpp | 24 ---- .../DirectionalLightComponentController.cpp | 34 ------ .../DirectionalLightComponentController.h | 4 - .../Source/CoreLights/DiskLightDelegate.cpp | 16 --- .../Source/CoreLights/DiskLightDelegate.h | 2 - .../CoreLights/EditorAreaLightComponent.cpp | 18 +-- .../EditorDirectionalLightComponent.cpp | 18 +-- .../Source/CoreLights/LightDelegateBase.h | 2 - .../CoreLights/LightDelegateInterface.h | 4 - .../Source/CoreLights/SphereLightDelegate.cpp | 16 --- .../Source/CoreLights/SphereLightDelegate.h | 2 - 36 files changed, 35 insertions(+), 533 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py index 24866f3b19..8d138e67b8 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py @@ -31,8 +31,6 @@ SPHERE_AND_SPOT_DISK_LIGHT_PROPERTIES = [ ("Controller|Configuration|Shadows|Shadow filter method", 1), # PCF ("Controller|Configuration|Shadows|Filtering sample count", 4.0), ("Controller|Configuration|Shadows|Filtering sample count", 64.0), - ("Controller|Configuration|Shadows|PCF method", 0), # Bicubic - ("Controller|Configuration|Shadows|PCF method", 1), # Boundary search ("Controller|Configuration|Shadows|Shadow filter method", 2), # ECM ("Controller|Configuration|Shadows|ESM exponent", 50), ("Controller|Configuration|Shadows|ESM exponent", 5000), diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index c40dc8f178..ce496ce268 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -200,8 +200,6 @@ class TestAtomEditorComponentsMain(object): "Controller|Configuration|Shadows|Shadow filter method set to 1", # PCF "Controller|Configuration|Shadows|Filtering sample count set to 4", "Controller|Configuration|Shadows|Filtering sample count set to 64", - "Controller|Configuration|Shadows|PCF method set to 0", - "Controller|Configuration|Shadows|PCF method set to 1", "Controller|Configuration|Shadows|Shadow filter method set to 2", # ESM "Controller|Configuration|Shadows|ESM exponent set to 50.0", "Controller|Configuration|Shadows|ESM exponent set to 5000.0", diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli index 8df13bd19a..dd235fcd3a 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli @@ -101,7 +101,6 @@ class DirectionalLightShadow // This outputs visibility ratio (from 0.0 to 1.0) for ESM+PCF. float GetVisibilityFromLightEsmPcf(); - float SamplePcfBicubic(); float SamplePcfBicubic(float3 shadowCoord, uint indexOfCascade); uint m_lightIndex; @@ -278,70 +277,26 @@ float DirectionalLightShadow::GetVisibilityFromLightNoFilter() } float DirectionalLightShadow::GetVisibilityFromLightPcf() -{ - const uint predictionCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_predictionSampleCount; +{ + static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds. + static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. - if (predictionCount <= 1) + const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; + const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount; + for (uint indexOfCascade = 0; indexOfCascade < cascadeCount; ++indexOfCascade) { - return GetVisibilityFromLightNoFilter(); - } + const float3 shadowCoord = m_shadowCoords[indexOfCascade]; - if (ViewSrg::m_directionalLightShadows[m_lightIndex].m_pcfFilterMethod == PcfFilterMethod_Bicubic) - { - return SamplePcfBicubic(); - } - - const float3 lightDirection = - normalize(SceneSrg::m_directionalLights[m_lightIndex].m_direction); - const float4 jitterUnitVectorDepthDiffBase = - Shadow::GetJitterUnitVectorDepthDiffBase(m_normalVector, lightDirection); - const float3 jitterUnit = jitterUnitVectorDepthDiffBase.xyz; - const float jitterDepthDiffBase = jitterUnitVectorDepthDiffBase.w; - - uint shadowedCount = 0; - uint jitterIndex = 0; - - // Predicting - for (; jitterIndex < predictionCount; ++jitterIndex) - { - if (IsShadowedWithJitter( - jitterUnit, - jitterDepthDiffBase, - jitterIndex)) - { - ++shadowedCount; - } - } - if (shadowedCount == 0) - { - return 1.; - } - else if (shadowedCount == predictionCount) - { - return 0.; - } - - // Filtering - - // When the prediction detects the point on the boundary of shadow, - // i.e., both of a lit point and a a shadowed one exists in the jittering area, - // we calculate the more precious lit ratio in the area. - const uint filteringCount = max( - predictionCount, - ViewSrg::m_directionalLightShadows[m_lightIndex].m_filteringSampleCount); - - for (; jitterIndex < filteringCount; ++jitterIndex) - { - if (IsShadowedWithJitter( - jitterUnit, - jitterDepthDiffBase, - jitterIndex)) + if (shadowCoord.x >= 0. && shadowCoord.x * size < size - PixelMargin && + shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin && + shadowCoord.z < 1. - DepthMargin) { - ++shadowedCount; + m_debugInfo.m_cascadeIndex = indexOfCascade; + return SamplePcfBicubic(shadowCoord, indexOfCascade); } } - - return (filteringCount - shadowedCount) * 1. / filteringCount; + m_debugInfo.m_cascadeIndex = cascadeCount; + return 1.; } float DirectionalLightShadow::GetVisibilityFromLightEsm() @@ -415,29 +370,6 @@ float DirectionalLightShadow::GetVisibilityFromLightEsmPcf() return 1.; } -float DirectionalLightShadow::SamplePcfBicubic() -{ - static const float DepthMargin = 0.01; // avoiding artifact when near depth bounds. - static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. - - const uint size = ViewSrg::m_directionalLightShadows[m_lightIndex].m_shadowmapSize; - const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount; - for (uint indexOfCascade = 0; indexOfCascade < cascadeCount; ++indexOfCascade) - { - const float3 shadowCoord = m_shadowCoords[indexOfCascade]; - - if (shadowCoord.x >= 0. && shadowCoord.x * size < size - PixelMargin && - shadowCoord.y >= 0. && shadowCoord.y * size < size - PixelMargin && - shadowCoord.z < 1. - DepthMargin) - { - m_debugInfo.m_cascadeIndex = indexOfCascade; - return SamplePcfBicubic(shadowCoord, indexOfCascade); - } - } - m_debugInfo.m_cascadeIndex = cascadeCount; - return 1.; -} - float DirectionalLightShadow::SamplePcfBicubic(float3 shadowCoord, uint indexOfCascade) { const uint filteringSampleCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_filteringSampleCount; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli index 2fea4650b3..899fbb1553 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli @@ -44,8 +44,6 @@ class ProjectedShadow float GetVisibilityEsmPcf(); float GetThickness(); - float SamplePcfBicubic(); - bool IsShadowed(float3 shadowPosition); bool IsShadowedWithJitter( float3 jitterUnitX, @@ -87,8 +85,7 @@ float ProjectedShadow::GetVisibility( shadow.SetShadowPosition(); float visibility = 1.; - // Filter method is stored in top 16 bits. - uint filterMethod = ViewSrg::m_projectedShadows[shadow.m_shadowIndex].m_shadowFilterMethod & 0x0000FFFF; + const uint filterMethod = ViewSrg::m_projectedShadows[shadow.m_shadowIndex].m_shadowFilterMethod; switch (filterMethod) { case ViewSrg::ShadowFilterMethodNone: @@ -145,72 +142,29 @@ float ProjectedShadow::GetVisibilityNoFilter() float ProjectedShadow::GetVisibilityPcf() { - // PCF filter method is stored in bottom 16 bits. - const uint pcfFilterMethod = ViewSrg::m_projectedShadows[m_shadowIndex].m_shadowFilterMethod >> 16; - if (pcfFilterMethod == PcfFilterMethod_Bicubic) - { - return SamplePcfBicubic(); - } - - const uint predictionCount = ViewSrg::m_projectedShadows[m_shadowIndex].m_predictionSampleCount; - - if (predictionCount <= 1) - { - return GetVisibilityNoFilter(); - } - - const float4 jitterUnitVectorDepthDiffBase = - Shadow::GetJitterUnitVectorDepthDiffBase(m_normalVector, m_lightDirection); - const float3 jitterUnitY = jitterUnitVectorDepthDiffBase.xyz; - const float3 jitterUnitX = cross(jitterUnitY, m_lightDirection); - const float jitterDepthDiffBase = jitterUnitVectorDepthDiffBase.w; + const uint filteringSampleCount = ViewSrg::m_projectedShadows[m_shadowIndex].m_filteringSampleCount; + const float3 atlasPosition = GetAtlasPosition(m_shadowPosition.xy); - uint shadowedCount = 0; - uint jitterIndex = 0; + SampleShadowMapBicubicParameters param; + param.shadowMap = PassSrg::m_projectedShadowmaps; + param.shadowPos = float3(atlasPosition.xy * ViewSrg::m_invShadowmapAtlasSize, atlasPosition.z); + param.shadowMapSize = ViewSrg::m_shadowmapAtlasSize; + param.invShadowMapSize = ViewSrg::m_invShadowmapAtlasSize; + param.comparisonValue = m_shadowPosition.z - m_bias; + param.samplerState = SceneSrg::m_hwPcfSampler; - // Predicting - for (; jitterIndex < predictionCount; ++jitterIndex) - { - if (IsShadowedWithJitter( - jitterUnitX, - jitterUnitY, - jitterDepthDiffBase, - jitterIndex)) - { - ++shadowedCount; - } - } - if (shadowedCount == 0) + if (filteringSampleCount <= 4) { - return 1.; + return SampleShadowMapBicubic_4Tap(param); } - else if (shadowedCount == predictionCount) + else if (filteringSampleCount <= 9) { - return 0.; + return SampleShadowMapBicubic_9Tap(param); } - - // Filtering - - // When the prediction detects the point on the boundary of shadow, - // i.e., both of a lit point and a a shadowed one exists in the jittering area, - // we calculate the more precious lit ratio in the area. - const uint filteringCount = max( - predictionCount, - ViewSrg::m_projectedShadows[m_shadowIndex].m_filteringSampleCount); - - for (; jitterIndex < filteringCount; ++jitterIndex) + else { - if (IsShadowedWithJitter( - jitterUnitX, - jitterUnitY, - jitterDepthDiffBase, - jitterIndex)) - { - ++shadowedCount; - } + return SampleShadowMapBicubic_16Tap(param); } - - return (filteringCount - shadowedCount) * 1. / filteringCount; } float ProjectedShadow::GetVisibilityEsm() @@ -337,33 +291,6 @@ float ProjectedShadow::GetThickness() return 0.; } -float ProjectedShadow::SamplePcfBicubic() -{ - const uint filteringSampleCount = ViewSrg::m_projectedShadows[m_shadowIndex].m_filteringSampleCount; - const float3 atlasPosition = GetAtlasPosition(m_shadowPosition.xy); - - SampleShadowMapBicubicParameters param; - param.shadowMap = PassSrg::m_projectedShadowmaps; - param.shadowPos = float3(atlasPosition.xy * ViewSrg::m_invShadowmapAtlasSize, atlasPosition.z); - param.shadowMapSize = ViewSrg::m_shadowmapAtlasSize; - param.invShadowMapSize = ViewSrg::m_invShadowmapAtlasSize; - param.comparisonValue = m_shadowPosition.z - m_bias; - param.samplerState = SceneSrg::m_hwPcfSampler; - - if (filteringSampleCount <= 4) - { - return SampleShadowMapBicubic_4Tap(param); - } - else if (filteringSampleCount <= 9) - { - return SampleShadowMapBicubic_9Tap(param); - } - else - { - return SampleShadowMapBicubic_16Tap(param); - } -} - bool ProjectedShadow::IsShadowed(float3 shadowPosition) { static const float PixelMargin = 1.5; // avoiding artifact between cascade levels. diff --git a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli index 01e5f3e61c..2065e28703 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderResourceGroups/CoreLights/ViewSrg.azsli @@ -82,7 +82,7 @@ partial ShaderResourceGroup ViewSrg { float4x4 m_depthBiasMatrix; uint m_shadowmapArraySlice; // array slice who has shadowmap in the atlas. - uint m_shadowFilterMethod; // Includes overall filter method in top 16 bits and pcf method in bottom 16 bits. + uint m_shadowFilterMethod; float m_boundaryScale; uint m_predictionSampleCount; uint m_filteringSampleCount; @@ -117,8 +117,6 @@ partial ShaderResourceGroup ViewSrg uint m_debugFlags; uint m_shadowFilterMethod; float m_far_minus_near; - uint m_pcfFilterMethod; // Matches with PcfFilterMethod in ShadowConstants.h - uint m_padding[3]; }; enum ShadowFilterMethod diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h index 3244c8249e..75d266cc52 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DirectionalLightFeatureProcessorInterface.h @@ -149,12 +149,6 @@ namespace AZ //! @param method filter method. virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0; - //! This sets sample count to predict boundary of shadow. - //! @param handle the light handle. - //! @param count Sample Count for prediction of whether the pixel is on the boundary (up to 16) - //! The value should be less than or equal to m_filteringSampleCount. - virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0; - //! This sets sample count for filtering of shadow boundary. //! @param handle the light handle. //! @param count Sample Count for filtering (up to 64) @@ -166,9 +160,6 @@ namespace AZ //! If width == 0, softening edge is disabled. Units are in meters. virtual void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) = 0; - //! Sets the shadowmap Pcf method. - virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; - //! Sets whether the directional shadowmap should use receiver plane bias. //! This attempts to reduce shadow acne when using large pcf filters. virtual void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) = 0; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h index bcb470d831..3ab83200ae 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/DiskLightFeatureProcessorInterface.h @@ -92,12 +92,8 @@ namespace AZ virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0; //! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on the boundary. 0 disables softening. virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0; - //! Sets sample count to predict boundary of shadow (up to 16). It will be clamped to be less than or equal to the filtering sample count. - virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets sample count for filtering of shadow boundary (up to 64) virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; - //! Sets the shadowmap Pcf (percentage closer filtering) method. - virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; //! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow. virtual void SetEsmExponent(LightHandle handle, float exponent) = 0; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h index 3383378dc7..6752ac4c52 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/PointLightFeatureProcessorInterface.h @@ -73,13 +73,8 @@ namespace AZ //! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on //! the boundary. 0 disables softening. virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0; - //! Sets sample count to predict boundary of shadow (up to 16). It will be clamped to be less than or equal to the filtering - //! sample count. - virtual void SetPredictionSampleCount(LightHandle handle, uint16_t count) = 0; //! Sets sample count for filtering of shadow boundary (up to 64) virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0; - //! Sets the shadowmap Pcf (percentage closer filtering) method. - virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0; //! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow. virtual void SetEsmExponent(LightHandle handle, float exponent) = 0; //! Sets all of the the point data for the provided LightHandle. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h index 2d0811be9e..dbad3af21f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/CoreLights/ShadowConstants.h @@ -37,14 +37,6 @@ namespace AZ Count }; - enum class PcfMethod : uint16_t - { - BoundarySearch = 0, // Performs a variable number of taps, first to determine if we are on a shadow boundary, then the remaining taps are to find the occlusion amount - Bicubic, // Uses a fixed size Pcf kernel with kernel weights set to approximate bicubic filtering - - Count - }; - namespace Shadow { // [GFX TODO][ATOM-2408] Make the max number of cascade modifiable at runtime. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h index 6cbb0cfef1..3d6c0c3015 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Shadows/ProjectedShadowFeatureProcessorInterface.h @@ -52,14 +52,10 @@ namespace AZ::Render virtual void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) = 0; //! Sets the shadow bias virtual void SetShadowBias(ShadowId id, float bias) = 0; - //! Sets the shadowmap Pcf method. - virtual void SetPcfMethod(ShadowId id, PcfMethod method) = 0; //! Sets the shadow filter method virtual void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) = 0; //! Sets the width of boundary between shadowed area and lit area. virtual void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) = 0; - //! Sets the sample count to predict the boundary of the shadow. Max 16, should be less than filtering sample count. - virtual void SetPredictionSampleCount(ShadowId id, uint16_t count) = 0; //! Sets the sample count for filtering of the shadow boundary, max 64. virtual void SetFilteringSampleCount(ShadowId id, uint16_t count) = 0; //! Sets all of the shadow properites in one call diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 44f95a8b85..c235f78595 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -571,20 +571,6 @@ namespace AZ } } - void DirectionalLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count) - { - if (count > Shadow::MaxPcfSamplingCount) - { - AZ_Warning(FeatureProcessorName, false, "Sampling count exceed the limit."); - count = Shadow::MaxPcfSamplingCount; - } - for (auto& it : m_shadowData) - { - it.second.GetData(handle.GetIndex()).m_predictionSampleCount = count; - } - m_shadowBufferNeedsUpdate = true; - } - void DirectionalLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count) { if (count > Shadow::MaxPcfSamplingCount) @@ -608,15 +594,6 @@ namespace AZ m_shadowBufferNeedsUpdate = true; } - void DirectionalLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method) - { - for (auto& it : m_shadowData) - { - it.second.GetData(handle.GetIndex()).m_pcfMethod = method; - } - m_shadowBufferNeedsUpdate = true; - } - void DirectionalLightFeatureProcessor::SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) { m_shadowProperties.GetData(handle.GetIndex()).m_isReceiverPlaneBiasEnabled = enable; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h index d57b3aaf2b..039f51d549 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h @@ -102,8 +102,6 @@ namespace AZ uint32_t m_debugFlags = 0; uint32_t m_shadowFilterMethod = 0; float m_far_minus_near = 0; - PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; - uint32_t m_padding[3]; }; class DirectionalLightFeatureProcessor final @@ -218,10 +216,8 @@ namespace AZ void SetViewFrustumCorrectionEnabled(LightHandle handle, bool enabled) override; void SetDebugFlags(LightHandle handle, DebugDrawFlags flags) override; void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; - void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) override; - void SetPcfMethod(LightHandle handle, PcfMethod method) override; void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) override; const Data::Instance GetLightBuffer() const; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index 55be9d232e..dfbeea0ffe 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -329,21 +329,11 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians); } - void DiskLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count) - { - SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPredictionSampleCount, count); - } - void DiskLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count) { SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetFilteringSampleCount, count); } - void DiskLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method) - { - SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); - } - void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent) { SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h index 36837a67fb..d65f587718 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.h @@ -54,9 +54,7 @@ namespace AZ void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override; void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override; - void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; - void SetPcfMethod(LightHandle handle, PcfMethod method) override; void SetEsmExponent(LightHandle handle, float esmExponent) override; void SetDiskData(LightHandle handle, const DiskLightData& data) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp index 9baa2ae1c2..af440e5040 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp @@ -298,21 +298,11 @@ namespace AZ SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians); } - void PointLightFeatureProcessor::SetPredictionSampleCount(LightHandle handle, uint16_t count) - { - SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPredictionSampleCount, count); - } - void PointLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count) { SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetFilteringSampleCount, count); } - void PointLightFeatureProcessor::SetPcfMethod(LightHandle handle, PcfMethod method) - { - SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method); - } - void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent) { SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent); diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h index 3c231c1fb0..b784eb1bb5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.h @@ -51,9 +51,7 @@ namespace AZ void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override; void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override; - void SetPredictionSampleCount(LightHandle handle, uint16_t count) override; void SetFilteringSampleCount(LightHandle handle, uint16_t count) override; - void SetPcfMethod(LightHandle handle, PcfMethod method) override; void SetEsmExponent(LightHandle handle, float esmExponent) override; void SetPointData(LightHandle handle, const PointLightData& data) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index 68dac8f773..68c31bd859 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -165,15 +165,6 @@ namespace AZ::Render m_filterParameterNeedsUpdate = true; } - void ProjectedShadowFeatureProcessor::SetPcfMethod(ShadowId id, PcfMethod method) - { - AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPcfMethod()."); - ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); - shadowData.m_pcfMethod = method; - - m_deviceBufferNeedsUpdate = true; - } - void ProjectedShadowFeatureProcessor::SetEsmExponent(ShadowId id, float exponent) { AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetEsmExponent()."); @@ -188,7 +179,7 @@ namespace AZ::Render ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id); ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); - shadowData.m_shadowFilterMethod = aznumeric_cast(method); + shadowData.m_shadowFilterMethod = aznumeric_cast(method); UpdateShadowView(shadowProperty); @@ -207,19 +198,6 @@ namespace AZ::Render m_filterParameterNeedsUpdate = true; } - void ProjectedShadowFeatureProcessor::SetPredictionSampleCount(ShadowId id, uint16_t count) - { - AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPredictionSampleCount()."); - - AZ_Warning("ProjectedShadowFeatureProcessor", count <= Shadow::MaxPcfSamplingCount, "Sampling count exceed the limit."); - count = GetMin(count, Shadow::MaxPcfSamplingCount); - - ShadowData& shadowData = m_shadowData.GetElement(id.GetIndex()); - shadowData.m_predictionSampleCount = count; - - m_deviceBufferNeedsUpdate = true; - } - void ProjectedShadowFeatureProcessor::SetFilteringSampleCount(ShadowId id, uint16_t count) { AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetFilteringSampleCount()."); diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h index 8beed800b6..f4c6cad7bf 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.h @@ -48,11 +48,9 @@ namespace AZ::Render void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override; void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override; void SetShadowBias(ShadowId id, float bias) override; - void SetPcfMethod(ShadowId id, PcfMethod method); void SetEsmExponent(ShadowId id, float exponent); void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override; - void SetPredictionSampleCount(ShadowId id, uint16_t count) override; void SetFilteringSampleCount(ShadowId id, uint16_t count) override; void SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) override; const ProjectedShadowDescriptor& GetShadowProperties(ShadowId id) override; @@ -64,8 +62,7 @@ namespace AZ::Render { Matrix4x4 m_depthBiasMatrix = Matrix4x4::CreateIdentity(); uint32_t m_shadowmapArraySlice = 0; // array slice who has shadowmap in the atlas. - uint16_t m_shadowFilterMethod = 0; // filtering method of shadows. - PcfMethod m_pcfMethod = PcfMethod::BoundarySearch; // method for performing Pcf (uint16_t) + uint32_t m_shadowFilterMethod = 0; // filtering method of shadows. float m_boundaryScale = 0.f; // the half of boundary of lit/shadowed areas. (in degrees) uint32_t m_predictionSampleCount = 0; // sample count to judge whether it is on the shadow boundary or not. uint32_t m_filteringSampleCount = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h index 06b00a6b84..557e6b3dd2 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h @@ -127,25 +127,12 @@ namespace AZ //! 0 disables softening. virtual void SetSofteningBoundaryWidthAngle(float degrees) = 0; - //! Gets the sample count to predict boundary of shadow. - virtual uint32_t GetPredictionSampleCount() const = 0; - - //! Sets the sample count to predict boundary of shadow. Maximum 16, and should also be - //! less than the filtering sample count. - virtual void SetPredictionSampleCount(uint32_t count) = 0; - //! Gets the sample count for filtering of the shadow boundary. virtual uint32_t GetFilteringSampleCount() const = 0; //! Sets the sample count for filtering of the shadow boundary. Maximum 64. virtual void SetFilteringSampleCount(uint32_t count) = 0; - //! Gets the type of Pcf (percentage-closer filtering) to use. - virtual PcfMethod GetPcfMethod() const = 0; - - //! Sets the type of Pcf (percentage-closer filtering) to use. - virtual void SetPcfMethod(PcfMethod method) = 0; - //! Gets the Esm exponent. Higher values produce a steeper falloff between light and shadow. virtual float GetEsmExponent() const = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h index 74eb10fdb6..a6d3c6fbed 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/AreaLightComponentConfig.h @@ -59,9 +59,7 @@ namespace AZ float m_bias = 0.1f; ShadowmapSize m_shadowmapMaxSize = ShadowmapSize::Size256; ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None; - PcfMethod m_pcfMethod = PcfMethod::Bicubic; float m_boundaryWidthInDegrees = 0.25f; - uint16_t m_predictionSampleCount = 4; uint16_t m_filteringSampleCount = 12; float m_esmExponent = 87.0f; @@ -119,14 +117,8 @@ namespace AZ //! Returns true if pcf shadows are disabled. bool IsShadowPcfDisabled() const; - //! Returns true if pcf boundary search is disabled. - bool IsPcfBoundarySearchDisabled() const; - //! Returns true if exponential shadow maps are disabled. bool IsEsmDisabled() const; - - //! Returns true if the softening boundary width parameter is disabled. - bool IsSofteningBoundaryWidthDisabled() const; }; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h index 610578ee2d..644856e768 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightBus.h @@ -162,15 +162,6 @@ namespace AZ //! If width == 0, softening edge is disabled. Units are in meters. virtual void SetSofteningBoundaryWidth(float width) = 0; - //! This gets sample count to predict boundary of shadow. - //! @return Sample Count for prediction of whether the pixel is on the boundary (up to 16) - virtual uint32_t GetPredictionSampleCount() const = 0; - - //! This sets sample count to predict boundary of shadow. - //! @param count Sample Count for prediction of whether the pixel is on the boundary (up to 16) - //! The value should be less than or equal to m_filteringSampleCount. - virtual void SetPredictionSampleCount(uint32_t count) = 0; - //! This gets the sample count for filtering of the shadow boundary. //! @return Sample Count for filtering (up to 64) virtual uint32_t GetFilteringSampleCount() const = 0; @@ -179,13 +170,6 @@ namespace AZ //! @param count Sample Count for filtering (up to 64) virtual void SetFilteringSampleCount(uint32_t count) = 0; - //! This gets the type of Pcf (percentage-closer filtering) to use. - virtual PcfMethod GetPcfMethod() const = 0; - - //! This sets the type of Pcf (percentage-closer filtering) to use. - //! @param method The Pcf method to use. - virtual void SetPcfMethod(PcfMethod method) = 0; - //! Gets whether the directional shadowmap should use receiver plane bias. //! This attempts to reduce shadow acne when using large pcf filters. virtual bool GetShadowReceiverPlaneBiasEnabled() const = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h index e9e5778086..0123d06275 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/CoreLights/DirectionalLightComponentConfig.h @@ -105,16 +105,10 @@ namespace AZ //! If this is 0, edge softening is disabled. Units are in meters. float m_boundaryWidth = 0.03f; // 3cm - //! Sample Count for prediction of whether the pixel is on the boundary (from 4 to 16) - //! The value should be less than or equal to m_filteringSampleCount. - uint16_t m_predictionSampleCount = 4; - //! Sample Count for filtering (from 4 to 64) //! It is used only when the pixel is predicted as on the boundary. uint16_t m_filteringSampleCount = 32; - PcfMethod m_pcfMethod = PcfMethod::Bicubic; - //! Whether not to enable the receiver plane bias. //! This uses partial derivatives to reduce shadow acne when using large pcf kernels. bool m_receiverPlaneBiasEnabled = true; @@ -124,8 +118,6 @@ namespace AZ bool IsCascadeCorrectionDisabled() const; bool IsShadowFilteringDisabled() const; bool IsShadowPcfDisabled() const; - bool IsPcfBoundarySearchDisabled() const; - bool IsSofteningBoundaryWidthDisabled() const; bool IsEsmDisabled() const; }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp index 550a09469f..c7af44a28e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentConfig.cpp @@ -37,9 +37,7 @@ namespace AZ ->Field("Shadowmap Max Size", &AreaLightComponentConfig::m_shadowmapMaxSize) ->Field("Shadow Filter Method", &AreaLightComponentConfig::m_shadowFilterMethod) ->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees) - ->Field("Prediction Sample Count", &AreaLightComponentConfig::m_predictionSampleCount) ->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount) - ->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod) ->Field("Esm Exponent", &AreaLightComponentConfig::m_esmExponent) ; } @@ -182,31 +180,9 @@ namespace AZ m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); } - bool AreaLightComponentConfig::IsPcfBoundarySearchDisabled() const - { - if (IsShadowPcfDisabled()) - { - return true; - } - - return m_pcfMethod != PcfMethod::BoundarySearch; - } - bool AreaLightComponentConfig::IsEsmDisabled() const { return !(m_shadowFilterMethod == ShadowFilterMethod::Esm || m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); } - - bool AreaLightComponentConfig::IsSofteningBoundaryWidthDisabled() const - { - // softening boundary width is always available with ESM. It controls the width of the blur kernel during the ESM gaussian - // blur passes - if (!IsEsmDisabled()) - return false; - - // with PCF, softening boundary width is used with the boundary search method and NOT the bicubic pcf methods - return IsPcfBoundarySearchDisabled(); - } - } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp index 0a5598a74a..c0204ecac5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.cpp @@ -76,12 +76,8 @@ namespace AZ::Render ->Event("SetShadowFilterMethod", &AreaLightRequestBus::Events::SetShadowFilterMethod) ->Event("GetSofteningBoundaryWidthAngle", &AreaLightRequestBus::Events::GetSofteningBoundaryWidthAngle) ->Event("SetSofteningBoundaryWidthAngle", &AreaLightRequestBus::Events::SetSofteningBoundaryWidthAngle) - ->Event("GetPredictionSampleCount", &AreaLightRequestBus::Events::GetPredictionSampleCount) - ->Event("SetPredictionSampleCount", &AreaLightRequestBus::Events::SetPredictionSampleCount) ->Event("GetFilteringSampleCount", &AreaLightRequestBus::Events::GetFilteringSampleCount) ->Event("SetFilteringSampleCount", &AreaLightRequestBus::Events::SetFilteringSampleCount) - ->Event("GetPcfMethod", &AreaLightRequestBus::Events::GetPcfMethod) - ->Event("SetPcfMethod", &AreaLightRequestBus::Events::SetPcfMethod) ->Event("GetEsmExponent", &AreaLightRequestBus::Events::GetEsmExponent) ->Event("SetEsmExponent", &AreaLightRequestBus::Events::SetEsmExponent) @@ -100,9 +96,7 @@ namespace AZ::Render ->VirtualProperty("ShadowmapMaxSize", "GetShadowmapMaxSize", "SetShadowmapMaxSize") ->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod") ->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle") - ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod") ->VirtualProperty("EsmExponent", "GetEsmExponent", "SetEsmExponent"); ; } @@ -314,9 +308,7 @@ namespace AZ::Render m_lightShapeDelegate->SetShadowmapMaxSize(m_configuration.m_shadowmapMaxSize); m_lightShapeDelegate->SetShadowFilterMethod(m_configuration.m_shadowFilterMethod); m_lightShapeDelegate->SetSofteningBoundaryWidthAngle(m_configuration.m_boundaryWidthInDegrees); - m_lightShapeDelegate->SetPredictionSampleCount(m_configuration.m_predictionSampleCount); m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount); - m_lightShapeDelegate->SetPcfMethod(m_configuration.m_pcfMethod); m_lightShapeDelegate->SetEsmExponent(m_configuration.m_esmExponent); } } @@ -528,20 +520,6 @@ namespace AZ::Render } } - uint32_t AreaLightComponentController::GetPredictionSampleCount() const - { - return m_configuration.m_predictionSampleCount; - } - - void AreaLightComponentController::SetPredictionSampleCount(uint32_t count) - { - m_configuration.m_predictionSampleCount = static_cast(count); - if (m_lightShapeDelegate) - { - m_lightShapeDelegate->SetPredictionSampleCount(count); - } - } - uint32_t AreaLightComponentController::GetFilteringSampleCount() const { return m_configuration.m_filteringSampleCount; @@ -568,20 +546,6 @@ namespace AZ::Render m_lightShapeDelegate->DrawDebugDisplay(transform, m_configuration.m_color, debugDisplay, isSelected); } } - - PcfMethod AreaLightComponentController::GetPcfMethod() const - { - return m_configuration.m_pcfMethod; - } - - void AreaLightComponentController::SetPcfMethod(PcfMethod method) - { - m_configuration.m_pcfMethod = method; - if (m_lightShapeDelegate) - { - m_lightShapeDelegate->SetPcfMethod(method); - } - } float AreaLightComponentController::GetEsmExponent() const { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h index d290beb81d..3bec61551f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/AreaLightComponentController.h @@ -84,12 +84,8 @@ namespace AZ void SetShadowFilterMethod(ShadowFilterMethod method) override; float GetSofteningBoundaryWidthAngle() const override; void SetSofteningBoundaryWidthAngle(float width) override; - uint32_t GetPredictionSampleCount() const override; - void SetPredictionSampleCount(uint32_t count) override; uint32_t GetFilteringSampleCount() const override; void SetFilteringSampleCount(uint32_t count) override; - PcfMethod GetPcfMethod() const override; - void SetPcfMethod(PcfMethod method) override; float GetEsmExponent() const override; void SetEsmExponent(float exponent) override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp index 24ce566fb4..37d94f5ed1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentConfig.cpp @@ -38,9 +38,7 @@ namespace AZ ->Field("IsDebugColoringEnabled", &DirectionalLightComponentConfig::m_isDebugColoringEnabled) ->Field("ShadowFilterMethod", &DirectionalLightComponentConfig::m_shadowFilterMethod) ->Field("SofteningBoundaryWidth", &DirectionalLightComponentConfig::m_boundaryWidth) - ->Field("PcfPredictionSampleCount", &DirectionalLightComponentConfig::m_predictionSampleCount) ->Field("PcfFilteringSampleCount", &DirectionalLightComponentConfig::m_filteringSampleCount) - ->Field("Pcf Method", &DirectionalLightComponentConfig::m_pcfMethod) ->Field("ShadowReceiverPlaneBiasEnabled", &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled); } } @@ -118,31 +116,9 @@ namespace AZ m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); } - bool DirectionalLightComponentConfig::IsPcfBoundarySearchDisabled() const - { - if (IsShadowPcfDisabled()) - { - return true; - } - - return m_pcfMethod != PcfMethod::BoundarySearch; - } - bool DirectionalLightComponentConfig::IsEsmDisabled() const { return !(m_shadowFilterMethod == ShadowFilterMethod::Esm || m_shadowFilterMethod == ShadowFilterMethod::EsmPcf); } - - bool DirectionalLightComponentConfig::IsSofteningBoundaryWidthDisabled() const - { - // softening boundary width is always available with ESM. It controls the width of the blur kernel during the ESM gaussian - // blur passes - if (!IsEsmDisabled()) - return false; - - // with PCF, softening boundary width is used with the boundary search method and NOT the bicubic pcf methods - return IsPcfBoundarySearchDisabled(); - } - } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp index 6bf449803b..fbc1ccc35d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp @@ -82,12 +82,8 @@ namespace AZ ->Event("SetShadowFilterMethod", &DirectionalLightRequestBus::Events::SetShadowFilterMethod) ->Event("GetSofteningBoundaryWidth", &DirectionalLightRequestBus::Events::GetSofteningBoundaryWidth) ->Event("SetSofteningBoundaryWidth", &DirectionalLightRequestBus::Events::SetSofteningBoundaryWidth) - ->Event("GetPredictionSampleCount", &DirectionalLightRequestBus::Events::GetPredictionSampleCount) - ->Event("SetPredictionSampleCount", &DirectionalLightRequestBus::Events::SetPredictionSampleCount) ->Event("GetFilteringSampleCount", &DirectionalLightRequestBus::Events::GetFilteringSampleCount) ->Event("SetFilteringSampleCount", &DirectionalLightRequestBus::Events::SetFilteringSampleCount) - ->Event("GetPcfMethod", &DirectionalLightRequestBus::Events::GetPcfMethod) - ->Event("SetPcfMethod", &DirectionalLightRequestBus::Events::SetPcfMethod) ->Event("GetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::GetShadowReceiverPlaneBiasEnabled) ->Event("SetShadowReceiverPlaneBiasEnabled", &DirectionalLightRequestBus::Events::SetShadowReceiverPlaneBiasEnabled) ->VirtualProperty("Color", "GetColor", "SetColor") @@ -104,9 +100,7 @@ namespace AZ ->VirtualProperty("DebugColoringEnabled", "GetDebugColoringEnabled", "SetDebugColoringEnabled") ->VirtualProperty("ShadowFilterMethod", "GetShadowFilterMethod", "SetShadowFilterMethod") ->VirtualProperty("SofteningBoundaryWidth", "GetSofteningBoundaryWidth", "SetSofteningBoundaryWidth") - ->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount") ->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount") - ->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod") ->VirtualProperty("ShadowReceiverPlaneBiasEnabled", "GetShadowReceiverPlaneBiasEnabled", "SetShadowReceiverPlaneBiasEnabled"); ; } @@ -425,21 +419,6 @@ namespace AZ } } - uint32_t DirectionalLightComponentController::GetPredictionSampleCount() const - { - return aznumeric_cast(m_configuration.m_predictionSampleCount); - } - - void DirectionalLightComponentController::SetPredictionSampleCount(uint32_t count) - { - const uint16_t count16 = GetMin(Shadow::MaxPcfSamplingCount, aznumeric_cast(count)); - m_configuration.m_predictionSampleCount = count16; - if (m_featureProcessor) - { - m_featureProcessor->SetPredictionSampleCount(m_lightHandle, count16); - } - } - uint32_t DirectionalLightComponentController::GetFilteringSampleCount() const { return aznumeric_cast(m_configuration.m_filteringSampleCount); @@ -539,9 +518,7 @@ namespace AZ SetDebugColoringEnabled(m_configuration.m_isDebugColoringEnabled); SetShadowFilterMethod(m_configuration.m_shadowFilterMethod); SetSofteningBoundaryWidth(m_configuration.m_boundaryWidth); - SetPredictionSampleCount(m_configuration.m_predictionSampleCount); SetFilteringSampleCount(m_configuration.m_filteringSampleCount); - SetPcfMethod(m_configuration.m_pcfMethod); SetShadowReceiverPlaneBiasEnabled(m_configuration.m_receiverPlaneBiasEnabled); // [GFX TODO][ATOM-1726] share config for multiple light (e.g., light ID). @@ -631,17 +608,6 @@ namespace AZ } } - PcfMethod DirectionalLightComponentController::GetPcfMethod() const - { - return m_configuration.m_pcfMethod; - } - - void DirectionalLightComponentController::SetPcfMethod(PcfMethod method) - { - m_configuration.m_pcfMethod = method; - m_featureProcessor->SetPcfMethod(m_lightHandle, method); - } - bool DirectionalLightComponentController::GetShadowReceiverPlaneBiasEnabled() const { return m_configuration.m_receiverPlaneBiasEnabled; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h index 6b788c241c..b8052bfc36 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.h @@ -78,12 +78,8 @@ namespace AZ void SetShadowFilterMethod(ShadowFilterMethod method) override; float GetSofteningBoundaryWidth() const override; void SetSofteningBoundaryWidth(float width) override; - uint32_t GetPredictionSampleCount() const override; - void SetPredictionSampleCount(uint32_t count) override; uint32_t GetFilteringSampleCount() const override; void SetFilteringSampleCount(uint32_t count) override; - PcfMethod GetPcfMethod() const override; - void SetPcfMethod(PcfMethod method) override; bool GetShadowReceiverPlaneBiasEnabled() const override; void SetShadowReceiverPlaneBiasEnabled(bool enable) override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp index 91856f7ee5..baf0cdced1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.cpp @@ -155,14 +155,6 @@ namespace AZ::Render } } - void DiskLightDelegate::SetPredictionSampleCount(uint32_t count) - { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), static_cast(count)); - } - } - void DiskLightDelegate::SetFilteringSampleCount(uint32_t count) { if (GetShadowsEnabled() && GetLightHandle().IsValid()) @@ -171,14 +163,6 @@ namespace AZ::Render } } - void DiskLightDelegate::SetPcfMethod(PcfMethod method) - { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method); - } - } - void DiskLightDelegate::SetEsmExponent(float exponent) { if (GetShadowsEnabled() && GetLightHandle().IsValid()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h index 6931068635..e0fd16f6be 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DiskLightDelegate.h @@ -45,9 +45,7 @@ namespace AZ void SetShadowmapMaxSize(ShadowmapSize size) override; void SetShadowFilterMethod(ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(float widthInDegrees) override; - void SetPredictionSampleCount(uint32_t count) override; void SetFilteringSampleCount(uint32_t count) override; - void SetPcfMethod(PcfMethod method) override; void SetEsmExponent(float exponent) override; private: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 17fb9a5e1d..659c394cba 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -162,29 +162,13 @@ namespace AZ ->Attribute(Edit::Attributes::Max, 1.f) ->Attribute(Edit::Attributes::Suffix, " deg") ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsSofteningBoundaryWidthDisabled) - ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_predictionSampleCount, "Prediction sample count", - "Sample count for prediction of whether the pixel is on the boundary. Specific to PCF and ESM+PCF.") - ->Attribute(Edit::Attributes::Min, 4) - ->Attribute(Edit::Attributes::Max, 16) - ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsPcfBoundarySearchDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled) ->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_filteringSampleCount, "Filtering sample count", "This is only used when the pixel is predicted to be on the boundary. Specific to PCF and ESM+PCF.") ->Attribute(Edit::Attributes::Min, 4) ->Attribute(Edit::Attributes::Max, 64) ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) - ->DataElement( - Edit::UIHandlers::ComboBox, &AreaLightComponentConfig::m_pcfMethod, "PCF method", - "Type of PCF to use.\n" - " Bicubic: a smooth, fixed-size kernel \n" - " Boundary search: do several taps to first determine if we are on a shadow boundary\n") - ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") - ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows) - ->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled) ->DataElement( Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_esmExponent, "ESM exponent", "Exponent used by ESM shadows. " diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp index 18d9ad70e0..ef9c73c0b4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp @@ -141,14 +141,7 @@ namespace AZ ->Attribute(Edit::Attributes::Max, 0.1f) ->Attribute(Edit::Attributes::Suffix, " m") ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsSofteningBoundaryWidthDisabled) - ->DataElement(Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_predictionSampleCount, "Prediction sample count", - "Sample count for prediction of whether the pixel is on the boundary. " - "Specific to PCF and ESM+PCF.") - ->Attribute(Edit::Attributes::Min, 4) - ->Attribute(Edit::Attributes::Max, 16) - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsPcfBoundarySearchDisabled) + ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsEsmDisabled) ->DataElement(Edit::UIHandlers::Slider, &DirectionalLightComponentConfig::m_filteringSampleCount, "Filtering sample count", "This is used only when the pixel is predicted as on the boundary. " "Specific to PCF and ESM+PCF.") @@ -156,15 +149,6 @@ namespace AZ ->Attribute(Edit::Attributes::Max, 64) ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled) - ->DataElement( - Edit::UIHandlers::ComboBox, &DirectionalLightComponentConfig::m_pcfMethod, "Pcf method", - "Type of PCF to use.\n" - " Bicubic: a smooth, fixed-size kernel \n" - " Boundary search: do several taps to first determine if we are on a shadow boundary\n") - ->EnumAttribute(PcfMethod::Bicubic, "Bicubic") - ->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search") - ->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly) - ->Attribute(Edit::Attributes::ReadOnly, &DirectionalLightComponentConfig::IsShadowPcfDisabled) ->DataElement( Edit::UIHandlers::CheckBox, &DirectionalLightComponentConfig::m_receiverPlaneBiasEnabled, "Shadow Receiver Plane Bias Enable", diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h index 415878081c..2bd25b76a3 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateBase.h @@ -57,9 +57,7 @@ namespace AZ void SetShadowmapMaxSize([[maybe_unused]] ShadowmapSize size) override {}; void SetShadowFilterMethod([[maybe_unused]] ShadowFilterMethod method) override {}; void SetSofteningBoundaryWidthAngle([[maybe_unused]] float widthInDegrees) override {}; - void SetPredictionSampleCount([[maybe_unused]] uint32_t count) override {}; void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {}; - void SetPcfMethod([[maybe_unused]] PcfMethod method) override {}; void SetEsmExponent([[maybe_unused]] float esmExponent) override{}; protected: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h index f18c3ef9af..6d08971542 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/LightDelegateInterface.h @@ -77,12 +77,8 @@ namespace AZ virtual void SetShadowFilterMethod(ShadowFilterMethod method) = 0; //! Sets the width of boundary between shadowed area and lit area in degrees. virtual void SetSofteningBoundaryWidthAngle(float widthInDegrees) = 0; - //! Sets the sample count to predict the boundary of the shadow. Max 16, should be less than filtering sample count. - virtual void SetPredictionSampleCount(uint32_t count) = 0; //! Sets the sample count for filtering of the shadow boundary, max 64. virtual void SetFilteringSampleCount(uint32_t count) = 0; - //! Sets the Pcf (Percentage closer filtering) method to use. - virtual void SetPcfMethod(PcfMethod method) = 0; //! Sets the Esm exponent to use. Higher values produce a steeper falloff between light and shadow. virtual void SetEsmExponent(float exponent) = 0; }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp index b4728c0c38..8853db5751 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.cpp @@ -100,14 +100,6 @@ namespace AZ::Render } } - void SphereLightDelegate::SetPredictionSampleCount(uint32_t count) - { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPredictionSampleCount(GetLightHandle(), static_cast(count)); - } - } - void SphereLightDelegate::SetFilteringSampleCount(uint32_t count) { if (GetShadowsEnabled() && GetLightHandle().IsValid()) @@ -116,14 +108,6 @@ namespace AZ::Render } } - void SphereLightDelegate::SetPcfMethod(PcfMethod method) - { - if (GetShadowsEnabled() && GetLightHandle().IsValid()) - { - GetFeatureProcessor()->SetPcfMethod(GetLightHandle(), method); - } - } - void SphereLightDelegate::SetEsmExponent(float esmExponent) { if (GetShadowsEnabled() && GetLightHandle().IsValid()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h index 984af56c17..e2903b2d72 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/SphereLightDelegate.h @@ -35,9 +35,7 @@ namespace AZ void SetShadowmapMaxSize(ShadowmapSize size) override; void SetShadowFilterMethod(ShadowFilterMethod method) override; void SetSofteningBoundaryWidthAngle(float widthInDegrees) override; - void SetPredictionSampleCount(uint32_t count) override; void SetFilteringSampleCount(uint32_t count) override; - void SetPcfMethod(PcfMethod method) override; void SetEsmExponent(float esmExponent) override; private: From f7d4b8e70f5efd91b52a237dc31aaafa8d75f7f9 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 14 Sep 2021 19:11:11 -0500 Subject: [PATCH 121/274] Changing material component property inspector to dockable view pane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Inspector is locked to a specific entity and material assignment ID • All modifications are made via the material component request bus • Removed complicated configuration management in editor material component • Multiple material property inspectors can be opened • Multiple materials across different entities can be edited simultaneously • No longer blocks the viewport or other interactions • Added functions to material component request bus for retrieving material slot labels, default materials, getting and setting property and UV overrides • Added more asset related types to material property value conversion from any • Added support for static heading widget on top of atom tools inspector, currently used for menus and messages WIP: Still investigating intermittent crash because of corrupt asset property Signed-off-by: Guthrie Adams --- .../Material/MaterialPropertyValue.cpp | 20 +- .../Inspector/InspectorRequestBus.h | 6 + .../Inspector/InspectorWidget.h | 5 +- .../InspectorPropertyGroupWidget.cpp | 2 +- .../Code/Source/Inspector/InspectorWidget.cpp | 56 +-- .../Code/Source/Inspector/InspectorWidget.ui | 147 ++++-- .../EditorMaterialSystemComponentRequestBus.h | 10 +- .../Material/MaterialComponentBus.h | 16 +- .../Material/EditorMaterialComponent.cpp | 192 ++------ .../Source/Material/EditorMaterialComponent.h | 16 +- .../EditorMaterialComponentInspector.cpp | 444 ++++++++++++------ .../EditorMaterialComponentInspector.h | 60 ++- .../Material/EditorMaterialComponentSlot.cpp | 149 +++--- .../Material/EditorMaterialComponentSlot.h | 19 +- .../EditorMaterialSystemComponent.cpp | 68 ++- .../Material/EditorMaterialSystemComponent.h | 16 +- .../Material/MaterialBrowserInteractions.cpp | 15 +- .../Material/MaterialComponentController.cpp | 124 ++++- .../Material/MaterialComponentController.h | 9 +- 19 files changed, 822 insertions(+), 552 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp index 849e6cfffb..13ecea52dc 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialPropertyValue.cpp @@ -109,11 +109,20 @@ namespace AZ { result.m_value = AZStd::any_cast(value); } + else if (value.is()) + { + result.m_value = Data::Asset( + AZStd::any_cast(value), azrtti_typeid()); + } + else if (value.is>()) + { + result.m_value = Data::Asset( + AZStd::any_cast>(value).GetId(), azrtti_typeid()); + } else if (value.is>()) { result.m_value = Data::Asset( - AZStd::any_cast>(value).GetId(), - azrtti_typeid()); + AZStd::any_cast>(value).GetId(), azrtti_typeid()); } else if (value.is>()) { @@ -129,7 +138,8 @@ namespace AZ } else { - AZ_Warning("MaterialPropertyValue", false, "Cannot convert any to variant. Type in any is: %s.", + AZ_Warning( + "MaterialPropertyValue", false, "Cannot convert any to variant. Type in any is: %s.", value.get_type_info().m_id.ToString().data()); } @@ -187,5 +197,5 @@ namespace AZ return result; } - } -} + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h index ec16653540..900dc3535c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorRequestBus.h @@ -24,6 +24,12 @@ namespace AtomToolsFramework static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; typedef AZ::Uuid BusIdType; + //! Add heading widget above scroll area + virtual void AddHeading(QWidget* headingWidget) = 0; + + //! Clear heading widgets + virtual void ClearHeading() = 0; + //! Clear all inspector groups and content virtual void Reset() = 0; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h index 3d4e252967..adcd94ca10 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -41,6 +41,10 @@ namespace AtomToolsFramework ~InspectorWidget() override; // InspectorRequestBus::Handler overrides... + void AddHeading(QWidget* headingWidget) override; + + void ClearHeading() override; + void Reset() override; void AddGroupsBegin() override; @@ -77,7 +81,6 @@ namespace AtomToolsFramework virtual void OnHeaderClicked(const AZStd::string& groupNameId, QMouseEvent* event); private: - QVBoxLayout* m_layout = nullptr; QScopedPointer m_ui; struct GroupWidgetPair diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorPropertyGroupWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorPropertyGroupWidget.cpp index 56f9538452..e1f8573bb3 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorPropertyGroupWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorPropertyGroupWidget.cpp @@ -38,7 +38,7 @@ namespace AtomToolsFramework m_propertyEditor->Setup(context, instanceNotificationHandler, false); m_propertyEditor->AddInstance(instance, instanceClassId, nullptr, instanceToCompare); m_propertyEditor->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - m_propertyEditor->QueueInvalidation(AzToolsFramework::PropertyModificationRefreshLevel::Refresh_EntireTree); + m_propertyEditor->InvalidateAll(); m_layout->addWidget(m_propertyEditor); setLayout(m_layout); diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp index fe3af1d0ef..5eda93ca59 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.cpp @@ -29,30 +29,40 @@ namespace AtomToolsFramework { } + void InspectorWidget::AddHeading(QWidget* headingWidget) + { + headingWidget->setParent(m_ui->m_headingSection); + m_ui->m_headingSectionLayout->addWidget(headingWidget); + } + + void InspectorWidget::ClearHeading() + { + qDeleteAll(m_ui->m_headingSection->findChildren(QString(), Qt::FindDirectChildrenOnly)); + qDeleteAll(m_ui->m_headingSectionLayout->children()); + } + void InspectorWidget::Reset() { - qDeleteAll(m_ui->m_propertyContent->children()); - m_layout = new QVBoxLayout(m_ui->m_propertyContent); - m_layout->setContentsMargins(0, 0, 0, 0); - m_layout->setSpacing(0); + qDeleteAll(m_ui->m_groupContents->findChildren(QString(), Qt::FindDirectChildrenOnly)); + qDeleteAll(m_ui->m_groupContentsLayout->children()); m_groups.clear(); } void InspectorWidget::AddGroupsBegin() { - setUpdatesEnabled(false); + setVisible(false); Reset(); } void InspectorWidget::AddGroupsEnd() { - m_layout->addStretch(); + m_ui->m_groupContentsLayout->addStretch(); // Scroll to top whenever there is new content - m_ui->m_propertyScrollArea->verticalScrollBar()->setValue(m_ui->m_propertyScrollArea->verticalScrollBar()->minimum()); + m_ui->m_groupScrollArea->verticalScrollBar()->setValue(m_ui->m_groupScrollArea->verticalScrollBar()->minimum()); - setUpdatesEnabled(true); + setVisible(true); } void InspectorWidget::AddGroup( @@ -61,14 +71,14 @@ namespace AtomToolsFramework const AZStd::string& groupDescription, QWidget* groupWidget) { - InspectorGroupHeaderWidget* groupHeader = new InspectorGroupHeaderWidget(m_ui->m_propertyContent); + InspectorGroupHeaderWidget* groupHeader = new InspectorGroupHeaderWidget(m_ui->m_groupContents); groupHeader->setText(groupDisplayName.c_str()); groupHeader->setToolTip(groupDescription.c_str()); - m_layout->addWidget(groupHeader); + m_ui->m_groupContentsLayout->addWidget(groupHeader); groupWidget->setObjectName(groupNameId.c_str()); - groupWidget->setParent(m_ui->m_propertyContent); - m_layout->addWidget(groupWidget); + groupWidget->setParent(m_ui->m_groupContents); + m_ui->m_groupContentsLayout->addWidget(groupWidget); m_groups[groupNameId] = {groupHeader, groupWidget}; @@ -101,28 +111,18 @@ namespace AtomToolsFramework bool InspectorWidget::IsGroupVisible(const AZStd::string& groupNameId) const { auto groupItr = m_groups.find(groupNameId); - if (groupItr != m_groups.end()) - { - return groupItr->second.m_header->isVisible(); - } - - return false; + return groupItr != m_groups.end() ? groupItr->second.m_header->isVisible() : false; } bool InspectorWidget::IsGroupHidden(const AZStd::string& groupNameId) const { auto groupItr = m_groups.find(groupNameId); - if (groupItr != m_groups.end()) - { - return groupItr->second.m_header->isHidden(); - } - - return false; + return groupItr != m_groups.end() ? groupItr->second.m_header->isHidden() : false; } void InspectorWidget::RefreshGroup(const AZStd::string& groupNameId) { - for (auto groupWidget : m_ui->m_propertyContent->findChildren(groupNameId.c_str())) + for (auto groupWidget : m_ui->m_groupContents->findChildren(groupNameId.c_str())) { groupWidget->Refresh(); } @@ -130,7 +130,7 @@ namespace AtomToolsFramework void InspectorWidget::RebuildGroup(const AZStd::string& groupNameId) { - for (auto groupWidget : m_ui->m_propertyContent->findChildren(groupNameId.c_str())) + for (auto groupWidget : m_ui->m_groupContents->findChildren(groupNameId.c_str())) { groupWidget->Rebuild(); } @@ -138,7 +138,7 @@ namespace AtomToolsFramework void InspectorWidget::RefreshAll() { - for (auto groupWidget : m_ui->m_propertyContent->findChildren()) + for (auto groupWidget : m_ui->m_groupContents->findChildren()) { groupWidget->Refresh(); } @@ -146,7 +146,7 @@ namespace AtomToolsFramework void InspectorWidget::RebuildAll() { - for (auto groupWidget : m_ui->m_propertyContent->findChildren()) + for (auto groupWidget : m_ui->m_groupContents->findChildren()) { groupWidget->Rebuild(); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.ui b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.ui index 54976db849..13f9c9e41c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.ui +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.ui @@ -6,20 +6,14 @@ 0 0 - 693 - 798 + 685 + 775 - - - 0 - 0 - - Inspector - + 0 @@ -36,50 +30,103 @@ 0 - - - Qt::ScrollBarAsNeeded - - - true - - - - - 0 - 0 - 691 - 796 - + + + + 0 + + + 0 + + + 0 + + + 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::StyledPanel + + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 - - QFrame::Raised + + 0 - - - - + + + + Qt::ScrollBarAsNeeded + + + true + + + + + 0 + 0 + 683 + 763 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h index c75d596b52..47fad038b6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h @@ -7,6 +7,8 @@ */ #pragma once +#include +#include #include #include @@ -23,8 +25,12 @@ namespace AZ static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - //! Open document in material editor - virtual void OpenInMaterialEditor(const AZStd::string& sourcePath) = 0; + //! Open source material in material editor + virtual void OpenMaterialEditor(const AZStd::string& sourcePath) = 0; + + //! Open material instance editor + virtual void OpenMaterialInspector( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) = 0; }; using EditorMaterialSystemComponentRequestBus = AZ::EBus; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 01c87fa2fb..23fd276e95 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -23,6 +23,10 @@ namespace AZ virtual MaterialAssignmentMap GetOriginalMaterialAssignments() const = 0; //! Get material assignment id matching lod and label substring virtual MaterialAssignmentId FindMaterialAssignmentId(const MaterialAssignmentLodIndex lod, const AZStd::string& label) const = 0; + //! Get default material asset + virtual AZ::Data::AssetId GetDefaultMaterialAssetId(const MaterialAssignmentId& materialAssignmentId) const = 0; + //! Get material slot label + virtual AZStd::string GetMaterialSlotLabel(const MaterialAssignmentId& materialAssignmentId) const = 0; //! Set material overrides virtual void SetMaterialOverrides(const MaterialAssignmentMap& materials) = 0; //! Get material overrides @@ -38,7 +42,7 @@ namespace AZ //! Set material override virtual void SetMaterialOverride(const MaterialAssignmentId& materialAssignmentId, const AZ::Data::AssetId& materialAssetId) = 0; //! Get material override - virtual const AZ::Data::AssetId GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const = 0; + virtual AZ::Data::AssetId GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const = 0; //! Clear material override virtual void ClearMaterialOverride(const MaterialAssignmentId& materialAssignmentId) = 0; //! Set a material property override value wrapped by an AZStd::any @@ -95,8 +99,16 @@ namespace AZ virtual void ClearPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) = 0; //! Clear all property overrides virtual void ClearAllPropertyOverrides() = 0; + //! Set Property overrides for a specific material assignment + virtual void SetPropertyOverrides( + const MaterialAssignmentId& materialAssignmentId, const MaterialPropertyOverrideMap& propertyOverrides) = 0; //! Get Property overrides for a specific material assignment virtual MaterialPropertyOverrideMap GetPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) const = 0; + //! Set Model UV overrides for a specific material assignment + virtual void SetModelUvOverrides( + const MaterialAssignmentId& materialAssignmentId, const AZ::RPI::MaterialModelUvOverrideMap& modelUvOverrides) = 0; + //! Get Model UV overrides for a specific material assignment + virtual AZ::RPI::MaterialModelUvOverrideMap GetModelUvOverrides(const MaterialAssignmentId& materialAssignmentId) const = 0; }; using MaterialComponentRequestBus = EBus; @@ -106,7 +118,7 @@ namespace AZ { public: virtual void OnMaterialsUpdated([[maybe_unused]] const MaterialAssignmentMap& materials) {} - virtual void OnMaterialsEdited([[maybe_unused]] const MaterialAssignmentMap& materials) {} + virtual void OnMaterialsEdited() {} }; using MaterialComponentNotificationBus = EBus; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index a4e058561e..848a6cc992 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -215,91 +215,21 @@ namespace AZ void EditorMaterialComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) { m_controller.SetDefaultMaterialOverride(assetId); - } - AZ::u32 EditorMaterialComponent::OnConfigurationChanged() - { - // Whenever the user makes changes to the editor component data the controller configuration must be rebuilt - m_configurationChangeInProgress = true; - UpdateController(); - m_configurationChangeInProgress = false; - - return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; - } - - void EditorMaterialComponent::OnMaterialAssignmentsChanged() - { - // [GFX TODO][ATOM-4604] remove flag after mesh component material handling is fixed to not recreate/reload mesh for material changes - if (!m_configurationChangeInProgress) - { - UpdateMaterialSlots(); - } - } - - void EditorMaterialComponent::OnMaterialsEdited(const MaterialAssignmentMap& materials) - { - AzToolsFramework::ScopedUndoBatch undoBatch("Materials edited."); - SetDirty(); - - // The layout of the materials slots is already set. - // We just need to read the values from any edited overrides into the editor component - // and refresh. - for (auto& materialSlotPair : GetMaterialSlots()) - { - EditorMaterialComponentSlot& slot = *materialSlotPair.second; - const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(materials, slot.m_id); - slot.m_materialAsset = materialFromController.m_materialAsset; - slot.m_propertyOverrides = materialFromController.m_propertyOverrides; - slot.m_matModUvOverrides = materialFromController.m_matModUvOverrides; - } + MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); } - void EditorMaterialComponent::UpdateConfiguration(const MaterialComponentConfig& config) + AZ::u32 EditorMaterialComponent::OnConfigurationChanged() { - m_controller.SetMaterialOverrides(config.m_materials); + return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; } - void EditorMaterialComponent::UpdateController() + void EditorMaterialComponent::OnMaterialAssignmentsChanged() { - SetDirty(); - - // Build the controller configuration from the editor configuration - MaterialComponentConfig config = m_controller.GetConfiguration(); - config.m_materials.clear(); - - for (const auto& materialSlotPair : GetMaterialSlots()) - { - const EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - - // Do not apply materials for lods if they are disabled - if (materialSlot->m_id.m_lodIndex != MaterialAssignmentId::NonLodIndex && !m_materialSlotsByLodEnabled) - { - continue; - } - - // Only material slots with a valid asset IDs or property overrides will be copied - // to minimize the amount of data stored in the controller and game component - if (materialSlot->m_materialAsset.GetId().IsValid()) - { - MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; - materialAssignment.m_materialAsset = materialSlot->m_materialAsset; - materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; - materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; - } - else if (!materialSlot->m_propertyOverrides.empty() || !materialSlot->m_matModUvOverrides.empty()) - { - MaterialAssignment& materialAssignment = config.m_materials[materialSlot->m_id]; - materialAssignment.m_materialAsset = materialSlot->m_defaultMaterialAsset; - materialAssignment.m_propertyOverrides = materialSlot->m_propertyOverrides; - materialAssignment.m_matModUvOverrides = materialSlot->m_matModUvOverrides; - } - } - - UpdateConfiguration(config); + UpdateMaterialSlots(); } void EditorMaterialComponent::UpdateMaterialSlots() @@ -315,64 +245,18 @@ namespace AZ MaterialAssignmentMap materialsFromSource; MaterialReceiverRequestBus::EventResult(materialsFromSource, GetEntityId(), &MaterialReceiverRequestBus::Events::GetMaterialAssignments); - RPI::ModelMaterialSlotMap modelMaterialSlots; - MaterialReceiverRequestBus::EventResult(modelMaterialSlots, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); - // Generate the table of editable materials using the source data to define number of groups, elements, and initial values for (const auto& materialPair : materialsFromSource) { // Setup the material slot entry EditorMaterialComponentSlot slot; + slot.m_entityId = GetEntityId(); slot.m_id = materialPair.first; - slot.m_materialChangedCallback = [this]() { - // This callback is triggered whenever an individual material slot changes outside of normal inspector interactions - // So we must manually handle undo, update configuration, and refresh the inspector to display the new values - AzToolsFramework::ScopedUndoBatch undoBatch("Material slot changed."); - SetDirty(); - - OnConfigurationChanged(); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); - }; - slot.m_propertyChangedCallback = [this]() { - OnConfigurationChanged(); - }; - - const char* UnknownSlotName = ""; - - // If this is the default material assignment ID then it represents the default slot which is not contained in any other group - if (slot.m_id == DefaultMaterialAssignmentId) - { - slot.m_label = "Default Material"; - } - else - { - auto slotIter = modelMaterialSlots.find(slot.m_id.m_materialSlotStableId); - if (slotIter != modelMaterialSlots.end()) - { - const Name& displayName = slotIter->second.m_displayName; - slot.m_label = !displayName.IsEmpty() ? displayName.GetStringView() : UnknownSlotName; - - slot.m_defaultMaterialAsset = slotIter->second.m_defaultMaterialAsset; - } - else - { - slot.m_label = UnknownSlotName; - } - } // if material is present in controller configuration, assign its data const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); slot.m_materialAsset = materialFromController.m_materialAsset; - slot.m_propertyOverrides = materialFromController.m_propertyOverrides; - slot.m_matModUvOverrides = materialFromController.m_matModUvOverrides; - - // Attempt to get the UV names from model meshes. - MaterialReceiverRequestBus::EventResult(slot.m_modelUvNames, GetEntityId(), &MaterialReceiverRequestBus::Events::GetModelUvNames); - if (slot.m_id.IsDefault()) { m_defaultMaterialSlot = slot; @@ -388,7 +272,8 @@ namespace AZ if (slot.m_id.IsLodAndSlotId()) { // Resize the containers to fit all elements - m_materialSlotsByLod.resize(AZ::GetMax(m_materialSlotsByLod.size(), aznumeric_cast(slot.m_id.m_lodIndex + 1))); + m_materialSlotsByLod.resize( + AZ::GetMax(m_materialSlotsByLod.size(), aznumeric_cast(slot.m_id.m_lodIndex + 1))); m_materialSlotsByLod[slot.m_id.m_lodIndex].push_back(slot); continue; } @@ -404,9 +289,10 @@ namespace AZ [](const auto& a, const auto& b) { return a.GetLabel() < b.GetLabel(); }); } + MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_EntireTree); + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } AZ::u32 EditorMaterialComponent::ResetMaterialSlots() @@ -414,15 +300,15 @@ namespace AZ AzToolsFramework::ScopedUndoBatch undoBatch("Resetting materials."); SetDirty(); - UpdateConfiguration(MaterialComponentConfig()); + m_controller.SetMaterialOverrides(MaterialAssignmentMap()); UpdateMaterialSlots(); m_materialSlotsByLodEnabled = false; - // Forcing refresh in case triggered from context menu action + MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_EntireTree); + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); return AZ::Edit::PropertyRefreshLevels::EntireTree; } @@ -431,26 +317,26 @@ namespace AZ { AzToolsFramework::ScopedUndoBatch undoBatch("Generating materials."); SetDirty(); - + // First generating a unique set of all material asset IDs that will be used for source data generation AZStd::unordered_map assetIdMap; auto materialSlots = GetMaterialSlots(); for (auto& materialSlotPair : materialSlots) { - Data::AssetId defaultMaterialAssetId = materialSlotPair.second->m_defaultMaterialAsset.GetId(); + Data::AssetId defaultMaterialAssetId = materialSlotPair.second->GetDefaultAssetId(); if (defaultMaterialAssetId.IsValid()) { assetIdMap[defaultMaterialAssetId] = materialSlotPair.second->GetLabel(); } } - // Convert the unique set of asset IDs into export items that can be configured in the dialog + // Convert the unique set of asset IDs into export items that can be configured in the dialog // The order should not matter because the table in the dialog can sort itself for a specific row EditorMaterialComponentExporter::ExportItemsContainer exportItems; for (auto assetIdInfo : assetIdMap) { - EditorMaterialComponentExporter::ExportItem exportItem{assetIdInfo.first, assetIdInfo.second}; + EditorMaterialComponentExporter::ExportItem exportItem{ assetIdInfo.first, assetIdInfo.second }; exportItems.push_back(exportItem); } @@ -474,9 +360,9 @@ namespace AZ if (editorMaterialSlot) { // We need to check whether replaced material corresponds to this slot's default material. - if (editorMaterialSlot->m_defaultMaterialAsset.GetId() == exportItem.GetOriginalAssetId()) + if (editorMaterialSlot->GetDefaultAssetId() == exportItem.GetOriginalAssetId()) { - editorMaterialSlot->m_materialAsset.Create(assetIdOutcome.GetValue()); + editorMaterialSlot->SetAsset(assetIdOutcome.GetValue()); } } } @@ -484,17 +370,31 @@ namespace AZ } } - // Forcing refresh in case triggered from context menu action + MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - return OnConfigurationChanged(); + return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; } AZ::u32 EditorMaterialComponent::OnLodsToggled() { - OnConfigurationChanged(); + AzToolsFramework::ScopedUndoBatch undoBatch("Toggling LOD materials."); + SetDirty(); + + if (!m_materialSlotsByLodEnabled) + { + MaterialComponentConfig config = m_controller.GetConfiguration(); + AZStd::erase_if(config.m_materials, [](const auto& item) { + const auto& [key, value] = item; + return key.m_lodIndex != MaterialAssignmentId::NonLodIndex; + }); + m_controller.SetMaterialOverrides(config.m_materials); + } + + MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + return AZ::Edit::PropertyRefreshLevels::EntireTree; } @@ -541,11 +441,14 @@ namespace AZ materialSlots[slot.m_id] = &slot; } - for (auto& slotsForLod : component.m_materialSlotsByLod) + if (component.m_materialSlotsByLodEnabled) { - for (auto& slot : slotsForLod) + for (auto& slotsForLod : component.m_materialSlotsByLod) { - materialSlots[slot.m_id] = &slot; + for (auto& slot : slotsForLod) + { + materialSlots[slot.m_id] = &slot; + } } } } @@ -565,4 +468,3 @@ namespace AZ } } // namespace Render } // namespace AZ - diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h index 88ffef9366..6ae96b5c3c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h @@ -8,11 +8,11 @@ #pragma once +#include #include #include -#include -#include #include +#include namespace AZ { @@ -49,16 +49,6 @@ namespace AZ //! MaterialReceiverNotificationBus::Handler overrides... void OnMaterialAssignmentsChanged() override; - //! MaterialComponentNotificationBus::Handler overrides... - void OnMaterialsEdited(const MaterialAssignmentMap& materials) override; - - // Apply a material component configuration to the active controller - void UpdateConfiguration(const MaterialComponentConfig& config); - - // Converts the editor components material slots to the material component - // configuration and updates the controller - void UpdateController(); - // Regenerates the editor component material slots based on the material and // LOD mapping from the model or other consumer of materials. // If any corresponding material assignments are found in the component @@ -101,8 +91,6 @@ namespace AZ EditorMaterialComponentSlotsByLodContainer m_materialSlotsByLod; bool m_materialSlotsByLodEnabled = false; - bool m_configurationChangeInProgress = false; // when true, model changes are ignored - static const char* GenerateMaterialsButtonText; static const char* GenerateMaterialsToolTipText; static const char* ResetMaterialsButtonText; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index b9a4adc068..939417f236 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -27,19 +27,16 @@ #include #include #include - #include +#include +#include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include -#include #include -#include #include #include #include -#include #include AZ_POP_DISABLE_WARNING @@ -49,26 +46,59 @@ namespace AZ { namespace EditorMaterialComponentInspector { - MaterialPropertyInspector::MaterialPropertyInspector( - const AZStd::string& slotName, const AZ::Data::AssetId& assetId, PropertyChangedCallback propertyChangedCallback, - QWidget* parent) + MaterialPropertyInspector::MaterialPropertyInspector(QWidget* parent) : AtomToolsFramework::InspectorWidget(parent) - , m_slotName(slotName) - , m_materialAssetId(assetId) - , m_propertyChangedCallback(propertyChangedCallback) { + // Create the menu button + QToolButton* menuButton = new QToolButton(this); + menuButton->setAutoRaise(true); + menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); + menuButton->setVisible(true); + QObject::connect(menuButton, &QToolButton::clicked, this, [this]() { OpenMenu(); }); + AddHeading(menuButton); + + m_messageLabel = new QLabel(this); + m_messageLabel->setWordWrap(true); + m_messageLabel->setVisible(true); + m_messageLabel->setAlignment(Qt::AlignCenter); + m_messageLabel->setText(tr("Material not available")); + AddHeading(m_messageLabel); + + AZ::EntitySystemBus::Handler::BusConnect(); } MaterialPropertyInspector::~MaterialPropertyInspector() { AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); + AZ::EntitySystemBus::Handler::BusDisconnect(); + AZ::TickBus::Handler::BusDisconnect(); + MaterialComponentNotificationBus::Handler::BusDisconnect(); } - bool MaterialPropertyInspector::LoadMaterial() + bool MaterialPropertyInspector::LoadMaterial( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) { - if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(m_materialAssetId, m_editData)) + UnloadMaterial(); + + m_entityId = entityId; + m_materialAssignmentId = materialAssignmentId; + MaterialComponentNotificationBus::Handler::BusDisconnect(); + MaterialComponentNotificationBus::Handler::BusConnect(m_entityId); + + AZ::Data::AssetId materialAssetId = {}; + MaterialComponentRequestBus::EventResult( + materialAssetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + + if (!materialAssetId.IsValid()) + { + UnloadMaterial(); + return false; + } + + if (!EditorMaterialComponentUtil::LoadMaterialEditDataFromAssetId(materialAssetId, m_editData)) { AZ_Warning("AZ::Render::EditorMaterialComponentInspector", false, "Failed to load material data."); + UnloadMaterial(); return false; } @@ -77,6 +107,7 @@ namespace AZ if (!m_materialInstance) { AZ_Error("AZ::Render::EditorMaterialComponentInspector", false, "Material instance could not be created."); + UnloadMaterial(); return false; } @@ -102,15 +133,36 @@ namespace AZ } } + Populate(); + m_messageLabel->setVisible(false); return true; } + void MaterialPropertyInspector::UnloadMaterial() + { + Reset(); + m_editData = EditorMaterialComponentUtil::MaterialEditData(); + m_materialInstance = {}; + m_dirtyPropertyFlags.set(); + m_editorFunctors = {}; + m_internalEditNotification = {}; + m_messageLabel->setVisible(true); + m_messageLabel->setText(tr("Material not available")); + } + + bool MaterialPropertyInspector::IsLoaded() const + { + return m_entityId.IsValid() && m_materialInstance && m_editData.m_materialAsset.IsReady(); + } + void MaterialPropertyInspector::Reset() { m_activeProperty = {}; m_groups = {}; m_dirtyPropertyFlags.set(); + m_internalEditNotification = {}; + AZ::TickBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorWidget::Reset(); } @@ -150,9 +202,18 @@ namespace AZ QFileInfo materialTypeSourceFileInfo(m_editData.m_materialTypeSourcePath.c_str()); QFileInfo materialParentSourceFileInfo(AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_editData.m_materialParentAsset.GetId()).c_str()); + AZStd::string entityName; + AZ::ComponentApplicationBus::BroadcastResult( + entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, m_entityId); + + AZStd::string slotName; + MaterialComponentRequestBus::EventResult( + slotName, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialSlotLabel, m_materialAssignmentId); + QString materialInfo; materialInfo += tr(""); - materialInfo += tr("").arg(m_slotName.c_str()); + materialInfo += tr("").arg(entityName.c_str()); + materialInfo += tr("").arg(slotName.c_str()); if (!materialFileInfo.fileName().isEmpty()) { materialInfo += tr("").arg(materialFileInfo.fileName()); @@ -209,16 +270,8 @@ namespace AZ } // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties - const AZ::Crc32 saveStateKey(AZStd::string::format( - "MaterialPropertyInspector::PropertyGroup::%s::%s", m_materialAssetId.ToString().c_str(), - groupNameId.c_str())); auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey, - [](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) { - AZ_UNUSED(source); - const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target); - return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue); - }); + &group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupNameId)); AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); } @@ -262,35 +315,90 @@ namespace AZ } // Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties - const AZ::Crc32 saveStateKey(AZStd::string::format( - "MaterialPropertyInspector::PropertyGroup::%s::%s", m_materialAssetId.ToString().c_str(), - groupNameId.c_str())); auto propertyGroupWidget = new AtomToolsFramework::InspectorPropertyGroupWidget( - &group, &group, group.TYPEINFO_Uuid(), this, this, saveStateKey, - [](const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) { - AZ_UNUSED(source); - const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target); - return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue); - }); + &group, nullptr, group.TYPEINFO_Uuid(), this, this, GetSaveStateKeyForGroup(groupNameId)); AddGroup(groupNameId, groupDisplayName, groupDescription, propertyGroupWidget); } AddGroupsEnd(); + LoadOverridesFromEntity(); + } + + void MaterialPropertyInspector::LoadOverridesFromEntity() + { + if (!IsLoaded()) + { + return; + } + + m_editData.m_materialPropertyOverrideMap.clear(); + MaterialComponentRequestBus::EventResult( + m_editData.m_materialPropertyOverrideMap, m_entityId, &MaterialComponentRequestBus::Events::GetPropertyOverrides, + m_materialAssignmentId); + + for (auto& group : m_groups) + { + for (auto& property : group.second.m_properties) + { + const AtomToolsFramework::DynamicPropertyConfig& propertyConfig = property.GetConfig(); + const auto overrideItr = m_editData.m_materialPropertyOverrideMap.find(propertyConfig.m_id); + const auto& editValue = overrideItr != m_editData.m_materialPropertyOverrideMap.end() ? overrideItr->second : propertyConfig.m_originalValue; + + // This first converts to an acceptable runtime type in case the value came from script + const auto propertyIndex = m_materialInstance->FindPropertyIndex(property.GetId()); + if (!propertyIndex.IsNull()) + { + const auto runtimeValue = AtomToolsFramework::ConvertToRuntimeType(editValue); + if (runtimeValue.IsValid()) + { + property.SetValue(AtomToolsFramework::ConvertToEditableType(runtimeValue)); + } + } + else + { + property.SetValue(editValue); + } + + UpdateMaterialInstanceProperty(property); + } + } + m_dirtyPropertyFlags.set(); RunEditorMaterialFunctors(); + RefreshAll(); } - void MaterialPropertyInspector::RunPropertyChangedCallback() + void MaterialPropertyInspector::SaveOverridesToEntity(bool commitChanges) { - if (m_propertyChangedCallback) + if (!IsLoaded()) { - m_propertyChangedCallback(m_editData.m_materialPropertyOverrideMap); + return; + } + + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetPropertyOverrides, m_materialAssignmentId, + m_editData.m_materialPropertyOverrideMap); + + if (commitChanges) + { + AzToolsFramework::ScopedUndoBatch undoBatch("Material slot changed."); + AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, m_entityId); + + m_internalEditNotification = true; + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited); + m_internalEditNotification = false; } } void MaterialPropertyInspector::RunEditorMaterialFunctors() { + if (!IsLoaded()) + { + return; + } + AZStd::unordered_set changedPropertyNames; AZStd::unordered_set changedPropertyGroupNames; @@ -337,11 +445,13 @@ namespace AZ // Apply any changes to material property meta data back to the editor property configurations for (auto& groupPair : m_groups) { - AZ::Name groupName{groupPair.first}; + AZ::Name groupName{ groupPair.first }; if (changedPropertyGroupNames.find(groupName) != changedPropertyGroupNames.end()) { - SetGroupVisible(groupPair.first, propertyGroupDynamicMetadata[groupName].m_visibility == AZ::RPI::MaterialPropertyGroupVisibility::Enabled); + SetGroupVisible( + groupPair.first, + propertyGroupDynamicMetadata[groupName].m_visibility == AZ::RPI::MaterialPropertyGroupVisibility::Enabled); } for (auto& property : groupPair.second.m_properties) @@ -355,12 +465,12 @@ namespace AZ if (oldReadOnly != propertyConfig.m_readOnly) { - RefreshAll(); + RefreshGroup(groupPair.first); } if (oldVisible != propertyConfig.m_visible) { - RebuildAll(); + RebuildGroup(groupPair.first); } } } @@ -368,57 +478,37 @@ namespace AZ void MaterialPropertyInspector::UpdateMaterialInstanceProperty(const AtomToolsFramework::DynamicProperty& property) { - if (m_materialInstance) + if (!IsLoaded()) { - const auto propertyIndex = m_materialInstance->FindPropertyIndex(property.GetId()); - if (!propertyIndex.IsNull()) - { - m_dirtyPropertyFlags.set(propertyIndex.GetIndex()); - - const auto runtimeValue = AtomToolsFramework::ConvertToRuntimeType(property.GetValue()); - if (runtimeValue.IsValid()) - { - m_materialInstance->SetPropertyValue(propertyIndex, runtimeValue); - } - } + return; } - } - void MaterialPropertyInspector::SetOverrides(const MaterialPropertyOverrideMap& propertyOverrideMap) - { - m_editData.m_materialPropertyOverrideMap = propertyOverrideMap; - - for (auto& group : m_groups) + const auto propertyIndex = m_materialInstance->FindPropertyIndex(property.GetId()); + if (!propertyIndex.IsNull()) { - for (auto& property : group.second.m_properties) - { - const AtomToolsFramework::DynamicPropertyConfig& propertyConfig = property.GetConfig(); - const auto overrideItr = m_editData.m_materialPropertyOverrideMap.find(propertyConfig.m_id); - const auto& editValue = overrideItr != m_editData.m_materialPropertyOverrideMap.end() ? overrideItr->second : propertyConfig.m_originalValue; - - // This first converts to an acceptable runtime type in case the value came from script - const auto propertyIndex = m_materialInstance->FindPropertyIndex(property.GetId()); - if (!propertyIndex.IsNull()) - { - const auto runtimeValue = AtomToolsFramework::ConvertToRuntimeType(editValue); - if (runtimeValue.IsValid()) - { - property.SetValue(AtomToolsFramework::ConvertToEditableType(runtimeValue)); - } - } - else - { - property.SetValue(editValue); - } + m_dirtyPropertyFlags.set(propertyIndex.GetIndex()); - UpdateMaterialInstanceProperty(property); + const auto runtimeValue = AtomToolsFramework::ConvertToRuntimeType(property.GetValue()); + if (runtimeValue.IsValid()) + { + m_materialInstance->SetPropertyValue(propertyIndex, runtimeValue); } } + } - m_dirtyPropertyFlags.set(); - RunPropertyChangedCallback(); - RunEditorMaterialFunctors(); - RebuildAll(); + AZ::Crc32 MaterialPropertyInspector::GetSaveStateKeyForGroup(const AZStd::string& groupNameId) const + { + return AZ::Crc32(AZStd::string::format( + "MaterialPropertyInspector::PropertyGroup::%s::%s", m_editData.m_materialAssetId.ToString().c_str(), + groupNameId.c_str())); + } + + bool MaterialPropertyInspector::AreNodePropertyValuesEqual( + const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) + { + AZ_UNUSED(source); + const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(target); + return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue); } bool MaterialPropertyInspector::SaveMaterial() const @@ -446,7 +536,8 @@ namespace AZ bool MaterialPropertyInspector::SaveMaterialToSource() const { - const QString saveFilePath = AtomToolsFramework::GetSaveFileInfo(m_editData.m_materialSourcePath.c_str()).absoluteFilePath(); + const QString saveFilePath = + AtomToolsFramework::GetSaveFileInfo(m_editData.m_materialSourcePath.c_str()).absoluteFilePath(); if (saveFilePath.isEmpty()) { return false; @@ -463,13 +554,13 @@ namespace AZ bool MaterialPropertyInspector::HasMaterialSource() const { - return !m_editData.m_materialSourcePath.empty() && + return IsLoaded() && !m_editData.m_materialSourcePath.empty() && AZ::StringFunc::Path::IsExtension(m_editData.m_materialSourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } bool MaterialPropertyInspector::HasMaterialParentSource() const { - return !m_editData.m_materialParentSourcePath.empty() && + return IsLoaded() && !m_editData.m_materialParentSourcePath.empty() && AZ::StringFunc::Path::IsExtension( m_editData.m_materialParentSourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } @@ -479,7 +570,7 @@ namespace AZ if (HasMaterialSource()) { EditorMaterialSystemComponentRequestBus::Broadcast( - &EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, m_editData.m_materialSourcePath); + &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialEditor, m_editData.m_materialSourcePath); } } @@ -488,10 +579,42 @@ namespace AZ if (HasMaterialParentSource()) { EditorMaterialSystemComponentRequestBus::Broadcast( - &EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, m_editData.m_materialParentSourcePath); + &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialEditor, m_editData.m_materialParentSourcePath); } } + void MaterialPropertyInspector::OpenMenu() + { + QAction* action = nullptr; + + QMenu menu(this); + action = menu.addAction("Clear Overrides", [this] { + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetPropertyOverrides, m_materialAssignmentId, + MaterialPropertyOverrideMap()); + QueueUpdateUI(); + }); + action->setEnabled(IsLoaded()); + + menu.addSeparator(); + + action = menu.addAction("Save Material", [this] { SaveMaterial(); }); + action->setEnabled(IsLoaded()); + + action = menu.addAction("Save Material To Source", [this] { SaveMaterialToSource(); }); + action->setEnabled(HasMaterialSource()); + + menu.addSeparator(); + + action = menu.addAction("Open Source Material In Editor", [this] { OpenMaterialSourceInEditor(); }); + action->setEnabled(HasMaterialSource()); + + action = menu.addAction("Open Parent Material In Editor", [this] { OpenMaterialParentSourceInEditor(); }); + action->setEnabled(HasMaterialParentSource()); + + menu.exec(QCursor::pos()); + } + const EditorMaterialComponentUtil::MaterialEditData& MaterialPropertyInspector::GetEditData() const { return m_editData; @@ -501,7 +624,8 @@ namespace AZ { // For some reason the reflected property editor notifications are not symmetrical // This function is called continuously anytime a property changes until the edit has completed - // Because of that, we have to track whether or not we are continuing to edit the same property to know when editing has started and ended + // Because of that, we have to track whether or not we are continuing to edit the same property to know when editing has + // started and ended const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(pNode); if (property) { @@ -521,15 +645,16 @@ namespace AZ { m_editData.m_materialPropertyOverrideMap[m_activeProperty->GetId()] = m_activeProperty->GetValue(); UpdateMaterialInstanceProperty(*m_activeProperty); - RunPropertyChangedCallback(); + SaveOverridesToEntity(false); } } } void MaterialPropertyInspector::SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* pNode) { - // As above, there are symmetrical functions on the notification interface for when editing begins and ends and has been completed but they are not being called following that pattern. - // when this function executes the changes to the property are ready to be committed or reverted + // As above, there are symmetrical functions on the notification interface for when editing begins and ends and has been + // completed but they are not being called following that pattern. when this function executes the changes to the property + // are ready to be committed or reverted const AtomToolsFramework::DynamicProperty* property = AtomToolsFramework::FindDynamicPropertyForInstanceDataNode(pNode); if (property) { @@ -537,85 +662,92 @@ namespace AZ { m_editData.m_materialPropertyOverrideMap[m_activeProperty->GetId()] = m_activeProperty->GetValue(); UpdateMaterialInstanceProperty(*m_activeProperty); - RunPropertyChangedCallback(); + SaveOverridesToEntity(true); RunEditorMaterialFunctors(); m_activeProperty = nullptr; } } } - bool OpenInspectorDialog( - const AZStd::string& slotName, const AZ::Data::AssetId& assetId, MaterialPropertyOverrideMap propertyOverrideMap, - PropertyChangedCallback propertyChangedCallback) + void MaterialPropertyInspector::OnEntityInitialized(const AZ::EntityId& entityId) { - QWidget* activeWindow = nullptr; - AzToolsFramework::EditorWindowRequestBus::BroadcastResult(activeWindow, &AzToolsFramework::EditorWindowRequests::GetAppMainWindow); + if (m_entityId == entityId) + { + UnloadMaterial(); + } + } - // Constructing a dialog with a table to display all configurable material export items - QDialog dialog(activeWindow); - dialog.setWindowTitle("Material Inspector"); + void MaterialPropertyInspector::OnEntityDestroyed(const AZ::EntityId& entityId) + { + if (m_entityId == entityId) + { + UnloadMaterial(); + } + } - MaterialPropertyInspector* inspector = new MaterialPropertyInspector(slotName, assetId, propertyChangedCallback, &dialog); - if (!inspector->LoadMaterial()) + void MaterialPropertyInspector::OnEntityActivated(const AZ::EntityId& entityId) + { + if (m_entityId == entityId) { - return false; + QueueUpdateUI(); } + } - inspector->Populate(); - inspector->SetOverrides(propertyOverrideMap); + void MaterialPropertyInspector::OnEntityDeactivated(const AZ::EntityId& entityId) + { + if (m_entityId == entityId) + { + UnloadMaterial(); + } + } - // Create the menu button - QToolButton* menuButton = new QToolButton(&dialog); - menuButton->setAutoRaise(true); - menuButton->setIcon(QIcon(":/Cards/img/UI20/Cards/menu_ico.svg")); - menuButton->setVisible(true); - QObject::connect(menuButton, &QToolButton::clicked, &dialog, [&]() { - QAction* action = nullptr; - - QMenu menu(&dialog); - action = menu.addAction("Clear Overrides", [&] { inspector->SetOverrides(MaterialPropertyOverrideMap()); }); - action = menu.addAction("Revert Changes", [&] { inspector->SetOverrides(propertyOverrideMap); }); - - menu.addSeparator(); - action = menu.addAction("Save Material", [&] { inspector->SaveMaterial(); }); - action = menu.addAction("Save Material To Source", [&] { inspector->SaveMaterialToSource(); }); - action->setEnabled(inspector->HasMaterialSource()); - - menu.addSeparator(); - action = menu.addAction("Open Source Material In Editor", [&] { inspector->OpenMaterialSourceInEditor(); }); - action->setEnabled(inspector->HasMaterialSource()); - action = menu.addAction("Open Parent Material In Editor", [&] { inspector->OpenMaterialParentSourceInEditor(); }); - action->setEnabled(inspector->HasMaterialParentSource()); - menu.exec(QCursor::pos()); - }); + void MaterialPropertyInspector::OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) + { + AZ_UNUSED(name); + if (m_entityId == entityId) + { + QueueUpdateUI(); + } + } - QDialogButtonBox* buttonBox = new QDialogButtonBox(&dialog); - buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); - QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); - - QObject::connect(&dialog, &QDialog::rejected, &dialog, [&] { inspector->SetOverrides(propertyOverrideMap); }); - - QVBoxLayout* dialogLayout = new QVBoxLayout(&dialog); - dialogLayout->addWidget(menuButton); - dialogLayout->addWidget(inspector); - dialogLayout->addWidget(buttonBox); - dialog.setLayout(dialogLayout); - dialog.setModal(true); - - // Forcing the initial dialog size to accomodate typical content. - // Temporarily settng fixed size because dialog.show/exec invokes WindowDecorationWrapper::showEvent. - // This forces the dialog to be centered and sized based on the layout of content. - // Resizing the dialog after show will not be centered and moving the dialog programatically doesn't m0ve the custmk frame. - dialog.setFixedSize(500, 800); - dialog.show(); - - // Removing fixed size to allow drag resizing - dialog.setMinimumSize(0, 0); - dialog.setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - - // Return true if the user press the export button - return dialog.exec() == QDialog::Accepted; + void MaterialPropertyInspector::OnTick(float deltaTime, ScriptTimePoint time) + { + AZ_UNUSED(time); + AZ_UNUSED(deltaTime); + UpdateUI(); + AZ::TickBus::Handler::BusDisconnect(); + } + + void MaterialPropertyInspector::OnMaterialsEdited() + { + if (!m_internalEditNotification) + { + QueueUpdateUI(); + } + } + + void MaterialPropertyInspector::UpdateUI() + { + AZ::Data::AssetId assetId; + MaterialComponentRequestBus::EventResult( + assetId, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialOverride, m_materialAssignmentId); + + if (IsLoaded() && m_editData.m_materialAssetId == assetId) + { + LoadOverridesFromEntity(); + } + else + { + LoadMaterial(m_entityId, m_materialAssignmentId); + } + } + + void MaterialPropertyInspector::QueueUpdateUI() + { + if (!AZ::TickBus::Handler::BusIsConnected()) + { + AZ::TickBus::Handler::BusConnect(); + } } } // namespace EditorMaterialComponentInspector } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h index 12c4fbfdd9..11eb2cec51 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.h @@ -9,17 +9,22 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include +#include +#include #include #include -#include #include +#include #include #include #endif +class QLabel; + namespace AZ { namespace Render @@ -31,31 +36,33 @@ namespace AZ class MaterialPropertyInspector : public AtomToolsFramework::InspectorWidget , public AzToolsFramework::IPropertyEditorNotify - { + , public AZ::EntitySystemBus::Handler + , public AZ::TickBus::Handler + , public MaterialComponentNotificationBus::Handler + { Q_OBJECT public: AZ_CLASS_ALLOCATOR(MaterialPropertyInspector, AZ::SystemAllocator, 0); - explicit MaterialPropertyInspector( - const AZStd::string& slotName, const AZ::Data::AssetId& assetId, PropertyChangedCallback propertyChangedCallback, - QWidget* parent = nullptr); + MaterialPropertyInspector(QWidget* parent = nullptr); ~MaterialPropertyInspector() override; - bool LoadMaterial(); + bool LoadMaterial(const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId); + void UnloadMaterial(); + bool IsLoaded() const; // AtomToolsFramework::InspectorRequestBus::Handler overrides... void Reset() override; void Populate(); - void SetOverrides(const MaterialPropertyOverrideMap& propertyOverrideMap); - bool SaveMaterial() const; bool SaveMaterialToSource() const; bool HasMaterialSource() const; bool HasMaterialParentSource() const; void OpenMaterialSourceInEditor() const; void OpenMaterialParentSourceInEditor() const; + void OpenMenu(); const EditorMaterialComponentUtil::MaterialEditData& GetEditData() const; private: @@ -69,28 +76,47 @@ namespace AZ void RequestPropertyContextMenu([[maybe_unused]] AzToolsFramework::InstanceDataNode*, const QPoint&) override {} void PropertySelectionChanged([[maybe_unused]] AzToolsFramework::InstanceDataNode*, bool) override {} + // AZ::EntitySystemBus::Handler overrides... + void OnEntityInitialized(const AZ::EntityId& entityId) override; + void OnEntityDestroyed(const AZ::EntityId& entityId) override; + void OnEntityActivated(const AZ::EntityId& entityId) override; + void OnEntityDeactivated(const AZ::EntityId& entityId) override; + void OnEntityNameChanged(const AZ::EntityId& entityId, const AZStd::string& name) override; + + //! AZ::TickBus::Handler overrides... + void OnTick(float deltaTime, ScriptTimePoint time) override; + + //! MaterialComponentNotificationBus::Handler overrides... + void OnMaterialsEdited() override; + + void UpdateUI(); + void QueueUpdateUI(); + void AddDetailsGroup(); void AddUvNamesGroup(); - void RunPropertyChangedCallback(); + + void LoadOverridesFromEntity(); + void SaveOverridesToEntity(bool commitChanges); void RunEditorMaterialFunctors(); void UpdateMaterialInstanceProperty(const AtomToolsFramework::DynamicProperty& property); + AZ::Crc32 GetSaveStateKeyForGroup(const AZStd::string& groupNameId) const; + static bool AreNodePropertyValuesEqual( + const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target); + // Tracking the property that is actively being edited in the inspector const AtomToolsFramework::DynamicProperty* m_activeProperty = {}; - AZStd::string m_slotName; - AZ::Data::AssetId m_materialAssetId = {}; + AZ::EntityId m_entityId; + AZ::Render::MaterialAssignmentId m_materialAssignmentId; EditorMaterialComponentUtil::MaterialEditData m_editData; - PropertyChangedCallback m_propertyChangedCallback = {}; AZ::Data::Instance m_materialInstance = {}; AZStd::vector> m_editorFunctors = {}; AZ::RPI::MaterialPropertyFlags m_dirtyPropertyFlags = {}; AZStd::unordered_map m_groups = {}; - }; - - bool OpenInspectorDialog( - const AZStd::string& slotName, const AZ::Data::AssetId& assetId, MaterialPropertyOverrideMap propertyOverrideMap, - PropertyChangedCallback propertyChangedCallback); + bool m_internalEditNotification = {}; + QLabel* m_messageLabel = {}; + }; } // namespace EditorMaterialComponentInspector } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 39dde65a99..37a9ee7b93 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -80,10 +80,9 @@ namespace AZ if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(6, &EditorMaterialComponentSlot::ConvertVersion) + ->Version(7, &EditorMaterialComponentSlot::ConvertVersion) ->Field("id", &EditorMaterialComponentSlot::m_id) ->Field("materialAsset", &EditorMaterialComponentSlot::m_materialAsset) - ->Field("defaultMaterialAsset", &EditorMaterialComponentSlot::m_defaultMaterialAsset) ; if (AZ::EditContext* editContext = serializeContext->GetEditContext()) @@ -114,20 +113,22 @@ namespace AZ ->Constructor() ->Property("id", BehaviorValueProperty(&EditorMaterialComponentSlot::m_id)) ->Property("materialAsset", BehaviorValueProperty(&EditorMaterialComponentSlot::m_materialAsset)) - ->Property("propertyOverrides", BehaviorValueProperty(&EditorMaterialComponentSlot::m_propertyOverrides)) - ->Property("matModUvOverrides", BehaviorValueProperty(&EditorMaterialComponentSlot::m_matModUvOverrides)) ; } }; AZ::Data::AssetId EditorMaterialComponentSlot::GetDefaultAssetId() const { - return m_defaultMaterialAsset.GetId(); + AZ::Data::AssetId assetId; + MaterialComponentRequestBus::EventResult(assetId, m_entityId, &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId, m_id); + return assetId; } AZStd::string EditorMaterialComponentSlot::GetLabel() const { - return m_label; + AZStd::string label; + MaterialComponentRequestBus::EventResult(label, m_entityId, &MaterialComponentRequestBus::Events::GetMaterialSlotLabel, m_id); + return label; } bool EditorMaterialComponentSlot::HasSourceData() const @@ -137,50 +138,45 @@ namespace AZ return !sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension); } - void EditorMaterialComponentSlot::OnMaterialChanged() const + void EditorMaterialComponentSlot::SetAsset(const Data::AssetId& assetId) { - if (m_materialChangedCallback) - { - m_materialChangedCallback(); - } + m_materialAsset.Create(assetId); + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); + OnDataChanged(); } - void EditorMaterialComponentSlot::OnPropertyChanged() const + void EditorMaterialComponentSlot::SetAsset(const Data::Asset& asset) { - if (m_propertyChangedCallback) - { - m_propertyChangedCallback(); - } - } - - void EditorMaterialComponentSlot::OpenMaterialEditor() const - { - const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialAsset.GetId()); - if (!sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) - { - EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, sourcePath); - } + m_materialAsset = asset; + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); + OnDataChanged(); } void EditorMaterialComponentSlot::Clear() { m_materialAsset = {}; + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); ClearOverrides(); } - void EditorMaterialComponentSlot::ClearOverrides() + void EditorMaterialComponentSlot::ClearToDefaultAsset() { - m_propertyOverrides = {}; - m_matModUvOverrides = {}; - OnMaterialChanged(); + m_materialAsset.Create(GetDefaultAssetId()); + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); + ClearOverrides(); } - void EditorMaterialComponentSlot::ResetToDefaultAsset() + void EditorMaterialComponentSlot::ClearOverrides() { - m_materialAsset = m_defaultMaterialAsset; - m_propertyOverrides = {}; - m_matModUvOverrides = {}; - OnMaterialChanged(); + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetPropertyOverrides, m_id, MaterialPropertyOverrideMap()); + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id, AZ::RPI::MaterialModelUvOverrideMap()); + OnDataChanged(); } void EditorMaterialComponentSlot::OpenMaterialExporter() @@ -189,7 +185,7 @@ namespace AZ // But we still need to allow the user to reconfigure it using the dialog EditorMaterialComponentExporter::ExportItemsContainer exportItems; { - EditorMaterialComponentExporter::ExportItem exportItem{m_defaultMaterialAsset.GetId(), m_label}; + EditorMaterialComponentExporter::ExportItem exportItem{ GetDefaultAssetId(), GetLabel() }; exportItems.push_back(exportItem); } @@ -203,7 +199,8 @@ namespace AZ continue; } - // Generate a new asset ID utilizing the export file path so that we can update this material slot to reference the new asset + // Generate a new asset ID utilizing the export file path so that we can update this material slot to reference the new + // asset const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { @@ -219,37 +216,43 @@ namespace AZ } } - void EditorMaterialComponentSlot::OpenMaterialInspector() + void EditorMaterialComponentSlot::OpenMaterialEditor() const { - MaterialPropertyOverrideMap initialPropertyOverrides = m_propertyOverrides; - auto applyPropertyChangedCallback = [this](const MaterialPropertyOverrideMap& propertyOverrides) { - m_propertyOverrides = propertyOverrides; - OnPropertyChanged(); - }; - - if (m_materialAsset.GetId().IsValid()) + const AZStd::string& sourcePath = AZ::RPI::AssetUtils::GetSourcePathByAssetId(m_materialAsset.GetId()); + if (!sourcePath.empty() && AZ::StringFunc::Path::IsExtension(sourcePath.c_str(), AZ::RPI::MaterialSourceData::Extension)) { - if (EditorMaterialComponentInspector::OpenInspectorDialog(GetLabel(), m_materialAsset.GetId(), m_propertyOverrides, applyPropertyChangedCallback)) - { - OnMaterialChanged(); - } + EditorMaterialSystemComponentRequestBus::Broadcast( + &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialEditor, sourcePath); } } + void EditorMaterialComponentSlot::OpenMaterialInspector() + { + EditorMaterialSystemComponentRequestBus::Broadcast( + &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialInspector, m_entityId, m_id); + } + void EditorMaterialComponentSlot::OpenUvNameMapInspector() { - RPI::MaterialModelUvOverrideMap initialUvOverrides = m_matModUvOverrides; - auto applyMatModUvOverrideChangedCallback = [this](const RPI::MaterialModelUvOverrideMap& matModUvOverrides) { - m_matModUvOverrides = matModUvOverrides; - // Treated as a special property. It will be updated together with properties. - OnPropertyChanged(); - }; - if (m_materialAsset.GetId().IsValid()) { - if (EditorMaterialComponentInspector::OpenInspectorDialog(m_materialAsset.GetId(), m_matModUvOverrides, m_modelUvNames, applyMatModUvOverrideChangedCallback)) + AZStd::unordered_set modelUvNames; + MaterialReceiverRequestBus::EventResult(modelUvNames, m_entityId, &MaterialReceiverRequestBus::Events::GetModelUvNames); + + RPI::MaterialModelUvOverrideMap matModUvOverrides; + MaterialComponentRequestBus::EventResult( + matModUvOverrides, m_entityId, &MaterialComponentRequestBus::Events::GetModelUvOverrides, m_id); + + auto applyMatModUvOverrideChangedCallback = [this](const RPI::MaterialModelUvOverrideMap& matModUvOverrides) + { + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetModelUvOverrides, m_id, matModUvOverrides); + }; + + if (EditorMaterialComponentInspector::OpenInspectorDialog( + m_materialAsset.GetId(), matModUvOverrides, modelUvNames, applyMatModUvOverrideChangedCallback)) { - OnMaterialChanged(); + OnDataChanged(); } } } @@ -261,7 +264,7 @@ namespace AZ QAction* action = nullptr; action = menu.addAction("Generate/Manage Source Material...", [this]() { OpenMaterialExporter(); }); - action->setEnabled(m_defaultMaterialAsset.GetId().IsValid()); + action->setEnabled(GetDefaultAssetId().IsValid()); menu.addSeparator(); @@ -276,10 +279,38 @@ namespace AZ menu.addSeparator(); + MaterialPropertyOverrideMap propertyOverrides; + MaterialComponentRequestBus::EventResult( + propertyOverrides, m_entityId, &MaterialComponentRequestBus::Events::GetPropertyOverrides, m_id); + RPI::MaterialModelUvOverrideMap matModUvOverrides; + MaterialComponentRequestBus::EventResult( + matModUvOverrides, m_entityId, &MaterialComponentRequestBus::Events::GetModelUvOverrides, m_id); + action = menu.addAction("Clear Material Instance Overrides", [this]() { ClearOverrides(); }); - action->setEnabled(!m_propertyOverrides.empty() || !m_matModUvOverrides.empty()); + action->setEnabled(!propertyOverrides.empty() || !matModUvOverrides.empty()); menu.exec(QCursor::pos()); } + + void EditorMaterialComponentSlot::OnMaterialChanged() const + { + MaterialComponentRequestBus::Event( + m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); + OnDataChanged(); + } + + void EditorMaterialComponentSlot::OnDataChanged() const + { + // This is triggered whenever a material slot changes outside of normal inspector interactions + // Handle undo, update configuration, and refresh the inspector to display the new values + AzToolsFramework::ScopedUndoBatch undoBatch("Material slot changed."); + AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationRequests::Bus::Events::AddDirtyEntity, m_entityId); + + MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited); + + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h index 58d6fa9ab0..01e357f1bb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.h @@ -33,29 +33,26 @@ namespace AZ AZ::Data::AssetId GetDefaultAssetId() const; AZStd::string GetLabel() const; bool HasSourceData() const; - void OpenMaterialEditor() const; - void ResetToDefaultAsset(); + + void SetAsset(const Data::AssetId& assetId); + void SetAsset(const Data::Asset& asset); void Clear(); + void ClearToDefaultAsset(); void ClearOverrides(); + void OpenMaterialExporter(); + void OpenMaterialEditor() const; void OpenMaterialInspector(); void OpenUvNameMapInspector(); + AZ::EntityId m_entityId; MaterialAssignmentId m_id; - AZStd::string m_label; Data::Asset m_materialAsset; - Data::Asset m_defaultMaterialAsset; - MaterialPropertyOverrideMap m_propertyOverrides; - AZStd::function m_materialChangedCallback; - AZStd::function m_propertyChangedCallback; - - RPI::MaterialModelUvOverrideMap m_matModUvOverrides; - AZStd::unordered_set m_modelUvNames; // Cached for override options. private: void OpenPopupMenu(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType); void OnMaterialChanged() const; - void OnPropertyChanged() const; + void OnDataChanged() const; }; // Vector of slots for assignable or overridable material data. diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index e25653988e..83ddbf46c5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -6,33 +6,31 @@ * */ -#include - -#include +#include +#include #include #include +#include #include #include - #include - #include +#include #include - -#include - -#include - +#include +#include +#include #include // Disables warning messages triggered by the Qt library // 4251: class needs to have dll-interface to be used by clients of class // 4800: forcing value to bool 'true' or 'false' (performance warning) AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") +#include #include -#include +#include #include -#include +#include AZ_POP_DISABLE_WARNING void InitMaterialEditorResources() @@ -95,6 +93,7 @@ namespace AZ AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect(); + AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); SetupThumbnails(); m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); @@ -106,6 +105,7 @@ namespace AZ AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); TeardownThumbnails(); m_materialBrowserInteractions.reset(); @@ -117,7 +117,7 @@ namespace AZ } } - void EditorMaterialSystemComponent::OpenInMaterialEditor(const AZStd::string& sourcePath) + void EditorMaterialSystemComponent::OpenMaterialEditor(const AZStd::string& sourcePath) { AZ_TracePrintf("MaterialComponent", "Launching Material Editor"); @@ -140,6 +140,20 @@ namespace AZ AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments); } + void EditorMaterialSystemComponent::OpenMaterialInspector( + const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) + { + auto dockWidget = AzToolsFramework::InstanceViewPane("Material Property Inspector"); + if (dockWidget) + { + auto inspector = static_cast(dockWidget->widget()); + if (inspector) + { + inspector->LoadMaterial(entityId, materialAssignmentId); + } + } + } + void EditorMaterialSystemComponent::OnApplicationAboutToStop() { TeardownThumbnails(); @@ -157,11 +171,12 @@ namespace AZ QObject::connect( m_openMaterialEditorAction, &QAction::triggered, m_openMaterialEditorAction, [this]() { - OpenInMaterialEditor(""); + OpenMaterialEditor(""); } ); - AzToolsFramework::EditorMenuRequestBus::Broadcast(&AzToolsFramework::EditorMenuRequestBus::Handler::AddMenuAction, "ToolMenu", m_openMaterialEditorAction, true); + AzToolsFramework::EditorMenuRequestBus::Broadcast( + &AzToolsFramework::EditorMenuRequestBus::Handler::AddMenuAction, "ToolMenu", m_openMaterialEditorAction, true); } } @@ -174,13 +189,25 @@ namespace AZ } } + void EditorMaterialSystemComponent::NotifyRegisterViews() + { + AzToolsFramework::ViewPaneOptions inspectorOptions; + inspectorOptions.canHaveMultipleInstances = true; + inspectorOptions.preferedDockingArea = Qt::NoDockWidgetArea; + inspectorOptions.paneRect = QRect(50, 50, 400, 700); + inspectorOptions.showInMenu = false; + inspectorOptions.showOnToolsToolbar = false; + AzToolsFramework::RegisterViewPane( + "Material Property Inspector", LyViewPane::CategoryTools, inspectorOptions); + } + void EditorMaterialSystemComponent::SetupThumbnails() { using namespace AzToolsFramework::Thumbnailer; using namespace LyIntegration; - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, - MAKE_TCACHE(Thumbnails::MaterialThumbnailCache), + ThumbnailerRequestsBus::Broadcast( + &ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(Thumbnails::MaterialThumbnailCache), ThumbnailContext::DefaultContext); } @@ -189,12 +216,13 @@ namespace AZ using namespace AzToolsFramework::Thumbnailer; using namespace LyIntegration; - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::UnregisterThumbnailProvider, - Thumbnails::MaterialThumbnailCache::ProviderName, + ThumbnailerRequestsBus::Broadcast( + &ThumbnailerRequests::UnregisterThumbnailProvider, Thumbnails::MaterialThumbnailCache::ProviderName, ThumbnailContext::DefaultContext); } - AzToolsFramework::AssetBrowser::SourceFileDetails EditorMaterialSystemComponent::GetSourceFileDetails(const char* fullSourceFileName) + AzToolsFramework::AssetBrowser::SourceFileDetails EditorMaterialSystemComponent::GetSourceFileDetails( + const char* fullSourceFileName) { static const char* MaterialTypeIconPath = ":/Icons/materialtype.svg"; static const char* MaterialTypeExtension = "materialtype"; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h index 267f31f92b..7fa43ea309 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h @@ -8,11 +8,10 @@ #pragma once #include - #include - -#include +#include #include +#include #include #include @@ -28,8 +27,9 @@ namespace AZ : public AZ::Component , private EditorMaterialSystemComponentRequestBus::Handler , private AzFramework::ApplicationLifecycleEvents::Bus::Handler - , public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - , public AzToolsFramework::EditorMenuNotificationBus::Handler + , private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler + , private AzToolsFramework::EditorMenuNotificationBus::Handler + , private AzToolsFramework::EditorEvents::Bus::Handler { public: AZ_COMPONENT(EditorMaterialSystemComponent, "{96652157-DA0B-420F-B49C-0207C585144C}"); @@ -49,7 +49,8 @@ namespace AZ private: //! EditorMaterialSystemComponentRequestBus::Handler overrides... - void OpenInMaterialEditor(const AZStd::string& sourcePath) override; + void OpenMaterialEditor(const AZStd::string& sourcePath) override; + void OpenMaterialInspector(const AZ::EntityId& entityId, const AZ::Render::MaterialAssignmentId& materialAssignmentId) override; // AzFramework::ApplicationLifecycleEvents overrides... void OnApplicationAboutToStop() override; @@ -61,6 +62,9 @@ namespace AZ void OnPopulateToolMenuItems() override; void OnResetToolMenuItems() override; + // AztoolsFramework::EditorEvents::Bus::Handler overrides... + void NotifyRegisterViews() override; + void SetupThumbnails(); void TeardownThumbnails(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp index 258727e835..18812d45e9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp @@ -29,16 +29,13 @@ namespace AZ { if (HandlesSource(fullSourceFileName)) { - openers.push_back( - { - "Material_Editor", - "Open in Material Editor...", - QIcon(), + openers.push_back({ "Material_Editor", "Open in Material Editor...", QIcon(), [&](const char* fullSourceFileNameInCallback, [[maybe_unused]] const AZ::Uuid& sourceUUID) - { - EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, fullSourceFileNameInCallback); - } - }); + { + EditorMaterialSystemComponentRequestBus::Broadcast( + &EditorMaterialSystemComponentRequestBus::Events::OpenMaterialEditor, + fullSourceFileNameInCallback); + } }); } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index 6e1e710282..3e41a8072e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -35,6 +35,8 @@ namespace AZ ->Attribute(AZ::Script::Attributes::Module, "render") ->Event("GetOriginalMaterialAssignments", &MaterialComponentRequestBus::Events::GetOriginalMaterialAssignments) ->Event("FindMaterialAssignmentId", &MaterialComponentRequestBus::Events::FindMaterialAssignmentId) + ->Event("GetDefaultMaterialAssetId", &MaterialComponentRequestBus::Events::GetDefaultMaterialAssetId) + ->Event("GetMaterialSlotLabel", &MaterialComponentRequestBus::Events::GetMaterialSlotLabel) ->Event("SetMaterialOverrides", &MaterialComponentRequestBus::Events::SetMaterialOverrides) ->Event("GetMaterialOverrides", &MaterialComponentRequestBus::Events::GetMaterialOverrides) ->Event("ClearAllMaterialOverrides", &MaterialComponentRequestBus::Events::ClearAllMaterialOverrides) @@ -71,6 +73,7 @@ namespace AZ ->Event("ClearPropertyOverride", &MaterialComponentRequestBus::Events::ClearPropertyOverride) ->Event("ClearPropertyOverrides", &MaterialComponentRequestBus::Events::ClearPropertyOverrides) ->Event("ClearAllPropertyOverrides", &MaterialComponentRequestBus::Events::ClearAllPropertyOverrides) + ->Event("SetPropertyOverrides", &MaterialComponentRequestBus::Events::SetPropertyOverrides) ->Event("GetPropertyOverrides", &MaterialComponentRequestBus::Events::GetPropertyOverrides) ; } @@ -168,19 +171,26 @@ namespace AZ const auto& propertyOverrides2 = materialIt->second.m_propertyOverrides; for (auto& propertyPair : propertyOverrides2) { + if (propertyPair.second.empty()) + { + continue; + } + const auto& materialPropertyIndex = materialInstance->FindPropertyIndex(propertyPair.first); - if (!materialPropertyIndex.IsNull()) + if (materialPropertyIndex.IsNull()) + { + continue; + } + + if (propertyPair.second.is()) + { + const auto& assetId = *AZStd::any_cast(&propertyPair.second); + Data::Asset imageAsset(assetId, azrtti_typeid()); + materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue(imageAsset)); + } + else { - if (propertyPair.second.is()) - { - const auto& assetId = *AZStd::any_cast(&propertyPair.second); - Data::Asset imageAsset(assetId, azrtti_typeid()); - materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue(imageAsset)); - } - else - { - materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second)); - } + materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second)); } } @@ -288,6 +298,40 @@ namespace AZ return materialAssignmentId; } + AZ::Data::AssetId MaterialComponentController::GetDefaultMaterialAssetId(const MaterialAssignmentId& materialAssignmentId) const + { + RPI::ModelMaterialSlotMap modelMaterialSlots; + MaterialReceiverRequestBus::EventResult( + modelMaterialSlots, m_entityId, &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); + + auto slotIter = modelMaterialSlots.find(materialAssignmentId.m_materialSlotStableId); + return slotIter != modelMaterialSlots.end() ? slotIter->second.m_defaultMaterialAsset.GetId() : AZ::Data::AssetId(); + } + + AZStd::string MaterialComponentController::GetMaterialSlotLabel(const MaterialAssignmentId& materialAssignmentId) const + { + if (materialAssignmentId == DefaultMaterialAssignmentId) + { + return "Default Material"; + } + + RPI::ModelMaterialSlotMap modelMaterialSlots; + MaterialReceiverRequestBus::EventResult( + modelMaterialSlots, m_entityId, &MaterialReceiverRequestBus::Events::GetModelMaterialSlots); + + auto slotIter = modelMaterialSlots.find(materialAssignmentId.m_materialSlotStableId); + if (slotIter != modelMaterialSlots.end()) + { + const Name& displayName = slotIter->second.m_displayName; + if (!displayName.IsEmpty()) + { + return displayName.GetStringView(); + } + } + + return ""; + } + void MaterialComponentController::SetMaterialOverrides(const MaterialAssignmentMap& materials) { // this function is called twice once material asset is changed, a temp variable is @@ -309,7 +353,6 @@ namespace AZ { m_configuration.m_materials.clear(); QueueMaterialUpdateNotification(); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } } @@ -334,12 +377,11 @@ namespace AZ LoadMaterials(); } - const AZ::Data::AssetId MaterialComponentController::GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const + AZ::Data::AssetId MaterialComponentController::GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const { auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) { - AZ_Error("MaterialComponentController", false, "MaterialAssignmentId not found."); return {}; } @@ -351,7 +393,6 @@ namespace AZ if (m_configuration.m_materials.erase(materialAssignmentId) > 0) { QueueMaterialUpdateNotification(); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } } @@ -372,7 +413,6 @@ namespace AZ } QueuePropertyChanges(materialAssignmentId); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } void MaterialComponentController::SetPropertyOverrideBool( @@ -450,14 +490,12 @@ namespace AZ const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) { - AZ_Error("MaterialComponentController", false, "MaterialAssignmentId not found."); return {}; } const auto propertyIt = materialIt->second.m_propertyOverrides.find(AZ::Name(propertyName)); if (propertyIt == materialIt->second.m_propertyOverrides.end()) { - AZ_Error("MaterialComponentController", false, "Property not found: %s.", propertyName.c_str()); return {}; } @@ -546,14 +584,12 @@ namespace AZ auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) { - AZ_Error("MaterialComponentController", false, "MaterialAssignmentId not found."); return; } auto propertyIt = materialIt->second.m_propertyOverrides.find(AZ::Name(propertyName)); if (propertyIt == materialIt->second.m_propertyOverrides.end()) { - AZ_Error("MaterialComponentController", false, "Property not found: %s.", propertyName.c_str()); return; } @@ -565,7 +601,6 @@ namespace AZ } QueuePropertyChanges(materialAssignmentId); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } void MaterialComponentController::ClearPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) @@ -573,7 +608,6 @@ namespace AZ auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) { - AZ_Error("MaterialComponentController", false, "MaterialAssignmentId not found."); return; } @@ -582,7 +616,6 @@ namespace AZ materialIt->second.m_propertyOverrides = {}; materialIt->second.RebuildInstance(); QueueMaterialUpdateNotification(); - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } } @@ -602,21 +635,62 @@ namespace AZ if (cleared) { - MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialsEdited, m_configuration.m_materials); } } + void MaterialComponentController::SetPropertyOverrides( + const MaterialAssignmentId& materialAssignmentId, const MaterialPropertyOverrideMap& propertyOverrides) + { + auto& materialAssignment = m_configuration.m_materials[materialAssignmentId]; + const bool wasEmpty = materialAssignment.m_propertyOverrides.empty(); + materialAssignment.m_propertyOverrides = propertyOverrides; + + if (wasEmpty != materialAssignment.m_propertyOverrides.empty()) + { + materialAssignment.RebuildInstance(); + QueueMaterialUpdateNotification(); + } + + QueuePropertyChanges(materialAssignmentId); + } + MaterialPropertyOverrideMap MaterialComponentController::GetPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) const { const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); if (materialIt == m_configuration.m_materials.end()) { - AZ_Warning("MaterialComponentController", false, "MaterialAssignmentId not found."); return {}; } return materialIt->second.m_propertyOverrides; } + void MaterialComponentController::SetModelUvOverrides( + const MaterialAssignmentId& materialAssignmentId, const AZ::RPI::MaterialModelUvOverrideMap& modelUvOverrides) + { + auto& materialAssignment = m_configuration.m_materials[materialAssignmentId]; + const bool wasEmpty = materialAssignment.m_matModUvOverrides.empty(); + materialAssignment.m_matModUvOverrides = modelUvOverrides; + + if (wasEmpty != materialAssignment.m_matModUvOverrides.empty()) + { + materialAssignment.RebuildInstance(); + QueueMaterialUpdateNotification(); + } + + QueuePropertyChanges(materialAssignmentId); + } + + AZ::RPI::MaterialModelUvOverrideMap MaterialComponentController::GetModelUvOverrides( + const MaterialAssignmentId& materialAssignmentId) const + { + const auto materialIt = m_configuration.m_materials.find(materialAssignmentId); + if (materialIt == m_configuration.m_materials.end()) + { + return {}; + } + return materialIt->second.m_matModUvOverrides; + } + void MaterialComponentController::QueuePropertyChanges(const MaterialAssignmentId& materialAssignmentId) { m_queuedPropertyOverrides.emplace(materialAssignmentId); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index 9e59bbef19..c9dd330412 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -47,6 +47,8 @@ namespace AZ //! MaterialComponentRequestBus overrides... MaterialAssignmentMap GetOriginalMaterialAssignments() const override; MaterialAssignmentId FindMaterialAssignmentId(const MaterialAssignmentLodIndex lod, const AZStd::string& label) const override; + AZ::Data::AssetId GetDefaultMaterialAssetId(const MaterialAssignmentId& materialAssignmentId) const override; + AZStd::string GetMaterialSlotLabel(const MaterialAssignmentId& materialAssignmentId) const override; void SetMaterialOverrides(const MaterialAssignmentMap& materials) override; const MaterialAssignmentMap& GetMaterialOverrides() const override; void ClearAllMaterialOverrides() override; @@ -54,7 +56,7 @@ namespace AZ const AZ::Data::AssetId GetDefaultMaterialOverride() const override; void ClearDefaultMaterialOverride() override; void SetMaterialOverride(const MaterialAssignmentId& materialAssignmentId, const AZ::Data::AssetId& materialAssetId) override; - const AZ::Data::AssetId GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const override; + AZ::Data::AssetId GetMaterialOverride(const MaterialAssignmentId& materialAssignmentId) const override; void ClearMaterialOverride(const MaterialAssignmentId& materialAssignmentId) override; void SetPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName, const AZStd::any& value) override; @@ -86,7 +88,12 @@ namespace AZ void ClearPropertyOverride(const MaterialAssignmentId& materialAssignmentId, const AZStd::string& propertyName) override; void ClearPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) override; void ClearAllPropertyOverrides() override; + void SetPropertyOverrides( + const MaterialAssignmentId& materialAssignmentId, const MaterialPropertyOverrideMap& propertyOverrides) override; MaterialPropertyOverrideMap GetPropertyOverrides(const MaterialAssignmentId& materialAssignmentId) const override; + void SetModelUvOverrides( + const MaterialAssignmentId& materialAssignmentId, const AZ::RPI::MaterialModelUvOverrideMap& modelUvOverrides) override; + AZ::RPI::MaterialModelUvOverrideMap GetModelUvOverrides(const MaterialAssignmentId& materialAssignmentId) const override; private: From bd8c53550a5e00f89f4f89107c0a7bd8c24cac52 Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Tue, 14 Sep 2021 17:12:17 -0700 Subject: [PATCH 122/274] Replacing the old esm shadow blur with faster blur (#4095) * Replacing the old gaussian blur with a much faster, better quality kawase blur Signed-off-by: mrieggeramzn * Removing atomtesting outdated msg Signed-off-by: mrieggeramzn * Some recommendations from Tommy Signed-off-by: mrieggeramzn * Adding early termination from previous gaussian filtering algorithm that kawase replaces Signed-off-by: mrieggeramzn * Removing pcf method Signed-off-by: mrieggeramzn * removing the old blur and adding in the new kawase blur into .cmake file Signed-off-by: mrieggeramzn --- .../Common/Assets/Passes/EsmShadowmaps.pass | 19 +-- .../Assets/Passes/FilterDepthHorizontal.pass | 72 ---------- ...pthVertical.pass => KawaseShadowBlur.pass} | 10 +- .../Assets/Passes/PassTemplates.azasset | 14 +- .../Math/GaussianFilterFloatHorizontal.azsl | 60 -------- .../Math/GaussianFilterFloatHorizontal.shader | 16 --- .../Math/GaussianFilterFloatVertical.azsl | 60 -------- .../Shaders/Shadow/KawaseShadowBlur.azsl | 132 ++++++++++++++++++ .../KawaseShadowBlur.shader} | 2 +- .../atom_feature_common_asset_files.cmake | 9 +- .../Source/CoreLights/EsmShadowmapsPass.cpp | 52 ++++--- .../Source/CoreLights/EsmShadowmapsPass.h | 14 +- 12 files changed, 201 insertions(+), 259 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Assets/Passes/FilterDepthHorizontal.pass rename Gems/Atom/Feature/Common/Assets/Passes/{FilterDepthVertical.pass => KawaseShadowBlur.pass} (88%) delete mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.azsl delete mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.shader delete mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.azsl rename Gems/Atom/Feature/Common/Assets/Shaders/{Math/GaussianFilterFloatVertical.shader => Shadow/KawaseShadowBlur.shader} (79%) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EsmShadowmaps.pass b/Gems/Atom/Feature/Common/Assets/Passes/EsmShadowmaps.pass index 27b777d549..a3bd6604dc 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EsmShadowmaps.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EsmShadowmaps.pass @@ -40,9 +40,11 @@ } ] }, + { - "Name": "HorizontalGaussianFilter", - "TemplateName": "FilterDepthHorizontalTemplate", + "Name": "KawaseBlur0", + "TemplateName": "KawaseShadowBlurTemplate", + "Enabled": true, "Connections": [ { "LocalSlot": "Input", @@ -54,26 +56,27 @@ ] }, { - "Name": "VerticalGaussianFiter", - "TemplateName": "FilterDepthVerticalTemplate", + "Name": "KawaseBlur1", + "TemplateName": "KawaseShadowBlurTemplate", + "Enabled": true, "Connections": [ { "LocalSlot": "Input", "AttachmentRef": { - "Pass": "HorizontalGaussianFilter", + "Pass": "KawaseBlur0", "Attachment": "Output" } } ] - } + } ], "Connections": [ { "LocalSlot": "EsmShadowmaps", "AttachmentRef": { - "Pass": "VerticalGaussianFiter", + "Pass": "KawaseBlur1", "Attachment": "Output" - } + } } ] } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/FilterDepthHorizontal.pass b/Gems/Atom/Feature/Common/Assets/Passes/FilterDepthHorizontal.pass deleted file mode 100644 index 2b2ae40fdc..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Passes/FilterDepthHorizontal.pass +++ /dev/null @@ -1,72 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "PassAsset", - "ClassData": { - "PassTemplate": { - "Name": "FilterDepthHorizontalTemplate", - "PassClass": "ComputePass", - "Slots": [ - { - "Name": "Input", - "SlotType": "Input", - "ShaderInputName": "m_inputImage", - "ScopeAttachmentUsage": "Shader", - "LoadStoreAction": { - "LoadAction": "Load", - "StoreAction": "DontCare" - }, - "ImageViewDesc": { - "IsArray": 1 - } - }, - { - "Name": "Output", - "SlotType": "Output", - "ShaderInputName": "m_outputImage", - "ScopeAttachmentUsage": "Shader", - "LoadStoreAction": { - "LoadAction": "DontCare", - "StoreAction": "Store" - }, - "ImageViewDesc": { - "IsArray": 1 - } - } - ], - "PassData": { - "$type": "ComputePassData", - "ShaderAsset": { - "FilePath": "Shaders/Math/GaussianFilterFloatHorizontal.shader" - } - }, - "ImageAttachments": [ - { - "Name": "HorizontalFiltered", - "SizeSource": { - "Source": { - "Pass": "This", - "Attachment": "Input" - } - }, - "ArraySizeSource": { - "Pass": "This", - "Attachment": "Input" - }, - "ImageDescriptor": { - "Format": "R32_FLOAT" - } - } - ], - "Connections": [ - { - "localSlot": "Output", - "AttachmentRef": { - "Pass": "This", - "Attachment": "HorizontalFiltered" - } - } - ] - } - } -} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/FilterDepthVertical.pass b/Gems/Atom/Feature/Common/Assets/Passes/KawaseShadowBlur.pass similarity index 88% rename from Gems/Atom/Feature/Common/Assets/Passes/FilterDepthVertical.pass rename to Gems/Atom/Feature/Common/Assets/Passes/KawaseShadowBlur.pass index 5d8a4de21b..46ef8ba8ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/FilterDepthVertical.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/KawaseShadowBlur.pass @@ -4,7 +4,7 @@ "ClassName": "PassAsset", "ClassData": { "PassTemplate": { - "Name": "FilterDepthVerticalTemplate", + "Name": "KawaseShadowBlurTemplate", "PassClass": "ComputePass", "Slots": [ { @@ -28,7 +28,7 @@ "LoadStoreAction": { "LoadAction": "DontCare", "StoreAction": "Store" - }, + }, "ImageViewDesc": { "IsArray": 1 } @@ -37,12 +37,12 @@ "PassData": { "$type": "ComputePassData", "ShaderAsset": { - "FilePath": "Shaders/Math/GaussianFilterFloatVertical.shader" + "FilePath": "Shaders/Shadow/KawaseShadowBlur.shader" } }, "ImageAttachments": [ { - "Name": "VerticalFiltered", + "Name": "FilteredImage", "SizeSource": { "Source": { "Pass": "This", @@ -63,7 +63,7 @@ "localSlot": "Output", "AttachmentRef": { "Pass": "This", - "Attachment": "VerticalFiltered" + "Attachment": "FilteredImage" } } ] diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset index 57d35fb48d..8b7d6a8438 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset +++ b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset @@ -184,14 +184,6 @@ "Name": "DepthOfFieldWriteFocusDepthFromGpuTemplate", "Path": "Passes/DepthOfFieldWriteFocusDepthFromGpu.pass" }, - { - "Name": "FilterDepthHorizontalTemplate", - "Path": "Passes/FilterDepthHorizontal.pass" - }, - { - "Name": "FilterDepthVerticalTemplate", - "Path": "Passes/FilterDepthVertical.pass" - }, { "Name": "EsmShadowmapsTemplate", "Path": "Passes/EsmShadowmaps.pass" @@ -503,7 +495,11 @@ { "Name": "LowEndPipelineTemplate", "Path": "Passes/LowEndPipeline.pass" - } + }, + { + "Name": "KawaseShadowBlurTemplate", + "Path": "Passes/KawaseShadowBlur.pass" + } ] } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.azsl deleted file mode 100644 index 353f08427d..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.azsl +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// [GFX TODO][ATOM-3365] optimization using intermediary results in groupshared memory. - -#include -#include -#include - -[numthreads(16,16,1)] -void MainCS(uint3 dispatchId: SV_DispatchThreadID) -{ - const float3 inputSize = GetImageSize(FilterPassSrg::m_inputImage); - const float3 outputSize = GetImageSize(FilterPassSrg::m_outputImage); - - const uint shadowmapIndex = GetShadowmapIndex( - FilterPassSrg::m_shadowmapIndexTable, - dispatchId, - inputSize.x); - // Early return if thread is outside of shadowmaps. - if (shadowmapIndex == ~0) - { - return; - } - const FilterParameter filterParameter = FilterPassSrg::m_filterParameters[shadowmapIndex]; - const uint shadowmapSize = filterParameter.m_shadowmapSize; - // Early return if filter is disabled. - if (!filterParameter.m_isEnabled || shadowmapSize <= 1) - { - return; // early return if filter parameter is empty. - } - - const uint sourceMin = filterParameter.m_shadowmapOriginInSlice.x; - const uint sourceMax = sourceMin + shadowmapSize - 1; - - uint filterTableSize = 0; - FilterPassSrg::m_filterTable.GetDimensions(filterTableSize); - if (filterTableSize == 0 || filterParameter.m_parameterCount == 0) - { - return; // If filter parameter is empty, early return. - } - - // [GFX TODO][ATOM-5676] pass proper source min/max for each shadowmap - const float result = FilteredFloat( - dispatchId, - FilterPassSrg::m_inputImage, - uint2(1, 0), // horizontal - sourceMin, - sourceMax, - FilterPassSrg::m_filterTable, - filterParameter.m_parameterOffset, - filterParameter.m_parameterCount); - - FilterPassSrg::m_outputImage[dispatchId].r = result; -} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.shader deleted file mode 100644 index 6998fd000c..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatHorizontal.shader +++ /dev/null @@ -1,16 +0,0 @@ -{ - "Source" : "GaussianFilterFloatHorizontal", - - "DrawList" : "shadow", - - "ProgramSettings": - { - "EntryPoints": - [ - { - "name": "MainCS", - "type": "Compute" - } - ] - } -} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.azsl deleted file mode 100644 index 11c7d04bb1..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.azsl +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// [GFX TODO][ATOM-3365] optimization using intermediary results in groupshared memory. - -#include -#include -#include - -[numthreads(16,16,1)] -void MainCS(uint3 dispatchId: SV_DispatchThreadID) -{ - const float3 inputSize = GetImageSize(FilterPassSrg::m_inputImage); - const float3 outputSize = GetImageSize(FilterPassSrg::m_outputImage); - - const uint shadowmapIndex = GetShadowmapIndex( - FilterPassSrg::m_shadowmapIndexTable, - dispatchId, - inputSize.x); - // Early return if thread is outside of shadowmaps. - if (shadowmapIndex == ~0) - { - return; - } - const FilterParameter filterParameter = FilterPassSrg::m_filterParameters[shadowmapIndex]; - const uint shadowmapSize = filterParameter.m_shadowmapSize; - // Early return if filter is disabled. - if (!filterParameter.m_isEnabled || shadowmapSize <= 1) - { - return; // early return if filter parameter is empty. - } - - const uint sourceMin = filterParameter.m_shadowmapOriginInSlice.y; - const uint sourceMax = sourceMin + shadowmapSize - 1; - - uint filterTableSize = 0; - FilterPassSrg::m_filterTable.GetDimensions(filterTableSize); - if (filterTableSize == 0 || filterParameter.m_parameterCount == 0) - { - return; // If filter parameter is empty, early return. - } - - // [GFX TODO][ATOM-5676] pass proper source min/max for each shadowmap - const float result = FilteredFloat( - dispatchId, - FilterPassSrg::m_inputImage, - uint2(0, 1), // vertical - sourceMin, - sourceMax, - FilterPassSrg::m_filterTable, - filterParameter.m_parameterOffset, - filterParameter.m_parameterCount); - - FilterPassSrg::m_outputImage[dispatchId].r = result; -} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.azsl new file mode 100644 index 0000000000..9b480a4e40 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.azsl @@ -0,0 +1,132 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +// [GFX TODO][ATOM-3365] optimization using intermediary results in groupshared memory. + +// This shader blurs the ESM results using a multi-pass kawase filter. +// It should generally be faster than separable gaussian blur +// https://software.intel.com/content/www/us/en/develop/blogs/an-investigation-of-fast-real-time-gpu-based-image-blur-algorithms.html + +#include +#include +#include +#include + +ShaderResourceGroup FilterPassSrg : SRG_PerPass +{ + // This shader filters multiple images with distinct filter parameters. + // So, the input and output are arrays of texture2Ds. + Texture2DArray m_inputImage; + RWTexture2DArray m_outputImage; + + // This can convert a coordinate in an atlas to + // the shadowmap index. + Buffer m_shadowmapIndexTable; + + // This contains parameters related to filtering. + StructuredBuffer m_filterParameters; + + // x and y contain the inverse of the texture map resolution, z contains the kawase iteration + // i.e. a two pass kawase blur passes in 0 for the 1st pass and 1 for the second pass + float4 m_rcpResolutionAndIteration; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +void CalculateBlurBoundaries(const uint shadowmapIndex, out float2 sourceMinTex, out float2 sourceMaxTex) +{ + const float2 rcpPixelSize = FilterPassSrg::m_rcpResolutionAndIteration.xy; + + const FilterParameter filterParameter = FilterPassSrg::m_filterParameters[shadowmapIndex]; + const uint shadowmapSize = filterParameter.m_shadowmapSize; + + // location of the shadow bounds in texels + const uint2 sourceMinPixel = filterParameter.m_shadowmapOriginInSlice.xy; + const uint2 sourceMaxPixel = sourceMinPixel + shadowmapSize - 1; + + // location of the shadow bounds in uv space + sourceMinTex = (sourceMinPixel + 0.5f) * rcpPixelSize; + sourceMaxTex = (sourceMaxPixel + 0.5f) * rcpPixelSize; +} + +float AccumulateShadowSamples(Texture2DArray tex, float3 texCoord, SamplerState s) +{ + float4 values = tex.GatherRed(s, texCoord); + float result = values.x + values.y + values.z + values.w; + return result; +} + +[numthreads(16,16,1)] +void MainCS(uint3 dispatchId: SV_DispatchThreadID) +{ + const float inputSize = GetImageSize(FilterPassSrg::m_inputImage).x; + const uint shadowmapIndex = GetShadowmapIndex( + FilterPassSrg::m_shadowmapIndexTable, + dispatchId, + inputSize); + + // Early return if thread is outside of shadowmaps. + if (shadowmapIndex == ~0) + { + return; + } + + const FilterParameter filterParameter = FilterPassSrg::m_filterParameters[shadowmapIndex]; + const uint shadowmapSize = filterParameter.m_shadowmapSize; + // Early return if filter is disabled. + if (!filterParameter.m_isEnabled || shadowmapSize <= 1) + { + return; // early return if filter parameter is empty. + } + + const float2 rcpPixelSize = FilterPassSrg::m_rcpResolutionAndIteration.xy; + const float blurIteration = FilterPassSrg::m_rcpResolutionAndIteration.z; + + float2 sourceMinTex, sourceMaxTex; + CalculateBlurBoundaries(shadowmapIndex, sourceMinTex, sourceMaxTex); + + const float2 halfRcpPixelSize = rcpPixelSize / 2.0f; + const float2 dUV = rcpPixelSize.xy * blurIteration + halfRcpPixelSize.xy; + const float2 texCoord = (dispatchId.xy + 0.5f) * rcpPixelSize; + + const float3 texCoordSamples[4] = { + float3(texCoord.x - dUV.x, texCoord.y - dUV.y, dispatchId.z), + float3(texCoord.x - dUV.x, texCoord.y + dUV.y, dispatchId.z), + float3(texCoord.x + dUV.x, texCoord.y - dUV.y, dispatchId.z), + float3(texCoord.x + dUV.x, texCoord.y + dUV.y, dispatchId.z), + }; + + float accumulatedBlur = 0; + float numSamplesAccumulated = 0; + for(int i = 0 ; i < 4; ++i) + { + if (texCoordSamples[i].x >= sourceMinTex.x && + texCoordSamples[i].y >= sourceMinTex.y && + texCoordSamples[i].x < sourceMaxTex.x && + texCoordSamples[i].y < sourceMaxTex.y) + { + // we should be tapping the location directly in between 4 adjacent texels + accumulatedBlur += AccumulateShadowSamples(FilterPassSrg::m_inputImage, texCoordSamples[i], FilterPassSrg::LinearSampler); + numSamplesAccumulated += 4; + } + } + + if (numSamplesAccumulated > 0) + { + float result = accumulatedBlur / numSamplesAccumulated; + FilterPassSrg::m_outputImage[dispatchId].r = result; + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader similarity index 79% rename from Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.shader rename to Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader index db303e1ea7..dacacdafff 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Math/GaussianFilterFloatVertical.shader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/KawaseShadowBlur.shader @@ -1,5 +1,5 @@ { - "Source" : "GaussianFilterFloatVertical", + "Source" : "KawaseShadowBlur", "DrawList" : "shadow", diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index e43498c55d..8435625833 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -137,8 +137,6 @@ set(FILES Passes/FastDepthAwareBlur.pass Passes/FastDepthAwareBlurHor.pass Passes/FastDepthAwareBlurVer.pass - Passes/FilterDepthHorizontal.pass - Passes/FilterDepthVertical.pass Passes/Forward.pass Passes/ForwardCheckerboard.pass Passes/ForwardMSAA.pass @@ -146,6 +144,7 @@ set(FILES Passes/FullscreenCopy.pass Passes/FullscreenOutputOnly.pass Passes/ImGui.pass + Passes/KawaseShadowBlur.pass Passes/LightAdaptationParent.pass Passes/LightCulling.pass Passes/LightCullingHeatmap.pass @@ -331,10 +330,6 @@ set(FILES Shaders/LightCulling/LightCullingTilePrepare.shader Shaders/LuxCore/RenderTexture.azsl Shaders/LuxCore/RenderTexture.shader - Shaders/Math/GaussianFilterFloatHorizontal.azsl - Shaders/Math/GaussianFilterFloatHorizontal.shader - Shaders/Math/GaussianFilterFloatVertical.azsl - Shaders/Math/GaussianFilterFloatVertical.shader Shaders/MorphTargets/MorphTargetCS.azsl Shaders/MorphTargets/MorphTargetCS.shader Shaders/MorphTargets/MorphTargetSRG.azsli @@ -457,6 +452,8 @@ set(FILES Shaders/ScreenSpace/DeferredFog.shader Shaders/Shadow/DepthExponentiation.azsl Shaders/Shadow/DepthExponentiation.shader + Shaders/Shadow/KawaseShadowBlur.azsl + Shaders/Shadow/KawaseShadowBlur.shader Shaders/Shadow/Shadowmap.azsl Shaders/Shadow/Shadowmap.shader Shaders/SkinnedMesh/LinearSkinningCS.azsl diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp index 6948eb598e..99eaa8a919 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.cpp @@ -130,32 +130,17 @@ namespace AZ const AZStd::array_view>& children = GetChildren(); AZ_Assert(children.size() == EsmChildPassKindCount, "[EsmShadowmapsPass '%s'] The count of children is wrong.", GetPathName().GetCStr()); - for (uint32_t index = 0; index < EsmChildPassKindCount; ++index) + for (uint32_t childPassIndex = 0; childPassIndex < EsmChildPassKindCount; ++childPassIndex) { - RPI::ComputePass* child = azrtti_cast(children[index].get()); + RPI::ComputePass* child = azrtti_cast(children[childPassIndex].get()); AZ_Assert(child, "[EsmShadowmapsPass '%s'] A child does not compute.", GetPathName().GetCStr()); Data::Instance srg = child->GetShaderResourceGroup(); - if (m_shadowmapIndexTableBufferIndices[index].IsNull()) + SetBlurParameters(srg, childPassIndex); + if (childPassIndex >= aznumeric_cast(EsmChildPassKind::KawaseBlur0)) { - m_shadowmapIndexTableBufferIndices[index] = srg->FindShaderInputBufferIndex(Name("m_shadowmapIndexTable")); - } - srg->SetBuffer(m_shadowmapIndexTableBufferIndices[index], m_shadowmapIndexTableBuffer); - - if (m_filterParameterBufferIndices[index].IsNull()) - { - m_filterParameterBufferIndices[index] = srg->FindShaderInputBufferIndex(Name("m_filterParameters")); - } - srg->SetBuffer(m_filterParameterBufferIndices[index], m_filterParameterBuffer); - - if (index != static_cast(EsmChildPassKind::Exponentiation)) - { - if (m_filterTableBufferIndices[index].IsNull()) - { - m_filterTableBufferIndices[index] = srg->FindShaderInputBufferIndex(Name("m_filterTable")); - } - srg->SetBuffer(m_filterTableBufferIndices[index], m_filterTableBuffer); + SetKawaseBlurSpecificParameters(srg, childPassIndex - aznumeric_cast(EsmChildPassKind::KawaseBlur0)); } child->SetTargetThreadCounts( @@ -165,5 +150,32 @@ namespace AZ } } + void EsmShadowmapsPass::SetBlurParameters(Data::Instance srg, const uint32_t childPassIndex) + { + if (m_shadowmapIndexTableBufferIndices[childPassIndex].IsNull()) + { + m_shadowmapIndexTableBufferIndices[childPassIndex] = srg->FindShaderInputBufferIndex(Name("m_shadowmapIndexTable")); + } + srg->SetBuffer(m_shadowmapIndexTableBufferIndices[childPassIndex], m_shadowmapIndexTableBuffer); + + if (m_filterParameterBufferIndices[childPassIndex].IsNull()) + { + m_filterParameterBufferIndices[childPassIndex] = srg->FindShaderInputBufferIndex(Name("m_filterParameters")); + } + srg->SetBuffer(m_filterParameterBufferIndices[childPassIndex], m_filterParameterBuffer); + } + + void EsmShadowmapsPass::SetKawaseBlurSpecificParameters(Data::Instance srg, uint32_t kawaseBlurIndex) + { + if (m_kawaseBlurConstantIndices[kawaseBlurIndex].IsNull()) + { + m_kawaseBlurConstantIndices[kawaseBlurIndex] = srg->FindShaderInputConstantIndex(Name("m_rcpResolutionAndIteration")); + } + const AZ::Vector4 data( + 1.0f / m_shadowmapImageSize.m_width, 1.0f / m_shadowmapImageSize.m_height, aznumeric_cast(kawaseBlurIndex), 0.0f); + + srg->SetConstant(m_kawaseBlurConstantIndices[kawaseBlurIndex], data); + } + } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.h index 236855c8c5..6e5e1aa311 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/EsmShadowmapsPass.h @@ -21,12 +21,17 @@ namespace AZ { + namespace RPI + { + class ShaderResourceGroup; + } + namespace Render { AZ_ENUM_CLASS_WITH_UNDERLYING_TYPE(EsmChildPassKind, uint32_t, (Exponentiation, 0), - HorizontalFilter, - VerticalFilter); + KawaseBlur0, + KawaseBlur1); //! This pass outputs filtered shadowmap images used in ESM. //! ESM is an abbreviation of Exponential Shadow Maps. @@ -88,6 +93,9 @@ namespace AZ void FrameBeginInternal(FramePrepareParams params) override; void UpdateChildren(); + // Parameters for both the depth exponentiation pass along with the kawase blur passes + void SetBlurParameters(Data::Instance srg, const uint32_t childPassIndex); + void SetKawaseBlurSpecificParameters(Data::Instance srg, const uint32_t kawaseBlurIndex); bool m_computationEnabled = false; Name m_lightTypeName; @@ -102,6 +110,8 @@ namespace AZ Data::Instance m_shadowmapIndexTableBuffer; AZStd::array m_filterParameterBufferIndices; Data::Instance m_filterParameterBuffer; + + AZStd::array m_kawaseBlurConstantIndices; }; } // namespace Render } // namespace AZ From ce72e32cfc640af8029194578fe1ecf4766c8d49 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Tue, 14 Sep 2021 19:21:29 -0500 Subject: [PATCH 123/274] Fixed issue where two Paths could compare equal to each other, but hash differently (#4126) * Fixed issue where two Paths could compare equal to each other, but hash differently This issue is caused by the Path comparison logic using the path separator of the left path in a comparison of two paths(left and right) to determine whether the PathComparison is case-sensitive or not. The logic has been updated to only perform a non-case-sensitive path comparison if both paths are using the WindowsPathSeperator of `\` Also fixed issue with the Hashing algorihtm of the Path class to always hash the root directory as if it is `/`. This allows a path of "C:\foo" and "C:/foo" to hash to the equivalent value. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * MS Build Tools 14.29 workaround around suppressing warnings using the external header feature Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/IO/Path/Path.h | 4 +- Code/Framework/AzCore/AzCore/IO/Path/Path.inl | 55 +++++--------- .../AzCore/AzCore/IO/Path/PathParser.inl | 56 ++++++++++++-- .../AzCore/Tests/IO/Path/PathTests.cpp | 76 +++++++++++++++++++ 4 files changed, 148 insertions(+), 43 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.h b/Code/Framework/AzCore/AzCore/IO/Path/Path.h index c0c4b1c974..24f26daa51 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.h +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.h @@ -273,7 +273,7 @@ namespace AZ::IO // If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ] static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept; - constexpr int compare_string_view(AZStd::string_view other) const; + constexpr int ComparePathView(const PathView& other) const; constexpr AZStd::string_view root_name_view() const; constexpr AZStd::string_view root_directory_view() const; constexpr AZStd::string_view root_path_raw_view() const; @@ -480,6 +480,8 @@ namespace AZ::IO // compare //! Performs a compare of each of the path parts for equivalence //! Each part of the path is compare using string comparison + //! If both *this path and the input path uses the WindowsPathSeparator + //! then a non-case sensitive compare is performed //! Ex: Comparing "test/foo" against "test/fop" returns -1; //! Path separators of the contained path string aren't compared //! Ex. Comparing "C:/test\foo" against C:\test/foo" returns 0; diff --git a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl index 40cbf6f46b..0147ad3356 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/Path.inl +++ b/Code/Framework/AzCore/AzCore/IO/Path/Path.inl @@ -224,15 +224,15 @@ namespace AZ::IO // compare constexpr int PathView::Compare(const PathView& other) const noexcept { - return compare_string_view(other.m_path); + return ComparePathView(other); } constexpr int PathView::Compare(AZStd::string_view pathView) const noexcept { - return compare_string_view(pathView); + return ComparePathView(PathView(pathView, m_preferred_separator)); } constexpr int PathView::Compare(const value_type* path) const noexcept { - return compare_string_view(path); + return ComparePathView(PathView(path, m_preferred_separator)); } constexpr AZStd::fixed_string PathView::FixedMaxPathString() const noexcept @@ -398,10 +398,10 @@ namespace AZ::IO return true; } - constexpr int PathView::compare_string_view(AZStd::string_view pathView) const + constexpr int PathView::ComparePathView(const PathView& other) const { auto lhsPathParser = parser::PathParser::CreateBegin(m_path, m_preferred_separator); - auto rhsPathParser = parser::PathParser::CreateBegin(pathView, m_preferred_separator); + auto rhsPathParser = parser::PathParser::CreateBegin(other.m_path, other.m_preferred_separator); if (int res = CompareRootName(&lhsPathParser, &rhsPathParser); res != 0) { @@ -476,6 +476,8 @@ namespace AZ::IO template constexpr void PathView::MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base) { + const bool exactCaseCompare = path.m_preferred_separator == PosixPathSeparator + || base.m_preferred_separator == PosixPathSeparator; { // perform root-name/root-directory mismatch checks auto pathParser = parser::PathParser::CreateBegin(path.m_path, path.m_preferred_separator); @@ -487,7 +489,7 @@ namespace AZ::IO }; if (pathParser.InRootName() && pathParserBase.InRootName()) { - if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, pathParser.m_preferred_separator); + if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare); res != 0) { pathResult.m_path = AZStd::string_view{}; @@ -519,7 +521,7 @@ namespace AZ::IO auto pathParser = parser::PathParser::CreateBegin(path.m_path, path.m_preferred_separator); auto pathParserBase = parser::PathParser::CreateBegin(base.m_path, base.m_preferred_separator); while (pathParser && pathParserBase && pathParser.m_parser_state == pathParserBase.m_parser_state && - Internal::ComparePathSegment(*pathParser, *pathParserBase, pathParser.m_preferred_separator) == 0) + Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare) == 0) { ++pathParser; ++pathParserBase; @@ -1080,25 +1082,25 @@ namespace AZ::IO template constexpr int BasicPath::Compare(const PathView& other) const noexcept { - return static_cast(*this).compare_string_view(other.m_path); + return static_cast(*this).ComparePathView(other); } template constexpr int BasicPath::Compare(const string_type& pathString) const { - return static_cast(*this).compare_string_view(pathString); + return static_cast(*this).ComparePathView(PathView(pathString, m_preferred_separator)); } template constexpr int BasicPath::Compare(AZStd::string_view pathView) const noexcept { - return static_cast(*this).compare_string_view(pathView); + return static_cast(*this).ComparePathView(pathView); } template constexpr int BasicPath::Compare(const value_type* pathString) const noexcept { - return static_cast(*this).compare_string_view(pathString); + return static_cast(*this).ComparePathView(pathString); } // decomposition @@ -1330,10 +1332,12 @@ namespace AZ::IO // PathView::LexicallyRelative is not being used as it returns a FixedMaxPath // which has a limitation that it requires the relative path to fit within // an AZ::IO::MaxPathLength buffer - auto ComparePathPart = [pathSeparator = m_preferred_separator]( + const bool exactCaseCompare = m_preferred_separator == PosixPathSeparator + || base.m_preferred_separator == PosixPathSeparator; + auto ComparePathPart = [exactCaseCompare]( const PathIterable::PartKindPair& left, const PathIterable::PartKindPair& right) -> bool { - return Internal::ComparePathSegment(left.first, right.first, pathSeparator) == 0; + return Internal::ComparePathSegment(left.first, right.first, exactCaseCompare) == 0; }; const PathIterable thisPathParts = GetNormalPathParts(*this); @@ -1471,37 +1475,16 @@ namespace AZStd template <> struct hash { - /// Path is using FNV-1a algorithm 64 bit version. - static size_t hash_path(AZStd::string_view pathSegment, const char pathSeparator) - { - size_t hash = 14695981039346656037ULL; - constexpr size_t fnvPrime = 1099511628211ULL; - - for (const char first : pathSegment) - { - hash ^= static_cast((pathSeparator == AZ::IO::PosixPathSeparator) - ? first : tolower(first)); - hash *= fnvPrime; - } - return hash; - } - size_t operator()(const AZ::IO::PathView& pathToHash) noexcept { auto pathParser = AZ::IO::parser::PathParser::CreateBegin(pathToHash.Native(), pathToHash.m_preferred_separator); - size_t hash_value = 0; - while (pathParser) - { - AZStd::hash_combine(hash_value, hash_path(*pathParser, pathToHash.m_preferred_separator)); - ++pathParser; - } - return hash_value; + return AZ::IO::parser::HashPath(pathParser); } }; template struct hash> { - const size_t operator()(const AZ::IO::BasicPath& pathToHash) noexcept + size_t operator()(const AZ::IO::BasicPath& pathToHash) noexcept { return AZStd::hash{}(pathToHash); } diff --git a/Code/Framework/AzCore/AzCore/IO/Path/PathParser.inl b/Code/Framework/AzCore/AzCore/IO/Path/PathParser.inl index 3ab2c4376c..b19c518ff9 100644 --- a/Code/Framework/AzCore/AzCore/IO/Path/PathParser.inl +++ b/Code/Framework/AzCore/AzCore/IO/Path/PathParser.inl @@ -183,13 +183,12 @@ namespace AZ::IO::Internal return IsAbsolute(pathView.begin(), pathView.end(), preferredSeparator); } - // Compares path segments using either Posix or Windows path rules based on the path separator in use - // Posix paths perform a case-sensitive comparison, while Windows paths perform a case-insensitive comparison - static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, char pathSeparator) + // Compares path segments using either Posix or Windows path rules based on the exactCaseCompare option + static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, bool exactCaseCompare) { const size_t maxCharsToCompare = (AZStd::min)(left.size(), right.size()); - int charCompareResult = pathSeparator == PosixPathSeparator + int charCompareResult = exactCaseCompare ? maxCharsToCompare ? strncmp(left.data(), right.data(), maxCharsToCompare) : 0 : maxCharsToCompare ? azstrnicmp(left.data(), right.data(), maxCharsToCompare) : 0; return charCompareResult == 0 @@ -594,7 +593,10 @@ namespace AZ::IO::parser { return pathParser->InRootName() ? **pathParser : ""; }; - int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), lhsPathParser->m_preferred_separator); + + const bool exactCaseCompare = lhsPathParser->m_preferred_separator == PosixPathSeparator + || rhsPathParser->m_preferred_separator == PosixPathSeparator; + int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), exactCaseCompare); ConsumeRootName(lhsPathParser); ConsumeRootName(rhsPathParser); return res; @@ -621,9 +623,11 @@ namespace AZ::IO::parser auto& lhsPathParser = *lhsPathParserPtr; auto& rhsPathParser = *rhsPathParserPtr; + const bool exactCaseCompare = lhsPathParser.m_preferred_separator == PosixPathSeparator + || rhsPathParser.m_preferred_separator == PosixPathSeparator; while (lhsPathParser && rhsPathParser) { - if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, lhsPathParser.m_preferred_separator); + if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, exactCaseCompare); res != 0) { return res; @@ -646,6 +650,46 @@ namespace AZ::IO::parser return 0; } + //path.hash + /// Path is using FNV-1a algorithm 64 bit version. + inline size_t HashSegment(AZStd::string_view pathSegment, bool hashExactPath) + { + size_t hash = 14695981039346656037ULL; + constexpr size_t fnvPrime = 1099511628211ULL; + + for (const char first : pathSegment) + { + hash ^= static_cast(hashExactPath ? first : tolower(first)); + hash *= fnvPrime; + } + return hash; + } + constexpr size_t HashPath(PathParser& pathParser) + { + size_t hash_value = 0; + const bool hashExactPath = pathParser.m_preferred_separator == AZ::IO::PosixPathSeparator; + while (pathParser) + { + switch (pathParser.m_parser_state) + { + case PS_InRootName: + case PS_InFilenames: + AZStd::hash_combine(hash_value, HashSegment(*pathParser, hashExactPath)); + break; + case PS_InRootDir: + // Only hash the PosixPathSeparator when a root directory is seen + // This makes the hash consistent for root directories path of C:\ and C:/ + AZStd::hash_combine(hash_value, HashSegment("/", hashExactPath)); + break; + default: + // The BeforeBegin and AtEnd states contain no segments to hash + break; + } + ++pathParser; + } + return hash_value; + } + constexpr int DetermineLexicalElementCount(PathParser pathParser) { int count = 0; diff --git a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp index dbdb4fee78..cf212aa34c 100644 --- a/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp +++ b/Code/Framework/AzCore/Tests/IO/Path/PathTests.cpp @@ -213,6 +213,82 @@ namespace UnitTest AZStd::tuple(R"(foO/Bar)", "foo/bar") )); + + struct PathHashCompareParams + { + AZ::IO::PathView m_testPath{}; + ::testing::Matcher m_compareMatcher; + ::testing::Matcher m_hashMatcher; + }; + + class PathHashCompareFixture + : public ScopedAllocatorSetupFixture + , public ::testing::WithParamInterface + {}; + + // Verifies that two paths that compare equal has their hash value compare equal + TEST_P(PathHashCompareFixture, PathsWhichCompareEqual_HashesToSameValue_Succeeds) + { + auto&& [testPath1, compareMatcher, hashMatcher] = GetParam(); + + // Compare path using parameterized Matcher + EXPECT_THAT(testPath1, compareMatcher); + // Compare hash using parameterized Matcher + const size_t testPath1Hash = AZStd::hash{}(testPath1); +AZ_PUSH_DISABLE_WARNING(4296, "-Wunknown-warning-option") + EXPECT_THAT(testPath1Hash, hashMatcher); +AZ_POP_DISABLE_WARNING + } + + INSTANTIATE_TEST_CASE_P( + HashPathCompareValidation, + PathHashCompareFixture, + ::testing::Values( + PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::WindowsPathSeparator), + testing::Eq(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)), + testing::Eq(AZStd::hash{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/foo", AZ::IO::WindowsPathSeparator), + testing::Eq(AZ::IO::PathView(R"(/test/FOO)", AZ::IO::WindowsPathSeparator)), + testing::Eq(AZStd::hash{}(AZ::IO::PathView(R"(/test/FOO)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::WindowsPathSeparator), + testing::Eq(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)), + testing::Eq(AZStd::hash{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::PosixPathSeparator), + testing::Ne(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView(R"(C:\test\foo)", AZ::IO::WindowsPathSeparator), + testing::Ne(AZ::IO::PathView(R"(c:/test/foo)", AZ::IO::PosixPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(c:/test/foo)", AZ::IO::PosixPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator), + testing::Eq(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator)), + testing::Eq(AZStd::hash{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::PosixPathSeparator), + testing::Gt(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator)), + testing::Eq(AZStd::hash{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator), + testing::Gt(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::PosixPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::PosixPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/AOO", AZ::IO::PosixPathSeparator), + testing::Lt(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/AOO", AZ::IO::WindowsPathSeparator), + testing::Lt(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::PosixPathSeparator)), + testing::Eq(AZStd::hash{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::PosixPathSeparator))) }, + // Paths with different character values, comparison based on path separator + PathHashCompareParams{ AZ::IO::PathView("/test/BOO", AZ::IO::PosixPathSeparator), + testing::Le(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/BOO", AZ::IO::WindowsPathSeparator), + testing::Ge(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator), + testing::Le(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator))) }, + PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::PosixPathSeparator), + testing::Ge(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator)), + testing::Ne(AZStd::hash{}(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator))) } + )); + class PathSingleParamFixture : public ScopedAllocatorSetupFixture , public ::testing::WithParamInterface> From bdf9005c53cc968e3dc8aefef874f58761a50794 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 14 Sep 2021 18:19:42 -0700 Subject: [PATCH 124/274] PR comments Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/Clang/Configurations_clang.cmake | 2 +- cmake/Platform/Common/MSVC/Directory.Build.props | 2 +- cmake/Platform/Common/MSVC/VisualStudio_common.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/Platform/Common/Clang/Configurations_clang.cmake b/cmake/Platform/Common/Clang/Configurations_clang.cmake index 86f4faccfb..2a311d6079 100644 --- a/cmake/Platform/Common/Clang/Configurations_clang.cmake +++ b/cmake/Platform/Common/Clang/Configurations_clang.cmake @@ -20,7 +20,7 @@ ly_append_configurations_options( # Disabled warnings (please do not disable any others without first consulting sig-build) ################### -Wno-inconsistent-missing-override # unfortunately there is no warning in MSVC to detect missing overrides, - # MSVC's static analyzer can, but that is a different run that most developers are not ware of. A pass + # MSVC's static analyzer can, but that is a different run that most developers are not aware of. A pass # was done to fix all hits. Leaving this disabled until there is a matching warning in MSVC. -Wrange-loop-analysis diff --git a/cmake/Platform/Common/MSVC/Directory.Build.props b/cmake/Platform/Common/MSVC/Directory.Build.props index 589e14a6cb..b8e9b716d9 100644 --- a/cmake/Platform/Common/MSVC/Directory.Build.props +++ b/cmake/Platform/Common/MSVC/Directory.Build.props @@ -14,7 +14,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT @VCPKG_CONFIGURATION_MAPPING@ false - @LY_ROOT_FOLDER@\cmake\Platform\Common\MSVC\CodeAnalysis.ruleset + $(MSBuildThisFileDirectory)CodeAnalysis.ruleset diff --git a/cmake/Platform/Common/MSVC/VisualStudio_common.cmake b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake index 9124758b18..d9e58090d9 100644 --- a/cmake/Platform/Common/MSVC/VisualStudio_common.cmake +++ b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake @@ -15,4 +15,4 @@ foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) endforeach() configure_file("${CMAKE_CURRENT_LIST_DIR}/Directory.Build.props" "${CMAKE_BINARY_DIR}/Directory.Build.props" @ONLY) - +file(COPY_FILE "${CMAKE_CURRENT_LIST_DIR}/CodeAnalysis.ruleset" "${CMAKE_BINARY_DIR}/CodeAnalysis.ruleset" ONLY_IF_DIFFERENT) From 9f0de3b916caa03a5073dcb7db0842f14a07d0ba Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Tue, 14 Sep 2021 18:20:44 -0700 Subject: [PATCH 125/274] Fixes for toolchain 19.28.29913.0 Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- .../RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h index 85b782aa6b..2eef783932 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/DX12_Windows.h @@ -16,7 +16,10 @@ #include #include + +AZ_PUSH_DISABLE_WARNING(4265, "-Wunknown-warning-option") // class has virtual functions, but its non-trivial destructor is not virtual; #include +AZ_POP_DISABLE_WARNING #include #include From 81bd7b1f5f6a63e5dcc68846c1695a64dc32d5f6 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 14 Sep 2021 20:11:00 -0700 Subject: [PATCH 126/274] Implement a system that resizes the ghost widget appropriately to avoid undefined behavior due to it being moved into the gap between screens caused by scaling. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Components/FancyDocking.cpp | 14 +++--- .../Components/FancyDockingGhostWidget.cpp | 50 ++++++++++++++++++- .../Components/FancyDockingGhostWidget.h | 9 ++++ 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp index f60a98f392..7a76781cd7 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp @@ -1615,14 +1615,16 @@ namespace AzQtComponents } // Handle snapping to the screen edges/other floating windows while dragging - QScreen* screen = Utilities::ScreenAtPoint(globalPos); + QScreen* screen = QApplication::screenAt(globalPos); - AdjustForSnapping(placeholder, screen); - - m_state.setPlaceholder(placeholder, screen); + if (screen) + { + AdjustForSnapping(placeholder, screen); + m_state.setPlaceholder(placeholder, screen); - m_ghostWidget->Enable(); - RepaintFloatingIndicators(); + m_ghostWidget->Enable(); + RepaintFloatingIndicators(); + } } return m_dropZoneState.dragging(); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp index 6894e5b011..04387875df 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -76,7 +77,32 @@ namespace AzQtComponents window->setScreen(screen); } - setGeometry(targetRect); + QPoint midPoint = targetRect.topLeft() + QPoint(targetRect.width() / 2, targetRect.height() / 2); + QScreen* pointScreen = QApplication::screenAt(midPoint); + QRect rect(targetRect); + + if (!pointScreen || pointScreen != screen) + { + if (midPoint.x() >= QCursor::pos().x()) + { + rect.setLeft(rect.left() - rect.width()); + rect.setTop(rect.top() - rect.height()); + m_paintMode = PaintMode::BOTTOMRIGHT; + } + else + { + rect.setRight(rect.right() + rect.width()); + rect.setTop(rect.top() - rect.height()); + m_paintMode = PaintMode::BOTTOMLEFT; + } + } + else + { + m_paintMode = PaintMode::FULL; + } + + setGeometry(rect); + setPixmapVisible(true); if (needsRepaint) { @@ -135,7 +161,27 @@ namespace AzQtComponents yOffset = widgetSize.height() - aspectRatioHeight; } - painter.drawPixmap(QRect(0, yOffset, widgetSize.width(), aspectRatioHeight), m_pixmap); + switch (m_paintMode) + { + case PaintMode::FULL: + { + painter.drawPixmap(QRect(0, yOffset, widgetSize.width(), aspectRatioHeight), m_pixmap); + } + break; + + case PaintMode::BOTTOMLEFT: + { + painter.drawPixmap(QRect(0, (widgetSize.height() + yOffset) / 2, widgetSize.width() / 2, aspectRatioHeight / 2), m_pixmap); + } + break; + + case PaintMode::BOTTOMRIGHT: + { + painter.drawPixmap(QRect(widgetSize.width() / 2, (widgetSize.height() + yOffset) / 2, widgetSize.width() / 2, aspectRatioHeight / 2), m_pixmap); + } + break; + } + if (m_clipToWidgets) { painter.restore(); diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h index cadcbd9c8a..6649c6d848 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h @@ -45,5 +45,14 @@ namespace AzQtComponents QPixmap m_pixmap; bool m_visible = false; // maintain our own flag, so that we're always ready to render ignoring Qt's widget caching system bool m_clipToWidgets = false; + + enum class PaintMode + { + FULL = 0, + BOTTOMLEFT, + BOTTOMRIGHT + }; + + PaintMode m_paintMode = PaintMode::FULL; }; } // namespace AzQtComponents From 52095e3e165ccc0d1cab0d11da74e882efa73919 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:12:26 +0100 Subject: [PATCH 127/274] Ensure undo/redo operation for change entity selection is atomic (#4122) --- .../EditorTransformComponentSelection.cpp | 260 +++++++++--------- ...EditorTransformComponentSelectionTests.cpp | 28 +- 2 files changed, 159 insertions(+), 129 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 5a7b097e29..064fbb9da6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -86,59 +86,60 @@ namespace AzToolsFramework "Sticky select implies a single click will not change selection with an entity already selected"); // strings related to new viewport interaction model (EditorTransformComponentSelection) - static const char* const s_togglePivotTitleRightClick = "Toggle pivot"; - static const char* const s_togglePivotTitleEditMenu = "Toggle Pivot Location"; - static const char* const s_togglePivotDesc = "Toggle pivot location"; - static const char* const s_manipulatorUndoRedoName = "Manipulator Adjustment"; - static const char* const s_lockSelectionTitle = "Lock Selection"; - static const char* const s_lockSelectionDesc = "Lock the selected entities so that they can't be selected in the viewport"; - static const char* const s_hideSelectionTitle = "Hide Selection"; - static const char* const s_hideSelectionDesc = "Hide the selected entities so that they don't appear in the viewport"; - static const char* const s_unlockAllTitle = "Unlock All Entities"; - static const char* const s_unlockAllDesc = "Unlock all entities the level"; - static const char* const s_showAllTitle = "Show All"; - static const char* const s_showAllDesc = "Show all entities so that they appear in the viewport"; - static const char* const s_selectAllTitle = "Select All"; - static const char* const s_selectAllDesc = "Select all entities"; - static const char* const s_invertSelectionTitle = "Invert Selection"; - static const char* const s_invertSelectionDesc = "Invert the current entity selection"; - static const char* const s_duplicateTitle = "Duplicate"; - static const char* const s_duplicateDesc = "Duplicate selected entities"; - static const char* const s_deleteTitle = "Delete"; - static const char* const s_deleteDesc = "Delete selected entities"; - static const char* const s_resetEntityTransformTitle = "Reset Entity Transform"; - static const char* const s_resetEntityTransformDesc = "Reset transform based on manipulator mode"; - static const char* const s_resetManipulatorTitle = "Reset Manipulator"; - static const char* const s_resetManipulatorDesc = "Reset the manipulator to recenter it on the selected entity"; - static const char* const s_resetTransformLocalTitle = "Reset Transform (Local)"; - static const char* const s_resetTransformLocalDesc = "Reset transform to local space"; - static const char* const s_resetTransformWorldTitle = "Reset Transform (World)"; - static const char* const s_resetTransformWorldDesc = "Reset transform to world space"; - - static const char* const s_entityBoxSelectUndoRedoDesc = "Box Select Entities"; - static const char* const s_entityDeselectUndoRedoDesc = "Deselect Entity"; - static const char* const s_entitiesDeselectUndoRedoDesc = "Deselect Entities"; - static const char* const s_entitySelectUndoRedoDesc = "Select Entity"; - static const char* const s_dittoManipulatorUndoRedoDesc = "Ditto Manipulator"; - static const char* const s_resetManipulatorTranslationUndoRedoDesc = "Reset Manipulator Translation"; - static const char* const s_resetManipulatorOrientationUndoRedoDesc = "Reset Manipulator Orientation"; - static const char* const s_dittoEntityOrientationIndividualUndoRedoDesc = "Ditto orientation individual"; - static const char* const s_dittoEntityOrientationGroupUndoRedoDesc = "Ditto orientation group"; - static const char* const s_resetTranslationToParentUndoRedoDesc = "Reset translation to parent"; - static const char* const s_resetOrientationToParentUndoRedoDesc = "Reset orientation to parent"; - static const char* const s_dittoTranslationGroupUndoRedoDesc = "Ditto translation group"; - static const char* const s_dittoTranslationIndividualUndoRedoDesc = "Ditto translation individual"; - static const char* const s_dittoScaleIndividualWorldUndoRedoDesc = "Ditto scale individual world"; - static const char* const s_dittoScaleIndividualLocalUndoRedoDesc = "Ditto scale individual local"; - static const char* const s_snapToWorldGridUndoRedoDesc = "Snap to world grid"; - static const char* const s_showAllEntitiesUndoRedoDesc = s_showAllTitle; - static const char* const s_lockSelectionUndoRedoDesc = s_lockSelectionTitle; - static const char* const s_hideSelectionUndoRedoDesc = s_hideSelectionTitle; - static const char* const s_unlockAllUndoRedoDesc = s_unlockAllTitle; - static const char* const s_selectAllEntitiesUndoRedoDesc = s_selectAllTitle; - static const char* const s_invertSelectionUndoRedoDesc = s_invertSelectionTitle; - static const char* const s_duplicateUndoRedoDesc = s_duplicateTitle; - static const char* const s_deleteUndoRedoDesc = s_deleteTitle; + static const char* const TogglePivotTitleRightClick = "Toggle pivot"; + static const char* const TogglePivotTitleEditMenu = "Toggle Pivot Location"; + static const char* const TogglePivotDesc = "Toggle pivot location"; + static const char* const ManipulatorUndoRedoName = "Manipulator Adjustment"; + static const char* const LockSelectionTitle = "Lock Selection"; + static const char* const LockSelectionDesc = "Lock the selected entities so that they can't be selected in the viewport"; + static const char* const HideSelectionTitle = "Hide Selection"; + static const char* const HideSelectionDesc = "Hide the selected entities so that they don't appear in the viewport"; + static const char* const UnlockAllTitle = "Unlock All Entities"; + static const char* const UnlockAllDesc = "Unlock all entities the level"; + static const char* const ShowAllTitle = "Show All"; + static const char* const ShowAllDesc = "Show all entities so that they appear in the viewport"; + static const char* const SelectAllTitle = "Select All"; + static const char* const SelectAllDesc = "Select all entities"; + static const char* const InvertSelectionTitle = "Invert Selection"; + static const char* const InvertSelectionDesc = "Invert the current entity selection"; + static const char* const DuplicateTitle = "Duplicate"; + static const char* const DuplicateDesc = "Duplicate selected entities"; + static const char* const DeleteTitle = "Delete"; + static const char* const DeleteDesc = "Delete selected entities"; + static const char* const ResetEntityTransformTitle = "Reset Entity Transform"; + static const char* const ResetEntityTransformDesc = "Reset transform based on manipulator mode"; + static const char* const ResetManipulatorTitle = "Reset Manipulator"; + static const char* const ResetManipulatorDesc = "Reset the manipulator to recenter it on the selected entity"; + static const char* const ResetTransformLocalTitle = "Reset Transform (Local)"; + static const char* const ResetTransformLocalDesc = "Reset transform to local space"; + static const char* const ResetTransformWorldTitle = "Reset Transform (World)"; + static const char* const ResetTransformWorldDesc = "Reset transform to world space"; + + static const char* const EntityBoxSelectUndoRedoDesc = "Box Select Entities"; + static const char* const EntityDeselectUndoRedoDesc = "Deselect Entity"; + static const char* const EntitiesDeselectUndoRedoDesc = "Deselect Entities"; + static const char* const ChangeEntitySelectionUndoRedoDesc = "Change Selected Entity"; + static const char* const EntitySelectUndoRedoDesc = "Select Entity"; + static const char* const DittoManipulatorUndoRedoDesc = "Ditto Manipulator"; + static const char* const ResetManipulatorTranslationUndoRedoDesc = "Reset Manipulator Translation"; + static const char* const ResetManipulatorOrientationUndoRedoDesc = "Reset Manipulator Orientation"; + static const char* const DittoEntityOrientationIndividualUndoRedoDesc = "Ditto orientation individual"; + static const char* const DittoEntityOrientationGroupUndoRedoDesc = "Ditto orientation group"; + static const char* const ResetTranslationToParentUndoRedoDesc = "Reset translation to parent"; + static const char* const ResetOrientationToParentUndoRedoDesc = "Reset orientation to parent"; + static const char* const DittoTranslationGroupUndoRedoDesc = "Ditto translation group"; + static const char* const DittoTranslationIndividualUndoRedoDesc = "Ditto translation individual"; + static const char* const DittoScaleIndividualWorldUndoRedoDesc = "Ditto scale individual world"; + static const char* const DittoScaleIndividualLocalUndoRedoDesc = "Ditto scale individual local"; + static const char* const SnapToWorldGridUndoRedoDesc = "Snap to world grid"; + static const char* const ShowAllEntitiesUndoRedoDesc = ShowAllTitle; + static const char* const LockSelectionUndoRedoDesc = LockSelectionTitle; + static const char* const HideSelectionUndoRedoDesc = HideSelectionTitle; + static const char* const UnlockAllUndoRedoDesc = UnlockAllTitle; + static const char* const SelectAllEntitiesUndoRedoDesc = SelectAllTitle; + static const char* const InvertSelectionUndoRedoDesc = InvertSelectionTitle; + static const char* const DuplicateUndoRedoDesc = DuplicateTitle; + static const char* const DeleteUndoRedoDesc = DeleteTitle; static const char* const TransformModeClusterTranslateTooltip = "Switch to translate mode"; static const char* const TransformModeClusterRotateTooltip = "Switch to rotate mode"; @@ -148,14 +149,14 @@ namespace AzToolsFramework static const char* const SpaceClusterLocalTooltip = "Toggle local space lock"; static const char* const SnappingClusterSnapToWorldTooltip = "Snap selected entities to the world space grid"; - static const AZ::Color s_fadedXAxisColor = AZ::Color(AZ::u8(200), AZ::u8(127), AZ::u8(127), AZ::u8(255)); - static const AZ::Color s_fadedYAxisColor = AZ::Color(AZ::u8(127), AZ::u8(190), AZ::u8(127), AZ::u8(255)); - static const AZ::Color s_fadedZAxisColor = AZ::Color(AZ::u8(120), AZ::u8(120), AZ::u8(180), AZ::u8(255)); + static const AZ::Color FadedXAxisColor = AZ::Color(AZ::u8(200), AZ::u8(127), AZ::u8(127), AZ::u8(255)); + static const AZ::Color FadedYAxisColor = AZ::Color(AZ::u8(127), AZ::u8(190), AZ::u8(127), AZ::u8(255)); + static const AZ::Color FadedZAxisColor = AZ::Color(AZ::u8(120), AZ::u8(120), AZ::u8(180), AZ::u8(255)); - static const AZ::Color s_pickedOrientationColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f); - static const AZ::Color s_selectedEntityAabbColor = AZ::Color(0.6f, 0.6f, 0.6f, 0.4f); + static const AZ::Color PickedOrientationColor = AZ::Color(0.0f, 1.0f, 0.0f, 1.0f); + static const AZ::Color SelectedEntityAabbColor = AZ::Color(0.6f, 0.6f, 0.6f, 0.4f); - static const float s_pivotSize = 0.075f; // the size of the pivot (box) to render when selected + static const float PivotSize = 0.075f; // the size of the pivot (box) to render when selected // data passed to manipulators when processing mouse interactions // m_entityIds should be sorted based on the entity hierarchy @@ -1107,7 +1108,7 @@ namespace AzToolsFramework { // begin selection undo/redo command entityBoxSelectData->m_boxSelectSelectionCommand = - AZStd::make_unique(EntityIdList(), s_entityBoxSelectUndoRedoDesc); + AZStd::make_unique(EntityIdList(), EntityBoxSelectUndoRedoDesc); // grab currently selected entities entityBoxSelectData->m_selectedEntityIdsBeforeBoxSelect = m_selectedEntityIds; }); @@ -1131,7 +1132,7 @@ namespace AzToolsFramework if (!entityBoxSelectData->m_potentialDeselectedEntityIds.empty() || !entityBoxSelectData->m_potentialSelectedEntityIds.empty()) { - ScopedUndoBatch undoBatch(s_entityBoxSelectUndoRedoDesc); + ScopedUndoBatch undoBatch(EntityBoxSelectUndoRedoDesc); // restore manipulator overrides when undoing if (m_entityIdManipulators.m_manipulators && m_selectedEntityIds.empty()) @@ -1174,7 +1175,7 @@ namespace AzToolsFramework } debugDisplay.DepthTestOff(); - debugDisplay.SetColor(s_selectedEntityAabbColor); + debugDisplay.SetColor(SelectedEntityAabbColor); for (AZ::EntityId entityId : entityBoxSelectData->m_potentialSelectedEntityIds) { @@ -1222,7 +1223,7 @@ namespace AzToolsFramework { // check here if translation or orientation override are set m_manipulatorMoveCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); } } @@ -1696,7 +1697,7 @@ namespace AzToolsFramework if (!UndoRedoOperationInProgress()) { - ScopedUndoBatch undoBatch(s_entitiesDeselectUndoRedoDesc); + ScopedUndoBatch undoBatch(EntitiesDeselectUndoRedoDesc); // restore manipulator overrides when undoing if (m_entityIdManipulators.m_manipulators) @@ -1706,7 +1707,7 @@ namespace AzToolsFramework // select must happen after to ensure in the undo/redo step the selection command // happens before the manipulator command - auto selectionCommand = AZStd::make_unique(EntityIdList(), s_entitiesDeselectUndoRedoDesc); + auto selectionCommand = AZStd::make_unique(EntityIdList(), EntitiesDeselectUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); selectionCommand.release(); } @@ -1732,7 +1733,7 @@ namespace AzToolsFramework const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds); - ScopedUndoBatch undoBatch(s_entityDeselectUndoRedoDesc); + ScopedUndoBatch undoBatch(EntityDeselectUndoRedoDesc); // store manipulator state when removing last entity from selection if (m_entityIdManipulators.m_manipulators && nextEntityIds.empty()) @@ -1740,7 +1741,7 @@ namespace AzToolsFramework CreateEntityManipulatorDeselectCommand(undoBatch); } - auto selectionCommand = AZStd::make_unique(nextEntityIds, s_entityDeselectUndoRedoDesc); + auto selectionCommand = AZStd::make_unique(nextEntityIds, EntityDeselectUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); selectionCommand.release(); @@ -1755,8 +1756,8 @@ namespace AzToolsFramework const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds); - ScopedUndoBatch undoBatch(s_entitySelectUndoRedoDesc); - auto selectionCommand = AZStd::make_unique(nextEntityIds, s_entitySelectUndoRedoDesc); + ScopedUndoBatch undoBatch(EntitySelectUndoRedoDesc); + auto selectionCommand = AZStd::make_unique(nextEntityIds, EntitySelectUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); selectionCommand.release(); @@ -1772,6 +1773,13 @@ namespace AzToolsFramework void EditorTransformComponentSelection::ChangeSelectedEntity(const AZ::EntityId entityId) { + AZ_Assert( + !UndoRedoOperationInProgress(), + "ChangeSelectedEntity called from undo/redo operation - this is unexpected and not currently supported"); + + // ensure deselect/select is tracked as an atomic undo/redo operation + ScopedUndoBatch undoBatch(ChangeEntitySelectionUndoRedoDesc); + DeselectEntities(); SelectDeselect(entityId); } @@ -1799,7 +1807,7 @@ namespace AzToolsFramework const AZ::Transform& worldFromLocal = m_entityDataCache->GetVisibleEntityTransform(*entityIndex); const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode)); const AZ::Vector3 scaledSize = - AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState); + AZ::Vector3(PivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState); if (AabbIntersectMouseRay( mouseInteraction.m_mouseInteraction, @@ -2002,10 +2010,10 @@ namespace AzToolsFramework { if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch(s_dittoManipulatorUndoRedoDesc); + ScopedUndoBatch undoBatch(DittoManipulatorUndoRedoDesc); auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); if (entityId.IsValid()) { @@ -2131,7 +2139,7 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_lockSelectionUndoRedoDesc); + ScopedUndoBatch undoBatch(LockSelectionUndoRedoDesc); if (m_entityIdManipulators.m_manipulators) { @@ -2151,7 +2159,7 @@ namespace AzToolsFramework // lock selection AddAction( - m_actions, { QKeySequence(Qt::Key_L) }, LockSelection, s_lockSelectionTitle, s_lockSelectionDesc, + m_actions, { QKeySequence(Qt::Key_L) }, LockSelection, LockSelectionTitle, LockSelectionDesc, [lockUnlock]() { lockUnlock(true); @@ -2159,7 +2167,7 @@ namespace AzToolsFramework // unlock selection AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::Key_L) }, UnlockSelection, s_lockSelectionTitle, s_lockSelectionDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::Key_L) }, UnlockSelection, LockSelectionTitle, LockSelectionDesc, [lockUnlock]() { lockUnlock(false); @@ -2169,7 +2177,7 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_hideSelectionUndoRedoDesc); + ScopedUndoBatch undoBatch(HideSelectionUndoRedoDesc); if (m_entityIdManipulators.m_manipulators) { @@ -2189,7 +2197,7 @@ namespace AzToolsFramework // hide selection AddAction( - m_actions, { QKeySequence(Qt::Key_H) }, HideSelection, s_hideSelectionTitle, s_hideSelectionDesc, + m_actions, { QKeySequence(Qt::Key_H) }, HideSelection, HideSelectionTitle, HideSelectionDesc, [showHide]() { showHide(false); @@ -2197,7 +2205,7 @@ namespace AzToolsFramework // show selection AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::Key_H) }, ShowSelection, s_hideSelectionTitle, s_hideSelectionDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::Key_H) }, ShowSelection, HideSelectionTitle, HideSelectionDesc, [showHide]() { showHide(true); @@ -2205,12 +2213,12 @@ namespace AzToolsFramework // unlock all entities in the level/scene AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_L) }, UnlockAll, s_unlockAllTitle, s_unlockAllDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_L) }, UnlockAll, UnlockAllTitle, UnlockAllDesc, []() { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_unlockAllUndoRedoDesc); + ScopedUndoBatch undoBatch(UnlockAllUndoRedoDesc); EnumerateEditorEntities( [](AZ::EntityId entityId) @@ -2222,12 +2230,12 @@ namespace AzToolsFramework // show all entities in the level/scene AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_H) }, ShowAll, s_showAllTitle, s_showAllDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_H) }, ShowAll, ShowAllTitle, ShowAllDesc, []() { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_showAllEntitiesUndoRedoDesc); + ScopedUndoBatch undoBatch(ShowAllEntitiesUndoRedoDesc); EnumerateEditorEntities( [](AZ::EntityId entityId) @@ -2239,17 +2247,17 @@ namespace AzToolsFramework // select all entities in the level/scene AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::Key_A) }, SelectAll, s_selectAllTitle, s_selectAllDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::Key_A) }, SelectAll, SelectAllTitle, SelectAllDesc, [this]() { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_selectAllEntitiesUndoRedoDesc); + ScopedUndoBatch undoBatch(SelectAllEntitiesUndoRedoDesc); if (m_entityIdManipulators.m_manipulators) { auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); // note, nothing will change that the manipulatorCommand needs to keep track // for after so no need to call SetManipulatorAfter @@ -2269,7 +2277,7 @@ namespace AzToolsFramework auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds); - auto selectionCommand = AZStd::make_unique(nextEntityIds, s_selectAllEntitiesUndoRedoDesc); + auto selectionCommand = AZStd::make_unique(nextEntityIds, SelectAllEntitiesUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); selectionCommand.release(); @@ -2279,17 +2287,17 @@ namespace AzToolsFramework // invert current selection AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I) }, InvertSelect, s_invertSelectionTitle, s_invertSelectionDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I) }, InvertSelect, InvertSelectionTitle, InvertSelectionDesc, [this]() { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_invertSelectionUndoRedoDesc); + ScopedUndoBatch undoBatch(InvertSelectionUndoRedoDesc); if (m_entityIdManipulators.m_manipulators) { auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); // note, nothing will change that the manipulatorCommand needs to keep track // for after so no need to call SetManipulatorAfter @@ -2316,7 +2324,7 @@ namespace AzToolsFramework auto nextEntityIds = EntityIdVectorFromContainer(entityIds); - auto selectionCommand = AZStd::make_unique(nextEntityIds, s_invertSelectionUndoRedoDesc); + auto selectionCommand = AZStd::make_unique(nextEntityIds, InvertSelectionUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); selectionCommand.release(); @@ -2326,7 +2334,7 @@ namespace AzToolsFramework // duplicate selection AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::Key_D) }, DuplicateSelect, s_duplicateTitle, s_duplicateDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::Key_D) }, DuplicateSelect, DuplicateTitle, DuplicateDesc, []() { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -2338,8 +2346,8 @@ namespace AzToolsFramework QApplication::focusWidget()->clearFocus(); } - ScopedUndoBatch undoBatch(s_duplicateUndoRedoDesc); - auto selectionCommand = AZStd::make_unique(EntityIdList(), s_duplicateUndoRedoDesc); + ScopedUndoBatch undoBatch(DuplicateUndoRedoDesc); + auto selectionCommand = AZStd::make_unique(EntityIdList(), DuplicateUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); selectionCommand.release(); @@ -2351,12 +2359,12 @@ namespace AzToolsFramework // delete selection AddAction( - m_actions, { QKeySequence(Qt::Key_Delete) }, DeleteSelect, s_deleteTitle, s_deleteDesc, + m_actions, { QKeySequence(Qt::Key_Delete) }, DeleteSelect, DeleteTitle, DeleteDesc, [this]() { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_deleteUndoRedoDesc); + ScopedUndoBatch undoBatch(DeleteUndoRedoDesc); CreateEntityManipulatorDeselectCommand(undoBatch); @@ -2375,14 +2383,14 @@ namespace AzToolsFramework }); AddAction( - m_actions, { QKeySequence(Qt::Key_P) }, EditPivot, s_togglePivotTitleEditMenu, s_togglePivotDesc, + m_actions, { QKeySequence(Qt::Key_P) }, EditPivot, TogglePivotTitleEditMenu, TogglePivotDesc, [this]() { ToggleCenterPivotSelection(); }); AddAction( - m_actions, { QKeySequence(Qt::Key_R) }, EditReset, s_resetEntityTransformTitle, s_resetEntityTransformDesc, + m_actions, { QKeySequence(Qt::Key_R) }, EditReset, ResetEntityTransformTitle, ResetEntityTransformDesc, [this]() { switch (m_mode) @@ -2400,11 +2408,11 @@ namespace AzToolsFramework }); AddAction( - m_actions, { QKeySequence(Qt::CTRL + Qt::Key_R) }, EditResetManipulator, s_resetManipulatorTitle, s_resetManipulatorDesc, + m_actions, { QKeySequence(Qt::CTRL + Qt::Key_R) }, EditResetManipulator, ResetManipulatorTitle, ResetManipulatorDesc, AZStd::bind(AZStd::mem_fn(&EditorTransformComponentSelection::DelegateClearManipulatorOverride), this)); AddAction( - m_actions, { QKeySequence(Qt::ALT + Qt::Key_R) }, EditResetLocal, s_resetTransformLocalTitle, s_resetTransformLocalDesc, + m_actions, { QKeySequence(Qt::ALT + Qt::Key_R) }, EditResetLocal, ResetTransformLocalTitle, ResetTransformLocalDesc, [this]() { switch (m_mode) @@ -2422,7 +2430,7 @@ namespace AzToolsFramework }); AddAction( - m_actions, { QKeySequence(Qt::SHIFT + Qt::Key_R) }, EditResetWorld, s_resetTransformWorldTitle, s_resetTransformWorldDesc, + m_actions, { QKeySequence(Qt::SHIFT + Qt::Key_R) }, EditResetWorld, ResetTransformWorldTitle, ResetTransformWorldDesc, [this]() { switch (m_mode) @@ -2431,7 +2439,7 @@ namespace AzToolsFramework { // begin an undo batch so operations inside CopyOrientation... and // DelegateClear... are grouped into a single undo/redo - ScopedUndoBatch undoBatch{ s_resetTransformWorldTitle }; + ScopedUndoBatch undoBatch{ ResetTransformWorldTitle }; CopyOrientationToSelectedEntitiesIndividual(AZ::Quaternion::CreateIdentity()); ClearManipulatorOrientationOverride(); } @@ -2685,7 +2693,7 @@ namespace AzToolsFramework const AZStd::array snapAxes = { AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ() }; - ScopedUndoBatch undoBatch(s_snapToWorldGridUndoRedoDesc); + ScopedUndoBatch undoBatch(SnapToWorldGridUndoRedoDesc); for (const AZ::EntityId& entityId : m_selectedEntityIds) { ScopedUndoBatch::MarkEntityDirty(entityId); @@ -2870,10 +2878,10 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch(s_resetManipulatorTranslationUndoRedoDesc); + ScopedUndoBatch undoBatch(ResetManipulatorTranslationUndoRedoDesc); auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); m_pivotOverrideFrame.ResetPickedTranslation(); m_pivotOverrideFrame.m_pickedEntityIdOverride.SetInvalid(); @@ -2896,10 +2904,10 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch{ s_resetManipulatorOrientationUndoRedoDesc }; + ScopedUndoBatch undoBatch{ ResetManipulatorOrientationUndoRedoDesc }; auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); m_pivotOverrideFrame.ResetPickedOrientation(); m_pivotOverrideFrame.m_pickedEntityIdOverride.SetInvalid(); @@ -2961,13 +2969,13 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch(s_dittoTranslationGroupUndoRedoDesc); + ScopedUndoBatch undoBatch(DittoTranslationGroupUndoRedoDesc); // store previous translation manipulator position const AZ::Vector3 previousPivotTranslation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation(); auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); // refresh the transform pivot override if it's set if (m_pivotOverrideFrame.m_translationOverride) @@ -3017,10 +3025,10 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch(s_dittoTranslationIndividualUndoRedoDesc); + ScopedUndoBatch undoBatch(DittoTranslationIndividualUndoRedoDesc); auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); // refresh the transform pivot override if it's set if (m_pivotOverrideFrame.m_translationOverride) @@ -3055,7 +3063,7 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_dittoScaleIndividualWorldUndoRedoDesc); + ScopedUndoBatch undoBatch(DittoScaleIndividualWorldUndoRedoDesc); ManipulatorEntityIds manipulatorEntityIds; BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds.m_entityIds); @@ -3089,7 +3097,7 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_dittoScaleIndividualLocalUndoRedoDesc); + ScopedUndoBatch undoBatch(DittoScaleIndividualLocalUndoRedoDesc); ManipulatorEntityIds manipulatorEntityIds; BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds.m_entityIds); @@ -3110,10 +3118,10 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch{ s_dittoEntityOrientationIndividualUndoRedoDesc }; + ScopedUndoBatch undoBatch{ DittoEntityOrientationIndividualUndoRedoDesc }; auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); ManipulatorEntityIds manipulatorEntityIds; BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds.m_entityIds); @@ -3148,10 +3156,10 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch(s_dittoEntityOrientationGroupUndoRedoDesc); + ScopedUndoBatch undoBatch(DittoEntityOrientationGroupUndoRedoDesc); auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); ManipulatorEntityIds manipulatorEntityIds; BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds.m_entityIds); @@ -3194,7 +3202,7 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); - ScopedUndoBatch undoBatch(s_resetOrientationToParentUndoRedoDesc); + ScopedUndoBatch undoBatch(ResetOrientationToParentUndoRedoDesc); for (const auto& entityIdLookup : m_entityIdManipulators.m_lookups) { ScopedUndoBatch::MarkEntityDirty(entityIdLookup.first); @@ -3215,7 +3223,7 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { - ScopedUndoBatch undoBatch(s_resetTranslationToParentUndoRedoDesc); + ScopedUndoBatch undoBatch(ResetTranslationToParentUndoRedoDesc); ManipulatorEntityIds manipulatorEntityIds; BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds.m_entityIds); @@ -3251,7 +3259,7 @@ namespace AzToolsFramework void EditorTransformComponentSelection::PopulateEditorGlobalContextMenu( QMenu* menu, [[maybe_unused]] const AZ::Vector2& point, [[maybe_unused]] int flags) { - QAction* action = menu->addAction(QObject::tr(s_togglePivotTitleRightClick)); + QAction* action = menu->addAction(QObject::tr(TogglePivotTitleRightClick)); QObject::connect( action, &QAction::triggered, action, [this]() @@ -3329,15 +3337,15 @@ namespace AzToolsFramework : 1.0f; }; - display.SetColor(s_fadedXAxisColor); + display.SetColor(FadedXAxisColor); display.DrawLine( transform.GetTranslation(), transform.GetTranslation() + transform.GetBasisX().GetNormalizedSafe() * axisLength * axisFlip(AZ::Vector3::CreateAxisX())); - display.SetColor(s_fadedYAxisColor); + display.SetColor(FadedYAxisColor); display.DrawLine( transform.GetTranslation(), transform.GetTranslation() + transform.GetBasisY().GetNormalizedSafe() * axisLength * axisFlip(AZ::Vector3::CreateAxisY())); - display.SetColor(s_fadedZAxisColor); + display.SetColor(FadedZAxisColor); display.DrawLine( transform.GetTranslation(), transform.GetTranslation() + transform.GetBasisZ().GetNormalizedSafe() * axisLength * axisFlip(AZ::Vector3::CreateAxisZ())); @@ -3416,11 +3424,11 @@ namespace AzToolsFramework CalculatePivotTranslation(m_pivotOverrideFrame.m_pickedEntityIdOverride, m_pivotMode)); const float scaledSize = - s_pivotSize * CalculateScreenToWorldMultiplier(pickedEntityWorldTransform.GetTranslation(), cameraState); + PivotSize * CalculateScreenToWorldMultiplier(pickedEntityWorldTransform.GetTranslation(), cameraState); debugDisplay.DepthWriteOff(); debugDisplay.DepthTestOff(); - debugDisplay.SetColor(s_pickedOrientationColor); + debugDisplay.SetColor(PickedOrientationColor); debugDisplay.DrawWireSphere(pickedEntityWorldTransform.GetTranslation(), scaledSize); @@ -3462,7 +3470,7 @@ namespace AzToolsFramework const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode)); const AZ::Vector3 scaledSize = - AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState); + AZ::Vector3(PivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState); const AZ::Color hiddenNormal[] = { AzFramework::ViewportColors::SelectedColor, AzFramework::ViewportColors::HiddenColor }; @@ -3708,7 +3716,7 @@ namespace AzToolsFramework if (m_entityIdManipulators.m_manipulators) { auto manipulatorCommand = - AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), s_manipulatorUndoRedoName); + AZStd::make_unique(CreateManipulatorCommandStateFromSelf(), ManipulatorUndoRedoName); manipulatorCommand->SetManipulatorAfter(EntityManipulatorCommand::State()); diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index 241ee3f576..72cafe5cd5 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -866,9 +866,7 @@ namespace UnitTest EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1)); } - TEST_F( - EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, - BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) { AzToolsFramework::ed_viewportStickySelect = true; @@ -989,6 +987,30 @@ namespace UnitTest EXPECT_TRUE(selectedEntitiesAfter.empty()); } + TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickyUndoOperationForChangeInSelectionIsAtomic) + { + AzToolsFramework::ed_viewportStickySelect = false; + + PositionEntities(); + PositionCamera(m_cameraState); + + AzToolsFramework::SelectEntity(m_entityId1); + + // calculate the position in screen space of the second entity + const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); + + // single click select entity2 + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + + // undo action + AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::UndoPressed); + + // entity1 is selected after undo + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = SelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1)); + } + using EditorTransformComponentSelectionManipulatorTestFixture = IndirectCallManipulatorViewportInteractionFixtureMixin; From 169b8f36793f93d0dcab7902f736617b1952cd4c Mon Sep 17 00:00:00 2001 From: galibzon <66021303+galibzon@users.noreply.github.com> Date: Wed, 15 Sep 2021 07:50:14 -0500 Subject: [PATCH 128/274] [ATOM-5441] Shader Builders May Fail When Multiple New Files Are Added (#3862) * [ATOM-5441] Shader Builders May Fail When Multiple New Files Are Added ShaderAssetBuilder::CreateJobs now recursively parses *.azsl files looking for #include lines and builds the list of source dependencies using a depth-first algorithm. It was using MCPP before but not anymore (during CreateJobs). The new algorithm may over prescribe, but fixes the issues when multiple new shader related files are added, at once or out of order, to a game project or Gem. Overall the new ShaderAssetBuilder::CreateJobs() is around 40% faster and, of course, handles source dependencies in a robust way. * Added new test suite to AutomatedTesting project: Gem/PythonTests/atom_renderer/test_Atom_ShaderBuildPipelineSuite.py Bug fix to Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp discovered thanks to the automated test suite. The idea is that CreateJobs doesn't fail if the AZSL file doesn't exist. The failure is deferred during ProcessJob. This way if the AZSL file exists the .shader file is rebuilt automatically. * For testability purposes and avoid memory leakage errors during Unit Tests created the class ShaderBuilderUtility::IncludedFilesParser Now accepts "# include " with space between '#' and 'include'. Also now accepts the '-' character inside the file path. Added Unit Test to validate all cases of "#include " parsing. * Fixed linux runtime issues for Unit Tests in Atom_Asset_Shader.Tests Signed-off-by: garrieta --- .../PythonTests/atom_renderer/CMakeLists.txt | 11 + .../DependencyValidation.azsl.txt | 55 +++++ .../DependencyValidation.shader.txt | 26 +++ .../ShaderAssetBuilder/Test1Color.azsli.txt | 18 ++ .../ShaderAssetBuilder/Test2Color.azsli.txt | 16 ++ .../ShaderAssetBuilder/Test3Color.azsli.txt | 16 ++ ...pilesShaderAsChainOfDependenciesChanges.py | 188 ++++++++++++++++++ .../test_Atom_ShaderBuildPipelineSuite.py | 19 ++ Gems/Atom/Asset/Shader/Code/CMakeLists.txt | 1 + .../Code/Source/Editor/ShaderAssetBuilder.cpp | 136 ++++++++++--- .../Source/Editor/ShaderBuilderUtility.cpp | 46 +++++ .../Code/Source/Editor/ShaderBuilderUtility.h | 23 +++ .../Code/Tests/ShaderBuilderUtilityTests.cpp | 86 ++++++++ ...om_asset_shader_builders_tests_files.cmake | 1 + .../PostProcessing/FastDepthAwareBlurHor.azsl | 2 +- .../PostProcessing/FastDepthAwareBlurVer.azsl | 2 +- .../Assets/Shaders/PostProcessing/SMAA.azsli | 2 +- 17 files changed, 622 insertions(+), 26 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_ShaderBuildPipelineSuite.py create mode 100644 Gems/Atom/Asset/Shader/Code/Tests/ShaderBuilderUtilityTests.cpp diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt index f056623ecd..992420904c 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt @@ -46,4 +46,15 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT AutomatedTesting.Assets Editor ) + ly_add_pytest( + NAME AutomatedTesting::AtomRenderer_HydraTests_ShaderBuildPipeline + TEST_SUITE main + PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_ShaderBuildPipelineSuite.py + TEST_SERIAL + TIMEOUT 600 + RUNTIME_DEPENDENCIES + AssetProcessor + AutomatedTesting.Assets + Editor + ) endif() diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt new file mode 100644 index 0000000000..c0b64f40b7 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + /* + This is a dummy shader used to validate detection of "#included files" + */ + +#include + +#include "Test1Color.azsli" +#include + +ShaderResourceGroup DummySrg : SRG_PerDraw +{ + float4 m_color; +} + +struct VSInput +{ + float3 m_position : POSITION; + float4 m_color : COLOR0; +}; + +struct VSOutput +{ + float4 m_position : SV_Position; + float4 m_color : COLOR0; +}; + +VSOutput MainVS(VSInput vsInput) +{ + VSOutput OUT; + OUT.m_position = float4(vsInput.m_position, 1.0); + OUT.m_color = vsInput.m_color; + return OUT; +} + +struct PSOutput +{ + float4 m_color : SV_Target0; +}; + +PSOutput MainPS(VSOutput vsOutput) +{ + PSOutput OUT; + + OUT.m_color = GetTest1Color(DummySrg::m_color) + GetTest3Color(DummySrg::m_color); + + return OUT; +} diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt new file mode 100644 index 0000000000..b0eac1783e --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt @@ -0,0 +1,26 @@ +// This is a dummy shader used to validate detection of "#included files" +{ + "Source" : "DependencyValidation.azsl", + + "DepthStencilState" : { + "Depth" : { "Enable" : false, "CompareFunc" : "GreaterEqual" } + }, + + "DrawList" : "forward", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } + +} diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt new file mode 100644 index 0000000000..7d097beafb --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt @@ -0,0 +1,18 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + /* + This is a dummy shader used to validate detection of "#included files" + */ + +#include "Test2Color.azsli" + +float4 GetTest1Color(float4 color) +{ + return color + GetTest2Color(color); +} diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt new file mode 100644 index 0000000000..2ef946b947 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt @@ -0,0 +1,16 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + /* + This is a dummy shader used to validate detection of "#included files" + */ + +float4 GetTest2Color(float4 color) +{ + return color * 0.5; +} diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt new file mode 100644 index 0000000000..73b0cca434 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt @@ -0,0 +1,16 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + + /* + This is a dummy shader used to validate detection of "#included files" + */ + +float4 GetTest3Color(float4 color) +{ + return color * 0.13; +} diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py new file mode 100644 index 0000000000..a05420d960 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py @@ -0,0 +1,188 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +""" + +import os +import shutil + +def _copy_file(src_file, src_path, target_file, target_path): + # type: (str, str, str, str) -> None + """ + Copies the [src_file] located in [src_path] to the [target_file] located at [target_path]. + Leaves the [target_file] unlocked for reading and writing privileges + :param src_file: The source file to copy (file name) + :param src_path: The source file's path + :param target_file: The target file to copy into (file name) + :param target_path: The target file's path + :return: None + """ + target_file_path = os.path.join(target_path, target_file) + src_file_path = os.path.join(src_path, src_file) + if os.path.exists(target_file_path): + fs.unlock_file(target_file_path) + shutil.copyfile(src_file_path, target_file_path) + +def _copy_tmp_files_in_order(src_directory, file_list, dst_directory, wait_time_in_between = 0.0): + # type: (str, list, str, float) -> None + """ + This function assumes that for each file name listed in @file_list + there's file named "@filename.txt" which the original source file + but they will be copied with just the @filename (.txt removed). + """ + for filename in file_list: + src_name = f"{filename}.txt" + _copy_file(src_name, src_directory, filename, dst_directory) + if wait_time_in_between > 0.0: + print(f"Created {filename} in {dst_directory}") + general.idle_wait(wait_time_in_between) + + +def _remove_file(src_file, src_path): + # type: (str, str) -> None + """ + Removes the [src_file] located in [src_path]. + :param src_file: The source file to copy (file name) + :param src_path: The source file's path + :return: None + """ + src_file_path = os.path.join(src_path, src_file) + if os.path.exists(src_file_path): + fs.unlock_file(src_file_path) + os.remove(src_file_path) + + +def _remove_files(directory, file_list): + for filename in file_list: + _remove_file(filename, directory) + + +def _asset_exists(cache_relative_path): + asset_id = azasset.AssetCatalogRequestBus(azbus.Broadcast, "GetAssetIdByPath", cache_relative_path, azmath.Uuid(), False) + return asset_id.is_valid() + +# List of results that we want to check, this is not 100% necessary but it's a good +# practice to make it easier to debug tests. +# Here we define a tuple of tests +class Results(): + azshader_was_removed = ("azshader was removed", "Failed to remove azshader") + azshader_was_compiled = ("azshader was compiled", "Failed to compile azshader") + + +def ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(): + """ + This test validates [ATOM-5441] Shader Builders May Fail When Multiple New Files Are Added + It creates source assets to compile a particular shader. + 1- The first phase generates the source assets out of order and slowly. The AP should + wakeup each time one of the source dependencies appears but will fail each time. Only when the + last dependency appears then the shader should build successfully. + 2- The second phase is similar as above, except that all source assets will be created + at once and We also expect that in the end the shader is built successfully. + """ + # Required for automated tests + helper.init_idle() + + game_root_path = os.path.normpath(general.get_game_folder()) + game_asset_path = os.path.join(game_root_path, "Assets") + + base_dir = os.path.dirname(__file__) + src_assets_subdir = os.path.join(base_dir, "TestAssets", "ShaderAssetBuilder") + + with Tracer() as error_tracer: + # The script drives the execution of the test, to return the flow back to the editor, + # we will tick it one time + general.idle_wait_frames(1) + + # This is the order in which the source assets should be deployed + # to avoid source dependency issues with the old MCPP-based CreateJobs. + file_list = [ + "Test2Color.azsli", + "Test3Color.azsli", + "Test1Color.azsli", + "DependencyValidation.azsl", + "DependencyValidation.shader" + ] + + reverse_file_list = file_list[::-1] + + # Remove files in reverse order + _remove_files(game_asset_path, reverse_file_list) + + # Wait here until the azshader doesn't exist anymore. + azshader_name = "assets/dependencyvalidation.azshader" + helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0) + + Report.critical_result(Results.azshader_was_removed, not _asset_exists(azshader_name)) + + _copy_tmp_files_in_order(src_assets_subdir, file_list, game_asset_path, 1.0) + + # Give enough time to AP to compile the shader + helper.wait_for_condition(lambda: _asset_exists(azshader_name), 60.0) + + Report.critical_result(Results.azshader_was_compiled, _asset_exists(azshader_name)) + + # The first part was about compiling the shader under normal conditions. + # Let's remove the files from the previous phase and will proceed + # to make the source files visible to the AP in reverse order. The + # ShaderAssetBuilder will only succeed when the last file becomes visible. + _remove_files(game_asset_path, reverse_file_list) + helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0) + Report.critical_result(Results.azshader_was_removed, not _asset_exists(azshader_name)) + + # Remark, if you are running this test manually from the Editor with "pyRunFile", + # You'll notice how the AP issues notifications that it fails to compile the shader + # as the source files are being copied to the "Assets" subfolder. + # Those errors are OK and also expected because We need the AP to wake up as each + # reported source dependency exists. Once the last file is copied then all source + # dependencies are fully satisfied and the shader should compile successfully. + # And this summarizes the importance of this Test: The previous version + # of ShaderAssetBuilder::CreateJobs was incapable of compiling the shader under the conditions + # presented in this test, but with the new version of ShaderAssetBuilder::CreateJobs, which + # doesn't use MCPP for #include files discovery, it should eventually compile the shader + # once all the source files are in place. + _copy_tmp_files_in_order(src_assets_subdir, reverse_file_list, game_asset_path, 3.0) + + # Give enough time to AP to compile the shader + helper.wait_for_condition(lambda: _asset_exists(azshader_name), 60.0) + + Report.critical_result(Results.azshader_was_compiled, _asset_exists(azshader_name)) + + # The last phase of the test puts stress on potential race conditions + # when all required files appear as soon as possible. + + # First Clean up. + # Remove left over files. + _remove_files(game_asset_path, reverse_file_list) + helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0) + Report.critical_result(Results.azshader_was_removed, not _asset_exists(azshader_name)) + + # Now let's copy all the source files to the "Assets" folder as fast as possible. + _copy_tmp_files_in_order(src_assets_subdir, reverse_file_list, game_asset_path) + + # Give enough time to AP to compile the shader + helper.wait_for_condition(lambda: _asset_exists(azshader_name), 60.0) + + Report.critical_result(Results.azshader_was_compiled, _asset_exists(azshader_name)) + + # All good, let's cleanup leftover files before closing the test. + _remove_files(game_asset_path, reverse_file_list) + helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0) + + +if __name__ == "__main__": + # All exposed python bindings are in azlmbr + import azlmbr.legacy.general as general + import azlmbr.bus as azbus + import azlmbr.asset as azasset + import azlmbr.math as azmath + + # Import report and test helper utilities + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer + import ly_test_tools.environment.file_system as fs + + Report.start_test(ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges) \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_ShaderBuildPipelineSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_ShaderBuildPipelineSuite.py new file mode 100644 index 0000000000..9ef93ea238 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_ShaderBuildPipelineSuite.py @@ -0,0 +1,19 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT + +Main suite tests for the Shader Build Pipeline. +""" +import pytest +from ly_test_tools import LAUNCHERS +from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest + +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +@pytest.mark.parametrize("launcher_platform", ['windows_editor']) +class TestShaderBuildPipelineMain(EditorTestSuite): + """Holds tests for Shader Build Pipeline validation""" + + class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSingleTest): + from .atom_hydra_scripts import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module \ No newline at end of file diff --git a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt index c0bdfd4a8b..efbedb0a38 100644 --- a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt @@ -65,6 +65,7 @@ ly_add_target( AZ::AzFramework AZ::AzToolsFramework Gem::Atom_RHI.Edit + Gem::Atom_RPI.Edit Gem::Atom_RPI.Public ) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp index 6673da2be3..2babba1ecc 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderAssetBuilder.cpp @@ -61,10 +61,99 @@ namespace AZ static constexpr char ShaderAssetBuilderName[] = "ShaderAssetBuilder"; static constexpr uint32_t ShaderAssetBuildTimestampParam = 0; + //! The search will start in @currentFolderPath. + //! if the file is not found then it searches in order of appearence in @includeDirectories. + //! If the search yields no existing file it returns an empty string. + static AZStd::string DiscoverFullPath(AZStd::string_view normalizedRelativePath, AZStd::string_view currentFolderPath, const AZStd::vector& includeDirectories) + { + AZStd::string fullPath; + AzFramework::StringFunc::Path::Join(currentFolderPath.data(), normalizedRelativePath.data(), fullPath); + if (AZ::IO::SystemFile::Exists(fullPath.c_str())) + { + return fullPath; + } + + for (const auto &includeDir : includeDirectories) + { + AzFramework::StringFunc::Path::Join(includeDir.c_str(), normalizedRelativePath.data(), fullPath); + if (AZ::IO::SystemFile::Exists(fullPath.c_str())) + { + return fullPath; + } + } + + return ""; + } + + // Appends to @includedFiles normalized paths of possible future locations of the file @normalizedRelativePath. + // The future locations are each directory listed in @includeDirectories joined with @normalizedRelativePath. + // This function is called when an included file doesn't exist but We need to declare source dependency so a .shader + // asset is rebuilt when the missing file appears in the future. + static void AppendListOfPossibleFutureLocations(AZStd::unordered_set& includedFiles, AZStd::string_view normalizedRelativePath, AZStd::string_view currentFolderPath, const AZStd::vector& includeDirectories) + { + AZStd::string fullPath; + AzFramework::StringFunc::Path::Join(currentFolderPath.data(), normalizedRelativePath.data(), fullPath); + includedFiles.insert(fullPath); + for (const auto &includeDir : includeDirectories) + { + AzFramework::StringFunc::Path::Join(includeDir.c_str(), normalizedRelativePath.data(), fullPath); + includedFiles.insert(fullPath); + } + } + + //! Parses, using depth-first recursive approach, azsl files. Looks for '#include ' or '#include "foo/bar/blah.h"' lines + //! and in turn parses the included files. + //! The included files are searched in the directories listed in @includeDirectories. Basically it's a similar approach + //! as how most C-preprocessors would find included files. + static void GetListOfIncludedFiles(AZStd::string_view sourceFilePath, const AZStd::vector& includeDirectories, + const ShaderBuilderUtility::IncludedFilesParser& includedFilesParser, AZStd::unordered_set& includedFiles) + { + auto outcome = includedFilesParser.ParseFileAndGetIncludedFiles(sourceFilePath); + if (!outcome.IsSuccess()) + { + AZ_Warning(ShaderAssetBuilderName, false, outcome.GetError().c_str()); + return; + } + + // Cache the path of the folder where @sourceFilePath is located. + AZStd::string sourceFileFolderPath; + { + AZStd::string drive; + AzFramework::StringFunc::Path::Split(sourceFilePath.data(), &drive, &sourceFileFolderPath); + if (!drive.empty()) + { + AzFramework::StringFunc::Path::Join(drive.c_str(), sourceFileFolderPath.c_str(), sourceFileFolderPath); + } + } + + auto listOfRelativePaths = outcome.TakeValue(); + for (auto relativePath : listOfRelativePaths) + { + auto fullPath = DiscoverFullPath(relativePath, sourceFileFolderPath, includeDirectories); + if (fullPath.empty()) + { + // The file doesn't exist in any of the includeDirectories. It doesn't exist in @sourceFileFolderPath either. + // The file may appear in the future in one of those directories, We must build an exhaustive list + // of full file paths where the file may appear in the future. + AppendListOfPossibleFutureLocations(includedFiles, relativePath, sourceFileFolderPath, includeDirectories); + continue; + } + + // Add the file to the list and keep parsing recursively. + if (includedFiles.count(fullPath)) + { + continue; + } + includedFiles.insert(fullPath); + GetListOfIncludedFiles(fullPath, includeDirectories, includedFilesParser, includedFiles); + } + } + void ShaderAssetBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) const { AZStd::string fullPath; AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), fullPath, true); + ShaderBuilderUtility::IncludedFilesParser includedFilesParser; AZ_TracePrintf(ShaderAssetBuilderName, "CreateJobs for Shader \"%s\"\n", fullPath.data()); @@ -90,44 +179,34 @@ namespace AZ AZStd::string azslFullPath; ShaderBuilderUtility::GetAbsolutePathToAzslFile(fullPath, shaderSourceData.m_source, azslFullPath); + + { + // Add the AZSL as source dependency + AssetBuilderSDK::SourceFileDependency azslFileDependency; + azslFileDependency.m_sourceFileDependencyPath = azslFullPath; + response.m_sourceFileDependencyList.emplace_back(azslFileDependency); + } + if (!IO::FileIOBase::GetInstance()->Exists(azslFullPath.c_str())) { AZ_Error( ShaderAssetBuilderName, false, "Shader program listed as the source entry does not exist: %s.", azslFullPath.c_str()); - response.m_result = AssetBuilderSDK::CreateJobsResultCode::Failed; + // Treat as success, so when the azsl file shows up the AP will try to recompile. + response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; return; } - GlobalBuildOptions buildOptions = ReadBuildOptions(ShaderAssetBuilderName); - // [GFX TODO] [ATOM-14966] In principle, based on macro definitions, included files can change per supervariant. - // So, the list of source asset dependencies must be collected by running MCPP on each supervariant. - // For now, we will run MCPP only once because CreateJobs() should be as light as possible. - // - // Regardless of the PlatformInfo and enabled ShaderPlatformInterfaces, the azsl file will be preprocessed - // with the sole purpose of extracting all included files. For each included file a SourceDependency will be declared. - PreprocessorData output; - buildOptions.m_compilerArguments.Merge(shaderSourceData.m_compiler); - PreprocessFile(azslFullPath, output, buildOptions.m_preprocessorSettings, true, true); - for (auto includePath : output.includedPaths) + AZStd::unordered_set includedFiles; + GetListOfIncludedFiles(azslFullPath, buildOptions.m_preprocessorSettings.m_projectIncludePaths, includedFilesParser, includedFiles); + for (auto includePath : includedFiles) { - // m_sourceFileDependencyList does not support paths with "." or ".." for relative lookup, but the preprocessor - // may produce path strings like "C:/a/b/c/../../d/file.azsli" so we have to normalize - AzFramework::StringFunc::Path::Normalize(includePath); - AssetBuilderSDK::SourceFileDependency includeFileDependency; includeFileDependency.m_sourceFileDependencyPath = includePath; response.m_sourceFileDependencyList.emplace_back(includeFileDependency); } - { - // Add the AZSL as source dependency - AssetBuilderSDK::SourceFileDependency azslFileDependency; - azslFileDependency.m_sourceFileDependencyPath = azslFullPath; - response.m_sourceFileDependencyList.emplace_back(azslFileDependency); - } - for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms) { AZ_TraceContext("For platform", platformInfo.m_identifier.data()); @@ -149,6 +228,10 @@ namespace AZ response.m_createJobOutputs.push_back(jobDescriptor); } // for all request.m_enabledPlatforms + const AZStd::sys_time_t createJobsEndStamp = AZStd::GetTimeNowMicroSecond(); + const u64 createJobDurationMicros = createJobsEndStamp - shaderAssetBuildTimestamp; + AZ_TracePrintf(ShaderAssetBuilderName, "CreateJobs for %s took %llu microseconds", fullPath.c_str(), createJobDurationMicros ); + response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } @@ -286,6 +369,13 @@ namespace AZ return; } } + else + { + // CreateJobs was not successful if there's no timestamp property in m_jobParameters. + response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; + AZ_Assert(false, "Missing ShaderAssetBuildTimestampParam"); + return; + } auto supervariantList = ShaderBuilderUtility::GetSupervariantListFromShaderSourceData(shaderSourceData); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index e47dd55a97..eb91d9e866 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -814,6 +815,51 @@ namespace AZ return success; } + IncludedFilesParser::IncludedFilesParser() + { + AZStd::regex regex(R"(#\s*include\s+[<|"]([\w|/|\\|\.|-]+)[>|"])", AZStd::regex::ECMAScript); + m_includeRegex.swap(regex); + } + + AZStd::vector IncludedFilesParser::ParseStringAndGetIncludedFiles(AZStd::string_view haystack) const + { + AZStd::vector listOfFilePaths; + AZStd::smatch match; + AZStd::string::const_iterator searchStart(haystack.cbegin()); + while (AZStd::regex_search(searchStart, haystack.cend(), match, m_includeRegex)) + { + if (match.size() > 1) + { + AZStd::string relativeFilePath(match[1].str().c_str()); + AzFramework::StringFunc::Path::Normalize(relativeFilePath); + listOfFilePaths.push_back(relativeFilePath); + } + searchStart = match.suffix().first; + } + return listOfFilePaths; + } + + AZ::Outcome, AZStd::string> IncludedFilesParser::ParseFileAndGetIncludedFiles(AZStd::string_view sourceFilePath) const + { + AZ::IO::FileIOStream stream(sourceFilePath.data(), AZ::IO::OpenMode::ModeRead); + if (!stream.IsOpen()) + { + return AZ::Failure(AZStd::string::format("\"%s\" source file could not be opened.", sourceFilePath.data())); + } + + if (!stream.CanRead()) + { + return AZ::Failure(AZStd::string::format("\"%s\" source file could not be read.", sourceFilePath.data())); + } + + AZStd::string hayStack; + hayStack.resize_no_construct(stream.GetLength()); + stream.Read(stream.GetLength(), hayStack.data()); + + auto listOfFilePaths = ParseStringAndGetIncludedFiles(hayStack); + return AZ::Success(AZStd::move(listOfFilePaths)); + } + } // namespace ShaderBuilderUtility } // namespace ShaderBuilder } // AZ diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h index c000ba9df6..5d45ade9cb 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.h @@ -141,6 +141,29 @@ namespace AZ const uint32_t rhiUniqueIndex, const AZStd::string& platformIdentifier, const AZStd::string& shaderJsonPath, const uint32_t supervariantIndex, RPI::ShaderAssetSubId shaderAssetSubId); + + class IncludedFilesParser + { + public: + IncludedFilesParser(); + ~IncludedFilesParser() = default; + + //! This static function was made public for testability purposes only. + //! Parses the string @haystack, looking for "#include file" lines with a regular expression. + //! Returns the list of relative paths as included by the file. + //! REMARK: The algorithm may over prescribe what files to include because it doesn't discern between comments, etc. + //! Also, a #include line may be protected by #ifdef macros but this algorithm doesn't care. + //! Over prescribing is not a real problem, albeit potential waste in processing. Under prescribing would be a real problem. + AZStd::vector ParseStringAndGetIncludedFiles(AZStd::string_view haystack) const; + + //! This static function was made public for testability purposes only. + //! Opens the file @sourceFilePath, loads the content into a string and returns ParseStringAndGetIncludedFiles(content) + AZ::Outcome, AZStd::string> ParseFileAndGetIncludedFiles(AZStd::string_view sourceFilePath) const; + + private: + AZStd::regex m_includeRegex; + }; + } // ShaderBuilderUtility namespace } // ShaderBuilder namespace } // AZ diff --git a/Gems/Atom/Asset/Shader/Code/Tests/ShaderBuilderUtilityTests.cpp b/Gems/Atom/Asset/Shader/Code/Tests/ShaderBuilderUtilityTests.cpp new file mode 100644 index 0000000000..d477060d04 --- /dev/null +++ b/Gems/Atom/Asset/Shader/Code/Tests/ShaderBuilderUtilityTests.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include "Common/ShaderBuilderTestFixture.h" + +#include + +namespace UnitTest +{ + using namespace AZ; + + // The main purpose of this class is to test ShaderBuilderUtility functions + class ShaderBuilderUtilityTests : public ShaderBuilderTestFixture + { + }; // class ShaderBuilderUtilityTests + + + TEST_F(ShaderBuilderUtilityTests, IncludedFilesParser_ParseStringAndGetIncludedFiles) + { + AZStd::string haystack( + "Some content to parse\n" + "#include \n" + "// #include \n" + "blah # include \"valid_file3.azsli\"\n" + "bar include \n" + "foo # include \"a/directory/valid-file5.azsli\"\n" + "# include \n" + "#includ \"a\\dire-ctory\\invalid-file7.azsli\"\n" + ); + + AZ::ShaderBuilder::ShaderBuilderUtility::IncludedFilesParser includedFilesParser; + auto fileList = includedFilesParser.ParseStringAndGetIncludedFiles(haystack); + EXPECT_EQ(fileList.size(), 5); + + auto it = AZStd::find(fileList.begin(), fileList.end(), "valid_file1.azsli"); + EXPECT_TRUE(it != fileList.end()); + + it = AZStd::find(fileList.begin(), fileList.end(), "valid_file2.azsli"); + EXPECT_TRUE(it != fileList.end()); + + it = AZStd::find(fileList.begin(), fileList.end(), "valid_file3.azsli"); + EXPECT_TRUE(it != fileList.end()); + + // Remark: From now on We must normalize because internally AZ::ShaderBuilder::ShaderBuilderUtility::IncludedFilesParser + // always returns normalized paths. + { + AZStd::string fileName("a\\dire-ctory\\invalid-file4.azsli"); + AzFramework::StringFunc::Path::Normalize(fileName); + it = AZStd::find(fileList.begin(), fileList.end(), fileName); + EXPECT_TRUE(it == fileList.end()); + } + + { + AZStd::string fileName("a\\directory\\valid-file5.azsli"); + AzFramework::StringFunc::Path::Normalize(fileName); + it = AZStd::find(fileList.begin(), fileList.end(), fileName); + EXPECT_TRUE(it != fileList.end()); + } + + { + AZStd::string fileName("a\\dire-ctory\\valid-file6.azsli"); + AzFramework::StringFunc::Path::Normalize(fileName); + it = AZStd::find(fileList.begin(), fileList.end(), fileName); + EXPECT_TRUE(it != fileList.end()); + } + + { + AZStd::string fileName("a\\dire-ctory\\invalid-file7.azsli"); + AzFramework::StringFunc::Path::Normalize(fileName); + it = AZStd::find(fileList.begin(), fileList.end(), fileName); + EXPECT_TRUE(it == fileList.end()); + } + } + +} //namespace UnitTest + +//AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); + diff --git a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake index 033b399478..ab8df70bdb 100644 --- a/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake +++ b/Gems/Atom/Asset/Shader/Code/atom_asset_shader_builders_tests_files.cmake @@ -11,4 +11,5 @@ set(FILES Tests/Common/ShaderBuilderTestFixture.cpp Tests/SupervariantCmdArgumentTests.cpp Tests/McppBinderTests.cpp + Tests/ShaderBuilderUtilityTests.cpp ) diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.azsl index 64f6b3a4b5..a7dfad1c24 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurHor.azsl @@ -55,7 +55,7 @@ int GetLdsIndex(int2 ldsPosition) // --- Common file start --- -// #include +// include ('#' symbol before 'include' was removed on purpose to avoid parsing this azsli file during ShaderAssetBuilder::CreateJobs) // This include fails with the asset processor when generating the .shader for this file // Everything below this is copy pasted from FastDepthAwareBlurCommon.azsli up until the // "Common file end" marker below diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.azsl index cfb49f5911..b4f230c99c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/FastDepthAwareBlurVer.azsl @@ -55,7 +55,7 @@ int GetLdsIndex(int2 ldsPosition) // --- Common file start --- -// #include +// include ('#' symbol before 'include' was removed on purpose to avoid parsing this azsli file during ShaderAssetBuilder::CreateJobs) // This include fails with the asset processor when generating the .shader for this file // Everything below this is copy pasted from FastDepthAwareBlurCommon.azsli up until the // "Common file end" marker below diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAA.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAA.azsli index 8c03816b26..a32b56857c 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAA.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SMAA.azsli @@ -157,7 +157,7 @@ * #define SMAA_RT_METRICS float4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0) * #define SMAA_HLSL_4 * #define SMAA_PRESET_HIGH - * #include "SMAA.h" + * include "SMAA.h" ('#' symbol before 'include' was removed on purpose to avoid parsing this azsli file during ShaderAssetBuilder::CreateJobs) * * Note that SMAA_RT_METRICS doesn't need to be a macro, it can be a * uniform variable. The code is designed to minimize the impact of not From 714dc0a0e8255a62b72e87029a542cbf41957cb9 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:29:10 -0400 Subject: [PATCH 129/274] Refactoring away the use of AZ::TransformNotificationBus. Added unittests for deactivating parents of inner roots. Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyBus.h | 4 + .../NetworkHierarchyChildComponent.h | 21 +- .../NetworkHierarchyRootComponent.h | 29 ++- .../NetworkHierarchyChildComponent.cpp | 108 +++++++-- .../NetworkHierarchyRootComponent.cpp | 208 +++++++++++------- .../Code/Tests/ServerHierarchyTests.cpp | 35 +++ 6 files changed, 295 insertions(+), 110 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h index 1401856afe..45119a89e3 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -19,6 +19,10 @@ namespace Multiplayer : public AZ::ComponentBus { public: + //! @returns true if the entity a hierarchical component attached should be considered for inclusion in a hierarchy + //! this should return false when an entity is deactivating + virtual bool IsHierarchyEnabled() const = 0; + //! @returns hierarchical entities, the first element is the top level root virtual AZStd::vector GetHierarchicalEntities() const = 0; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index 93ce3e25d0..2effb18bb8 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -42,12 +43,13 @@ namespace Multiplayer //! NetworkHierarchyChildComponentBase overrides. //! @{ void OnInit() override; - void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; - void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnActivate(EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(EntityIsMigrating entityIsMigrating) override; //! @} //! NetworkHierarchyRequestBus overrides. //! @{ + bool IsHierarchyEnabled() const override; bool IsHierarchicalChild() const override; bool IsHierarchicalRoot() const override { return false; } AZ::Entity* GetHierarchicalRoot() const override; @@ -58,15 +60,26 @@ namespace Multiplayer protected: //! Used by @NetworkHierarchyRootComponent - void SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot); + void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); private: - const NetworkHierarchyRootComponent* m_hierarchyRootComponent = nullptr; + AZ::ChildChangedEvent::Handler m_childChangedHandler; + AZ::ParentChangedEvent::Handler m_parentChangedHandler; + + void OnChildChanged(AZ::ChildChangeType type, AZ::EntityId child); + void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId parent); + + //! Points to the top level root. + AZ::Entity* m_rootEntity = nullptr; AZ::Event::Handler m_hierarchyRootNetIdChanged; void OnHierarchyRootNetIdChanged(NetEntityId rootNetId); NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; + + bool m_isDeactivating = false; + + void NotifyChildrenHierarchyDisbanded(); }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 228f953a32..35f0da5965 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace Multiplayer { @@ -27,8 +27,8 @@ namespace Multiplayer class NetworkHierarchyRootComponent final : public NetworkHierarchyRootComponentBase , public NetworkHierarchyRequestBus::Handler - , protected AZ::TransformNotificationBus::MultiHandler { + friend class NetworkHierarchyChildComponent; public: AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase); @@ -37,6 +37,8 @@ namespace Multiplayer static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + NetworkHierarchyRootComponent(); + //! NetworkHierarchyRootComponentBase overrides. //! @{ void OnInit() override; @@ -46,6 +48,7 @@ namespace Multiplayer //! NetworkHierarchyRequestBus overrides. //! @{ + bool IsHierarchyEnabled() const override; bool IsHierarchicalRoot() const override; bool IsHierarchicalChild() const override; AZStd::vector GetHierarchicalEntities() const override; @@ -55,22 +58,24 @@ namespace Multiplayer //! @} protected: - //! AZ::TransformNotificationBus::Handler overrides. - //! @{ - void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent) override; - void OnChildAdded(AZ::EntityId child) override; - void OnChildRemoved(AZ::EntityId childRemovedId) override; - //! @} - void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); private: + AZ::ChildChangedEvent::Handler m_childChangedHandler; + AZ::ParentChangedEvent::Handler m_parentChangedHandler; + + void OnChildChanged(AZ::ChildChangeType type, AZ::EntityId child); + void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId parent); + NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; - AZ::Entity* m_higherRootEntity = nullptr; + //! Points to the top level root, if this root is an inner root in this hierarchy. + AZ::Entity* m_rootEntity = nullptr; + AZStd::vector m_hierarchicalEntities; + //! Rebuilds hierarchy starting from this root component's entity. void RebuildHierarchy(); //! @param underEntity Walk the child entities that belong to @underEntity and consider adding them to the hierarchy @@ -86,5 +91,9 @@ namespace Multiplayer //! @currentEntityCount will be modified to reflect the total entity count upon completion of this method. //! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); + + void SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity); + + bool m_isDeactivating = false; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index 93574ec5b4..eff051ed93 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -53,7 +54,9 @@ namespace Multiplayer } NetworkHierarchyChildComponent::NetworkHierarchyChildComponent() - : m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); }) + : m_childChangedHandler([this](AZ::ChildChangeType type, AZ::EntityId child) { OnChildChanged(type, child); }) + , m_parentChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId parent) { OnParentChanged(oldParent, parent); }) + , m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); }) { } @@ -66,13 +69,36 @@ namespace Multiplayer { HierarchyRootAddEvent(m_hierarchyRootNetIdChanged); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); + + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + transformComponent->BindChildChangedEventHandler(m_childChangedHandler); + transformComponent->BindParentChangedEventHandler(m_parentChangedHandler); + } } void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) { + m_isDeactivating = true; + + if (m_rootEntity) + { + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) + { + root->RebuildHierarchy(); + } + } + + NotifyChildrenHierarchyDisbanded(); + NetworkHierarchyRequestBus::Handler::BusDisconnect(); } + bool NetworkHierarchyChildComponent::IsHierarchyEnabled() const + { + return !m_isDeactivating; + } + bool NetworkHierarchyChildComponent::IsHierarchicalChild() const { if (GetHierarchyRoot() != InvalidNetEntityId) @@ -85,14 +111,14 @@ namespace Multiplayer AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const { - return m_hierarchyRootComponent ? m_hierarchyRootComponent->GetEntity() : nullptr; + return m_rootEntity; } AZStd::vector NetworkHierarchyChildComponent::GetHierarchicalEntities() const { - if (m_hierarchyRootComponent) + if (m_rootEntity) { - return m_hierarchyRootComponent->GetHierarchicalEntities(); + return m_rootEntity->FindComponent()->GetHierarchicalEntities(); } return {}; @@ -108,18 +134,18 @@ namespace Multiplayer handler.Connect(m_networkHierarchyLeaveEvent); } - void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot) + void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) { - m_hierarchyRootComponent = hierarchyRoot; + m_rootEntity = hierarchyRoot; if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) { NetworkHierarchyChildComponentController* controller = static_cast(GetController()); - if (hierarchyRoot) + if (m_rootEntity) { - const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetEntityId()); + const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(m_rootEntity->GetId()); controller->SetHierarchyRoot(netRootId); - m_networkHierarchyChangedEvent.Signal(hierarchyRoot->GetEntityId()); + m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId()); } else { @@ -128,20 +154,74 @@ namespace Multiplayer m_networkHierarchyLeaveEvent.Signal(); } } + + if (m_rootEntity == nullptr) + { + NotifyChildrenHierarchyDisbanded(); + } + } + + void NetworkHierarchyChildComponent::OnChildChanged([[maybe_unused]] AZ::ChildChangeType type, [[maybe_unused]] AZ::EntityId child) + { + if (m_rootEntity) + { + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) + { + root->RebuildHierarchy(); + } + } + } + + void NetworkHierarchyChildComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, [[maybe_unused]] AZ::EntityId parent) + { + if (m_rootEntity) + { + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) + { + root->RebuildHierarchy(); + } + } } void NetworkHierarchyChildComponent::OnHierarchyRootNetIdChanged(NetEntityId rootNetId) { - const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId); + ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId); if (rootHandle.Exists()) { - m_hierarchyRootComponent = rootHandle.FindComponent(); - m_networkHierarchyChangedEvent.Signal(m_hierarchyRootComponent->GetEntityId()); + AZ::Entity* newRoot = rootHandle.GetEntity(); + if (m_rootEntity != newRoot) + { + m_rootEntity = newRoot; + m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId()); + } } else { - m_hierarchyRootComponent = nullptr; - m_networkHierarchyLeaveEvent.Signal(); + if (!m_rootEntity) + { + m_rootEntity = nullptr; + m_networkHierarchyLeaveEvent.Signal(); + } + } + } + + void NetworkHierarchyChildComponent::NotifyChildrenHierarchyDisbanded() + { + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren); + for (const AZ::EntityId& childEntityId : allChildren) + { + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(childEntityId)) + { + if (auto* hierarchyChildComponent = childEntity->FindComponent()) + { + hierarchyChildComponent->SetTopLevelHierarchyRootEntity(nullptr); + } + else if (auto* hierarchyRootComponent = childEntity->FindComponent()) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr); + } + } } } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index ced2c79bce..d2b45a8971 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,12 @@ namespace Multiplayer incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); } + NetworkHierarchyRootComponent::NetworkHierarchyRootComponent() + : m_childChangedHandler([this](AZ::ChildChangeType type, AZ::EntityId child) { OnChildChanged(type, child); }) + , m_parentChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId parent) { OnParentChanged(oldParent, parent); }) + { + } + void NetworkHierarchyRootComponent::OnInit() { } @@ -67,31 +74,54 @@ namespace Multiplayer m_hierarchicalEntities.push_back(GetEntity()); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); - AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + transformComponent->BindChildChangedEventHandler(m_childChangedHandler); + transformComponent->BindParentChangedEventHandler(m_parentChangedHandler); + } } void NetworkHierarchyRootComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); - NetworkHierarchyRequestBus::Handler::BusDisconnect(); + m_isDeactivating = true; - for (const AZ::Entity* childEntity : m_hierarchicalEntities) + if (m_rootEntity) { - auto* hierarchyChildComponent = childEntity->FindComponent(); - auto* hierarchyRootComponent = childEntity->FindComponent(); - - if (hierarchyChildComponent) + // tell parent to re-build the hierarchy + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) { - hierarchyChildComponent->SetTopLevelHierarchyRootComponent(nullptr); + root->RebuildHierarchy(); } - if (hierarchyRootComponent) + } + else + { + // notify children to that a hierarchy is disbanded + + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren); + + for (const AZ::EntityId& childEntityId : allChildren) { - hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr); + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(childEntityId)) + { + SetRootForEntity(nullptr, childEntity); + } } } + m_childChangedHandler.Disconnect(); + m_parentChangedHandler.Disconnect(); + + NetworkHierarchyRequestBus::Handler::BusDisconnect(); + m_hierarchicalEntities.clear(); - m_higherRootEntity = nullptr; + m_rootEntity = nullptr; + } + + bool NetworkHierarchyRootComponent::IsHierarchyEnabled() const + { + return !m_isDeactivating; } bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const @@ -116,9 +146,9 @@ namespace Multiplayer AZ::Entity* NetworkHierarchyRootComponent::GetHierarchicalRoot() const { - if (m_higherRootEntity) + if (m_rootEntity) { - return m_higherRootEntity; + return m_rootEntity; } return GetEntity(); @@ -134,24 +164,36 @@ namespace Multiplayer handler.Connect(m_networkHierarchyLeaveEvent); } - void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) + void NetworkHierarchyRootComponent::OnChildChanged([[maybe_unused]] AZ::ChildChangeType type, [[maybe_unused]] AZ::EntityId child) { - const AZ::EntityId entityBusId = *AZ::TransformNotificationBus::GetCurrentBusId(); - if (GetEntityId() != entityBusId) + if (IsHierarchicalRoot()) + { + // Parent-child notifications are not reliable enough to avoid duplicate notifications, + // so we will rebuild from scratch to avoid duplicate entries in @m_hierarchicalEntities. + RebuildHierarchy(); + } + else if (NetworkHierarchyRootComponent* root = GetHierarchicalRoot()->FindComponent()) { - return; // ignore parent changes of child entities + root->RebuildHierarchy(); } + } + + void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) + { + // If the parent is part of a hierarchy, it will detect this entity as a new child and rebuild hierarchy. + // Thus, we only need to take care of a case when the parent is not part of a hierarchy, + // in which case, this entity will be a new root of a new hierarchy. if (AZ::Entity* parentEntity = AZ::Interface::Get()->FindEntity(newParent)) { - if (parentEntity->FindComponent()) + if (parentEntity->FindComponent() == nullptr && + parentEntity->FindComponent() == nullptr) + { + RebuildHierarchy(); + } + else { - m_higherRootEntity = parentEntity; m_hierarchicalEntities.clear(); - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); - - // Should still listen for its events, such as when this root detaches - AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); } } else @@ -161,25 +203,63 @@ namespace Multiplayer } } - void NetworkHierarchyRootComponent::OnChildAdded([[maybe_unused]] AZ::EntityId child) - { - // Parent-child notifications from TransformNotificationBus are not reliable enough to avoid duplicate notifications, - // so we will rebuild from scratch to avoid duplicate entries in @m_hierarchicalEntities. - RebuildHierarchy(); - } - void NetworkHierarchyRootComponent::RebuildHierarchy() { - m_hierarchicalEntities.clear(); - m_hierarchicalEntities.push_back(GetEntity()); // add the root itself + AZStd::vector previousEntities; + m_hierarchicalEntities.swap(previousEntities); - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); - AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + m_hierarchicalEntities.push_back(GetEntity()); // Add the root. uint32_t currentEntityCount = aznumeric_cast(m_hierarchicalEntities.size()); RecursiveAttachHierarchicalEntities(GetEntityId(), currentEntityCount); - m_networkHierarchyChangedEvent.Signal(GetEntityId()); + bool hierarchyChanged = false; + + // Send out join and leave events. + + for (AZ::Entity* currentEntity : m_hierarchicalEntities) + { + const auto prevEntityIterator = AZStd::find(previousEntities.begin(), previousEntities.end(), currentEntity); + if (prevEntityIterator != previousEntities.end()) + { + // This entity was here before the build of the hierarchy. + previousEntities.erase(prevEntityIterator); + } + else + { + // This is a newly added entity to the network hierarchy. + hierarchyChanged = true; + SetRootForEntity(GetEntity(), currentEntity); + } + } + + // These entities were removed since last rebuild. + for (const AZ::Entity* previousEntity : previousEntities) + { + SetRootForEntity(nullptr, previousEntity); + } + + if (!previousEntities.empty()) + { + hierarchyChanged = true; + } + + if (hierarchyChanged) + { + m_networkHierarchyChangedEvent.Signal(GetEntityId()); + } + } + + void NetworkHierarchyRootComponent::SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity) + { + if (auto* hierarchyChildComponent = childEntity->FindComponent()) + { + hierarchyChildComponent->SetTopLevelHierarchyRootEntity(root); + } + else if (auto* hierarchyRootComponent = childEntity->FindComponent()) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(root); + } } bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount) @@ -212,21 +292,12 @@ namespace Multiplayer auto* hierarchyChildComponent = childEntity->FindComponent(); auto* hierarchyRootComponent = childEntity->FindComponent(); - if (hierarchyChildComponent || hierarchyRootComponent) + if ((hierarchyChildComponent && hierarchyChildComponent->IsHierarchyEnabled()) || + (hierarchyRootComponent && hierarchyRootComponent->IsHierarchyEnabled())) { - AZ::TransformNotificationBus::MultiHandler::BusConnect(entity); m_hierarchicalEntities.push_back(childEntity); ++currentEntityCount; - if (hierarchyChildComponent) - { - hierarchyChildComponent->SetTopLevelHierarchyRootComponent(this); - } - else if (hierarchyRootComponent) - { - hierarchyRootComponent->SetTopLevelHierarchyRootEntity(GetEntity()); - } - if (!RecursiveAttachHierarchicalEntities(entity, currentEntityCount)) { return false; @@ -237,43 +308,10 @@ namespace Multiplayer return true; } - void NetworkHierarchyRootComponent::OnChildRemoved(AZ::EntityId childRemovedId) - { - AZStd::vector allChildren; - AZ::TransformBus::EventResult(allChildren, childRemovedId, &AZ::TransformBus::Events::GetEntityAndAllDescendants); - - for (AZ::EntityId childId : allChildren) - { - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(childId); - - const AZ::Entity* childEntity = nullptr; - - AZStd::erase_if(m_hierarchicalEntities, [childId, &childEntity](const AZ::Entity* entity) - { - if (entity->GetId() == childId) - { - childEntity = entity; - return true; - } - - return false; - }); - - if (childEntity) - { - if (NetworkHierarchyChildComponent* childComponent = childEntity->FindComponent()) - { - childComponent->SetTopLevelHierarchyRootComponent(nullptr); - } - } - } - - m_networkHierarchyChangedEvent.Signal(GetEntityId()); - } - void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) { - m_higherRootEntity = hierarchyRoot; + m_rootEntity = hierarchyRoot; + if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) { NetworkHierarchyChildComponentController* controller = static_cast(GetController()); @@ -287,5 +325,11 @@ namespace Multiplayer controller->SetHierarchyRoot(InvalidNetEntityId); } } + + if (m_rootEntity == nullptr) + { + // We lost the parent hierarchical entity, so as a root we need to re-build our own hierarchy. + RebuildHierarchy(); + } } } diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index 708a39d439..0b76e276fd 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -847,6 +847,41 @@ namespace Multiplayer ); } + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Top_Root_Deactivates) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + StopAndDeleteEntity(m_rootEntity); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Top_Root_Deactivates) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + StopAndDeleteEntity(m_childEntity); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Child_Deactivates) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + StopAndDeleteEntity(m_childOfChildEntity); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + TEST_F(ServerHierarchyOfHierarchyTests, Stress_Test_Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) { for (int i = 0; i < 100; ++i) From dc930a5987af99e333e7f858a498faf682c045e7 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Wed, 15 Sep 2021 08:32:52 -0700 Subject: [PATCH 130/274] Fix LuaIDE crash at startup caused by missing System Allocator Initialization (#4130) Signed-off-by: Steve Pham --- Code/Tools/Standalone/Source/Editor/LuaEditor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Code/Tools/Standalone/Source/Editor/LuaEditor.cpp b/Code/Tools/Standalone/Source/Editor/LuaEditor.cpp index 89ab8207ff..f6d905515b 100644 --- a/Code/Tools/Standalone/Source/Editor/LuaEditor.cpp +++ b/Code/Tools/Standalone/Source/Editor/LuaEditor.cpp @@ -35,6 +35,10 @@ int main(int argc, char* argv[]) { AZ::AllocatorInstance::Create(); } + if (!AZ::AllocatorInstance::IsReady()) + { + AZ::AllocatorInstance::Create(); + } AZStd::unique_ptr fileIO = AZStd::unique_ptr(aznew AZ::IO::LocalFileIO()); AZ::IO::FileIOBase::SetInstance(fileIO.get()); @@ -70,6 +74,10 @@ int main(int argc, char* argv[]) // if its in GUI mode or not. } + if (AZ::AllocatorInstance::IsReady()) + { + AZ::AllocatorInstance::Destroy(); + } if (AZ::AllocatorInstance::IsReady()) { AZ::AllocatorInstance::Destroy(); From 089391f761ab3a1e1bda34273e8c7f3333ee1b9b Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Wed, 15 Sep 2021 10:57:37 -0500 Subject: [PATCH 131/274] Terrain System cleanups and unit tests (#4119) * Remove the "TEST_SUPPORTED" traits. Terrain unit tests should be usable on all platforms, so they shouldn't need a platform-specific trait to enable/disable. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fix a few misc terrain bugs. * Change Activate/Deactivate to happen immediately instead of deferring. There were too many order-of-operation bugs caused by trying to defer this. * Added implementation for calculating normals. * Fixed bug where GetHeightSynchronous wasn't stopping at the highest-priority layer. * Added locks for SurfaceData bus to help ensure we lock our mutexes in the correct order and avoid deadlocks. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Add trivial TerrainSystem tests. Tests construction, Activate(), Deactivate(), and destruction. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Unified Terrain system calls on single bus. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added mock for TerrainDataNotificationBus listener. Also added unit tests to verify the listener, and added in missing notification events. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Removed extra Sampler class. Fixed up APIs to correctly pass Sampler and terrainExistsPtr around. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Switched MockTerrainSystem to be proper gmock. This makes it for flexible to use and easier to reuse from other test environments. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fix settings bug caused by bad order of operations that occurred when the methods moved to a different bus. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Eliminate extra EBus by simplifying area initialization. Previously, there was a back-and-forth ebus signal used for the terrain system to find any terrain spawners that were created prior to the terrain system activation. Now it uses the more simple technique of just grabbing all the spawners that are currently hooked up to the spawner ebus. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Switch to NiceMock so that "uninteresting" mock calls get ignored. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Addressed PR feedback. Filled in terrainExistsPtr at the end, and added it to GetNormal as well. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed shader height calculation. It was off by half a pixel, and it was interpolating, both of which were wrong. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- Code/Editor/GameExporter.cpp | 2 +- .../Terrain/TerrainDataRequestBus.cpp | 3 +- .../Terrain/TerrainDataRequestBus.h | 5 +- Gems/PhysX/Code/Tests/PhysXTestUtil.h | 23 +- .../Shaders/Terrain/TerrainCommon.azsli | 14 +- Gems/Terrain/Code/CMakeLists.txt | 67 +++--- .../TerrainHeightGradientListComponent.cpp | 12 +- .../TerrainHeightGradientListComponent.h | 10 +- .../TerrainLayerSpawnerComponent.cpp | 7 - .../Components/TerrainLayerSpawnerComponent.h | 5 +- .../Components/TerrainWorldComponent.cpp | 14 +- .../TerrainWorldDebuggerComponent.cpp | 4 +- .../Source/TerrainSystem/TerrainSystem.cpp | 209 +++++++++++------- .../Code/Source/TerrainSystem/TerrainSystem.h | 17 +- .../Source/TerrainSystem/TerrainSystemBus.h | 47 +--- Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp | 59 +++-- Gems/Terrain/Code/Tests/TerrainMocks.h | 46 ++-- Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 92 ++++++++ Gems/Terrain/Code/Tests/TerrainTest.cpp | 20 -- Gems/Terrain/Code/terrain_tests_files.cmake | 1 + 20 files changed, 382 insertions(+), 275 deletions(-) create mode 100644 Gems/Terrain/Code/Tests/TerrainSystemTest.cpp diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 1fc980fdac..00dc3d8de1 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -318,7 +318,7 @@ void CGameExporter::ExportLevelInfo(const QString& path) root->setAttr("Name", levelName.toUtf8().data()); auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler(); const AZ::Aabb terrainAabb = terrain ? terrain->GetTerrainAabb() : AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero()); - const AZ::Vector2 terrainGridResolution = terrain ? terrain->GetTerrainGridResolution() : AZ::Vector2::CreateOne(); + const AZ::Vector2 terrainGridResolution = terrain ? terrain->GetTerrainHeightQueryResolution() : AZ::Vector2::CreateOne(); const int compiledHeightmapSize = static_cast(terrainAabb.GetXExtent() / terrainGridResolution.GetX()); root->setAttr("HeightmapSize", compiledHeightmapSize); diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp index 947d3821ab..1fb29cfa30 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.cpp @@ -51,7 +51,8 @@ namespace AzFramework ->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal) ->Event("GetNormalFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormalFromFloats) ->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb) - ->Event("GetTerrainGridResolution", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainGridResolution) + ->Event("GetTerrainHeightQueryResolution", + &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution) ; } diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h index 08e238434e..92eb28a110 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h @@ -59,8 +59,11 @@ namespace AzFramework static AZ::Vector3 GetDefaultTerrainNormal() { return AZ::Vector3::CreateAxisZ(); } // System-level queries to understand world size and resolution - virtual AZ::Vector2 GetTerrainGridResolution() const = 0; + virtual AZ::Vector2 GetTerrainHeightQueryResolution() const = 0; + virtual void SetTerrainHeightQueryResolution(AZ::Vector2 queryResolution) = 0; + virtual AZ::Aabb GetTerrainAabb() const = 0; + virtual void SetTerrainAabb(const AZ::Aabb& worldBounds) = 0; //! Returns terrains height in meters at location x,y. //! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will become false, diff --git a/Gems/PhysX/Code/Tests/PhysXTestUtil.h b/Gems/PhysX/Code/Tests/PhysXTestUtil.h index b1ba23600a..8e81b9cb89 100644 --- a/Gems/PhysX/Code/Tests/PhysXTestUtil.h +++ b/Gems/PhysX/Code/Tests/PhysXTestUtil.h @@ -93,9 +93,26 @@ namespace PhysX //////////////////////////////////////////////////////////////////////// // TerrainDataRequestBus interface dummy implementation - AZ::Vector2 GetTerrainGridResolution() const override { return {}; } - AZ::Aabb GetTerrainAabb() const override { return {}; } - float GetHeight(AZ::Vector3, Sampler, bool*) const override { return {}; } + AZ::Vector2 GetTerrainHeightQueryResolution() const override + { + return {}; + } + void SetTerrainHeightQueryResolution([[maybe_unused]] AZ::Vector2 queryResolution) override + { + } + + AZ::Aabb GetTerrainAabb() const override + { + return {}; + } + void SetTerrainAabb([[maybe_unused]] const AZ::Aabb& worldBounds) override + { + } + + float GetHeight(AZ::Vector3, Sampler, bool*) const override + { + return {}; + } float GetHeightFromFloats(float, float, Sampler, bool*) const override { return {}; } AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeight(AZ::Vector3, Sampler, bool*) const override { return {}; } AzFramework::SurfaceData::SurfaceTagWeight GetMaxSurfaceWeightFromFloats(float, float, Sampler, bool*) const override { return {}; } diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli index 6e489796d7..18b85bbd43 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli @@ -11,16 +11,16 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject { Texture2D m_heightmapImage; - Sampler LinearSampler + Sampler PointSampler { - MinFilter = Linear; - MagFilter = Linear; - MipFilter = Linear; + MinFilter = Point; + MagFilter = Point; + MipFilter = Point; AddressU = Clamp; AddressV = Clamp; AddressW = Clamp; }; - + row_major float3x4 m_modelToWorld; struct TerrainData @@ -57,8 +57,8 @@ float4x4 GetObject_WorldMatrix() float GetHeight(float2 origUv) { - float2 uv = clamp(origUv, 0.0f, 1.0f); - return ObjectSrg::m_terrainData.m_heightScale * (ObjectSrg::m_heightmapImage.SampleLevel(ObjectSrg::LinearSampler, uv, 0).r - 0.5f); + float2 uv = clamp(origUv + (ObjectSrg::m_terrainData.m_uvStep * 0.5f), 0.0f, 1.0f); + return ObjectSrg::m_terrainData.m_heightScale * (ObjectSrg::m_heightmapImage.SampleLevel(ObjectSrg::PointSampler, uv, 0).r - 0.5f); } float4 GetTerrainProjectedPosition(ObjectSrg::TerrainData terrainData, float2 vertexPosition, float2 uv) diff --git a/Gems/Terrain/Code/CMakeLists.txt b/Gems/Terrain/Code/CMakeLists.txt index b4a35edbbf..0feacdaf71 100644 --- a/Gems/Terrain/Code/CMakeLists.txt +++ b/Gems/Terrain/Code/CMakeLists.txt @@ -83,15 +83,36 @@ endif() ################################################################################ # See if globally, tests are supported if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) - # We globally support tests, see if we support tests on this platform for Terrain.Static - if(PAL_TRAIT_TERRAIN_TEST_SUPPORTED) - # We support Terrain.Tests on this platform, add Terrain.Tests target which depends on Terrain.Static + ly_add_target( + NAME Terrain.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + terrain_files.cmake + terrain_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Tests + Source + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + AZ::AzFramework + Gem::Terrain.Static + ) + + # Add Terrain.Tests to googletest + ly_add_googletest( + NAME Gem::Terrain.Tests + ) + + # If we are a host platform we want to add tools test like editor tests here + if(PAL_TRAIT_BUILD_HOST_TOOLS) + # We support Terrain.Editor.Tests on this platform, add Terrain.Editor.Tests target which depends on Terrain.Editor ly_add_target( - NAME Terrain.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAME Terrain.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem FILES_CMAKE - terrain_files.cmake - terrain_tests_files.cmake + terrain_editor_tests_files.cmake INCLUDE_DIRECTORIES PRIVATE Tests @@ -99,40 +120,12 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzTest - AZ::AzFramework - Gem::Terrain.Static + Gem::Terrain.Editor ) - # Add Terrain.Tests to googletest + # Add Terrain.Editor.Tests to googletest ly_add_googletest( - NAME Gem::Terrain.Tests + NAME Gem::Terrain.Editor.Tests ) endif() - - # If we are a host platform we want to add tools test like editor tests here - if(PAL_TRAIT_BUILD_HOST_TOOLS) - # We are a host platform, see if Editor tests are supported on this platform - if(PAL_TRAIT_TERRAIN_EDITOR_TEST_SUPPORTED) - # We support Terrain.Editor.Tests on this platform, add Terrain.Editor.Tests target which depends on Terrain.Editor - ly_add_target( - NAME Terrain.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE Gem - FILES_CMAKE - terrain_editor_tests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Tests - Source - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - Gem::Terrain.Editor - ) - - # Add Terrain.Editor.Tests to googletest - ly_add_googletest( - NAME Gem::Terrain.Editor.Tests - ) - endif() - endif() endif() diff --git a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp index d64f660d90..4d0cb6576d 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp @@ -166,14 +166,20 @@ namespace Terrain } void TerrainHeightGradientListComponent::GetHeight( - const AZ::Vector3& inPosition, AZ::Vector3& outPosition, [[maybe_unused]] Sampler sampleFilter = Sampler::DEFAULT) + const AZ::Vector3& inPosition, + AZ::Vector3& outPosition, + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = + AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) { const float height = GetHeight(inPosition.GetX(), inPosition.GetY()); outPosition.SetZ(height); } void TerrainHeightGradientListComponent::GetNormal( - const AZ::Vector3& inPosition, AZ::Vector3& outNormal, [[maybe_unused]] Sampler sampleFilter = Sampler::DEFAULT) + const AZ::Vector3& inPosition, + AZ::Vector3& outNormal, + [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = + AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) { const float x = inPosition.GetX(); const float y = inPosition.GetY(); @@ -206,7 +212,7 @@ namespace Terrain // Get the height range of the entire world m_cachedHeightQueryResolution = AZ::Vector2(1.0f); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - m_cachedHeightQueryResolution, &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainGridResolution); + m_cachedHeightQueryResolution, &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution); AZ::Aabb worldBounds = AZ::Aabb::CreateNull(); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( diff --git a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h index 7635680815..509f003afa 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h @@ -64,8 +64,14 @@ namespace Terrain TerrainHeightGradientListComponent() = default; ~TerrainHeightGradientListComponent() = default; - void GetHeight(const AZ::Vector3& inPosition, AZ::Vector3& outPosition, Sampler sampleFilter) override; - void GetNormal(const AZ::Vector3& inPosition, AZ::Vector3& outNormal, Sampler sampleFilter) override; + void GetHeight( + const AZ::Vector3& inPosition, + AZ::Vector3& outPosition, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) override; + void GetNormal( + const AZ::Vector3& inPosition, + AZ::Vector3& outNormal, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) override; ////////////////////////////////////////////////////////////////////////// // AZ::Component interface implementation diff --git a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp index e17dbd0e93..245c98ccac 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.cpp @@ -104,7 +104,6 @@ namespace Terrain { AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId()); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId()); - TerrainAreaRequestBus::Handler::BusConnect(GetEntityId()); TerrainSpawnerRequestBus::Handler::BusConnect(GetEntityId()); TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RegisterArea, GetEntityId()); @@ -114,7 +113,6 @@ namespace Terrain { TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::UnregisterArea, GetEntityId()); TerrainSpawnerRequestBus::Handler::BusDisconnect(); - TerrainAreaRequestBus::Handler::BusDisconnect(); LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); @@ -161,11 +159,6 @@ namespace Terrain return m_configuration.m_useGroundPlane; } - void TerrainLayerSpawnerComponent::RegisterArea() - { - TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RegisterArea, GetEntityId()); - } - void TerrainLayerSpawnerComponent::RefreshArea() { TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RefreshArea, GetEntityId()); diff --git a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h index 3f8e72e1b8..c7398bf93e 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainLayerSpawnerComponent.h @@ -58,7 +58,6 @@ namespace Terrain : public AZ::Component , private AZ::TransformNotificationBus::Handler , private LmbrCentral::ShapeComponentNotificationsBus::Handler - , private Terrain::TerrainAreaRequestBus::Handler , private Terrain::TerrainSpawnerRequestBus::Handler { public: @@ -81,6 +80,7 @@ namespace Terrain bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override; bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; + protected: ////////////////////////////////////////////////////////////////////////// // AZ::TransformNotificationBus::Handler void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; @@ -92,8 +92,7 @@ namespace Terrain void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) override; bool GetUseGroundPlane() override; - void RegisterArea() override; - void RefreshArea() override; + void RefreshArea(); private: TerrainLayerSpawnerConfig m_configuration; diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp index 669a8f4b02..d8b7308ef7 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldComponent.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace Terrain { @@ -85,17 +86,16 @@ namespace Terrain void TerrainWorldComponent::Activate() { - TerrainSystemServiceRequestBus::Broadcast( - &TerrainSystemServiceRequestBus::Events::SetWorldBounds, - AZ::Aabb::CreateFromMinMax(m_configuration.m_worldMin, m_configuration.m_worldMax) - ); - TerrainSystemServiceRequestBus::Broadcast( - &TerrainSystemServiceRequestBus::Events::SetHeightQueryResolution, m_configuration.m_heightQueryResolution); - // Currently, the Terrain System Component owns the Terrain System instance because the Terrain World component gets recreated // every time an entity is added or removed to a level. If this ever changes, the Terrain System ownership could move into // the level component. TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::Activate); + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequestBus::Events::SetTerrainAabb, + AZ::Aabb::CreateFromMinMax(m_configuration.m_worldMin, m_configuration.m_worldMax)); + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequestBus::Events::SetTerrainHeightQueryResolution, m_configuration.m_heightQueryResolution); } void TerrainWorldComponent::Deactivate() diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp index d7504295c2..89ffa6364f 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp @@ -171,7 +171,7 @@ namespace Terrain // Determine how far to draw in each direction in world space based on our MaxSectorsToDraw AZ::Vector2 queryResolution = AZ::Vector2(1.0f); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainGridResolution); + queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainHeightQueryResolution); AZ::Vector3 viewDistance( queryResolution.GetX() * SectorSizeInGridPoints * sqrtf(MaxSectorsToDraw), queryResolution.GetY() * SectorSizeInGridPoints * sqrtf(MaxSectorsToDraw), @@ -214,7 +214,7 @@ namespace Terrain AZ::Vector2 queryResolution = AZ::Vector2(1.0f); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( - queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainGridResolution); + queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainHeightQueryResolution); // Calculate the world size of each sector. Note that this size actually ends at the last point, not the last square. // So for example, the sector size for 3 points will go from (*--*--*) even though it will be used to draw (*--*--*--). diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index a271d624f5..674af376e4 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,7 @@ TerrainSystem::TerrainSystem() m_currentSettings.m_worldBounds = AZ::Aabb::CreateNull(); m_requestedSettings = m_currentSettings; - m_requestedSettings.m_worldBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(4096.0f, 4096.0f, 2048.0f)); + m_requestedSettings.m_worldBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-512.0f), AZ::Vector3(512.0f)); } TerrainSystem::~TerrainSystem() @@ -66,23 +67,76 @@ TerrainSystem::~TerrainSystem() void TerrainSystem::Activate() { - m_requestedSettings.m_systemActive = true; + AzFramework::Terrain::TerrainDataNotificationBus::Broadcast( + &AzFramework::Terrain::TerrainDataNotificationBus::Events::OnTerrainDataCreateBegin); + + m_dirtyRegion = AZ::Aabb::CreateNull(); + m_terrainHeightDirty = true; m_terrainSettingsDirty = true; + m_requestedSettings.m_systemActive = true; + + { + AZStd::shared_lock lock(m_areaMutex); + m_registeredAreas.clear(); + } + + AzFramework::Terrain::TerrainDataRequestBus::Handler::BusConnect(); + + // Register any terrain spawners that were already active before the terrain system activated. + auto enumerationCallback = [&]([[maybe_unused]] Terrain::TerrainSpawnerRequests* terrainSpawner) -> bool + { + AZ::EntityId areaId = *(Terrain::TerrainSpawnerRequestBus::GetCurrentBusId()); + RegisterArea(areaId); + + // Keep Enumerating + return true; + }; + Terrain::TerrainSpawnerRequestBus::EnumerateHandlers(enumerationCallback); + + AzFramework::Terrain::TerrainDataNotificationBus::Broadcast( + &AzFramework::Terrain::TerrainDataNotificationBus::Events::OnTerrainDataCreateEnd); } void TerrainSystem::Deactivate() { - m_requestedSettings.m_systemActive = false; + AzFramework::Terrain::TerrainDataNotificationBus::Broadcast( + &AzFramework::Terrain::TerrainDataNotificationBus::Events::OnTerrainDataDestroyBegin); + + AzFramework::Terrain::TerrainDataRequestBus::Handler::BusDisconnect(); + + { + AZStd::shared_lock lock(m_areaMutex); + m_registeredAreas.clear(); + } + + m_dirtyRegion = AZ::Aabb::CreateNull(); + m_terrainHeightDirty = true; m_terrainSettingsDirty = true; + m_requestedSettings.m_systemActive = false; + + if (auto rpi = AZ::RPI::RPISystemInterface::Get(); rpi) + { + if (auto defaultScene = rpi->GetDefaultScene(); defaultScene) + { + const AZ::RPI::Scene* scene = defaultScene.get(); + if (auto terrainFeatureProcessor = scene->GetFeatureProcessor(); terrainFeatureProcessor) + { + terrainFeatureProcessor->RemoveTerrainData(); + } + } + } + + AzFramework::Terrain::TerrainDataNotificationBus::Broadcast( + &AzFramework::Terrain::TerrainDataNotificationBus::Events::OnTerrainDataDestroyEnd); } -void TerrainSystem::SetWorldBounds(const AZ::Aabb& worldBounds) +void TerrainSystem::SetTerrainAabb(const AZ::Aabb& worldBounds) { m_requestedSettings.m_worldBounds = worldBounds; m_terrainSettingsDirty = true; } -void TerrainSystem::SetHeightQueryResolution(AZ::Vector2 queryResolution) +void TerrainSystem::SetTerrainHeightQueryResolution(AZ::Vector2 queryResolution) { m_requestedSettings.m_heightQueryResolution = queryResolution; m_terrainSettingsDirty = true; @@ -93,13 +147,15 @@ AZ::Aabb TerrainSystem::GetTerrainAabb() const return m_currentSettings.m_worldBounds; } -AZ::Vector2 TerrainSystem::GetTerrainGridResolution() const +AZ::Vector2 TerrainSystem::GetTerrainHeightQueryResolution() const { return m_currentSettings.m_heightQueryResolution; } -float TerrainSystem::GetHeightSynchronous(float x, float y) const +float TerrainSystem::GetHeightSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { + bool terrainExists = false; + AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); AZ::Vector3 outPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); @@ -111,67 +167,77 @@ float TerrainSystem::GetHeightSynchronous(float x, float y) const if (areaBounds.Contains(inPosition)) { Terrain::TerrainAreaHeightRequestBus::Event( - areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, - Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT); + areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampler); + + terrainExists = true; + + break; } } - return AZ::GetClamp( - outPosition.GetZ(), m_currentSettings.m_worldBounds.GetMin().GetZ(), m_currentSettings.m_worldBounds.GetMax().GetZ()); -} - -float TerrainSystem::GetHeight(AZ::Vector3 position, [[maybe_unused]] Sampler sampler, [[maybe_unused]] bool* terrainExistsPtr) const -{ if (terrainExistsPtr) { - *terrainExistsPtr = true; + *terrainExistsPtr = terrainExists; } - return GetHeightSynchronous(position.GetX(), position.GetY()); + return AZ::GetClamp( + outPosition.GetZ(), m_currentSettings.m_worldBounds.GetMin().GetZ(), m_currentSettings.m_worldBounds.GetMax().GetZ()); } -float TerrainSystem::GetHeightFromFloats( - float x, float y, [[maybe_unused]] Sampler sampler, [[maybe_unused]] bool* terrainExistsPtr) const +float TerrainSystem::GetHeight(AZ::Vector3 position, Sampler sampler, bool* terrainExistsPtr) const { - if (terrainExistsPtr) - { - *terrainExistsPtr = true; - } - - return GetHeightSynchronous(x, y); + return GetHeightSynchronous(position.GetX(), position.GetY(), sampler, terrainExistsPtr); } -bool TerrainSystem::GetIsHoleFromFloats( - [[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] Sampler sampleFilter) const +float TerrainSystem::GetHeightFromFloats(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { - return false; + return GetHeightSynchronous(x, y, sampler, terrainExistsPtr); } -AZ::Vector3 TerrainSystem::GetNormalSynchronous([[maybe_unused]] float x, [[maybe_unused]] float y) const +bool TerrainSystem::GetIsHoleFromFloats(float x, float y, Sampler sampler) const { - return AZ::Vector3::CreateAxisZ(); + bool terrainExists = false; + GetHeightSynchronous(x, y, sampler, &terrainExists); + return !terrainExists; } -AZ::Vector3 TerrainSystem::GetNormal( - AZ::Vector3 position, [[maybe_unused]] Sampler sampleFilter, [[maybe_unused]] bool* terrainExistsPtr) const +AZ::Vector3 TerrainSystem::GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { + bool terrainExists = false; + + AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); + AZ::Vector3 outNormal = AZ::Vector3::CreateAxisZ(); + + AZStd::shared_lock lock(m_areaMutex); + + for (auto& [areaId, areaBounds] : m_registeredAreas) + { + inPosition.SetZ(areaBounds.GetMin().GetZ()); + if (areaBounds.Contains(inPosition)) + { + Terrain::TerrainAreaHeightRequestBus::Event( + areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetNormal, inPosition, outNormal, sampler); + terrainExists = true; + break; + } + } + if (terrainExistsPtr) { - *terrainExistsPtr = true; + *terrainExistsPtr = terrainExists; } - return GetNormalSynchronous(position.GetX(), position.GetY()); + return outNormal; } -AZ::Vector3 TerrainSystem::GetNormalFromFloats( - float x, float y, [[maybe_unused]] Sampler sampleFilter, [[maybe_unused]] bool* terrainExistsPtr) const +AZ::Vector3 TerrainSystem::GetNormal(AZ::Vector3 position, Sampler sampler, bool* terrainExistsPtr) const { - if (terrainExistsPtr) - { - *terrainExistsPtr = true; - } + return GetNormalSynchronous(position.GetX(), position.GetY(), sampler, terrainExistsPtr); +} - return GetNormalSynchronous(x, y); +AZ::Vector3 TerrainSystem::GetNormalFromFloats(float x, float y, Sampler sampler, bool* terrainExistsPtr) const +{ + return GetNormalSynchronous(x, y, sampler, terrainExistsPtr); } @@ -298,35 +364,6 @@ void TerrainSystem::ProcessSurfacePointsFromRegion(const AZ::Aabb& inRegion, con } */ -void TerrainSystem::SystemActivate() -{ - { - AZStd::shared_lock lock(m_areaMutex); - m_registeredAreas.clear(); - } - - AzFramework::Terrain::TerrainDataRequestBus::Handler::BusConnect(); - - TerrainAreaRequestBus::Broadcast(&TerrainAreaRequestBus::Events::RegisterArea); -} - -void TerrainSystem::SystemDeactivate() -{ - AzFramework::Terrain::TerrainDataRequestBus::Handler::BusDisconnect(); - - { - AZStd::shared_lock lock(m_areaMutex); - m_registeredAreas.clear(); - } - - const AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get(); - auto terrainFeatureProcessor = scene->GetFeatureProcessor(); - if (terrainFeatureProcessor) - { - terrainFeatureProcessor->RemoveTerrainData(); - } -} - void TerrainSystem::RegisterArea(AZ::EntityId areaId) { AZStd::unique_lock lock(m_areaMutex); @@ -383,6 +420,7 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) if (m_terrainSettingsDirty) { + terrainSettingsChanged = true; m_terrainSettingsDirty = false; // This needs to happen before the "system active" check below, because activating the system will cause the various @@ -393,24 +431,12 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) m_dirtyRegion.AddAabb(m_requestedSettings.m_worldBounds); m_terrainHeightDirty = true; m_currentSettings.m_worldBounds = m_requestedSettings.m_worldBounds; - terrainSettingsChanged = true; } if (m_requestedSettings.m_heightQueryResolution != m_currentSettings.m_heightQueryResolution) { m_dirtyRegion = AZ::Aabb::CreateNull(); m_terrainHeightDirty = true; - terrainSettingsChanged = true; - } - - if (m_requestedSettings.m_systemActive != m_currentSettings.m_systemActive) - { - m_requestedSettings.m_systemActive ? SystemActivate() : SystemDeactivate(); - - // Null dirty region will be interpreted as updating everything - m_dirtyRegion = AZ::Aabb::CreateNull(); - m_terrainHeightDirty = true; - terrainSettingsChanged = true; } m_currentSettings = m_requestedSettings; @@ -420,6 +446,14 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) { AZStd::shared_lock lock(m_areaMutex); + // Block other threads from accessing the surface data bus while we are in GetValue (which may call into the SurfaceData bus). + // We lock our surface data mutex *before* checking / setting "isRequestInProgress" so that we prevent race conditions + // that create false detection of cyclic dependencies when multiple requests occur on different threads simultaneously. + // (One case where this was previously able to occur was in rapid updating of the Preview widget on the + // GradientSurfaceDataComponent in the Editor when moving the threshold sliders back and forth rapidly) + auto& surfaceDataContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false); + typename SurfaceData::SurfaceDataSystemRequestBus::Context::DispatchLockGuard scopeLock(surfaceDataContext.m_contextMutex); + AZ::Transform transform = AZ::Transform::CreateTranslation(m_currentSettings.m_worldBounds.GetCenter()); uint32_t width = aznumeric_cast( @@ -449,7 +483,8 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) } AZ::Vector3 outPosition; - const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter = Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT; + const AzFramework::Terrain::TerrainDataRequestBus::Events::Sampler sampleFilter = + AzFramework::Terrain::TerrainDataRequestBus::Events::Sampler::DEFAULT; Terrain::TerrainAreaHeightRequestBus::Event( areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter); @@ -476,6 +511,14 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) if (terrainSettingsChanged || m_terrainHeightDirty) { + // Block other threads from accessing the surface data bus while we are in GetValue (which may call into the SurfaceData bus). + // We lock our surface data mutex *before* checking / setting "isRequestInProgress" so that we prevent race conditions + // that create false detection of cyclic dependencies when multiple requests occur on different threads simultaneously. + // (One case where this was previously able to occur was in rapid updating of the Preview widget on the + // GradientSurfaceDataComponent in the Editor when moving the threshold sliders back and forth rapidly) + auto& surfaceDataContext = SurfaceData::SurfaceDataSystemRequestBus::GetOrCreateContext(false); + typename SurfaceData::SurfaceDataSystemRequestBus::Context::DispatchLockGuard scopeLock(surfaceDataContext.m_contextMutex); + AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask changeMask = AzFramework::Terrain::TerrainDataNotifications::TerrainDataChangedMask::None; diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index a75685fb12..c52165da6b 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -42,10 +42,6 @@ namespace Terrain /////////////////////////////////////////// // TerrainSystemServiceRequestBus::Handler Impl - - void SetWorldBounds(const AZ::Aabb& worldBounds) override; - void SetHeightQueryResolution(AZ::Vector2 queryResolution) override; - void Activate() override; void Deactivate() override; @@ -55,8 +51,12 @@ namespace Terrain /////////////////////////////////////////// // TerrainDataRequestBus::Handler Impl - AZ::Vector2 GetTerrainGridResolution() const override; + AZ::Vector2 GetTerrainHeightQueryResolution() const override; + void SetTerrainHeightQueryResolution(AZ::Vector2 queryResolution) override; + AZ::Aabb GetTerrainAabb() const override; + void SetTerrainAabb(const AZ::Aabb& worldBounds) override; + //! Returns terrains height in meters at location x,y. //! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain @@ -94,15 +94,12 @@ namespace Terrain float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; private: - float GetHeightSynchronous(float x, float y) const; - AZ::Vector3 GetNormalSynchronous(float x, float y) const; + float GetHeightSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; + AZ::Vector3 GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; // AZ::TickBus::Handler overrides ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - void SystemActivate(); - void SystemDeactivate(); - struct TerrainSystemSettings { AZ::Aabb m_worldBounds; diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h index cb41ba9957..1ba63a8f84 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h @@ -16,6 +16,8 @@ #include #include +#include + namespace Terrain { /** @@ -39,9 +41,6 @@ namespace Terrain virtual void Activate() = 0; virtual void Deactivate() = 0; - virtual void SetWorldBounds(const AZ::Aabb& worldBounds) = 0; - virtual void SetHeightQueryResolution(AZ::Vector2 queryResolution) = 0; - // register an area to override terrain virtual void RegisterArea(AZ::EntityId areaId) = 0; virtual void UnregisterArea(AZ::EntityId areaId) = 0; @@ -50,27 +49,6 @@ namespace Terrain using TerrainSystemServiceRequestBus = AZ::EBus; - /** - * A bus to signal the life times of terrain areas - * Note: all the API are meant to be queued events - */ - class TerrainAreaRequests - : public AZ::ComponentBus - { - public: - //////////////////////////////////////////////////////////////////////// - // EBusTraits - using MutexType = AZStd::recursive_mutex; - //////////////////////////////////////////////////////////////////////// - - virtual ~TerrainAreaRequests() = default; - - virtual void RegisterArea() = 0; - virtual void RefreshArea() = 0; - - }; - - using TerrainAreaRequestBus = AZ::EBus; /** * A bus to signal the life times of terrain areas @@ -87,15 +65,6 @@ namespace Terrain virtual ~TerrainAreaHeightRequests() = default; - enum class Sampler - { - BILINEAR, // Get the value at the requested location, using terrain sample grid to bilinear filter between sample grid points - CLAMP, // Clamp the input point to the terrain sample grid, then get the exact value - EXACT, // Directly get the value at the location, regardless of terrain sample grid density - - DEFAULT = BILINEAR - }; - enum SurfacePointDataMask { POSITION = 0x01, @@ -107,8 +76,16 @@ namespace Terrain // Synchronous single input location. The Vector3 input position versions are defined to ignore the input Z value. - virtual void GetHeight(const AZ::Vector3& inPosition, AZ::Vector3& outPosition, Sampler sampleFilter = Sampler::DEFAULT) = 0; - virtual void GetNormal(const AZ::Vector3& inPosition, AZ::Vector3& outNormal, Sampler sampleFilter = Sampler::DEFAULT) = 0; + virtual void GetHeight( + const AZ::Vector3& inPosition, + AZ::Vector3& outPosition, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = + AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) = 0; + virtual void GetNormal( + const AZ::Vector3& inPosition, + AZ::Vector3& outNormal, + AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = + AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) = 0; }; using TerrainAreaHeightRequestBus = AZ::EBus; diff --git a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp index 91d6a26f75..f0533322c8 100644 --- a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp +++ b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp @@ -17,6 +17,10 @@ #include +using ::testing::NiceMock; +using ::testing::AtLeast; +using ::testing::_; + class LayerSpawnerComponentTest : public ::testing::Test { @@ -26,7 +30,7 @@ protected: AZStd::unique_ptr m_entity; Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent; UnitTest::MockBoxShapeComponent* m_shapeComponent; - AZStd::unique_ptr m_terrainSystem; + AZStd::unique_ptr> m_terrainSystem; void SetUp() override { @@ -40,10 +44,8 @@ protected: void TearDown() override { - if (m_terrainSystem) - { - m_terrainSystem->Deactivate(); - } + m_entity.reset(); + m_terrainSystem.reset(); m_app.Destroy(); } @@ -72,16 +74,9 @@ protected: ASSERT_TRUE(m_shapeComponent); } - void ResetEntity() - { - m_entity->Deactivate(); - m_entity->Reset(); - } - void CreateMockTerrainSystem() { - m_terrainSystem = AZStd::make_unique(); - m_terrainSystem->Activate(); + m_terrainSystem = AZStd::make_unique>(); } }; @@ -93,7 +88,7 @@ TEST_F(LayerSpawnerComponentTest, ActivatEntityActivateSuccess) m_entity->Activate(); EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active); - ResetEntity(); + m_entity->Deactivate(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect) @@ -115,7 +110,7 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect) EXPECT_TRUE(useGroundPlane); - ResetEntity(); + m_entity->Deactivate(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) @@ -147,7 +142,7 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect) EXPECT_FALSE(useGroundPlane); - ResetEntity(); + m_entity->Deactivate(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem) @@ -156,14 +151,14 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem) CreateMockTerrainSystem(); + // The Activate call should register the area. + EXPECT_CALL(*m_terrainSystem, RegisterArea(_)).Times(1); + AddLayerSpawnerAndShapeComponentToEntity(); m_entity->Activate(); - // The Activate call should have registered the area. - EXPECT_EQ(1, m_terrainSystem->m_registerAreaCalledCount); - - ResetEntity(); + m_entity->Deactivate(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem) @@ -172,16 +167,14 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem CreateMockTerrainSystem(); + // The Deactivate call should unregister the area. + EXPECT_CALL(*m_terrainSystem, UnregisterArea(_)).Times(1); + AddLayerSpawnerAndShapeComponentToEntity(); m_entity->Activate(); - m_layerSpawnerComponent->Deactivate(); - - // The Deactivate call should have unregistered the area. - EXPECT_EQ(1, m_terrainSystem->m_unregisterAreaCalledCount); - - ResetEntity(); + m_entity->Deactivate(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem) @@ -190,6 +183,9 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSyst CreateMockTerrainSystem(); + // The TransformChanged call should refresh the area. + EXPECT_CALL(*m_terrainSystem, RefreshArea(_)).Times(1); + AddLayerSpawnerAndShapeComponentToEntity(); m_entity->Activate(); @@ -197,9 +193,7 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSyst AZ::TransformNotificationBus::Event( m_entity->GetId(), &AZ::TransformNotificationBus::Events::OnTransformChanged, AZ::Transform(), AZ::Transform()); - EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount); - - ResetEntity(); + m_entity->Deactivate(); } TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem) @@ -208,6 +202,9 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem) CreateMockTerrainSystem(); + // The ShapeChanged call should refresh the area. + EXPECT_CALL(*m_terrainSystem, RefreshArea(_)).Times(1); + AddLayerSpawnerAndShapeComponentToEntity(); m_entity->Activate(); @@ -216,7 +213,5 @@ TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem) m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged, LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged); - EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount); - - ResetEntity(); + m_entity->Deactivate(); } diff --git a/Gems/Terrain/Code/Tests/TerrainMocks.h b/Gems/Terrain/Code/Tests/TerrainMocks.h index 674104e26b..03a2eccf1d 100644 --- a/Gems/Terrain/Code/Tests/TerrainMocks.h +++ b/Gems/Terrain/Code/Tests/TerrainMocks.h @@ -7,7 +7,10 @@ */ #pragma once +#include + #include +#include #include namespace UnitTest @@ -62,44 +65,45 @@ namespace UnitTest } }; - class MockTerrainSystem : private Terrain::TerrainSystemServiceRequestBus::Handler + class MockTerrainSystemService : private Terrain::TerrainSystemServiceRequestBus::Handler { public: - void Activate() override + MockTerrainSystemService() { Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect(); } - void Deactivate() override + ~MockTerrainSystemService() { Terrain::TerrainSystemServiceRequestBus::Handler::BusDisconnect(); } - void SetWorldBounds([[maybe_unused]] const AZ::Aabb& worldBounds) override - { - } - - void SetHeightQueryResolution([[maybe_unused]] AZ::Vector2 queryResolution) override - { - } + MOCK_METHOD0(Activate, void()); + MOCK_METHOD0(Deactivate, void()); - void RegisterArea([[maybe_unused]] AZ::EntityId areaId) override - { - m_registerAreaCalledCount++; - } + MOCK_METHOD1(RegisterArea, void(AZ::EntityId areaId)); + MOCK_METHOD1(UnregisterArea, void(AZ::EntityId areaId)); + MOCK_METHOD1(RefreshArea, void(AZ::EntityId areaId)); + }; - void UnregisterArea([[maybe_unused]] AZ::EntityId areaId) override + class MockTerrainDataNotificationListener : public AzFramework::Terrain::TerrainDataNotificationBus::Handler + { + public: + MockTerrainDataNotificationListener() { - m_unregisterAreaCalledCount++; + AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect(); } - void RefreshArea([[maybe_unused]] AZ::EntityId areaId) override + ~MockTerrainDataNotificationListener() { - m_refreshAreaCalledCount++; + AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusDisconnect(); } - int m_registerAreaCalledCount = 0; - int m_refreshAreaCalledCount = 0; - int m_unregisterAreaCalledCount = 0; + MOCK_METHOD0(OnTerrainDataCreateBegin, void()); + MOCK_METHOD0(OnTerrainDataCreateEnd, void()); + MOCK_METHOD0(OnTerrainDataDestroyBegin, void()); + MOCK_METHOD0(OnTerrainDataDestroyEnd, void()); + MOCK_METHOD2(OnTerrainDataChanged, void(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask)); }; + } diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp new file mode 100644 index 0000000000..3e557c66a6 --- /dev/null +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include + +#include +#include + +using ::testing::AtLeast; +using ::testing::NiceMock; + +class TerrainSystemTest : public ::testing::Test +{ +protected: + AZ::ComponentApplication m_app; + + AZStd::unique_ptr m_entity; + AZStd::unique_ptr m_terrainSystem; + + void SetUp() override + { + AZ::ComponentApplication::Descriptor appDesc; + appDesc.m_memoryBlocksByteSize = 20 * 1024 * 1024; + appDesc.m_recordingMode = AZ::Debug::AllocationRecords::RECORD_NO_RECORDS; + appDesc.m_stackRecordLevels = 20; + + m_app.Create(appDesc); + } + + void TearDown() override + { + m_terrainSystem.reset(); + m_app.Destroy(); + } + + void CreateEntity() + { + m_entity = AZStd::make_unique(); + m_entity->Init(); + + ASSERT_TRUE(m_entity); + } + + void ResetEntity() + { + m_entity->Deactivate(); + m_entity->Reset(); + } +}; + +TEST_F(TerrainSystemTest, TrivialCreateDestroy) +{ + m_terrainSystem = AZStd::make_unique(); +} + +TEST_F(TerrainSystemTest, TrivialActivateDeactivate) +{ + m_terrainSystem = AZStd::make_unique(); + m_terrainSystem->Activate(); + m_terrainSystem->Deactivate(); +} + +TEST_F(TerrainSystemTest, CreateEventsCalledOnActivation) +{ + NiceMock mockTerrainListener; + EXPECT_CALL(mockTerrainListener, OnTerrainDataCreateBegin()).Times(AtLeast(1)); + EXPECT_CALL(mockTerrainListener, OnTerrainDataCreateEnd()).Times(AtLeast(1)); + + m_terrainSystem = AZStd::make_unique(); + m_terrainSystem->Activate(); +} + +TEST_F(TerrainSystemTest, DestroyEventsCalledOnDeactivation) +{ + NiceMock mockTerrainListener; + EXPECT_CALL(mockTerrainListener, OnTerrainDataDestroyBegin()).Times(AtLeast(1)); + EXPECT_CALL(mockTerrainListener, OnTerrainDataDestroyEnd()).Times(AtLeast(1)); + + m_terrainSystem = AZStd::make_unique(); + m_terrainSystem->Activate(); + m_terrainSystem->Deactivate(); +} + + diff --git a/Gems/Terrain/Code/Tests/TerrainTest.cpp b/Gems/Terrain/Code/Tests/TerrainTest.cpp index 9b47c91a31..40217ff9bc 100644 --- a/Gems/Terrain/Code/Tests/TerrainTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainTest.cpp @@ -8,24 +8,4 @@ #include -class TerrainTest - : public ::testing::Test -{ -protected: - void SetUp() override - { - - } - - void TearDown() override - { - - } -}; - -TEST_F(TerrainTest, SanityTest) -{ - ASSERT_TRUE(true); -} - AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); diff --git a/Gems/Terrain/Code/terrain_tests_files.cmake b/Gems/Terrain/Code/terrain_tests_files.cmake index b44f143f3b..6d1cf97fd9 100644 --- a/Gems/Terrain/Code/terrain_tests_files.cmake +++ b/Gems/Terrain/Code/terrain_tests_files.cmake @@ -9,5 +9,6 @@ set(FILES Tests/TerrainMocks.h Tests/TerrainTest.cpp + Tests/TerrainSystemTest.cpp Tests/LayerSpawnerTests.cpp ) From 0cda54c84da922cc77d67c388dba43cf67d9562c Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Wed, 15 Sep 2021 09:08:06 -0700 Subject: [PATCH 132/274] Fixing copyright headers. Also removing some #includes that HitVolumes didn't need Signed-off-by: Gene Walters --- .../Multiplayer/Components/NetworkCharacterComponent.h | 5 +++-- .../Multiplayer/Components/NetworkHitVolumesComponent.h | 5 +++-- .../Code/Source/Components/NetworkCharacterComponent.cpp | 5 +++-- .../Code/Source/Components/NetworkHitVolumesComponent.cpp | 7 +++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h index 8939284d17..2599155346 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h @@ -1,6 +1,7 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project - * + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h index 74f6dcc571..1b80ba85c0 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHitVolumesComponent.h @@ -1,6 +1,7 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project - * + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp index 31be4a490d..583f01f92a 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp @@ -1,6 +1,7 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project - * + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp index e95afbdc86..0dd5fa8a01 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHitVolumesComponent.cpp @@ -1,6 +1,7 @@ /* - * Copyright (c) Contributors to the Open 3D Engine Project - * + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ @@ -11,10 +12,8 @@ #include #include #include -#include #include #include -#include namespace Multiplayer { From b53bf52e0dc0a2af6886b35478a9c65eb64e03ba Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 15 Sep 2021 09:48:08 -0700 Subject: [PATCH 133/274] Perform global deinitialization when exiting the game launcher (#4131) * Fix code that deregisters the Atom Scene subsystem from the AzFramework Scene The AzFramework Scene subsystem API is a generic container based on the type of argument that is passed to it. It maintains a vector of typeids, and only one object of any type is stored at a time. The Bootstrap system component registers the Atom scene as a `ScenePtr` (aka `AZStd::shared_ptr`) with the AzFramework Scene's generic subsystem. However, the component was previously deregistering the type by value, `RPI::Scene`. Since no subsystem for the type `RPI::Scene` was set, unsetting this type did nothing. The result was that the `RPI::Scene` object would still be around by the time that all the Atom `InstanceDatabse`s were being destroyed, resulting in a large number of errors reported about leaked instances during global shutdown. This fixes the above issue by passing the `m_defaultScene` as a parameter to `AzFramework::Scene::UnsetSubsystem`, the same value that is passed to `SetSubsystem`. This is better, because instead of providing explicit template arguments (which were specifying the incorrect type), this now allows the compiler to deduce the correct type, and the syntax is symmetric with the call to `SetSubsystem`. Signed-off-by: Chris Burel * Correctly release the AWS API from the `HttpRequestManager` module This code was incorrectly assuming that `AWSNativeSDKInit::InitializationManager::Shutdown()` would be called automatically by the `InitializationManager` itself. However, all that `InitAwsApi()` does is create an `AZ::EnvironmentVariable`, which is a ref-counted type, and stores it in a global static. That global static is defined in a static library (namely `AWSNativeSDKInit`), which is linked in to the `HttpRequestManager` dynamic lib. Because it is a global static, it has to be explicitly cleared with the call to `Shutdown()`. Otherwise the destructor of the EnvironmentVariable doesn't happen until global destruction, by which time the allocator that is supplied to the AWS SDK has already been destroyed, and the shutdown of the AWS SDK attempts to use the already-destroyed allocator. Signed-off-by: Chris Burel * Avoid blocking the remote console server thread if there are no connections The Remote console server runs in a separate thread. Previously, it would directly call `AzSock::Accept()` and block the server thread until some client connected to it. However, if no client connected, the thread would continue to be blocked, even if the game launcher tried to exit. This adds a check to see if there's a client on the socket before calling `Accept()`, to avoid the deadlock on launcher exit. Signed-off-by: Chris Burel * Fix a log message to print one message per line Signed-off-by: Chris Burel * Allow pumping the event loop to close the launcher window Events from the OS are handled in the game's main loop. The general loop looks like this: * Read events from the OS * Tick the game application One of the events that can come from the OS is that the window hosting the game is closed. When this event happens, many resources provided by the renderer are freed, and the game application's `shouldExit` bit is set. However, when the game's `Tick()` is called, there is lots of code that assumes the renderer is still there. To avoid crashing in the `Tick()` call, check if the game should exit after pumping the system events. Signed-off-by: Chris Burel * Unload the level when exiting the launcher This ensures that any resources held onto by the level are freed before the launcher exits. Signed-off-by: Chris Burel * Add an explicit bus `Disconnect()` call to `AZCoreLogSink` This is necessary because this bus has virtual functions and can be called from multiple threads. Signed-off-by: Chris Burel * Allow normal cleanup to take place when exiting the game launcher Previously, global cleanup was side-stepped by calling `TerminateProcess` or `exit`, when quitting the game launcher. This is in contrast to the call to `_exit` on Linux and Mac when exiting the Editor. That leading `_` makes a big difference: the former runs object destruction, the latter does not. Instead of making the launcher exit with `_exit` on Linux, instead, remove that call and actually run all the atexit code. This does not modify the Editor's behavior however. It still uses `_exit` and `TerminateProcess`. Signed-off-by: Chris Burel --- .../AzFramework/Archive/Archive.cpp | 2 +- Code/LauncherUnified/Launcher.cpp | 11 +++++---- Code/Legacy/CrySystem/AZCoreLogSink.h | 5 ++++ .../CrySystem/LevelSystem/LevelSystem.cpp | 1 + Code/Legacy/CrySystem/System.cpp | 23 ------------------- .../RemoteConsole/Core/RemoteConsoleCore.cpp | 5 ++++ .../Code/Source/BootstrapSystemComponent.cpp | 2 +- .../Code/Source/HttpRequestManager.cpp | 3 +-- 8 files changed, 20 insertions(+), 32 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index 012d713cf5..1891c50d10 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -2185,7 +2185,7 @@ namespace AZ::IO AZStd::unique_lock lock(m_archiveMutex); if (pArchive) { - AZ_TracePrintf("Archive", "Closing Archive file: %s", pArchive->GetFullPath()); + AZ_TracePrintf("Archive", "Closing Archive file: %s\n", pArchive->GetFullPath()); } ArchiveArray::iterator it; if (m_arrArchives.size() < 16) diff --git a/Code/LauncherUnified/Launcher.cpp b/Code/LauncherUnified/Launcher.cpp index de4c496b2a..27aab074ef 100644 --- a/Code/LauncherUnified/Launcher.cpp +++ b/Code/LauncherUnified/Launcher.cpp @@ -232,13 +232,17 @@ namespace // our frame time to be managed by AzGameFramework::GameApplication // instead, which probably isn't going to happen anytime soon given // how many things depend on the ITimer interface). - bool continueRunning = true; ISystem* system = gEnv ? gEnv->pSystem : nullptr; - while (continueRunning) + while (!gameApplication.WasExitMainLoopRequested()) { // Pump the system event loop gameApplication.PumpSystemEventLoopUntilEmpty(); + if (gameApplication.WasExitMainLoopRequested()) + { + break; + } + // Update the AzFramework system tick bus gameApplication.TickSystem(); @@ -256,9 +260,6 @@ namespace { system->UpdatePostTickBus(); } - - // Check for quit requests - continueRunning = !gameApplication.WasExitMainLoopRequested() && continueRunning; } } } diff --git a/Code/Legacy/CrySystem/AZCoreLogSink.h b/Code/Legacy/CrySystem/AZCoreLogSink.h index e824c4c172..a54a78157c 100644 --- a/Code/Legacy/CrySystem/AZCoreLogSink.h +++ b/Code/Legacy/CrySystem/AZCoreLogSink.h @@ -31,6 +31,11 @@ class AZCoreLogSink : public AZ::Debug::TraceMessageBus::Handler { public: + ~AZCoreLogSink() + { + Disconnect(); + } + inline static void Connect() { GetInstance().m_ignoredAsserts = new IgnoredAssertMap(); diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index a0338941b5..c5d364a025 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -233,6 +233,7 @@ CLevelSystem::CLevelSystem(ISystem* pSystem, const char* levelsFolder) //------------------------------------------------------------------------ CLevelSystem::~CLevelSystem() { + UnloadLevel(); } //------------------------------------------------------------------------ diff --git a/Code/Legacy/CrySystem/System.cpp b/Code/Legacy/CrySystem/System.cpp index 4a9d9ece5f..2e18e13841 100644 --- a/Code/Legacy/CrySystem/System.cpp +++ b/Code/Legacy/CrySystem/System.cpp @@ -548,29 +548,6 @@ void CSystem::Quit() logger->Flush(); } - /* - * TODO: This call to _exit, _Exit, TerminateProcess etc. needs to - * eventually be removed. This causes an extremely early exit before we - * actually perform cleanup. When this gets called most managers are - * simply never deleted and we leave it to the OS to clean up our mess - * which is just really bad practice. However there are LOTS of issues - * with shutdown at the moment. Removing this will simply cause - * a crash when either the Editor or Launcher initiate shutdown. Both - * applications crash differently too. Bugs will be logged about those - * issues. - */ -#if defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_4 -#include AZ_RESTRICTED_FILE(System_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(WIN32) || defined(WIN64) - TerminateProcess(GetCurrentProcess(), m_env.retCode); -#else - exit(m_env.retCode); -#endif - #ifdef WIN32 //Post a WM_QUIT message to the Win32 api which causes the message loop to END //This is not the same as handling a WM_DESTROY event which destroys a window diff --git a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp index d0e9e6a760..0a8d9d8eb7 100644 --- a/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp +++ b/Code/Tools/RemoteConsole/Core/RemoteConsoleCore.cpp @@ -239,6 +239,11 @@ void SRemoteServer::Run() while (m_bAcceptClients) { + AZTIMEVAL timeout { 1, 0 }; + if (!AZ::AzSock::IsRecvPending(m_socket, &timeout)) + { + continue; + } AZ::AzSock::AzSocketAddress clientAddress; sClient = AZ::AzSock::Accept(m_socket, clientAddress); if (!m_bAcceptClients || !AZ::AzSock::IsAzSocketValid(sClient)) diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index 97faa7380f..ddd88a1f52 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -386,7 +386,7 @@ namespace AZ // Unbind m_defaultScene to the GameEntityContext's AzFramework::Scene if (m_defaultFrameworkScene) { - m_defaultFrameworkScene->UnsetSubsystem(); + m_defaultFrameworkScene->UnsetSubsystem(m_defaultScene); } m_defaultScene = nullptr; diff --git a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp index 8ed40c1599..523d84f0f5 100644 --- a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp +++ b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp @@ -35,7 +35,6 @@ namespace HttpRequestor desc.m_name = s_loggingName; desc.m_cpuId = AFFINITY_MASK_USERTHREADS; m_runThread = true; - // Shutdown will be handled by the InitializationManager - no need to call in the destructor AWSNativeSDKInit::InitializationManager::InitAwsApi(); auto function = AZStd::bind(&Manager::ThreadFunction, this); m_thread = AZStd::thread(function, &desc); @@ -43,7 +42,7 @@ namespace HttpRequestor Manager::~Manager() { - // NativeSDK Shutdown does not need to be called here - will be taken care of by the InitializationManager + AWSNativeSDKInit::InitializationManager::Shutdown(); m_runThread = false; m_requestConditionVar.notify_all(); if (m_thread.joinable()) From c2864e2ec035455856e190120f927a63ec681ca7 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 15 Sep 2021 09:49:28 -0700 Subject: [PATCH 134/274] used a CMake 3.21 function, but that is not the min version we support Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/VisualStudio_common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Common/MSVC/VisualStudio_common.cmake b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake index d9e58090d9..7de7da3cc7 100644 --- a/cmake/Platform/Common/MSVC/VisualStudio_common.cmake +++ b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake @@ -15,4 +15,4 @@ foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) endforeach() configure_file("${CMAKE_CURRENT_LIST_DIR}/Directory.Build.props" "${CMAKE_BINARY_DIR}/Directory.Build.props" @ONLY) -file(COPY_FILE "${CMAKE_CURRENT_LIST_DIR}/CodeAnalysis.ruleset" "${CMAKE_BINARY_DIR}/CodeAnalysis.ruleset" ONLY_IF_DIFFERENT) +file(COPY "${CMAKE_CURRENT_LIST_DIR}/CodeAnalysis.ruleset" "${CMAKE_BINARY_DIR}/CodeAnalysis.ruleset") From a5306f10f346ff465b0805b1279ed493b6af732a Mon Sep 17 00:00:00 2001 From: smurly Date: Wed, 15 Sep 2021 11:27:26 -0700 Subject: [PATCH 135/274] Reflection Probe component added to AtomEditorComponents test (#4135) Signed-off-by: Scott Murray --- ...ydra_AtomEditorComponents_AddedToEntity.py | 22 +++++++++++++++++-- .../atom_renderer/test_Atom_MainSuite.py | 15 +++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py index cd10caf57b..a2e950e1dc 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py @@ -3,8 +3,6 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. SPDX-License-Identifier: Apache-2.0 OR MIT - -Hydra script that creates an entity and attaches Atom components to it for test verification. """ import os @@ -17,6 +15,7 @@ import azlmbr.asset as asset import azlmbr.entity as entity import azlmbr.legacy.general as general import azlmbr.editor as editor +import azlmbr.render as render sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) @@ -125,6 +124,19 @@ def run(): def verify_set_property(entity_obj, path, value): entity_obj.get_set_test(0, path, value) + # Verify cubemap generation + def verify_cubemap_generation(component_name, entity_obj): + # Initially Check if the component has Reflection Probe component + if not hydra.has_components(entity_obj.id, ["Reflection Probe"]): + raise ValueError(f"Given entity {entity_obj.name} has no Reflection Probe component") + render.EditorReflectionProbeBus(azlmbr.bus.Event, "BakeReflectionProbe", entity_obj.id) + + def get_value(): + hydra.get_component_property_value(entity_obj.components[0], "Cubemap|Baked Cubemap Path") + + TestHelper.wait_for_condition(lambda: get_value() != "", 20.0) + general.log(f"{component_name}_test: Cubemap is generated: {get_value() != ''}") + # Wait for Editor idle loop before executing Python hydra scripts. TestHelper.init_idle() @@ -215,6 +227,12 @@ def run(): # Display Mapper Component ComponentTests("Display Mapper") + # Reflection Probe Component + reflection_probe = "Reflection Probe" + ComponentTests( + reflection_probe, + lambda entity_obj: verify_required_component_addition(entity_obj, ["Box Shape"], reflection_probe), + lambda entity_obj: verify_cubemap_generation(reflection_probe, entity_obj),) if __name__ == "__main__": run() diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index ce496ce268..16e281e494 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -161,6 +161,21 @@ class TestAtomEditorComponentsMain(object): "Display Mapper_test: Entity deleted: True", "Display Mapper_test: UNDO entity deletion works: True", "Display Mapper_test: REDO entity deletion works: True", + # Reflection Probe Component + "Reflection Probe Entity successfully created", + "Reflection Probe_test: Component added to the entity: True", + "Reflection Probe_test: Component removed after UNDO: True", + "Reflection Probe_test: Component added after REDO: True", + "Reflection Probe_test: Entered game mode: True", + "Reflection Probe_test: Exit game mode: True", + "Reflection Probe_test: Entity disabled initially: True", + "Reflection Probe_test: Entity enabled after adding required components: True", + "Reflection Probe_test: Cubemap is generated: True", + "Reflection Probe_test: Entity is hidden: True", + "Reflection Probe_test: Entity is shown: True", + "Reflection Probe_test: Entity deleted: True", + "Reflection Probe_test: UNDO entity deletion works: True", + "Reflection Probe_test: REDO entity deletion works: True", ] unexpected_lines = [ From 2c464c3ee0dc79775d77c32780b8cc2e9212c833 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:35:09 -0700 Subject: [PATCH 136/274] Updated the ScopedValue constructor per code review feedback. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h b/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h index 8cb985cffe..f6ed6d6df4 100644 --- a/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h +++ b/Code/Framework/AtomCore/AtomCore/Utils/ScopedValue.h @@ -20,11 +20,11 @@ namespace AZ T m_finalValue; public: - ScopedValue(T* ptr, T initialValue, T finalValue) + ScopedValue(T* ptr, T initialValue, T finalValue) : + m_ptr(ptr), m_finalValue(finalValue) { - m_ptr = ptr; + AZ_Assert(m_ptr, "ScopedValue::m_ptr is null"); *m_ptr = initialValue; - m_finalValue = finalValue; } ~ScopedValue() From 9cba144e3942356b7bb93e7338b41ea59c3943ee Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:44:45 -0700 Subject: [PATCH 137/274] forgot destination Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- cmake/Platform/Common/MSVC/VisualStudio_common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Common/MSVC/VisualStudio_common.cmake b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake index 7de7da3cc7..843b3dcd9d 100644 --- a/cmake/Platform/Common/MSVC/VisualStudio_common.cmake +++ b/cmake/Platform/Common/MSVC/VisualStudio_common.cmake @@ -15,4 +15,4 @@ foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) endforeach() configure_file("${CMAKE_CURRENT_LIST_DIR}/Directory.Build.props" "${CMAKE_BINARY_DIR}/Directory.Build.props" @ONLY) -file(COPY "${CMAKE_CURRENT_LIST_DIR}/CodeAnalysis.ruleset" "${CMAKE_BINARY_DIR}/CodeAnalysis.ruleset") +file(COPY "${CMAKE_CURRENT_LIST_DIR}/CodeAnalysis.ruleset" DESTINATION "${CMAKE_BINARY_DIR}") From 346e2d9f663b27ef0b4a29afe7450fb330b53510 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 15 Sep 2021 13:26:48 -0700 Subject: [PATCH 138/274] Fixed unit test compile issues, and added a unit test for PSO handling setting. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Material/LuaMaterialFunctorTests.cpp | 43 ++++++++++++++++++- .../Tests/Material/MaterialFunctorTests.cpp | 12 ++++-- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp index 99efa38c3a..37d0930d97 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/LuaMaterialFunctorTests.cpp @@ -1039,6 +1039,42 @@ namespace UnitTest drawListTagRegistry->ReleaseTag(tag); } + + TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_PsoChangesNotAllowed_Error) + { + using namespace AZ::RPI; + + const char* functorScript = + R"( + function GetMaterialPropertyDependencies() + return {"general.MyBool"} + end + + function GetShaderOptionDependencies() + return {} + end + + function Process(context) + local boolValue = context:GetMaterialPropertyValue_bool("general.MyBool") + if(boolValue) then + context:GetShader(0):GetRenderStatesOverride():SetFillMode(FillMode_Wireframe) + else + context:GetShader(0):GetRenderStatesOverride():ClearFillMode() + end + end + )"; + + TestMaterialData testData; + testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript); + + testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true}); + + ErrorMessageFinder errorMessageFinder; + + errorMessageFinder.AddExpectedErrorMessage("not be changed at runtime because they impact Pipeline State Objects: general.MyBool"); + EXPECT_TRUE(testData.GetMaterial()->Compile()); + errorMessageFinder.CheckExpectedErrorsFound(); + } TEST_F(LuaMaterialFunctorTests, LuaMaterialFunctor_RuntimeContext_MultisampleCustomPositionCountIndex_Error) { @@ -1067,6 +1103,7 @@ namespace UnitTest TestMaterialData testData; testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript); + testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed); testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true}); ErrorMessageFinder errorMessageFinder; @@ -1107,7 +1144,8 @@ namespace UnitTest errorMessageFinder.AddExpectedErrorMessage("ClearMultisampleCustomPosition(18,...) index is out of range. Must be less than 16."); testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript); errorMessageFinder.CheckExpectedErrorsFound(); - + + testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed); testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true}); errorMessageFinder.AddExpectedErrorMessage("SetMultisampleCustomPosition(17,...) index is out of range. Must be less than 16."); @@ -1146,7 +1184,8 @@ namespace UnitTest errorMessageFinder.AddExpectedErrorMessage("ClearBlendEnabled(10,...) index is out of range. Must be less than 8."); testData.Setup(MaterialPropertyDataType::Bool, "general.MyBool", functorScript); errorMessageFinder.CheckExpectedErrorsFound(); - + + testData.GetMaterial()->SetPsoHandlingOverride(AZ::RPI::MaterialPropertyPsoHandling::Allowed); testData.GetMaterial()->SetPropertyValue(testData.GetMaterialPropertyIndex(), MaterialPropertyValue{true}); errorMessageFinder.AddExpectedErrorMessage("SetBlendEnabled(9,...) index is out of range. Must be less than 8."); diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp index 0c84484508..6cd84b6e4c 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialFunctorTests.cpp @@ -165,7 +165,8 @@ namespace UnitTest materialTypeAsset->GetMaterialPropertiesLayout(), &shaderCollectionCopy, unusedSrg, - &testFunctorSetOptionA.GetMaterialPropertyDependencies() + &testFunctorSetOptionA.GetMaterialPropertyDependencies(), + AZ::RPI::MaterialPropertyPsoHandling::Allowed }; testFunctorSetOptionA.Process(runtimeContext); EXPECT_TRUE(testFunctorSetOptionA.GetProcessResult()); @@ -181,7 +182,8 @@ namespace UnitTest materialTypeAsset->GetMaterialPropertiesLayout(), &shaderCollectionCopy, unusedSrg, - &testFunctorSetOptionB.GetMaterialPropertyDependencies() + &testFunctorSetOptionB.GetMaterialPropertyDependencies(), + AZ::RPI::MaterialPropertyPsoHandling::Allowed }; testFunctorSetOptionB.Process(runtimeContext); EXPECT_TRUE(testFunctorSetOptionB.GetProcessResult()); @@ -198,7 +200,8 @@ namespace UnitTest materialTypeAsset->GetMaterialPropertiesLayout(), &shaderCollectionCopy, unusedSrg, - &testFunctorSetOptionC.GetMaterialPropertyDependencies() + &testFunctorSetOptionC.GetMaterialPropertyDependencies(), + AZ::RPI::MaterialPropertyPsoHandling::Allowed }; testFunctorSetOptionC.Process(runtimeContext); EXPECT_FALSE(testFunctorSetOptionC.GetProcessResult()); @@ -213,7 +216,8 @@ namespace UnitTest materialTypeAsset->GetMaterialPropertiesLayout(), &shaderCollectionCopy, unusedSrg, - &testFunctorSetOptionInvalid.GetMaterialPropertyDependencies() + &testFunctorSetOptionInvalid.GetMaterialPropertyDependencies(), + AZ::RPI::MaterialPropertyPsoHandling::Allowed }; testFunctorSetOptionInvalid.Process(runtimeContext); EXPECT_FALSE(testFunctorSetOptionInvalid.GetProcessResult()); From c50f3b263885c0716e4bc2344cceb2719fac8034 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Wed, 15 Sep 2021 14:03:45 -0700 Subject: [PATCH 139/274] Fix the destruction failure and update the instructions for running automation tests (#4124) Signed-off-by: Junbo Liang --- AutomatedTesting/Gem/PythonTests/AWS/README.md | 2 +- .../aws_metrics/aws_metrics_automation_test.py | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/AWS/README.md b/AutomatedTesting/Gem/PythonTests/AWS/README.md index 1429fc487f..1bb36f178d 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/README.md +++ b/AutomatedTesting/Gem/PythonTests/AWS/README.md @@ -11,7 +11,7 @@ 3. Open a new Command Prompt window at the engine root and set the following environment variables: Set O3DE_AWS_PROJECT_NAME=AWSAUTO Set O3DE_AWS_DEPLOY_REGION=us-east-1 - Set ASSUME_ROLE_ARN="arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests" + Set ASSUME_ROLE_ARN=arn:aws:iam::{your_aws_account_id}:role/o3de-automation-tests Set COMMIT_ID=HEAD 4. In the same Command Prompt window, Deploy the CDK applications for AWS gems by running deploy_cdk_applications.cmd. diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py index a0a53f92b5..5f6103c46a 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py +++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py @@ -139,7 +139,6 @@ def update_kinesis_analytics_application_status(aws_metrics_utils: pytest.fixtur @pytest.mark.usefixtures('resource_mappings') @pytest.mark.parametrize('assume_role_arn', [constants.ASSUME_ROLE_ARN]) @pytest.mark.parametrize('feature_name', [AWS_METRICS_FEATURE_NAME]) -@pytest.mark.parametrize('level', ['AWS/Metrics']) @pytest.mark.parametrize('profile_name', ['AWSAutomationTest']) @pytest.mark.parametrize('project', ['AutomatedTesting']) @pytest.mark.parametrize('region_name', [constants.AWS_REGION]) @@ -150,6 +149,7 @@ class TestAWSMetricsWindows(object): """ Test class to verify the real-time and batch analytics for metrics. """ + @pytest.mark.parametrize('level', ['AWS/Metrics']) def test_realtime_and_batch_analytics(self, level: str, launcher: pytest.fixture, @@ -201,10 +201,7 @@ class TestAWSMetricsWindows(object): for thread in operational_threads: thread.join() - # Clear the analytics bucket objects so that the S3 bucket can be destroyed during tear down. - aws_metrics_utils.empty_bucket( - resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName')) - + @pytest.mark.parametrize('level', ['AWS/Metrics']) def test_unauthorized_user_request_rejected(self, level: str, launcher: pytest.fixture, @@ -227,3 +224,13 @@ class TestAWSMetricsWindows(object): halt_on_unexpected=True) assert result, 'Metrics events are sent successfully by unauthorized user' logger.info('Unauthorized user is rejected to send metrics.') + + def test_clean_up_s3_bucket(self, + aws_utils: pytest.fixture, + resource_mappings: pytest.fixture, + aws_metrics_utils: pytest.fixture): + """ + Clear the analytics bucket objects so that the S3 bucket can be destroyed during tear down. + """ + aws_metrics_utils.empty_bucket( + resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName')) From b2445ebe0cebbc37bea3f47221dca64a1adf6fae Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Wed, 15 Sep 2021 14:28:50 -0700 Subject: [PATCH 140/274] Add color grading pass into main pipeline (#4005) * Add HDR color grading pass and shaders. Signed-off-by: Robin * Improve code quality. Signed-off-by: Robin * Code refactor. Signed-off-by: Robin * Remove color grading pass from light adaptation parent pass due to failing ASV tests. This will be added back later on. Signed-off-by: Robin * Add newline. Signed-off-by: Robin * Correct case for file. Signed-off-by: Robin * Update comment. Signed-off-by: Robin Co-authored-by: Robin --- .../Common/Assets/Passes/HDRColorGrading.pass | 215 ++++++++++++ .../Assets/Passes/PassTemplates.azasset | 6 +- .../Features/PostProcessing/KelvinToRgb.azsli | 75 +++++ .../PSstyleColorBlends_NonSeparable.azsli | 177 ++++++++++ .../PSstyleColorBlends_Separable.azsli | 306 ++++++++++++++++++ .../GeneratedTransforms/AcesCcToAcesCg.azsli | 80 +++++ .../GeneratedTransforms/AcesCgToAcesCc.azsli | 79 +++++ .../ColorManagement/TransformColor.azsli | 45 ++- .../PostProcessing/HDRColorGrading.azsl | 206 ++++++++++++ .../PostProcessing/HDRColorGrading.shader | 22 ++ .../atom_feature_common_asset_files.cmake | 8 + 11 files changed, 1217 insertions(+), 2 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader diff --git a/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass b/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass new file mode 100644 index 0000000000..f1e8304b30 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass @@ -0,0 +1,215 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "HDRColorGradingTemplate", + "PassClass": "FullScreenTriangle", + "Slots": [ + { + "Name": "Input", + "SlotType": "Input", + "ShaderInputName": "m_framebuffer", + "ScopeAttachmentUsage": "Shader" + }, + { + "Name": "Output", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "LoadStoreAction": { + "LoadAction": "DontCare" + } + } + ], + "ImageAttachments": [ + { + "Name": "ColorGradingOutput", + "SizeSource": { + "Source": { + "Pass": "This", + "Attachment": "Input" + } + }, + "FormatSource": { + "Pass": "This", + "Attachment": "Input" + } + } + ], + "Connections": [ + { + "LocalSlot": "Output", + "AttachmentRef": { + "Pass": "This", + "Attachment": "ColorGradingOutput" + } + } + ], + "FallbackConnections": [ + { + "Input": "Input", + "Output": "Output" + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/HDRColorGrading.shader" + }, + "ShaderDataMappings": { + "FloatMappings": [ + { + "Name": "m_colorGradingExposure", + "Value": 0.0 // unconstrained, log2 stops + }, + { + "Name": "m_colorGradingContrast", + "Value": 0.0 // -100 ... 100 + }, + { + "Name": "m_colorGradingHueShift", + "Value": 0.0 // 0 ... 1, can wrap + }, + { + "Name": "m_colorGradingPreSaturation", + "Value": 1.0 // -100 ... 100 + }, + { + "Name": "m_colorFilterIntensity", + "Value": 1.0 // unconstrained, log2 stops + }, + { + "Name": "m_colorFilterMultiply", + "Value": 0.0 // modulate, 0 ... 1 + }, + { + "Name": "m_whiteBalanceKelvin", + "Value": 6500.0 // 1000.0f ... 40000.0f kelvin + }, + { + "Name": "m_whiteBalanceTint", + "Value": 0.0 // -100 ... 100 + }, + { + "Name": "m_splitToneBalance", + "Value": 0.0 // -1 ... 1 + }, + { + "Name": "m_splitToneMix", + "Value": 0.0 // 0 ... 1 + }, + { + "Name": "m_colorGradingPostSaturation", + "Value": 1.0 // -100 ... 100 + }, + { + "Name": "m_smhShadowsStart", + "Value": 0.0 // 0 ... 1 + }, + { + "Name": "m_smhShadowsEnd", + "Value": 0.3 // 0 ... 1 + }, + { + "Name": "m_smhHighlightsStart", + "Value": 0.55 // 0 ... 1 + }, + { + "Name": "m_smhHighlightsEnd", + "Value": 1.0 // 0 ... 1 + }, + { + "Name": "m_smhMix", + "Value": 0.0 // 0 ... 1 + } + ], + // The colors defined here are expected to be in linear rgb color space. + // These are converted to ACEScg color space within the HDRColorGrading.azsl shader + "ColorMappings": [ + { + "Name": "m_colorFilterSwatch", + "Value": [ + 1.0, + 0.5, + 0.5, + 1.0 + ] + }, + { + "Name": "m_splitToneShadowsColor", + "Value": [ + 1.0, + 0.1, + 0.1, + 1.0 + ] + }, + { + "Name": "m_splitToneHighlightsColor", + "Value": [ + 0.1, + 1.0, + 0.1, + 1.0 + ] + }, + { + "Name": "m_smhShadowsColor", + "Value": [ + 1.0, + 0.25, + 0.25, + 1.0 + ] + }, + { + "Name": "m_smhMidtonesColor", + "Value": [ + 0.1, + 0.1, + 1.0, + 1.0 + ] + }, + { + "Name": "m_smhHighlightsColor", + "Value": [ + 1.0, + 0.0, + 1.0, + 1.0 + ] + } + ], + "Float3Mappings": [ + { + "Name": "m_channelMixingRed", + "Value": [ + 1.0, + 0.0, + 0.0 + ] + }, + { + "Name": "m_channelMixingGreen", + "Value": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "Name": "m_channelMixingBlue", + "Value": [ + 0.0, + 0.0, + 1.0 + ] + } + ] + } + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset index 8b7d6a8438..4e38717d31 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset +++ b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset @@ -499,7 +499,11 @@ { "Name": "KawaseShadowBlurTemplate", "Path": "Passes/KawaseShadowBlur.pass" - } + }, + { + "Name": "HDRColorGradingTemplate", + "Path": "Passes/HDRColorGrading.pass" + } ] } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli new file mode 100644 index 0000000000..aa57f0f4a1 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli @@ -0,0 +1,75 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) AND Creative Commons 3.0 + * + */ + +// Ref: https://www.shadertoy.com/view/lsSXW1 +// ported by Renaud Bédard (@renaudbedard) from original code from Tanner Helland +// http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/ + +// color space functions translated from HLSL versions on Chilli Ant (by Ian Taylor) +// http://www.chilliant.com/rgb2hsv.html + +// licensed and released under Creative Commons 3.0 Attribution +// https://creativecommons.org/licenses/by/3.0/ + +float3 HueToRgb(float hue) +{ + return saturate(float3(abs(hue * 6.0f - 3.0f) - 1.0f, + 2.0f - abs(hue * 6.0f - 2.0f), + 2.0f - abs(hue * 6.0f - 4.0f))); +} + +float3 RgbToHcv(float3 rgb) +{ + // Based on work by Sam Hocevar and Emil Persson + const float4 p = (rgb.g < rgb.b) ? float4(rgb.bg, -1.0f, 2.0f/3.0f) : float4(rgb.gb, 0.0f, -1.0f/3.0f); + const float4 q1 = (rgb.r < p.x) ? float4(p.xyw, rgb.r) : float4(rgb.r, p.yzx); + const float c = q1.x - min(q1.w, q1.y); + const float h = abs((q1.w - q1.y) / (6.0f * c + 0.000001f ) + q1.z); + return float3(h, c, q1.x); +} + +float3 RgbToHsl(float3 rgb) +{ + rgb.xyz = max(rgb.xyz, 0.000001f); + const float3 hcv = RgbToHcv(rgb); + const float L = hcv.z - hcv.y * 0.5f; + const float S = hcv.y / (1.0f - abs(L * 2.0f - 1.0f) + 0.000001f); + return float3(hcv.x, S, L); +} + +float3 HslToRgb(float3 hsl) +{ + const float3 rgb = HueToRgb(hsl.x); + const float c = (1.0f - abs(2.0f * hsl.z - 1.0f)) * hsl.y; + return (rgb - 0.5f) * c + hsl.z; +} + +// Color temperature +float3 KelvinToRgb(float kelvin) +{ + float3 ret; + kelvin = clamp(kelvin, 1000.0f, 40000.0f) / 100.0f; + if(kelvin <= 66.0f) + { + ret.r = 1.0f; + ret.g = saturate(0.39008157876901960784f * log(kelvin) - 0.63184144378862745098f); + } + else + { + float t = max(kelvin - 60.0f, 0.0f); + ret.r = saturate(1.29293618606274509804f * pow(t, -0.1332047592f)); + ret.g = saturate(1.12989086089529411765f * pow(t, -0.0755148492f)); + } + if(kelvin >= 66.0f) + ret.b = 1.0f; + else if(kelvin < 19.0f) + ret.b = 0.0f; + else + ret.b = saturate(0.54320678911019607843f * log(kelvin - 10.0f) - 1.19625408914f); + return ret; +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli new file mode 100644 index 0000000000..9c2a5bc306 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli @@ -0,0 +1,177 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +/* +------------------------------------------------------------------------------ + Public Domain +------------------------------------------------------------------------------ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + +Source: https://www.ryanjuckett.com/photoshop-blend-modes-in-hlsl/ +*/ +//****************************************************************************** +//****************************************************************************** +float Color_GetLuminosity(float3 c) +{ + return 0.3*c.r + 0.59*c.g + 0.11*c.b; +} + +//****************************************************************************** +//****************************************************************************** +float3 Color_SetLuminosity(float3 c, float lum) +{ + float d = lum - Color_GetLuminosity(c); + c.rgb += float3(d,d,d); + + // clip back into legal range + lum = Color_GetLuminosity(c); + float cMin = min(c.r, min(c.g, c.b)); + float cMax = max(c.r, max(c.g, c.b)); + + if(cMin < 0) + c = lerp(float3(lum,lum,lum), c, lum / (lum - cMin)); + + if(cMax > 1) + c = lerp(float3(lum,lum,lum), c, (1 - lum) / (cMax - lum)); + + return c; +} + +//****************************************************************************** +//****************************************************************************** +float Color_GetSaturation(float3 c) +{ + return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b)); +} + +//****************************************************************************** +// Set saturation if color components are sorted in ascending order. +//****************************************************************************** +float3 Color_SetSaturation_MinMidMax(float3 cSorted, float s) +{ + if(cSorted.z > cSorted.x) + { + cSorted.y = (((cSorted.y - cSorted.x) * s) / (cSorted.z - cSorted.x)); + cSorted.z = s; + } + else + { + cSorted.y = 0; + cSorted.z = 0; + } + + cSorted.x = 0; + + return cSorted; +} + +//****************************************************************************** +//****************************************************************************** +float3 Color_SetSaturation(float3 c, float s) +{ + if (c.r <= c.g && c.r <= c.b) + { + if (c.g <= c.b) + c.rgb = Color_SetSaturation_MinMidMax(c.rgb, s); + else + c.rbg = Color_SetSaturation_MinMidMax(c.rbg, s); + } + else if (c.g <= c.r && c.g <= c.b) + { + if (c.r <= c.b) + c.grb = Color_SetSaturation_MinMidMax(c.grb, s); + else + c.gbr = Color_SetSaturation_MinMidMax(c.gbr, s); + } + else + { + if (c.r <= c.g) + c.brg = Color_SetSaturation_MinMidMax(c.brg, s); + else + c.bgr = Color_SetSaturation_MinMidMax(c.bgr, s); + } + + return c; +} + +//****************************************************************************** +// Creates a color with the hue of the blend color and the saturation and +// luminosity of the base color. +//****************************************************************************** +float3 BlendMode_Hue(float3 base, float3 blend) +{ + return Color_SetLuminosity(Color_SetSaturation(blend, Color_GetSaturation(base)), Color_GetLuminosity(base)); +} + +//****************************************************************************** +// Creates a color with the saturation of the blend color and the hue and +// luminosity of the base color. +//****************************************************************************** +float3 BlendMode_Saturation(float3 base, float3 blend) +{ + return Color_SetLuminosity(Color_SetSaturation(base, Color_GetSaturation(blend)), Color_GetLuminosity(base)); +} + +//****************************************************************************** +// Creates a color with the hue and saturation of the blend color and the +// luminosity of the base color. +//****************************************************************************** +float3 BlendMode_Color(float3 base, float3 blend) +{ + return Color_SetLuminosity(blend, Color_GetLuminosity(base)); +} + +//****************************************************************************** +// Creates a color with the luminosity of the blend color and the hue and +// saturation of the base color. +//****************************************************************************** +float3 BlendMode_Luminosity(float3 base, float3 blend) +{ + return Color_SetLuminosity(base, Color_GetLuminosity(blend)); +} + +//****************************************************************************** +// Compares the total of all channel values for the blend and base color and +// displays the lower value color. +//****************************************************************************** +float3 BlendMode_DarkerColor(float3 base, float3 blend) +{ + return Color_GetLuminosity(base) <= Color_GetLuminosity(blend) ? base : blend; +} + +//****************************************************************************** +// Compares the total of all channel values for the blend and base color and +// displays the higher value color. +//****************************************************************************** +float3 BlendMode_LighterColor(float3 base, float3 blend) +{ + return Color_GetLuminosity(base) > Color_GetLuminosity(blend) ? base : blend; +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli new file mode 100644 index 0000000000..f64df30231 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli @@ -0,0 +1,306 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +/* +------------------------------------------------------------------------------ + Public Domain +------------------------------------------------------------------------------ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to + +Source: https://www.ryanjuckett.com/photoshop-blend-modes-in-hlsl/ +*/ +//****************************************************************************** +// Selects the blend color, ignoring the base. +//****************************************************************************** +float3 BlendMode_Normal(float3 base, float3 blend) +{ + return blend; +} + +//****************************************************************************** +// Looks at the color information in each channel and selects the base or blend +// color—whichever is darker—as the result color. +//****************************************************************************** +float3 BlendMode_Darken(float3 base, float3 blend) +{ + return min(base, blend); +} + +//****************************************************************************** +// Looks at the color information in each channel and multiplies the base color +// by the blend color. +//****************************************************************************** +float3 BlendMode_Multiply(float3 base, float3 blend) +{ + return base*blend; +} + +//****************************************************************************** +// Looks at the color information in each channel and darkens the base color to +// reflect the blend color by increasing the contrast between the two. +//****************************************************************************** +float BlendMode_ColorBurn(float base, float blend) +{ + return blend > 0 ? 1 - min(1, (1-base) / blend) : 0; +} + +float3 BlendMode_ColorBurn(float3 base, float3 blend) +{ + return float3( BlendMode_ColorBurn(base.r, blend.r), + BlendMode_ColorBurn(base.g, blend.g), + BlendMode_ColorBurn(base.b, blend.b) ); +} + +//****************************************************************************** +// Looks at the color information in each channel and darkens the base color to +// reflect the blend color by decreasing the brightness. +//****************************************************************************** +float BlendMode_LinearBurn(float base, float blend) +{ + return max(0, base + blend - 1); +} + +float3 BlendMode_LinearBurn(float3 base, float3 blend) +{ + return float3( BlendMode_LinearBurn(base.r, blend.r), + BlendMode_LinearBurn(base.g, blend.g), + BlendMode_LinearBurn(base.b, blend.b) ); +} + +//****************************************************************************** +// Looks at the color information in each channel and selects the base or blend +// color—whichever is lighter—as the result color. +//****************************************************************************** +float3 BlendMode_Lighten(float3 base, float3 blend) +{ + return max(base, blend); +} + +//****************************************************************************** +// Looks at each channel’s color information and multiplies the inverse of the +// blend and base colors. +//****************************************************************************** +float3 BlendMode_Screen(float3 base, float3 blend) +{ + return base + blend - base*blend; +} + +//****************************************************************************** +// Looks at the color information in each channel and brightens the base color +// to reflect the blend color by decreasing contrast between the two. +//****************************************************************************** +float BlendMode_ColorDodge(float base, float blend) +{ + return blend < 1 ? min(1, base / (1-blend)) : 1; +} + +float3 BlendMode_ColorDodge(float3 base, float3 blend) +{ + return float3( BlendMode_ColorDodge(base.r, blend.r), + BlendMode_ColorDodge(base.g, blend.g), + BlendMode_ColorDodge(base.b, blend.b) ); +} + +//****************************************************************************** +// Looks at the color information in each channel and brightens the base color +// to reflect the blend color by decreasing contrast between the two. +//****************************************************************************** +float BlendMode_LinearDodge(float base, float blend) +{ + return min(1, base + blend); +} + +float3 BlendMode_LinearDodge(float3 base, float3 blend) +{ + return float3( BlendMode_LinearDodge(base.r, blend.r), + BlendMode_LinearDodge(base.g, blend.g), + BlendMode_LinearDodge(base.b, blend.b) ); +} + +//****************************************************************************** +// Multiplies or screens the colors, depending on the base color. +//****************************************************************************** +float BlendMode_Overlay(float base, float blend) +{ + return (base <= 0.5) ? 2*base*blend : 1 - 2*(1-base)*(1-blend); +} + +float3 BlendMode_Overlay(float3 base, float3 blend) +{ + return float3( BlendMode_Overlay(base.r, blend.r), + BlendMode_Overlay(base.g, blend.g), + BlendMode_Overlay(base.b, blend.b) ); +} + +//****************************************************************************** +// Darkens or lightens the colors, depending on the blend color. +//****************************************************************************** +float BlendMode_SoftLight(float base, float blend) +{ + if (blend <= 0.5) + { + return base - (1-2*blend)*base*(1-base); + } + else + { + float d = (base <= 0.25) ? ((16*base-12)*base+4)*base : sqrt(base); + return base + (2*blend-1)*(d-base); + } +} + +float3 BlendMode_SoftLight(float3 base, float3 blend) +{ + return float3( BlendMode_SoftLight(base.r, blend.r), + BlendMode_SoftLight(base.g, blend.g), + BlendMode_SoftLight(base.b, blend.b) ); +} + +//****************************************************************************** +// Multiplies or screens the colors, depending on the blend color. +//****************************************************************************** +float BlendMode_HardLight(float base, float blend) +{ + return (blend <= 0.5) ? 2*base*blend : 1 - 2*(1-base)*(1-blend); +} + +float3 BlendMode_HardLight(float3 base, float3 blend) +{ + return float3( BlendMode_HardLight(base.r, blend.r), + BlendMode_HardLight(base.g, blend.g), + BlendMode_HardLight(base.b, blend.b) ); +} + +//****************************************************************************** +// Burns or dodges the colors by increasing or decreasing the contrast, +// depending on the blend color. +//****************************************************************************** +float BlendMode_VividLight(float base, float blend) +{ + return (blend <= 0.5) ? BlendMode_ColorBurn(base,2*blend) : BlendMode_ColorDodge(base,2*(blend-0.5)); +} + +float3 BlendMode_VividLight(float3 base, float3 blend) +{ + return float3( BlendMode_VividLight(base.r, blend.r), + BlendMode_VividLight(base.g, blend.g), + BlendMode_VividLight(base.b, blend.b) ); +} + +//****************************************************************************** +// Burns or dodges the colors by decreasing or increasing the brightness, +// depending on the blend color. +//****************************************************************************** +float BlendMode_LinearLight(float base, float blend) +{ + return (blend <= 0.5) ? BlendMode_LinearBurn(base,2*blend) : BlendMode_LinearDodge(base,2*(blend-0.5)); +} + +float3 BlendMode_LinearLight(float3 base, float3 blend) +{ + return float3( BlendMode_LinearLight(base.r, blend.r), + BlendMode_LinearLight(base.g, blend.g), + BlendMode_LinearLight(base.b, blend.b) ); +} + +//****************************************************************************** +// Replaces the colors, depending on the blend color. +//****************************************************************************** +float BlendMode_PinLight(float base, float blend) +{ + return (blend <= 0.5) ? min(base,2*blend) : max(base,2*(blend-0.5)); +} + +float3 BlendMode_PinLight(float3 base, float3 blend) +{ + return float3( BlendMode_PinLight(base.r, blend.r), + BlendMode_PinLight(base.g, blend.g), + BlendMode_PinLight(base.b, blend.b) ); +} + +//****************************************************************************** +// Adds the red, green and blue channel values of the blend color to the RGB +// values of the base color. If the resulting sum for a channel is 255 or +// greater, it receives a value of 255; if less than 255, a value of 0. +//****************************************************************************** +float BlendMode_HardMix(float base, float blend) +{ + return (base + blend >= 1.0) ? 1.0 : 0.0; +} + +float3 BlendMode_HardMix(float3 base, float3 blend) +{ + return float3( BlendMode_HardMix(base.r, blend.r), + BlendMode_HardMix(base.g, blend.g), + BlendMode_HardMix(base.b, blend.b) ); +} + +//****************************************************************************** +// Looks at the color information in each channel and subtracts either the +// blend color from the base color or the base color from the blend color, +// depending on which has the greater brightness value. +//****************************************************************************** +float3 BlendMode_Difference(float3 base, float3 blend) +{ + return abs(base-blend); +} + +//****************************************************************************** +// Creates an effect similar to but lower in contrast than the Difference mode. +//****************************************************************************** +float3 BlendMode_Exclusion(float3 base, float3 blend) +{ + return base + blend - 2*base*blend; +} + +//****************************************************************************** +// Looks at the color information in each channel and subtracts the blend color +// from the base color. +//****************************************************************************** +float3 BlendMode_Subtract(float3 base, float3 blend) +{ + return max(0, base - blend); +} + +//****************************************************************************** +// Looks at the color information in each channel and divides the blend color +// from the base color. +//****************************************************************************** +float BlendMode_Divide(float base, float blend) +{ + return blend > 0 ? min(1, base / blend) : 1; +} + +float3 BlendMode_Divide(float3 base, float3 blend) +{ + return float3( BlendMode_Divide(base.r, blend.r), + BlendMode_Divide(base.g, blend.g), + BlendMode_Divide(base.b, blend.b) ); +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli new file mode 100644 index 0000000000..e84b18c550 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli @@ -0,0 +1,80 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: (MIT OR Apache-2.0) AND LicenseRef-ACES + * + */ + +/* +License Terms for Academy Color Encoding System Components + +Academy Color Encoding System (ACES) software and tools are provided by the + Academy under the following terms and conditions: A worldwide, royalty-free, + non-exclusive right to copy, modify, create derivatives, and use, in source and + binary forms, is hereby granted, subject to acceptance of this license. + +Copyright © 2015 Academy of Motion Picture Arts and Sciences (A.M.P.A.S.). +Portions contributed by others as indicated. All rights reserved. + +Performance of any of the aforementioned acts indicates acceptance to be bound + by the following terms and conditions: + +* Copies of source code, in whole or in part, must retain the above copyright + notice, this list of conditions and the Disclaimer of Warranty. +* Use in binary form must retain the above copyright notice, this list of + conditions and the Disclaimer of Warranty in the documentation and/or other + materials provided with the distribution. +* Nothing in this license shall be deemed to grant any rights to trademarks, + copyrights, patents, trade secrets or any other intellectual property of + A.M.P.A.S. or any contributors, except as expressly stated herein. +* Neither the name "A.M.P.A.S." nor the name of any other contributors to this + software may be used to endorse or promote products derivative of or based on + this software without express prior written permission of A.M.P.A.S. or the + contributors, as appropriate. + +This license shall be construed pursuant to the laws of the State of California, +and any disputes related thereto shall be subject to the jurisdiction of the + courts therein. + +Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL A.M.P.A.S., OR ANY +CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, RESITUTIONARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY SPECIFICALLY +DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER RELATED TO PATENT OR +OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY COLOR ENCODING SYSTEM, OR +APPLICATIONS THEREOF, HELD BY PARTIES OTHER THAN A.M.P.A.S.,WHETHER DISCLOSED OR +UNDISCLOSED. +*/ + +#pragma once + +static const float HALF_MAX = 65504.0f; + +float AcesCcToLinear(float value) +{ + if (value < -0.3013698630) // (9.72-15)/17.52 + return (pow( 2., value*17.52-9.72) - pow( 2.,-16.))*2.0; + else if (value < (log2(HALF_MAX)+9.72)/17.52) + return pow( 2., value*17.52-9.72); + else // (value >= (log2(HALF_MAX)+9.72)/17.52) + return HALF_MAX; +} + +float3 AcesCcToAcesCg(float3 color) +{ + return float3( + AcesCcToLinear(color.r), + AcesCcToLinear(color.g), + AcesCcToLinear(color.b)); +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli new file mode 100644 index 0000000000..f784a76990 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli @@ -0,0 +1,79 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: (MIT OR Apache-2.0) AND LicenseRef-ACES + * + */ + +/* +License Terms for Academy Color Encoding System Components + +Academy Color Encoding System (ACES) software and tools are provided by the + Academy under the following terms and conditions: A worldwide, royalty-free, + non-exclusive right to copy, modify, create derivatives, and use, in source and + binary forms, is hereby granted, subject to acceptance of this license. + +Copyright © 2015 Academy of Motion Picture Arts and Sciences (A.M.P.A.S.). +Portions contributed by others as indicated. All rights reserved. + +Performance of any of the aforementioned acts indicates acceptance to be bound + by the following terms and conditions: + +* Copies of source code, in whole or in part, must retain the above copyright + notice, this list of conditions and the Disclaimer of Warranty. +* Use in binary form must retain the above copyright notice, this list of + conditions and the Disclaimer of Warranty in the documentation and/or other + materials provided with the distribution. +* Nothing in this license shall be deemed to grant any rights to trademarks, + copyrights, patents, trade secrets or any other intellectual property of + A.M.P.A.S. or any contributors, except as expressly stated herein. +* Neither the name "A.M.P.A.S." nor the name of any other contributors to this + software may be used to endorse or promote products derivative of or based on + this software without express prior written permission of A.M.P.A.S. or the + contributors, as appropriate. + +This license shall be construed pursuant to the laws of the State of California, +and any disputes related thereto shall be subject to the jurisdiction of the + courts therein. + +Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, +AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL A.M.P.A.S., OR ANY +CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, RESITUTIONARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//////////////////////////////////////////////////////////////////////////////// +WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY SPECIFICALLY +DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER RELATED TO PATENT OR +OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY COLOR ENCODING SYSTEM, OR +APPLICATIONS THEREOF, HELD BY PARTIES OTHER THAN A.M.P.A.S.,WHETHER DISCLOSED OR +UNDISCLOSED. +*/ + +#pragma once + +float LinearToAcesCc(float value) +{ + if (value <= 0) + return -0.3584474886; // =(log2( pow(2.,-16.))+9.72)/17.52 + else if (value < pow(2.,-15.)) + return (log2( pow(2.,-16.) + value * 0.5) + 9.72) / 17.52; + else // (value >= pow(2.,-15)) + return (log2(value) + 9.72) / 17.52; +} + +float3 AcesCgToAcesCc(float3 color) +{ + return float3( + LinearToAcesCc(color.r), + LinearToAcesCc(color.g), + LinearToAcesCc(color.b) + ); +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/TransformColor.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/TransformColor.azsli index e298445c7c..c9d1b7d979 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/TransformColor.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/ColorManagement/TransformColor.azsli @@ -8,11 +8,14 @@ #pragma once +#include #include "GeneratedTransforms/LinearSrgb_To_AcesCg.azsli" #include "GeneratedTransforms/AcesCg_To_LinearSrgb.azsli" #include "GeneratedTransforms/LinearSrgb_To_Srgb.azsli" #include "GeneratedTransforms/Srgb_To_LinearSrgb.azsli" #include "GeneratedTransforms/Aces_To_AcesCg.azsli" +#include "GeneratedTransforms/AcesCcToAcesCg.azsli" +#include "GeneratedTransforms/AcesCgToAcesCc.azsli" #include "GeneratedTransforms/CalculateLuminance_LinearSrgb.azsli" #include "GeneratedTransforms/CalculateLuminance_AcesCg.azsli" @@ -20,6 +23,7 @@ enum class ColorSpaceId { SRGB = 0, LinearSRGB, + ACEScc, ACEScg, ACES2065, XYZ, @@ -51,15 +55,27 @@ float3 TransformColor(in float3 color, ColorSpaceId fromColorSpace, ColorSpaceId color = AcesCg_To_LinearSrgb(color); color = LinearSrgb_To_Srgb(color); } + else if (fromColorSpace == ColorSpaceId::ACEScg && toColorSpace == ColorSpaceId::LinearSRGB) + { + color = AcesCg_To_LinearSrgb(color); + } + else if (fromColorSpace == ColorSpaceId::ACEScg && toColorSpace == ColorSpaceId::ACEScc) + { + color = AcesCgToAcesCc(color); + } else if (fromColorSpace == ColorSpaceId::ACES2065 && toColorSpace == ColorSpaceId::ACEScg) { color = Aces_To_AcesCg(color); } + else if (fromColorSpace == ColorSpaceId::ACEScc && toColorSpace == ColorSpaceId::ACEScg) + { + color = AcesCcToAcesCg(color); + } else { color = float3(1, 0, 1); } - + return color; } @@ -75,6 +91,7 @@ float CalculateLuminance(in float3 color, ColorSpaceId colorSpace) luminance = CalculateLuminance_AcesCg(color); break; case ColorSpaceId::SRGB: + case ColorSpaceId::ACEScc: case ColorSpaceId::ACES2065: case ColorSpaceId::XYZ: case ColorSpaceId::Invalid: @@ -83,3 +100,29 @@ float CalculateLuminance(in float3 color, ColorSpaceId colorSpace) return luminance; } + +float RotateHue(float hue, float low, float hi) +{ + return (hue < low) + ? hue + hi + : (hue > hi) + ? hue - hi + : hue; +} + +float3 RgbToHsv(float3 color) +{ + const float4 k = float4(0.0f, -1.0f / 3.0f, 2.0f / 3.0f, -1.0f); + const float4 p = lerp(float4(color.bg, k.wz), float4(color.gb, k.xy), step(color.b, color.g)); + const float4 q = lerp(float4(p.xyw, color.r), float4(color.r, p.yzx), step(p.x, color.r)); + const float d = q.x - min(q.w, q.y); + const float e = EPSILON; + return float3(abs(q.z + (q.w - q.y) / (6.0f * d + e)), d / (q.x + e), q.x); +} + +float3 HsvToRgb(float3 color) +{ + const float4 k = float4(1.0f, 2.0f / 3.0f, 1.0f / 3.0f, 3.0f); + const float3 p = abs(frac(color.xxx + k.xyz) * 6.0f - k.www); + return color.z * lerp(k.xxx, saturate(p - k.xxx), color.y); +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl new file mode 100644 index 0000000000..9ae4a2bd68 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl @@ -0,0 +1,206 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include + +#include +#include + +#include +#include +#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli> +#include <3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli> +#include <3rdParty/Features/PostProcessing/KelvinToRgb.azsli> + +static const float FloatEpsilon = 1.192092896e-07; // 1.0 + FloatEpsilon != 1.0, smallest positive float +static const float FloatMin = FLOAT_32_MIN; // Min float number that is positive +static const float FloatMax = FLOAT_32_MAX; // Max float number representable + +static const float AcesCcMidGrey = 0.4135884; + +ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback +{ + // get the framebuffer + Texture2D m_framebuffer; + + // framebuffer sampler + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; + + float m_colorGradingExposure; + float m_colorGradingContrast; + float m_colorGradingHueShift; + float m_colorGradingPreSaturation; + float m_colorFilterIntensity; + float m_colorFilterMultiply; + float m_whiteBalanceKelvin; + float m_whiteBalanceTint; + float m_splitToneBalance; + float m_splitToneMix; + float m_colorGradingPostSaturation; + float m_smhShadowsStart; + float m_smhShadowsEnd; + float m_smhHighlightsStart; + float m_smhHighlightsEnd; + float m_smhMix; + + float3 m_channelMixingRed; + float3 m_channelMixingGreen; + float3 m_channelMixingBlue; + + float4 m_colorFilterSwatch; + float4 m_splitToneShadowsColor; + float4 m_splitToneHighlightsColor; + + float4 m_smhShadowsColor; + float4 m_smhMidtonesColor; + float4 m_smhHighlightsColor; + + // my color grading output + float4 m_color; +} + +float SaturateWithEpsilon(float value) +{ + return clamp(value, FloatEpsilon, 1.0f); +} + +// Below are the color grading functions. These expect the frame color to be in ACEScg space. +// Note that some functions may have some quirks in their implementation and is subject to change. +float3 ColorGradePostExposure (float3 frameColor, float exposure) +{ + frameColor *= pow(2.0f, exposure); + return frameColor; +} + +// The contrast equation is performed in ACEScc (logarithmic) color space. +float3 ColorGradingContrast (float3 frameColor, float midgrey, float amount) +{ + const float contrastAdjustment = amount * 0.01f + 1.0f; + frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScg, ColorSpaceId::ACEScc); + frameColor = (frameColor - midgrey) * contrastAdjustment + midgrey; + return frameColor = TransformColor(frameColor.rgb, ColorSpaceId::ACEScc, ColorSpaceId::ACEScg); +} + +// The swatchColor param expects a linear RGB value. +float3 ColorGradeColorFilter (float3 frameColor, float3 swatchColor, float alpha) +{ + swatchColor = TransformColor(swatchColor, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + swatchColor *= pow(2.0f, PassSrg::m_colorFilterIntensity); + const float3 frameAdjust = frameColor * swatchColor; + return frameColor = lerp(frameColor, frameAdjust, alpha); +} + +float3 ColorGradeHueShift (float3 frameColor, float amount) +{ + float3 frameHsv = RgbToHsv(frameColor); + const float hue = frameHsv.x + amount; + frameHsv.x = RotateHue(hue, 0.0, 1.0); + return HsvToRgb(frameHsv); +} + +float3 ColorGradeSaturation (float3 frameColor, float control) +{ + const float vLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); + return (frameColor - vLuminance) * control + vLuminance; +} + +float3 ColorGradeKelvinColorTemp(float3 frameColor, float kelvin) +{ + const float3 kColor = TransformColor(KelvinToRgb(kelvin), ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + const float luminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); + const float3 resHsl = RgbToHsl(frameColor.rgb * kColor.rgb); // Apply Kelvin color and convert to HSL + return HslToRgb(float3(resHsl.xy, luminance)); // Preserve luminance +} + +// pow(f, e) won't work if f is negative, or may cause inf/NAN. +float3 NoNanPow(float3 base, float3 power) +{ + return pow(max(abs(base), float3(FloatEpsilon, FloatEpsilon, FloatEpsilon)), power); +} + +float3 ColorGradeSplitTone (float3 frameColor, float balance, float mix) +{ + float3 frameSplitTone = NoNanPow(frameColor, 1.0 / 2.2); + const float t = SaturateWithEpsilon(CalculateLuminance(SaturateWithEpsilon(frameSplitTone), ColorSpaceId::ACEScg) + balance); + const float3 shadows = lerp(0.5, PassSrg::m_splitToneShadowsColor.rgb, 1.0 - t); + const float3 highlights = lerp(0.5, PassSrg::m_splitToneHighlightsColor.rgb, t); + frameSplitTone = BlendMode_SoftLight(frameSplitTone, shadows); + frameSplitTone = BlendMode_SoftLight(frameSplitTone, highlights); + frameSplitTone = NoNanPow(frameSplitTone, 2.2); + return lerp(frameColor.rgb, frameSplitTone.rgb, mix); +} + +float3 ColorGradeChannelMixer (float3 frameColor) +{ + return mul(float3x3(PassSrg::m_channelMixingRed.rgb, + PassSrg::m_channelMixingGreen.rgb, + PassSrg::m_channelMixingBlue.rgb), + frameColor); +} + +float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStart, float shadowsEnd, + float highlightsStart, float highlightsEnd, float mix, + float4 shadowsColor, float4 midtonesColor, float4 highlightsColor) +{ + const float3 shadowsColorACEScg = TransformColor(shadowsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + const float3 midtonesColorACEScg = TransformColor(midtonesColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + const float3 highlightsColorACEScg = TransformColor(highlightsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); + + const float cLuminance = CalculateLuminance(frameColor, ColorSpaceId::ACEScg); + const float shadowsWeight = 1.0 - smoothstep(shadowsStart, shadowsEnd, cLuminance); + const float highlightsWeight = smoothstep(highlightsStart, highlightsEnd, cLuminance); + const float midtonesWeight = 1.0 - shadowsWeight - highlightsWeight; + + const float3 frameSmh = frameColor * shadowsColorACEScg * shadowsWeight + + frameColor * midtonesColorACEScg * midtonesWeight + + frameColor * highlightsColorACEScg * highlightsWeight; + return lerp(frameColor.rgb, frameSmh.rgb, mix); +} + +float3 ColorGrade (float3 frameColor) +{ + frameColor = ColorGradePostExposure(frameColor, PassSrg::m_colorGradingExposure); + frameColor = ColorGradeKelvinColorTemp(frameColor, PassSrg::m_whiteBalanceKelvin); + frameColor = ColorGradingContrast(frameColor, AcesCcMidGrey, PassSrg::m_colorGradingContrast); + frameColor = ColorGradeColorFilter(frameColor, PassSrg::m_colorFilterSwatch.rgb, + PassSrg::m_colorFilterMultiply); + frameColor = max(frameColor, 0.0); + frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation); + frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneMix); + frameColor = ColorGradeChannelMixer(frameColor); + frameColor = max(frameColor, 0.0); + frameColor = ColorGradeShadowsMidtonesHighlights(frameColor, PassSrg::m_smhShadowsStart, PassSrg::m_smhShadowsEnd, + PassSrg::m_smhHighlightsStart, PassSrg::m_smhHighlightsEnd, PassSrg::m_smhMix, + PassSrg::m_smhShadowsColor, PassSrg::m_smhMidtonesColor, PassSrg::m_smhHighlightsColor); + frameColor = ColorGradeHueShift(frameColor, PassSrg::m_colorGradingHueShift); + frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPostSaturation); + return frameColor.rgb; +} + +PSOutput MainPS(VSOutput IN) +{ + PSOutput OUT; + + // Fetch the pixel color from the input texture + float3 frameColor = PassSrg::m_framebuffer.Sample(PassSrg::LinearSampler, IN.m_texCoord).rgb; + + OUT.m_color.rgb = ColorGrade(frameColor); + OUT.m_color.w = 1; + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader new file mode 100644 index 0000000000..f76f6708b7 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.shader @@ -0,0 +1,22 @@ +{ + "Source" : "HDRColorGrading", + + "DepthStencilState" : { + "Depth" : { "Enable" : false } + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index 8435625833..c8f99cdb24 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -86,6 +86,7 @@ set(FILES Passes/CascadedShadowmaps.pass Passes/CheckerboardResolveColor.pass Passes/CheckerboardResolveDepth.pass + Passes/HDRColorGrading.pass Passes/ContrastAdaptiveSharpening.pass Passes/ConvertToAcescg.pass Passes/DebugOverlayParent.pass @@ -221,6 +222,8 @@ set(FILES ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/LinearSrgb_To_AcesCg.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/LinearSrgb_To_Srgb.azsli ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/Srgb_To_LinearSrgb.azsli + ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCcToAcesCg.azsli + ShaderLib/Atom/Features/ColorManagement/GeneratedTransforms/AcesCgToAcesCc.azsli ShaderLib/Atom/Features/CoreLights/PhotometricValue.azsli ShaderLib/Atom/Features/Decals/DecalTextureUtil.azsli ShaderLib/Atom/Features/LightCulling/LightCullingShared.azsli @@ -286,6 +289,9 @@ set(FILES ShaderLib/Atom/Features/Shadow/Shadow.azsli ShaderLib/Atom/Features/Shadow/ShadowmapAtlasLib.azsli ShaderLib/Atom/Features/Vertex/VertexHelper.azsli + ShaderLib/3rdParty/Features/PostProcessing/KelvinToRgb.azsli + ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_NonSeparable.azsli + ShaderLib/3rdParty/Features/PostProcessing/PSstyleColorBlends_Separable.azsli ShaderResourceGroups/SceneSrg.azsli ShaderResourceGroups/SceneSrgAll.azsli ShaderResourceGroups/ViewSrg.azsli @@ -392,6 +398,8 @@ set(FILES Shaders/PostProcessing/FastDepthAwareBlurVer.shader Shaders/PostProcessing/FullscreenCopy.azsl Shaders/PostProcessing/FullscreenCopy.shader + Shaders/PostProcessing/HDRColorGrading.azsl + Shaders/PostProcessing/HDRColorGrading.shader Shaders/PostProcessing/LookModificationTransform.azsl Shaders/PostProcessing/LookModificationTransform.shader Shaders/PostProcessing/LuminanceHeatmap.azsl From f111b67df608b504b48c71f8a4661ff6e0fed6ce Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 15 Sep 2021 14:44:27 -0700 Subject: [PATCH 141/274] Fix issue with one frame flicker in the transition between paint modes. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Components/FancyDockingGhostWidget.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp index 04387875df..5456356458 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp @@ -48,7 +48,7 @@ namespace AzQtComponents void FancyDockingGhostWidget::setPixmap(const QPixmap& pixmap, const QRect& targetRect, QScreen* screen) { - const bool needsRepaint = m_pixmap.cacheKey() != pixmap.cacheKey() || m_clipToWidgets; + bool needsRepaint = m_pixmap.cacheKey() != pixmap.cacheKey() || m_clipToWidgets; m_pixmap = pixmap; if (pixmap.isNull() || targetRect.isNull() || !screen) @@ -80,6 +80,7 @@ namespace AzQtComponents QPoint midPoint = targetRect.topLeft() + QPoint(targetRect.width() / 2, targetRect.height() / 2); QScreen* pointScreen = QApplication::screenAt(midPoint); QRect rect(targetRect); + PaintMode paintMode = PaintMode::FULL; if (!pointScreen || pointScreen != screen) { @@ -87,26 +88,28 @@ namespace AzQtComponents { rect.setLeft(rect.left() - rect.width()); rect.setTop(rect.top() - rect.height()); - m_paintMode = PaintMode::BOTTOMRIGHT; + paintMode = PaintMode::BOTTOMRIGHT; } else { rect.setRight(rect.right() + rect.width()); rect.setTop(rect.top() - rect.height()); - m_paintMode = PaintMode::BOTTOMLEFT; + paintMode = PaintMode::BOTTOMLEFT; } } - else + + if (m_paintMode != paintMode) { - m_paintMode = PaintMode::FULL; + needsRepaint = true; } setGeometry(rect); + m_paintMode = paintMode; setPixmapVisible(true); if (needsRepaint) { - update(); + repaint(); } } From 50e4d549f44ade8b615c73a33b76e975fb21347f Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 15 Sep 2021 14:51:36 -0700 Subject: [PATCH 142/274] Add comments Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzQtComponents/Components/FancyDockingGhostWidget.cpp | 8 ++++++++ .../AzQtComponents/Components/FancyDockingGhostWidget.h | 7 ++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp index 5456356458..d259b28636 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp @@ -80,6 +80,14 @@ namespace AzQtComponents QPoint midPoint = targetRect.topLeft() + QPoint(targetRect.width() / 2, targetRect.height() / 2); QScreen* pointScreen = QApplication::screenAt(midPoint); QRect rect(targetRect); + + // On environment with multiple screens with different scaling settings, the screen coordinate system may have gaps + // due to the screen real estate shrinking according to the scale. When that happens, if a widget is moved into the gap + // it will resize and translate with undefined behavior, causing a lot of jitter and flashes. + // To prevent this, whenever the widget would end up outside screen boundaries, we resize the widget to be twice its + // original size so that the center of the widget is back inside the screen boundaries, and set the ghost widget + // to paint the widget pixmap at half the previous size to make the process seamless. + // This makes the dragging a lot smoother in most situations. PaintMode paintMode = PaintMode::FULL; if (!pointScreen || pointScreen != screen) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h index 6649c6d848..5244bcdd0a 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.h @@ -46,11 +46,12 @@ namespace AzQtComponents bool m_visible = false; // maintain our own flag, so that we're always ready to render ignoring Qt's widget caching system bool m_clipToWidgets = false; + //! Determines the way the ghost widget pixmap should be painted on the widget. enum class PaintMode { - FULL = 0, - BOTTOMLEFT, - BOTTOMRIGHT + FULL = 0, //!< Paint the pixmap on the full widget + BOTTOMLEFT, //!< Paint the pixmap on the bottom left quarter of the widget, halving its size + BOTTOMRIGHT //!< Paint the pixmap on the bottom right quarter of the widget, halving its size }; PaintMode m_paintMode = PaintMode::FULL; From 28b18a33bd170e2e482c6ca35532cd005eb27bc4 Mon Sep 17 00:00:00 2001 From: Jonny Galloway Date: Wed, 15 Sep 2021 16:55:14 -0500 Subject: [PATCH 143/274] Atom/gallowj/clean up atom content (#4151) * Update the atom content to make best practice (latest conventions) Signed-off-by: Jonny Gallowy * file tweaks cleanup Signed-off-by: Jonny Gallowy * correct license headers Signed-off-by: Jonny Gallowy --- Gems/AtomContent/.gitignore | 8 ++ .../ReferenceMaterials/Launch_WingIDE-7-1.bat | 79 ------------- .../ReferenceMaterials/LyProjectRootStub | 0 .../ReferenceMaterials/Project_Env.bat | 70 ----------- .../{ => Tools}/Launch_Cmd.bat | 18 ++- .../Launch_Maya.bat} | 10 +- .../ReferenceMaterials/Tools/Project_Env.bat | 110 ++++++++++++++++++ .../Tools/User_Env.bat.template | 42 +++++++ Gems/AtomContent/ReferenceMaterials/gem.json | 10 +- Gems/AtomContent/Sponza/Project_Env.bat | 72 ------------ Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat | 16 +-- .../Launch_Maya_2020.bat => Launch_Maya.bat} | 36 +++--- .../Sponza/Tools/Maya/Scripts/stub | 0 Gems/AtomContent/Sponza/Tools/Project_Env.bat | 110 ++++++++++++++++++ .../Sponza/Tools/User_Env.bat.template | 42 +++++++ Gems/AtomContent/Sponza/User_env.bat.template | 1 - .../Launchers/Windows/Env_Maya.bat | 2 +- .../azpy/config_utils.py | 32 ++++- 18 files changed, 383 insertions(+), 275 deletions(-) create mode 100644 Gems/AtomContent/.gitignore delete mode 100644 Gems/AtomContent/ReferenceMaterials/Launch_WingIDE-7-1.bat delete mode 100644 Gems/AtomContent/ReferenceMaterials/LyProjectRootStub delete mode 100644 Gems/AtomContent/ReferenceMaterials/Project_Env.bat rename Gems/AtomContent/ReferenceMaterials/{ => Tools}/Launch_Cmd.bat (72%) rename Gems/AtomContent/ReferenceMaterials/{Launch_Maya_2020.bat => Tools/Launch_Maya.bat} (82%) create mode 100644 Gems/AtomContent/ReferenceMaterials/Tools/Project_Env.bat create mode 100644 Gems/AtomContent/ReferenceMaterials/Tools/User_Env.bat.template delete mode 100644 Gems/AtomContent/Sponza/Project_Env.bat rename Gems/AtomContent/Sponza/Tools/{Maya/Launch_Maya_2020.bat => Launch_Maya.bat} (63%) delete mode 100644 Gems/AtomContent/Sponza/Tools/Maya/Scripts/stub create mode 100644 Gems/AtomContent/Sponza/Tools/Project_Env.bat create mode 100644 Gems/AtomContent/Sponza/Tools/User_Env.bat.template delete mode 100644 Gems/AtomContent/Sponza/User_env.bat.template diff --git a/Gems/AtomContent/.gitignore b/Gems/AtomContent/.gitignore new file mode 100644 index 0000000000..174c2dd972 --- /dev/null +++ b/Gems/AtomContent/.gitignore @@ -0,0 +1,8 @@ +_savebackup/ +.mayaSwatches/ +*.swatches +[Bb]uild/ +[Cc]ache/ +[Uu]ser/ +[Uu]ser_Env.bat +.maya_data/ \ No newline at end of file diff --git a/Gems/AtomContent/ReferenceMaterials/Launch_WingIDE-7-1.bat b/Gems/AtomContent/ReferenceMaterials/Launch_WingIDE-7-1.bat deleted file mode 100644 index c9b380ad64..0000000000 --- a/Gems/AtomContent/ReferenceMaterials/Launch_WingIDE-7-1.bat +++ /dev/null @@ -1,79 +0,0 @@ -@echo off -:: Launches Wing IDE and the DccScriptingInterface Project Files - -REM -REM Copyright (c) Contributors to the Open 3D Engine Project. -REM For complete copyright and license terms please see the LICENSE at the root of this distribution. -REM -REM SPDX-License-Identifier: Apache-2.0 OR MIT -REM -REM - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Setting up LY DCCsi WingIDE Dev Env... -echo _____________________________________________________________________ -echo. - -:: Store current dir -%~d0 -cd %~dp0 -PUSHD %~dp0 - -:: Keep changes local -SETLOCAL enableDelayedExpansion - -SET ABS_PATH=%~dp0 -echo Current Dir, %ABS_PATH% - -:: WingIDE version Major -SET WING_VERSION_MAJOR=7 -echo WING_VERSION_MAJOR = %WING_VERSION_MAJOR% - -:: WingIDE version Major -SET WING_VERSION_MINOR=1 -echo WING_VERSION_MINOR = %WING_VERSION_MINOR% - -:: note the changed path from IDE to Pro -set WINGHOME=%PROGRAMFILES(X86)%\Wing Pro %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% -echo WINGHOME = %WINGHOME% - -CALL %~dp0\Project_Env.bat - -echo. -echo _____________________________________________________________________ -echo. -echo ~ WingIDE Version %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% -echo _____________________________________________________________________ -echo. - -SET WING_PROJ=%DCCSIG_PATH%\Solutions\.wing\DCCsi_%WING_VERSION_MAJOR%x.wpr -echo WING_PROJ = %WING_PROJ% - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Launching %LY_PROJECT% project in WingIDE %WING_VERSION_MAJOR%.%WING_VERSION_MINOR% ... -echo _____________________________________________________________________ -echo. - - -IF EXIST "%WINGHOME%\bin\wing.exe" ( - start "" "%WINGHOME%\bin\wing.exe" "%WING_PROJ%" -) ELSE ( - Where wing.exe 2> NUL - IF ERRORLEVEL 1 ( - echo wing.exe could not be found - pause - ) ELSE ( - start "" wing.exe "%WING_PROJ%" - ) -) - -ENDLOCAL - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/ReferenceMaterials/LyProjectRootStub b/Gems/AtomContent/ReferenceMaterials/LyProjectRootStub deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Gems/AtomContent/ReferenceMaterials/Project_Env.bat b/Gems/AtomContent/ReferenceMaterials/Project_Env.bat deleted file mode 100644 index 6612ca5399..0000000000 --- a/Gems/AtomContent/ReferenceMaterials/Project_Env.bat +++ /dev/null @@ -1,70 +0,0 @@ -@echo off -:: Sets up environment for Lumberyard DCC tools and code access - -REM -REM Copyright (c) Contributors to the Open 3D Engine Project. -REM For complete copyright and license terms please see the LICENSE at the root of this distribution. -REM -REM SPDX-License-Identifier: Apache-2.0 OR MIT -REM -REM - -:: Store current dir -%~d0 -cd %~dp0 -PUSHD %~dp0 - -for %%a in (.) do set LY_PROJECT=%%~na - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Setting up LY DSI PROJECT Environment ... -echo _____________________________________________________________________ -echo. - -echo LY_PROJECT = %LY_PROJECT% - -:: Put you project env vars and overrides here - -:: chanhe the relative path up to dev -set DEV_REL_PATH=../../.. -set ABS_PATH=%~dp0 - -:: Override the default maya version -set MAYA_VERSION=2020 -echo MAYA_VERSION = %MAYA_VERSION% - -set LY_PROJECT_PATH=%ABS_PATH% -echo LY_PROJECT_PATH = %LY_PROJECT_PATH% - -:: Change to root Lumberyard dev dir -CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH% -set LY_DEV=%CD% -echo LY_DEV = %LY_DEV% - -CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env.bat - -rem :: Constant Vars (Global) -rem SET LYPY_GDEBUG=0 -rem echo LYPY_GDEBUG = %LYPY_GDEBUG% -rem SET LYPY_DEV_MODE=0 -rem echo LYPY_DEV_MODE = %LYPY_DEV_MODE% -rem SET LYPY_DEBUGGER=WING -rem echo LYPY_DEBUGGER = %LYPY_DEBUGGER% - -:: Restore original directory -popd - -:: Change to root dir -CD /D %ABS_PATH% - -:: if the user has set up a custom env call it -IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat - -GOTO END_OF_FILE - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/ReferenceMaterials/Launch_Cmd.bat b/Gems/AtomContent/ReferenceMaterials/Tools/Launch_Cmd.bat similarity index 72% rename from Gems/AtomContent/ReferenceMaterials/Launch_Cmd.bat rename to Gems/AtomContent/ReferenceMaterials/Tools/Launch_Cmd.bat index 8ec894c21f..d100c9ddc7 100644 --- a/Gems/AtomContent/ReferenceMaterials/Launch_Cmd.bat +++ b/Gems/AtomContent/ReferenceMaterials/Tools/Launch_Cmd.bat @@ -1,21 +1,19 @@ -:: Need to set up - @echo off REM -REM Copyright (c) Contributors to the Open 3D Engine Project. -REM For complete copyright and license terms please see the LICENSE at the root of this distribution. -REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. REM REM -:: Set up and run LY Python CMD prompt -:: Sets up the DccScriptingInterface_Env, +:: Set up and start a O3DE CMD prompt +:: Sets up the current (DCC) Project_Env, :: Puts you in the CMD within the dev environment :: Set up window -TITLE Lumberyard DCC Scripting Interface Cmd +TITLE O3DE Asset Gem Cmd :: Use obvious color to prevent confusion (Grey with Yellow Text) COLOR 8E @@ -31,7 +29,7 @@ CALL %~dp0\Project_Env.bat echo. echo _____________________________________________________________________ echo. -echo ~ LY DCC Scripting Interface CMD ... +echo ~ O3DE Asset Gem CMD ... echo _____________________________________________________________________ echo. @@ -43,4 +41,4 @@ ENDLOCAL :: Return to starting directory POPD -:END_OF_FILE +:END_OF_FILE \ No newline at end of file diff --git a/Gems/AtomContent/ReferenceMaterials/Launch_Maya_2020.bat b/Gems/AtomContent/ReferenceMaterials/Tools/Launch_Maya.bat similarity index 82% rename from Gems/AtomContent/ReferenceMaterials/Launch_Maya_2020.bat rename to Gems/AtomContent/ReferenceMaterials/Tools/Launch_Maya.bat index 1dc504e684..b9a6b399f3 100644 --- a/Gems/AtomContent/ReferenceMaterials/Launch_Maya_2020.bat +++ b/Gems/AtomContent/ReferenceMaterials/Tools/Launch_Maya.bat @@ -22,22 +22,22 @@ echo ~ calling PROJ_Env.bat SETLOCAL enableDelayedExpansion :: PY version Major -set DCCSI_PY_VERSION_MAJOR=2 +IF "%DCCSI_PY_VERSION_MAJOR%"=="" (set DCCSI_PY_VERSION_MAJOR=2) echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR% :: PY version Major -set DCCSI_PY_VERSION_MINOR=7 +IF "%DCCSI_PY_VERSION_MINOR%"=="" (set DCCSI_PY_VERSION_MINOR=7) echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR% :: Maya Version -set MAYA_VERSION=2020 -echo MAYA_VERSION = %MAYA_VERSION% +IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=2020) +echo DCCSI_MAYA_VERSION = %DCCSI_MAYA_VERSION% :: if a local customEnv.bat exists, run it IF EXIST "%~dp0Project_Env.bat" CALL %~dp0Project_Env.bat echo ________________________________ -echo Launching Maya %MAYA_VERSION% for Lumberyard... +echo Launching Maya %DCCSI_MAYA_VERSION% for Lumberyard... :::: Set Maya native project acess to this project ::set MAYA_PROJECT=%LY_PROJECT% diff --git a/Gems/AtomContent/ReferenceMaterials/Tools/Project_Env.bat b/Gems/AtomContent/ReferenceMaterials/Tools/Project_Env.bat new file mode 100644 index 0000000000..6e2c8b5914 --- /dev/null +++ b/Gems/AtomContent/ReferenceMaterials/Tools/Project_Env.bat @@ -0,0 +1,110 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Sets up environment for O3DE DCC tools and code access + +:: Set up window +TITLE O3DE Asset Gem +:: Use obvious color to prevent confusion (Grey with Yellow Text) +COLOR 8E + +:: Skip initialization if already completed +IF "%O3DE_PROJ_ENV_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +:: Put you project env vars and overrides in this file + +:: chanhe the relative path up to dev +set ABS_PATH=%~dp0 + +:: project name as a str tag +IF "%LY_PROJECT_NAME%"=="" ( + for %%I in ("%~dp0.") do for %%J in ("%%~dpI.") do set LY_PROJECT_NAME=%%~nxJ + ) + +echo. +echo _____________________________________________________________________ +echo. +echo ~ Setting up O3DE %LY_PROJECT_NAME% Environment ... +echo _____________________________________________________________________ +echo. +echo LY_PROJECT_NAME = %LY_PROJECT_NAME% + +:: if the user has set up a custom env call it +:: this should allow the user to locally +:: set env hooks like LY_DEV or LY_PROJECT +IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat +echo LY_DEV = %LY_DEV% + +:: Constant Vars (Global) +:: global debug flag (propogates) +:: The intent here is to set and globally enter a debug mode +IF "%DCCSI_GDEBUG%"=="" (set DCCSI_GDEBUG=false) +echo DCCSI_GDEBUG = %DCCSI_GDEBUG% +:: initiates earliest debugger connection +:: we support attaching to WingIDE... PyCharm and VScode in the future +IF "%DCCSI_DEV_MODE%"=="" (set DCCSI_DEV_MODE=false) +echo DCCSI_DEV_MODE = %DCCSI_DEV_MODE% +:: sets debugger, options: WING, PYCHARM +IF "%DCCSI_GDEBUGGER%"=="" (set DCCSI_GDEBUGGER=WING) +echo DCCSI_GDEBUGGER = %DCCSI_GDEBUGGER% +:: Default level logger will handle +:: Override this to control the setting +:: CRITICAL:50 +:: ERROR:40 +:: WARNING:30 +:: INFO:20 +:: DEBUG:10 +:: NOTSET:0 +IF "%DCCSI_LOGLEVEL%"=="" (set DCCSI_LOGLEVEL=20) +echo DCCSI_LOGLEVEL = %DCCSI_LOGLEVEL% + +:: Override the default maya version +IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=2020) +echo DCCSI_MAYA_VERSION = %DCCSI_MAYA_VERSION% + +:: LY_PROJECT is ideally treated as a full path in the env launchers +:: do to changes in o3de, external engine/project/gem folder structures, etc. +IF "%LY_PROJECT%"=="" ( + for %%i in ("%~dp0..") do set "LY_PROJECT=%%~fi" + ) +echo LY_PROJECT = %LY_PROJECT% + +:: this is here for archaic reasons, WILL DEPRECATE +IF "%LY_PROJECT_PATH%"=="" (set LY_PROJECT_PATH=%LY_PROJECT%) +echo LY_PROJECT_PATH = %LY_PROJECT_PATH% + +:: Change to root Lumberyard dev dir +:: You must set this in a User_Env.bat to match youe engine repo location! +IF "%LY_DEV%"=="" (set LY_DEV=C:\Depot\o3de-engine) +echo LY_DEV = %LY_DEV% + +CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat + +:: Restore original directory +popd + +:: Change to root dir +CD /D %ABS_PATH% + +::ENDLOCAL + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_PROJ_ENV_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/AtomContent/ReferenceMaterials/Tools/User_Env.bat.template b/Gems/AtomContent/ReferenceMaterials/Tools/User_Env.bat.template new file mode 100644 index 0000000000..d108f30a5b --- /dev/null +++ b/Gems/AtomContent/ReferenceMaterials/Tools/User_Env.bat.template @@ -0,0 +1,42 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: copy this file, rename to User_Env.bat (remove .template) +:: use this file to override any local properties that differ from base + +:: Skip initialization if already completed +IF "%O3DE_USER_ENV_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +SET O3DE_DEV=C:\Depot\o3de-engine +::SET OCIO_APPS=C:\Depot\o3de-engine\Tools\ColorGrading\ocio\build\src\apps +SET TAG_LY_BUILD_PATH=build +SET DCCSI_GDEBUG=True +SET DCCSI_DEV_MODE=True + +set DCCSI_MAYA_VERSION=2020 + +:: set the your user name here for windows path +SET TAG_USERNAME=NOT_SET +SET DCCSI_PY_REV=rev1 +SET DCCSI_PY_PLATFORM=windows + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_USER_ENV_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE \ No newline at end of file diff --git a/Gems/AtomContent/ReferenceMaterials/gem.json b/Gems/AtomContent/ReferenceMaterials/gem.json index d66c2fa1db..9e145c20cc 100644 --- a/Gems/AtomContent/ReferenceMaterials/gem.json +++ b/Gems/AtomContent/ReferenceMaterials/gem.json @@ -1,11 +1,11 @@ { "gem_name": "ReferenceMaterials", - "display_name": "ReferenceMaterials", - "license": "Apache-2.0 Or MIT", - "origin": "Open 3D Engine - o3de.org", + "display_name": "PBR Reference Materials", + "license": "Code, text, data files: Apache-2.0 Or MIT, assets/content/images: CC BY 4.0", + "origin": "https://github.com/aws-lumberyard-dev/o3de.git", "type": "Asset", "summary": "Atom Asset Gem with a library of reference materials for StandardPBR (and others in the future)", "canonical_tags": ["Gem"], - "user_tags": ["Assets"], - "requirements": "" + "user_tags": ["Assets", "PBR", "Materials"], + "icon_path": "preview.png" } diff --git a/Gems/AtomContent/Sponza/Project_Env.bat b/Gems/AtomContent/Sponza/Project_Env.bat deleted file mode 100644 index 74b70a2320..0000000000 --- a/Gems/AtomContent/Sponza/Project_Env.bat +++ /dev/null @@ -1,72 +0,0 @@ -@echo off -REM -REM Copyright (c) Contributors to the Open 3D Engine Project. -REM For complete copyright and license terms please see the LICENSE at the root of this distribution. -REM -REM SPDX-License-Identifier: Apache-2.0 OR MIT -REM -REM - -:: Store current dir -%~d0 -cd %~dp0 -PUSHD %~dp0 - -:: This is a legacy envar which is being migrated to LY_PROJECT_NAME -for %%a in (.) do set LY_PROJECT=%%~na - -echo. -echo _____________________________________________________________________ -echo. -echo ~ Setting up LY DSI PROJECT Environment ... -echo _____________________________________________________________________ -echo. - -echo LY_PROJECT = %LY_PROJECT% - -set LY_PROJECT_NAME=%LY_PROJECT% -echo LY_PROJECT_NAME = %LY_PROJECT_NAME% - -:: Put you project env vars and overrides here - -:: chanhe the relative path up to dev -set DEV_REL_PATH=../../.. -set ABS_PATH=%~dp0 - -:: Override the default maya version -set MAYA_VERSION=2020 -echo MAYA_VERSION = %MAYA_VERSION% - -set LY_PROJECT_PATH=%ABS_PATH% -echo LY_PROJECT_PATH = %LY_PROJECT_PATH% - -:: Change to root Lumberyard dev dir -CD /d %LY_PROJECT_PATH%\%DEV_REL_PATH% -set LY_DEV=%CD% -echo LY_DEV = %LY_DEV% - -CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat - -rem :: Constant Vars (Global) -rem SET LYPY_GDEBUG=0 -rem echo LYPY_GDEBUG = %LYPY_GDEBUG% -rem SET LYPY_DEV_MODE=0 -rem echo LYPY_DEV_MODE = %LYPY_DEV_MODE% -rem SET LYPY_DEBUGGER=WING -rem echo LYPY_DEBUGGER = %LYPY_DEBUGGER% - -:: Restore original directory -popd - -:: Change to root dir -CD /D %ABS_PATH% - -:: if the user has set up a custom env call it -IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat - -GOTO END_OF_FILE - -:: Return to starting directory -POPD - -:END_OF_FILE diff --git a/Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat b/Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat index 2636b3dea4..99c2c12c51 100644 --- a/Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat +++ b/Gems/AtomContent/Sponza/Tools/Launch_Cmd.bat @@ -1,19 +1,19 @@ @echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project REM -REM Copyright (c) Contributors to the Open 3D Engine Project. -REM For complete copyright and license terms please see the LICENSE at the root of this distribution. -REM REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. REM REM -@echo off -:: Set up and run LY Python CMD prompt -:: Sets up the DccScriptingInterface_Env, +:: Set up and start a O3DE CMD prompt +:: Sets up the current (DCC) Project_Env, :: Puts you in the CMD within the dev environment :: Set up window -TITLE Lumberyard DCC Scripting Interface Cmd +TITLE O3DE DCC Scripting Interface Cmd :: Use obvious color to prevent confusion (Grey with Yellow Text) COLOR 8E @@ -24,7 +24,7 @@ PUSHD %~dp0 :: Keep changes local SETLOCAL enableDelayedExpansion -CALL %~dp0\..\Project_Env.bat +CALL %~dp0\Project_Env.bat echo. echo _____________________________________________________________________ diff --git a/Gems/AtomContent/Sponza/Tools/Maya/Launch_Maya_2020.bat b/Gems/AtomContent/Sponza/Tools/Launch_Maya.bat similarity index 63% rename from Gems/AtomContent/Sponza/Tools/Maya/Launch_Maya_2020.bat rename to Gems/AtomContent/Sponza/Tools/Launch_Maya.bat index 53344d527e..d774adf79b 100644 --- a/Gems/AtomContent/Sponza/Tools/Maya/Launch_Maya_2020.bat +++ b/Gems/AtomContent/Sponza/Tools/Launch_Maya.bat @@ -1,4 +1,5 @@ @echo off + REM REM Copyright (c) Contributors to the Open 3D Engine Project. REM For complete copyright and license terms please see the LICENSE at the root of this distribution. @@ -7,11 +8,6 @@ REM SPDX-License-Identifier: Apache-2.0 OR MIT REM REM -:: Launches maya wityh a bunch of local hooks for Lumberyard -:: ToDo: move all of this to a .json data driven boostrapping system - -@echo off - %~d0 cd %~dp0 PUSHD %~dp0 @@ -23,22 +19,22 @@ echo ~ calling PROJ_Env.bat SETLOCAL enableDelayedExpansion :: PY version Major -set DCCSI_PY_VERSION_MAJOR=2 +IF "%DCCSI_PY_VERSION_MAJOR%"=="" (set DCCSI_PY_VERSION_MAJOR=2) echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR% :: PY version Major -set DCCSI_PY_VERSION_MINOR=7 +IF "%DCCSI_PY_VERSION_MINOR%"=="" (set DCCSI_PY_VERSION_MINOR=7) echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR% :: Maya Version -set MAYA_VERSION=2020 -echo MAYA_VERSION = %MAYA_VERSION% +IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=2020) +echo DCCSI_MAYA_VERSION = %DCCSI_MAYA_VERSION% :: if a local customEnv.bat exists, run it -IF EXIST "%~dp0..\..\Project_Env.bat" CALL %~dp0..\..\Project_Env.bat +IF EXIST "%~dp0Project_Env.bat" CALL %~dp0Project_Env.bat echo ________________________________ -echo Launching Maya %MAYA_VERSION% for Lumberyard... +echo Launching Maya %DCCSI_MAYA_VERSION% for Lumberyard... :::: Set Maya native project acess to this project ::set MAYA_PROJECT=%LY_PROJECT% @@ -49,15 +45,15 @@ Set MAYA_VP2_DEVICE_OVERRIDE = VirtualDeviceDx11 :: Default to the right version of Maya if we can detect it... and launch IF EXIST "%MAYA_LOCATION%\bin\Maya.exe" ( - start "" "%MAYA_LOCATION%\bin\Maya.exe" %* + start "" "%MAYA_LOCATION%\bin\Maya.exe" %* ) ELSE ( - Where maya.exe 2> NUL - IF ERRORLEVEL 1 ( - echo Maya.exe could not be found - pause - ) ELSE ( - start "" Maya.exe %* - ) + Where maya.exe 2> NUL + IF ERRORLEVEL 1 ( + echo Maya.exe could not be found + pause + ) ELSE ( + start "" Maya.exe %* + ) ) :: Return to starting directory @@ -65,4 +61,4 @@ POPD :END_OF_FILE -exit /b 0 \ No newline at end of file +exit /b 0 diff --git a/Gems/AtomContent/Sponza/Tools/Maya/Scripts/stub b/Gems/AtomContent/Sponza/Tools/Maya/Scripts/stub deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Gems/AtomContent/Sponza/Tools/Project_Env.bat b/Gems/AtomContent/Sponza/Tools/Project_Env.bat new file mode 100644 index 0000000000..6e2c8b5914 --- /dev/null +++ b/Gems/AtomContent/Sponza/Tools/Project_Env.bat @@ -0,0 +1,110 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: Sets up environment for O3DE DCC tools and code access + +:: Set up window +TITLE O3DE Asset Gem +:: Use obvious color to prevent confusion (Grey with Yellow Text) +COLOR 8E + +:: Skip initialization if already completed +IF "%O3DE_PROJ_ENV_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +:: Put you project env vars and overrides in this file + +:: chanhe the relative path up to dev +set ABS_PATH=%~dp0 + +:: project name as a str tag +IF "%LY_PROJECT_NAME%"=="" ( + for %%I in ("%~dp0.") do for %%J in ("%%~dpI.") do set LY_PROJECT_NAME=%%~nxJ + ) + +echo. +echo _____________________________________________________________________ +echo. +echo ~ Setting up O3DE %LY_PROJECT_NAME% Environment ... +echo _____________________________________________________________________ +echo. +echo LY_PROJECT_NAME = %LY_PROJECT_NAME% + +:: if the user has set up a custom env call it +:: this should allow the user to locally +:: set env hooks like LY_DEV or LY_PROJECT +IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat +echo LY_DEV = %LY_DEV% + +:: Constant Vars (Global) +:: global debug flag (propogates) +:: The intent here is to set and globally enter a debug mode +IF "%DCCSI_GDEBUG%"=="" (set DCCSI_GDEBUG=false) +echo DCCSI_GDEBUG = %DCCSI_GDEBUG% +:: initiates earliest debugger connection +:: we support attaching to WingIDE... PyCharm and VScode in the future +IF "%DCCSI_DEV_MODE%"=="" (set DCCSI_DEV_MODE=false) +echo DCCSI_DEV_MODE = %DCCSI_DEV_MODE% +:: sets debugger, options: WING, PYCHARM +IF "%DCCSI_GDEBUGGER%"=="" (set DCCSI_GDEBUGGER=WING) +echo DCCSI_GDEBUGGER = %DCCSI_GDEBUGGER% +:: Default level logger will handle +:: Override this to control the setting +:: CRITICAL:50 +:: ERROR:40 +:: WARNING:30 +:: INFO:20 +:: DEBUG:10 +:: NOTSET:0 +IF "%DCCSI_LOGLEVEL%"=="" (set DCCSI_LOGLEVEL=20) +echo DCCSI_LOGLEVEL = %DCCSI_LOGLEVEL% + +:: Override the default maya version +IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=2020) +echo DCCSI_MAYA_VERSION = %DCCSI_MAYA_VERSION% + +:: LY_PROJECT is ideally treated as a full path in the env launchers +:: do to changes in o3de, external engine/project/gem folder structures, etc. +IF "%LY_PROJECT%"=="" ( + for %%i in ("%~dp0..") do set "LY_PROJECT=%%~fi" + ) +echo LY_PROJECT = %LY_PROJECT% + +:: this is here for archaic reasons, WILL DEPRECATE +IF "%LY_PROJECT_PATH%"=="" (set LY_PROJECT_PATH=%LY_PROJECT%) +echo LY_PROJECT_PATH = %LY_PROJECT_PATH% + +:: Change to root Lumberyard dev dir +:: You must set this in a User_Env.bat to match youe engine repo location! +IF "%LY_DEV%"=="" (set LY_DEV=C:\Depot\o3de-engine) +echo LY_DEV = %LY_DEV% + +CALL %LY_DEV%\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\Launchers\Windows\Env_Maya.bat + +:: Restore original directory +popd + +:: Change to root dir +CD /D %ABS_PATH% + +::ENDLOCAL + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_PROJ_ENV_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE diff --git a/Gems/AtomContent/Sponza/Tools/User_Env.bat.template b/Gems/AtomContent/Sponza/Tools/User_Env.bat.template new file mode 100644 index 0000000000..d108f30a5b --- /dev/null +++ b/Gems/AtomContent/Sponza/Tools/User_Env.bat.template @@ -0,0 +1,42 @@ +@echo off + +REM +REM Copyright (c) Contributors to the Open 3D Engine Project +REM +REM SPDX-License-Identifier: Apache-2.0 OR MIT +REM For complete copyright and license terms please see the LICENSE at the root of this distribution. +REM +REM + +:: copy this file, rename to User_Env.bat (remove .template) +:: use this file to override any local properties that differ from base + +:: Skip initialization if already completed +IF "%O3DE_USER_ENV_INIT%"=="1" GOTO :END_OF_FILE + +:: Store current dir +%~d0 +cd %~dp0 +PUSHD %~dp0 + +SET O3DE_DEV=C:\Depot\o3de-engine +::SET OCIO_APPS=C:\Depot\o3de-engine\Tools\ColorGrading\ocio\build\src\apps +SET TAG_LY_BUILD_PATH=build +SET DCCSI_GDEBUG=True +SET DCCSI_DEV_MODE=True + +set DCCSI_MAYA_VERSION=2020 + +:: set the your user name here for windows path +SET TAG_USERNAME=NOT_SET +SET DCCSI_PY_REV=rev1 +SET DCCSI_PY_PLATFORM=windows + +:: Set flag so we don't initialize dccsi environment twice +SET O3DE_USER_ENV_INIT=1 +GOTO END_OF_FILE + +:: Return to starting directory +POPD + +:END_OF_FILE \ No newline at end of file diff --git a/Gems/AtomContent/Sponza/User_env.bat.template b/Gems/AtomContent/Sponza/User_env.bat.template deleted file mode 100644 index 99bc7a951d..0000000000 --- a/Gems/AtomContent/Sponza/User_env.bat.template +++ /dev/null @@ -1 +0,0 @@ -set LY_DEV=C:\Depot\o3de-engine \ No newline at end of file diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Maya.bat b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Maya.bat index f3d9aaec69..cceaa80b75 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Maya.bat +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/Launchers/Windows/Env_Maya.bat @@ -27,7 +27,7 @@ IF "%DCCSI_PY_VERSION_MINOR%"=="" (set DCCSI_PY_VERSION_MINOR=7) IF "%DCCSI_PY_VERSION_RELEASE%"=="" (set DCCSI_PY_VERSION_RELEASE=11) :: Default Maya Version -IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=2020) +IF "%DCCSI_MAYA_VERSION%"=="" (set DCCSI_MAYA_VERSION=%MAYA_VERSION%) :: Initialize env CALL %~dp0\Env_Core.bat diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py index 4baf68d85e..2df85cbfaa 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py @@ -7,15 +7,16 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # -# -- This line is 75 characters ------------------------------------------- +# note: this module should reamin py2.7 compatible (Maya) so no f'strings +# -------------------------------------------------------------------------- import sys import os import re import site import logging as _logging +# ------------------------------------------------------------------------- + -from pathlib import Path # note: we provide this in py2.7 -# so using it here suggests some boostrapping has occured before using azpy # -------------------------------------------------------------------------- _PACKAGENAME = 'azpy.config_utils' @@ -28,8 +29,31 @@ _LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME})) __all__ = ['get_os', 'return_stub', 'get_stub_check_path', 'get_dccsi_config', 'get_current_project'] +# ------------------------------------------------------------------------- -# note: this module should reamin py2.7 compatible (Maya) so no f'strings + +# ------------------------------------------------------------------------- +# just a quick check to ensure what paths have code access +_G_DEBUG = False # enable for debug prints +if _G_DEBUG: + known_paths = list() + for p in sys.path: + known_paths.append(p) + _LOGGER.debug(known_paths) + +# this import can fail in Maya 2020 (and earlier) stuck on py2.7 +# wrapped in a try, to trap and providing messaging to help user correct +try: + from pathlib import Path # note: we provide this in py2.7 + # so using it here suggests some boostrapping has occured before using azpy +except Exception as e: + _LOGGER.warning('Maya 2020 and below, use py2.7') + _LOGGER.warning('py2.7 does not include pathlib') + _LOGGER.warning('Try installing the O3DE DCCsi py2.7 requirements.txt') + _LOGGER.warning("See instructions: 'C:\\< your o3de engine >\\Gems\\AtomLyIntegration\\TechnicalArt\\DccScriptingInterface\\SDK\Maya\\readme.txt'") + _LOGGER.warning("Other code in this module with fail!!!") + _LOGGER.error(e) + pass # fail gracefully, note: code accesing Path will fail! # ------------------------------------------------------------------------- From c673988935b0602c8ed33b347c02bbc1605e178f Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 17:58:06 -0400 Subject: [PATCH 144/274] Unittest refactoring Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Tests/ClientHierarchyTests.cpp | 160 ++-- .../Code/Tests/CommonHierarchySetup.h | 82 +- .../Code/Tests/ServerHierarchyTests.cpp | 758 +++++++++--------- 3 files changed, 509 insertions(+), 491 deletions(-) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 1483f32023..38ea451c85 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -27,14 +27,14 @@ namespace Multiplayer */ TEST_F(HierarchyTests, On_Client_NetBindComponent_Activate) { - AZ::Entity entity; - entity.CreateComponent(); + AZStd::unique_ptr entity = AZStd::make_unique(); + entity->CreateComponent(); SetupEntity(entity, NetEntityId{ 1 }, NetEntityRole::Client); - entity.Activate(); + entity->Activate(); StopEntity(entity); - entity.Deactivate(); + entity->Deactivate(); } /* @@ -43,7 +43,7 @@ namespace Multiplayer TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_BeforeParent) { // Create a child entity that will be tested for activation inside a hierarchy - AZ::Entity childEntity; + AZStd::unique_ptr childEntity = AZStd::make_unique(); CreateEntityWithChildHierarchy(childEntity); SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); // child entity is not activated on purpose here, we are about to test conditional activation check @@ -53,7 +53,7 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(childEntity.get(), m_networkEntityTracker.get()); EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); entityReplicator.Initialize(childHandle); @@ -64,7 +64,7 @@ namespace Multiplayer TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_Inner_Root_Before_Top_Root) { // Create a child entity that will be tested for activation inside a hierarchy - AZ::Entity innerRootEntity; + AZStd::unique_ptr innerRootEntity = AZStd::make_unique(); CreateEntityWithRootHierarchy(innerRootEntity); SetupEntity(innerRootEntity, NetEntityId{ 2 }, NetEntityRole::Client); // child entity is not activated on purpose here, we are about to test conditional activation check @@ -74,7 +74,7 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(innerRootEntity, NetEntityId{ 1 }); // Create an entity replicator for the child entity - const NetworkEntityHandle innerRootHandle(&innerRootEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle innerRootHandle(innerRootEntity.get(), m_networkEntityTracker.get()); EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, innerRootHandle); entityReplicator.Initialize(innerRootHandle); @@ -85,7 +85,7 @@ namespace Multiplayer TEST_F(HierarchyTests, On_Client_Not_In_Hierarchy_EntityReplicator_Ignores_Parent) { // Create a child entity that will be tested for activation inside a hierarchy - AZ::Entity childEntity; + AZStd::unique_ptr childEntity = AZStd::make_unique(); CreateEntityWithChildHierarchy(childEntity); SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); // child entity is not activated on purpose here, we are about to test conditional activation check @@ -95,7 +95,7 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, InvalidNetEntityId); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(childEntity.get(), m_networkEntityTracker.get()); EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); entityReplicator.Initialize(childHandle); @@ -108,7 +108,7 @@ namespace Multiplayer */ TEST_F(HierarchyTests, On_Client_EntityReplicator_Activates_AfterParent) { - AZ::Entity childEntity; + AZStd::unique_ptr childEntity = AZStd::make_unique(); CreateEntityWithChildHierarchy(childEntity); SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); @@ -117,29 +117,29 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(childEntity.get(), m_networkEntityTracker.get()); EntityReplicator childEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); childEntityReplicator.Initialize(childHandle); // Now let's create a parent entity and activate it - AZ::Entity parentEntity; + AZStd::unique_ptr parentEntity = AZStd::make_unique(); CreateEntityWithRootHierarchy(parentEntity); SetupEntity(parentEntity, NetEntityId{ 1 }, NetEntityRole::Client); // Create an entity replicator for the parent entity - const NetworkEntityHandle parentHandle(&parentEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle parentHandle(parentEntity.get(), m_networkEntityTracker.get()); ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Return(parentHandle)); EntityReplicator parentEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, parentHandle); parentEntityReplicator.Initialize(parentHandle); - parentEntity.Activate(); + parentEntity->Activate(); // The child should be ready to be activated EXPECT_EQ(childEntityReplicator.IsReadyToActivate(), true); StopEntity(parentEntity); - parentEntity.Deactivate(); + parentEntity->Deactivate(); } /* @@ -155,25 +155,19 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_root = AZStd::make_unique(1, "root", RootNetEntityId, EntityInfo::Role::Root); + m_child = AZStd::make_unique(2, "child", ChildNetEntityId, EntityInfo::Role::Child); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + CreateSimpleHierarchy(*m_root, *m_child); - CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // now the two entities are under one hierarchy } void TearDown() override { - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } @@ -191,20 +185,20 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(child.m_entity, root.m_netId); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); child.m_replicator->Initialize(childHandle); // Create an entity replicator for the root entity - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); } - void SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(const AZ::Entity& entity, NetEntityId value) + void SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(const AZStd::unique_ptr& entity, NetEntityId value) { /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; @@ -225,47 +219,44 @@ namespace Multiplayer ReplicationRecord notifyRecord = currentRecord; - entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + entity->FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + entity->FindComponent()->NotifyStateDeltaChanges(notifyRecord); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; }; TEST_F(ClientSimpleHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchyRoot(), + m_root->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), - m_rootEntity.get() + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 2) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 2) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); } } @@ -273,15 +264,15 @@ namespace Multiplayer TEST_F(ClientSimpleHierarchyTests, Client_Detaches_Child_When_Server_Detaches) { // simulate server detaching child entity - SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); - SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + SetParentIdOnNetworkTransform(m_child->m_entity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(m_child->m_entity, InvalidNetEntityId); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), nullptr ); } @@ -289,13 +280,13 @@ namespace Multiplayer TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Updated_Event_On_Child_Detached_On_Server) { MockNetworkHierarchyCallbackHandler mock; - EXPECT_CALL(mock, OnNetworkHierarchyUpdated(m_rootEntity->GetId())); + EXPECT_CALL(mock, OnNetworkHierarchyUpdated(m_root->m_entity->GetId())); - m_rootEntity->FindComponent()->BindNetworkHierarchyChangedEventHandler(mock.m_changedHandler); + m_root->m_entity->FindComponent()->BindNetworkHierarchyChangedEventHandler(mock.m_changedHandler); // simulate server detaching a child entity - SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); - SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + SetParentIdOnNetworkTransform(m_child->m_entity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(m_child->m_entity, InvalidNetEntityId); } TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Leave_Event_On_Child_Detached_On_Server) @@ -303,11 +294,11 @@ namespace Multiplayer MockNetworkHierarchyCallbackHandler mock; EXPECT_CALL(mock, OnNetworkHierarchyLeave); - m_childEntity->FindComponent()->BindNetworkHierarchyLeaveEventHandler(mock.m_leaveHandler); + m_child->m_entity->FindComponent()->BindNetworkHierarchyLeaveEventHandler(mock.m_leaveHandler); // simulate server detaching a child entity - SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); - SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + SetParentIdOnNetworkTransform(m_child->m_entity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(m_child->m_entity, InvalidNetEntityId); } /* @@ -322,18 +313,16 @@ namespace Multiplayer { ClientSimpleHierarchyTests::SetUp(); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", ChildOfChildNetEntityId, EntityInfo::Role::Child); - CreateDeepHierarchyOnClient(*m_childOfChildEntityInfo); + CreateDeepHierarchyOnClient(*m_childOfChild); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); } void TearDown() override { - m_childOfChildEntityInfo.reset(); - StopAndDeleteEntity(m_childOfChildEntity); + m_childOfChild.reset(); ClientSimpleHierarchyTests::TearDown(); } @@ -344,58 +333,57 @@ namespace Multiplayer SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Client); // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) - SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childEntityInfo->m_netId); - SetHierarchyRootFieldOnNetworkHierarchyChild(childOfChild.m_entity, m_rootEntityInfo->m_netId); + SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childOfChild->m_netId); + SetHierarchyRootFieldOnNetworkHierarchyChild(childOfChild.m_entity, m_root->m_netId); // Create an entity replicator for the child entity - const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childOfChildHandle); childOfChild.m_replicator->Initialize(childOfChildHandle); - childOfChild.m_entity.Activate(); + childOfChild.m_entity->Activate(); } - AZStd::unique_ptr m_childOfChildEntity; - AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_childOfChild; }; TEST_F(ClientDeepHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchyRoot(), + m_root->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), - m_rootEntity.get() + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); } } diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h index d4f9d218e2..7fc1eef8b7 100644 --- a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -38,6 +38,7 @@ namespace Multiplayer class NetworkHierarchyCallbacks { public: + virtual ~NetworkHierarchyCallbacks() = default; virtual void OnNetworkHierarchyLeave() = 0; virtual void OnNetworkHierarchyUpdated(const AZ::EntityId& hierarchyRootId) = 0; }; @@ -245,48 +246,48 @@ namespace Multiplayer return nullptr; } - void SetupEntity(AZ::Entity& entity, NetEntityId netId, NetEntityRole role) + void SetupEntity(const AZStd::unique_ptr& entity, NetEntityId netId, NetEntityRole role) { - const auto netBindComponent = entity.FindComponent(); + const auto netBindComponent = entity->FindComponent(); EXPECT_NE(netBindComponent, nullptr); - netBindComponent->PreInit(&entity, PrefabEntityId{ AZ::Name("test"), 1 }, netId, role); - entity.Init(); + netBindComponent->PreInit(entity.get(), PrefabEntityId{ AZ::Name("test"), 1 }, netId, role); + entity->Init(); } - void StopEntity(const AZ::Entity& entity) + static void StopEntity(const AZStd::unique_ptr& entity) { - const auto netBindComponent = entity.FindComponent(); + const auto netBindComponent = entity->FindComponent(); EXPECT_NE(netBindComponent, nullptr); netBindComponent->StopEntity(); } - void StopAndDeleteEntity(AZStd::unique_ptr& entity) + static void StopAndDeactivateEntity(AZStd::unique_ptr& entity) { if (entity) { - StopEntity(*entity); + StopEntity(entity); entity->Deactivate(); entity.reset(); } } - void CreateEntityWithRootHierarchy(AZ::Entity& rootEntity) + void CreateEntityWithRootHierarchy(AZStd::unique_ptr& rootEntity) { - rootEntity.CreateComponent(); - rootEntity.CreateComponent(); - rootEntity.CreateComponent(); - rootEntity.CreateComponent(); + rootEntity->CreateComponent(); + rootEntity->CreateComponent(); + rootEntity->CreateComponent(); + rootEntity->CreateComponent(); } - void CreateEntityWithChildHierarchy(AZ::Entity& childEntity) + void CreateEntityWithChildHierarchy(AZStd::unique_ptr& childEntity) { - childEntity.CreateComponent(); - childEntity.CreateComponent(); - childEntity.CreateComponent(); - childEntity.CreateComponent(); + childEntity->CreateComponent(); + childEntity->CreateComponent(); + childEntity->CreateComponent(); + childEntity->CreateComponent(); } - void SetParentIdOnNetworkTransform(const AZ::Entity& entity, NetEntityId netParentId) + void SetParentIdOnNetworkTransform(const AZStd::unique_ptr& entity, NetEntityId netParentId) { /* Derived from NetworkTransformComponent.AutoComponent.xml */ constexpr int totalBits = 6 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::Count*/; @@ -306,12 +307,12 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); ReplicationRecord notifyRecord = currentRecord; - entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + entity->FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + entity->FindComponent()->NotifyStateDeltaChanges(notifyRecord); } template - void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZ::Entity& entity, NetEntityId value) + void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZStd::unique_ptr& entity, NetEntityId value) { /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; @@ -331,8 +332,8 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); ReplicationRecord notifyRecord = currentRecord; - entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + entity->FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + entity->FindComponent()->NotifyStateDeltaChanges(notifyRecord); } struct EntityInfo @@ -344,14 +345,19 @@ namespace Multiplayer None }; - EntityInfo(AZ::Entity& entity, NetEntityId netId, Role role) - : m_entity(entity) + EntityInfo(AZ::u64 entityId, const char* entityName, NetEntityId netId, Role role) + : m_entity(AZStd::make_unique(AZ::EntityId(entityId), entityName)) , m_netId(netId) , m_role(role) { } - AZ::Entity& m_entity; + ~EntityInfo() + { + StopAndDeactivateEntity(m_entity); + } + + AZStd::unique_ptr m_entity; NetEntityId m_netId; AZStd::unique_ptr m_replicator; Role m_role = Role::None; @@ -359,16 +365,16 @@ namespace Multiplayer void PopulateHierarchicalEntity(const EntityInfo& entityInfo) { - entityInfo.m_entity.CreateComponent(); - entityInfo.m_entity.CreateComponent(); - entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity->CreateComponent(); + entityInfo.m_entity->CreateComponent(); + entityInfo.m_entity->CreateComponent(); switch (entityInfo.m_role) { case EntityInfo::Role::Root: - entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity->CreateComponent(); break; case EntityInfo::Role::Child: - entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity->CreateComponent(); break; case EntityInfo::Role::None: break; @@ -390,23 +396,23 @@ namespace Multiplayer SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); // Create an entity replicator for the child entity - const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); childOfChild.m_replicator->Initialize(childOfChildHandle); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); child.m_replicator->Initialize(childHandle); // Create an entity replicator for the root entity - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); - childOfChild.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); + childOfChild.m_entity->Activate(); } }; } diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index 0b76e276fd..05e36e466d 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -35,25 +35,19 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_root = AZStd::make_unique(1, "root", NetEntityId{ 1 }, EntityInfo::Role::Root); + m_child = AZStd::make_unique(2, "child", NetEntityId{ 2 }, EntityInfo::Role::Child); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); + CreateSimpleHierarchy(*m_root, *m_child); - CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // now the two entities are under one hierarchy } void TearDown() override { - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } @@ -67,35 +61,32 @@ namespace Multiplayer SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); child.m_replicator->Initialize(childHandle); // Create an entity replicator for the root entity - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; }; TEST_F(ServerSimpleHierarchyTests, Server_Sets_Appropriate_Network_Fields_For_Clients) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchyRoot(), + m_root->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), NetEntityId{ 1 } ); } @@ -103,7 +94,7 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Root_Is_Top_Level_Root) { EXPECT_EQ( - m_rootEntity->FindComponent()->IsHierarchicalChild(), + m_root->m_entity->FindComponent()->IsHierarchicalChild(), false ); } @@ -111,18 +102,18 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Set) { EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), NetEntityId{ 1 } ); } TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Cleared_On_Detach) { - // now detach the child - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + // now detach the child + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } @@ -130,7 +121,7 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_Reference) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } @@ -138,34 +129,32 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_References_Removed_On_Detach) { // now detach the child - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerSimpleHierarchyTests, Root_Deactivates_Child_Has_No_References_To_Root) { - StopEntity(*m_rootEntity); - m_rootEntity->Deactivate(); - m_rootEntity.reset(); + StopEntity(m_root->m_entity); + m_root->m_entity->Deactivate(); + m_root->m_entity.reset(); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerSimpleHierarchyTests, Child_Deactivates_Root_Has_No_References_To_Child) { - StopEntity(*m_childEntity); - m_childEntity->Deactivate(); - m_childEntity.reset(); + m_child.reset(); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } @@ -184,47 +173,35 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); - - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_root = AZStd::make_unique((1), "root", RootNetEntityId, EntityInfo::Role::Root); + m_child = AZStd::make_unique((2), "child", ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", ChildOfChildNetEntityId, EntityInfo::Role::Child); - CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); + CreateDeepHierarchy(*m_root, *m_child, *m_childOfChild); - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo.reset(); - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childOfChildEntity); - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_childOfChild.reset(); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - AZStd::unique_ptr m_childOfChildEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; - AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; + AZStd::unique_ptr m_childOfChild; }; TEST_F(ServerDeepHierarchyTests, Root_Is_Top_Level_Root) { EXPECT_EQ( - m_rootEntity->FindComponent()->IsHierarchicalChild(), + m_root->m_entity->FindComponent()->IsHierarchicalChild(), false ); } @@ -232,144 +209,144 @@ namespace Multiplayer TEST_F(ServerDeepHierarchyTests, Root_Has_Child_References) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); } } TEST_F(ServerDeepHierarchyTests, Root_Has_Child_Of_Child_Reference_Removed_On_Detach) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_Removed_On_Detach_Of_Mid_Child) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Mid_Child_Added_With_Child) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Child_Of_Child_Added) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Points_To_Root_After_Attach) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerDeepHierarchyTests, All_New_Children_Point_To_Root_If_Mid_Child_Added_With_Child) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Children_Clear_Reference_To_Root_After_Mid_Child_Detached) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Clears_Reference_To_Root_After_Detached) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Root_Deactivates_Children_Have_No_References_To_Root) { - StopAndDeleteEntity(m_rootEntity); + m_root.reset(); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Deactivates_Root_Removes_References_To_It) { - StopAndDeleteEntity(m_childOfChildEntity); + m_childOfChild.reset(); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } @@ -381,11 +358,11 @@ namespace Multiplayer m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); // remake the hierarchy - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); @@ -412,43 +389,29 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); - m_child2Entity = AZStd::make_unique(AZ::EntityId(4), "child2"); - m_childOfChild2Entity = AZStd::make_unique(AZ::EntityId(5), "child of child2"); - m_child2OfChild2Entity = AZStd::make_unique(AZ::EntityId(6), "child2 of child2"); - - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); - m_child2EntityInfo = AZStd::make_unique(*m_child2Entity.get(), Child2NetEntityId, EntityInfo::Role::Child); - m_childOfChild2EntityInfo = AZStd::make_unique(*m_childOfChild2Entity.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); - m_child2OfChild2EntityInfo = AZStd::make_unique(*m_child2OfChild2Entity.get(), Child2OfChild2NetEntityId, EntityInfo::Role::Child); - - CreateBranchedHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo, - *m_child2EntityInfo, *m_childOfChild2EntityInfo, *m_child2OfChild2EntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_root = AZStd::make_unique((1), "root", RootNetEntityId, EntityInfo::Role::Root); + m_child = AZStd::make_unique((2), "child", ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_child2 = AZStd::make_unique((4), "child2", Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChild2 = AZStd::make_unique((5), "child of child2", ChildOfChild2NetEntityId, EntityInfo::Role::Child); + m_child2OfChild2 = AZStd::make_unique((6), "child2 of child2", Child2OfChild2NetEntityId, EntityInfo::Role::Child); + + CreateBranchedHierarchy(*m_root, *m_child, *m_childOfChild, + *m_child2, *m_childOfChild2, *m_child2OfChild2); + + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_child2OfChild2EntityInfo.reset(); - m_childOfChild2EntityInfo.reset(); - m_child2EntityInfo.reset(); - m_childOfChildEntityInfo.reset(); - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_child2OfChild2Entity); - StopAndDeleteEntity(m_childOfChild2Entity); - StopAndDeleteEntity(m_child2Entity); - StopAndDeleteEntity(m_childOfChildEntity); - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_child2OfChild2.reset(); + m_childOfChild2.reset(); + m_child2.reset(); + m_childOfChild.reset(); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } @@ -479,139 +442,132 @@ namespace Multiplayer SetParentIdOnNetworkTransform(child2OfChild2.m_entity, child2.m_netId); // Create entity replicators - const NetworkEntityHandle childOfChild2Handle(&childOfChild2.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChild2Handle(childOfChild2.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChild2Handle); childOfChild.m_replicator->Initialize(childOfChild2Handle); - const NetworkEntityHandle child2OfChild2Handle(&child2OfChild2.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle child2OfChild2Handle(child2OfChild2.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2OfChild2Handle); childOfChild.m_replicator->Initialize(child2OfChild2Handle); - const NetworkEntityHandle child2Handle(&child2.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle child2Handle(child2.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2Handle); child.m_replicator->Initialize(child2Handle); - const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); childOfChild.m_replicator->Initialize(childOfChildHandle); - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); child.m_replicator->Initialize(childHandle); - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); - childOfChild.m_entity.Activate(); - child2.m_entity.Activate(); - childOfChild2.m_entity.Activate(); - child2OfChild2.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); + childOfChild.m_entity->Activate(); + child2.m_entity->Activate(); + childOfChild2.m_entity->Activate(); + child2OfChild2.m_entity->Activate(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - AZStd::unique_ptr m_childOfChildEntity; - AZStd::unique_ptr m_child2Entity; - AZStd::unique_ptr m_childOfChild2Entity; - AZStd::unique_ptr m_child2OfChild2Entity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; - AZStd::unique_ptr m_childOfChildEntityInfo; - AZStd::unique_ptr m_child2EntityInfo; - AZStd::unique_ptr m_childOfChild2EntityInfo; - AZStd::unique_ptr m_child2OfChild2EntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; + AZStd::unique_ptr m_childOfChild; + AZStd::unique_ptr m_child2; + AZStd::unique_ptr m_childOfChild2; + AZStd::unique_ptr m_child2OfChild2; }; TEST_F(ServerBranchedHierarchyTests, Sanity_Check) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 6) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 6) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], - m_child2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[3], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[4], - m_child2OfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[4], + m_child2OfChild2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[5], - m_childOfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[5], + m_childOfChild2->m_entity.get() ); } } TEST_F(ServerBranchedHierarchyTests, Detach_Child_While_Child2_Remains_Attached) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 4 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 4) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 4) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_child2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_child2OfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_child2OfChild2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], - m_childOfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[3], + m_childOfChild2->m_entity.get() ); } EXPECT_EQ( - m_child2Entity->FindComponent()->GetHierarchicalRoot(), - m_rootEntity.get() + m_child2->m_entity->FindComponent()->GetHierarchicalRoot(), + m_root->m_entity.get() ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), nullptr ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchicalRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchicalRoot(), nullptr ); } TEST_F(ServerBranchedHierarchyTests, Detach_Child_Then_Attach_To_Child2) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childEntity->FindComponent()->SetParent(m_child2Entity->GetId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } @@ -630,254 +586,242 @@ namespace Multiplayer { ServerDeepHierarchyTests::SetUp(); - m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); - m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); - m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + m_root2 = AZStd::make_unique((4), "root 2", Root2NetEntityId, EntityInfo::Role::Root); + m_child2 = AZStd::make_unique((5), "child 2", Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChild2 = AZStd::make_unique((6), "child of child 2", ChildOfChild2NetEntityId, EntityInfo::Role::Child); - m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), Root2NetEntityId, EntityInfo::Role::Root); - m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), Child2NetEntityId, EntityInfo::Role::Child); - m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); + CreateDeepHierarchy(*m_root2, *m_child2, *m_childOfChild2); - CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); - - m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root2->m_entity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo2.reset(); - m_childEntityInfo2.reset(); - m_rootEntityInfo2.reset(); - - StopAndDeleteEntity(m_childOfChildEntity2); - StopAndDeleteEntity(m_childEntity2); - StopAndDeleteEntity(m_rootEntity2); + m_childOfChild2.reset(); + m_child2.reset(); + m_root2.reset(); ServerDeepHierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity2; - AZStd::unique_ptr m_childEntity2; - AZStd::unique_ptr m_childOfChildEntity2; - - AZStd::unique_ptr m_rootEntityInfo2; - AZStd::unique_ptr m_childEntityInfo2; - AZStd::unique_ptr m_childOfChildEntityInfo2; + AZStd::unique_ptr m_root2; + AZStd::unique_ptr m_child2; + AZStd::unique_ptr m_childOfChild2; }; TEST_F(ServerHierarchyOfHierarchyTests, Hierarchies_Are_Not_Related) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); } EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild2->m_entity.get() ); } } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Is_Not_Top_Level_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->IsHierarchicalChild(), + m_root->m_entity->FindComponent()->IsHierarchicalChild(), false ); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child_Of_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchyRoot(), + m_root2->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchyRoot(), + m_root2->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child_Of_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchyRoot(), + m_root2->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Doesnt_Keep_Child_References) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 0 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Top_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild2->m_entity.get() ); } } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Top_Root_Deactivates) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - StopAndDeleteEntity(m_rootEntity); + m_root.reset(); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Top_Root_Deactivates) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - StopAndDeleteEntity(m_childEntity); + m_child.reset(); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Child_Deactivates) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); - StopAndDeleteEntity(m_childOfChildEntity); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_childOfChild.reset(); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } @@ -886,108 +830,108 @@ namespace Multiplayer { for (int i = 0; i < 100; ++i) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); } EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_Of_Child_In_Inner_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 5 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Attachment_Of_Child_Of_Child_In_Inner_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(AZ::EntityId()); // re-connect - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Of_Child_Changed_Hierarchies) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(AZ::EntityId()); // connect to a different hierarchy - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_In_Inner_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_child2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 4 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Changed_Hierarchies) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_child2->m_entity->FindComponent()->SetParent(AZ::EntityId()); // connect to a different hierarchy - m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_No_Child_References_After_All_Children_Moved_To_Another_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Child_Deactivated_Top_Root_Has_No_Child_Reference_To_It) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - StopAndDeleteEntity(m_childEntity2); + m_child2.reset(); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 4 ); } @@ -999,18 +943,18 @@ namespace Multiplayer m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); // remake the top level hierarchy - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); @@ -1028,68 +972,56 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); - - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), NetEntityId{ 3 }, EntityInfo::Role::None); + m_root = AZStd::make_unique((1), "root", NetEntityId{ 1 }, EntityInfo::Role::Root); + m_child = AZStd::make_unique((2), "child", NetEntityId{ 2 }, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", NetEntityId{ 3 }, EntityInfo::Role::None); - CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); + CreateDeepHierarchy(*m_root, *m_child, *m_childOfChild); - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo.reset(); - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childOfChildEntity); - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_childOfChild.reset(); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - AZStd::unique_ptr m_childOfChildEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; - AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; + AZStd::unique_ptr m_childOfChild; }; TEST_F(ServerMixedDeepHierarchyTests, Top_Root_Ignores_Non_Hierarchical_Entities) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } TEST_F(ServerMixedDeepHierarchyTests, Detaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } TEST_F(ServerMixedDeepHierarchyTests, Attaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childOfChildEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } @@ -1105,73 +1037,165 @@ namespace Multiplayer { ServerMixedDeepHierarchyTests::SetUp(); - m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); - m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); - m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); - - m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), NetEntityId{ 4 }, EntityInfo::Role::Root); - m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), NetEntityId{ 5 }, EntityInfo::Role::None); - m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), NetEntityId{ 6 }, EntityInfo::Role::Child); + m_root2 = AZStd::make_unique((4), "root 2", NetEntityId{ 4 }, EntityInfo::Role::Root); + m_child2 = AZStd::make_unique((5), "child 2", NetEntityId{ 5 }, EntityInfo::Role::None); + m_childOfChild2 = AZStd::make_unique((6), "child of child 2", NetEntityId{ 6 }, EntityInfo::Role::Child); - CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); + CreateDeepHierarchy(*m_root2, *m_child2, *m_childOfChild2); - m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root2->m_entity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo2.reset(); - m_childEntityInfo2.reset(); - m_rootEntityInfo2.reset(); - - - StopAndDeleteEntity(m_childOfChildEntity2); - StopAndDeleteEntity(m_childEntity2); - StopAndDeleteEntity(m_rootEntity2); + m_childOfChild2.reset(); + m_child2.reset(); + m_root2.reset(); ServerMixedDeepHierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity2; - AZStd::unique_ptr m_childEntity2; - AZStd::unique_ptr m_childOfChildEntity2; - - AZStd::unique_ptr m_rootEntityInfo2; - AZStd::unique_ptr m_childEntityInfo2; - AZStd::unique_ptr m_childOfChildEntityInfo2; + AZStd::unique_ptr m_root2; + AZStd::unique_ptr m_child2; + AZStd::unique_ptr m_childOfChild2; }; TEST_F(ServerMixedHierarchyOfHierarchyTests, Sanity_Check_Ingore_Children_Without_Hierarchy_Components) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerMixedHierarchyOfHierarchyTests, Adding_Mixed_Hierarchy_Ingores_Children_Without_Hierarchy_Components) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerMixedHierarchyOfHierarchyTests, Attaching_Hierarchy_To_Non_Hierarchical_Entity_Does_Not_Merge_Hierarchies) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), false ); } + + /* + * Sets up a hierarchy with 3 roots, 2 of them being inner roots. + */ + class ServerHierarchyWithThreeRoots : public ServerHierarchyOfHierarchyTests + { + public: + static const NetEntityId Root3NetEntityId = NetEntityId{ 7 }; + static const NetEntityId Child3NetEntityId = NetEntityId{ 8 }; + static const NetEntityId ChildOfChild3NetEntityId = NetEntityId{ 9 }; + + void SetUp() override + { + ServerHierarchyOfHierarchyTests::SetUp(); + + m_root3 = AZStd::make_unique((7), "root 3", Root3NetEntityId, EntityInfo::Role::Root); + m_child3 = AZStd::make_unique((8), "child 3", Child3NetEntityId, EntityInfo::Role::Child); + m_childOfChild3 = AZStd::make_unique((9), "child of child 3", ChildOfChild3NetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_root3, *m_child3, *m_childOfChild3); + + m_child3->m_entity->FindComponent()->SetParent(m_root3->m_entity->GetId()); + m_childOfChild3->m_entity->FindComponent()->SetParent(m_child3->m_entity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChild3.reset(); + m_child3.reset(); + m_root3.reset(); + + ServerHierarchyOfHierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_root3; + AZStd::unique_ptr m_child3; + AZStd::unique_ptr m_childOfChild3; + }; + + TEST_F(ServerHierarchyWithThreeRoots, Top_Root_Active_Then_Inner_Roots_Have_No_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 0 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 0 + ); + } + + TEST_F(ServerHierarchyWithThreeRoots, Top_Root_Deactivates_Inner_Roots_Have_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + m_root.reset(); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyWithThreeRoots, Child_Of_Top_Root_Deactivates_Inner_Roots_Have_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + m_child.reset(); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyWithThreeRoots, Child_Of_Child_Of_Top_Root_Deactivates_Inner_Roots_Have_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + m_childOfChild.reset(); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } } From 1591f6519297221d287d79ab7265792a1d68cfc1 Mon Sep 17 00:00:00 2001 From: AMZN-tpeng <82184807+AMZN-tpeng@users.noreply.github.com> Date: Wed, 15 Sep 2021 15:14:33 -0700 Subject: [PATCH 145/274] [ATOM][RHI][Vulkan] - Account for null descriptor for sampler. (#4127) Signed-off-by: Peng --- Gems/Atom/RHI/Vulkan/Code/Source/RHI/DescriptorSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/DescriptorSet.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/DescriptorSet.cpp index c192b49a48..d70d4a01b5 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/DescriptorSet.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/DescriptorSet.cpp @@ -466,7 +466,7 @@ namespace AZ bool DescriptorSet::IsNullDescriptorInfo(const VkDescriptorImageInfo& descriptorInfo) { - return descriptorInfo.imageView == VK_NULL_HANDLE; + return (descriptorInfo.imageView == VK_NULL_HANDLE && descriptorInfo.sampler == VK_NULL_HANDLE); } bool DescriptorSet::IsNullDescriptorInfo(const VkBufferView& descriptorInfo) From 0f5fc1de4d824d9a298a2343d5c0578145c9bbd4 Mon Sep 17 00:00:00 2001 From: AMZN-tpeng <82184807+AMZN-tpeng@users.noreply.github.com> Date: Wed, 15 Sep 2021 15:15:20 -0700 Subject: [PATCH 146/274] =?UTF-8?q?[ATOM][RHI][Vulkan]=20Make=20sure=20to?= =?UTF-8?q?=20set=20super-variant=20for=20non-MSAA=20pipel=E2=80=A6=20(#41?= =?UTF-8?q?34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [ATOM][RHI][Vulkan] Make sure to set super-variant for non-MSAA pipeline. Separate out reflection probe draw packet checks. Signed-off-by: Peng * Missed from previous commit to make sure non-MSAA super-variant is used. Signed-off-by: Peng * Minor comment edit. Signed-off-by: Peng --- .../Code/Source/BootstrapSystemComponent.cpp | 6 +++++ .../ReflectionProbe/ReflectionProbe.cpp | 26 +++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index ddd88a1f52..e3749175bc 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -303,6 +304,11 @@ namespace AZ RPI::RenderPipelineDescriptor renderPipelineDescriptor = *RPI::GetDataFromAnyAsset(pipelineAsset); renderPipelineDescriptor.m_name = AZStd::string::format("%s_%i", renderPipelineDescriptor.m_name.c_str(), viewportContext->GetId()); + // Make sure non-msaa super variant is used for non-msaa pipeline + bool isNonMsaaPipeline = (renderPipelineDescriptor.m_renderSettings.m_multisampleState.m_samples == 1); + const char* supervariantName = isNonMsaaPipeline ? AZ::RPI::NoMsaaSupervariantName : ""; + AZ::RPI::ShaderSystemInterface::Get()->SetSupervariantName(AZ::Name(supervariantName)); + if (!scene->GetRenderPipeline(AZ::Name(renderPipelineDescriptor.m_name))) { RPI::RenderPipelinePtr renderPipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(renderPipelineDescriptor, *viewportContext->GetWindowContext().get()); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 66c326e6e7..778f06c3be 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -370,11 +370,27 @@ namespace AZ { // set draw list mask m_cullable.m_cullData.m_drawListMask.reset(); - m_cullable.m_cullData.m_drawListMask = - m_stencilDrawPacket->GetDrawListMask() | - m_blendWeightDrawPacket->GetDrawListMask() | - m_renderOuterDrawPacket->GetDrawListMask() | - m_renderInnerDrawPacket->GetDrawListMask(); + + // check for draw packets due certain render pipelines such as lowend render pipeline that might not have this feature enabled + if (m_stencilDrawPacket) + { + m_cullable.m_cullData.m_drawListMask |= m_stencilDrawPacket->GetDrawListMask(); + } + + if (m_blendWeightDrawPacket) + { + m_cullable.m_cullData.m_drawListMask |= m_blendWeightDrawPacket->GetDrawListMask(); + } + + if (m_renderOuterDrawPacket) + { + m_cullable.m_cullData.m_drawListMask |= m_renderOuterDrawPacket->GetDrawListMask(); + } + + if (m_renderInnerDrawPacket) + { + m_cullable.m_cullData.m_drawListMask |= m_renderInnerDrawPacket->GetDrawListMask(); + } // setup the Lod entry, using one entry for all four draw packets m_cullable.m_lodData.m_lods.clear(); From 9e31c3ebf53b6dd9b26c5187322b84a1ab2ac212 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:41:08 -0400 Subject: [PATCH 147/274] Refactoring m_isDeactivating into m_isHierarchyEnabled Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyChildComponent.h | 3 ++- .../Components/NetworkHierarchyRootComponent.h | 5 +++-- .../Components/NetworkHierarchyChildComponent.cpp | 14 +++++++------- .../Components/NetworkHierarchyRootComponent.cpp | 5 +++-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index 2effb18bb8..544fb3d6cb 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -78,7 +78,8 @@ namespace Multiplayer NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; - bool m_isDeactivating = false; + //! Set to false when deactivating or otherwise not to be included in hierarchy considerations. + bool m_isHierarchyEnabled = true; void NotifyChildrenHierarchyDisbanded(); }; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 35f0da5965..4c9f94c004 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -93,7 +93,8 @@ namespace Multiplayer bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); void SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity); - - bool m_isDeactivating = false; + + //! Set to false when deactivating or otherwise not to be included in hierarchy considerations. + bool m_isHierarchyEnabled = true; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index eff051ed93..6ee407990e 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -67,6 +67,8 @@ namespace Multiplayer void NetworkHierarchyChildComponent::OnActivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) { + m_isHierarchyEnabled = true; + HierarchyRootAddEvent(m_hierarchyRootNetIdChanged); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); @@ -79,7 +81,7 @@ namespace Multiplayer void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) { - m_isDeactivating = true; + m_isHierarchyEnabled = false; if (m_rootEntity) { @@ -96,7 +98,7 @@ namespace Multiplayer bool NetworkHierarchyChildComponent::IsHierarchyEnabled() const { - return !m_isDeactivating; + return m_isHierarchyEnabled; } bool NetworkHierarchyChildComponent::IsHierarchicalChild() const @@ -197,11 +199,9 @@ namespace Multiplayer } else { - if (!m_rootEntity) - { - m_rootEntity = nullptr; - m_networkHierarchyLeaveEvent.Signal(); - } + m_isHierarchyEnabled = false; + m_rootEntity = nullptr; + m_networkHierarchyLeaveEvent.Signal(); } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index d2b45a8971..f704242f34 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -71,6 +71,7 @@ namespace Multiplayer void NetworkHierarchyRootComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { + m_isHierarchyEnabled = true; m_hierarchicalEntities.push_back(GetEntity()); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); @@ -84,7 +85,7 @@ namespace Multiplayer void NetworkHierarchyRootComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { - m_isDeactivating = true; + m_isHierarchyEnabled = false; if (m_rootEntity) { @@ -121,7 +122,7 @@ namespace Multiplayer bool NetworkHierarchyRootComponent::IsHierarchyEnabled() const { - return !m_isDeactivating; + return m_isHierarchyEnabled; } bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const From 2637fa45b8010537a1752ff84438479930f5b718 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:43:56 -0400 Subject: [PATCH 148/274] Minor refactor to address CR Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Source/Components/NetworkHierarchyChildComponent.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index 6ee407990e..3124eccaa8 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -103,12 +103,7 @@ namespace Multiplayer bool NetworkHierarchyChildComponent::IsHierarchicalChild() const { - if (GetHierarchyRoot() != InvalidNetEntityId) - { - return true; - } - - return false; + return GetHierarchyRoot() != InvalidNetEntityId; } AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const From a9091b0a72572f05f5871b26a3231d678fc10bb8 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 15 Sep 2021 15:47:23 -0700 Subject: [PATCH 149/274] Minor changes to comments Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzQtComponents/Components/FancyDockingGhostWidget.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp index d259b28636..fd20f4d125 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDockingGhostWidget.cpp @@ -81,9 +81,8 @@ namespace AzQtComponents QScreen* pointScreen = QApplication::screenAt(midPoint); QRect rect(targetRect); - // On environment with multiple screens with different scaling settings, the screen coordinate system may have gaps - // due to the screen real estate shrinking according to the scale. When that happens, if a widget is moved into the gap - // it will resize and translate with undefined behavior, causing a lot of jitter and flashes. + // In environments with multiple screens the screen coordinate system may have gaps, especially when different scaling settings + // are involved. When that happens, if a widget is moved into the gap it will resize and translate with undefined behavior. // To prevent this, whenever the widget would end up outside screen boundaries, we resize the widget to be twice its // original size so that the center of the widget is back inside the screen boundaries, and set the ghost widget // to paint the widget pixmap at half the previous size to make the process seamless. @@ -117,6 +116,8 @@ namespace AzQtComponents setPixmapVisible(true); if (needsRepaint) { + // We use repaint instead of update since the latter has a delay of 1 frame, + // which would cause the ghost widget to flicker when changing paint mode. repaint(); } } From 2be5854beb1fbe2398608e224895b23663dd0b06 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:49:24 -0400 Subject: [PATCH 150/274] Cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyRootComponent.cpp | 15 ++++----------- .../EntityReplication/EntityReplicator.cpp | 4 ++-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index f704242f34..4a5e9ce8d2 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -89,7 +89,7 @@ namespace Multiplayer if (m_rootEntity) { - // tell parent to re-build the hierarchy + // Tell parent to re-build the hierarchy if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) { root->RebuildHierarchy(); @@ -97,8 +97,7 @@ namespace Multiplayer } else { - // notify children to that a hierarchy is disbanded - + // Notify children that the hierarchy is disbanding AZStd::vector allChildren; AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren); @@ -127,12 +126,7 @@ namespace Multiplayer bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const { - if (GetHierarchyRoot() != InvalidNetEntityId) - { - return false; - } - - return true; + return GetHierarchyRoot() == InvalidNetEntityId; } bool NetworkHierarchyRootComponent::IsHierarchicalChild() const @@ -199,7 +193,7 @@ namespace Multiplayer } else { - // detached from parent + // Detached from parent RebuildHierarchy(); } } @@ -217,7 +211,6 @@ namespace Multiplayer bool hierarchyChanged = false; // Send out join and leave events. - for (AZ::Entity* currentEntity : m_hierarchicalEntities) { const auto prevEntityIterator = AZStd::find(previousEntities.begin(), previousEntities.end(), currentEntity); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index bd98d15923..b684473ea3 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -417,14 +417,14 @@ namespace Multiplayer if (hierarchyChildComponent == nullptr) { - // child and root hierarchy components are mutually exclusive + // Child and root hierarchy components are mutually exclusive hierarchyRootComponent = entity->FindComponent(); } if ((hierarchyChildComponent && hierarchyChildComponent->IsHierarchicalChild()) || (hierarchyRootComponent && hierarchyRootComponent->IsHierarchicalChild())) { - // if hierarchy is enabled for the entity, check if the parent is available + // If hierarchy is enabled for the entity, check if the parent is available if (const NetworkTransformComponent* networkTransform = entity->FindComponent()) { const NetEntityId parentId = networkTransform->GetParentEntityId(); From d07b115569e5cb7b343dd0d0ea1fccc448cfd633 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 15 Sep 2021 18:14:18 -0500 Subject: [PATCH 151/274] Rebuilding UI and instance data hierarchy on any external property change Signed-off-by: Guthrie Adams --- .../Code/Source/Material/EditorMaterialComponentInspector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index 939417f236..a3152faf87 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -366,7 +366,7 @@ namespace AZ m_dirtyPropertyFlags.set(); RunEditorMaterialFunctors(); - RefreshAll(); + RebuildAll(); } void MaterialPropertyInspector::SaveOverridesToEntity(bool commitChanges) From 9f6527790639b2fc073a8f79d24d96127cf7f731 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 15 Sep 2021 19:17:33 -0500 Subject: [PATCH 152/274] restoring changes lost in merge Signed-off-by: Guthrie Adams --- .../Source/Material/MaterialComponentController.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index fab62be530..14f81c5021 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -182,16 +182,7 @@ namespace AZ continue; } - if (propertyPair.second.is()) - { - const auto& assetId = *AZStd::any_cast(&propertyPair.second); - Data::Asset imageAsset(assetId, azrtti_typeid()); - materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue(imageAsset)); - } - else - { - materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second)); - } + materialInstance->SetPropertyValue(materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second)); } materialInstance->Compile(); From a8908a987a23efdb12c7ecf507ebd29553b7a76d Mon Sep 17 00:00:00 2001 From: Mikhail Naumov <82239319+AMZN-mnaumov@users.noreply.github.com> Date: Wed, 15 Sep 2021 19:19:01 -0500 Subject: [PATCH 153/274] Fixing Save level As template path (#4054) * Fixing Save level As template path Signed-off-by: Mikhail Naumov * CR Feedback Signed-off-by: Mikhail Naumov * CR feedback Signed-off-by: Mikhail Naumov * PR feedback Signed-off-by: Mikhail Naumov * remove emplace Signed-off-by: Mikhail Naumov * more PR feedback Signed-off-by: Mikhail Naumov --- .../PrefabEditorEntityOwnershipService.cpp | 3 +- .../Prefab/PrefabSystemComponent.cpp | 42 +++++++++++++++++++ .../Prefab/PrefabSystemComponent.h | 7 ++++ .../Prefab/PrefabSystemComponentInterface.h | 1 + .../Prefab/Template/Template.cpp | 4 ++ .../Prefab/Template/Template.h | 1 + 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 114f45d501..0f2b896b40 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -221,7 +221,8 @@ namespace AzToolsFramework AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename); m_rootInstance->SetTemplateSourcePath(relativePath); - + m_prefabSystemComponent->UpdateTemplateFilePath(m_rootInstance->GetTemplateId(), relativePath); + AZStd::string out; if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index e88e999878..0d2696f14b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -424,6 +424,48 @@ namespace AzToolsFramework return newTemplateId; } + void PrefabSystemComponent::UpdateTemplateFilePath(TemplateId templateId, const AZ::IO::PathView& filePath) + { + auto findTemplateResult = FindTemplate(templateId); + if (!findTemplateResult.has_value()) + { + AZ_Error( + "Prefab", false, + "Template associated by given Id '%llu' doesn't exist in PrefabSystemComponent.", + templateId); + return; + } + + if (!filePath.IsRelative()) + { + AZ_Error("Prefab", false, "Provided filePath '%.*s' must be relative.", AZ_STRING_ARG(filePath.Native())); + return; + } + + Template& templateToChange = findTemplateResult->get(); + if (templateToChange.GetFilePath() == filePath) + { + return; + } + + m_templateFilePathToIdMap.erase(templateToChange.GetFilePath()); + if (!m_templateFilePathToIdMap.try_emplace(filePath, templateId).second) + { + AZ_Error("Prefab", false, "Provided filePath '%.*s' already exists.", AZ_STRING_ARG(filePath.Native())); + return; + } + + PrefabDom& prefabDom = templateToChange.GetPrefabDom(); + PrefabDomValueReference pathReference = Prefab::PrefabDomUtils::FindPrefabDomValue(prefabDom, "Source"); + if (pathReference) + { + const AZStd::string_view pathStr = filePath.Native(); + pathReference->get().SetString(pathStr.data(), aznumeric_caster(pathStr.length()), prefabDom.GetAllocator()); + } + + templateToChange.SetFilePath(filePath); + } + void PrefabSystemComponent::RemoveTemplate(const TemplateId& templateId) { auto findTemplateResult = FindTemplate(templateId); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 04bcee2961..d6908922c9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -101,6 +101,13 @@ namespace AzToolsFramework */ TemplateId AddTemplate(const AZ::IO::Path& filePath, PrefabDom prefabDom) override; + /** + * Updates relative filepath location of a prefab (in case of SaveAs operation). + * @param templateId An id of a Template to change filepath of. + * @param filePath new relative path of the Template. + */ + void UpdateTemplateFilePath(TemplateId templateId, const AZ::IO::PathView& filePath) override; + /** * Remove the Template associated with the given id from Prefab System Component. * @param templateId A unique id of a Template. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index ae66700728..1f59088518 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -33,6 +33,7 @@ namespace AzToolsFramework virtual LinkReference FindLink(const LinkId& id) = 0; virtual TemplateId AddTemplate(const AZ::IO::Path& filePath, PrefabDom prefabDom) = 0; + virtual void UpdateTemplateFilePath(TemplateId templateId, const AZ::IO::PathView& filePath) = 0; virtual void RemoveTemplate(const TemplateId& templateId) = 0; virtual void RemoveAllTemplates() = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.cpp index 99dce3d14f..e5ab403ea6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.cpp @@ -180,5 +180,9 @@ namespace AzToolsFramework return m_filePath; } + void Template::SetFilePath(const AZ::IO::PathView& path) + { + m_filePath = path; + } } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.h index fbc9a26f36..f7a41431f8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Template/Template.h @@ -63,6 +63,7 @@ namespace AzToolsFramework PrefabDomValueConstReference GetInstancesValue() const; const AZ::IO::Path& GetFilePath() const; + void SetFilePath(const AZ::IO::PathView& path); private: // Container for keeping links representing the Template's nested instances. From 880f4d96cc7773e2378bd051b1dcfb1ee37b9989 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Wed, 15 Sep 2021 18:19:39 -0700 Subject: [PATCH 154/274] Changed the ReflectionProbe component to use an OBB Signed-off-by: dmcdiar --- .../Atom/Features/PBR/DefaultObjectSrg.azsli | 37 ++++++++++++-- .../Atom/Features/PBR/LightingUtils.azsli | 11 +++- .../Atom/Features/PBR/Lights/Ibl.azsli | 16 +++--- .../ReflectionProbeBlendWeight.azsl | 10 ++-- .../ReflectionProbeRenderCommon.azsli | 10 ++-- .../ReflectionProbeRenderInner.azsl | 2 +- .../ReflectionProbeRenderObjectSrg.azsli | 23 ++++++--- .../ReflectionProbeRenderOuter.azsl | 12 +++-- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 28 +++++------ .../ReflectionProbe/ReflectionProbe.cpp | 50 +++++++++---------- .../Source/ReflectionProbe/ReflectionProbe.h | 20 ++++---- .../ReflectionProbeFeatureProcessor.cpp | 40 +++++++-------- .../RPI/Assets/ShaderLib/Atom/RPI/Math.azsli | 16 ++++++ .../EditorReflectionProbeComponent.cpp | 7 +-- 14 files changed, 172 insertions(+), 110 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli index ccaf5cf5d0..7a2d2ee428 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli @@ -40,11 +40,10 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject //! Reflection Probe (smallest probe volume that overlaps the object position) struct ReflectionProbeData { - float3 m_aabbPos; - float3 m_outerAabbMin; - float3 m_outerAabbMax; - float3 m_innerAabbMin; - float3 m_innerAabbMax; + row_major float3x4 m_modelToWorld; + row_major float3x4 m_modelToWorldInverse; // does not include extents + float3 m_outerObbHalfLengths; + float3 m_innerObbHalfLengths; float m_padding; bool m_useReflectionProbe; bool m_useParallaxCorrection; @@ -52,4 +51,32 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject ReflectionProbeData m_reflectionProbeData; TextureCube m_reflectionProbeCubeMap; + + float4x4 GetReflectionProbeWorldMatrix() + { + float4x4 modelToWorld = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorld[0] = m_reflectionProbeData.m_modelToWorld[0]; + modelToWorld[1] = m_reflectionProbeData.m_modelToWorld[1]; + modelToWorld[2] = m_reflectionProbeData.m_modelToWorld[2]; + return modelToWorld; + } + + float4x4 GetReflectionProbeWorldMatrixInverse() + { + float4x4 modelToWorldInverse = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorldInverse[0] = m_reflectionProbeData.m_modelToWorldInverse[0]; + modelToWorldInverse[1] = m_reflectionProbeData.m_modelToWorldInverse[1]; + modelToWorldInverse[2] = m_reflectionProbeData.m_modelToWorldInverse[2]; + return modelToWorldInverse; + } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli index 503095020c..3248fc83eb 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli @@ -50,10 +50,10 @@ float GetRoughnessMip(float roughness) return roughness * maxRoughnessMip; } -// compute parallax corrected reflection vector +// compute parallax corrected reflection vector, AABB version // we do this by finding the intersection with the volume and adjusting the reflection vector for the surface position // https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ -float3 ApplyParallaxCorrection(float3 aabbMin, float3 aabbMax, float3 aabbPos, float3 positionWS, float3 reflectDir) +float3 ApplyParallaxCorrectionAABB(float3 aabbMin, float3 aabbMax, float3 aabbPos, float3 positionWS, float3 reflectDir) { float3 rcpReflectDir = 1.0f / reflectDir; float3 intersectA = (aabbMax - positionWS) * rcpReflectDir; @@ -63,3 +63,10 @@ float3 ApplyParallaxCorrection(float3 aabbMin, float3 aabbMax, float3 aabbPos, f float3 intersectPos = reflectDir * distance + positionWS; return (intersectPos - aabbPos); } + +// compute parallax corrected reflection vector, OBB version +float3 ApplyParallaxCorrectionOBB(float4x4 obbTransformInverse, float3 obbHalfExtents, float3 positionWS, float3 reflectDir) +{ + float4 p = mul(obbTransformInverse, float4(positionWS, 1.0f)); + return ApplyParallaxCorrectionAABB(-obbHalfExtents, obbHalfExtents, float3(0.0f, 0.0f, 0.0f), p, reflectDir); +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index 5a0e150dbb..b1cfb47be6 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -48,10 +48,9 @@ float3 GetIblSpecular( { if (ObjectSrg::m_reflectionProbeData.m_useParallaxCorrection) { - reflectDir = ApplyParallaxCorrection( - ObjectSrg::m_reflectionProbeData.m_outerAabbMin, - ObjectSrg::m_reflectionProbeData.m_outerAabbMax, - ObjectSrg::m_reflectionProbeData.m_aabbPos, + reflectDir = ApplyParallaxCorrectionOBB( + ObjectSrg::GetReflectionProbeWorldMatrixInverse(), + ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths, position, reflectDir); } @@ -60,11 +59,10 @@ float3 GetIblSpecular( probeSpecular *= (specularF0 * brdf.x + brdf.y); // compute blend amount based on world position in the reflection probe volume - float blendAmount = ComputeLerpBetweenInnerOuterAABBs( - ObjectSrg::m_reflectionProbeData.m_innerAabbMin, - ObjectSrg::m_reflectionProbeData.m_innerAabbMax, - ObjectSrg::m_reflectionProbeData.m_outerAabbMax, - ObjectSrg::m_reflectionProbeData.m_aabbPos, + float blendAmount = ComputeLerpBetweenInnerOuterOBBs( + ObjectSrg::m_reflectionProbeData.m_modelToWorldInverse, + ObjectSrg::m_reflectionProbeData.m_innerObbHalfLengths, + ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths, position); outSpecular = lerp(outSpecular, probeSpecular, blendAmount); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl index 095576caaf..0fca4d03c6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl @@ -63,7 +63,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // make sure the pixel belongs to this probe volume // this is necessary since it could have the correct stencil value but actually reside // in another volume that's in between the camera and the volume we're rendering - if (!AabbContainsPoint(ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, positionWS)) + if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, positionWS)) { discard; } @@ -71,11 +71,15 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // determine blend based on position with respect to the inner and outer AABBs // if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB float blendWeight = 1.0f; - if (!AabbContainsPoint(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, positionWS)) + if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS)) { // not inside the inner AABB, so it's in between the inner and outer AABBs // compute blend amount based on the distance to the outer AABB - blendWeight = ComputeLerpBetweenInnerOuterAABBs(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS); + blendWeight = ComputeLerpBetweenInnerOuterOBBs( + ObjectSrg::GetWorldMatrixInverse(), + ObjectSrg::m_innerObbHalfLengths, + ObjectSrg::m_outerObbHalfLengths, + positionWS); } // write the blend weight (additive) at this position for the probe volume diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli index f172035177..ce4684b150 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli @@ -12,12 +12,12 @@ #include // compute final probe specular using the probe cubemap and the roughness, normals, and specularF0 for the surface -bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float3 aabbMin, float3 aabbMax, uint sampleIndex, out float3 specular) +bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float4x4 obbTransformInverse, float3 outerObbHalfLengths, uint sampleIndex, out float3 specular) { // make sure the pixel belongs to this probe volume // this is necessary since it could have the correct stencil value but actually reside // in another volume that's in between the camera and the volume we're rendering - if (!AabbContainsPoint(aabbMin, aabbMax, positionWS)) + if (!ObbContainsPoint(obbTransformInverse, outerObbHalfLengths, positionWS)) { return false; } @@ -47,7 +47,11 @@ bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float3 aabbMin float3 localReflectDir = reflectDir; if (ObjectSrg::m_useParallaxCorrection) { - localReflectDir = ApplyParallaxCorrection(ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS, reflectDir); + localReflectDir = ApplyParallaxCorrectionOBB( + ObjectSrg::GetWorldMatrixInverse(), + ObjectSrg::m_outerObbHalfLengths, + positionWS, + reflectDir); } // sample reflection cubemap with the appropriate roughness mip diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl index 209605be03..a0734caf02 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl @@ -75,7 +75,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // compute specular using the probe cubemap and the roughness, normals, and specularF0 for the surface float3 specular = float3(0.0f, 0.0f, 0.0f); - if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, sampleIndex, specular)) + if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, sampleIndex, specular)) { discard; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli index 92ecd82dee..8151ed2fd5 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli @@ -13,12 +13,9 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject { row_major float3x4 m_modelToWorld; - - float3 m_aabbPos; - float3 m_outerAabbMin; - float3 m_outerAabbMax; - float3 m_innerAabbMin; - float3 m_innerAabbMax; + row_major float3x4 m_modelToWorldInverse; // does not include extents + float3 m_outerObbHalfLengths; + float3 m_innerObbHalfLengths; bool m_useParallaxCorrection; TextureCube m_reflectionCubeMap; @@ -35,4 +32,18 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject modelToWorld[2] = ObjectSrg::m_modelToWorld[2]; return modelToWorld; } + + float4x4 GetWorldMatrixInverse() + { + float4x4 modelToWorldInverse = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorldInverse[0] = ObjectSrg::m_modelToWorldInverse[0]; + modelToWorldInverse[1] = ObjectSrg::m_modelToWorldInverse[1]; + modelToWorldInverse[2] = ObjectSrg::m_modelToWorldInverse[2]; + return modelToWorldInverse; + } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl index be94a53588..ac97172f1f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl @@ -77,7 +77,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // compute specular using the probe cubemap and the roughness, normals, and specularF0 for the surface float3 specular = float3(0.0f, 0.0f, 0.0f); - if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, sampleIndex, specular)) + if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, sampleIndex, specular)) { discard; } @@ -85,13 +85,17 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // determine blend based on position with respect to the inner and outer AABBs // if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB float blendWeight = 1.0f; - if (!AabbContainsPoint(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, positionWS)) + if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS)) { // not inside the inner AABB, so it's in between the inner and outer AABBs // compute blend amount based on the distance to the outer AABB - blendWeight = ComputeLerpBetweenInnerOuterAABBs(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS); + blendWeight = ComputeLerpBetweenInnerOuterOBBs( + ObjectSrg::GetWorldMatrixInverse(), + ObjectSrg::m_innerObbHalfLengths, + ObjectSrg::m_outerObbHalfLengths, + positionWS); } - + // retrieve the blend weight of all probes at this location float blendWeightAllProbes = PassSrg::m_blendWeight.Load(IN.m_position.xy, sampleIndex).r; diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 67702a8176..41ccec0fb5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -1119,20 +1119,17 @@ namespace AZ if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial)) { // retrieve probe constant indices - AZ::RHI::ShaderInputConstantIndex posConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_aabbPos")); - AZ_Error("MeshDataInstance", posConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld")); + AZ_Error("MeshDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - AZ::RHI::ShaderInputConstantIndex outerAabbMinConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerAabbMin")); - AZ_Error("MeshDataInstance", outerAabbMinConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse")); + AZ_Error("MeshDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - AZ::RHI::ShaderInputConstantIndex outerAabbMaxConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerAabbMax")); - AZ_Error("MeshDataInstance", outerAabbMaxConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths")); + AZ_Error("MeshDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - AZ::RHI::ShaderInputConstantIndex innerAabbMinConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerAabbMin")); - AZ_Error("MeshDataInstance", innerAabbMinConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex innerAabbMaxConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerAabbMax")); - AZ_Error("MeshDataInstance", innerAabbMaxConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths")); + AZ_Error("MeshDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe")); AZ_Error("MeshDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); @@ -1154,11 +1151,10 @@ namespace AZ if (!reflectionProbes.empty() && reflectionProbes[0]) { - m_shaderResourceGroup->SetConstant(posConstantIndex, reflectionProbes[0]->GetPosition()); - m_shaderResourceGroup->SetConstant(outerAabbMinConstantIndex, reflectionProbes[0]->GetOuterAabbWs().GetMin()); - m_shaderResourceGroup->SetConstant(outerAabbMaxConstantIndex, reflectionProbes[0]->GetOuterAabbWs().GetMax()); - m_shaderResourceGroup->SetConstant(innerAabbMinConstantIndex, reflectionProbes[0]->GetInnerAabbWs().GetMin()); - m_shaderResourceGroup->SetConstant(innerAabbMaxConstantIndex, reflectionProbes[0]->GetInnerAabbWs().GetMax()); + m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform()); + m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, reflectionProbes[0]->GetTransform().GetInverse()); + m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths()); + m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths()); m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true); m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection()); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 66c326e6e7..2be2ec72c8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -138,43 +138,40 @@ namespace AZ if (m_updateSrg) { // stencil Srg - // Note: the stencil pass uses a slightly reduced inner AABB to avoid seams + // Note: the stencil pass uses a slightly reduced inner OBB to avoid seams Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f); - Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); + Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil); + m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseStencilConstantIndex, modelToWorldStencil.GetInverseFull()); m_stencilSrg->Compile(); + Matrix3x4 modelToWorldInverse = Matrix3x4::CreateFromTransform(m_transform).GetInverseFull(); + // blend weight Srg - Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents); + Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax()); + m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse); + m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); + m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); m_blendWeightSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_blendWeightSrg->Compile(); // render outer Srg m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax()); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); m_renderOuterSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_renderOuterSrg->Compile(); // render inner Srg - Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents); + Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax()); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); m_renderInnerSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_renderInnerSrg->Compile(); @@ -244,22 +241,22 @@ namespace AZ m_outerExtents *= m_transform.GetUniformScale(); m_innerExtents *= m_transform.GetUniformScale(); - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f); - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f); + m_outerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_outerExtents / 2.0f); + m_innerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_innerExtents / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents) { m_outerExtents = outerExtents * m_transform.GetUniformScale(); - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f); + m_outerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_outerExtents / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents) { m_innerExtents = innerExtents * m_transform.GetUniformScale(); - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f); + m_innerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_innerExtents / 2.0f); m_updateSrg = true; } @@ -394,13 +391,14 @@ namespace AZ lod.m_screenCoverageMax = 1.0f; // update cullable bounds + Aabb outerAabb = Aabb::CreateFromObb(m_outerObbWs); Vector3 center; float radius; - m_outerAabbWs.GetAsSphere(center, radius); + outerAabb.GetAsSphere(center, radius); m_cullable.m_cullData.m_boundingSphere = Sphere(center, radius); - m_cullable.m_cullData.m_boundingObb = m_outerAabbWs.GetTransformedObb(AZ::Transform::CreateIdentity()); - m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = m_outerAabbWs; + m_cullable.m_cullData.m_boundingObb = m_outerObbWs; + m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = outerAabb; m_cullable.m_cullData.m_visibilityEntry.m_userData = &m_cullable; m_cullable.m_cullData.m_visibilityEntry.m_typeFlags = AzFramework::VisibilityEntry::TYPE_RPI_Cullable; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index bb30ce9470..169c4f1df2 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -56,12 +56,11 @@ namespace AZ RHI::DrawListTag m_renderInnerDrawListTag; RHI::ShaderInputConstantIndex m_modelToWorldStencilConstantIndex; + RHI::ShaderInputConstantIndex m_modelToWorldInverseStencilConstantIndex; RHI::ShaderInputConstantIndex m_modelToWorldRenderConstantIndex; - RHI::ShaderInputConstantIndex m_aabbPosRenderConstantIndex; - RHI::ShaderInputConstantIndex m_outerAabbMinRenderConstantIndex; - RHI::ShaderInputConstantIndex m_outerAabbMaxRenderConstantIndex; - RHI::ShaderInputConstantIndex m_innerAabbMinRenderConstantIndex; - RHI::ShaderInputConstantIndex m_innerAabbMaxRenderConstantIndex; + RHI::ShaderInputConstantIndex m_modelToWorldInverseRenderConstantIndex; + RHI::ShaderInputConstantIndex m_outerObbHalfLengthsRenderConstantIndex; + RHI::ShaderInputConstantIndex m_innerObbHalfLengthsRenderConstantIndex; RHI::ShaderInputConstantIndex m_useParallaxCorrectionRenderConstantIndex; RHI::ShaderInputImageIndex m_reflectionCubeMapRenderImageIndex; }; @@ -78,6 +77,7 @@ namespace AZ void Simulate(uint32_t probeIndex); const Vector3& GetPosition() const { return m_transform.GetTranslation(); } + const AZ::Transform& GetTransform() const { return m_transform; } void SetTransform(const AZ::Transform& transform); const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } @@ -86,8 +86,8 @@ namespace AZ const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; } void SetInnerExtents(const AZ::Vector3& innerExtents); - const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; } - const Aabb& GetInnerAabbWs() const { return m_innerAabbWs; } + const Obb& GetOuterObbWs() const { return m_outerObbWs; } + const Obb& GetInnerObbWs() const { return m_innerObbWs; } const Data::Instance& GetCubeMapImage() const { return m_cubeMapImage; } void SetCubeMapImage(const Data::Instance& cubeMapImage, const AZStd::string& relativePath); @@ -133,9 +133,9 @@ namespace AZ AZ::Vector3 m_outerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); AZ::Vector3 m_innerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); - // probe volume AABBs (world space), built from position and extents - Aabb m_outerAabbWs; - Aabb m_innerAabbWs; + // probe volume OBBs (world space), built from position and extents + Obb m_outerObbWs; + Obb m_innerObbWs; // cubemap Data::Instance m_cubeMapImage; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 341d1a0274..5c07fbae66 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -92,6 +92,10 @@ namespace AZ m_reflectionRenderData.m_modelToWorldStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldConstantName.GetCStr()); + Name modelToWorldInverseConstantName = Name("m_modelToWorldInverse"); + m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); + // cache probe render shader indices // Note: the outer and inner render shaders use the same Srg Data::Instance renderReflectionSrg = RPI::ShaderResourceGroup::Create( @@ -104,25 +108,16 @@ namespace AZ m_reflectionRenderData.m_modelToWorldRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldConstantName.GetCStr()); - Name aabbPosConstantName = Name("m_aabbPos"); - m_reflectionRenderData.m_aabbPosRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(aabbPosConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_aabbPosRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", aabbPosConstantName.GetCStr()); - - Name outerAabbMinConstantName = Name("m_outerAabbMin"); - m_reflectionRenderData.m_outerAabbMinRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerAabbMinConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerAabbMinRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerAabbMinConstantName.GetCStr()); + m_reflectionRenderData.m_modelToWorldInverseRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); - Name outerAabbMaxConstantName = Name("m_outerAabbMax"); - m_reflectionRenderData.m_outerAabbMaxRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerAabbMaxConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerAabbMaxRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerAabbMaxConstantName.GetCStr()); + Name outerObbHalfLengthsConstantName = Name("m_outerObbHalfLengths"); + m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerObbHalfLengthsConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerObbHalfLengthsConstantName.GetCStr()); - Name innerAabbMinConstantName = Name("m_innerAabbMin"); - m_reflectionRenderData.m_innerAabbMinRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerAabbMinConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerAabbMinRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerAabbMinConstantName.GetCStr()); - - Name innerAabbMaxConstantName = Name("m_innerAabbMax"); - m_reflectionRenderData.m_innerAabbMaxRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerAabbMaxConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerAabbMaxRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerAabbMaxConstantName.GetCStr()); + Name innerObbHalfLengthsConstantName = Name("m_innerObbHalfLengths"); + m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerObbHalfLengthsConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerObbHalfLengthsConstantName.GetCStr()); Name useParallaxCorrectionConstantName = Name("m_useParallaxCorrection"); m_reflectionRenderData.m_useParallaxCorrectionRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(useParallaxCorrectionConstantName); @@ -199,10 +194,11 @@ namespace AZ // sort the probes by descending inner volume size, so the smallest volumes are rendered last auto sortFn = [](AZStd::shared_ptr const& probe1, AZStd::shared_ptr const& probe2) -> bool { - const Aabb& aabb1 = probe1->GetInnerAabbWs(); - const Aabb& aabb2 = probe2->GetInnerAabbWs(); - float size1 = aabb1.GetXExtent() * aabb1.GetZExtent() * aabb1.GetYExtent(); - float size2 = aabb2.GetXExtent() * aabb2.GetZExtent() * aabb2.GetYExtent(); + const Obb& obb1 = probe1->GetInnerObbWs(); + const Obb& obb2 = probe2->GetInnerObbWs(); + float size1 = obb1.GetHalfLengthX() * obb1.GetHalfLengthZ() * obb1.GetHalfLengthY(); + float size2 = obb2.GetHalfLengthX() * obb2.GetHalfLengthZ() * obb2.GetHalfLengthY(); + return (size1 > size2); }; @@ -347,7 +343,7 @@ namespace AZ // simple AABB check to find the reflection probes that contain the position for (auto& reflectionProbe : m_reflectionProbes) { - if (reflectionProbe->GetOuterAabbWs().Contains(position) + if (reflectionProbe->GetOuterObbWs().Contains(position) && reflectionProbe->GetCubeMapImage() && reflectionProbe->GetCubeMapImage()->IsInitialized()) { diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli index a94e01e11b..b004623c4e 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli @@ -116,6 +116,22 @@ float ComputeLerpBetweenInnerOuterAABBs(float3 innerAabbMin, float3 innerAabbMax return totalDistance > 0.0f ? saturate(shortestDistance / totalDistance) : 1.0f; } +// returns true if the Obb contains the specified point +bool ObbContainsPoint(float4x4 obbTransformInverse, float3 obbHalfExtents, float3 testPoint) +{ + // get the position in Obb local space, force to positive quadrant with abs() + float4 p = abs(mul(obbTransformInverse, float4(testPoint, 1.0f))); + return AabbContainsPoint(-obbHalfExtents, obbHalfExtents, p); +} + +// computes [0..1] percentage of a point that's in between the inner and outer OBBs +float ComputeLerpBetweenInnerOuterOBBs(float3x4 obbTransformInverse, float3 innerObbHalfExtents, float3 outerObbHalfExtents, float3 position) +{ + // get the position in Obb local space, force to positive quadrant with abs() + float3 p = abs(mul(obbTransformInverse, float4(position, 1.0f))); + return ComputeLerpBetweenInnerOuterAABBs(-innerObbHalfExtents, innerObbHalfExtents, outerObbHalfExtents, float3(0.0f, 0.0f, 0.0f), p); +} + // ---------- Normal Encoding ----------- // Encode/Decode functions for Signed Octahedron normals diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index 4f4f21ab0f..aa68333108 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -212,6 +212,9 @@ namespace AZ AZ::Vector3 position = AZ::Vector3::CreateZero(); AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); + AZ::Quaternion rotationQuaternion = AZ::Quaternion::CreateIdentity(); + AZ::TransformBus::EventResult(rotationQuaternion, GetEntityId(), &AZ::TransformBus::Events::GetWorldRotationQuaternion); + AZ::Matrix3x3 rotationMatrix = AZ::Matrix3x3::CreateFromQuaternion(rotationQuaternion); float scale = 1.0f; AZ::TransformBus::EventResult(scale, GetEntityId(), &AZ::TransformBus::Events::GetLocalUniformScale); @@ -224,9 +227,7 @@ namespace AZ AZ::Vector3 innerExtents(configuration.m_innerWidth, configuration.m_innerLength, configuration.m_innerHeight); innerExtents *= scale; - AZ::Vector3 innerMin(position.GetX() - innerExtents.GetX() / 2, position.GetY() - innerExtents.GetY() / 2, position.GetZ() - innerExtents.GetZ() / 2); - AZ::Vector3 innerMax(position.GetX() + innerExtents.GetX() / 2, position.GetY() + innerExtents.GetY() / 2, position.GetZ() + innerExtents.GetZ() / 2); - debugDisplay.DrawWireBox(innerMin, innerMax); + debugDisplay.DrawWireOBB(position, rotationMatrix.GetBasisX(), rotationMatrix.GetBasisY(), rotationMatrix.GetBasisZ(), innerExtents / 2.0f); } AZ::Aabb EditorReflectionProbeComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) From ae8ed4462fc697a883aafe7151688fb68a6522cd Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Wed, 15 Sep 2021 18:31:35 -0700 Subject: [PATCH 155/274] Small fix for Linux compiler Signed-off-by: Gene Walters --- .../Include/Multiplayer/Components/NetworkCharacterComponent.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h index 2599155346..97dfcd4328 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h @@ -10,6 +10,7 @@ #include #include +#include namespace Physics { From 7e85b1512a7b95cf54fe2b26aad44a697669959f Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Thu, 16 Sep 2021 09:14:37 +0100 Subject: [PATCH 156/274] Expose sticky select option to the SettingsRegistry and disable by default (#4149) * expose sticky select option to the SettingsRegistry Signed-off-by: hultonha * update missed callsites after API change to Manipulator Test Framework Signed-off-by: hultonha * updates following review feedback Signed-off-by: hultonha --- .../EditorPreferencesPageViewportGeneral.cpp | 172 ++++++++++++------ .../EditorPreferencesPageViewportGeneral.h | 22 +-- Code/Editor/EditorViewportSettings.cpp | 11 ++ Code/Editor/EditorViewportSettings.h | 3 + Code/Editor/EditorViewportWidget.cpp | 5 + Code/Editor/EditorViewportWidget.h | 1 + Code/Editor/ViewportTitleDlg.cpp | 2 + .../ActionDispatcher.h | 28 +-- .../AzManipulatorTestFramework.h | 24 ++- .../ImmediateModeActionDispatcher.h | 4 +- .../ViewportInteraction.h | 9 +- .../Source/ImmediateModeActionDispatcher.cpp | 10 +- .../Source/ViewportInteraction.cpp | 31 ++-- .../Tests/GridSnappingTest.cpp | 4 +- .../Tests/ViewportInteractionTest.cpp | 10 +- .../Viewport/ViewportMessages.h | 2 + .../EditorTransformComponentSelection.cpp | 20 +- .../EditorTransformComponentSelection.h | 2 - ...EditorTransformComponentSelectionTests.cpp | 97 +++++----- 19 files changed, 275 insertions(+), 182 deletions(-) diff --git a/Code/Editor/EditorPreferencesPageViewportGeneral.cpp b/Code/Editor/EditorPreferencesPageViewportGeneral.cpp index a9eec22e69..77560e24f8 100644 --- a/Code/Editor/EditorPreferencesPageViewportGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageViewportGeneral.cpp @@ -5,9 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #include "EditorDefs.h" #include "EditorPreferencesPageViewportGeneral.h" +#include "EditorViewportSettings.h" #include @@ -15,7 +17,6 @@ #include "DisplaySettings.h" #include "Settings.h" - void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& serialize) { serialize.Class() @@ -23,7 +24,8 @@ void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& seria ->Field("Sync2DViews", &General::m_sync2DViews) ->Field("DefaultFOV", &General::m_defaultFOV) ->Field("DefaultAspectRatio", &General::m_defaultAspectRatio) - ->Field("EnableContextMenu", &General::m_enableContextMenu); + ->Field("EnableContextMenu", &General::m_contextMenuEnabled) + ->Field("StickySelect", &General::m_stickySelectEnabled); serialize.Class() ->Version(1) @@ -46,10 +48,12 @@ void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& seria ->Field("ShowGridGuide", &Display::m_showGridGuide) ->Field("DisplayDimensions", &Display::m_displayDimension); + // clang-format off serialize.Class() ->Version(1) ->Field("SwapXY", &MapViewport::m_swapXY) ->Field("Resolution", &MapViewport::m_resolution); + // clang-format on serialize.Class() ->Version(1) @@ -80,31 +84,51 @@ void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& seria editContext->Class("General Viewport Settings", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &General::m_sync2DViews, "Synchronize 2D Viewports", "Synchronize 2D Viewports") ->DataElement(AZ::Edit::UIHandlers::SpinBox, &General::m_defaultFOV, "Perspective View FOV", "Perspective View FOV") - ->Attribute("Multiplier", RAD2DEG(1)) - ->Attribute(AZ::Edit::Attributes::Min, 1.0f) - ->Attribute(AZ::Edit::Attributes::Max, 120.0f) - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &General::m_defaultAspectRatio, "Perspective View Aspect Ratio", "Perspective View Aspect Ratio") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &General::m_enableContextMenu, "Enable Right-Click Context Menu", "Enable Right-Click Context Menu"); + ->Attribute("Multiplier", RAD2DEG(1)) + ->Attribute(AZ::Edit::Attributes::Min, 1.0f) + ->Attribute(AZ::Edit::Attributes::Max, 120.0f) + ->DataElement( + AZ::Edit::UIHandlers::SpinBox, &General::m_defaultAspectRatio, "Perspective View Aspect Ratio", + "Perspective View Aspect Ratio") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &General::m_contextMenuEnabled, "Enable Right-Click Context Menu", + "Enable Right-Click Context Menu") + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &General::m_stickySelectEnabled, "Enable Sticky Select", "Enable Sticky Select"); editContext->Class("Viewport Display Settings", "") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showSafeFrame, "Show 4:3 Aspect Ratio Frame", "Show 4:3 Aspect Ratio Frame") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_highlightSelGeom, "Highlight Selected Geometry", "Highlight Selected Geometry") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_highlightSelVegetation, "Highlight Selected Vegetation", "Highlight Selected Vegetation") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_highlightOnMouseOver, "Highlight Geometry On Mouse Over", "Highlight Geometry On Mouse Over") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_hideMouseCursorWhenCaptured, "Hide Cursor When Captured", "Hide Mouse Cursor When Captured") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_showSafeFrame, "Show 4:3 Aspect Ratio Frame", "Show 4:3 Aspect Ratio Frame") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_highlightSelGeom, "Highlight Selected Geometry", "Highlight Selected Geometry") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_highlightSelVegetation, "Highlight Selected Vegetation", + "Highlight Selected Vegetation") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_highlightOnMouseOver, "Highlight Geometry On Mouse Over", + "Highlight Geometry On Mouse Over") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_hideMouseCursorWhenCaptured, "Hide Cursor When Captured", + "Hide Mouse Cursor When Captured") ->DataElement(AZ::Edit::UIHandlers::SpinBox, &Display::m_dragSquareSize, "Drag Square Size", "Drag Square Size") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_displayLinks, "Display Object Links", "Display Object Links") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_displayTracks, "Display Animation Tracks", "Display Animation Tracks") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_alwaysShowRadii, "Always Show Radii", "Always Show Radii") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showBBoxes, "Show Bounding Boxes", "Show Bounding Boxes") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_drawEntityLabels, "Always Draw Entity Labels", "Always Draw Entity Labels") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showTriggerBounds, "Always Show Trigger Bounds", "Always Show Trigger Bounds") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_drawEntityLabels, "Always Draw Entity Labels", "Always Draw Entity Labels") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_showTriggerBounds, "Always Show Trigger Bounds", "Always Show Trigger Bounds") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showIcons, "Show Object Icons", "Show Object Icons") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_distanceScaleIcons, "Scale Object Icons with Distance", "Scale Object Icons with Distance") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showFrozenHelpers, "Show Helpers of Frozen Objects", "Show Helpers of Frozen Objects") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_distanceScaleIcons, "Scale Object Icons with Distance", + "Scale Object Icons with Distance") + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_showFrozenHelpers, "Show Helpers of Frozen Objects", + "Show Helpers of Frozen Objects") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_fillSelectedShapes, "Fill Selected Shapes", "Fill Selected Shapes") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showGridGuide, "Show Snapping Grid Guide", "Show Snapping Grid Guide") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_displayDimension, "Display Dimension Figures", "Display Dimension Figures"); + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, &Display::m_displayDimension, "Display Dimension Figures", "Display Dimension Figures"); editContext->Class("Map Viewport Settings", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MapViewport::m_swapXY, "Swap X/Y Axis", "Swap X/Y Axis") @@ -113,42 +137,64 @@ void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& seria editContext->Class("Text Label Settings", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &TextLabels::m_labelsOn, "Enabled", "Enabled") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &TextLabels::m_labelsDistance, "Distance", "Distance") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 100000.f); + ->Attribute(AZ::Edit::Attributes::Min, 0.f) + ->Attribute(AZ::Edit::Attributes::Max, 100000.f); editContext->Class("Selection Preview Color Settings", "") ->DataElement(AZ::Edit::UIHandlers::Color, &SelectionPreviewColor::m_colorGroupBBox, "Group Bounding Box", "Group Bounding Box") - ->DataElement(AZ::Edit::UIHandlers::Color, &SelectionPreviewColor::m_colorEntityBBox, "Entity Bounding Box", "Entity Bounding Box") - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &SelectionPreviewColor::m_fBBoxAlpha, "Bounding Box Highlight Alpha", "Bounding Box Highlight Alpha") - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::Max, 1.0f) + ->DataElement( + AZ::Edit::UIHandlers::Color, &SelectionPreviewColor::m_colorEntityBBox, "Entity Bounding Box", "Entity Bounding Box") + ->DataElement( + AZ::Edit::UIHandlers::SpinBox, &SelectionPreviewColor::m_fBBoxAlpha, "Bounding Box Highlight Alpha", + "Bounding Box Highlight Alpha") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->DataElement(AZ::Edit::UIHandlers::Color, &SelectionPreviewColor::m_geometryHighlightColor, "Geometry Color", "Geometry Color") - ->DataElement(AZ::Edit::UIHandlers::Color, &SelectionPreviewColor::m_solidBrushGeometryColor, "Solid Brush Geometry Color", "Solid Brush Geometry Color") - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &SelectionPreviewColor::m_fgeomAlpha, "Geometry Highlight Alpha", "Geometry Highlight Alpha") - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::Max, 1.0f) - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &SelectionPreviewColor::m_childObjectGeomAlpha, "Child Geometry Highlight Alpha", "Child Geometry Highlight Alpha") - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::Max, 1.0f); + ->DataElement( + AZ::Edit::UIHandlers::Color, &SelectionPreviewColor::m_solidBrushGeometryColor, "Solid Brush Geometry Color", + "Solid Brush Geometry Color") + ->DataElement( + AZ::Edit::UIHandlers::SpinBox, &SelectionPreviewColor::m_fgeomAlpha, "Geometry Highlight Alpha", "Geometry Highlight Alpha") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Max, 1.0f) + ->DataElement( + AZ::Edit::UIHandlers::SpinBox, &SelectionPreviewColor::m_childObjectGeomAlpha, "Child Geometry Highlight Alpha", + "Child Geometry Highlight Alpha") + ->Attribute(AZ::Edit::Attributes::Min, 0.0f) + ->Attribute(AZ::Edit::Attributes::Max, 1.0f); editContext->Class("General Viewport Preferences", "General Viewport Preferences") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_general, "General Viewport Settings", "General Viewport Settings") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_display, "Viewport Display Settings", "Viewport Display Settings") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_map, "Map Viewport Settings", "Map Viewport Settings") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_textLabels, "Text Label Settings", "Text Label Settings") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_selectionPreviewColor, "Selection Preview Color Settings", "Selection Preview Color Settings"); + ->DataElement( + AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_general, "General Viewport Settings", + "General Viewport Settings") + ->DataElement( + AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_display, "Viewport Display Settings", + "Viewport Display Settings") + ->DataElement( + AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_map, "Map Viewport Settings", + "Map Viewport Settings") + ->DataElement( + AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_textLabels, "Text Label Settings", + "Text Label Settings") + ->DataElement( + AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportGeneral::m_selectionPreviewColor, + "Selection Preview Color Settings", "Selection Preview Color Settings"); } } - CEditorPreferencesPage_ViewportGeneral::CEditorPreferencesPage_ViewportGeneral() { InitializeSettings(); m_icon = QIcon(":/res/Viewport.svg"); } +const char* CEditorPreferencesPage_ViewportGeneral::GetCategory() +{ + return "Viewports"; +} + const char* CEditorPreferencesPage_ViewportGeneral::GetTitle() { return "Viewport"; @@ -159,14 +205,25 @@ QIcon& CEditorPreferencesPage_ViewportGeneral::GetIcon() return m_icon; } +void CEditorPreferencesPage_ViewportGeneral::OnCancel() +{ + // noop +} + +bool CEditorPreferencesPage_ViewportGeneral::OnQueryCancel() +{ + return true; +} + void CEditorPreferencesPage_ViewportGeneral::OnApply() { CDisplaySettings* ds = GetIEditor()->GetDisplaySettings(); gSettings.viewports.fDefaultAspectRatio = m_general.m_defaultAspectRatio; gSettings.viewports.fDefaultFov = m_general.m_defaultFOV; - gSettings.viewports.bEnableContextMenu = m_general.m_enableContextMenu; + gSettings.viewports.bEnableContextMenu = m_general.m_contextMenuEnabled; gSettings.viewports.bSync2DViews = m_general.m_sync2DViews; + SandboxEditor::SetStickySelectEnabled(m_general.m_stickySelectEnabled); gSettings.viewports.bShowSafeFrame = m_display.m_showSafeFrame; gSettings.viewports.bHighlightSelectedGeometry = m_display.m_highlightSelGeom; @@ -202,19 +259,19 @@ void CEditorPreferencesPage_ViewportGeneral::OnApply() gSettings.objectColorSettings.fChildGeomAlpha = m_selectionPreviewColor.m_childObjectGeomAlpha; gSettings.objectColorSettings.entityHighlight = QColor( - static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetR() * 255.0f), - static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetG() * 255.0f), - static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetB() * 255.0f)); + static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorEntityBBox.GetB() * 255.0f)); gSettings.objectColorSettings.groupHighlight = QColor( - static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetR() * 255.0f), - static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetG() * 255.0f), - static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetB() * 255.0f)); + static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_colorGroupBBox.GetB() * 255.0f)); gSettings.objectColorSettings.fBBoxAlpha = m_selectionPreviewColor.m_fBBoxAlpha; gSettings.objectColorSettings.fGeomAlpha = m_selectionPreviewColor.m_fgeomAlpha; gSettings.objectColorSettings.geometryHighlightColor = QColor( - static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetR() * 255.0f), - static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetG() * 255.0f), - static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetB() * 255.0f)); + static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetR() * 255.0f), + static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetG() * 255.0f), + static_cast(m_selectionPreviewColor.m_geometryHighlightColor.GetB() * 255.0f)); gSettings.objectColorSettings.solidBrushGeometryColor = QColor( static_cast(m_selectionPreviewColor.m_solidBrushGeometryColor.GetR() * 255.0f), static_cast(m_selectionPreviewColor.m_solidBrushGeometryColor.GetG() * 255.0f), @@ -227,8 +284,9 @@ void CEditorPreferencesPage_ViewportGeneral::InitializeSettings() m_general.m_defaultAspectRatio = gSettings.viewports.fDefaultAspectRatio; m_general.m_defaultFOV = gSettings.viewports.fDefaultFov; - m_general.m_enableContextMenu = gSettings.viewports.bEnableContextMenu; + m_general.m_contextMenuEnabled = gSettings.viewports.bEnableContextMenu; m_general.m_sync2DViews = gSettings.viewports.bSync2DViews; + m_general.m_stickySelectEnabled = SandboxEditor::StickySelectEnabled(); m_display.m_showSafeFrame = gSettings.viewports.bShowSafeFrame; m_display.m_highlightSelGeom = gSettings.viewports.bHighlightSelectedGeometry; @@ -256,10 +314,22 @@ void CEditorPreferencesPage_ViewportGeneral::InitializeSettings() m_textLabels.m_labelsDistance = ds->GetLabelsDistance(); m_selectionPreviewColor.m_childObjectGeomAlpha = gSettings.objectColorSettings.fChildGeomAlpha; - m_selectionPreviewColor.m_colorEntityBBox.Set(static_cast(gSettings.objectColorSettings.entityHighlight.redF()), static_cast(gSettings.objectColorSettings.entityHighlight.greenF()), static_cast(gSettings.objectColorSettings.entityHighlight.blueF()), 1.0f); - m_selectionPreviewColor.m_colorGroupBBox.Set(static_cast(gSettings.objectColorSettings.groupHighlight.redF()), static_cast(gSettings.objectColorSettings.groupHighlight.greenF()), static_cast(gSettings.objectColorSettings.groupHighlight.blueF()), 1.0f); + m_selectionPreviewColor.m_colorEntityBBox.Set( + static_cast(gSettings.objectColorSettings.entityHighlight.redF()), + static_cast(gSettings.objectColorSettings.entityHighlight.greenF()), + static_cast(gSettings.objectColorSettings.entityHighlight.blueF()), 1.0f); + m_selectionPreviewColor.m_colorGroupBBox.Set( + static_cast(gSettings.objectColorSettings.groupHighlight.redF()), + static_cast(gSettings.objectColorSettings.groupHighlight.greenF()), + static_cast(gSettings.objectColorSettings.groupHighlight.blueF()), 1.0f); m_selectionPreviewColor.m_fBBoxAlpha = gSettings.objectColorSettings.fBBoxAlpha; m_selectionPreviewColor.m_fgeomAlpha = gSettings.objectColorSettings.fGeomAlpha; - m_selectionPreviewColor.m_geometryHighlightColor.Set(static_cast(gSettings.objectColorSettings.geometryHighlightColor.redF()), static_cast(gSettings.objectColorSettings.geometryHighlightColor.greenF()), static_cast(gSettings.objectColorSettings.geometryHighlightColor.blueF()), 1.0f); - m_selectionPreviewColor.m_solidBrushGeometryColor.Set(static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.redF()), static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.greenF()), static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.blueF()), 1.0f); + m_selectionPreviewColor.m_geometryHighlightColor.Set( + static_cast(gSettings.objectColorSettings.geometryHighlightColor.redF()), + static_cast(gSettings.objectColorSettings.geometryHighlightColor.greenF()), + static_cast(gSettings.objectColorSettings.geometryHighlightColor.blueF()), 1.0f); + m_selectionPreviewColor.m_solidBrushGeometryColor.Set( + static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.redF()), + static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.greenF()), + static_cast(gSettings.objectColorSettings.solidBrushGeometryColor.blueF()), 1.0f); } diff --git a/Code/Editor/EditorPreferencesPageViewportGeneral.h b/Code/Editor/EditorPreferencesPageViewportGeneral.h index a042bcf19b..be89cc6df4 100644 --- a/Code/Editor/EditorPreferencesPageViewportGeneral.h +++ b/Code/Editor/EditorPreferencesPageViewportGeneral.h @@ -5,18 +5,17 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #pragma once #include "Include/IPreferencesPage.h" -#include -#include -#include #include +#include +#include +#include #include - -class CEditorPreferencesPage_ViewportGeneral - : public IPreferencesPage +class CEditorPreferencesPage_ViewportGeneral : public IPreferencesPage { public: AZ_RTTI(CEditorPreferencesPage_ViewportGeneral, "{8511FF7F-F774-47E1-A99B-3DE3A867E403}", IPreferencesPage) @@ -26,12 +25,12 @@ public: CEditorPreferencesPage_ViewportGeneral(); virtual ~CEditorPreferencesPage_ViewportGeneral() = default; - virtual const char* GetCategory() override { return "Viewports"; } + virtual const char* GetCategory() override; virtual const char* GetTitle() override; virtual QIcon& GetIcon() override; virtual void OnApply() override; - virtual void OnCancel() override {} - virtual bool OnQueryCancel() override { return true; } + virtual void OnCancel() override; + virtual bool OnQueryCancel() override; private: void InitializeSettings(); @@ -43,7 +42,8 @@ private: bool m_sync2DViews; float m_defaultFOV; float m_defaultAspectRatio; - bool m_enableContextMenu; + bool m_contextMenuEnabled; + bool m_stickySelectEnabled; }; struct Display @@ -106,5 +106,3 @@ private: SelectionPreviewColor m_selectionPreviewColor; QIcon m_icon; }; - - diff --git a/Code/Editor/EditorViewportSettings.cpp b/Code/Editor/EditorViewportSettings.cpp index c1bd85a174..063ec125ba 100644 --- a/Code/Editor/EditorViewportSettings.cpp +++ b/Code/Editor/EditorViewportSettings.cpp @@ -20,6 +20,7 @@ namespace SandboxEditor constexpr AZStd::string_view AngleSnappingSetting = "/Amazon/Preferences/Editor/AngleSnapping"; constexpr AZStd::string_view AngleSizeSetting = "/Amazon/Preferences/Editor/AngleSize"; constexpr AZStd::string_view ShowGridSetting = "/Amazon/Preferences/Editor/ShowGrid"; + constexpr AZStd::string_view StickySelectSetting = "/Amazon/Preferences/Editor/StickySelect"; constexpr AZStd::string_view ManipulatorLineBoundWidthSetting = "/Amazon/Preferences/Editor/Manipulator/LineBoundWidth"; constexpr AZStd::string_view ManipulatorCircleBoundWidthSetting = "/Amazon/Preferences/Editor/Manipulator/CircleBoundWidth"; constexpr AZStd::string_view CameraTranslateSpeedSetting = "/Amazon/Preferences/Editor/Camera/TranslateSpeed"; @@ -158,6 +159,16 @@ namespace SandboxEditor SetRegistry(ShowGridSetting, showing); } + bool StickySelectEnabled() + { + return GetRegistry(StickySelectSetting, false); + } + + void SetStickySelectEnabled(const bool enabled) + { + SetRegistry(StickySelectSetting, enabled); + } + float ManipulatorLineBoundWidth() { return aznumeric_cast(GetRegistry(ManipulatorLineBoundWidthSetting, 0.1)); diff --git a/Code/Editor/EditorViewportSettings.h b/Code/Editor/EditorViewportSettings.h index 8aeeee1384..20d397a29e 100644 --- a/Code/Editor/EditorViewportSettings.h +++ b/Code/Editor/EditorViewportSettings.h @@ -47,6 +47,9 @@ namespace SandboxEditor SANDBOX_API bool ShowingGrid(); SANDBOX_API void SetShowingGrid(bool showing); + SANDBOX_API bool StickySelectEnabled(); + SANDBOX_API void SetStickySelectEnabled(bool enabled); + SANDBOX_API float ManipulatorLineBoundWidth(); SANDBOX_API void SetManipulatorLineBoundWidth(float lineBoundWidth); diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index f009fe7602..1ed901e514 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -2522,6 +2522,11 @@ float EditorViewportSettings::ManipulatorCircleBoundWidth() const return SandboxEditor::ManipulatorCircleBoundWidth(); } +bool EditorViewportSettings::StickySelectEnabled() const +{ + return SandboxEditor::StickySelectEnabled(); +} + AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); bool EditorViewportWidget::ShouldPreviewFullscreen() const diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index c4a8e9fcca..6b46524394 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -77,6 +77,7 @@ struct EditorViewportSettings : public AzToolsFramework::ViewportInteraction::Vi float AngleStep() const override; float ManipulatorLineBoundWidth() const override; float ManipulatorCircleBoundWidth() const override; + bool StickySelectEnabled() const override; }; // EditorViewportWidget window diff --git a/Code/Editor/ViewportTitleDlg.cpp b/Code/Editor/ViewportTitleDlg.cpp index 1f04f71712..65d6de8944 100644 --- a/Code/Editor/ViewportTitleDlg.cpp +++ b/Code/Editor/ViewportTitleDlg.cpp @@ -154,6 +154,8 @@ void CViewportTitleDlg::SetupCameraDropdownMenu() cameraMenu->addMenu(GetFovMenu()); m_ui->m_cameraMenu->setMenu(cameraMenu); m_ui->m_cameraMenu->setPopupMode(QToolButton::InstantPopup); + QObject::connect(cameraMenu, &QMenu::aboutToShow, this, &CViewportTitleDlg::CheckForCameraSpeedUpdate); + QAction* gotoPositionAction = new QAction("Go to position", cameraMenu); connect(gotoPositionAction, &QAction::triggered, this, &CViewportTitleDlg::OnBnClickedGotoPosition); cameraMenu->addAction(gotoPositionAction); diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h index 6bd72f5101..06db67a05f 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ActionDispatcher.h @@ -15,19 +15,19 @@ namespace AzManipulatorTestFramework { - //! Base class for derived immediate and retained action dispatchers. + //! Base class for derived immediate action dispatchers. template class ActionDispatcher { public: virtual ~ActionDispatcher() = default; - //! Enable grid snapping. - DerivedDispatcherT* EnableSnapToGrid(); - //! Disable grid snapping. - DerivedDispatcherT* DisableSnapToGrid(); + //! Enable/disable grid snapping. + DerivedDispatcherT* SetSnapToGrid(bool enabled); //! Set the grid size. DerivedDispatcherT* GridSize(float size); + //! Enable/disable sticky select. + DerivedDispatcherT* SetStickySelect(bool enabled); //! Enable/disable action logging. DerivedDispatcherT* LogActions(bool logging); //! Output a trace debug message. @@ -66,9 +66,9 @@ namespace AzManipulatorTestFramework DerivedDispatcherT* EnterComponentMode(); protected: - // Actions to be implemented by derived immediate and retained action dispatchers. - virtual void EnableSnapToGridImpl() = 0; - virtual void DisableSnapToGridImpl() = 0; + // Actions to be implemented by derived immediate action dispatcher. + virtual void SetSnapToGridImpl(bool enabled) = 0; + virtual void SetStickySelectImpl(bool enabled) = 0; virtual void GridSizeImpl(float size) = 0; virtual void CameraStateImpl(const AzFramework::CameraState& cameraState) = 0; virtual void MouseLButtonDownImpl() = 0; @@ -127,18 +127,18 @@ namespace AzManipulatorTestFramework } template - DerivedDispatcherT* ActionDispatcher::EnableSnapToGrid() + DerivedDispatcherT* ActionDispatcher::SetSnapToGrid(const bool enabled) { - Log("Enabling SnapToGrid"); - EnableSnapToGridImpl(); + Log("SnapToGrid %s", enabled ? "on" : "off"); + SetSnapToGridImpl(enabled); return static_cast(this); } template - DerivedDispatcherT* ActionDispatcher::DisableSnapToGrid() + DerivedDispatcherT* ActionDispatcher::SetStickySelect(bool enabled) { - Log("Disabling SnapToGrid"); - DisableSnapToGridImpl(); + Log("StickySelect %s", enabled ? "on" : "off"); + SetStickySelectImpl(enabled); return static_cast(this); } diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h index 7f838b0073..a911534dd9 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/AzManipulatorTestFramework.h @@ -16,7 +16,7 @@ namespace AzFramework { class DebugDisplayRequests; struct CameraState; -} +} // namespace AzFramework namespace AzManipulatorTestFramework { @@ -31,14 +31,10 @@ namespace AzManipulatorTestFramework virtual void SetCameraState(const AzFramework::CameraState& cameraState) = 0; //! Retrieve the debug display. virtual AzFramework::DebugDisplayRequests& GetDebugDisplay() = 0; - //! Enable grid snapping. - virtual void EnableGridSnaping() = 0; - //! Disable grid snapping. - virtual void DisableGridSnaping() = 0; - //! Enable grid snapping. - virtual void EnableAngularSnaping() = 0; - //! Disable grid snapping. - virtual void DisableAngularSnaping() = 0; + //! Set if grid snapping is enabled or not. + virtual void SetGridSnapping(bool enabled) = 0; + //! Set if angular snapping is enabled or not. + virtual void SetAngularSnapping(bool enabled) = 0; //! Set the grid size. virtual void SetGridSize(float size) = 0; //! Set the angular step. @@ -48,6 +44,8 @@ namespace AzManipulatorTestFramework //! Updates the visibility state. //! Updates which entities are currently visible given the current camera state. virtual void UpdateVisibility() = 0; + //! Set if sticky select is enabled or not. + virtual void SetStickySelect(bool enabled) = 0; }; //! This interface is used to simulate the manipulator manager while the manipulators are under test. @@ -82,15 +80,15 @@ namespace AzManipulatorTestFramework //! Return the representation of the viewport interaction model. ViewportInteractionInterface& GetViewportInteraction() { - return const_cast< - ViewportInteractionInterface&>(const_cast(this)->GetViewportInteraction()); + return const_cast( + const_cast(this)->GetViewportInteraction()); } //! Return the const representation of the manipulator manager. ManipulatorManagerInterface& GetManipulatorManager() { - return const_cast< - ManipulatorManagerInterface&>(const_cast(this)->GetManipulatorManager()); + return const_cast( + const_cast(this)->GetManipulatorManager()); } }; } // namespace AzManipulatorTestFramework diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h index 9e11a7543c..7eddd8b915 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h @@ -52,8 +52,8 @@ namespace AzManipulatorTestFramework protected: // ActionDispatcher ... - void EnableSnapToGridImpl() override; - void DisableSnapToGridImpl() override; + void SetSnapToGridImpl(bool enabled) override; + void SetStickySelectImpl(bool enabled) override; void GridSizeImpl(float size) override; void CameraStateImpl(const AzFramework::CameraState& cameraState) override; void MouseLButtonDownImpl() override; diff --git a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h index 1bc329d404..cfecc0c91a 100644 --- a/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h +++ b/Code/Framework/AzManipulatorTestFramework/Include/AzManipulatorTestFramework/ViewportInteraction.h @@ -29,14 +29,13 @@ namespace AzManipulatorTestFramework // ViewportInteractionInterface overrides ... void SetCameraState(const AzFramework::CameraState& cameraState) override; AzFramework::DebugDisplayRequests& GetDebugDisplay() override; - void EnableGridSnaping() override; - void DisableGridSnaping() override; - void EnableAngularSnaping() override; - void DisableAngularSnaping() override; + void SetGridSnapping(bool enabled) override; + void SetAngularSnapping(bool enabled) override; void SetGridSize(float size) override; void SetAngularStep(float step) override; int GetViewportId() const override; void UpdateVisibility() override; + void SetStickySelect(bool enabled) override; // ViewportInteractionRequestBus overrides ... AzFramework::CameraState GetCameraState() override; @@ -54,6 +53,7 @@ namespace AzManipulatorTestFramework float AngleStep() const override; float ManipulatorLineBoundWidth() const override; float ManipulatorCircleBoundWidth() const override; + bool StickySelectEnabled() const override; // EditorEntityViewportInteractionRequestBus overrides ... void FindVisibleEntities(AZStd::vector& visibleEntities) override; @@ -65,6 +65,7 @@ namespace AzManipulatorTestFramework AzFramework::CameraState m_cameraState; bool m_gridSnapping = false; bool m_angularSnapping = false; + bool m_stickySelect = true; float m_gridSize = 1.0f; float m_angularStep = 0.0f; }; diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp index 23cc2a21f5..08db7497f4 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/ImmediateModeActionDispatcher.cpp @@ -49,17 +49,17 @@ namespace AzManipulatorTestFramework m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event); } - void ImmediateModeActionDispatcher::EnableSnapToGridImpl() + void ImmediateModeActionDispatcher::SetSnapToGridImpl(const bool enabled) { - m_viewportManipulatorInteraction.GetViewportInteraction().EnableGridSnaping(); + m_viewportManipulatorInteraction.GetViewportInteraction().SetGridSnapping(enabled); } - void ImmediateModeActionDispatcher::DisableSnapToGridImpl() + void ImmediateModeActionDispatcher::SetStickySelectImpl(const bool enabled) { - m_viewportManipulatorInteraction.GetViewportInteraction().DisableGridSnaping(); + m_viewportManipulatorInteraction.GetViewportInteraction().SetStickySelect(enabled); } - void ImmediateModeActionDispatcher::GridSizeImpl(float size) + void ImmediateModeActionDispatcher::GridSizeImpl(const float size) { m_viewportManipulatorInteraction.GetViewportInteraction().SetGridSize(size); } diff --git a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp index 4dae4fc00d..509674e5c0 100644 --- a/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Source/ViewportInteraction.cpp @@ -6,16 +6,15 @@ * */ -#include -#include #include +#include +#include #include namespace AzManipulatorTestFramework { // Null debug display for dummy draw calls - class NullDebugDisplayRequests - : public AzFramework::DebugDisplayRequests + class NullDebugDisplayRequests : public AzFramework::DebugDisplayRequests { public: virtual ~NullDebugDisplayRequests() = default; @@ -76,6 +75,11 @@ namespace AzManipulatorTestFramework return 0.1f; } + bool ViewportInteraction::StickySelectEnabled() const + { + return m_stickySelect; + } + void ViewportInteraction::FindVisibleEntities(AZStd::vector& visibleEntitiesOut) { visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End()); @@ -101,24 +105,19 @@ namespace AzManipulatorTestFramework return *m_nullDebugDisplayRequests; } - void ViewportInteraction::EnableGridSnaping() - { - m_gridSnapping = true; - } - - void ViewportInteraction::DisableGridSnaping() + void ViewportInteraction::SetGridSnapping(const bool enabled) { - m_gridSnapping = false; + m_gridSnapping = enabled; } - void ViewportInteraction::EnableAngularSnaping() + void ViewportInteraction::SetAngularSnapping(const bool enabled) { - m_angularSnapping = true; + m_angularSnapping = enabled; } - void ViewportInteraction::DisableAngularSnaping() + void ViewportInteraction::SetStickySelect(const bool enabled) { - m_angularSnapping = false; + m_stickySelect = enabled; } void ViewportInteraction::SetGridSize(float size) @@ -152,4 +151,4 @@ namespace AzManipulatorTestFramework { return 1.0f; } -}// namespace AzManipulatorTestFramework +} // namespace AzManipulatorTestFramework diff --git a/Code/Framework/AzManipulatorTestFramework/Tests/GridSnappingTest.cpp b/Code/Framework/AzManipulatorTestFramework/Tests/GridSnappingTest.cpp index 12b2a6546c..4af66edc0a 100644 --- a/Code/Framework/AzManipulatorTestFramework/Tests/GridSnappingTest.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Tests/GridSnappingTest.cpp @@ -76,7 +76,7 @@ namespace UnitTest linearManipulator->SetLocalPosition(action.LocalPosition()); }); - m_actionDispatcher->EnableSnapToGrid() + m_actionDispatcher->SetSnapToGrid(true) ->GridSize(5.0f) ->CameraState(m_cameraState) ->MousePosition(initialPositionScreen) @@ -114,7 +114,7 @@ namespace UnitTest manipulator->SetLocalPosition(action.LocalPosition()); }); - actionDispatcher->EnableSnapToGrid() + actionDispatcher->SetSnapToGrid(true) ->GridSize(1.0f) ->CameraState(cameraState) ->MousePosition(initialPositionScreen) diff --git a/Code/Framework/AzManipulatorTestFramework/Tests/ViewportInteractionTest.cpp b/Code/Framework/AzManipulatorTestFramework/Tests/ViewportInteractionTest.cpp index f1fba39651..38c3e33977 100644 --- a/Code/Framework/AzManipulatorTestFramework/Tests/ViewportInteractionTest.cpp +++ b/Code/Framework/AzManipulatorTestFramework/Tests/ViewportInteractionTest.cpp @@ -48,7 +48,7 @@ namespace UnitTest { bool snapping = false; - m_viewportInteraction->EnableGridSnaping(); + m_viewportInteraction->SetGridSnapping(true); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult( snapping, m_viewportInteraction->GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled); @@ -60,7 +60,7 @@ namespace UnitTest { bool snapping = true; - m_viewportInteraction->DisableGridSnaping(); + m_viewportInteraction->SetGridSnapping(false); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult( snapping, m_viewportInteraction->GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled); @@ -75,7 +75,7 @@ namespace UnitTest m_viewportInteraction->SetGridSize(expectedGridSize); - m_viewportInteraction->DisableGridSnaping(); + m_viewportInteraction->SetGridSnapping(false); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult( gridSize, m_viewportInteraction->GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::GridSize); @@ -87,7 +87,7 @@ namespace UnitTest { bool snapping = false; - m_viewportInteraction->EnableAngularSnaping(); + m_viewportInteraction->SetAngularSnapping(true); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult( snapping, m_viewportInteraction->GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::AngleSnappingEnabled); @@ -99,7 +99,7 @@ namespace UnitTest { bool snapping = true; - m_viewportInteraction->DisableAngularSnaping(); + m_viewportInteraction->SetAngularSnapping(false); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::EventResult( snapping, m_viewportInteraction->GetViewportId(), &AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::AngleSnappingEnabled); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 8bddeb7a44..c9438e640d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -196,6 +196,8 @@ namespace AzToolsFramework virtual float ManipulatorLineBoundWidth() const = 0; //! Returns the current circle (torus) bound width for manipulators. virtual float ManipulatorCircleBoundWidth() const = 0; + //! Returns if sticky select is enabled or not. + virtual bool StickySelectEnabled() const = 0; protected: ~ViewportSettingsRequests() = default; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 064fbb9da6..5820eaafe1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -77,13 +77,6 @@ namespace AzToolsFramework nullptr, AZ::ConsoleFunctorFlags::Null, "The screen position of the gizmo in normalized (0-1) ndc space"); - AZ_CVAR( - bool, - ed_viewportStickySelect, - true, - nullptr, - AZ::ConsoleFunctorFlags::Null, - "Sticky select implies a single click will not change selection with an entity already selected"); // strings related to new viewport interaction model (EditorTransformComponentSelection) static const char* const TogglePivotTitleRightClick = "Toggle pivot"; @@ -1790,7 +1783,8 @@ namespace AzToolsFramework CheckDirtyEntityIds(); - const AzFramework::CameraState cameraState = GetCameraState(mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId); + const AzFramework::ViewportId viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId; + const AzFramework::CameraState cameraState = GetCameraState(viewportId); m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction); @@ -1835,7 +1829,11 @@ namespace AzToolsFramework return true; } - if (ed_viewportStickySelect) + bool stickySelect = false; + ViewportInteraction::ViewportSettingsRequestBus::EventResult( + stickySelect, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::StickySelectEnabled); + + if (stickySelect) { // double click to deselect all if (Input::DeselectAll(mouseInteraction)) @@ -1891,7 +1889,7 @@ namespace AzToolsFramework return false; } - if (ed_viewportStickySelect) + if (stickySelect) { return false; } @@ -1900,7 +1898,7 @@ namespace AzToolsFramework // standard toggle selection if (Input::IndividualSelect(clickOutcome)) { - if (!ed_viewportStickySelect) + if (!stickySelect) { ChangeSelectedEntity(entityIdUnderCursor); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index 478c0b775e..935e80951a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -33,8 +33,6 @@ namespace AzToolsFramework { - AZ_CVAR_EXTERNED(bool, ed_viewportStickySelect); - class EditorVisibleEntityDataCache; using EntityIdSet = AZStd::unordered_set; //!< Alias for unordered_set of EntityIds. diff --git a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp index 72cafe5cd5..c94e174108 100644 --- a/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/EditorTransformComponentSelectionTests.cpp @@ -616,8 +616,6 @@ namespace UnitTest TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickySingleClickWithNoSelectionWillSelectEntity) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -629,7 +627,11 @@ namespace UnitTest const auto entity1ScreenPosition = AzFramework::WorldToScreen(m_entity1WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) + ->MousePosition(entity1ScreenPosition) + ->MouseLButtonDown() + ->MouseLButtonUp(); // entity is selected auto selectedEntitiesAfter = SelectedEntities(); @@ -639,8 +641,6 @@ namespace UnitTest TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickWithNoSelectionWillSelectEntity) { - AzToolsFramework::ed_viewportStickySelect = false; - PositionEntities(); PositionCamera(m_cameraState); @@ -652,7 +652,11 @@ namespace UnitTest const auto entity1ScreenPosition = AzFramework::WorldToScreen(m_entity1WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(false) + ->CameraState(m_cameraState) + ->MousePosition(entity1ScreenPosition) + ->MouseLButtonDown() + ->MouseLButtonUp(); // entity is selected auto selectedEntitiesAfter = SelectedEntities(); @@ -664,8 +668,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickySingleClickOffEntityWithSelectionWillNotDeselectEntity) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -678,7 +680,11 @@ namespace UnitTest const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); // click the empty space in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) + ->MousePosition(clickOffPositionScreen) + ->MouseLButtonDown() + ->MouseLButtonUp(); // entity was not deselected using ::testing::Eq; @@ -690,8 +696,6 @@ namespace UnitTest TEST_F( EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickOffEntityWithSelectionWillDeselectEntity) { - AzToolsFramework::ed_viewportStickySelect = false; - PositionEntities(); PositionCamera(m_cameraState); @@ -703,7 +707,11 @@ namespace UnitTest const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); // click the empty space in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(false) + ->CameraState(m_cameraState) + ->MousePosition(clickOffPositionScreen) + ->MouseLButtonDown() + ->MouseLButtonUp(); // entity was deselected auto selectedEntitiesAfter = SelectedEntities(); @@ -714,8 +722,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickySingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -725,7 +731,11 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) + ->MousePosition(entity2ScreenPosition) + ->MouseLButtonDown() + ->MouseLButtonUp(); // entity selection was not changed using ::testing::Eq; @@ -738,8 +748,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickOnNewEntityWithSelectionWillChangeSelectedEntity) { - AzToolsFramework::ed_viewportStickySelect = false; - PositionEntities(); PositionCamera(m_cameraState); @@ -749,7 +757,11 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(false) + ->CameraState(m_cameraState) + ->MousePosition(entity2ScreenPosition) + ->MouseLButtonDown() + ->MouseLButtonUp(); // entity selection was changed using ::testing::Eq; @@ -762,8 +774,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickyCtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -773,7 +783,7 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(true)->CameraState(m_cameraState) ->MousePosition(entity2ScreenPosition) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() @@ -789,8 +799,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickyCtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection) { - AzToolsFramework::ed_viewportStickySelect = false; - PositionEntities(); PositionCamera(m_cameraState); @@ -800,7 +808,8 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(false) + ->CameraState(m_cameraState) ->MousePosition(entity2ScreenPosition) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() @@ -816,8 +825,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickyCtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -827,7 +834,8 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) ->MousePosition(entity2ScreenPosition) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() @@ -843,8 +851,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickyCtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection) { - AzToolsFramework::ed_viewportStickySelect = false; - PositionEntities(); PositionCamera(m_cameraState); @@ -854,7 +860,8 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(false) + ->CameraState(m_cameraState) ->MousePosition(entity2ScreenPosition) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() @@ -868,8 +875,6 @@ namespace UnitTest TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithNoInitialSelectionAddsEntitiesToSelection) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -882,7 +887,8 @@ namespace UnitTest const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); // perform a box select in the viewport - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) ->MousePosition(beginningPositionWorldBoxSelect) ->MouseLButtonDown() ->MousePosition(endingPositionWorldBoxSelect) @@ -896,8 +902,6 @@ namespace UnitTest TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithSelectionAppendsEntitiesToSelection) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -914,7 +918,8 @@ namespace UnitTest const auto endingPositionWorldBoxSelect2 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); // perform a box select in the viewport (going left and right) - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) ->MousePosition(beginningPositionWorldBoxSelect1) ->MouseLButtonDown() ->MousePosition(endingPositionWorldBoxSelect1) @@ -933,8 +938,6 @@ namespace UnitTest EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectHoldingCtrlWithSelectionRemovesEntitiesFromSelection) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -949,7 +952,8 @@ namespace UnitTest const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState); // perform a box select in the viewport - m_actionDispatcher->CameraState(m_cameraState) + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) ->MousePosition(beginningPositionWorldBoxSelect) ->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control) ->MouseLButtonDown() @@ -963,8 +967,6 @@ namespace UnitTest TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickyDoubleClickWithSelectionWillDeselectEntities) { - AzToolsFramework::ed_viewportStickySelect = true; - PositionEntities(); PositionCamera(m_cameraState); @@ -980,7 +982,10 @@ namespace UnitTest const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState); // double click to deselect entities - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDoubleClick(); + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) + ->MousePosition(clickOffPositionScreen) + ->MouseLButtonDoubleClick(); // no entities are selected auto selectedEntitiesAfter = SelectedEntities(); @@ -989,8 +994,6 @@ namespace UnitTest TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickyUndoOperationForChangeInSelectionIsAtomic) { - AzToolsFramework::ed_viewportStickySelect = false; - PositionEntities(); PositionCamera(m_cameraState); @@ -1000,7 +1003,11 @@ namespace UnitTest const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState); // single click select entity2 - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + m_actionDispatcher->SetStickySelect(false) + ->CameraState(m_cameraState) + ->MousePosition(entity2ScreenPosition) + ->MouseLButtonDown() + ->MouseLButtonUp(); // undo action AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::UndoPressed); From 7c3f59ba5e99948886c79e3e3234ff812546ea2d Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Thu, 16 Sep 2021 12:41:24 +0200 Subject: [PATCH 157/274] EMotion FX: Resetting the Motion extraction joint when the Anim Graph is active crashes the Editor (#4138) Wrong invalid index type caused the crash. Selecting another joint was broken as well and got fixed directly, too. The selection done event was never received due to not being connected to the node hierarchy widget. Resolves #4108 Signed-off-by: Benjamin Jillich --- Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp | 2 +- Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 94a56cc0d5..3e592113b1 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -1245,7 +1245,7 @@ namespace EMotionFX } else { - SetMotionExtractionNodeIndex(MCORE_INVALIDINDEX32); + SetMotionExtractionNodeIndex(InvalidIndex); } } diff --git a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp index 41253a513e..b1f8733bfe 100644 --- a/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/ActorJointBrowseEdit.cpp @@ -66,6 +66,7 @@ namespace EMStudio m_jointSelectionWindow = new NodeSelectionWindow(this, m_singleJointSelection); connect(m_jointSelectionWindow, &NodeSelectionWindow::rejected, this, &ActorJointBrowseEdit::OnSelectionRejected); connect(m_jointSelectionWindow->GetNodeHierarchyWidget()->GetTreeWidget(), &QTreeWidget::itemSelectionChanged, this, &ActorJointBrowseEdit::OnSelectionChanged); + connect(m_jointSelectionWindow->GetNodeHierarchyWidget(), &NodeHierarchyWidget::OnSelectionDone, this, &ActorJointBrowseEdit::OnSelectionDone); NodeSelectionWindow::connect(m_jointSelectionWindow, &QDialog::finished, [=]([[maybe_unused]] int resultCode) { From 33b86b567b65085e9b07049a1f156f43412a525f Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Wed, 15 Sep 2021 16:40:29 -0700 Subject: [PATCH 158/274] Allow for `AZCoreLogSink::Disconnect()` to be called more than once Signed-off-by: Chris Burel --- Code/Legacy/CrySystem/AZCoreLogSink.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Legacy/CrySystem/AZCoreLogSink.h b/Code/Legacy/CrySystem/AZCoreLogSink.h index a54a78157c..8c88752e9a 100644 --- a/Code/Legacy/CrySystem/AZCoreLogSink.h +++ b/Code/Legacy/CrySystem/AZCoreLogSink.h @@ -46,6 +46,7 @@ public: { GetInstance().BusDisconnect(); delete GetInstance().m_ignoredAsserts; + GetInstance().m_ignoredAsserts = nullptr; } static AZCoreLogSink& GetInstance() From b95e170f9e394d15787b8ee4205fd44302ed8841 Mon Sep 17 00:00:00 2001 From: jckand-amzn <82226555+jckand-amzn@users.noreply.github.com> Date: Thu, 16 Sep 2021 10:53:38 -0500 Subject: [PATCH 159/274] Marking DistanceBetweenFilter tests with xfail due to Editor deadlock (#4156) * Marking DistanceBetweenFilter tests with xfail due to Editor deadlock Signed-off-by: jckand-amzn * Updating xfail mark Signed-off-by: jckand-amzn --- .../largeworlds/dyn_veg/test_DistanceBetweenFilter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py index 6d1b688315..d525e4a599 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py @@ -35,6 +35,7 @@ class TestDistanceBetweenFilter(object): @pytest.mark.test_case_id("C4851066") @pytest.mark.SUITE_periodic @pytest.mark.dynveg_filter + @pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/4155") def test_DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius(self, request, editor, level, launcher_platform): expected_lines = [ @@ -56,6 +57,7 @@ class TestDistanceBetweenFilter(object): @pytest.mark.test_case_id("C4814458") @pytest.mark.SUITE_periodic @pytest.mark.dynveg_filter + @pytest.mark.xfail(reason="https://github.com/o3de/o3de/issues/4155") def test_DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius(self, request, editor, level, launcher_platform): From 447832dd81c74eab4927d1f595b029593ea59a0e Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 16 Sep 2021 11:01:00 -0500 Subject: [PATCH 160/274] Updated the GameApplication to mount the engine.pak (#4128) * Updated the GameApplication to mount the engine.pak This allows loading the autoexec.cfg and bootstrap.game...setreg from the engine.pak files The engine.pak is searched for in the following order: /engine.pak, followed by /engine.pak Removed a lot of unused APIs from the AZ::IO::Archive feature suite Updated many of the AZ::IO::Archive classes to use AZ::IO::Path internally. The logic to search for files within an Archive has been updated to use AZ::IO::Path and to remove case-insensitve string comparisons Somehow removed the CryFile dependency on anything Cry Updated the Settings Registry to support reading from the FileIOBase and therefore Archive files in the GameLauncher via the `SetUseFileIO` function Removed AzFramework Dependency on md5 3rdParty library Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Linux build fix Added an include of before the include as it usesnprintf. Added `static` to the constexpr constants in ExtractFileDescription in SettingsRegistryImpl.cpp to fix clang compile issue Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the case used to mount the Engine PAK file in the GameApplication to be Engine.pak to match the other locations where it is mounted Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the proper FFont call to FileIOBase::Size to supply the correct integer type of AZ::u64 instead of size_t This fixes building on platforms where size_t is type defined to be unsigned long Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed segmentation fault in Archive::Unregister when outputing the filename of the Archive file being closed Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fix calls to OpenPack in the Legacy LevelSystem The LevelSystem was calling the incorrect overload of OpenPack that accepts BindRoot for the mounted level.pak instead of the overload that that passes a memory block object. This was causing the level pak files to be mounted using an invalid directory, causing file accesses inside the level pak to fail. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the error messages in the ZipDir CacheFactory class to use AZ_Warning directly Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the ArchiveFileIO m_trackedFiles container to store mapped type as an AZ::IO::Path Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Editor/CryEditDoc.cpp | 8 +- Code/Editor/GameExporter.cpp | 19 - .../PerforcePlugin/PerforceSourceControl.cpp | 1 + Code/Editor/PythonEditorEventsBus.h | 3 +- Code/Editor/PythonEditorFuncs.cpp | 9 +- Code/Editor/PythonEditorFuncs.h | 2 +- Code/Editor/Settings.cpp | 3 +- Code/Editor/Settings.h | 2 - Code/Editor/Util/FileUtil.cpp | 29 +- Code/Editor/Util/XmlArchive.cpp | 2 +- .../AzCore/AzCore/Settings/SettingsRegistry.h | 5 + .../AzCore/Settings/SettingsRegistryImpl.cpp | 272 ++++-- .../AzCore/Settings/SettingsRegistryImpl.h | 10 +- .../UnitTest/Mocks/MockSettingsRegistry.h | 1 + Code/Framework/AzCore/AzCore/XML/rapidxml.h | 1 + .../AzFramework/Application/Application.cpp | 65 -- .../AzFramework/Archive/Archive.cpp | 895 ++++-------------- .../AzFramework/AzFramework/Archive/Archive.h | 102 +- .../AzFramework/Archive/ArchiveFileIO.cpp | 42 +- .../AzFramework/Archive/ArchiveFileIO.h | 3 +- .../AzFramework/Archive/ArchiveFindData.cpp | 141 ++- .../AzFramework/Archive/ArchiveFindData.h | 56 +- .../AzFramework/Archive/IArchive.h | 178 +--- .../AzFramework/Archive/INestedArchive.h | 26 +- .../AzFramework/Archive/NestedArchive.cpp | 30 +- .../AzFramework/Archive/NestedArchive.h | 10 +- .../AzFramework/Archive/ZipDirCache.cpp | 70 +- .../AzFramework/Archive/ZipDirCache.h | 12 +- .../Archive/ZipDirCacheFactory.cpp | 95 +- .../AzFramework/Archive/ZipDirCacheFactory.h | 9 +- .../AzFramework/Archive/ZipDirFind.cpp | 83 +- .../AzFramework/Archive/ZipDirFind.h | 15 +- .../AzFramework/Archive/ZipDirList.cpp | 4 +- .../AzFramework/Archive/ZipDirStructures.cpp | 25 +- .../AzFramework/Archive/ZipDirStructures.h | 4 - .../AzFramework/Archive/ZipDirTree.cpp | 57 +- .../AzFramework/Archive/ZipDirTree.h | 29 +- .../AzFramework/IO/LocalFileIO.cpp | 2 +- Code/Framework/AzFramework/CMakeLists.txt | 1 - .../Tests/ArchiveCompressionTests.cpp | 2 +- .../AzFramework/Tests/ArchiveTests.cpp | 256 +---- .../Application/GameApplication.cpp | 32 +- Code/Legacy/CryCommon/CryFile.h | 124 +-- Code/Legacy/CryCommon/CryPath.h | 1 + Code/Legacy/CryCommon/Mocks/ICryPakMock.h | 49 +- Code/Legacy/CrySystem/ConsoleBatchFile.cpp | 6 +- .../CrySystem/LevelSystem/LevelSystem.cpp | 16 +- Code/Legacy/CrySystem/SystemCFG.cpp | 18 +- Code/Legacy/CrySystem/SystemInit.cpp | 26 +- .../CrySystem/WindowsErrorReporting.cpp | 9 +- Code/Legacy/CrySystem/XConsoleVariable.h | 4 +- Code/Legacy/CrySystem/XML/XmlUtils.cpp | 2 +- Code/Legacy/CrySystem/XML/xml.cpp | 25 +- .../SettingsRegistryBuilder.cpp | 43 +- .../AtomLyIntegration/AtomFont/FFont.h | 2 +- .../AtomFont/Code/Source/FFont.cpp | 43 +- .../CommonFeatures/Code/CMakeLists.txt | 1 + 57 files changed, 987 insertions(+), 1993 deletions(-) diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index a61429fc87..07d946c609 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -1135,7 +1135,6 @@ bool CCryEditDoc::SaveLevel(const QString& filename) { // if we're saving to a new folder, we need to copy the old folder tree. auto pIPak = GetIEditor()->GetSystem()->GetIPak(); - pIPak->Lock(); const QString oldLevelPattern = QDir(oldLevelFolder).absoluteFilePath("*.*"); const QString oldLevelName = Path::GetFile(GetLevelPathName()); @@ -1199,7 +1198,6 @@ bool CCryEditDoc::SaveLevel(const QString& filename) QFile(filePath).setPermissions(QFile::ReadOther | QFile::WriteOther); }); - pIPak->Unlock(); } // Save level to XML archive. @@ -1813,8 +1811,8 @@ bool CCryEditDoc::BackupBeforeSave(bool force) QString subFolder = theTime.toString("yyyy-MM-dd [HH.mm.ss]"); QString levelName = GetIEditor()->GetGameEngine()->GetLevelName(); - QString backupPath = saveBackupPath + "/" + subFolder + "/"; - gEnv->pCryPak->MakeDir(backupPath.toUtf8().data()); + QString backupPath = saveBackupPath + "/" + subFolder; + AZ::IO::FileIOBase::GetDirectInstance()->CreatePath(backupPath.toUtf8().data()); QString sourcePath = QString::fromUtf8(resolvedLevelPath) + "/"; @@ -2028,7 +2026,7 @@ const char* CCryEditDoc::GetTemporaryLevelName() const void CCryEditDoc::DeleteTemporaryLevel() { QString tempLevelPath = (Path::GetEditingGameDataFolder() + "/Levels/" + GetTemporaryLevelName()).c_str(); - GetIEditor()->GetSystem()->GetIPak()->ClosePacks(tempLevelPath.toUtf8().data(), AZ::IO::IArchive::EPathResolutionRules::FLAGS_ADD_TRAILING_SLASH); + GetIEditor()->GetSystem()->GetIPak()->ClosePacks(tempLevelPath.toUtf8().data()); CFileUtil::Deltree(tempLevelPath.toUtf8().data(), true); } diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 00dc3d8de1..9315505e08 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -432,25 +432,6 @@ void CGameExporter::ExportFileList(const QString& path, const QString& levelName newFileNode->setAttr("src", handle.m_filename.data()); newFileNode->setAttr("dest", handle.m_filename.data()); newFileNode->setAttr("size", handle.m_fileDesc.nSize); - - unsigned char md5[16]; - AZStd::string filenameToHash = GetIEditor()->GetGameEngine()->GetLevelPath().toUtf8().data(); - filenameToHash += "/"; - filenameToHash += AZStd::string{ handle.m_filename.data(), handle.m_filename.size() }; - if (gEnv->pCryPak->ComputeMD5(filenameToHash.data(), md5)) - { - char md5string[33]; - sprintf_s(md5string, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - md5[0], md5[1], md5[2], md5[3], - md5[4], md5[5], md5[6], md5[7], - md5[8], md5[9], md5[10], md5[11], - md5[12], md5[13], md5[14], md5[15]); - newFileNode->setAttr("md5", md5string); - } - else - { - newFileNode->setAttr("md5", ""); - } } } } while (handle = gEnv->pCryPak->FindNext(handle)); diff --git a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp index 10c43c3d1b..dd9ccaa832 100644 --- a/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp +++ b/Code/Editor/Plugins/PerforcePlugin/PerforceSourceControl.cpp @@ -6,6 +6,7 @@ * */ +#include #include "CryFile.h" #include "PerforceSourceControl.h" #include "PasswordDlg.h" diff --git a/Code/Editor/PythonEditorEventsBus.h b/Code/Editor/PythonEditorEventsBus.h index 5107a1c9cc..ffc357e64d 100644 --- a/Code/Editor/PythonEditorEventsBus.h +++ b/Code/Editor/PythonEditorEventsBus.h @@ -8,6 +8,7 @@ */ #pragma once +#include #include namespace AzToolsFramework @@ -138,7 +139,7 @@ namespace AzToolsFramework /* * Finds a pak file name for a given file. */ - virtual const char* GetPakFromFile(const char* filename) = 0; + virtual AZ::IO::Path GetPakFromFile(const char* filename) = 0; /* * Prints the message to the editor console window. diff --git a/Code/Editor/PythonEditorFuncs.cpp b/Code/Editor/PythonEditorFuncs.cpp index 200fd28f87..455cdfa17d 100644 --- a/Code/Editor/PythonEditorFuncs.cpp +++ b/Code/Editor/PythonEditorFuncs.cpp @@ -625,7 +625,7 @@ namespace } ////////////////////////////////////////////////////////////////////////// - const char* PyGetPakFromFile(const char* filename) + AZ::IO::Path PyGetPakFromFile(const char* filename) { auto pIPak = GetIEditor()->GetSystem()->GetIPak(); AZ::IO::HandleType fileHandle = pIPak->FOpen(filename, "rb"); @@ -633,8 +633,9 @@ namespace { throw std::logic_error("Invalid file name."); } - const char* pArchPath = pIPak->GetFileArchivePath(fileHandle); + AZ::IO::Path pArchPath = pIPak->GetFileArchivePath(fileHandle); pIPak->FClose(fileHandle); + return pArchPath; } @@ -1040,7 +1041,7 @@ namespace AzToolsFramework return PySetAxisConstraint(pConstrain); } - const char* PythonEditorComponent::GetPakFromFile(const char* filename) + AZ::IO::Path PythonEditorComponent::GetPakFromFile(const char* filename) { return PyGetPakFromFile(filename); } @@ -1114,7 +1115,7 @@ namespace AzToolsFramework addLegacyGeneral(behaviorContext->Method("get_axis_constraint", PyGetAxisConstraint, nullptr, "Gets axis.")); addLegacyGeneral(behaviorContext->Method("set_axis_constraint", PySetAxisConstraint, nullptr, "Sets axis.")); - addLegacyGeneral(behaviorContext->Method("get_pak_from_file", PyGetPakFromFile, nullptr, "Finds a pak file name for a given file.")); + addLegacyGeneral(behaviorContext->Method("get_pak_from_file", [](const char* filename) -> AZStd::string { return PyGetPakFromFile(filename).Native(); }, nullptr, "Finds a pak file name for a given file.")); addLegacyGeneral(behaviorContext->Method("log", PyLog, nullptr, "Prints the message to the editor console window.")); diff --git a/Code/Editor/PythonEditorFuncs.h b/Code/Editor/PythonEditorFuncs.h index 97ad8829ba..ef0c1327fa 100644 --- a/Code/Editor/PythonEditorFuncs.h +++ b/Code/Editor/PythonEditorFuncs.h @@ -91,7 +91,7 @@ namespace AzToolsFramework void SetAxisConstraint(AZStd::string_view pConstrain) override; - const char* GetPakFromFile(const char* filename) override; + AZ::IO::Path GetPakFromFile(const char* filename) override; void Log(const char* pMessage) override; diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index 80d248e1bf..05a6960695 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -171,7 +171,6 @@ SEditorSettings::SEditorSettings() bBackupOnSave = true; backupOnSaveMaxCount = 3; bApplyConfigSpecInEditor = true; - useLowercasePaths = 0; showErrorDialogOnLoad = 1; consoleBackgroundColorTheme = AzToolsFramework::ConsoleColorTheme::Dark; @@ -887,6 +886,7 @@ void SEditorSettings::Load() ////////////////////////////////////////////////////////////////////////// AZ_CVAR(bool, ed_previewGameInFullscreen_once, false, nullptr, AZ::ConsoleFunctorFlags::IsInvisible, "Preview the game (Ctrl+G, \"Play Game\", etc.) in fullscreen once"); +AZ_CVAR(bool, ed_lowercasepaths, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Convert CCryFile paths to lowercase on Open"); void SEditorSettings::PostInitApply() { @@ -898,7 +898,6 @@ void SEditorSettings::PostInitApply() // Create CVars. REGISTER_CVAR2("ed_highlightGeometry", &viewports.bHighlightMouseOverGeometry, viewports.bHighlightMouseOverGeometry, 0, "Highlight geometry when mouse over it"); REGISTER_CVAR2("ed_showFrozenHelpers", &viewports.nShowFrozenHelpers, viewports.nShowFrozenHelpers, 0, "Show helpers of frozen objects"); - REGISTER_CVAR2("ed_lowercasepaths", &useLowercasePaths, useLowercasePaths, 0, "generate paths in lowercase"); gEnv->pConsole->RegisterInt("fe_fbx_savetempfile", 0, 0, "When importing an FBX file into Facial Editor, this will save out a conversion FSQ to the Animations/temp folder for trouble shooting"); REGISTER_CVAR2_CB("ed_toolbarIconSize", &gui.nToolbarIconSize, gui.nToolbarIconSize, VF_NULL, "Override size of the toolbar icons 0-default, 16,32,...", ToolbarIconSizeChanged); diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index a408822129..8bf22b43e5 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -340,8 +340,6 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING //! how many save backups to keep int backupOnSaveMaxCount; - int useLowercasePaths; - ////////////////////////////////////////////////////////////////////////// // Autobackup. ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Editor/Util/FileUtil.cpp b/Code/Editor/Util/FileUtil.cpp index 610a9c6e16..eeb6912acf 100644 --- a/Code/Editor/Util/FileUtil.cpp +++ b/Code/Editor/Util/FileUtil.cpp @@ -149,12 +149,13 @@ bool CFileUtil::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const c // Check if in pack. if (cryfile.IsInPak()) { - const char* sPakName = cryfile.GetPakPath(); - if (bMsgBoxAskForExtraction) { + AZ::IO::FixedMaxPath sPakName{ cryfile.GetPakPath() }; // Cannot edit file in pack, suggest to extract it for editing. - if (QMessageBox::critical(QApplication::activeWindow(), QString(), QObject::tr("File %1 is inside a PAK file %2\r\nDo you want it to be extracted for editing ?").arg(file, sPakName), QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + if (QMessageBox::critical(QApplication::activeWindow(), QString(), + QObject::tr("File %1 is inside a PAK file %2\r\nDo you want it to be extracted for editing ?").arg(file, sPakName.c_str()), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { return false; } @@ -173,10 +174,9 @@ bool CFileUtil::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const c if (diskFile.open(QFile::WriteOnly)) { // Copy data from packed file to disk file. - char* data = new char[cryfile.GetLength()]; - cryfile.ReadRaw(data, cryfile.GetLength()); - diskFile.write(data, cryfile.GetLength()); - delete []data; + auto data = AZStd::make_unique(cryfile.GetLength()); + cryfile.ReadRaw(data.get(), cryfile.GetLength()); + diskFile.write(data.get(), cryfile.GetLength()); } else { @@ -185,7 +185,14 @@ bool CFileUtil::ExtractFile(QString& file, bool bMsgBoxAskForExtraction, const c } else { - file = cryfile.GetAdjustedFilename(); + + if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr) + { + if (AZ::IO::FixedMaxPath resolvedFilePath; fileIoBase->ResolvePath(resolvedFilePath, cryfile.GetFilename())) + { + file = QString::fromUtf8(resolvedFilePath.c_str(), static_cast(resolvedFilePath.Native().size())); + } + } } return true; @@ -2157,13 +2164,13 @@ uint32 CFileUtil::GetAttributes(const char* filename, bool bUseSourceControl /*= return SCC_FILE_ATTRIBUTE_READONLY | SCC_FILE_ATTRIBUTE_INPAK; } - const char* adjustedFile = file.GetAdjustedFilename(); - if (!AZ::IO::SystemFile::Exists(adjustedFile)) + auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); + if (!fileIoBase->Exists(file.GetFilename())) { return SCC_FILE_ATTRIBUTE_INVALID; } - if (!AZ::IO::SystemFile::IsWritable(adjustedFile)) + if (fileIoBase->IsReadOnly(file.GetFilename())) { return SCC_FILE_ATTRIBUTE_NORMAL | SCC_FILE_ATTRIBUTE_READONLY; } diff --git a/Code/Editor/Util/XmlArchive.cpp b/Code/Editor/Util/XmlArchive.cpp index e6bc93fdf4..18c3fc8e63 100644 --- a/Code/Editor/Util/XmlArchive.cpp +++ b/Code/Editor/Util/XmlArchive.cpp @@ -124,7 +124,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile& if (pakFile.GetArchive()) { - CLogFile::FormatLine("Saving pak file %s", (const char*)pakFile.GetArchive()->GetFullPath()); + CLogFile::FormatLine("Saving pak file %.*s", AZ_STRING_ARG(pakFile.GetArchive()->GetFullPath().Native())); } pNamedData->Save(pakFile); diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index 106e232904..3dc1be87c5 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -370,6 +370,11 @@ namespace AZ //! @param applyPatchSettings The ApplyPatchSettings which are using during JSON Merging virtual void SetApplyPatchSettings(const AZ::JsonApplyPatchSettings& applyPatchSettings) = 0; virtual void GetApplyPatchSettings(AZ::JsonApplyPatchSettings& applyPatchSettings) = 0; + + //! Stores option to indicate whether the FileIOBase instance should be used for file operations + //! @param useFileIo If true the FileIOBase instance will attempted to be used for FileIOBase + //! operations before falling back to use SystemFile + virtual void SetUseFileIO(bool useFileIo) = 0; }; inline SettingsRegistryInterface::Visitor::~Visitor() = default; diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp index 6864dcd1c8..7ef1fa661d 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.cpp @@ -9,11 +9,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -131,6 +134,12 @@ namespace AZ pointer.Create(m_settings, m_settings.GetAllocator()).SetArray(); } + SettingsRegistryImpl::SettingsRegistryImpl(bool useFileIo) + : SettingsRegistryImpl() + { + m_useFileIo = useFileIo; + } + void SettingsRegistryImpl::SetContext(SerializeContext* context) { AZStd::scoped_lock lock(m_settingMutex); @@ -723,15 +732,10 @@ namespace AZ RegistryFileList fileList; scratchBuffer->clear(); - AZ::IO::FixedMaxPathString folderPath{ path }; - constexpr AZStd::string_view pathSeparators{ AZ_CORRECT_AND_WRONG_DATABASE_SEPARATOR }; - if (pathSeparators.find_first_of(folderPath.back()) == AZStd::string_view::npos) - { - folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR); - } + AZ::IO::FixedMaxPath folderPath{ path }; - const size_t platformKeyOffset = folderPath.size(); - folderPath.push_back('*'); + const size_t platformKeyOffset = folderPath.Native().size(); + folderPath /= '*'; Value specialzationArray(kArrayType); size_t specializationCount = specializations.GetCount(); @@ -741,47 +745,13 @@ namespace AZ specialzationArray.PushBack(Value(name.data(), aznumeric_caster(name.length()), m_settings.GetAllocator()), m_settings.GetAllocator()); } pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() - .AddMember(StringRef("Folder"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) + .AddMember(StringRef("Folder"), Value(folderPath.c_str(), aznumeric_caster(folderPath.Native().size()), m_settings.GetAllocator()), m_settings.GetAllocator()) .AddMember(StringRef("Specializations"), AZStd::move(specialzationArray), m_settings.GetAllocator()); - auto callback = [this, &fileList, &specializations, &pointer, &folderPath](const char* filename, bool isFile) -> bool - { - if (isFile) - { - if (fileList.size() >= MaxRegistryFolderEntries) - { - AZ_Error("Settings Registry", false, "Too many files in registry folder."); - AZStd::scoped_lock lock(m_settingMutex); - pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() - .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) - .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) - .AddMember(StringRef("File"), Value(filename, m_settings.GetAllocator()), m_settings.GetAllocator()); - return false; - } - - fileList.push_back(); - RegistryFile& registryFile = fileList.back(); - if (!ExtractFileDescription(registryFile, filename, specializations)) - { - fileList.pop_back(); - } - } - return true; - }; - SystemFile::FindFiles(folderPath.c_str(), callback); - - if (!platform.empty()) + auto CreateSettingsFindCallback = [this, &fileList, &specializations, &pointer, &folderPath](bool isPlatformFile) { - // Move the folderPath prefix back to the supplied path before the wildcard - folderPath.erase(platformKeyOffset); - folderPath += PlatformFolder; - folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR); - folderPath += platform; - folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR); - folderPath.push_back('*'); - - auto platformCallback = [this, &fileList, &specializations, &pointer, &folderPath](const char* filename, bool isFile) -> bool + return [this, &fileList, &specializations, &pointer, &folderPath, isPlatformFile](AZStd::string_view filename, bool isFile) -> bool { if (isFile) { @@ -791,8 +761,8 @@ namespace AZ AZStd::scoped_lock lock(m_settingMutex); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() .AddMember(StringRef("Error"), StringRef("Too many files in registry folder."), m_settings.GetAllocator()) - .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.size()), m_settings.GetAllocator()), m_settings.GetAllocator()) - .AddMember(StringRef("File"), Value(filename, m_settings.GetAllocator()), m_settings.GetAllocator()); + .AddMember(StringRef("Path"), Value(folderPath.c_str(), aznumeric_caster(folderPath.Native().size()), m_settings.GetAllocator()), m_settings.GetAllocator()) + .AddMember(StringRef("File"), Value(filename.data(), aznumeric_caster(filename.size()), m_settings.GetAllocator()), m_settings.GetAllocator()); return false; } @@ -800,7 +770,7 @@ namespace AZ RegistryFile& registryFile = fileList.back(); if (ExtractFileDescription(registryFile, filename, specializations)) { - registryFile.m_isPlatformFile = true; + registryFile.m_isPlatformFile = isPlatformFile; } else { @@ -809,7 +779,42 @@ namespace AZ } return true; }; - SystemFile::FindFiles(folderPath.c_str(), platformCallback); + }; + + struct FindFilesPayload + { + bool m_isPlatformFile{}; + AZStd::fixed_vector m_pathSegmentsToAppend; + }; + + AZStd::fixed_vector findFilesPayloads{ {false} }; + if (!platform.empty()) + { + findFilesPayloads.push_back(FindFilesPayload{ true, { PlatformFolder, platform } }); + } + + for (const FindFilesPayload& findFilesPayload : findFilesPayloads) + { + // Erase back to initial path + folderPath.Native().erase(platformKeyOffset); + for (AZStd::string_view pathSegmentToAppend : findFilesPayload.m_pathSegmentsToAppend) + { + folderPath /= pathSegmentToAppend; + } + + auto findFilesCallback = CreateSettingsFindCallback(findFilesPayload.m_isPlatformFile); + if (AZ::IO::FileIOBase* fileIo = m_useFileIo ? AZ::IO::FileIOBase::GetInstance() : nullptr; fileIo != nullptr) + { + auto FileIoToSystemFileFindFiles = [findFilesCallback = AZStd::move(findFilesCallback), fileIo](const char* filePath) -> bool + { + return findFilesCallback(AZ::IO::PathView(filePath).Filename().Native(), !fileIo->IsDirectory(filePath)); + }; + fileIo->FindFiles(folderPath.c_str(), "*", FileIoToSystemFileFindFiles); + } + else + { + SystemFile::FindFiles((folderPath / "*").c_str(), findFilesCallback); + } } if (!fileList.empty()) @@ -831,16 +836,14 @@ namespace AZ // Load the registry files in the sorted order. for (RegistryFile& registryFile : fileList) { - folderPath.erase(platformKeyOffset); // Erase all characters after the platformKeyOffset + folderPath.Native().erase(platformKeyOffset); // Erase all characters after the platformKeyOffset if (registryFile.m_isPlatformFile) { - folderPath += PlatformFolder; - folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR); - folderPath += platform; - folderPath.push_back(AZ_CORRECT_DATABASE_SEPARATOR); + folderPath /= PlatformFolder; + folderPath /= platform; } - folderPath += registryFile.m_relativePath; + folderPath /= registryFile.m_relativePath; if (!registryFile.m_isPatch) { @@ -1027,39 +1030,44 @@ namespace AZ return false; } - bool SettingsRegistryImpl::ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations) + bool SettingsRegistryImpl::ExtractFileDescription(RegistryFile& output, AZStd::string_view filename, const Specializations& specializations) { - if (!filename || filename[0] == 0) + static constexpr auto PatchExtensionWithDot = AZStd::fixed_string<32>(".") + PatchExtension; + static constexpr auto ExtensionWithDot = AZStd::fixed_string<32>(".") + Extension; + static constexpr AZ::IO::PathView PatchExtensionView(PatchExtensionWithDot); + static constexpr AZ::IO::PathView ExtensionView(ExtensionWithDot); + + if (filename.empty()) { AZ_Error("Settings Registry", false, "Settings file without name found"); return false; } - AZStd::string_view filePath{ filename }; - const size_t filePathSize = filePath.size(); + AZ::IO::PathView filePath{ filename }; + const size_t filePathSize = filePath.Native().size(); // The filePath.empty() check makes sure that the file extension after the final isn't added to the output.m_tags - AZStd::optional pathTag = AZ::StringFunc::TokenizeNext(filePath, '.'); - for (; pathTag && !filePath.empty(); pathTag = AZ::StringFunc::TokenizeNext(filePath, '.')) + auto AppendSpecTags = [&output](AZStd::string_view pathTag) { - output.m_tags.push_back(Specializations::Hash(*pathTag)); - } + output.m_tags.push_back(Specializations::Hash(pathTag)); + }; + AZ::StringFunc::TokenizeVisitor(filePath.Stem().Native(), AppendSpecTags, '.'); // If token is invalid, then the filename has no characters and therefore no extension - if (pathTag) + if (AZ::IO::PathView fileExtension = filePath.Extension(); !fileExtension.empty()) { - if (pathTag->size() >= AZStd::char_traits::length(PatchExtension) && azstrnicmp(pathTag->data(), PatchExtension, pathTag->size()) == 0) + if (fileExtension == PatchExtensionView) { output.m_isPatch = true; } - else if (pathTag->size() != AZStd::char_traits::length(Extension) || azstrnicmp(pathTag->data(), Extension, pathTag->size()) != 0) + else if (fileExtension != ExtensionView) { return false; } } else { - AZ_Error("Settings Registry", false, R"(Settings file without extension found: "%s")", filename); + AZ_Error("Settings Registry", false, R"(Settings file without extension found: "%.*s")", AZ_STRING_ARG(filename)); return false; } @@ -1074,7 +1082,7 @@ namespace AZ { if (*currentIt == *(currentIt - 1)) { - AZ_Error("Settings Registry", false, R"(One or more tags are duplicated in registry file "%s")", filename); + AZ_Error("Settings Registry", false, R"(One or more tags are duplicated in registry file "%.*s")", AZ_STRING_ARG(filename)); return false; } ++currentIt; @@ -1103,11 +1111,123 @@ namespace AZ } else { - AZ_Error("Settings Registry", false, R"(Found relative path to settings file "%s" is too long.)", filename); + AZ_Error("Settings Registry", false, R"(Found relative path to settings file "%.*s" is too long.)", AZ_STRING_ARG(filename)); return false; } } + //! Structure which encapsulates Commands to either the FileIOBase or SystemFile classes based on + //! the SettingsRegistry option to use FileIO + struct SettingsRegistryFileReader + { + using FileHandleType = AZStd::variant; + + SettingsRegistryFileReader() = default; + SettingsRegistryFileReader(bool useFileIo, const char* filePath) + { + Open(useFileIo, filePath); + } + + ~SettingsRegistryFileReader() + { + if (auto fileHandle = AZStd::get_if(&m_file); fileHandle != nullptr) + { + if (AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance(); fileIo != nullptr) + { + fileIo->Close(*fileHandle); + } + } + } + + bool Open(bool useFileIo, const char* filePath) + { + Close(); + if (AZ::IO::FileIOBase* fileIo = useFileIo ? AZ::IO::FileIOBase::GetInstance() : nullptr; fileIo != nullptr) + { + AZ::IO::HandleType fileHandle; + if (fileIo->Open(filePath, IO::OpenMode::ModeRead, fileHandle)) + { + m_file = fileHandle; + return true; + } + } + else + { + AZ::IO::SystemFile file; + if (file.Open(filePath, IO::SystemFile::OpenMode::SF_OPEN_READ_ONLY)) + { + m_file = AZStd::move(file); + return true; + } + } + + return false; + } + + bool IsOpen() const + { + if (auto fileHandle = AZStd::get_if(&m_file); fileHandle != nullptr) + { + return *fileHandle != AZ::IO::InvalidHandle; + } + else if (auto systemFile = AZStd::get_if(&m_file); systemFile != nullptr) + { + return systemFile->IsOpen(); + } + + return false; + } + + void Close() + { + if (auto fileHandle = AZStd::get_if(&m_file); fileHandle != nullptr) + { + if (AZ::IO::FileIOBase* fileIo = AZ::IO::FileIOBase::GetInstance(); fileIo != nullptr) + { + fileIo->Close(*fileHandle); + } + } + + m_file = AZStd::monostate{}; + } + + u64 Length() const + { + if (auto fileHandle = AZStd::get_if(&m_file); fileHandle != nullptr) + { + if (u64 fileSize{}; AZ::IO::FileIOBase::GetInstance()->Size(*fileHandle, fileSize)) + { + return fileSize; + } + } + else if (auto systemFile = AZStd::get_if(&m_file); systemFile != nullptr) + { + return systemFile->Length(); + } + + return 0; + } + + AZ::IO::SizeType Read(AZ::IO::SizeType byteSize, void* buffer) + { + if (auto fileHandle = AZStd::get_if(&m_file); fileHandle != nullptr) + { + if (AZ::u64 bytesRead{}; AZ::IO::FileIOBase::GetInstance()->Read(*fileHandle, buffer, byteSize, false, &bytesRead)) + { + return bytesRead; + } + } + else if (auto systemFile = AZStd::get_if(&m_file); systemFile != nullptr) + { + return systemFile->Read(byteSize, buffer); + } + + return 0; + } + + FileHandleType m_file; + }; + bool SettingsRegistryImpl::MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey, AZStd::vector& scratchBuffer) { @@ -1116,8 +1236,8 @@ namespace AZ Pointer pointer(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/-"); - SystemFile file; - if (!file.Open(path, SystemFile::OpenMode::SF_OPEN_READ_ONLY)) + SettingsRegistryFileReader fileReader(m_useFileIo, path); + if (!fileReader.IsOpen()) { AZ_Error("Settings Registry", false, R"(Unable to open registry file "%s".)", path); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() @@ -1126,7 +1246,7 @@ namespace AZ return false; } - u64 fileSize = file.Length(); + u64 fileSize = fileReader.Length(); if (fileSize == 0) { AZ_Warning("Settings Registry", false, R"(Registry file "%s" is 0 bytes in length. There is no nothing to merge)", path); @@ -1136,9 +1256,10 @@ namespace AZ .AddMember(StringRef("Path"), Value(path, m_settings.GetAllocator()), m_settings.GetAllocator()); return false; } + scratchBuffer.clear(); scratchBuffer.resize_no_construct(fileSize + 1); - if (file.Read(fileSize, scratchBuffer.data()) != fileSize) + if (fileReader.Read(fileSize, scratchBuffer.data()) != fileSize) { AZ_Error("Settings Registry", false, R"(Unable to read registry file "%s".)", path); pointer.Create(m_settings, m_settings.GetAllocator()).SetObject() @@ -1268,4 +1389,9 @@ namespace AZ { applyPatchSettings = m_applyPatchSettings; } + + void SettingsRegistryImpl::SetUseFileIO(bool useFileIo) + { + m_useFileIo = useFileIo; + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h index 036f5c6596..ac214711b8 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryImpl.h @@ -35,6 +35,10 @@ namespace AZ static constexpr size_t MaxRegistryFolderEntries = 128; SettingsRegistryImpl(); + //! @param useFileIo - If true attempt to redirect + //! file read operations through the FileIOBase instance first before falling back to SystemFile + //! otherwise always use SystemFile + explicit SettingsRegistryImpl(bool useFileIo); AZ_DISABLE_COPY_MOVE(SettingsRegistryImpl); ~SettingsRegistryImpl() override = default; @@ -83,6 +87,8 @@ namespace AZ void SetApplyPatchSettings(const AZ::JsonApplyPatchSettings& applyPatchSettings) override; void GetApplyPatchSettings(AZ::JsonApplyPatchSettings& applyPatchSettings) override; + void SetUseFileIO(bool useFileIo) override; + private: using TagList = AZStd::fixed_vector; struct RegistryFile @@ -104,7 +110,7 @@ namespace AZ // Compares if lhs is less than rhs in terms of processing order. This can also detect and report conflicts. bool IsLessThan(bool& collisionFound, const RegistryFile& lhs, const RegistryFile& rhs, const Specializations& specializations, const rapidjson::Pointer& historyPointer, AZStd::string_view folderPath); - bool ExtractFileDescription(RegistryFile& output, const char* filename, const Specializations& specializations); + bool ExtractFileDescription(RegistryFile& output, AZStd::string_view filename, const Specializations& specializations); bool MergeSettingsFileInternal(const char* path, Format format, AZStd::string_view rootKey, AZStd::vector& scratchBuffer); void SignalNotifier(AZStd::string_view jsonPath, Type type); @@ -119,5 +125,7 @@ namespace AZ JsonSerializerSettings m_serializationSettings; JsonDeserializerSettings m_deserializationSettings; JsonApplyPatchSettings m_applyPatchSettings; + + bool m_useFileIo{}; }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h index 7e6bb3d7b4..91dc0924c8 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/Mocks/MockSettingsRegistry.h @@ -57,6 +57,7 @@ namespace AZ MOCK_METHOD1(SetApplyPatchSettings, void(const JsonApplyPatchSettings&)); MOCK_METHOD1(GetApplyPatchSettings, void(JsonApplyPatchSettings&)); + MOCK_METHOD1(SetUseFileIO, void(bool)); }; } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/XML/rapidxml.h b/Code/Framework/AzCore/AzCore/XML/rapidxml.h index 694e0a1bf6..9e6d648293 100644 --- a/Code/Framework/AzCore/AzCore/XML/rapidxml.h +++ b/Code/Framework/AzCore/AzCore/XML/rapidxml.h @@ -13,6 +13,7 @@ // the intention is that you only include the customized version of rapidXML through this header, so that // you can override behavior here. +#include #include #endif // AZCORE_RAPIDXML_RAPIDXML_H_INCLUDED diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index 958dba2cc9..12974d03cf 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -81,71 +81,6 @@ namespace AzFramework static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem"; static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures"; static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage"; - - // A Helper function that can load an app descriptor from file. - AZ::Outcome, AZStd::string> LoadDescriptorFromFilePath(const char* appDescriptorFilePath, AZ::SerializeContext& serializeContext) - { - AZStd::unique_ptr loadedDescriptor; - - AZ::IO::SystemFile appDescriptorFile; - if (!appDescriptorFile.Open(appDescriptorFilePath, AZ::IO::SystemFile::SF_OPEN_READ_ONLY)) - { - return AZ::Failure(AZStd::string::format("Failed to open file: %s", appDescriptorFilePath)); - } - - AZ::IO::SystemFileStream appDescriptorFileStream(&appDescriptorFile, true); - if (!appDescriptorFileStream.IsOpen()) - { - return AZ::Failure(AZStd::string::format("Failed to stream file: %s", appDescriptorFilePath)); - } - - // Callback function for allocating the root elements in the file. - AZ::ObjectStream::InplaceLoadRootInfoCB inplaceLoadCb = - [](void** rootAddress, const AZ::SerializeContext::ClassData**, const AZ::Uuid& classId, AZ::SerializeContext*) - { - if (rootAddress && classId == azrtti_typeid()) - { - // ComponentApplication::Descriptor is normally a singleton. - // Force a unique instance to be created. - *rootAddress = aznew AZ::ComponentApplication::Descriptor(); - } - }; - - // Callback function for saving the root elements in the file. - AZ::ObjectStream::ClassReadyCB classReadyCb = - [&loadedDescriptor](void* classPtr, const AZ::Uuid& classId, AZ::SerializeContext* context) - { - // Save descriptor, delete anything else loaded from file. - if (classId == azrtti_typeid()) - { - loadedDescriptor.reset(static_cast(classPtr)); - } - else if (const AZ::SerializeContext::ClassData* classData = context->FindClassData(classId)) - { - classData->m_factory->Destroy(classPtr); - } - else - { - AZ_Error("Application", false, "Unexpected type %s found in application descriptor file. This memory will leak.", - classId.ToString().c_str()); - } - }; - - // There's other stuff in the file we may not recognize (system components), but we're not interested in that stuff. - AZ::ObjectStream::FilterDescriptor loadFilter(&AZ::Data::AssetFilterNoAssetLoading, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES); - - if (!AZ::ObjectStream::LoadBlocking(&appDescriptorFileStream, serializeContext, classReadyCb, loadFilter, inplaceLoadCb)) - { - return AZ::Failure(AZStd::string::format("Failed to load objects from file: %s", appDescriptorFilePath)); - } - - if (!loadedDescriptor) - { - return AZ::Failure(AZStd::string::format("Failed to find descriptor object in file: %s", appDescriptorFilePath)); - } - - return AZ::Success(AZStd::move(loadedDescriptor)); - } } Application::Application() diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index 1891c50d10..c94d588a90 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -40,8 +40,6 @@ #include -#include - namespace AZ::IO { AZ_CVAR(int, sys_PakPriority, aznumeric_cast(ArchiveVars{}.nPriority), nullptr, AZ::ConsoleFunctorFlags::Null, @@ -64,40 +62,6 @@ namespace AZ::IO::ArchiveInternal // to the actual index , this offset is added to get the valid handle static constexpr size_t PseudoFileIdxOffset = 1; - // Explanation of this function: it is like a 'find and replace' for paths - // if the source path starts with 'aliasToLookFor' it will replace it with 'aliasToReplaceWith' - // else it will leave it untouched. - // the only caveat here is that it will perform this replacement if the source path either begins - // with the literal alias to look for, or begins with the actual absolute path that the alias to - // look for represents. It is a way of redirecting all @devassets@ to @assets@ regardless of whether - // you input a string that literally starts with @devassets@ or one that starts with the absolute path to the - // folder that @devassets@ aliases. - AZStd::optional ConvertAbsolutePathToAliasedPath(AZStd::string_view sourcePath, - AZStd::string_view aliasToLookFor, AZStd::string_view aliasToReplaceWith) - { - if (auto fileIo = AZ::IO::FileIOBase::GetDirectInstance(); !aliasToLookFor.empty() && !aliasToReplaceWith.empty() && !sourcePath.empty() && fileIo) - { - auto convertedPath = fileIo->ConvertToAlias(sourcePath); - if (!convertedPath) - { - return AZStd::nullopt; - } - - if (convertedPath->Native().starts_with(aliasToLookFor)) - { - convertedPath->Native().replace(0, aliasToLookFor.size(), aliasToReplaceWith); - } - // lowercase path if it starts with either the @assets@ or @root@ alias - if (convertedPath->Native().starts_with("@assets@") || convertedPath->Native().starts_with("@root@") - || convertedPath->Native().starts_with("@projectplatformcache@")) - { - AZStd::to_lower(convertedPath->Native().begin(), convertedPath->Native().end()); - } - return convertedPath; - } - return AZStd::make_optional(sourcePath); - } - struct CCachedFileRawData { void* m_pCachedData; @@ -146,15 +110,12 @@ namespace AZ::IO::ArchiveInternal uint32_t GetFileSize() { return GetFile() ? GetFile()->GetFileEntry()->desc.lSizeUncompressed : 0; } int FSeek(uint64_t nOffset, int nMode); - size_t FRead(void* pDest, size_t nSize, size_t nCount, AZ::IO::HandleType fileHandle); - size_t FReadAll(void* pDest, size_t nFileSize, AZ::IO::HandleType fileHandle); + size_t FRead(void* pDest, size_t bytesToRead, AZ::IO::HandleType fileHandle); void* GetFileData(size_t& nFileSize, AZ::IO::HandleType fileHandle); int FEof(); - char* FGets(char* pBuf, int n); - int Getc(); uint64_t GetModificationTime() { return m_pFileData->GetFileEntry()->GetModificationTime(); } - const char* GetArchivePath() { return m_pFileData->GetZip()->GetFilePath(); } + AZ::IO::PathView GetArchivePath() { return m_pFileData->GetZip()->GetFilePath(); } protected: uint64_t m_nCurSeek; CCachedFileDataPtr m_pFileData; @@ -205,7 +166,7 @@ namespace AZ::IO::ArchiveInternal } ////////////////////////////////////////////////////////////////////////// - size_t ArchiveInternal::CZipPseudoFile::FRead(void* pDest, size_t nSize, size_t nCount, [[maybe_unused]] AZ::IO::HandleType fileHandle) + size_t ArchiveInternal::CZipPseudoFile::FRead(void* pDest, size_t bytesToRead, [[maybe_unused]] AZ::IO::HandleType fileHandle) { AZ_PROFILE_FUNCTION(AzCore); @@ -214,21 +175,13 @@ namespace AZ::IO::ArchiveInternal return 0; } - size_t nTotal = nSize * nCount; + size_t nTotal = bytesToRead; if (!nTotal || (uint32_t)m_nCurSeek >= GetFileSize()) { return 0; } - if (nTotal > GetFileSize() - m_nCurSeek) - { - nTotal = GetFileSize() - m_nCurSeek; - if (nTotal < nSize) - { - return 0; - } - nTotal -= nTotal % nSize; - } + nTotal = (AZStd::min)(nTotal, GetFileSize() - m_nCurSeek); int64_t nReadBytes = GetFile()->ReadData(pDest, m_nCurSeek, nTotal); if (nReadBytes == -1) @@ -242,32 +195,9 @@ namespace AZ::IO::ArchiveInternal nTotal = (size_t)nReadBytes; } m_nCurSeek += nTotal; - return nTotal / nSize; + return nTotal; } - ////////////////////////////////////////////////////////////////////////// - size_t ArchiveInternal::CZipPseudoFile::FReadAll(void* pDest, size_t nFileSize, [[maybe_unused]] AZ::IO::HandleType fileHandle) - { - if (!GetFile()) - { - return 0; - } - - if (nFileSize != GetFileSize()) - { - AZ_Assert(false, "File size parameter of nFileSize does not match the file size of the zip file"); // Bad call - return 0; - } - - if (!GetFile()->ReadData(pDest, 0, nFileSize)) - { - return 0; - } - - m_nCurSeek = nFileSize; - - return nFileSize; - } ////////////////////////////////////////////////////////////////////////// void* ArchiveInternal::CZipPseudoFile::GetFileData(size_t& nFileSize, [[maybe_unused]] AZ::IO::HandleType fileHandle) @@ -292,70 +222,6 @@ namespace AZ::IO::ArchiveInternal return (uint32_t)m_nCurSeek >= GetFileSize(); } - char* ArchiveInternal::CZipPseudoFile::FGets(char* pBuf, int n) - { - if (!GetFile()) - { - return nullptr; - } - - char* pData = (char*)GetFile()->GetData(); - if (!pData) - { - return nullptr; - } - int nn = 0; - int i; - for (i = 0; i < n; i++) - { - if (i + m_nCurSeek == GetFileSize()) - { - break; - } - char c = pData[i + m_nCurSeek]; - if (c == 0xa || c == 0) - { - pBuf[nn++] = c; - i++; - break; - } - else - if (c == 0xd) - { - continue; - } - pBuf[nn++] = c; - } - pBuf[nn] = 0; - m_nCurSeek += i; - - if (m_nCurSeek == GetFileSize()) - { - return nullptr; - } - return pBuf; - } - - int ArchiveInternal::CZipPseudoFile::Getc() - { - if (!GetFile()) - { - return EOF; - } - char* pData = (char*)GetFile()->GetData(); - if (!pData) - { - return EOF; - } - int c = EOF; - if (m_nCurSeek == GetFileSize()) - { - return c; - } - c = pData[m_nCurSeek]; - m_nCurSeek += 1; - return c; - } } namespace AZ::IO @@ -379,16 +245,17 @@ namespace AZ::IO void Add(AZStd::string_view sResourceFile) override { - auto filename = ArchiveInternal::ConvertAbsolutePathToAliasedPath(sResourceFile); - if (!filename) + if (sResourceFile.empty()) + { + return; + } + AZ::IO::FixedMaxPath convertedFilename; + if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(convertedFilename, sResourceFile)) { - AZ_Error("Archive", false, "Path %s cannot be converted to @alias@ form. It is longer than MaxPathLength %zu", aznumeric_cast(sResourceFile.size()), - sResourceFile.data(), AZ::IO::MaxPathLength); + AZ_Error("Archive", false, "Path %.*s cannot be resolved. It is longer than MaxPathLength %zu", + AZ_STRING_ARG(sResourceFile), AZ::IO::MaxPathLength); return; } - AZ::IO::FixedMaxPathString& convertedFilename = filename->Native(); - AZStd::replace(convertedFilename.begin(), convertedFilename.end(), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR); - AZStd::to_lower(convertedFilename.begin(), convertedFilename.end()); AZStd::scoped_lock lock(m_lock); m_set.emplace(convertedFilename); @@ -397,23 +264,20 @@ namespace AZ::IO { AZStd::scoped_lock lock(m_lock); m_set.clear(); - m_iter = m_set.begin(); + m_iter = m_set.end(); } bool IsExist(AZStd::string_view sResourceFile) override { - auto filename = ArchiveInternal::ConvertAbsolutePathToAliasedPath(sResourceFile); - if (!filename) + AZ::IO::FixedMaxPath convertedFilename; + if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(convertedFilename, sResourceFile)) { - AZ_Error("Archive", false, "Path %.*s cannot be converted to @alias@ form. It is longer than MaxPathLength %zu", aznumeric_cast(sResourceFile.size()), - sResourceFile.data(), AZ::IO::MaxPathLength); + AZ_Error("Archive", false, "Path %.*s cannot be resolved. It is longer than MaxPathLength %zu", + AZ_STRING_ARG(sResourceFile), AZ::IO::MaxPathLength); return false; } - AZ::IO::FixedMaxPathString& convertedFilename = filename->Native(); - AZStd::replace(convertedFilename.begin(), convertedFilename.end(), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR); - AZStd::to_lower(convertedFilename.begin(), convertedFilename.end()); AZStd::scoped_lock lock(m_lock); - return m_set.contains(AZStd::string_view{ convertedFilename }); + return m_set.contains(AZ::IO::PathView{ convertedFilename }); } bool Load(AZStd::string_view sResourceListFilename) override { @@ -425,9 +289,8 @@ namespace AZ::IO AZ::IO::SizeType nLen = file.Length(); AZStd::string pMemBlock; - pMemBlock.resize_no_construct(nLen); - char* buf = pMemBlock.data(); - file.Read(nLen, buf); + pMemBlock.resize_no_construct(nLen);; + file.Read(pMemBlock.size(), pMemBlock.data()); // Parse file, every line in a file represents a resource filename. AZ::StringFunc::TokenizeVisitor(pMemBlock, @@ -464,7 +327,7 @@ namespace AZ::IO } private: - using ResourceSet = AZStd::set; + using ResourceSet = AZStd::set>; AZStd::recursive_mutex m_lock; ResourceSet m_set; ResourceSet::iterator m_iter; @@ -499,12 +362,13 @@ namespace AZ::IO , m_pNextLevelResourceList{ new CResourceList{} } , m_mainThreadId{ AZStd::this_thread::get_id() } { + CompressionBus::Handler::BusConnect(); } ////////////////////////////////////////////////////////////////////////// Archive::~Archive() { - Release(); + CompressionBus::Handler::BusDisconnect(); m_arrZips = {}; @@ -530,51 +394,13 @@ namespace AZ::IO AZ_Assert(m_cachedFileRawDataSet.empty(), "All Archive file cached raw data instances not closed"); } - bool Archive::CheckFileAccessDisabled([[maybe_unused]] AZStd::string_view name, [[maybe_unused]] const char* mode) - { - return false; - } - void Archive::LogFileAccessCallStack([[maybe_unused]] AZStd::string_view name, [[maybe_unused]] AZStd::string_view nameFull, [[maybe_unused]] const char* mode) { // Print call stack for each find. - AZ_TracePrintf("Archive", "LogFileAccessCallStack() - name=%.*s; nameFull=%.*s; mode=%s\n", aznumeric_cast(name.size()), name.data(), aznumeric_cast(nameFull.size()), nameFull.data(), mode); + AZ_TracePrintf("Archive", "LogFileAccessCallStack() - name=%.*s; nameFull=%.*s; mode=%s\n", AZ_STRING_ARG(name), AZ_STRING_ARG(nameFull), mode); AZ::Debug::Trace::PrintCallstack("Archive", 32); } - ////////////////////////////////////////////////////////////////////////// - - bool Archive::IsInstalledToHDD(AZStd::string_view) const - { - return true; - } - - ////////////////////////////////////////////////////////////////////////// - void Archive::ParseAliases(AZStd::string_view szCommandLine) - { - // this is a list of pairs separated by commas, i.e. Folder1,FolderNew,Textures,TestBuildTextures etc. - AZStd::optional aliasKey = AZ::StringFunc::TokenizeNext(szCommandLine, ','); - AZStd::optional aliasPath = AZ::StringFunc::TokenizeNext(szCommandLine, ','); - for ( ;aliasKey && aliasPath; aliasKey = AZ::StringFunc::TokenizeNext(szCommandLine,','), AZ::StringFunc::TokenizeNext(szCommandLine,',')) - { - // inform the Archive system - SetAlias(*aliasKey, *aliasPath, true); - AZ_TracePrintf("Archive", "Archive ALIAS:%.*s = %.*s\n", aznumeric_cast(aliasKey->size()), aliasKey->data(), - aznumeric_cast(aliasPath->size()), aliasPath->data()); - - } - } - - ////////////////////////////////////////////////////////////////////////// - //! if bReturnSame==true, it will return the input name if an alias doesn't exist. Otherwise returns nullptr - const char* Archive::GetAlias(AZStd::string_view szName, bool bReturnSame) - { - constexpr size_t MaxAliasLength = 32; - AZStd::fixed_string aliasKey{ szName }; - const char* dest = AZ::IO::FileIOBase::GetDirectInstance()->GetAlias(aliasKey.c_str()); - return (bReturnSame && !dest) ? szName.data() : dest; - } - ////////////////////////////////////////////////////////////////////////// void Archive::SetLocalizationFolder(AZStd::string_view sLocalizationFolder) { @@ -591,28 +417,6 @@ namespace AZ::IO m_sLocalizationFolder += AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING; } - ////////////////////////////////////////////////////////////////////////// - void Archive::SetAlias(AZStd::string_view szName, AZStd::string_view szAlias, bool bAdd) - { - constexpr size_t MaxAliasLength = 32; - AZStd::fixed_string aliasKey{ szName }; - if (bAdd) - { - AZ::IO::PathString aliasPath{ szAlias }; - AZ::IO::FileIOBase::GetDirectInstance()->SetAlias(aliasKey.c_str(), aliasPath.c_str()); - } - else - { - AZ::IO::FileIOBase::GetDirectInstance()->ClearAlias(aliasKey.c_str()); - } - } - - - const char* Archive::AdjustFileName(AZStd::string_view src, char* dst, size_t dstSize, uint32_t, bool) - { - AZ::IO::FixedMaxPathString srcPath{ src }; - return AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(srcPath.c_str(), dst, dstSize) ? dst : nullptr; - } ////////////////////////////////////////////////////////////////////////// bool Archive::IsFileExist(AZStd::string_view sFilename, EFileSearchLocation fileLocation) @@ -679,52 +483,50 @@ namespace AZ::IO } ////////////////////////////////////////////////////////////////////////// - AZ::IO::HandleType Archive::FOpen(AZStd::string_view pName, const char* szMode, uint32_t nInputFlags) + AZ::IO::HandleType Archive::FOpen(AZStd::string_view pName, const char* szMode) { AZ_PROFILE_FUNCTION(AzCore); const size_t pathLen = pName.size(); - if (pathLen == 0 || pathLen >= MaxPath) + if (pathLen == 0 || pathLen >= AZ::IO::MaxPathLength) { return AZ::IO::InvalidHandle; } SAutoCollectFileAccessTime accessTime(this); - AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; - - const bool bFileCanBeOnDisk = 0 != (nInputFlags & FOPEN_ONDISK); - // get the priority into local variable to avoid it changing in the course of // this function execution (?) const ArchiveLocationPriority nVarPakPriority = GetPakPriority(); AZ::IO::OpenMode nOSFlags = AZ::IO::GetOpenModeFromStringMode(szMode); - auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pName); - if (!szFullPath) + AZ::IO::FixedMaxPath szFullPath; + if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(szFullPath, pName)) { - AZ_Assert(szFullPath, "Unable to resolve path for filepath %.*s", aznumeric_cast(pName.size()), pName.data()); + AZ_Assert(false, "Unable to resolve path for filepath %.*s", aznumeric_cast(pName.size()), pName.data()); return false; } const bool fileWritable = (nOSFlags & (AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeAppend | AZ::IO::OpenMode::ModeUpdate)) != AZ::IO::OpenMode::Invalid; - AZ_PROFILE_SCOPE(Game, "File: %s Archive: %p", szFullPath->c_str(), this); + AZ_PROFILE_SCOPE(Game, "File: %s Archive: %p", szFullPath.c_str(), this); if (fileWritable) { // we need to open the file for writing, but we failed to do so. // the only reason that can be is that there are no directories for that file. // now create those dirs - if (!MakeDir(szFullPath->ParentPath().Native())) + if (AZ::IO::FixedMaxPath parentPath = szFullPath.ParentPath(); + !AZ::IO::FileIOBase::GetDirectInstance()->CreatePath(parentPath.c_str())) { return AZ::IO::InvalidHandle; } - if (AZ::IO::FileIOBase::GetDirectInstance()->Open(szFullPath->c_str(), nOSFlags, fileHandle)) + if (AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; + AZ::IO::FileIOBase::GetDirectInstance()->Open(szFullPath.c_str(), nOSFlags, fileHandle)) { if (az_archive_verbosity) { - AZ_TracePrintf("Archive", " Archive::FOpen() has directly opened requested file %s for writing", szFullPath->c_str()); + AZ_TracePrintf("Archive", " Archive::FOpen() has directly opened requested file %s for writing", szFullPath.c_str()); } return fileHandle; } @@ -732,35 +534,41 @@ namespace AZ::IO return AZ::IO::InvalidHandle; } - if (nVarPakPriority == ArchiveLocationPriority::ePakPriorityFileFirst) // if the file system files have priority now.. + auto OpenFromFileSystem = [this, &szFullPath, pName, nOSFlags]() -> HandleType { - if (AZ::IO::FileIOBase::GetDirectInstance()->Open(szFullPath->c_str(), nOSFlags, fileHandle)) + if (AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; + AZ::IO::FileIOBase::GetDirectInstance()->Open(szFullPath.c_str(), nOSFlags, fileHandle)) { if (az_archive_verbosity) { - AZ_TracePrintf("Archive", " Archive::FOpen() has directly opened requested file %s with FileFirst priority", szFullPath->c_str()); + AZ_TracePrintf("Archive", " Archive::FOpen() has directly opened requested file %s on for reading", szFullPath.c_str()); } RecordFile(fileHandle, pName); return fileHandle; } - } - uint32_t archiveFlags = 0; - CCachedFileDataPtr pFileData = GetFileData(szFullPath->Native(), archiveFlags); - if (pFileData) + return AZ::IO::InvalidHandle; + }; + auto OpenFromArchive = [this, &szFullPath, pName]() -> HandleType { + uint32_t archiveFlags = 0; + CCachedFileDataPtr pFileData = GetFileData(szFullPath.Native(), archiveFlags); + if (pFileData == nullptr) + { + return AZ::IO::InvalidHandle; + } + bool logged = false; - ZipDir::Cache* pZip = pFileData->GetZip(); - if (pZip) + if (ZipDir::Cache* pZip = pFileData->GetZip(); pZip != nullptr) { - const char* pZipFilePath = pZip->GetFilePath(); - if (pZipFilePath && pZipFilePath[0]) + AZ::IO::PathView pZipFilePath = pZip->GetFilePath(); + if (!pZipFilePath.empty()) { if (az_archive_verbosity) { - AZ_TracePrintf("Archive", " Archive::FOpen() has opened requested file %s from archive %s, disk offset %u", - szFullPath->c_str(), pZipFilePath, pFileData->GetFileEntry()->nFileDataOffset); + AZ_TracePrintf("Archive", " Archive::FOpen() has opened requested file %s from archive %.*s, disk offset %u", + szFullPath.c_str(), AZ_STRING_ARG(pZipFilePath.Native()), pFileData->GetFileEntry()->nFileDataOffset); logged = true; } } @@ -771,57 +579,54 @@ namespace AZ::IO if (az_archive_verbosity) { AZ_TracePrintf("Archive", " Archive::FOpen() has opened requested file %s from an archive file who's path isn't known", - szFullPath->c_str()); + szFullPath.c_str()); } } - } - else - { - if (nVarPakPriority != ArchiveLocationPriority::ePakPriorityPakOnly || bFileCanBeOnDisk) // if the archive files had more priority, we didn't attempt fopen before- try it now + + size_t nFile; + // find the empty slot and open the file there; return the handle { - if (AZ::IO::FileIOBase::GetDirectInstance()->Open(szFullPath->c_str(), nOSFlags, fileHandle)) + // try to open the pseudofile from one of the zips, make sure there is no user alias + AZStd::unique_lock lock(m_csOpenFiles); + for (nFile = 0; nFile < m_arrOpenFiles.size() && m_arrOpenFiles[nFile]->GetFile(); ++nFile) { - if (az_archive_verbosity) - { - AZ_TracePrintf("Archive", " Archive::FOpen() has directly opened requested file %s after failing to open from archives", - szFullPath->c_str()); - } - - RecordFile(fileHandle, pName); - return fileHandle; + continue; + } + if (nFile == m_arrOpenFiles.size()) + { + m_arrOpenFiles.emplace_back(AZStd::make_unique()); } + AZStd::unique_ptr& rZipFile = m_arrOpenFiles[nFile]; + rZipFile->Construct(pFileData.get()); } - return AZ::IO::InvalidHandle; // we can't find such file in the pack files - } - // try to open the pseudofile from one of the zips, make sure there is no user alias - AZStd::unique_lock lock(m_csOpenFiles); + AZ::IO::HandleType handle = (AZ::IO::HandleType)(nFile + ArchiveInternal::PseudoFileIdxOffset); - size_t nFile; - // find the empty slot and open the file there; return the handle - { - for (nFile = 0; nFile < m_arrOpenFiles.size() && m_arrOpenFiles[nFile]->GetFile(); ++nFile) - { - continue; - } - if (nFile == m_arrOpenFiles.size()) - { - m_arrOpenFiles.emplace_back(AZStd::make_unique()); - } - AZStd::unique_ptr& rZipFile = m_arrOpenFiles[nFile]; - rZipFile->Construct(pFileData.get()); - } + RecordFile(handle, pName); - AZ::IO::HandleType ret = (AZ::IO::HandleType)(nFile + ArchiveInternal::PseudoFileIdxOffset); + return handle; // the handle to the file + }; - if (az_archive_verbosity) + switch (nVarPakPriority) { - AZ_TracePrintf("Archive", " Archive::FOpen() has opened psuedo zip file %.*s", aznumeric_cast(pName.size()), pName.data()); + case ArchiveLocationPriority::ePakPriorityFileFirst: + { + AZ::IO::HandleType fileHandle = OpenFromFileSystem(); + return fileHandle != AZ::IO::InvalidHandle ? fileHandle : OpenFromArchive(); + } + case ArchiveLocationPriority::ePakPriorityPakFirst: + { + AZ::IO::HandleType fileHandle = OpenFromArchive(); + return fileHandle != AZ::IO::InvalidHandle ? fileHandle : OpenFromFileSystem(); + } + case ArchiveLocationPriority::ePakPriorityPakOnly: + { + return OpenFromArchive(); + } + default: + return AZ::IO::InvalidHandle; } - RecordFile(ret, pName); - - return ret; // the handle to the file } ////////////////////////////////////////////////////////////////////////// @@ -872,19 +677,14 @@ namespace AZ::IO ////////////////////////////////////////////////////////////////////////// // tests if the given file path refers to an existing file inside registered (opened) packs // the path must be absolute normalized lower-case with forward-slashes - ZipDir::FileEntry* Archive::FindPakFileEntry(AZStd::string_view szPath, uint32_t& nArchiveFlags, ZipDir::CachePtr* pZip, bool bSkipInMemoryArchives) const + ZipDir::FileEntry* Archive::FindPakFileEntry(AZStd::string_view szPath, uint32_t& nArchiveFlags, ZipDir::CachePtr* pZip) const { - AZ::IO::FixedMaxPath unaliasedPath; + AZ::IO::FixedMaxPath resolvedPath; + if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedPath, szPath)) { - auto convertedPath = ArchiveInternal::ConvertAbsolutePathToAliasedPath(szPath); - - if (!convertedPath) - { - AZ_Error("Archive", false, "Path %s cannot be converted to @alias@ form. It is longer than MaxPathLength %zu", aznumeric_cast(szPath.size()), - szPath.data(), AZ::IO::MaxPathLength); - return nullptr; - } - unaliasedPath = AZStd::move(*convertedPath); + AZ_Error("Archive", false, "Path %s cannot be converted to @alias@ form. It is longer than MaxPathLength %zu", aznumeric_cast(szPath.size()), + szPath.data(), AZ::IO::MaxPathLength); + return nullptr; } @@ -892,28 +692,17 @@ namespace AZ::IO // scan through registered archive files and try to find this file for (auto itZip = m_arrZips.rbegin(); itZip != m_arrZips.rend(); ++itZip) { - if (bSkipInMemoryArchives && itZip->pArchive->GetFlags() & INestedArchive::FLAGS_IN_MEMORY_MASK) - { - continue; - } - if (itZip->pArchive->GetFlags() & INestedArchive::FLAGS_DISABLE_PAK) { continue; } - auto [bindRootIter, unaliasedIter] = AZStd::mismatch(itZip->m_pathBindRoot.begin(), itZip->m_pathBindRoot.end(), - unaliasedPath.begin(), unaliasedPath.end()); // If the bindRootIter is at the end then it is a prefix of the source path - if (bindRootIter == itZip->m_pathBindRoot.end()) + if (resolvedPath.IsRelativeTo(itZip->m_pathBindRoot)) { // unaliasedIter is past the bind root, so append the rest of it to a new relative path object - AZ::IO::FixedMaxPath relativePathInZip; - for (; unaliasedIter != unaliasedPath.end(); ++unaliasedIter) - { - relativePathInZip /= *unaliasedIter; - } + AZ::IO::FixedMaxPath relativePathInZip = resolvedPath.LexicallyRelative(itZip->m_pathBindRoot); ZipDir::FileEntry* pFileEntry = itZip->pZip->FindFile(relativePathInZip.Native()); if (pFileEntry) @@ -955,7 +744,7 @@ namespace AZ::IO } // returns the path to the archive in which the file was opened - const char* Archive::GetFileArchivePath(AZ::IO::HandleType fileHandle) + AZ::IO::PathView Archive::GetFileArchivePath(AZ::IO::HandleType fileHandle) { ArchiveInternal::CZipPseudoFile* pseudoFile = GetPseudoFile(fileHandle); if (pseudoFile) @@ -964,7 +753,7 @@ namespace AZ::IO } else { - return nullptr; + return {}; } } @@ -1066,7 +855,7 @@ namespace AZ::IO return 1; } - size_t Archive::FWrite(const void* data, size_t length, size_t elems, AZ::IO::HandleType fileHandle) + size_t Archive::FWrite(const void* data, size_t bytesToWrite, AZ::IO::HandleType fileHandle) { SAutoCollectFileAccessTime accessTime(this); @@ -1077,47 +866,28 @@ namespace AZ::IO } AZ_Assert(fileHandle != AZ::IO::InvalidHandle, "Invalid file has been passed to FWrite"); - if (AZ::IO::FileIOBase::GetDirectInstance()->Write(fileHandle, data, length * elems)) + if (AZ::u64 bytesWritten{}; AZ::IO::FileIOBase::GetDirectInstance()->Write(fileHandle, data, bytesToWrite, &bytesWritten)) { - return elems; + return bytesWritten; } return 0; } ////////////////////////////////////////////////////////////////////////// - size_t Archive::FReadRaw(void* pData, size_t nSize, size_t nCount, AZ::IO::HandleType fileHandle) + size_t Archive::FRead(void* pData, size_t bytesToRead, AZ::IO::HandleType fileHandle) { AZ_PROFILE_FUNCTION(AzCore); - AZ_PROFILE_SCOPE(Game, "Size: %d Archive: %p", nSize, this); SAutoCollectFileAccessTime accessTime(this); ArchiveInternal::CZipPseudoFile* pseudoFile = GetPseudoFile(fileHandle); if (pseudoFile) { - return pseudoFile->FRead(pData, nSize, nCount, fileHandle); - } - - AZ::u64 bytesRead = 0; - AZ::IO::FileIOBase::GetDirectInstance()->Read(fileHandle, pData, nSize * nCount, false, &bytesRead); - return static_cast(bytesRead / nSize); - } - - ////////////////////////////////////////////////////////////////////////// - size_t Archive::FReadRawAll(void* pData, size_t nFileSize, AZ::IO::HandleType fileHandle) - { - AZ_PROFILE_FUNCTION(AzCore); - - SAutoCollectFileAccessTime accessTime(this); - ArchiveInternal::CZipPseudoFile* pseudoFile = GetPseudoFile(fileHandle); - if (pseudoFile) - { - return pseudoFile->FReadAll(pData, nFileSize, fileHandle); + return pseudoFile->FRead(pData, bytesToRead, fileHandle); } - AZ::IO::FileIOBase::GetDirectInstance()->Seek(fileHandle, 0, AZ::IO::SeekType::SeekFromStart); AZ::u64 bytesRead = 0; - AZ::IO::FileIOBase::GetDirectInstance()->Read(fileHandle, pData, nFileSize, false, &bytesRead); - return static_cast(bytesRead); + AZ::IO::FileIOBase::GetDirectInstance()->Read(fileHandle, pData, bytesToRead, false, &bytesRead); + return bytesRead; } ////////////////////////////////////////////////////////////////////////// @@ -1234,48 +1004,6 @@ namespace AZ::IO } - int Archive::FPrintf(AZ::IO::HandleType fileHandle, const char* szFormat, ...) - { - SAutoCollectFileAccessTime accessTime(this); - ArchiveInternal::CZipPseudoFile* pseudoFile = GetPseudoFile(fileHandle); - if (pseudoFile) - { - return 0; // we don't support it now - } - - va_list arglist; - int rv; - va_start(arglist, szFormat); - rv = static_cast(AZ::IO::PrintV(fileHandle, szFormat, arglist)); - va_end(arglist); - return rv; - } - - char* Archive::FGets(char* str, int n, AZ::IO::HandleType fileHandle) - { - SAutoCollectFileAccessTime accessTime(this); - ArchiveInternal::CZipPseudoFile* pseudoFile = GetPseudoFile(fileHandle); - if (pseudoFile) - { - return pseudoFile->FGets(str, n); - } - - return AZ::IO::FGetS(str, n, fileHandle); - } - - int Archive::Getc(AZ::IO::HandleType fileHandle) - { - SAutoCollectFileAccessTime accessTime(this); - ArchiveInternal::CZipPseudoFile* pseudoFile = GetPseudoFile(fileHandle); - if (pseudoFile) - { - return pseudoFile->Getc(); - } - - return AZ::IO::GetC(fileHandle); - } - - ////////////////////////////////////////////////////////////////////////// AZ::IO::ArchiveFileIterator Archive::FindFirst(AZStd::string_view pDir, EFileSearchType searchType) { @@ -1304,7 +1032,7 @@ namespace AZ::IO break; } - AZStd::intrusive_ptr pFindData = new AZ::IO::FindData(); + AZStd::intrusive_ptr pFindData = aznew AZ::IO::FindData(); pFindData->Scan(this, szFullPath->Native(), bAllowUseFileSystem, bScanZips); return pFindData->Fetch(); @@ -1322,18 +1050,6 @@ namespace AZ::IO return true; } - ////////////////////////////////////////////////////////////////////////// - bool Archive::LoadPakToMemory([[maybe_unused]] AZStd::string_view pName, [[maybe_unused]] IArchive::EInMemoryArchiveLocation nLoadPakToMemory, - [[maybe_unused]] AZStd::intrusive_ptr pMemoryBlock) - { - return true; - } - - ////////////////////////////////////////////////////////////////////////// - void Archive::LoadPaksToMemory([[maybe_unused]] int nMaxArchiveSize, [[maybe_unused]] bool bLoadToMemory) - { - } - auto Archive::GetLevelPackOpenEvent() -> LevelPackOpenEvent* { return &m_levelOpenEvent; @@ -1344,7 +1060,7 @@ namespace AZ::IO return &m_levelCloseEvent; } //====================================================================== - bool Archive::OpenPack(AZStd::string_view szBindRootIn, AZStd::string_view szPath, uint32_t nFlags, + bool Archive::OpenPack(AZStd::string_view szBindRootIn, AZStd::string_view szPath, AZStd::intrusive_ptr pData, AZ::IO::FixedMaxPathString* pFullPath, bool addLevels) { AZ_Assert(!szBindRootIn.empty(), "Bind Root should not be empty"); @@ -1363,7 +1079,7 @@ namespace AZ::IO return false; } - bool result = OpenPackCommon(szBindRoot->Native(), szFullPath->Native(), nFlags, pData, addLevels); + bool result = OpenPackCommon(szBindRoot->Native(), szFullPath->Native(), pData, addLevels); if (pFullPath) { @@ -1373,7 +1089,7 @@ namespace AZ::IO return result; } - bool Archive::OpenPack(AZStd::string_view szPath, uint32_t nFlags, AZStd::intrusive_ptr pData, + bool Archive::OpenPack(AZStd::string_view szPath, AZStd::intrusive_ptr pData, AZ::IO::FixedMaxPathString* pFullPath, bool addLevels) { auto szFullPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(szPath); @@ -1385,7 +1101,7 @@ namespace AZ::IO AZStd::string_view bindRoot = szFullPath->ParentPath().Native(); - bool result = OpenPackCommon(bindRoot, szFullPath->Native(), nFlags, pData, addLevels); + bool result = OpenPackCommon(bindRoot, szFullPath->Native(), pData, addLevels); if (pFullPath) { @@ -1396,34 +1112,22 @@ namespace AZ::IO } - bool Archive::OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view szFullPath, uint32_t nArchiveFlags, + bool Archive::OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view szFullPath, AZStd::intrusive_ptr pData, bool addLevels) { - // Note this will replace @devassets@ with @assets@ to provide a proper bind root for the archives - auto conversionResult = ArchiveInternal::ConvertAbsolutePathToAliasedPath(szBindRoot); - if (!conversionResult) - { - AZ_Error("Archive", false, "Path %.*s cannot be converted to @alias@ form. It is longer than MaxPathLength %zu", - aznumeric_cast(szBindRoot.size()), szBindRoot.data(), AZ::IO::MaxPathLength); - return false; - } - // setup PackDesc before the duplicate test PackDesc desc; - desc.strFileName = szFullPath; + desc.m_strFileName = szFullPath; - if (!conversionResult || conversionResult->empty()) + if (AZ::IO::FixedMaxPath pathBindRoot; !AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, szBindRoot)) { - desc.m_pathBindRoot = "@assets@"; + AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@assets@"); + desc.m_pathBindRoot = pathBindRoot.LexicallyNormal().String(); } else { - // Create a bind root without any trailing slashes - desc.m_pathBindRoot = AZStd::move(*conversionResult); - if (desc.m_pathBindRoot.HasRelativePath() && !desc.m_pathBindRoot.HasFilename()) - { - desc.m_pathBindRoot = desc.m_pathBindRoot.ParentPath(); - } + // Create a bind root + desc.m_pathBindRoot = pathBindRoot.LexicallyNormal().String(); } // hold the lock from the point we query the zip array, @@ -1433,56 +1137,23 @@ namespace AZ::IO // try to find this - maybe the pack has already been opened for (auto it = m_arrZips.begin(); it != m_arrZips.end(); ++it) { - const char* pFilePath = it->pZip->GetFilePath(); - if (pFilePath == desc.strFileName && it->m_pathBindRoot == desc.m_pathBindRoot) + if (AZ::IO::PathView archiveFilePath = it->pZip->GetFilePath(); + archiveFilePath == desc.m_strFileName && it->m_pathBindRoot == desc.m_pathBindRoot) { return true; // already opened } } } - int flags = INestedArchive::FLAGS_OPTIMIZED_READ_ONLY | INestedArchive::FLAGS_ABSOLUTE_PATHS; - if ((nArchiveFlags & FLAGS_PAK_IN_MEMORY) != 0) - { - flags |= INestedArchive::FLAGS_IN_MEMORY; - } - if ((nArchiveFlags & FLAGS_PAK_IN_MEMORY_CPU) != 0) - { - flags |= INestedArchive::FLAGS_IN_MEMORY_CPU; - } - if ((nArchiveFlags & FLAGS_FILENAMES_AS_CRC32) != 0) - { - flags |= INestedArchive::FLAGS_FILENAMES_AS_CRC32; - } - if ((nArchiveFlags & FLAGS_REDIRECT_TO_DISC) != 0) - { - flags |= FLAGS_REDIRECT_TO_DISC; - } - if ((nArchiveFlags & INestedArchive::FLAGS_OVERRIDE_PAK) != 0) - { - flags |= INestedArchive::FLAGS_OVERRIDE_PAK; - } - if ((nArchiveFlags & FLAGS_LEVEL_PAK_INSIDE_PAK) != 0) - { - flags |= INestedArchive::FLAGS_INSIDE_PAK; - } + const int flags = INestedArchive::FLAGS_OPTIMIZED_READ_ONLY | INestedArchive::FLAGS_ABSOLUTE_PATHS; desc.pArchive = OpenArchive(szFullPath, szBindRoot, flags, pData); if (!desc.pArchive) { return false; // couldn't open the archive } - if (m_filesCachedOnHDD.size()) - { - uint32_t crc = AZ::Crc32(szFullPath); - if (m_filesCachedOnHDD.find(crc) != m_filesCachedOnHDD.end()) - { - uint32_t eFlags = desc.pArchive->GetFlags(); - desc.pArchive->SetFlags(eFlags | INestedArchive::FLAGS_ON_HDD); - } - } - AZ_TracePrintf("Archive", "Opening archive file %.*s\n", aznumeric_cast(szFullPath.size()), szFullPath.data()); + AZ_TracePrintf("Archive", "Opening archive file %.*s\n", AZ_STRING_ARG(szFullPath)); desc.pZip = static_cast(desc.pArchive.get())->GetCache(); AZStd::unique_lock lock(m_csZips); @@ -1493,20 +1164,14 @@ namespace AZ::IO // All we have to do is name the archive appropriately to make // sure later archives added to the current set of archives sort higher // and therefore get used instead of lower sorted archives - AZStd::string_view nextBundle; + AZ::IO::PathView nextBundle; ZipArray::reverse_iterator revItZip = m_arrZips.rbegin(); - if ((nArchiveFlags & INestedArchive::FLAGS_OVERRIDE_PAK) == 0) + for (; revItZip != m_arrZips.rend(); ++revItZip) { - for (; revItZip != m_arrZips.rend(); ++revItZip) + nextBundle = revItZip->GetFullPath(); + if (desc.GetFullPath() > revItZip->GetFullPath()) { - if ((revItZip->pArchive->GetFlags() & INestedArchive::FLAGS_OVERRIDE_PAK) == 0) - { - nextBundle = revItZip->GetFullPath(); - if (azstricmp(desc.GetFullPath(), revItZip->GetFullPath()) > 0) - { - break; - } - } + break; } } @@ -1555,17 +1220,17 @@ namespace AZ::IO } AZ::IO::ArchiveNotificationBus::Broadcast([](AZ::IO::ArchiveNotifications* archiveNotifications, const char* bundleName, - AZStd::shared_ptr bundleManifest, const char* nextBundle, AZStd::shared_ptr bundleCatalog) + AZStd::shared_ptr bundleManifest, const AZ::IO::FixedMaxPath& nextBundle, AZStd::shared_ptr bundleCatalog) { - archiveNotifications->BundleOpened(bundleName, bundleManifest, nextBundle, bundleCatalog); - }, desc.strFileName.c_str(), bundleManifest, nextBundle.data(), bundleCatalog); + archiveNotifications->BundleOpened(bundleName, bundleManifest, nextBundle.c_str(), bundleCatalog); + }, desc.m_strFileName.c_str(), bundleManifest, nextBundle, bundleCatalog); return true; } // after this call, the file will be unlocked and closed, and its contents won't be used to search for files - bool Archive::ClosePack(AZStd::string_view pName, [[maybe_unused]] uint32_t nFlags) + bool Archive::ClosePack(AZStd::string_view pName) { auto szZipPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pName); if (!szZipPath) @@ -1581,16 +1246,16 @@ namespace AZ::IO AZStd::unique_lock lock(m_csZips); for (auto it = m_arrZips.begin(); it != m_arrZips.end();) { - if (azstricmp(szZipPath->c_str(), it->GetFullPath()) == 0) + if (szZipPath == it->GetFullPath()) { // this is the pack with the given name - remove it, and if possible it will be deleted // the zip is referenced from the archive and *it; the archive is referenced only from *it // // the pZip (cache) can be referenced from stream engine and pseudo-files. // the archive can be referenced from outside - AZ::IO::ArchiveNotificationBus::Broadcast([](AZ::IO::ArchiveNotifications* archiveNotifications, const char* bundleName) + AZ::IO::ArchiveNotificationBus::Broadcast([](AZ::IO::ArchiveNotifications* archiveNotifications, const AZ::IO::FixedMaxPath& bundleName) { - archiveNotifications->BundleClosed(bundleName); + archiveNotifications->BundleClosed(bundleName.c_str()); }, it->GetFullPath()); if (usePrefabSystemForLevels) @@ -1643,7 +1308,7 @@ namespace AZ::IO return foundMatchingPackFile; } - bool Archive::OpenPacks(AZStd::string_view pWildcardIn, uint32_t nFlags, AZStd::vector* pFullPaths) + bool Archive::OpenPacks(AZStd::string_view pWildcardIn, AZStd::vector* pFullPaths) { auto strBindRoot{ AZ::IO::PathView(pWildcardIn).ParentPath() }; AZ::IO::FixedMaxPath bindRoot; @@ -1651,10 +1316,10 @@ namespace AZ::IO { bindRoot = strBindRoot; } - return OpenPacksCommon(bindRoot.Native(), pWildcardIn, nFlags, pFullPaths); + return OpenPacksCommon(bindRoot.Native(), pWildcardIn, pFullPaths); } - bool Archive::OpenPacks(AZStd::string_view szBindRoot, AZStd::string_view pWildcardIn, uint32_t nFlags, AZStd::vector* pFullPaths) + bool Archive::OpenPacks(AZStd::string_view szBindRoot, AZStd::string_view pWildcardIn, AZStd::vector* pFullPaths) { auto bindRoot = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(szBindRoot); if (!bindRoot) @@ -1662,16 +1327,16 @@ namespace AZ::IO AZ_Assert(false, "Unable to resolve path for filepath %.*s", aznumeric_cast(szBindRoot.size()), szBindRoot.data()); return false; } - return OpenPacksCommon(bindRoot->Native(), pWildcardIn, nFlags, pFullPaths); + return OpenPacksCommon(bindRoot->Native(), pWildcardIn, pFullPaths); } - bool Archive::OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, uint32_t nArchiveFlags, AZStd::vector* pFullPaths, bool addLevels) + bool Archive::OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, AZStd::vector* pFullPaths, bool addLevels) { constexpr AZStd::string_view wildcards{ "*?" }; if (wildcards.find_first_of(pWildcardIn) == AZStd::string_view::npos) { // No wildcards, just open pack - if (OpenPackCommon(szDir, pWildcardIn, nArchiveFlags, nullptr, addLevels)) + if (OpenPackCommon(szDir, pWildcardIn, nullptr, addLevels)) { if (pFullPaths) { @@ -1683,25 +1348,24 @@ namespace AZ::IO if (AZ::IO::ArchiveFileIterator fileIterator = FindFirst(pWildcardIn, IArchive::eFileSearchType_AllowOnDiskOnly); fileIterator) { - AZStd::vector files; + AZStd::vector files; do { - AZStd::string foundFilename{ fileIterator.m_filename }; - AZStd::to_lower(foundFilename.begin(), foundFilename.end()); - files.emplace_back(AZStd::move(foundFilename)); + auto& foundFilename = files.emplace_back(fileIterator.m_filename); + AZStd::to_lower(foundFilename.Native().begin(), foundFilename.Native().end()); } while (fileIterator = FindNext(fileIterator)); - // Open files in alphabet order. + // Open files in alphabetical order. AZStd::sort(files.begin(), files.end()); bool bAllOk = true; - for (const AZStd::string& file : files) + for (const AZ::IO::FixedMaxPath& file : files) { - bAllOk = OpenPackCommon(szDir, file, nArchiveFlags, nullptr, addLevels) && bAllOk; + bAllOk = OpenPackCommon(szDir, file.Native(), nullptr, addLevels) && bAllOk; if (pFullPaths) { - pFullPaths->emplace_back(file.begin(), file.end()); + pFullPaths->emplace_back(AZStd::move(file.Native())); } } @@ -1713,7 +1377,7 @@ namespace AZ::IO } - bool Archive::ClosePacks(AZStd::string_view pWildcardIn, uint32_t nFlags) + bool Archive::ClosePacks(AZStd::string_view pWildcardIn) { auto path = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pWildcardIn); if (!path) @@ -1723,26 +1387,13 @@ namespace AZ::IO } return AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(AZ::IO::FixedMaxPath(path->ParentPath()).c_str(), - AZ::IO::FixedMaxPath(path->Filename()).c_str(), [&](const char* filePath) -> bool + AZ::IO::FixedMaxPath(path->Filename()).c_str(), [this](const char* filePath) -> bool { - ClosePack(filePath, nFlags); + ClosePack(filePath); return true; }); } - - ///////////////////////////////////////////////////// - bool Archive::Init([[maybe_unused]] AZStd::string_view szBasePath) - { - BusConnect(); - return true; - } - - void Archive::Release() - { - BusDisconnect(); - } - ////////////////////////////////////////////////////////////////////////// ArchiveInternal::CZipPseudoFile* Archive::GetPseudoFile(AZ::IO::HandleType fileHandle) const { @@ -1912,36 +1563,6 @@ namespace AZ::IO return m_pFileEntry->nFileDataOffset; } - bool Archive::MakeDir(AZStd::string_view szPathIn) - { - AZ::IO::StackString pathStr{ szPathIn }; - // Determine if there is a period ('.') after the last slash to determine if the path contains a file. - // This used to be a strchr on the whole path which could contain a period in a path, such as network domain paths (domain.user). - size_t findDotFromPos = pathStr.rfind(AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (findDotFromPos == AZ::IO::StackString::npos) - { - findDotFromPos = pathStr.rfind(AZ_WRONG_FILESYSTEM_SEPARATOR); - if (findDotFromPos == AZ::IO::StackString::npos) - { - findDotFromPos = 0; - } - } - size_t dotPos = pathStr.find('.', findDotFromPos); - if (dotPos != AZ::IO::StackString::npos) - { - AZStd::string fullPath; - AZ::StringFunc::Path::GetFullPath(pathStr.c_str(), fullPath); - pathStr = fullPath; - } - - if (pathStr.empty()) - { - return true; - } - - return AZ::IO::FileIOBase::GetDirectInstance()->CreatePath(pathStr.c_str()); - } - ////////////////////////////////////////////////////////////////////////// // open the physical archive file - creates if it doesn't exist // returns nullptr if it's invalid or can't open the file @@ -1962,15 +1583,6 @@ namespace AZ::IO uint32_t nFactoryFlags = 0; - if (nFlags & INestedArchive::FLAGS_IN_MEMORY) - { - nFactoryFlags |= ZipDir::CacheFactory::FLAGS_IN_MEMORY; - } - - if (nFlags & INestedArchive::FLAGS_IN_MEMORY_CPU) - { - nFactoryFlags |= ZipDir::CacheFactory::FLAGS_IN_MEMORY_CPU; - } if (nFlags & INestedArchive::FLAGS_DONT_COMPACT) { @@ -1982,10 +1594,6 @@ namespace AZ::IO nFactoryFlags |= ZipDir::CacheFactory::FLAGS_READ_ONLY; } - if (nFlags & INestedArchive::FLAGS_INSIDE_PAK) - { - nFactoryFlags |= ZipDir::CacheFactory::FLAGS_READ_INSIDE_PAK; - } INestedArchive* pArchive = FindArchive(szFullPath->Native()); if (pArchive) @@ -2016,7 +1624,10 @@ namespace AZ::IO if (!pakOnDisk && (nFactoryFlags & ZipDir::CacheFactory::FLAGS_READ_ONLY)) { // Archive file not found. - AZ_TracePrintf("Archive", "Archive file %s does not exist\n", szFullPath->c_str()); + if (az_archive_verbosity) + { + AZ_TracePrintf("Archive", "Archive file %s does not exist\n", szFullPath->c_str()); + } return nullptr; } @@ -2031,148 +1642,6 @@ namespace AZ::IO return nullptr; } - uint32_t Archive::ComputeCRC(AZStd::string_view szPath, [[maybe_unused]] uint32_t nFileOpenFlags) - { - AZ_Assert(!szPath.empty(), "Path to compute Crc cannot be empty"); - - AZ::Crc32 dwCRC = 0; - - // generate crc32 - { - // avoid heap allocation by working in 8k chunks - const uint32_t dwChunkSize = 1024 * 8; - - // note that the actual CRC algorithm can work on various sized words but operates on individual words - // so there's little difference between feeding it 8k and 8mb, except you might save yourself some io calls. - - uint8_t pMem[dwChunkSize]; - - - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - if (!fileIO) - { - return ZipDir::ZD_ERROR_INVALID_CALL; - } - - AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; - - if (AZ::IO::PathString filepath{ szPath }; !fileIO->Open(filepath.c_str(), AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, fileHandle)) - { - return ZipDir::ZD_ERROR_INVALID_PATH; - } - // load whole file in chunks and compute CRC - while (true) - { - AZ::u64 bytesRead = 0; - fileIO->Read(fileHandle, pMem, dwChunkSize, false, &bytesRead); // read up to ChunkSize bytes and put the actual number of bytes read into bytesRead. - - if (bytesRead) - { - dwCRC.Add(pMem, aznumeric_caster(bytesRead)); - } - else - { - break; - } - } - - FClose(fileHandle); - } - - return dwCRC; - } - - bool Archive::ComputeMD5(AZStd::string_view szPath, uint8_t* md5, uint32_t nFileOpenFlags, bool useDirectFileAccess) - { - if (szPath.empty() || !md5) - { - return false; - } - - MD5Context context; - MD5Init(&context); - - // generate checksum - { - const AZ::u64 dwChunkSize = 1024 * 1024; // 1MB chunks - AZStd::unique_ptr pMem{ reinterpret_cast(AZ::AllocatorInstance::Get().Allocate(dwChunkSize, alignof(uint8_t))), - [](uint8_t* ptr) { AZ::AllocatorInstance::Get().DeAllocate(ptr); } - }; - - if (!pMem) - { - return false; - } - - AZ::u64 dwSize = 0; - - AZ::IO::PathString filepath{ szPath }; - if (useDirectFileAccess) - { - - AZ::IO::FileIOBase::GetDirectInstance()->Size(filepath.c_str(), dwSize); - } - else - { - AZ::IO::HandleType fileHandle = FOpen(filepath, "rb", nFileOpenFlags); - - if (fileHandle != AZ::IO::InvalidHandle) - { - dwSize = FGetSize(fileHandle); - FClose(fileHandle); - } - } - - // rbx open flags, x is a hint to not cache whole file in memory. - AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; - if (useDirectFileAccess) - { - AZ::IO::FileIOBase::GetDirectInstance()->Open(filepath.c_str(), AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, fileHandle); - } - else - { - fileHandle = FOpen(filepath, "rbx", nFileOpenFlags); - } - - if (fileHandle == AZ::IO::InvalidHandle) - { - return false; - } - - // load whole file in chunks and compute Md5 - while (dwSize > 0) - { - uint64_t dwLocalSize = AZStd::min(dwSize, dwChunkSize); - - AZ::u64 read{ 0 }; - if (useDirectFileAccess) - { - AZ::IO::FileIOBase::GetDirectInstance()->Read(fileHandle, pMem.get(), dwLocalSize, false, &read); - } - else - { - read = FReadRaw(pMem.get(), 1, dwLocalSize, fileHandle); - } - AZ_Assert(read == dwLocalSize, "Failed to read dwLocalSize %" PRIu32 " bytes from file", dwLocalSize); - - MD5Update(&context, pMem.get(), aznumeric_cast(dwLocalSize)); - dwSize -= dwLocalSize; - } - - if (useDirectFileAccess) - { - AZ::IO::FileIOBase::GetDirectInstance()->Close(fileHandle); - } - else - { - FClose(fileHandle); - } - } - - MD5Final(md5, &context); - return true; - } - void Archive::Register(INestedArchive* pArchive) { AZStd::unique_lock lock(m_archiveMutex); @@ -2185,7 +1654,7 @@ namespace AZ::IO AZStd::unique_lock lock(m_archiveMutex); if (pArchive) { - AZ_TracePrintf("Archive", "Closing Archive file: %s\n", pArchive->GetFullPath()); + AZ_TracePrintf("Archive", "Closing Archive file: %.*s\n", AZ_STRING_ARG(pArchive->GetFullPath().Native())); } ArchiveArray::iterator it; if (m_arrArchives.size() < 16) @@ -2212,7 +1681,7 @@ namespace AZ::IO { AZStd::shared_lock lock(m_archiveMutex); auto it = AZStd::lower_bound(m_arrArchives.begin(), m_arrArchives.end(), szFullPath, NestedArchiveSortByName()); - if (it != m_arrArchives.end() && !azstrnicmp(szFullPath.data(), (*it)->GetFullPath(), szFullPath.size())) + if (it != m_arrArchives.end() && szFullPath == (*it)->GetFullPath()) { return *it; } @@ -2280,7 +1749,7 @@ namespace AZ::IO case RFOM_Disabled: default: - AZ_Assert(false, "File record option %d", aznumeric_cast(eList));; + AZ_Assert(false, "File record option %d", aznumeric_cast(eList)); } return nullptr; } @@ -2325,11 +1794,14 @@ namespace AZ::IO if (m_eRecordFileOpenList != IArchive::RFOM_Disabled) { // we only want to record ASSET access - // assets are identified as things which start with no alias, or with the @assets@ alias - auto assetPath = AZ::IO::FileIOBase::GetInstance()->ConvertToAlias(szFilename); - if (assetPath && (assetPath->Native().starts_with("@assets@") - || assetPath->Native().starts_with("@root@") - || assetPath->Native().starts_with("@projectplatformcache@"))) + // assets are identified as files that are relative to the resolved @assets@ alias path + auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); + const char* aliasValue = fileIoBase->GetAlias("@assets@"); + + if (AZ::IO::FixedMaxPath resolvedFilePath; + fileIoBase->ResolvePath(resolvedFilePath, szFilename) + && aliasValue != nullptr + && resolvedFilePath.IsRelativeTo(aliasValue)) { IResourceList* pList = GetResourceList(m_eRecordFileOpenList); @@ -2360,13 +1832,8 @@ namespace AZ::IO bool prev = false; if (threadId == m_mainThreadId) { - prev = m_disableRuntimeFileAccess[0]; - m_disableRuntimeFileAccess[0] = status; - } - else if (threadId == m_renderThreadId) - { - prev = m_disableRuntimeFileAccess[1]; - m_disableRuntimeFileAccess[1] = status; + prev = m_disableRuntimeFileAccess; + m_disableRuntimeFileAccess = status; } return prev; } @@ -2440,16 +1907,6 @@ namespace AZ::IO return AZ::AllocatorInstance::Get().DeAllocate(p); } - void Archive::Lock() - { - m_csMain.lock(); - } - - void Archive::Unlock() - { - m_csMain.unlock(); - } - // gets the current archive priority ArchiveLocationPriority Archive::GetPakPriority() const { @@ -2519,7 +1976,7 @@ namespace AZ::IO { found = true; - info.m_archiveFilename.InitFromRelativePath(archive->GetFilePath()); + info.m_archiveFilename.InitFromRelativePath(archive->GetFilePath().Native()); info.m_offset = pFileData->GetFileDataOffset(); info.m_compressedSize = entry->desc.lSizeCompressed; info.m_uncompressedSize = entry->desc.lSizeUncompressed; @@ -2561,7 +2018,7 @@ namespace AZ::IO ZipDir::CachePtr pZip; uint32_t nArchiveFlags; - ZipDir::FileEntry* pFileEntry = FindPakFileEntry(szFullPath->Native(), nArchiveFlags, &pZip, false); + ZipDir::FileEntry* pFileEntry = FindPakFileEntry(szFullPath->Native(), nArchiveFlags, &pZip); if (!pFileEntry) { return 0; @@ -2589,7 +2046,7 @@ namespace AZ::IO return static_cast(StreamMediaType::TypeHDD); } - bool Archive::SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard, uint32_t nFlags) + bool Archive::SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard) { auto filePath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pWildcard); if (!filePath) @@ -2601,24 +2058,24 @@ namespace AZ::IO return AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(AZ::IO::FixedMaxPath(filePath->ParentPath()).c_str(), AZ::IO::FixedMaxPath(filePath->Filename()).c_str(), [&](const char* filePath) -> bool { - SetPackAccessible(bAccessible, filePath, nFlags); + SetPackAccessible(bAccessible, filePath); return true; }); } - bool Archive::SetPackAccessible(bool bAccessible, AZStd::string_view pName, [[maybe_unused]] uint32_t nFlags) + bool Archive::SetPackAccessible(bool bAccessible, AZStd::string_view pName) { auto szZipPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pName); if (!szZipPath) { - AZ_Assert(false, "Unable to resolve path for filepath %.*s", aznumeric_cast(pName.size()), pName.data()); + AZ_Assert(false, "Unable to resolve path for filepath %.*s", AZ_STRING_ARG(pName)); return false; } AZStd::unique_lock lock(m_csZips); for (auto it = m_arrZips.begin(); it != m_arrZips.end(); ++it) { - if (!azstricmp(szZipPath->c_str(), it->GetFullPath())) + if (szZipPath == it->GetFullPath()) { return it->pArchive->SetPackAccessible(bAccessible); } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.h b/Code/Framework/AzFramework/AzFramework/Archive/Archive.h index ec964f7fa3..f08d90a66e 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include @@ -115,12 +115,12 @@ namespace AZ::IO struct PackDesc { AZ::IO::Path m_pathBindRoot; // the zip binding root - AZStd::string strFileName; // the zip file name (with path) - very useful for debugging so please don't remove + AZ::IO::Path m_strFileName; // the zip file name (with path) - very useful for debugging so please don't remove // [LYN-2376] Remove once legacy slice support is removed bool m_containsLevelPak = false; // indicates whether this archive has level.pak inside it or not - const char* GetFullPath() const { return pZip->GetFilePath(); } + AZ::IO::PathView GetFullPath() const { return pZip->GetFilePath(); } AZStd::intrusive_ptr pArchive; ZipDir::CachePtr pZip; @@ -129,10 +129,7 @@ namespace AZ::IO // ArchiveFindDataSet entire purpose is to keep a reference to the intrusive_ptr of ArchiveFindData // so that it doesn't go out of scope - using ArchiveFindDataSet = AZStd::set, AZ::OSStdAllocator>; - - // given the source relative path, constructs the full path to the file according to the flags - const char* AdjustFileName(AZStd::string_view src, char* dst, size_t dstSize, uint32_t nFlags, bool skipMods = false) override; + using ArchiveFindDataSet = AZStd::set>; /** @@ -154,29 +151,17 @@ namespace AZ::IO //! CompressionBus Handler implementation. void FindCompressionInfo(bool& found, AZ::IO::CompressionInfo& info, const AZStd::string_view filename) override; - //! Processes an alias command line containing multiple aliases. - void ParseAliases(AZStd::string_view szCommandLine) override; - //! adds or removes an alias from the list - if bAdd set to false will remove it - void SetAlias(AZStd::string_view szName, AZStd::string_view szAlias, bool bAdd) override; - //! gets an alias from the list, if any exist. - //! if bReturnSame==true, it will return the input name if an alias doesn't exist. Otherwise returns nullptr - const char* GetAlias(AZStd::string_view szName, bool bReturnSame = true) override; - // Set the localization folder void SetLocalizationFolder(AZStd::string_view sLocalizationFolder) override; const char* GetLocalizationFolder() const override { return m_sLocalizationFolder.c_str(); } const char* GetLocalizationRoot() const override { return m_sLocalizationRoot.c_str(); } - // lock all the operations - void Lock() override; - void Unlock() override; - // open the physical archive file - creates if it doesn't exist // returns nullptr if it's invalid or can't open the file - AZStd::intrusive_ptr OpenArchive(AZStd::string_view szPath, AZStd::string_view bindRoot = {}, uint32_t nFlags = 0, AZStd::intrusive_ptr pData = nullptr) override; + AZStd::intrusive_ptr OpenArchive(AZStd::string_view szPath, AZStd::string_view bindRoot = {}, uint32_t nArchiveFlags = 0, AZStd::intrusive_ptr pData = nullptr) override; // returns the path to the archive in which the file was opened - const char* GetFileArchivePath(AZ::IO::HandleType fileHandle) override; + AZ::IO::PathView GetFileArchivePath(AZ::IO::HandleType fileHandle) override; ////////////////////////////////////////////////////////////////////////// @@ -192,40 +177,31 @@ namespace AZ::IO void RegisterFileAccessSink(IArchiveFileAccessSink* pSink) override; void UnregisterFileAccessSink(IArchiveFileAccessSink* pSink) override; - bool Init(AZStd::string_view szBasePath) override; - void Release() override; - - bool IsInstalledToHDD(AZStd::string_view acFilePath = 0) const override; - // [LYN-2376] Remove 'addLevels' parameter once legacy slice support is removed - bool OpenPack(AZStd::string_view pName, uint32_t nFlags = 0, AZStd::intrusive_ptr pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override; - bool OpenPack(AZStd::string_view szBindRoot, AZStd::string_view pName, uint32_t nFlags = 0, AZStd::intrusive_ptr pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override; + bool OpenPack(AZStd::string_view pName, AZStd::intrusive_ptr pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override; + bool OpenPack(AZStd::string_view szBindRoot, AZStd::string_view pName, AZStd::intrusive_ptr pData = nullptr, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) override; // after this call, the file will be unlocked and closed, and its contents won't be used to search for files - bool ClosePack(AZStd::string_view pName, uint32_t nFlags = 0) override; - bool OpenPacks(AZStd::string_view pWildcard, uint32_t nFlags = 0, AZStd::vector* pFullPaths = nullptr) override; - bool OpenPacks(AZStd::string_view szBindRoot, AZStd::string_view pWildcard, uint32_t nFlags = 0, AZStd::vector* pFullPaths = nullptr) override; + bool ClosePack(AZStd::string_view pName) override; + bool OpenPacks(AZStd::string_view pWildcard, AZStd::vector* pFullPaths = nullptr) override; + bool OpenPacks(AZStd::string_view szBindRoot, AZStd::string_view pWildcard, AZStd::vector* pFullPaths = nullptr) override; // closes pack files by the path and wildcard - bool ClosePacks(AZStd::string_view pWildcard, uint32_t nFlags = 0) override; + bool ClosePacks(AZStd::string_view pWildcard) override; //returns if a archive exists matching the wildcard bool FindPacks(AZStd::string_view pWildcardIn) override; // prevent access to specific archive files - bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard, uint32_t nFlags = 0) override; - bool SetPackAccessible(bool bAccessible, AZStd::string_view pName, uint32_t nFlags = 0) override; + bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard) override; + bool SetPackAccessible(bool bAccessible, AZStd::string_view pName) override; // returns the file modification time uint64_t GetModificationTime(AZ::IO::HandleType fileHandle) override; - bool LoadPakToMemory(AZStd::string_view pName, EInMemoryArchiveLocation nLoadArchiveToMemory, AZStd::intrusive_ptr pMemoryBlock = nullptr) override; - void LoadPaksToMemory(int nMaxArchiveSize, bool bLoadToMemory) override; - - AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode, uint32_t nPathFlags = 0) override; - size_t FReadRaw(void* data, size_t length, size_t elems, AZ::IO::HandleType handle) override; - size_t FReadRawAll(void* data, size_t nFileSize, AZ::IO::HandleType handle) override; + AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode) override; + size_t FRead(void* data, size_t bytesToRead, AZ::IO::HandleType handle) override; void* FGetCachedFileData(AZ::IO::HandleType handle, size_t& nFileSize) override; - size_t FWrite(const void* data, size_t length, size_t elems, AZ::IO::HandleType handle) override; + size_t FWrite(const void* data, size_t bytesToWrite, AZ::IO::HandleType handle) override; size_t FSeek(AZ::IO::HandleType handle, uint64_t seek, int mode) override; uint64_t FTell(AZ::IO::HandleType handle) override; int FFlush(AZ::IO::HandleType handle) override; @@ -234,9 +210,7 @@ namespace AZ::IO AZ::IO::ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator fileIterator) override; bool FindClose(AZ::IO::ArchiveFileIterator fileIterator) override; int FEof(AZ::IO::HandleType handle) override; - char* FGets(char*, int, AZ::IO::HandleType) override; - int Getc(AZ::IO::HandleType) override; - int FPrintf(AZ::IO::HandleType handle, const char* format, ...) override; + size_t FGetSize(AZ::IO::HandleType fileHandle) override; size_t FGetSize(AZStd::string_view sFilename, bool bAllowUseFileSystem = false) override; bool IsInPak(AZ::IO::HandleType handle) override; @@ -248,9 +222,6 @@ namespace AZ::IO bool IsFolder(AZStd::string_view sPath) override; IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) override; - // creates a directory - bool MakeDir(AZStd::string_view szPath) override; - // compresses the raw data into raw data. The buffer for compressed data itself with the heap passed. Uses method 8 (deflate) // returns one of the Z_* errors (Z_OK upon success) // MT-safe @@ -275,22 +246,12 @@ namespace AZ::IO IResourceList* GetResourceList(ERecordFileOpenList eList) override; void SetResourceList(ERecordFileOpenList eList, IResourceList* pResourceList) override; - uint32_t ComputeCRC(AZStd::string_view szPath, uint32_t nFileOpenFlags = 0) override; - bool ComputeMD5(AZStd::string_view szPath, uint8_t* md5, uint32_t nFileOpenFlags = 0, bool useDirectFileAccess = false) override; - void DisableRuntimeFileAccess(bool status) override { - m_disableRuntimeFileAccess[0] = status; - m_disableRuntimeFileAccess[1] = status; + m_disableRuntimeFileAccess = status; } bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) override; - bool CheckFileAccessDisabled(AZStd::string_view name, const char* mode) override; - - void SetRenderThreadId(AZStd::thread_id renderThreadId) override - { - m_renderThreadId = renderThreadId; - } // gets the current archive priority ArchiveLocationPriority GetPakPriority() const override; @@ -307,11 +268,11 @@ namespace AZ::IO // Return cached file data for entries inside archive file. CCachedFileDataPtr GetOpenedFileDataInZip(AZ::IO::HandleType file); ZipDir::FileEntry* FindPakFileEntry(AZStd::string_view szPath, uint32_t& nArchiveFlags, - ZipDir::CachePtr* pZip = {}, bool bSkipInMemoryArchives = {}) const; + ZipDir::CachePtr* pZip = {}) const; private: - bool OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view pName, uint32_t nArchiveFlags, AZStd::intrusive_ptr pData = nullptr, bool addLevels = true); - bool OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, uint32_t nArchiveFlags, AZStd::vector* pFullPaths = nullptr, bool addLevels = true); + bool OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view pName, AZStd::intrusive_ptr pData = nullptr, bool addLevels = true); + bool OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, AZStd::vector* pFullPaths = nullptr, bool addLevels = true); ZipDir::FileEntry* FindPakFileEntry(AZStd::string_view szPath) const; @@ -346,9 +307,6 @@ namespace AZ::IO AZStd::mutex m_cachedFileRawDataMutex; // For m_pCachedFileRawDataSet using RawDataCacheLockGuard = AZStd::scoped_lock; - // The F* emulation functions critical section: protects all F* functions - // that don't have a chance to be called recursively (to avoid deadlocks) - AZStd::mutex m_csMain; mutable AZStd::shared_mutex m_archiveMutex; ArchiveArray m_arrArchives; @@ -360,8 +318,6 @@ namespace AZ::IO ////////////////////////////////////////////////////////////////////////// IArchive::ERecordFileOpenList m_eRecordFileOpenList = RFOM_Disabled; - using RecordedFilesSet = AZStd::set; - RecordedFilesSet m_recordedFilesSet; AZStd::intrusive_ptr m_pEngineStartupResourceList; @@ -372,28 +328,16 @@ namespace AZ::IO float m_fFileAccessTime{}; // Time used to perform file operations AZStd::vector m_FileAccessSinks; // useful for gathering file access statistics - bool m_disableRuntimeFileAccess[2]{}; + bool m_disableRuntimeFileAccess{}; //threads which we don't want to access files from during the game AZStd::thread_id m_mainThreadId{}; - AZStd::thread_id m_renderThreadId{}; AZStd::fixed_string<128> m_sLocalizationFolder; AZStd::fixed_string<128> m_sLocalizationRoot; - AZStd::set, AZ::OSStdAllocator> m_filesCachedOnHDD; - // [LYN-2376] Remove once legacy slice support is removed LevelPackOpenEvent m_levelOpenEvent; LevelPackCloseEvent m_levelCloseEvent; }; } - -namespace AZ::IO::ArchiveInternal -{ - // Utility function to de-alias archive file opening and file-within-archive opening - // if the file specified was an absolute path but it points at one of the aliases, de-alias it and replace it with that alias. - // this works around problems where the level editor is in control but still mounts asset packs (ie, level.pak mounted as @assets@) - AZStd::optional ConvertAbsolutePathToAliasedPath(AZStd::string_view sourcePath, - AZStd::string_view aliasToLookFor = "@devassets@", AZStd::string_view aliasToReplaceWith = "@assets@"); -} diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.cpp index 55f7640785..85ce0b6f9a 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.cpp @@ -5,10 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include +#include #include #include // for function<> in the find files callback. -#include #include #include @@ -188,7 +187,7 @@ namespace AZ::IO return IO::ResultCode::Error; } - size_t result = m_archive->FReadRaw(buffer, 1, size, fileHandle); + size_t result = m_archive->FRead(buffer, size, fileHandle); if (bytesRead) { *bytesRead = static_cast(result); @@ -213,7 +212,7 @@ namespace AZ::IO return IO::ResultCode::Error; } - size_t result = m_archive->FWrite(buffer, 1, size, fileHandle); + size_t result = m_archive->FWrite(buffer, size, fileHandle); if (bytesWritten) { *bytesWritten = static_cast(result); @@ -357,14 +356,8 @@ namespace AZ::IO return IO::ResultCode::Error; } - // avoid using AZStd::string if possible - use OSString instead of StringFunc - AZ::OSString destPath(destinationFilePath); + IO::Path destPath(IO::PathView(destinationFilePath).ParentPath()); - AZ::OSString::size_type pos = destPath.find_last_of(AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); - if (pos != AZ::OSString::npos) - { - destPath.resize(pos); - } CreatePath(destPath.c_str()); if (!Open(destinationFilePath, IO::OpenMode::ModeWrite | IO::OpenMode::ModeBinary, destinationFile)) @@ -466,31 +459,25 @@ namespace AZ::IO return IO::ResultCode::Error; } - AZStd::fixed_string total = filePath; + AZ::IO::FixedMaxPath total = filePath; if (total.empty()) { return IO::ResultCode::Error; } - if (!total.ends_with(AZ_CORRECT_FILESYSTEM_SEPARATOR) && !total.ends_with(AZ_WRONG_FILESYSTEM_SEPARATOR)) - { - total.append(AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); - } - - total.append(filter); + total /= filter; AZ::IO::ArchiveFileIterator fileIterator = m_archive->FindFirst(total.c_str()); if (!fileIterator) { return IO::ResultCode::Success; // its not an actual fatal error to not find anything. } - for (;fileIterator; fileIterator = m_archive->FindNext(fileIterator)) + for (; fileIterator; fileIterator = m_archive->FindNext(fileIterator)) { - total = AZStd::fixed_string::format("%s/%.*s", filePath, aznumeric_cast(fileIterator.m_filename.size()), fileIterator.m_filename.data()); - AZStd::optional resolvedAliasLength = ConvertToAlias(total.data(), total.capacity()); - if (resolvedAliasLength) + total = filePath; + total /= fileIterator.m_filename; + if (ConvertToAlias(total, total)) { - total.resize_no_construct(*resolvedAliasLength); if (!callback(total.c_str())) { break; @@ -510,8 +497,13 @@ namespace AZ::IO const auto fileIt = m_trackedFiles.find(fileHandle); if (fileIt != m_trackedFiles.end()) { - AZ_Assert(filenameSize >= fileIt->second.length(), "Filename size %" PRIu64 " is larger than the size of the tracked file %s:%zu", fileIt->second.c_str(), fileIt->second.size()); - azstrncpy(filename, filenameSize, fileIt->second.c_str(), fileIt->second.length()); + const AZStd::string_view trackedFileView = fileIt->second.Native(); + if (filenameSize <= trackedFileView.size()) + { + return false; + } + size_t trackedFileViewLength = trackedFileView.copy(filename, trackedFileView.size()); + filename[trackedFileViewLength] = '\0'; return true; } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h index c99fbb14c5..21cef18a7a 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFileIO.h @@ -13,7 +13,6 @@ #include #include #include -#include namespace AZ::IO @@ -78,7 +77,7 @@ namespace AZ::IO protected: // we keep a list of file names ever opened so that we can easily return it. mutable AZStd::recursive_mutex m_operationGuard; - AZStd::unordered_map, AZStd::equal_to, AZ::OSStdAllocator> m_trackedFiles; + AZStd::unordered_map m_trackedFiles; AZStd::fixed_vector m_copyBuffer; IArchive* m_archive; }; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp index c4c845a832..d7a92efbf6 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.cpp @@ -15,34 +15,6 @@ namespace AZ::IO { - size_t ArchiveFileIteratorHash::operator()(const AZ::IO::ArchiveFileIterator& iter) const - { - return iter.GetHash(); - } - - bool AZStdStringLessCaseInsensitive::operator()(AZStd::string_view left, AZStd::string_view right) const - { - // If one or both strings are 0-length, return true if the left side is smaller, false if they're equal or left is larger. - size_t compareLength = (AZStd::min)(left.size(), right.size()); - if (compareLength == 0) - { - return left.size() < right.size(); - } - - // They're both non-zero, so compare the strings up until the length of the shorter string. - int compareResult = azstrnicmp(left.data(), right.data(), compareLength); - - // If both strings are equal for the number of characters compared, return true if the left side is shorter, false if - // they're equal or left is longer. - if (compareResult == 0) - { - return left.size() < right.size(); - } - - // Return true if the left side should come first alphabetically, false if the right side should. - return compareResult < 0; - } - FileDesc::FileDesc(Attribute fileAttribute, uint64_t fileSize, time_t accessTime, time_t creationTime, time_t writeTime) : nAttrib{ fileAttribute } , nSize{ fileSize } @@ -52,10 +24,9 @@ namespace AZ::IO { } - ArchiveFileIterator::ArchiveFileIterator(FindData* findData, AZStd::string_view filename, const FileDesc& fileDesc) + // ArchiveFileIterator + ArchiveFileIterator::ArchiveFileIterator(FindData* findData) : m_findData{ findData } - , m_filename{ filename } - , m_fileDesc{ fileDesc } { } @@ -73,21 +44,36 @@ namespace AZ::IO return operator++(); } - bool ArchiveFileIterator::operator==(const AZ::IO::ArchiveFileIterator& rhs) const - { - return GetHash() == rhs.GetHash(); - } ArchiveFileIterator::operator bool() const { return m_findData && m_lastFetchValid; } - size_t ArchiveFileIterator::GetHash() const + // FindData::ArchiveFile + FindData::ArchiveFile::ArchiveFile() = default; + FindData::ArchiveFile::ArchiveFile(AZStd::string_view filename, const FileDesc& fileDesc) + : m_filename(filename) + , m_fileDesc(fileDesc) + { + } + size_t FindData::ArchiveFile::GetHash() const { return AZStd::hash{}(m_filename.c_str()); } + bool FindData::ArchiveFile::operator==(const ArchiveFile& rhs) const + { + return GetHash() == rhs.GetHash(); + } + + // FindData::ArchiveFilehash + size_t FindData::ArchiveFileHash::operator()(const ArchiveFile& archiveFile) const + { + return archiveFile.GetHash(); + } + + // FindData void FindData::Scan(IArchive* archive, AZStd::string_view szDir, bool bAllowUseFS, bool bScanZips) { // get the priority into local variable to avoid it changing in the course of @@ -119,40 +105,37 @@ namespace AZ::IO void FindData::ScanFS([[maybe_unused]] IArchive* archive, AZStd::string_view szDirIn) { - AZStd::string searchDirectory; - AZStd::string pattern; - { - AZ::IO::PathString directory{ szDirIn }; - AZ::StringFunc::Path::GetFullPath(directory.c_str(), searchDirectory); - AZ::StringFunc::Path::GetFullFileName(directory.c_str(), pattern); - } - AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), [&](const char* filePath) -> bool + AZ::IO::PathView directory{ szDirIn }; + AZ::IO::FixedMaxPath searchDirectory = directory.ParentPath(); + AZ::IO::FixedMaxPath pattern = directory.Filename(); + auto ScanFileSystem = [this](const char* filePath) -> bool { - AZ::IO::ArchiveFileIterator fileIterator{ nullptr, AZ::IO::PathView(filePath).Filename().Native(), {} }; + ArchiveFile archiveFile{ AZ::IO::PathView(filePath).Filename().Native(), {} }; if (AZ::IO::FileIOBase::GetDirectInstance()->IsDirectory(filePath)) { - fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory; - m_fileSet.emplace(AZStd::move(fileIterator)); + archiveFile.m_fileDesc.nAttrib = archiveFile.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::Subdirectory; + m_fileSet.emplace(AZStd::move(archiveFile)); } else { if (AZ::IO::FileIOBase::GetDirectInstance()->IsReadOnly(filePath)) { - fileIterator.m_fileDesc.nAttrib = fileIterator.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly; + archiveFile.m_fileDesc.nAttrib = archiveFile.m_fileDesc.nAttrib | AZ::IO::FileDesc::Attribute::ReadOnly; } AZ::u64 fileSize = 0; AZ::IO::FileIOBase::GetDirectInstance()->Size(filePath, fileSize); - fileIterator.m_fileDesc.nSize = fileSize; - fileIterator.m_fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath); + archiveFile.m_fileDesc.nSize = fileSize; + archiveFile.m_fileDesc.tWrite = AZ::IO::FileIOBase::GetDirectInstance()->ModificationTime(filePath); // These times are not supported by our file interface - fileIterator.m_fileDesc.tAccess = fileIterator.m_fileDesc.tWrite; - fileIterator.m_fileDesc.tCreate = fileIterator.m_fileDesc.tWrite; - m_fileSet.emplace(AZStd::move(fileIterator)); + archiveFile.m_fileDesc.tAccess = archiveFile.m_fileDesc.tWrite; + archiveFile.m_fileDesc.tCreate = archiveFile.m_fileDesc.tWrite; + m_fileSet.emplace(AZStd::move(archiveFile)); } return true; - }); + }; + AZ::IO::FileIOBase::GetDirectInstance()->FindFiles(searchDirectory.c_str(), pattern.c_str(), ScanFileSystem); } ////////////////////////////////////////////////////////////////////////// @@ -180,7 +163,7 @@ namespace AZ::IO fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive; fileDesc.nSize = fileEntry->desc.lSizeUncompressed; fileDesc.tWrite = fileEntry->GetModificationTime(); - m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc }); + m_fileSet.emplace(fname, fileDesc); } ZipDir::FindDir findDirectoryEntry(zipCache); @@ -193,7 +176,7 @@ namespace AZ::IO } AZ::IO::FileDesc fileDesc; fileDesc.nAttrib = AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory; - m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ this, fname, fileDesc }); + m_fileSet.emplace(fname, fileDesc); } }; @@ -208,30 +191,16 @@ namespace AZ::IO // so there's really no way to filter out opening the pack and looking at the files inside. // however, the bind root is not part of the inner zip entry name either // and the ZipDir::FindFile actually expects just the chopped off piece. - // we have to find whats in common between them and check that: + // we have to find the common path segments between them and check that: - auto resolvedBindRoot = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(it->m_pathBindRoot); - if (!resolvedBindRoot) + AZ::IO::FixedMaxPath bindRoot; + if (!AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(bindRoot, it->m_pathBindRoot)) { AZ_Assert(false, "Unable to resolve Path for archive %s bind root %s", it->GetFullPath(), it->m_pathBindRoot.c_str()); return; } - AZ::IO::FixedMaxPath bindRoot{ *resolvedBindRoot }; - auto [bindRootIter, sourcePathIter] = AZStd::mismatch(AZStd::begin(bindRoot), AZStd::end(bindRoot), - AZStd::begin(sourcePath), AZStd::end(sourcePath)); - if (sourcePathIter == AZStd::begin(sourcePath)) - { - // The path has no characters in common , early out the search as filepath is not part of the iterated zip - continue; - } - - AZ::IO::FixedMaxPath sourcePathRemainder; - for (; sourcePathIter != AZStd::end(sourcePath); ++sourcePathIter) - { - sourcePathRemainder /= *sourcePathIter; - } // Example: // "@assets@\\levels\\*" <--- szDir // "@assets@\\" <--- mount point @@ -256,18 +225,26 @@ namespace AZ::IO // then it means that the pack's mount point itself might be a return value, not the files inside the pack // in that case, we compare the mount point remainder itself with the search filter + auto [bindRootIter, sourcePathIter] = AZStd::mismatch(bindRoot.begin(), bindRoot.end(), + sourcePath.begin(), sourcePath.end()); if (bindRootIter != bindRoot.end()) { + AZ::IO::FixedMaxPath sourcePathRemainder; + for (; sourcePathIter != sourcePath.end(); ++sourcePathIter) + { + sourcePathRemainder /= *sourcePathIter; + } + // Retrieve next path component of the mount point remainder - if (!bindRootIter->empty() && AZStd::wildcard_match(sourcePathRemainder.Native(), bindRootIter->Native())) + if (!bindRootIter->empty() && bindRootIter->Match(sourcePathRemainder.Native())) { AZ::IO::FileDesc fileDesc{ AZ::IO::FileDesc::Attribute::ReadOnly | AZ::IO::FileDesc::Attribute::Archive | AZ::IO::FileDesc::Attribute::Subdirectory }; - m_fileSet.emplace(AZ::IO::ArchiveFileIterator{ this, bindRootIter->Native(), fileDesc }); + m_fileSet.emplace(AZStd::move(bindRootIter->Native()), fileDesc); } } else { - + AZ::IO::FixedMaxPath sourcePathRemainder = sourcePath.LexicallyRelative(bindRoot); // if we get here, it means that the search pattern's root and the mount point for this pack are identical // which means we may search inside the pack. ScanInZip(it->pZip.get(), sourcePathRemainder.Native()); @@ -280,17 +257,17 @@ namespace AZ::IO { if (m_fileSet.empty()) { - AZ::IO::ArchiveFileIterator emptyFileIterator; - emptyFileIterator.m_lastFetchValid = false; - emptyFileIterator.m_findData = this; - return emptyFileIterator; + return {}; } // Remove Fetched item from the FindData map so that the iteration continues - AZ::IO::ArchiveFileIterator fileIterator{ *m_fileSet.begin() }; + AZ::IO::ArchiveFileIterator fileIterator; + auto archiveFileIt = m_fileSet.begin(); + fileIterator.m_filename = archiveFileIt->m_filename; + fileIterator.m_fileDesc = archiveFileIt->m_fileDesc; fileIterator.m_lastFetchValid = true; fileIterator.m_findData = this; - m_fileSet.erase(m_fileSet.begin()); + m_fileSet.erase(archiveFileIt); return fileIterator; } } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h index 12544d124d..ebdbf45626 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ArchiveFindData.h @@ -36,56 +36,72 @@ namespace AZ::IO AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::IO::FileDesc::Attribute); + inline constexpr size_t ArchiveFilenameMaxLength = 256; + using ArchiveFileString = AZStd::fixed_string; + class FindData; + //! This is not really an iterator, but a handle + //! that extends ownership of any found filenames from an archive file or the file system struct ArchiveFileIterator { ArchiveFileIterator() = default; - ArchiveFileIterator(FindData* findData, AZStd::string_view filename, const FileDesc& fileDesc); + explicit ArchiveFileIterator(FindData* findData); ArchiveFileIterator operator++(); ArchiveFileIterator operator++(int); - bool operator==(const AZ::IO::ArchiveFileIterator& rhs) const; - explicit operator bool() const; - size_t GetHash() const; - - inline static constexpr size_t FilenameMaxLength = 256; - AZStd::fixed_string m_filename; + ArchiveFileString m_filename; FileDesc m_fileDesc; - AZStd::intrusive_ptr m_findData{}; private: friend class FindData; + friend class Archive; + AZStd::intrusive_ptr m_findData; bool m_lastFetchValid{}; }; - struct ArchiveFileIteratorHash - { - size_t operator()(const AZ::IO::ArchiveFileIterator& iter) const; - }; - struct AZStdStringLessCaseInsensitive - { - bool operator()(AZStd::string_view left, AZStd::string_view right) const; - - using is_transparent = void; - }; class FindData : public AZStd::intrusive_base { public: AZ_CLASS_ALLOCATOR(FindData, AZ::SystemAllocator, 0); FindData() = default; - AZ::IO::ArchiveFileIterator Fetch(); + ArchiveFileIterator Fetch(); void Scan(IArchive* archive, AZStd::string_view path, bool bAllowUseFS = false, bool bScanZips = true); protected: void ScanFS(IArchive* archive, AZStd::string_view path); + // Populates the FileSet with files within the that match the path pattern that is + // if it refers to a file within a bound archive root or returns the archive root + // path if the path pattern matches it. void ScanZips(IArchive* archive, AZStd::string_view path); - using FileSet = AZStd::unordered_set; + class ArchiveFile + { + public: + friend class FindData; + + ArchiveFile(); + ArchiveFile(AZStd::string_view filename, const FileDesc& fileDesc); + + size_t GetHash() const; + bool operator==(const ArchiveFile& rhs) const; + + private: + ArchiveFileString m_filename; + FileDesc m_fileDesc; + }; + + struct ArchiveFileHash + { + size_t operator()(const ArchiveFile& archiveFile) const; + }; + + using FileSet = AZStd::unordered_set; FileSet m_fileSet; }; + } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h index 5ac417564a..bd9615110a 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/IArchive.h @@ -12,12 +12,10 @@ #include #include #include -#include #include #include #include #include -#include #include @@ -106,66 +104,6 @@ namespace AZ::IO { AZ_RTTI(IArchive, "{764A2260-FF8A-4C86-B958-EBB0B69D9DFA}"); using FileTime = uint64_t; - // Flags used in file path resolution rules - enum EPathResolutionRules - { - // If used, the source path will be treated as the destination path - // and no transformations will be done. Pass this flag when the path is to be the actual - // path on the disk/in the packs and doesn't need adjustment (or after it has come through adjustments already) - // if this is set, AdjustFileName will not map the input path into the folder (Ex: Shaders will not be converted to Game\Shaders) - FLAGS_PATH_REAL = 1 << 16, - - // AdjustFileName will always copy the file path to the destination path: - // regardless of the returned value, szDestpath can be used - FLAGS_COPY_DEST_ALWAYS = 1 << 17, - - // Adds trailing slash to the path - FLAGS_ADD_TRAILING_SLASH = 1L << 18, - - // if this is set, AdjustFileName will not make relative paths into full paths - FLAGS_NO_FULL_PATH = 1 << 21, - - // if this is set, AdjustFileName will redirect path to disc - FLAGS_REDIRECT_TO_DISC = 1 << 22, - - // if this is set, AdjustFileName will not adjust path for writing files - FLAGS_FOR_WRITING = 1 << 23, - - // if this is set, the archive would be stored in memory (gpu) - FLAGS_PAK_IN_MEMORY = 1 << 25, - - // Store all file names as crc32 in a flat directory structure. - FLAGS_FILENAMES_AS_CRC32 = 1 << 26, - - // if this is set, AdjustFileName will try to find the file under any mod paths we know about - FLAGS_CHECK_MOD_PATHS = 1 << 27, - - // if this is set, AdjustFileName will always check the filesystem/disk and not check inside open archives - FLAGS_NEVER_IN_PAK = 1 << 28, - - // returns existing file name from the local data or existing cache file name - // used by the resource compiler to pass the real file name - FLAGS_RESOLVE_TO_CACHE = 1 << 29, - - // if this is set, the archive would be stored in memory (cpu) - FLAGS_PAK_IN_MEMORY_CPU = 1 << 30, - - // if this is set, the level pak is inside another archive - FLAGS_LEVEL_PAK_INSIDE_PAK = 1 << 31, - }; - - // Used for widening FOpen functionality. They're ignored for the regular File System files. - enum EFOpenFlags - { - // If possible, will prevent the file from being read from memory. - FOPEN_HINT_DIRECT_OPERATION = 1, - // Will prevent a "missing file" warnings to be created. - FOPEN_HINT_QUIET = 1 << 1, - // File should be on disk - FOPEN_ONDISK = 1 << 2, - // Open is done by the streaming thread. - FOPEN_FORSTREAMING = 1 << 3, - }; // enum ERecordFileOpenList @@ -175,8 +113,6 @@ namespace AZ::IO RFOM_Level, // during level loading till export2game -> resourcelist.txt, used to generate the list for level2level loading RFOM_NextLevel // used for level2level loading }; - // the size of the buffer that receives the full path to the file - inline static constexpr size_t MaxPath = 1024; //file location enum used in isFileExist to control where the archive system looks for the file. enum EFileSearchLocation @@ -205,63 +141,31 @@ namespace AZ::IO virtual ~IArchive() = default; - /** - * Deprecated: Use the AZ::IO::FileIOBase::ResolvePath function below that doesn't accept the nFlags or skipMods parameters - * given the source relative path, constructs the full path to the file according to the flags - * returns the pointer to the constructed path (can be either szSourcePath, or szDestPath, or NULL in case of error - */ - // - virtual const char* AdjustFileName(AZStd::string_view src, char* dst, size_t dstSize, uint32_t nFlags, bool skipMods = false) = 0; - - virtual bool Init(AZStd::string_view szBasePath) = 0; - virtual void Release() = 0; - - // Summary: - // Returns true if given archivepath is installed to HDD - // If no file path is given it will return true if whole application is installed to HDD - virtual bool IsInstalledToHDD(AZStd::string_view acFilePath = 0) const = 0; - // after this call, the archive file will be searched for files when they aren't on the OS file system // Arguments: // pName - must not be 0 - virtual bool OpenPack(AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL, AZStd::intrusive_ptr pData = {}, + virtual bool OpenPack(AZStd::string_view pName, AZStd::intrusive_ptr pData = {}, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) = 0; // after this call, the archive file will be searched for files when they aren't on the OS file system - virtual bool OpenPack(AZStd::string_view pBindingRoot, AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL, + virtual bool OpenPack(AZStd::string_view pBindingRoot, AZStd::string_view pName, AZStd::intrusive_ptr pData = {}, AZ::IO::FixedMaxPathString* pFullPath = nullptr, bool addLevels = true) = 0; // after this call, the file will be unlocked and closed, and its contents won't be used to search for files - virtual bool ClosePack(AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL) = 0; + virtual bool ClosePack(AZStd::string_view pName) = 0; // opens pack files by the path and wildcard - virtual bool OpenPacks(AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL, AZStd::vector* pFullPaths = nullptr) = 0; + virtual bool OpenPacks(AZStd::string_view pWildcard, AZStd::vector* pFullPaths = nullptr) = 0; // opens pack files by the path and wildcard - virtual bool OpenPacks(AZStd::string_view pBindingRoot, AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL, + virtual bool OpenPacks(AZStd::string_view pBindingRoot, AZStd::string_view pWildcard, AZStd::vector* pFullPaths = nullptr) = 0; // closes pack files by the path and wildcard - virtual bool ClosePacks(AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL) = 0; + virtual bool ClosePacks(AZStd::string_view pWildcard) = 0; //returns if a archive exists matching the wildcard virtual bool FindPacks(AZStd::string_view pWildcardIn) = 0; // Set access status of a archive files with a wildcard - virtual bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard, uint32_t nFlags = FLAGS_PATH_REAL) = 0; + virtual bool SetPacksAccessible(bool bAccessible, AZStd::string_view pWildcard) = 0; // Set access status of a pack file - virtual bool SetPackAccessible(bool bAccessible, AZStd::string_view pName, uint32_t nFlags = FLAGS_PATH_REAL) = 0; - - // Load or unload archive file completely to memory. - virtual bool LoadPakToMemory(AZStd::string_view pName, EInMemoryArchiveLocation eLoadToMemory, AZStd::intrusive_ptr pMemoryBlock = nullptr) = 0; - virtual void LoadPaksToMemory(int nMaxArchiveSize, bool bLoadToMemory) = 0; - - // Processes an alias command line containing multiple aliases. - virtual void ParseAliases(AZStd::string_view szCommandLine) = 0; - // adds or removes an alias from the list - virtual void SetAlias(AZStd::string_view szName, AZStd::string_view szAlias, bool bAdd) = 0; - // gets an alias from the list, if any exist. - // if bReturnSame==true, it will return the input name if an alias doesn't exist. Otherwise returns NULL - virtual const char* GetAlias(AZStd::string_view szName, bool bReturnSame = true) = 0; - - // lock all the operations - virtual void Lock() = 0; - virtual void Unlock() = 0; + virtual bool SetPackAccessible(bool bAccessible, AZStd::string_view pName) = 0; // Set and Get the localization folder name (Languages, Localization, ...) virtual void SetLocalizationFolder(AZStd::string_view sLocalizationFolder) = 0; @@ -273,28 +177,19 @@ namespace AZ::IO // ex: AZ::IO::HandleType fileHandle = FOpen( "test.txt","rbx" ); // mode x is a direct access mode, when used file reads will go directly into the low level file system without any internal data caching. // Text mode is not supported for files in Archives. - // for nFlags @see IArchive::EFOpenFlags - virtual AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode, uint32_t nFlags = 0) = 0; - - // Read raw data from file, no endian conversion. - virtual size_t FReadRaw(void* data, size_t length, size_t elems, AZ::IO::HandleType fileHandle) = 0; - - // Read all file contents into the provided memory, nSizeOfFile must be the same as returned by GetFileSize(handle) - // Current seek pointer is ignored and reseted to 0. - // no endian conversion. - virtual size_t FReadRawAll(void* data, size_t nFileSize, AZ::IO::HandleType fileHandle) = 0; + virtual AZ::IO::HandleType FOpen(AZStd::string_view pName, const char* mode) = 0; // Get pointer to the internally cached, loaded data of the file. // WARNING! The returned pointer is only valid while the fileHandle has not been closed. virtual void* FGetCachedFileData(AZ::IO::HandleType fileHandle, size_t& nFileSize) = 0; + // Read raw data from file, no endian conversion. + virtual size_t FRead(void* data, size_t bytesToRead, AZ::IO::HandleType fileHandle) = 0; + // Write file data, cannot be used for writing into the Archive. - // Use INestedArchive interface for writing into the archivefiles. - virtual size_t FWrite(const void* data, size_t length, size_t elems, AZ::IO::HandleType fileHandle) = 0; + // Use INestedArchive interface for writing into the archive files. + virtual size_t FWrite(const void* data, size_t bytesToWrite, AZ::IO::HandleType fileHandle) = 0; - virtual int FPrintf(AZ::IO::HandleType fileHandle, const char* format, ...) = 0; - virtual char* FGets(char*, int, AZ::IO::HandleType) = 0; - virtual int Getc(AZ::IO::HandleType) = 0; virtual size_t FGetSize(AZ::IO::HandleType fileHandle) = 0; virtual size_t FGetSize(AZStd::string_view pName, bool bAllowUseFileSystem = false) = 0; virtual bool IsInPak(AZ::IO::HandleType fileHandle) = 0; @@ -318,7 +213,6 @@ namespace AZ::IO virtual AZStd::intrusive_ptr PoolAllocMemoryBlock(size_t nSize, const char* sUsage, size_t nAlign = 1) = 0; // Arguments: - // nFlags is a combination of EPathResolutionRules flags. virtual ArchiveFileIterator FindFirst(AZStd::string_view pDir, EFileSearchType searchType = eFileSearchType_AllowInZipsOnly) = 0; virtual ArchiveFileIterator FindNext(AZ::IO::ArchiveFileIterator handle) = 0; virtual bool FindClose(AZ::IO::ArchiveFileIterator handle) = 0; @@ -334,9 +228,6 @@ namespace AZ::IO virtual IArchive::SignedFileSize GetFileSizeOnDisk(AZStd::string_view filename) = 0; - // creates a directory - virtual bool MakeDir(AZStd::string_view szPath) = 0; - // open the physical archive file - creates if it doesn't exist // returns NULL if it's invalid or can't open the file // nFlags is a combination of flags from EArchiveFlags enum. @@ -344,8 +235,8 @@ namespace AZ::IO AZStd::intrusive_ptr pData = nullptr) = 0; // returns the path to the archive in which the file was opened - // returns NULL if the file is a physical file, and "" if the path to archive is unknown (shouldn't ever happen) - virtual const char* GetFileArchivePath(AZ::IO::HandleType fileHandle) = 0; + // returns empty path view if the file is a physical file + virtual AZ::IO::PathView GetFileArchivePath(AZ::IO::HandleType fileHandle) = 0; // compresses the raw data into raw data. The buffer for compressed data itself with the heap passed. Uses method 8 (deflate) // returns one of the Z_* errors (Z_OK upon success) @@ -378,25 +269,7 @@ namespace AZ::IO // get the current mode, can be set by RecordFileOpen() virtual IArchive::ERecordFileOpenList GetRecordFileOpenList() = 0; - // computes CRC (zip compatible) for a file - // useful if a huge uncompressed file is generation in non continuous way - // good for big files - low memory overhead (1MB) - // Arguments: - // szPath - must not be 0 - // Returns: - // error code - virtual uint32_t ComputeCRC(AZStd::string_view szPath, uint32_t nFileOpenFlags = 0) = 0; - - // computes MD5 checksum for a file - // good for big files - low memory overhead (1MB) - // Arguments: - // szPath - must not be 0 - // md5 - destination array of uint8_t [16] - // Returns: - // true if success, false on failure - virtual bool ComputeMD5(AZStd::string_view szPath, uint8_t* md5, uint32_t nFileOpenFlags = 0, bool useDirectFileAccess = false) = 0; - - // useful for gathering file access statistics, assert if it was inserted already but then it does not become insersted + // useful for gathering file access statistics, assert if it was inserted already but then it does not become inserted // Arguments: // pSink - must not be 0 virtual void RegisterFileAccessSink(IArchiveFileAccessSink* pSink) = 0; @@ -408,8 +281,6 @@ namespace AZ::IO // When enabled, files accessed at runtime will be tracked virtual void DisableRuntimeFileAccess(bool status) = 0; virtual bool DisableRuntimeFileAccess(bool status, AZStd::thread_id threadId) = 0; - virtual bool CheckFileAccessDisabled(AZStd::string_view name, const char* mode) = 0; - virtual void SetRenderThreadId(AZStd::thread_id renderThreadId) = 0; // gets the current pak priority virtual ArchiveLocationPriority GetPakPriority() const = 0; @@ -431,21 +302,6 @@ namespace AZ::IO using LevelPackCloseEvent = AZ::Event; virtual auto GetLevelPackCloseEvent()->LevelPackCloseEvent* = 0; - // Type-safe endian conversion read. - template - size_t FRead(T* data, size_t elems, AZ::IO::HandleType fileHandle, bool bSwapEndian = false) - { - size_t count = FReadRaw(data, sizeof(T), elems, fileHandle); - SwapEndian(data, count, bSwapEndian); - return count; - } - // Type-independent Write. - template - void FWrite(T* data, size_t elems, AZ::IO::HandleType fileHandle) - { - FWrite((void*)data, sizeof(T), elems, fileHandle); - } - inline static constexpr IArchive::SignedFileSize FILE_NOT_PRESENT = -1; }; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/INestedArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/INestedArchive.h index b45d705259..f85fd273ce 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/INestedArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/INestedArchive.h @@ -9,9 +9,9 @@ #pragma once +#include #include #include -#include #include namespace AZ::IO @@ -71,28 +71,10 @@ namespace AZ::IO // multiple times FLAGS_DONT_COMPACT = 1 << 5, - // flag is set when complete pak has been loaded into memory - FLAGS_IN_MEMORY = 1 << 6, - FLAGS_IN_MEMORY_CPU = 1 << 7, - FLAGS_IN_MEMORY_MASK = FLAGS_IN_MEMORY | FLAGS_IN_MEMORY_CPU, - - // Store all file names as crc32 in a flat directory structure. - FLAGS_FILENAMES_AS_CRC32 = 1 << 8, - - // flag is set when pak is stored on HDD - FLAGS_ON_HDD = 1 << 9, - - //Override pak - paks opened with this flag go at the end of the list and contents will be found before other paks - //Used for patching - FLAGS_OVERRIDE_PAK = 1 << 10, - // Disable a pak file without unloading it, this flag is used in combination with patches and multiplayer - // to ensure that specific paks stay in the position(to keep the same priority) but beeing disabled + // to ensure that specific paks stay in the position(to keep the same priority) but being disabled // when running multiplayer FLAGS_DISABLE_PAK = 1 << 11, - - // flag is set when pak is inside another pak - FLAGS_INSIDE_PAK = 1 << 12, }; using Handle = void*; @@ -122,7 +104,7 @@ namespace AZ::IO virtual int StartContinuousFileUpdate(AZStd::string_view szRelativePath, uint64_t nSize) = 0; // Summary: - // Adds a new file to the zip or update an existing's segment if it is not compressed - just stored + // Adds a new file to the zip or update an existing segment if it is not compressed - just stored // adds a directory (creates several nested directories if needed) // ( name might be misleading as if nOverwriteSeekPos is used the update is not continuous ) // Arguments: @@ -164,7 +146,7 @@ namespace AZ::IO // Summary: // Get the full path to the archive file. - virtual const char* GetFullPath() const = 0; + virtual AZ::IO::PathView GetFullPath() const = 0; // Summary: // Get the flags of this object. diff --git a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp index dc1d4aa864..1e0f237df5 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.cpp @@ -174,7 +174,7 @@ namespace AZ::IO return m_pCache->ReadFile(reinterpret_cast(fileHandle), nullptr, pBuffer); } - const char* NestedArchive::GetFullPath() const + AZ::IO::PathView NestedArchive::GetFullPath() const { return m_pCache->GetFilePath(); } @@ -193,19 +193,9 @@ namespace AZ::IO if (nFlagsToSet & FLAGS_RELATIVE_PATHS_ONLY) { m_nFlags |= FLAGS_RELATIVE_PATHS_ONLY; - } - - if (nFlagsToSet & FLAGS_ON_HDD) - { - m_nFlags |= FLAGS_ON_HDD; - } - - if (nFlagsToSet & FLAGS_RELATIVE_PATHS_ONLY || - nFlagsToSet & FLAGS_ON_HDD) - { - // we don't support changing of any other flags return true; } + return false; } @@ -252,20 +242,12 @@ namespace AZ::IO return AZ::IO::FixedMaxPathString{ szRelativePath }; } - if ((szRelativePath.size() > 1 && szRelativePath[1] == ':') || (m_nFlags & FLAGS_ABSOLUTE_PATHS)) + if ((m_nFlags & FLAGS_ABSOLUTE_PATHS) == FLAGS_ABSOLUTE_PATHS) { // make the normalized full path and try to match it against the binding root of this object - auto resolvedPath = AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(szRelativePath); - - // Make sure the resolve path is longer than the bind root and that it starts with the bind root - if (!resolvedPath || resolvedPath->Native().size() <= m_strBindRoot.size() || azstrnicmp(resolvedPath->c_str(), m_strBindRoot.c_str(), m_strBindRoot.size()) != 0) - { - return {}; - } - - // Remove the bind root prefix from the resolved path - resolvedPath->Native().erase(0, m_strBindRoot.size() + 1); - return resolvedPath->Native(); + AZ::IO::FixedMaxPath resolvedPath; + AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedPath, szRelativePath); + return resolvedPath.LexicallyProximate(m_strBindRoot).Native(); } return AZ::IO::FixedMaxPathString{ szRelativePath }; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h index eac98b2f07..34bbcdc201 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/NestedArchive.h @@ -19,15 +19,15 @@ namespace AZ::IO { bool operator()(const INestedArchive* left, const INestedArchive* right) const { - return azstricmp(left->GetFullPath(), right->GetFullPath()) < 0; + return left->GetFullPath() < right->GetFullPath(); } bool operator()(AZStd::string_view left, const INestedArchive* right) const { - return azstrnicmp(left.data(), right->GetFullPath(), left.size()) < 0; + return AZ::IO::PathView(left) < right->GetFullPath(); } bool operator()(const INestedArchive* left, AZStd::string_view right) const { - return azstrnicmp(left->GetFullPath(), right.data(), right.size()) < 0; + return left->GetFullPath() < AZ::IO::PathView(right); } }; @@ -78,7 +78,7 @@ namespace AZ::IO int ReadFile(Handle fileHandle, void* pBuffer) override; // returns the full path to the archive file - const char* GetFullPath() const override; + AZ::IO::PathView GetFullPath() const override; ZipDir::Cache* GetCache(); uint32_t GetFlags() const override; @@ -95,7 +95,7 @@ namespace AZ::IO ZipDir::CachePtr m_pCache; // the binding root may be empty string - in this case, the absolute path binding won't work - AZStd::string m_strBindRoot; + AZ::IO::Path m_strBindRoot; IArchive* m_archive{}; uint32_t m_nFlags{}; }; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp index 81f26d78b8..328541c4d0 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -104,24 +103,21 @@ namespace AZ::IO::ZipDir : m_pCache(pCache) , m_bCommitted(false) { - AZ::IO::PathString normalizedPath{ szRelativePath }; - AZ::StringFunc::Path::Normalize(normalizedPath); - AZStd::to_lower(AZStd::begin(normalizedPath), AZStd::end(normalizedPath)); // Update the cache string pool with the relative path to the file - auto pathIt = m_pCache->m_relativePathPool.emplace(normalizedPath); + auto pathIt = m_pCache->m_relativePathPool.emplace(AZ::IO::PathView(szRelativePath).LexicallyNormal()); m_szRelativePath = *pathIt.first; // this is the name of the directory - create it or find it - m_pFileEntry = m_pCache->GetRoot()->Add(m_szRelativePath); + m_pFileEntry = m_pCache->GetRoot()->Add(m_szRelativePath.Native()); if (m_pFileEntry && az_archive_zip_directory_cache_verbosity) { - AZ_TracePrintf("Archive", R"(File "%s" has been added to archive at root "%s")", normalizedPath.c_str(), pCache->GetFilePath()); + AZ_TracePrintf("Archive", R"(File "%s" has been added to archive at root "%s")", pathIt.first->c_str(), pCache->GetFilePath()); } } ~FileEntryTransactionAdd() { if (m_pFileEntry && !m_bCommitted) { - m_pCache->RemoveFile(m_szRelativePath); + m_pCache->RemoveFile(m_szRelativePath.Native()); m_pCache->m_relativePathPool.erase(m_szRelativePath); } } @@ -131,11 +127,11 @@ namespace AZ::IO::ZipDir } AZStd::string_view GetRelativePath() const { - return m_szRelativePath; + return m_szRelativePath.Native(); } private: Cache* m_pCache; - AZStd::string_view m_szRelativePath; + AZ::IO::PathView m_szRelativePath; FileEntry* m_pFileEntry; bool m_bCommitted; }; @@ -587,34 +583,27 @@ namespace AZ::IO::ZipDir // deletes the file from the archive ErrorEnum Cache::RemoveFile(AZStd::string_view szRelativePathSrc) { - // Normalize and lower case the relative path - AZ::IO::PathString szRelativePath{ szRelativePathSrc }; - AZ::StringFunc::Path::Normalize(szRelativePath); - AZStd::to_lower(AZStd::begin(szRelativePath), AZStd::end(szRelativePath)); - AZStd::string_view normalizedRelativePath = szRelativePath; - - // find the last slash in the path - size_t slashOffset = normalizedRelativePath.find_last_of(AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); + AZ::IO::PathView szRelativePath{ szRelativePathSrc }; AZStd::string_view fileName; // the name of the file to delete FileEntryTree* pDir; // the dir from which the subdir will be deleted - if (slashOffset != AZStd::string_view::npos) + if (szRelativePath.HasParentPath()) { FindDir fd(GetRoot()); // the directory to remove - pDir = fd.FindExact(normalizedRelativePath.substr(0, slashOffset)); + pDir = fd.FindExact(szRelativePath.ParentPath()); if (!pDir) { return ZD_ERROR_DIR_NOT_FOUND;// there is no such directory } - fileName = normalizedRelativePath.substr(slashOffset + 1); + fileName = szRelativePath.Filename().Native(); } else { pDir = GetRoot(); - fileName = normalizedRelativePath; + fileName = szRelativePath.Native(); } ErrorEnum e = pDir->RemoveFile(fileName); @@ -625,7 +614,7 @@ namespace AZ::IO::ZipDir if (az_archive_zip_directory_cache_verbosity) { AZ_TracePrintf("Archive", R"(File "%.*s" has been remove from archive at root "%s")", - aznumeric_cast(fileName.size()), fileName.data(), GetFilePath()); + AZ_STRING_ARG(szRelativePath.Native()), GetFilePath()); } } return e; @@ -635,45 +624,38 @@ namespace AZ::IO::ZipDir // deletes the directory, with all its descendants (files and subdirs) ErrorEnum Cache::RemoveDir(AZStd::string_view szRelativePathSrc) { - // Normalize and lower case the relative path - AZ::IO::PathString szRelativePath{ szRelativePathSrc }; - AZ::StringFunc::Path::Normalize(szRelativePath); - AZStd::to_lower(AZStd::begin(szRelativePath), AZStd::end(szRelativePath)); - AZStd::string_view normalizedRelativePath = szRelativePath; - - // find the last slash in the path - size_t slashOffset = normalizedRelativePath.find_last_of(AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); + AZ::IO::PathView szRelativePath{ szRelativePathSrc }; AZStd::string_view dirName; // the name of the dir to delete FileEntryTree* pDir; // the dir from which the subdir will be deleted - if (slashOffset != AZStd::string_view::npos) + if (szRelativePath.HasParentPath()) { FindDir fd(GetRoot()); // the directory to remove - pDir = fd.FindExact(normalizedRelativePath.substr(0, slashOffset)); + pDir = fd.FindExact(szRelativePath.ParentPath()); if (!pDir) { return ZD_ERROR_DIR_NOT_FOUND;// there is no such directory } - dirName = normalizedRelativePath.substr(slashOffset + 1); + dirName = szRelativePath.Filename().Native(); } else { pDir = GetRoot(); - dirName = normalizedRelativePath; + dirName = szRelativePath.Native(); } - ErrorEnum e = pDir->RemoveDir(normalizedRelativePath); + ErrorEnum e = pDir->RemoveDir(dirName); if (e == ZD_ERROR_SUCCESS) { m_nFlags |= FLAGS_UNCOMPACTED | FLAGS_CDR_DIRTY; if (az_archive_zip_directory_cache_verbosity) { - AZ_TracePrintf("Archive", R"(File "%.*s" has been remove from archive at root "%s")", - aznumeric_cast(normalizedRelativePath.size()), normalizedRelativePath.data(), GetFilePath()); + AZ_TracePrintf("Archive", R"(Directory "%.*s" has been remove from archive at root "%s")", + AZ_STRING_ARG(szRelativePath.Native()), GetFilePath()); } } return e; @@ -769,9 +751,7 @@ namespace AZ::IO::ZipDir // finds the file by exact path FileEntry* Cache::FindFile(AZStd::string_view szPathSrc, [[maybe_unused]] bool bFullInfo) { - AZ::IO::PathString szPath{ szPathSrc }; - AZ::StringFunc::Path::Normalize(szPath); - AZStd::to_lower(AZStd::begin(szPath), AZStd::end(szPath)); + AZ::IO::PathView szPath{ szPathSrc }; ZipDir::FindFile fd(GetRoot()); FileEntry* fileEntry = fd.FindExact(szPath); @@ -779,19 +759,13 @@ namespace AZ::IO::ZipDir { if (az_archive_zip_directory_cache_verbosity) { - AZ_TracePrintf("Archive", "FindExact failed to find file %s at root %s", szPath.c_str(), GetFilePath()); + AZ_TracePrintf("Archive", "FindExact failed to find file %.*s at root %s", AZ_STRING_ARG(szPath.Native()), GetFilePath()); } return {}; } return fileEntry; } - // returns the size of memory occupied by the instance referred to by this cache - size_t Cache::GetSize() const - { - return sizeof(*this) + m_strFilePath.capacity() + m_treeDir.GetSize() - sizeof(m_treeDir); - } - // refreshes information about the given file entry into this file entry ErrorEnum Cache::Refresh(FileEntryBase* pFileEntry) { diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h index 35bf0ae251..646410f8db 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCache.h @@ -16,6 +16,7 @@ #pragma once #include +#include #include #include #include @@ -89,9 +90,6 @@ namespace AZ::IO::ZipDir // refreshes information about the given file entry into this file entry ErrorEnum Refresh(FileEntryBase* pFileEntry); - // returns the size of memory occupied by the instance of this cache - size_t GetSize() const; - // QUICK check to determine whether the file entry belongs to this object bool IsOwnerOf(const FileEntry* pFileEntry) const { @@ -100,9 +98,9 @@ namespace AZ::IO::ZipDir // returns the string - path to the zip file from which this object was constructed. // this will be "" if the object was constructed with a factory that wasn't created with FLAGS_MEMORIZE_ZIP_PATH - const char* GetFilePath() const + AZ::IO::PathView GetFilePath() const { - return m_strFilePath.c_str(); + return m_strFilePath; } FileEntryTree* GetRoot() @@ -135,10 +133,10 @@ namespace AZ::IO::ZipDir FileEntryTree m_treeDir; AZ::IO::HandleType m_fileHandle; AZ::IAllocatorAllocate* m_allocator; - AZStd::string m_strFilePath; + AZ::IO::Path m_strFilePath; // String Pool for persistently storing paths as long as they reside in the cache - AZStd::unordered_set m_relativePathPool; + AZStd::unordered_set m_relativePathPool; // offset to the start of CDR in the file,even if there's no CDR there currently // when a new file is added, it can start from here, but this value will need to be updated then diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp index 0092c7c8f8..6adab594ed 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.cpp @@ -41,13 +41,6 @@ namespace AZ::IO::ZipDir m_encryptedHeaders = ZipFile::HEADERS_NOT_ENCRYPTED; m_signedHeaders = ZipFile::HEADERS_NOT_SIGNED; - if (m_nFlags & FLAGS_FILENAMES_AS_CRC32) - { - m_bBuildFileEntryMap = false; - m_bBuildFileEntryTree = false; - m_bBuildOptimizedFileEntry = true; - } - if (m_nFlags & FLAGS_READ_INSIDE_PAK) { m_fileExt.m_fileIOBase = AZ::IO::FileIOBase::GetInstance(); @@ -88,12 +81,12 @@ namespace AZ::IO::ZipDir if (m_fileExt.m_fileHandle == AZ::IO::InvalidHandle) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not open file in binary mode for reading"); + AZ_Warning("Archive", false, R"(ZD_ERROR_IO_FAILED: Could not open file "%s" in binary mode for reading)", szFileName); return {}; } if (!ReadCache(*pCache)) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not read the CDR of the pack file."); + AZ_Warning("Archive", false, R"(ZD_ERROR_IO_FAILED: Could not read the CDR of the pack file "%s".)", pCache->m_strFilePath.c_str()); return {}; } } @@ -113,12 +106,12 @@ namespace AZ::IO::ZipDir size_t nFileSize = (size_t)Tell(); Seek(0, SEEK_SET); - AZ_Assert(nFileSize != 0, "File of size 0 will not be open for reading"); + AZ_Warning("Archive", nFileSize != 0, R"(ZD_ERROR_IO_FAILED: File "%s" with size 0 will not be open for reading)", szFileName); if (nFileSize) { if (!ReadCache(*pCache)) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not open file in binary mode for reading"); + AZ_Warning("Archive", false, R"(ZD_ERROR_IO_FAILED: Could not open file "%s" in binary mode for reading)", szFileName); return {}; } bOpenForWriting = false; @@ -143,7 +136,7 @@ namespace AZ::IO::ZipDir if (m_fileExt.m_fileHandle == AZ::IO::InvalidHandle) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Could not open file in binary mode for appending (read/write)"); + AZ_Warning("Archive", false, R"(ZD_ERROR_IO_FAILED: Could not open file "%s" in binary mode for appending (read/write))", szFileName); return {}; } } @@ -211,7 +204,7 @@ namespace AZ::IO::ZipDir if (m_headerExtended.nHeaderSize != sizeof(m_headerExtended)) { // Extended Header is not valid - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Bad extended header"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: Bad extended header"); return false; } //We have the header, so read the encryption and signing techniques @@ -224,7 +217,7 @@ namespace AZ::IO::ZipDir if (m_headerExtended.nEncryption != ZipFile::HEADERS_NOT_ENCRYPTED && m_encryptedHeaders != ZipFile::HEADERS_NOT_ENCRYPTED) { //Encryption technique has been specified in both the disk number (old technique) and the custom header (new technique). - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Unexpected encryption technique in header"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: Unexpected encryption technique in header"); return false; } else @@ -240,7 +233,7 @@ namespace AZ::IO::ZipDir break; default: // Unexpected technique - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Bad encryption technique in header"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: Bad encryption technique in header"); return false; } } @@ -255,7 +248,7 @@ namespace AZ::IO::ZipDir break; default: // Unexpected technique - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Bad signing technique in header"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: Bad signing technique in header"); return false; } @@ -266,7 +259,7 @@ namespace AZ::IO::ZipDir Read(&m_headerSignature, sizeof(m_headerSignature)); if (m_headerSignature.nHeaderSize != sizeof(m_headerSignature)) { - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Bad signature header"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: Bad signature header"); return false; } } @@ -274,7 +267,7 @@ namespace AZ::IO::ZipDir else { // Unexpected technique - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Comment field is the wrong length"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: Comment field is the wrong length"); return false; } } @@ -285,7 +278,7 @@ namespace AZ::IO::ZipDir || m_CDREnd.nCDRStartDisk != 0 || m_CDREnd.numEntriesOnDisk != m_CDREnd.numEntriesTotal) { - THROW_ZIPDIR_ERROR(ZD_ERROR_UNSUPPORTED, "Multivolume archive detected. Current version of ZipDir does not support multivolume archives"); + AZ_Warning("Archive", false, "ZD_ERROR_UNSUPPORTED: Multivolume archive detected.Current version of ZipDir does not support multivolume archives"); return false; } @@ -295,7 +288,7 @@ namespace AZ::IO::ZipDir || m_CDREnd.lCDRSize > m_nCDREndPos || m_CDREnd.lCDROffset + m_CDREnd.lCDRSize > m_nCDREndPos) { - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "The central directory offset or size are out of range, the pak is probably corrupt, try to repare or delete the file"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT: The central directory offset or size are out of range, the pak is probably corrupt, try to repare or delete the file"); return false; } @@ -394,7 +387,12 @@ namespace AZ::IO::ZipDir // if there's nothing to search if (nNewBufPos >= nOldBufPos) { - THROW_ZIPDIR_ERROR(ZD_ERROR_NO_CDR, "Cannot find Central Directory Record in pak. This is either not a pak file, or a pak file without Central Directory. It does not mean that the data is permanently lost, but it may be severely damaged. Please repair the file with external tools, there may be enough information left to recover the file completely."); // we didn't find anything + AZ_Warning("Archive", false, "ZD_ERROR_NO_CDR: Cannot find Central Directory Record in pak." + " This is either not a pak file, or a pak file without Central Directory." + " It does not mean that the data is permanently lost," + " but it may be severely damaged." + " Please repair the file with external tools," + " there may be enough information left to recover the file completely."); // we didn't find anything return false; } @@ -418,7 +416,11 @@ namespace AZ::IO::ZipDir } else { - THROW_ZIPDIR_ERROR(ZD_ERROR_DATA_IS_CORRUPT, "Central Directory Record is followed by a comment of inconsistent length. This might be a minor misconsistency, please try to repair the file. However, it is dangerous to open the file because I will have to guess some structure offsets, which can lead to permanent unrecoverable damage of the archive content"); + AZ_Warning("Archive", false, "ZD_ERROR_DATA_IS_CORRUPT:" + " Central Directory Record is followed by a comment of inconsistent length." + " This might be a minor misconsistency, please try to repair the file.However," + " it is dangerous to open the file because I will have to guess some structure offsets," + " which can lead to permanent unrecoverable damage of the archive content"); return false; } } @@ -436,7 +438,7 @@ namespace AZ::IO::ZipDir nOldBufPos = nNewBufPos; memmove(&pReservedBuffer[CDRSearchWindowSize], pWindow, sizeof(ZipFile::CDREnd) - 1); } - THROW_ZIPDIR_ERROR(ZD_ERROR_UNEXPECTED, "The program flow may not have possibly lead here. This error is unexplainable"); // we shouldn't be here + AZ_Assert(false, "ZD_ERROR_UNEXPECTED: The program flow may not have possibly lead here. This error is unexplainable"); // we shouldn't be here return false; } @@ -460,13 +462,13 @@ namespace AZ::IO::ZipDir if (pBuffer.empty()) // couldn't allocate enough memory for temporary copy of CDR { - THROW_ZIPDIR_ERROR(ZD_ERROR_NO_MEMORY, "Not enough memory to cache Central Directory record for fast initialization. This error may not happen on non-console systems"); + AZ_Warning("Archive", false, "ZD_ERROR_NO_MEMORY: Not enough memory to cache Central Directory record for fast initialization. This error may not happen on non-console systems"); return false; } if (!ReadHeaderData(&pBuffer[0], m_CDREnd.lCDRSize)) { - THROW_ZIPDIR_ERROR(ZD_ERROR_CORRUPTED_DATA, "Archive contains corrupted CDR."); + AZ_Warning("Archive", false, "ZD_ERROR_CORRUPTED_DATA: Archive contains corrupted CDR."); return false; } @@ -482,7 +484,7 @@ namespace AZ::IO::ZipDir if ((pFile->nVersionNeeded & 0xFF) > 20) { - THROW_ZIPDIR_ERROR(ZD_ERROR_UNSUPPORTED, "Cannot read the archive file (nVersionNeeded > 20)."); + AZ_Warning("Archive", false, "ZD_ERROR_UNSUPPORTED: Cannot read the archive file (nVersionNeeded > 20)."); return false; } //if (pFile->lSignature != pFile->SIGNATURE) // Timur, Dont compare signatures as signatue in memory can be overwritten by the code below @@ -492,7 +494,8 @@ namespace AZ::IO::ZipDir // if the record overlaps with the End Of CDR structure, something is wrong if (pEndOfRecord > pEndOfData) { - THROW_ZIPDIR_ERROR(ZD_ERROR_CDR_IS_CORRUPT, "Central Directory record is either corrupt, or truncated, or missing. Cannot read the archive directory"); + AZ_Warning("Archive", false, "ZD_ERROR_CDR_IS_CORRUPT: Central Directory record is either corrupt, or truncated, or missing." + " Cannot read the archive directory"); return false; } @@ -555,13 +558,17 @@ namespace AZ::IO::ZipDir { if (pFileHeader->lLocalHeaderOffset > m_CDREnd.lCDROffset) { - THROW_ZIPDIR_ERROR(ZD_ERROR_CDR_IS_CORRUPT, "Central Directory contains file descriptors pointing outside the archive file boundaries. The archive file is either truncated or damaged. Please try to repair the file"); // the file offset is beyond the CDR: impossible + AZ_Warning("Archive", false, "ZD_ERROR_CDR_IS_CORRUPT:" + " Central Directory contains file descriptors pointing outside the archive file boundaries." + " The archive file is either truncated or damaged.Please try to repair the file"); // the file offset is beyond the CDR: impossible return; } if ((pFileHeader->nMethod == ZipFile::METHOD_STORE || pFileHeader->nMethod == ZipFile::METHOD_STORE_AND_STREAMCIPHER_KEYTABLE) && pFileHeader->desc.lSizeUncompressed != pFileHeader->desc.lSizeCompressed) { - THROW_ZIPDIR_ERROR(ZD_ERROR_VALIDATION_FAILED, "File with STORE compression method declares its compressed size not matching its uncompressed size. File descriptor is inconsistent, archive content may be damaged, please try to repair the archive"); + AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:" + " File with STORE compression method declares its compressed size not matching its uncompressed size." + " File descriptor is inconsistent, archive content may be damaged, please try to repair the archive"); return; } @@ -617,7 +624,9 @@ namespace AZ::IO::ZipDir //|| pFileHeader->nLastModTime != pLocalFileHeader->nLastModTime ) { - THROW_ZIPDIR_ERROR(ZD_ERROR_VALIDATION_FAILED, "The local file header descriptor doesn't match the basic parameters declared in the global file header in the file. The archive content is misconsistent and may be damaged. Please try to repair the archive"); + AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:" + " The local file header descriptor doesn't match the basic parameters declared in the global file header in the file." + " The archive content is misconsistent and may be damaged. Please try to repair the archive"); return; } @@ -628,7 +637,9 @@ namespace AZ::IO::ZipDir if (!AZStd::equal(zipFileDataBegin, zipFileDataEnd, reinterpret_cast(pFileHeader + 1), CompareNoCase)) { // either file name, or the extra field do not match - THROW_ZIPDIR_ERROR(ZD_ERROR_VALIDATION_FAILED, "The local file header contains file name which does not match the file name of the global file header. The archive content is misconsistent with its directory. Please repair the archive"); + AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:" + " The local file header contains file name which does not match the file name of the global file header." + " The archive content is misconsistent with its directory. Please repair the archive"); return; } @@ -642,7 +653,9 @@ namespace AZ::IO::ZipDir if (fileEntry.nFileDataOffset >= m_nCDREndPos) { - THROW_ZIPDIR_ERROR(ZD_ERROR_VALIDATION_FAILED, "The global file header declares the file which crosses the boundaries of the archive. The archive is either corrupted or truncated, please try to repair it"); + AZ_Warning("Archive", false, "ZD_ERROR_VALIDATION_FAILED:" + " The global file header declares the file which crosses the boundaries of the archive." + " The archive is either corrupted or truncated, please try to repair it"); return; } @@ -686,29 +699,29 @@ namespace AZ::IO::ZipDir case Z_OK: break; case Z_MEM_ERROR: - THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_NO_MEMORY, "ZLib reported out-of-memory error"); + AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_NO_MEMORY: ZLib reported out-of-memory error"); return; case Z_BUF_ERROR: - THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_CORRUPTED_DATA, "ZLib reported compressed stream buffer error"); + AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_CORRUPTED_DATA: ZLib reported compressed stream buffer error"); return; case Z_DATA_ERROR: - THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_CORRUPTED_DATA, "ZLib reported compressed stream data error"); + AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_CORRUPTED_DATA: ZLib reported compressed stream data error"); return; default: - THROW_ZIPDIR_ERROR(ZD_ERROR_ZLIB_FAILED, "ZLib reported an unexpected unknown error"); + AZ_Warning("Archive", false, "ZD_ERROR_ZLIB_FAILED: ZLib reported an unexpected unknown error"); return; } if (nDestSize != fileEntry.desc.lSizeUncompressed) { - THROW_ZIPDIR_ERROR(ZD_ERROR_CORRUPTED_DATA, "Uncompressed stream doesn't match the size of uncompressed file stored in the archive file headers"); + AZ_Warning("Archive", false, "ZD_ERROR_CORRUPTED_DATA: Uncompressed stream doesn't match the size of uncompressed file stored in the archive file headers"); return; } uLong uCRC32 = AZ::Crc32((Bytef*)pUncompressed, nDestSize); if (uCRC32 != fileEntry.desc.lCRC32) { - THROW_ZIPDIR_ERROR(ZD_ERROR_CRC32_CHECK, "Uncompressed stream CRC32 check failed"); + AZ_Warning("Archive", false, "ZD_ERROR_CRC32_CHECK: Uncompressed stream CRC32 check failed"); return; } } @@ -737,7 +750,7 @@ namespace AZ::IO::ZipDir { if (FSeek(&m_fileExt, nPos, nOrigin)) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot fseek() to the new position in the file. This is unexpected error and should not happen under any circumstances. Perhaps some network or disk failure error has caused this"); + AZ_Warning("Archive", false, "ZD_ERROR_IO_FAILED: Cannot fseek() to the new position in the file. This is unexpected error and should not happen under any circumstances. Perhaps some network or disk failure error has caused this"); return; } } @@ -747,7 +760,7 @@ namespace AZ::IO::ZipDir int64_t nPos = FTell(&m_fileExt); if (nPos == -1) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot ftell() position in the archive. This is unexpected error and should not happen under any circumstances. Perhaps some network or disk failure error has caused this"); + AZ_Warning("Archive", false, "ZD_ERROR_IO_FAILED: Cannot ftell() position in the archive. This is unexpected error and should not happen under any circumstances. Perhaps some network or disk failure error has caused this"); return 0; } return nPos; @@ -757,7 +770,7 @@ namespace AZ::IO::ZipDir { if (FRead(&m_fileExt, pDest, nSize, 1) != 1) { - THROW_ZIPDIR_ERROR(ZD_ERROR_IO_FAILED, "Cannot fread() a portion of data from archive"); + AZ_Warning("Archive", false, "ZD_ERROR_IO_FAILED: Cannot fread() a portion of data from archive"); return false; } return true; diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.h index 1f27cb5504..c31d4d7dfd 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirCacheFactory.h @@ -33,20 +33,13 @@ namespace AZ::IO::ZipDir // if this is set, the archive will be created anew (the existing file will be overwritten) FLAGS_CREATE_NEW = 1 << 3, - // Cache will be loaded completely into the memory. - FLAGS_IN_MEMORY = 1 << 4, - FLAGS_IN_MEMORY_CPU = 1 << 5, - - // Store all file names as crc32 in a flat directory structure. - FLAGS_FILENAMES_AS_CRC32 = 1 << 6, - // if this is set, zip path will be searched inside other zips FLAGS_READ_INSIDE_PAK = 1 << 7, }; // initializes the internal structures // nFlags can have FLAGS_READ_ONLY flag, in this case the object will be opened only for reading - CacheFactory (InitMethodEnum nInitMethod, uint32_t nFlags = 0); + CacheFactory(InitMethodEnum nInitMethod, uint32_t nFlags = 0); ~CacheFactory(); // the new function creates a new cache diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.cpp index 30c8676f75..4fb1a54ded 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.cpp @@ -17,7 +17,7 @@ namespace AZ::IO::ZipDir { - bool FindFile::FindFirst(AZStd::string_view szWildcard) + bool FindFile::FindFirst(AZ::IO::PathView szWildcard) { if (!PreFind(szWildcard)) { @@ -29,7 +29,7 @@ namespace AZ::IO::ZipDir return SkipNonMatchingFiles(); } - bool FindDir::FindFirst(AZStd::string_view szWildcard) + bool FindDir::FindFirst(AZ::IO::PathView szWildcard) { if (!PreFind(szWildcard)) { @@ -42,37 +42,20 @@ namespace AZ::IO::ZipDir } // matches the file wildcard in the m_szWildcard to the given file/dir name - // this takes into account the fact that xxx. is the alias name for xxx - bool FindData::MatchWildcard(AZStd::string_view szName) + bool FindData::MatchWildcard(AZ::IO::PathView szName) { - if (AZStd::wildcard_match(m_szWildcard, szName)) - { - return true; - } - - // check if the file object name contains extension sign (.) - size_t extensionOffset = szName.find('.'); - if (extensionOffset != AZStd::string_view::npos) - { - return false; - } - - // no extension sign - add it - AZStd::fixed_string szAlias{ szName }; - szAlias.push_back('.'); - - return AZStd::wildcard_match(m_szWildcard, szAlias); + return szName.Match(m_szWildcard.Native()); } - FileEntry* FindFile::FindExact(AZStd::string_view szPath) + FileEntry* FindFile::FindExact(AZ::IO::PathView szPath) { if (!PreFind(szPath)) { return nullptr; } - FileEntryTree::FileMap::iterator itFile = m_pDirHeader->FindFile(m_szWildcard.c_str()); + FileEntryTree::FileMap::iterator itFile = m_pDirHeader->FindFile(m_szWildcard); if (itFile == m_pDirHeader->GetFileEnd()) { m_pDirHeader = nullptr; // we didn't find it, fail the search @@ -84,7 +67,7 @@ namespace AZ::IO::ZipDir return m_pDirHeader->GetFileEntry(m_itFile); } - FileEntryTree* FindDir::FindExact(AZStd::string_view szPath) + FileEntryTree* FindDir::FindExact(AZ::IO::PathView szPath) { if (!PreFind(szPath)) { @@ -97,40 +80,50 @@ namespace AZ::IO::ZipDir ////////////////////////////////////////////////////////////////////////// // after this call returns successfully (with true returned), the m_szWildcard - // contains the file name/wildcard and m_pDirHeader contains the directory where + // contains the file name/glob and m_pDirHeader contains the directory where // the file (s) are to be found - bool FindData::PreFind(AZStd::string_view szWildcard) + bool FindData::PreFind(AZ::IO::PathView pathGlob) { if (!m_pRoot) { return false; } - // start the search from the root - m_pDirHeader = m_pRoot; - m_szWildcard = szWildcard; - - // for each path directory, copy it into the wildcard buffer and try to find the subdirectory - for (AZStd::optional pathEntry = AZ::StringFunc::TokenizeNext(szWildcard, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); pathEntry; - pathEntry = AZ::StringFunc::TokenizeNext(szWildcard, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR)) + FileEntryTree* entryTreeHeader = m_pRoot; + // If there is a root path in the glob path, attempt to locate it from the root + if (AZ::IO::PathView rootPath = m_szWildcard.RootPath(); !rootPath.empty()) { - // Update wildcard to new path entry - m_szWildcard = *pathEntry; + FileEntryTree* dirEntry = entryTreeHeader->FindDir(rootPath); + if (dirEntry == nullptr) + { + return false; + } - // If the wildcard parameter that has been passed to TokenizeNext is empty - // Then pathEntry is the final portion of the path - if (!szWildcard.empty()) + entryTreeHeader = dirEntry->GetDirectory(); + pathGlob = pathGlob.RelativePath(); + } + + + AZ::IO::PathView filenameSegment = pathGlob; + // Recurse through the directories within the file tree for each remaining parent path segment + // of pathGlob parameter + auto parentPathIter = pathGlob.begin(); + for (auto filenamePathIter = parentPathIter == pathGlob.end() ? pathGlob.end() : AZStd::next(parentPathIter, 1); + filenamePathIter != pathGlob.end(); ++parentPathIter, ++filenamePathIter) + { + FileEntryTree* dirEntry = entryTreeHeader->FindDir(*parentPathIter); + if (dirEntry == nullptr) { - FileEntryTree* dirEntry = m_pDirHeader->FindDir(*pathEntry); - if (!dirEntry) - { - m_pDirHeader = nullptr; // an intermediate directory has not been found continue the search - return false; - } - m_pDirHeader = dirEntry->GetDirectory(); + return false; } + entryTreeHeader = dirEntry->GetDirectory(); + filenameSegment = *filenamePathIter; } + // At this point the all the intermediate directories have been found + // so update the directory header to point at the last file entry tree + m_pDirHeader = entryTreeHeader; + m_szWildcard = filenameSegment; return true; } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.h index 2bb3932aa9..f9b773a42d 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirFind.h @@ -38,11 +38,10 @@ namespace AZ::IO::ZipDir // after this call returns successfully (with true returned), the m_szWildcard // contains the file name/wildcard and m_pDirHeader contains the directory where // the file (s) are to be found - bool PreFind(AZStd::string_view szWildcard); + bool PreFind(AZ::IO::PathView szWildcard); // matches the file wildcard in the m_szWildcard to the given file/dir name - // this takes into account the fact that xxx. is the alias name for xxx - bool MatchWildcard(AZStd::string_view szName); + bool MatchWildcard(AZ::IO::PathView szName); // the directory inside which the current object (file or directory) is being searched FileEntryTree* m_pDirHeader{}; @@ -50,7 +49,7 @@ namespace AZ::IO::ZipDir FileEntryTree* m_pRoot{}; // the root of the zip file in which to search // the actual wildcard being used in the current scan - the file name wildcard only! - AZStd::fixed_string m_szWildcard; + AZ::IO::FixedMaxPath m_szWildcard; }; class FindFile @@ -66,9 +65,9 @@ namespace AZ::IO::ZipDir { } // if bExactFile is passed, only the file is searched, and besides with the exact name as passed (no wildcards) - bool FindFirst(AZStd::string_view szWildcard); + bool FindFirst(AZ::IO::PathView szWildcard); - FileEntry* FindExact(AZStd::string_view szPath); + FileEntry* FindExact(AZ::IO::PathView szPath); // goes on to the next file entry bool FindNext(); @@ -94,9 +93,9 @@ namespace AZ::IO::ZipDir { } // if bExactFile is passed, only the file is searched, and besides with the exact name as passed (no wildcards) - bool FindFirst(AZStd::string_view szWildcard); + bool FindFirst(AZ::IO::PathView szWildcard); - FileEntryTree* FindExact(AZStd::string_view szPath); + FileEntryTree* FindExact(AZ::IO::PathView szPath); // goes on to the next file entry bool FindNext(); diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirList.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirList.cpp index 2f96a93a82..729f394b9d 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirList.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirList.cpp @@ -68,14 +68,14 @@ namespace AZ::IO::ZipDir { for (FileEntryTree::SubdirMap::iterator it = pTree->GetDirBegin(); it != pTree->GetDirEnd(); ++it) { - AddAllFiles(it->second.get(), AZStd::string::format("%.*s%.*s/", aznumeric_cast(strRoot.size()), strRoot.data(), aznumeric_cast(it->first.size()), it->first.data())); + AddAllFiles(it->second.get(), (AZ::IO::Path(strRoot) / it->first).Native()); } for (FileEntryTree::FileMap::iterator it = pTree->GetFileBegin(); it != pTree->GetFileEnd(); ++it) { FileRecord rec; rec.pFileEntryBase = pTree->GetFileEntry(it); - rec.strPath = AZStd::string::format("%.*s%.*s", aznumeric_cast(strRoot.size()), strRoot.data(), aznumeric_cast(it->first.size()), it->first.data()); + rec.strPath = (AZ::IO::Path(strRoot) / it->first).Native(); push_back(rec); } } diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp index 1d09705900..f9aa249339 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.cpp @@ -432,18 +432,18 @@ namespace AZ::IO::ZipDir bool CZipFile::EvaluateSectorSize(const char* filename) { - char volume[AZ_MAX_PATH_LEN]; + AZ::IO::FixedMaxPath volume; - if (AZ::StringFunc::Path::IsRelative(filename)) + if (AZ::IO::PathView(filename).IsRelative()) { - AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(filename, volume, AZ_ARRAY_SIZE(volume)); + AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(volume, filename); } else { - azstrcpy(volume, AZ_ARRAY_SIZE(volume), filename); + volume = filename; } - AZ::IO::FixedMaxPathString drive{ AZ::IO::PathView(volume).RootName().Native() }; + AZ::IO::FixedMaxPath drive = volume.RootName(); if (drive.empty()) { return false; @@ -666,7 +666,9 @@ namespace AZ::IO::ZipDir DirEntry* pEnd = pBegin + this->numDirs; DirEntry* pEntry = AZStd::lower_bound(pBegin, pEnd, szName, pred); #if AZ_TRAIT_LEGACY_CRYPAK_UNIX_LIKE_FILE_SYSTEM - if (pEntry != pEnd && !azstrnicmp(szName.data(), pEntry->GetName(pNamePool), szName.size())) + AZ::IO::PathView searchPath(szName, AZ::IO::WindowsPathSeparator); + AZ::IO::PathView entryPath(pEntry->GetName(pNamePool), AZ::IO::WindowsPathSeparator); + if (pEntry != pEnd && searchPath == entryPath) #else if (pEntry != pEnd && szName == pEntry->GetName(pNamePool)) #endif @@ -690,7 +692,9 @@ namespace AZ::IO::ZipDir FileEntry* pEnd = pBegin + this->numFiles; FileEntry* pEntry = AZStd::lower_bound(pBegin, pEnd, szName, pred); #if AZ_TRAIT_LEGACY_CRYPAK_UNIX_LIKE_FILE_SYSTEM - if (pEntry != pEnd && !azstrnicmp(szName.data(), pEntry->GetName(pNamePool), szName.size())) + AZ::IO::PathView searchPath(szName, AZ::IO::WindowsPathSeparator); + AZ::IO::PathView entryPath(pEntry->GetName(pNamePool), AZ::IO::WindowsPathSeparator); + if (pEntry != pEnd && searchPath == entryPath) #else if (pEntry != pEnd && szName == pEntry->GetName(pNamePool)) #endif @@ -990,13 +994,6 @@ namespace AZ::IO::ZipDir } ////////////////////////////////////////////////////////////////////////// - uint32_t FileNameHash(AZStd::string_view filename) - { - AZ::IO::StackString pathname{ filename }; - AZStd::replace(AZStd::begin(pathname), AZStd::end(pathname), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR); - - return AZ::Crc32(pathname); - } int64_t FSeek(CZipFile* file, int64_t origin, int command) { diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h index 2f9046f53e..7e1d54b405 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirStructures.h @@ -119,8 +119,6 @@ namespace AZ::IO::ZipDir const char* m_szDescription; }; -#define THROW_ZIPDIR_ERROR(ZD_ERR, DESC) AZ_Warning("Archive", false, DESC) - // possible initialization methods enum InitMethodEnum { @@ -157,8 +155,6 @@ namespace AZ::IO::ZipDir int FEof(CZipFile* zipFile); - uint32_t FileNameHash(AZStd::string_view filename); - ////////////////////////////////////////////////////////////////////////// struct SExtraZipFileData diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.cpp b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.cpp index 213287ef74..e772cb596a 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -18,37 +17,42 @@ namespace AZ::IO::ZipDir { // Adds or finds the file. Returns non-initialized structure if it was added, // or an IsInitialized() structure if it was found - FileEntry* FileEntryTree::Add(AZStd::string_view szPath) + FileEntry* FileEntryTree::Add(AZ::IO::PathView inputPathView) { - AZStd::optional pathEntry = AZ::StringFunc::TokenizeNext(szPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); - if (!pathEntry) + if (inputPathView.empty()) { AZ_Assert(false, "An empty file path cannot be added to the zip file entry tree"); return nullptr; } // If a path separator was found, add a subdirectory - if (!szPath.empty()) + auto inputPathIter = inputPathView.begin(); + AZ::IO::PathView firstPathSegment(*inputPathIter); + auto inputPathNextIter = inputPathIter == inputPathView.end() ? inputPathView.end() : AZStd::next(inputPathIter, 1); + AZ::IO::PathView remainingPath = inputPathNextIter != inputPathView.end() ? + AZStd::string_view(inputPathNextIter->Native().begin(), inputPathView.Native().end()) + : AZStd::string_view{}; + if (!remainingPath.empty()) { - auto dirEntryIter = m_mapDirs.find(*pathEntry); + auto dirEntryIter = m_mapDirs.find(firstPathSegment); // we have a subdirectory here - create the file in it if (dirEntryIter == m_mapDirs.end()) { - dirEntryIter = m_mapDirs.emplace(*pathEntry, AZStd::make_unique()).first; + dirEntryIter = m_mapDirs.emplace(firstPathSegment, AZStd::make_unique()).first; } - return dirEntryIter->second->Add(szPath); + return dirEntryIter->second->Add(remainingPath); } // Add the filename - auto fileEntryIter = m_mapFiles.find(*pathEntry); + auto fileEntryIter = m_mapFiles.find(firstPathSegment); if (fileEntryIter == m_mapFiles.end()) { - fileEntryIter = m_mapFiles.emplace(*pathEntry, AZStd::make_unique()).first; + fileEntryIter = m_mapFiles.emplace(firstPathSegment, AZStd::make_unique()).first; } return fileEntryIter->second.get(); } // adds a file to this directory - ErrorEnum FileEntryTree::Add(AZStd::string_view szPath, const FileEntryBase& file) + ErrorEnum FileEntryTree::Add(AZ::IO::PathView szPath, const FileEntryBase& file) { FileEntry* pFile = Add(szPath); if (!pFile) @@ -63,7 +67,7 @@ namespace AZ::IO::ZipDir return ZD_ERROR_SUCCESS; } - // returns the number of files in this tree, including this and sublevels + // returns the number of files in this tree, including this and subdirectories uint32_t FileEntryTree::NumFilesTotal() const { uint32_t numFiles = aznumeric_cast(m_mapFiles.size()); @@ -91,21 +95,6 @@ namespace AZ::IO::ZipDir m_mapFiles.clear(); } - size_t FileEntryTree::GetSize() const - { - size_t nSize = sizeof(*this); - for (const auto& [dirname, dirEntry] : m_mapDirs) - { - nSize += dirname.size() + sizeof(decltype(m_mapDirs)::value_type) + dirEntry->GetSize(); - } - - for (const auto& [filename, fileEntry] : m_mapFiles) - { - nSize += filename.size() + sizeof(decltype(m_mapFiles)::value_type); - } - return nSize; - } - bool FileEntryTree::IsOwnerOf(const FileEntry* pFileEntry) const { for (const auto& [path, fileEntry] : m_mapFiles) @@ -127,7 +116,7 @@ namespace AZ::IO::ZipDir return false; } - FileEntryTree* FileEntryTree::FindDir(AZStd::string_view szDirName) + FileEntryTree* FileEntryTree::FindDir(AZ::IO::PathView szDirName) { if (auto it = m_mapDirs.find(szDirName); it != m_mapDirs.end()) { @@ -137,7 +126,7 @@ namespace AZ::IO::ZipDir return nullptr; } - FileEntryTree::FileMap::iterator FileEntryTree::FindFile(AZStd::string_view szFileName) + FileEntryTree::FileMap::iterator FileEntryTree::FindFile(AZ::IO::PathView szFileName) { return m_mapFiles.find(szFileName); } @@ -152,7 +141,7 @@ namespace AZ::IO::ZipDir return it == GetDirEnd() ? nullptr : it->second.get(); } - ErrorEnum FileEntryTree::RemoveDir(AZStd::string_view szDirName) + ErrorEnum FileEntryTree::RemoveDir(AZ::IO::PathView szDirName) { SubdirMap::iterator itRemove = m_mapDirs.find(szDirName); if (itRemove == m_mapDirs.end()) @@ -164,7 +153,13 @@ namespace AZ::IO::ZipDir return ZD_ERROR_SUCCESS; } - ErrorEnum FileEntryTree::RemoveFile(AZStd::string_view szFileName) + ErrorEnum FileEntryTree::RemoveAll() + { + Clear(); + return ZD_ERROR_SUCCESS; + } + + ErrorEnum FileEntryTree::RemoveFile(AZ::IO::PathView szFileName) { FileMap::iterator itRemove = m_mapFiles.find(szFileName); if (itRemove == m_mapFiles.end()) diff --git a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.h b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.h index cfe539e896..9bdc047a7a 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.h +++ b/Code/Framework/AzFramework/AzFramework/Archive/ZipDirTree.h @@ -10,6 +10,7 @@ #pragma once #include +#include #include #include #include @@ -24,12 +25,12 @@ namespace AZ::IO::ZipDir // adds a file to this directory // Function can modify szPath input - ErrorEnum Add(AZStd::string_view szPath, const FileEntryBase& file); + ErrorEnum Add(AZ::IO::PathView szPath, const FileEntryBase& file); // Adds or finds the file. Returns non-initialized structure if it was added, // or an IsInitialized() structure if it was found // Function can modify szPath input - FileEntry* Add(AZStd::string_view szPath); + FileEntry* Add(AZ::IO::PathView szPath); // returns the number of files in this tree, including this and sublevels uint32_t NumFilesTotal() const; @@ -45,24 +46,18 @@ namespace AZ::IO::ZipDir m_mapFiles.swap(rThat.m_mapFiles); } - size_t GetSize() const; - bool IsOwnerOf(const FileEntry* pFileEntry) const; // subdirectories - using SubdirMap = AZStd::map>; + using SubdirMap = AZStd::map>; // file entries - using FileMap = AZStd::map>; + using FileMap = AZStd::map>; - FileEntryTree* FindDir(AZStd::string_view szDirName); - ErrorEnum RemoveDir (AZStd::string_view szDirName); - ErrorEnum RemoveAll () - { - Clear(); - return ZD_ERROR_SUCCESS; - } - FileMap::iterator FindFile(AZStd::string_view szFileName); - ErrorEnum RemoveFile(AZStd::string_view szFileName); + FileEntryTree* FindDir(AZ::IO::PathView szDirName); + ErrorEnum RemoveDir(AZ::IO::PathView szDirName); + ErrorEnum RemoveAll(); + FileMap::iterator FindFile(AZ::IO::PathView szFileName); + ErrorEnum RemoveFile(AZ::IO::PathView szFileName); // the FileEntryTree is simultaneously an entry in the dir list AND the directory header FileEntryTree* GetDirectory() { @@ -75,8 +70,8 @@ namespace AZ::IO::ZipDir SubdirMap::iterator GetDirBegin() { return m_mapDirs.begin(); } SubdirMap::iterator GetDirEnd() { return m_mapDirs.end(); } uint32_t NumDirs() const { return aznumeric_cast(m_mapDirs.size()); } - AZStd::string_view GetFileName(FileMap::iterator it) { return it->first; } - AZStd::string_view GetDirName(SubdirMap::iterator it) { return it->first; } + AZStd::string_view GetFileName(FileMap::iterator it) { return it->first.Native(); } + AZStd::string_view GetDirName(SubdirMap::iterator it) { return it->first.Native(); } FileEntry* GetFileEntry(FileMap::iterator it); FileEntryTree* GetDirEntry(SubdirMap::iterator it); diff --git a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp index 50190ac7d5..4072c17ea0 100644 --- a/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp +++ b/Code/Framework/AzFramework/AzFramework/IO/LocalFileIO.cpp @@ -734,7 +734,7 @@ namespace AZ { if (AZ::StringFunc::StartsWith(pathStrView, aliasKey)) { - // Reduce of the size result result path by the size of the and add the resolved alias size + // Add to the size of result path by the resolved alias length - the alias key length AZStd::string_view postAliasView = pathStrView.substr(aliasKey.size()); size_t requiredFixedMaxPathSize = postAliasView.size(); requiredFixedMaxPathSize += aliasValue.size(); diff --git a/Code/Framework/AzFramework/CMakeLists.txt b/Code/Framework/AzFramework/CMakeLists.txt index 1164d81f04..6f6e47855e 100644 --- a/Code/Framework/AzFramework/CMakeLists.txt +++ b/Code/Framework/AzFramework/CMakeLists.txt @@ -29,7 +29,6 @@ ly_add_target( AZ::AzCore PUBLIC AZ::GridMate - 3rdParty::md5 3rdParty::zlib 3rdParty::zstd 3rdParty::lz4 diff --git a/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp b/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp index b8eb8d2f9f..d2a6d63db5 100644 --- a/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp +++ b/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp @@ -68,7 +68,7 @@ namespace UnitTest return false; } - if (!archive->OpenPack(path, AZ::IO::IArchive::FLAGS_PATH_REAL)) + if (!archive->OpenPack(path)) { return false; } diff --git a/Code/Framework/AzFramework/Tests/ArchiveTests.cpp b/Code/Framework/AzFramework/Tests/ArchiveTests.cpp index f3764a5e96..ecb495cd61 100644 --- a/Code/Framework/AzFramework/Tests/ArchiveTests.cpp +++ b/Code/Framework/AzFramework/Tests/ArchiveTests.cpp @@ -30,16 +30,17 @@ namespace UnitTest : public ScopedAllocatorSetupFixture { public: + // Use an Immediately invoked function to initlaize the m_stackRecordLevels value of the AZ::SystemAllocator::Descriptor class ArchiveTestFixture() - : m_application{ AZStd::make_unique() } + : ScopedAllocatorSetupFixture( + []() { AZ::SystemAllocator::Descriptor desc; desc.m_stackRecordLevels = 30; return desc; }() + ) + , m_application{ AZStd::make_unique() } { } void SetUp() override { - AZ::ComponentApplication::Descriptor descriptor; - descriptor.m_stackRecordLevels = 30; - AZ::SettingsRegistryInterface* registry = AZ::SettingsRegistry::Get(); auto projectPathKey = @@ -47,7 +48,7 @@ namespace UnitTest registry->Set(projectPathKey, "AutomatedTesting"); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*registry); - m_application->Start(descriptor); + m_application->Start({}); // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash // in the unit tests. @@ -68,7 +69,7 @@ namespace UnitTest return false; } - return archive->OpenPack(path, AZ::IO::IArchive::FLAGS_PATH_REAL) && archive->ClosePack(path); + return archive->OpenPack(path) && archive->ClosePack(path); } template @@ -116,7 +117,7 @@ namespace UnitTest { // Canary tests first - AZ::IO::HandleType fileHandle = archive->FOpen(testFilePath, "rb", 0); + AZ::IO::HandleType fileHandle = archive->FOpen(testFilePath, "rb"); ASSERT_NE(AZ::IO::InvalidHandle, fileHandle); @@ -136,9 +137,9 @@ namespace UnitTest // open already open file and call FGetCachedFileData fileSize = 0; { - AZ::IO::HandleType fileHandle2 = archive->FOpen(testFilePath, "rb", 0); + AZ::IO::HandleType fileHandle2 = archive->FOpen(testFilePath, "rb"); char* pFileBuffer3 = (char*)archive->FGetCachedFileData(fileHandle2, fileSize); - ASSERT_NE(nullptr,pFileBuffer3); + ASSERT_NE(nullptr, pFileBuffer3); EXPECT_EQ(dataLen, fileSize); EXPECT_EQ(0, memcmp(pFileBuffer3, testData, dataLen)); archive->FClose(fileHandle2); @@ -174,7 +175,7 @@ namespace UnitTest // Multithreaded Test #2 reading from the same file concurrently auto concurrentArchiveFileReadFunc = [archive, testFilePath, dataLen, testData]() { - AZ::IO::HandleType threadFileHandle = archive->FOpen(testFilePath, "rb", 0); + AZ::IO::HandleType threadFileHandle = archive->FOpen(testFilePath, "rb"); if (threadFileHandle == AZ::IO::InvalidHandle) { @@ -305,7 +306,7 @@ namespace UnitTest // open and fetch the opened pak file using a *.pak AZStd::vector fullPaths; - archive->OpenPacks("@usercache@/*.pak", AZ::IO::IArchive::EPathResolutionRules::FLAGS_PATH_REAL, &fullPaths); + archive->OpenPacks("@usercache@/*.pak", &fullPaths); EXPECT_TRUE(AZStd::any_of(fullPaths.cbegin(), fullPaths.cend(), [](auto& path) { return path.ends_with("one.pak"); })); EXPECT_TRUE(AZStd::any_of(fullPaths.cbegin(), fullPaths.cend(), [](auto& path) { return path.ends_with("two.pak"); })); } @@ -712,13 +713,16 @@ namespace UnitTest EXPECT_TRUE(cpfio.Exists("@log@/unittesttemp/copiedfile2.xml")); // find files test. - + AZ::IO::FixedMaxPath resolvedTestFilePath; + EXPECT_TRUE(cpfio.ResolvePath(resolvedTestFilePath, AZ::IO::PathView("@assets@/testfile.xml"))); bool foundIt = false; // note that this file exists only in the archive. - cpfio.FindFiles("@assets@", "*.xml", [&foundIt](const char* foundName) + cpfio.FindFiles("@assets@", "*.xml", [&foundIt, &cpfio, &resolvedTestFilePath](const char* foundName) { + AZ::IO::FixedMaxPath resolvedFoundPath; + EXPECT_TRUE(cpfio.ResolvePath(resolvedFoundPath, AZ::IO::PathView(foundName))); // according to the contract stated in the FileIO.h file, we expect full paths. (Aliases are full paths) - if (azstricmp(foundName, "@assets@/testfile.xml") == 0) + if (resolvedTestFilePath == resolvedFoundPath) { foundIt = true; return false; @@ -803,40 +807,49 @@ namespace UnitTest EXPECT_TRUE(archive->ClosePack(realNameBuf)); } - TEST_F(ArchiveTestFixture, IResourceList_Add_EmptyFileName_DoesNotCrash) + TEST_F(ArchiveTestFixture, IResourceList_Add_EmptyFileName_DoesNotInsert) { AZ::IO::IResourceList* reslist = AZ::Interface::Get()->GetResourceList(AZ::IO::IArchive::RFOM_EngineStartup); ASSERT_NE(nullptr, reslist); reslist->Clear(); reslist->Add(""); - EXPECT_STREQ(reslist->GetFirst(), ""); - reslist->Clear(); + EXPECT_EQ(nullptr, reslist->GetFirst()); } - TEST_F(ArchiveTestFixture, IResourceList_Add_RegularFileName_NormalizesAppropriately) + TEST_F(ArchiveTestFixture, IResourceList_Add_RegularFileName_ResolvesAppropriately) { AZ::IO::IResourceList* reslist = AZ::Interface::Get()->GetResourceList(AZ::IO::IArchive::RFOM_EngineStartup); ASSERT_NE(nullptr, reslist); + AZ::IO::FileIOBase* ioBase = AZ::IO::FileIOBase::GetInstance(); + ASSERT_NE(nullptr, ioBase); + AZ::IO::FixedMaxPath resolvedTestPath; + EXPECT_TRUE(ioBase->ResolvePath(resolvedTestPath, "blah/blah/abcde")); + reslist->Clear(); reslist->Add("blah\\blah/AbCDE"); - - // it normalizes the string, so the slashes flip and everything is lowercased. - EXPECT_STREQ(reslist->GetFirst(), "blah/blah/abcde"); + AZ::IO::FixedMaxPath resolvedAddedPath; + EXPECT_TRUE(ioBase->ResolvePath(resolvedAddedPath, reslist->GetFirst())); + EXPECT_EQ(resolvedTestPath, resolvedAddedPath); reslist->Clear(); } - TEST_F(ArchiveTestFixture, IResourceList_Add_ReallyShortFileName_NormalizesAppropriately) + TEST_F(ArchiveTestFixture, IResourceList_Add_ReallyShortFileName_ResolvesAppropriately) { AZ::IO::IResourceList* reslist = AZ::Interface::Get()->GetResourceList(AZ::IO::IArchive::RFOM_EngineStartup); ASSERT_NE(nullptr, reslist); + AZ::IO::FileIOBase* ioBase = AZ::IO::FileIOBase::GetInstance(); + ASSERT_NE(nullptr, ioBase); + AZ::IO::FixedMaxPath resolvedTestPath; + EXPECT_TRUE(ioBase->ResolvePath(resolvedTestPath, "a")); + reslist->Clear(); reslist->Add("A"); - - // it normalizes the string, so the slashes flip and everything is lowercased. - EXPECT_STREQ(reslist->GetFirst(), "a"); + AZ::IO::FixedMaxPath resolvedAddedPath; + EXPECT_TRUE(ioBase->ResolvePath(resolvedAddedPath, reslist->GetFirst())); + EXPECT_EQ(resolvedTestPath, resolvedAddedPath); reslist->Clear(); } @@ -848,7 +861,7 @@ namespace UnitTest AZ::IO::FileIOBase* ioBase = AZ::IO::FileIOBase::GetInstance(); ASSERT_NE(nullptr, ioBase); - const char *assetsPath = ioBase->GetAlias("@assets@"); + const char* assetsPath = ioBase->GetAlias("@assets@"); ASSERT_NE(nullptr, assetsPath); auto stringToAdd = AZ::IO::Path(assetsPath) / "textures" / "test.dds"; @@ -864,195 +877,4 @@ namespace UnitTest EXPECT_EQ(resolvedAddedPath, resolvedResourcePath); reslist->Clear(); } - - - class ArchiveUnitTestsWithAllocators - : public ScopedAllocatorSetupFixture - { - protected: - - void SetUp() override - { - m_localFileIO = aznew AZ::IO::LocalFileIO(); - AZ::IO::FileIOBase::SetDirectInstance(m_localFileIO); - m_localFileIO->SetAlias(m_firstAlias.c_str(), m_firstAliasPath.c_str()); - m_localFileIO->SetAlias(m_secondAlias.c_str(), m_secondAliasPath.c_str()); - } - - void TearDown() override - { - AZ::IO::FileIOBase::SetDirectInstance(nullptr); - delete m_localFileIO; - m_localFileIO = nullptr; - } - - AZ::IO::FileIOBase* m_localFileIO = nullptr; - AZStd::string m_firstAlias = "@devassets@"; - AZStd::string m_firstAliasPath = "devassets_absolutepath"; - AZStd::string m_secondAlias = "@assets@"; - AZStd::string m_secondAliasPath = "assets_absolutepath"; - }; - - // ConvertAbsolutePathToAliasedPath tests are built to verify existing behavior doesn't change. - // It's a legacy function and the actual intended behavior is unknown, so these are black box unit tests. - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_NullString_ReturnsSuccess) - { - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath(nullptr); - EXPECT_TRUE(conversionResult); - EXPECT_TRUE(conversionResult->empty()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_NoAliasInSource_ReturnsSource) - { - AZStd::string sourceString("NoAlias"); - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath(sourceString.c_str()); - EXPECT_TRUE(conversionResult); - // ConvertAbsolutePathToAliasedPath returns sourceString if there is no alias in the source. - EXPECT_STREQ(sourceString.c_str(), conversionResult->c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_NullAliasToLookFor_ReturnsSource) - { - AZStd::string sourceString("NoAlias"); - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath(sourceString.c_str(), nullptr); - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(sourceString.c_str(), conversionResult->c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_NullAliasToReplaceWith_ReturnsSource) - { - AZStd::string sourceString("NoAlias"); - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath(sourceString.c_str(), "@SomeAlias", nullptr); - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(sourceString.c_str(), conversionResult->c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_NullAliases_ReturnsSource) - { - AZStd::string sourceString("NoAlias"); - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath(sourceString.c_str(), nullptr, nullptr); - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(sourceString.c_str(), conversionResult->c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_AbsPathInSource_ReturnsReplacedAlias) - { - // ConvertAbsolutePathToAliasedPath only replaces data if GetDirectInstance is valid. - EXPECT_TRUE(AZ::IO::FileIOBase::GetDirectInstance() != nullptr); - - const char* fullPath = AZ::IO::FileIOBase::GetDirectInstance()->GetAlias(m_firstAlias.c_str()); - AZStd::string sourceString = AZStd::string::format("%s" AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "SomeStringWithAlias", fullPath); - AZStd::string expectedResult = AZStd::string::format("%s" AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "somestringwithalias", m_secondAlias.c_str()); - - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath( - sourceString.c_str(), - m_firstAlias.c_str(), // find any instance of FirstAlias in sourceString - m_secondAlias.c_str()); // replace it with SecondAlias - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(conversionResult->c_str(), expectedResult.c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_AliasInSource_ReturnsReplacedAlias) - { - // ConvertAbsolutePathToAliasedPath only replaces data if GetDirectInstance is valid. - EXPECT_TRUE(AZ::IO::FileIOBase::GetDirectInstance() != nullptr); - - AZStd::string sourceString = AZStd::string::format("%s" AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "SomeStringWithAlias", m_firstAlias.c_str()); - AZStd::string expectedResult = AZStd::string::format("%s" AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "somestringwithalias", m_secondAlias.c_str()); - - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath( - sourceString.c_str(), - m_firstAlias.c_str(), // find any instance of FirstAlias in sourceString - m_secondAlias.c_str()); // replace it with SecondAlias - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(conversionResult->c_str(), expectedResult.c_str()); - } - -#if AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_AbsPathInSource_DOSSlashInSource_ReturnsReplacedAlias) - { - // ConvertAbsolutePathToAliasedPath only replaces data if GetDirectInstance is valid. - EXPECT_TRUE(AZ::IO::FileIOBase::GetDirectInstance() != nullptr); - - const char* fullPath = AZ::IO::FileIOBase::GetDirectInstance()->GetAlias(m_firstAlias.c_str()); - AZStd::string sourceString = AZStd::string::format("%s" AZ_WRONG_DATABASE_SEPARATOR_STRING "SomeStringWithAlias", fullPath); - AZStd::string expectedResult = AZStd::string::format("%s" AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING "somestringwithalias", m_secondAlias.c_str()); - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath( - sourceString.c_str(), - m_firstAlias.c_str(), // find any instance of FirstAlias in sourceString - m_secondAlias.c_str()); // replace it with SecondAlias - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(conversionResult->c_str(), expectedResult.c_str()); - } -#endif // AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_AbsPathInSource_UNIXSlashInSource_ReturnsReplacedAlias) - { - // ConvertAbsolutePathToAliasedPath only replaces data if GetDirectInstance is valid. - EXPECT_TRUE(AZ::IO::FileIOBase::GetDirectInstance() != nullptr); - - const char* fullPath = AZ::IO::FileIOBase::GetDirectInstance()->GetAlias(m_firstAlias.c_str()); - AZStd::string sourceString = AZStd::string::format("%s" AZ_CORRECT_DATABASE_SEPARATOR_STRING "SomeStringWithAlias", fullPath); - AZStd::string expectedResult = AZStd::string::format("%s" AZ_CORRECT_DATABASE_SEPARATOR_STRING "somestringwithalias", m_secondAlias.c_str()); - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath( - sourceString.c_str(), - m_firstAlias.c_str(), // find any instance of FirstAlias in sourceString - m_secondAlias.c_str()); // replace it with SecondAlias - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(conversionResult->c_str(), expectedResult.c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_AliasInSource_DOSSlashInSource_ReturnsReplacedAlias) - { - // ConvertAbsolutePathToAliasedPath only replaces data if GetDirectInstance is valid. - EXPECT_TRUE(AZ::IO::FileIOBase::GetDirectInstance() != nullptr); - - AZStd::string sourceString = AZStd::string::format("%s" AZ_WRONG_DATABASE_SEPARATOR_STRING "SomeStringWithAlias", m_firstAlias.c_str()); - AZStd::string expectedResult = AZStd::string::format("%s" AZ_WRONG_DATABASE_SEPARATOR_STRING "somestringwithalias", m_secondAlias.c_str()); - - // sourceString is now (firstAlias)SomeStringWithAlias - - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath( - sourceString.c_str(), - m_firstAlias.c_str(), // find any instance of FirstAlias in sourceString - m_secondAlias.c_str()); // replace it with SecondAlias - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(conversionResult->c_str(), expectedResult.c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_AliasInSource_UNIXSlashInSource_ReturnsReplacedAlias) - { - // ConvertAbsolutePathToAliasedPath only replaces data if GetDirectInstance is valid. - EXPECT_TRUE(AZ::IO::FileIOBase::GetDirectInstance() != nullptr); - - AZStd::string sourceString = AZStd::string::format("%s" AZ_CORRECT_DATABASE_SEPARATOR_STRING "SomeStringWithAlias", m_firstAlias.c_str()); - AZStd::string expectedResult = AZStd::string::format("%s" AZ_CORRECT_DATABASE_SEPARATOR_STRING "somestringwithalias", m_secondAlias.c_str()); - - // sourceString is now (firstAlias)SomeStringWithAlias - - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath( - sourceString.c_str(), - m_firstAlias.c_str(), // find any instance of FirstAlias in sourceString - m_secondAlias.c_str()); // replace it with SecondAlias - EXPECT_TRUE(conversionResult); - EXPECT_STREQ(conversionResult->c_str(), expectedResult.c_str()); - } - - TEST_F(ArchiveUnitTestsWithAllocators, ConvertAbsolutePathToAliasedPath_SourceLongerThanMaxPath_ReturnsFailure) - { - const int longPathArraySize = AZ::IO::MaxPathLength + 2; - char longPath[longPathArraySize]; - memset(longPath, 'a', sizeof(char) * longPathArraySize); - longPath[longPathArraySize - 1] = '\0'; - AZ_TEST_START_TRACE_SUPPRESSION; - auto conversionResult = AZ::IO::ArchiveInternal::ConvertAbsolutePathToAliasedPath(longPath); - AZ_TEST_STOP_TRACE_SUPPRESSION(1); - EXPECT_FALSE(conversionResult); - } - - class ArchivePathCompareTestFixture - : public ScopedAllocatorSetupFixture - , public ::testing::WithParamInterface> - { - }; } diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index c42720311c..f759857505 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -9,12 +9,10 @@ #include "GameApplication.h" #include #include -#include -#include -#include -#include +#include + +#include #include -#include #include namespace AzGameFramework @@ -26,6 +24,28 @@ namespace AzGameFramework GameApplication::GameApplication(int argc, char** argv) : Application(&argc, &argv) { + // In the Launcher Applications the Settings Registry + // can read from the FileIOBase instance if available + m_settingsRegistry->SetUseFileIO(true); + + // Attempt to mount the engine pak from the Executable Directory + // at the Assets alias, otherwise to attempting to mount the engine pak + // from the Cache folder + AZ::IO::FixedMaxPath enginePakPath = AZ::Utils::GetExecutableDirectory(); + enginePakPath /= "Engine.pak"; + if (m_archiveFileIO->Exists(enginePakPath.c_str())) + { + m_archive->OpenPack("@assets@", enginePakPath.Native()); + } + else if (enginePakPath.clear(); m_settingsRegistry->Get(enginePakPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder)) + { + // fall back to checking if there is an Engine.pak in the Asset Cache + enginePakPath /= "Engine.pak"; + if (m_archiveFileIO->Exists(enginePakPath.c_str())) + { + m_archive->OpenPack("@assets@", enginePakPath.Native()); + } + } } GameApplication::~GameApplication() @@ -50,8 +70,8 @@ namespace AzGameFramework AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false); - AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); #endif + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_TargetBuildDependencyRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); diff --git a/Code/Legacy/CryCommon/CryFile.h b/Code/Legacy/CryCommon/CryFile.h index 56d7097344..8850b90932 100644 --- a/Code/Legacy/CryCommon/CryFile.h +++ b/Code/Legacy/CryCommon/CryFile.h @@ -9,11 +9,11 @@ // Description : File wrapper. #pragma once -#include -#include -#include -#include +#include +#include #include +#include +#include ////////////////////////////////////////////////////////////////////////// #define CRYFILE_MAX_PATH 260 @@ -28,7 +28,7 @@ public: CCryFile(const char* filename, const char* mode); ~CCryFile(); - bool Open(const char* filename, const char* mode, int nOpenFlagsEx = 0); + bool Open(const char* filename, const char* mode); void Close(); // Summary: @@ -58,15 +58,7 @@ public: // Description: // Retrieves the filename of the selected file. - const char* GetFilename() const { return m_filename; }; - - // Description: - // Retrieves the filename after adjustment to the real relative to engine root path. - // Example: - // Original filename "textures/red.dds" adjusted filename will look like "game/textures/red.dds" - // Return: - // Adjusted filename, this is a pointer to a static string, copy return value if you want to keep it. - const char* GetAdjustedFilename() const; + const char* GetFilename() const { return m_filename.c_str(); }; // Summary: // Checks if file is opened from Archive file. @@ -74,12 +66,11 @@ public: // Summary: // Gets path of archive this file is in. - const char* GetPakPath() const; + AZ::IO::PathView GetPakPath() const; private: - char m_filename[CRYFILE_MAX_PATH]; + AZ::IO::FixedMaxPath m_filename; AZ::IO::HandleType m_fileHandle; - AZ::IO::IArchive* m_pIArchive; }; // Summary: @@ -87,14 +78,12 @@ private: inline CCryFile::CCryFile() { m_fileHandle = AZ::IO::InvalidHandle; - m_pIArchive = gEnv ? gEnv->pCryPak : NULL; } ////////////////////////////////////////////////////////////////////////// inline CCryFile::CCryFile(const char* filename, const char* mode) { m_fileHandle = AZ::IO::InvalidHandle; - m_pIArchive = gEnv ? gEnv->pCryPak : NULL; Open(filename, mode); } @@ -109,22 +98,17 @@ inline CCryFile::~CCryFile() // For nOpenFlagsEx see IArchive::EFOpenFlags // See also: // IArchive::EFOpenFlags -inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlagsEx) +inline bool CCryFile::Open(const char* filename, const char* mode) { - char tempfilename[CRYFILE_MAX_PATH] = ""; - azstrcpy(tempfilename, CRYFILE_MAX_PATH, filename); - + m_filename = filename; #if !defined (_RELEASE) - if (gEnv && gEnv->IsEditor() && gEnv->pConsole) + if (auto console = AZ::Interface::Get(); console != nullptr) { - ICVar* const pCvar = gEnv->pConsole->GetCVar("ed_lowercasepaths"); - if (pCvar) + if (bool lowercasePaths{}; console->GetCvarValue("ed_lowercasepaths", lowercasePaths) == AZ::GetValueResult::Success) { - const int lowercasePaths = pCvar->GetIVal(); if (lowercasePaths) { - const AZStd::string lowerString = PathUtil::ToLower(tempfilename); - azstrcpy(tempfilename, CRYFILE_MAX_PATH, lowerString.c_str()); + AZStd::to_lower(m_filename.Native().begin(), m_filename.Native().end()); } } } @@ -133,16 +117,8 @@ inline bool CCryFile::Open(const char* filename, const char* mode, int nOpenFlag { Close(); } - azstrcpy(m_filename, CRYFILE_MAX_PATH, tempfilename); - if (m_pIArchive) - { - m_fileHandle = m_pIArchive->FOpen(tempfilename, mode, nOpenFlagsEx); - } - else - { - AZ::IO::FileIOBase::GetInstance()->Open(tempfilename, AZ::IO::GetOpenModeFromStringMode(mode), m_fileHandle); - } + AZ::IO::FileIOBase::GetInstance()->Open(m_filename.c_str(), AZ::IO::GetOpenModeFromStringMode(mode), m_fileHandle); return m_fileHandle != AZ::IO::InvalidHandle; } @@ -152,27 +128,17 @@ inline void CCryFile::Close() { if (m_fileHandle != AZ::IO::InvalidHandle) { - if (m_pIArchive) - { - m_pIArchive->FClose(m_fileHandle); - } - else - { - AZ::IO::FileIOBase::GetInstance()->Close(m_fileHandle); - } + AZ::IO::FileIOBase::GetInstance()->Close(m_fileHandle); + m_fileHandle = AZ::IO::InvalidHandle; - m_filename[0] = 0; + m_filename.clear(); } } ////////////////////////////////////////////////////////////////////////// inline size_t CCryFile::Write(const void* lpBuf, size_t nSize) { - assert(m_fileHandle != AZ::IO::InvalidHandle); - if (m_pIArchive) - { - return m_pIArchive->FWrite(lpBuf, 1, nSize, m_fileHandle); - } + AZ_Assert(m_fileHandle != AZ::IO::InvalidHandle, "File Handle is invalid. Cannot Write"); if (AZ::IO::FileIOBase::GetInstance()->Write(m_fileHandle, lpBuf, nSize)) { @@ -185,11 +151,7 @@ inline size_t CCryFile::Write(const void* lpBuf, size_t nSize) ////////////////////////////////////////////////////////////////////////// inline size_t CCryFile::ReadRaw(void* lpBuf, size_t nSize) { - assert(m_fileHandle != AZ::IO::InvalidHandle); - if (m_pIArchive) - { - return m_pIArchive->FReadRaw(lpBuf, 1, nSize, m_fileHandle); - } + AZ_Assert(m_fileHandle != AZ::IO::InvalidHandle, "File Handle is invalid. Cannot Read"); AZ::u64 bytesRead = 0; AZ::IO::FileIOBase::GetInstance()->Read(m_fileHandle, lpBuf, nSize, false, &bytesRead); @@ -200,11 +162,7 @@ inline size_t CCryFile::ReadRaw(void* lpBuf, size_t nSize) ////////////////////////////////////////////////////////////////////////// inline size_t CCryFile::GetLength() { - assert(m_fileHandle != AZ::IO::InvalidHandle); - if (m_pIArchive) - { - return m_pIArchive->FGetSize(m_fileHandle); - } + AZ_Assert(m_fileHandle != AZ::IO::InvalidHandle, "File Handle is invalid. Cannot query file length"); //long curr = ftell(m_file); AZ::u64 size = 0; AZ::IO::FileIOBase::GetInstance()->Size(m_fileHandle, size); @@ -214,11 +172,7 @@ inline size_t CCryFile::GetLength() ////////////////////////////////////////////////////////////////////////// inline size_t CCryFile::Seek(size_t seek, int mode) { - assert(m_fileHandle != AZ::IO::InvalidHandle); - if (m_pIArchive) - { - return m_pIArchive->FSeek(m_fileHandle, long(seek), mode); - } + AZ_Assert(m_fileHandle != AZ::IO::InvalidHandle, "File Handle is invalid. Cannot seek in unopen file"); if (AZ::IO::FileIOBase::GetInstance()->Seek(m_fileHandle, seek, AZ::IO::GetSeekTypeFromFSeekMode(mode))) { @@ -230,45 +184,25 @@ inline size_t CCryFile::Seek(size_t seek, int mode) ////////////////////////////////////////////////////////////////////////// inline bool CCryFile::IsInPak() const { - if (m_fileHandle != AZ::IO::InvalidHandle && m_pIArchive) + if (auto archive = AZ::Interface::Get(); + m_fileHandle != AZ::IO::InvalidHandle && archive != nullptr) { - return m_pIArchive->GetFileArchivePath(m_fileHandle) != NULL; + return !archive->GetFileArchivePath(m_fileHandle).empty(); } return false; } ////////////////////////////////////////////////////////////////////////// -inline const char* CCryFile::GetPakPath() const +inline AZ::IO::PathView CCryFile::GetPakPath() const { - if (m_fileHandle != AZ::IO::InvalidHandle && m_pIArchive) + if (auto archive = AZ::Interface::Get(); + m_fileHandle != AZ::IO::InvalidHandle && archive != nullptr) { - const char* sPath = m_pIArchive->GetFileArchivePath(m_fileHandle); - if (sPath != NULL) + if (AZ::IO::PathView sPath(archive->GetFileArchivePath(m_fileHandle)); sPath.empty()) { return sPath; } } - return ""; + return {}; } - -////////////////////////////////////////////////////////////////////////// -inline const char* CCryFile::GetAdjustedFilename() const -{ - static char szAdjustedFile[AZ::IO::IArchive::MaxPath]; - assert(m_pIArchive); - if (!m_pIArchive) - { - return ""; - } - - // Gets mod path to file. - const char* gameUrl = m_pIArchive->AdjustFileName(m_filename, szAdjustedFile, AZ::IO::IArchive::MaxPath, 0); - - // Returns standard path otherwise. - if (gameUrl != &szAdjustedFile[0]) - { - azstrcpy(szAdjustedFile, AZ::IO::IArchive::MaxPath, gameUrl); - } - return szAdjustedFile; -} diff --git a/Code/Legacy/CryCommon/CryPath.h b/Code/Legacy/CryCommon/CryPath.h index 046006f738..197c9b2d56 100644 --- a/Code/Legacy/CryCommon/CryPath.h +++ b/Code/Legacy/CryCommon/CryPath.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "platform.h" diff --git a/Code/Legacy/CryCommon/Mocks/ICryPakMock.h b/Code/Legacy/CryCommon/Mocks/ICryPakMock.h index ab3b3875af..50cae45991 100644 --- a/Code/Legacy/CryCommon/Mocks/ICryPakMock.h +++ b/Code/Legacy/CryCommon/Mocks/ICryPakMock.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -20,35 +21,23 @@ struct CryPakMock MOCK_METHOD5(AdjustFileName, const char*(AZStd::string_view src, char* dst, size_t dstSize, uint32_t nFlags, bool skipMods)); MOCK_METHOD1(Init, bool(AZStd::string_view szBasePath)); MOCK_METHOD0(Release, void()); - MOCK_CONST_METHOD1(IsInstalledToHDD, bool(AZStd::string_view acFilePath)); - MOCK_METHOD5(OpenPack, bool(AZStd::string_view, uint32_t, AZStd::intrusive_ptr, AZStd::fixed_string*, bool)); - MOCK_METHOD6(OpenPack, bool(AZStd::string_view, AZStd::string_view, uint32_t, AZStd::intrusive_ptr, AZStd::fixed_string*, bool)); - MOCK_METHOD3(OpenPacks, bool(AZStd::string_view pWildcard, uint32_t nFlags, AZStd::vector>* pFullPaths)); - MOCK_METHOD4(OpenPacks, bool(AZStd::string_view pBindingRoot, AZStd::string_view pWildcard, uint32_t nFlags, AZStd::vector>* pFullPaths)); - MOCK_METHOD2(ClosePack, bool(AZStd::string_view pName, uint32_t nFlags)); - MOCK_METHOD2(ClosePacks, bool(AZStd::string_view pWildcard, uint32_t nFlags)); + MOCK_METHOD4(OpenPack, bool(AZStd::string_view, AZStd::intrusive_ptr, AZ::IO::FixedMaxPathString*, bool)); + MOCK_METHOD5(OpenPack, bool(AZStd::string_view, AZStd::string_view, AZStd::intrusive_ptr, AZ::IO::FixedMaxPathString*, bool)); + MOCK_METHOD2(OpenPacks, bool(AZStd::string_view pWildcard, AZStd::vector* pFullPaths)); + MOCK_METHOD3(OpenPacks, bool(AZStd::string_view pBindingRoot, AZStd::string_view pWildcard, AZStd::vector* pFullPaths)); + MOCK_METHOD1(ClosePack, bool(AZStd::string_view pName)); + MOCK_METHOD1(ClosePacks, bool(AZStd::string_view pWildcard)); MOCK_METHOD1(FindPacks, bool(AZStd::string_view pWildcardIn)); - MOCK_METHOD3(SetPacksAccessible, bool(bool bAccessible, AZStd::string_view pWildcard, uint32_t nFlags)); - MOCK_METHOD3(SetPackAccessible, bool(bool bAccessible, AZStd::string_view pName, uint32_t nFlags)); - MOCK_METHOD3(LoadPakToMemory, bool(AZStd::string_view pName, EInMemoryArchiveLocation eLoadToMemory, AZStd::intrusive_ptr pMemoryBlock)); - MOCK_METHOD2(LoadPaksToMemory, void(int nMaxPakSize, bool bLoadToMemory)); - MOCK_METHOD1(GetMod, const char*(int index)); - MOCK_METHOD1(ParseAliases, void(AZStd::string_view szCommandLine)); - MOCK_METHOD3(SetAlias, void(AZStd::string_view szName, AZStd::string_view szAlias, bool bAdd)); - MOCK_METHOD2(GetAlias, const char*(AZStd::string_view szName, bool bReturnSame)); - MOCK_METHOD0(Lock, void()); - MOCK_METHOD0(Unlock, void()); + MOCK_METHOD2(SetPacksAccessible, bool(bool bAccessible, AZStd::string_view pWildcard)); + MOCK_METHOD2(SetPackAccessible, bool(bool bAccessible, AZStd::string_view pName)); MOCK_METHOD1(SetLocalizationFolder, void(AZStd::string_view sLocalizationFolder)); MOCK_CONST_METHOD0(GetLocalizationFolder, const char*()); MOCK_CONST_METHOD0(GetLocalizationRoot, const char*()); - MOCK_METHOD3(FOpen, AZ::IO::HandleType(AZStd::string_view pName, const char* mode, uint32_t nFlags)); - MOCK_METHOD4(FReadRaw, size_t(void* data, size_t length, size_t elems, AZ::IO::HandleType handle)); - MOCK_METHOD3(FReadRawAll, size_t(void* data, size_t nFileSize, AZ::IO::HandleType handle)); - MOCK_METHOD2(FGetCachedFileData, void*(AZ::IO::HandleType handle, size_t & nFileSize)); - MOCK_METHOD4(FWrite, size_t(const void* data, size_t length, size_t elems, AZ::IO::HandleType handle)); - MOCK_METHOD3(FGets, char*(char*, int, AZ::IO::HandleType)); - MOCK_METHOD1(Getc, int(AZ::IO::HandleType)); + MOCK_METHOD2(FOpen, AZ::IO::HandleType(AZStd::string_view pName, const char* mode)); + MOCK_METHOD2(FGetCachedFileData, void*(AZ::IO::HandleType handle, size_t& nFileSize)); + MOCK_METHOD3(FRead, size_t(void* data, size_t bytesToRead, AZ::IO::HandleType handle)); + MOCK_METHOD3(FWrite, size_t(const void* data, size_t bytesToWrite, AZ::IO::HandleType handle)); MOCK_METHOD1(FGetSize, size_t(AZ::IO::HandleType f)); MOCK_METHOD2(FGetSize, size_t(AZStd::string_view pName, bool bAllowUseFileSystem)); MOCK_METHOD1(IsInPak, bool(AZ::IO::HandleType handle)); @@ -70,9 +59,8 @@ struct CryPakMock MOCK_METHOD2(IsFileExist, bool(AZStd::string_view sFilename, EFileSearchLocation)); MOCK_METHOD1(IsFolder, bool(AZStd::string_view sPath)); MOCK_METHOD1(GetFileSizeOnDisk, AZ::IO::IArchive::SignedFileSize(AZStd::string_view filename)); - MOCK_METHOD1(MakeDir, bool(AZStd::string_view szPath)); MOCK_METHOD4(OpenArchive, AZStd::intrusive_ptr (AZStd::string_view szPath, AZStd::string_view bindRoot, uint32_t nFlags, AZStd::intrusive_ptr pData)); - MOCK_METHOD1(GetFileArchivePath, const char* (AZ::IO::HandleType f)); + MOCK_METHOD1(GetFileArchivePath, AZ::IO::PathView (AZ::IO::HandleType f)); MOCK_METHOD5(RawCompress, int(const void* pUncompressed, size_t* pDestSize, void* pCompressed, size_t nSrcSize, int nLevel)); MOCK_METHOD4(RawUncompress, int(void* pUncompressed, size_t* pDestSize, const void* pCompressed, size_t nSrcSize)); MOCK_METHOD1(RecordFileOpen, void(ERecordFileOpenList eList)); @@ -80,24 +68,15 @@ struct CryPakMock MOCK_METHOD1(GetResourceList, AZ::IO::IResourceList * (ERecordFileOpenList eList)); MOCK_METHOD2(SetResourceList, void(ERecordFileOpenList eList, AZ::IO::IResourceList * pResourceList)); MOCK_METHOD0(GetRecordFileOpenList, AZ::IO::IArchive::ERecordFileOpenList()); - MOCK_METHOD2(ComputeCRC, uint32_t(AZStd::string_view szPath, uint32_t nFileOpenFlags)); - MOCK_METHOD4(ComputeMD5, bool(AZStd::string_view szPath, uint8_t* md5, uint32_t nFileOpenFlags, bool useDirectAccess)); MOCK_METHOD1(RegisterFileAccessSink, void(AZ::IO::IArchiveFileAccessSink * pSink)); MOCK_METHOD1(UnregisterFileAccessSink, void(AZ::IO::IArchiveFileAccessSink * pSink)); MOCK_METHOD1(DisableRuntimeFileAccess, void(bool status)); MOCK_METHOD2(DisableRuntimeFileAccess, bool(bool status, AZStd::thread_id threadId)); - MOCK_METHOD2(CheckFileAccessDisabled, bool(AZStd::string_view name, const char* mode)); - MOCK_METHOD1(SetRenderThreadId, void(AZStd::thread_id renderThreadId)); MOCK_CONST_METHOD0(GetPakPriority, AZ::IO::ArchiveLocationPriority()); MOCK_CONST_METHOD1(GetFileOffsetOnMedia, uint64_t(AZStd::string_view szName)); MOCK_CONST_METHOD1(GetFileMediaType, EStreamSourceMediaType(AZStd::string_view szName)); MOCK_METHOD0(GetLevelPackOpenEvent, auto()->LevelPackOpenEvent*); MOCK_METHOD0(GetLevelPackCloseEvent, auto()->LevelPackCloseEvent*); - // Implementations required for variadic functions - virtual int FPrintf([[maybe_unused]] AZ::IO::HandleType handle, [[maybe_unused]] const char* format, ...) PRINTF_PARAMS(3, 4) - { - return 0; - } }; diff --git a/Code/Legacy/CrySystem/ConsoleBatchFile.cpp b/Code/Legacy/CrySystem/ConsoleBatchFile.cpp index d3a0ccf4de..bdc8d6de7d 100644 --- a/Code/Legacy/CrySystem/ConsoleBatchFile.cpp +++ b/Code/Legacy/CrySystem/ConsoleBatchFile.cpp @@ -91,15 +91,15 @@ bool CConsoleBatchFile::ExecuteConfigFile(const char* sFilename) AZStd::string filenameLog; AZStd::string sfn = PathUtil::GetFile(filename); - if (file.Open(filename.c_str(), "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) + if (file.Open(filename.c_str(), "rb")) { filenameLog = AZStd::string("game/") + sfn; } - else if (file.Open((AZStd::string("config/") + sfn).c_str(), "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) + else if (file.Open((AZStd::string("config/") + sfn).c_str(), "rb")) { filenameLog = AZStd::string("game/config/") + sfn; } - else if (file.Open((AZStd::string("./") + sfn).c_str(), "rb", AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK)) + else if (file.Open((AZStd::string("./") + sfn).c_str(), "rb")) { filenameLog = AZStd::string("./") + sfn; } diff --git a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp index c5d364a025..2e61760d8c 100644 --- a/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/LevelSystem.cpp @@ -50,12 +50,11 @@ bool CLevelInfo::OpenLevelPak() return false; } - AZStd::string levelpak(m_levelPath); - levelpak += "/level.pak"; - AZStd::fixed_string fullLevelPakPath; - bool bOk = gEnv->pCryPak->OpenPack( - levelpak.c_str(), m_isPak ? AZ::IO::IArchive::FLAGS_LEVEL_PAK_INSIDE_PAK : (unsigned)0, NULL, &fullLevelPakPath, false); - m_levelPakFullPath.assign(fullLevelPakPath.c_str()); + AZ::IO::Path levelPak(m_levelPath); + levelPak /= "level.pak"; + AZ::IO::FixedMaxPathString fullLevelPakPath; + bool bOk = gEnv->pCryPak->OpenPack(levelPak.Native(), nullptr, &fullLevelPakPath, false); + m_levelPakFullPath.assign(fullLevelPakPath.c_str(), fullLevelPakPath.size()); return bOk; } @@ -74,7 +73,7 @@ void CLevelInfo::CloseLevelPak() if (!m_levelPakFullPath.empty()) { - gEnv->pCryPak->ClosePack(m_levelPakFullPath.c_str(), AZ::IO::IArchive::FLAGS_PATH_REAL); + gEnv->pCryPak->ClosePack(m_levelPakFullPath.c_str()); m_levelPakFullPath.clear(); } } @@ -324,8 +323,7 @@ void CLevelSystem::ScanFolder(const char* subfolder, bool modFolder) // Open all the available paks found in the levels folder for (auto iter = pakList.begin(); iter != pakList.end(); iter++) { - AZStd::fixed_string fullLevelPakPath; - gEnv->pCryPak->OpenPack(iter->c_str(), (unsigned)0, nullptr, &fullLevelPakPath, false); + gEnv->pCryPak->OpenPack(iter->c_str(), nullptr, nullptr, false); } // Levels in bundles now take priority over levels outside of bundles. diff --git a/Code/Legacy/CrySystem/SystemCFG.cpp b/Code/Legacy/CrySystem/SystemCFG.cpp index 802e577386..c97345a518 100644 --- a/Code/Legacy/CrySystem/SystemCFG.cpp +++ b/Code/Legacy/CrySystem/SystemCFG.cpp @@ -272,14 +272,12 @@ static bool ParseSystemConfig(const AZStd::string& strSysConfigFilePath, ILoadCo CCryFile file; AZStd::string filenameLog; { - int flags = AZ::IO::IArchive::FOPEN_HINT_QUIET | AZ::IO::IArchive::FOPEN_ONDISK; - if (filename[0] == '@') { // this is used when theres a very specific file to read, like @user@/game.cfg which is read // IN ADDITION to the one in the game folder, and afterwards to override values in it. // if the file is missing and its already prefixed with an alias, there is no need to look any further. - if (!(file.Open(filename.c_str(), "rb", flags))) + if (!(file.Open(filename.c_str(), "rb"))) { if (warnIfMissing) { @@ -293,11 +291,11 @@ static bool ParseSystemConfig(const AZStd::string& strSysConfigFilePath, ILoadCo // otherwise, if the file isn't prefixed with an alias, then its likely one of the convenience mappings // to either root or assets/config. this is done so that code can just request a simple file name and get its data if ( - !(file.Open(filename.c_str(), "rb", flags)) && - !(file.Open((AZStd::string("@root@/") + filename).c_str(), "rb", flags)) && - !(file.Open((AZStd::string("@assets@/") + filename).c_str(), "rb", flags)) && - !(file.Open((AZStd::string("@assets@/config/") + filename).c_str(), "rb", flags)) && - !(file.Open((AZStd::string("@assets@/config/spec/") + filename).c_str(), "rb", flags)) + !(file.Open(filename.c_str(), "rb")) && + !(file.Open((AZStd::string("@root@/") + filename).c_str(), "rb")) && + !(file.Open((AZStd::string("@assets@/") + filename).c_str(), "rb")) && + !(file.Open((AZStd::string("@assets@/config/") + filename).c_str(), "rb")) && + !(file.Open((AZStd::string("@assets@/config/spec/") + filename).c_str(), "rb")) ) { if (warnIfMissing) @@ -308,7 +306,9 @@ static bool ParseSystemConfig(const AZStd::string& strSysConfigFilePath, ILoadCo } } - filenameLog = file.GetAdjustedFilename(); + AZ::IO::FixedMaxPath resolvedFilePath; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(resolvedFilePath, file.GetFilename()); + filenameLog = resolvedFilePath.String(); } INDENT_LOG_DURING_SCOPE(); diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index 5205b19e19..2c70717e8f 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -588,25 +588,6 @@ bool CSystem::InitFileSystem() m_env.pCryPak->RecordFileOpen(AZ::IO::IArchive::RFOM_EngineStartup); } - //init crypak - if (m_env.pCryPak->Init("")) - { -#if !defined(_RELEASE) - const ICmdLineArg* pakalias = m_pCmdLine->FindArg(eCLAT_Pre, "pakalias"); -#else - const ICmdLineArg* pakalias = nullptr; -#endif // !defined(_RELEASE) - if (pakalias && strlen(pakalias->GetValue()) > 0) - { - m_env.pCryPak->ParseAliases(pakalias->GetValue()); - } - } - else - { - AZ_Assert(false, "Failed to initialize CryPak."); - return false; - } - // Now that file systems are init, we will clear any events that have arrived // during file system init, so that systems do not reload assets that were already compiled in the // critical compilation section. @@ -844,9 +825,6 @@ void CSystem::OpenBasicPaks() #endif //AZ_PLATFORM_ANDROID InlineInitializationProcessing("CSystem::OpenBasicPaks OpenPacks( Engine... )"); - - // Load paks required for game init to mem - gEnv->pCryPak->LoadPakToMemory("Engine.pak", AZ::IO::IArchive::eInMemoryPakLocale_GPU); } ////////////////////////////////////////////////////////////////////////// @@ -891,8 +869,6 @@ void CSystem::OpenLanguageAudioPak([[maybe_unused]] const char* sLanguage) // Initialize languages. - int nPakFlags = 0; - // Omit the trailing slash! AZStd::string sLocalizationFolder(AZStd::string().assign(PathUtil::GetLocalizationFolder(), 0, PathUtil::GetLocalizationFolder().size() - 1)); @@ -904,7 +880,7 @@ void CSystem::OpenLanguageAudioPak([[maybe_unused]] const char* sLanguage) // load localized pak with crc32 filenames on consoles to save memory. AZStd::string sLocalizedPath = "loc.pak"; - if (!m_env.pCryPak->OpenPacks(sLocalizationFolder.c_str(), sLocalizedPath.c_str(), nPakFlags)) + if (!m_env.pCryPak->OpenPacks(sLocalizationFolder.c_str(), sLocalizedPath.c_str())) { // make sure the localized language is found - not really necessary, for TC AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "Localized language content(%s) not available or modified from the original installation.", sLanguage); diff --git a/Code/Legacy/CrySystem/WindowsErrorReporting.cpp b/Code/Legacy/CrySystem/WindowsErrorReporting.cpp index d467923c74..cde5d4f8c6 100644 --- a/Code/Legacy/CrySystem/WindowsErrorReporting.cpp +++ b/Code/Legacy/CrySystem/WindowsErrorReporting.cpp @@ -101,8 +101,11 @@ LONG WINAPI CryEngineExceptionFilterWER(struct _EXCEPTION_POINTERS* pExceptionPo { if (g_cvars.sys_WER > 1) { - char szScratch [_MAX_PATH]; - const char* szDumpPath = gEnv->pCryPak->AdjustFileName("@log@/CE2Dump.dmp", szScratch, AZ_ARRAY_SIZE(szScratch), 0); + AZ::IO::FixedMaxPath dumpPath{ "@log@/CE2Dump.dmp" }; + if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr) + { + dumpPath = fileIoBase->ResolvePath(dumpPath, "@log@/CE2Dump.dmp"); + } MINIDUMP_TYPE mdumpValue = (MINIDUMP_TYPE)(MiniDumpNormal); if (g_cvars.sys_WER > 1) @@ -110,7 +113,7 @@ LONG WINAPI CryEngineExceptionFilterWER(struct _EXCEPTION_POINTERS* pExceptionPo mdumpValue = (MINIDUMP_TYPE)(g_cvars.sys_WER - 2); } - return CryEngineExceptionFilterMiniDump(pExceptionPointers, szDumpPath, mdumpValue); + return CryEngineExceptionFilterMiniDump(pExceptionPointers, dumpPath.c_str(), mdumpValue); } LONG lRet = EXCEPTION_CONTINUE_SEARCH; diff --git a/Code/Legacy/CrySystem/XConsoleVariable.h b/Code/Legacy/CrySystem/XConsoleVariable.h index 3ff71f9f39..d62685c94c 100644 --- a/Code/Legacy/CrySystem/XConsoleVariable.h +++ b/Code/Legacy/CrySystem/XConsoleVariable.h @@ -257,12 +257,12 @@ public: void Set(const char* s) override; void Set(float f) override { - stack_string s = stack_string::format("%g", f); + AZStd::fixed_string<32> s = AZStd::fixed_string<32>::format("%g", f); Set(s.c_str()); } void Set(int i) override { - stack_string s = stack_string::format("%d", i); + AZStd::fixed_string<32> s = AZStd::fixed_string<32>::format("%d", i); Set(s.c_str()); } int GetType() override { return CVAR_STRING; } diff --git a/Code/Legacy/CrySystem/XML/XmlUtils.cpp b/Code/Legacy/CrySystem/XML/XmlUtils.cpp index 111831ed41..3e6a49f266 100644 --- a/Code/Legacy/CrySystem/XML/XmlUtils.cpp +++ b/Code/Legacy/CrySystem/XML/XmlUtils.cpp @@ -169,7 +169,7 @@ public: { if (m_fileHandle != AZ::IO::InvalidHandle) { - gEnv->pCryPak->FWrite(pData, size, 1, m_fileHandle); + gEnv->pCryPak->FWrite(pData, size, m_fileHandle); } } private: diff --git a/Code/Legacy/CrySystem/XML/xml.cpp b/Code/Legacy/CrySystem/XML/xml.cpp index 826e74b758..65a2cb6ffd 100644 --- a/Code/Legacy/CrySystem/XML/xml.cpp +++ b/Code/Legacy/CrySystem/XML/xml.cpp @@ -948,10 +948,12 @@ void CXmlNode::AddToXmlString(XmlString& xml, int level, AZ::IO::HandleType file { if (fileHandle != AZ::IO::InvalidHandle && chunkSize > 0) { + auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIoBase != nullptr, "FileIOBase is expected to be initialized for CXmlNode"); size_t len = xml.length(); if (len >= chunkSize) { - gEnv->pCryPak->FWrite(xml.c_str(), len, 1, fileHandle); + fileIoBase->Write(fileHandle, xml.c_str(), len); xml.assign (""); // should not free memory and does not! } } @@ -1258,7 +1260,8 @@ bool CXmlNode::saveToFile([[maybe_unused]] const char* fileName, size_t chunkSiz XmlString xml; xml.assign (""); xml.reserve(chunkSize * 2); // we reserve double memory, as writing in chunks is not really writing in fixed blocks but a bit fuzzy - auto pCryPak = gEnv->pCryPak; + auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIoBase != nullptr, "FileIOBase is expected to be initialized for CXmlNode"); if (fileHandle == AZ::IO::InvalidHandle) { return false; @@ -1267,7 +1270,7 @@ bool CXmlNode::saveToFile([[maybe_unused]] const char* fileName, size_t chunkSiz size_t len = xml.length(); if (len > 0) { - pCryPak->FWrite(xml.c_str(), len, 1, fileHandle); + fileIoBase->Write(fileHandle, xml.c_str(), len); } xml.clear(); // xml.resize(0) would not reclaim memory return true; @@ -1639,10 +1642,18 @@ XmlNodeRef XmlParserImp::ParseFile(const char* filename, XmlString& errorString, CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "%s", str); return 0; } - adjustedFilename = xmlFile.GetAdjustedFilename(); - AZStd::replace(adjustedFilename.begin(), adjustedFilename.end(), '\\', '/'); - pakPath = xmlFile.GetPakPath(); - AZStd::replace(pakPath.begin(), pakPath.end(), '\\', '/'); + + AZ::IO::FixedMaxPath resolvedPath(AZ::IO::PosixPathSeparator); + auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); + AZ_Assert(fileIoBase != nullptr, "FileIOBase is expected to be initialized for CXmlNode"); + if (fileIoBase->ResolvePath(resolvedPath, xmlFile.GetFilename())) + { + adjustedFilename = resolvedPath.MakePreferred().Native(); + } + if (fileIoBase->ResolvePath(resolvedPath, xmlFile.GetPakPath())) + { + pakPath = resolvedPath.MakePreferred().Native(); + } } XMLBinary::XMLBinaryReader reader; diff --git a/Code/Tools/AssetProcessor/native/InternalBuilders/SettingsRegistryBuilder.cpp b/Code/Tools/AssetProcessor/native/InternalBuilders/SettingsRegistryBuilder.cpp index 7c88c4324c..e6d9894116 100644 --- a/Code/Tools/AssetProcessor/native/InternalBuilders/SettingsRegistryBuilder.cpp +++ b/Code/Tools/AssetProcessor/native/InternalBuilders/SettingsRegistryBuilder.cpp @@ -191,10 +191,51 @@ namespace AssetProcessor response.m_createJobOutputs.push_back(AZStd::move(job)); } - AZ::IO::Path settingsRegistryWildcard = AZ::SettingsRegistryInterface::RegistryFolder; + AZ::IO::Path settingsRegistryWildcard = AZStd::string_view(AZ::Utils::GetEnginePath()); + settingsRegistryWildcard /= AZ::SettingsRegistryInterface::RegistryFolder; settingsRegistryWildcard /= "*.setreg"; response.m_sourceFileDependencyList.emplace_back(AZStd::move(settingsRegistryWildcard.Native()), AZ::Uuid::CreateNull(), AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards); + + auto projectPath = AZ::IO::Path(AZStd::string_view(AZ::Utils::GetProjectPath())); + response.m_sourceFileDependencyList.emplace_back( + AZStd::move((projectPath / AZ::SettingsRegistryInterface::RegistryFolder / "*.setreg").Native()), + AZ::Uuid::CreateNull(), + AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards); + response.m_sourceFileDependencyList.emplace_back( + AZStd::move((projectPath / AZ::SettingsRegistryInterface::DevUserRegistryFolder / "*.setreg").Native()), + AZ::Uuid::CreateNull(), + AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards); + + if (auto settingsRegistry = AZ::Interface::Get(); settingsRegistry != nullptr) + { + AZStd::vector gemInfos; + if (AzFramework::GetGemsInfo(gemInfos, *settingsRegistry)) + { + // Gather unique list of Settings Registry wildcard directories + AZStd::vector gemSettingsRegistryWildcards; + for (const AzFramework::GemInfo& gemInfo : gemInfos) + { + for (const AZ::IO::Path& absoluteSourcePath : gemInfo.m_absoluteSourcePaths) + { + auto gemSettingsRegistryWildcard = absoluteSourcePath / AZ::SettingsRegistryInterface::RegistryFolder / "*.setreg"; + if (auto foundIt = AZStd::find(gemSettingsRegistryWildcards.begin(), gemSettingsRegistryWildcards.end(), gemSettingsRegistryWildcard); + foundIt == gemSettingsRegistryWildcards.end()) + { + gemSettingsRegistryWildcards.emplace_back(gemSettingsRegistryWildcard); + } + } + } + + // Add to the Source File Dependency list + for (AZ::IO::Path& gemSettingsRegistryWildcard : gemSettingsRegistryWildcards) + { + response.m_sourceFileDependencyList.emplace_back( + AZStd::move(gemSettingsRegistryWildcard.Native()), AZ::Uuid::CreateNull(), + AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards); + } + } + } response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; } diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 83f53ffec2..2cc8a67cfa 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -283,7 +283,7 @@ namespace AZ FontTexture* m_fontTexture = nullptr; size_t m_fontBufferSize = 0; - unsigned char* m_fontBuffer = nullptr; + AZStd::unique_ptr m_fontBuffer; AZ::Data::Instance m_fontStreamingImage; AZ::RHI::Ptr m_fontImage; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index 5e96af0b1b..c5268b427f 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -13,8 +13,6 @@ #if !defined(USE_NULLFONT_ALWAYS) -#include - #include #include #include @@ -124,17 +122,10 @@ bool AZ::FFont::Load(const char* fontFilePath, unsigned int width, unsigned int Free(); - auto pPak = gEnv->pCryPak; + auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); - AZStd::string fullFile; - if (pPak->IsAbsPath(fontFilePath)) - { - fullFile = fontFilePath; - } - else - { - fullFile = m_curPath + fontFilePath; - } + AZ::IO::Path fullFile(m_curPath); + fullFile /= fontFilePath; int smoothMethodFlag = (flags & TTFFLAG_SMOOTH_MASK) >> TTFFLAG_SMOOTH_SHIFT; AZ::FontSmoothMethod smoothMethod = AZ::FontSmoothMethod::None; @@ -161,42 +152,41 @@ bool AZ::FFont::Load(const char* fontFilePath, unsigned int width, unsigned int } - AZ::IO::HandleType fileHandle = pPak->FOpen(fullFile.c_str(), "rb"); + AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; + fileIoBase->Open(fullFile.c_str(), AZ::IO::GetOpenModeFromStringMode("rb"), fileHandle); if (fileHandle == AZ::IO::InvalidHandle) { return false; } - size_t fileSize = pPak->FGetSize(fileHandle); + AZ::u64 fileSize{}; + fileIoBase->Size(fileHandle, fileSize); if (!fileSize) { - pPak->FClose(fileHandle); + fileIoBase->Close(fileHandle); return false; } - unsigned char* buffer = new unsigned char[fileSize]; - if (!pPak->FReadRaw(buffer, fileSize, 1, fileHandle)) + auto buffer = AZStd::make_unique(fileSize); + if (!fileIoBase->Read(fileHandle, buffer.get(), fileSize)) { - pPak->FClose(fileHandle); - delete [] buffer; + fileIoBase->Close(fileHandle); return false; } - pPak->FClose(fileHandle); + fileIoBase->Close(fileHandle); if (!m_fontTexture) { m_fontTexture = new FontTexture(); } - - if (!m_fontTexture || !m_fontTexture->CreateFromMemory(buffer, (int)fileSize, width, height, smoothMethod, smoothAmount, widthNumSlots, heightNumSlots, sizeRatio)) + if (!m_fontTexture || !m_fontTexture->CreateFromMemory(buffer.get(), (int)fileSize, width, height, smoothMethod, smoothAmount, widthNumSlots, heightNumSlots, sizeRatio)) { - delete [] buffer; return false; } m_monospacedFont = m_fontTexture->GetMonospaced(); - m_fontBuffer = buffer; + m_fontBuffer = AZStd::move(buffer); m_fontBufferSize = fileSize; m_fontTexDirty = false; m_sizeRatio = sizeRatio; @@ -213,10 +203,9 @@ void AZ::FFont::Free() m_fontImageVersion = 0; delete m_fontTexture; - m_fontTexture = 0; + m_fontTexture = nullptr; - delete[] m_fontBuffer; - m_fontBuffer = 0; + m_fontBuffer.reset(); m_fontBufferSize = 0; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt index df5ab134fa..bf28ed3f14 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt @@ -115,6 +115,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_create_alias(NAME AtomLyIntegration_CommonFeatures.Builders NAMESPACE Gem TARGETS Gem::AtomLyIntegration_CommonFeatures.Editor + Gem::Atom_Feature_Common.Builders Gem::Atom_RPI.Builders Gem::GradientSignal.Builders ) From a3dfb8869691abf341dd27ac50dead1a890b6c52 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 16 Sep 2021 17:48:53 +0100 Subject: [PATCH 161/274] Added support for instantiating network spawnables for any spawnables, not just root spawnable Signed-off-by: pereslav --- .../Spawnable/SpawnableEntitiesInterface.h | 9 +++ .../Spawnable/SpawnableEntitiesManager.cpp | 20 +++++ .../Spawnable/SpawnableEntitiesManager.h | 6 ++ .../Mocks/MockSpawnableEntitiesInterface.h | 2 + .../NetworkEntity/NetworkEntityManager.cpp | 79 ++++++++++++++----- .../NetworkEntity/NetworkEntityManager.h | 12 ++- 6 files changed, 105 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index 4b09dcbc75..254df8f1b0 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -320,6 +320,15 @@ namespace AzFramework //! @param optionalArgs Optional additional arguments, see BarrierOptionalArgs. virtual void Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) = 0; + //! Register a handler for OnSpawned events. + //! @param handler The handler to receive the event. + virtual void AddOnSpawnedHandler(AZ::Event, + const AZStd::vector&, const void*>::Handler& handler) = 0; + + //! Register a handler for OnDespawned events. + //! @param handler The handler to receive the event. + virtual void AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) = 0; + protected: [[nodiscard]] virtual AZStd::pair CreateTicket(AZ::Data::Asset&& spawnable) = 0; virtual void DestroyTicket(void* ticket) = 0; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index 5fa072a451..f052f83224 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -146,6 +146,16 @@ namespace AzFramework QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } + void SpawnableEntitiesManager::AddOnSpawnedHandler(AZ::Event, const AZStd::vector&, const void*>::Handler& handler) + { + handler.Connect(m_onSpawnedEvent); + } + + void SpawnableEntitiesManager::AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) + { + handler.Connect(m_onDespawnedEvent); + } + auto SpawnableEntitiesManager::ProcessQueue(CommandQueuePriority priority) -> CommandQueueStatus { CommandQueueStatus result = CommandQueueStatus::NoCommandsLeft; @@ -349,6 +359,8 @@ namespace AzFramework ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end())); } + m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); + ticket.m_currentRequestId++; return true; } @@ -429,6 +441,8 @@ namespace AzFramework ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end())); } + m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); + ticket.m_currentRequestId++; return true; } @@ -460,6 +474,8 @@ namespace AzFramework request.m_completionCallback(request.m_ticketId); } + m_onDespawnedEvent.Signal(ticket.m_spawnable, &ticket); + ticket.m_currentRequestId++; return true; } @@ -487,6 +503,8 @@ namespace AzFramework } } + m_onDespawnedEvent.Signal(ticket.m_spawnable, &ticket); + // Rebuild the list of entities. ticket.m_spawnedEntities.clear(); const Spawnable::EntityList& entities = request.m_spawnable->GetEntities(); @@ -544,6 +562,8 @@ namespace AzFramework ticket.m_spawnedEntities.begin(), ticket.m_spawnedEntities.end())); } + m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); + ticket.m_currentRequestId++; return true; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h index 69985f8aa9..c78b1778a4 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h @@ -69,6 +69,9 @@ namespace AzFramework void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) override; + void AddOnSpawnedHandler(AZ::Event, const AZStd::vector&, const void*>::Handler& handler) override; + void AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) override; + // // The following function is thread safe but intended to be run from the main thread. // @@ -224,6 +227,9 @@ namespace AzFramework //! SpawnablePriority_Default which gives users a bit of room to fine tune the priorities as this value can be configured //! through the Settings Registry under the key "/O3DE/AzFramework/Spawnables/HighPriorityThreshold". SpawnablePriority m_highPriorityThreshold { 64 }; + + AZ::Event, const AZStd::vector&, const void*> m_onSpawnedEvent; + AZ::Event, const void*> m_onDespawnedEvent; }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(AzFramework::SpawnableEntitiesManager::CommandQueuePriority); diff --git a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h index a5df7af4c3..89e79ecf9b 100644 --- a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h @@ -59,6 +59,8 @@ namespace AzFramework MOCK_METHOD1(CreateTicket, AZStd::pair(AZ::Data::Asset&& spawnable)); MOCK_METHOD1(DestroyTicket, void(void* ticket)); + MOCK_METHOD1(AddOnSpawnedHandler, void(AZ::Event, const AZStd::vector&, const void*>::Handler& handler)); + MOCK_METHOD1(AddOnDespawnedHandler, void(AZ::Event, const void*>::Handler& handler)); /** Installs some default result values for the above functions. * Note that you can always override these in scope of your test by adding additional ON_CALL / EXPECT_CALL diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 793acc17ff..62b57d9603 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -30,9 +30,14 @@ namespace Multiplayer : m_networkEntityAuthorityTracker(*this) , m_removeEntitiesEvent([this] { RemoveEntities(); }, AZ::Name("NetworkEntityManager remove entities event")) , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) + , m_onSpawnedHandler([this](AZ::Data::Asset spawnable, const AZStd::vector& entities, const void* spawnTicket) { this->OnSpawned(spawnable, entities, spawnTicket); }) + , m_onDespawnedHandler([this](AZ::Data::Asset spawnable, const void* spawnTicket) { this->OnDespawned(spawnable, spawnTicket); }) { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); + + AzFramework::SpawnableEntitiesInterface::Get()->AddOnSpawnedHandler(m_onSpawnedHandler); + AzFramework::SpawnableEntitiesInterface::Get()->AddOnDespawnedHandler(m_onDespawnedHandler); } NetworkEntityManager::~NetworkEntityManager() @@ -467,30 +472,39 @@ namespace Multiplayer return netEntityId; } - AzFramework::EntitySpawnTicket NetworkEntityManager::RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable) + AZStd::unique_ptr NetworkEntityManager::RequestNetSpawnableInstantiation( + const AZ::Data::Asset& rootSpawnable, const AZStd::vector& entities) { - const AzFramework::Spawnable::EntityList& entityList = rootSpawnable->GetEntities(); - if (entityList.empty()) + if (entities.empty()) { AZ_Error("NetworkEntityManager", false, "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()); - return {}; + return nullptr; } // The first entity in every spawnable is the root one - const AZ::Entity* rootEntity = (entityList.begin())->get(); + const AZ::Entity* rootEntity = *entities.begin(); if(!rootEntity) { AZ_Error("NetworkEntityManager", false, "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); - return {}; + return nullptr; } const auto* holderComponent = rootEntity->FindComponent(); if(!holderComponent) { // This spawnable doesn't have a corresponding network spawnable. - return {}; + return nullptr; + } + + AzFramework::TransformComponent* rootEntityTransform = + rootEntity->FindComponent(); + if (!rootEntityTransform) + { + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: Root entity has no transform in the spawnable %s", rootSpawnable.GetHint().c_str()); + return nullptr; } // Retrieve the corresponding network spawnable asset @@ -504,14 +518,26 @@ namespace Multiplayer AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [netSpawnableName](AzFramework::EntitySpawnTicket::Id, - AzFramework::SpawnableEntityContainerView entities) + optionalArgs.m_preInsertionCallback = [netSpawnableName, rootTransform = rootEntityTransform->GetWorldTM()] + (AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { + bool shouldUpdateTransform = (rootTransform.IsClose(AZ::Transform::Identity()) == false); + for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); netEntityIndex < entitiesSize; netEntityIndex++) { AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); + if(shouldUpdateTransform) + { + AzFramework::TransformComponent* netEntityTransform = + netEntity->FindComponent(); + + AZ::Transform worldTm = netEntityTransform->GetWorldTM(); + worldTm = rootTransform * worldTm; + netEntityTransform->SetWorldTM(worldTm); + } + PrefabEntityId prefabEntityId; prefabEntityId.m_prefabName = netSpawnableName; prefabEntityId.m_entityOffset = netEntityIndex; @@ -520,13 +546,13 @@ namespace Multiplayer }; // Spawn with the newly created ticket. This allows the calling code to manage the lifetime of the constructed entities - AzFramework::EntitySpawnTicket ticket(netSpawnableAsset); - AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(ticket, AZStd::move(optionalArgs)); + auto ticket = AZStd::make_unique(netSpawnableAsset); + AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*ticket, AZStd::move(optionalArgs)); return ticket; } - void NetworkEntityManager::OnRootSpawnableAssigned( - [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) + void NetworkEntityManager::OnRootSpawnableAssigned(AZ::Data::Asset rootSpawnable, + [[maybe_unused]] uint32_t generation) { auto* multiplayer = GetMultiplayer(); const auto agentType = multiplayer->GetAgentType(); @@ -535,11 +561,6 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(true); } - - if(ShouldSpawnNetEntities()) - { - m_rootNetSpawnableTicket = RequestNetSpawnableInstantiation(rootSpawnable); - } } void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) @@ -552,13 +573,29 @@ namespace Multiplayer multiplayer->SendReadyForEntityUpdates(false); } - // Despawn any remaining net entities created locally - if (m_rootNetSpawnableTicket.IsValid()) + m_netSpawnableTickets.clear(); + } + + void NetworkEntityManager::OnSpawned(AZ::Data::Asset spawnable, + const AZStd::vector& entities, const void* spawnTicket) + { + if (ShouldSpawnNetEntities()) { - AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_rootNetSpawnableTicket); + AZStd::unique_ptr ticket = RequestNetSpawnableInstantiation(spawnable, entities); + if(ticket) + { + AZ::Data::AssetId spawnableAssetId = spawnable.GetId(); + m_netSpawnableTickets[spawnTicket] = AZStd::move(ticket); + } } } + void NetworkEntityManager::OnDespawned([[maybe_unused]] AZ::Data::Asset spawnable, + const void* spawnTicket) + { + m_netSpawnableTickets.erase(spawnTicket); + } + void NetworkEntityManager::SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) { auto* netBindComponent = netEntity->FindComponent(); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index a5956b448f..14efa4feeb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -94,10 +94,14 @@ namespace Multiplayer void RemoveEntities(); NetEntityId NextId(); bool ShouldSpawnNetEntities() const; + void OnSpawned(AZ::Data::Asset spawnable, + const AZStd::vector& entities, const void* spawnTicket); + void OnDespawned(AZ::Data::Asset spawnable, const void* spawnTicket); // Note: This is an async function. // The instantiated entities are not available immediately but will be constructed by the spawnable system - AzFramework::EntitySpawnTicket RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable); + AZStd::unique_ptr RequestNetSpawnableInstantiation( + const AZ::Data::Asset& rootSpawnable, const AZStd::vector& entities); NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; @@ -126,6 +130,10 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; - AzFramework::EntitySpawnTicket m_rootNetSpawnableTicket; + + AZStd::unordered_map> m_netSpawnableTickets; + + AZ::Event, const AZStd::vector&, const void*>::Handler m_onSpawnedHandler; + AZ::Event, const void*>::Handler m_onDespawnedHandler; }; } From db14d378057ccc2a98246cdc9da0b2d912a5843d Mon Sep 17 00:00:00 2001 From: Dihara Wijetunga <84074485+DiharaWijetunga@users.noreply.github.com> Date: Thu, 16 Sep 2021 18:08:34 +0100 Subject: [PATCH 162/274] Fixed crash in Atom Vulkan RHI when physical device limits timestampComputeAndGraphics is false (#4051) * Fixed crash in Atom Vulkan RHI when physical device limits timestampComputeAndGraphics is false. Signed-off-by: Dihara Wijetunga * Revert "Fixed crash in Atom Vulkan RHI when physical device limits timestampComputeAndGraphics is false." This reverts commit f2b7d4eb704ef13701cb66b6b5802cb4e5eb9632. Signed-off-by: Dihara Wijetunga * Moved ATOM Vulkan RHI Device::InitFeaturesAndLimits() after m_commandQueueContext is initialized. Signed-off-by: Dihara Wijetunga --- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp index 4f800f114b..35bc966d1d 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp @@ -235,8 +235,6 @@ namespace AZ //Load device features now that we have loaded all extension info physicalDevice.LoadSupportedFeatures(); - - InitFeaturesAndLimits(physicalDevice); return RHI::ResultCode::Success; } @@ -247,6 +245,8 @@ namespace AZ RHI::ResultCode result = m_commandQueueContext.Init(*this, commandQueueContextDescriptor); RETURN_RESULT_IF_UNSUCCESSFUL(result); + InitFeaturesAndLimits(static_cast(GetPhysicalDevice())); + // Initialize member variables. ReleaseQueue::Descriptor releaseQueueDescriptor; releaseQueueDescriptor.m_collectLatency = m_descriptor.m_frameCountMax - 1; From 2a9cf06b6b5c28b11945177be3bbc140218819e6 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 16 Sep 2021 12:49:28 -0500 Subject: [PATCH 163/274] Fixed the Comment component viewport icon. Signed-off-by: Chris Galvan --- Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp b/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp index 7eb0db1832..97f8dc60a2 100644 --- a/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp @@ -30,7 +30,7 @@ namespace LmbrCentral ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Editor") ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Comment.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Comment.png") + ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Comment.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector({ AZ_CRC("Level", 0x9aeacc13), AZ_CRC("Game", 0x232b318c), AZ_CRC("Layer", 0xe4db211a) })) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/comment/") From 58c227ceb13285f327cd57ebc1cdce91a5ed064f Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Thu, 16 Sep 2021 12:50:18 -0500 Subject: [PATCH 164/274] Implemented C++23 deleted nullptr_t constructor/assignment for AZStd string classes (#4158) * Added string and string_view class constructor overloads which is deleted that prevents initializing them from a nullptr or an integer type Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed locations where string and string_view were initialized with nullptr Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fix IArchive::IsInstalledToHDD signature Updated calls to ConvertAbsolutePathToAliasedPath to use an list initialization instead of nullptr Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Editor/Controls/SplineCtrlEx.cpp | 2 +- Code/Editor/Util/PakFile.cpp | 4 ++-- .../AzCore/AzCore/std/string/fixed_string.h | 5 +++++ Code/Framework/AzCore/AzCore/std/string/string.h | 4 ++++ .../AzCore/AzCore/std/string/string_view.h | 3 +++ Code/Framework/AzCore/Tests/AZStd/String.cpp | 16 +--------------- Code/Framework/AzCore/Tests/Name/NameTests.cpp | 2 +- .../AzCore/Tests/SettingsRegistryTests.cpp | 16 ++++++++-------- .../Tests/ArchiveCompressionTests.cpp | 12 ++++++------ .../Framework/AzFramework/Tests/ArchiveTests.cpp | 10 +++++----- .../AssetEditor/AssetEditorWidget.cpp | 2 +- .../Code/MCore/Source/MCoreCommandManager.h | 2 +- .../Editor/Animation/Controls/UiSplineCtrlEx.cpp | 2 +- .../Android/SaveData_SystemComponent_Android.cpp | 2 +- .../Apple/SaveData_SystemComponent_Apple.mm | 2 +- .../Windows/SaveData_SystemComponent_Windows.cpp | 2 +- .../Widgets/NodePalette/NodePaletteModel.cpp | 2 +- .../CreateElementsStates.h | 2 +- 18 files changed, 44 insertions(+), 46 deletions(-) diff --git a/Code/Editor/Controls/SplineCtrlEx.cpp b/Code/Editor/Controls/SplineCtrlEx.cpp index 9e0a954c79..1dc2ff19e1 100644 --- a/Code/Editor/Controls/SplineCtrlEx.cpp +++ b/Code/Editor/Controls/SplineCtrlEx.cpp @@ -70,7 +70,7 @@ protected: m_splineEntries.resize(m_splineEntries.size() + 1); SplineEntry& entry = m_splineEntries.back(); ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : nullptr); - entry.id = (pSplineSet ? pSplineSet->GetIDFromSpline(pSpline) : nullptr); + entry.id = (pSplineSet ? pSplineSet->GetIDFromSpline(pSpline) : AZStd::string{}); entry.pSpline = pSpline; const int numKeys = pSpline->GetKeyCount(); diff --git a/Code/Editor/Util/PakFile.cpp b/Code/Editor/Util/PakFile.cpp index fc8431ef24..b629b45f74 100644 --- a/Code/Editor/Util/PakFile.cpp +++ b/Code/Editor/Util/PakFile.cpp @@ -68,7 +68,7 @@ bool CPakFile::Open(const char* filename, bool bAbsolutePath) if (bAbsolutePath) { - m_pArchive = pCryPak->OpenArchive(filename, nullptr, AZ::IO::INestedArchive::FLAGS_ABSOLUTE_PATHS); + m_pArchive = pCryPak->OpenArchive(filename, {}, AZ::IO::INestedArchive::FLAGS_ABSOLUTE_PATHS); } else { @@ -93,7 +93,7 @@ bool CPakFile::OpenForRead(const char* filename) { return false; } - m_pArchive = pCryPak->OpenArchive(filename, nullptr, AZ::IO::INestedArchive::FLAGS_OPTIMIZED_READ_ONLY | AZ::IO::INestedArchive::FLAGS_ABSOLUTE_PATHS); + m_pArchive = pCryPak->OpenArchive(filename, {}, AZ::IO::INestedArchive::FLAGS_OPTIMIZED_READ_ONLY | AZ::IO::INestedArchive::FLAGS_ABSOLUTE_PATHS); if (m_pArchive) { return true; diff --git a/Code/Framework/AzCore/AzCore/std/string/fixed_string.h b/Code/Framework/AzCore/AzCore/std/string/fixed_string.h index 079fe40cda..b68f21784b 100644 --- a/Code/Framework/AzCore/AzCore/std/string/fixed_string.h +++ b/Code/Framework/AzCore/AzCore/std/string/fixed_string.h @@ -96,6 +96,10 @@ namespace AZStd && !is_convertible_v>> constexpr basic_fixed_string(const T& convertibleToView, size_type rhsOffset, size_type count); + + // #12 + constexpr basic_fixed_string(AZStd::nullptr_t) = delete; + constexpr operator AZStd::basic_string_view() const; constexpr auto begin() -> iterator; @@ -120,6 +124,7 @@ namespace AZStd constexpr auto operator=(const T& convertible_to_view) -> AZStd::enable_if_t> && !is_convertible_v, basic_fixed_string&>; + constexpr auto operator=(AZStd::nullptr_t) -> basic_fixed_string& = delete; constexpr auto operator+=(const basic_fixed_string& rhs) -> basic_fixed_string&; constexpr auto operator+=(const_pointer ptr) -> basic_fixed_string&; diff --git a/Code/Framework/AzCore/AzCore/std/string/string.h b/Code/Framework/AzCore/AzCore/std/string/string.h index c02c6805a1..9ef7ea3086 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string.h +++ b/Code/Framework/AzCore/AzCore/std/string/string.h @@ -168,6 +168,9 @@ namespace AZStd { } + // C++23 overload to prevent initializing a string_view via a nullptr or integer type + constexpr basic_string(AZStd::nullptr_t) = delete; + inline ~basic_string() { // destroy the string @@ -197,6 +200,7 @@ namespace AZStd inline this_type& operator=(AZStd::basic_string_view view) { return assign(view); } inline this_type& operator=(const_pointer ptr) { return assign(ptr); } inline this_type& operator=(Element ch) { return assign(1, ch); } + inline this_type& operator=(AZStd::nullptr_t) = delete; inline this_type& operator+=(const this_type& rhs) { return append(rhs); } inline this_type& operator+=(const_pointer ptr) { return append(ptr); } inline this_type& operator+=(Element ch) { return append(1, ch); } diff --git a/Code/Framework/AzCore/AzCore/std/string/string_view.h b/Code/Framework/AzCore/AzCore/std/string/string_view.h index b2390c293a..30e61f95ce 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string_view.h +++ b/Code/Framework/AzCore/AzCore/std/string/string_view.h @@ -502,6 +502,9 @@ namespace AZStd swap(other); } + // C++23 overload to prevent initializing a string_view via a nullptr or integer type + constexpr basic_string_view(AZStd::nullptr_t) = delete; + constexpr const_reference operator[](size_type index) const { return data()[index]; } /// Returns value, not reference. If index is out of bounds, 0 is returned (can't be reference). constexpr value_type at(size_type index) const diff --git a/Code/Framework/AzCore/Tests/AZStd/String.cpp b/Code/Framework/AzCore/Tests/AZStd/String.cpp index 91d2237ca2..68bdd311d5 100644 --- a/Code/Framework/AzCore/Tests/AZStd/String.cpp +++ b/Code/Framework/AzCore/Tests/AZStd/String.cpp @@ -1210,9 +1210,6 @@ namespace UnitTest AZStd::string findStr("Hay"); string_view view3(findStr); - string_view nullptrView4(nullptr); - - EXPECT_EQ(emptyView1, nullptrView4); // copy const size_t destBufferSize = 32; @@ -1264,9 +1261,6 @@ namespace UnitTest AZStd::size_t rfindResult = view3.rfind('a', 2); EXPECT_EQ(1, rfindResult); - rfindResult = nullptrView4.rfind(""); - EXPECT_EQ(string_view::npos, rfindResult); - rfindResult = emptyView1.rfind(""); EXPECT_EQ(string_view::npos, rfindResult); @@ -1373,17 +1367,11 @@ namespace UnitTest { string_view view1("The quick brown fox jumped over the lazy dog"); string_view view2("Needle in Haystack"); - string_view nullBeaverView(nullptr); string_view emptyBeaverView; string_view superEmptyBeaverView(""); - EXPECT_EQ(nullBeaverView, emptyBeaverView); - EXPECT_EQ(superEmptyBeaverView, nullBeaverView); - EXPECT_EQ(emptyBeaverView, superEmptyBeaverView); - EXPECT_EQ(nullBeaverView, ""); - EXPECT_EQ(nullBeaverView, nullptr); EXPECT_EQ("", emptyBeaverView); - EXPECT_EQ(nullptr, superEmptyBeaverView); + EXPECT_EQ("", superEmptyBeaverView); EXPECT_EQ("The quick brown fox jumped over the lazy dog", view1); EXPECT_NE("The slow brown fox jumped over the lazy dog", view1); @@ -1421,8 +1409,6 @@ namespace UnitTest EXPECT_LE(beaverView, "Busy Beaver"); EXPECT_LE("Likable Beaver", notBeaverView); EXPECT_LE("Busy Beaver", beaverView); - EXPECT_LE(nullBeaverView, nullBeaverView); - EXPECT_LE(nullBeaverView, lowerBeaverStr); EXPECT_LE(microBeaverStr, view1); EXPECT_LE(compareStr, beaverView); diff --git a/Code/Framework/AzCore/Tests/Name/NameTests.cpp b/Code/Framework/AzCore/Tests/Name/NameTests.cpp index 5417d36051..eb0a048e2f 100644 --- a/Code/Framework/AzCore/Tests/Name/NameTests.cpp +++ b/Code/Framework/AzCore/Tests/Name/NameTests.cpp @@ -362,7 +362,7 @@ namespace UnitTest // Test specific construction case that was failing. // The constructor calls Name::SetName() which does a move assignment // Name& Name::operator=(Name&& rhs) was leaving m_view pointing to the m_data in a temporary Name object. - AZ::Name emptyName(AZStd::string_view(nullptr)); + AZ::Name emptyName(AZStd::string_view{}); EXPECT_TRUE(emptyName.IsEmpty()); EXPECT_EQ(0, emptyName.GetStringView().data()[0]); } diff --git a/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp b/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp index 8485747991..2da5701207 100644 --- a/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp +++ b/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp @@ -1517,7 +1517,7 @@ namespace SettingsRegistryTests m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR); *m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder; - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}); EXPECT_TRUE(result); EXPECT_EQ(4, counter); @@ -1559,7 +1559,7 @@ namespace SettingsRegistryTests m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR); *m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder; - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special", nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special"); EXPECT_TRUE(result); EXPECT_EQ(6, counter); @@ -1598,7 +1598,7 @@ namespace SettingsRegistryTests m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR); *m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder; - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}); EXPECT_TRUE(result); EXPECT_EQ(4, counter); @@ -1639,7 +1639,7 @@ namespace SettingsRegistryTests m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR); *m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder; - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}); EXPECT_TRUE(result); EXPECT_EQ(4, counter); @@ -1672,7 +1672,7 @@ namespace SettingsRegistryTests m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR); *m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder; - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special", nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, "Special"); EXPECT_TRUE(result); EXPECT_EQ(1, counter); @@ -1722,7 +1722,7 @@ namespace SettingsRegistryTests TEST_F(SettingsRegistryTest, MergeSettingsFolder_EmptyFolder_ReportsSuccessButNothingAdded) { - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}); EXPECT_TRUE(result); EXPECT_EQ(AZ::SettingsRegistryInterface::Type::Object, m_registry->GetType(AZ_SETTINGS_REGISTRY_HISTORY_KEY "/0")); // Folder and specialization settings. @@ -1734,7 +1734,7 @@ namespace SettingsRegistryTests constexpr AZStd::fixed_string path(AZ::IO::MaxPathLength + 1, 'a'); AZ_TEST_START_TRACE_SUPPRESSION; - bool result = m_registry->MergeSettingsFolder(path, { "editor", "test" }, {}, nullptr); + bool result = m_registry->MergeSettingsFolder(path, { "editor", "test" }, {}); AZ_TEST_STOP_TRACE_SUPPRESSION(1); EXPECT_FALSE(result); @@ -1751,7 +1751,7 @@ namespace SettingsRegistryTests AZ_TEST_START_TRACE_SUPPRESSION; m_testFolder->push_back(AZ_CORRECT_DATABASE_SEPARATOR); *m_testFolder += AZ::SettingsRegistryInterface::RegistryFolder; - bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}, nullptr); + bool result = m_registry->MergeSettingsFolder(*m_testFolder, { "editor", "test" }, {}); EXPECT_GT(::UnitTest::TestRunner::Instance().StopAssertTests(), 0); EXPECT_FALSE(result); diff --git a/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp b/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp index d2a6d63db5..6cde5b5e84 100644 --- a/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp +++ b/Code/Framework/AzFramework/Tests/ArchiveCompressionTests.cpp @@ -94,7 +94,7 @@ namespace UnitTest fileIo->Remove(testArchivePath.c_str()); // ------------ BASIC TEST: Create and read Empty Archive ------------ - AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath.c_str(), nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath.c_str(), {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); pArchive.reset(); EXPECT_TRUE(IsPackValid(testArchivePath.c_str())); @@ -122,7 +122,7 @@ namespace UnitTest checkSums[pos] = static_cast(pos % 256); } - auto pArchive = archive->OpenArchive(testArchivePath.c_str(), nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + auto pArchive = archive->OpenArchive(testArchivePath.c_str(), {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); // the strategy here is to find errors related to file sizes, alignment, overwrites @@ -143,7 +143,7 @@ namespace UnitTest // --------------------------------------------- read it back and verify - pArchive = archive->OpenArchive(testArchivePath.c_str(), nullptr, openFlags); + pArchive = archive->OpenArchive(testArchivePath.c_str(), {}, openFlags); EXPECT_NE(nullptr, pArchive); for (int j = 0; j < iterations; ++j) @@ -241,7 +241,7 @@ namespace UnitTest // ------------------------------------------------------------------------------------------- // read it back and verify - pArchive = archive->OpenArchive(testArchivePath.c_str(), nullptr, openFlags); + pArchive = archive->OpenArchive(testArchivePath.c_str(), {}, openFlags); EXPECT_NE(nullptr, pArchive); for (int j = 0; j < iterations; ++j) @@ -298,7 +298,7 @@ namespace UnitTest } // first, reset the pack to the original state: - auto pArchive = archive->OpenArchive(testArchivePath.c_str(), nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + auto pArchive = archive->OpenArchive(testArchivePath.c_str(), {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); for (int j = 0; j < iterations; ++j) @@ -382,7 +382,7 @@ namespace UnitTest // ------------------------------------------------------------------------------------------- // read it back and verify - pArchive = archive->OpenArchive(testArchivePath.c_str(), nullptr, openFlags); + pArchive = archive->OpenArchive(testArchivePath.c_str(), {}, openFlags); EXPECT_NE(nullptr, pArchive); writeCount = 0; diff --git a/Code/Framework/AzFramework/Tests/ArchiveTests.cpp b/Code/Framework/AzFramework/Tests/ArchiveTests.cpp index ecb495cd61..8e88ccfc39 100644 --- a/Code/Framework/AzFramework/Tests/ArchiveTests.cpp +++ b/Code/Framework/AzFramework/Tests/ArchiveTests.cpp @@ -256,7 +256,7 @@ namespace UnitTest fileIo->CreatePath("@usercache@/levels/test"); // setup test archive and file - AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath_withSubfolders.c_str(), nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath_withSubfolders.c_str(), {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); EXPECT_EQ(0, pArchive->UpdateFile(fileInArchiveFile, dataString.data(), dataString.size(), AZ::IO::INestedArchive::METHOD_COMPRESS, AZ::IO::INestedArchive::LEVEL_FASTEST)); pArchive.reset(); @@ -291,7 +291,7 @@ namespace UnitTest archive->ClosePack(filePath.c_str()); fileIo->Remove(filePath.c_str()); - auto pArchive = archive->OpenArchive(filePath.c_str(), nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + auto pArchive = archive->OpenArchive(filePath.c_str(), {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); pArchive.reset(); archive->ClosePack(filePath.c_str()); @@ -478,7 +478,7 @@ namespace UnitTest bool found_mylevel_file{}; bool found_mylevel_folder{}; - AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath_withMountPoint, nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath_withMountPoint, {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); EXPECT_EQ(0, pArchive->UpdateFile("levelinfo.xml", dataString.data(), dataString.size(), AZ::IO::INestedArchive::METHOD_COMPRESS, AZ::IO::INestedArchive::LEVEL_FASTEST)); pArchive.reset(); @@ -629,7 +629,7 @@ namespace UnitTest normalFileHandle = InvalidHandle; EXPECT_TRUE(cpfio.Exists("@log@/unittesttemp/realfileforunittest.xml")); - AZStd::intrusive_ptr pArchive = archive->OpenArchive(genericArchiveFileName, nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + AZStd::intrusive_ptr pArchive = archive->OpenArchive(genericArchiveFileName, {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); EXPECT_EQ(0, pArchive->UpdateFile("testfile.xml", dataString, aznumeric_cast(dataLen), AZ::IO::INestedArchive::METHOD_COMPRESS, AZ::IO::INestedArchive::LEVEL_FASTEST)); pArchive.reset(); @@ -773,7 +773,7 @@ namespace UnitTest fileIo->Remove(testArchivePath); // ------------ BASIC TEST: Create and read Empty Archive ------------ - AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath, nullptr, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); + AZStd::intrusive_ptr pArchive = archive->OpenArchive(testArchivePath, {}, AZ::IO::INestedArchive::FLAGS_CREATE_NEW); EXPECT_NE(nullptr, pArchive); EXPECT_EQ(0, pArchive->UpdateFile("foundit.dat", const_cast("test"), 4, AZ::IO::INestedArchive::METHOD_COMPRESS, AZ::IO::INestedArchive::LEVEL_BEST)); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp index 77b9185e82..95dc0f36c4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp @@ -102,7 +102,7 @@ namespace AzToolsFramework else { AZStd::string error = AZStd::string::format("Could not resolve path name for asset {%s}.", id.ToString().c_str()); - assetCheckoutAndSaveCallback(false, error, nullptr); + assetCheckoutAndSaveCallback(false, error, AZStd::string{}); } } diff --git a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h index d59639dee5..495fdcde07 100644 --- a/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h +++ b/Gems/EMotionFX/Code/MCore/Source/MCoreCommandManager.h @@ -40,7 +40,7 @@ namespace MCore CommandHistoryEntry() : m_commandGroup(nullptr) , m_executedCommand(nullptr) - , m_parameters(nullptr) {} + {} /** * Extended Constructor. diff --git a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp index 94a4c77593..60109fc49c 100644 --- a/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp +++ b/Gems/LyShine/Code/Editor/Animation/Controls/UiSplineCtrlEx.cpp @@ -78,7 +78,7 @@ protected: m_splineEntries.resize(m_splineEntries.size() + 1); SplineEntry& entry = m_splineEntries.back(); ISplineSet* pSplineSet = (pCtrl ? pCtrl->m_pSplineSet : 0); - entry.id = (pSplineSet ? pSplineSet->GetIDFromSpline(pSpline) : 0); + entry.id = (pSplineSet ? pSplineSet->GetIDFromSpline(pSpline) : AZStd::string{}); entry.pSpline = pSpline; const int numKeys = pSpline->GetKeyCount(); diff --git a/Gems/SaveData/Code/Source/Platform/Android/SaveData_SystemComponent_Android.cpp b/Gems/SaveData/Code/Source/Platform/Android/SaveData_SystemComponent_Android.cpp index 26760ca002..cf083e26ca 100644 --- a/Gems/SaveData/Code/Source/Platform/Android/SaveData_SystemComponent_Android.cpp +++ b/Gems/SaveData/Code/Source/Platform/Android/SaveData_SystemComponent_Android.cpp @@ -59,7 +59,7 @@ namespace SaveData //////////////////////////////////////////////////////////////////////////////////////////// //! The absolute path to the application's save data dircetory. - AZStd::string m_saveDataDircetoryPathAbsolute = nullptr; + AZStd::string m_saveDataDircetoryPathAbsolute; }; //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/SaveData/Code/Source/Platform/Common/Apple/SaveData_SystemComponent_Apple.mm b/Gems/SaveData/Code/Source/Platform/Common/Apple/SaveData_SystemComponent_Apple.mm index 882723de13..e4c1f8a0d8 100644 --- a/Gems/SaveData/Code/Source/Platform/Common/Apple/SaveData_SystemComponent_Apple.mm +++ b/Gems/SaveData/Code/Source/Platform/Common/Apple/SaveData_SystemComponent_Apple.mm @@ -60,7 +60,7 @@ namespace SaveData //////////////////////////////////////////////////////////////////////////////////////////// //! The absolute path to the application's save data dircetory. - AZStd::string m_saveDataDircetoryPathAbsolute = nullptr; + AZStd::string m_saveDataDircetoryPathAbsolute; }; //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp b/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp index 2e473cfea7..4c182ecd17 100644 --- a/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp +++ b/Gems/SaveData/Code/Source/Platform/Windows/SaveData_SystemComponent_Windows.cpp @@ -62,7 +62,7 @@ namespace SaveData //////////////////////////////////////////////////////////////////////////////////////////// //! The absolute path to the application's save data dircetory. - AZStd::string m_saveDataDircetoryPathAbsolute = nullptr; + AZStd::string m_saveDataDircetoryPathAbsolute; }; //////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp index 390dbaf0fb..b29992f9b1 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp @@ -1322,7 +1322,7 @@ namespace ScriptCanvasEditor if (seperator == AZStd::string_view::npos) { - categoryTrail = nullptr; + categoryTrail = {}; } else { diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/CreateElementsStates.h b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/CreateElementsStates.h index 156933063f..58779e91f6 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/CreateElementsStates.h +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Include/ScriptCanvasDeveloperEditor/EditorAutomation/EditorAutomationStates/CreateElementsStates.h @@ -131,7 +131,7 @@ namespace ScriptCanvasDeveloper QString m_nodeName; - AutomationStateModelId m_endpointId = nullptr; + AutomationStateModelId m_endpointId; AutomationStateModelId m_scenePointId; AutomationStateModelId m_nodeOutputId; From 47a8dbc1d05a1a5a7b6125ae677896de18666104 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Thu, 16 Sep 2021 10:59:23 -0700 Subject: [PATCH 165/274] Adds Atom component tests into the new parallel + batched test approach (#4039) * create PoC for starting point for parallel + batched Atom tests Signed-off-by: jromnoa * CMakeLists.txt update Signed-off-by: jromnoa * saving progress on re-factor for parallel and batched tests, added Tracer(), added Report(), and added new exit code validation method but code is unfinished still Signed-off-by: jromnoa * finalize conversion of component tests into new optimized test setup for batched/parallel runs Signed-off-by: jromnoa * fix REDO deletion check, remove class referencing a test not yet added to parallel runs Signed-off-by: jromnoa * revert hydra_AtomEditorComponents_AddedToEntity.py back to its original version Signed-off-by: jromnoa * re-add the DepthOfField component to expected_lines for non-optimized main suite (removed on accident) Signed-off-by: jromnoa * remove test comments from legal header, add EditorEntity() class, remove hydra calls - updated for Decal component, but the next commit will get the rest Signed-off-by: jromnoa * saving progress on converting over fully to using EditorEntity() per PR comments - almost done, will finish tomorrow Signed-off-by: jromnoa * add new test setup docstring, fix the create entity test step wording, re-add accidental removal of string text from editor_entity_utils.py Signed-off-by: jromnoa * finalize PR concerns, use EditorEntity object for most/all calls, tests pass when run Signed-off-by: jromnoa * remove accidental change Signed-off-by: jromnoa * update helper.open_level() call to not include 'Physics' in path, remove unnecessary f-string calls Signed-off-by: jromnoa * editor_python_test_tools.asset_utils.Asset.find_asset_by_path(), add is_hidden() and is_visible() to editor_python_test_tools to use for verification, clean up UNDO/REDO comments, fix test order in file to match the order of the test files Signed-off-by: jromnoa --- .../editor_entity_utils.py | 47 ++++- .../PythonTests/atom_renderer/CMakeLists.txt | 19 ++ .../hydra_AtomEditorComponents_DecalAdded.py | 151 +++++++++++++++ ..._AtomEditorComponents_DepthOfFieldAdded.py | 173 ++++++++++++++++++ ...mEditorComponents_DirectionalLightAdded.py | 157 ++++++++++++++++ ...AtomEditorComponents_DisplayMapperAdded.py | 137 ++++++++++++++ ...omEditorComponents_ExposureControlAdded.py | 145 +++++++++++++++ ...EditorComponents_GlobalSkylightIBLAdded.py | 164 +++++++++++++++++ .../hydra_AtomEditorComponents_LightAdded.py | 136 ++++++++++++++ ...dra_AtomEditorComponents_LightComponent.py | 6 +- ...a_AtomEditorComponents_PhysicalSkyAdded.py | 136 ++++++++++++++ ...ponents_PostFXRadiusWeightModifierAdded.py | 138 ++++++++++++++ .../hydra_AtomMaterialEditor_BasicTests.py | 8 +- ...GPUTest_AtomFeatureIntegrationBenchmark.py | 5 - .../hydra_GPUTest_BasicLevelSetup.py | 5 - .../hydra_GPUTest_LightComponent.py | 6 - .../test_Atom_MainSuite_Optimized.py | 43 +++++ 17 files changed, 1450 insertions(+), 26 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DecalAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DepthOfFieldAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DirectionalLightAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DisplayMapperAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_ExposureControlAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PhysicalSkyAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py create mode 100644 AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index fec9d9880b..154b5730d7 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -20,6 +20,7 @@ import azlmbr.legacy.general as general # Helper file Imports from editor_python_test_tools.utils import Report + class EditorComponent: """ EditorComponent class used to set and get the component property value using path @@ -28,7 +29,6 @@ class EditorComponent: which also assigns self.id and self.type_id to the EditorComponent object. """ - # Methods def get_component_name(self) -> str: """ Used to get name of component @@ -87,6 +87,13 @@ class EditorComponent: outcome.IsSuccess() ), f"Failure: Could not set value to '{self.get_component_name()}' : '{component_property_path}'" + def is_enabled(self): + """ + Used to verify if the component is enabled. + :return: True if enabled, otherwise False. + """ + return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", self.id) + @staticmethod def get_type_ids(component_names: list) -> list: """ @@ -254,7 +261,7 @@ class EditorEntity: def get_components_of_type(self, component_names: list) -> List[EditorComponent]: """ Used to get components of type component_name that already exists on Entity - :param component_name: Name to component to check + :param component_names: List of names of components to check :return: List of Entity Component objects of given component name """ component_list = [] @@ -318,3 +325,39 @@ class EditorEntity: editor.EditorEntityAPIBus(bus.Event, "SetStartStatus", self.id, status_to_set) set_status = self.get_start_status() assert set_status == status_to_set, f"Failed to set start status of {desired_start_status} to {self.get_name}" + + def delete(self) -> None: + """ + Used to delete the Entity. + :return: None + """ + editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntityById", self.id) + + def set_visibility_state(self, is_visible: bool) -> None: + """ + Sets the visibility state on the object to visible or not visible. + :param is_visible: True for making visible, False to make not visible. + :return: None + """ + editor.EditorEntityAPIBus(bus.Event, "SetVisibilityState", self.id, is_visible) + + def exists(self) -> bool: + """ + Used to verify if the Entity exists. + :return: True if the Entity exists, False otherwise. + """ + return editor.ToolsApplicationRequestBus(bus.Broadcast, "EntityExists", self.id) + + def is_hidden(self) -> bool: + """ + Gets the "isHidden" value from the Entity. + :return: True if "isHidden" is enabled, False otherwise. + """ + return editor.EditorEntityInfoRequestBus(bus.Event, "IsHidden", self.id) + + def is_visible(self) -> bool: + """ + Gets the "isVisible" value from the Entity. + :return: True if "isVisible" is enabled, False otherwise. + """ + return editor.EditorEntityInfoRequestBus(bus.Event, "IsVisible", self.id) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt index 992420904c..f91423324d 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt @@ -22,6 +22,21 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT AssetProcessor AutomatedTesting.Assets Editor + COMPONENT + Atom + ) + ly_add_pytest( + NAME AutomatedTesting::AtomRenderer_HydraTests_MainOptimized + TEST_SUITE main + PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_MainSuite_Optimized.py + TEST_SERIAL + TIMEOUT 600 + RUNTIME_DEPENDENCIES + AssetProcessor + AutomatedTesting.Assets + Editor + COMPONENT + Atom ) ly_add_pytest( NAME AutomatedTesting::AtomRenderer_HydraTests_Sandbox @@ -33,6 +48,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT AssetProcessor AutomatedTesting.Assets Editor + COMPONENT + Atom ) ly_add_pytest( NAME AutomatedTesting::AtomRenderer_HydraTests_GPUTests @@ -45,6 +62,8 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT AssetProcessor AutomatedTesting.Assets Editor + COMPONENT + Atom ) ly_add_pytest( NAME AutomatedTesting::AtomRenderer_HydraTests_ShaderBuildPipeline diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DecalAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DecalAdded.py new file mode 100644 index 0000000000..d68e1f5844 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DecalAdded.py @@ -0,0 +1,151 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + decal_creation = ("Decal Entity successfully created", "Decal Entity failed to be created") + decal_component = ("Entity has a Decal component", "Entity failed to find Decal component") + material_property_set = ("Material property set on Decal component", "Couldn't set Material property on Decal component") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_Decal_AddedToEntity(): + """ + Summary: + Tests the Decal component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Decal entity with no components. + 2) Add Decal component to Decal entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Set Material property on Decal component. + 9) Delete Decal entity. + 10) UNDO deletion. + 11) REDO deletion. + 12) Look for errors. + + :return: None + """ + import os + + import azlmbr.asset as asset + import azlmbr.bus as bus + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Decal entity with no components. + decal_name = "Decal (Atom)" + decal_entity = EditorEntity.create_editor_entity_at(math.Vector3(512.0, 512.0, 34.0), decal_name) + Report.critical_result(Tests.decal_creation, decal_entity.exists()) + + # 2. Add Decal component to Decal entity. + decal_component = decal_entity.add_component(decal_name) + Report.critical_result(Tests.decal_component, decal_entity.has_component(decal_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not decal_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, decal_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + decal_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, decal_entity.is_hidden() is True) + + # 7. Test IsVisible. + decal_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, decal_entity.is_visible() is True) + + # 8. Set Material property on Decal component. + decal_material_property_path = "Controller|Configuration|Material" + decal_material_asset_path = os.path.join("AutomatedTesting", "Materials", "basic_grey.material") + decal_material_asset = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", decal_material_asset_path, math.Uuid(), False) + decal_component.set_component_property_value(decal_material_property_path, decal_material_asset) + get_material_property = decal_component.get_component_property_value(decal_material_property_path) + Report.result(Tests.material_property_set, get_material_property == decal_material_asset) + + # 9. Delete Decal entity. + decal_entity.delete() + Report.result(Tests.entity_deleted, not decal_entity.exists()) + + # 10. UNDO deletion. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.deletion_undo, decal_entity.exists()) + + # 11. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not decal_entity.exists()) + + # 12. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_Decal_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DepthOfFieldAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DepthOfFieldAdded.py new file mode 100644 index 0000000000..80284902ea --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DepthOfFieldAdded.py @@ -0,0 +1,173 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to Camera entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + camera_property_set = ("DepthOfField Entity set Camera Entity", "DepthOfField Entity could not set Camera Entity") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + depth_of_field_creation = ("DepthOfField Entity successfully created", "DepthOfField Entity failed to be created") + depth_of_field_component = ("Entity has a DepthOfField component", "Entity failed to find DepthOfField component") + depth_of_field_disabled = ("DepthOfField component disabled", "DepthOfField component was not disabled.") + post_fx_component = ("Entity has a Post FX Layer component", "Entity did not have a Post FX Layer component") + depth_of_field_enabled = ("DepthOfField component enabled", "DepthOfField component was not enabled.") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_DepthOfField_AddedToEntity(): + """ + Summary: + Tests the DepthOfField component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a DepthOfField entity with no components. + 2) Add a DepthOfField component to DepthOfField entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Verify DepthOfField component not enabled. + 6) Add Post FX Layer component since it is required by the DepthOfField component. + 7) Verify DepthOfField component is enabled. + 8) Enter/Exit game mode. + 9) Test IsHidden. + 10) Test IsVisible. + 11) Add Camera entity. + 12) Add Camera component to Camera entity. + 13) Set the DepthOfField components's Camera Entity to the newly created Camera entity. + 14) Delete DepthOfField entity. + 15) UNDO deletion. + 16) REDO deletion. + 17) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a DepthOfField entity with no components. + depth_of_field_name = "DepthOfField" + depth_of_field_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), depth_of_field_name) + Report.critical_result(Tests.depth_of_field_creation, depth_of_field_entity.exists()) + + # 2. Add a DepthOfField component to DepthOfField entity. + depth_of_field_component = depth_of_field_entity.add_component(depth_of_field_name) + Report.critical_result(Tests.depth_of_field_component, depth_of_field_entity.has_component(depth_of_field_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not depth_of_field_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, depth_of_field_entity.exists()) + + # 5. Verify DepthOfField component not enabled. + Report.result(Tests.depth_of_field_disabled, not depth_of_field_component.is_enabled()) + + # 6. Add Post FX Layer component since it is required by the DepthOfField component. + post_fx_layer = "PostFX Layer" + depth_of_field_entity.add_component(post_fx_layer) + Report.result(Tests.post_fx_component, depth_of_field_entity.has_component(post_fx_layer)) + + # 7. Verify DepthOfField component is enabled. + Report.result(Tests.depth_of_field_enabled, depth_of_field_component.is_enabled()) + + # 8. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 9. Test IsHidden. + depth_of_field_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, depth_of_field_entity.is_hidden() is True) + + # 10. Test IsVisible. + depth_of_field_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, depth_of_field_entity.is_visible() is True) + + # 11. Add Camera entity. + camera_name = "Camera" + camera_entity = EditorEntity.create_editor_entity_at(math.Vector3(512.0, 512.0, 34.0), camera_name) + Report.result(Tests.camera_creation, camera_entity.exists()) + + # 12. Add Camera component to Camera entity. + camera_entity.add_component(camera_name) + Report.result(Tests.camera_component_added, camera_entity.has_component(camera_name)) + + # 13. Set the DepthOfField components's Camera Entity to the newly created Camera entity. + depth_of_field_camera_property_path = "Controller|Configuration|Camera Entity" + depth_of_field_component.set_component_property_value(depth_of_field_camera_property_path, camera_entity.id) + camera_entity_set = depth_of_field_component.get_component_property_value(depth_of_field_camera_property_path) + Report.result(Tests.camera_property_set, camera_entity.id == camera_entity_set) + + # 14. Delete DepthOfField entity. + depth_of_field_entity.delete() + Report.result(Tests.entity_deleted, not depth_of_field_entity.exists()) + + # 15. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, depth_of_field_entity.exists()) + + # 16. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not depth_of_field_entity.exists()) + + # 17. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_DepthOfField_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DirectionalLightAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DirectionalLightAdded.py new file mode 100644 index 0000000000..048e132df4 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DirectionalLightAdded.py @@ -0,0 +1,157 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + directional_light_creation = ("Directional Light Entity successfully created", "Directional Light Entity failed to be created") + directional_light_component = ("Entity has a Directional Light component", "Entity failed to find Directional Light component") + shadow_camera_check = ("Directional Light component Shadow camera set", "Directional Light component Shadow camera was not set") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_DirectionalLight_AddedToEntity(): + """ + Summary: + Tests the Directional Light component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Directional Light entity with no components. + 2) Add Directional Light component to Directional Light entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Add Camera entity. + 9) Add Camera component to Camera entity + 10) Set the Directional Light component property Shadow|Camera to the Camera entity. + 11) Delete Directional Light entity. + 12) UNDO deletion. + 13) REDO deletion. + 14) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Directional Light entity with no components. + directional_light_name = "Directional Light" + directional_light_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), directional_light_name) + Report.critical_result(Tests.directional_light_creation, directional_light_entity.exists()) + + # 2. Add Directional Light component to Directional Light entity. + directional_light_component = directional_light_entity.add_component(directional_light_name) + Report.critical_result( + Tests.directional_light_component, directional_light_entity.has_component(directional_light_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not directional_light_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, directional_light_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + directional_light_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, directional_light_entity.is_hidden() is True) + + # 7. Test IsVisible. + directional_light_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, directional_light_entity.is_visible() is True) + + # 8. Add Camera entity. + camera_name = "Camera" + camera_entity = EditorEntity.create_editor_entity_at(math.Vector3(512.0, 512.0, 34.0), camera_name) + Report.result(Tests.camera_creation, camera_entity.exists()) + + # 9. Add Camera component to Camera entity. + camera_entity.add_component(camera_name) + Report.result(Tests.camera_component_added, camera_entity.has_component(camera_name)) + + # 10. Set the Directional Light component property Shadow|Camera to the Camera entity. + shadow_camera_property_path = "Controller|Configuration|Shadow|Camera" + directional_light_component.set_component_property_value(shadow_camera_property_path, camera_entity.id) + shadow_camera_set = directional_light_component.get_component_property_value(shadow_camera_property_path) + Report.result(Tests.shadow_camera_check, camera_entity.id == shadow_camera_set) + + # 11. Delete DirectionalLight entity. + directional_light_entity.delete() + Report.result(Tests.entity_deleted, not directional_light_entity.exists()) + + # 12. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, directional_light_entity.exists()) + + # 13. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not directional_light_entity.exists()) + + # 14. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_DirectionalLight_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DisplayMapperAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DisplayMapperAdded.py new file mode 100644 index 0000000000..39d7acf4f4 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DisplayMapperAdded.py @@ -0,0 +1,137 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + display_mapper_creation = ("Display Mapper Entity successfully created", "Display Mapper Entity failed to be created") + display_mapper_component = ("Entity has a Display Mapper component", "Entity failed to find Display Mapper component") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_DisplayMapper_AddedToEntity(): + """ + Summary: + Tests the Display Mapper component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Display Mapper entity with no components. + 2) Add Display Mapper component to Display Mapper entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Delete Display Mapper entity. + 9) UNDO deletion. + 10) REDO deletion. + 11) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Display Mapper entity with no components. + display_mapper = "Display Mapper" + display_mapper_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), f"{display_mapper}") + Report.critical_result(Tests.display_mapper_creation, display_mapper_entity.exists()) + + # 2. Add Display Mapper component to Display Mapper entity. + display_mapper_entity.add_component(display_mapper) + Report.critical_result(Tests.display_mapper_component, display_mapper_entity.has_component(display_mapper)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not display_mapper_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, display_mapper_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + display_mapper_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, display_mapper_entity.is_hidden() is True) + + # 7. Test IsVisible. + display_mapper_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, display_mapper_entity.is_visible() is True) + + # 8. Delete Display Mapper entity. + display_mapper_entity.delete() + Report.result(Tests.entity_deleted, not display_mapper_entity.exists()) + + # 9. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, display_mapper_entity.exists()) + + # 10. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not display_mapper_entity.exists()) + + # 11. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_DisplayMapper_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_ExposureControlAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_ExposureControlAdded.py new file mode 100644 index 0000000000..23a84435f7 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_ExposureControlAdded.py @@ -0,0 +1,145 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + exposure_control_creation = ("ExposureControl Entity successfully created", "ExposureControl Entity failed to be created") + exposure_control_component = ("Entity has a Exposure Control component", "Entity failed to find Exposure Control component") + post_fx_component = ("Entity has a Post FX Layer component", "Entity did not have a Post FX Layer component") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_ExposureControl_AddedToEntity(): + """ + Summary: + Tests the Exposure Control component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create an Exposure Control entity with no components. + 2) Add Exposure Control component to Exposure Control entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Add Post FX Layer component. + 9) Delete Exposure Control entity. + 10) UNDO deletion. + 11) REDO deletion. + 12) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Creation of Exposure Control entity with no components. + exposure_control_name = "Exposure Control" + exposure_control_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), f"{exposure_control_name}") + Report.critical_result(Tests.exposure_control_creation, exposure_control_entity.exists()) + + # 2. Add Exposure Control component to Exposure Control entity. + exposure_control_entity.add_component(exposure_control_name) + Report.critical_result( + Tests.exposure_control_component, exposure_control_entity.has_component(exposure_control_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not exposure_control_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, exposure_control_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + exposure_control_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, exposure_control_entity.is_hidden() is True) + + # 7. Test IsVisible. + exposure_control_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, exposure_control_entity.is_visible() is True) + + # 8. Add Post FX Layer component. + post_fx_layer_name = "PostFX Layer" + exposure_control_entity.add_component(post_fx_layer_name) + Report.result(Tests.post_fx_component, exposure_control_entity.has_component(post_fx_layer_name)) + + # 9. Delete ExposureControl entity. + exposure_control_entity.delete() + Report.result(Tests.entity_deleted, not exposure_control_entity.exists()) + + # 10. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, exposure_control_entity.exists()) + + # 11. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not exposure_control_entity.exists()) + + # 12. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_ExposureControl_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py new file mode 100644 index 0000000000..cc891f5929 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py @@ -0,0 +1,164 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + global_skylight_creation = ("Global Skylight (IBL) Entity successfully created", "Global Skylight (IBL) Entity failed to be created") + global_skylight_component = ("Entity has a Global Skylight (IBL) component", "Entity failed to find Global Skylight (IBL) component") + diffuse_image_set = ("Entity has the Diffuse Image set", "Entity did not the Diffuse Image set") + specular_image_set = ("Entity has the Specular Image set", "Entity did not the Specular Image set") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_GlobalSkylightIBL_AddedToEntity(): + """ + Summary: + Tests the Global Skylight (IBL) component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Global Skylight (IBL) entity with no components. + 2) Add Global Skylight (IBL) component to Global Skylight (IBL) entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Add Post FX Layer component. + 9) Add Camera component + 10) Delete Global Skylight (IBL) entity. + 11) UNDO deletion. + 12) REDO deletion. + 13) Look for errors. + + :return: None + """ + import os + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.asset_utils import Asset + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Global Skylight (IBL) entity with no components. + global_skylight_name = "Global Skylight (IBL)" + global_skylight_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), global_skylight_name) + Report.critical_result(Tests.global_skylight_creation, global_skylight_entity.exists()) + + # 2. Add Global Skylight (IBL) component to Global Skylight (IBL) entity. + global_skylight_component = global_skylight_entity.add_component(global_skylight_name) + Report.critical_result( + Tests.global_skylight_component, global_skylight_entity.has_component(global_skylight_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not global_skylight_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, global_skylight_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + global_skylight_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, global_skylight_entity.is_hidden() is True) + + # 7. Test IsVisible. + global_skylight_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, global_skylight_entity.is_visible() is True) + + # 8. Set the Diffuse Image asset on the Global Skylight (IBL) entity. + global_skylight_diffuse_image_property = "Controller|Configuration|Diffuse Image" + diffuse_image_path = os.path.join("LightingPresets", "greenwich_park_02_4k_iblskyboxcm.exr.streamingimage") + diffuse_image_asset = Asset.find_asset_by_path(diffuse_image_path, False) + global_skylight_component.set_component_property_value( + global_skylight_diffuse_image_property, diffuse_image_asset.id) + diffuse_image_set = global_skylight_component.get_component_property_value( + global_skylight_diffuse_image_property) + Report.result(Tests.diffuse_image_set, diffuse_image_set == diffuse_image_asset.id) + + # 9. Set the Specular Image asset on the Global Light (IBL) entity. + global_skylight_specular_image_property = "Controller|Configuration|Specular Image" + specular_image_path = os.path.join("LightingPresets", "greenwich_park_02_4k_iblskyboxcm.exr.streamingimage") + specular_image_asset = Asset.find_asset_by_path(specular_image_path, False) + global_skylight_component.set_component_property_value( + global_skylight_specular_image_property, specular_image_asset.id) + specular_image_added = global_skylight_component.get_component_property_value( + global_skylight_specular_image_property) + Report.result(Tests.specular_image_set, specular_image_added == specular_image_asset.id) + + # 10. Delete Global Skylight (IBL) entity. + global_skylight_entity.delete() + Report.result(Tests.entity_deleted, not global_skylight_entity.exists()) + + # 11. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, global_skylight_entity.exists()) + + # 12. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not global_skylight_entity.exists()) + + # 13. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_GlobalSkylightIBL_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightAdded.py new file mode 100644 index 0000000000..8b1432f1f7 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightAdded.py @@ -0,0 +1,136 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + light_creation = ("Light Entity successfully created", "Light Entity failed to be created") + light_component = ("Entity has a Light component", "Entity failed to find Light component") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_Light_AddedToEntity(): + """ + Summary: + Tests the Light component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Light entity with no components. + 2) Add Light component to the Light entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Delete Light entity. + 9) UNDO deletion. + 10) REDO deletion. + 11) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Light entity with no components. + light_name = "Light" + light_entity = EditorEntity.create_editor_entity_at(math.Vector3(512.0, 512.0, 34.0), light_name) + Report.critical_result(Tests.light_creation, light_entity.exists()) + + # 2. Add Light component to the Light entity. + light_entity.add_component(light_name) + Report.critical_result(Tests.light_component, light_entity.has_component(light_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not light_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, light_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + light_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, light_entity.is_hidden() is True) + + # 7. Test IsVisible. + light_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, light_entity.is_visible() is True) + + # 8. Delete Light entity. + light_entity.delete() + Report.result(Tests.entity_deleted, not light_entity.exists()) + + # 9. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, light_entity.exists()) + + # 10. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not light_entity.exists()) + + # 11. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_Light_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py index 8d138e67b8..6da922bd9f 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py @@ -1,10 +1,8 @@ """ -Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. SPDX-License-Identifier: Apache-2.0 OR MIT - -Hydra script that creates an entity, attaches the Light component to it for test verifications. -The test verifies that each light type option is available and can be selected without errors. """ import os diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PhysicalSkyAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PhysicalSkyAdded.py new file mode 100644 index 0000000000..04441d5b2c --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PhysicalSkyAdded.py @@ -0,0 +1,136 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + physical_sky_creation = ("Physical Sky Entity successfully created", "Physical Sky Entity failed to be created") + physical_sky_component = ("Entity has a Physical Sky component", "Entity failed to find Physical Sky component") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_PhysicalSky_AddedToEntity(): + """ + Summary: + Tests the Physical Sky component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Physical Sky entity with no components. + 2) Add Physical Sky component to Physical Sky entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Delete Physical Sky entity. + 9) UNDO deletion. + 10) REDO deletion. + 11) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Physical Sky entity with no components. + physical_sky_name = "Physical Sky" + physical_sky_entity = EditorEntity.create_editor_entity_at(math.Vector3(512.0, 512.0, 34.0), physical_sky_name) + Report.critical_result(Tests.physical_sky_creation, physical_sky_entity.exists()) + + # 2. Add Physical Sky component to Physical Sky entity. + physical_sky_entity.add_component(physical_sky_name) + Report.critical_result(Tests.physical_sky_component, physical_sky_entity.has_component(physical_sky_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not physical_sky_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, physical_sky_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + physical_sky_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, physical_sky_entity.is_hidden() is True) + + # 7. Test IsVisible. + physical_sky_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, physical_sky_entity.is_visible() is True) + + # 8. Delete Physical Sky entity. + physical_sky_entity.delete() + Report.result(Tests.entity_deleted, not physical_sky_entity.exists()) + + # 9. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, physical_sky_entity.exists()) + + # 10. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not physical_sky_entity.exists()) + + # 11. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_PhysicalSky_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py new file mode 100644 index 0000000000..8914ab9e7e --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py @@ -0,0 +1,138 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +# fmt: off +class Tests: + camera_creation = ("Camera Entity successfully created", "Camera Entity failed to be created") + camera_component_added = ("Camera component was added to entity", "Camera component failed to be added to entity") + camera_component_check = ("Entity has a Camera component", "Entity failed to find Camera component") + creation_undo = ("UNDO Entity creation success", "UNDO Entity creation failed") + creation_redo = ("REDO Entity creation success", "REDO Entity creation failed") + postfx_radius_weight_creation = ("PostFX Radius Weight Modifier Entity successfully created", "PostFX Radius Weight Modifier Entity failed to be created") + postfx_radius_weight_component = ("Entity has a PostFX Radius Weight Modifier component", "Entity failed to find PostFX Radius Weight Modifier component") + enter_game_mode = ("Entered game mode", "Failed to enter game mode") + exit_game_mode = ("Exited game mode", "Couldn't exit game mode") + is_visible = ("Entity is visible", "Entity was not visible") + is_hidden = ("Entity is hidden", "Entity was not hidden") + entity_deleted = ("Entity deleted", "Entity was not deleted") + deletion_undo = ("UNDO deletion success", "UNDO deletion failed") + deletion_redo = ("REDO deletion success", "REDO deletion failed") + no_error_occurred = ("No errors detected", "Errors were detected") +# fmt: on + + +def AtomEditorComponents_PostFXRadiusWeightModifier_AddedToEntity(): + """ + Summary: + Tests the PostFX Radius Weight Modifier component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Post FX Radius Weight Modifier entity with no components. + 2) Add Post FX Radius Weight Modifier component to Post FX Radius Weight Modifier entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Delete PostFX Radius Weight Modifier entity. + 9) UNDO deletion. + 10) REDO deletion. + 11) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Post FX Radius Weight Modifier entity with no components. + postfx_radius_weight_name = "PostFX Radius Weight Modifier" + postfx_radius_weight_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), postfx_radius_weight_name) + Report.critical_result(Tests.postfx_radius_weight_creation, postfx_radius_weight_entity.exists()) + + # 2. Add Post FX Radius Weight Modifier component to Post FX Radius Weight Modifier entity. + postfx_radius_weight_entity.add_component(postfx_radius_weight_name) + Report.critical_result( + Tests.postfx_radius_weight_component, postfx_radius_weight_entity.has_component(postfx_radius_weight_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not postfx_radius_weight_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, postfx_radius_weight_entity.exists()) + + # 5. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + postfx_radius_weight_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, postfx_radius_weight_entity.is_hidden() is True) + + # 7. Test IsVisible. + postfx_radius_weight_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, postfx_radius_weight_entity.is_visible() is True) + + # 8. Delete PostFX Radius Weight Modifier entity. + postfx_radius_weight_entity.delete() + Report.result(Tests.entity_deleted, not postfx_radius_weight_entity.exists()) + + # 9. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, postfx_radius_weight_entity.exists()) + + # 10. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not postfx_radius_weight_entity.exists()) + + # 11. Look for errors. + helper.wait_for_condition(lambda: error_tracer.has_errors, 1.0) + Report.result(Tests.no_error_occurred, not error_tracer.has_errors) + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_PostFXRadiusWeightModifier_AddedToEntity) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py index 9047b4c871..1e250e5b9f 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py @@ -3,12 +3,12 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. SPDX-License-Identifier: Apache-2.0 OR MIT - -import azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe -This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe -You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear. """ +# import azlmbr.materialeditor will fail with a ModuleNotFound error when using this script with Editor.exe +# This is because azlmbr.materialeditor only binds to MaterialEditor.exe and not Editor.exe +# You need to launch this script with MaterialEditor.exe in order for azlmbr.materialeditor to appear. + import os import sys import time diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py index 3aa9fe660c..7e7087fb42 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py @@ -3,11 +3,6 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. SPDX-License-Identifier: Apache-2.0 OR MIT - -Hydra script that is used to create a new level with a default rendering setup. -After the level is setup, screenshots are diffed against golden images are used to verify pass/fail results of the test. - -See the run() function for more in-depth test info. """ import os diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py index 920c044be0..24ebbdff63 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py @@ -3,11 +3,6 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. SPDX-License-Identifier: Apache-2.0 OR MIT - -Hydra script that is used to create a new level with a default rendering setup. -After the level is setup, screenshots are diffed against golden images are used to verify pass/fail results of the test. - -See the run() function for more in-depth test info. """ import os diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py index 8063445608..5c019dc3f3 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py @@ -3,12 +3,6 @@ Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution. SPDX-License-Identifier: Apache-2.0 OR MIT - -Hydra script that is used to create an entity with a Light component attached. -It then updates the property values of the Light component and takes a screenshot. -The screenshot is compared against an expected golden image for test verification. - -See the run() function for more in-depth test info. """ import os import sys diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py new file mode 100644 index 0000000000..329d3ecb91 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py @@ -0,0 +1,43 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" +import pytest + +from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite + + +@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.") +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +@pytest.mark.parametrize("launcher_platform", ['windows_editor']) +class TestAutomation(EditorTestSuite): + + class AtomEditorComponents_DecalAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DecalAdded as test_module + + class AtomEditorComponents_DepthOfFieldAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DepthOfFieldAdded as test_module + + class AtomEditorComponents_DirectionalLightAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DirectionalLightAdded as test_module + + class AtomEditorComponents_ExposureControlAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_ExposureControlAdded as test_module + + class AtomEditorComponents_GlobalSkylightIBLAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_GlobalSkylightIBLAdded as test_module + + class AtomEditorComponents_PhysicalSkyAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_PhysicalSkyAdded as test_module + + class AtomEditorComponents_PostFXRadiusWeightModifierAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import ( + hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded as test_module) + + class AtomEditorComponents_LightAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_LightAdded as test_module + + class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest): + from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DisplayMapperAdded as test_module From 86ccf1c86e5a4255a8c5e09231d0351a34ac3cb8 Mon Sep 17 00:00:00 2001 From: bosnichd Date: Thu, 16 Sep 2021 12:26:57 -0600 Subject: [PATCH 166/274] Input context component (#4152) * Create a new InputContextComponent. - An InputContextComponent is used to configure (at edit time) the data necessary to create an AzFrameowrk::InputContext (at run time). The lifecycle of any InputContextComponent is controlled by the AZ::Entity it is attached to (adhering to the same rules as any other AZ::Component), and the InputContext which it owns is created/destroyed when the component is activated/deactivated. - The underlying AzFramework::InputContext and AzFramework::InputMapping* classes already exist, along with comprehensive unit tests (see Code/Framework/AzFramework/Tests/InputTests.cpp). All changes in this PR are simply to allow input contexts / input mappings to be defined/edited from the editor using data. - The new InputContextComponent is similar in many respects to the InputConfigurationComponent found in the StartingPointInput Gem, the main difference being that the user-defined input mapping objects the new component creates are identical (from the perspective of any input consumer) to 'raw' engine-defined input channels (the existing AzFramework::InputMapping class inherits from the existing AzFramework::InputChannel class). This means that any system which consumes input (in either C++ or lua) can seamlessly interchange between obtaining input using either the 'raw' engine-defined input channels (eg. InputDeviceGamepad::Button::A, InputDeviceKeyboard::Key::AlphanumericA, etc.) or any user-defined input mapping, which can now be defined from the editor using data. Ultimately I would like to deprecate the StartingPointInput::InputConfigurationComponent in favour of this new InputContextComponent, which isn't realistic at present because the former is used pervasively throughout many different projects, and it integrates with ScriptCanvas in a way that I have yet to replicate, but this is a step towards the goal of a unified, engine-wide input context/input mapping solution that can be used interchangeably by any system, project, or Gem. Signed-off-by: bosnichd * Edited some reflected property descriptions for clarity. Signed-off-by: bosnichd * Fix clang builds: - Add a missing virtual destructor. - Fix the scope of two reflected property attribute functions. Signed-off-by: bosnichd * Fix for InputContextComponent being reflected twice in some cirsumstances. Signed-off-by: bosnichd * Updates in response to PR feedback. Signed-off-by: bosnichd * More updates based on review feedback. Signed-off-by: bosnichd --- .../AzFramework/AzFrameworkModule.cpp | 2 + .../AzFramework/Input/Contexts/InputContext.h | 4 + .../Input/Contexts/InputContextComponent.cpp | 172 ++++++++++++++++++ .../Input/Contexts/InputContextComponent.h | 129 +++++++++++++ .../Input/Mappings/InputMapping.cpp | 147 +++++++++++++++ .../AzFramework/Input/Mappings/InputMapping.h | 106 +++++++++++ .../Input/Mappings/InputMappingAnd.cpp | 63 +++++++ .../Input/Mappings/InputMappingAnd.h | 32 ++++ .../Input/Mappings/InputMappingOr.cpp | 63 +++++++ .../Input/Mappings/InputMappingOr.h | 32 ++++ .../AzFramework/azframework_files.cmake | 2 + 11 files changed, 752 insertions(+) create mode 100644 Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.cpp create mode 100644 Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.h diff --git a/Code/Framework/AzFramework/AzFramework/AzFrameworkModule.cpp b/Code/Framework/AzFramework/AzFramework/AzFrameworkModule.cpp index c5fee7ec9a..83f1954e11 100644 --- a/Code/Framework/AzFramework/AzFramework/AzFrameworkModule.cpp +++ b/Code/Framework/AzFramework/AzFramework/AzFrameworkModule.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ namespace AzFramework AzFramework::CreateScriptDebugAgentFactory(), AzFramework::AssetSystem::AssetSystemComponent::CreateDescriptor(), AzFramework::InputSystemComponent::CreateDescriptor(), + AzFramework::InputContextComponent::CreateDescriptor(), #if !defined(AZCORE_EXCLUDE_LUA) AzFramework::ScriptComponent::CreateDescriptor(), diff --git a/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContext.h b/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContext.h index 7220b8b8d5..e7143a25b9 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContext.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContext.h @@ -55,6 +55,10 @@ namespace AzFramework // Allocator AZ_CLASS_ALLOCATOR(InputContext, AZ::SystemAllocator, 0); + //////////////////////////////////////////////////////////////////////////////////////////// + // Type Info + AZ_RTTI(InputContext, "{D17A85B2-405F-40AB-BBA7-F118256D39AB}", InputDevice); + //////////////////////////////////////////////////////////////////////////////////////////// //! Constructor //! \param[in] name Unique, will be truncated if exceeds InputDeviceId::MAX_NAME_LENGTH = 64 diff --git a/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.cpp b/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.cpp new file mode 100644 index 0000000000..ff147bd9d8 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.cpp @@ -0,0 +1,172 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +namespace AzFramework +{ + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("InputContextService", 0xa2734425)); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("Unique Name", &InputContextComponent::m_uniqueName) + ->Field("Input Mappings", &InputContextComponent::m_inputMappings) + ->Field("Local Player Index", &InputContextComponent::m_localPlayerIndex) + ->Field("Input Listener Priority", &InputContextComponent::m_inputListenerPriority) + ->Field("Consumes Processed Input", &InputContextComponent::m_consumesProcessedInput) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("Input Context", + "An input context is a collection of input mappings, which map 'raw' input to custom input channels (ie. events).") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::Category, "Input") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) + ->DataElement(AZ::Edit::UIHandlers::Default, &InputContextComponent::m_uniqueName, "Unique Name", + "The name of the input context, unique among all active input contexts and input devices.\n" + "This will be truncated if its length exceeds that of InputDeviceId::MAX_NAME_LENGTH = 64") + ->DataElement(AZ::Edit::UIHandlers::Default, &InputContextComponent::m_inputMappings, "Input Mappings", + "The list of all input mappings that will be created when the input context is activated.") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::SpinBox, &InputContextComponent::m_localPlayerIndex, "Local Player Index", + "The local player index that this context will receive input from (0 based, -1 means all controllers).\n" + "Will only work on platforms such as PC where the local user id corresponds to the local player index.\n" + "For other platforms, SetLocalUserId must be called at runtime with the id of a logged in user.") + ->Attribute(AZ::Edit::Attributes::Min, -1) + ->Attribute(AZ::Edit::Attributes::Max, 3) + ->DataElement(AZ::Edit::UIHandlers::SpinBox, &InputContextComponent::m_inputListenerPriority, "Input Listener Priority", + "The priority used to sort the input context relative to all other input event listeners.\n" + "Higher numbers indicate greater priority.") + ->Attribute(AZ::Edit::Attributes::Min, InputChannelEventListener::GetPriorityLast()) + ->Attribute(AZ::Edit::Attributes::Max, InputChannelEventListener::GetPriorityFirst()) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &InputContextComponent::m_consumesProcessedInput, "Consumes Processed Input", + "Should the input context consume input that is processed by any of its input mappings?") + ; + } + } + + InputMapping::ConfigBase::Reflect(context); + InputMappingAnd::Config::Reflect(context); + InputMappingOr::Config::Reflect(context); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + InputContextComponent::~InputContextComponent() + { + Deactivate(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::Init() + { + // The local player index that this component will receive input from (0 base, -1 wildcard) + // can be set from data, but will only work on platforms where the local user id corresponds + // to a local player index. For other platforms SetLocalUserId must be called at runtime with + // the id of a logged in local user, which will overwrite anything that is set here from data. + const LocalUserId localUserId = (m_localPlayerIndex == -1) ? LocalUserIdAny : aznumeric_cast(m_localPlayerIndex); + SetLocalUserId(localUserId); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::Activate() + { + InputContextComponentRequestBus::Handler::BusConnect(GetEntityId()); + CreateInputContext(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::Deactivate() + { + ResetInputContext(); + InputContextComponentRequestBus::Handler::BusDisconnect(GetEntityId()); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::SetLocalUserId(LocalUserId localUserId) + { + // Create a new filter, or reset any existing one if we have been passed LocalUserIdAny. + if (localUserId != LocalUserIdAny) + { + m_localUserIdFilter = AZStd::make_shared(InputChannelEventFilter::AnyChannelNameCrc32, + InputChannelEventFilter::AnyDeviceNameCrc32, + aznumeric_cast(m_localPlayerIndex)); + } + else + { + m_localUserIdFilter.reset(); + } + + // Set the filter if the input context has already been created. + if (m_inputContext) + { + m_inputContext->SetFilter(m_localUserIdFilter); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::CreateInputContext() + { + if (m_uniqueName.empty()) + { + AZ_Error("InputContextComponent", false, "Cannot create input context with empty name."); + return; + } + + if (InputDeviceRequests::FindInputDevice(InputDeviceId(m_uniqueName.c_str()))) + { + AZ_Error("InputContextComponent", false, + "Cannot create input context '%s' with non-unique name.", m_uniqueName.c_str()); + return; + } + + if (m_inputMappings.empty()) + { + AZ_Error("InputContextComponent", false, + "Cannot create input context '%s' with no input mappings.", m_uniqueName.c_str()); + return; + } + + // Create the input context. + InputContext::InitData initData; + initData.autoActivate = true; + initData.filter = m_localUserIdFilter; + initData.priority = m_inputListenerPriority; + initData.consumesProcessedInput = m_consumesProcessedInput; + m_inputContext = AZStd::make_unique(m_uniqueName.c_str(), initData); + + // Create and add all input mappings. + for (const InputMapping::ConfigBase* inputMapping : m_inputMappings) + { + inputMapping->CreateInputMappingAndAddToContext(*m_inputContext); + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputContextComponent::ResetInputContext() + { + m_inputContext.reset(); + } +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.h b/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.h new file mode 100644 index 0000000000..1b9286bd4c --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Input/Contexts/InputContextComponent.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +namespace AzFramework +{ + //////////////////////////////////////////////////////////////////////////////////////////////// + class InputContextComponentRequests : public AZ::ComponentBus + { + public: + //////////////////////////////////////////////////////////////////////////////////////////// + //! Set the local user id that the InputContextComponent should process input from + //! \param[in] localUserId Local user id the InputContextComponent should process input from + virtual void SetLocalUserId(LocalUserId localUserId) = 0; + }; + using InputContextComponentRequestBus = AZ::EBus; + + //////////////////////////////////////////////////////////////////////////////////////////////// + //! An InputContextComponent is used to configure (at edit time) the data necessary to create an + //! InputContext (at run time). The life cycle of any InputContextComponent is controlled by the + //! AZ::Entity it is attached to, adhering to the same rules as any other AZ::Component, and the + //! InputContext which it owns is created/destroyed when the component is activated/deactivated. + class InputContextComponent : public AZ::Component + , public InputContextComponentRequestBus::Handler + { + public: + //////////////////////////////////////////////////////////////////////////////////////////// + // AZ::Component Setup + AZ_COMPONENT(InputContextComponent, "{321689F8-A572-47D7-9D1C-EF9E0D2CD472}"); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! \ref AZ::ComponentDescriptor::GetProvidedServices + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! \ref AZ::ComponentDescriptor::Reflect + static void Reflect(AZ::ReflectContext* context); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Default Constructor + InputContextComponent() = default; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Destructor + ~InputContextComponent() override; + + protected: + //////////////////////////////////////////////////////////////////////////////////////////// + //! \ref AZ::Component::Init + void Init() override; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! \ref AZ::Component::Activate + void Activate() override; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! \ref AZ::Component::Deactivate + void Deactivate() override; + + //////////////////////////////////////////////////////////////////////////////////////////// + // \ref AzFramework::InputContextComponentRequests::SetLocalUserId + void SetLocalUserId(LocalUserId localUserId) override; + + private: + //////////////////////////////////////////////////////////////////////////////////////////// + //! Create the input context. + void CreateInputContext(); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Reset the input context. + void ResetInputContext(); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! The list of all input mappings that will be created when the input context is activated. + //! Reflected to EditContext, then used to create and add input mapping classes in Activate. + AZStd::vector m_inputMappings; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! The name of the input context, unique among all active input contexts and input devices. + //! This will be truncated if its length exceeds that of InputDeviceId::MAX_NAME_LENGTH = 64 + //! Reflected to EditContext, then used to create the unique input context class in Activate. + AZStd::string m_uniqueName; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Input context that is created and owned by this component. Not reflected to EditContext. + AZStd::unique_ptr m_inputContext; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Filter used to determine whether an input event should be handled by this input context. + //! Not reflected, but created inside SetLocalUserId if needed to fliter by a local user id. + AZStd::shared_ptr m_localUserIdFilter; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! The local player index that this component will receive input from (0 base, -1 wildcard). + //! Will only work on platforms where the local user id corresponds to the local player index. + //! For other platforms, SetLocalUserId must be called at runtime with id of a logged in user. + //! Reflected to EditContext, then used if needed to create the local user id filter in Init. + AZ::s32 m_localPlayerIndex = -1; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! The priority used to sort the input context relative to all other input event listeners. + //! Reflected to EditContext, then used to create the unique input context class in Activate. + AZ::s32 m_inputListenerPriority = InputChannelEventListener::GetPriorityDefault(); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Should the input context consume input that is processed by any of its input mappings? + //! Reflected to EditContext, then used to create the unique input context class in Activate. + bool m_consumesProcessedInput = false; + }; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.cpp b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.cpp index 2f848368ca..b8a261677f 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.cpp @@ -9,9 +9,156 @@ #include #include +#include +#include +#include + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputMapping::InputChannelNameFilteredByDeviceType::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("Input Device Type", &InputChannelNameFilteredByDeviceType::m_inputDeviceType) + ->Field("Input Channel Name", &InputChannelNameFilteredByDeviceType::m_inputChannelName) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("InputChannelNameFilteredByDeviceType", + "An input channel name (filtered by an input device type) to add to the input mapping.") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputChannelNameFilteredByDeviceType::GetNameLabelOverride) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &InputChannelNameFilteredByDeviceType::m_inputDeviceType, "Input Device Type", + "The type of input device by which to filter input channel names.") + ->Attribute(AZ::Edit::Attributes::StringList, &InputChannelNameFilteredByDeviceType::GetValidInputDeviceTypes) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &InputChannelNameFilteredByDeviceType::OnInputDeviceTypeSelected) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &InputChannelNameFilteredByDeviceType::m_inputChannelName, "Input Channel Name", + "The input channel name to add to the input mapping.") + ->Attribute(AZ::Edit::Attributes::StringList, &InputChannelNameFilteredByDeviceType::GetValidInputChannelNamesBySelectedDevice) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ; + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + InputMapping::InputChannelNameFilteredByDeviceType::InputChannelNameFilteredByDeviceType() + { + // Try initialize the selected input device type and input channel name to something valid. + if (m_inputDeviceType.empty()) + { + const AZStd::vector validInputDeviceTypes = GetValidInputDeviceTypes(); + if (!validInputDeviceTypes.empty()) + { + m_inputDeviceType = validInputDeviceTypes[0]; + OnInputDeviceTypeSelected(); + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + AZ::Crc32 InputMapping::InputChannelNameFilteredByDeviceType::OnInputDeviceTypeSelected() + { + const AZStd::vector validInputNames = GetValidInputChannelNamesBySelectedDevice(); + if (!validInputNames.empty()) + { + m_inputChannelName = validInputNames[0]; + } + return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + AZStd::string InputMapping::InputChannelNameFilteredByDeviceType::GetNameLabelOverride() const + { + return m_inputChannelName.empty() ? "" : m_outputInputChannelName; + } + //////////////////////////////////////////////////////////////////////////////////////////////// InputMapping::InputMapping(const InputChannelId& inputChannelId, const InputContext& inputContext) : InputChannel(inputChannelId, inputContext) diff --git a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.h b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.h index 93ca96eded..c2f82fb7f8 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMapping.h @@ -12,6 +12,7 @@ #include #include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework @@ -26,6 +27,111 @@ namespace AzFramework class InputMapping : public InputChannel { public: + //////////////////////////////////////////////////////////////////////////////////////////// + //! Convenience class that allows for selection of an input channel name filtered by device. + struct InputChannelNameFilteredByDeviceType + { + public: + //////////////////////////////////////////////////////////////////////////////////////// + // Allocator + AZ_CLASS_ALLOCATOR(InputChannelNameFilteredByDeviceType, AZ::SystemAllocator, 0); + + //////////////////////////////////////////////////////////////////////////////////////// + // Type Info + AZ_RTTI(InputChannelNameFilteredByDeviceType, "{68CC4865-1C0E-4E2E-BDAE-AF42EA30DBE8}"); + + //////////////////////////////////////////////////////////////////////////////////////// + // Reflection + static void Reflect(AZ::ReflectContext* context); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Constructor + InputChannelNameFilteredByDeviceType(); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Destructor + virtual ~InputChannelNameFilteredByDeviceType() = default; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Get the currently selected input device type. + //! \return Currently selected input device type. + inline const AZStd::string& GetInputDeviceType() const { return m_inputDeviceType; } + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Get the currently selected input channel name. + //! \return Currently selected input channel name. + inline const AZStd::string& GetInputChannelName() const { return m_inputChannelName; } + + protected: + //////////////////////////////////////////////////////////////////////////////////////////// + //! Called when an input device type is selected. + //! \return The AZ::Edit::PropertyRefreshLevels to apply to the property tree view. + virtual AZ::Crc32 OnInputDeviceTypeSelected(); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Get the name label override to display. + //! \return Name label override to display. + virtual AZStd::string GetNameLabelOverride() const; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Get the valid input device types for this input mapping. + //! \return Valid input device types for this input mapping. + virtual AZStd::vector GetValidInputDeviceTypes() const; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Get the valid input channel names for this input mapping given the selected device type. + //! \return Valid input channel names for this input mapping given the selected device type. + virtual AZStd::vector GetValidInputChannelNamesBySelectedDevice() const; + + private: + //////////////////////////////////////////////////////////////////////////////////////////// + // Variables + AZStd::string m_inputDeviceType; //!< The currently selected input device type. + AZStd::string m_inputChannelName; //!< The currently selected input channel name. + }; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Base class for input mapping configuration values that are exposed to the editor. + class ConfigBase + { + public: + //////////////////////////////////////////////////////////////////////////////////////// + // Allocator + AZ_CLASS_ALLOCATOR(ConfigBase, AZ::SystemAllocator, 0); + + //////////////////////////////////////////////////////////////////////////////////////// + // Type Info + AZ_RTTI(ConfigBase, "{72EBBBCC-D57E-4085-AFD9-4910506010B6}"); + + //////////////////////////////////////////////////////////////////////////////////////// + // Reflection + static void Reflect(AZ::ReflectContext* context); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Destructor + virtual ~ConfigBase() = default; + + //////////////////////////////////////////////////////////////////////////////////////// + //! Create an input mapping and add it to the input context. + //! \param[in] inputContext Input context that the input mapping will be added to. + AZStd::shared_ptr CreateInputMappingAndAddToContext(InputContext& inputContext) const; + + //////////////////////////////////////////////////////////////////////////////////////// + //! Override to create the relevant input mapping. + //! \param[in] inputContext Input context that owns the input mapping. + virtual AZStd::shared_ptr CreateInputMapping(const InputContext& inputContext) const = 0; + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Get the name label override to display. + //! \return Name label override to display. + virtual AZStd::string GetNameLabelOverride() const; + + protected: + //////////////////////////////////////////////////////////////////////////////////////// + //! The unique input channel name (event) output by the input mapping. + AZStd::string m_outputInputChannelName; + }; + //////////////////////////////////////////////////////////////////////////////////////////// // Allocator AZ_CLASS_ALLOCATOR(InputMapping, AZ::SystemAllocator, 0); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.cpp b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.cpp index 5d371888da..6837807f4e 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.cpp @@ -8,9 +8,72 @@ #include +#include +#include +#include + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputMappingAnd::Config::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("Source Input Channel Names", &Config::m_sourceInputChannelNames) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("Input Mapping: And", + "Maps multiple different input sources to a single output using 'AND' logic.") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingAnd::Config::GetNameLabelOverride) + ->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names", + "The source input channel names that will be mapped to the output input channel name.") + ; + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + AZStd::shared_ptr InputMappingAnd::Config::CreateInputMapping(const InputContext& inputContext) const + { + if (m_outputInputChannelName.empty()) + { + AZ_Error("InputMappingAnd::Config", false, "Cannot create input mapping with empty name."); + return nullptr; + } + + if (InputChannelRequests::FindInputChannel(InputChannelId(m_outputInputChannelName.c_str()))) + { + AZ_Error("InputMappingAnd::Config", false, + "Cannot create input mapping '%s' with non-unique name.", m_outputInputChannelName.c_str()); + return nullptr; + } + + if (m_sourceInputChannelNames.empty()) + { + AZ_Error("InputMappingAnd::Config", false, + "Cannot create input mapping '%s' with no source inputs.", m_outputInputChannelName.c_str()); + return nullptr; + } + + const InputChannelId outputInputChannelId(m_outputInputChannelName.c_str()); + AZStd::shared_ptr inputMapping = AZStd::make_shared(outputInputChannelId, + inputContext); + for (const InputChannelNameFilteredByDeviceType& sourceInputChannelName : m_sourceInputChannelNames) + { + const InputChannelId sourceInputChannelId(sourceInputChannelName.GetInputChannelName().c_str()); + inputMapping->AddSourceInput(sourceInputChannelId); + } + return inputMapping; + } + //////////////////////////////////////////////////////////////////////////////////////////////// InputMappingAnd::InputMappingAnd(const InputChannelId& inputChannelId, const InputContext& inputContext) : InputMapping(inputChannelId, inputContext) diff --git a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.h b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.h index d7a767e3a5..61e54497db 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingAnd.h @@ -19,6 +19,38 @@ namespace AzFramework class InputMappingAnd : public InputMapping { public: + //////////////////////////////////////////////////////////////////////////////////////////// + //! The input mapping configuration values that are exposed to the editor. + class Config : public InputMapping::ConfigBase + { + public: + //////////////////////////////////////////////////////////////////////////////////////// + // Allocator + AZ_CLASS_ALLOCATOR(Config, AZ::SystemAllocator, 0); + + //////////////////////////////////////////////////////////////////////////////////////// + // Type Info + AZ_RTTI(Config, "{54E972F3-0477-4E2E-93F5-4E06ED755DF6}", InputMapping::ConfigBase); + + //////////////////////////////////////////////////////////////////////////////////////// + // Reflection + static void Reflect(AZ::ReflectContext* context); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Destructor + ~Config() override = default; + + protected: + //////////////////////////////////////////////////////////////////////////////////////// + //! \ref AzFramework::InputMapping::Type::CreateInputMapping + AZStd::shared_ptr CreateInputMapping(const InputContext& inputContext) const override; + + private: + //////////////////////////////////////////////////////////////////////////////////////// + //! The source input channel names that will be mapped to the output input channel name. + AZStd::vector m_sourceInputChannelNames; + }; + //////////////////////////////////////////////////////////////////////////////////////////// // Allocator AZ_CLASS_ALLOCATOR(InputMappingAnd, AZ::SystemAllocator, 0); diff --git a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.cpp b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.cpp index 459d32dc68..bc47065c05 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.cpp @@ -8,9 +8,72 @@ #include +#include +#include +#include + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework { + //////////////////////////////////////////////////////////////////////////////////////////////// + void InputMappingOr::Config::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("Source Input Channel Names", &Config::m_sourceInputChannelNames) + ; + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("Input Mapping: Or", + "Maps multiple different input sources to a single output using 'OR' logic.") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingOr::Config::GetNameLabelOverride) + ->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names", + "The source input channel names that will be mapped to the output input channel name.") + ; + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + AZStd::shared_ptr InputMappingOr::Config::CreateInputMapping(const InputContext& inputContext) const + { + if (m_outputInputChannelName.empty()) + { + AZ_Error("InputMappingOr::Config", false, "Cannot create input mapping with empty name."); + return nullptr; + } + + if (InputChannelRequests::FindInputChannel(InputChannelId(m_outputInputChannelName.c_str()))) + { + AZ_Error("InputMappingOr::Config", false, + "Cannot create input mapping '%s' with non-unique name.", m_outputInputChannelName.c_str()); + return nullptr; + } + + if (m_sourceInputChannelNames.empty()) + { + AZ_Error("InputMappingOr::Config", false, + "Cannot create input mapping '%s' with no source inputs.", m_outputInputChannelName.c_str()); + return nullptr; + } + + const InputChannelId outputInputChannelId(m_outputInputChannelName.c_str()); + AZStd::shared_ptr inputMapping = AZStd::make_shared(outputInputChannelId, + inputContext); + for (const InputChannelNameFilteredByDeviceType& sourceInputChannelName : m_sourceInputChannelNames) + { + const InputChannelId sourceInputChannelId(sourceInputChannelName.GetInputChannelName().c_str()); + inputMapping->AddSourceInput(sourceInputChannelId); + } + return inputMapping; + } + //////////////////////////////////////////////////////////////////////////////////////////////// InputMappingOr::InputMappingOr(const InputChannelId& inputChannelId, const InputContext& inputContext) : InputMapping(inputChannelId, inputContext) diff --git a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.h b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.h index b8359f828e..a0440d1855 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.h +++ b/Code/Framework/AzFramework/AzFramework/Input/Mappings/InputMappingOr.h @@ -19,6 +19,38 @@ namespace AzFramework class InputMappingOr : public InputMapping { public: + //////////////////////////////////////////////////////////////////////////////////////////// + //! The input mapping configuration values that are exposed to the editor. + class Config : public InputMapping::ConfigBase + { + public: + //////////////////////////////////////////////////////////////////////////////////////// + // Allocator + AZ_CLASS_ALLOCATOR(Config, AZ::SystemAllocator, 0); + + //////////////////////////////////////////////////////////////////////////////////////// + // Type Info + AZ_RTTI(Config, "{428AFDD4-D353-494A-BBAC-37E00F82CFFD}", InputMapping::ConfigBase); + + //////////////////////////////////////////////////////////////////////////////////////// + // Reflection + static void Reflect(AZ::ReflectContext* context); + + //////////////////////////////////////////////////////////////////////////////////////////// + //! Destructor + ~Config() override = default; + + protected: + //////////////////////////////////////////////////////////////////////////////////////// + //! \ref AzFramework::InputMapping::Type::CreateInputMapping + AZStd::shared_ptr CreateInputMapping(const InputContext& inputContext) const override; + + private: + //////////////////////////////////////////////////////////////////////////////////////// + //! The source input channel names that will be mapped to the output input channel name. + AZStd::vector m_sourceInputChannelNames; + }; + //////////////////////////////////////////////////////////////////////////////////////////// // Allocator AZ_CLASS_ALLOCATOR(InputMappingOr, AZ::SystemAllocator, 0); diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index 87cf29ffec..e752e5ae04 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -343,6 +343,8 @@ set(FILES Input/Channels/InputChannelQuaternion.h Input/Contexts/InputContext.cpp Input/Contexts/InputContext.h + Input/Contexts/InputContextComponent.cpp + Input/Contexts/InputContextComponent.h Input/Devices/InputDevice.cpp Input/Devices/InputDevice.h Input/Devices/InputDeviceId.cpp From b40e0494291f85b5a6ecee87c9d2a074c94b0f1d Mon Sep 17 00:00:00 2001 From: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> Date: Thu, 16 Sep 2021 12:13:28 -0700 Subject: [PATCH 167/274] Added array index operators to Spawnable(Const)EntityContainerView. (#4153) * Added array index operators to Spawnable(Const)EntityContainerView. This commit also includes some tweaks to the begin/end functions and unit tests. Ticket: https://github.com/o3de/o3de/issues/4110 Signed-off-by: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> * Fixed string formatter for assert in Spawnable(Const)EntityContainerView. Signed-off-by: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> * Added empty() to Spawnable(Const)EntityContainerView and made move functions use [[nodiscard]] Signed-off-by: AMZN-koppersr <82230785+AMZN-koppersr@users.noreply.github.com> --- .../Spawnable/SpawnableEntitiesInterface.cpp | 58 ++++++++- .../Spawnable/SpawnableEntitiesInterface.h | 34 +++-- .../SpawnableEntitiesInterfaceTests.cpp | 122 ++++++++++++++++++ .../Tests/frameworktests_files.cmake | 1 + 4 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesInterfaceTests.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp index 617eb3a0b9..75fca39574 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.cpp @@ -36,6 +36,16 @@ namespace AzFramework return m_end; } + const AZ::Entity* const* SpawnableEntityContainerView::begin() const + { + return m_begin; + } + + const AZ::Entity* const* SpawnableEntityContainerView::end() const + { + return m_end; + } + const AZ::Entity* const* SpawnableEntityContainerView::cbegin() { return m_begin; @@ -46,11 +56,28 @@ namespace AzFramework return m_end; } - size_t SpawnableEntityContainerView::size() + AZ::Entity* SpawnableEntityContainerView::operator[](size_t n) + { + AZ_Assert(n < size(), "Index %zu is out of bounds (size: %llu) for Spawnable Entity Container View", n, size()); + return *(m_begin + n); + } + + const AZ::Entity* SpawnableEntityContainerView::operator[](size_t n) const + { + AZ_Assert(n < size(), "Index %zu is out of bounds (size: %llu) for Spawnable Entity Container View", n, size()); + return *(m_begin + n); + } + + size_t SpawnableEntityContainerView::size() const { return AZStd::distance(m_begin, m_end); } + bool SpawnableEntityContainerView::empty() const + { + return m_begin == m_end; + } + // // SpawnableConstEntityContainerView @@ -78,6 +105,16 @@ namespace AzFramework return m_end; } + const AZ::Entity* const* SpawnableConstEntityContainerView::begin() const + { + return m_begin; + } + + const AZ::Entity* const* SpawnableConstEntityContainerView::end() const + { + return m_end; + } + const AZ::Entity* const* SpawnableConstEntityContainerView::cbegin() { return m_begin; @@ -88,11 +125,28 @@ namespace AzFramework return m_end; } - size_t SpawnableConstEntityContainerView::size() + const AZ::Entity* SpawnableConstEntityContainerView::operator[](size_t n) + { + AZ_Assert(n < size(), "Index %zu is out of bounds (size: %llu) for Spawnable Const Entity Container View", n, size()); + return *(m_begin + n); + } + + const AZ::Entity* SpawnableConstEntityContainerView::operator[](size_t n) const + { + AZ_Assert(n < size(), "Index %zu is out of bounds (size: %llu) for Spawnable Entity Container View", n, size()); + return *(m_begin + n); + } + + size_t SpawnableConstEntityContainerView::size() const { return AZStd::distance(m_begin, m_end); } + bool SpawnableConstEntityContainerView::empty() const + { + return m_begin == m_end; + } + // // SpawnableIndexEntityPair diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index 4b09dcbc75..6901fc7116 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -36,11 +36,18 @@ namespace AzFramework SpawnableEntityContainerView(AZ::Entity** begin, size_t length); SpawnableEntityContainerView(AZ::Entity** begin, AZ::Entity** end); - AZ::Entity** begin(); - AZ::Entity** end(); - const AZ::Entity* const* cbegin(); - const AZ::Entity* const* cend(); - size_t size(); + [[nodiscard]] AZ::Entity** begin(); + [[nodiscard]] AZ::Entity** end(); + [[nodiscard]] const AZ::Entity* const* begin() const; + [[nodiscard]] const AZ::Entity* const* end() const; + [[nodiscard]] const AZ::Entity* const* cbegin(); + [[nodiscard]] const AZ::Entity* const* cend(); + + [[nodiscard]] AZ::Entity* operator[](size_t n); + [[nodiscard]] const AZ::Entity* operator[](size_t n) const; + + [[nodiscard]] size_t size() const; + [[nodiscard]] bool empty() const; private: AZ::Entity** m_begin; @@ -53,11 +60,18 @@ namespace AzFramework SpawnableConstEntityContainerView(AZ::Entity** begin, size_t length); SpawnableConstEntityContainerView(AZ::Entity** begin, AZ::Entity** end); - const AZ::Entity* const* begin(); - const AZ::Entity* const* end(); - const AZ::Entity* const* cbegin(); - const AZ::Entity* const* cend(); - size_t size(); + [[nodiscard]] const AZ::Entity* const* begin(); + [[nodiscard]] const AZ::Entity* const* end(); + [[nodiscard]] const AZ::Entity* const* begin() const; + [[nodiscard]] const AZ::Entity* const* end() const; + [[nodiscard]] const AZ::Entity* const* cbegin(); + [[nodiscard]] const AZ::Entity* const* cend(); + + [[nodiscard]] const AZ::Entity* operator[](size_t n); + [[nodiscard]] const AZ::Entity* operator[](size_t n) const; + + [[nodiscard]] size_t size() const; + [[nodiscard]] bool empty() const; private: AZ::Entity** m_begin; diff --git a/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesInterfaceTests.cpp b/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesInterfaceTests.cpp new file mode 100644 index 0000000000..ed90231073 --- /dev/null +++ b/Code/Framework/AzFramework/Tests/Spawnable/SpawnableEntitiesInterfaceTests.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +namespace UnitTest +{ + // + // SpawnableEntityContainerView + // + + class SpawnableEntityContainerViewTest : public ::testing::Test + { + protected: + AZStd::array m_values{ reinterpret_cast(1), reinterpret_cast(2), + reinterpret_cast(3), reinterpret_cast(4) }; + AzFramework::SpawnableEntityContainerView m_view{ m_values.begin(), m_values.end() }; + }; + + TEST_F(SpawnableEntityContainerViewTest, begin_Get_MatchesBeginOfArray) + { + EXPECT_EQ(m_view.begin(), m_values.begin()); + } + + TEST_F(SpawnableEntityContainerViewTest, end_Get_MatchesEndOfArray) + { + EXPECT_EQ(m_view.end(), m_values.end()); + } + + TEST_F(SpawnableEntityContainerViewTest, cbegin_Get_MatchesBeginOfArray) + { + EXPECT_EQ(m_view.cbegin(), m_values.cbegin()); + } + + TEST_F(SpawnableEntityContainerViewTest, cend_Get_MatchesEndOfArray) + { + EXPECT_EQ(m_view.cend(), m_values.cend()); + } + + TEST_F(SpawnableEntityContainerViewTest, IndexOperator_Get_MatchesThirdElement) + { + EXPECT_EQ(m_view[2], m_values[2]); + } + + TEST_F(SpawnableEntityContainerViewTest, Size_Get_MatchesSizeOfArray) + { + EXPECT_EQ(m_view.size(), m_values.size()); + } + + TEST_F(SpawnableEntityContainerViewTest, empty_GetFromFilledArray_ReturnsFalse) + { + EXPECT_FALSE(m_view.empty()); + } + + TEST_F(SpawnableEntityContainerViewTest, empty_GetFromEmtpyView_ReturnsTrue) + { + AzFramework::SpawnableEntityContainerView view{ nullptr, nullptr }; + EXPECT_TRUE(view.empty()); + } + + + // + // SpawnableConstEntityContainerView + // + + class SpawnableConstEntityContainerViewTest : public ::testing::Test + { + protected: + AZStd::array m_values{ reinterpret_cast(1), reinterpret_cast(2), + reinterpret_cast(3), reinterpret_cast(4) }; + AzFramework::SpawnableConstEntityContainerView m_view{ m_values.begin(), m_values.end() }; + }; + + TEST_F(SpawnableConstEntityContainerViewTest, begin_Get_MatchesBeginOfArray) + { + EXPECT_EQ(m_view.begin(), m_values.begin()); + } + + TEST_F(SpawnableConstEntityContainerViewTest, end_Get_MatchesEndOfArray) + { + EXPECT_EQ(m_view.end(), m_values.end()); + } + + TEST_F(SpawnableConstEntityContainerViewTest, cbegin_Get_MatchesBeginOfArray) + { + EXPECT_EQ(m_view.cbegin(), m_values.cbegin()); + } + + TEST_F(SpawnableConstEntityContainerViewTest, cend_Get_MatchesEndOfArray) + { + EXPECT_EQ(m_view.cend(), m_values.cend()); + } + + TEST_F(SpawnableConstEntityContainerViewTest, IndexOperator_Get_MatchesThirdElement) + { + EXPECT_EQ(m_view[2], m_values[2]); + } + + TEST_F(SpawnableConstEntityContainerViewTest, size_Get_MatchesSizeOfArray) + { + EXPECT_EQ(m_view.size(), m_values.size()); + } + + TEST_F(SpawnableConstEntityContainerViewTest, empty_GetFromFilledArray_ReturnsFalse) + { + EXPECT_FALSE(m_view.empty()); + } + + TEST_F(SpawnableConstEntityContainerViewTest, empty_GetFromEmtpyView_ReturnsTrue) + { + AzFramework::SpawnableConstEntityContainerView view{ nullptr, nullptr }; + EXPECT_TRUE(view.empty()); + } +} // namespace UnitTest diff --git a/Code/Framework/AzFramework/Tests/frameworktests_files.cmake b/Code/Framework/AzFramework/Tests/frameworktests_files.cmake index f70f8624c9..680155d49d 100644 --- a/Code/Framework/AzFramework/Tests/frameworktests_files.cmake +++ b/Code/Framework/AzFramework/Tests/frameworktests_files.cmake @@ -8,6 +8,7 @@ set(FILES ../../AzCore/Tests/Main.cpp + Spawnable/SpawnableEntitiesInterfaceTests.cpp Spawnable/SpawnableEntitiesManagerTests.cpp ArchiveCompressionTests.cpp ArchiveTests.cpp From 2b092bae812424c1b8ec3887fcbbfa00803c2f6c Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 16 Sep 2021 12:51:36 -0700 Subject: [PATCH 168/274] Fix missing virtual destructor causing debug build failure (#4174) Signed-off-by: Steve Pham --- Code/Framework/AzCore/AzCore/EBus/EBus.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h index 1bff4ff297..58754ff9b8 100644 --- a/Code/Framework/AzCore/AzCore/EBus/EBus.h +++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h @@ -1717,6 +1717,7 @@ AZ_POP_DISABLE_WARNING { EBusRouterNode m_routerNode; public: + virtual ~EBusNestedVersionRouter() = default; template void BusRouterConnect(Container& container, int order = 0); From ac5cc04b592750561f891ef3fcd6b8c77714edc9 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Thu, 16 Sep 2021 13:52:27 -0700 Subject: [PATCH 169/274] [AWSI Automation] Export more AWS resource names via CloudFormation stack outputs for the automation tests (#4161) * Read resources name via CloudFormation stack outputs and trim resource names when they are too long Signed-off-by: Junbo Liang --- .../aws_metrics_automation_test.py | 27 ++++++----- Gems/AWSClientAuth/cdk/utils/name_utils.py | 6 ++- .../cdk/utils/resource_name_sanitizer.py | 45 +++++++++++++++++++ .../cdk/aws_metrics/aws_metrics_stack.py | 2 + .../cdk/aws_metrics/batch_analytics.py | 8 ++++ .../cdk/aws_metrics/batch_processing.py | 8 ++++ Gems/AWSMetrics/cdk/aws_metrics/dashboard.py | 2 +- .../cdk/aws_metrics/data_ingestion.py | 4 +- .../cdk/aws_metrics/data_lake_integration.py | 10 ++++- .../aws_metrics/real_time_data_processing.py | 8 +++- 10 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 Gems/AWSClientAuth/cdk/utils/resource_name_sanitizer.py diff --git a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py index 5f6103c46a..34b2217916 100644 --- a/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py +++ b/AutomatedTesting/Gem/PythonTests/AWS/Windows/aws_metrics/aws_metrics_automation_test.py @@ -31,7 +31,7 @@ def setup(launcher: pytest.fixture, Set up the resource mapping configuration and start the log monitor. :param launcher: Client launcher for running the test level. :param asset_processor: asset_processor fixture. - :return log monitor object, metrics file path and the metrics stack name. + :return log monitor object. """ asset_processor.start() asset_processor.wait_for_idle() @@ -73,12 +73,11 @@ def monitor_metrics_submission(log_monitor: pytest.fixture) -> None: f'unexpected_lines values: {unexpected_lines}') -def query_metrics_from_s3(aws_metrics_utils: pytest.fixture, resource_mappings: pytest.fixture, stack_name: str) -> None: +def query_metrics_from_s3(aws_metrics_utils: pytest.fixture, resource_mappings: pytest.fixture) -> None: """ Verify that the metrics events are delivered to the S3 bucket and can be queried. :param aws_metrics_utils: aws_metrics_utils fixture. :param resource_mappings: resource_mappings fixture. - :param stack_name: name of the CloudFormation stack. """ aws_metrics_utils.verify_s3_delivery( resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsBucketName') @@ -89,23 +88,24 @@ def query_metrics_from_s3(aws_metrics_utils: pytest.fixture, resource_mappings: resource_mappings.get_resource_name_id('AWSMetrics.EventsCrawlerName')) # Remove the events_json table if exists so that the sample query can create a table with the same name. - aws_metrics_utils.delete_table(f'{stack_name}-eventsdatabase', 'events_json') - aws_metrics_utils.run_named_queries(f'{stack_name}-AthenaWorkGroup') + aws_metrics_utils.delete_table(resource_mappings.get_resource_name_id('AWSMetrics.EventDatabaseName'), 'events_json') + aws_metrics_utils.run_named_queries(resource_mappings.get_resource_name_id('AWSMetrics.AthenaWorkGroupName')) logger.info('Query metrics from S3 successfully.') -def verify_operational_metrics(aws_metrics_utils: pytest.fixture, stack_name: str, start_time: datetime) -> None: +def verify_operational_metrics(aws_metrics_utils: pytest.fixture, + resource_mappings: pytest.fixture, start_time: datetime) -> None: """ Verify that operational health metrics are delivered to CloudWatch. - aws_metrics_utils: aws_metrics_utils fixture. - stack_name: name of the CloudFormation stack. - start_time: Time when the game launcher starts. + :param aws_metrics_utils: aws_metrics_utils fixture. + :param resource_mappings: resource_mappings fixture. + :param start_time: Time when the game launcher starts. """ aws_metrics_utils.verify_cloud_watch_delivery( 'AWS/Lambda', 'Invocations', [{'Name': 'FunctionName', - 'Value': f'{stack_name}-AnalyticsProcessingLambda'}], + 'Value': resource_mappings.get_resource_name_id('AWSMetrics.AnalyticsProcessingLambdaName')}], start_time) logger.info('AnalyticsProcessingLambda metrics are sent to CloudWatch.') @@ -113,7 +113,7 @@ def verify_operational_metrics(aws_metrics_utils: pytest.fixture, stack_name: st 'AWS/Lambda', 'Invocations', [{'Name': 'FunctionName', - 'Value': f'{stack_name}-EventsProcessingLambda'}], + 'Value': resource_mappings.get_resource_name_id('AWSMetrics.EventProcessingLambdaName')}], start_time) logger.info('EventsProcessingLambda metrics are sent to CloudWatch.') @@ -157,7 +157,6 @@ class TestAWSMetricsWindows(object): workspace: pytest.fixture, aws_utils: pytest.fixture, resource_mappings: pytest.fixture, - stacks: typing.List, aws_metrics_utils: pytest.fixture): """ Verify that the metrics events are sent to CloudWatch and S3 for analytics. @@ -189,10 +188,10 @@ class TestAWSMetricsWindows(object): operational_threads = list() operational_threads.append( AWSMetricsThread(target=query_metrics_from_s3, - args=(aws_metrics_utils, resource_mappings, stacks[0]))) + args=(aws_metrics_utils, resource_mappings))) operational_threads.append( AWSMetricsThread(target=verify_operational_metrics, - args=(aws_metrics_utils, stacks[0], start_time))) + args=(aws_metrics_utils, resource_mappings, start_time))) operational_threads.append( AWSMetricsThread(target=update_kinesis_analytics_application_status, args=(aws_metrics_utils, resource_mappings, False))) diff --git a/Gems/AWSClientAuth/cdk/utils/name_utils.py b/Gems/AWSClientAuth/cdk/utils/name_utils.py index 4921b735eb..ea9dd68060 100755 --- a/Gems/AWSClientAuth/cdk/utils/name_utils.py +++ b/Gems/AWSClientAuth/cdk/utils/name_utils.py @@ -6,10 +6,11 @@ SPDX-License-Identifier: Apache-2.0 OR MIT """ import re from aws_cdk import core +from .resource_name_sanitizer import sanitize_resource_name def format_aws_resource_name(feature_name: str, project_name: str, env: core.Environment, resource_type: str): - return f'{project_name}-{feature_name}-{resource_type}-{env.region}' + return sanitize_resource_name(f'{project_name}-{feature_name}-{resource_type}-{env.region}', resource_type) def format_aws_resource_id(feature_name: str, project_name: str, env: core.Environment, resource_type: str): @@ -31,4 +32,5 @@ def format_aws_resource_authenticated_id(feature_name: str, project_name: str, e def format_aws_resource_authenticated_name(feature_name: str, project_name: str, env: core.Environment, resource_type: str, authenticated: bool): authenticated_string = 'Authenticated' if authenticated else 'Unauthenticated' - return f'{project_name}{feature_name}{resource_type}{authenticated_string}-{env.region}' + return sanitize_resource_name( + f'{project_name}{feature_name}{resource_type}{authenticated_string}-{env.region}', resource_type) diff --git a/Gems/AWSClientAuth/cdk/utils/resource_name_sanitizer.py b/Gems/AWSClientAuth/cdk/utils/resource_name_sanitizer.py new file mode 100644 index 0000000000..d4a2d77f44 --- /dev/null +++ b/Gems/AWSClientAuth/cdk/utils/resource_name_sanitizer.py @@ -0,0 +1,45 @@ +""" +Copyright (c) Contributors to the Open 3D Engine Project. +For complete copyright and license terms please see the LICENSE at the root of this distribution. + +SPDX-License-Identifier: Apache-2.0 OR MIT +""" + +import hashlib +from aws_cdk import ( + core, + aws_cognito as cognito, + aws_iam as iam +) + +MAX_RESOURCE_NAME_LENGTH_MAPPING = { + core.Stack.__name__: 128, + iam.Role.__name__: 64, + iam.ManagedPolicy.__name__: 144, + cognito.CfnUserPoolClient.__name__: 128, + cognito.CfnUserPool.__name__: 128, + cognito.CfnIdentityPool.__name__: 128 + +} + + +def sanitize_resource_name(resource_name: str, resource_type: str) -> str: + """ + Truncate the resource name if its length exceeds the limit. + This is the best effort for sanitizing resource names based on the AWS documents since each AWS service + has its unique restrictions. Customers can extend this function for validation or sanitization. + + :param resource_name: Original name of the resource. + :param resource_type: Type of the resource. + :return Sanitized resource name that can be deployed with AWS. + """ + result = resource_name + if not MAX_RESOURCE_NAME_LENGTH_MAPPING.get(resource_type): + return result + + if len(resource_name) > MAX_RESOURCE_NAME_LENGTH_MAPPING[resource_type]: + # PYTHONHASHSEED is set to "random" by default in Python 3.3 and up. Cannot use + # the built-in hash function here since it will give a different return value in each session + digest = "-%x" % (int(hashlib.md5(resource_name.encode('ascii', 'ignore')).hexdigest(), 16) & 0xffffffff) + result = resource_name[:MAX_RESOURCE_NAME_LENGTH_MAPPING[resource_type] - len(digest)] + digest + return result diff --git a/Gems/AWSMetrics/cdk/aws_metrics/aws_metrics_stack.py b/Gems/AWSMetrics/cdk/aws_metrics/aws_metrics_stack.py index 337a14a301..41d70f83ec 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/aws_metrics_stack.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/aws_metrics_stack.py @@ -53,6 +53,7 @@ class AWSMetricsStack(core.Stack): self._batch_processing = BatchProcessing( self, input_stream_arn=self._data_ingestion.input_stream_arn, + application_name=application_name, analytics_bucket_arn=self._data_lake_integration.analytics_bucket_arn, events_database_name=self._data_lake_integration.events_database_name, events_table_name=self._data_lake_integration.events_table_name @@ -60,6 +61,7 @@ class AWSMetricsStack(core.Stack): self._batch_analytics = BatchAnalytics( self, + application_name=application_name, analytics_bucket_name=self._data_lake_integration.analytics_bucket_name, events_database_name=self._data_lake_integration.events_database_name, events_table_name=self._data_lake_integration.events_table_name diff --git a/Gems/AWSMetrics/cdk/aws_metrics/batch_analytics.py b/Gems/AWSMetrics/cdk/aws_metrics/batch_analytics.py index 8398113bc4..eb36d8a5da 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/batch_analytics.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/batch_analytics.py @@ -20,10 +20,12 @@ class BatchAnalytics: """ def __init__(self, stack: core.Construct, + application_name: str, analytics_bucket_name: str, events_database_name: str, events_table_name) -> None: self._stack = stack + self._application_name = application_name self._analytics_bucket_name = analytics_bucket_name self._events_database_name = events_database_name self._events_table_name = events_table_name @@ -58,6 +60,12 @@ class BatchAnalytics: ) ) ) + core.CfnOutput( + self._stack, + id='AthenaWorkGroupName', + description='Name of the Athena work group that contains sample queries', + export_name=f"{self._application_name}:AthenaWorkGroup", + value=self._athena_work_group.name) def _create_athena_queries(self) -> None: """ diff --git a/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py b/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py index 4dbb3b2120..803f6076c8 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py @@ -26,11 +26,13 @@ class BatchProcessing: """ def __init__(self, stack: core.Construct, + application_name: str, input_stream_arn: str, analytics_bucket_arn: str, events_database_name: str, events_table_name) -> None: self._stack = stack + self._application_name = application_name self._input_stream_arn = input_stream_arn self._analytics_bucket_arn = analytics_bucket_arn self._events_database_name = events_database_name @@ -60,6 +62,12 @@ class BatchProcessing: os.path.join(os.path.dirname(__file__), 'lambdas', 'events_processing_lambda')), role=self._events_processing_lambda_role ) + core.CfnOutput( + self._stack, + id='EventProcessingLambdaName', + description='Lambda function for processing metrics events data.', + export_name=f"{self._application_name}:EventProcessingLambda", + value=self._events_processing_lambda.function_name) def _create_events_processing_lambda_role(self, function_name: str) -> None: """ diff --git a/Gems/AWSMetrics/cdk/aws_metrics/dashboard.py b/Gems/AWSMetrics/cdk/aws_metrics/dashboard.py index 32ff0d9c84..616643ebb1 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/dashboard.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/dashboard.py @@ -52,7 +52,7 @@ class Dashboard: max_width=aws_metrics_constants.DASHBOARD_MAX_WIDGET_WIDTH) ) - dashboard_output = core.CfnOutput( + core.CfnOutput( stack, id='DashboardName', description='CloudWatch dashboard to monitor the operational health and real-time metrics', diff --git a/Gems/AWSMetrics/cdk/aws_metrics/data_ingestion.py b/Gems/AWSMetrics/cdk/aws_metrics/data_ingestion.py index a21e629c38..cc11796ee9 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/data_ingestion.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/data_ingestion.py @@ -69,14 +69,14 @@ class DataIngestion: cfn_rest_api.add_property_deletion_override("BodyS3Location") cfn_rest_api.add_property_override("FailOnWarnings", True) - api_id_output = core.CfnOutput( + core.CfnOutput( self._stack, id='RESTApiId', description='Service API Id for the analytics pipeline', export_name=f"{application_name}:RestApiId", value=self._rest_api.rest_api_id) - stage_output = core.CfnOutput( + core.CfnOutput( self._stack, id='RESTApiStage', description='Stage for the REST API deployment', diff --git a/Gems/AWSMetrics/cdk/aws_metrics/data_lake_integration.py b/Gems/AWSMetrics/cdk/aws_metrics/data_lake_integration.py index e47b1a95c2..a0b93eb212 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/data_lake_integration.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/data_lake_integration.py @@ -67,7 +67,7 @@ class DataLakeIntegration: cfn_bucket = self._analytics_bucket.node.find_child('Resource') cfn_bucket.apply_removal_policy(core.RemovalPolicy.DESTROY) - analytics_bucket_output = core.CfnOutput( + core.CfnOutput( self._stack, id='AnalyticsBucketName', description='Name of the S3 bucket for storing metrics event data', @@ -89,6 +89,12 @@ class DataLakeIntegration: name=f'{self._stack.stack_name}-EventsDatabase'.lower() ) ) + core.CfnOutput( + self._stack, + id='EventDatabaseName', + description='Glue database for metrics events.', + export_name=f"{self._application_name}:EventsDatabase", + value=self._events_database.ref) def _create_events_table(self) -> None: """ @@ -199,7 +205,7 @@ class DataLakeIntegration: configuration=aws_metrics_constants.CRAWLER_CONFIGURATION ) - events_crawler_output = core.CfnOutput( + core.CfnOutput( self._stack, id='EventsCrawlerName', description='Glue Crawler to populate the AWS Glue Data Catalog with metrics events tables', diff --git a/Gems/AWSMetrics/cdk/aws_metrics/real_time_data_processing.py b/Gems/AWSMetrics/cdk/aws_metrics/real_time_data_processing.py index 4ef9caa022..ffd74a51a9 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/real_time_data_processing.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/real_time_data_processing.py @@ -113,7 +113,7 @@ class RealTimeDataProcessing: ), ) - analytics_application_output = core.CfnOutput( + core.CfnOutput( self._stack, id='AnalyticsApplicationName', description='Kinesis Data Analytics application to process the real-time metrics data', @@ -199,6 +199,12 @@ class RealTimeDataProcessing: os.path.join(os.path.dirname(__file__), 'lambdas', 'analytics_processing_lambda')), role=self._analytics_processing_lambda_role ) + core.CfnOutput( + self._stack, + id='AnalyticsProcessingLambdaName', + description='Lambda function for sending processed data to CloudWatch.', + export_name=f"{self._application_name}:AnalyticsProcessingLambda", + value=self._analytics_processing_lambda.function_name) def _create_analytics_processing_lambda_role(self, function_name: str) -> iam.Role: """ From 2d156364dae9b02f2cbdf7230a54c0cb5f24f5a8 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 16 Sep 2021 13:53:32 -0700 Subject: [PATCH 170/274] Fix remain copyright header issues for .in files (#4177) Signed-off-by: Steve Pham --- .../Platform/Windows/Launcher.rc.in | 16 ++++++---------- Code/LauncherUnified/StaticModules.in | 16 ++++++---------- .../Tools/Android/ProjectBuilder/build.gradle.in | 14 +++++--------- .../Android/ProjectBuilder/gradle.properties.in | 10 +++------- .../Android/ProjectBuilder/local.properties.in | 10 +++------- .../Android/ProjectBuilder/root.build.gradle.in | 11 ++++------- 6 files changed, 27 insertions(+), 50 deletions(-) diff --git a/Code/LauncherUnified/Platform/Windows/Launcher.rc.in b/Code/LauncherUnified/Platform/Windows/Launcher.rc.in index ae08976c2a..52a238032e 100644 --- a/Code/LauncherUnified/Platform/Windows/Launcher.rc.in +++ b/Code/LauncherUnified/Platform/Windows/Launcher.rc.in @@ -1,13 +1,9 @@ /* -* 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. -* -*/ + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ IDI_ICON1 ICON DISCARDABLE "@ICON_FILE@" diff --git a/Code/LauncherUnified/StaticModules.in b/Code/LauncherUnified/StaticModules.in index 03b22b076a..ef5a565480 100644 --- a/Code/LauncherUnified/StaticModules.in +++ b/Code/LauncherUnified/StaticModules.in @@ -1,14 +1,10 @@ /* -* 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. -* -*/ + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ ///////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// // THIS CODE IS AUTOGENERATED, DO NOT MODIFY diff --git a/Code/Tools/Android/ProjectBuilder/build.gradle.in b/Code/Tools/Android/ProjectBuilder/build.gradle.in index 5980984516..da5f4b599a 100644 --- a/Code/Tools/Android/ProjectBuilder/build.gradle.in +++ b/Code/Tools/Android/ProjectBuilder/build.gradle.in @@ -1,13 +1,9 @@ // -// All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -// its licensors. +// Copyright (c) Contributors to the Open 3D Engine Project. +// For complete copyright and license terms please see the LICENSE at the root of this distribution. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT // -// 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. - apply plugin: "com.android.${TARGET_TYPE}" @@ -16,7 +12,7 @@ ${SIGNING_CONFIGS} compileSdkVersion sdkVer buildToolsVersion buildToolsVer ndkVersion ndkPlatformVer - lintOptions { + lintOptions { abortOnError false checkReleaseBuilds false } diff --git a/Code/Tools/Android/ProjectBuilder/gradle.properties.in b/Code/Tools/Android/ProjectBuilder/gradle.properties.in index 71a1cadde9..4ade102ae0 100644 --- a/Code/Tools/Android/ProjectBuilder/gradle.properties.in +++ b/Code/Tools/Android/ProjectBuilder/gradle.properties.in @@ -1,12 +1,8 @@ ### -### All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -### its licensors. +### Copyright (c) Contributors to the Open 3D Engine Project. +### For complete copyright and license terms please see the LICENSE at the root of this distribution. ### -### 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. +### SPDX-License-Identifier: Apache-2.0 OR MIT ### # For more details on how to configure your build environment visit diff --git a/Code/Tools/Android/ProjectBuilder/local.properties.in b/Code/Tools/Android/ProjectBuilder/local.properties.in index 4e82cb2940..e9843fe5c3 100644 --- a/Code/Tools/Android/ProjectBuilder/local.properties.in +++ b/Code/Tools/Android/ProjectBuilder/local.properties.in @@ -1,12 +1,8 @@ ### -### All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -### its licensors. +### Copyright (c) Contributors to the Open 3D Engine Project. +### For complete copyright and license terms please see the LICENSE at the root of this distribution. ### -### 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. +### SPDX-License-Identifier: Apache-2.0 OR MIT ### ## This file must *NOT* be checked into Version Control Systems, diff --git a/Code/Tools/Android/ProjectBuilder/root.build.gradle.in b/Code/Tools/Android/ProjectBuilder/root.build.gradle.in index dfce99c3c7..14606bee7b 100644 --- a/Code/Tools/Android/ProjectBuilder/root.build.gradle.in +++ b/Code/Tools/Android/ProjectBuilder/root.build.gradle.in @@ -1,12 +1,9 @@ // -// All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -// its licensors. +// Copyright (c) Contributors to the Open 3D Engine Project. +// For complete copyright and license terms please see the LICENSE at the root of this distribution. +// +// SPDX-License-Identifier: Apache-2.0 OR MIT // -// 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. buildscript { repositories { From 6914cfe5bc670218562efd2ef5dd5de14a3cfcec Mon Sep 17 00:00:00 2001 From: nvsickle Date: Thu, 16 Sep 2021 14:33:15 -0700 Subject: [PATCH 171/274] Remove legacy Cry dependencies from the Camera Gem Signed-off-by: nvsickle --- Gems/Camera/Code/CMakeLists.txt | 8 +- Gems/Camera/Code/Source/CameraComponent.cpp | 2 - Gems/Camera/Code/Source/CameraComponent.h | 3 - .../Code/Source/CameraComponentController.cpp | 84 +++---------------- .../Code/Source/CameraComponentController.h | 15 ++-- .../Source/CameraEditorSystemComponent.cpp | 23 +---- Gems/Camera/Code/Source/CameraGem.cpp | 5 +- .../Code/Source/EditorCameraComponent.cpp | 11 ++- .../Code/Source/EditorCameraComponent.h | 2 - .../Source/ViewportCameraSelectorWindow.cpp | 7 +- 10 files changed, 34 insertions(+), 126 deletions(-) diff --git a/Gems/Camera/Code/CMakeLists.txt b/Gems/Camera/Code/CMakeLists.txt index 3fbeec0908..329e0c88ad 100644 --- a/Gems/Camera/Code/CMakeLists.txt +++ b/Gems/Camera/Code/CMakeLists.txt @@ -18,8 +18,8 @@ ly_add_target( PUBLIC Gem::Atom_RPI.Public AZ::AtomCore - PRIVATE - Legacy::CryCommon + AZ::AzCore + AZ::AzFramework ) ly_add_target( @@ -32,7 +32,6 @@ ly_add_target( Source BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon Gem::Camera.Static ) @@ -56,9 +55,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Source BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon - Legacy::Editor.Headers - Legacy::EditorCommon AZ::AzToolsFramework Gem::Camera.Static ) diff --git a/Gems/Camera/Code/Source/CameraComponent.cpp b/Gems/Camera/Code/Source/CameraComponent.cpp index 0b892b0367..960f13a082 100644 --- a/Gems/Camera/Code/Source/CameraComponent.cpp +++ b/Gems/Camera/Code/Source/CameraComponent.cpp @@ -14,9 +14,7 @@ #include "CameraComponent.h" -#include #include -#include #include namespace Camera diff --git a/Gems/Camera/Code/Source/CameraComponent.h b/Gems/Camera/Code/Source/CameraComponent.h index de6e98154d..b9c94d482f 100644 --- a/Gems/Camera/Code/Source/CameraComponent.h +++ b/Gems/Camera/Code/Source/CameraComponent.h @@ -11,9 +11,6 @@ #include #include -#include -#include -#include #include #include diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index a8b5b8992e..b8e5738145 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -9,7 +9,6 @@ #include "CameraComponentController.h" #include "CameraViewRegistrationBus.h" -#include #include #include #include @@ -53,7 +52,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_fov, "Field of view", "Vertical field of view in degrees") - ->Attribute(AZ::Edit::Attributes::Min, MIN_FOV) + ->Attribute(AZ::Edit::Attributes::Min, MinFoV) ->Attribute(AZ::Edit::Attributes::Suffix, " degrees") ->Attribute(AZ::Edit::Attributes::Step, 1.f) ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::Pi) - 0.0001f) //We assert at fovs >= Pi so set the max for this field to be just under that @@ -61,7 +60,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::Visibility, &CameraComponentConfig::GetPerspectiveParameterVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_nearClipDistance, "Near clip distance", "Distance to the near clip plane of the view Frustum") - ->Attribute(AZ::Edit::Attributes::Min, CAMERA_MIN_NEAR) + ->Attribute(AZ::Edit::Attributes::Min, MinimumNearPlaneDistance) ->Attribute(AZ::Edit::Attributes::Suffix, " m") ->Attribute(AZ::Edit::Attributes::Step, 0.1f) ->Attribute(AZ::Edit::Attributes::Max, &CameraComponentConfig::GetFarClipDistance) @@ -150,6 +149,11 @@ namespace Camera } } + void CameraComponentController::SetShouldActivateFunction(AZStd::function shouldActivateFunction) + { + m_shouldActivateFn = shouldActivateFunction; + } + void CameraComponentController::Reflect(AZ::ReflectContext* context) { CameraComponentConfig::Reflect(context); @@ -202,36 +206,6 @@ namespace Camera { m_entityId = entityId; - if ((!m_viewSystem)||(!m_system)) - { - // perform first-time init - if (gEnv) - { - m_system = gEnv->pSystem; - } - if (m_system) - { - // Initialize local view. - m_viewSystem = m_system->GetIViewSystem(); - if (!m_viewSystem) - { - AZ_Error("CameraComponent", m_viewSystem != nullptr, "The CameraComponent shouldn't be used without a local view system"); - } - } - } - - if (m_viewSystem) - { - if (m_view == nullptr) - { - m_view = m_viewSystem->CreateView(); - - AZ::Entity* entity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, m_entityId); - m_view->LinkTo(entity); - } - } - auto atomViewportRequests = AZ::Interface::Get(); if (atomViewportRequests) { @@ -270,9 +244,8 @@ namespace Camera CameraBus::Handler::BusConnect(); CameraNotificationBus::Broadcast(&CameraNotificationBus::Events::OnCameraAdded, m_entityId); - // Activate our camera if we're running from the launcher or Editor game mode - // Otherwise, let the Editor keep managing the active camera - if (m_config.m_makeActiveViewOnActivation && (!gEnv || !gEnv->IsEditor() || gEnv->IsEditorGameMode())) + // Only activate if we're configured to do so, and our activation call back indicates that we should + if (m_config.m_makeActiveViewOnActivation && (!m_shouldActivateFn || m_shouldActivateFn())) { MakeActiveView(); } @@ -284,20 +257,6 @@ namespace Camera CameraBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(m_entityId); CameraRequestBus::Handler::BusDisconnect(m_entityId); - if (m_viewSystem) - { - if (m_view != nullptr && m_viewSystem->GetViewId(m_view) != 0) - { - m_view->Unlink(); - } - if (m_viewSystem->GetActiveView() == m_view) - { - m_viewSystem->SetActiveView(m_prevViewId); - } - m_viewSystem->RemoveView(m_view); - m_prevViewId = 0; - m_view = nullptr; - } auto atomViewportRequests = AZ::Interface::Get(); if (atomViewportRequests) @@ -429,13 +388,6 @@ namespace Camera return; } - // Set Legacy Cry view, if it exists - if (m_viewSystem) - { - m_prevViewId = AZ::u32(m_viewSystem->GetActiveViewId()); - m_viewSystem->SetActiveView(m_view); - } - // Set Atom camera, if it exists if (m_atomCamera) { @@ -461,12 +413,6 @@ namespace Camera return; } - if (m_view) - { - CCamera& camera = m_view->GetCamera(); - camera.SetMatrix(AZTransformToLYTransform(world.GetOrthogonalized())); - } - if (m_atomCamera) { m_updatingTransformFromEntity = true; @@ -495,25 +441,15 @@ namespace Camera void CameraComponentController::UpdateCamera() { - if (m_view) - { - auto viewParams = *m_view->GetCurrentParams(); - viewParams.fov = AZ::DegToRad(m_config.m_fov); - viewParams.nearplane = m_config.m_nearClipDistance; - viewParams.farplane = m_config.m_farClipDistance; - m_view->SetCurrentParams(viewParams); - } - if (auto viewportContext = GetViewportContext()) { AZ::Matrix4x4 viewToClipMatrix; - float aspectRatio = m_view ? m_view->GetCamera().GetPixelAspectRatio() : 1.f; if (!m_atomAuxGeom) { SetupAtomAuxGeom(viewportContext); } auto windowSize = viewportContext->GetViewportSize(); - aspectRatio = aznumeric_cast(windowSize.m_width) / aznumeric_cast(windowSize.m_height); + const float aspectRatio = aznumeric_cast(windowSize.m_width) / aznumeric_cast(windowSize.m_height); // This assumes a reversed depth buffer, in line with other LY Atom integration if (m_config.m_orthographic) diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index 923da65618..5eca6b1711 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -16,15 +16,12 @@ #include #include -#include -#include -#include - namespace Camera { static constexpr float DefaultFoV = 75.0f; static constexpr float MinFoV = std::numeric_limits::epsilon(); static constexpr float MaxFoV = AZ::RadToDeg(AZ::Constants::Pi); + static constexpr float MinimumNearPlaneDistance = 0.001f; static constexpr float DefaultNearPlaneDistance = 0.2f; static constexpr float DefaultFarClipPlaneDistance = 1024.0f; static constexpr float DefaultFrustumDimension = 256.f; @@ -69,6 +66,10 @@ namespace Camera CameraComponentController() = default; explicit CameraComponentController(const CameraComponentConfig& config); + //! Defines a callback for determining whether this camera should push itself to the top of the Atom camera stack. + //! Used by the Editor to disable undesirable camera changes in edit mode. + void SetShouldActivateFunction(AZStd::function shouldActivateFunction); + // Controller interface static void Reflect(AZ::ReflectContext* context); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); @@ -134,10 +135,6 @@ namespace Camera bool m_updatingTransformFromEntity = false; bool m_isActiveView = false; - // Cry view integration - IView* m_view = nullptr; - AZ::u32 m_prevViewId = 0; - IViewSystem* m_viewSystem = nullptr; - ISystem* m_system = nullptr; + AZStd::function m_shouldActivateFn; }; } // namespace Camera diff --git a/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp b/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp index bf3083bf59..00a147c17a 100644 --- a/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp +++ b/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp @@ -21,17 +21,12 @@ #include #include -#include -#include -#include -#include -#include - -#include -#include #include #include "ViewportCameraSelectorWindow.h" +#include +#include + namespace Camera { void CameraEditorSystemComponent::Reflect(AZ::ReflectContext* context) @@ -72,15 +67,6 @@ namespace Camera void CameraEditorSystemComponent::PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2&, int flags) { - IEditor* editor; - AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); - - CGameEngine* gameEngine = editor->GetGameEngine(); - if (!gameEngine || !gameEngine->IsLevelLoaded()) - { - return; - } - if (!(flags & AzToolsFramework::EditorEvents::eECMF_HIDE_ENTITY_CREATION)) { QAction* action = menu->addAction(QObject::tr("Create camera entity from view")); @@ -90,9 +76,6 @@ namespace Camera void CameraEditorSystemComponent::CreateCameraEntityFromViewport() { - IEditor* editor = nullptr; - AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); - AzFramework::CameraState cameraState{}; AZ::EBusReduceResult> aggregator; Camera::EditorCameraRequestBus::BroadcastResult( diff --git a/Gems/Camera/Code/Source/CameraGem.cpp b/Gems/Camera/Code/Source/CameraGem.cpp index 7efb09a59c..99f270e71b 100644 --- a/Gems/Camera/Code/Source/CameraGem.cpp +++ b/Gems/Camera/Code/Source/CameraGem.cpp @@ -7,7 +7,6 @@ */ #include -#include #include "CameraComponent.h" #include "CameraSystemComponent.h" @@ -22,13 +21,13 @@ namespace Camera { class CameraModule - : public CryHooksModule + : public AZ::Module { public: AZ_RTTI(CameraModule, "{C2E72B0D-BCEF-452A-9BFA-03833015258C}", AZ::Module); CameraModule() - : CryHooksModule() + : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { Camera::CameraComponent::CreateDescriptor(), diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.cpp b/Gems/Camera/Code/Source/EditorCameraComponent.cpp index 4ebec334ec..3ac60cbff8 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.cpp +++ b/Gems/Camera/Code/Source/EditorCameraComponent.cpp @@ -12,10 +12,9 @@ #include "EditorCameraComponent.h" #include "ViewportCameraSelectorWindow.h" -#include -#include #include #include +#include #include #include @@ -33,6 +32,14 @@ namespace Camera CameraComponentConfig controllerConfig = m_controller.GetConfiguration(); controllerConfig.m_editorEntityId = GetEntityId().operator AZ::u64(); m_controller.SetConfiguration(controllerConfig); + // Only allow our camera to activate with the component if we're currently in game mode. + m_controller.SetShouldActivateFunction([]() + { + bool isInGameMode = true; + AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( + isInGameMode, &AzToolsFramework::EditorEntityContextRequestBus::Events::IsEditorRunningGame); + return isInGameMode; + }); // Call base class activate, which in turn calls Activate on our controller. EditorCameraComponentBase::Activate(); diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.h b/Gems/Camera/Code/Source/EditorCameraComponent.h index 02b9d591d0..0cb130e7a0 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.h +++ b/Gems/Camera/Code/Source/EditorCameraComponent.h @@ -21,8 +21,6 @@ #include #include "CameraComponent.h" #include "CameraComponentController.h" -#include -#include #include diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index 7a8d6be020..dc091db9e5 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -7,17 +7,14 @@ */ #include "ViewportCameraSelectorWindow.h" #include "ViewportCameraSelectorWindow_Internals.h" -#include #include #include #include #include #include #include -#include -#include -#include #include +#include namespace Qt { @@ -308,7 +305,7 @@ namespace Camera void RegisterViewportCameraSelectorWindow() { - QtViewOptions viewOptions; + AzToolsFramework::ViewPaneOptions viewOptions; viewOptions.isPreview = true; viewOptions.showInMenu = true; viewOptions.preferedDockingArea = Qt::DockWidgetArea::LeftDockWidgetArea; From 0ed82e21d52e9c18da38d026ba9d75ee0cd3fbc6 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 16 Sep 2021 16:39:59 -0700 Subject: [PATCH 172/274] Switch job dependency type to OrderOnce for material assets when property names are included. Signed-off-by: Robin --- .../Source/RPI.Builders/Material/MaterialBuilder.cpp | 7 ++++++- .../Model/MaterialAssetBuilderComponent.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 5ddeb08ef8..099fdf33dd 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -9,6 +9,7 @@ #include "MaterialBuilder.h" #include #include +#include #include #include #include @@ -93,8 +94,12 @@ namespace AZ { AssetBuilderSDK::JobDependency jobDependency; jobDependency.m_jobKey = jobKey; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + + bool includeMaterialPropertyNames = true; + RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); + jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; + jobDependencies.push_back(jobDependency); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index cf7e53c596..b2c590a376 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -78,10 +78,7 @@ namespace AZ AZStd::string materialTypePath; RPI::MaterialConverterBus::BroadcastResult(materialTypePath, &RPI::MaterialConverterBus::Events::GetMaterialTypePath); - bool includeMaterialPropertyNames = true; - RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); - // TODO: Use includeMaterialPropertyNames to break materialtype dependency on fbx files. Materialasset's dependency on materialtypeasset will need to be decoupled first - if (conversionEnabled && !materialTypePath.empty() /*&& !includeMaterialPropertyNames*/) + if (conversionEnabled && !materialTypePath.empty()) { AssetBuilderSDK::SourceFileDependency materialTypeSource; materialTypeSource.m_sourceFileDependencyPath = materialTypePath; @@ -90,7 +87,10 @@ namespace AZ jobDependency.m_jobKey = "Atom Material Builder"; jobDependency.m_sourceFile = materialTypeSource; jobDependency.m_platformIdentifier = platformIdentifier; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + + bool includeMaterialPropertyNames = true; + RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); + jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; jobDependencyList.push_back(jobDependency); } From 4dab267dc90513af1c46b4c8e6d615e44fb628c5 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Thu, 16 Sep 2021 21:36:33 -0700 Subject: [PATCH 173/274] Fix AzAutoGen output to use a proper output using path.commonpath instead of path.commonprefix, which unlike commonprefix always return a valid path. For example, commonprefix [usr/hello.txt, usr/helium.cpp] would return usr/he Signed-off-by: Gene Walters --- cmake/AzAutoGen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/AzAutoGen.py b/cmake/AzAutoGen.py index 51c46b53d8..19b9711325 100755 --- a/cmake/AzAutoGen.py +++ b/cmake/AzAutoGen.py @@ -71,10 +71,10 @@ def SearchPaths(filename, paths=[]): return None def ComputeOutputPath(inputFiles, projectDir, outputDir): - commonInputPath = os.path.commonprefix(inputFiles) # If we've globbed many source files, this finds the common prefix + commonInputPath = os.path.commonpath(inputFiles) # If we've globbed many source files, this finds the common path if os.path.isfile(commonInputPath): # If the commonInputPath resolves to an actual file, slice off the filename commonInputPath = os.path.dirname(commonInputPath) - commonPath = os.path.commonprefix([commonInputPath, projectDir]) # Finds the common path between the data source files and our project directory (//depot/dev/Code/Framework/AzCore/) + commonPath = os.path.commonpath([commonInputPath, projectDir]) # Finds the common path between the data source files and our project directory (//depot/dev/Code/Framework/AzCore/) inputRelativePath = os.path.relpath(commonInputPath, commonPath) # Computes the relative path for the project source directory (Code/Framework/AzCore/AutoGen/) return os.path.join(outputDir, inputRelativePath) # Returns a suitable output directory (//depot/dev/Generated/Code/Framework/AzCore/AutoGen/) From f5bd450673c656eb81f3081fbd92ba9fd6ce05e4 Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Fri, 17 Sep 2021 04:06:19 -0700 Subject: [PATCH 174/274] Fixed the crash by clear out the item and map array (#4162) * Fixed the crash by clear out the item and map array Signed-off-by: rhhong * emplace is doing an insert which is not expected. Signed-off-by: rhhong --- .../Code/EMotionFX/Source/Recorder.cpp | 19 ++++++++----------- .../Code/EMotionFX/Source/Recorder.h | 8 ++++---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp index 085d164a94..54fb130ad3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.cpp @@ -1421,17 +1421,16 @@ namespace EMotionFX // extract sorted active items void Recorder::ExtractNodeHistoryItems(const ActorInstanceData& actorInstanceData, float timeValue, bool sort, EValueType valueType, AZStd::vector* outItems, AZStd::vector* outMap) const { - // clear the map array + // Reinit the item array. const size_t maxIndex = CalcMaxNodeHistoryTrackIndex(actorInstanceData); outItems->resize(maxIndex + 1); for (size_t i = 0; i <= maxIndex; ++i) { - ExtractedNodeHistoryItem item; - item.m_trackIndex = i; - item.m_value = 0.0f; + ExtractedNodeHistoryItem& item = (*outItems)[i]; + item.m_nodeHistoryItem = nullptr; + item.m_trackIndex = i; item.m_keyTrackSampleTime = 0.0f; - item.m_nodeHistoryItem = nullptr; - outItems->emplace(AZStd::next(begin(*outItems), i), AZStd::move(item)); + item.m_value = 0.0f; } // find all node history items @@ -1440,7 +1439,7 @@ namespace EMotionFX { if (curItem->m_startTime <= timeValue && curItem->m_endTime > timeValue) { - ExtractedNodeHistoryItem item; + ExtractedNodeHistoryItem& item = (*outItems)[curItem->m_trackIndex]; item.m_trackIndex = curItem->m_trackIndex; item.m_keyTrackSampleTime = timeValue - curItem->m_startTime; item.m_nodeHistoryItem = curItem; @@ -1463,8 +1462,6 @@ namespace EMotionFX MCORE_ASSERT(false); // unsupported mode item.m_value = curItem->m_globalWeights.GetValueAtTime(item.m_keyTrackSampleTime, nullptr, nullptr, m_recordSettings.m_interpolate); } - - outItems->emplace(AZStd::next(begin(*outItems), curItem->m_trackIndex), item); } } @@ -1472,7 +1469,7 @@ namespace EMotionFX outMap->resize(maxIndex + 1); for (size_t i = 0; i <= maxIndex; ++i) { - outMap->emplace(AZStd::next(begin(*outMap), i), i); + (*outMap)[i] = i; } // sort if desired @@ -1482,7 +1479,7 @@ namespace EMotionFX for (size_t i = 0; i <= maxIndex; ++i) { - outMap->emplace(AZStd::next(begin(*outMap), outItems->at(i).m_trackIndex), i); + (*outMap)[outItems->at(i).m_trackIndex] = i; } } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h index fe87d36ea1..c486427159 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Recorder.h @@ -168,10 +168,10 @@ namespace EMotionFX struct EMFX_API ExtractedNodeHistoryItem { - NodeHistoryItem* m_nodeHistoryItem; - size_t m_trackIndex; - float m_value; - float m_keyTrackSampleTime; + NodeHistoryItem* m_nodeHistoryItem = nullptr; + size_t m_trackIndex = 0; + float m_value = 0.0f; + float m_keyTrackSampleTime = 0.0f; friend bool operator< (const ExtractedNodeHistoryItem& a, const ExtractedNodeHistoryItem& b) { return (a.m_value > b.m_value); } friend bool operator==(const ExtractedNodeHistoryItem& a, const ExtractedNodeHistoryItem& b) { return (a.m_value == b.m_value); } From 9a71a902d0037fa717ba8af7bd74db67fe519b4a Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:07:01 +0200 Subject: [PATCH 175/274] Animation Editor: Closing the Create Group window creates a new Parameter Group (#4167) Signed-off-by: Benjamin Jillich --- .../StandardPlugins/Source/AnimGraph/ParameterWindow.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp index 3f3c7c1c7d..c8ce48fe18 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ParameterWindow.cpp @@ -1461,10 +1461,15 @@ namespace EMStudio // show the create window auto createWindow = new ParameterCreateRenameWindow("Create Group", "Please enter the group name:", uniqueGroupName.c_str(), "", invalidNames, this); - connect(createWindow, &QDialog::finished, this, [this, createWindow]() + connect(createWindow, &QDialog::finished, this, [this, createWindow](int resultCode) { createWindow->deleteLater(); + if (resultCode == QDialog::Rejected) + { + return; + } + AZStd::string command = AZStd::string::format("AnimGraphAddGroupParameter -animGraphID %i -name \"%s\"", m_animGraph->GetID(), createWindow->GetName().c_str()); const EMotionFX::GroupParameter* parentGroup = nullptr; const EMotionFX::Parameter* selectedParameter = GetSingleSelectedParameter(); From c28bc7c6d8c7316f9c7053423d40a7b8ebd0c696 Mon Sep 17 00:00:00 2001 From: jonawals Date: Fri, 17 Sep 2021 12:41:19 +0100 Subject: [PATCH 176/274] Add deserialization to sequence reports. (#4018) * Add deserialization to sequence reports. Signed-off-by: John * Address PR comments. Signed-off-by: John * Address PR comments. Signed-off-by: John * Address PR comments. Signed-off-by: John * Revert last change. Signed-off-by: John --- .../TestImpactClientSequenceReport.h | 157 ++++++----- ...TestImpactClientSequenceReportSerializer.h | 20 +- .../TestImpactFramework/TestImpactUtils.h | 39 +++ .../Source/TestImpactClientSequenceReport.cpp | 101 +++---- ...stImpactClientSequenceReportSerializer.cpp | 262 +++++++++++++++++- .../Runtime/Code/Source/TestImpactUtils.cpp | 252 +++++++++++++++++ 6 files changed, 678 insertions(+), 153 deletions(-) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h index b39c2c8bcb..b668bda155 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReport.h @@ -122,12 +122,14 @@ namespace TestImpact }; //! Base class for all sequence report types. - template + template class SequenceReportBase { public: + static constexpr SequenceReportType ReportType = Type; + using PolicyState = PolicyStateType; + //! Constructs the report for a sequence of selected tests. - //! @param type The type of sequence this report is generated for. //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). @@ -136,33 +138,49 @@ namespace TestImpact //! @param selectedTestRuns The target names of the selected test runs. //! @param selectedTestRunReport The report for the set of selected test runs. SequenceReportBase( - SequenceReportType type, size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const PolicyStateType& policyState, + AZStd::optional testTargetTimeout, + AZStd::optional globalTimeout, + PolicyStateType policyState, SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - TestRunReport&& selectedTestRunReport) - : m_type(type) - , m_maxConcurrency(maxConcurrency) - , m_testTargetTimeout(testTargetTimeout) - , m_globalTimeout(globalTimeout) - , m_policyState(policyState) + TestRunSelection selectedTestRuns, + TestRunReport selectedTestRunReport) + : m_maxConcurrency(maxConcurrency) + , m_testTargetTimeout(AZStd::move(testTargetTimeout)) + , m_globalTimeout(AZStd::move(globalTimeout)) + , m_policyState(AZStd::move(policyState)) , m_suite(suiteType) - , m_selectedTestRuns(selectedTestRuns) + , m_selectedTestRuns(AZStd::move(selectedTestRuns)) , m_selectedTestRunReport(AZStd::move(selectedTestRunReport)) { } - virtual ~SequenceReportBase() = default; + SequenceReportBase(SequenceReportBase&& report) + : SequenceReportBase( + AZStd::move(report.m_maxConcurrency), + AZStd::move(report.m_testTargetTimeout), + AZStd::move(report.m_globalTimeout), + AZStd::move(report.m_policyState), + AZStd::move(report.m_suite), + AZStd::move(report.m_selectedTestRuns), + AZStd::move(report.m_selectedTestRunReport)) + { + } - //! Returns the identifying type for this sequence report. - SequenceReportType GetType() const + SequenceReportBase(const SequenceReportBase& report) + : SequenceReportBase( + report.m_maxConcurrency, + report.m_testTargetTimeout, + report.m_globalTimeout, + report.m_policyState, + report.m_suite, + report.m_selectedTestRuns, + report.m_selectedTestRunReport) { - return m_type; } + virtual ~SequenceReportBase() = default; + //! Returns the maximum concurrency for this sequence. size_t GetMaxConcurrency() const { @@ -284,7 +302,6 @@ namespace TestImpact } private: - SequenceReportType m_type; size_t m_maxConcurrency = 0; AZStd::optional m_testTargetTimeout; AZStd::optional m_globalTimeout; @@ -296,58 +313,27 @@ namespace TestImpact //! Report type for regular test sequences. class RegularSequenceReport - : public SequenceReportBase + : public SequenceReportBase { public: - //! Constructs the report for a regular sequence. - //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. - //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). - //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). - //! @param policyState The policy state this sequence was executed under. - //! @param suiteType The suite from which the tests have been selected from. - //! @param selectedTestRuns The target names of the selected test runs. - //! @param selectedTestRunReport The report for the set of selected test runs. - RegularSequenceReport( - size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const SequencePolicyState& policyState, - SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - TestRunReport&& selectedTestRunReport); + using SequenceReportBase::SequenceReportBase; }; //! Report type for seed test sequences. class SeedSequenceReport - : public SequenceReportBase + : public SequenceReportBase { public: - //! Constructs the report for a seed sequence. - //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. - //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). - //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). - //! @param policyState The policy state this sequence was executed under. - //! @param suiteType The suite from which the tests have been selected from. - //! @param selectedTestRuns The target names of the selected test runs. - //! @param selectedTestRunReport The report for the set of selected test runs. - SeedSequenceReport( - size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const SequencePolicyState& policyState, - SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - TestRunReport&& selectedTestRunReport); + using SequenceReportBase::SequenceReportBase; }; //! Report detailing a test run sequence of selected and drafted tests. - template + template class DraftingSequenceReportBase - : public SequenceReportBase + : public SequenceReportBase { public: //! Constructs the report for sequences that draft in previously failed/newly added test targets. - //! @param type The type of sequence this report is generated for. //! @param maxConcurrency The maximum number of concurrent test targets in flight at any given time. //! @param testTargetTimeout The maximum duration individual test targets may be in flight for (infinite if empty). //! @param globalTimeout The maximum duration the entire test sequence may run for (infinite if empty). @@ -358,18 +344,16 @@ namespace TestImpact //! @param selectedTestRunReport The report for the set of selected test runs. //! @param draftedTestRunReport The report for the set of drafted test runs. DraftingSequenceReportBase( - SequenceReportType type, size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const PolicyStateType& policyState, + AZStd::optional testTargetTimeout, + AZStd::optional globalTimeout, + PolicyStateType policyState, SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - const AZStd::vector& draftedTestRuns, + TestRunSelection selectedTestRuns, + AZStd::vector draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& draftedTestRunReport) - : SequenceReportBase ( - type, + : SequenceReportBase( maxConcurrency, testTargetTimeout, globalTimeout, @@ -377,7 +361,17 @@ namespace TestImpact suiteType, selectedTestRuns, AZStd::move(selectedTestRunReport)) - , m_draftedTestRuns(draftedTestRuns) + , m_draftedTestRuns(AZStd::move(draftedTestRuns)) + , m_draftedTestRunReport(AZStd::move(draftedTestRunReport)) + { + } + + DraftingSequenceReportBase( + SequenceReportBase&& report, + AZStd::vector draftedTestRuns, + TestRunReport&& draftedTestRunReport) + : SequenceReportBase(AZStd::move(report)) + , m_draftedTestRuns(AZStd::move(draftedTestRuns)) , m_draftedTestRunReport(AZStd::move(draftedTestRunReport)) { } @@ -456,7 +450,7 @@ namespace TestImpact //! Report detailing an impact analysis sequence of selected, discarded and drafted tests. class ImpactAnalysisSequenceReport - : public DraftingSequenceReportBase + : public DraftingSequenceReportBase { public: //! Constructs the report for an impact analysis sequence. @@ -471,16 +465,18 @@ namespace TestImpact //! @param draftedTestRunReport The report for the set of drafted test runs. ImpactAnalysisSequenceReport( size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const ImpactAnalysisSequencePolicyState& policyState, + AZStd::optional testTargetTimeout, + AZStd::optional globalTimeout, + ImpactAnalysisSequencePolicyState policyState, SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - const AZStd::vector& discardedTestRuns, - const AZStd::vector& draftedTestRuns, + TestRunSelection selectedTestRuns, + AZStd::vector discardedTestRuns, + AZStd::vector draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& draftedTestRunReport); + ImpactAnalysisSequenceReport(DraftingSequenceReportBase&& report, AZStd::vector discardedTestRuns); + //! Returns the test runs discarded from running in the sequence. const AZStd::vector& GetDiscardedTestRuns() const; private: @@ -489,7 +485,7 @@ namespace TestImpact //! Report detailing an impact analysis sequence of selected, discarded and drafted test runs. class SafeImpactAnalysisSequenceReport - : public DraftingSequenceReportBase + : public DraftingSequenceReportBase { public: //! Constructs the report for a sequence of selected, discarded and drafted test runs. @@ -506,17 +502,20 @@ namespace TestImpact //! @param draftedTestRunReport The report for the set of drafted test runs. SafeImpactAnalysisSequenceReport( size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const SafeImpactAnalysisSequencePolicyState& policyState, + AZStd::optional testTargetTimeout, + AZStd::optional globalTimeout, + SafeImpactAnalysisSequencePolicyState policyState, SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - const TestRunSelection& discardedTestRuns, - const AZStd::vector& draftedTestRuns, + TestRunSelection selectedTestRuns, + TestRunSelection discardedTestRuns, + AZStd::vector draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& discardedTestRunReport, TestRunReport&& draftedTestRunReport); + SafeImpactAnalysisSequenceReport( + DraftingSequenceReportBase&& report, TestRunSelection discardedTestRuns, TestRunReport&& discardedTestRunReport); + // SequenceReport overrides ... AZStd::chrono::milliseconds GetDuration() const override; TestSequenceResult GetResult() const override; diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h index fc226588e7..06bb0cdaa1 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactClientSequenceReportSerializer.h @@ -14,15 +14,27 @@ namespace TestImpact { - //! Serializes a regular sequence report to JSON format. + //! Serializes a regular sequence report to Json format. AZStd::string SerializeSequenceReport(const Client::RegularSequenceReport& sequenceReport); - //! Serializes a seed sequence report to JSON format. + //! Serializes a seed sequence report to Json format. AZStd::string SerializeSequenceReport(const Client::SeedSequenceReport& sequenceReport); - //! Serializes an impact analysis sequence report to JSON format. + //! Serializes an impact analysis sequence report to Json format. AZStd::string SerializeSequenceReport(const Client::ImpactAnalysisSequenceReport& sequenceReport); - //! Serializes a safe impact analysis sequence report to JSON format. + //! Serializes a safe impact analysis sequence report to Json format. AZStd::string SerializeSequenceReport(const Client::SafeImpactAnalysisSequenceReport& sequenceReport); + + //! Deserialize a regular sequence report from Json format. + Client::RegularSequenceReport DeserializeRegularSequenceReport(const AZStd::string& sequenceReportJson); + + //! Deserialize a seed sequence report from Json format. + Client::SeedSequenceReport DeserializeSeedSequenceReport(const AZStd::string& sequenceReportJson); + + //! Deserialize an impact analysis sequence report from Json format. + Client::ImpactAnalysisSequenceReport DeserializeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson); + + //! Deserialize a safe impact analysis sequence report from Json format. + Client::SafeImpactAnalysisSequenceReport DeserializeSafeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson); } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h index c4625e9d2c..f7afd49b26 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Include/TestImpactFramework/TestImpactUtils.h @@ -103,4 +103,43 @@ namespace TestImpact //! User-friendly names for the client test result types. AZStd::string ClientTestResultAsString(Client::TestResult result); + + //! User-friendly names for the suite types. + SuiteType SuiteTypeFromString(const AZStd::string& suiteType); + + //! Returns the sequence report type for the specified string. + Client::SequenceReportType SequenceReportTypeFromString(const AZStd::string& type); + + //! Returns the test run result for the specified string. + Client::TestRunResult TestRunResultFromString(const AZStd::string& result); + + //! Returns the test result for the specified string. + Client::TestResult TestResultFromString(const AZStd::string& result); + + //! Returns the test sequence result for the specified string. + TestSequenceResult TestSequenceResultFromString(const AZStd::string& result); + + //! Returns the execution failure policy for the specified string. + Policy::ExecutionFailure ExecutionFailurePolicyFromString(const AZStd::string& executionFailurePolicy); + + //! Returns the failed test coverage policy for the specified string. + Policy::FailedTestCoverage FailedTestCoveragePolicyFromString(const AZStd::string& failedTestCoveragePolicy); + + //! Returns the test prioritization policy for the specified string. + Policy::TestPrioritization TestPrioritizationPolicyFromString(const AZStd::string& testPrioritizationPolicy); + + //! Returns the test failure policy for the specified string. + Policy::TestFailure TestFailurePolicyFromString(const AZStd::string& testFailurePolicy); + + //! Returns the integrity failure policy for the specified string. + Policy::IntegrityFailure IntegrityFailurePolicyFromString(const AZStd::string& integrityFailurePolicy); + + //! Returns the dynamic dependency map policy for the specified string. + Policy::DynamicDependencyMap DynamicDependencyMapPolicyFromString(const AZStd::string& dynamicDependencyMapPolicy); + + //! Returns the test sharding policy for the specified string. + Policy::TestSharding TestShardingPolicyFromString(const AZStd::string& testShardingPolicy); + + //! Returns the target output capture policy for the specified string. + Policy::TargetOutputCapture TargetOutputCapturePolicyFromString(const AZStd::string& targetOutputCapturePolicy); } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp index 3f4656758a..17157e70fc 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReport.cpp @@ -159,72 +159,38 @@ namespace TestImpact return m_totalNumDisabledTests; } - RegularSequenceReport::RegularSequenceReport( - size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const SequencePolicyState& policyState, - SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - TestRunReport&& selectedTestRunReport) - : SequenceReportBase( - SequenceReportType::RegularSequence, - maxConcurrency, - testTargetTimeout, - globalTimeout, - policyState, - suiteType, - selectedTestRuns, - AZStd::move(selectedTestRunReport)) - { - } - - SeedSequenceReport::SeedSequenceReport( - size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const SequencePolicyState& policyState, - SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - TestRunReport&& selectedTestRunReport) - : SequenceReportBase( - SequenceReportType::SeedSequence, - maxConcurrency, - testTargetTimeout, - globalTimeout, - policyState, - suiteType, - selectedTestRuns, - AZStd::move(selectedTestRunReport)) - { - } - ImpactAnalysisSequenceReport::ImpactAnalysisSequenceReport( size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const ImpactAnalysisSequencePolicyState& policyState, + AZStd::optional testTargetTimeout, + AZStd::optional globalTimeout, + ImpactAnalysisSequencePolicyState policyState, SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - const AZStd::vector& discardedTestRuns, - const AZStd::vector& draftedTestRuns, + TestRunSelection selectedTestRuns, + AZStd::vector discardedTestRuns, + AZStd::vector draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& draftedTestRunReport) : DraftingSequenceReportBase( - SequenceReportType::ImpactAnalysisSequence, maxConcurrency, - testTargetTimeout, - globalTimeout, - policyState, + AZStd::move(testTargetTimeout), + AZStd::move(globalTimeout), + AZStd::move(policyState), suiteType, - selectedTestRuns, - draftedTestRuns, + AZStd::move(selectedTestRuns), + AZStd::move(draftedTestRuns), AZStd::move(selectedTestRunReport), AZStd::move(draftedTestRunReport)) , m_discardedTestRuns(discardedTestRuns) { } + ImpactAnalysisSequenceReport::ImpactAnalysisSequenceReport( + DraftingSequenceReportBase&& report, AZStd::vector discardedTestRuns) + : DraftingSequenceReportBase(AZStd::move(report)) + , m_discardedTestRuns(AZStd::move(discardedTestRuns)) + { + } + const AZStd::vector& ImpactAnalysisSequenceReport::GetDiscardedTestRuns() const { return m_discardedTestRuns; @@ -232,25 +198,24 @@ namespace TestImpact SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport( size_t maxConcurrency, - const AZStd::optional& testTargetTimeout, - const AZStd::optional& globalTimeout, - const SafeImpactAnalysisSequencePolicyState& policyState, + AZStd::optional testTargetTimeout, + AZStd::optional globalTimeout, + SafeImpactAnalysisSequencePolicyState policyState, SuiteType suiteType, - const TestRunSelection& selectedTestRuns, - const TestRunSelection& discardedTestRuns, - const AZStd::vector& draftedTestRuns, + TestRunSelection selectedTestRuns, + TestRunSelection discardedTestRuns, + AZStd::vector draftedTestRuns, TestRunReport&& selectedTestRunReport, TestRunReport&& discardedTestRunReport, TestRunReport&& draftedTestRunReport) : DraftingSequenceReportBase( - SequenceReportType::SafeImpactAnalysisSequence, maxConcurrency, - testTargetTimeout, - globalTimeout, - policyState, + AZStd::move(testTargetTimeout), + AZStd::move(globalTimeout), + AZStd::move(policyState), suiteType, - selectedTestRuns, - draftedTestRuns, + AZStd::move(selectedTestRuns), + AZStd::move(draftedTestRuns), AZStd::move(selectedTestRunReport), AZStd::move(draftedTestRunReport)) , m_discardedTestRuns(discardedTestRuns) @@ -258,6 +223,14 @@ namespace TestImpact { } + SafeImpactAnalysisSequenceReport::SafeImpactAnalysisSequenceReport( + DraftingSequenceReportBase&& report, TestRunSelection discardedTestRuns, TestRunReport&& discardedTestRunReport) + : DraftingSequenceReportBase(AZStd::move(report)) + , m_discardedTestRuns(AZStd::move(discardedTestRuns)) + , m_discardedTestRunReport(AZStd::move(discardedTestRunReport)) + { + } + TestSequenceResult SafeImpactAnalysisSequenceReport::GetResult() const { return CalculateMultiTestSequenceResult({ DraftingSequenceReportBase::GetResult(), m_discardedTestRunReport.GetResult() }); diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp index 99a187fe16..944fd4ac38 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactClientSequenceReportSerializer.cpp @@ -21,7 +21,7 @@ namespace TestImpact { namespace SequenceReportFields { - // Keys for pertinent JSON node and attribute names + // Keys for pertinent Json node and attribute names constexpr const char* Keys[] = { "name", @@ -417,13 +417,13 @@ namespace TestImpact writer.String(DynamicDependencyMapPolicyAsString(policyState.m_dynamicDependencyMap).c_str()); } - template + template void SerializeSequenceReportBaseMembers( - const Client::SequenceReportBase& sequenceReport, rapidjson::PrettyWriter& writer) + const SequenceReportBaseType& sequenceReport, rapidjson::PrettyWriter& writer) { // Type writer.Key(SequenceReportFields::Keys[SequenceReportFields::Type]); - writer.String(SequenceReportTypeAsString(sequenceReport.GetType()).c_str()); + writer.String(SequenceReportTypeAsString(sequenceReport.ReportType).c_str()); // Test target timeout writer.Key(SequenceReportFields::Keys[SequenceReportFields::TestTargetTimeout]); @@ -510,9 +510,9 @@ namespace TestImpact writer.Uint64(sequenceReport.GetTotalNumDisabledTests()); } - template + template void SerializeDraftingSequenceReportMembers( - const Client::DraftingSequenceReportBase& sequenceReport, rapidjson::PrettyWriter& writer) + const DraftingSequenceReportBaseType& sequenceReport, rapidjson::PrettyWriter& writer) { SerializeSequenceReportBaseMembers(sequenceReport, writer); @@ -603,4 +603,254 @@ namespace TestImpact return stringBuffer.GetString(); } + + AZStd::chrono::high_resolution_clock::time_point TimePointFromMsInt64(AZ::s64 ms) + { + return AZStd::chrono::high_resolution_clock::time_point(AZStd::chrono::milliseconds(ms)); + } + + AZStd::vector DeserializeTests(const rapidjson::Value& serialTests) + { + AZStd::vector tests; + tests.reserve(serialTests[SequenceReportFields::Keys[SequenceReportFields::Tests]].GetArray().Size()); + for (const auto& test : serialTests[SequenceReportFields::Keys[SequenceReportFields::Tests]].GetArray()) + { + const AZStd::string name = test[SequenceReportFields::Keys[SequenceReportFields::Name]].GetString(); + const auto result = TestResultFromString(test[SequenceReportFields::Keys[SequenceReportFields::Result]].GetString()); + tests.emplace_back(name, result); + } + + return tests; + } + + Client::TestRunBase DeserializeTestRunBase(const rapidjson::Value& serialTestRun) + { + return Client::TestRunBase( + serialTestRun[SequenceReportFields::Keys[SequenceReportFields::Name]].GetString(), + serialTestRun[SequenceReportFields::Keys[SequenceReportFields::CommandArgs]].GetString(), + TimePointFromMsInt64(serialTestRun[SequenceReportFields::Keys[SequenceReportFields::StartTime]].GetInt64()), + AZStd::chrono::milliseconds(serialTestRun[SequenceReportFields::Keys[SequenceReportFields::Duration]].GetInt64()), + TestRunResultFromString(serialTestRun[SequenceReportFields::Keys[SequenceReportFields::Result]].GetString())); + } + + template + AZStd::vector DeserializeTestRuns(const rapidjson::Value& serialTestRuns) + { + AZStd::vector testRuns; + testRuns.reserve(serialTestRuns.GetArray().Size()); + for (const auto& testRun : serialTestRuns.GetArray()) + { + testRuns.emplace_back(DeserializeTestRunBase(testRun)); + } + + return testRuns; + } + + template + AZStd::vector DeserializeCompletedTestRuns(const rapidjson::Value& serialCompletedTestRuns) + { + AZStd::vector testRuns; + testRuns.reserve(serialCompletedTestRuns.GetArray().Size()); + for (const auto& testRun : serialCompletedTestRuns.GetArray()) + { + testRuns.emplace_back( + DeserializeTestRunBase(testRun), DeserializeTests(testRun[SequenceReportFields::Keys[SequenceReportFields::Tests]])); + } + + return testRuns; + } + + Client::TestRunReport DeserializeTestRunReport(const rapidjson::Value& serialTestRunReport) + { + return Client::TestRunReport( + TestSequenceResultFromString(serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::Result]].GetString()), + TimePointFromMsInt64(serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::StartTime]].GetInt64()), + AZStd::chrono::milliseconds(serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::Duration]].GetInt64()), + DeserializeCompletedTestRuns( + serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::PassingTestRuns]]), + DeserializeCompletedTestRuns( + serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::FailingTestRuns]]), + DeserializeTestRuns( + serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::ExecutionFailureTestRuns]]), + DeserializeTestRuns( + serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::TimedOutTestRuns]]), + DeserializeTestRuns( + serialTestRunReport[SequenceReportFields::Keys[SequenceReportFields::UnexecutedTestRuns]])); + } + + Client::TestRunSelection DeserializeTestSelection(const rapidjson::Value& serialTestRunSelection) + { + const auto extractTestTargetNames = [](const rapidjson::Value& serialTestTargets) + { + AZStd::vector testTargets; + testTargets.reserve(serialTestTargets.GetArray().Size()); + for (const auto& testTarget : serialTestTargets.GetArray()) + { + testTargets.emplace_back(testTarget.GetString()); + } + + return testTargets; + }; + + return Client::TestRunSelection( + extractTestTargetNames(serialTestRunSelection[SequenceReportFields::Keys[SequenceReportFields::IncludedTestRuns]]), + extractTestTargetNames(serialTestRunSelection[SequenceReportFields::Keys[SequenceReportFields::ExcludedTestRuns]])); + } + + PolicyStateBase DeserializePolicyStateBaseMembers(const rapidjson::Value& serialPolicyState) + { + return + { + ExecutionFailurePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::ExecutionFailure]].GetString()), + FailedTestCoveragePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::CoverageFailure]].GetString()), + TestFailurePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestFailure]].GetString()), + IntegrityFailurePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::IntegrityFailure]].GetString()), + TestShardingPolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestSharding]].GetString()), + TargetOutputCapturePolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TargetOutputCapture]].GetString()) + }; + } + + SequencePolicyState DeserializePolicyStateMembers(const rapidjson::Value& serialPolicyState) + { + return { DeserializePolicyStateBaseMembers(serialPolicyState) }; + } + + SafeImpactAnalysisSequencePolicyState DeserializeSafeImpactAnalysisPolicyStateMembers(const rapidjson::Value& serialPolicyState) + { + return + { + DeserializePolicyStateBaseMembers(serialPolicyState), + TestPrioritizationPolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]].GetString()) + }; + } + + ImpactAnalysisSequencePolicyState DeserializeImpactAnalysisSequencePolicyStateMembers(const rapidjson::Value& serialPolicyState) + { + return + { + DeserializePolicyStateBaseMembers(serialPolicyState), + TestPrioritizationPolicyFromString(serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::TestPrioritization]].GetString()), + DynamicDependencyMapPolicyFromString( + serialPolicyState[SequenceReportFields::Keys[SequenceReportFields::DynamicDependencyMap]].GetString()) + }; + } + + template + PolicyStateType DeserializePolicyStateType(const rapidjson::Value& serialPolicyStateType) + { + if constexpr (AZStd::is_same_v) + { + return DeserializePolicyStateMembers(serialPolicyStateType); + } + else if constexpr (AZStd::is_same_v) + { + return DeserializeSafeImpactAnalysisPolicyStateMembers(serialPolicyStateType); + } + else if constexpr (AZStd::is_same_v) + { + return DeserializeImpactAnalysisSequencePolicyStateMembers(serialPolicyStateType); + } + else + { + static_assert(false, "Template paramater must be a valid policy state type"); + } + } + + template + SequenceReportBaseType DeserialiseSequenceReportBase(const rapidjson::Value& serialSequenceReportBase) + { + const auto type = SequenceReportTypeFromString(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::Type]].GetString()); + AZ_TestImpact_Eval( + type == SequenceReportBaseType::ReportType, + SequenceReportException, AZStd::string::format( + "The JSON sequence report type '%s' does not match the constructed report type", + serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::Type]].GetString())); + + const auto testTargetTimeout = + serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::TestTargetTimeout]].GetUint64(); + const auto globalTimeout = + serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::GlobalTimeout]].GetUint64(); + + return SequenceReportBaseType( + serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::MaxConcurrency]].GetUint64(), + testTargetTimeout ? AZStd::optional{ testTargetTimeout } : AZStd::nullopt, + globalTimeout ? AZStd::optional{ globalTimeout } : AZStd::nullopt, + DeserializePolicyStateType(serialSequenceReportBase), + SuiteTypeFromString(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::Suite]].GetString()), + DeserializeTestSelection(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::SelectedTestRuns]]), + DeserializeTestRunReport(serialSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::SelectedTestRunReport]])); + } + + template + Client::DraftingSequenceReportBase + DeserializeDraftingSequenceReportBase(const rapidjson::Value& serialDraftingSequenceReportBase) + { + AZStd::vector draftingTestRuns; + draftingTestRuns.reserve( + serialDraftingSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::DraftedTestRuns]].GetArray().Size()); + for (const auto& testRun : + serialDraftingSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::DraftedTestRuns]].GetArray()) + { + draftingTestRuns.emplace_back(testRun.GetString()); + } + + using SequenceBase = + Client::SequenceReportBase; + using DraftingSequenceBase = + Client::DraftingSequenceReportBase; + + return DraftingSequenceBase( + DeserialiseSequenceReportBase(serialDraftingSequenceReportBase), + AZStd::move(draftingTestRuns), + DeserializeTestRunReport(serialDraftingSequenceReportBase[SequenceReportFields::Keys[SequenceReportFields::DraftedTestRunReport]])); + } + + rapidjson::Document OpenSequenceReportJson(const AZStd::string& sequenceReportJson) + { + rapidjson::Document doc; + + if (doc.Parse<0>(sequenceReportJson.c_str()).HasParseError()) + { + throw SequenceReportException("Could not parse sequence report data"); + } + + return doc; + } + + Client::RegularSequenceReport DeserializeRegularSequenceReport(const AZStd::string& sequenceReportJson) + { + const auto doc = OpenSequenceReportJson(sequenceReportJson); + return DeserialiseSequenceReportBase(doc); + } + + Client::SeedSequenceReport DeserializeSeedSequenceReport(const AZStd::string& sequenceReportJson) + { + const auto doc = OpenSequenceReportJson(sequenceReportJson); + return DeserialiseSequenceReportBase(doc); + } + + Client::ImpactAnalysisSequenceReport DeserializeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson) + { + const auto doc = OpenSequenceReportJson(sequenceReportJson); + + AZStd::vector discardedTestRuns; + discardedTestRuns.reserve(doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]].GetArray().Size()); + for (const auto& testRun : doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]].GetArray()) + { + discardedTestRuns.emplace_back(testRun.GetString()); + } + + return Client::ImpactAnalysisSequenceReport( + DeserializeDraftingSequenceReportBase(doc), AZStd::move(discardedTestRuns)); + } + + Client::SafeImpactAnalysisSequenceReport DeserializeSafeImpactAnalysisSequenceReport(const AZStd::string& sequenceReportJson) + { + const auto doc = OpenSequenceReportJson(sequenceReportJson); + + return Client::SafeImpactAnalysisSequenceReport( + DeserializeDraftingSequenceReportBase(doc), + DeserializeTestSelection(doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRuns]]), + DeserializeTestRunReport(doc[SequenceReportFields::Keys[SequenceReportFields::DiscardedTestRunReport]])); + } } // namespace TestImpact diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp index 3f6c9dafd4..ecfdec287b 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp +++ b/Code/Tools/TestImpactFramework/Runtime/Code/Source/TestImpactUtils.cpp @@ -243,4 +243,256 @@ namespace TestImpact throw(Exception(AZStd::string::format("Unexpected client test case result: %u", aznumeric_cast(result)))); } } + + SuiteType SuiteTypeFromString(const AZStd::string& suiteType) + { + if (suiteType == SuiteTypeAsString(SuiteType::Main)) + { + return SuiteType::Main; + } + else if (suiteType == SuiteTypeAsString(SuiteType::Periodic)) + { + return SuiteType::Periodic; + } + else if (suiteType == SuiteTypeAsString(SuiteType::Sandbox)) + { + return SuiteType::Sandbox; + } + else + { + throw Exception(AZStd::string::format("Unexpected suite type: '%s'", suiteType.c_str())); + } + } + + Client::SequenceReportType SequenceReportTypeFromString(const AZStd::string& type) + { + if (type == SequenceReportTypeAsString(Client::SequenceReportType::ImpactAnalysisSequence)) + { + return Client::SequenceReportType::ImpactAnalysisSequence; + } + else if (type == SequenceReportTypeAsString(Client::SequenceReportType::RegularSequence)) + { + return Client::SequenceReportType::RegularSequence; + } + else if (type == SequenceReportTypeAsString(Client::SequenceReportType::SafeImpactAnalysisSequence)) + { + return Client::SequenceReportType::SafeImpactAnalysisSequence; + } + else if (type == SequenceReportTypeAsString(Client::SequenceReportType::SeedSequence)) + { + return Client::SequenceReportType::SeedSequence; + } + else + { + throw Exception(AZStd::string::format("Unexpected sequence report type: '%s'", type.c_str())); + } + } + + Client::TestRunResult TestRunResultFromString(const AZStd::string& result) + { + if (result == TestRunResultAsString(Client::TestRunResult::AllTestsPass)) + { + return Client::TestRunResult::AllTestsPass; + } + else if (result == TestRunResultAsString(Client::TestRunResult::FailedToExecute)) + { + return Client::TestRunResult::FailedToExecute; + } + else if (result == TestRunResultAsString(Client::TestRunResult::NotRun)) + { + return Client::TestRunResult::NotRun; + } + else if (result == TestRunResultAsString(Client::TestRunResult::TestFailures)) + { + return Client::TestRunResult::TestFailures; + } + else if (result == TestRunResultAsString(Client::TestRunResult::Timeout)) + { + return Client::TestRunResult::Timeout; + } + else + { + throw Exception(AZStd::string::format("Unexpected client test run result: '%s'", result.c_str())); + } + } + + Client::TestResult TestResultFromString(const AZStd::string& result) + { + if (result == ClientTestResultAsString(Client::TestResult::Failed)) + { + return Client::TestResult::Failed; + } + else if (result == ClientTestResultAsString(Client::TestResult::NotRun)) + { + return Client::TestResult::NotRun; + } + else if (result == ClientTestResultAsString(Client::TestResult::Passed)) + { + return Client::TestResult::Passed; + } + else + { + throw Exception(AZStd::string::format("Unexpected client test result: '%s'", result.c_str())); + } + } + + TestSequenceResult TestSequenceResultFromString(const AZStd::string& result) + { + if (result == TestSequenceResultAsString(TestSequenceResult::Failure)) + { + return TestSequenceResult::Failure; + } + else if (result == TestSequenceResultAsString(TestSequenceResult::Success)) + { + return TestSequenceResult::Success; + } + else if (result == TestSequenceResultAsString(TestSequenceResult::Timeout)) + { + return TestSequenceResult::Timeout; + } + else + { + throw Exception(AZStd::string::format("Unexpected test sequence result: '%s'", result.c_str())); + } + } + + Policy::ExecutionFailure ExecutionFailurePolicyFromString(const AZStd::string& executionFailurePolicy) + { + if (executionFailurePolicy == ExecutionFailurePolicyAsString(Policy::ExecutionFailure::Abort)) + { + return Policy::ExecutionFailure::Abort; + } + else if (executionFailurePolicy == ExecutionFailurePolicyAsString(Policy::ExecutionFailure::Continue)) + { + return Policy::ExecutionFailure::Continue; + } + else if (executionFailurePolicy == ExecutionFailurePolicyAsString(Policy::ExecutionFailure::Ignore)) + { + return Policy::ExecutionFailure::Ignore; + } + else + { + throw Exception(AZStd::string::format("Unexpected execution failure policy: '%s'", executionFailurePolicy.c_str())); + } + } + + Policy::FailedTestCoverage FailedTestCoveragePolicyFromString(const AZStd::string& failedTestCoveragePolicy) + { + if (failedTestCoveragePolicy == FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage::Discard)) + { + return Policy::FailedTestCoverage::Discard; + } + else if (failedTestCoveragePolicy == FailedTestCoveragePolicyAsString(Policy::FailedTestCoverage::Keep)) + { + return Policy::FailedTestCoverage::Keep; + } + else + { + throw Exception(AZStd::string::format("Unexpected failed test coverage policy: '%s'", failedTestCoveragePolicy.c_str())); + } + } + + Policy::TestPrioritization TestPrioritizationPolicyFromString(const AZStd::string& testPrioritizationPolicy) + { + if (testPrioritizationPolicy == TestPrioritizationPolicyAsString(Policy::TestPrioritization::DependencyLocality)) + { + return Policy::TestPrioritization::DependencyLocality; + } + else if (testPrioritizationPolicy == TestPrioritizationPolicyAsString(Policy::TestPrioritization::None)) + { + return Policy::TestPrioritization::None; + } + else + { + throw Exception(AZStd::string::format("Unexpected test prioritization policy: '%s'", testPrioritizationPolicy.c_str())); + } + } + + Policy::TestFailure TestFailurePolicyFromString(const AZStd::string& testFailurePolicy) + { + if (testFailurePolicy == TestFailurePolicyAsString(Policy::TestFailure::Abort)) + { + return Policy::TestFailure::Abort; + } + else if (testFailurePolicy == TestFailurePolicyAsString(Policy::TestFailure::Continue)) + { + return Policy::TestFailure::Continue; + } + else + { + throw Exception(AZStd::string::format("Unexpected test failure policy: '%s'", testFailurePolicy.c_str())); + } + } + + Policy::IntegrityFailure IntegrityFailurePolicyFromString(const AZStd::string& integrityFailurePolicy) + { + if (integrityFailurePolicy == IntegrityFailurePolicyAsString(Policy::IntegrityFailure::Abort)) + { + return Policy::IntegrityFailure::Abort; + } + else if (integrityFailurePolicy == IntegrityFailurePolicyAsString(Policy::IntegrityFailure::Continue)) + { + return Policy::IntegrityFailure::Continue; + } + else + { + throw Exception(AZStd::string::format("Unexpected integration failure policy: '%s'", integrityFailurePolicy.c_str())); + } + } + + Policy::DynamicDependencyMap DynamicDependencyMapPolicyFromString(const AZStd::string& dynamicDependencyMapPolicy) + { + if (dynamicDependencyMapPolicy == DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap::Discard)) + { + return Policy::DynamicDependencyMap::Discard; + } + else if (dynamicDependencyMapPolicy == DynamicDependencyMapPolicyAsString(Policy::DynamicDependencyMap::Update)) + { + return Policy::DynamicDependencyMap::Update; + } + else + { + throw Exception(AZStd::string::format("Unexpected dynamic dependency map policy: '%s'", dynamicDependencyMapPolicy.c_str())); + } + } + + Policy::TestSharding TestShardingPolicyFromString(const AZStd::string& testShardingPolicy) + { + if (testShardingPolicy == TestShardingPolicyAsString(Policy::TestSharding::Always)) + { + return Policy::TestSharding::Always; + } + else if (testShardingPolicy == TestShardingPolicyAsString(Policy::TestSharding::Never)) + { + return Policy::TestSharding::Never; + } + else + { + throw Exception(AZStd::string::format("Unexpected test sharding policy: '%s'", testShardingPolicy.c_str())); + } + } + + Policy::TargetOutputCapture TargetOutputCapturePolicyFromString(const AZStd::string& targetOutputCapturePolicy) + { + if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::File)) + { + return Policy::TargetOutputCapture::File; + } + else if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::None)) + { + return Policy::TargetOutputCapture::None; + } + else if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::StdOut)) + { + return Policy::TargetOutputCapture::StdOut; + } + else if (targetOutputCapturePolicy == TargetOutputCapturePolicyAsString(Policy::TargetOutputCapture::StdOutAndFile)) + { + return Policy::TargetOutputCapture::StdOutAndFile; + } + else + { + throw Exception(AZStd::string::format("Unexpected target output capture policy: '%s'", targetOutputCapturePolicy.c_str())); + } + } } // namespace TestImpact From 4167bb6cde4e703b201544ef0bddf8f9f1dcfff6 Mon Sep 17 00:00:00 2001 From: AMZN-Alexandre Corcia Aguilera <82398284+aaguilea@users.noreply.github.com> Date: Fri, 17 Sep 2021 14:49:48 +0100 Subject: [PATCH 177/274] Warning System Changes (polish) Redo (#4009) * Restores the branch to the old status from old branch Signed-off-by: aaguilea * Changes that didnt make it from merge manually fixed Signed-off-by: aaguilea * forgot one Signed-off-by: aaguilea * Added Ebus in order to remove rigidbody's dependencies Signed-off-by: aaguilea * answering some of the comments in the PR Signed-off-by: aaguilea * Small typo changed Signed-off-by: aaguilea --- .../UI/PropertyEditor/ComponentEditor.cpp | 6 --- .../PhysX/EditorColliderComponentRequestBus.h | 14 ++++++ .../Code/Source/EditorColliderComponent.cpp | 47 ++++++++++++++----- .../Code/Source/EditorColliderComponent.h | 10 ++-- .../Code/Source/EditorRigidBodyComponent.cpp | 3 ++ 5 files changed, 58 insertions(+), 22 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.cpp index 85676df243..91d2359ca6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.cpp @@ -395,12 +395,6 @@ namespace AzToolsFramework AzQtComponents::CardNotification* ComponentEditor::CreateNotificationForWarningComponents(const QString& message) { AzQtComponents::CardNotification * notification = CreateNotification(message); - const QPushButton * featureButton = notification->addButtonFeature(tr("Continue")); - - connect(featureButton, &QPushButton::clicked, this, [notification]() - { - notification->close(); - }); return notification; } diff --git a/Gems/PhysX/Code/Include/PhysX/EditorColliderComponentRequestBus.h b/Gems/PhysX/Code/Include/PhysX/EditorColliderComponentRequestBus.h index 2cfb48effa..20b02b7098 100644 --- a/Gems/PhysX/Code/Include/PhysX/EditorColliderComponentRequestBus.h +++ b/Gems/PhysX/Code/Include/PhysX/EditorColliderComponentRequestBus.h @@ -82,4 +82,18 @@ namespace PhysX }; using EditorColliderComponentRequestBus = AZ::EBus; + + /// + /// This is a Bus in order to communicate the status of the meshes of the collider and avoid dependencies with the rigidbody + /// + class EditorColliderValidationRequests : public AZ::ComponentBus + { + public: + /// Checks if the the mesh in the collider is correct with the current state of the Rigidbody! + virtual void ValidateRigidBodyMeshGeometryType() = 0; + }; + + using EditorColliderValidationRequestBus = AZ::EBus; } + + diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 4aa240eaae..566903d84a 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -118,11 +118,10 @@ namespace PhysX AZ::u32 EditorProxyShapeConfig::OnShapeTypeChanged() { - //reset the physics asset if the shape type was Physics Asset - if (m_shapeType != Physics::ShapeType::PhysicsAsset && - m_lastShapeType == Physics::ShapeType::PhysicsAsset) + // reset the physics asset if the shape type was Physics Asset + if (m_shapeType != Physics::ShapeType::PhysicsAsset && m_lastShapeType == Physics::ShapeType::PhysicsAsset) { - //clean up any reference to a physics assets, and re-initialize to an empty Pipeline::MeshAsset asset. + // clean up any reference to a physics assets, and re-initialize to an empty Pipeline::MeshAsset asset. m_physicsAsset.m_pxAsset.Reset(); m_physicsAsset.m_pxAsset = AZ::Data::Asset(AZ::Data::AssetLoadBehavior::QueueLoad); @@ -212,6 +211,7 @@ namespace PhysX ->DataElement(AZ::Edit::UIHandlers::Default, &EditorColliderComponent::m_shapeConfiguration, "Shape Configuration", "Configuration of the shape") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorColliderComponent::OnConfigurationChanged) + ->Attribute(AZ::Edit::Attributes::RemoveNotify, &EditorColliderComponent::ValidateRigidBodyMeshGeometryType) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorColliderComponent::m_componentModeDelegate, "Component Mode", "Collider Component Mode") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorColliderComponent::m_colliderDebugDraw, @@ -383,6 +383,7 @@ namespace PhysX ColliderShapeRequestBus::Handler::BusConnect(GetEntityId()); AZ::Render::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); EditorColliderComponentRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(GetEntityId(), GetId())); + EditorColliderValidationRequestBus::Handler::BusConnect(GetEntityId()); m_nonUniformScaleChangedHandler = AZ::NonUniformScaleChangedEvent::Handler( [this](const AZ::Vector3& scale) {OnNonUniformScaleChanged(scale); }); AZ::NonUniformScaleRequestBus::Event(GetEntityId(), &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, @@ -427,6 +428,7 @@ namespace PhysX m_colliderDebugDraw.Disconnect(); AZ::Data::AssetBus::MultiHandler::BusDisconnect(); m_nonUniformScaleChangedHandler.Disconnect(); + EditorColliderValidationRequestBus::Handler::BusDisconnect(); EditorColliderComponentRequestBus::Handler::BusDisconnect(); AZ::Render::MeshComponentNotificationBus::Handler::BusDisconnect(); ColliderShapeRequestBus::Handler::BusDisconnect(); @@ -466,6 +468,7 @@ namespace PhysX UpdateShapeConfigurationScale(); CreateStaticEditorCollider(); + ValidateRigidBodyMeshGeometryType(); m_colliderDebugDraw.ClearCachedGeometry(); @@ -768,15 +771,16 @@ namespace PhysX { m_componentWarnings.clear(); m_configuration.m_materialSelection.SetMaterialSlots(Physics::MaterialSelection::SlotsArray()); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } void EditorColliderComponent::ValidateRigidBodyMeshGeometryType() { const PhysX::EditorRigidBodyComponent* entityRigidbody = m_entity->FindComponent(); - if (m_shapeConfiguration.m_physicsAsset.m_configuration.GetShapeType() == Physics::ShapeType::PhysicsAsset && entityRigidbody) + if (m_shapeConfiguration.m_physicsAsset.m_pxAsset && (m_shapeConfiguration.m_shapeType == Physics::ShapeType::PhysicsAsset) && entityRigidbody) { AZStd::vector> shapes; Utils::GetShapesFromAsset(m_shapeConfiguration.m_physicsAsset.m_configuration, m_configuration, m_hasNonUniformScale, @@ -784,17 +788,32 @@ namespace PhysX if (shapes.empty()) { + m_componentWarnings.clear(); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); return; } - //We grab the first shape to check if it is a triangle mesh. - auto shape = AZStd::rtti_pointer_cast(shapes[0]); + //We check if the shapes are triangle meshes, if any mesh is a triangle mesh we activate the warning. + bool shapeIsTriangleMesh = false; - if (shape && - shape->GetPxShape()->getGeometryType() == physx::PxGeometryType::eTRIANGLEMESH && - entityRigidbody->GetRigidBody() && - entityRigidbody->GetRigidBody()->IsKinematic() == false) + for (const auto& shape : shapes) { + auto current_shape = AZStd::rtti_pointer_cast(shape); + if (current_shape && + current_shape->GetPxShape()->getGeometryType() == physx::PxGeometryType::eTRIANGLEMESH && + entityRigidbody->GetRigidBody() && + entityRigidbody->GetRigidBody()->IsKinematic() == false) + { + shapeIsTriangleMesh = true; + break; + } + } + + if (shapeIsTriangleMesh) + { + m_componentWarnings.clear(); + AZStd::string assetPath = m_shapeConfiguration.m_physicsAsset.m_configuration.m_asset.GetHint().c_str(); const size_t lastSlash = assetPath.rfind('/'); if (lastSlash != AZStd::string::npos) @@ -816,6 +835,10 @@ namespace PhysX { m_componentWarnings.clear(); } + + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); + } void EditorColliderComponent::OnAssetReloaded(AZ::Data::Asset asset) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index 1331fd08b6..773dd0a9b8 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -58,8 +58,8 @@ namespace PhysX //! Proxy container for only displaying a specific shape configuration depending on the shapeType selected. struct EditorProxyShapeConfig { - AZ_CLASS_ALLOCATOR(PhysX::EditorProxyShapeConfig, AZ::SystemAllocator, 0); - AZ_RTTI(PhysX::EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}"); + AZ_CLASS_ALLOCATOR(EditorProxyShapeConfig, AZ::SystemAllocator, 0); + AZ_RTTI(EditorProxyShapeConfig, "{531FB42A-42A9-4234-89BA-FD349EF83D0C}"); static void Reflect(AZ::ReflectContext* context); EditorProxyShapeConfig() = default; @@ -106,6 +106,7 @@ namespace PhysX , private PhysX::ColliderShapeRequestBus::Handler , private AZ::Render::MeshComponentNotificationBus::Handler , private PhysX::EditorColliderComponentRequestBus::Handler + , private PhysX::EditorColliderValidationRequestBus::Handler , private AzPhysics::SimulatedBodyComponentRequestsBus::Handler { public: @@ -197,6 +198,9 @@ namespace PhysX void SetAssetScale(const AZ::Vector3& scale) override; AZ::Vector3 GetAssetScale() override; + // PhysX::EditorColliderValidationRequestBus overrides ... + void ValidateRigidBodyMeshGeometryType() override; + AZ::Transform GetColliderLocalTransform() const; EditorProxyShapeConfig m_shapeConfiguration; @@ -223,8 +227,6 @@ namespace PhysX void BuildDebugDrawMesh() const; - void ValidateRigidBodyMeshGeometryType(); - AZ::ComponentDescriptor::StringWarningArray GetComponentWarnings() const { return m_componentWarnings; }; using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate; diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index ce812a9f31..447c2755c6 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -286,6 +286,9 @@ namespace PhysX } CreateEditorWorldRigidBody(); + PhysX::EditorColliderValidationRequestBus::Event( + GetEntityId(), &PhysX::EditorColliderValidationRequestBus::Events::ValidateRigidBodyMeshGeometryType); + AzPhysics::SimulatedBodyComponentRequestsBus::Handler::BusConnect(GetEntityId()); } From 9184d52a9bb75ac6f8523082a7cff3bc4ec9b0e0 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 17 Sep 2021 11:14:09 -0500 Subject: [PATCH 178/274] Fixed creation of the Engine.pak file (#4188) First the Cache directory itself was being added to the archive. It has been updated to query the assets from the asset type folder i.e Cache/ Second execute_process is being used to invoke CMake `tar` command to create the zip archive since the CMake `file(ARCHIVE_CREATE)` adds the files to the archive relative to the current working directory which is ${CMAKE_BINARY_DIR} when invoking the install script. This was causing the archive to store files with a path of "../../Cache/pc" Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- cmake/Platform/Linux/PAL_linux.cmake | 2 +- cmake/Projects.cmake | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/cmake/Platform/Linux/PAL_linux.cmake b/cmake/Platform/Linux/PAL_linux.cmake index c088163dca..e74adb287e 100644 --- a/cmake/Platform/Linux/PAL_linux.cmake +++ b/cmake/Platform/Linux/PAL_linux.cmake @@ -35,7 +35,7 @@ else() endif() # Set the default asset type for deployment -set(LY_ASSET_DEPLOY_ASSET_TYPE "pc" CACHE STRING "Set the asset type for deployment.") +set(LY_ASSET_DEPLOY_ASSET_TYPE "linux" CACHE STRING "Set the asset type for deployment.") # Set the python cmd tool ly_set(LY_PYTHON_CMD ${CMAKE_CURRENT_SOURCE_DIR}/python/python.sh) diff --git a/cmake/Projects.cmake b/cmake/Projects.cmake index 7f2ac6a4fd..d3f4b33b03 100644 --- a/cmake/Projects.cmake +++ b/cmake/Projects.cmake @@ -147,14 +147,24 @@ foreach(project ${LY_PROJECTS}) cmake_path(RELATIVE_PATH CMAKE_RUNTIME_OUTPUT_DIRECTORY BASE_DIRECTORY ${CMAKE_BINARY_DIR} OUTPUT_VARIABLE runtime_output_directory) set(install_engine_pak_template [=[ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$") - set(install_output_folder "${CMAKE_INSTALL_PREFIX}/@runtime_output_directory@/@PAL_PLATFORM_NAME@/${CMAKE_INSTALL_CONFIG_NAME}") - message(STATUS "Generating ${install_output_folder}/Engine.pak from @full_directory_path@/Cache") + set(install_output_folder "${CMAKE_INSTALL_PREFIX}/@runtime_output_directory@/@PAL_PLATFORM_NAME@/${CMAKE_INSTALL_CONFIG_NAME}/@LY_BUILD_PERMUTATION@") + if(NOT DEFINED LY_ASSET_DEPLOY_ASSET_TYPE) + set(LY_ASSET_DEPLOY_ASSET_TYPE @LY_ASSET_DEPLOY_ASSET_TYPE@) + endif() + message(STATUS "Generating ${install_output_folder}/Engine.pak from @full_directory_path@/Cache/${LY_ASSET_DEPLOY_ASSET_TYPE}") file(MAKE_DIRECTORY "${install_output_folder}") - file(ARCHIVE_CREATE OUTPUT "${install_output_folder}/Engine.pak" - PATHS "@full_directory_path@/Cache" - FORMAT zip - ) - message(STATUS "${install_output_folder}/Engine.pak generated") + cmake_path(SET cache_product_path "@full_directory_path@/Cache/${LY_ASSET_DEPLOY_ASSET_TYPE}") + file(GLOB product_assets "${cache_product_path}/*") + if(product_assets) + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar "cf" "${install_output_folder}/Engine.pak" --format=zip -- ${product_assets} + WORKING_DIRECTORY "${cache_product_path}" + RESULT_VARIABLE archive_creation_result + ) + if(archive_creation_result EQUAL 0) + message(STATUS "${install_output_folder}/Engine.pak generated") + endif() + endif() endif() ]=]) string(CONFIGURE "${install_engine_pak_template}" install_engine_pak_code @ONLY) From 454ae90afb9124d2f0b126ea51bb20cb305db78e Mon Sep 17 00:00:00 2001 From: pereslav Date: Fri, 17 Sep 2021 17:15:21 +0100 Subject: [PATCH 179/274] Added a few whitespaces Signed-off-by: pereslav --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 62b57d9603..61fd741dc6 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -484,7 +484,7 @@ namespace Multiplayer // The first entity in every spawnable is the root one const AZ::Entity* rootEntity = *entities.begin(); - if(!rootEntity) + if (!rootEntity) { AZ_Error("NetworkEntityManager", false, "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); @@ -492,7 +492,7 @@ namespace Multiplayer } const auto* holderComponent = rootEntity->FindComponent(); - if(!holderComponent) + if (!holderComponent) { // This spawnable doesn't have a corresponding network spawnable. return nullptr; @@ -524,11 +524,11 @@ namespace Multiplayer bool shouldUpdateTransform = (rootTransform.IsClose(AZ::Transform::Identity()) == false); for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); - netEntityIndex < entitiesSize; netEntityIndex++) + netEntityIndex < entitiesSize; ++netEntityIndex) { AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); - if(shouldUpdateTransform) + if (shouldUpdateTransform) { AzFramework::TransformComponent* netEntityTransform = netEntity->FindComponent(); @@ -582,7 +582,7 @@ namespace Multiplayer if (ShouldSpawnNetEntities()) { AZStd::unique_ptr ticket = RequestNetSpawnableInstantiation(spawnable, entities); - if(ticket) + if (ticket) { AZ::Data::AssetId spawnableAssetId = spawnable.GetId(); m_netSpawnableTickets[spawnTicket] = AZStd::move(ticket); From fc8697edd5e68d00fef899ba51faf3f4584d358f Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Fri, 17 Sep 2021 09:36:55 -0700 Subject: [PATCH 180/274] ATOM-16029 Add direct support for Astc compression (#4157) * ATOM-16029 Add direct support for Astc compression Changes include: - Add ASTCCompressor class - Enabled 3rdparty::astc-encoder static library. - Remove ASTC support in PVRTC compressor and ISPC compressor. - Update unit test to include texts for ASTC compress/decompress. Signed-off-by: Qing Tao --- .../ImageProcessingAtom/Code/CMakeLists.txt | 3 +- .../Source/Compressors/ASTCCompressor.cpp | 322 ++++++++++++++++++ .../Code/Source/Compressors/ASTCCompressor.h | 30 ++ .../Code/Source/Compressors/Compressor.cpp | 14 +- .../Code/Source/Compressors/Compressor.h | 3 +- .../Compressors/ISPCTextureCompressor.cpp | 32 +- .../Code/Source/Compressors/PVRTC.cpp | 53 +-- .../Code/Source/Processing/ImageConvert.cpp | 20 +- .../Code/Source/Processing/ImageConvert.h | 2 + .../Code/Tests/ImageProcessing_Test.cpp | 150 +++++++- .../Tests/TestAssets/1024x1024_normal.tiff | 3 + .../Code/Tests/TestAssets/512x512_RGB_N.tga | 3 - .../Code/imageprocessing_files.cmake | 2 + .../Linux/BuiltInPackages_linux.cmake | 2 +- .../Platform/Mac/BuiltInPackages_mac.cmake | 2 +- .../Windows/BuiltInPackages_windows.cmake | 2 +- 16 files changed, 538 insertions(+), 105 deletions(-) create mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.cpp create mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.h create mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_normal.tiff delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/512x512_RGB_N.tga diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt index dfeee011cc..1463124e27 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt @@ -62,6 +62,7 @@ ly_add_target( 3rdParty::Qt::Core 3rdParty::Qt::Widgets 3rdParty::Qt::Gui + 3rdParty::astc-encoder 3rdParty::etc2comp 3rdParty::PVRTexTool 3rdParty::squish-ccr @@ -77,8 +78,6 @@ ly_add_target( Gem::Atom_RPI.Public Gem::Atom_RHI.Reflect Gem::Atom_Utils.Static - RUNTIME_DEPENDENCIES - 3rdParty::ASTCEncoder ) ly_add_source_properties( diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.cpp new file mode 100644 index 0000000000..4ef47c043d --- /dev/null +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace ImageProcessingAtom +{ + bool ASTCCompressor::IsCompressedPixelFormatSupported(EPixelFormat fmt) + { + return IsASTCFormat(fmt); + } + + bool ASTCCompressor::IsUncompressedPixelFormatSupported(EPixelFormat fmt) + { + // astc encoder requires the compress input image or decompress output image to have four channels + switch (fmt) + { + // uint 8 + case ePixelFormat_R8G8B8A8: + case ePixelFormat_R8G8B8X8: + // fp16 + case ePixelFormat_R16G16B16A16F: + // fp32 + case ePixelFormat_R32G32B32A32F: + return true; + default: + return false; + } + } + + EPixelFormat ASTCCompressor::GetSuggestedUncompressedFormat([[maybe_unused]] EPixelFormat compressedfmt, EPixelFormat uncompressedfmt) const + { + if (IsUncompressedPixelFormatSupported(uncompressedfmt)) + { + return uncompressedfmt; + } + + auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(uncompressedfmt); + switch (formatInfo->eSampleType) + { + case ESampleType::eSampleType_Half: + return ePixelFormat_R16G16B16A16F; + case ESampleType::eSampleType_Float: + return ePixelFormat_R32G32B32A32F; + } + + return ePixelFormat_R8G8B8A8; + } + + ColorSpace ASTCCompressor::GetSupportedColorSpace([[maybe_unused]] EPixelFormat compressFormat) const + { + return ColorSpace::autoSelect; + } + + const char* ASTCCompressor::GetName() const + { + return "ASTCCompressor"; + } + + bool ASTCCompressor::DoesSupportDecompress([[maybe_unused]] EPixelFormat fmtDst) + { + return true; + } + + astcenc_profile GetAstcProfile(bool isSrgb, EPixelFormat pixelFormat) + { + // select profile depends on LDR or HDR, SRGB or Linear + // ASTCENC_PRF_LDR + // ASTCENC_PRF_LDR_SRGB + // ASTCENC_PRF_HDR_RGB_LDR_A + // ASTCENC_PRF_HDR + + auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); + bool isHDR = formatInfo->eSampleType == ESampleType::eSampleType_Half || formatInfo->eSampleType == ESampleType::eSampleType_Float; + astcenc_profile profile; + if (isHDR) + { + // HDR is not support in core vulkan 1.1 for android. + // https://arm-software.github.io/vulkan-sdk/_a_s_t_c.html + profile = isSrgb?ASTCENC_PRF_HDR_RGB_LDR_A:ASTCENC_PRF_HDR; + } + else + { + + profile = isSrgb?ASTCENC_PRF_LDR_SRGB:ASTCENC_PRF_LDR; + } + return profile; + } + + astcenc_type GetAstcDataType(EPixelFormat pixelFormat) + { + auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); + astcenc_type dataType = ASTCENC_TYPE_U8; + + switch (formatInfo->eSampleType) + { + case ESampleType::eSampleType_Uint8: + dataType = ASTCENC_TYPE_U8; + break; + case ESampleType::eSampleType_Half: + dataType = ASTCENC_TYPE_F16; + break; + case ESampleType::eSampleType_Float: + dataType = ASTCENC_TYPE_F32; + break; + default: + dataType = ASTCENC_TYPE_U8; + AZ_Assert(false, "Unsupport uncompressed format %s", formatInfo->szName); + break; + } + + return dataType; + } + + float GetAstcCompressQuality(ICompressor::EQuality quality) + { + switch (quality) + { + case ICompressor::EQuality::eQuality_Fast: + return ASTCENC_PRE_FAST; + case ICompressor::EQuality::eQuality_Slow: + return ASTCENC_PRE_THOROUGH; + case ICompressor::EQuality::eQuality_Preview: + case ICompressor::EQuality::eQuality_Normal: + default: + return ASTCENC_PRE_MEDIUM; + } + } + + IImageObjectPtr ASTCCompressor::CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, const CompressOption* compressOption) const + { + //validate input + EPixelFormat fmtSrc = srcImage->GetPixelFormat(); + + //src format need to be uncompressed and dst format need to compressed. + if (!IsUncompressedPixelFormatSupported(fmtSrc) || !IsCompressedPixelFormatSupported(fmtDst)) + { + return nullptr; + } + + astcenc_swizzle swizzle {ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, compressOption->discardAlpha? ASTCENC_SWZ_1:ASTCENC_SWZ_A}; + AZ::u32 flags = 0; + if (srcImage->HasImageFlags(EIF_RenormalizedTexture)) + { + ImageToProcess imageToProcess(srcImage); + imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8); + srcImage = imageToProcess.Get(); + fmtSrc = srcImage->GetPixelFormat(); + + flags = ASTCENC_FLG_MAP_NORMAL; + swizzle = astcenc_swizzle{ ASTCENC_SWZ_R, ASTCENC_SWZ_R, ASTCENC_SWZ_R, ASTCENC_SWZ_G }; + } + + auto dstFormatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(fmtDst); + + const float quality = GetAstcCompressQuality(compressOption->compressQuality); + const astcenc_profile profile = GetAstcProfile(srcImage->HasImageFlags(EIF_SRGBRead), fmtSrc); + + astcenc_config config; + astcenc_error status; + status = astcenc_config_init(profile, dstFormatInfo->blockWidth, dstFormatInfo->blockHeight, 1, quality, flags, &config); + + //ASTCENC_FLG_MAP_NORMAL + AZ_Assert( status == ASTCENC_SUCCESS, "ERROR: Codec config init failed: %s\n", astcenc_get_error_string(status)); + + // Create a context based on the configuration + astcenc_context* context; + AZ::u32 blockCount = ((srcImage->GetWidth(0)+ dstFormatInfo->blockWidth-1)/dstFormatInfo->blockWidth) * ((srcImage->GetHeight(0) + dstFormatInfo->blockHeight-1)/dstFormatInfo->blockHeight); + AZ::u32 threadCount = AZStd::min(AZStd::thread::hardware_concurrency(), blockCount); + status = astcenc_context_alloc(&config, threadCount, &context); + AZ_Assert( status == ASTCENC_SUCCESS, "ERROR: Codec context alloc failed: %s\n", astcenc_get_error_string(status)); + + const astcenc_type dataType =GetAstcDataType(fmtSrc); + + // Compress the image for each mips + IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst)); + const AZ::u32 dstMips = dstImage->GetMipCount(); + for (AZ::u32 mip = 0; mip < dstMips; ++mip) + { + astcenc_image image; + image.dim_x = srcImage->GetWidth(mip); + image.dim_y = srcImage->GetHeight(mip); + image.dim_z = 1; + image.data_type = dataType; + + AZ::u8* srcMem; + AZ::u32 srcPitch; + srcImage->GetImagePointer(mip, srcMem, srcPitch); + image.data = reinterpret_cast(&srcMem); + + AZ::u8* dstMem; + AZ::u32 dstPitch; + dstImage->GetImagePointer(mip, dstMem, dstPitch); + AZ::u32 dataSize = dstImage->GetMipBufSize(mip); + + // Create jobs for each compression thread + auto completionJob = aznew AZ::JobCompletion(); + for (AZ::u32 threadIdx = 0; threadIdx < threadCount; threadIdx++) + { + const auto jobLambda = [&status, context, &image, &swizzle, dstMem, dataSize, threadIdx]() + { + astcenc_error error = astcenc_compress_image(context, &image, &swizzle, dstMem, dataSize, threadIdx); + if (error != ASTCENC_SUCCESS) + { + status = error; + } + }; + + AZ::Job* simulationJob = AZ::CreateJobFunction(AZStd::move(jobLambda), true, nullptr); //auto-deletes + simulationJob->SetDependent(completionJob); + simulationJob->Start(); + } + + if (completionJob) + { + completionJob->StartAndWaitForCompletion(); + delete completionJob; + completionJob = nullptr; + } + + if (status != ASTCENC_SUCCESS) + { + AZ_Error("Image Processing", false, "ASTCCompressor::CompressImage failed: %s\n", astcenc_get_error_string(status)); + astcenc_context_free(context); + return nullptr; + } + + // Need to reset to compress next mip + astcenc_compress_reset(context); + } + astcenc_context_free(context); + + return dstImage; + } + + IImageObjectPtr ASTCCompressor::DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const + { + //validate input + EPixelFormat fmtSrc = srcImage->GetPixelFormat(); //compressed + auto srcFormatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(fmtSrc); + + if (!IsCompressedPixelFormatSupported(fmtSrc) || !IsUncompressedPixelFormatSupported(fmtDst)) + { + return nullptr; + } + + const float quality = ASTCENC_PRE_MEDIUM; + astcenc_swizzle swizzle {ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A}; + if (srcImage->HasImageFlags(EIF_RenormalizedTexture)) + { + swizzle = astcenc_swizzle{ASTCENC_SWZ_R, ASTCENC_SWZ_A, ASTCENC_SWZ_Z, ASTCENC_SWZ_1}; + } + + astcenc_config config; + astcenc_error status; + astcenc_profile profile = GetAstcProfile(srcImage->HasImageFlags(EIF_SRGBRead), fmtDst); + AZ::u32 flags = ASTCENC_FLG_DECOMPRESS_ONLY; + status = astcenc_config_init(profile, srcFormatInfo->blockWidth, srcFormatInfo->blockHeight, 1, quality, flags, &config); + + //ASTCENC_FLG_MAP_NORMAL + AZ_Assert( status == ASTCENC_SUCCESS, "astcenc_config_init failed: %s\n", astcenc_get_error_string(status)); + + // Create a context based on the configuration + const AZ::u32 threadCount = 1; // Decompress function doesn't support multiple threads + astcenc_context* context; + status = astcenc_context_alloc(&config, threadCount, &context); + AZ_Assert( status == ASTCENC_SUCCESS, "astcenc_context_alloc failed: %s\n", astcenc_get_error_string(status)); + + astcenc_type dataType =GetAstcDataType(fmtDst); + + // Decompress the image for each mips + IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst)); + const AZ::u32 dstMips = dstImage->GetMipCount(); + for (AZ::u32 mip = 0; mip < dstMips; ++mip) + { + astcenc_image image; + image.dim_x = srcImage->GetWidth(mip); + image.dim_y = srcImage->GetHeight(mip); + image.dim_z = 1; + image.data_type = dataType; + + AZ::u8* srcMem; + AZ::u32 srcPitch; + srcImage->GetImagePointer(mip, srcMem, srcPitch); + AZ::u32 srcDataSize = srcImage->GetMipBufSize(mip); + + AZ::u8* dstMem; + AZ::u32 dstPitch; + dstImage->GetImagePointer(mip, dstMem, dstPitch); + image.data = reinterpret_cast(&dstMem); + + status = astcenc_decompress_image(context, srcMem, srcDataSize, &image, &swizzle, 0); + + if (status != ASTCENC_SUCCESS) + { + AZ_Error("Image Processing", false, "ASTCCompressor::DecompressImage failed: %s\n", astcenc_get_error_string(status)); + astcenc_context_free(context); + return nullptr; + } + } + + astcenc_context_free(context); + + return dstImage; + } +} //namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.h new file mode 100644 index 0000000000..cf191c7072 --- /dev/null +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ASTCCompressor.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +namespace ImageProcessingAtom +{ + class ASTCCompressor + : public ICompressor + { + public: + static bool IsCompressedPixelFormatSupported(EPixelFormat fmt); + static bool IsUncompressedPixelFormatSupported(EPixelFormat fmt); + static bool DoesSupportDecompress(EPixelFormat fmtDst); + + IImageObjectPtr CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, const CompressOption* compressOption) const override; + IImageObjectPtr DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const override; + + EPixelFormat GetSuggestedUncompressedFormat(EPixelFormat compressedfmt, EPixelFormat uncompressedfmt) const override; + ColorSpace GetSupportedColorSpace(EPixelFormat compressFormat) const final; + const char* GetName() const final; + }; +} // namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp index 9013bff1db..1dd18faaf3 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -15,11 +16,8 @@ namespace ImageProcessingAtom { - ICompressorPtr ICompressor::FindCompressor(EPixelFormat fmt, [[maybe_unused]] ColorSpace colorSpace, bool isCompressing) + ICompressorPtr ICompressor::FindCompressor(EPixelFormat fmt, ColorSpace colorSpace, bool isCompressing) { - // The ISPC texture compressor is able to compress BC1, BC3, BC6H and BC7 formats, and all of the ASTC formats. - // Note: The ISPC texture compressor is only able to compress images that are a multiple of the compressed format's blocksize. - // Another limitation is that the compressor requires LDR source images to be in sRGB colorspace. if (ISPCCompressor::IsCompressedPixelFormatSupported(fmt)) { if ((isCompressing && ISPCCompressor::IsSourceColorSpaceSupported(colorSpace, fmt)) || (!isCompressing && ISPCCompressor::DoesSupportDecompress(fmt))) @@ -35,6 +33,14 @@ namespace ImageProcessingAtom return ICompressorPtr(new CTSquisher()); } } + + if (ASTCCompressor::IsCompressedPixelFormatSupported(fmt)) + { + if (isCompressing || (!isCompressing && ASTCCompressor::DoesSupportDecompress(fmt))) + { + return ICompressorPtr(new ASTCCompressor()); + } + } // Both ETC2Compressor and PVRTCCompressor can process ETC formats // According to Mobile team, Etc2Com is faster than PVRTexLib, so we check with ETC2Compressor before PVRTCCompressor diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h index dff71e59db..6920ae0cc1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.h @@ -38,8 +38,7 @@ namespace ImageProcessingAtom EQuality compressQuality = eQuality_Normal; //required for CTSquisher AZ::Vector3 rgbWeight = AZ::Vector3(0.3333f, 0.3334f, 0.3333f); - //required for ISPC texture compressor - bool ispcDiscardAlpha = false; + bool discardAlpha = false; }; public: diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ISPCTextureCompressor.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ISPCTextureCompressor.cpp index 5e96c7274d..b1b41d98bc 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ISPCTextureCompressor.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ISPCTextureCompressor.cpp @@ -57,6 +57,12 @@ namespace ImageProcessingAtom bool ISPCCompressor::IsCompressedPixelFormatSupported(EPixelFormat fmt) { + // Even though the ISPC compressor support ASTC formats. But it has restrictions + // 1. Only supports LDR color profile + // 2. Only supports a subset of 2D block sizes + // Also it has overall lower quality compare to astc-encoder + // So we won't add ASTC as part of supported formats here + // Ref: https://solidpixel.github.io/2020/03/02/astc-compared.html switch (fmt) { case ePixelFormat_BC3: @@ -152,7 +158,7 @@ namespace ImageProcessingAtom if (compressOption) { quality = compressOption->compressQuality; - discardAlpha = compressOption->ispcDiscardAlpha; + discardAlpha = compressOption->discardAlpha; } // Get the compression profile @@ -230,24 +236,12 @@ namespace ImageProcessingAtom } break; default: - if (IsASTCFormat(destinationFormat)) - { - const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo(destinationFormat); - astc_enc_settings settings = {}; - - const auto setProfile = compressionProfile->GetASTC(discardAlpha); - setProfile(&settings, info->blockWidth, info->blockHeight); - - // Compress with ASTC - CompressBlocksASTC(&sourceSurface, destinationImageData, &settings); - } - else - { - // No valid pixel format - AZ_Assert(false, "Unhandled pixel format %d", destinationFormat); - return nullptr; - } - break; + { + // No valid pixel format + AZ_Assert(false, "Unhandled pixel format %d", destinationFormat); + return nullptr; + } + break; } } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp index 7c899e4ad2..f3a630e8c1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp @@ -19,7 +19,7 @@ namespace ImageProcessingAtom { - // Note: PVRTexLib supports ASTC formats, ETC formats, PVRTC formats and BC formats + // Note: PVRTexLib supports ETC formats, PVRTC formats and BC formats // We haven't tested the performace to compress BC formats compare to CTSquisher // For PVRTC formats, we only added PVRTC 1 support for now // The compression for ePVRTPF_EAC_R11 and ePVRTPF_EAC_RG11 are very slow. It takes 7 and 14 minutes for a 2048x2048 texture. @@ -27,34 +27,6 @@ namespace ImageProcessingAtom { switch (fmt) { - case ePixelFormat_ASTC_4x4: - return ePVRTPF_ASTC_4x4; - case ePixelFormat_ASTC_5x4: - return ePVRTPF_ASTC_5x4; - case ePixelFormat_ASTC_5x5: - return ePVRTPF_ASTC_5x5; - case ePixelFormat_ASTC_6x5: - return ePVRTPF_ASTC_6x5; - case ePixelFormat_ASTC_6x6: - return ePVRTPF_ASTC_6x6; - case ePixelFormat_ASTC_8x5: - return ePVRTPF_ASTC_8x5; - case ePixelFormat_ASTC_8x6: - return ePVRTPF_ASTC_8x6; - case ePixelFormat_ASTC_8x8: - return ePVRTPF_ASTC_8x8; - case ePixelFormat_ASTC_10x5: - return ePVRTPF_ASTC_10x5; - case ePixelFormat_ASTC_10x6: - return ePVRTPF_ASTC_10x6; - case ePixelFormat_ASTC_10x8: - return ePVRTPF_ASTC_10x8; - case ePixelFormat_ASTC_10x10: - return ePVRTPF_ASTC_10x10; - case ePixelFormat_ASTC_12x10: - return ePVRTPF_ASTC_12x10; - case ePixelFormat_ASTC_12x12: - return ePVRTPF_ASTC_12x12; case ePixelFormat_PVRTC2: return ePVRTPF_PVRTCI_2bpp_RGBA; case ePixelFormat_PVRTC4: @@ -156,26 +128,7 @@ namespace ImageProcessingAtom internalQuality = pvrtexture::eETCSlow; } } - else if (IsASTCFormat(fmtDst)) - { - if (quality == eQuality_Preview) - { - internalQuality = pvrtexture::eASTCVeryFast; - } - else if (quality == eQuality_Fast) - { - internalQuality = pvrtexture::eASTCFast; - } - else if (quality == eQuality_Normal) - { - internalQuality = pvrtexture::eASTCMedium; - } - else - { - internalQuality = pvrtexture::eASTCThorough; - } - } - else + else { if (quality == eQuality_Preview) { @@ -252,7 +205,7 @@ namespace ImageProcessingAtom if (!isSuccess) { - AZ_Error("Image Processing", false, "Failed to compress image with PVRTexLib. You may not have astcenc.exe for compressing ASTC formates"); + AZ_Error("Image Processing", false, "Failed to compress image with PVRTexLib."); return nullptr; } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp index 9b41645280..5995146c59 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp @@ -117,6 +117,11 @@ namespace ImageProcessingAtom } } + const ImageConvertProcessDescriptor* ImageConvertProcess::GetInputDesc() const + { + return m_input.get(); + } + ImageConvertProcess::ImageConvertProcess(AZStd::unique_ptr&& descriptor) : m_image(nullptr) , m_progressStep(0) @@ -554,12 +559,6 @@ namespace ImageProcessingAtom // pixel format conversion bool ImageConvertProcess::ConvertPixelformat() { - //For ASTC compression we need to clear out the alpha to get accurate rgb compression. - if(m_alphaImage && IsASTCFormat(m_input->m_presetSetting.m_pixelFormat)) - { - m_image->Get()->Swizzle("rgb1"); - } - //set up compress option ICompressor::EQuality quality; if (m_input->m_isPreview) @@ -574,7 +573,14 @@ namespace ImageProcessingAtom // set the compression options m_image->GetCompressOption().compressQuality = quality; m_image->GetCompressOption().rgbWeight = m_input->m_presetSetting.GetColorWeight(); - m_image->GetCompressOption().ispcDiscardAlpha = m_input->m_presetSetting.m_discardAlpha; + m_image->GetCompressOption().discardAlpha = m_input->m_presetSetting.m_discardAlpha; + + //For ASTC compression we need to clear out the alpha to get accurate rgb compression. + if(m_alphaImage && IsASTCFormat(m_input->m_presetSetting.m_pixelFormat)) + { + m_image->GetCompressOption().discardAlpha = true; + } + m_image->ConvertFormat(m_input->m_presetSetting.m_pixelFormat); return true; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h index 190e68ca31..6ab866ee09 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h @@ -122,6 +122,8 @@ namespace ImageProcessingAtom // Get output JobProducts and append them to the outProducts vector. void GetAppendOutputProducts(AZStd::vector& outProducts); + const ImageConvertProcessDescriptor* GetInputDesc() const; + private: //input image and settings AZStd::shared_ptr m_input; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index 0656fb4e46..c4240306c4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -12,8 +12,12 @@ #include +#include + #include #include +#include +#include #include #include #include @@ -123,6 +127,9 @@ namespace UnitTest AZStd::string m_outputRootFolder; AZStd::string m_outputFolder; + AZStd::unique_ptr m_jobManager; + AZStd::unique_ptr m_jobContext; + void SetUp() override { AllocatorsBase::SetupAllocator(); @@ -159,6 +166,27 @@ namespace UnitTest m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); BuilderPluginComponent::Reflect(m_jsonRegistrationContext.get()); + // Setup job context for job system + JobManagerDesc jobManagerDesc; + JobManagerThreadDesc threadDesc; +#if AZ_TRAIT_SET_JOB_PROCESSOR_ID + threadDesc.m_cpuId = 0; // Don't set processors IDs on windows +#endif + + uint32_t numWorkerThreads = AZStd::thread::hardware_concurrency(); + + for (unsigned int i = 0; i < numWorkerThreads; ++i) + { + jobManagerDesc.m_workerThreads.push_back(threadDesc); +#if AZ_TRAIT_SET_JOB_PROCESSOR_ID + threadDesc.m_cpuId++; +#endif + } + + m_jobManager = AZStd::make_unique(jobManagerDesc); + m_jobContext = AZStd::make_unique(*m_jobManager); + JobContext::SetGlobalContext(m_jobContext.get()); + // Startup default local FileIO (hits OSAllocator) if not already setup. if (AZ::IO::FileIOBase::GetInstance() == nullptr) { @@ -192,6 +220,10 @@ namespace UnitTest delete AZ::IO::FileIOBase::GetInstance(); AZ::IO::FileIOBase::SetInstance(nullptr); + JobContext::SetGlobalContext(nullptr); + m_jobContext = nullptr; + m_jobManager = nullptr; + m_jsonRegistrationContext->EnableRemoveReflection(); m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); BuilderPluginComponent::Reflect(m_jsonRegistrationContext.get()); @@ -223,7 +255,7 @@ namespace UnitTest Image_512X288_RGB8_Tga, Image_1024X1024_RGB8_Tif, Image_UpperCase_Tga, - Image_512x512_Normal_Tga, // QImage doesn't support loading this file. + Image_1024x1024_normal_tiff, Image_128x128_Transparent_Tga, Image_237x177_RGB_Jpg, Image_GreyScale_Png, @@ -251,7 +283,7 @@ namespace UnitTest m_imagFileNameMap[Image_512X288_RGB8_Tga] = m_testFileFolder + "512x288_24bit.tga"; m_imagFileNameMap[Image_1024X1024_RGB8_Tif] = m_testFileFolder + "1024x1024_24bit.tif"; m_imagFileNameMap[Image_UpperCase_Tga] = m_testFileFolder + "uppercase.TGA"; - m_imagFileNameMap[Image_512x512_Normal_Tga] = m_testFileFolder + "512x512_RGB_N.tga"; + m_imagFileNameMap[Image_1024x1024_normal_tiff] = m_testFileFolder + "1024x1024_normal.tiff"; m_imagFileNameMap[Image_128x128_Transparent_Tga] = m_testFileFolder + "128x128_RGBA8.tga"; m_imagFileNameMap[Image_237x177_RGB_Jpg] = m_testFileFolder + "237x177_RGB.jpg"; m_imagFileNameMap[Image_GreyScale_Png] = m_testFileFolder + "greyscale.png"; @@ -801,8 +833,7 @@ namespace UnitTest auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); if (formatInfo->bCompressed) { - // exclude astc formats until we add astc compressor to all platforms - // exclude pvrtc formats (deprecating) + // skip ASTC formats which are tested in TestConvertASTCCompressor if (!IsASTCFormat(pixelFormat) && pixelFormat != ePixelFormat_PVRTC2 && pixelFormat != ePixelFormat_PVRTC4 && !IsETCFormat(pixelFormat)) // skip ETC since it's very slow @@ -830,32 +861,121 @@ namespace UnitTest continue; } - [[maybe_unused]] auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); - imageToProcess.Set(srcImage); - imageToProcess.ConvertFormat(pixelFormat); + auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat); + ColorSpace sourceColorSpace = srcImage->HasImageFlags(EIF_SRGBRead) ? ColorSpace::sRGB : ColorSpace::linear; + ICompressorPtr compressor = ICompressor::FindCompressor(pixelFormat, sourceColorSpace, true); - if (!imageToProcess.Get()) + if (!compressor) { AZ_Warning("test", false, "unsupported format: %s", formatInfo->szName); continue; } + + imageToProcess.Set(srcImage); + imageToProcess.ConvertFormat(pixelFormat); + ASSERT_TRUE(imageToProcess.Get()); ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == pixelFormat); - // Get compressor name - ColorSpace sourceColorSpace = srcImage->HasImageFlags(EIF_SRGBRead) ? ColorSpace::sRGB : ColorSpace::linear; - ICompressorPtr compressor = ICompressor::FindCompressor(pixelFormat, sourceColorSpace, true); + //convert back to an uncompressed format and expect it will be successful + imageToProcess.ConvertFormat(srcImage->GetPixelFormat()); + ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == srcImage->GetPixelFormat()); - //save the image to a file so we can check the visual result + // Save the image to a file so we can check the visual result AZStd::string outputName = AZStd::string::format("%s_%s", imageName.c_str(), compressor->GetName()); SaveImageToFile(imageToProcess.Get(), outputName, 1); + } + } + } + + TEST_F(ImageProcessingTest, Test_ConvertAllAstc_Success) + { + // Compress/Decompress to all astc formats (LDR) + auto imageIdx = Image_237x177_RGB_Jpg; + IImageObjectPtr srcImage = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[imageIdx])); + QFileInfo fi(m_imagFileNameMap[imageIdx].c_str()); + AZStd::string imageName = fi.baseName().toUtf8().constData(); + for (uint32 i = 0; i < ePixelFormat_Count; i++) + { + EPixelFormat pixelFormat = (EPixelFormat)i; + if (IsASTCFormat(pixelFormat)) + { + ImageToProcess imageToProcess(srcImage); + imageToProcess.ConvertFormat(pixelFormat); - //convert back to an uncompressed format and expect it will be successful - imageToProcess.ConvertFormat(ePixelFormat_R8G8B8A8); - ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == ePixelFormat_R8G8B8A8); + ASSERT_TRUE(imageToProcess.Get()); + ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == pixelFormat); + ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) == srcImage->GetWidth(0)); + ASSERT_TRUE(imageToProcess.Get()->GetHeight(0) == srcImage->GetHeight(0)); + + // convert back to an uncompressed format and expect it will be successful + imageToProcess.ConvertFormat(srcImage->GetPixelFormat()); + ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == srcImage->GetPixelFormat()); + + // save the image to a file so we can check the visual result + AZStd::string outputName = AZStd::string::format("ASTC_%s", imageName.c_str()); + SaveImageToFile(imageToProcess.Get(), outputName, 1); } } } + + TEST_F(ImageProcessingTest, Test_ConvertHdrToAstc_Success) + { + // Compress/Decompress HDR + auto imageIdx = Image_defaultprobe_cm_1536x256_64bits_tif; + IImageObjectPtr srcImage = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[imageIdx])); + + EPixelFormat dstFormat = ePixelFormat_ASTC_4x4; + ImageToProcess imageToProcess(srcImage); + imageToProcess.ConvertFormat(ePixelFormat_ASTC_4x4); + + ASSERT_TRUE(imageToProcess.Get()); + ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == dstFormat); + ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) == srcImage->GetWidth(0)); + ASSERT_TRUE(imageToProcess.Get()->GetHeight(0) == srcImage->GetHeight(0)); + + //convert back to an uncompressed format and expect it will be successful + imageToProcess.ConvertFormat(srcImage->GetPixelFormat()); + ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == srcImage->GetPixelFormat()); + + //save the image to a file so we can check the visual result + SaveImageToFile(imageToProcess.Get(), "ASTC_HDR", 1); + } + + TEST_F(ImageProcessingTest, Test_AstcNormalPreset_Success) + { + // Normal.preset which uses ASTC as output format + // This test compress a normal texture and its mipmaps + + auto outcome = BuilderSettingManager::Instance()->LoadConfigFromFolder(m_defaultSettingFolder); + ASSERT_TRUE(outcome.IsSuccess()); + + AZStd::string inputFile; + AZStd::vector outProducts; + + inputFile = m_imagFileNameMap[Image_1024x1024_normal_tiff]; + IImageObjectPtr srcImage = IImageObjectPtr(LoadImageFromFile(inputFile)); + + ImageConvertProcess* process = CreateImageConvertProcess(inputFile, m_outputFolder, "ios", outProducts, m_context.get()); + + const PresetSettings* preset = &process->GetInputDesc()->m_presetSetting; + + if (process != nullptr) + { + process->ProcessAll(); + + //get process result + ASSERT_TRUE(process->IsSucceed()); + auto outputImage = process->GetOutputImage(); + ASSERT_TRUE(outputImage->GetPixelFormat() == preset->m_pixelFormat); + ASSERT_TRUE(outputImage->GetWidth(0) == srcImage->GetWidth(0)); + ASSERT_TRUE(outputImage->GetHeight(0) == srcImage->GetHeight(0)); + + SaveImageToFile(outputImage, "ASTC_Normal", 10); + + delete process; + } + } TEST_F(ImageProcessingTest, DISABLED_TestImageFilter) { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_normal.tiff b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_normal.tiff new file mode 100644 index 0000000000..8120514ddc --- /dev/null +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_normal.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:120aaf43057b07fb3c784264eb48b899cc612f30917d316fe843bb839220dc22 +size 203062 diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/512x512_RGB_N.tga b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/512x512_RGB_N.tga deleted file mode 100644 index d47f00912a..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/512x512_RGB_N.tga +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:646a9a9035cc3f4dfd57babc0055710d2f5bb8aee0a792f2b65d69b4fd6a94b3 -size 786450 diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake index 55ccdf1d89..ba9e9f29b7 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake @@ -114,6 +114,8 @@ set(FILES ../External/CubeMapGen/CImageSurface.cpp ../External/CubeMapGen/CImageSurface.h ../External/CubeMapGen/VectorMacros.h + Source/Compressors/ASTCCompressor.cpp + Source/Compressors/ASTCCompressor.h Source/Compressors/Compressor.h Source/Compressors/Compressor.cpp Source/Compressors/CTSquisher.h diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 429665f04a..816ef6db30 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -9,7 +9,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) -ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) @@ -44,5 +43,6 @@ ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-linux ly_associate_package(PACKAGE_NAME azslc-1.7.23-rev2-linux TARGETS azslc PACKAGE_HASH 1ba84d8321a566d35a1e9aa7400211ba8e6d1c11c08e4be3c93e6e74b8f7aef1) ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-linux TARGETS zlib PACKAGE_HASH 16f3b9e11cda525efb62144f354c1cfc30a5def9eff020dbe49cb00ee7d8234f) ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-linux TARGETS squish-ccr PACKAGE_HASH 85fecafbddc6a41a27c5f59ed4a5dfb123a94cb4666782cf26e63c0a4724c530) +ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev1-linux TARGETS astc-encoder PACKAGE_HASH 2ba97a06474d609945f0ab4419af1f6bbffdd294ca6b869f5fcebec75c573c0f) ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-linux TARGETS ISPCTexComp PACKAGE_HASH 065fd12abe4247dde247330313763cf816c3375c221da030bdec35024947f259) ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-linux TARGETS lz4 PACKAGE_HASH 5de3dbd3e2a3537c6555d759b3c5bb98e5456cf85c74ff6d046f809b7087290d) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 4900a9d77e..58cafdd4b8 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -9,7 +9,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) -ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) @@ -42,6 +41,7 @@ ly_associate_package(PACKAGE_NAME qt-5.15.2-rev5-mac ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac TARGETS libsamplerate PACKAGE_HASH b912af40c0ac197af9c43d85004395ba92a6a859a24b7eacd920fed5854a97fe) ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-mac TARGETS zlib PACKAGE_HASH 21714e8a6de4f2523ee92a7f52d51fbee29c5f37ced334e00dc3c029115b472e) ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-mac TARGETS squish-ccr PACKAGE_HASH 155bfbfa17c19a9cd2ef025de14c5db598f4290045d5b0d83ab58cb345089a77) +ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev1-mac TARGETS astc-encoder PACKAGE_HASH 96f6ea8c3e45ec7fe525230c7c53ca665c8300d8e28456cc19bb3159ce6f8dcc) ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-mac TARGETS ISPCTexComp PACKAGE_HASH 8a4e93277b8face6ea2fd57c6d017bdb55643ed3d6387110bc5f6b3b884dd169) ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-mac TARGETS lz4 PACKAGE_HASH 891ff630bf34f7ab1d8eaee2ea0a8f1fca89dbdc63fca41ee592703dd488a73b) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 3855b7d712..d02fefc0e9 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -9,7 +9,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) -ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) @@ -49,5 +48,6 @@ ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-windows ly_associate_package(PACKAGE_NAME Crashpad-0.8.0-rev1-windows TARGETS Crashpad PACKAGE_HASH d162aa3070147bc0130a44caab02c5fe58606910252caf7f90472bd48d4e31e2) ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-windows TARGETS zlib PACKAGE_HASH 9afab1d67641ed8bef2fb38fc53942da47f2ab339d9e77d3d20704a48af2da0b) ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-windows TARGETS squish-ccr PACKAGE_HASH 5c3d9fa491e488ccaf802304ad23b932268a2b2846e383f088779962af2bfa84) +ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev1-windows TARGETS astc-encoder PACKAGE_HASH 3addc6fc1a7eb0d6b7f3d530e962af967e6d92b3825ef485da243346357cf78e) ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-windows TARGETS ISPCTexComp PACKAGE_HASH b6fa6ea28a2808a9a5524c72c37789c525925e435770f2d94eb2d387360fa2d0) ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-windows TARGETS lz4 PACKAGE_HASH 4ea457b833cd8cfaf8e8e06ed6df601d3e6783b606bdbc44a677f77e19e0db16) From dc050d4acd45f4764364e098c34547fb70867e56 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Fri, 17 Sep 2021 12:59:25 -0500 Subject: [PATCH 181/274] Terrain System bugfixes (#4180) * Remove the "TEST_SUPPORTED" traits. Terrain unit tests should be usable on all platforms, so they shouldn't need a platform-specific trait to enable/disable. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fix a few misc terrain bugs. * Change Activate/Deactivate to happen immediately instead of deferring. There were too many order-of-operation bugs caused by trying to defer this. * Added implementation for calculating normals. * Fixed bug where GetHeightSynchronous wasn't stopping at the highest-priority layer. * Added locks for SurfaceData bus to help ensure we lock our mutexes in the correct order and avoid deadlocks. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Add trivial TerrainSystem tests. Tests construction, Activate(), Deactivate(), and destruction. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Unified Terrain system calls on single bus. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added mock for TerrainDataNotificationBus listener. Also added unit tests to verify the listener, and added in missing notification events. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Removed extra Sampler class. Fixed up APIs to correctly pass Sampler and terrainExistsPtr around. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Switched MockTerrainSystem to be proper gmock. This makes it for flexible to use and easier to reuse from other test environments. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fix settings bug caused by bad order of operations that occurred when the methods moved to a different bus. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Eliminate extra EBus by simplifying area initialization. Previously, there was a back-and-forth ebus signal used for the terrain system to find any terrain spawners that were created prior to the terrain system activation. Now it uses the more simple technique of just grabbing all the spawners that are currently hooked up to the spawner ebus. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Switch to NiceMock so that "uninteresting" mock calls get ignored. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Addressed PR feedback. Filled in terrainExistsPtr at the end, and added it to GetNormal as well. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed shader height calculation. It was off by half a pixel, and it was interpolating, both of which were wrong. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Create initial LmbrCentral mocks that other Gems can use. To help improve mock maintenance over time, this creates mocks in the same Gem as the systems being mocked, instead of the other Gems that need to use mocked systems during testing. This way, the mocks should more easily stay in sync with the interface that they mock out. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Null-guard any uses of Atom to make the class easier to unit test. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Add more mocked terrain services Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Moved Terrain mocks to publicly-available Mocks directory. Also added more unit tests. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Change debug code to use EXACT instead of BILINEAR height sampling, because it's specifically using the terrain grid. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added support for the sampler filters. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fix bad merge. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Add unit test to verify terrain layers define terrain regions. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Moved the AABB component mock into a private terrain header, since it's a specialized mock just for the terrain tests. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Moved sampler and normal calculations into TerrainSystem so that they can work across multiple adjacent areas. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Missed a couple of unit test changes. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Removed normal query as well, that needs a seprate unit test. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Removed unused variable that was only caught in Linux/Android builds. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Addressed PR feedback Made the parameter names consistently listed in MockShapes.h. Added comments to TerrainHeightGradientListComponent explaining why terrainExists is always true when a gradient exists. Also fixed a bug where terrainExists should technically be *false* if no gradient exists. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added more descriptive comments and names for ClampPosition. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- Gems/LmbrCentral/Code/CMakeLists.txt | 11 ++ .../Code/Mocks/LmbrCentral/Shape/MockShapes.h | 60 +++++++ .../Code/Tests/LmbrCentralTest.cpp | 3 + .../Code/lmbrcentral_mocks_files.cmake | 11 ++ Gems/Terrain/Code/CMakeLists.txt | 13 ++ .../Terrain/MockTerrain.h} | 86 ++++----- .../TerrainHeightGradientListComponent.cpp | 51 ++---- .../TerrainHeightGradientListComponent.h | 13 +- .../TerrainWorldDebuggerComponent.cpp | 6 +- .../Source/TerrainSystem/TerrainSystem.cpp | 166 ++++++++++++------ .../Code/Source/TerrainSystem/TerrainSystem.h | 5 +- .../Source/TerrainSystem/TerrainSystemBus.h | 21 +-- Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp | 11 +- .../Tests/MockAxisAlignedBoxShapeComponent.h | 45 +++++ Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 158 +++++++++++++++-- Gems/Terrain/Code/terrain_mocks_files.cmake | 11 ++ Gems/Terrain/Code/terrain_tests_files.cmake | 2 +- 17 files changed, 477 insertions(+), 196 deletions(-) create mode 100644 Gems/LmbrCentral/Code/Mocks/LmbrCentral/Shape/MockShapes.h create mode 100644 Gems/LmbrCentral/Code/lmbrcentral_mocks_files.cmake rename Gems/Terrain/Code/{Tests/TerrainMocks.h => Mocks/Terrain/MockTerrain.h} (57%) create mode 100644 Gems/Terrain/Code/Tests/MockAxisAlignedBoxShapeComponent.h create mode 100644 Gems/Terrain/Code/terrain_mocks_files.cmake diff --git a/Gems/LmbrCentral/Code/CMakeLists.txt b/Gems/LmbrCentral/Code/CMakeLists.txt index 00176ae2c2..b047a9f65e 100644 --- a/Gems/LmbrCentral/Code/CMakeLists.txt +++ b/Gems/LmbrCentral/Code/CMakeLists.txt @@ -114,6 +114,16 @@ endif() # Tests ################################################################################ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + ly_add_target( + NAME LmbrCentral.Mocks HEADERONLY + NAMESPACE Gem + FILES_CMAKE + lmbrcentral_mocks_files.cmake + INCLUDE_DIRECTORIES + INTERFACE + Mocks + ) + ly_add_target( NAME LmbrCentral.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem @@ -131,6 +141,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) Legacy::CryCommon AZ::AzFramework Gem::LmbrCentral.Static + Gem::LmbrCentral.Mocks ) ly_add_googletest( NAME Gem::LmbrCentral.Tests diff --git a/Gems/LmbrCentral/Code/Mocks/LmbrCentral/Shape/MockShapes.h b/Gems/LmbrCentral/Code/Mocks/LmbrCentral/Shape/MockShapes.h new file mode 100644 index 0000000000..20be74dd90 --- /dev/null +++ b/Gems/LmbrCentral/Code/Mocks/LmbrCentral/Shape/MockShapes.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include + +#include +#include +#include + +namespace UnitTest +{ + class MockBoxShapeComponentRequests + : public LmbrCentral::BoxShapeComponentRequestsBus::Handler + { + public: + MockBoxShapeComponentRequests(AZ::EntityId entityId) + { + LmbrCentral::BoxShapeComponentRequestsBus::Handler::BusConnect(entityId); + } + + ~MockBoxShapeComponentRequests() + { + LmbrCentral::BoxShapeComponentRequestsBus::Handler::BusDisconnect(); + } + + MOCK_METHOD0(GetBoxConfiguration, LmbrCentral::BoxShapeConfig()); + MOCK_METHOD0(GetBoxDimensions, AZ::Vector3()); + MOCK_METHOD1(SetBoxDimensions, void(const AZ::Vector3& newDimensions)); + }; + + class MockShapeComponentRequests + : public LmbrCentral::ShapeComponentRequestsBus::Handler + { + public: + MockShapeComponentRequests(AZ::EntityId entityId) + { + LmbrCentral::ShapeComponentRequestsBus::Handler::BusConnect(entityId); + } + + ~MockShapeComponentRequests() + { + LmbrCentral::ShapeComponentRequestsBus::Handler::BusDisconnect(); + } + + MOCK_METHOD0(GetShapeType, AZ::Crc32()); + MOCK_METHOD0(GetEncompassingAabb, AZ::Aabb()); + MOCK_METHOD2(GetTransformAndLocalBounds, void(AZ::Transform& transform, AZ::Aabb& bounds)); + MOCK_METHOD1(IsPointInside, bool(const AZ::Vector3& point)); + MOCK_METHOD1(DistanceSquaredFromPoint, float(const AZ::Vector3& point)); + MOCK_METHOD1(GenerateRandomPointInside, AZ::Vector3(AZ::RandomDistributionType randomDistribution)); + MOCK_METHOD3(IntersectRay, bool(const AZ::Vector3& src, const AZ::Vector3& dir, float& distance)); + }; +} + diff --git a/Gems/LmbrCentral/Code/Tests/LmbrCentralTest.cpp b/Gems/LmbrCentral/Code/Tests/LmbrCentralTest.cpp index 40217ff9bc..f36978f22d 100644 --- a/Gems/LmbrCentral/Code/Tests/LmbrCentralTest.cpp +++ b/Gems/LmbrCentral/Code/Tests/LmbrCentralTest.cpp @@ -8,4 +8,7 @@ #include +// Include any public mocks here to ensure they get compiled as a part of the test project. +#include + AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); diff --git a/Gems/LmbrCentral/Code/lmbrcentral_mocks_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_mocks_files.cmake new file mode 100644 index 0000000000..c3a5cca3f8 --- /dev/null +++ b/Gems/LmbrCentral/Code/lmbrcentral_mocks_files.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Mocks/LmbrCentral/Shape/MockShapes.h +) diff --git a/Gems/Terrain/Code/CMakeLists.txt b/Gems/Terrain/Code/CMakeLists.txt index 0feacdaf71..fc07294dab 100644 --- a/Gems/Terrain/Code/CMakeLists.txt +++ b/Gems/Terrain/Code/CMakeLists.txt @@ -83,6 +83,15 @@ endif() ################################################################################ # See if globally, tests are supported if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + ly_add_target( + NAME Terrain.Mocks HEADERONLY + NAMESPACE Gem + FILES_CMAKE + terrain_mocks_files.cmake + INCLUDE_DIRECTORIES + INTERFACE + Mocks + ) ly_add_target( NAME Terrain.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem @@ -97,6 +106,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PRIVATE AZ::AzTest AZ::AzFramework + Gem::LmbrCentral.Mocks + Gem::Terrain.Mocks Gem::Terrain.Static ) @@ -120,6 +131,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzTest + Gem::LmbrCentral.Mocks + Gem::Terrain.Mocks Gem::Terrain.Editor ) diff --git a/Gems/Terrain/Code/Tests/TerrainMocks.h b/Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h similarity index 57% rename from Gems/Terrain/Code/Tests/TerrainMocks.h rename to Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h index 03a2eccf1d..ea0413be9a 100644 --- a/Gems/Terrain/Code/Tests/TerrainMocks.h +++ b/Gems/Terrain/Code/Mocks/Terrain/MockTerrain.h @@ -11,59 +11,9 @@ #include #include -#include namespace UnitTest { - static const AZ::Uuid BoxShapeComponentTypeId = "{5EDF4B9E-0D3D-40B8-8C91-5142BCFC30A6}"; - - class MockBoxShapeComponent - : public AZ::Component - { - public: - AZ_COMPONENT(MockBoxShapeComponent, BoxShapeComponentTypeId) - static void Reflect([[maybe_unused]] AZ::ReflectContext* context) - { - } - - void Activate() override - { - } - - void Deactivate() override - { - } - - bool ReadInConfig([[maybe_unused]] const AZ::ComponentConfig* baseConfig) override - { - return true; - } - - bool WriteOutConfig([[maybe_unused]] AZ::ComponentConfig* outBaseConfig) const override - { - return true; - } - - private: - static void GetProvidedServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe)); - provided.push_back(AZ_CRC("BoxShapeService", 0x946a0032)); - provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); - } - - static void GetIncompatibleServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - } - - static void GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) - { - } - - static void GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - } - }; class MockTerrainSystemService : private Terrain::TerrainSystemServiceRequestBus::Handler { @@ -106,4 +56,40 @@ namespace UnitTest MOCK_METHOD2(OnTerrainDataChanged, void(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask)); }; + class MockTerrainAreaHeightRequests : public Terrain::TerrainAreaHeightRequestBus::Handler + { + public: + MockTerrainAreaHeightRequests(AZ::EntityId entityId) + { + Terrain::TerrainAreaHeightRequestBus::Handler::BusConnect(entityId); + } + + ~MockTerrainAreaHeightRequests() + { + Terrain::TerrainAreaHeightRequestBus::Handler::BusDisconnect(); + } + + MOCK_METHOD3(GetHeight, void( + const AZ::Vector3& inPosition, + AZ::Vector3& outPosition, + bool& terrainExists)); + + }; + + class MockTerrainSpawnerRequests : public Terrain::TerrainSpawnerRequestBus::Handler + { + public: + MockTerrainSpawnerRequests(AZ::EntityId entityId) + { + Terrain::TerrainSpawnerRequestBus::Handler::BusConnect(entityId); + } + + ~MockTerrainSpawnerRequests() + { + Terrain::TerrainSpawnerRequestBus::Handler::BusDisconnect(); + } + + MOCK_METHOD2(GetPriority, void(AZ::u32& outLayer, AZ::u32& outPriority)); + MOCK_METHOD0(GetUseGroundPlane, bool()); + }; } diff --git a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp index 4d0cb6576d..4ea16018d1 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.cpp @@ -142,11 +142,15 @@ namespace Terrain return false; } - float TerrainHeightGradientListComponent::GetHeight(float x, float y) + void TerrainHeightGradientListComponent::GetHeight( + const AZ::Vector3& inPosition, + AZ::Vector3& outPosition, + bool& terrainExists) { float maxSample = 0.0f; + terrainExists = false; - GradientSignal::GradientSampleParams params(AZ::Vector3(x, y, 0.0f)); + GradientSignal::GradientSampleParams params(AZ::Vector3(inPosition.GetX(), inPosition.GetY(), 0.0f)); // Right now, when the list contains multiple entries, we will use the highest point from each gradient. // This is needed in part because gradients don't really have world bounds, so they exist everywhere but generally have a value @@ -155,49 +159,20 @@ namespace Terrain // make this list a prioritized list from top to bottom for any points that overlap. for (auto& gradientId : m_configuration.m_gradientEntities) { + // If gradients ever provide bounds, or if we add a value threshold in this component, it would be possible for terrain + // to *not* exist at a specific point. + terrainExists = true; + float sample = 0.0f; - GradientSignal::GradientRequestBus::EventResult(sample, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params); + GradientSignal::GradientRequestBus::EventResult( + sample, gradientId, &GradientSignal::GradientRequestBus::Events::GetValue, params); maxSample = AZ::GetMax(maxSample, sample); } const float height = AZ::Lerp(m_cachedShapeBounds.GetMin().GetZ(), m_cachedShapeBounds.GetMax().GetZ(), maxSample); - - return AZ::GetClamp(height, m_cachedMinWorldHeight, m_cachedMaxWorldHeight); - } - - void TerrainHeightGradientListComponent::GetHeight( - const AZ::Vector3& inPosition, - AZ::Vector3& outPosition, - [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) - { - const float height = GetHeight(inPosition.GetX(), inPosition.GetY()); - outPosition.SetZ(height); - } - - void TerrainHeightGradientListComponent::GetNormal( - const AZ::Vector3& inPosition, - AZ::Vector3& outNormal, - [[maybe_unused]] AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) - { - const float x = inPosition.GetX(); - const float y = inPosition.GetY(); - - if ((x >= m_cachedShapeBounds.GetMin().GetX()) && (x <= m_cachedShapeBounds.GetMax().GetX()) && - (y >= m_cachedShapeBounds.GetMin().GetY()) && (y <= m_cachedShapeBounds.GetMax().GetY())) - { - AZ::Vector2 fRange = (m_cachedHeightQueryResolution / 2.0f) + AZ::Vector2(0.05f); - - AZ::Vector3 v1(x - fRange.GetX(), y - fRange.GetY(), GetHeight(x - fRange.GetX(), y - fRange.GetY())); - AZ::Vector3 v2(x - fRange.GetX(), y + fRange.GetY(), GetHeight(x - fRange.GetX(), y + fRange.GetY())); - AZ::Vector3 v3(x + fRange.GetX(), y - fRange.GetY(), GetHeight(x + fRange.GetX(), y - fRange.GetY())); - AZ::Vector3 v4(x + fRange.GetX(), y + fRange.GetY(), GetHeight(x + fRange.GetX(), y + fRange.GetY())); - outNormal = (v3 - v2).Cross(v4 - v1).GetNormalized(); - } + outPosition.SetZ(AZ::GetClamp(height, m_cachedMinWorldHeight, m_cachedMaxWorldHeight)); } - void TerrainHeightGradientListComponent::OnCompositionChanged() { RefreshMinMaxHeights(); diff --git a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h index 509f003afa..6c3fd7b820 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainHeightGradientListComponent.h @@ -64,14 +64,7 @@ namespace Terrain TerrainHeightGradientListComponent() = default; ~TerrainHeightGradientListComponent() = default; - void GetHeight( - const AZ::Vector3& inPosition, - AZ::Vector3& outPosition, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) override; - void GetNormal( - const AZ::Vector3& inPosition, - AZ::Vector3& outNormal, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter) override; + void GetHeight(const AZ::Vector3& inPosition, AZ::Vector3& outPosition, bool& terrainExists) override; ////////////////////////////////////////////////////////////////////////// // AZ::Component interface implementation @@ -91,11 +84,7 @@ namespace Terrain private: TerrainHeightGradientListConfig m_configuration; - /////////////////////////////////////////// - void GetNormalSynchronous(float x, float y, AZ::Vector3& normal); - void RefreshMinMaxHeights(); - float GetHeight(float x, float y); float m_cachedMinWorldHeight{ 0.0f }; float m_cachedMaxWorldHeight{ 0.0f }; diff --git a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp index 89ffa6364f..7233d08281 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainWorldDebuggerComponent.cpp @@ -285,13 +285,13 @@ namespace Terrain AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( z00, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y, - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT, &terrainExists); + AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( z01, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x, y1, - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT, &terrainExists); + AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( z10, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats, x1, y, - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT, &terrainExists); + AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); sector.m_lineVertices.push_back(AZ::Vector3(x, y, z00)); sector.m_lineVertices.push_back(AZ::Vector3(x1, y, z10)); diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 674af376e4..5ec6af6f37 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -152,27 +152,69 @@ AZ::Vector2 TerrainSystem::GetTerrainHeightQueryResolution() const return m_currentSettings.m_heightQueryResolution; } +void TerrainSystem::ClampPosition(float x, float y, AZ::Vector2& outPosition, AZ::Vector2& normalizedDelta) const +{ + // Given an input position, clamp the values to our terrain grid, where it will always go to the terrain grid point + // at a lower value, whether positive or negative. Ex: 3.3 -> 3, -3.3 -> -4 + // Also, return the normalized delta as a value of [0-1) describing what fraction of a grid point the value moved. + + // Scale the position by the query resolution, so that integer values represent exact steps on the grid, + // and fractional values are the amount in-between each grid point, in the range [0-1). + AZ::Vector2 normalizedPosition = AZ::Vector2(x, y) / m_currentSettings.m_heightQueryResolution; + normalizedDelta = AZ::Vector2( + normalizedPosition.GetX() - floor(normalizedPosition.GetX()), normalizedPosition.GetY() - floor(normalizedPosition.GetY())); + + // Remove the fractional part, then scale back down into world space. + outPosition = (normalizedPosition - normalizedDelta) * m_currentSettings.m_heightQueryResolution; +} + float TerrainSystem::GetHeightSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { bool terrainExists = false; - - AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); - AZ::Vector3 outPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); + float height = m_currentSettings.m_worldBounds.GetMin().GetZ(); AZStd::shared_lock lock(m_areaMutex); - for (auto& [areaId, areaBounds] : m_registeredAreas) + switch (sampler) { - inPosition.SetZ(areaBounds.GetMin().GetZ()); - if (areaBounds.Contains(inPosition)) + // Get the value at the requested location, using the terrain grid to bilinear filter between sample grid points. + case AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR: { - Terrain::TerrainAreaHeightRequestBus::Event( - areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampler); + // pos0 contains one corner of our grid square, pos1 contains the opposite corner, and normalizedDelta is the fractional + // amount the position exists between those corners. + // Ex: (3.3, 4.4) would have a pos0 of (3, 4), a pos1 of (4, 5), and a delta of (0.3, 0.4). + AZ::Vector2 normalizedDelta; + AZ::Vector2 pos0; + ClampPosition(x, y, pos0, normalizedDelta); + const AZ::Vector2 pos1 = pos0 + m_currentSettings.m_heightQueryResolution; + + const float heightX0Y0 = GetTerrainAreaHeight(pos0.GetX(), pos0.GetY(), terrainExists); + const float heightX1Y0 = GetTerrainAreaHeight(pos1.GetX(), pos0.GetY(), terrainExists); + const float heightX0Y1 = GetTerrainAreaHeight(pos0.GetX(), pos1.GetY(), terrainExists); + const float heightX1Y1 = GetTerrainAreaHeight(pos1.GetX(), pos1.GetY(), terrainExists); + const float heightXY0 = AZ::Lerp(heightX0Y0, heightX1Y0, normalizedDelta.GetX()); + const float heightXY1 = AZ::Lerp(heightX0Y1, heightX1Y1, normalizedDelta.GetX()); + height = AZ::Lerp(heightXY0, heightXY1, normalizedDelta.GetY()); + } + break; - terrainExists = true; + //! Clamp the input point to the terrain sample grid, then get the height at the given grid location. + case AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP: + { + AZ::Vector2 normalizedDelta; + AZ::Vector2 clampedPosition; + ClampPosition(x, y, clampedPosition, normalizedDelta); - break; + height = GetTerrainAreaHeight(clampedPosition.GetX(), clampedPosition.GetY(), terrainExists); } + break; + + //! Directly get the value at the location, regardless of terrain sample grid density. + case AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT: + [[fallthrough]]; + default: + height = GetTerrainAreaHeight(x, y, terrainExists); + break; } if (terrainExistsPtr) @@ -181,7 +223,30 @@ float TerrainSystem::GetHeightSynchronous(float x, float y, Sampler sampler, boo } return AZ::GetClamp( - outPosition.GetZ(), m_currentSettings.m_worldBounds.GetMin().GetZ(), m_currentSettings.m_worldBounds.GetMax().GetZ()); + height, m_currentSettings.m_worldBounds.GetMin().GetZ(), m_currentSettings.m_worldBounds.GetMax().GetZ()); +} + +float TerrainSystem::GetTerrainAreaHeight(float x, float y, bool& terrainExists) const +{ + AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); + float height = m_currentSettings.m_worldBounds.GetMin().GetZ(); + + AZStd::shared_lock lock(m_areaMutex); + + for (auto& [areaId, areaBounds] : m_registeredAreas) + { + inPosition.SetZ(areaBounds.GetMin().GetZ()); + if (areaBounds.Contains(inPosition)) + { + AZ::Vector3 outPosition; + Terrain::TerrainAreaHeightRequestBus::Event( + areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, terrainExists); + height = outPosition.GetZ(); + break; + } + } + + return height; } float TerrainSystem::GetHeight(AZ::Vector3 position, Sampler sampler, bool* terrainExistsPtr) const @@ -203,24 +268,24 @@ bool TerrainSystem::GetIsHoleFromFloats(float x, float y, Sampler sampler) const AZ::Vector3 TerrainSystem::GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { + AZStd::shared_lock lock(m_areaMutex); + bool terrainExists = false; - AZ::Vector3 inPosition((float)x, (float)y, m_currentSettings.m_worldBounds.GetMin().GetZ()); AZ::Vector3 outNormal = AZ::Vector3::CreateAxisZ(); - AZStd::shared_lock lock(m_areaMutex); + const AZ::Vector2 range = (m_currentSettings.m_heightQueryResolution / 2.0f); + const AZ::Vector2 left (x - range.GetX(), y); + const AZ::Vector2 right(x + range.GetX(), y); + const AZ::Vector2 up (x, y - range.GetY()); + const AZ::Vector2 down (x, y + range.GetY()); - for (auto& [areaId, areaBounds] : m_registeredAreas) - { - inPosition.SetZ(areaBounds.GetMin().GetZ()); - if (areaBounds.Contains(inPosition)) - { - Terrain::TerrainAreaHeightRequestBus::Event( - areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetNormal, inPosition, outNormal, sampler); - terrainExists = true; - break; - } - } + AZ::Vector3 v1(up.GetX(), up.GetY(), GetHeightSynchronous(up.GetX(), up.GetY(), sampler, &terrainExists)); + AZ::Vector3 v2(left.GetX(), left.GetY(), GetHeightSynchronous(left.GetX(), left.GetY(), sampler, &terrainExists)); + AZ::Vector3 v3(right.GetX(), right.GetY(), GetHeightSynchronous(right.GetX(), right.GetY(), sampler, &terrainExists)); + AZ::Vector3 v4(down.GetX(), down.GetY(), GetHeightSynchronous(down.GetX(), down.GetY(), sampler, &terrainExists)); + + outNormal = (v3 - v2).Cross(v4 - v1).GetNormalized(); if (terrainExistsPtr) { @@ -469,43 +534,30 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) { for (uint32_t x = 0; x < width; x++) { - // Find the first terrain layer that covers this position. This will be the highest priority, so others can be ignored. - for (auto& [areaId, areaBounds] : m_registeredAreas) - { - AZ::Vector3 inPosition( - (x * m_currentSettings.m_heightQueryResolution.GetX()) + m_currentSettings.m_worldBounds.GetMin().GetX(), - (y * m_currentSettings.m_heightQueryResolution.GetY()) + m_currentSettings.m_worldBounds.GetMin().GetY(), - areaBounds.GetMin().GetZ()); - - if (!areaBounds.Contains(inPosition)) - { - continue; - } - - AZ::Vector3 outPosition; - const AzFramework::Terrain::TerrainDataRequestBus::Events::Sampler sampleFilter = - AzFramework::Terrain::TerrainDataRequestBus::Events::Sampler::DEFAULT; - - Terrain::TerrainAreaHeightRequestBus::Event( - areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter); - - pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) / - m_currentSettings.m_worldBounds.GetExtents().GetZ(); - - break; - } + bool terrainExists; + float terrainHeight = GetTerrainAreaHeight( + (x * m_currentSettings.m_heightQueryResolution.GetX()) + m_currentSettings.m_worldBounds.GetMin().GetX(), + (y * m_currentSettings.m_heightQueryResolution.GetY()) + m_currentSettings.m_worldBounds.GetMin().GetY(), + terrainExists); + + pixels[(y * width) + x] = + (terrainHeight - m_currentSettings.m_worldBounds.GetMin().GetZ()) / + m_currentSettings.m_worldBounds.GetExtents().GetZ(); } } - - const AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get(); - auto terrainFeatureProcessor = scene->GetFeatureProcessor(); - - AZ_Assert(terrainFeatureProcessor, "Unable to find a TerrainFeatureProcessor."); - if (terrainFeatureProcessor) + if (auto rpi = AZ::RPI::RPISystemInterface::Get(); rpi) { - terrainFeatureProcessor->UpdateTerrainData( - transform, m_currentSettings.m_worldBounds, m_currentSettings.m_heightQueryResolution.GetX(), width, height, pixels); + if (auto defaultScene = rpi->GetDefaultScene(); defaultScene) + { + const AZ::RPI::Scene* scene = defaultScene.get(); + if (auto terrainFeatureProcessor = scene->GetFeatureProcessor(); terrainFeatureProcessor) + { + terrainFeatureProcessor->UpdateTerrainData( + transform, m_currentSettings.m_worldBounds, m_currentSettings.m_heightQueryResolution.GetX(), width, height, + pixels); + } + } } } diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index c52165da6b..a9240e02a6 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -94,8 +94,11 @@ namespace Terrain float x, float y, Sampler sampleFilter = Sampler::BILINEAR, bool* terrainExistsPtr = nullptr) const override; private: + void ClampPosition(float x, float y, AZ::Vector2& outPosition, AZ::Vector2& normalizedDelta) const; + float GetHeightSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; - AZ::Vector3 GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; + float GetTerrainAreaHeight(float x, float y, bool& terrainExists) const; + AZ::Vector3 GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; // AZ::TickBus::Handler overrides ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h index 1ba63a8f84..cda6d65a1e 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystemBus.h @@ -65,27 +65,8 @@ namespace Terrain virtual ~TerrainAreaHeightRequests() = default; - enum SurfacePointDataMask - { - POSITION = 0x01, - NORMAL = 0x02, - SURFACE_WEIGHTS = 0x04, - - DEFAULT = POSITION | NORMAL | SURFACE_WEIGHTS - }; - // Synchronous single input location. The Vector3 input position versions are defined to ignore the input Z value. - - virtual void GetHeight( - const AZ::Vector3& inPosition, - AZ::Vector3& outPosition, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) = 0; - virtual void GetNormal( - const AZ::Vector3& inPosition, - AZ::Vector3& outNormal, - AzFramework::Terrain::TerrainDataRequests::Sampler sampleFilter = - AzFramework::Terrain::TerrainDataRequests::Sampler::DEFAULT) = 0; + virtual void GetHeight(const AZ::Vector3& inPosition, AZ::Vector3& outPosition, bool& terrainExists) = 0; }; using TerrainAreaHeightRequestBus = AZ::EBus; diff --git a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp index f0533322c8..ee4b18e2fb 100644 --- a/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp +++ b/Gems/Terrain/Code/Tests/LayerSpawnerTests.cpp @@ -15,7 +15,12 @@ #include #include -#include +#include +#include + +using ::testing::NiceMock; +using ::testing::AtLeast; +using ::testing::_; using ::testing::NiceMock; using ::testing::AtLeast; @@ -29,7 +34,7 @@ protected: AZStd::unique_ptr m_entity; Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent; - UnitTest::MockBoxShapeComponent* m_shapeComponent; + UnitTest::MockAxisAlignedBoxShapeComponent* m_shapeComponent; AZStd::unique_ptr> m_terrainSystem; void SetUp() override @@ -67,7 +72,7 @@ protected: m_layerSpawnerComponent = m_entity->CreateComponent(config); m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor()); - m_shapeComponent = m_entity->CreateComponent(); + m_shapeComponent = m_entity->CreateComponent(); m_app.RegisterComponentDescriptor(m_shapeComponent->CreateDescriptor()); ASSERT_TRUE(m_layerSpawnerComponent); diff --git a/Gems/Terrain/Code/Tests/MockAxisAlignedBoxShapeComponent.h b/Gems/Terrain/Code/Tests/MockAxisAlignedBoxShapeComponent.h new file mode 100644 index 0000000000..aeaaa609c4 --- /dev/null +++ b/Gems/Terrain/Code/Tests/MockAxisAlignedBoxShapeComponent.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include + +#include +#include +#include +#include + +namespace UnitTest +{ + class MockAxisAlignedBoxShapeComponent + : public AZ::Component + { + public: + AZ_COMPONENT(MockAxisAlignedBoxShapeComponent, "{77CBEED3-FAA3-4BC7-85A9-1A2BFC37BC2A}"); + + static void Reflect([[maybe_unused]] AZ::ReflectContext* context) + { + } + + void Activate() override + { + } + + void Deactivate() override + { + } + + private: + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("ShapeService")); + provided.push_back(AZ_CRC_CE("BoxShapeService")); + provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); + } + }; +} diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index 3e557c66a6..91a9744f0b 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -9,20 +9,23 @@ #include #include +#include + #include +#include +#include -#include -#include +#include +#include using ::testing::AtLeast; using ::testing::NiceMock; +using ::testing::Return; class TerrainSystemTest : public ::testing::Test { protected: AZ::ComponentApplication m_app; - - AZStd::unique_ptr m_entity; AZStd::unique_ptr m_terrainSystem; void SetUp() override @@ -41,28 +44,46 @@ protected: m_app.Destroy(); } - void CreateEntity() + AZStd::unique_ptr CreateEntity() { - m_entity = AZStd::make_unique(); - m_entity->Init(); + return AZStd::make_unique(); + } - ASSERT_TRUE(m_entity); + void ActivateEntity(AZ::Entity* entity) + { + entity->Init(); + EXPECT_EQ(AZ::Entity::State::Init, entity->GetState()); + + entity->Activate(); + EXPECT_EQ(AZ::Entity::State::Active, entity->GetState()); } - void ResetEntity() + template + AZ::Component* CreateComponent(AZ::Entity* entity, const Configuration& config) { - m_entity->Deactivate(); - m_entity->Reset(); + m_app.RegisterComponentDescriptor(Component::CreateDescriptor()); + return entity->CreateComponent(config); + } + + template + AZ::Component* CreateComponent(AZ::Entity* entity) + { + m_app.RegisterComponentDescriptor(Component::CreateDescriptor()); + return entity->CreateComponent(); } }; TEST_F(TerrainSystemTest, TrivialCreateDestroy) { + // Trivially verify that the terrain system can successfully be constructed and destructed without errors. + m_terrainSystem = AZStd::make_unique(); } TEST_F(TerrainSystemTest, TrivialActivateDeactivate) { + // Verify that the terrain system can be activated and deactivated without errors. + m_terrainSystem = AZStd::make_unique(); m_terrainSystem->Activate(); m_terrainSystem->Deactivate(); @@ -70,6 +91,8 @@ TEST_F(TerrainSystemTest, TrivialActivateDeactivate) TEST_F(TerrainSystemTest, CreateEventsCalledOnActivation) { + // Verify that when the terrain system is activated, the OnTerrainDataCreate* ebus notifications are generated. + NiceMock mockTerrainListener; EXPECT_CALL(mockTerrainListener, OnTerrainDataCreateBegin()).Times(AtLeast(1)); EXPECT_CALL(mockTerrainListener, OnTerrainDataCreateEnd()).Times(AtLeast(1)); @@ -80,6 +103,8 @@ TEST_F(TerrainSystemTest, CreateEventsCalledOnActivation) TEST_F(TerrainSystemTest, DestroyEventsCalledOnDeactivation) { + // Verify that when the terrain system is deactivated, the OnTerrainDataDestroy* ebus notifications are generated. + NiceMock mockTerrainListener; EXPECT_CALL(mockTerrainListener, OnTerrainDataDestroyBegin()).Times(AtLeast(1)); EXPECT_CALL(mockTerrainListener, OnTerrainDataDestroyEnd()).Times(AtLeast(1)); @@ -89,4 +114,115 @@ TEST_F(TerrainSystemTest, DestroyEventsCalledOnDeactivation) m_terrainSystem->Deactivate(); } +TEST_F(TerrainSystemTest, TerrainDoesNotExistWhenNoTerrainLayerSpawnersAreRegistered) +{ + // For the terrain system, terrain should only exist where terrain layer spawners are present. + + // Verify that in the active terrain system, if there are no terrain layer spawners, any arbitrary point + // will return false for terrainExists, returns a height equal to the min world bounds of the terrain system, and returns + // a normal facing up the Z axis. + + // Create the terrain system and give it one tick to fully initialize itself. + m_terrainSystem = AZStd::make_unique(); + m_terrainSystem->Activate(); + AZ::TickBus::Broadcast(&AZ::TickBus::Events::OnTick, 0.f, AZ::ScriptTimePoint{}); + + AZ::Aabb worldBounds = m_terrainSystem->GetTerrainAabb(); + + // Loop through several points within the world bounds, including on the edges, and verify that they all return false for + // terrainExists with default heights and normals. + for (float y = worldBounds.GetMin().GetY(); y <= worldBounds.GetMax().GetY(); y += (worldBounds.GetExtents().GetY() / 4.0f)) + { + for (float x = worldBounds.GetMin().GetX(); x <= worldBounds.GetMax().GetX(); x += (worldBounds.GetExtents().GetX() / 4.0f)) + { + AZ::Vector3 position(x, y, 0.0f); + bool terrainExists = true; + float height = m_terrainSystem->GetHeight(position, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); + EXPECT_FALSE(terrainExists); + EXPECT_EQ(height, worldBounds.GetMin().GetZ()); + + terrainExists = true; + AZ::Vector3 normal = m_terrainSystem->GetNormal( + position, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); + EXPECT_FALSE(terrainExists); + EXPECT_EQ(normal, AZ::Vector3::CreateAxisZ()); + + bool isHole = m_terrainSystem->GetIsHoleFromFloats( + position.GetX(), position.GetY(), AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); + EXPECT_TRUE(isHole); + } + } +} + +TEST_F(TerrainSystemTest, TerrainExistsOnlyWithinTerrainLayerSpawnerBounds) +{ + // Verify that the presence of a TerrainLayerSpawner causes terrain to exist in (and *only* in) the box where the TerrainLayerSpawner + // is defined. + + // The terrain system should only query Heights from the TerrainAreaHeightRequest bus within the + // TerrainLayerSpawner region, and so those values should only get returned from GetHeight for queries inside that region. + + // Create the base entity with a mock Box Shape and a Terrain Layer Spawner. + auto entity = CreateEntity(); + CreateComponent(entity.get()); + CreateComponent(entity.get()); + + // Set up the box shape to return a box from (0,0,5) to (10, 10, 15) + AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(0.0f, 0.0f, 5.0f, 10.0f, 10.0f, 15.0f); + NiceMock boxShapeRequests(entity->GetId()); + NiceMock shapeRequests(entity->GetId()); + ON_CALL(shapeRequests, GetEncompassingAabb).WillByDefault(Return(spawnerBox)); + + // Set up a mock height provider that always returns 5.0 and a normal of Y-up. + const float spawnerHeight = 5.0f; + NiceMock terrainAreaHeightRequests(entity->GetId()); + ON_CALL(terrainAreaHeightRequests, GetHeight) + .WillByDefault( + [spawnerHeight](const AZ::Vector3& inPosition, AZ::Vector3& outPosition, bool& terrainExists) + { + outPosition = inPosition; + outPosition.SetZ(spawnerHeight); + terrainExists = true; + }); + + ActivateEntity(entity.get()); + + // Verify that terrain exists within the layer spawner bounds, and doesn't exist outside of it. + + // Create the terrain system and give it one tick to fully initialize itself. + m_terrainSystem = AZStd::make_unique(); + m_terrainSystem->Activate(); + AZ::TickBus::Broadcast(&AZ::TickBus::Events::OnTick, 0.f, AZ::ScriptTimePoint{}); + + // Create a box that's twice as big as the layer spawner box. Loop through it and verify that points within the layer box contain + // terrain and the expected height & normal values, and points outside the layer box don't contain terrain. + const AZ::Aabb encompassingBox = + AZ::Aabb::CreateFromMinMax(spawnerBox.GetMin() - (spawnerBox.GetExtents() / 2.0f), + spawnerBox.GetMax() + (spawnerBox.GetExtents() / 2.0f)); + + for (float y = encompassingBox.GetMin().GetY(); y < encompassingBox.GetMax().GetY(); y += 1.0f) + { + for (float x = encompassingBox.GetMin().GetX(); x < encompassingBox.GetMax().GetX(); x += 1.0f) + { + AZ::Vector3 position(x, y, 0.0f); + bool heightQueryTerrainExists = false; + float height = + m_terrainSystem->GetHeight(position, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &heightQueryTerrainExists); + bool isHole = m_terrainSystem->GetIsHoleFromFloats( + position.GetX(), position.GetY(), AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT); + + if (spawnerBox.Contains(AZ::Vector3(position.GetX(), position.GetY(), spawnerBox.GetMin().GetZ()))) + { + EXPECT_TRUE(heightQueryTerrainExists); + EXPECT_FALSE(isHole); + EXPECT_EQ(height, spawnerHeight); + } + else + { + EXPECT_FALSE(heightQueryTerrainExists); + EXPECT_TRUE(isHole); + } + } + } +} diff --git a/Gems/Terrain/Code/terrain_mocks_files.cmake b/Gems/Terrain/Code/terrain_mocks_files.cmake new file mode 100644 index 0000000000..2aedd1c5d8 --- /dev/null +++ b/Gems/Terrain/Code/terrain_mocks_files.cmake @@ -0,0 +1,11 @@ +# +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# +# + +set(FILES + Mocks/Terrain/MockTerrain.h +) diff --git a/Gems/Terrain/Code/terrain_tests_files.cmake b/Gems/Terrain/Code/terrain_tests_files.cmake index 6d1cf97fd9..3ce1d05003 100644 --- a/Gems/Terrain/Code/terrain_tests_files.cmake +++ b/Gems/Terrain/Code/terrain_tests_files.cmake @@ -7,8 +7,8 @@ # set(FILES - Tests/TerrainMocks.h Tests/TerrainTest.cpp Tests/TerrainSystemTest.cpp Tests/LayerSpawnerTests.cpp + Tests/MockAxisAlignedBoxShapeComponent.h ) From f2841f2eba67a37f73e2df29cca1f2d47b698770 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Fri, 17 Sep 2021 14:11:29 -0700 Subject: [PATCH 182/274] Fix interpolation logic errors in NetworkTransform Signed-off-by: puvvadar --- .../Code/Source/Components/NetworkTransformComponent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index 671228f89d..1d9fee16e0 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -57,8 +57,8 @@ namespace Multiplayer blendTransform.SetTranslation(GetTranslation()); blendTransform.SetUniformScale(GetScale()); - const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); - if (!!AZ::IsClose(blendFactor, 1.0f)) + const float blendFactor = GetMultiplayer()->GetCurrentBlendFactor(); + if (!AZ::IsClose(blendFactor, 1.0f)) { AZ::Transform blendTransformPrevious; blendTransformPrevious.SetRotation(GetRotationPrevious()); From 67e2498a12c658ee39c5900d40918bf854105119 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Fri, 17 Sep 2021 14:43:14 -0700 Subject: [PATCH 183/274] Update GetPrevious to behave similarly to Get when rewound on owning connection Signed-off-by: puvvadar --- .../Multiplayer/NetworkTime/INetworkTime.h | 6 ------ .../NetworkTime/RewindableObject.h | 8 ++++++-- .../NetworkTime/RewindableObject.inl | 19 +++++++++++++++++-- .../Code/Source/NetworkTime/NetworkTime.cpp | 5 ----- .../Code/Source/NetworkTime/NetworkTime.h | 1 - 5 files changed, 23 insertions(+), 16 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h index bfddcbdebb..c12cbb660b 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/INetworkTime.h @@ -52,12 +52,6 @@ namespace Multiplayer //! @return the ConnectionId of the connection requesting the rewind operation virtual AzNetworking::ConnectionId GetRewindingConnectionId() const = 0; - //! Get the controlling connection that may be currently altering global game time. - //! Note this abstraction is required at a relatively high level to allow for 'don't rewind the shooter' semantics - //! @param rewindConnectionId if this parameter matches the current rewindConnectionId, it will return the unaltered hostFrameId - //! @return the HostFrameId taking into account the provided rewinding connectionId - virtual HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const = 0; - //! Forcibly sets the current network time to the provided frameId and game time in milliseconds. //! @param frameId the new HostFrameId to use //! @param timeMs the new HostTimeMs to use diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h index a8af564c15..152f6f47a7 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.h @@ -60,7 +60,7 @@ namespace Multiplayer //! @return value in const base type form const BASE_TYPE& Get() const; - //! Const base type retriever for one host frame behind Get(). Only intended for use in SyncRewind contexts. + //! Const base type retriever for one host frame behind Get() when contextually appropriate, otherwise identical to Get(). //! @return value in const base type form const BASE_TYPE& GetPrevious() const; @@ -86,9 +86,13 @@ namespace Multiplayer private: //! Returns what the appropriate current time is for this rewindable property. - //! @return the appropriate current time is for this rewindable property + //! @return the appropriate current time for this rewindable property HostFrameId GetCurrentTimeForProperty() const; + //! Returns what the appropriate previous time is for this rewindable property. + //! @return the appropriate previous time for this rewindable property + HostFrameId GetPreviousTimeForProperty() const; + //! Updates the latest value for this object instance, if frameTime represents a current or future time. //! Any attempts to set old values on the object will fail //! @param value the new value to set in the object history diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl index b0c9bc0c46..9183a1e9da 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkTime/RewindableObject.inl @@ -69,7 +69,7 @@ namespace Multiplayer template inline const BASE_TYPE& RewindableObject::GetPrevious() const { - return GetValueForTime(GetCurrentTimeForProperty() - HostFrameId(1)); + return GetValueForTime(GetPreviousTimeForProperty()); } template @@ -118,7 +118,22 @@ namespace Multiplayer inline HostFrameId RewindableObject::GetCurrentTimeForProperty() const { INetworkTime* networkTime = Multiplayer::GetNetworkTime(); - return networkTime->GetHostFrameIdForRewindingConnection(m_owningConnectionId); + if (networkTime->IsTimeRewound() && (m_owningConnectionId == networkTime->GetRewindingConnectionId())) + { + return networkTime->GetUnalteredHostFrameId(); + } + return networkTime->GetHostFrameId(); + } + + template + inline HostFrameId RewindableObject::GetPreviousTimeForProperty() const + { + INetworkTime* networkTime = Multiplayer::GetNetworkTime(); + if (networkTime->IsTimeRewound() && (m_owningConnectionId == networkTime->GetRewindingConnectionId())) + { + return networkTime->GetUnalteredHostFrameId(); + } + return networkTime->GetHostFrameId() - HostFrameId(1); } template diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 8edf2a8ce4..0838a1ef3d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -65,11 +65,6 @@ namespace Multiplayer return m_rewindingConnectionId; } - HostFrameId NetworkTime::GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const - { - return (IsTimeRewound() && (rewindConnectionId == m_rewindingConnectionId)) ? m_unalteredFrameId : m_hostFrameId; - } - void NetworkTime::ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) { AZ_Assert(!IsTimeRewound(), "Forcibly setting network time is unsupported under a rewound time scope"); diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h index 7c845db8b6..2bcf019623 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.h @@ -32,7 +32,6 @@ namespace Multiplayer AZ::TimeMs GetHostTimeMs() const override; float GetHostBlendFactor() const override; AzNetworking::ConnectionId GetRewindingConnectionId() const override; - HostFrameId GetHostFrameIdForRewindingConnection(AzNetworking::ConnectionId rewindConnectionId) const override; void ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) override; void AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId rewindConnectionId) override; void SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) override; From 95a1b9c1a3cc83c80ce8972e6e0c8a33f847403f Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Fri, 17 Sep 2021 15:37:18 -0700 Subject: [PATCH 184/274] Minor commenting improvements based on PR feedback Signed-off-by: Gene Walters --- .../Components/NetworkCharacterComponent.h | 15 +++++++++++++-- .../Components/NetworkCharacterComponent.cpp | 6 ------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h index 97dfcd4328..478c925299 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkCharacterComponent.h @@ -19,6 +19,8 @@ namespace Physics namespace Multiplayer { + //! NetworkCharacterComponent + //! Provides multiplayer support for game-play player characters. class NetworkCharacterComponent : public NetworkCharacterComponentBase , private PhysX::CharacterGameplayRequestBus::Handler @@ -37,7 +39,8 @@ namespace Multiplayer incompatible.push_back(AZ_CRC_CE("NetworkRigidBodyService")); } - void OnInit() override; + // AZ::Component + void OnInit() override {} void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; @@ -46,7 +49,7 @@ namespace Multiplayer void OnSyncRewind(); // CharacterGameplayRequestBus - bool IsOnGround() const override; + bool IsOnGround() const override; float GetGravityMultiplier() const override { return {}; } void SetGravityMultiplier([[maybe_unused]] float gravityMultiplier) override {} AZ::Vector3 GetFallingVelocity() const override { return {}; } @@ -57,15 +60,23 @@ namespace Multiplayer AZ::Event::Handler m_translationEventHandler; }; + //! NetworkCharacterComponentController + //! This is the network controller for NetworkCharacterComponent. + //! Class provides the ability to move characters in physical space while keeping the network in-sync. class NetworkCharacterComponentController : public NetworkCharacterComponentControllerBase { public: NetworkCharacterComponentController(NetworkCharacterComponent& parent); + // NetworkCharacterComponentControllerBase void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + //! TryMoveWithVelocity + //! Will move this character entity kinematically through physical world while also ensuring the network stays in-sync. + //! Velocity will be applied over delta-time to determine the movement amount. + //! Returns this entity's world-space position after the move. AZ::Vector3 TryMoveWithVelocity(const AZ::Vector3& velocity, float deltaTime); }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp index 583f01f92a..b14fc8761f 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkCharacterComponent.cpp @@ -97,12 +97,6 @@ namespace Multiplayer NetworkCharacterComponent::NetworkCharacterComponent() : m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) { - ; - } - - void NetworkCharacterComponent::OnInit() - { - ; } void NetworkCharacterComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) From 3e8fe7df395f3d1d9e356d96693acd269ef29cd0 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Fri, 17 Sep 2021 15:41:54 -0700 Subject: [PATCH 185/274] Add unit tests for RewindableObject Get and GetPrevious Signed-off-by: puvvadar --- .../Code/Tests/RewindableObjectTests.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp b/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp index b8d60a94e8..04de971f0d 100644 --- a/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp +++ b/Gems/Multiplayer/Code/Tests/RewindableObjectTests.cpp @@ -57,6 +57,35 @@ namespace UnitTest } } + TEST_F(RewindableObjectTests, CurrentPreviousTests) + { + Multiplayer::RewindableObject test(0); + + for (uint32_t i = 0; i < RewindableBufferFrames; ++i) + { + test = i; + EXPECT_EQ(i, test); + Multiplayer::GetNetworkTime()->IncrementHostFrameId(); + } + + { + // Test that Get/GetPrevious return different value when not on the owning connection + Multiplayer::ScopedAlterTime time(static_cast(RewindableBufferFrames - 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId); + EXPECT_EQ(RewindableBufferFrames - 1, test.Get()); + EXPECT_EQ(RewindableBufferFrames - 2, test.GetPrevious()); + } + + // Test that Get/GetPrevious return the unaltered frame on the owning conection + Multiplayer::GetNetworkTime()->AlterTime(static_cast(RewindableBufferFrames - 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::ConnectionId(0)); + { + Multiplayer::ScopedAlterTime time(static_cast(RewindableBufferFrames - 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::ConnectionId(0)); + test.SetOwningConnectionId(AzNetworking::ConnectionId(0)); + EXPECT_EQ(RewindableBufferFrames - 1, test.Get()); + EXPECT_EQ(RewindableBufferFrames - 1, test.GetPrevious()); + } + Multiplayer::GetNetworkTime()->AlterTime(static_cast(RewindableBufferFrames), AZ::TimeMs(0), 1.f, AzNetworking::InvalidConnectionId); + } + TEST_F(RewindableObjectTests, OverflowTests) { Multiplayer::RewindableObject test(0); From efce1033bc3b1306e705420a03d264bf22a84a8b Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Fri, 17 Sep 2021 16:11:33 -0700 Subject: [PATCH 186/274] Instanced the RayTracingBLAS objects to enable re-use when the same model is added multiple times. Signed-off-by: dmcdiar --- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 2 +- .../RayTracing/RayTracingFeatureProcessor.cpp | 54 ++++++++++++++++--- .../RayTracing/RayTracingFeatureProcessor.h | 15 +++++- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 8ab324cdf7..e243687b1c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -952,7 +952,7 @@ namespace AZ subMeshes.push_back(subMesh); } - rayTracingFeatureProcessor->SetMesh(m_objectId, subMeshes); + rayTracingFeatureProcessor->SetMesh(m_objectId, m_model->GetModelAsset()->GetId(), subMeshes); } void MeshDataInstance::SetSortKey(RHI::DrawItemSortKey sortKey) diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index ea89f64b73..d10da818ee 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -79,7 +79,7 @@ namespace AZ AZ_Assert(m_rayTracingMaterialSrg, "Failed to create RayTracingMaterialSrg"); } - void RayTracingFeatureProcessor::SetMesh(const ObjectId objectId, const SubMeshVector& subMeshes) + void RayTracingFeatureProcessor::SetMesh(const ObjectId objectId, const AZ::Data::AssetId& assetId, const SubMeshVector& subMeshes) { if (!m_rayTracingEnabled) { @@ -92,7 +92,7 @@ namespace AZ MeshMap::iterator itMesh = m_meshes.find(objectIndex); if (itMesh == m_meshes.end()) { - m_meshes.insert(AZStd::make_pair(objectIndex, Mesh{ subMeshes })); + m_meshes.insert(AZStd::make_pair(objectIndex, Mesh{ assetId, subMeshes })); } else { @@ -102,9 +102,12 @@ namespace AZ m_meshes[objectIndex].m_subMeshes = subMeshes; } - // create the BLAS buffers for each sub-mesh + // create the BLAS buffers for each sub-mesh, or re-use existing BLAS objects if they were already created. + // Note: all sub-meshes must either create new BLAS objects or re-use existing ones, otherwise it's an error (it's the same model in both cases) // Note: the buffer is just reserved here, the BLAS is built in the RayTracingAccelerationStructurePass Mesh& mesh = m_meshes[objectIndex]; + bool blasInstanceFound = false; + for (auto& subMesh : mesh.m_subMeshes) { RHI::RayTracingBlasDescriptor blasDescriptor; @@ -115,11 +118,37 @@ namespace AZ ->IndexBuffer(subMesh.m_indexBufferView) ; - // create the BLAS object - subMesh.m_blas = AZ::RHI::RayTracingBlas::CreateRHIRayTracingBlas(); + // search for an existing BLAS object for this model + RayTracingBlasMap::iterator itBlas = m_blasMap.find(assetId); + if (itBlas != m_blasMap.end()) + { + // re-use existing BLAS + subMesh.m_blas = itBlas->second.m_blas; + itBlas->second.m_count++; + + // keep track of the fact that we re-used a BLAS + blasInstanceFound = true; + } + else + { + AZ_Assert(blasInstanceFound == false, "Partial set of RayTracingBlas objects found for mesh"); + + // create the BLAS object + subMesh.m_blas = AZ::RHI::RayTracingBlas::CreateRHIRayTracingBlas(); - // create the buffers from the descriptor - subMesh.m_blas->CreateBuffers(*device, &blasDescriptor, *m_bufferPools); + // create the buffers from the descriptor + subMesh.m_blas->CreateBuffers(*device, &blasDescriptor, *m_bufferPools); + + // store the BLAS in the side list + RayTracingBlasInstance blasInstance = { subMesh.m_blas, 1 }; + m_blasMap.insert({ assetId, blasInstance }); + } + } + + if (blasInstanceFound) + { + // set the mesh BLAS flag so we don't try to rebuild it in the RayTracingAccelerationStructurePass + mesh.m_blasBuilt = true; } // set initial transform @@ -146,6 +175,17 @@ namespace AZ m_subMeshCount -= aznumeric_cast(itMesh->second.m_subMeshes.size()); m_meshes.erase(itMesh); m_revision++; + + // decrement the count from the BLAS instance, and check to see if we can remove it + RayTracingBlasMap::iterator itBlas = m_blasMap.find(itMesh->second.m_assetId); + if (itBlas != m_blasMap.end()) + { + itBlas->second.m_count--; + if (itBlas->second.m_count == 0) + { + m_blasMap.erase(itBlas); + } + } } m_meshInfoBufferNeedsUpdate = true; diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index 6bd9829c7e..ee0a27b814 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -116,6 +116,9 @@ namespace AZ //! Contains data for the top level mesh, including the list of sub-meshes struct Mesh { + // assetId of the model + AZ::Data::AssetId m_assetId = AZ::Data::AssetId{}; + // sub-mesh list SubMeshVector m_subMeshes; @@ -134,7 +137,7 @@ namespace AZ //! Sets ray tracing data for a mesh. //! This will cause an update to the RayTracing acceleration structure on the next frame - void SetMesh(const ObjectId objectId, const SubMeshVector& subMeshes); + void SetMesh(const ObjectId objectId, const AZ::Data::AssetId& assetId, const SubMeshVector& subMeshes); //! Removes ray tracing data for a mesh. //! This will cause an update to the RayTracing acceleration structure on the next frame @@ -260,6 +263,16 @@ namespace AZ // flag indicating we need to update the materialInfo buffer bool m_materialInfoBufferNeedsUpdate = false; + + // side list for looking up existing BLAS objects so they can be re-used when the same mesh is added multiple times + struct RayTracingBlasInstance + { + RHI::Ptr m_blas; + uint32_t m_count = 0; + }; + + using RayTracingBlasMap = AZStd::unordered_map; + RayTracingBlasMap m_blasMap; }; } } From bd0032a6d111ba249f3b8b36a3f6ad8fa4664162 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 17 Sep 2021 18:03:33 -0700 Subject: [PATCH 187/274] Fixed a recently introduced Material initialization bug. An early-return in Material::SetPropertyValue was breaking initialization because Init() was called multiple times, and on subsequent initializations the property values weren't getting reset. Added a unit test to ensure this kind of thing doesn't happen again. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Atom/RPI.Reflect/Material/MaterialAsset.h | 6 ++ .../Source/RPI.Public/Material/Material.cpp | 8 ++- .../RPI/Code/Tests/Material/MaterialTests.cpp | 72 +++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h index 52af56ba0e..6ca3bca652 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Material/MaterialAsset.h @@ -19,6 +19,11 @@ #include +namespace UnitTest +{ + class MaterialTests; +} + namespace AZ { class ReflectContext; @@ -40,6 +45,7 @@ namespace AZ friend class MaterialAssetCreator; friend class MaterialAssetHandler; friend class MaterialAssetCreatorCommon; + friend class UnitTest::MaterialTests; public: AZ_RTTI(MaterialAsset, "{522C7BE0-501D-463E-92C6-15184A2B7AD8}", AZ::Data::AssetData); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index 2dcaa70deb..d44ed40c7b 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -100,9 +100,15 @@ namespace AZ ShaderReloadNotificationBus::MultiHandler::BusConnect(shaderItem.GetShaderAsset().GetId()); } + // If this Init() is actually a re-initialize, we need to re-apply any overridden property values + // after loading the property values from the asset, so we save that data here. MaterialPropertyFlags prevOverrideFlags = m_propertyOverrideFlags; AZStd::vector prevPropertyValues = m_propertyValues; + // The property values are cleared to their default state to ensure that SetPropertyValue() does not early-return + // when called below. This is important when Init() is actually a re-initialize. + m_propertyValues.clear(); + // Initialize the shader runtime data like shader constant buffers and shader variants by applying the // material's property values. This will feed through the normal runtime material value-change data flow, which may // include custom property change handlers provided by the material type. @@ -504,7 +510,7 @@ namespace AZ MaterialPropertyValue& savedPropertyValue = m_propertyValues[index.GetIndex()]; - // If the property value didn't actually change, don't waste time running functors and compiling the changes + // If the property value didn't actually change, don't waste time running functors and compiling the changes. if (savedPropertyValue == value) { return false; diff --git a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp index d82a17e1f3..f202747bf6 100644 --- a/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Material/MaterialTests.cpp @@ -182,6 +182,13 @@ namespace UnitTest EXPECT_EQ(srgData.GetImageView(srgData.FindShaderInputImageIndex(Name{ "m_image" }), 0), m_testImage->GetImageView()); EXPECT_EQ(srgData.GetConstant(srgData.FindShaderInputConstantIndex(Name{ "m_enum" })), 2u); } + + //! Provides write access to private material asset property values, primarily for simulating + //! MaterialAsset hot reload. + MaterialPropertyValue& AccessMaterialAssetPropertyValue(Data::Asset materialAsset, Name propertyName) + { + return materialAsset->m_propertyValues[materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyName).GetIndex()]; + } }; TEST_F(MaterialTests, TestCreateVsFindOrCreate) @@ -313,6 +320,30 @@ namespace UnitTest EXPECT_EQ(srgData.GetConstant(srgData.FindShaderInputConstantIndex(Name{ "m_uint" })), 42u); } + TEST_F(MaterialTests, TestSetPropertyValueWhenValueIsUnchanged) + { + Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); + + EXPECT_TRUE(material->SetPropertyValue(material->FindPropertyIndex(Name{ "MyFloat" }), 2.5f)); + + ProcessQueuedSrgCompilations(m_testMaterialShaderAsset, m_testMaterialSrgLayout->GetName()); + EXPECT_TRUE(material->Compile()); + + // Taint the SRG so we can check whether it was set by the SetPropertyValue() calls below. + const RHI::ShaderResourceGroup* srg = material->GetRHIShaderResourceGroup(); + const RHI::ShaderResourceGroupData& srgData = srg->GetData(); + const_cast(&srgData)->SetConstant(m_testMaterialSrgLayout->FindShaderInputConstantIndex(Name{"m_float"}), 0.0f); + + // Set the properties to the same values as before + EXPECT_FALSE(material->SetPropertyValue(material->FindPropertyIndex(Name{ "MyFloat" }), 2.5f)); + + ProcessQueuedSrgCompilations(m_testMaterialShaderAsset, m_testMaterialSrgLayout->GetName()); + EXPECT_FALSE(material->Compile()); + + // Make sure the SRG is still tainted, because the SetPropertyValue() functions weren't processed + EXPECT_EQ(srgData.GetConstant(srgData.FindShaderInputConstantIndex(Name{ "m_float" })), 0.0f); + } + TEST_F(MaterialTests, TestImageNotProvided) { Data::Asset materialAssetWithEmptyImage; @@ -785,4 +816,45 @@ namespace UnitTest EXPECT_EQ((float)inputColor.GetElement(i), (float)colorFromMaterial.GetElement(i)); } } + + TEST_F(MaterialTests, TestReinitializeForHotReload) + { + Data::Instance material = Material::FindOrCreate(m_testMaterialAsset); + const RHI::ShaderResourceGroupData* srgData = &material->GetRHIShaderResourceGroup()->GetData(); + ProcessQueuedSrgCompilations(m_testMaterialShaderAsset, m_testMaterialSrgLayout->GetName()); + + // Check the default property value + EXPECT_EQ(material->GetPropertyValue(material->FindPropertyIndex(Name{ "MyFloat" })), 1.5f); + EXPECT_EQ(srgData->GetConstant(srgData->FindShaderInputConstantIndex(Name{ "m_float" })), 1.5f); + EXPECT_EQ(material->GetPropertyValue(material->FindPropertyIndex(Name{ "MyInt" })), -2); + EXPECT_EQ(srgData->GetConstant(srgData->FindShaderInputConstantIndex(Name{ "m_int" })), -2); + + // Override a property value + EXPECT_TRUE(material->SetPropertyValue(material->FindPropertyIndex(Name{ "MyFloat" }), 5.5f)); + + // Apply the changes + EXPECT_TRUE(material->Compile()); + ProcessQueuedSrgCompilations(m_testMaterialShaderAsset, m_testMaterialSrgLayout->GetName()); + + // Check the updated values with one overridden + EXPECT_EQ(material->GetPropertyValue(material->FindPropertyIndex(Name{ "MyFloat" })), 5.5f); + EXPECT_EQ(srgData->GetConstant(srgData->FindShaderInputConstantIndex(Name{ "m_float" })), 5.5f); + EXPECT_EQ(material->GetPropertyValue(material->FindPropertyIndex(Name{ "MyInt" })), -2); + EXPECT_EQ(srgData->GetConstant(srgData->FindShaderInputConstantIndex(Name{ "m_int" })), -2); + + // Pretend there was a hot-reload with new default values + AccessMaterialAssetPropertyValue(m_testMaterialAsset, Name{"MyFloat"}) = 0.5f; + AccessMaterialAssetPropertyValue(m_testMaterialAsset, Name{"MyInt"}) = -7; + AZ::Data::AssetBus::Event(m_testMaterialAsset.GetId(), &AZ::Data::AssetBus::Handler::OnAssetReloaded, m_testMaterialAsset); + srgData = &material->GetRHIShaderResourceGroup()->GetData(); + ProcessQueuedSrgCompilations(m_testMaterialShaderAsset, m_testMaterialSrgLayout->GetName()); + + // Make sure the override values are still there + EXPECT_EQ(srgData->GetConstant(srgData->FindShaderInputConstantIndex(Name{ "m_float" })), 5.5f); + EXPECT_EQ(material->GetPropertyValue(material->FindPropertyIndex(Name{ "MyFloat" })), 5.5f); + + // Make sure the new default value is applied where it was not overridden + EXPECT_EQ(material->GetPropertyValue(material->FindPropertyIndex(Name{ "MyInt" })), -7); + EXPECT_EQ(srgData->GetConstant(srgData->FindShaderInputConstantIndex(Name{ "m_int" })), -7); + } } From 22e43c9122fdb4debe5edd48b745ac64c7c8bcb2 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Fri, 17 Sep 2021 21:16:04 -0700 Subject: [PATCH 188/274] Nearly all build jobs fail with a missing function in Archive.cpp (#4195) Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> --- Code/Editor/Include/IEditorClassFactory.h | 6 ++++-- Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Code/Editor/Include/IEditorClassFactory.h b/Code/Editor/Include/IEditorClassFactory.h index 0827dc96dc..dd47f803e2 100644 --- a/Code/Editor/Include/IEditorClassFactory.h +++ b/Code/Editor/Include/IEditorClassFactory.h @@ -14,8 +14,10 @@ #define CRYINCLUDE_EDITOR_INCLUDE_IEDITORCLASSFACTORY_H #pragma once +#include #include #include +#include #define DEFINE_UUID(l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ static const GUID uuid() { return { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; } @@ -34,7 +36,7 @@ struct IUnknown #endif #define __uuidof(T) T::uuid() -#if defined(AZ_PLATFORM_LINUX) +#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) # ifndef _REFGUID_DEFINED # define _REFGUID_DEFINED @@ -65,7 +67,7 @@ enum }; #endif -#endif // defined(AZ_PLATFORM_LINUX) +#endif // defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) #include "SandboxAPI.h" diff --git a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp index c94d588a90..d2a81102dc 100644 --- a/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp +++ b/Code/Framework/AzFramework/AzFramework/Archive/Archive.cpp @@ -181,7 +181,7 @@ namespace AZ::IO::ArchiveInternal return 0; } - nTotal = (AZStd::min)(nTotal, GetFileSize() - m_nCurSeek); + nTotal = AZStd::min(nTotal, GetFileSize() - m_nCurSeek); int64_t nReadBytes = GetFile()->ReadData(pDest, m_nCurSeek, nTotal); if (nReadBytes == -1) From 0c9dbb86581f5b42fbd165820cf689403aec9adb Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 19 Sep 2021 18:42:24 -0500 Subject: [PATCH 189/274] =?UTF-8?q?Adding=20new=20commands=20to=20the=20ma?= =?UTF-8?q?terial=20component=20for=20managing,=20removing,=20repairing=20?= =?UTF-8?q?material=20slots=20=E2=80=A2=20Adding=20commands=20to=20materia?= =?UTF-8?q?l=20component=20to=20clear=20or=20repair=20material=20slots=20?= =?UTF-8?q?=E2=80=A2=20Moved=20all=20clear=20and=20repair=20functions=20fr?= =?UTF-8?q?om=20the=20editor=20component=20to=20the=20material=20component?= =?UTF-8?q?=20controller,=20bound=20to=20its=20buses=20so=20they=20can=20b?= =?UTF-8?q?e=20accessed=20from=20script=20=E2=80=A2=20Added=20new=20functi?= =?UTF-8?q?ons=20to=20clear=20model=20and=20LOD=20material=20groups=20?= =?UTF-8?q?=E2=80=A2=20Added=20function=20to=20remove=20material=20assignm?= =?UTF-8?q?ents=20with=20bad=20asset=20references=20=E2=80=A2=20Added=20fu?= =?UTF-8?q?nction=20to=20reassign=20materials=20with=20bad=20asset=20refer?= =?UTF-8?q?ences=20to=20the=20default=20asset=20=E2=80=A2=20Added=20functi?= =?UTF-8?q?on=20to=20remove=20material=20assignments=20that=20don=E2=80=99?= =?UTF-8?q?t=20match=20slots=20available=20on=20the=20active=20model.=20Th?= =?UTF-8?q?is=20case=20arises=20when=20switching=20between=20different=20m?= =?UTF-8?q?odels,=20changing=20the=20materials=20on=20a=20given=20model,?= =?UTF-8?q?=20or=20copying=20and=20pasting=20the=20material=20component=20?= =?UTF-8?q?to=20a=20different=20entity=20with=20a=20different=20model.=20T?= =?UTF-8?q?he=20user=20might=20end=20up=20with=20hidden=20material=20slots?= =?UTF-8?q?=20that=20load=20assets=20but=20have=20no=20effect.=20=E2=80=A2?= =?UTF-8?q?=20Converted=20remaining=20code=20that=20iterated=20over=20edit?= =?UTF-8?q?or=20material=20slots=20to=20instead=20use=20the=20material=20c?= =?UTF-8?q?omponent=20request=20bus=20=E2=80=A2=20Removed=20functions=20fr?= =?UTF-8?q?om=20the=20editor=20material=20component=20that=20enumerated=20?= =?UTF-8?q?editor=20material=20slots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guthrie Adams --- .../Material/MaterialComponentBus.h | 10 + .../Material/EditorMaterialComponent.cpp | 206 ++++++++---------- .../Source/Material/EditorMaterialComponent.h | 7 - .../EditorMaterialComponentExporter.cpp | 4 + .../Material/EditorMaterialComponentSlot.cpp | 7 +- .../Material/MaterialComponentController.cpp | 84 ++++++- .../Material/MaterialComponentController.h | 5 + 7 files changed, 187 insertions(+), 136 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 3b65750b5f..ab7a180dd1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -33,6 +33,16 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialOverrides() const = 0; //! Clear all material overrides virtual void ClearAllMaterialOverrides() = 0; + //! Clear non-lod material override + virtual void ClearModelMaterialOverrides() = 0; + //! Clear lod material override + virtual void ClearLodMaterialOverrides() = 0; + //! Clear residual materials that don't correspond to the associated model + virtual void ClearIncompatibleMaterialOverrides() = 0; + //! Clear materials that reference missing assets + virtual void ClearInvalidMaterialOverrides() = 0; + //! Repair materials that reference missing assets by assigning the default asset + virtual void RepairInvalidMaterialOverrides() = 0; //! Set default material override virtual void SetDefaultMaterialOverride(const AZ::Data::AssetId& materialAssetId) = 0; //! Get default material override diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index c243522257..ab39e7f208 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -32,9 +32,6 @@ namespace AZ const char* EditorMaterialComponent::GenerateMaterialsButtonText = "Generate/Manage Source Materials..."; const char* EditorMaterialComponent::GenerateMaterialsToolTipText = "Generate editable source material files from materials provided by the model."; - const char* EditorMaterialComponent::ResetMaterialsButtonText = "Reset Materials"; - const char* EditorMaterialComponent::ResetMaterialsToolTipText = "Clear all settings, materials, and properties then rebuild material slots from the associated model."; - // Update serialized data to the new format and data types bool EditorMaterialComponent::ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) { @@ -178,43 +175,74 @@ namespace AZ menu->addSeparator(); - action = menu->addAction(ResetMaterialsButtonText, [this]() { ResetMaterialSlots(); }); - action->setToolTip(ResetMaterialsToolTipText); + action = menu->addAction("Clear All Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Clearing all materials."); + SetDirty(); - menu->addSeparator(); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearAllMaterialOverrides); + + m_materialSlotsByLodEnabled = false; + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear all materials and properties then rebuild material slots from the associated model."); action = menu->addAction("Clear Model Materials", [this]() { AzToolsFramework::ScopedUndoBatch undoBatch("Clearing model materials."); SetDirty(); - for (auto& materialSlotPair : GetMaterialSlots()) - { - EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.IsSlotIdOnly()) - { - materialSlot->Clear(); - } - } - }); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearModelMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear model materials and properties then rebuild material slots from the associated model."); + action = menu->addAction("Clear LOD Materials", [this]() { AzToolsFramework::ScopedUndoBatch undoBatch("Clearing LOD materials."); SetDirty(); - for (auto& materialSlotPair : GetMaterialSlots()) - { - EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.IsLodAndSlotId()) - { - materialSlot->Clear(); - } - } - }); - action->setEnabled(m_materialSlotsByLodEnabled); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearLodMaterialOverrides); + + m_materialSlotsByLodEnabled = false; + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear LOD materials and properties then rebuild material slots from the associated model."); + + action = menu->addAction("Clear Incompatible Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Clearing incompatible materials."); + SetDirty(); + + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearIncompatibleMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear residual materials that don't correspond to the associated model."); + + action = menu->addAction("Clear Invalid Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Clearing invalid materials."); + SetDirty(); + + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearInvalidMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear materials that reference missing assets."); + + action = menu->addAction("Repair Invalid Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Repairing invalid materials."); + SetDirty(); + + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::RepairInvalidMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Repair materials that reference missing assets by assigning the default asset."); } void EditorMaterialComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) { - m_controller.SetDefaultMaterialOverride(assetId); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::SetDefaultMaterialOverride, assetId); MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); @@ -249,14 +277,18 @@ namespace AZ m_materialSlots = {}; m_materialSlotsByLod = {}; - const MaterialComponentConfig& config = m_controller.GetConfiguration(); + // Get current material assignments + MaterialAssignmentMap currentMaterials; + MaterialComponentRequestBus::EventResult( + currentMaterials, GetEntityId(), &MaterialComponentRequestBus::Events::GetMaterialOverrides); // Get the known material assignment slots from the associated model or other source - MaterialAssignmentMap materialsFromSource; - MaterialReceiverRequestBus::EventResult(materialsFromSource, GetEntityId(), &MaterialReceiverRequestBus::Events::GetMaterialAssignments); + MaterialAssignmentMap originalMaterials; + MaterialComponentRequestBus::EventResult( + originalMaterials, GetEntityId(), &MaterialComponentRequestBus::Events::GetOriginalMaterialAssignments); // Generate the table of editable materials using the source data to define number of groups, elements, and initial values - for (const auto& materialPair : materialsFromSource) + for (const auto& materialPair : originalMaterials) { // Setup the material slot entry EditorMaterialComponentSlot slot; @@ -264,7 +296,7 @@ namespace AZ slot.m_id = materialPair.first; // if material is present in controller configuration, assign its data - const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); + const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(currentMaterials, slot.m_id); slot.m_materialAsset = materialFromController.m_materialAsset; if (slot.m_id.IsDefault()) @@ -289,7 +321,7 @@ namespace AZ } } - // Sort all of the slots by label to ensure stable index values (materialsFromSource is an unordered map) + // Sort all of the slots by label to ensure stable index values (originalMaterials is an unordered map) AZStd::sort(m_materialSlots.begin(), m_materialSlots.end(), [](const auto& a, const auto& b) { return a.GetLabel() < b.GetLabel(); }); @@ -305,49 +337,36 @@ namespace AZ &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } - AZ::u32 EditorMaterialComponent::ResetMaterialSlots() - { - AzToolsFramework::ScopedUndoBatch undoBatch("Resetting materials."); - SetDirty(); - - m_controller.SetMaterialOverrides(MaterialAssignmentMap()); - UpdateMaterialSlots(); - - m_materialSlotsByLodEnabled = false; - - MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); - - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - AZ::u32 EditorMaterialComponent::OpenMaterialExporter() { AzToolsFramework::ScopedUndoBatch undoBatch("Generating materials."); SetDirty(); - // First generating a unique set of all material asset IDs that will be used for source data generation - AZStd::unordered_map assetIdMap; + MaterialAssignmentMap originalMaterials; + MaterialComponentRequestBus::EventResult( + originalMaterials, GetEntityId(), &MaterialComponentRequestBus::Events::GetOriginalMaterialAssignments); - auto materialSlots = GetMaterialSlots(); - for (auto& materialSlotPair : materialSlots) + // Generate a unique set of all material asset IDs that will be used for source data generation + AZStd::unordered_map assetIdToSlotNameMap; + for (const auto& materialPair : originalMaterials) { - Data::AssetId defaultMaterialAssetId = materialSlotPair.second->GetDefaultAssetId(); - if (defaultMaterialAssetId.IsValid()) + const Data::AssetId originalAssetId = materialPair.second.m_materialAsset.GetId(); + if (originalAssetId.IsValid()) { - assetIdMap[defaultMaterialAssetId] = materialSlotPair.second->GetLabel(); + MaterialComponentRequestBus::EventResult( + assetIdToSlotNameMap[originalAssetId], GetEntityId(), &MaterialComponentRequestBus::Events::GetMaterialSlotLabel, + materialPair.first); } } // Convert the unique set of asset IDs into export items that can be configured in the dialog // The order should not matter because the table in the dialog can sort itself for a specific row EditorMaterialComponentExporter::ExportItemsContainer exportItems; - for (auto assetIdInfo : assetIdMap) + exportItems.reserve(assetIdToSlotNameMap.size()); + + for (const auto& assetIdToSlotNamePair : assetIdToSlotNameMap) { - EditorMaterialComponentExporter::ExportItem exportItem{ assetIdInfo.first, assetIdInfo.second }; - exportItems.push_back(exportItem); + exportItems.emplace_back(assetIdToSlotNamePair.first, assetIdToSlotNamePair.second); } // Display the export dialog so that the user can configure how they want different materials to be exported @@ -363,16 +382,17 @@ namespace AZ const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { - for (auto& materialSlotPair : materialSlots) + for (const auto& materialPair : originalMaterials) { - EditorMaterialComponentSlot* editorMaterialSlot = materialSlotPair.second; - - if (editorMaterialSlot) + // We need to check whether replaced material corresponds to this slot's default material. + const Data::AssetId originalAssetId = materialPair.second.m_materialAsset.GetId(); + if (originalAssetId == exportItem.GetOriginalAssetId()) { - // We need to check whether replaced material corresponds to this slot's default material. - if (editorMaterialSlot->GetDefaultAssetId() == exportItem.GetOriginalAssetId()) + if (m_materialSlotsByLodEnabled || !materialPair.first.IsLodAndSlotId()) { - editorMaterialSlot->SetAsset(assetIdOutcome.GetValue()); + MaterialComponentRequestBus::Event( + GetEntityId(), &MaterialComponentRequestBus::Events::SetMaterialOverride, materialPair.first, + assetIdOutcome.GetValue()); } } } @@ -380,12 +400,9 @@ namespace AZ } } - MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); + UpdateMaterialSlots(); - return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; + return AZ::Edit::PropertyRefreshLevels::EntireTree; } AZ::u32 EditorMaterialComponent::OnLodsToggled() @@ -395,15 +412,10 @@ namespace AZ if (!m_materialSlotsByLodEnabled) { - MaterialComponentConfig config = m_controller.GetConfiguration(); - AZStd::erase_if(config.m_materials, [](const auto& item) { - const auto& [key, value] = item; - return key.m_lodIndex != MaterialAssignmentId::NonLodIndex; - }); - m_controller.SetMaterialOverrides(config.m_materials); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearLodMaterialOverrides); } - MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + UpdateMaterialSlots(); return AZ::Edit::PropertyRefreshLevels::EntireTree; } @@ -440,41 +452,5 @@ namespace AZ { return AZStd::string::format("LOD %d", lodIndex); } - - template - void EditorMaterialComponent::BuildMaterialSlotMap(ComponentType& component, ContainerType& materialSlots) - { - materialSlots[DefaultMaterialAssignmentId] = &component.m_defaultMaterialSlot; - - for (auto& slot : component.m_materialSlots) - { - materialSlots[slot.m_id] = &slot; - } - - if (component.m_materialSlotsByLodEnabled) - { - for (auto& slotsForLod : component.m_materialSlotsByLod) - { - for (auto& slot : slotsForLod) - { - materialSlots[slot.m_id] = &slot; - } - } - } - } - - AZStd::unordered_map EditorMaterialComponent::GetMaterialSlots() - { - AZStd::unordered_map materialSlots; - BuildMaterialSlotMap(*this, materialSlots); - return AZStd::move(materialSlots); - } - - AZStd::unordered_map EditorMaterialComponent::GetMaterialSlots() const - { - AZStd::unordered_map materialSlots; - BuildMaterialSlotMap(*this, materialSlots); - return AZStd::move(materialSlots); - } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h index 6a218e23b7..f8895d994f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h @@ -58,9 +58,6 @@ namespace AZ // controller configuration then those values will be assigned to the editor component slots. void UpdateMaterialSlots(); - // Clears all values related to the material component and regenerates the editor slots - AZ::u32 ResetMaterialSlots(); - // Opens the source material export dialog and updates editor material slots based on // selected actions AZ::u32 OpenMaterialExporter(); @@ -82,10 +79,6 @@ namespace AZ // Evaluate if materials can be edited bool IsEditingAllowed() const; - template - static void BuildMaterialSlotMap(ComponentType& component, ContainerType& materialSlots); - AZStd::unordered_map GetMaterialSlots(); - AZStd::unordered_map GetMaterialSlots() const; AZStd::string GetLabelForLod(int lodIndex) const; AZStd::string m_message; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index f55da28fa6..14cc28b91e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -55,6 +55,10 @@ namespace AZ bool OpenExportDialog(ExportItemsContainer& exportItems) { + // Sort material entries so they are ordered by name in the table + AZStd::sort(exportItems.begin(), exportItems.end(), + [](const auto& a, const auto& b) { return a.GetMaterialSlotName() < b.GetMaterialSlotName(); }); + QWidget* activeWindow = nullptr; AzToolsFramework::EditorWindowRequestBus::BroadcastResult(activeWindow, &AzToolsFramework::EditorWindowRequests::GetAppMainWindow); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 37a9ee7b93..363221d3fc 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -140,7 +140,7 @@ namespace AZ void EditorMaterialComponentSlot::SetAsset(const Data::AssetId& assetId) { - m_materialAsset.Create(assetId); + m_materialAsset = AZ::Data::Asset(assetId, AZ::AzTypeInfo::Uuid()); MaterialComponentRequestBus::Event( m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); OnDataChanged(); @@ -164,7 +164,7 @@ namespace AZ void EditorMaterialComponentSlot::ClearToDefaultAsset() { - m_materialAsset.Create(GetDefaultAssetId()); + m_materialAsset = AZ::Data::Asset(GetDefaultAssetId(), AZ::AzTypeInfo::Uuid()); MaterialComponentRequestBus::Event( m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); ClearOverrides(); @@ -204,7 +204,8 @@ namespace AZ const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { - m_materialAsset.Create(assetIdOutcome.GetValue()); + m_materialAsset = AZ::Data::Asset( + assetIdOutcome.GetValue(), AZ::AzTypeInfo::Uuid()); changed = true; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index 14f81c5021..1d9f1e81dd 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -43,6 +43,11 @@ namespace AZ ->Event("SetDefaultMaterialOverride", &MaterialComponentRequestBus::Events::SetDefaultMaterialOverride) ->Event("GetDefaultMaterialOverride", &MaterialComponentRequestBus::Events::GetDefaultMaterialOverride) ->Event("ClearDefaultMaterialOverride", &MaterialComponentRequestBus::Events::ClearDefaultMaterialOverride) + ->Event("ClearModelMaterialOverrides", &MaterialComponentRequestBus::Events::ClearModelMaterialOverrides) + ->Event("ClearLodMaterialOverrides", &MaterialComponentRequestBus::Events::ClearLodMaterialOverrides) + ->Event("ClearIncompatibleMaterialOverrides", &MaterialComponentRequestBus::Events::ClearIncompatibleMaterialOverrides) + ->Event("ClearInvalidMaterialOverrides", &MaterialComponentRequestBus::Events::ClearInvalidMaterialOverrides) + ->Event("RepairInvalidMaterialOverrides", &MaterialComponentRequestBus::Events::RepairInvalidMaterialOverrides) ->Event("SetMaterialOverride", &MaterialComponentRequestBus::Events::SetMaterialOverride) ->Event("GetMaterialOverride", &MaterialComponentRequestBus::Events::GetMaterialOverride) ->Event("ClearMaterialOverride", &MaterialComponentRequestBus::Events::ClearMaterialOverride) @@ -275,10 +280,10 @@ namespace AZ MaterialAssignmentMap MaterialComponentController::GetOriginalMaterialAssignments() const { - MaterialAssignmentMap materialAssignmentMap; + MaterialAssignmentMap originalMaterials; MaterialReceiverRequestBus::EventResult( - materialAssignmentMap, m_entityId, &MaterialReceiverRequestBus::Events::GetMaterialAssignments); - return materialAssignmentMap; + originalMaterials, m_entityId, &MaterialReceiverRequestBus::Events::GetMaterialAssignments); + return originalMaterials; } MaterialAssignmentId MaterialComponentController::FindMaterialAssignmentId( @@ -348,6 +353,67 @@ namespace AZ } } + void MaterialComponentController::ClearModelMaterialOverrides() + { + AZStd::erase_if(m_configuration.m_materials, [](const auto& materialPair) { + return materialPair.first.IsSlotIdOnly(); + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::ClearLodMaterialOverrides() + { + AZStd::erase_if(m_configuration.m_materials, [](const auto& materialPair) { + return materialPair.first.IsLodAndSlotId(); + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::ClearIncompatibleMaterialOverrides() + { + const MaterialAssignmentMap& originalMaterials = GetOriginalMaterialAssignments(); + AZStd::erase_if(m_configuration.m_materials, [&originalMaterials](const auto& materialPair) { + return originalMaterials.find(materialPair.first) == originalMaterials.end(); + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::ClearInvalidMaterialOverrides() + { + AZStd::erase_if(m_configuration.m_materials, [](const auto& materialPair) { + if (materialPair.second.m_materialAsset.GetId().IsValid()) + { + AZ::Data::AssetInfo assetInfo; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, + materialPair.second.m_materialAsset.GetId()); + return !assetInfo.m_assetId.IsValid(); + } + return false; + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::RepairInvalidMaterialOverrides() + { + for (auto& materialPair : m_configuration.m_materials) + { + if (materialPair.second.m_materialAsset.GetId().IsValid()) + { + AZ::Data::AssetInfo assetInfo; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, + materialPair.second.m_materialAsset.GetId()); + if (!assetInfo.m_assetId.IsValid()) + { + materialPair.second.m_materialAsset = AZ::Data::Asset( + GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo::Uuid()); + } + } + } + LoadMaterials(); + } + void MaterialComponentController::SetDefaultMaterialOverride(const AZ::Data::AssetId& materialAssetId) { SetMaterialOverride(DefaultMaterialAssignmentId, materialAssetId); @@ -363,9 +429,11 @@ namespace AZ ClearMaterialOverride(DefaultMaterialAssignmentId); } - void MaterialComponentController::SetMaterialOverride(const MaterialAssignmentId& materialAssignmentId, const AZ::Data::AssetId& materialAssetId) + void MaterialComponentController::SetMaterialOverride( + const MaterialAssignmentId& materialAssignmentId, const AZ::Data::AssetId& materialAssetId) { - m_configuration.m_materials[materialAssignmentId].m_materialAsset.Create(materialAssetId); + m_configuration.m_materials[materialAssignmentId].m_materialAsset = + AZ::Data::Asset(materialAssetId, AZ::AzTypeInfo::Uuid()); LoadMaterials(); } @@ -616,7 +684,6 @@ namespace AZ void MaterialComponentController::ClearAllPropertyOverrides() { - bool cleared = false; for (auto& materialPair : m_configuration.m_materials) { if (!materialPair.second.m_propertyOverrides.empty()) @@ -625,13 +692,8 @@ namespace AZ materialPair.second.RebuildInstance(); MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialPair.second); QueueMaterialUpdateNotification(); - cleared = true; } } - - if (cleared) - { - } } void MaterialComponentController::SetPropertyOverrides( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index c9dd330412..2bf15ca3b8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -52,6 +52,11 @@ namespace AZ void SetMaterialOverrides(const MaterialAssignmentMap& materials) override; const MaterialAssignmentMap& GetMaterialOverrides() const override; void ClearAllMaterialOverrides() override; + void ClearModelMaterialOverrides() override; + void ClearLodMaterialOverrides() override; + void ClearIncompatibleMaterialOverrides() override; + void ClearInvalidMaterialOverrides() override; + void RepairInvalidMaterialOverrides() override; void SetDefaultMaterialOverride(const AZ::Data::AssetId& materialAssetId) override; const AZ::Data::AssetId GetDefaultMaterialOverride() const override; void ClearDefaultMaterialOverride() override; From de9a27597be342516c8bb02036b214f72bec3aa5 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Mon, 20 Sep 2021 09:49:01 +0100 Subject: [PATCH 190/274] Additional test support for Manipulator Ditto commands (#4191) * additional test support for manipulator ditto Signed-off-by: hultonha * tidy-up to changes Signed-off-by: hultonha * fix for non-unity build compile error Signed-off-by: hultonha --- Code/Editor/EditorToolsApplication.cpp | 16 ++- Code/Editor/EditorToolsApplication.h | 10 ++ Code/Editor/EditorViewportWidget.cpp | 19 ++-- Code/Editor/EditorViewportWidget.h | 4 - .../AzFramework/Viewport/ClickDetector.cpp | 27 ++++- .../AzFramework/Viewport/ClickDetector.h | 14 ++- .../ImmediateModeActionDispatcher.h | 16 +++ .../Source/ImmediateModeActionDispatcher.cpp | 2 + .../Viewport/ViewportMessages.h | 18 ++++ .../EditorTransformComponentSelection.cpp | 19 +++- ...EditorTransformComponentSelectionTests.cpp | 102 +++++++++++++++++- 11 files changed, 220 insertions(+), 27 deletions(-) diff --git a/Code/Editor/EditorToolsApplication.cpp b/Code/Editor/EditorToolsApplication.cpp index 1e5d747e4a..26e608f657 100644 --- a/Code/Editor/EditorToolsApplication.cpp +++ b/Code/Editor/EditorToolsApplication.cpp @@ -34,10 +34,14 @@ namespace EditorInternal : ToolsApplication(argc, argv) { EditorToolsApplicationRequests::Bus::Handler::BusConnect(); + AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusConnect(); + AzToolsFramework::ViewportInteraction::EditorViewportInputTimeNowRequestBus::Handler::BusConnect(); } EditorToolsApplication::~EditorToolsApplication() { + AzToolsFramework::ViewportInteraction::EditorViewportInputTimeNowRequestBus::Handler::BusDisconnect(); + AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusDisconnect(); EditorToolsApplicationRequests::Bus::Handler::BusDisconnect(); Stop(); } @@ -48,7 +52,6 @@ namespace EditorInternal return m_StartupAborted; } - void EditorToolsApplication::RegisterCoreComponents() { AzToolsFramework::ToolsApplication::RegisterCoreComponents(); @@ -274,5 +277,14 @@ namespace EditorInternal Exit(); } -} + AzToolsFramework::ViewportInteraction::KeyboardModifiers EditorToolsApplication::QueryKeyboardModifiers() + { + return AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()); + } + AZStd::chrono::milliseconds EditorToolsApplication::EditorViewportInputTimeNow() + { + const auto now = AZStd::chrono::high_resolution_clock::now(); + return AZStd::chrono::time_point_cast(now).time_since_epoch(); + } +} // namespace EditorInternal diff --git a/Code/Editor/EditorToolsApplication.h b/Code/Editor/EditorToolsApplication.h index 422772cbc4..d4e6223445 100644 --- a/Code/Editor/EditorToolsApplication.h +++ b/Code/Editor/EditorToolsApplication.h @@ -7,7 +7,9 @@ */ #pragma once + #include +#include #include "Core/EditorMetricsPlainTextNameRegistration.h" #include "EditorToolsApplicationAPI.h" @@ -19,6 +21,8 @@ namespace EditorInternal class EditorToolsApplication : public AzToolsFramework::ToolsApplication , public EditorToolsApplicationRequests::Bus::Handler + , public AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler + , public AzToolsFramework::ViewportInteraction::EditorViewportInputTimeNowRequestBus::Handler { public: EditorToolsApplication(int* argc, char*** argv); @@ -44,6 +48,12 @@ namespace EditorInternal void CreateReflectionManager() override; void Reflect(AZ::ReflectContext* context) override; + // EditorModifierKeyRequestBus overrides ... + AzToolsFramework::ViewportInteraction::KeyboardModifiers QueryKeyboardModifiers() override; + + // EditorViewportInputTimeNowRequestBus overrides ... + AZStd::chrono::milliseconds EditorViewportInputTimeNow() override; + protected: // From EditorToolsApplicationRequests bool OpenLevel(AZStd::string_view levelName) override; diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 1ed901e514..5b5b52d28f 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -744,11 +744,15 @@ void EditorViewportWidget::RenderAll() { namespace AztfVi = AzToolsFramework::ViewportInteraction; + AztfVi::KeyboardModifiers keyboardModifiers; + AztfVi::EditorModifierKeyRequestBus::BroadcastResult( + keyboardModifiers, &AztfVi::EditorModifierKeyRequestBus::Events::QueryKeyboardModifiers); + m_debugDisplay->DepthTestOff(); m_manipulatorManager->DrawManipulators( *m_debugDisplay, GetCameraState(), BuildMouseInteractionInternal( - AztfVi::MouseButtons(AztfVi::TranslateMouseButtons(QGuiApplication::mouseButtons())), QueryKeyboardModifiers(), + AztfVi::MouseButtons(AztfVi::TranslateMouseButtons(QGuiApplication::mouseButtons())), keyboardModifiers, BuildMousePick(WidgetToViewport(mapFromGlobal(QCursor::pos()))))); m_debugDisplay->DepthTestOn(); } @@ -959,12 +963,13 @@ QWidget* EditorViewportWidget::GetWidgetForViewportContextMenu() bool EditorViewportWidget::ShowingWorldSpace() { - return QueryKeyboardModifiers().Shift(); -} + namespace AztfVi = AzToolsFramework::ViewportInteraction; -AzToolsFramework::ViewportInteraction::KeyboardModifiers EditorViewportWidget::QueryKeyboardModifiers() -{ - return AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()); + AztfVi::KeyboardModifiers keyboardModifiers; + AztfVi::EditorModifierKeyRequestBus::BroadcastResult( + keyboardModifiers, &AztfVi::EditorModifierKeyRequestBus::Events::QueryKeyboardModifiers); + + return keyboardModifiers.Shift(); } void EditorViewportWidget::SetViewportId(int id) @@ -1039,7 +1044,6 @@ void EditorViewportWidget::ConnectViewportInteractionRequestBus() { AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId()); - AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusConnect(); m_viewportUi.ConnectViewportUiBus(GetViewportId()); AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect(); @@ -1050,7 +1054,6 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus() AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect(); m_viewportUi.DisconnectViewportUiBus(); - AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect(); AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect(); } diff --git a/Code/Editor/EditorViewportWidget.h b/Code/Editor/EditorViewportWidget.h index 6b46524394..49930a2a13 100644 --- a/Code/Editor/EditorViewportWidget.h +++ b/Code/Editor/EditorViewportWidget.h @@ -92,7 +92,6 @@ class SANDBOX_API EditorViewportWidget final , private AzFramework::InputSystemCursorConstraintRequestBus::Handler , private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler , private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler - , private AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler , private AzFramework::AssetCatalogEventBus::Handler , private AZ::RPI::SceneNotificationBus::Handler { @@ -212,9 +211,6 @@ private: // EditorEntityViewportInteractionRequestBus overrides ... void FindVisibleEntities(AZStd::vector& visibleEntities) override; - // EditorModifierKeyRequestBus overrides ... - AzToolsFramework::ViewportInteraction::KeyboardModifiers QueryKeyboardModifiers() override; - // Camera::EditorCameraRequestBus overrides ... void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.cpp index b909689c22..1b3645630e 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.cpp @@ -9,8 +9,19 @@ #include #include +#include + namespace AzFramework { + ClickDetector::ClickDetector() + { + m_timeNowFn = [] + { + const auto now = AZStd::chrono::high_resolution_clock::now(); + return AZStd::chrono::time_point_cast(now).time_since_epoch(); + }; + } + ClickDetector::ClickOutcome ClickDetector::DetectClick(const ClickEvent clickEvent, const ScreenVector& cursorDelta) { const auto previousDetectionState = m_detectionState; @@ -26,11 +37,13 @@ namespace AzFramework if (clickEvent == ClickEvent::Down) { - const auto now = std::chrono::steady_clock::now(); + const auto now = m_timeNowFn(); if (m_tryBeginTime) { - const std::chrono::duration diff = now - m_tryBeginTime.value(); - if (diff.count() < m_doubleClickInterval) + using FloatingPointSeconds = AZStd::chrono::duration; + + const auto diff = now - m_tryBeginTime.value(); + if (FloatingPointSeconds(diff).count() < m_doubleClickInterval) { return ClickOutcome::Nil; } @@ -43,7 +56,8 @@ namespace AzFramework } else if (clickEvent == ClickEvent::Up) { - const auto clickOutcome = [detectionState = m_detectionState] { + const auto clickOutcome = [detectionState = m_detectionState] + { if (detectionState == DetectionState::WaitingForMove) { return ClickOutcome::Click; @@ -66,4 +80,9 @@ namespace AzFramework return ClickOutcome::Nil; } + + void ClickDetector::OverrideTimeNowFn(AZStd::function timeNowFn) + { + m_timeNowFn = AZStd::move(timeNowFn); + } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.h b/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.h index f95924550a..70bdeb4619 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/ClickDetector.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -21,10 +22,9 @@ namespace AzFramework //! (mouse down with movement and then mouse up). class ClickDetector { - //! Alias for recording time of mouse down events - using Time = std::chrono::time_point; - public: + ClickDetector(); + //! Internal representation of click event (map from external event for this when //! calling DetectClick). enum class ClickEvent @@ -51,6 +51,10 @@ namespace AzFramework void SetDoubleClickInterval(float doubleClickInterval); //! Override the dead zone before a 'move' outcome will be triggered. void SetDeadZone(float deadZone); + //! Override how the current time is retrieved. + //! This is helpful to override when it comes to simulating different passages of + //! time to avoid double click issues in tests for example. + void OverrideTimeNowFn(AZStd::function timeNowFn); private: //! Internal state of ClickDetector based on incoming events. @@ -65,7 +69,9 @@ namespace AzFramework float m_deadZone = 2.0f; //!< How far to move before a click is cancelled (when Move will fire). float m_doubleClickInterval = 0.4f; //!< Default double click interval, can be overridden. DetectionState m_detectionState; //!< Internal state of ClickDetector. - AZStd::optional
Material Slot %1
Entity %1
Material Slot %1
Material %1