From 3a3869b4da63b7cc06603fcb637ed1bfecf48c28 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Thu, 20 May 2021 22:32:29 -0700 Subject: [PATCH 01/12] Removed unnecessary "is not a function" warnings from ScriptContext. All these warnings are followed by returning false, which call sites can use to report warnings where appropriate. In the case of material lua functors, it is not appropriate to report a warning which is why I'm removing these. The material system uses the "Call" API to potentially call a function that may or may not exist, and it is acceptable for that function to be absent. --- Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp index ac1e61a5aa..9bf6247e97 100644 --- a/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp +++ b/Code/Framework/AzCore/AzCore/Script/ScriptContext.cpp @@ -2048,10 +2048,6 @@ LUA_API const Node* lua_getDummyNode() return true; } - else - { - AZ_Warning("Script", false, "Index %d is not a function!", functionIndex); - } return false; } @@ -2078,7 +2074,6 @@ LUA_API const Node* lua_getDummyNode() } else { - AZ_Warning("Script", lua_isnil(m_nativeContext, -1), "Name %s exists but is not a function!", functionName); lua_pop(m_nativeContext, 1); } @@ -5888,7 +5883,6 @@ LUA_API const Node* lua_getDummyNode() else { lua_pop(m_impl->m_lua, 1); - AZ_Warning("Script", false, "%s is not a function!", functionName); } return false; } @@ -5906,7 +5900,6 @@ LUA_API const Node* lua_getDummyNode() else { lua_pop(m_impl->m_lua, 1); - AZ_Warning("Script", false, "CacheIndex %d is not a function!", cachedIndex); } return false; } From 7d0fc036745b20222c617aa4bb93255dccd241b5 Mon Sep 17 00:00:00 2001 From: mriegger Date: Mon, 24 May 2021 17:13:14 -0700 Subject: [PATCH 02/12] Fixing spelling in lua files --- .../Materials/Types/StandardMultilayerPBR_ShaderEnable.lua | 4 ++-- .../Assets/Materials/Types/StandardPBR_ShaderEnable.lua | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ShaderEnable.lua index 69df610ab2..778edeea18 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ShaderEnable.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ShaderEnable.lua @@ -24,7 +24,7 @@ function Process(context) local shadowMap = context:GetShaderByTag("Shadowmap") local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS") local depthPassWithPS = context:GetShaderByTag("DepthPass_WithPS") - local shadowMapWitPS = context:GetShaderByTag("Shadowmap_WithPS") + local shadowMapWithPS = context:GetShaderByTag("Shadowmap_WithPS") local forwardPass = context:GetShaderByTag("ForwardPass") local shadingAffectsDepth = parallaxEnabled and parallaxPdoEnabled; @@ -34,6 +34,6 @@ function Process(context) forwardPassEDS:SetEnabled(not shadingAffectsDepth) depthPassWithPS:SetEnabled(shadingAffectsDepth) - shadowMapWitPS:SetEnabled(shadingAffectsDepth) + shadowMapWithPS:SetEnabled(shadingAffectsDepth) forwardPass:SetEnabled(shadingAffectsDepth) end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua index 2733713122..e502eb38f8 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ShaderEnable.lua @@ -32,7 +32,7 @@ function Process(context) local lowEndForwardEDS = context:GetShaderByTag("LowEndForward_EDS") local depthPassWithPS = context:GetShaderByTag("DepthPass_WithPS") - local shadowMapWitPS = context:GetShaderByTag("Shadowmap_WithPS") + local shadowMapWithPS = context:GetShaderByTag("Shadowmap_WithPS") local forwardPass = context:GetShaderByTag("ForwardPass") local lowEndForward = context:GetShaderByTag("LowEndForward") @@ -43,7 +43,7 @@ function Process(context) lowEndForwardEDS:SetEnabled(false) depthPassWithPS:SetEnabled(true) - shadowMapWitPS:SetEnabled(true) + shadowMapWithPS:SetEnabled(true) forwardPass:SetEnabled(true) lowEndForward:SetEnabled(true) else @@ -53,7 +53,7 @@ function Process(context) lowEndForwardEDS:SetEnabled((opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent)) depthPassWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) - shadowMapWitPS:SetEnabled(opacityMode == OpacityMode_Cutout) + shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout) forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout) lowEndForward:SetEnabled(opacityMode == OpacityMode_Cutout) end From 14513af1fe035eb59d150b9a7057563a8c37cc34 Mon Sep 17 00:00:00 2001 From: mriegger Date: Tue, 25 May 2021 08:48:18 -0700 Subject: [PATCH 03/12] Fix for lowend pipeline not having shadows (needed update call) --- .../CoreLights/DirectionalLightFeatureProcessor.cpp | 12 +++++++++++- .../CoreLights/DirectionalLightFeatureProcessor.h | 3 +++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index ade4b5b592..9b40097716 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -203,7 +203,7 @@ namespace AZ if (m_shadowingLightHandle.IsValid()) { uint32_t shadowFilterMethod = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_shadowFilterMethod; - RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(AZ::Name{"o_directional_shadow_filtering_method"}, AZ::RPI::ShaderOptionValue{shadowFilterMethod}); + RPI::ShaderSystemInterface::Get()->SetGlobalShaderOption(m_directionalShadowFilteringMethodName, AZ::RPI::ShaderOptionValue{shadowFilterMethod}); const uint32_t cascadeCount = m_shadowData.at(nullptr).GetData(m_shadowingLightHandle.GetIndex()).m_cascadeCount; ShadowProperty& property = m_shadowProperties.GetData(m_shadowingLightHandle.GetIndex()); @@ -656,6 +656,7 @@ namespace AZ CacheRenderPipelineIdsForPersistentView(); SetConfigurationToPasses(); SetCameraViewNameToPass(); + UpdateViewsOfCascadeSegments(); } void DirectionalLightFeatureProcessor::CacheCascadedShadowmapsPass() { @@ -1344,6 +1345,15 @@ namespace AZ } } + void DirectionalLightFeatureProcessor::UpdateViewsOfCascadeSegments() + { + if (m_shadowingLightHandle.IsValid()) + { + const uint16_t cascadeCount = GetCascadeCount(m_shadowingLightHandle); + UpdateViewsOfCascadeSegments(m_shadowingLightHandle, cascadeCount); + } + } + Aabb DirectionalLightFeatureProcessor::CalculateShadowViewAabb( LightHandle handle, const RPI::View* cameraView, diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h index a276ea3f3e..f8c00c859c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.h @@ -296,6 +296,8 @@ namespace AZ //! This updates the shadowmap view. void UpdateShadowmapViews(LightHandle handle); + void UpdateViewsOfCascadeSegments(); + //! This calculate shadow view AABB. Aabb CalculateShadowViewAabb( LightHandle handle, @@ -372,6 +374,7 @@ namespace AZ uint32_t m_shadowmapIndexTableBufferNameIndex = 0; Name m_lightTypeName = Name("directional"); + Name m_directionalShadowFilteringMethodName = Name("o_directional_shadow_filtering_method"); static constexpr const char* FeatureProcessorName = "DirectionalLightFeatureProcessor"; }; } // namespace Render From c1e7970dbbbef6afa51c06c9743e7a9184093d9f Mon Sep 17 00:00:00 2001 From: chcurran Date: Tue, 25 May 2021 12:07:14 -0700 Subject: [PATCH 04/12] Add support for unordered_set to ScriptCanvas. Improved graph version upgrade systems and fixed related bugs. --- .../AzCore/RTTI/AzStdOnDemandReflection.inl | 111 +++++++++-- .../AzCore/AzCore/RTTI/BehaviorContext.cpp | 6 +- .../AzCore/RTTI/BehaviorContextUtilities.cpp | 45 +++-- .../AzCore/RTTI/BehaviorContextUtilities.h | 2 + .../UI/PropertyEditor/GenericComboBoxCtrl.h | 9 +- .../Code/Editor/Components/EditorGraph.cpp | 107 ++++------ .../Code/Editor/Components/GraphUpgrade.cpp | 29 +-- .../ScriptCanvas/Components/EditorGraph.h | 5 +- .../ScriptCanvas/Components/GraphUpgrade.h | 2 +- .../View/EditCtrls/GenericLineEditCtrl.h | 5 + .../AutoGen/ScriptCanvasGrammar_Header.jinja | 4 +- .../Include/ScriptCanvas/Core/Connection.h | 3 + .../Core/Contracts/MethodOverloadContract.cpp | 27 +-- .../Code/Include/ScriptCanvas/Core/Graph.cpp | 29 ++- .../Code/Include/ScriptCanvas/Core/Graph.h | 1 + .../Code/Include/ScriptCanvas/Core/PureData.h | 4 +- .../Code/Include/ScriptCanvas/Core/Slot.cpp | 5 + .../Code/Include/ScriptCanvas/Core/Slot.h | 2 + .../Grammar/AbstractCodeModel.cpp | 24 +-- .../Libraries/Core/BinaryOperator.cpp | 9 - .../Libraries/Core/BinaryOperator.h | 1 - .../ScriptCanvas/Libraries/Core/ForEach.cpp | 184 ------------------ .../ScriptCanvas/Libraries/Core/ForEach.h | 45 ++--- .../Libraries/Core/FunctionCallNode.cpp | 5 + .../Libraries/Core/FunctionCallNode.h | 2 + .../Libraries/Core/FunctionDefinitionNode.cpp | 23 ++- .../Libraries/Core/FunctionDefinitionNode.h | 8 +- .../ScriptCanvas/Libraries/Core/Method.cpp | 7 +- .../ScriptCanvas/Libraries/Core/Method.h | 4 + .../Libraries/Core/MethodOverloaded.cpp | 49 ++++- .../Libraries/Core/MethodOverloaded.h | 2 +- .../Libraries/Operators/Operator.cpp | 8 - .../Libraries/Operators/Operator.h | 1 - .../Time/Timer.ScriptCanvasGrammar.xml | 4 +- .../ScriptCanvas/Utils/VersioningUtils.cpp | 110 +++++++++++ .../ScriptCanvas/Utils/VersioningUtils.h | 29 ++- .../Source/InputNode.ScriptCanvasGrammar.xml | 6 +- 37 files changed, 505 insertions(+), 412 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl index 079c70c878..537d3e5c83 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl +++ b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl @@ -1020,29 +1020,60 @@ namespace AZ } }; - /// OnDemand reflection for AZStd::set + + template + class Iterator_VM> + { + public: + using ContainerType = AZStd::unordered_set; + using IteratorType = typename ContainerType::iterator; + Iterator_VM(ContainerType& container) + : m_iterator(container.begin()) + , m_end(container.end()) + {} + + const t_Key& GetKeyUnchecked() const + { + return *m_iterator; + } + + bool IsNotAtEnd() const + { + return m_iterator != m_end; + } + + t_Key& ModValueUnchecked() + { + return *m_iterator; + } + + void Next() + { + ++m_iterator; + } + + private: + IteratorType m_iterator; + IteratorType m_end; + }; + + /// OnDemand reflection for AZStd::unordered_set template struct OnDemandReflection< AZStd::unordered_set > { using ContainerType = AZStd::unordered_set; using KeyListType = AZStd::vector; - static AZ::Outcome Erase(ContainerType& thisMap, Key& key) + using ValueIteratorType = Iterator_VM; + + static bool EraseCheck_VM(ContainerType& thisSet, Key& key) { - const auto result = thisMap.erase(key); - if (result) - { - return AZ::Success(); - } - else - { - return AZ::Failure(); - } + return thisSet.erase(key) != 0; } - static void Insert(ContainerType& thisSet, Key& key) + static ContainerType& ErasePost_VM(ContainerType& thisSet, [[maybe_unused]] Key&) { - thisSet.insert(key); + return thisSet; } static KeyListType GetKeys(ContainerType& thisSet) @@ -1055,6 +1086,17 @@ namespace AZ return keys; } + static ContainerType& Insert(ContainerType& thisSet, Key& key) + { + thisSet.insert(key); + return thisSet; + } + + static ValueIteratorType Iterate_VM(ContainerType& thisContainer) + { + return ValueIteratorType(thisContainer); + } + static void Swap(ContainerType& thisSet, ContainerType& otherSet) { thisSet.swap(otherSet); @@ -1064,33 +1106,68 @@ namespace AZ { if (BehaviorContext* behaviorContext = azrtti_cast(context)) { + BranchOnResultInfo emptyBranchInfo; + emptyBranchInfo.m_returnResultInBranches = true; + emptyBranchInfo.m_trueToolTip = "The container is empty"; + emptyBranchInfo.m_falseToolTip = "The container is not empty"; + auto ContainsTransparent = [](const ContainerType& containerType, typename ContainerType::key_type& key)->bool { return containerType.contains(key); }; + ExplicitOverloadInfo explicitOverloadInfo; behaviorContext->Class() - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly) ->Attribute(AZ::ScriptCanvasAttributes::PrettyName, ScriptCanvasOnDemandReflection::OnDemandPrettyName::Get(*behaviorContext)) ->Attribute(AZ::Script::Attributes::ToolTip, ScriptCanvasOnDemandReflection::OnDemandToolTip::Get(*behaviorContext)) ->Attribute(AZ::Script::Attributes::Category, ScriptCanvasOnDemandReflection::OnDemandCategoryName::Get(*behaviorContext)) ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::ScriptOwn) ->Method("BucketCount", static_cast(&ContainerType::bucket_count)) - ->Method("Erase", &Erase) - ->Method("Empty", [](ContainerType& thisSet)->bool { return thisSet.empty(); }) + ->Method("Empty", static_cast(&ContainerType::empty), { { { "Container", "The container to check if it is empty", nullptr, {} } } }) + ->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Is Empty", "Containers")) + ->Attribute(AZ::ScriptCanvasAttributes::BranchOnResult, emptyBranchInfo) + ->Method("EraseCheck_VM", &EraseCheck_VM) + ->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent) + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) + ->Method("Erase", &ErasePost_VM) + ->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent) + ->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Erase", "Containers")) + ->Attribute(AZ::ScriptCanvasAttributes::CheckedOperation, CheckedOperationInfo("EraseCheck_VM", {}, "Out", "Key Not Found", true)) + ->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup", "" }, { "ContainerGroup" })) ->Method("contains", ContainsTransparent) + ->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Has Key", "Containers")) ->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent) ->Method("Insert", &Insert) + ->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent) + ->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Insert", "Containers")) + ->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup", "", "" }, { "ContainerGroup" })) ->Method(k_sizeName, [](ContainerType* thisPtr) { return aznumeric_cast(thisPtr->size()); }) ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::Length) ->Method("GetKeys", &GetKeys) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) + ->Method("GetSize", [](ContainerType& thisPtr) { return aznumeric_cast(thisPtr.size()); }) + ->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Get Size", "Containers")) + ->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent) ->Method("Reserve", static_cast(&ContainerType::reserve)) ->Method("Swap", &Swap) + ->Method("Clear", [](ContainerType& thisContainer)->ContainerType& { thisContainer.clear(); return thisContainer; }) + ->Attribute(AZ::Script::Attributes::TreatAsMemberFunction, AZ::AttributeIsValid::IfPresent) + ->Attribute(AZ::ScriptCanvasAttributes::ExplicitOverloadCrc, ExplicitOverloadInfo("Clear All Elements", "Containers")) + ->Attribute(AZ::ScriptCanvasAttributes::OverloadArgumentGroup, AZ::OverloadArgumentGroupInfo({ "ContainerGroup" }, { "ContainerGroup" })) + ->Method(k_iteratorConstructorName, &Iterate_VM) + ; + + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly) + ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::ScriptOwn) + ->Method(k_iteratorGetKeyName, &ValueIteratorType::GetKeyUnchecked) + ->Method(k_iteratorModValueName, &ValueIteratorType::ModValueUnchecked) + ->Method(k_iteratorIsNotAtEndName, &ValueIteratorType::IsNotAtEnd) + ->Method(k_iteratorNextName, &ValueIteratorType::Next) ; } } - }; template <> diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.cpp b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.cpp index 635d160434..31a2cfc09e 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.cpp +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContext.cpp @@ -165,7 +165,7 @@ namespace AZ if (HasResult() != overload->HasResult()) { - AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all"); + AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all: %s", m_name.c_str()); return false; } @@ -176,7 +176,7 @@ namespace AZ if (!(methodResult->m_typeId == overloadResult->m_typeId && methodResult->m_traits == overloadResult->m_traits)) { - AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all"); + AZ_Error("Reflection", false, "Overload failure, all methods must have the same result, or none at all: %s", m_name.c_str()); return false; } } @@ -575,7 +575,7 @@ namespace AZ } else { - AZ_Error("BehaviorContext", false, "safety check declared for method %s but it was not found in the class"); + AZ_Error("BehaviorContext", false, "Method: %s, declared safety check: %s, but it was not found in class: %s", method.m_name.c_str(), m_name.c_str(), checkedOperationInfo.m_safetyCheckName.c_str()); } } } diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.cpp b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.cpp index c64b86ae0f..f6aac0fa16 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.cpp +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.cpp @@ -34,10 +34,17 @@ namespace BehaviorContextUtilitiesCPP using argument_type = const BehaviorParameter*; using result_type = size_t; result_type operator()(const argument_type& value) const - { - result_type result = AZStd::hash()(value->m_typeId); - AZStd::hash_combine(result, CleanTraits(value->m_traits)); - return result; + { + if (value) + { + result_type result = AZStd::hash()(value->m_typeId); + AZStd::hash_combine(result, CleanTraits(value->m_traits)); + return result; + } + else + { + return 0; + } } }; @@ -45,7 +52,11 @@ namespace BehaviorContextUtilitiesCPP { bool operator()(const BehaviorParameter* left, const BehaviorParameter* right) const { - return left->m_typeId == right->m_typeId && CleanTraits(left->m_traits) == CleanTraits(right->m_traits); + return (left == nullptr && right == nullptr) + || (left != nullptr + && right != nullptr + && left->m_typeId == right->m_typeId + && CleanTraits(left->m_traits) == CleanTraits(right->m_traits)); } }; @@ -137,7 +148,7 @@ namespace AZ for (size_t argIndex = 0, argSentinel = overload.GetNumArguments(); argIndex < argSentinel; ++argIndex) { auto overloadedArgIter = variance.m_input.find(argIndex); - if (overloadedArgIter != variance.m_input.end()) + if (overloadedArgIter != variance.m_input.end() && overloadedArgIter->second[overloadIndex]) { // if this doesn't work try the type name overloadName += ReplaceCppArtifacts(overloadedArgIter->second[overloadIndex]->m_name); @@ -185,16 +196,24 @@ namespace AZ { auto argument = overloads[overloadIndex].first->GetArgument(0); - const bool isThisPointer - = (argument->m_traits & AZ::BehaviorParameter::Traits::TR_THIS_PTR) != 0 - || AZ::FindAttribute(AZ::Script::Attributes::TreatAsMemberFunction, overloads[overloadIndex].first->m_attributes); + if (argument) + { + const bool isThisPointer + = (argument->m_traits & AZ::BehaviorParameter::Traits::TR_THIS_PTR) != 0 + || AZ::FindAttribute(AZ::Script::Attributes::TreatAsMemberFunction, overloads[overloadIndex].first->m_attributes); - oneArgIsThisPointer = oneArgIsThisPointer || isThisPointer; + oneArgIsThisPointer = oneArgIsThisPointer || isThisPointer; + } types.insert(argument); stripedArgs.emplace_back(argument); } + if (types.size() == overloads.size()) + { + variance.m_unambiguousInput.insert(0); + } + if (types.size() > 1 && (onThis == VariantOnThis::Yes || !oneArgIsThisPointer)) { variance.m_input.insert(AZStd::make_pair(0, stripedArgs)); @@ -210,11 +229,15 @@ namespace AZ for (size_t overloadIndex = 0, overloadSentinel = overloads.size(); overloadIndex < overloadSentinel; ++overloadIndex) { auto argument = overloads[overloadIndex].first->GetArgument(argIndex); - types.insert(argument); stripedArgs.emplace_back(argument); } + if (types.size() == overloads.size()) + { + variance.m_unambiguousInput.insert(0); + } + if (types.size() > 1) { variance.m_input.insert(AZStd::make_pair(argIndex, stripedArgs)); diff --git a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.h b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.h index 4663635cdf..0dc9ecc969 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.h +++ b/Code/Framework/AzCore/AzCore/RTTI/BehaviorContextUtilities.h @@ -27,6 +27,8 @@ namespace AZ struct OverloadVariance { AZStd::unordered_map> m_input; + // the indices of inputs that make selection of overload unambiguous + AZStd::unordered_set m_unambiguousInput; AZStd::vector m_output; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h index 48b5148d3c..4cf6d077e7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/GenericComboBoxCtrl.h @@ -83,7 +83,7 @@ namespace AzToolsFramework protected: QWidget* GetFirstInTabOrder() override; QWidget* GetLastInTabOrder() override; - void UpdateTabOrder() override; + void UpdateTabOrder() override; void onChildComboBoxValueChange(int comboBoxIndex) override; @@ -93,7 +93,7 @@ namespace AzToolsFramework void addElementImpl(const AZStd::pair& genericValue); - QLabel* m_warningLabel = nullptr; + QLabel* m_warningLabel = nullptr; DHQComboBox* m_pComboBox; AZStd::vector> m_values; AZ::AttributeFunction * m_postChangeNotifyCB{}; @@ -131,6 +131,11 @@ namespace AzToolsFramework template AzToolsFramework::PropertyHandlerBase* RegisterGenericComboBoxHandler() { + if (!AzToolsFramework::PropertyTypeRegistrationMessages::Bus::FindFirstHandler()) + { + return nullptr; + } + auto propertyHandler = aznew GenericComboBoxHandler(); AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(&AzToolsFramework::PropertyTypeRegistrationMessages::RegisterPropertyType, propertyHandler); return propertyHandler; diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 9c9297ec1c..6f28cbfe19 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -512,7 +512,7 @@ namespace ScriptCanvasEditor } } - bool Graph::SanityCheckNodeReplacement(ScriptCanvas::Node* oldNode, ScriptCanvas::Node* newNode, AZStd::unordered_map>& outSlotIdMap) + bool Graph::SanityCheckNodeReplacement(ScriptCanvas::Node* oldNode, ScriptCanvas::Node* newNode, ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport) { auto findReplacementMatch = [](const ScriptCanvas::Slot* oldSlot, const AZStd::vector& newSlots)->ScriptCanvas::SlotId { @@ -529,14 +529,14 @@ namespace ScriptCanvasEditor return {}; }; - oldNode->CustomizeReplacementNode(newNode, outSlotIdMap); - if (!newNode) { AZ_Warning("ScriptCanvas", false, "Replacement node can not be null."); return false; } + oldNode->CustomizeReplacementNode(newNode, nodeUpdateSlotReport.m_oldSlotsToNewSlots); + AZStd::unordered_map> slotNameMap = oldNode->GetReplacementSlotsMap(); const auto newSlots = newNode->GetAllSlots(); @@ -544,16 +544,19 @@ namespace ScriptCanvasEditor bool usingDefaults = true; size_t defaultMatchesFound = 0; + auto& oldSlotsToNewSlots = nodeUpdateSlotReport.m_oldSlotsToNewSlots; + for (auto oldSlot : oldSlots) { const ScriptCanvas::SlotId oldSlotId = oldSlot->GetId(); const AZStd::string oldSlotName = oldSlot->GetName(); - auto slotIdsIter = outSlotIdMap.find(oldSlotId); + + auto slotIdsIter = oldSlotsToNewSlots.find(oldSlotId); auto slotNamesIter = slotNameMap.find(oldSlotName); // For old node slot remapping, we should get: // 1. if old slot name is not static, we should find the mapping in user provided slot id map // 2. if old slot name is static, we should find the mapping in codegen generated map (case 1 can override case 2) - if (slotIdsIter != outSlotIdMap.end()) + if (slotIdsIter != oldSlotsToNewSlots.end()) { for (auto newSlotId : slotIdsIter->second) { @@ -581,9 +584,10 @@ namespace ScriptCanvasEditor if (!newSlotName.empty()) { auto newSlot = newNode->GetSlotByName(newSlotName); + if (!newSlot) { - AZ_Warning("ScriptCanvas", false, "Failed to find slot with name %s in replacement Node(%s).", newSlotName.c_str(), newNode->GetNodeName().c_str()); + AZ_Warning("ScriptCanvas", false, "Failed to find slot with name %s in replacement Node (%s).", newSlotName.c_str(), newNode->GetNodeName().c_str()); return false; } else if (newSlot && oldSlot->GetType() != newSlot->GetType()) @@ -591,10 +595,11 @@ namespace ScriptCanvasEditor AZ_Warning("ScriptCanvas", false, "Failed to map deprecated Node (%s) Slot (%s) to replacement Node (%s) Slot (%s).", oldNode->GetNodeName().c_str(), oldSlot->GetName().c_str(), newNode->GetNodeName().c_str(), newSlot->GetName().c_str()); return false; } + newSlotIds.push_back(newSlot->GetId()); } } - outSlotIdMap.emplace(oldSlot->GetId(), newSlotIds); + oldSlotsToNewSlots.emplace(oldSlot->GetId(), newSlotIds); } else if (slotNameMap.empty()) { @@ -605,7 +610,7 @@ namespace ScriptCanvasEditor { ++defaultMatchesFound; AZStd::vector slotIds{ newSlotId }; - outSlotIdMap.emplace(oldSlot->GetId(), slotIds); + oldSlotsToNewSlots.emplace(oldSlot->GetId(), slotIds); } } else @@ -615,7 +620,7 @@ namespace ScriptCanvasEditor } } - if (usingDefaults && defaultMatchesFound != oldSlots.size()) + if (usingDefaults && oldSlotsToNewSlots.size() != oldSlots.size()) { AZ_Warning("ScriptCanvas", false, "Failed to remap deprecated Node(%s) not all old slots were present in the new node.", oldNode->GetNodeName().c_str()); } @@ -690,8 +695,10 @@ namespace ScriptCanvasEditor } } - AZ::Outcome Graph::ReplaceNodeByConfig(ScriptCanvas::Node* oldNode, const ScriptCanvas::NodeConfiguration& nodeConfig, - ScriptCanvas::ReplacementConnectionMap& remapConnections) + AZ::Outcome Graph::ReplaceNodeByConfig + ( ScriptCanvas::Node* oldNode + , const ScriptCanvas::NodeConfiguration& nodeConfig + , ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport) { auto nodeEntity = oldNode->GetEntity(); if (!nodeEntity) @@ -731,8 +738,8 @@ namespace ScriptCanvasEditor AddNode(newNode->GetEntityId()); ScriptCanvas::NodeUtils::InitializeNode(newNode, nodeConfig); - AZStd::unordered_map> slotIdMap; - rollbackRequired = !SanityCheckNodeReplacement(oldNode, newNode, slotIdMap); + rollbackRequired = !SanityCheckNodeReplacement(oldNode, newNode, nodeUpdateSlotReport); + auto& slotIdMap = nodeUpdateSlotReport.m_oldSlotsToNewSlots; if (rollbackRequired) { @@ -748,25 +755,15 @@ namespace ScriptCanvasEditor else { nodeEntity->Activate(); - newNode->SignalReconfigurationBegin(); - newNode->SetNodeDisabledFlag(oldNode->GetNodeDisabledFlag()); + for (auto slotIdIter : slotIdMap) { ScriptCanvas::Slot* oldSlot = oldNode->GetSlot(slotIdIter.first); const ScriptCanvas::Endpoint oldEndpoint{ nodeEntity->GetId(), oldSlot->GetId() }; if (slotIdIter.second.size() == 0) { - // If remap id is empty, then we should just cache the old slot connection for delete - if (oldSlot->IsInput()) - { - ScriptCanvas::VersioningUtils::CreateRemapConnectionsForTargetEndpoint(*this, oldEndpoint, ScriptCanvas::Endpoint(), remapConnections); - } - else - { - ScriptCanvas::VersioningUtils::CreateRemapConnectionsForSourceEndpoint(*this, oldEndpoint, ScriptCanvas::Endpoint(), remapConnections); - } continue; } @@ -808,35 +805,11 @@ namespace ScriptCanvasEditor ScriptCanvas::VersioningUtils::CopyOldValueToDataSlot(newSlot, oldSlot->GetVariableReference(), oldSlot->FindDatum()); } - - // if old slot is visible, we need to check its connections for remapping - if (oldSlot->IsVisible()) - { - ScriptCanvas::Endpoint newEndpoint; - if (newSlot) - { - newEndpoint = { nodeEntity->GetId(), newSlot->GetId() }; - } - else - { - AZ_Warning("ScriptCanvas", false, "Invalid slot! Unable to create new connection for Node (%s).", newNode->GetNodeName().c_str()); - } - - if (oldSlot->IsInput()) - { - ScriptCanvas::VersioningUtils::CreateRemapConnectionsForTargetEndpoint(*this, oldEndpoint, newEndpoint, remapConnections); - } - else - { - ScriptCanvas::VersioningUtils::CreateRemapConnectionsForSourceEndpoint(*this, oldEndpoint, newEndpoint, remapConnections); - } - } } } + delete oldNode; - newNode->SignalReconfigurationEnd(); - return AZ::Success(newNode); } } @@ -3634,8 +3607,7 @@ namespace ScriptCanvasEditor AZStd::unordered_map< AZ::EntityId, AZ::EntityId > scriptCanvasToGraphCanvasMapping; - bool graphNeedsDirtying = false; - + bool graphNeedsDirtying = !GetVersion().IsLatest(); { QScopedValueRollback ignoreRequests(m_ignoreSaveRequests, true); @@ -3659,7 +3631,8 @@ namespace ScriptCanvasEditor AZStd::unordered_set deletedNodes; AZStd::unordered_set assetSanitizationSet; AZStd::unordered_set sanityCheckRequiredNodes; - ScriptCanvas::ReplacementConnectionMap remapConnections; + + ScriptCanvas::GraphUpdateSlotReport graphUpdateSlotReport; for (const AZ::EntityId& scriptCanvasNodeId : nodeList) { @@ -3674,12 +3647,15 @@ namespace ScriptCanvasEditor ScriptCanvas::NodeConfiguration nodeConfig = scriptCanvasNode->GetReplacementNodeConfiguration(); if (nodeConfig.IsValid()) { - auto nodeOutcome = ReplaceNodeByConfig(scriptCanvasNode, nodeConfig, remapConnections); + ScriptCanvas::NodeUpdateSlotReport nodeUpdateSlotReport; + auto nodeOutcome = ReplaceNodeByConfig(scriptCanvasNode, nodeConfig, nodeUpdateSlotReport); + if (nodeOutcome.IsSuccess()) { graphNeedsDirtying = true; scriptCanvasNode = nodeOutcome.GetValue(); m_updateStrings.insert(AZStd::string::format("Replaced node (%s)", scriptCanvasNode->GetNodeName().c_str())); + ScriptCanvas::MergeUpdateSlotReport(scriptCanvasNodeId, graphUpdateSlotReport, nodeUpdateSlotReport); } } } @@ -3688,7 +3664,6 @@ namespace ScriptCanvasEditor scriptCanvasToGraphCanvasMapping[scriptCanvasNodeId] = graphCanvasNodeId; auto saveDataIter2 = m_graphCanvasSaveData.find(scriptCanvasNodeId); - if (saveDataIter2 != m_graphCanvasSaveData.end()) { GraphCanvas::EntitySaveDataRequestBus::Event(graphCanvasNodeId, &GraphCanvas::EntitySaveDataRequests::ReadSaveData, (*saveDataIter2->second)); @@ -3699,7 +3674,7 @@ namespace ScriptCanvasEditor GraphCanvas::SceneRequestBus::Event(graphCanvasGraphId, &GraphCanvas::SceneRequests::AddNode, graphCanvasNodeId, position, false); - // If the node is deprecated, we want to stomp whatever style it had saved and apply the deperecated style + // If the node is deprecated, we want to stomp whatever style it had saved and apply the deprecated style if (scriptCanvasNode->IsDeprecated()) { GraphCanvas::NodeTitleRequestBus::Event(graphCanvasNodeId, &GraphCanvas::NodeTitleRequests::SetPaletteOverride, "DeprecatedNodeTitlePalette"); @@ -3719,27 +3694,13 @@ namespace ScriptCanvasEditor } } - // Remap connections step should be done before editor processing connections for graph - // - // Delete underlying data conenections. - for (auto remapConnection : remapConnections) + if (!graphUpdateSlotReport.IsEmpty()) { - RemoveConnection(remapConnection.first); + // currently, it is expected that there are no deleted old slots, those need manual correction + AZ_Error("ScriptCanvas", graphUpdateSlotReport.m_deletedOldSlots.empty(), "Graph upgrade path: If old slots are deleted, manual upgrading is required"); + UpdateConnectionStatus(*this, graphUpdateSlotReport); } - // Recreate connections in a separate pass to avoid triggering display updates for invalid slot ids. - for (auto remapConnection : remapConnections) - { - for (auto newEndpointPair : remapConnection.second) - { - if (newEndpointPair.first.IsValid() && newEndpointPair.second.IsValid()) - { - ConnectByEndpoint(newEndpointPair.first, newEndpointPair.second); - } - } - } - //// - AZStd::unordered_set graphCanvasNodesToDelete; for (auto scriptCanvasNode : outOfDateNodes) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp index 7762e1d095..581c3775d6 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/GraphUpgrade.cpp @@ -424,24 +424,11 @@ namespace ScriptCanvasEditor EditorGraphUpgradeMachine* sm = GetStateMachine(); auto* graph = sm->m_graph; - // Delete underlying data connections. - for (auto remapConnection : sm->m_replacementConnections) + if (!sm->m_updateReport.IsEmpty()) { - graph->RemoveConnection(remapConnection.first); - } - - // Recreate connections in a separate pass to avoid triggering display updates for invalid slot ids. - for (auto remapConnection : sm->m_replacementConnections) - { - for (auto newEndpointPair : remapConnection.second) - { - if (newEndpointPair.first.IsValid() && newEndpointPair.second.IsValid()) - { - graph->ConnectByEndpoint(newEndpointPair.first, newEndpointPair.second); - - Log("Replaced Connection: %s\n", Helpers::ConnectionToText(graph, newEndpointPair.first, newEndpointPair.second).c_str()); - } - } + // currently, it is expected that there are no deleted old slots, those need manual correction + AZ_Error("ScriptCanvas", sm->m_updateReport.m_deletedOldSlots.empty(), "Graph upgrade path: If old slots are deleted, manual upgrading is required"); + UpdateConnectionStatus(*graph, sm->m_updateReport); } } @@ -455,16 +442,18 @@ namespace ScriptCanvasEditor ScriptCanvas::NodeConfiguration nodeConfig = node->GetReplacementNodeConfiguration(); if (nodeConfig.IsValid()) { - auto nodeOutcome = graph->ReplaceNodeByConfig(node, nodeConfig, sm->m_replacementConnections); + ScriptCanvas::NodeUpdateSlotReport nodeUpdateSlotReport; + auto nodeOutcome = graph->ReplaceNodeByConfig(node, nodeConfig, nodeUpdateSlotReport); if (nodeOutcome.IsSuccess()) { + ScriptCanvas::MergeUpdateSlotReport(node->GetEntityId(), sm->m_updateReport, nodeUpdateSlotReport); + sm->m_allNodes.erase(node); sm->m_outOfDateNodes.erase(node); sm->m_sanityCheckRequiredNodes.erase(node); - sm->m_graphNeedsDirtying = true; - auto replacedNode = nodeOutcome.GetValue(); + auto replacedNode = nodeOutcome.GetValue(); sm->m_allNodes.insert(replacedNode); if (replacedNode->IsOutOfDate(graph->GetVersion())) diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h index 3bd8270629..687d783e63 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h @@ -42,6 +42,7 @@ namespace ScriptCanvas { struct NodeConfiguration; + struct NodeUpdateSlotReport; } namespace ScriptCanvasEditor @@ -361,8 +362,8 @@ namespace ScriptCanvasEditor void HandleFunctionDefinitionExtension(ScriptCanvas::Node* node, GraphCanvas::SlotId graphCanvasSlotId, const GraphCanvas::NodeId& nodeId); //// Version Update code - AZ::Outcome ReplaceNodeByConfig(ScriptCanvas::Node*, const ScriptCanvas::NodeConfiguration&, ScriptCanvas::ReplacementConnectionMap&); - bool SanityCheckNodeReplacement(ScriptCanvas::Node*, ScriptCanvas::Node*, AZStd::unordered_map>&); + AZ::Outcome ReplaceNodeByConfig(ScriptCanvas::Node*, const ScriptCanvas::NodeConfiguration&, ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport); + bool SanityCheckNodeReplacement(ScriptCanvas::Node*, ScriptCanvas::Node*, ScriptCanvas::NodeUpdateSlotReport& nodeUpdateSlotReport); bool m_allowVersionUpdate = false; AZStd::unordered_set< AZ::EntityId > m_queuedConvertingNodes; diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h index 791e649e3a..cc5315808e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/GraphUpgrade.h @@ -159,7 +159,7 @@ namespace ScriptCanvasEditor AZStd::unordered_set m_deletedNodes; AZStd::unordered_set m_assetSanitizationSet; - ScriptCanvas::ReplacementConnectionMap m_replacementConnections; + ScriptCanvas::GraphUpdateSlotReport m_updateReport; AZStd::unordered_map< AZ::EntityId, AZ::EntityId > m_scriptCanvasToGraphCanvasMapping; diff --git a/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h b/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h index 74f363f569..06a63fe8b6 100644 --- a/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h +++ b/Gems/ScriptCanvas/Code/Editor/Static/Include/ScriptCanvas/View/EditCtrls/GenericLineEditCtrl.h @@ -123,6 +123,11 @@ namespace ScriptCanvasEditor template AzToolsFramework::PropertyHandlerBase* RegisterGenericLineEditHandler(const EditCtrl::PropertyToStringCB& propertyToStringCB, const EditCtrl::StringToPropertyCB& stringToPropertyCB) { + if (!AzToolsFramework::PropertyTypeRegistrationMessages::Bus::FindFirstHandler()) + { + return nullptr; + } + auto propertyHandler(aznew GenericLineEditHandler(propertyToStringCB, stringToPropertyCB)); AzToolsFramework::PropertyTypeRegistrationMessages::Bus::Broadcast(&AzToolsFramework::PropertyTypeRegistrationMessages::RegisterPropertyType, propertyHandler); return propertyHandler; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja index 089e5fe6ff..fbf2bd5355 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasGrammar_Header.jinja @@ -75,7 +75,7 @@ public: \ void ConfigureSlots() override; \ bool RequiresDynamicSlotOrdering() const override; \ bool IsDeprecated() const override; \ -{% if deprecationUuid is defined %} NodeConfiguration GetReplacementNodeConfiguration() const override; \ +{% if deprecationUuid is defined %} ScriptCanvas::NodeConfiguration GetReplacementNodeConfiguration() const override; \ {% endif %} using Node::FindDatum; \ {% if Class.attrib['GraphEntryPoint'] is defined %} bool IsEntryPoint() const override { return {%if Class.attrib['GraphEntryPoint'] == "True" %}true{%else%}false{%endif%}; } \ @@ -168,4 +168,4 @@ struct {{ className | replace(' ','') }}Property {% endfor %} -{% endfor %} +{% endfor %} \ No newline at end of file diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Connection.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Connection.h index 155e5bb4c2..e2cd7008c8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Connection.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Connection.h @@ -22,6 +22,7 @@ namespace ScriptCanvas { class Slot; + struct NodeUpdateSlotReport; class Connection : public AZ::Component @@ -64,6 +65,8 @@ namespace ScriptCanvas // GraphNotificationBus void OnNodeRemoved(const ID& nodeId) override; + void UpdateConnectionStatus(NodeUpdateSlotReport& report); + protected: //------------------------------------------------------------------------- static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Contracts/MethodOverloadContract.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Contracts/MethodOverloadContract.cpp index dd223f34ec..0f49fb8b5d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Contracts/MethodOverloadContract.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Contracts/MethodOverloadContract.cpp @@ -33,7 +33,7 @@ namespace ScriptCanvas { if (m_availableIndexes.empty()) { - return -1; + return std::numeric_limits::max(); } return (*m_availableIndexes.begin()); @@ -151,19 +151,22 @@ namespace ScriptCanvas for (const AZ::BehaviorParameter* behaviorParameter : paramTypes.second) { - ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(behaviorParameter->m_typeId); - if (ScriptCanvas::Data::IsValueType(dataType)) + if (behaviorParameter) { - isValueType = true; - } - else if (ScriptCanvas::Data::IsContainerType(dataType)) - { - isContainerType = true; - } + ScriptCanvas::Data::Type dataType = ScriptCanvas::Data::FromAZType(behaviorParameter->m_typeId); + if (ScriptCanvas::Data::IsValueType(dataType)) + { + isValueType = true; + } + else if (ScriptCanvas::Data::IsContainerType(dataType)) + { + isContainerType = true; + } - if (isValueType && isContainerType) - { - break; + if (isValueType && isContainerType) + { + break; + } } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp index 8d24b67b4f..1637a2e71b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.cpp @@ -616,6 +616,34 @@ namespace ScriptCanvas return false; } + + void Graph::RemoveAllConnections() + { + for (auto connectionEntity : m_graphData.m_connections) + { + if (auto connection = connectionEntity ? AZ::EntityUtils::FindFirstDerivedComponent(connectionEntity) : nullptr) + { + if (connection->GetSourceEndpoint().IsValid()) + { + EndpointNotificationBus::Event(connection->GetSourceEndpoint(), &EndpointNotifications::OnEndpointDisconnected, connection->GetTargetEndpoint()); + } + if (connection->GetTargetEndpoint().IsValid()) + { + EndpointNotificationBus::Event(connection->GetTargetEndpoint(), &EndpointNotifications::OnEndpointDisconnected, connection->GetSourceEndpoint()); + } + } + + GraphNotificationBus::Event(GetScriptCanvasId(), &GraphNotifications::OnConnectionRemoved, connectionEntity->GetId()); + } + + for (auto& connectionRef : m_graphData.m_connections) + { + delete connectionRef; + } + + m_graphData.m_connections.clear(); + } + bool Graph::RemoveConnection(const AZ::EntityId& connectionId) { if (connectionId.IsValid()) @@ -752,7 +780,6 @@ namespace ScriptCanvas auto* connectionEntity = aznew AZ::Entity("Connection"); connectionEntity->CreateComponent(sourceEndpoint, targetEndpoint); - AZ::Entity* nodeEntity{}; AZ::ComponentApplicationBus::BroadcastResult(nodeEntity, &AZ::ComponentApplicationRequests::FindEntity, sourceEndpoint.GetNodeId()); auto node = nodeEntity ? AZ::EntityUtils::FindFirstDerivedComponent(nodeEntity) : nullptr; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h index 1862ce4966..49b22db2bf 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Graph.h @@ -87,6 +87,7 @@ namespace ScriptCanvas Slot* FindSlot(const Endpoint& endpoint) const override; bool AddConnection(const AZ::EntityId&) override; + void RemoveAllConnections(); bool RemoveConnection(const AZ::EntityId& connectionId) override; AZStd::vector GetConnections() const override; AZStd::vector GetConnectedEndpoints(const Endpoint& firstEndpoint) const override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/PureData.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/PureData.h index e34bdb1c71..8426e90515 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/PureData.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/PureData.h @@ -53,7 +53,9 @@ namespace ScriptCanvas template void AddDefaultInputAndOutputTypeSlot(DatumType&& defaultValue); void AddInputTypeAndOutputTypeSlot(const Data::Type& type); - + + bool IsDeprecated() const override { return true; } + void OnActivate() override; void OnInputChanged(const Datum& input, const SlotId& id) override; void MarkDefaultableInput() override {} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp index d37427af0b..9784cc97c4 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp @@ -347,6 +347,11 @@ namespace ScriptCanvas } } + void Slot::ClearDynamicGroup() + { + m_dynamicGroup = AZ::Crc32{}; + } + void Slot::ConvertToLatentExecutionOut() { if (IsExecution() && IsOutput()) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h index c65d4efc84..794ce091b1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h @@ -68,6 +68,8 @@ namespace ScriptCanvas void AddContract(const ContractDescriptor& contractDesc); + void ClearDynamicGroup(); + template T* FindContract() { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 8dff6da9b1..d30c8f857c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -1036,12 +1036,12 @@ namespace ScriptCanvas if (azrtti_istypeof(&node)) { // todo Add node to these errors - AddError(nullptr, ValidationConstPtr(aznew NotYetImplemented(node.GetEntityId(), AZStd::string::format("NodeableNodeOverloaded doesn't have enough data connected to select a valid overload: %s", node.GetDebugName().data())))); + AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("NodeableNodeOverloaded doesn't have enough data connected to select a valid overload: %s", node.GetDebugName().data())))); } else { // todo Add node to these errors - AddError(nullptr, ValidationConstPtr(aznew NotYetImplemented(node.GetEntityId(), AZStd::string::format("NodeableNode did not construct its internal node: %s", node.GetDebugName().data())))); + AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("NodeableNode did not construct its internal node: %s", node.GetDebugName().data())))); } } } @@ -2535,7 +2535,7 @@ namespace ScriptCanvas if (IsInfiniteVariableWriteHandlingLoop(*this, variableHandling, variableHandling->m_function, true)) { - AddError(variableHandling->m_function, aznew NotYetImplemented(AZ::EntityId(), ScriptCanvas::ParseErrors::InfiniteLoopWritingToVariable)); + AddError(variableHandling->m_function, aznew Internal::ParseError(AZ::EntityId(), ScriptCanvas::ParseErrors::InfiniteLoopWritingToVariable)); return false; } @@ -3312,7 +3312,7 @@ namespace ScriptCanvas } else { - AddError(execution, aznew NotYetImplemented(execution->GetNodeId(), childOutSlotsOutcome.TakeError())); + AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), childOutSlotsOutcome.TakeError())); } } } @@ -3615,9 +3615,11 @@ namespace ScriptCanvas void AbstractCodeModel::ParseExecutionMultipleOutSyntaxSugar(ExecutionTreePtr execution, const EndpointsResolved& executionOutNodes, const AZStd::vector& outSlots) { + const auto executionNodeId = execution->GetId().m_node ? execution->GetId().m_node->GetEntityId() : AZ::EntityId(); + if (executionOutNodes.size() != outSlots.size()) { - AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarMismatchOutSize); + AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarMismatchOutSize); } if (execution->GetSymbol() != Symbol::Sequence) @@ -3630,13 +3632,13 @@ namespace ScriptCanvas if (!child) { - AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNullChildFound); + AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNullChildFound); return; } if (child->m_execution) { - AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNonNullChildExecutionFound); + AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarNonNullChildExecutionFound); return; } @@ -3660,7 +3662,7 @@ namespace ScriptCanvas if (execution->GetChildrenCount() != executionOutNodes.size()) { - AddError(AZ::EntityId(), execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarChildExecutionRemovedAndNotReplaced); + AddError(executionNodeId, execution, ParseErrors::ParseExecutionMultipleOutSyntaxSugarChildExecutionRemovedAndNotReplaced); return; } } @@ -4187,7 +4189,7 @@ namespace ScriptCanvas } else { - AddError(nullptr, aznew NotYetImplemented(execution->GetNodeId(), dataSlotsOutcome.TakeError())); + AddError(nullptr, aznew Internal::ParseError(execution->GetNodeId(), dataSlotsOutcome.TakeError())); } } } @@ -4494,13 +4496,13 @@ namespace ScriptCanvas } else { - AddError(execution, aznew NotYetImplemented(execution->GetNodeId(), returnSlotsOutcome.TakeError())); + AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), returnSlotsOutcome.TakeError())); } } } else { - AddError(execution, aznew NotYetImplemented(execution->GetNodeId(), outputSlotsOutcome.TakeError())); + AddError(execution, aznew Internal::ParseError(execution->GetNodeId(), outputSlotsOutcome.TakeError())); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.cpp index e04f7c1725..cda93c1b36 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.cpp @@ -35,15 +35,6 @@ namespace ScriptCanvas } } - AZStd::unordered_map> ArithmeticExpression::GetReplacementSlotsMap() const - { - AZStd::unordered_map> slotsMap; - slotsMap.emplace(k_evaluateName, AZStd::vector{ "In" }); - slotsMap.emplace(k_outName, AZStd::vector{ "Out" }); - slotsMap.emplace(k_resultName, AZStd::vector{ "Result" }); - return slotsMap; - } - void ArithmeticExpression::OnInit() { { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.h index 351d02f2cc..7c230b359a 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/BinaryOperator.h @@ -72,7 +72,6 @@ namespace ScriptCanvas bool IsDeprecated() const override { return true; } - AZStd::unordered_map> GetReplacementSlotsMap() const override; void CustomizeReplacementNode(Node* replacementNode, AZStd::unordered_map>& outSlotIdMap) const override; protected: diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.cpp index 0b7b6020e3..d730b6bcc9 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.cpp @@ -94,8 +94,6 @@ namespace ScriptCanvas void ForEach::OnInit() { - ResetLoop(); - if (!m_sourceSlot.IsValid()) { DynamicDataSlotConfiguration slotConfiguration; @@ -130,33 +128,6 @@ namespace ScriptCanvas EndpointNotificationBus::Handler::BusConnect({ GetEntityId(), m_sourceSlot }); } - void ForEach::OnInputSignal(const SlotId& slotId) - { - auto inSlotId = ForEachProperty::GetInSlotId(this); - if (slotId == inSlotId || slotId == SlotId{}) - { - if (slotId == inSlotId) - { - if (!InitializeLoop()) - { - // Loop initialization failed - SignalOutput(ForEachProperty::GetFinishedSlotId(this)); - return; - } - } - - if (!m_breakCalled) - { - Iterate(); - } - } - else if (slotId == ForEachProperty::GetBreakSlotId(this)) - { - m_breakCalled = true; - SignalOutput(ForEachProperty::GetFinishedSlotId(this)); - } - } - UpdateResult ForEach::OnUpdateNode() { if (auto continueSlot = GetSlotByNameAndType("Continue", CombinedSlotType::ExecutionIn)) @@ -167,161 +138,6 @@ namespace ScriptCanvas return UpdateResult::DirtyGraph; } - bool ForEach::InitializeLoop() - { - ResetLoop(); - - const Datum* input = FindDatum(m_sourceSlot); - - if (input && !input->Empty()) - { - if (!Data::IsContainerType(input->GetType())) - { - SCRIPTCANVAS_REPORT_ERROR((*this), "Iteration not supported on this type: %s", Data::GetName(m_sourceContainer.GetType()).c_str()); - return false; - } - - // Make a copy of the source datum - m_sourceContainer = *input; - - // Get the size of the container - auto sizeOutcome = BehaviorContextMethodHelper::CallMethodOnDatum(m_sourceContainer, "Size"); - - if (!sizeOutcome) - { - SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get size of container: %s", sizeOutcome.GetError().c_str()); - return false; - } - - Datum sizeResult = sizeOutcome.TakeValue(); - const size_t* sizePtr = sizeResult.GetAs(); - m_size = sizePtr ? *sizePtr : 0; - - if (Data::IsSetContainerType(m_sourceContainer.GetType()) || Data::IsMapContainerType(m_sourceContainer.GetType())) - { - // If it's a map or set, get the vector of keys - auto keysVectorOutcome = BehaviorContextMethodHelper::CallMethodOnDatum(m_sourceContainer, "GetKeys"); - - if (!keysVectorOutcome) - { - SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get vector of keys: %s", keysVectorOutcome.GetError().c_str()); - return false; - } - - m_keysVector = keysVectorOutcome.TakeValue(); - - // Check size of vector of keys for safety - auto keysSizeOutcome = BehaviorContextMethodHelper::CallMethodOnDatum(m_keysVector, "Size"); - - if (!keysSizeOutcome) - { - SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get size of vector of keys: %s", keysSizeOutcome.GetError().c_str()); - return false; - } - - Datum keysSizeResult = keysSizeOutcome.TakeValue(); - const size_t* keysSizePtr = keysSizeResult.GetAs(); - size_t keysSize = keysSizePtr ? *keysSizePtr : 0; - - if (m_size != keysSize) - { - // This shouldn't happen - SCRIPTCANVAS_REPORT_ERROR((*this), "Container size and vector of keys size mismatch."); - return false; - } - } - - return true; - } - - return false; - } - - void ForEach::Iterate() - { - if (m_sourceContainer.Empty() || m_index >= m_size) - { - SignalOutput(ForEachProperty::GetFinishedSlotId(this)); - return; - } - - Datum& container = Data::IsVectorContainerType(m_sourceContainer.GetType()) ? m_sourceContainer : m_keysVector; - - auto keyAtOutcome = BehaviorContextMethodHelper::CallMethodOnDatumUnpackOutcomeSuccess(container, "At", m_index); - - if (!keyAtOutcome) - { - SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get key in container: %s", keyAtOutcome.GetError().c_str()); - return; - } - - Datum keyAtResult = keyAtOutcome.TakeValue(); - - if (!SetPropertySlotData(keyAtResult, k_keySlotIndex)) - { - // Unable to set property slot - SCRIPTCANVAS_REPORT_ERROR((*this), "Unable to set one of the property slots on this node."); - SignalOutput(ForEachProperty::GetFinishedSlotId(this)); - return; - } - - if (Data::IsMapContainerType(m_sourceContainer.GetType())) - { - // If the container is a map, we want to get the value for the current key - auto valueAtOutcome = BehaviorContextMethodHelper::CallMethodOnDatumUnpackOutcomeSuccess(m_sourceContainer, "At", keyAtResult); - - if (!valueAtOutcome) - { - SCRIPTCANVAS_REPORT_ERROR((*this), "Failed to get value for key in container: %s", valueAtOutcome.GetError().c_str()); - return; - } - - Datum valueAtResult = valueAtOutcome.TakeValue(); - - if (!SetPropertySlotData(valueAtResult, k_valueSlotIndex)) - { - // Unable to set property slot - SCRIPTCANVAS_REPORT_ERROR((*this), "Unable to set one of the property slots on this node."); - SignalOutput(ForEachProperty::GetFinishedSlotId(this)); - return; - } - } - - ++m_index; - - SignalOutput(ForEachProperty::GetEachSlotId(this)); - } - - bool ForEach::SetPropertySlotData(Datum& atResult, size_t propertyIndex) - { - if (atResult.Empty()) - { - // Something went wrong with the Behavior Context call - SCRIPTCANVAS_REPORT_ERROR((*this), "Behavior Context call failed; unable to retrieve element from container."); - return false; - } - - if (m_propertySlots.size() <= propertyIndex) - { - // Missing a property slot - SCRIPTCANVAS_REPORT_ERROR((*this), "Node in invalid state; missing a property slot."); - return false; - } - - PushOutput(atResult, *GetSlot(m_propertySlots[propertyIndex].m_propertySlotId)); - return true; - } - - void ForEach::ResetLoop() - { - // Reset node state - m_index = 0; - m_size = 0; - m_breakCalled = false; - m_sourceContainer = Datum(); - m_keysVector = Datum(); - } - void ForEach::OnDynamicGroupDisplayTypeChanged(const AZ::Crc32& dynamicGroup, const Data::Type& dataType) { if (dynamicGroup == GetContainerGroupId() && dataType.IsValid()) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.h index 68e75adc80..32bca9eefd 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ForEach.h @@ -56,44 +56,29 @@ namespace ScriptCanvas bool IsBreakSlot(const SlotId&) const; - bool IsOutOfDate(const VersionData& graphVersion) const override; - - + bool IsOutOfDate(const VersionData& graphVersion) const override; UpdateResult OnUpdateNode() override; - protected: - ExecutionNameMap GetExecutionNameMap() const override; - - void OnInit() override; - void OnInputSignal(const SlotId&) override; - - bool InitializeLoop(); - void Iterate(); - bool SetPropertySlotData(Datum& atResult, size_t propertyIndex); - void ResetLoop(); - - void OnDynamicGroupDisplayTypeChanged(const AZ::Crc32& dynamicGroup, const Data::Type& dataType) override; - - void ClearPropertySlots(); - void AddPropertySlotsFromType(const Data::Type& dataType); - - static AZ::Crc32 GetContainerGroupId() { return AZ_CRC("ContainerGroup", 0xb81ed451); } - - SlotId m_sourceSlot; - AZ::TypeId m_previousTypeId; - AZStd::vector m_propertySlots; - + private: static const size_t k_keySlotIndex; static const size_t k_valueSlotIndex; - size_t m_index; - size_t m_size; + static AZ::Crc32 GetContainerGroupId() { return AZ_CRC("ContainerGroup", 0xb81ed451); } - bool m_breakCalled; + void AddPropertySlotsFromType(const Data::Type& dataType); - Datum m_sourceContainer; - Datum m_keysVector; + void ClearPropertySlots(); + + ExecutionNameMap GetExecutionNameMap() const override; + + void OnInit() override; + + void OnDynamicGroupDisplayTypeChanged(const AZ::Crc32& dynamicGroup, const Data::Type& dataType) override; + + SlotId m_sourceSlot; + AZ::TypeId m_previousTypeId; + AZStd::vector m_propertySlots; }; } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.cpp index cec643d799..678ca60ef3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.cpp @@ -410,6 +410,11 @@ namespace ScriptCanvas return m_asset.GetId(); } + const AZStd::string& FunctionCallNode::GetAssetHint() const + { + return m_asset.GetHint(); + } + AZ::Outcome FunctionCallNode::GetDependencies() const { DependencyReport report; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.h index fe5b453cf3..003bc2581b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionCallNode.h @@ -70,6 +70,8 @@ namespace ScriptCanvas AZ::Data::AssetId GetAssetId() const; + const AZStd::string& GetAssetHint() const; + const AZStd::string& GetName() const; void Initialize(AZ::Data::AssetId assetId, const ScriptCanvas::Grammar::FunctionSourceId& sourceId); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp index ad556ae093..d485a15be3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp @@ -113,6 +113,28 @@ namespace ScriptCanvas } } + void FunctionDefinitionNode::OnInit() + { + Nodeling::OnInit(); + + AZ::SerializeContext* serializeContext{}; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); + if (serializeContext) + { + const auto& classData = serializeContext->FindClassData(azrtti_typeid()); + if (classData && classData->m_version < NodeVersion::RemoveDefaultDisplayGroup) + { + for (auto& slot : ModAllSlots()) + { + if (slot->GetType() == CombinedSlotType::DataIn || slot->GetType() == CombinedSlotType::DataOut) + { + slot->ClearDynamicGroup(); + } + } + } + } + } + void FunctionDefinitionNode::SetupSlots() { auto groupedSlots = GetSlotsWithDisplayGroup(GetSlotDisplayGroup()); @@ -208,7 +230,6 @@ namespace ScriptCanvas slotConfiguration.SetConnectionType(connectionType); slotConfiguration.m_displayGroup = GetDataDisplayGroup(); - slotConfiguration.m_dynamicGroup = GetDataDynamicTypeGroup(); slotConfiguration.m_dynamicDataType = DynamicDataType::Any; slotConfiguration.m_isUserAdded = true; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h index 20b20cb65d..0e3119cdfd 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h @@ -32,7 +32,8 @@ namespace ScriptCanvas private: enum NodeVersion { - Initial = 1 + Initial = 1, + RemoveDefaultDisplayGroup, }; public: @@ -78,14 +79,15 @@ namespace ScriptCanvas static constexpr AZ::Crc32 GetAddNodelingInputDataSlot() { return AZ_CRC_CE("AddNodelingInputDataSlot"); } static constexpr AZ::Crc32 GetAddNodelingOutputDataSlot() { return AZ_CRC_CE("AddNodelingOutputDataSlot"); } - static constexpr AZ::Crc32 GetDataDynamicTypeGroup() { return AZ_CRC_CE("DataGroup"); } - + AZStd::string GetDataDisplayGroup() const { return "DataDisplayGroup"; } SlotId HandleExtension(AZ::Crc32 extensionId) override; void ConfigureVisualExtensions() override; + void OnInit() override; + void OnSetup() override; private: diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp index b6f7bc2972..4a9e8ac3e3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp @@ -208,7 +208,6 @@ namespace ScriptCanvas } } - void Method::InitializeMethod(const MethodConfiguration& config) { m_namespaces = config.m_namespaces ? *config.m_namespaces : m_namespaces; @@ -239,7 +238,11 @@ namespace ScriptCanvas for (size_t argIndex(0), sentinel(config.m_method.GetNumArguments()); argIndex != sentinel; ++argIndex) { SlotId addedSlot = AddMethodInputSlot(config, argIndex); - MethodHelper::SetSlotToDefaultValue(*this, addedSlot, config, argIndex); + + if (addedSlot.IsValid()) + { + MethodHelper::SetSlotToDefaultValue(*this, addedSlot, config, argIndex); + } } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h index 6a53054ddf..829dff2c29 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h @@ -132,6 +132,8 @@ namespace ScriptCanvas const Slot* GetIfBranchSlot(bool branch) const; + AZ_INLINE const AZStd::string& GetLookupName() const { return m_lookupName; } + AZ_INLINE AZStd::recursive_mutex& GetMutex() { return m_mutex; } ConstSlotsOutcome GetSlotsInExecutionThreadByTypeImpl(const Slot& executionSlot, CombinedSlotType targetSlotType, const Slot* executionChildSlot) const override; @@ -160,6 +162,8 @@ namespace ScriptCanvas bool SanityCheckBranchOnResultMethod(const AZ::BehaviorMethod& branchOnResultMethod) const; + AZ_INLINE void SetClassNamePretty(AZStd::string_view classNamePretty) { m_classNamePretty = classNamePretty; } + void SetMethodUnchecked(const AZ::BehaviorMethod* method, const AZ::BehaviorClass* behaviorClass); AZ_INLINE void SetWarnOnMissingFunction(bool enabled) { m_warnOnMissingFunction = enabled; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp index ed7fce7ffc..bfd0bb824d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.cpp @@ -94,7 +94,7 @@ namespace ScriptCanvas { if (!m_updatingDisplay) { - RefreshActiveIndexes(); + RefreshActiveIndexes(true, true); UpdateSlotDisplay(); } } @@ -135,10 +135,8 @@ namespace ScriptCanvas return Data::Type::Invalid(); } - AZ::Outcome MethodOverloaded::GetFunctionCallName(const Slot* slot) const + AZ::Outcome MethodOverloaded::GetFunctionCallName([[maybe_unused]] const Slot* slot) const { - AZ_UNUSED(slot); - AZStd::string overloadName; int activeIndex = GetActiveIndex(); @@ -188,7 +186,7 @@ namespace ScriptCanvas // this prevents repeated updates based on changes to slots Method::InitializeMethod(config); - + SetClassNamePretty(""); RefreshActiveIndexes(); ConfigureContracts(); @@ -197,7 +195,12 @@ namespace ScriptCanvas SlotId MethodOverloaded::AddMethodInputSlot(const MethodConfiguration& config, size_t argumentIndex) { const AZ::BehaviorParameter* argumentPtr = config.m_method.GetArgument(argumentIndex); - AZ_Assert(argumentPtr, "Method: %s had a null argument at index: %d", config.m_lookupName->data(), argumentIndex); + + if (!argumentPtr) + { + return SlotId{}; + } + const auto& argument = *argumentPtr; auto nameAndToolTip = MethodHelper::GetArgumentNameAndToolTip(config, argumentIndex); @@ -507,7 +510,7 @@ namespace ScriptCanvas } } - void MethodOverloaded::RefreshActiveIndexes(bool checkForConnections) + void MethodOverloaded::RefreshActiveIndexes(bool checkForConnections, bool adjustSlots) { DataIndexMapping concreteInputTypes; DataIndexMapping concreteOutputTypes; @@ -519,6 +522,35 @@ namespace ScriptCanvas if (m_overloadSelection.m_availableIndexes.size() == 1) { auto methodOverload = m_overloadConfiguration.m_overloads[(*m_overloadSelection.m_availableIndexes.begin())]; + + if (adjustSlots) + { + const size_t numArguments = methodOverload.first->GetNumArguments(); + const size_t numInputSlots = m_orderedInputSlotIds.size(); + + if (numArguments > numInputSlots) + { + MethodConfiguration config(*methodOverload.first, GetMethodType()); + AZStd::string_view lookupName = GetLookupName(); + config.m_lookupName = &lookupName; + + for (size_t index = numInputSlots; index != numArguments; ++index) + { + AddMethodInputSlot(config, index); + } + } + else if (numArguments < numInputSlots) + { + const size_t removeCount = numInputSlots - numArguments; + // remove extra slots, assuming remaining ones are of valid type (if not valid name) + for (size_t count = 0; count != removeCount; ++count) + { + RemoveSlot(m_orderedInputSlotIds.back()); + m_orderedInputSlotIds.pop_back(); + } + } + } + SetMethodUnchecked(methodOverload.first, methodOverload.second); } } @@ -681,9 +713,6 @@ namespace ScriptCanvas return AZ::Success(); } - } - } - } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h index 1fffbd7eac..517d3dd072 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/MethodOverloaded.h @@ -106,7 +106,7 @@ namespace ScriptCanvas void SetupMethodData(const AZ::BehaviorMethod* lookupMethod, const AZ::BehaviorClass* lookupClass); void ConfigureContracts(); - void RefreshActiveIndexes(bool checkForConnections = true); + void RefreshActiveIndexes(bool checkForConnections = true, bool adjustSlots = false); void FindDataIndexMappings(DataIndexMapping& inputMapping, DataIndexMapping& outputMapping, bool checkForConnections) const; void UpdateSlotDisplay(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.cpp index b8c1e9e400..6f8a23a2ed 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.cpp @@ -393,14 +393,6 @@ namespace ScriptCanvas AZ_UNUSED(sourceType); } - AZStd::unordered_map> OperatorBase::GetReplacementSlotsMap() const - { - AZStd::unordered_map> slotsMap; - slotsMap.emplace("In", AZStd::vector{ "In" }); - slotsMap.emplace("Out", AZStd::vector{ "Out" }); - return slotsMap; - } - void OperatorBase::CustomizeReplacementNode(Node* replacementNode, AZStd::unordered_map>& outSlotIdMap) const { auto newDataInSlots = replacementNode->GetSlotsByType(ScriptCanvas::CombinedSlotType::DataIn); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.h index bc49f3fac6..7091d7fa87 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Operator.h @@ -57,7 +57,6 @@ namespace ScriptCanvas AZStd::vector< SourceSlotConfiguration > m_sourceSlotConfigurations; }; - AZStd::unordered_map> GetReplacementSlotsMap() const override; void CustomizeReplacementNode(Node* replacementNode, AZStd::unordered_map>& outSlotIdMap) const override; using TypeList = AZStd::vector; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/Timer.ScriptCanvasGrammar.xml b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/Timer.ScriptCanvasGrammar.xml index 21adecb8fe..e1ea8a4b73 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/Timer.ScriptCanvasGrammar.xml +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Time/Timer.ScriptCanvasGrammar.xml @@ -8,7 +8,7 @@ Base="ScriptCanvas::Node" Version="2" GeneratePropertyFriend="True" - DeprecationUUID="32A4BEDC-C207-4472-61DE-9A716402620A" + DeprecationUUID="{32A4BEDC-C207-4472-61DE-9A716402620A}" Deprecated="This node has been deprecated in favor of the nodeable form" Description="Provides a time value."> @@ -25,4 +25,4 @@ IsInput="False" IsOutput="True" /> - + \ No newline at end of file diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.cpp index 5bf5f83916..0dc16f721c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.cpp @@ -12,9 +12,26 @@ #include "VersioningUtils.h" #include +#include namespace ScriptCanvas { + AZStd::vector GraphUpdateSlotReport::Convert(const Endpoint& oldEndpoint) const + { + auto iter = m_oldSlotsToNewSlots.find(oldEndpoint); + return iter != m_oldSlotsToNewSlots.end() ? iter->second : AZStd::vector{ oldEndpoint }; + } + + bool GraphUpdateSlotReport::IsEmpty() const + { + return m_deletedOldSlots.empty() && m_oldSlotsToNewSlots.empty(); + } + + bool NodeUpdateSlotReport::IsEmpty() const + { + return m_deletedOldSlots.empty() && m_oldSlotsToNewSlots.empty(); + } + void VersioningUtils::CopyOldValueToDataSlot(Slot* newSlot, const VariableId& oldVariableReference, const Datum* oldDatum) { if (oldVariableReference.IsValid()) @@ -36,6 +53,99 @@ namespace ScriptCanvas } } + void MergeUpdateSlotReport(const AZ::EntityId& scriptCanvasNodeId, GraphUpdateSlotReport& report, const NodeUpdateSlotReport& source) + { + report.m_deletedOldSlots.reserve(source.m_deletedOldSlots.size()); + + for (auto& slotId : source.m_deletedOldSlots) + { + report.m_deletedOldSlots.insert({ scriptCanvasNodeId, slotId }); + } + + report.m_oldSlotsToNewSlots.reserve(source.m_oldSlotsToNewSlots.size()); + + for (auto& oldToNewIter : source.m_oldSlotsToNewSlots) + { + AZStd::vector newEndpoints; + newEndpoints.reserve(oldToNewIter.second.size()); + + for (auto& targetSlotId : oldToNewIter.second) + { + newEndpoints.push_back({ scriptCanvasNodeId, targetSlotId }); + } + + report.m_oldSlotsToNewSlots[{ scriptCanvasNodeId, oldToNewIter.first}] = AZStd::move(newEndpoints); + } + } + + AZStd::vector> CollectEndpoints(const AZStd::vector& connections, bool logEntityNames) + { + AZStd::vector names; + AZStd::vector> endpoints; + + for (auto& connectionEntity : connections) + { + if (logEntityNames) + { + names.push_back(connectionEntity->GetName()); + } + + if (auto connection = AZ::EntityUtils::FindFirstDerivedComponent(connectionEntity->GetId())) + { + endpoints.push_back(AZStd::make_pair(connection->GetSourceEndpoint(), connection->GetTargetEndpoint())); + } + } + + if (logEntityNames) + { + AZStd::sort(names.begin(), names.end()); + + AZStd::string result = "\nConnection Name list:\n"; + for (auto& name : names) + { + result += "\n"; + result += name; + } + + AZ_TracePrintf("ScriptCanvas", result.c_str()); + } + + return endpoints; + } + + void UpdateConnectionStatus(Graph& graph, const GraphUpdateSlotReport& report) + { + GraphData* graphData = graph.GetGraphData(); + if (!graphData) + { + AZ_Error("ScriptCanvas", false, "Graph was missing graph data to update"); + return; + } + + AZStd::unordered_set oldConnectedSlots; + AZ_TracePrintf("ScriptCanvas", "Connections list before: "); + auto endpoints = CollectEndpoints(graphData->m_connections, true); + graph.RemoveAllConnections(); + + for (auto& iter : endpoints) + { + const AZStd::vector& sources = report.Convert(iter.first); + const AZStd::vector& targets = report.Convert(iter.second); + + for (const auto& source : sources) + { + for (const auto& target : targets) + { + graph.ConnectByEndpoint(source, target); + } + } + } + + graphData->BuildEndpointMap(); + AZ_TracePrintf("ScriptCanvas", "Connections list after: "); + CollectEndpoints(graphData->m_connections, true); + } + void VersioningUtils::CreateRemapConnectionsForSourceEndpoint(const Graph& graph, const Endpoint& oldSourceEndpoint, const Endpoint& newSourceEndpoint, ReplacementConnectionMap& connectionMap) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.h index 51960e08e7..a9a40305c3 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Utils/VersioningUtils.h @@ -15,6 +15,8 @@ #include #include +#include +#include #include namespace AZ @@ -25,13 +27,36 @@ namespace AZ namespace ScriptCanvas { class Datum; - class Endpoint; class Graph; class Slot; - using ReplacementEndpointPairs = AZStd::unordered_set>; + using ReplacementEndpointPairs = AZStd::unordered_set>; using ReplacementConnectionMap = AZStd::unordered_map; + struct NodeUpdateSlotReport + { + AZStd::unordered_set m_deletedOldSlots; + AZStd::unordered_map> m_oldSlotsToNewSlots; + + bool IsEmpty() const; + }; + + struct GraphUpdateSlotReport + { + AZStd::unordered_set m_deletedOldSlots; + AZStd::unordered_map> m_oldSlotsToNewSlots; + + AZStd::vector Convert(const Endpoint& oldEndpoint) const; + + bool IsEmpty() const; + }; + + void MergeUpdateSlotReport(const AZ::EntityId& scriptCanvasNodeId, GraphUpdateSlotReport& report, const NodeUpdateSlotReport& source); + + AZStd::vector> CollectEndpoints(const AZStd::vector& connections, bool logEntityNames = false); + + void UpdateConnectionStatus(Graph& graph, const GraphUpdateSlotReport& report); + class VersioningUtils { public: diff --git a/Gems/StartingPointInput/Code/Source/InputNode.ScriptCanvasGrammar.xml b/Gems/StartingPointInput/Code/Source/InputNode.ScriptCanvasGrammar.xml index 9d6c555c97..8c8cc34597 100644 --- a/Gems/StartingPointInput/Code/Source/InputNode.ScriptCanvasGrammar.xml +++ b/Gems/StartingPointInput/Code/Source/InputNode.ScriptCanvasGrammar.xml @@ -6,8 +6,10 @@ PreferredClassName="Input Handler" Uuid="{0B0AC61B-4BBA-42BF-BDCD-DAF2D3CA41A8}" Base="ScriptCanvas::Node" - Icon="Icons/ScriptCanvas/Bus.png" + Icon="Editor/Icons/ScriptCanvas/Bus.png" EditAttributes="AZ::Edit::Attributes::Category@Gameplay/Input" + DeprecationUUID="{0A2EB488-5A6A-E166-BB62-23FF81499E33}" + Deprecated="This node has been deprecated in favor of the nodeable form" GraphEntryPoint="True" GeneratePropertyFriend="True" Description="Handle processed input events found in input binding assets"> @@ -25,4 +27,4 @@ IsInput="False" IsOutput="True" /> - + \ No newline at end of file From 82b4b83256d8f45e936a907fa7a3c49b80f3ba8b Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Tue, 25 May 2021 13:15:15 -0700 Subject: [PATCH 05/12] Launch o3de.exe instead of project_manager.py Launch the o3de project manager application instead of project_manager.py when the editor is started but no project is specified. --- .../ProjectManager/ProjectManager.cpp | 45 +++---------------- scripts/project_manager/projects.py | 2 +- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index 985bc4665d..bdbfe6197f 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -99,51 +99,18 @@ namespace AzFramework::ProjectManager AZ::AllocatorInstance::Create(); } { - const char projectsScript[] = "projects.py"; + AZStd::string filename = "o3de"; + AZ::IO::FixedMaxPath executablePath = AZ::Utils::GetExecutableDirectory(); + executablePath /= filename + AZ_TRAIT_OS_EXECUTABLE_EXTENSION; - AZ_Warning("ProjectManager", false, "No project provided - launching project selector."); - - if (engineRootPath.empty()) + if (!AZ::IO::SystemFile::Exists(executablePath.c_str())) { - AZ_Error("ProjectManager", false, "Couldn't find engine root"); + AZ_Error("ProjectManager", false, "%s not found", executablePath.c_str()); return false; } - auto projectManagerPath = engineRootPath / "scripts" / "project_manager"; - - if (!AZ::IO::SystemFile::Exists((projectManagerPath / projectsScript).c_str())) - { - AZ_Error("ProjectManager", false, "%s not found at %s!", projectsScript, projectManagerPath.c_str()); - return false; - } - AZ::IO::FixedMaxPathString executablePath; - AZ::Utils::GetExecutablePathReturnType result = AZ::Utils::GetExecutablePath(executablePath.data(), executablePath.capacity()); - if (result.m_pathStored != AZ::Utils::ExecutablePathResult::Success) - { - AZ_Error("ProjectManager", false, "Could not determine executable path!"); - return false; - } - AZ::IO::FixedMaxPath parentPath(executablePath.c_str()); - auto exeFolder = parentPath.ParentPath(); - AZStd::fixed_string<8> debugOption; - auto lastSep = exeFolder.Native().find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR); - if (lastSep != AZStd::string_view::npos) - { - exeFolder = exeFolder.Native().substr(lastSep + 1); - } - if (exeFolder == "debug") - { - // We need to use the debug version of the python interpreter to load up our debug version of our libraries which work with the debug version of QT living in this folder - debugOption = "debug "; - } - AZ::IO::FixedMaxPath pythonPath = engineRootPath / "python"; - pythonPath /= AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL; - auto cmdPath = AZ::IO::FixedMaxPathString::format("%s %s%s --executable_path=%s --parent_pid=%" PRIu32, pythonPath.Native().c_str(), - debugOption.c_str(), (projectManagerPath / projectsScript).c_str(), executablePath.c_str(), AZ::Platform::GetCurrentProcessId()); AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; - - processLaunchInfo.m_commandlineParameters = cmdPath; - processLaunchInfo.m_showWindow = false; + processLaunchInfo.m_commandlineParameters = executablePath.String(); launchSuccess = AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo); } if (ownsSystemAllocator) diff --git a/scripts/project_manager/projects.py b/scripts/project_manager/projects.py index 51db7a6440..51ffc2be91 100755 --- a/scripts/project_manager/projects.py +++ b/scripts/project_manager/projects.py @@ -34,7 +34,7 @@ from cmake.Tools import registration o3de_folder = registration.get_o3de_folder() o3de_logs_folder = registration.get_o3de_logs_folder() -project_manager_log_file_path = o3de_log_folder / "project_manager.log" +project_manager_log_file_path = o3de_logs_folder / "project_manager.log" log_file_handler = RotatingFileHandler(filename=project_manager_log_file_path, maxBytes=1024 * 1024, backupCount=1) formatter = logging.Formatter('%(asctime)s | %(levelname)s : %(message)s') log_file_handler.setFormatter(formatter) From 713a3fd8851835181236e160daa834e03a4252c7 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Tue, 25 May 2021 14:05:03 -0700 Subject: [PATCH 06/12] Convert TextureAtlas gem/builder to use Atom (#853) * Convert TextureAtlas gem/builder to use Atom * Convert image markup to use Atom image --- .../Gem/Code/tool_dependencies.cmake | 2 +- Gems/LyShine/Code/CMakeLists.txt | 8 +- Gems/LyShine/Code/Source/UiTextComponent.cpp | 83 ++----- Gems/LyShine/Code/Source/UiTextComponent.h | 11 +- Gems/TextureAtlas/Code/CMakeLists.txt | 44 +++- .../Code/Include/TextureAtlas/TextureAtlas.h | 7 +- .../Source/Editor/AtlasBuilderComponent.cpp | 1 - .../Code/Source/Editor/AtlasBuilderWorker.cpp | 221 +++++++----------- .../Code/Source/Editor/AtlasBuilderWorker.h | 3 +- .../Code/Source/TextureAtlasImpl.cpp | 4 +- .../Code/Source/TextureAtlasImpl.h | 9 +- .../Code/Source/TextureAtlasModule.cpp | 7 + .../Source/TextureAtlasSystemComponent.cpp | 78 +++---- .../Code/textureatlas_builder_files.cmake | 17 ++ .../Code/textureatlas_files.cmake | 1 - .../Code/textureatlas_module_files.cmake | 14 ++ 16 files changed, 252 insertions(+), 258 deletions(-) create mode 100644 Gems/TextureAtlas/Code/textureatlas_builder_files.cmake create mode 100644 Gems/TextureAtlas/Code/textureatlas_module_files.cmake diff --git a/AutomatedTesting/Gem/Code/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/tool_dependencies.cmake index e2e57d4012..1d70c02b1c 100644 --- a/AutomatedTesting/Gem/Code/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/tool_dependencies.cmake @@ -12,7 +12,7 @@ # Extracted from Editor.xml set(GEM_DEPENDENCIES Gem::Maestro.Editor - Gem::TextureAtlas + Gem::TextureAtlas.Editor Gem::LmbrCentral.Editor Gem::LyShine.Editor Gem::HttpRequestor diff --git a/Gems/LyShine/Code/CMakeLists.txt b/Gems/LyShine/Code/CMakeLists.txt index 732bd1cfd4..796cb22292 100644 --- a/Gems/LyShine/Code/CMakeLists.txt +++ b/Gems/LyShine/Code/CMakeLists.txt @@ -86,7 +86,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Gem::LyShine.Static Legacy::CryCommon Gem::LmbrCentral - Gem::TextureAtlas + Gem::TextureAtlas.Editor Gem::AtomToolsFramework.Static Gem::AtomToolsFramework.Editor ${additional_dependencies} @@ -118,10 +118,10 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AssetBuilderSDK Gem::LyShine.Editor.Static Gem::LmbrCentral - Gem::TextureAtlas + Gem::TextureAtlas.Editor RUNTIME_DEPENDENCIES Gem::LmbrCentral.Editor - Gem::TextureAtlas + Gem::TextureAtlas.Editor ) endif() @@ -176,7 +176,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) Legacy::CryCommon AZ::AssetBuilderSDK Gem::LmbrCentral - Gem::TextureAtlas + Gem::TextureAtlas.Editor Gem::LyShine.Editor.Static ) ly_add_googletest( diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index 648013108b..72c36ed66d 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -40,6 +40,7 @@ #include "RenderGraph.h" #include +#include namespace { @@ -1076,7 +1077,7 @@ UiTextComponent::InlineImage::InlineImage(const AZStd::string& texturePathname, { m_filepath = texturePathname; AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePath, m_filepath); - m_texture = nullptr; + m_texture.reset(); m_size = AZ::Vector2(0.0f, 0.0f); m_vAlign = vAlign; m_yOffset = yOffset; @@ -1094,24 +1095,11 @@ UiTextComponent::InlineImage::InlineImage(const AZStd::string& texturePathname, else { // Load the texture - uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM); - ITexture* texture = gEnv->pRenderer->EF_LoadTexture(texturePathname.c_str(), loadTextureFlags); - - if (!texture || !texture->IsTextureLoaded()) + m_texture = CDraw2d::LoadTexture(m_filepath); + if (m_texture) { - gEnv->pSystem->Warning( - VALIDATOR_MODULE_SHINE, - VALIDATOR_WARNING, - VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE, - texturePathname.c_str(), - "No texture file found for image: %s. " - "NOTE: File must be in current project or a gem.", - texturePathname.c_str()); - } - else - { - m_texture = texture; - m_size = AZ::Vector2(static_cast(m_texture->GetWidth()), static_cast(m_texture->GetHeight())); + AZ::RHI::Size size = m_texture->GetDescriptor().m_size; + m_size = AZ::Vector2(size.m_width, size.m_height); } } @@ -1127,17 +1115,6 @@ UiTextComponent::InlineImage::InlineImage(const AZStd::string& texturePathname, //////////////////////////////////////////////////////////////////////////////////////////////////// UiTextComponent::InlineImage::~InlineImage() { - // In order to avoid the texture being deleted while there are still commands on the render - // thread command queue that use it, we queue a command to delete the texture onto the - // command queue. - - if (m_texture && !m_atlas) - { - SResourceAsync* pInfo = new SResourceAsync(); - pInfo->eClassName = eRCN_Texture; - pInfo->pResource = m_texture; - gEnv->pRenderer->ReleaseResourceAsync(pInfo); - } } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1148,13 +1125,6 @@ bool UiTextComponent::InlineImage::OnAtlasLoaded(const TextureAtlasNamespace::Te m_coordinates = atlas->GetAtlasCoordinates(m_filepath); if (m_coordinates.GetWidth() > 0) { - if (m_texture) - { - SResourceAsync* pInfo = new SResourceAsync(); - pInfo->eClassName = eRCN_Texture; - pInfo->pResource = m_texture; - gEnv->pRenderer->ReleaseResourceAsync(pInfo); - } m_atlas = atlas; m_texture = m_atlas->GetTexture(); return true; @@ -1177,25 +1147,7 @@ bool UiTextComponent::InlineImage::OnAtlasUnloaded(const TextureAtlasNamespace:: else { // Load the texture - uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM); - ITexture* texture = gEnv->pRenderer->EF_LoadTexture(m_filepath.c_str(), loadTextureFlags); - - if (!texture || !texture->IsTextureLoaded()) - { - gEnv->pSystem->Warning( - VALIDATOR_MODULE_SHINE, - VALIDATOR_WARNING, - VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE, - m_filepath.c_str(), - "No texture file found for image: %s. " - "NOTE: File must be in current project or a gem.", - m_filepath.c_str()); - m_texture = nullptr; - } - else - { - m_texture = texture; - } + m_texture = CDraw2d::LoadTexture(m_filepath); } return true; } @@ -1869,7 +1821,7 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) UiTransformInterface::RectPointsArray rectPoints; GetTextBoundingBoxPrivate(GetDrawBatchLines(), m_selectionStart, m_selectionEnd, rectPoints); - ITexture* whiteTexture = gEnv->pRenderer->GetWhiteTexture(); + auto systemImage = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); bool isClampTextureMode = true; uint32 packedColor = (m_textSelectionColor.GetA8() << 24) | (m_textSelectionColor.GetR8() << 16) | (m_textSelectionColor.GetG8() << 8) | m_textSelectionColor.GetB8(); @@ -1878,7 +1830,12 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) { IRenderer::DynUiPrimitive* primitive = renderGraph->GetDynamicQuadPrimitive(rect.pt, packedColor); primitive->m_next = nullptr; - renderGraph->AddPrimitive(primitive, whiteTexture, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode); + + LyShine::RenderGraph* lyRenderGraph = dynamic_cast(renderGraph); + if (lyRenderGraph) + { + lyRenderGraph->AddPrimitiveAtom(primitive, systemImage, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode); + } } } @@ -1887,21 +1844,25 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) { for (auto batch : m_renderCache.m_imageBatches) { - ITexture* texture = batch->m_texture; + AZ::Data::Instance texture = batch->m_texture; // If the fade value has changed we need to update the alpha values in the vertex colors but we do // not want to touch or recompute the RGB values if (batch->m_cachedPrimitive.m_vertices[0].color.a != finalAlphaByte) { - for (int i=0; i < 4; ++i) + for (int i = 0; i < 4; ++i) { batch->m_cachedPrimitive.m_vertices[i].color.a = finalAlphaByte; } } bool isClampTextureMode = true; - renderGraph->AddPrimitive(&batch->m_cachedPrimitive, texture, - isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode); + LyShine::RenderGraph* lyRenderGraph = dynamic_cast(renderGraph); + if (lyRenderGraph) + { + lyRenderGraph->AddPrimitiveAtom(&batch->m_cachedPrimitive, texture, + isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode); + } } } diff --git a/Gems/LyShine/Code/Source/UiTextComponent.h b/Gems/LyShine/Code/Source/UiTextComponent.h index c3983c5454..b23f2a2886 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.h +++ b/Gems/LyShine/Code/Source/UiTextComponent.h @@ -21,13 +21,14 @@ #include #include #include +#include +#include #include #include #include -#include -#include +#include // Only needed for internal unit-testing #include @@ -91,7 +92,7 @@ public: //types bool OnAtlasLoaded(const TextureAtlasNamespace::TextureAtlas* atlas); bool OnAtlasUnloaded(const TextureAtlasNamespace::TextureAtlas* atlas); - ITexture* m_texture; + AZ::Data::Instance m_texture; AZ::Vector2 m_size; VAlign m_vAlign; float m_yOffset; @@ -616,8 +617,8 @@ private: // types struct RenderCacheImageBatch { - ITexture* m_texture; - IRenderer::DynUiPrimitive m_cachedPrimitive; + AZ::Data::Instance m_texture; + IRenderer::DynUiPrimitive m_cachedPrimitive; }; struct RenderCacheData diff --git a/Gems/TextureAtlas/Code/CMakeLists.txt b/Gems/TextureAtlas/Code/CMakeLists.txt index b7072321dc..5e29a7ea65 100644 --- a/Gems/TextureAtlas/Code/CMakeLists.txt +++ b/Gems/TextureAtlas/Code/CMakeLists.txt @@ -10,7 +10,7 @@ # ly_add_target( - NAME TextureAtlas ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAME TextureAtlas.Static STATIC NAMESPACE Gem FILES_CMAKE textureatlas_files.cmake @@ -21,4 +21,46 @@ ly_add_target( PRIVATE Legacy::CryCommon AZ::AzFramework + PUBLIC + Gem::Atom_RPI.Public + AZ::AtomCore ) + +ly_add_target( + NAME TextureAtlas ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAMESPACE Gem + FILES_CMAKE + textureatlas_module_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + Legacy::CryCommon + Gem::TextureAtlas.Static +) + +if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME TextureAtlas.Editor GEM_MODULE + NAMESPACE Gem + FILES_CMAKE + textureatlas_module_files.cmake + textureatlas_builder_files.cmake + COMPILE_DEFINITIONS + PRIVATE + TEXTUREATLAS_EDITOR + INCLUDE_DIRECTORIES + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + Legacy::CryCommon + AZ::AzCore + AZ::AzFramework + AZ::AssetBuilderSDK + Gem::TextureAtlas.Static + Gem::ImageProcessingAtom.Headers + ) +endif() + diff --git a/Gems/TextureAtlas/Code/Include/TextureAtlas/TextureAtlas.h b/Gems/TextureAtlas/Code/Include/TextureAtlas/TextureAtlas.h index c4e222230d..0703f19c29 100644 --- a/Gems/TextureAtlas/Code/Include/TextureAtlas/TextureAtlas.h +++ b/Gems/TextureAtlas/Code/Include/TextureAtlas/TextureAtlas.h @@ -16,7 +16,8 @@ #include #include -class ITexture; +#include +#include namespace TextureAtlasNamespace { @@ -77,9 +78,9 @@ namespace TextureAtlasNamespace //! Retrieve a coordinate set from the Atlas by its handle virtual AtlasCoordinates GetAtlasCoordinates(const AZStd::string& handle) const = 0; //! Links this atlas to an image pointer - virtual void SetTexture(ITexture* image) = 0; + virtual void SetTexture(AZ::Data::Instance image) = 0; //! Returns the image linked to this atlas - virtual ITexture* GetTexture() const = 0; + virtual AZ::Data::Instance GetTexture() const = 0; //! Returns the width of the atlas virtual int GetWidth() const = 0; //! Returns the height of the atlas diff --git a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderComponent.cpp b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderComponent.cpp index e8d4948cc9..0cbc653730 100644 --- a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderComponent.cpp +++ b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderComponent.cpp @@ -10,7 +10,6 @@ * */ -#include "ImageProcessing_precompiled.h" #include "AtlasBuilderComponent.h" #include diff --git a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp index 81e98251cc..ca60d33c0a 100644 --- a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp +++ b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp @@ -10,7 +10,6 @@ * */ -#include "ImageProcessing_precompiled.h" #include "AtlasBuilderWorker.h" #include @@ -19,22 +18,17 @@ #include #include #include +#include #include #include #include #include #include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include +#include +#include +#include #include #include @@ -44,13 +38,13 @@ namespace TextureAtlasBuilder { //! Counts leading zeros - uint32 CountLeadingZeros32(uint32 x) + uint32_t CountLeadingZeros32(uint32_t x) { return x == 0 ? 32 : az_clz_u32(x); } //! Integer log2 - uint32 IntegerLog2(uint32 x) + uint32_t IntegerLog2(uint32_t x) { return 31 - CountLeadingZeros32(x); } @@ -113,13 +107,24 @@ namespace TextureAtlasBuilder { bool resolved = false; - // Get full path by appending the relative path to the watch directory - AZStd::string fullPath = watchDirectory; - fullPath.append("/"); - fullPath.append(relativePath); + if (relativePath[0] == '@') + { + // Get full path by resolving the alias at the front of the path + char resolvedPath[AZ_MAX_PATH_LEN]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath(relativePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN); + resolvedFullPathOut = resolvedPath; + resolved = true; + } + else + { + // Get full path by appending the relative path to the watch directory + AZStd::string fullPath = watchDirectory; + fullPath.append("/"); + fullPath.append(relativePath); - // Resolve to canonical path (remove "./" and "../") - resolved = GetCanonicalPathFromFullPath(fullPath, resolvedFullPathOut); + // Resolve to canonical path (remove "./" and "../") + resolved = GetCanonicalPathFromFullPath(fullPath, resolvedFullPathOut); + } return resolved; } @@ -140,23 +145,6 @@ namespace TextureAtlasBuilder return result; } - const ImageProcessing::PresetSettings* GetImageProcessPresetSettings(const AZStd::string& presetName, const AZStd::string& platformIdentifier) - { - // Get the specified presetId - AZ::Uuid presetId = ImageProcessing::BuilderSettingManager::Instance()->GetPresetIdFromName(presetName); - if (presetId.IsNull()) - { - AZ_Error("Texture Editor", false, "Texture Preset %s has no associated UUID.", presetName.c_str()); - return nullptr; - } - - // Get the preset settings for the platform this job is building for - const ImageProcessing::PresetSettings* presetSettings = ImageProcessing::BuilderSettingManager::Instance()->GetPreset( - presetId, platformIdentifier); - - return presetSettings; - } - // Reflect the input parameters void AtlasBuilderInput::Reflect(AZ::ReflectContext* context) { @@ -474,7 +462,7 @@ namespace TextureAtlasBuilder { AZStd::string ext; AzFramework::StringFunc::Path::GetExtension(candidates[i].c_str(), ext, false); - if (ImageProcessing::IsExtensionSupported(ext.c_str()) && ext != "dds") + if (ext != "dds") { bool duplicate = false; for (size_t j = 0; j < paths.size() && !duplicate; ++j) @@ -589,7 +577,7 @@ namespace TextureAtlasBuilder { AddFolderContents(paths, child, valid); } - else if (ImageProcessing::IsExtensionSupported(ext.c_str()) && ext != "dds") + else if (ext != "dds") { AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePathKeepCase, child); bool duplicate = false; @@ -652,7 +640,11 @@ namespace TextureAtlasBuilder // We process the same file for all platforms for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms) { - if (ImageProcessing::BuilderSettingManager::Instance()->DoesSupportPlatform(info.m_identifier)) + bool doesSupportPlatform = false; + ImageProcessingAtom::ImageBuilderRequestBus::BroadcastResult(doesSupportPlatform, + &ImageProcessingAtom::ImageBuilderRequests::DoesSupportPlatform, + info.m_identifier); + if (doesSupportPlatform) { AssetBuilderSDK::JobDescriptor descriptor = GetJobDescriptor(request.m_sourceFile, input); descriptor.SetPlatformIdentifier(info.m_identifier.c_str()); @@ -707,12 +699,8 @@ namespace TextureAtlasBuilder // Before we begin, let's make sure we are not meant to abort. AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId); - AZStd::vector productFilepaths; - const AZStd::string path = request.m_fullPath; - bool imageProcessingSuccessful = false; - // read in settings/filepaths AtlasBuilderInput input; input.m_forceSquare = AzFramework::StringFunc::ToBool(request.m_jobDescription.m_jobParameters.find(AZ_CRC("forceSquare"))->second.c_str()); @@ -752,43 +740,37 @@ namespace TextureAtlasBuilder // Default to the TextureAtlas preset which is currently set to use compression for all platforms except for iOS. // Currently the only fully supported compression for iOS is PVRTC which requires the texture to be square and a power of 2. // Due to this limitation, we default to using no compression for iOS until ASTC is fully supported - const AZStd::string defaultPresetName = "TextureAtlas"; + const AZStd::string defaultPresetName = "UserInterface_Compressed"; input.m_presetName = defaultPresetName; } - // Get a preset to use for the output image - const ImageProcessing::PresetSettings* preset = GetImageProcessPresetSettings(input.m_presetName, request.m_platformInfo.m_identifier); - if (preset) + bool isFormatSquarePow2 = false; + ImageProcessingAtom::ImageBuilderRequestBus::BroadcastResult(isFormatSquarePow2, + &ImageProcessingAtom::ImageBuilderRequests::IsPresetFormatSquarePow2, + input.m_presetName, request.m_platformInfo.m_identifier); + + if (isFormatSquarePow2) { - // Check the preset's pixel format requirements - const ImageProcessing::PixelFormatInfo* pixelFormatInfo = ImageProcessing::CPixelFormats::GetInstance().GetPixelFormatInfo(preset->m_pixelFormat); - if (pixelFormatInfo && pixelFormatInfo->bSquarePow2) - { - // Override the user config settings to force square and power of 2. - // Otherwise the image conversion process will stretch the image to satisfy these requirements - input.m_forceSquare = true; - input.m_forcePowerOf2 = true; - } - } - else - { - AZ_Error("AtlasBuilder", false, "Could not find a preset setting for the output image."); - return; + // Override the user config settings to force square and power of 2. + // Otherwise the image conversion process will stretch the image to satisfy these requirements + input.m_forceSquare = true; + input.m_forcePowerOf2 = true; } // Read in images - AZStd::vector images; + AZStd::vector images; AZ::u64 totalArea = 0; int maxArea = input.m_maxDimension * input.m_maxDimension; bool sizeFailure = false; for (int i = 0; i < input.m_filePaths.size() && !jobCancelListener.IsCancelled(); ++i) { - ImageProcessing::IImageObject* inputImage = ImageProcessing::LoadImageFromFile(input.m_filePaths[i]); + ImageProcessingAtom::IImageObjectPtr inputImage; + ImageProcessingAtom::ImageProcessingRequestBus::BroadcastResult(inputImage, &ImageProcessingAtom::ImageProcessingRequests::LoadImage, input.m_filePaths[i]); + // Check if we were able to load the image if (inputImage) { - ImageProcessing::IImageObjectPtr image = ImageProcessing::IImageObjectPtr(inputImage); - images.push_back(image); + images.push_back(inputImage); totalArea += inputImage->GetWidth(0) * inputImage->GetHeight(0); } else @@ -837,8 +819,13 @@ namespace TextureAtlasBuilder // Add white texture if we need to if (input.m_includeWhiteTexture) { - ImageProcessing::IImageObjectPtr texture(ImageProcessing::IImageObject::CreateImage( - cellSize, cellSize, 1, ImageProcessing::EPixelFormat::ePixelFormat_R8G8B8A8)); + ImageProcessingAtom::IImageObjectPtr texture; + ImageProcessingAtom::ImageBuilderRequestBus::BroadcastResult(texture, + &ImageProcessingAtom::ImageBuilderRequests::CreateImage, + aznumeric_cast(cellSize), + aznumeric_cast(cellSize), + 1, + ImageProcessingAtom::EPixelFormat::ePixelFormat_R8G8B8A8); // Make the texture white texture->ClearColor(1, 1, 1, 1); @@ -897,8 +884,8 @@ namespace TextureAtlasBuilder } if (input.m_forcePowerOf2) { - resultWidth = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(resultWidth - 1)))); - resultHeight = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(resultHeight - 1)))); + resultWidth = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(resultWidth - 1)))); + resultHeight = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(resultHeight - 1)))); } else { @@ -918,8 +905,13 @@ namespace TextureAtlasBuilder } // Process texture sheet - ImageProcessing::IImageObjectPtr outImage(ImageProcessing::IImageObject::CreateImage( - resultWidth, resultHeight, 1, ImageProcessing::EPixelFormat::ePixelFormat_R8G8B8A8)); + ImageProcessingAtom::IImageObjectPtr outImage; + ImageProcessingAtom::ImageBuilderRequestBus::BroadcastResult(outImage, + &ImageProcessingAtom::ImageBuilderRequests::CreateImage, + aznumeric_cast(resultWidth), + aznumeric_cast(resultHeight), + 1, + ImageProcessingAtom::EPixelFormat::ePixelFormat_R8G8B8A8); // Clear the sheet outImage->ClearColor(input.m_unusedColor.GetR(), input.m_unusedColor.GetG(), input.m_unusedColor.GetB(), input.m_unusedColor.GetA()); @@ -1010,54 +1002,21 @@ namespace TextureAtlasBuilder // Output texture sheet AZStd::string imageFileName, imageOutputPath; AzFramework::StringFunc::Path::GetFileName(request.m_sourceFile.c_str(), imageFileName); - imageFileName += ".dds"; + imageFileName += ".texatlas"; AzFramework::StringFunc::Path::Join( request.m_tempDirPath.c_str(), imageFileName.c_str(), imageOutputPath, true, true); - // Let the ImageProcessor do the rest of the work. - ImageProcessing::TextureSettings textureSettings; - textureSettings.m_preset = preset->m_uuid; + AZStd::vector outProducts; + ImageProcessingAtom::ImageBuilderRequestBus::BroadcastResult(outProducts, + &ImageProcessingAtom::ImageBuilderRequests::ConvertImageObject, + outImage, + input.m_presetName, + request.m_platformInfo.m_identifier, + imageOutputPath, + request.m_sourceFileUUID, + request.m_sourceFile); - // Mipmaps for the texture atlas would require more work than the Image Processor does. This is because if we - // let the Image Processor make mipmaps, it might bleed the textures in the atlas together. - textureSettings.m_enableMipmap = false; - - // Check if the ImageBuilder wants to enable streaming - bool isStreaming = ImageProcessing::BuilderSettingManager::Instance() - ->GetBuilderSetting(request.m_platformInfo.m_identifier) - ->m_enableStreaming; - - bool canOverridePreset = false; - ImageProcessing::ImageConvertProcess* process = - new ImageProcessing::ImageConvertProcess(outImage, - textureSettings, - *preset, - false, - isStreaming, - canOverridePreset, - imageOutputPath, - request.m_platformInfo.m_identifier); - - if (process != nullptr) - { - // the process can be stopped if the job is cancelled or the worker is shutting down - while (!process->IsFinished() && !m_isShuttingDown && !jobCancelListener.IsCancelled()) - { - process->UpdateProcess(); - } - - // get process result - imageProcessingSuccessful = process->IsSucceed(); - process->GetAppendOutputFilePaths(productFilepaths); - - delete process; - } - else - { - imageProcessingSuccessful = false; - } - - if (imageProcessingSuccessful) + if (!outProducts.empty()) { TextureAtlasNamespace::TextureAtlasRequestBus::Broadcast( &TextureAtlasNamespace::TextureAtlasRequests::SaveAtlasToFile, outputPath, output, resultWidth, resultHeight); @@ -1067,27 +1026,23 @@ namespace TextureAtlasBuilder // The Image Processing Gem can produce multiple output files under certain // circumstances, but the texture atlas is not expected to produce such output - if (productFilepaths.size() > 1) + if (outProducts.size() > 1) { AZ_Error("AtlasBuilder", false, "Image processing resulted in multiple output files. Texture atlas is expected to produce one output."); response.m_outputProducts.clear(); return; } - if (productFilepaths.size() > 0) - { - response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(productFilepaths[0])); - response.m_outputProducts.back().m_productAssetType = azrtti_typeid(); - response.m_outputProducts.back().m_productSubID = 1; + response.m_outputProducts.push_back(outProducts[0]); + + // The texatlasidx file is a data file that indicates where the original parts are inside the atlas, + // and this would usually imply that it refers to its dds file in some way or needs it to function. + // The texatlasidx file should be the one that depends on the DDS because it's possible to use the DDS + // without the texatlasid, but not the other way around + AZ::Data::AssetId productAssetId(request.m_sourceFileUUID, response.m_outputProducts.back().m_productSubID); + response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_dependencies.push_back(AssetBuilderSDK::ProductDependency(productAssetId, 0)); + response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_dependenciesHandled = true; // We've populated the dependencies immediately above so it's OK to tell the AP we've handled dependencies - // The texatlasidx file is a data file that indicates where the original parts are inside the atlas, - // and this would usually imply that it refers to its dds file in some way or needs it to function. - // The texatlasidx file should be the one that depends on the DDS because its possible to use the DDS - // without the texatlasid, but not the other way around - AZ::Data::AssetId productAssetId(request.m_sourceFileUUID, response.m_outputProducts.back().m_productSubID); - response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_dependencies.push_back(AssetBuilderSDK::ProductDependency(productAssetId, 0)); - response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_dependenciesHandled = true; // We've populated the dependencies immediately above so it's OK to tell the AP we've handled dependencies - } response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; } } @@ -1315,7 +1270,7 @@ namespace TextureAtlasBuilder if (powerOfTwo) { // Starting dimension needs to be rounded up to the nearest power of two - dimension = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(dimension - 1)))); + dimension = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(dimension - 1)))); } AZStd::vector track; @@ -1363,7 +1318,7 @@ namespace TextureAtlasBuilder if (powerOfTwo) { // Starting dimension needs to be rounded up to the nearest power of two - minWidth = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(minWidth - 1)))); + minWidth = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(minWidth - 1)))); } // Round min width up to the nearest compression unit @@ -1400,7 +1355,7 @@ namespace TextureAtlasBuilder // Find the height of the solution for (int i = 0; i < track.size(); ++i) { - uint32 bottom = static_cast(AZStd::max(0, track[i].GetBottom())); + uint32_t bottom = static_cast(AZStd::max(0, track[i].GetBottom())); if (height < bottom) { height = bottom; @@ -1411,7 +1366,7 @@ namespace TextureAtlasBuilder if (powerOfTwo) { // Starting dimensions need to be rounded up to the nearest power of two - height = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(height - 1)))); + height = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(height - 1)))); } AZ::u32 resultArea = height * width; diff --git a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.h b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.h index 94e2b5b226..36f0c3d486 100644 --- a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.h +++ b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.h @@ -13,6 +13,7 @@ #pragma once #include +#include #include #include #include @@ -110,7 +111,7 @@ namespace TextureAtlasBuilder enum class Product { TexatlasidxProduct = 0, - DdsProduct = 1 + StreamingImageProduct = 1 }; //! An asset builder for texture atlases diff --git a/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.cpp b/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.cpp index 70a1900c25..e84e843177 100644 --- a/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.cpp +++ b/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.cpp @@ -120,14 +120,14 @@ namespace TextureAtlasNamespace } // Links this atlas to an image pointer - void TextureAtlasImpl::SetTexture(ITexture* image) + void TextureAtlasImpl::SetTexture(AZ::Data::Instance image) { // We don't need to delete the old value because the pointer is handled elsewhere m_image = image; } // Returns the image linked to this atlas - ITexture* TextureAtlasImpl::GetTexture() const + AZ::Data::Instance TextureAtlasImpl::GetTexture() const { return m_image; } diff --git a/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h b/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h index af611c8c7d..22c03e0e3c 100644 --- a/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h +++ b/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h @@ -20,7 +20,8 @@ #include "TextureAtlas/TextureAtlas.h" #include "TextureAtlas/TextureAtlasBus.h" -#include +#include +#include namespace TextureAtlasNamespace { @@ -61,10 +62,10 @@ namespace TextureAtlasNamespace AtlasCoordinates GetAtlasCoordinates(const AZStd::string& handle) const override; //! Links this atlas to an image pointer - void SetTexture(ITexture* image) override; + void SetTexture(AZ::Data::Instance image) override; //! Returns the image linked to this atlas - ITexture* GetTexture() const override; + AZ::Data::Instance GetTexture() const override; //! Replaces the mappings of this Texture Atlas Object, with the source's mappings void OverwriteMappings(TextureAtlasImpl* source); @@ -80,7 +81,7 @@ namespace TextureAtlasNamespace private: AZStd::unordered_map m_data; - ITexture* m_image; + AZ::Data::Instance m_image; int m_width; int m_height; }; diff --git a/Gems/TextureAtlas/Code/Source/TextureAtlasModule.cpp b/Gems/TextureAtlas/Code/Source/TextureAtlasModule.cpp index 478a3f8ca6..90114f6e79 100644 --- a/Gems/TextureAtlas/Code/Source/TextureAtlasModule.cpp +++ b/Gems/TextureAtlas/Code/Source/TextureAtlasModule.cpp @@ -16,6 +16,10 @@ #include "TextureAtlasSystemComponent.h" +#ifdef TEXTUREATLAS_EDITOR +#include "Editor/AtlasBuilderComponent.h" +#endif + #include namespace TextureAtlasNamespace @@ -33,6 +37,9 @@ namespace TextureAtlasNamespace // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. m_descriptors.insert(m_descriptors.end(), { TextureAtlasSystemComponent::CreateDescriptor(), +#ifdef TEXTUREATLAS_EDITOR + TextureAtlasBuilder::AtlasBuilderComponent::CreateDescriptor(), //builder component for texture atlas +#endif }); } diff --git a/Gems/TextureAtlas/Code/Source/TextureAtlasSystemComponent.cpp b/Gems/TextureAtlas/Code/Source/TextureAtlasSystemComponent.cpp index 80d4898c41..24a5126df4 100644 --- a/Gems/TextureAtlas/Code/Source/TextureAtlasSystemComponent.cpp +++ b/Gems/TextureAtlas/Code/Source/TextureAtlasSystemComponent.cpp @@ -22,7 +22,25 @@ #include #include -#include +#include + +namespace +{ + AZ::Data::Instance LoadAtlasImage(const AZStd::string& imagePath) + { + // The file may not be in the AssetCatalog at this point if it is still processing or doesn't exist on disk. + // Use GenerateAssetIdTEMP instead of GetAssetIdByPath so that it will return a valid AssetId anyways + AZ::Data::AssetId streamingImageAssetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + streamingImageAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP, + imagePath.c_str()); + + streamingImageAssetId.m_subId = AZ::RPI::StreamingImageAsset::GetImageAssetSubId(); + auto streamingImageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(streamingImageAssetId, AZ::Data::AssetLoadBehavior::PreLoad); + AZ::Data::Instance image = AZ::RPI::StreamingImage::FindOrCreate(streamingImageAsset); + return image; + } +} namespace TextureAtlasNamespace { @@ -95,27 +113,15 @@ namespace TextureAtlasNamespace // We reload the image here to prevent stuttering in the editor if (iterator->second.m_atlas && iterator->second.m_atlas->GetTexture()) { - SResourceAsync* pInfo = new SResourceAsync(); - pInfo->eClassName = eRCN_Texture; - pInfo->pResource = iterator->second.m_atlas->GetTexture(); - // ToDo: Update to work with Atom? LYN-3680 - // ???->ReleaseResourceAsync(pInfo); + iterator->second.m_atlas->GetTexture().reset(); } - // Reload Texture - AZStd::string imagePath = iterator->second.m_path.substr(0, iterator->second.m_path.find_last_of('.')); - imagePath.append(".dds"); - - // ToDo: Update to work with Atom? LYN-3680 - // uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM); - ITexture* texture = nullptr; - - if (!texture || !texture->IsTextureLoaded()) + AZStd::string imagePath = iterator->second.m_path; + AZ::Data::Instance texture = LoadAtlasImage(imagePath); + if (!texture) { - gEnv->pSystem->Warning(VALIDATOR_MODULE_UNKNOWN, - VALIDATOR_WARNING, - VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE, - imagePath.c_str(), - "No texture file found for texture atlas: %s. " + AZ_Error("TextureAtlasSystemComponent", + false, + "Failed to find or create an image instance for texture atlas '%s'" "NOTE: File must be in current project or a gem.", imagePath.c_str()); TextureAtlas* temp = iterator->second.m_atlas; @@ -123,6 +129,7 @@ namespace TextureAtlasNamespace TextureAtlasNotificationBus::Broadcast(&TextureAtlasNotifications::OnAtlasUnloaded, temp); return; } + iterator->second.m_atlas->SetTexture(texture); TextureAtlasNotificationBus::Broadcast(&TextureAtlasNotifications::OnAtlasReloaded, iterator->second.m_atlas); break; @@ -186,30 +193,23 @@ namespace TextureAtlasNamespace delete[] buffer; if (loadedAtlas) { - // Get the image path based on the atlas path + // Convert to image path based on the atlas path AZStd::string imagePath = path; - AzFramework::StringFunc::Path::ReplaceExtension(imagePath, "dds"); - - // Load the image in - // ToDo: Update to work with Atom? LYN-3680 - // uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM); - ITexture* texture = nullptr; - - if (!texture || !texture->IsTextureLoaded()) + AzFramework::StringFunc::Path::ReplaceExtension(imagePath, "texatlas"); + AZ::Data::Instance texture = LoadAtlasImage(imagePath); + if (!texture) { - gEnv->pSystem->Warning(VALIDATOR_MODULE_UNKNOWN, - VALIDATOR_WARNING, - VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE, - imagePath.c_str(), - "No texture file found for texture atlas: %s. " + AZ_Error("TextureAtlasSystemComponent", + false, + "Failed to find or create an image instance for texture atlas '%s'" "NOTE: File must be in current project or a gem.", - imagePath.c_str()); + path.c_str()); + delete loadedAtlas; return nullptr; } else { - texture->SetFilter(FILTER_LINEAR); // Add the atlas to the list AtlasInfo info(loadedAtlas, assetPath); ++info.m_refs; @@ -241,11 +241,7 @@ namespace TextureAtlasNamespace // Tell the renderer to release the texture. if (temp.m_atlas && temp.m_atlas->GetTexture()) { - SResourceAsync* pInfo = new SResourceAsync(); - pInfo->eClassName = eRCN_Texture; - pInfo->pResource = temp.m_atlas->GetTexture(); - // ToDo: Update to work with Atom? LYN-3680 - // ???->ReleaseResourceAsync(pInfo); + temp.m_atlas->GetTexture().reset(); } // Delete the atlas SAFE_DELETE(temp.m_atlas); diff --git a/Gems/TextureAtlas/Code/textureatlas_builder_files.cmake b/Gems/TextureAtlas/Code/textureatlas_builder_files.cmake new file mode 100644 index 0000000000..51cb991aa8 --- /dev/null +++ b/Gems/TextureAtlas/Code/textureatlas_builder_files.cmake @@ -0,0 +1,17 @@ +# +# 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. +# + +set(FILES + Source/Editor/AtlasBuilderComponent.h + Source/Editor/AtlasBuilderComponent.cpp + Source/Editor/AtlasBuilderWorker.h + Source/Editor/AtlasBuilderWorker.cpp +) diff --git a/Gems/TextureAtlas/Code/textureatlas_files.cmake b/Gems/TextureAtlas/Code/textureatlas_files.cmake index 2da4e9ce1d..c45c1d49a8 100644 --- a/Gems/TextureAtlas/Code/textureatlas_files.cmake +++ b/Gems/TextureAtlas/Code/textureatlas_files.cmake @@ -15,7 +15,6 @@ set(FILES Include/TextureAtlas/TextureAtlasBus.h Include/TextureAtlas/TextureAtlasNotificationBus.h Include/TextureAtlas/TextureAtlas.h - Source/TextureAtlasModule.cpp Source/TextureAtlasSystemComponent.cpp Source/TextureAtlasSystemComponent.h Source/TextureAtlasImpl.h diff --git a/Gems/TextureAtlas/Code/textureatlas_module_files.cmake b/Gems/TextureAtlas/Code/textureatlas_module_files.cmake new file mode 100644 index 0000000000..00e18d92bc --- /dev/null +++ b/Gems/TextureAtlas/Code/textureatlas_module_files.cmake @@ -0,0 +1,14 @@ +# +# 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. +# + +set(FILES + Source/TextureAtlasModule.cpp +) From 24c17932e3298ec26e5f113516e4ebb0f3c472f1 Mon Sep 17 00:00:00 2001 From: chcurran Date: Tue, 25 May 2021 14:19:04 -0700 Subject: [PATCH 07/12] Add error messages to ErrorText.h, label functionality to fix default groups on FDNs. --- .../Grammar/AbstractCodeModel.cpp | 4 +- .../Libraries/Core/FunctionDefinitionNode.cpp | 44 ++++++++++++------- .../Libraries/Core/FunctionDefinitionNode.h | 6 +-- .../Include/ScriptCanvas/Results/ErrorText.h | 2 + 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index d30c8f857c..732455857e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -1036,12 +1036,12 @@ namespace ScriptCanvas if (azrtti_istypeof(&node)) { // todo Add node to these errors - AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("NodeableNodeOverloaded doesn't have enough data connected to select a valid overload: %s", node.GetDebugName().data())))); + AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("%s: %s", ParseErrors::NodeableNodeOverloadAmbiguous, node.GetDebugName().data())))); } else { // todo Add node to these errors - AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("NodeableNode did not construct its internal node: %s", node.GetDebugName().data())))); + AddError(nullptr, ValidationConstPtr(aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("%s: %s", ParseErrors::NodeableNodeDidNotConstructInternalNodeable, node.GetDebugName().data())))); } } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp index d485a15be3..a849983deb 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.cpp @@ -19,6 +19,32 @@ #include +namespace FunctionDefinitionNodeCpp +{ + void VersionUpdateRemoveDefaultDisplayGroup(ScriptCanvas::Nodes::Core::FunctionDefinitionNode& node) + { + using namespace ScriptCanvas; + using namespace ScriptCanvas::Nodes::Core; + + AZ::SerializeContext* serializeContext{}; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); + if (serializeContext) + { + const auto& classData = serializeContext->FindClassData(azrtti_typeid()); + if (classData && classData->m_version < FunctionDefinitionNode::NodeVersion::RemoveDefaultDisplayGroup) + { + for (auto& slot : node.ModAllSlots()) + { + if (slot->GetType() == CombinedSlotType::DataIn || slot->GetType() == CombinedSlotType::DataOut) + { + slot->ClearDynamicGroup(); + } + } + } + } + } +} + namespace ScriptCanvas { namespace Nodes @@ -116,23 +142,7 @@ namespace ScriptCanvas void FunctionDefinitionNode::OnInit() { Nodeling::OnInit(); - - AZ::SerializeContext* serializeContext{}; - AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); - if (serializeContext) - { - const auto& classData = serializeContext->FindClassData(azrtti_typeid()); - if (classData && classData->m_version < NodeVersion::RemoveDefaultDisplayGroup) - { - for (auto& slot : ModAllSlots()) - { - if (slot->GetType() == CombinedSlotType::DataIn || slot->GetType() == CombinedSlotType::DataOut) - { - slot->ClearDynamicGroup(); - } - } - } - } + FunctionDefinitionNodeCpp::VersionUpdateRemoveDefaultDisplayGroup(*this); } void FunctionDefinitionNode::SetupSlots() diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h index 0e3119cdfd..04dc0c7103 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/FunctionDefinitionNode.h @@ -29,15 +29,13 @@ namespace ScriptCanvas class FunctionDefinitionNode : public Internal::Nodeling { - private: + public: enum NodeVersion { - Initial = 1, + Initial = 1, RemoveDefaultDisplayGroup, }; - public: - SCRIPTCANVAS_NODE(FunctionDefinitionNode); FunctionDefinitionNode() = default; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Results/ErrorText.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Results/ErrorText.h index 16ac7e1fa0..def4fa7761 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Results/ErrorText.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Results/ErrorText.h @@ -62,6 +62,8 @@ namespace ScriptCanvas constexpr const char* NoChildrenAfterRoot = "No children after parsing function root"; constexpr const char* NoChildrenInExtraction = "No children found in property extraction node"; constexpr const char* NoDataPresent = "Could not construct from graph, no graph data was present"; + constexpr const char* NodeableNodeOverloadAmbiguous = "NodeableNodeOverloaded doesn't have enough data connected to select a valid overload"; + constexpr const char* NodeableNodeDidNotConstructInternalNodeable = "NodeableNode did not construct its internal Nodeable"; constexpr const char* NoInputToForEach = "No Input To For Each Loop"; constexpr const char* NoOutForExecution = "No out slot for execution root"; constexpr const char* NoOutSlotInFunctionDefinitionStart = "No 'Out' slot in start of function definition"; From dacffc8f07c62c5324baf8a9d882993234134c7c Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Tue, 25 May 2021 16:05:09 -0700 Subject: [PATCH 08/12] Remove the "(PREVIEW)" label from the Animation Editor (#926) --- .../Code/Source/Integration/System/SystemComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index 0a64c7b408..8e68c8cb44 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -890,7 +890,7 @@ namespace EMotionFX #if AZ_TRAIT_EMOTIONFX_MAIN_WINDOW_DETACHED emotionFXWindowOptions.detachedWindow = true; #endif - emotionFXWindowOptions.optionalMenuText = "Animation Editor (PREVIEW)"; + emotionFXWindowOptions.optionalMenuText = "Animation Editor"; EditorRequests::Bus::Broadcast(&EditorRequests::RegisterViewPane, EMStudio::MainWindow::GetEMotionFXPaneName(), LyViewPane::CategoryTools, emotionFXWindowOptions, windowCreationFunc); } From 6136bc270e77d8b7d4e6b63aa9265eae812b9335 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Tue, 25 May 2021 16:05:40 -0700 Subject: [PATCH 09/12] Remove flaky test from AzNetwork instead of using retry - Remove '--repeat until-pass' from profile test ctest argument - Moved flaky TCP tests from main googletest suite to sandbox - Added 'TARGET' to 'ly_add_googletest' to support adding the same module to multiple tests or adding a test that is not named the same as the module - Fix minor bug in ly_add_googletest --- Code/Framework/AzNetworking/CMakeLists.txt | 7 +++++ .../Tests/TcpTransport/TcpTransportTests.cpp | 4 +-- cmake/LYTestWrappers.cmake | 17 ++++++++---- .../build/Platform/Linux/build_config.json | 27 ++++++++++++++++--- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzNetworking/CMakeLists.txt b/Code/Framework/AzNetworking/CMakeLists.txt index 0fe95441ce..c6673058d7 100644 --- a/Code/Framework/AzNetworking/CMakeLists.txt +++ b/Code/Framework/AzNetworking/CMakeLists.txt @@ -65,5 +65,12 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME AZ::AzNetworking.Tests ) + + ly_add_googletest( + NAME AZ::AzNetworking.Tests.Sandbox + TARGET AZ::AzNetworking.Tests + TEST_SUITE sandbox + ) + endif() diff --git a/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp b/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp index eed12e1881..7cc3af5a51 100644 --- a/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp +++ b/Code/Framework/AzNetworking/Tests/TcpTransport/TcpTransportTests.cpp @@ -129,7 +129,7 @@ namespace UnitTest #if AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS TEST_F(TcpTransportTests, DISABLED_TestSingleClient) #else - TEST_F(TcpTransportTests, TestSingleClient) + TEST_F(TcpTransportTests, SUITE_sandbox_TestSingleClient) #endif // AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS { TestTcpServer testServer; @@ -157,7 +157,7 @@ namespace UnitTest #if AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS TEST_F(TcpTransportTests, DISABLED_TestMultipleClients) #else - TEST_F(TcpTransportTests, TestMultipleClients) + TEST_F(TcpTransportTests, SUITE_sandbox_TestMultipleClients) #endif // AZ_TRAIT_DISABLE_FAILED_NETWORKING_TESTS { constexpr uint32_t NumTestClients = 50; diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index 2a65929cf6..b4d6fe308e 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -370,6 +370,7 @@ endfunction() #! ly_add_googletest: Adds a new RUN_TEST using for the specified target using the supplied command or fallback to running # googletest tests through AzTestRunner # \arg:NAME Name to for the test run target +# \arg:TARGET Name of the target module that is being run for tests. If not provided, will default to 'NAME' # \arg:TEST_REQUIRES(optional) List of system resources that are required to run this test. # Only available option is "gpu" # \arg:TEST_SUITE(optional) - "smoke" or "periodic" or "sandbox" - prevents the test from running normally @@ -384,14 +385,20 @@ function(ly_add_googletest) message(FATAL_ERROR "Platform does not support test targets") endif() - set(one_value_args NAME TEST_SUITE) + set(one_value_args NAME TARGET TEST_SUITE) set(multi_value_args TEST_COMMAND COMPONENT) cmake_parse_arguments(ly_add_googletest "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) + if (ly_add_googletest_TARGET) + set(target_name ${ly_add_googletest_TARGET}) + else() + set(target_name ${ly_add_googletest_NAME}) + endif() + # AzTestRunner modules only supports google test libraries, regardless of whether or not # google test suites are supported - set_property(GLOBAL APPEND PROPERTY LY_AZTESTRUNNER_TEST_MODULES "${ly_add_googletest_NAME}") + set_property(GLOBAL APPEND PROPERTY LY_AZTESTRUNNER_TEST_MODULES "${target_name}") if(NOT PAL_TRAIT_TEST_GOOGLE_TEST_SUPPORTED) return() @@ -400,7 +407,7 @@ function(ly_add_googletest) if (ly_add_googletest_TEST_SUITE AND NOT ly_add_googletest_TEST_SUITE STREQUAL "main") # if a suite is specified, we filter to only accept things which match that suite (in c++) - set(non_ide_params "-gtest_filter=*SUITE_${ly_add_googletest_TEST_SUITE}*") + set(non_ide_params "--gtest_filter=*SUITE_${ly_add_googletest_TEST_SUITE}*") else() # otherwise, if its the main suite we only runs things that dont have any of the other suites. # Note: it doesn't do AND, only 'or' - so specifying SUITE_main:REQUIRES_gpu @@ -412,11 +419,11 @@ function(ly_add_googletest) if(NOT ly_add_googletest_TEST_COMMAND) # Use the NAME parameter as the build target - set(build_target ${ly_add_googletest_NAME}) + set(build_target ${target_name}) ly_strip_target_namespace(TARGET ${build_target} OUTPUT_VARIABLE build_target) if(NOT TARGET ${build_target}) - message(FATAL_ERROR "A valid build target \"${build_target}\" for test run \"${ly_add_googletest_NAME}\" has not been found.\ + message(FATAL_ERROR "A valid build target \"${build_target}\" for test run \"${target_name}\" has not been found.\ A valid target via the TARGET parameter or a custom TEST_COMMAND must be supplied") endif() diff --git a/scripts/build/Platform/Linux/build_config.json b/scripts/build/Platform/Linux/build_config.json index 5d96ae7846..c1646fc863 100644 --- a/scripts/build/Platform/Linux/build_config.json +++ b/scripts/build/Platform/Linux/build_config.json @@ -83,7 +83,7 @@ "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4 -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "all", - "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest --repeat until-pass:5" + "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest" } }, "test_profile_nounity": { @@ -95,7 +95,7 @@ "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4 -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "all", - "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest --repeat until-pass:5" + "CTEST_OPTIONS": "-E (Gem::EMotionFX.Editor.Tests|Gem::AWSClientAuth.Tests|Gem::AWSCore.Editor.Tests) -L FRAMEWORK_googletest" } }, "asset_profile": { @@ -143,7 +143,26 @@ "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4 -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "TEST_SUITE_periodic", - "CTEST_OPTIONS": "-L \"(SUITE_periodic)\"" + "CTEST_OPTIONS": "-L (SUITE_periodic)" + } + }, + "sandbox_test_profile": { + "TAGS": [ + "nightly-incremental", + "nightly-clean", + "weekly-build-metrics" + ], + "PIPELINE_ENV": { + "ON_FAILURE_MARK": "UNSTABLE" + }, + "COMMAND": "build_test_linux.sh", + "PARAMETERS": { + "CONFIGURATION": "profile", + "OUTPUT_DIRECTORY": "build/linux", + "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4 -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE", + "CMAKE_LY_PROJECTS": "AutomatedTesting", + "CMAKE_TARGET": "all", + "CTEST_OPTIONS": "-L (SUITE_sandbox)" } }, "benchmark_test_profile": { @@ -159,7 +178,7 @@ "CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-6.0 -DCMAKE_CXX_COMPILER=clang++-6.0 -DLY_UNITY_BUILD=TRUE -DLY_PARALLEL_LINK_JOBS=4 -DO3DE_HOME_PATH=\"${WORKSPACE}/home\" -DO3DE_REGISTER_ENGINE_PATH=\"${WORKSPACE}/o3de\" -DO3DE_REGISTER_THIS_ENGINE=TRUE", "CMAKE_LY_PROJECTS": "AutomatedTesting", "CMAKE_TARGET": "TEST_SUITE_benchmark", - "CTEST_OPTIONS": "-L \"(SUITE_benchmark)\"" + "CTEST_OPTIONS": "-L (SUITE_benchmark)" } }, "release": { From 4dd08ec21f382f00382ebc5871b9ac8621fd1516 Mon Sep 17 00:00:00 2001 From: Terry Michaels <81711813+tjmichaels@users.noreply.github.com> Date: Tue, 25 May 2021 18:15:19 -0500 Subject: [PATCH 10/12] Added a default level prefab concept for newly created levels (#931) * Started update for prefab based initial asset inclusion * Newly Created levels now use a template prefab * Review feedback changes * Moved to better asset-based queries to generate the full path. * Removed pesky pragma * Replaced with const name instead of literal string --- Assets/Editor/Prefabs/Default_Level.prefab | 666 ++++++++++++++++++ .../PrefabEditorEntityOwnershipService.cpp | 60 +- .../PrefabEditorEntityOwnershipService.h | 2 + 3 files changed, 718 insertions(+), 10 deletions(-) create mode 100644 Assets/Editor/Prefabs/Default_Level.prefab diff --git a/Assets/Editor/Prefabs/Default_Level.prefab b/Assets/Editor/Prefabs/Default_Level.prefab new file mode 100644 index 0000000000..fb82c5ab03 --- /dev/null +++ b/Assets/Editor/Prefabs/Default_Level.prefab @@ -0,0 +1,666 @@ +{ + "Source": "Default_Level.prefab", + "ContainerEntity": { + "Id": "Entity_[1146574390643]", + "Name": "Level", + "Components": { + "Component_[10641544592923449938]": { + "$type": "EditorInspectorComponent", + "Id": 10641544592923449938 + }, + "Component_[12039882709170782873]": { + "$type": "EditorOnlyEntityComponent", + "Id": 12039882709170782873 + }, + "Component_[12265484671603697631]": { + "$type": "EditorPendingCompositionComponent", + "Id": 12265484671603697631 + }, + "Component_[14126657869720434043]": { + "$type": "EditorEntitySortComponent", + "Id": 14126657869720434043 + }, + "Component_[15230859088967841193]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 15230859088967841193, + "Parent Entity": "", + "Cached World Transform Parent": "" + }, + "Component_[16239496886950819870]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 16239496886950819870 + }, + "Component_[5688118765544765547]": { + "$type": "EditorEntityIconComponent", + "Id": 5688118765544765547 + }, + "Component_[6545738857812235305]": { + "$type": "SelectionComponent", + "Id": 6545738857812235305 + }, + "Component_[7247035804068349658]": { + "$type": "EditorPrefabComponent", + "Id": 7247035804068349658 + }, + "Component_[9307224322037797205]": { + "$type": "EditorLockComponent", + "Id": 9307224322037797205 + }, + "Component_[9562516168917670048]": { + "$type": "EditorVisibilityComponent", + "Id": 9562516168917670048 + } + }, + "IsDependencyReady": true + }, + "Entities": { + "Entity_[1155164325235]": { + "Id": "Entity_[1155164325235]", + "Name": "Sun", + "Components": { + "Component_[10440557478882592717]": { + "$type": "SelectionComponent", + "Id": 10440557478882592717 + }, + "Component_[13620450453324765907]": { + "$type": "EditorLockComponent", + "Id": 13620450453324765907 + }, + "Component_[2134313378593666258]": { + "$type": "EditorInspectorComponent", + "Id": 2134313378593666258 + }, + "Component_[234010807770404186]": { + "$type": "EditorVisibilityComponent", + "Id": 234010807770404186 + }, + "Component_[2970359110423865725]": { + "$type": "EditorEntityIconComponent", + "Id": 2970359110423865725 + }, + "Component_[3722854130373041803]": { + "$type": "EditorOnlyEntityComponent", + "Id": 3722854130373041803 + }, + "Component_[5992533738676323195]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 5992533738676323195 + }, + "Component_[7378860763541895402]": { + "$type": "AZ::Render::EditorDirectionalLightComponent", + "Id": 7378860763541895402, + "Controller": { + "Configuration": { + "Intensity": 1.0, + "CameraEntityId": "", + "ShadowFilterMethod": 1, + "ShadowmapSize": "Size1024", + "Pcf Method": 1 + } + } + }, + "Component_[7892834440890947578]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 7892834440890947578, + "Parent Entity": "Entity_[1176639161715]", + "Transform Data": { + "Translate": [ + 0.0, + 0.0, + 13.487043380737305 + ], + "Rotate": [ + -76.13099670410156, + -0.847000002861023, + -15.8100004196167 + ] + }, + "Cached World Transform": { + "Translation": [ + 0.0, + 0.0, + 9.442070960998536 + ], + "Rotation": [ + -0.6098860502243042, + -0.09055805951356888, + -0.10376212745904924, + 0.7804304361343384 + ] + }, + "Cached World Transform Parent": "Entity_[1176639161715]" + }, + "Component_[8599729549570828259]": { + "$type": "EditorEntitySortComponent", + "Id": 8599729549570828259 + }, + "Component_[952797371922080273]": { + "$type": "EditorPendingCompositionComponent", + "Id": 952797371922080273 + } + }, + "IsDependencyReady": true + }, + "Entity_[1159459292531]": { + "Id": "Entity_[1159459292531]", + "Name": "Ground", + "Components": { + "Component_[11701138785793981042]": { + "$type": "SelectionComponent", + "Id": 11701138785793981042 + }, + "Component_[12260880513256986252]": { + "$type": "EditorEntityIconComponent", + "Id": 12260880513256986252 + }, + "Component_[13711420870643673468]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 13711420870643673468 + }, + "Component_[138002849734991713]": { + "$type": "EditorOnlyEntityComponent", + "Id": 138002849734991713 + }, + "Component_[16578565737331764849]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 16578565737331764849, + "Parent Entity": "Entity_[1176639161715]", + "Cached World Transform": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Cached World Transform Parent": "Entity_[1176639161715]" + }, + "Component_[16919232076966545697]": { + "$type": "EditorInspectorComponent", + "Id": 16919232076966545697 + }, + "Component_[5182430712893438093]": { + "$type": "EditorMaterialComponent", + "Id": 5182430712893438093, + "materialSlots": [ + { + "id": { + "materialAssetId": { + "guid": "{935F694A-8639-515B-8133-81CDC7948E5B}", + "subId": 803645540 + } + } + } + ], + "materialSlotsByLod": [ + [ + { + "id": { + "lodIndex": 0, + "materialAssetId": { + "guid": "{935F694A-8639-515B-8133-81CDC7948E5B}", + "subId": 803645540 + } + } + } + ] + ] + }, + "Component_[5675108321710651991]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 5675108321710651991, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{935F694A-8639-515B-8133-81CDC7948E5B}", + "subId": 277333723 + }, + "assetHint": "objects/groudplane/groundplane_521x521m.azmodel" + } + } + } + }, + "Component_[5681893399601237518]": { + "$type": "EditorEntitySortComponent", + "Id": 5681893399601237518 + }, + "Component_[592692962543397545]": { + "$type": "EditorPendingCompositionComponent", + "Id": 592692962543397545 + }, + "Component_[7090012899106946164]": { + "$type": "EditorLockComponent", + "Id": 7090012899106946164 + }, + "Component_[9410832619875640998]": { + "$type": "EditorVisibilityComponent", + "Id": 9410832619875640998 + } + }, + "IsDependencyReady": true + }, + "Entity_[1163754259827]": { + "Id": "Entity_[1163754259827]", + "Name": "Camera", + "Components": { + "Component_[11895140916889160460]": { + "$type": "EditorEntityIconComponent", + "Id": 11895140916889160460 + }, + "Component_[16880285896855930892]": { + "$type": "{CA11DA46-29FF-4083-B5F6-E02C3A8C3A3D} EditorCameraComponent", + "Id": 16880285896855930892, + "Controller": { + "Configuration": { + "Field of View": 55.0, + "EditorEntityId": 8929576024571800510 + } + } + }, + "Component_[17187464423780271193]": { + "$type": "EditorLockComponent", + "Id": 17187464423780271193 + }, + "Component_[17495696818315413311]": { + "$type": "EditorEntitySortComponent", + "Id": 17495696818315413311 + }, + "Component_[18086214374043522055]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 18086214374043522055, + "Parent Entity": "Entity_[1176639161715]", + "Transform Data": { + "Translate": [ + -2.300000190734864, + -3.9368600845336916, + 1.0 + ], + "Rotate": [ + -2.050307512283325, + 1.9552897214889529, + -43.62335586547852 + ] + }, + "Cached World Transform": { + "Translation": [ + -11.904647827148438, + 13.392678260803223, + -3.0449724197387697 + ], + "Rotation": [ + -0.02294669672846794, + 0.00919158011674881, + -0.37172695994377139, + 0.9280129671096802 + ] + }, + "Cached World Transform Parent": "Entity_[1176639161715]" + }, + "Component_[18387556550380114975]": { + "$type": "SelectionComponent", + "Id": 18387556550380114975 + }, + "Component_[2654521436129313160]": { + "$type": "EditorVisibilityComponent", + "Id": 2654521436129313160 + }, + "Component_[5265045084611556958]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 5265045084611556958 + }, + "Component_[7169798125182238623]": { + "$type": "EditorPendingCompositionComponent", + "Id": 7169798125182238623 + }, + "Component_[8866210352157164042]": { + "$type": "EditorInspectorComponent", + "Id": 8866210352157164042 + }, + "Component_[9129253381063760879]": { + "$type": "EditorOnlyEntityComponent", + "Id": 9129253381063760879 + } + }, + "IsDependencyReady": true + }, + "Entity_[1168049227123]": { + "Id": "Entity_[1168049227123]", + "Name": "Grid", + "Components": { + "Component_[11443347433215807130]": { + "$type": "EditorEntityIconComponent", + "Id": 11443347433215807130 + }, + "Component_[11779275529534764488]": { + "$type": "SelectionComponent", + "Id": 11779275529534764488 + }, + "Component_[14249419413039427459]": { + "$type": "EditorInspectorComponent", + "Id": 14249419413039427459 + }, + "Component_[15448581635946161318]": { + "$type": "AZ::Render::EditorGridComponent", + "Id": 15448581635946161318, + "Controller": { + "Configuration": { + "primarySpacing": 4.0, + "primaryColor": [ + 0.501960813999176, + 0.501960813999176, + 0.501960813999176 + ], + "secondarySpacing": 0.5, + "secondaryColor": [ + 0.250980406999588, + 0.250980406999588, + 0.250980406999588 + ] + } + } + }, + "Component_[1843303322527297409]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 1843303322527297409 + }, + "Component_[380249072065273654]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 380249072065273654, + "Parent Entity": "Entity_[1176639161715]", + "Cached World Transform": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Cached World Transform Parent": "Entity_[1176639161715]" + }, + "Component_[7476660583684339787]": { + "$type": "EditorPendingCompositionComponent", + "Id": 7476660583684339787 + }, + "Component_[7557626501215118375]": { + "$type": "EditorEntitySortComponent", + "Id": 7557626501215118375 + }, + "Component_[7984048488947365511]": { + "$type": "EditorVisibilityComponent", + "Id": 7984048488947365511 + }, + "Component_[8118181039276487398]": { + "$type": "EditorOnlyEntityComponent", + "Id": 8118181039276487398 + }, + "Component_[9189909764215270515]": { + "$type": "EditorLockComponent", + "Id": 9189909764215270515 + } + }, + "IsDependencyReady": true + }, + "Entity_[1172344194419]": { + "Id": "Entity_[1172344194419]", + "Name": "Shader Ball", + "Components": { + "Component_[10789351944715265527]": { + "$type": "EditorOnlyEntityComponent", + "Id": 10789351944715265527 + }, + "Component_[12037033284781049225]": { + "$type": "EditorEntitySortComponent", + "Id": 12037033284781049225 + }, + "Component_[13759153306105970079]": { + "$type": "EditorPendingCompositionComponent", + "Id": 13759153306105970079 + }, + "Component_[14135560884830586279]": { + "$type": "EditorInspectorComponent", + "Id": 14135560884830586279 + }, + "Component_[16247165675903986673]": { + "$type": "EditorVisibilityComponent", + "Id": 16247165675903986673 + }, + "Component_[18082433625958885247]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 18082433625958885247 + }, + "Component_[6472623349872972660]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 6472623349872972660, + "Parent Entity": "Entity_[1176639161715]", + "Transform Data": { + "Rotate": [ + 0.0, + 0.10000000149011612, + 180.0 + ] + }, + "Cached World Transform": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ], + "Rotation": [ + 0.0008726645028218627, + 0.0, + 0.9999996423721314, + 0.0 + ] + }, + "Cached World Transform Parent": "Entity_[1176639161715]" + }, + "Component_[6495255223970673916]": { + "$type": "AZ::Render::EditorMeshComponent", + "Id": 6495255223970673916, + "Controller": { + "Configuration": { + "ModelAsset": { + "assetId": { + "guid": "{FD340C30-755C-5911-92A3-19A3F7A77931}", + "subId": 281415304 + }, + "assetHint": "objects/shaderball/shaderball_default_1m.azmodel" + } + } + } + }, + "Component_[8056625192494070973]": { + "$type": "SelectionComponent", + "Id": 8056625192494070973 + }, + "Component_[8550141614185782969]": { + "$type": "EditorEntityIconComponent", + "Id": 8550141614185782969 + }, + "Component_[9439770997198325425]": { + "$type": "EditorLockComponent", + "Id": 9439770997198325425 + } + }, + "IsDependencyReady": true + }, + "Entity_[1176639161715]": { + "Id": "Entity_[1176639161715]", + "Name": "Atom Default Environment", + "Components": { + "Component_[10757302973393310045]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 10757302973393310045, + "Parent Entity": "Entity_[1146574390643]", + "Cached World Transform": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Cached World Transform Parent": "Entity_[1146574390643]" + }, + "Component_[14505817420424255464]": { + "$type": "EditorInspectorComponent", + "Id": 14505817420424255464, + "ComponentOrderEntryArray": [ + { + "ComponentId": 10757302973393310045 + } + ] + }, + "Component_[14988041764659020032]": { + "$type": "EditorLockComponent", + "Id": 14988041764659020032 + }, + "Component_[15808690248755038124]": { + "$type": "SelectionComponent", + "Id": 15808690248755038124 + }, + "Component_[15900837685796817138]": { + "$type": "EditorVisibilityComponent", + "Id": 15900837685796817138 + }, + "Component_[3298767348226484884]": { + "$type": "EditorOnlyEntityComponent", + "Id": 3298767348226484884 + }, + "Component_[4076975109609220594]": { + "$type": "EditorPendingCompositionComponent", + "Id": 4076975109609220594 + }, + "Component_[5679760548946028854]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 5679760548946028854 + }, + "Component_[5855590796136709437]": { + "$type": "EditorEntitySortComponent", + "Id": 5855590796136709437, + "ChildEntityOrderEntryArray": [ + { + "EntityId": "Entity_[1155164325235]" + }, + { + "EntityId": "Entity_[1180934129011]", + "SortIndex": 1 + }, + { + "EntityId": "Entity_[1172344194419]", + "SortIndex": 2 + }, + { + "EntityId": "Entity_[1168049227123]", + "SortIndex": 3 + }, + { + "EntityId": "Entity_[1163754259827]", + "SortIndex": 4 + }, + { + "EntityId": "Entity_[1159459292531]", + "SortIndex": 5 + } + ] + }, + "Component_[9277695270015777859]": { + "$type": "EditorEntityIconComponent", + "Id": 9277695270015777859 + } + }, + "IsDependencyReady": true + }, + "Entity_[1180934129011]": { + "Id": "Entity_[1180934129011]", + "Name": "Global Sky", + "Components": { + "Component_[11231930600558681245]": { + "$type": "AZ::Render::EditorHDRiSkyboxComponent", + "Id": 11231930600558681245, + "Controller": { + "Configuration": { + "CubemapAsset": { + "assetId": { + "guid": "{215E47FD-D181-5832-B1AB-91673ABF6399}", + "subId": 1000 + }, + "assetHint": "lightingpresets/highcontrast/goegap_4k_skyboxcm.exr.streamingimage" + } + } + } + }, + "Component_[11980494120202836095]": { + "$type": "SelectionComponent", + "Id": 11980494120202836095 + }, + "Component_[1428633914413949476]": { + "$type": "EditorLockComponent", + "Id": 1428633914413949476 + }, + "Component_[14936200426671614999]": { + "$type": "AZ::Render::EditorImageBasedLightComponent", + "Id": 14936200426671614999, + "Controller": { + "Configuration": { + "diffuseImageAsset": { + "assetId": { + "guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}", + "subId": 3000 + }, + "assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_ibldiffuse.exr.streamingimage" + }, + "specularImageAsset": { + "assetId": { + "guid": "{3FD09945-D0F2-55C8-B9AF-B2FD421FE3BE}", + "subId": 2000 + }, + "assetHint": "lightingpresets/highcontrast/goegap_4k_iblglobalcm_iblspecular.exr.streamingimage" + } + } + } + }, + "Component_[14994774102579326069]": { + "$type": "EditorDisabledCompositionComponent", + "Id": 14994774102579326069 + }, + "Component_[15417479889044493340]": { + "$type": "EditorPendingCompositionComponent", + "Id": 15417479889044493340 + }, + "Component_[15826613364991382688]": { + "$type": "EditorEntitySortComponent", + "Id": 15826613364991382688 + }, + "Component_[1665003113283562343]": { + "$type": "EditorOnlyEntityComponent", + "Id": 1665003113283562343 + }, + "Component_[3704934735944502280]": { + "$type": "EditorEntityIconComponent", + "Id": 3704934735944502280 + }, + "Component_[5698542331457326479]": { + "$type": "EditorVisibilityComponent", + "Id": 5698542331457326479 + }, + "Component_[6644513399057217122]": { + "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent", + "Id": 6644513399057217122, + "Parent Entity": "Entity_[1176639161715]", + "Cached World Transform": { + "Translation": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Cached World Transform Parent": "Entity_[1176639161715]" + }, + "Component_[931091830724002070]": { + "$type": "EditorInspectorComponent", + "Id": 931091830724002070 + } + }, + "IsDependencyReady": true + } + } +} \ No newline at end of file diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index da529d9349..97c3041de6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -14,9 +14,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -222,21 +224,52 @@ namespace AzToolsFramework AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath); m_rootInstance->SetTemplateSourcePath(relativePath); + + bool newLevelFromTemplate = false; + if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) { - // This has not been loaded yet, this is the case of being saved with a different name. - // Create it - m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); - HandleEntitiesAdded({m_rootInstance->m_containerEntity.get()}); + AZStd::string watchFolder; + AZ::Data::AssetInfo assetInfo; + bool sourceInfoFound = false; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult( + sourceInfoFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, DefaultLevelTemplateName, + assetInfo, watchFolder); - AzToolsFramework::Prefab::PrefabDom dom; - bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); - if (!success) + if (sourceInfoFound) { - AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); - return false; + AZStd::string fullPath; + AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath); + + // Get the default prefab and copy the Dom over to the new template being saved + Prefab::TemplateId defaultId = m_loaderInterface->LoadTemplateFromFile(fullPath.c_str()); + Prefab::PrefabDom& dom = m_prefabSystemComponent->FindTemplateDom(defaultId); + + Prefab::PrefabDom levelDefaultDom; + levelDefaultDom.CopyFrom(dom, levelDefaultDom.GetAllocator()); + + Prefab::PrefabDomPath sourcePath("/Source"); + sourcePath.Set(levelDefaultDom, relativePath.c_str()); + + templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(levelDefaultDom)); + newLevelFromTemplate = true; } - templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(dom)); + else + { + // Create an empty level since we couldn't find the default template + m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent()); + HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() }); + + AzToolsFramework::Prefab::PrefabDom dom; + bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom); + if (!success) + { + AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename)); + return false; + } + templateId = m_prefabSystemComponent->AddTemplate(relativePath, std::move(dom)); + } + if (templateId == AzToolsFramework::Prefab::InvalidTemplateId) { AZ_Error("Prefab", false, "Couldn't add new template id '%i' when saving file '%.*s'", templateId, AZ_STRING_ARG(filename)); @@ -253,6 +286,13 @@ namespace AzToolsFramework m_prefabSystemComponent->RemoveTemplate(prevTemplateId); } + // If we have a new level from a template, we need to make sure to propagate the changes here otherwise + // the entities from the new template won't show up + if (newLevelFromTemplate) + { + m_prefabSystemComponent->PropagateTemplateChanges(templateId); + } + AZStd::string out; if (m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out)) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h index 3be9b95df0..606d5f495f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.h @@ -216,5 +216,7 @@ namespace AzToolsFramework Prefab::PrefabLoaderInterface* m_loaderInterface; AzFramework::EntityContextId m_entityContextId; AZ::SerializeContext m_serializeContext; + + static inline constexpr const char* DefaultLevelTemplateName = "Prefabs/Default_Level.prefab"; }; } From 03ec6465b5038a4a875dc419f0d0ea70878cfe06 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Tue, 25 May 2021 18:49:06 -0700 Subject: [PATCH 11/12] Support deserializing non-reflected enums (#815) The serialize context allows users to reflect fields that are enums to a class without reflecting the enum type itself with the EnumBuilder. In this case, the serialize context stores the mapping of the enum's typeid to the underlying type's typeid. When asking for the class data for the enum typeid, the underlying type's class data is returned. This was throwing off the json serializer, which would then see that the type was "unsigned int" instead of an enum, and attempt to load the unsigned int value. The unsigned int deserializer would then complain, because the incoming typeid was the typeid of the enum, and not equal to the typeid of unsigned int. This change adds support for detecting the non-reflected enum, and loading it properly. --- .../Serialization/Json/JsonDeserializer.cpp | 31 +++++++---- .../Tests/Serialization/Json/TestCases.h | 2 +- .../Serialization/Json/TestCases_Classes.cpp | 51 +++++++++++++++++++ .../Serialization/Json/TestCases_Classes.h | 31 +++++++++++ 4 files changed, 105 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index 93d12acba3..9c4641741e 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -10,6 +10,7 @@ * */ +#include "AzCore/RTTI/TypeInfo.h" #include #include #include @@ -61,6 +62,13 @@ namespace AZ if (classData->m_azRtti && classData->m_azRtti->GetGenericTypeId() != typeId) { + if (((classData->m_azRtti->GetTypeTraits() & (AZ::TypeTraits::is_signed | AZ::TypeTraits::is_unsigned)) != AZ::TypeTraits{0}) && + context.GetSerializeContext()->GetUnderlyingTypeId(typeId) == classData->m_typeId) + { + // This value is from an enum, where a field has been reflected using ClassBuilder::Field, but the enum + // type itself has not been reflected using EnumBuilder. Treat it as an enum. + return LoadEnum(object, *classData, value, context); + } serializer = context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId()); if (serializer) { @@ -77,21 +85,18 @@ namespace AZ { return LoadEnum(object, *classData, value, context); } - else if (classData->m_container) + if (classData->m_container) { return context.Report(Tasks::ReadField, Outcomes::Unsupported, "The Json Serializer uses custom serializers to load containers. If this message is encountered " "then a serializer for the target containers is missing, isn't registered or doesn't exist."); } - else if (value.IsObject()) + if (value.IsObject()) { return LoadClass(object, *classData, value, context); } - else - { - return context.Report(Tasks::ReadField, Outcomes::Unsupported, - AZStd::string::format("Reading into targets of type '%s' is not supported.", classData->m_name)); - } + return context.Report(Tasks::ReadField, Outcomes::Unsupported, + AZStd::string::format("Reading into targets of type '%s' is not supported.", classData->m_name)); } JsonSerializationResult::ResultCode JsonDeserializer::LoadToPointer(void* object, const Uuid& typeId, @@ -233,8 +238,16 @@ namespace AZ AZ::TypeId underlyingTypeId = AZ::TypeId::CreateNull(); if (!attributeReader.Read(underlyingTypeId)) { - return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, - "Unable to find underlying type of enum in class data."); + // for non-reflected enums, the passed-in classData already represents the enum's underlying type + if (context.GetSerializeContext()->GetUnderlyingTypeId(classData.m_typeId) == classData.m_typeId) + { + underlyingTypeId = classData.m_typeId; + } + else + { + return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, + "Unable to find underlying type of enum in class data."); + } } const SerializeContext::ClassData* underlyingClassData = context.GetSerializeContext()->FindClassData(underlyingTypeId); diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases.h b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases.h index b01dbe9b0d..ae313632af 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases.h +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases.h @@ -21,7 +21,7 @@ namespace JsonSerializationTests { using JsonSerializationTestCases = ::testing::Types< // Structures - SimpleClass, SimpleInheritence, MultipleInheritence, SimpleNested, SimpleEnumWrapper, + SimpleClass, SimpleInheritence, MultipleInheritence, SimpleNested, SimpleEnumWrapper, NonReflectedEnumWrapper, // Pointers SimpleNullPointer, SimpleAssignedPointer, ComplexAssignedPointer, ComplexNullInheritedPointer, ComplexAssignedDifferentInheritedPointer, ComplexAssignedSameInheritedPointer, diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.cpp index 5be031d70a..6da3120f59 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.cpp @@ -373,6 +373,57 @@ namespace JsonSerializationTests return MakeInstanceWithoutDefaults(AZStd::move(instance), json); } + // NonReflectedEnumWrapper + bool NonReflectedEnumWrapper::Equals(const NonReflectedEnumWrapper& rhs, bool fullReflection) const + { + return !fullReflection || (m_enumClass == rhs.m_enumClass && m_rawEnum== rhs.m_rawEnum); + } + + void NonReflectedEnumWrapper::Reflect(AZStd::unique_ptr& context, bool fullReflection) + { + if (fullReflection) + { + // Note that the enums are not reflected using context->Enum<> + + context->Class() + ->Field("enumClass", &NonReflectedEnumWrapper::m_enumClass) + ->Field("rawEnum", &NonReflectedEnumWrapper::m_rawEnum); + } + } + + InstanceWithSomeDefaults NonReflectedEnumWrapper::GetInstanceWithSomeDefaults() + { + auto instance = AZStd::make_unique(); + instance->m_enumClass = NonReflectedEnumWrapper::SimpleEnumClass::Option2; + + const char* strippedDefaults = R"( + { + "enumClass": 2 + })"; + const char* keptDefaults = R"( + { + "enumClass": 2, + "rawEnum": 0 + })"; + + return MakeInstanceWithSomeDefaults(AZStd::move(instance), + strippedDefaults, keptDefaults); + } + + InstanceWithoutDefaults NonReflectedEnumWrapper::GetInstanceWithoutDefaults() + { + auto instance = AZStd::make_unique(); + instance->m_enumClass = NonReflectedEnumWrapper::SimpleEnumClass::Option2; + instance->m_rawEnum = NonReflectedEnumWrapper::SimpleRawEnum::RawOption1; + + const char* json = R"( + { + "enumClass": 2, + "rawEnum": 1 + })"; + return MakeInstanceWithoutDefaults(AZStd::move(instance), json); + } + // TemplatedClass bool TemplatedClass::Equals(const TemplatedClass& rhs, bool fullReflection) const diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.h b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.h index db5db23fba..1830ca9e6f 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.h +++ b/Code/Framework/AzCore/Tests/Serialization/Json/TestCases_Classes.h @@ -134,6 +134,35 @@ namespace JsonSerializationTests SimpleRawEnum m_rawEnum{}; }; + struct NonReflectedEnumWrapper + { + enum class SimpleEnumClass + { + Option1 = 1, + Option2, + }; + enum SimpleRawEnum + { + RawOption1 = 1, + RawOption2, + }; + AZ_CLASS_ALLOCATOR(NonReflectedEnumWrapper, AZ::SystemAllocator, 0); + AZ_RTTI(NonReflectedEnumWrapper, "{A80D5B6B-2FD1-46E9-A7A9-44C5E2650526}"); + + static constexpr bool SupportsPartialDefaults = true; + + NonReflectedEnumWrapper() = default; + virtual ~NonReflectedEnumWrapper() = default; + + bool Equals(const NonReflectedEnumWrapper& rhs, bool fullReflection) const; + static void Reflect(AZStd::unique_ptr& context, bool fullReflection); + static InstanceWithSomeDefaults GetInstanceWithSomeDefaults(); + static InstanceWithoutDefaults GetInstanceWithoutDefaults(); + + SimpleEnumClass m_enumClass{}; + SimpleRawEnum m_rawEnum{}; + }; + template struct TemplatedClass { @@ -158,5 +187,7 @@ namespace AZ { AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::SimpleEnumWrapper::SimpleEnumClass, "{AF6F1964-5B20-4689-BF23-F36B9C9AAE6A}"); AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::SimpleEnumWrapper::SimpleRawEnum, "{EB24207F-B48F-4D8B-940D-3CD06A371739}"); + AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::NonReflectedEnumWrapper::SimpleEnumClass, "{E80E4A41-B29E-4B7C-B630-3B599172C837}"); + AZ_TYPE_INFO_SPECIALIZE(JsonSerializationTests::NonReflectedEnumWrapper::SimpleRawEnum, "{C42AF28D-4F84-4540-972A-5B6EEFAB13FF}"); AZ_TYPE_INFO_TEMPLATE(JsonSerializationTests::TemplatedClass, "{CA4ADF74-66E7-4D16-B4AC-F71278C60EC7}", AZ_TYPE_INFO_TYPENAME); } From 29163fba1a79c2e4e027937a5dd0dce195bc5018 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Tue, 25 May 2021 18:51:37 -0700 Subject: [PATCH 12/12] Replace call to Cry renderer to get viewport height (#939) --- Gems/LyShine/Code/Source/UiTextInputComponent.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp index ca0d3fab02..6cfa2c911b 100644 --- a/Gems/LyShine/Code/Source/UiTextInputComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextInputComponent.cpp @@ -1450,13 +1450,17 @@ void UiTextInputComponent::CheckStartTextInput() EBUS_EVENT_ID_RESULT(textString, m_textEntity, UiTextBus, GetText); options.m_initialText = Utf8SubString(textString, m_textCursorPos, m_textSelectionStartPos); + AZ::EntityId canvasEntityId; + EBUS_EVENT_ID_RESULT(canvasEntityId, GetEntityId(), UiElementBus, GetCanvasEntityId); + + // Calculate height available for virtual keyboard. In game mode, canvas size is the same as viewport size + AZ::Vector2 canvasSize; + EBUS_EVENT_ID_RESULT(canvasSize, canvasEntityId, UiCanvasBus, GetCanvasSize); UiTransformInterface::RectPoints rectPoints; EBUS_EVENT_ID(GetEntityId(), UiTransformBus, GetViewportSpacePoints, rectPoints); const AZ::Vector2 bottomRight = rectPoints.GetAxisAlignedBottomRight(); - options.m_normalizedMinY = bottomRight.GetY() / static_cast(gEnv->pRenderer->GetHeight()); + options.m_normalizedMinY = (canvasSize.GetY() > 0.0f) ? bottomRight.GetY() / canvasSize.GetY() : 0.0f; - AZ::EntityId canvasEntityId; - EBUS_EVENT_ID_RESULT(canvasEntityId, GetEntityId(), UiElementBus, GetCanvasEntityId); EBUS_EVENT_ID_RESULT(options.m_localUserId, canvasEntityId, UiCanvasBus, GetLocalUserIdInputFilter); AzFramework::InputTextEntryRequestBus::Broadcast(&AzFramework::InputTextEntryRequests::TextEntryStart, options);