diff --git a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl index 454d998321..1016027966 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl +++ b/Code/Framework/AzCore/AzCore/Serialization/EditContextConstants.inl @@ -53,9 +53,10 @@ namespace AZ //! RemoveableByUser : A bool which determines if the component can be removed by the user. //! Setting this to false prevents the user from removing this component. Default behavior is removeable by user. const static AZ::Crc32 RemoveableByUser = AZ_CRC("RemoveableByUser", 0x32c7fd50); - //! A bool which determines if the component can be dragged to change where it appears in the entity sort order. - //! Setting this to false prevents the user from dragging the component. Default behaviour is draggable by user. - const static AZ::Crc32 DraggableByUser = AZ_CRC_CE("DraggableByUser"); + //! An int which, if specified, causes a component to be forced to a particular position in the sorted list of + //! components on an entity, and prevents dragging or moving operations which would affect that position. + const static AZ::Crc32 FixedComponentListIndex = AZ_CRC_CE("FixedComponentListIndex"); + const static AZ::Crc32 AppearsInAddComponentMenu = AZ_CRC("AppearsInAddComponentMenu", 0x53790e31); const static AZ::Crc32 ForceAutoExpand = AZ_CRC("ForceAutoExpand", 0x1a5c79d2); // Ignores expansion state set by user, enforces expansion. const static AZ::Crc32 AutoExpand = AZ_CRC("AutoExpand", 0x306ff5c0); // Expands automatically unless user changes expansion state. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp index 67f8212f5e..989398f196 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.cpp @@ -39,8 +39,8 @@ namespace AzToolsFramework editContext->Class("Non-uniform Scale", "Non-uniform scale for this entity only (does not propagate through hierarchy)") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::FixedComponentListIndex, 1) ->Attribute(AZ::Edit::Attributes::RemoveableByUser, true) - ->Attribute(AZ::Edit::Attributes::DraggableByUser, false) ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/NonUniformScale.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/NonUniformScale.svg") ->DataElement( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp index bca7dc08e2..f8d02b6581 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/TransformComponent.cpp @@ -1203,8 +1203,7 @@ namespace AzToolsFramework AZ::Component* TransformComponent::FindPresentOrPendingComponent(AZ::Uuid componentUuid) { // first check if the component is present and valid - AZ::Component* foundComponent = GetEntity()->FindComponent(componentUuid); - if (foundComponent) + if (AZ::Component* foundComponent = GetEntity()->FindComponent(componentUuid)) { return foundComponent; } @@ -1241,18 +1240,15 @@ namespace AzToolsFramework const AZStd::vector entityList = { GetEntityId() }; const AZ::ComponentTypeList componentsToAdd = { EditorNonUniformScaleComponent::TYPEINFO_Uuid() }; - AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome outcome; - AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(outcome, + AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome addComponentsOutcome; + AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(addComponentsOutcome, &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, entityList, componentsToAdd); - AZ::ComponentId nonUniformScaleComponentId = AZ::InvalidComponentId; - auto nonUniformScaleComponent = FindPresentOrPendingComponent(EditorNonUniformScaleComponent::RTTI_Type()); - if (nonUniformScaleComponent) - { - nonUniformScaleComponentId = nonUniformScaleComponent->GetId(); - } + const auto nonUniformScaleComponent = FindPresentOrPendingComponent(EditorNonUniformScaleComponent::RTTI_Type()); + AZ::ComponentId nonUniformScaleComponentId = + nonUniformScaleComponent ? nonUniformScaleComponent->GetId() : AZ::InvalidComponentId; - if (!outcome.IsSuccess() || nonUniformScaleComponentId == AZ::InvalidComponentId) + if (!addComponentsOutcome.IsSuccess() || !nonUniformScaleComponent) { AZ_Warning("Transform component", false, "Failed to add non-uniform scale component."); return AZ::Edit::PropertyRefreshLevels::None; @@ -1293,6 +1289,7 @@ namespace AzToolsFramework { ptrEdit->Class("Transform", "Controls the placement of the entity in the world in 3d")-> ClassElement(AZ::Edit::ClassElements::EditorData, "")-> + Attribute(AZ::Edit::Attributes::FixedComponentListIndex, 0)-> Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Transform.svg")-> Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Transform.png")-> Attribute(AZ::Edit::Attributes::AutoExpand, true)-> diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index 51d4ed5026..c3639b872e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -1045,28 +1045,23 @@ namespace AzToolsFramework sortedComponents.end(), [=](const OrderedSortComponentEntry& component1, const OrderedSortComponentEntry& component2) { - // Transform component must be first, always - // If component 1 is a transform component, it is sorted earlier - if (component1.m_component->RTTI_IsTypeOf(AZ::EditorTransformComponentTypeId)) + AZStd::optional fixedComponentListIndex1 = GetFixedComponentListIndex(component1.m_component); + AZStd::optional fixedComponentListIndex2 = GetFixedComponentListIndex(component2.m_component); + + // If both components have fixed list indices, sort based on those indices + if (fixedComponentListIndex1.has_value() && fixedComponentListIndex2.has_value()) + { + return fixedComponentListIndex1.value() < fixedComponentListIndex2.value(); + } + + // If component 1 has a fixed list index, sort it first + if (fixedComponentListIndex1.has_value()) { return true; } - // If component 2 is a transform component, component 1 is never sorted earlier - if (component2.m_component->RTTI_IsTypeOf(AZ::EditorTransformComponentTypeId)) - { - return false; - } - - // If component 1 is a non-uniform scale component, it is sorted earlier (it should appear immediately after transform) - if (component1.m_component->RTTI_IsTypeOf(AzToolsFramework::Components::EditorNonUniformScaleComponent::RTTI_Type())) - { - return true; - } - - // If component 2 is a non-uniform scale component, component 1 is never sorted earlier - // (transform will already dominate in the check above) - if (component2.m_component->RTTI_IsTypeOf(AzToolsFramework::Components::EditorNonUniformScaleComponent::RTTI_Type())) + // If component 2 has a fixed list index, component 1 should not be sorted before it + if (fixedComponentListIndex2.has_value()) { return false; } @@ -1182,32 +1177,34 @@ namespace AzToolsFramework return true; } - bool EntityPropertyEditor::IsComponentDraggable(const AZ::Component* component) + AZStd::optional EntityPropertyEditor::GetFixedComponentListIndex(const AZ::Component* component) { auto componentClassData = component ? GetComponentClassData(component) : nullptr; if (componentClassData && componentClassData->m_editData) { if (auto editorDataElement = componentClassData->m_editData->FindElementData(AZ::Edit::ClassElements::EditorData)) { - if (auto attribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::DraggableByUser)) + if (auto attribute = editorDataElement->FindAttribute(AZ::Edit::Attributes::FixedComponentListIndex)) { - if (auto attributeData = azdynamic_cast*>(attribute)) + if (auto attributeData = azdynamic_cast*>(attribute)) { - if (!attributeData->Get(nullptr)) - { - return false; - } + return { attributeData->Get(nullptr) }; } } } } + return {}; + } - return true; + bool EntityPropertyEditor::IsComponentDraggable(const AZ::Component* component) + { + return !GetFixedComponentListIndex(component).has_value(); } bool EntityPropertyEditor::AreComponentsDraggable(const AZ::Entity::ComponentArrayType& components) const { - return AZStd::all_of(components.begin(), components.end(), [](AZ::Component* component) {return IsComponentDraggable(component); }); + return AZStd::all_of( + components.begin(), components.end(), [](AZ::Component* component) { return IsComponentDraggable(component); }); } bool EntityPropertyEditor::AreComponentsCopyable(const AZ::Entity::ComponentArrayType& components) const diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index 2fb1c7e03a..9cd380ae06 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -238,6 +238,7 @@ namespace AzToolsFramework static bool DoesComponentPassFilter(const AZ::Component* component, const ComponentFilter& filter); static bool IsComponentRemovable(const AZ::Component* component); bool AreComponentsRemovable(const AZ::Entity::ComponentArrayType& components) const; + static AZStd::optional GetFixedComponentListIndex(const AZ::Component* component); static bool IsComponentDraggable(const AZ::Component* component); bool AreComponentsDraggable(const AZ::Entity::ComponentArrayType& components) const; bool AreComponentsCopyable(const AZ::Entity::ComponentArrayType& components) const;