diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index d31ea6334c..6d3727195e 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -25,10 +25,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/physics/TestSuite_Main.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets COMPONENT @@ -39,10 +38,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/physics/TestSuite_Periodic.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets COMPONENT @@ -56,7 +54,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TIMEOUT 3600 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets COMPONENT @@ -71,10 +68,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets COMPONENT @@ -85,10 +81,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE sandbox TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/scripting/TestSuite_Sandbox.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets ) @@ -101,10 +96,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/WhiteBox/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets COMPONENT @@ -120,10 +114,9 @@ endif() # TEST_SUITE main # TEST_SERIAL # PATH ${CMAKE_CURRENT_LIST_DIR}/NvCloth/TestSuite_Active.py -# TIMEOUT 3600 +# TIMEOUT 1500 # RUNTIME_DEPENDENCIES # Legacy::Editor -# Legacy::CryRenderNULL # AZ::AssetProcessor # AutomatedTesting.Assets # ) @@ -136,10 +129,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE sandbox TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/EditorPythonBindings - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets Gem::EditorPythonBindings.Editor @@ -154,10 +146,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/PythonAssetBuilder - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets Gem::EditorPythonBindings.Editor @@ -173,7 +164,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) TEST_SUITE main TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor AZ::AssetProcessor @@ -196,7 +187,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/dyn_veg PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark" - TIMEOUT 36000 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -212,7 +203,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE sandbox PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/dyn_veg PYTEST_MARKS "SUITE_sandbox" - TIMEOUT 36000 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -228,7 +219,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/dyn_veg PYTEST_MARKS "SUITE_periodic" - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -244,7 +235,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE main PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/landscape_canvas PYTEST_MARKS "not SUITE_sandbox and not SUITE_periodic and not SUITE_benchmark" - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -259,7 +250,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/landscape_canvas PYTEST_MARKS "SUITE_periodic" - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -274,7 +265,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SERIAL TEST_SUITE periodic PATH ${CMAKE_CURRENT_LIST_DIR}/largeworlds/gradient_signal - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES AZ::AssetProcessor Legacy::Editor @@ -292,10 +283,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ TEST_SUITE periodic TEST_SERIAL PATH ${CMAKE_CURRENT_LIST_DIR}/editor - TIMEOUT 3600 + TIMEOUT 1500 RUNTIME_DEPENDENCIES Legacy::Editor - Legacy::CryRenderNULL AZ::AssetProcessor AutomatedTesting.Assets COMPONENT @@ -314,7 +304,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) # AZ::AssetProcessor # AZ::AssetProcessorBatch # AutomatedTesting.GameLauncher - # Legacy::CryRenderNULL #) endif() diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt index de3e04e67e..6a865ee690 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt @@ -100,7 +100,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL - TIMEOUT 3600 + TIMEOUT 1500 TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessor @@ -123,7 +123,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL - TIMEOUT 3600 + TIMEOUT 1500 TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessorBatch diff --git a/Code/CryEngine/CMakeLists.txt b/Code/CryEngine/CMakeLists.txt index 1735224146..38fcbf4a27 100644 --- a/Code/CryEngine/CMakeLists.txt +++ b/Code/CryEngine/CMakeLists.txt @@ -9,8 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -add_subdirectory(Cry3DEngine) add_subdirectory(CryCommon) add_subdirectory(CryFont) add_subdirectory(CrySystem) -add_subdirectory(RenderDll) diff --git a/Code/CryEngine/CryCommon/CREGeomCache.h b/Code/CryEngine/CryCommon/CREGeomCache.h index 089915988e..6911b8486e 100644 --- a/Code/CryEngine/CryCommon/CREGeomCache.h +++ b/Code/CryEngine/CryCommon/CREGeomCache.h @@ -19,7 +19,7 @@ #if defined(USE_GEOM_CACHES) -#include "../RenderDll/Common/Shaders/Vertex.h" +#include #include class CREGeomCache diff --git a/Code/CryEngine/CryCommon/CRESky.h b/Code/CryEngine/CryCommon/CRESky.h index e1ef7bcaa8..3dfc7d184f 100644 --- a/Code/CryEngine/CryCommon/CRESky.h +++ b/Code/CryEngine/CryCommon/CRESky.h @@ -17,7 +17,7 @@ //============================================================= #include "VertexFormats.h" -#include "../RenderDll/Common/Shaders/Vertex.h" +#include struct SSkyLightRenderParams; diff --git a/Code/CryEngine/CryCommon/IIndexedMesh.h b/Code/CryEngine/CryCommon/IIndexedMesh.h index 9d0d77ffc8..d7ba19ae6c 100644 --- a/Code/CryEngine/CryCommon/IIndexedMesh.h +++ b/Code/CryEngine/CryCommon/IIndexedMesh.h @@ -22,7 +22,7 @@ #include #include // for AABB #include -#include <../RenderDll/Common/Shaders/Vertex.h> +#include #include // Description: diff --git a/Code/CryEngine/CryCommon/IShader.h b/Code/CryEngine/CryCommon/IShader.h index d284394904..1e8553ac57 100644 --- a/Code/CryEngine/CryCommon/IShader.h +++ b/Code/CryEngine/CryCommon/IShader.h @@ -26,7 +26,7 @@ #include "smartptr.h" #include // <> required for Interfuscator #include "VertexFormats.h" -#include +#include #include #include diff --git a/Code/CryEngine/CryCommon/Vertex.h b/Code/CryEngine/CryCommon/Vertex.h new file mode 100644 index 0000000000..44edd73903 --- /dev/null +++ b/Code/CryEngine/CryCommon/Vertex.h @@ -0,0 +1,1093 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once +#include +#include +#include +namespace AZ +{ + namespace Vertex + { + const uint32_t VERTEX_BUFFER_ALIGNMENT = 4; + // This enum must only have 8 entries because only 3 bits are used to store usage. + enum class AttributeUsage : uint8 + { + Position, + Color, + Normal, + TexCoord, + Weights, + Indices, + Tangent, + BiTangent, + NumUsages + }; + + struct AttributeUsageData + { + AZStd::string friendlyName; + AZStd::string semanticName; + }; + + static AttributeUsageData AttributeUsageDataTable[(uint)AttributeUsage::NumUsages] = + { + // {friendlyName, semanticName} + { "Position", "POSITION" }, + { "Color", "COLOR" }, + { "Normal", "NORMAL" }, + { "TexCoord", "TEXCOORD" }, + { "Weights", "BLENDWEIGHT" }, + { "Indices", "BLENDINDICES" }, + { "Tangent", "TEXCOORD" }, + { "BiTangent", "TEXCOORD" } + }; + + // This enum must have 32 or less entries as 5 bits are used to store type. + enum class AttributeType : uint8 + { + Float16_1 = 0, + Float16_2, + Float16_4, + + Float32_1, + Float32_2, + Float32_3, + Float32_4, + + Byte_1, + Byte_2, + Byte_4, + + Short_1, + Short_2, + Short_4, + + UInt16_1, + UInt16_2, + UInt16_4, + + UInt32_1, + UInt32_2, + UInt32_3, + UInt32_4, + + NumTypes + }; + + struct AttributeTypeData + { + AZStd::string friendlyName; + uint8 byteSize; + }; + + static AttributeTypeData AttributeTypeDataTable[(unsigned int)AZ::Vertex::AttributeType::NumTypes] = + { + { "Float16_1", 2 }, + { "Float16_2", 4 }, + { "Float16_4", 8 }, + + { "Float32_1", 4 }, + { "Float32_2", 8 }, + { "Float32_3", 12 }, + { "Float32_4", 16 }, + + { "Byte_1", 1 }, + { "Byte_2", 2 }, + { "Byte_4", 4 }, + + { "Short_1", 2 }, + { "Short_2", 4 }, + { "Short_4", 8 }, + + { "UInt16_1", 2 }, + { "UInt16_2", 4 }, + { "UInt16_4", 8 }, + + { "UInt32_1", 4 }, + { "UInt32_2", 8 }, + { "UInt32_3", 12 }, + { "UInt32_4", 16 }, + }; + + //! Stores the usage, type, and byte length of an individual vertex attribute + class Attribute + { + public: + // Usage stored in the 3 lower bits and Type stored in the 5 upper bits. + static const uint8 kUsageBitCount = 3; + static const uint8 kUsageMask = 0x07; + static const uint8 kTypeMask = 0xf8; + static uint8 CreateAttribute(AttributeUsage usage, AttributeType type) + { + return (static_cast(type) << kUsageBitCount) | static_cast(usage); + } + static AttributeUsage GetUsage(const uint8 attribute) + { + return static_cast(attribute & kUsageMask); + } + static AttributeType GetType(const uint8 attribute) + { + return static_cast((attribute & kTypeMask) >> kUsageBitCount); + } + static uint8 GetByteLength(const uint8 attribute) + { + return AttributeTypeDataTable[(uint)GetType(attribute)].byteSize; + } + static const AZStd::string& GetSemanticName(uint8 attribute) + { + return AttributeUsageDataTable[(uint)GetUsage(attribute)].semanticName; + } + }; + + //! Flexible vertex format class + class Format + { + public: + Format(){}; + + + //! Conversion from old hard-coded EVertexFormat enum to new, flexible vertex class + Format(EVertexFormat format) + { + m_enum = eVF_Unknown; + m_numAttributes = 0; + switch (format) + { + case eVF_Unknown: + m_enum = eVF_Unknown; + break; + case eVF_P3F_C4B_T2F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + m_enum = eVF_P3F_C4B_T2F; + break; + case eVF_P3F_C4B_T2F_T2F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + m_enum = eVF_P3F_C4B_T2F_T2F; + break; + case eVF_P3S_C4B_T2S: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4 + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); + m_enum = eVF_P3S_C4B_T2S; + break; + case eVF_P3S_C4B_T2S_T2S: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4 + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); + m_enum = eVF_P3S_C4B_T2S_T2S; + break; + case eVF_P3S_N4B_C4B_T2S: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_4));// vec3f16 is backed by a CryHalf4 + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Normal, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); + m_enum = eVF_P3S_N4B_C4B_T2S; + break; + case eVF_P3F_C4B_T4B_N3F2: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Tangent, AttributeType::Float32_3));//x-axis + AddAttribute(Attribute::CreateAttribute(AttributeUsage::BiTangent, AttributeType::Float32_3));//y-axis +#ifdef PARTICLE_MOTION_BLUR // Nonfunctional and disabled. + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3));//prevPos + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Tangent, AttributeType::Float32_3));//prevXTan + AddAttribute(Attribute::CreateAttribute(AttributeUsage::BiTangent, AttributeType::Float32_3));//prevYTan +#endif + m_enum = eVF_P3F_C4B_T4B_N3F2;// Particles. + break; + case eVF_TP3F_C4B_T2F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + m_enum = eVF_TP3F_C4B_T2F;// Fonts (28 bytes). + break; + case eVF_TP3F_T2F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_TP3F_T2F_T3F; + break; + case eVF_P3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_T3F; // Miscellaneus. + break; + case eVF_P3F_T2F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_T2F_T3F; + break; + // Additional streams + case eVF_T2F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + m_enum = eVF_T2F; // Light maps TC (8 bytes). + break; + case eVF_W4B_I4S:// Skinned weights/indices stream. + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::UInt16_4)); + m_enum = eVF_W4B_I4S; + break; + case eVF_C4B_C4B:// SH coefficients. + // We use the "Weights" usage since sh coefs use an unknown usage of 4 bytes. + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4)); //coef0 + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Weights, AttributeType::Byte_4)); //coef1 + m_enum = eVF_C4B_C4B; + break; + case eVF_P3F_P3F_I4B:// Shape deformation stream. + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); //thin + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); //fat + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::Byte_4)); + m_enum = eVF_P3F_P3F_I4B; + break; + case eVF_P3F:// Velocity stream. + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + m_enum = eVF_P3F; + break; + case eVF_C4B_T2S: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); + m_enum = eVF_C4B_T2S;// General (Position is merged with Tangent stream) + break; + case eVF_P2F_T4F_C4F: // Lens effects simulation + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + m_enum = eVF_P2F_T4F_C4F; + break; + case eVF_P2F_T4F_T4F_C4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + m_enum = eVF_P2F_T4F_T4F_C4F; + break; + case eVF_P2S_N4B_C4B_T1F:// terrain + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float16_2));// xy-coordinates in terrain + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Normal, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1));// z-coordinate in terrain + m_enum = eVF_P2S_N4B_C4B_T1F; + break; + case eVF_P3F_C4B_T2S: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float16_2)); + m_enum = eVF_P3F_C4B_T2S; + break; + case eVF_P2F_C4B_T2F_F4B: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Indices, AttributeType::UInt16_2)); + m_enum = eVF_P2F_C4B_T2F_F4B; + break; + case eVF_P3F_C4B: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Byte_4)); + m_enum = eVF_P3F_C4B; + break; + case eVF_P3F_C4F_T2F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + m_enum = eVF_P3F_C4F_T2F; + break; + case eVF_P3F_C4F_T2F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T3F; + break; + case eVF_P3F_C4F_T2F_T3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T3F_T3F; + break; + case eVF_P3F_C4F_T2F_T1F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + m_enum = eVF_P3F_C4F_T2F_T1F; + break; + case eVF_P3F_C4F_T2F_T1F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T1F_T3F; + break; + case eVF_P3F_C4F_T2F_T1F_T3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T3F; + break; + case eVF_P3F_C4F_T4F_T2F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + m_enum = eVF_P3F_C4F_T4F_T2F; + break; + case eVF_P3F_C4F_T4F_T2F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T4F_T2F_T3F; + break; + case eVF_P3F_C4F_T4F_T2F_T3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T3F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F; + break; + case eVF_P4F_T2F_C4F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P4F_T2F_C4F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T4F; + break; + case eVF_P3F_C4F_T2F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T3F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T3F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T1F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T1F_T4F; + break; + case eVF_P3F_C4F_T2F_T1F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F; + break; + case eVF_P4F_T2F_C4F_T4F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P4F_T2F_C4F_T4F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T3F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T3F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T1F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T1F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T1F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T1F_T3F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T4F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T3F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T4F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T4F_T2F_T1F_T3F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T3F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T4F_T4F; + break; + case eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_1)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_3)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P3F_C4F_T2F_T2F_T1F_T1F_T3F_T3F_T4F_T4F; + break; + case eVF_P4F_T2F_C4F_T4F_T4F_T4F_T4F: + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Position, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_2)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::Color, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + AddAttribute(Attribute::CreateAttribute(AttributeUsage::TexCoord, AttributeType::Float32_4)); + m_enum = eVF_P4F_T2F_C4F_T4F_T4F_T4F_T4F; + break; + case eVF_Max: + default: + AZ_Error("VF", false, "Invalid vertex format"); + m_enum = eVF_Unknown; + } + CalculateStrideAndUsageCounts(); + } + + //! Get the equivalent old-style EVertexFormat enum + uint GetEnum() const { return m_enum; } + + static const uint8 kHas16BitFloatPosition = 0x4; + static const uint8 kHas16BitFloatTexCoords = 0x2; + static const uint8 kHas32BitFloatTexCoords = 0x1; + + + //! Helper function to check to see if the vertex format has a position attribute that uses 16 bit floats for the underlying type + bool Has16BitFloatPosition() const + { + return (m_flags & kHas16BitFloatPosition) != 0x0; + } + + //! Helper function to check to see if the vertex format has a texture coordinate attribute that uses 16 bit floats for the underlying type + bool Has16BitFloatTextureCoordinates() const + { + return (m_flags & kHas16BitFloatTexCoords) != 0x0; + } + + //! Helper function to check to see if the vertex format has a texture coordinate attribute that uses 32 bit floats for the underlying type + bool Has32BitFloatTextureCoordinates() const + { + return (m_flags & kHas32BitFloatTexCoords) != 0x0; + } + + + uint32 GetAttributeUsageCount(AttributeUsage usage) const + { + return (uint32)m_attributeUsageCounts[(uint)usage]; + } + + bool TryGetAttributeOffsetAndType(AttributeUsage usage, uint32 index, uint& outOffset, AttributeType& outType) const + { + outOffset = 0; + outType = AttributeType::NumTypes; + for (uint ii=0; ii < m_numAttributes; ++ii) + { + uint8 attribute = m_vertexAttributes[ii]; + if (Attribute::GetUsage(attribute) == usage) + { + if (index == 0) + { + outType = Attribute::GetType(attribute); + return true; + } + else + { + --index; + } + } + outOffset += Attribute::GetByteLength(attribute); + } + return false; + } + + uint8 GetAttributeByteLength(AttributeUsage usage) const + { + for (uint ii = 0; ii < m_numAttributes; ++ii) + { + uint8 attribute = m_vertexAttributes[ii]; + if (Attribute::GetUsage(attribute) == usage) + { + return Attribute::GetByteLength(attribute); + } + } + return 0; + } + + + const uint8* GetAttributes( uint32 &outCount) const + { + outCount = m_numAttributes; + return m_vertexAttributes; + } + + //! Return true if the vertex format is a superset of the input + bool IsSupersetOf(const AZ::Vertex::Format& input) const + { + uint32 count = 0; + const uint8* attributes = input.GetAttributes(count); + for ( uint8 ii=0; ii(const Format& other) const + { + return !(*this <= other); + } + bool operator>=(const Format& other) const + { + return (*this == other || *this > other); + } + private: + void AddAttribute(uint8 attribute) + { + AZ_Assert(m_numAttributes < kMaxAttributes, "Too many attributes added. Change the size of kMaxAttributes"); + m_vertexAttributes[m_numAttributes++] = attribute; + + // Update the flags. + AttributeUsage usage = Attribute::GetUsage(attribute); + AttributeType type = Attribute::GetType(attribute); + if (usage == AttributeUsage::TexCoord) + { + if (type == AttributeType::Float16_2) { + m_flags |= kHas16BitFloatTexCoords; + } + else if (type == AttributeType::Float32_2 || type == AttributeType::Float32_3 || type == AttributeType::Float32_4) { + m_flags |= kHas32BitFloatTexCoords; + } + } + else if (usage == AttributeUsage::Position && type == AttributeType::Float16_4) { + m_flags |= kHas16BitFloatPosition; + } + } + + //! Calculates the sum of the size in bytes of all attributes that make up this format + void CalculateStrideAndUsageCounts() + { + static_assert((uint32)AttributeUsage::NumUsages <= 8, "We use 3 bits to represent usage so we only support 8 usages for a vertex format attribute."); + static_assert((uint32)AttributeType::NumTypes <= 32, "We use 5 bits to represent type so we only support up to 32 types for a vertex format attribute."); + + for (uint index = 0; index < (uint)AttributeUsage::NumUsages; ++index) + { + m_attributeUsageCounts[index] = 0; + } + uint32 stride = 0; + for (uint ii = 0; ii < m_numAttributes; ++ii) + { + uint8 attribute = m_vertexAttributes[ii]; + stride += Attribute::GetByteLength(attribute); + m_attributeUsageCounts[(uint)Attribute::GetUsage(attribute)]++; + } + AZ_Assert(stride < (0x1 << (sizeof(m_stride) * 8)), "Vertex stride is larger than the maximum supported, update the type for m_stride in Vertex.h"); + + m_stride = stride; + } + + + +#ifdef PARTICLE_MOTION_BLUR + static const uint32_t kMaxAttributes = 8; +#else + static const uint32_t kMaxAttributes = 10; +#endif + uint8 m_vertexAttributes[kMaxAttributes] = { 0 }; + + uint8 m_attributeUsageCounts[(uint)AttributeUsage::NumUsages] = { 0 }; + uint8 m_numAttributes = 0; + uint8 m_enum = eVF_Unknown; + uint8 m_stride = 0; + uint8 m_flags = 0x0; + }; + + + // bNeedNormals=1 - float normals; bNeedNormals=2 - byte normals //waltont TODO (this was copied as is from vertexformats.h) this comment is out of date and the function does not even use all the parameters. This should be replaceable with the new vertex class, and should be replaced when refactoring CHWShader_D3D::mfVertexFormat which handles the shader parsing/serialization + _inline Format VertFormatForComponents([[maybe_unused]] bool bNeedCol, [[maybe_unused]] bool bHasTC, bool bHasTC2, bool bHasPS, bool bHasNormal) + { + AZ::Vertex::Format RequestedVertFormat; + + if (bHasPS) + { + RequestedVertFormat = AZ::Vertex::Format(eVF_P3F_C4B_T4B_N3F2); + } + else + if (bHasNormal) + { + RequestedVertFormat = AZ::Vertex::Format(eVF_P3S_N4B_C4B_T2S); + } + else + { + if (!bHasTC2) + { + RequestedVertFormat = AZ::Vertex::Format(eVF_P3S_C4B_T2S); + } + else + { + RequestedVertFormat = AZ::Vertex::Format(eVF_P3F_C4B_T2F_T2F); + } + } + + return RequestedVertFormat; + } + } +} diff --git a/Code/CryEngine/CrySystem/CMakeLists.txt b/Code/CryEngine/CrySystem/CMakeLists.txt index 32ddc4a3a5..e7816cc1cd 100644 --- a/Code/CryEngine/CrySystem/CMakeLists.txt +++ b/Code/CryEngine/CrySystem/CMakeLists.txt @@ -60,8 +60,6 @@ ly_add_target( Legacy::CrySystem.XMLBinary Legacy::RemoteConsoleCore AZ::AzFramework - RUNTIME_DEPENDENCIES - Legacy::Cry3DEngine ) ly_add_source_properties( diff --git a/Code/CryEngine/CrySystem/Platform/Mac/platform_mac.cmake b/Code/CryEngine/CrySystem/Platform/Mac/platform_mac.cmake index 6c55ad5b08..bafe20e506 100644 --- a/Code/CryEngine/CrySystem/Platform/Mac/platform_mac.cmake +++ b/Code/CryEngine/CrySystem/Platform/Mac/platform_mac.cmake @@ -14,14 +14,3 @@ # NOTE: functions in cmake are global, therefore adding functions to this file # is being avoided to prevent overriding functions declared in other targets platfrom # specific cmake files - -if (LY_MONOLITHIC_GAME) # Only Atom is supported in monolithic builds - set(LY_BUILD_DEPENDENCIES - PUBLIC - Legacy::CryRenderOther - ) -else() - set(LY_RUNTIME_DEPENDENCIES - Legacy::CryRenderMetal - ) -endif() diff --git a/Code/CryEngine/CrySystem/SystemRender.cpp b/Code/CryEngine/CrySystem/SystemRender.cpp index 01828175db..a544cef4a5 100644 --- a/Code/CryEngine/CrySystem/SystemRender.cpp +++ b/Code/CryEngine/CrySystem/SystemRender.cpp @@ -58,75 +58,6 @@ extern CMTSafeHeap* g_pPakHeap; #if defined(AZ_PLATFORM_ANDROID) #include -#elif defined(AZ_PLATFORM_IOS) - -#if defined(AZ_MONOLITHIC_BUILD) -extern bool UIKitGetPrimaryPhysicalDisplayDimensions(int& o_widthPixels, int& o_heightPixels); -#else - -using NativeScreenType = UIScreen; -using NativeWindowType = UIWindow; - -//////////////////////////////////////////////////////////////////////////////// -bool UIKitGetPrimaryPhysicalDisplayDimensions(int& o_widthPixels, int& o_heightPixels) -{ - - NativeScreenType* nativeScreen = [NativeScreenType mainScreen]; - CGRect screenBounds = [nativeScreen bounds]; - CGFloat screenScale = [nativeScreen scale]; - o_widthPixels = static_cast(screenBounds.size.width * screenScale); - o_heightPixels = static_cast(screenBounds.size.height * screenScale); - - const bool isScreenLandscape = o_widthPixels > o_heightPixels; - - UIInterfaceOrientation uiOrientation = UIInterfaceOrientationUnknown; -#if defined(__IPHONE_13_0) || defined(__TVOS_13_0) - if(@available(iOS 13.0, tvOS 13.0, *)) - { - UIWindow* foundWindow = nil; - - //Find the key window - NSArray* windows = [[UIApplication sharedApplication] windows]; - for (UIWindow* window in windows) - { - if (window.isKeyWindow) - { - foundWindow = window; - break; - } - } - - //Check if the key window is found - if(foundWindow) - { - uiOrientation = foundWindow.windowScene.interfaceOrientation; - } - else - { - //If no key window is found create a temporary window in order to extract the orientation - //This can happen as this function gets called before the renderer is initialized - CGRect screenBounds = [[NativeScreenType mainScreen] bounds]; - UIWindow* tempWindow = [[NativeWindowType alloc] initWithFrame: screenBounds]; - uiOrientation = tempWindow.windowScene.interfaceOrientation; - [tempWindow release]; - } - } -#else - uiOrientation = UIApplication.sharedApplication.statusBarOrientation; -#endif - - const bool isInterfaceLandscape = UIInterfaceOrientationIsLandscape(uiOrientation); - if (isScreenLandscape != isInterfaceLandscape) - { - const int width = o_widthPixels; - o_widthPixels = o_heightPixels; - o_heightPixels = width; - } - - return true; -} -#endif - #endif extern int CryMemoryGetAllocatedSize(); @@ -151,8 +82,6 @@ bool CSystem::GetPrimaryPhysicalDisplayDimensions([[maybe_unused]] int& o_widthP return true; #elif defined(AZ_PLATFORM_ANDROID) return AZ::Android::Utils::GetWindowSize(o_widthPixels, o_heightPixels); -#elif defined(AZ_PLATFORM_IOS) - return UIKitGetPrimaryPhysicalDisplayDimensions(o_widthPixels, o_heightPixels); #else return false; #endif diff --git a/Code/Framework/AzCore/AzCore/AzCoreModule.cpp b/Code/Framework/AzCore/AzCore/AzCoreModule.cpp index 3c93ae5561..3d074455cc 100644 --- a/Code/Framework/AzCore/AzCore/AzCoreModule.cpp +++ b/Code/Framework/AzCore/AzCore/AzCoreModule.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +42,6 @@ namespace AZ AssetManagerComponent::CreateDescriptor(), UserSettingsComponent::CreateDescriptor(), Debug::FrameProfilerComponent::CreateDescriptor(), - NativeUI::NativeUISystemComponent::CreateDescriptor(), SliceComponent::CreateDescriptor(), SliceSystemComponent::CreateDescriptor(), SliceMetadataInfoComponent::CreateDescriptor(), diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index c55f565615..d0f277a6b8 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -28,6 +28,8 @@ #include #include +#include + #include #include #include @@ -424,7 +426,7 @@ namespace AZ // Now that the Allocators are initialized, the Command Line parameters can be parsed m_commandLine.Parse(m_argC, m_argV); - ParseCommandLine(m_commandLine); + SettingsRegistryMergeUtils::ParseCommandLine(m_commandLine); // Create the settings registry and register it with the AZ interface system // This is done after the AppRoot has been calculated so that the Bootstrap.cfg @@ -527,10 +529,42 @@ namespace AZ DestroyAllocator(); } + + void ReportBadEngineRoot() + { + AZStd::string errorMessage = {"Unable to determine a valid path to the engine.\n" + "Check parameters such as --project-path and --engine-path and make sure they are valid.\n"}; + if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr) + { + AZ::SettingsRegistryInterface::FixedValueString filePathErrorStr; + if (registry->Get(filePathErrorStr, AZ::SettingsRegistryMergeUtils::FilePathKey_ErrorText); !filePathErrorStr.empty()) + { + errorMessage += "Additional Info:\n"; + errorMessage += filePathErrorStr.c_str(); + } + } + + if (auto nativeUI = AZ::Interface::Get(); nativeUI != nullptr) + { + nativeUI->DisplayOkDialog("O3DE Fatal Error", errorMessage.c_str(), false); + } + else + { + AZ_Error("ComponentApplication", false, "O3DE Fatal Error: %s\n", errorMessage.c_str()); + } + } + + Entity* ComponentApplication::Create(const Descriptor& descriptor, const StartupParameters& startupParameters) { AZ_Assert(!m_isStarted, "Component application already started!"); + if (m_engineRoot.empty()) + { + ReportBadEngineRoot(); + return nullptr; + } + m_startupParameters = startupParameters; m_descriptor = descriptor; @@ -871,46 +905,6 @@ namespace AZ } } - void ComponentApplication::ParseCommandLine(const AZ::CommandLine& commandLine) - { - struct OptionKeyToRegsetKey - { - AZStd::string_view m_optionKey; - AZStd::string m_regsetKey; - }; - - // Provide overrides for the engine root, the project root and the project cache root - AZStd::array commandOptions = { - OptionKeyToRegsetKey{ "engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) }, - OptionKeyToRegsetKey{ "project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) }, - OptionKeyToRegsetKey{ "project-cache-path", AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) } - }; - - AZStd::fixed_vector overrideArgs; - - for (auto&& [optionKey, regsetKey] : commandOptions) - { - if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0) - { - // Use the last supplied command option value to override previous values - auto overrideArg = AZStd::string::format(R"(--regset="%s=%s")", regsetKey.c_str(), - commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str()); - overrideArgs.emplace_back(AZStd::move(overrideArg)); - } - } - - if (!overrideArgs.empty()) - { - // Dump the input command line, add the additional option overrides - // and Parse the new command line into the Component Application command line - AZ::CommandLine::ParamContainer commandLineArgs; - commandLine.Dump(commandLineArgs); - commandLineArgs.insert(commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()), - AZStd::make_move_iterator(overrideArgs.end())); - m_commandLine.Parse(commandLineArgs); - } - } - void ComponentApplication::MergeSettingsToRegistry(SettingsRegistryInterface& registry) { SettingsRegistryInterface::Specializations specializations; diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h index 3ebcf39d95..8617aa5f2e 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.h @@ -328,9 +328,6 @@ namespace AZ /// Create the drillers void CreateDrillers(); - /// Parse ComponentApplication specific command line arguments - void ParseCommandLine(const AZ::CommandLine& commandLine); - virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry); //! Sets the specializations that will be used when loading the Settings Registry. Extend this in derived diff --git a/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h b/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h index 5055540874..f45295d221 100644 --- a/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h +++ b/Code/Framework/AzCore/AzCore/NativeUI/NativeUIRequests.h @@ -15,45 +15,49 @@ #include #include -namespace AZ +namespace AZ::NativeUI { - namespace NativeUI + enum AssertAction { - enum AssertAction - { - IGNORE_ASSERT = 0, - IGNORE_ALL_ASSERTS, - BREAK, - NONE, - }; + IGNORE_ASSERT = 0, + IGNORE_ALL_ASSERTS, + BREAK, + NONE, + }; - class NativeUIRequests - : public AZ::EBusTraits - { - public: - ////////////////////////////////////////////////////////////////////////// - // EBusTraits overrides - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - using MutexType = AZStd::recursive_mutex; + class NativeUIRequests + { + public: + AZ_RTTI(NativeUIRequests, "{48361EE6-C1E7-4965-A13A-7425B2691817}"); + virtual ~NativeUIRequests() = default; - // Waits for user to select an option before execution continues - // Returns the option string selected by the user - virtual AZStd::string DisplayBlockingDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, const AZStd::vector& /*options*/) const { return ""; }; + // Waits for user to select an option before execution continues + // Returns the option string selected by the user + virtual AZStd::string DisplayBlockingDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, const AZStd::vector& /*options*/) const { return ""; }; - // Waits for user to select an option ('Ok' or optionally 'Cancel') before execution continues - // Returns the option string selected by the user - virtual AZStd::string DisplayOkDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; }; + // Waits for user to select an option ('Ok' or optionally 'Cancel') before execution continues + // Returns the option string selected by the user + virtual AZStd::string DisplayOkDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; }; - // Waits for user to select an option ('Yes', 'No' or optionally 'Cancel') before execution continues - // Returns the option string selected by the user - virtual AZStd::string DisplayYesNoDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; }; + // Waits for user to select an option ('Yes', 'No' or optionally 'Cancel') before execution continues + // Returns the option string selected by the user + virtual AZStd::string DisplayYesNoDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; }; - // Displays an assert dialog box - // Returns the action selected by the user - virtual AssertAction DisplayAssertDialog(const AZStd::string& /*message*/) const { return AssertAction::NONE; }; - }; + // Displays an assert dialog box + // Returns the action selected by the user + virtual AssertAction DisplayAssertDialog(const AZStd::string& /*message*/) const { return AssertAction::NONE; }; + }; - using NativeUIRequestBus = AZ::EBus; - } -} + class NativeUIEBusTraits + : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + using MutexType = AZStd::recursive_mutex; + }; + + using NativeUIRequestBus = AZ::EBus; +} // namespace AZ::NativeUI diff --git a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp index cf0c2872f1..bed066018a 100644 --- a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.cpp @@ -15,50 +15,19 @@ #include -namespace AZ +namespace AZ::NativeUI { - using namespace AZ::NativeUI; - - void NativeUISystemComponent::Reflect(AZ::ReflectContext* context) + NativeUISystem::NativeUISystem() { - if (AZ::SerializeContext* serialize = azrtti_cast(context)) - { - serialize->Class() - ->Version(0) - ; - - if (AZ::EditContext* ec = serialize->GetEditContext()) - { - ec->Class("NativeUI", "Adds basic support for native (platform specific) UI dialog boxes") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; - } - } + NativeUIRequestBus::Handler::BusConnect(); } - void NativeUISystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + NativeUISystem::~NativeUISystem() { - provided.push_back(AZ_CRC("NativeUIService", 0x8ec25f87)); + NativeUIRequestBus::Handler::BusDisconnect(); } - void NativeUISystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("NativeUIService", 0x8ec25f87)); - } - - void NativeUISystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - (void)required; - } - - void NativeUISystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - (void)dependent; - } - - AssertAction NativeUISystemComponent::DisplayAssertDialog(const AZStd::string& message) const + AssertAction NativeUISystem::DisplayAssertDialog(const AZStd::string& message) const { static const char* buttonNames[3] = { "Ignore", "Ignore All", "Break" }; AZStd::vector options; @@ -80,7 +49,7 @@ namespace AZ return AssertAction::NONE; } - AZStd::string NativeUISystemComponent::DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const + AZStd::string NativeUISystem::DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const { AZStd::vector options; @@ -93,7 +62,7 @@ namespace AZ return DisplayBlockingDialog(title, message, options); } - AZStd::string NativeUISystemComponent::DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const + AZStd::string NativeUISystem::DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const { AZStd::vector options; @@ -106,18 +75,4 @@ namespace AZ return DisplayBlockingDialog(title, message, options); } - - void NativeUISystemComponent::Init() - { - } - - void NativeUISystemComponent::Activate() - { - NativeUIRequestBus::Handler::BusConnect(); - } - - void NativeUISystemComponent::Deactivate() - { - NativeUIRequestBus::Handler::BusDisconnect(); - } -} +} // namespace AZ::NativeUI diff --git a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h index 2d5cc36ffc..771b9a2af9 100644 --- a/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h +++ b/Code/Framework/AzCore/AzCore/NativeUI/NativeUISystemComponent.h @@ -15,40 +15,24 @@ #include #include -namespace AZ +namespace AZ::NativeUI { - namespace NativeUI + class NativeUISystem + : public NativeUIRequestBus::Handler { - class NativeUISystemComponent - : public AZ::Component - , public NativeUIRequestBus::Handler - { - public: - AZ_COMPONENT(NativeUISystemComponent, "{E996C058-4AFE-4C8C-816F-98D864D8576D}"); + public: + AZ_RTTI(NativeUISystem, "{FF534B2C-11BE-4DEA-A5B7-A4FA96FE1EDE}", NativeUIRequests); + AZ_CLASS_ALLOCATOR(NativeUISystem, AZ::OSAllocator, 0); - static void Reflect(AZ::ReflectContext* context); + NativeUISystem(); + ~NativeUISystem() override; - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); - - //////////////////////////////////////////////////////////////////////// - // NativeUIRequestBus interface implementation - AZStd::string DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const override; - AZStd::string DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override; - AZStd::string DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override; - AssertAction DisplayAssertDialog(const AZStd::string& message) const override; - //////////////////////////////////////////////////////////////////////// - - protected: - - //////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Init() override; - void Activate() override; - void Deactivate() override; - //////////////////////////////////////////////////////////////////////// - }; - } -} + //////////////////////////////////////////////////////////////////////// + // NativeUIRequestBus interface implementation + AZStd::string DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const override; + AZStd::string DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override; + AZStd::string DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override; + AssertAction DisplayAssertDialog(const AZStd::string& message) const override; + //////////////////////////////////////////////////////////////////////// + }; +} // namespace AZ::NativeUI diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp index f12da5c60e..015554538f 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptSystemComponent.cpp @@ -699,6 +699,10 @@ Data::AssetHandler::LoadResult ScriptSystemComponent::LoadAssetData( script->m_scriptBuffer.resize(scriptDataLength); stream->Read(scriptDataLength, script->m_scriptBuffer.data()); + // Clear cached references in the event of a successful load. This function has to be queued on + // AssetBus where NotifyAssetReloaded is also queued, to ensure its execution before NotifyAssetReloaded + Data::AssetBus::QueueFunction(&ScriptSystemComponent::ClearAssetReferences, this, asset.GetId()); + return Data::AssetHandler::LoadResult::LoadComplete; } diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index 58cfa0d049..768841cc09 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -256,7 +256,7 @@ namespace AZ //! Remove the value at the provided path //! @param path The path to a value that should be removed - //! @return Whether or not the value was stored at the provided path. An invalid path will return false; + //! @return Whether or not the path was found and removed. An invalid path will return false; virtual bool Remove(AZStd::string_view path) = 0; //! Structure which contains configuration settings for how to parse a single command line argument diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp index 34f1bdef89..56dfbdcb71 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.cpp @@ -32,17 +32,12 @@ namespace AZ::Internal { AZ::SettingsRegistryInterface::FixedValueString GetEngineMonikerForProject( - SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectPath) + SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectJsonPath) { // projectPath needs to be an absolute path here. using namespace AZ::SettingsRegistryMergeUtils; - bool projectJsonMerged = false; - auto projectJsonPath = projectPath / "project.json"; - if (AZ::IO::SystemFile::Exists(projectJsonPath.c_str())) - { - projectJsonMerged = settingsRegistry.MergeSettingsFile( - projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey); - } + bool projectJsonMerged = settingsRegistry.MergeSettingsFile( + projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey); AZ::SettingsRegistryInterface::FixedValueString engineMoniker; if (projectJsonMerged) @@ -105,12 +100,12 @@ namespace AZ::Internal const auto engineMonikerKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engine_name", EngineSettingsRootKey); + AZStd::set projectPathsNotFound; + for (EngineInfo& engineInfo : pathVisitor.m_enginePaths) { - AZ::IO::FixedMaxPath engineSettingsPath{engineInfo.m_path}; - engineSettingsPath /= "engine.json"; - - if (AZ::IO::SystemFile::Exists(engineSettingsPath.c_str())) + if (auto engineSettingsPath = AZ::IO::FixedMaxPath{engineInfo.m_path} / "engine.json"; + AZ::IO::SystemFile::Exists(engineSettingsPath.c_str())) { if (settingsRegistry.MergeSettingsFile( engineSettingsPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, EngineSettingsRootKey)) @@ -119,12 +114,61 @@ namespace AZ::Internal } } - auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, engineInfo.m_path / projectPath); - if (!engineMoniker.empty() && engineMoniker == engineInfo.m_moniker) + if (auto projectJsonPath = (engineInfo.m_path / projectPath / "project.json").LexicallyNormal(); + AZ::IO::SystemFile::Exists(projectJsonPath.c_str())) { - engineRoot = engineInfo.m_path; - break; + if (auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, projectJsonPath); + !engineMoniker.empty() && engineMoniker == engineInfo.m_moniker) + { + engineRoot = engineInfo.m_path; + break; + } } + else + { + projectPathsNotFound.insert(projectJsonPath); + } + + // Continue looking for candidates, remove the previous engine and project settings that were merged above. + settingsRegistry.Remove(ProjectSettingsRootKey); + settingsRegistry.Remove(EngineSettingsRootKey); + } + + if (engineRoot.empty()) + { + AZStd::string errorStr; + if (!projectPathsNotFound.empty()) + { + // This case is usually encountered when a project path is given as a relative path, + // which is assumed to be relative to an engine root. + // When no project.json files are found this way, dump this error message about + // which project paths were checked. + AZStd::string projectPathsTested; + for (const auto& path : projectPathsNotFound) + { + projectPathsTested.append(AZStd::string::format(" %s\n", path.c_str())); + } + errorStr = AZStd::string::format("No valid project was found at these locations:\n%s" + "Please supply a valid --project-path to the application.", + projectPathsTested.c_str()); + } + else + { + // The other case is that a project.json was found, but after checking all the registered engines + // none of them matched the engine moniker. + AZStd::string enginePathsChecked; + for (const auto& engineInfo : pathVisitor.m_enginePaths) + { + enginePathsChecked.append(AZStd::string::format(" %s (%s)\n", engineInfo.m_path.c_str(), engineInfo.m_moniker.c_str())); + } + errorStr = AZStd::string::format( + "No engine was found in o3de_manifest.json with a name that matches the one set in the project.json.\n" + "Engines that were checked:\n%s" + "Please check that your engine and project have both been registered with scripts/o3de.py.", enginePathsChecked.c_str() + ); + } + + settingsRegistry.Set(FilePathKey_ErrorText, errorStr.c_str()); } } @@ -158,7 +202,7 @@ namespace AZ::Internal return {}; } - void InjectSettingToCommandLineFront(AZ::SettingsRegistryInterface& settingsRegistry, + void InjectSettingToCommandLineBack(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view path, AZStd::string_view value) { AZ::CommandLine commandLine; @@ -168,7 +212,7 @@ namespace AZ::Internal auto projectPathOverride = AZStd::string::format(R"(--regset="%.*s=%.*s")", aznumeric_cast(path.size()), path.data(), aznumeric_cast(value.size()), value.data()); - paramContainer.emplace(paramContainer.begin(), AZStd::move(projectPathOverride)); + paramContainer.emplace(paramContainer.end(), AZStd::move(projectPathOverride)); commandLine.Parse(paramContainer); AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine); } @@ -197,8 +241,8 @@ namespace AZ::SettingsRegistryMergeUtils if (!engineRoot.empty()) { settingsRegistry.Set(engineRootKey, engineRoot.Native()); - // Inject the engine root into the front of the command line settings - Internal::InjectSettingToCommandLineFront(settingsRegistry, engineRootKey, engineRoot.Native()); + // Inject the engine root at the end of the command line settings + Internal::InjectSettingToCommandLineBack(settingsRegistry, engineRootKey, engineRoot.Native()); return engineRoot; } } @@ -244,8 +288,8 @@ namespace AZ::SettingsRegistryMergeUtils if (!projectRoot.empty()) { settingsRegistry.Set(projectRootKey, projectRoot.c_str()); - // Inject the project root into the front of the command line settings - Internal::InjectSettingToCommandLineFront(settingsRegistry, projectRootKey, projectRoot.Native()); + // Inject the project root at the end of the command line settings + Internal::InjectSettingToCommandLineBack(settingsRegistry, projectRootKey, projectRoot.Native()); return projectRoot; } } @@ -874,6 +918,49 @@ namespace AZ::SettingsRegistryMergeUtils return true; } + void ParseCommandLine(AZ::CommandLine& commandLine) + { + struct OptionKeyToRegsetKey + { + AZStd::string_view m_optionKey; + AZStd::string m_regsetKey; + }; + + // Provide overrides for the engine root, the project root and the project cache root + AZStd::array commandOptions = { + OptionKeyToRegsetKey{ + "engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)}, + OptionKeyToRegsetKey{ + "project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)}, + OptionKeyToRegsetKey{ + "project-cache-path", + AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)}}; + + AZStd::fixed_vector overrideArgs; + + for (auto&& [optionKey, regsetKey] : commandOptions) + { + if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0) + { + // Use the last supplied command option value to override previous values + auto overrideArg = AZStd::string::format( + R"(--regset="%s=%s")", regsetKey.c_str(), commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str()); + overrideArgs.emplace_back(AZStd::move(overrideArg)); + } + } + + if (!overrideArgs.empty()) + { + // Dump the input command line, add the additional option overrides + // and Parse the new command line args (write back) into the input command line. + AZ::CommandLine::ParamContainer commandLineArgs; + commandLine.Dump(commandLineArgs); + commandLineArgs.insert( + commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()), AZStd::make_move_iterator(overrideArgs.end())); + commandLine.Parse(commandLineArgs); + } + } + bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key, AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings) { diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h index 10b3c2f18b..4e00c0e6ec 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryMergeUtils.h @@ -55,6 +55,9 @@ namespace AZ::SettingsRegistryMergeUtils //! Development write storage path may be considered temporary or cache storage on some platforms inline static constexpr char FilePathKey_DevWriteStorage[] = "/Amazon/AzCore/Runtime/FilePaths/DevWriteStorage"; + //! Stores error text regarding engine boot sequence when engine and project roots cannot be determined + inline static constexpr char FilePathKey_ErrorText[] = "/Amazon/AzCore/Runtime/FilePaths/ErrorText"; + //! Root key for where command line are stored at within the settings registry inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine"; //! Key set to trigger a notification that the CommandLine has been stored within the settings registry @@ -219,6 +222,9 @@ namespace AZ::SettingsRegistryMergeUtils //! into the AZ::CommandLine instance bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine); + //! Parse a CommandLine and transform certain options into formal "regset" options + void ParseCommandLine(AZ::CommandLine& commandLine); + //! Structure for configuring how values should be dumped from the Settings Registry struct DumperSettings { diff --git a/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp b/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp index b9f7e87b4b..b43044f0b3 100644 --- a/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp +++ b/Code/Framework/AzCore/Platform/Android/AzCore/NativeUI/NativeUISystemComponent_Android.cpp @@ -22,7 +22,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { AZ::Android::JNI::Object object("com/amazon/lumberyard/NativeUI/LumberyardNativeUI"); object.RegisterStaticMethod("DisplayDialog", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V"); diff --git a/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp b/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp index 6a24415ec5..ceba9d2701 100644 --- a/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp +++ b/Code/Framework/AzCore/Platform/Common/Unimplemented/AzCore/NativeUI/NativeUISystemComponent_Unimplemented.cpp @@ -12,16 +12,11 @@ #include -namespace AZ +namespace AZ::NativeUI { - namespace NativeUI + AZStd::string NativeUISystem::DisplayBlockingDialog([[maybe_unused]] const AZStd::string& title, [[maybe_unused]] const AZStd::string& message, + [[maybe_unused]] const AZStd::vector& options) const { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const - { - AZ_UNUSED(title); - AZ_UNUSED(message); - AZ_UNUSED(options); - return ""; - } + return {}; } } diff --git a/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm b/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm index 4af67a1d54..801adaf4ea 100644 --- a/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm +++ b/Code/Framework/AzCore/Platform/Mac/AzCore/NativeUI/NativeUISystemComponent_Mac.mm @@ -26,7 +26,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { __block NSModalResponse response = -1; diff --git a/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp b/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp index a5dd65512f..f88cea5313 100644 --- a/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp +++ b/Code/Framework/AzCore/Platform/Windows/AzCore/NativeUI/NativeUISystemComponent_Windows.cpp @@ -245,7 +245,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { if (options.size() >= MAX_ITEMS) { diff --git a/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm b/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm index 835a7fb5e7..62f07f7483 100644 --- a/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm +++ b/Code/Framework/AzCore/Platform/iOS/AzCore/NativeUI/NativeUISystemComponent_iOS.mm @@ -18,7 +18,7 @@ namespace AZ { namespace NativeUI { - AZStd::string NativeUISystemComponent::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const + AZStd::string NativeUISystem::DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector& options) const { __block AZStd::string userSelection = ""; diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp index 4b75a3d1cf..ba313812ce 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.cpp +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.cpp @@ -175,7 +175,7 @@ namespace AzFramework } // Initializes the IArchive for reading archive(.pak) files - if (auto archive = AZ::Interface::Get(); !archive) + if (auto archive = AZ::Interface::Get(); archive == nullptr) { m_archive = AZStd::make_unique(); AZ::Interface::Register(m_archive.get()); @@ -189,6 +189,12 @@ namespace AzFramework SetFileIOAliases(); } + if (auto nativeUI = AZ::Interface::Get(); nativeUI == nullptr) + { + m_nativeUI = AZStd::make_unique(); + AZ::Interface::Register(m_nativeUI.get()); + } + ApplicationRequests::Bus::Handler::BusConnect(); AZ::UserSettingsFileLocatorBus::Handler::BusConnect(); NetSystemRequestBus::Handler::BusConnect(); @@ -205,12 +211,17 @@ namespace AzFramework AZ::UserSettingsFileLocatorBus::Handler::BusDisconnect(); ApplicationRequests::Bus::Handler::BusDisconnect(); + if (AZ::Interface::Get() == m_nativeUI.get()) + { + AZ::Interface::Unregister(m_nativeUI.get()); + } + m_nativeUI.reset(); + // Unset the Archive file IO if it is set as the direct instance if (AZ::IO::FileIOBase::GetInstance() == m_archiveFileIO.get()) { AZ::IO::FileIOBase::SetInstance(nullptr); } - m_archiveFileIO.reset(); // Destroy the IArchive instance @@ -303,7 +314,6 @@ namespace AzFramework azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), @@ -372,7 +382,6 @@ namespace AzFramework azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), diff --git a/Code/Framework/AzFramework/AzFramework/Application/Application.h b/Code/Framework/AzFramework/AzFramework/Application/Application.h index fdc0ddcfb7..4d7e45a423 100644 --- a/Code/Framework/AzFramework/AzFramework/Application/Application.h +++ b/Code/Framework/AzFramework/AzFramework/Application/Application.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,7 @@ namespace AzFramework AZStd::unique_ptr m_archiveFileIO; ///> The Default file IO instance is a ArchiveFileIO. AZStd::unique_ptr m_archive; ///> The AZ::IO::Instance AZStd::unique_ptr m_pimpl; + AZStd::unique_ptr m_nativeUI; bool m_ownsConsole = false; bool m_exitMainLoopRequested = false; diff --git a/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp b/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp index 618fd92ac1..727d5051fa 100644 --- a/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp +++ b/Code/Framework/AzFramework/AzFramework/Asset/AssetSystemComponentHelper.cpp @@ -220,7 +220,7 @@ namespace AzFramework { // Read the wait for connection boolean from the Settings Registry AZ::s64 waitForConnect64{}; - if (!AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, waitForConnect64, AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, AzFramework::AssetSystem::WaitForConnect)) + if (AZ::SettingsRegistryMergeUtils::PlatformGet(*settingsRegistry, waitForConnect64, AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey, AzFramework::AssetSystem::WaitForConnect)) { outputConnectionSettings.m_waitForConnect = waitForConnect64 != 0; } diff --git a/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp index 7ab61df70e..a221d126bd 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Components/AzFrameworkConfigurationSystemComponent.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include namespace AzFramework @@ -50,36 +50,34 @@ namespace AzFramework void AzFrameworkConfigurationSystemComponent::Activate() { - // Create the defaults scene and associate the GameEntityContext with it. - AZ::Outcome createSceneOutcome = AZ::Failure("SceneSystemRequests bus not responding."); - SceneSystemRequestBus::BroadcastResult(createSceneOutcome, &AzFramework::SceneSystemRequests::CreateScene, "default"); + AZ::Outcome, AZStd::string> createSceneOutcome = + SceneSystemInterface::Get()->CreateScene(Scene::MainSceneName); if (createSceneOutcome) { - Scene* scene = createSceneOutcome.GetValue(); - bool success = false; - EntityContextId gameEntityContextId = EntityContextId::CreateNull(); - GameEntityContextRequestBus::BroadcastResult(gameEntityContextId, &GameEntityContextRequests::GetGameEntityContextId); - - if (!gameEntityContextId.IsNull()) + AZStd::shared_ptr scene = createSceneOutcome.TakeValue(); + EntityContext* gameEntityContext = nullptr; + GameEntityContextRequestBus::BroadcastResult(gameEntityContext, &GameEntityContextRequests::GetGameEntityContextInstance); + if (gameEntityContext != nullptr) { - SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequests::SetSceneForEntityContextId, gameEntityContextId, scene); + [[maybe_unused]] bool result = scene->SetSubsystem(gameEntityContext); + AZ_Assert(result, "Unable to register main entity context with the main scene."); + } + else + { + AZ_Assert(false, "Unable to retrieve the game entity context instance."); } - AZ_Assert(success, "The application was unable to setup a scene for the game entity context, this should always work"); } else { - AZ_Assert(false, "%s", createSceneOutcome.GetError().data()); + AZ_Assert(false, "Unable to create main scene due to: %s", createSceneOutcome.GetError().c_str()); } } void AzFrameworkConfigurationSystemComponent::Deactivate() { - bool success = false; - SceneSystemRequestBus::BroadcastResult( - success, &AzFramework::SceneSystemRequestBus::Events::RemoveScene, "default"); - - AZ_Assert(success, "\"default\" scene was not removed"); + [[maybe_unused]] bool success = SceneSystemInterface::Get()->RemoveScene(Scene::MainSceneName); + AZ_Assert(success, "Unable to remove the main scene."); } void AzFrameworkConfigurationSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp index ad3173ed56..60c70a25bb 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "EntityContext.h" @@ -37,6 +39,30 @@ namespace AzFramework } } + AZStd::shared_ptr EntityContext::FindContainingScene(const EntityContextId& contextId) + { + auto sceneSystem = SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Attempting to retrieve the scene containing a entity context before the scene system is available."); + + AZStd::shared_ptr result; + sceneSystem->IterateActiveScenes([&result, &contextId](const AZStd::shared_ptr& scene) + { + EntityContext** entityContext = scene->FindSubsystemInScene(); + if (entityContext && (*entityContext)->GetContextId() == contextId) + { + result = scene; + // Result found, returning. + return false; + } + else + { + // No match, continuing to search for containing scene. + return true; + } + }); + return result; + } + //========================================================================= // EntityContext ctor //========================================================================= diff --git a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h index f59a40f52b..c44429b6de 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/EntityContext.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -27,7 +28,7 @@ namespace AZ namespace AzFramework { - class EntityContext; + class Scene; /** * Provides services for a group of entities under the umbrella of a given context. @@ -47,9 +48,11 @@ namespace AzFramework , public EntityOwnershipServiceNotificationBus::Handler { public: - AZ_TYPE_INFO(EntityContext, "{4F98A6B9-C7B5-450E-8A8A-30EEFC411EF5}"); + /// The type used to store entity in AzFramework::Scene. + using SceneStorageType = EntityContext*; + EntityContext(AZ::SerializeContext* serializeContext = nullptr); EntityContext(const EntityContextId& contextId, AZ::SerializeContext* serializeContext = nullptr); EntityContext(const EntityContextId& contextId, AZStd::unique_ptr entityOwnershipService, @@ -75,6 +78,7 @@ namespace AzFramework ////////////////////////////////////////////////////////////////////////// static void Reflect(AZ::ReflectContext* context); + static AZStd::shared_ptr FindContainingScene(const EntityContextId& contextId); protected: diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h index ac638127ff..eb3a03ab51 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextBus.h @@ -66,6 +66,8 @@ namespace AzFramework */ virtual EntityContextId GetGameEntityContextId() = 0; + virtual EntityContext* GetGameEntityContextInstance() = 0; + /** * Creates an entity in the game context. * @param name A name for the new entity. diff --git a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h index 3f15027ac7..482b2133ca 100644 --- a/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Entity/GameEntityContextComponent.h @@ -51,6 +51,7 @@ namespace AzFramework ////////////////////////////////////////////////////////////////////////// // GameEntityContextRequestBus AZ::Uuid GetGameEntityContextId() override { return GetContextId(); } + EntityContext* GetGameEntityContextInstance() override { return this; } void ResetGameContext() override; AZ::Entity* CreateGameEntity(const char* name) override; BehaviorEntity CreateGameEntityForBehaviorContext(const char* name) override; diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index 7e968ffcd8..ea8fd75cfd 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -41,9 +41,10 @@ namespace AzFramework::ProjectManager // at the end of the function AZ::CommandLine commandLine; commandLine.Parse(argc, argv); - AZ::SettingsRegistryImpl settingsRegistry; - // Store the Command line to the Setting Registry + AZ::SettingsRegistryMergeUtils::ParseCommandLine(commandLine); + // Store the Command line to the Setting Registry + AZ::SettingsRegistryImpl settingsRegistry; AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(settingsRegistry); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {}); @@ -68,7 +69,14 @@ namespace AzFramework::ProjectManager // If we were able to locate a path to a project, we're done if (!projectRootPath.empty()) { - return ProjectPathCheckResult::ProjectPathFound; + AZ::IO::FixedMaxPath projectJsonPath = engineRootPath / projectRootPath / "project.json"; + if (AZ::IO::SystemFile::Exists(projectJsonPath.c_str())) + { + return ProjectPathCheckResult::ProjectPathFound; + } + AZ_TracePrintf( + "ProjectManager", "Did not find a project file at location '%s', launching the Project Manager...", + projectJsonPath.c_str()); } if (LaunchProjectManager(engineRootPath)) diff --git a/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp b/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp index 1d55ec9711..23d74f7578 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp +++ b/Code/Framework/AzFramework/AzFramework/Render/Intersector.cpp @@ -14,9 +14,9 @@ #include #include +#include #include #include -#include #include #include @@ -30,11 +30,11 @@ namespace AzFramework { IntersectorBus::Handler::BusConnect(m_contextId); IntersectionNotificationBus::Handler::BusConnect(m_contextId); - Scene* scene = nullptr; - SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, m_contextId); + + AZStd::shared_ptr scene = EntityContext::FindContainingScene(m_contextId); if (scene) { - scene->SetSubsystem(this); + scene->SetSubsystem(this); } } @@ -42,11 +42,12 @@ namespace AzFramework { IntersectorBus::Handler::BusDisconnect(); IntersectionNotificationBus::Handler::BusDisconnect(); - Scene* scene = nullptr; - SceneSystemRequestBus::BroadcastResult(scene, &AzFramework::SceneSystemRequestBus::Events::GetSceneFromEntityContextId, m_contextId); + + AZStd::shared_ptr scene = EntityContext::FindContainingScene(m_contextId); if (scene) { - scene->UnsetSubsystem(); + [[maybe_unused]] bool result = scene->UnsetSubsystem(this); + AZ_Assert(result, "Failed to unregister Intersector with scene"); } } diff --git a/Code/Framework/AzFramework/AzFramework/Render/Intersector.h b/Code/Framework/AzFramework/AzFramework/Render/Intersector.h index 5852310c21..65ba6b0ea9 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/Intersector.h +++ b/Code/Framework/AzFramework/AzFramework/Render/Intersector.h @@ -33,6 +33,8 @@ namespace AzFramework , protected IntersectionNotificationBus::Handler { public: + AZ_TYPE_INFO(AzFramework::RenderGeometry::Intersector, "{4CCA7971-CD83-4856-ADEA-89CEB41FB197}"); + Intersector(AzFramework::EntityContextId contextId); ~Intersector(); diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp b/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp index 98905b4574..5bdfb94fa1 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.cpp @@ -14,13 +14,102 @@ namespace AzFramework { - Scene::Scene(AZStd::string_view name) - : m_name(name) + Scene::Scene(AZStd::string name) + : m_name(AZStd::move(name)) { } - const AZStd::string& Scene::GetName() + Scene::Scene(AZStd::string name, AZStd::shared_ptr parent) + : m_name(AZStd::move(name)) + , m_parent(AZStd::move(parent)) + { + } + + Scene::~Scene() + { + m_removalEvent.Signal(*this, RemovalEventType::Destroyed); + } + + const AZStd::string& Scene::GetName() const { return m_name; } + + const AZStd::shared_ptr& Scene::GetParent() + { + return m_parent; + } + + AZStd::shared_ptr Scene::GetParent() const + { + return m_parent; + } + + bool Scene::IsAlive() const + { + return m_isAlive; + } + + void Scene::ConnectToEvents(RemovalEvent::Handler& handler) + { + handler.Connect(m_removalEvent); + } + + void Scene::ConnectToEvents(SubsystemEvent::Handler& handler) + { + handler.Connect(m_subsystemEvent); + } + + AZStd::any* Scene::FindSubsystem(const AZ::TypeId& typeId) + { + AZStd::any* result = FindSubsystemInScene(typeId); + return (!result && m_parent) ? m_parent->FindSubsystem(typeId) : result; + } + + const AZStd::any* Scene::FindSubsystem(const AZ::TypeId& typeId) const + { + return const_cast(this)->FindSubsystem(typeId); + } + + AZStd::any* Scene::FindSubsystemInScene(const AZ::TypeId& typeId) + { + // Spot check that the internal arrays remain consistent. + AZ_Assert( + m_systemKeys.size() == m_systemObjects.size(), "Key and object list in AzFramework::Scene '%s' have gone out of sync.", + m_name.c_str()); + + const size_t m_systemKeysCount = m_systemKeys.size(); + for (size_t i = 0; i < m_systemKeysCount; ++i) + { + if (m_systemKeys[i] != typeId) + { + continue; + } + else + { + return &m_systemObjects[i]; + } + } + return nullptr; + } + + const AZStd::any* Scene::FindSubsystemInScene(const AZ::TypeId& typeId) const + { + return const_cast(this)->FindSubsystemInScene(typeId); + } + + void Scene::MarkForDestruction() + { + m_isAlive = false; + m_removalEvent.Signal(*this, RemovalEventType::Zombified); + } + + void Scene::RemoveSubsystem(size_t index, const AZ::TypeId& subsystemType) + { + m_systemKeys[index] = m_systemKeys.back(); + m_systemObjects[index] = AZStd::move(m_systemObjects.back()); + m_systemKeys.pop_back(); + m_systemObjects.pop_back(); + m_subsystemEvent.Signal(*this, SubsystemEventType::Removed, subsystemType); + } } diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.h b/Code/Framework/AzFramework/AzFramework/Scene/Scene.h index 6b365dae0f..78fea316eb 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/Scene.h +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.h @@ -11,10 +11,14 @@ */ #pragma once +#include #include #include #include +#include #include +#include +#include namespace AzFramework { @@ -24,71 +28,100 @@ namespace AzFramework AZ_TYPE_INFO(Scene, "{DB449BB3-7A95-434D-BC61-47ACBB1F3436}"); AZ_CLASS_ALLOCATOR(Scene, AZ::SystemAllocator, 0); - explicit Scene(AZStd::string_view name); + friend class ISceneSystem; - const AZStd::string& GetName(); + constexpr static AZStd::string_view MainSceneName = "Main"; + constexpr static AZStd::string_view EditorMainSceneName = "Editor"; + + enum class RemovalEventType + { + Zombified, // The scene has be marked for destruction and is no longer visible in the scene system. + Destroyed, // The scene has been destroyed. + }; + using RemovalEvent = AZ::Event; + enum class SubsystemEventType + { + Added, + Removed + }; + using SubsystemEvent = AZ::Event; + + explicit Scene(AZStd::string name); + Scene(AZStd::string name, AZStd::shared_ptr parent); + ~Scene(); + + [[nodiscard]] const AZStd::string& GetName() const; + + [[nodiscard]] const AZStd::shared_ptr& GetParent(); + [[nodiscard]] AZStd::shared_ptr GetParent() const; + + [[nodiscard]] bool IsAlive() const; + + void ConnectToEvents(RemovalEvent::Handler& handler); + void ConnectToEvents(SubsystemEvent::Handler& handler); // Set the instance of a subsystem associated with this scene. template - bool SetSubsystem(T* system); + bool SetSubsystem(T&& system); // Unset the instance of a subsystem associated with this scene. template bool UnsetSubsystem(); - // Get the instance of a subsystem associated with this scene. + // Unset the instance of the exact system associated with this scene. + // Use this to make sure the expected instance is removed or to make sure type deduction is done in the same way as during setting. + template + bool UnsetSubsystem(const T& system); + + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] AZStd::any* FindSubsystem(const AZ::TypeId& typeId); + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] const AZStd::any* FindSubsystem(const AZ::TypeId& typeId) const; + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. template - T* GetSubsystem(); + [[nodiscard]] T* FindSubsystem(); + // Get the instance of a subsystem associated with this scene. This call will also look in parent scenes if not found on the target + // scene. Returns a pointer to the subsystem if found, otherwise returns a nullptr. + template + [[nodiscard]] const T* FindSubsystem() const; + + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] AZStd::any* FindSubsystemInScene(const AZ::TypeId& typeId); + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + [[nodiscard]] const AZStd::any* FindSubsystemInScene(const AZ::TypeId& typeId) const; + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + template + [[nodiscard]] T* FindSubsystemInScene(); + // Get the instance of a subsystem associated with this scene. This call will only look in the selected scene. Returns a pointer to + // the subsystem if found, otherwise returns a nullptr. + template + [[nodiscard]] const T* FindSubsystemInScene() const; private: + void MarkForDestruction(); + void RemoveSubsystem(size_t index, const AZ::TypeId& subsystemType); - AZStd::string m_name; + RemovalEvent m_removalEvent; + SubsystemEvent m_subsystemEvent; // Storing keys separate from data to optimize for fast key search. AZStd::vector m_systemKeys; - AZStd::vector m_systemPointers; + AZStd::vector m_systemObjects; + + // Name that identifies the scene. + AZStd::string m_name; + // Parent to this scene. Any subsystems are inherited from the parent but can be overwritten locally. + AZStd::shared_ptr m_parent; + // If false, the scene has been removed from scene system and can no longer be found. As soon as all handles to the scene are + // released it will be destroyed. + bool m_isAlive{ true }; }; - - template - bool Scene::SetSubsystem(T* system) - { - if (GetSubsystem() != nullptr) - { - return false; - } - m_systemKeys.push_back(T::RTTI_Type()); - m_systemPointers.push_back(system); - return true; - } - - template - bool Scene::UnsetSubsystem() - { - for (size_t i = 0; i < m_systemKeys.size(); ++i) - { - if (m_systemKeys.at(i) == T::RTTI_Type()) - { - m_systemKeys.at(i) = m_systemKeys.back(); - m_systemKeys.pop_back(); - m_systemPointers.at(i) = m_systemPointers.back(); - m_systemPointers.pop_back(); - return true; - } - } - return false; - } - - template - T* Scene::GetSubsystem() - { - for (size_t i = 0; i < m_systemKeys.size(); ++i) - { - if (m_systemKeys.at(i) == T::RTTI_Type()) - { - return reinterpret_cast(m_systemPointers.at(i)); - } - } - return nullptr; - } - } // AzFramework + +#include diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl new file mode 100644 index 0000000000..b0c1a18b08 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl @@ -0,0 +1,108 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +namespace AzFramework +{ + template + bool Scene::SetSubsystem(T&& system) + { + const AZ::TypeId& targetType = azrtti_typeid(); + for (const AZ::TypeId& key : m_systemKeys) + { + if (key == targetType) + { + return false; + } + } + + m_systemKeys.push_back(targetType); + m_systemObjects.emplace_back(AZStd::forward(system)); + m_subsystemEvent.Signal(*this, SubsystemEventType::Added, targetType); + return true; + } + + template + bool Scene::UnsetSubsystem() + { + const AZ::TypeId& targetType = azrtti_typeid(); + const size_t m_systemKeysCount = m_systemKeys.size(); + for (size_t i = 0; i < m_systemKeysCount; ++i) + { + if (m_systemKeys[i] != targetType) + { + continue; + } + else + { + RemoveSubsystem(i, targetType); + return true; + } + } + return false; + } + + template + bool Scene::UnsetSubsystem(const T& system) + { + const AZ::TypeId& targetType = azrtti_typeid(); + const size_t systemKeysCount = m_systemKeys.size(); + for (size_t i = 0; i < systemKeysCount; ++i) + { + if (m_systemKeys[i] != targetType) + { + continue; + } + else + { + [[maybe_unused]] T* instance = AZStd::any_cast(&m_systemObjects[i]); + AZ_Assert( + instance && *instance == system, + "Subsystem being released matched type, but wasn't pointing to the same system that was stored."); + RemoveSubsystem(i, targetType); + return true; + } + } + return false; + } + + template + T* Scene::FindSubsystem() + { + const AZ::TypeId& targetType = azrtti_typeid(); + AZStd::any* subSystem = FindSubsystem(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } + + template + const T* Scene::FindSubsystem() const + { + const AZ::TypeId& targetType = azrtti_typeid(); + const AZStd::any* subSystem = FindSubsystem(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } + + template + T* Scene::FindSubsystemInScene() + { + const AZ::TypeId& targetType = azrtti_typeid(); + AZStd::any* subSystem = FindSubsystemInScene(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } + + template + const T* Scene::FindSubsystemInScene() const + { + const AZ::TypeId& targetType = azrtti_typeid(); + const AZStd::any* subSystem = FindSubsystemInScene(targetType); + return subSystem ? AZStd::any_cast(subSystem) : nullptr; + } +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h deleted file mode 100644 index c75a8ceb9a..0000000000 --- a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemBus.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ -#pragma once - -#include -#include - -namespace AzFramework -{ - // Forward declarations - class Scene; - - //! Interface used to create, get, or destroy scenes. - class SceneSystemRequests - : public AZ::EBusTraits - { - public: - - virtual ~SceneSystemRequests() = default; - - //! Single handler policy since there should only be one instance of this system component. - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - - //! Creates a scene with a given name. - //! - If there is already a scene with the provided name this will return AZ::Failure(). - //! - If isDefault is set to true and there is already a default scene, the default scene will be switched to this one. - virtual AZ::Outcome CreateScene(AZStd::string_view name) = 0; - - //! Gets a scene with a given name - //! - If a scene does not exist with the given name, nullptr is returned. - virtual Scene* GetScene(AZStd::string_view name) = 0; - - //! Gets all the scenes that currently exist. - virtual AZStd::vector GetAllScenes() = 0; - - //! Remove a scene with a given name and return if the operation was successful. - //! - If the removed scene is the default scene, there will no longer be a default scene. - virtual bool RemoveScene(AZStd::string_view name) = 0; - - //! Add a mapping from the provided EntityContextId to a Scene - //! - If a scene is already associated with this EntityContextId, nothing is changed and false is returned. - virtual bool SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) = 0; - - //! Remove a mapping from the provided EntityContextId to a Scene - //! - If no scene is found from the provided EntityContextId, false is returned. - virtual bool RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) = 0; - - //! Get the scene associated with an EntityContextId - //! - If no scene is found for the provided EntityContextId, nullptr is returned. - virtual Scene* GetSceneFromEntityContextId(EntityContextId entityContextId) = 0; - }; - - using SceneSystemRequestBus = AZ::EBus; - - //! Interface used for notifications from the scene system - class SceneSystemNotifications - : public AZ::EBusTraits - { - public: - - virtual ~SceneSystemNotifications() = default; - - //! There can be multiple listeners to changes in the scene system. - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Called when a scene has been created. - virtual void SceneCreated(Scene& /*scene*/) {}; - - //! Called just before a scene is removed. - virtual void SceneAboutToBeRemoved(Scene& /*scene*/) {}; - - }; - - using SceneSystemNotificationBus = AZ::EBus; - - //! Interface used for notifications about individual scenes - class SceneNotifications - : public AZ::EBusTraits - { - public: - - virtual ~SceneNotifications() = default; - - //! There can be multiple listeners to changes in the scene system. - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; - - //! Bus is listened to using the pointer of the scene - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; - - //! Specifies that events are addressed by the pointer to the scene - using BusIdType = Scene*; - - //! Called just before a scene is removed. - virtual void SceneAboutToBeRemoved() {}; - - //! Called when an entity context is mapped to this scene. - virtual void EntityContextMapped(EntityContextId /*entityContextId*/) {}; - - //! Called when an entity context is unmapped from this scene. - virtual void EntityContextUnmapped(EntityContextId /*entityContextId*/) {}; - }; - - using SceneNotificationBus = AZ::EBus; - -} // AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp index 909880ff55..e677be4643 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace AzFramework { @@ -41,14 +41,10 @@ namespace AzFramework void SceneSystemComponent::Activate() { - // Connect busses - SceneSystemRequestBus::Handler::BusConnect(); } void SceneSystemComponent::Deactivate() { - // Disconnect Busses - SceneSystemRequestBus::Handler::BusDisconnect(); } void SceneSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) @@ -61,140 +57,105 @@ namespace AzFramework incompatible.push_back(AZ_CRC("SceneSystemComponentService", 0xd8975435)); } - AZ::Outcome SceneSystemComponent::CreateScene(AZStd::string_view name) + AZ::Outcome, AZStd::string> SceneSystemComponent::CreateScene(AZStd::string_view name) { - Scene* existingScene = GetScene(name); + return CreateSceneWithParent(name, nullptr); + } + AZ::Outcome, AZStd::string> SceneSystemComponent::CreateSceneWithParent( + AZStd::string_view name, AZStd::shared_ptr parent) + { + const AZStd::shared_ptr& existingScene = GetScene(name); if (existingScene) { return AZ::Failure("A scene already exists with this name."); } - auto newScene = AZStd::make_unique(name); - Scene* scenePointer = newScene.get(); - m_scenes.push_back(AZStd::move(newScene)); - SceneSystemNotificationBus::Broadcast(&SceneSystemNotificationBus::Events::SceneCreated, *scenePointer); - return AZ::Success(scenePointer); + auto newScene = AZStd::make_shared(name, AZStd::move(parent)); + m_activeScenes.push_back(newScene); + { + AZStd::lock_guard lock(m_eventMutex); + m_events.Signal(EventType::SceneCreated, newScene); + } + return AZ::Success(AZStd::move(newScene)); } - Scene* SceneSystemComponent::GetScene(AZStd::string_view name) + AZStd::shared_ptr SceneSystemComponent::GetScene(AZStd::string_view name) { - auto sceneIterator = AZStd::find_if(m_scenes.begin(), m_scenes.end(), + auto sceneIterator = AZStd::find_if(m_activeScenes.begin(), m_activeScenes.end(), [name](auto& scene) -> bool { return scene->GetName() == name; } ); - return sceneIterator == m_scenes.end() ? nullptr : sceneIterator->get(); + return sceneIterator == m_activeScenes.end() ? nullptr : *sceneIterator; } - AZStd::vector SceneSystemComponent::GetAllScenes() + void SceneSystemComponent::IterateActiveScenes(const ActiveIterationCallback& callback) { - AZStd::vector scenes; - scenes.resize_no_construct(m_scenes.size()); - - for (size_t i = 0; i < m_scenes.size(); ++i) + bool keepGoing = true; + auto end = m_activeScenes.end(); + for (auto it = m_activeScenes.begin(); it != end && keepGoing; ++it) { - scenes.at(i) = m_scenes.at(i).get(); + keepGoing = callback(*it); + } + } + + void SceneSystemComponent::IterateZombieScenes(const ZombieIterationCallback& callback) + { + bool keepGoing = true; + auto end = m_zombieScenes.end(); + for (auto it = m_zombieScenes.begin(); it != end && keepGoing;) + { + if (!it->expired()) + { + keepGoing = callback(*(it->lock())); + ++it; + } + else + { + *it = m_zombieScenes.back(); + m_zombieScenes.pop_back(); + end = m_zombieScenes.end(); + } } - return scenes; } bool SceneSystemComponent::RemoveScene(AZStd::string_view name) { - for (size_t i = 0; i < m_scenes.size(); ++i) + for (AZStd::shared_ptr& scene : m_activeScenes) { - auto& scenePtr = m_scenes.at(i); - if (scenePtr->GetName() == name) + if (scene->GetName() == name) { - // Remove any entityContext mappings. - Scene* scene = scenePtr.get(); - for (auto entityContextScenePairIt = m_entityContextToScenes.begin(); entityContextScenePairIt != m_entityContextToScenes.end();) + MarkSceneForDestruction(*scene); { - AZStd::pair& pair = *entityContextScenePairIt; - if (pair.second == scene) - { - // swap and pop back. - *entityContextScenePairIt = m_entityContextToScenes.back(); - m_entityContextToScenes.pop_back(); - } - else - { - ++entityContextScenePairIt; - } + AZStd::lock_guard lock(m_eventMutex); + m_events.Signal(EventType::ScenePendingRemoval, scene); } - SceneSystemNotificationBus::Broadcast(&SceneSystemNotificationBus::Events::SceneAboutToBeRemoved, *scene); - SceneNotificationBus::Event(scene, &SceneNotificationBus::Events::SceneAboutToBeRemoved); - - m_scenes.erase(&scenePtr); + // Zombies are weak pointers that are kept around for situations where there's a delay in deleting the scene. This can happen + // if there are outstanding calls like in-progress async calls or resources locked by hardware. A weak_ptr of the original + // scene is kept so the zombie scene can still be found through iteration as it may require additional calls such as Tick calls. + m_zombieScenes.push_back(scene); + scene = AZStd::move(m_activeScenes.back()); + m_activeScenes.pop_back(); + // The scene may not be held onto anymore, so check here to see if the previously added zombie can be released. + if (m_zombieScenes.back().expired()) + { + m_zombieScenes.pop_back(); + } return true; } } - AZ_Warning("SceneSystemComponent", false, "Attempting to remove scene name \"%.*s\", but that scene was not found.", static_cast(name.size()), name.data()); + AZ_Warning("SceneSystemComponent", false, R"(Attempting to remove scene name "%.*s", but that scene was not found.)", AZ_STRING_ARG(name)); return false; } - bool SceneSystemComponent::SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) + void SceneSystemComponent::ConnectToEvents(SceneEvent::Handler& handler) { - Scene* existingSceneForEntityContext = GetSceneFromEntityContextId(entityContextId); - if (existingSceneForEntityContext) - { - // This entity context is already mapped and must be unmapped explictely before it can be changed. - char entityContextIdString[EntityContextId::MaxStringBuffer]; - entityContextId.ToString(entityContextIdString, sizeof(entityContextIdString)); - AZ_Warning("SceneSystemComponent", false, "Failed to set a scene for entity context %s, scene is already set for that entity context.", entityContextIdString); - - return false; - } - m_entityContextToScenes.emplace_back(entityContextId, scene); - SceneNotificationBus::Event(scene, &SceneNotificationBus::Events::EntityContextMapped, entityContextId); - return true; + AZStd::lock_guard lock(m_eventMutex); + handler.Connect(m_events); } - - bool SceneSystemComponent::RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) - { - if (!scene || entityContextId.IsNull()) - { - return false; - } - - for (auto entityContextScenePairIt = m_entityContextToScenes.begin(); entityContextScenePairIt != m_entityContextToScenes.end();) - { - AZStd::pair& pair = *entityContextScenePairIt; - if (!(pair.first == entityContextId && pair.second == scene)) - { - ++entityContextScenePairIt; - } - else - { - // swap and pop back. - *entityContextScenePairIt = m_entityContextToScenes.back(); - m_entityContextToScenes.pop_back(); - - SceneNotificationBus::Event(scene, &SceneNotificationBus::Events::EntityContextUnmapped, entityContextId); - return true; - } - } - - char entityContextIdString[EntityContextId::MaxStringBuffer]; - entityContextId.ToString(entityContextIdString, sizeof(entityContextIdString)); - AZ_Warning("SceneSystemComponent", false, "Failed to remove scene \"%.*s\" for entity context %s, entity context is not currently mapped to that scene.", static_cast(scene->GetName().size()), scene->GetName().data(), entityContextIdString); - return false; - } - - Scene* SceneSystemComponent::GetSceneFromEntityContextId(EntityContextId entityContextId) - { - for (AZStd::pair& pair : m_entityContextToScenes) - { - if (pair.first == entityContextId) - { - return pair.second; - } - } - return nullptr; - } - -} // AzFramework +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h index 085efcd898..a5497bdb87 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h +++ b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemComponent.h @@ -13,18 +13,18 @@ #include #include -#include +#include +#include #include namespace AzFramework { class SceneSystemComponent : public AZ::Component - , public SceneSystemRequestBus::Handler + , public SceneSystemInterface::Registrar { public: - - AZ_COMPONENT(SceneSystemComponent, "{7AC53AF0-BE1A-437C-BE3E-4D6A998DA945}", AZ::Component); + AZ_COMPONENT(SceneSystemComponent, "{7AC53AF0-BE1A-437C-BE3E-4D6A998DA945}", AZ::Component, ISceneSystem); SceneSystemComponent(); ~SceneSystemComponent() override; @@ -41,24 +41,26 @@ namespace AzFramework static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); ////////////////////////////////////////////////////////////////////////// - // SceneSystemRequestsBus::Handler + // SceneSystemInterface overrides ////////////////////////////////////////////////////////////////////////// - AZ::Outcome CreateScene(AZStd::string_view name) override; - Scene* GetScene(AZStd::string_view name) override; - AZStd::vector GetAllScenes() override; + AZ::Outcome, AZStd::string> CreateScene(AZStd::string_view name) override; + AZ::Outcome, AZStd::string> CreateSceneWithParent( + AZStd::string_view name, AZStd::shared_ptr parent) override; + [[nodiscard]] AZStd::shared_ptr GetScene(AZStd::string_view name) override; + void IterateActiveScenes(const ActiveIterationCallback& callback) override; + void IterateZombieScenes(const ZombieIterationCallback& callback) override; bool RemoveScene(AZStd::string_view name) override; - bool SetSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) override; - bool RemoveSceneForEntityContextId(EntityContextId entityContextId, Scene* scene) override; - Scene* GetSceneFromEntityContextId(EntityContextId entityContextId) override; + void ConnectToEvents(SceneEvent::Handler& handler) override; private: + AZ_DISABLE_COPY_MOVE(SceneSystemComponent); - AZ_DISABLE_COPY(SceneSystemComponent); - - // Container of scene in order of creation - AZStd::vector> m_scenes; - - // Map of entity context Ids to scenes. Using a vector because lookups will be common, but the size will be small. - AZStd::vector> m_entityContextToScenes; + AZStd::vector> m_activeScenes; + AZStd::vector> m_zombieScenes; + // Using a mutex around the events as other threads may respond to a new/deleted scene by making + // local updates and unregistering themselves. Since Scene is single threaded, no updates (other + // then unregistering an event) should be done from other threads though. + AZStd::recursive_mutex m_eventMutex; + SceneEvent m_events; }; } diff --git a/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h new file mode 100644 index 0000000000..48dca7ed29 --- /dev/null +++ b/Code/Framework/AzFramework/AzFramework/Scene/SceneSystemInterface.h @@ -0,0 +1,88 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace AzFramework +{ + //! Interface used to create, get, or destroy scenes. + //! This interface is single thread and is intended to be called from a single thread, commonly the main thread. The exception + //! is connecting events, which is thread safe. + class ISceneSystem + { + public: + AZ_RTTI(AzFramework::ISceneSystem, "{DAE482A8-88AE-4BD3-8A5B-52D19A96E15F}"); + AZ_DISABLE_COPY_MOVE(ISceneSystem); + + enum class EventType + { + SceneCreated, + ScenePendingRemoval + }; + using SceneEvent = AZ::Event&>; + + ISceneSystem() = default; + virtual ~ISceneSystem() = default; + + using ActiveIterationCallback = AZStd::function& scene)>; + using ZombieIterationCallback = AZStd::function; + + //! Creates a scene with a given name. + //! - If there is already a scene with the provided name this will return AZ::Failure(). + virtual AZ::Outcome, AZStd::string> CreateScene(AZStd::string_view name) = 0; + + //! Creates a scene with a given name and a parent. + //! - If there is already a scene with the provided name this will return AZ::Failure(). + virtual AZ::Outcome, AZStd::string> CreateSceneWithParent( + AZStd::string_view name, AZStd::shared_ptr parent) = 0; + + //! Gets a scene with a given name + //! - If a scene does not exist with the given name, nullptr is returned. + [[nodiscard]] virtual AZStd::shared_ptr GetScene(AZStd::string_view name) = 0; + + //! Iterates over all scenes that are in active use. Iteration stops if the callback returns false or all scenes have been listed. + virtual void IterateActiveScenes(const ActiveIterationCallback& callback) = 0; + //! Iterates over all zombie scenes. Zombie scenes are scenes that have been removed but still have references held on to. This can + //! happen because scenes hold on to subsystems that can't immediately be deleted. These subsystems may still require being called + //! such as a periodic tick. Iteration stops if the callback returns false or all scenes have been listed. + virtual void IterateZombieScenes(const ZombieIterationCallback& callback) = 0; + + //! Remove a scene with a given name and return if the operation was successful. + virtual bool RemoveScene(AZStd::string_view name) = 0; + + //! Connects the provided handler to the events that are called after scenes are created or before they get removed. + virtual void ConnectToEvents(SceneEvent::Handler& handler) = 0; + + protected: + // Strictly a forwarding function to call private functions on the scene. + void MarkSceneForDestruction(Scene& scene) { scene.MarkForDestruction(); } + }; + + using SceneSystemInterface = AZ::Interface; + + // EBus wrapper for ScriptCanvas + class ISceneSystemRequests + : public AZ::EBusTraits + { + public: + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + }; + using ILoggerRequestBus = AZ::EBus; +} // AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index 312a3766ac..b126a192ac 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -194,10 +194,11 @@ set(FILES Logging/MissingAssetLogger.h Logging/MissingAssetNotificationBus.h Scene/Scene.h + Scene/Scene.inl Scene/Scene.cpp - Scene/SceneSystemBus.h Scene/SceneSystemComponent.h Scene/SceneSystemComponent.cpp + Scene/SceneSystemInterface.h Script/ScriptComponent.h Script/ScriptComponent.cpp Script/ScriptDebugAgentBus.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 50315e9d7a..e77704c920 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -284,6 +284,10 @@ namespace AzToolsFramework void ToolsApplication::Start(const Descriptor& descriptor, const StartupParameters& startupParameters/* = StartupParameters()*/) { Application::Start(descriptor, startupParameters); + if (!m_isStarted) + { + return; + } m_editorEntityManager.Start(); @@ -671,20 +675,8 @@ namespace AzToolsFramework // if the new viewport interaction model is enabled we do not want to // filter out locked entities as this breaks with the logic of being // able to select locked entities in the entity outliner - if (IsNewViewportInteractionModelEnabled()) - { - selectedEntitiesFiltered.insert( - selectedEntitiesFiltered.begin(), selectedEntities.begin(), selectedEntities.end()); - } - else - { - for (AZ::EntityId nowSelectedId : selectedEntities) - { - AZ_Assert(nowSelectedId.IsValid(), "Invalid entity Id being marked as selected."); - - selectedEntitiesFiltered.push_back(nowSelectedId); - } - } + selectedEntitiesFiltered.insert( + selectedEntitiesFiltered.begin(), selectedEntities.begin(), selectedEntities.end()); EntityIdList newlySelectedIds; EntityIdList newlyDeselectedIds; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h index cee47f55ef..7d08d87c3b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextBus.h @@ -49,6 +49,8 @@ namespace AzToolsFramework /// Retrieve the Id of the editor entity context. virtual AzFramework::EntityContextId GetEditorEntityContextId() = 0; + virtual AzFramework::EntityContext* GetEditorEntityContextInstance() = 0; + /// Creates an entity in the editor context. /// \return the EntityId for the created Entity virtual AZ::EntityId CreateNewEditorEntity(const char* name) = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h index 9a9a2dcff0..2313f27437 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.h @@ -77,6 +77,7 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // EditorEntityContextRequestBus AzFramework::EntityContextId GetEditorEntityContextId() override { return GetContextId(); } + AzFramework::EntityContext* GetEditorEntityContextInstance() override { return this; } void ResetEditorContext() override; AZ::EntityId CreateNewEditorEntity(const char* name) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp index 9a191f93de..089037bbf3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Manipulators/EditorVertexSelection.cpp @@ -769,12 +769,12 @@ namespace AzToolsFramework template void EditorVertexSelectionBase::DisplayViewport2d( - const AzFramework::ViewportInfo& /*viewportInfo*/, + const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); - m_editorBoxSelect.Display2d(debugDisplay); + m_editorBoxSelect.Display2d(viewportInfo, debugDisplay); } template diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp index 9fda3fa291..f3c6a014cd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include @@ -56,22 +56,47 @@ namespace AzToolsFramework void AzToolsFrameworkConfigurationSystemComponent::Activate() { - // Associate the EditorEntityContext with the default scene. + // Create the editor specific child scene to the main scene and add the editor entity context to it. AzFramework::EntityContextId editorEntityContextId; EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); - AzFramework::Scene* defaultScene = nullptr; - AzFramework::SceneSystemRequestBus::BroadcastResult(defaultScene, &AzFramework::SceneSystemRequests::GetScene, "default"); - - if (!editorEntityContextId.IsNull() && defaultScene) + if (!editorEntityContextId.IsNull()) { - bool success = false; - AzFramework::SceneSystemRequestBus::BroadcastResult(success, &AzFramework::SceneSystemRequests::SetSceneForEntityContextId, editorEntityContextId, defaultScene); + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Scene system not available to create the editor scene."); + AZStd::shared_ptr mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName); + if (mainScene) + { + AZ::Outcome, AZStd::string> editorScene = + sceneSystem->CreateSceneWithParent(AzFramework::Scene::EditorMainSceneName, mainScene); + if (editorScene.IsSuccess()) + { + AzFramework::EntityContext* editorEntityContext = nullptr; + EditorEntityContextRequestBus::BroadcastResult( + editorEntityContext, &EditorEntityContextRequests::GetEditorEntityContextInstance); + if (editorEntityContext != nullptr) + { + [[maybe_unused]] bool contextAdded = + editorScene.GetValue()->SetSubsystem(editorEntityContext); + AZ_Assert(contextAdded, "Unable to add editor entity context to scene."); + } + } + else + { + AZ_Assert(false, "Failed to create editor scene because: %s", editorScene.GetError().c_str()); + } + } + else + { + AZ_Assert(false, "No main scene to parent the editor scene under."); + } } } void AzToolsFrameworkConfigurationSystemComponent::Deactivate() { + [[maybe_unused]] bool success = AzFramework::SceneSystemInterface::Get()->RemoveScene(AzFramework::Scene::EditorMainSceneName); + AZ_Assert(success, "Unable to remove the main editor scene."); } void AzToolsFrameworkConfigurationSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp index 6f7ae362fd..922ff8ae8c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEntityIdCtrl.cpp @@ -121,17 +121,14 @@ namespace AzToolsFramework EditorPickModeRequestBus::Handler::BusConnect(pickModeEntityContextId); EditorEventsBus::Handler::BusConnect(); - if (IsNewViewportInteractionModelEnabled()) + // replace the default input handler with one specific for dealing with + // entity selection in the viewport + EditorInteractionSystemViewportSelectionRequestBus::Event( + GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetHandler, + [](const EditorVisibleEntityDataCache* entityDataCache) { - // replace the default input handler with one specific for dealing with - // entity selection in the viewport - EditorInteractionSystemViewportSelectionRequestBus::Event( - GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetHandler, - [](const EditorVisibleEntityDataCache* entityDataCache) - { - return AZStd::make_unique(entityDataCache); - }); - } + return AZStd::make_unique(entityDataCache); + }); if (!pickModeEntityContextId.IsNull()) { @@ -162,12 +159,9 @@ namespace AzToolsFramework EditorEventsBus::Handler::BusDisconnect(); emit OnPickComplete(); - if (IsNewViewportInteractionModelEnabled()) - { - // return to the default viewport editor selection - EditorInteractionSystemViewportSelectionRequestBus::Event( - GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetDefaultHandler); - } + // return to the default viewport editor selection + EditorInteractionSystemViewportSelectionRequestBus::Event( + GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetDefaultHandler); EditorPickModeNotificationBus::Broadcast(&EditorPickModeNotifications::OnEntityPickModeStopped); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index 5f7fce3c84..53dab661ce 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -126,7 +126,6 @@ namespace UnitTest /// Base fixture for ToolsApplication editor tests. class ToolsApplicationFixture : public AllocatorsTestFixture - , private AzToolsFramework::NewViewportInteractionModelEnabledRequestBus::Handler { public: void SetUp() override final @@ -148,8 +147,6 @@ namespace UnitTest // in the unit tests. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - AzToolsFramework::NewViewportInteractionModelEnabledRequestBus::Handler::BusConnect(); - m_editorActions.Connect(); const auto viewportHandlerBuilder = @@ -184,7 +181,6 @@ namespace UnitTest TearDownEditorFixtureImpl(); m_editorActions.Disconnect(); - AzToolsFramework::NewViewportInteractionModelEnabledRequestBus::Handler::BusDisconnect(); // Stop & delete the Application created by this fixture, hence not using GetApplication() here if (m_app) @@ -222,14 +218,6 @@ namespace UnitTest private: AZStd::unique_ptr m_app; - - // NewViewportInteractionModelEnabledRequestBus ... - bool IsNewViewportInteractionModelEnabled() override - { - // default to the new viewport interaction model bus being enabled so the - // manipulator manager is correctly instantiated in EditorDefaultSelection - return true; - } }; class EditorEntityComponentChangeDetector diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp index d9cf4af944..2e467caa4c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.cpp @@ -13,6 +13,7 @@ #include "EditorBoxSelect.h" #include +#include #include @@ -72,7 +73,7 @@ namespace AzToolsFramework m_previousModifiers = mouseInteraction.m_mouseInteraction.m_keyboardModifiers; } - void EditorBoxSelect::Display2d(AzFramework::DebugDisplayRequests& debugDisplay) + void EditorBoxSelect::Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework); @@ -82,12 +83,15 @@ namespace AzToolsFramework debugDisplay.SetLineWidth(s_boxSelectLineWidth); debugDisplay.SetColor(s_boxSelectColor); - debugDisplay.DrawWireBox( - AZ::Vector3( - static_cast(m_boxSelectRegion->x()), static_cast(m_boxSelectRegion->y()), 0.0f), - AZ::Vector3( - static_cast(m_boxSelectRegion->x()) + static_cast(m_boxSelectRegion->width()), - static_cast(m_boxSelectRegion->y()) + static_cast(m_boxSelectRegion->height()), 0.0f)); + AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize; + + debugDisplay.DrawWireQuad2d( + AZ::Vector2( + aznumeric_cast(m_boxSelectRegion->x()), aznumeric_cast(m_boxSelectRegion->y())) / viewportSize, + AZ::Vector2( + aznumeric_cast(m_boxSelectRegion->x()) + aznumeric_cast(m_boxSelectRegion->width()), + aznumeric_cast(m_boxSelectRegion->y()) + aznumeric_cast(m_boxSelectRegion->height())) / viewportSize, + 0.f); debugDisplay.DepthTestOn(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h index d9fca58168..7f50b16325 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorBoxSelect.h @@ -42,7 +42,7 @@ namespace AzToolsFramework const ViewportInteraction::MouseInteractionEvent& mouseInteraction); /// Responsible for drawing the 2d box representing the selection in screen space. - void Display2d(AzFramework::DebugDisplayRequests& debugDisplay); + void Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay); /// Custom drawing behavior to happen during a box select. void DisplayScene( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp index 1d32e5f6e6..a7f500cc5f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp @@ -30,15 +30,9 @@ namespace AzToolsFramework ActionOverrideRequestBus::Handler::BusConnect(GetEntityContextId()); ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusConnect(); - // only create EditorTransformComponentSelection if we are using the new viewport interaction model - // note: EditorDefaultSelection is still used when the new viewport interaction model is disabled to support - // Component Mode when using legacy viewport interaction model - if (IsNewViewportInteractionModelEnabled()) - { - m_manipulatorManager = - AZStd::make_shared(AzToolsFramework::g_mainManipulatorManagerId); - m_transformComponentSelection = AZStd::make_unique(entityDataCache); - } + m_manipulatorManager = + AZStd::make_shared(AzToolsFramework::g_mainManipulatorManagerId); + m_transformComponentSelection = AZStd::make_unique(entityDataCache); } EditorDefaultSelection::~EditorDefaultSelection() @@ -325,17 +319,14 @@ namespace AzToolsFramework m_transformComponentSelection->DisplayViewportSelection(viewportInfo, debugDisplay); } - if (IsNewViewportInteractionModelEnabled()) - { - // poll and set the keyboard modifiers to ensure the mouse interaction is up to date - m_currentInteraction.m_keyboardModifiers = - AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()); - // draw the manipulators - const AzFramework::CameraState cameraState = GetCameraState(viewportInfo.m_viewportId); - debugDisplay.DepthTestOff(); - m_manipulatorManager->DrawManipulators(debugDisplay, cameraState, m_currentInteraction); - debugDisplay.DepthTestOn(); - } + // poll and set the keyboard modifiers to ensure the mouse interaction is up to date + m_currentInteraction.m_keyboardModifiers = + AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers()); + // draw the manipulators + const AzFramework::CameraState cameraState = GetCameraState(viewportInfo.m_viewportId); + debugDisplay.DepthTestOff(); + m_manipulatorManager->DrawManipulators(debugDisplay, cameraState, m_currentInteraction); + debugDisplay.DepthTestOn(); } void EditorDefaultSelection::DisplayViewportSelection2d( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 433602e6d8..ec22a2f7c8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -441,7 +441,7 @@ namespace AzToolsFramework clusterId); } - static void SetViewportUiClusterVisible(ViewportUi::ClusterId clusterId, bool visible) + static void SetViewportUiClusterVisible(const ViewportUi::ClusterId clusterId, const bool visible) { ViewportUi::ViewportUiRequestBus::Event( ViewportUi::DefaultViewportId, @@ -449,7 +449,7 @@ namespace AzToolsFramework clusterId, visible); } - static void SetViewportUiClusterActiveButton(ViewportUi::ClusterId clusterId, ViewportUi::ButtonId buttonId) + static void SetViewportUiClusterActiveButton(const ViewportUi::ClusterId clusterId, const ViewportUi::ButtonId buttonId) { ViewportUi::ViewportUiRequestBus::Event( ViewportUi::DefaultViewportId, @@ -457,7 +457,7 @@ namespace AzToolsFramework clusterId, buttonId); } - static ViewportUi::ButtonId RegisterClusterButton(ViewportUi::ClusterId clusterId, const char* iconName) + static ViewportUi::ButtonId RegisterClusterButton(const ViewportUi::ClusterId clusterId, const char* iconName) { ViewportUi::ButtonId buttonId; ViewportUi::ViewportUiRequestBus::EventResult( @@ -3494,7 +3494,7 @@ namespace AzToolsFramework DrawAxisGizmo(viewportInfo, debugDisplay); - m_boxSelect.Display2d(debugDisplay); + m_boxSelect.Display2d(viewportInfo, debugDisplay); } void EditorTransformComponentSelection::RefreshSelectedEntityIds() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.cpp index 701344db18..7ef6d96223 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.cpp @@ -13,7 +13,6 @@ #include "AzToolsFramework_precompiled.h" #include -#include namespace AzToolsFramework::ViewportUi::Internal { @@ -22,4 +21,11 @@ namespace AzToolsFramework::ViewportUi::Internal , m_buttonId(buttonId) { } + + Button::Button(AZStd::string icon, AZStd::string name, ButtonId buttonId) + : m_icon(AZStd::move(icon)) + , m_name(AZStd::move(name)) + , m_buttonId(buttonId) + { + } } // namespace AzToolsFramework::ViewportUi::Internal diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.h index 8ff98abc5d..cd4d548510 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Button.h @@ -12,7 +12,6 @@ #pragma once -#include #include namespace AzToolsFramework::ViewportUi::Internal @@ -27,10 +26,12 @@ namespace AzToolsFramework::ViewportUi::Internal Deselected }; - explicit Button(AZStd::string icon, ButtonId buttonId); + Button(AZStd::string icon, ButtonId buttonId); + Button(AZStd::string icon, AZStd::string name, ButtonId buttonId); ~Button() = default; AZStd::string m_icon; //!< The icon for this button, string path to an image. + AZStd::string m_name; //!< The name displayed as a label next to the button's icon. State m_state = State::Deselected; ButtonId m_buttonId; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Cluster.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp similarity index 66% rename from Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Cluster.cpp rename to Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp index 2de6836aa5..3aeb14ed46 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/Cluster.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp @@ -11,37 +11,27 @@ */ #include -#include +#include namespace AzToolsFramework::ViewportUi::Internal { - Cluster::Cluster() + ButtonGroup::ButtonGroup() : m_buttons() , m_buttonTriggeredEvent() { } - void Cluster::SetViewportUiElementId(const ViewportUiElementId id) + void ButtonGroup::SetViewportUiElementId(const ViewportUiElementId id) { m_viewportUiId = id; } - ViewportUiElementId Cluster::GetViewportUiElementId() const + ViewportUiElementId ButtonGroup::GetViewportUiElementId() const { return m_viewportUiId; } - void Cluster::SetClusterId(const ClusterId clusterId) - { - m_clusterId = clusterId; - } - - ClusterId Cluster::GetClusterId() const - { - return m_clusterId; - } - - void Cluster::SetHighlightedButton(ButtonId buttonId) + void ButtonGroup::SetHighlightedButton(ButtonId buttonId) { if (auto buttonEntry = m_buttons.find(buttonId); buttonEntry != m_buttons.end()) { @@ -53,15 +43,22 @@ namespace AzToolsFramework::ViewportUi::Internal } } - ButtonId Cluster::AddButton(const AZStd::string& icon) + ButtonId ButtonGroup::AddButton(const AZStd::string& icon, const AZStd::string& name) { auto buttonId = ButtonId(m_buttons.size() + 1); - m_buttons.insert({buttonId, AZStd::make_unique