/* * 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. * */ #include #include #include #include #include #include #include #include namespace NvCloth { namespace Internal { extern const char* const StatusMessageSelectNode = "Select a node"; extern const char* const StatusMessageNoAsset = ""; extern const char* const StatusMessageNoClothNodes = ""; const char* const AttributeSuffixMetersUnit = " m"; } void EditorClothComponent::Reflect(AZ::ReflectContext* context) { if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() ->Field("Configuration", &EditorClothComponent::m_config) ->Version(0) ; if (auto editContext = serializeContext->GetEditContext()) { editContext->Class( "Cloth", "The mesh node behaves like a piece of cloth.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "PhysX") ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Cloth.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Cloth.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-cloth.html") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->UIElement(AZ::Edit::UIHandlers::CheckBox, "Simulate in editor", "Enables cloth simulation in editor when set.") ->Attribute(AZ::Edit::Attributes::CheckboxDefaultValue, &EditorClothComponent::IsSimulatedInEditor) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorClothComponent::OnSimulatedInEditorToggled) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorClothComponent::m_config) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorClothComponent::OnConfigurationChanged) ; editContext->Class("Cloth Configuration", "Configuration for cloth simulation.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "PhysX") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) // Mesh Node ->DataElement(Editor::MeshNodeSelector, &ClothConfiguration::m_meshNode, "Mesh node", "List of mesh nodes with cloth simulation data. These are the nodes selected inside Cloth Modifiers in FBX Editor Settings.") ->Attribute(AZ::Edit::UIHandlers::EntityId, &ClothConfiguration::GetEntityId) ->Attribute(AZ::Edit::Attributes::StringList, &ClothConfiguration::PopulateMeshNodeList) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) // Mass and Gravity ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_mass, "Mass", "Mass scale applied to all particles.") ->Attribute(AZ::Edit::Attributes::Min, 0.1f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_useCustomGravity, "Custom Gravity", "When enabled it allows to set a custom gravity value for this cloth.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_customGravity, "Gravity", "Gravity applied to particles.") ->Attribute(AZ::Edit::Attributes::ReadOnly, &ClothConfiguration::IsUsingWorldBusGravity) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_gravityScale, "Gravity Scale", "Use this parameter to scale the gravity applied to particles.") // Global stiffness frequency ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_stiffnessFrequency, "Stiffness frequency", "Stiffness exponent per second applied to damping, damping dragging, wind dragging, wind lifting, self collision stiffness, fabric stiffness, fabric compression, fabric stretch and tether constraint stiffness.") ->Attribute(AZ::Edit::Attributes::Min, 0.01f) // Motion Constraints ->ClassElement(AZ::Edit::ClassElements::Group, "Motion constraints") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_motionConstraintsMaxDistance, "Max Distance", "Maximum distance for motion constraints to limit particles movement during simulation.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Suffix, Internal::AttributeSuffixMetersUnit) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_motionConstraintsScale, "Scale", "Scale value applied to all motion constraints.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_motionConstraintsBias, "Bias", "Bias value added to all motion constraints.") ->Attribute(AZ::Edit::Attributes::Suffix, Internal::AttributeSuffixMetersUnit) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_motionConstraintsStiffness, "Stiffness", "Stiffness for motion constraints.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) // Backstop ->ClassElement(AZ::Edit::ClassElements::Group, "Backstop") ->Attribute(AZ::Edit::Attributes::Visibility, &ClothConfiguration::HasBackstopData) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_backstopRadius, "Radius", "Maximum radius that will prevent the associated cloth particle from moving into that area.") ->Attribute(AZ::Edit::Attributes::Min, 0.001f) ->Attribute(AZ::Edit::Attributes::Suffix, Internal::AttributeSuffixMetersUnit) ->Attribute(AZ::Edit::Attributes::Visibility, &ClothConfiguration::HasBackstopData) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_backstopBackOffset, "Back offset", "Maximum offset for backstop spheres behind the cloth.") ->Attribute(AZ::Edit::Attributes::Suffix, Internal::AttributeSuffixMetersUnit) ->Attribute(AZ::Edit::Attributes::Visibility, &ClothConfiguration::HasBackstopData) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_backstopFrontOffset, "Front offset", "Maximum offset for backstop spheres in front of the cloth.") ->Attribute(AZ::Edit::Attributes::Suffix, Internal::AttributeSuffixMetersUnit) ->Attribute(AZ::Edit::Attributes::Visibility, &ClothConfiguration::HasBackstopData) // Damping ->ClassElement(AZ::Edit::ClassElements::Group, "Damping") ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_damping, "Damping", "Damping of particle velocity.\n" "0: Velocity is unaffected\n" "1: Velocity is zeroed") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_linearDrag, "Linear drag", "Portion of velocity applied to particles.\n" "0: Particles is unaffected\n" "1: Damped global particle velocity") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_angularDrag, "Angular drag", "Portion of angular velocity applied to turning particles.\n" "0: Particles is unaffected\n" "1: Damped global particle angular velocity") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) // Inertia ->ClassElement(AZ::Edit::ClassElements::Group, "Inertia") ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_linearInteria, "Linear", "Portion of acceleration applied to particles.\n" "0: Particles are unaffected\n" "1: Physically correct") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_angularInteria, "Angular", "Portion of angular acceleration applied to turning particles.\n" "0: Particles are unaffected\n" "1: Physically correct") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_centrifugalInertia, "Centrifugal", "Portion of angular velocity applied to turning particles.\n" "0: Particles are unaffected\n" "1: Physically correct") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) // Wind ->ClassElement(AZ::Edit::ClassElements::Group, "Wind") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_useCustomWindVelocity, "Enable local wind velocity", "When enabled it allows to set a custom wind velocity value for this cloth, otherwise using wind velocity from Physics::WindBus.\n" "Wind is disabled when both air coefficients are zero.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_windVelocity, "Local velocity", "Wind in global coordinates acting on cloth's triangles. Disabled when both air coefficients are zero.\n" "NOTE: A combination of high values in wind properties can cause unstable results.") ->Attribute(AZ::Edit::Attributes::Min, -50.0f) ->Attribute(AZ::Edit::Attributes::Max, 50.0f) ->Attribute(AZ::Edit::Attributes::ReadOnly, &ClothConfiguration::IsUsingWindBus ) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_airDragCoefficient, "Air drag coefficient", "Amount of air dragging.\n" "NOTE: A combination of high values in wind properties can cause unstable results.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_airLiftCoefficient, "Air lift coefficient", "Amount of air lifting.\n" "NOTE: A combination of high values in wind properties can cause unstable results.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_fluidDensity, "Air Density", "Density of air used for air drag and lift calculations.\n" "NOTE: A combination of high values in wind properties can cause unstable results.") ->Attribute(AZ::Edit::Attributes::Min, 0.01f) // Collision ->ClassElement(AZ::Edit::ClassElements::Group, "Collision") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_collisionFriction, "Friction", "Amount of friction with colliders.\n" "0: No friction\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_collisionMassScale, "Mass scale", "Controls how quickly mass is increased during collisions.\n" "0: No mass scaling\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_continuousCollisionDetection, "Continuous detection", "Continuous collision detection improves collision by computing time of impact between cloth particles and colliders." "The increase in quality comes with a cost in performance, it's recommended to use only when required.") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_collisionAffectsStaticParticles, "Affects static particles", "When enabled colliders will move static particles (inverse mass 0).") // Self collision ->ClassElement(AZ::Edit::ClassElements::Group, "Self collision") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_selfCollisionDistance, "Distance", "Meters that particles need to be separated from each other.\n" "0: No self collision\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_selfCollisionStiffness, "Stiffness", "Stiffness for the self collision constraints.\n" "0: No self collision\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) // Fabric stiffness ->ClassElement(AZ::Edit::ClassElements::Group, "Fabric stiffness") ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_horizontalStiffness, "Horizontal", "Stiffness value for horizontal constraints.\n" "0: no horizontal constraints\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_horizontalStiffnessMultiplier, "Horizontal multiplier", "Scale value for horizontal fabric compression and stretch limits.\n" "0: No horizontal compression and stretch limits applied\n" "1: Fully apply horizontal compression and stretch limits\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_verticalStiffness, "Vertical", "Stiffness value for vertical constraints.\n" "0: no vertical constraints\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_verticalStiffnessMultiplier, "Vertical multiplier", "Scale value for vertical fabric compression and stretch limits.\n" "0: No vertical compression and stretch limits applied\n" "1: Fully apply vertical compression and stretch limits\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_bendingStiffness, "Bending", "Stiffness value for bending constraints.\n" "0: no bending constraints\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_bendingStiffnessMultiplier, "Bending multiplier", "Scale value for bending fabric compression and stretch limits.\n" "0: No bending compression and stretch limits applied\n" "1: Fully apply bending compression and stretch limits\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_shearingStiffness, "Shearing", "Stiffness value for shearing constraints.\n" "0: no shearing constraints\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_shearingStiffnessMultiplier, "Shearing multiplier", "Scale value for shearing fabric compression and stretch limits.\n" "0: No shearing compression and stretch limits applied\n" "1: Fully apply shearing compression and stretch limits\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) // Fabric compression ->ClassElement(AZ::Edit::ClassElements::Group, "Fabric compression") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_horizontalCompressionLimit, "Horizontal limit", "Compression limit for horizontal constraints. It's affected by fabric horizontal stiffness multiplier.\n" "0: No compression\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_verticalCompressionLimit, "Vertical limit", "Compression limit for vertical constraints. It's affected by fabric vertical stiffness multiplier.\n" "0: No compression\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_bendingCompressionLimit, "Bending limit", "Compression limit for bending constraints. It's affected by fabric bending stiffness multiplier.\n" "0: No compression\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_shearingCompressionLimit, "Shearing limit", "Compression limit for shearing constraints. It's affected by fabric shearing stiffness multiplier.\n" "0: No compression\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) // Fabric stretch ->ClassElement(AZ::Edit::ClassElements::Group, "Fabric stretch") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_horizontalStretchLimit, "Horizontal limit", "Stretch limit for horizontal constraints. It's affected by fabric horizontal stiffness multiplier." "Reduce stiffness of tether constraints (or increase its scale) to allow cloth to stretch.\n" "0: No stretching\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_verticalStretchLimit, "Vertical limit", "Stretch limit for vertical constraints. It's affected by fabric vertical stiffness multiplier." "Reduce stiffness of tether constraints (or increase its scale) to allow cloth to stretch.\n" "0: No stretching\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_bendingStretchLimit, "Bending limit", "Stretch limit for bending constraints. It's affected by fabric bending stiffness multiplier." "Reduce stiffness of tether constraints (or increase its scale) to allow cloth to stretch.\n" "0: No stretching\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_shearingStretchLimit, "Shearing limit", "Stretch limit for shearing constraints. It's affected by fabric shearing stiffness multiplier." "Reduce stiffness of tether constraints (or increase its scale) to allow cloth to stretch.\n" "0: No stretching\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) // Tether constraints ->ClassElement(AZ::Edit::ClassElements::Group, "Tether constraints") ->DataElement(AZ::Edit::UIHandlers::Slider, &ClothConfiguration::m_tetherConstraintStiffness, "Stiffness", "Stiffness for tether constraints. Tether constraints are generated when the inverse mass data of the cloth (selected in the cloth modifier) has static particles.\n" "0: No tether constraints applied\n" "1: Makes the constraints behave springy\n") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1.0f) ->Attribute(AZ::Edit::Attributes::Step, 0.0001f) ->Attribute(AZ::Edit::Attributes::Decimals, 6) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_tetherConstraintScale, "Scale", "Tether constraint scale") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) // Quality ->ClassElement(AZ::Edit::ClassElements::Group, "Quality") ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_solverFrequency, "Solver frequency", "Target solver iterations per second. At least 1 iteration per frame will be solved regardless of the value set.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_accelerationFilterIterations, "Acceleration filter Iterations", "Number of iterations to average delta time factor used for gravity and external acceleration.") ->Attribute(AZ::Edit::Attributes::Min, 1) ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_removeStaticTriangles, "Remove static triangles", "Removing static triangles improves performance by not taking into account triangles whose particles are all static.\n" "The removed static particles will not be present for collision or self collision during simulation.") ; } } } EditorClothComponent::EditorClothComponent() { m_meshNodeList = { {Internal::StatusMessageNoAsset} }; m_config.m_populateMeshNodeListCallback = [this]() { return m_meshNodeList; }; m_config.m_hasBackstopDataCallback = [this]() { auto meshNodeIt = m_meshNodesWithBackstopData.find(m_config.m_meshNode); return meshNodeIt != m_meshNodesWithBackstopData.end(); }; m_config.m_getEntityIdCallback = [this]() { return GetEntityId(); }; } EditorClothComponent::~EditorClothComponent() = default; void EditorClothComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC("ClothMeshService", 0x6ffcbca5)); } void EditorClothComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { required.push_back(AZ_CRC("MeshService", 0x71d8a455)); } const MeshNodeList& EditorClothComponent::GetMeshNodeList() const { return m_meshNodeList; } const AZStd::unordered_set& EditorClothComponent::GetMeshNodesWithBackstopData() const { return m_meshNodesWithBackstopData; } void EditorClothComponent::BuildGameEntity(AZ::Entity* gameEntity) { gameEntity->CreateComponent(m_config); } void EditorClothComponent::Activate() { AzToolsFramework::Components::EditorComponentBase::Activate(); LmbrCentral::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); } void EditorClothComponent::Deactivate() { LmbrCentral::MeshComponentNotificationBus::Handler::BusDisconnect(); AzToolsFramework::Components::EditorComponentBase::Deactivate(); m_clothComponentMesh.reset(); } void EditorClothComponent::OnMeshCreated(const AZ::Data::Asset& asset) { if (!asset.IsReady()) { return; } m_meshNodeList.clear(); m_meshNodesWithBackstopData.clear(); AZStd::unique_ptr assetHelper = AssetHelper::CreateAssetHelper(GetEntityId()); if (assetHelper) { // Gather cloth mesh node list assetHelper->GatherClothMeshNodes(m_meshNodeList); for (const auto& meshNode : m_meshNodeList) { if (ContainsBackstopData(assetHelper.get(), meshNode)) { m_meshNodesWithBackstopData.insert(meshNode); } } } if (m_meshNodeList.empty()) { m_meshNodeList.emplace_back(Internal::StatusMessageNoClothNodes); m_config.m_meshNode = Internal::StatusMessageNoClothNodes; } else { bool foundNode = AZStd::find(m_meshNodeList.cbegin(), m_meshNodeList.cend(), m_config.m_meshNode) != m_meshNodeList.cend(); if (!foundNode && !m_previousMeshNode.empty()) { // Check the if the mesh node previously selected is still part of the mesh list // to keep using it and avoid the user to select it again in the combo box. foundNode = AZStd::find(m_meshNodeList.cbegin(), m_meshNodeList.cend(), m_previousMeshNode) != m_meshNodeList.cend(); if (foundNode) { m_config.m_meshNode = m_previousMeshNode; } } // If the mesh node is not in the list then add and use an option // that tells the user to select the node. if (!foundNode) { m_meshNodeList.insert(m_meshNodeList.begin(), Internal::StatusMessageSelectNode); m_config.m_meshNode = Internal::StatusMessageSelectNode; } } m_previousMeshNode = ""; if (m_simulateInEditor) { m_clothComponentMesh = AZStd::make_unique(GetEntityId(), m_config); } // Refresh UI AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } void EditorClothComponent::OnMeshDestroyed() { m_previousMeshNode = m_config.m_meshNode; m_meshNodeList = { {Internal::StatusMessageNoAsset} }; m_config.m_meshNode = Internal::StatusMessageNoAsset; m_clothComponentMesh.reset(); m_meshNodesWithBackstopData.clear(); // Refresh UI AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } bool EditorClothComponent::IsSimulatedInEditor() const { return m_simulateInEditor; } AZ::u32 EditorClothComponent::OnSimulatedInEditorToggled() { m_clothComponentMesh.reset(); m_simulateInEditor = !m_simulateInEditor; if (m_simulateInEditor) { m_clothComponentMesh = AZStd::make_unique(GetEntityId(), m_config); } else { // Force MeshComponent to reload current mesh asset in order to restore original mesh AZ::Data::Asset meshAsset; LmbrCentral::MeshComponentRequestBus::EventResult(meshAsset, GetEntityId(), &LmbrCentral::MeshComponentRequests::GetMeshAsset); LmbrCentral::MeshComponentRequestBus::Event(GetEntityId(), &LmbrCentral::MeshComponentRequests::SetMeshAsset, meshAsset.GetId()); } return AZ::Edit::PropertyRefreshLevels::None; } void EditorClothComponent::OnConfigurationChanged() { if (m_clothComponentMesh) { m_clothComponentMesh->UpdateConfiguration(GetEntityId(), m_config); } } bool EditorClothComponent::ContainsBackstopData(AssetHelper* assetHelper, const AZStd::string& meshNode) const { if (!assetHelper) { return false; } // Obtain cloth mesh info MeshNodeInfo meshNodeInfo; MeshClothInfo meshClothInfo; bool clothInfoObtained = assetHelper->ObtainClothMeshNodeInfo(meshNode, meshNodeInfo, meshClothInfo); if (!clothInfoObtained) { return false; } return AZStd::any_of( meshClothInfo.m_backstopData.cbegin(), meshClothInfo.m_backstopData.cend(), [](const AZ::Vector2& backstop) { const float backstopRadius = backstop.GetY(); return backstopRadius > 0.0f; }); } } // namespace NvCloth