123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/Serialization/EditContext.h>
- #include <AzToolsFramework/API/ToolsApplicationAPI.h>
- #include <Editor/PropertyTypes.h>
- #include <Components/EditorClothComponent.h>
- #include <Components/ClothComponent.h>
- #include <Components/ClothComponentMesh/ClothComponentMesh.h>
- #include <Atom/RPI.Reflect/Model/ModelAsset.h>
- #include <Utils/AssetHelper.h>
- namespace NvCloth
- {
- namespace Internal
- {
- extern const char* const StatusMessageSelectNode = "Select a node";
- extern const char* const StatusMessageNoAsset = "<No asset>";
- extern const char* const StatusMessageNoClothNodes = "<No cloth modifiers>";
- const char* const AttributeSuffixMetersUnit = " m";
- }
- void EditorClothComponent::Reflect(AZ::ReflectContext* context)
- {
- if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<EditorClothComponent, AzToolsFramework::Components::EditorComponentBase>()
- ->Field("Configuration", &EditorClothComponent::m_config)
- ->Version(0)
- ;
- if (auto editContext = serializeContext->GetEditContext())
- {
- editContext->Class<EditorClothComponent>(
- "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, "Icons/Components/Cloth.svg")
- ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Cloth.svg")
- ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
- ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/physx/cloth/")
- ->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<ClothConfiguration>("Cloth Configuration", "Configuration for cloth simulation.")
- ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::Category, "PhysX")
- ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
- ->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 Scene Settings.")
- ->Attribute(AZ::Edit::UIHandlers::EntityId, &ClothConfiguration::m_entityId)
- ->Attribute(AZ::Edit::Attributes::StringList, &ClothConfiguration::m_meshNodeList)
- ->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::m_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::m_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::m_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::m_hasBackstopData)
- // Damping
- ->ClassElement(AZ::Edit::ClassElements::Group, "Damping")
- ->DataElement(AZ::Edit::UIHandlers::Default, &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::Default, &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::Default, &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::Default, &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::Default, &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::Default, &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.")
- ->DataElement(AZ::Edit::UIHandlers::Default, &ClothConfiguration::m_updateNormalsOfStaticParticles, "Update normals of static particles",
- "When enabled the normals of static particles will be updated according with the movement of the simulated mesh.\n"
- "When disabled the static particles will keep the same normals as the original mesh.")
- ;
- }
- }
- }
- EditorClothComponent::EditorClothComponent()
- {
- m_meshNodeList = { {Internal::StatusMessageNoAsset} };
- m_config.m_meshNodeList = m_meshNodeList;
- }
- EditorClothComponent::~EditorClothComponent() = default;
- void EditorClothComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
- {
- provided.push_back(AZ_CRC_CE("ClothMeshService"));
- }
- void EditorClothComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
- {
- required.push_back(AZ_CRC_CE("MeshService"));
- }
- void EditorClothComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
- {
- incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
- }
- const MeshNodeList& EditorClothComponent::GetMeshNodeList() const
- {
- return m_meshNodeList;
- }
- const AZStd::unordered_set<AZStd::string>& EditorClothComponent::GetMeshNodesWithBackstopData() const
- {
- return m_meshNodesWithBackstopData;
- }
- void EditorClothComponent::BuildGameEntity(AZ::Entity* gameEntity)
- {
- gameEntity->CreateComponent<ClothComponent>(m_config);
- }
- void EditorClothComponent::Activate()
- {
- AzToolsFramework::Components::EditorComponentBase::Activate();
- AZ::Render::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId());
- m_config.m_entityId = GetEntityId();
- }
- void EditorClothComponent::Deactivate()
- {
- AZ::Render::MeshComponentNotificationBus::Handler::BusDisconnect();
- AzToolsFramework::Components::EditorComponentBase::Deactivate();
- OnModelPreDestroy();
- }
- void EditorClothComponent::OnModelReady(
- const AZ::Data::Asset<AZ::RPI::ModelAsset>& asset,
- [[maybe_unused]] const AZ::Data::Instance<AZ::RPI::Model>& model)
- {
- if (!asset.IsReady())
- {
- return;
- }
- m_meshNodeList.clear();
- m_meshNodesWithBackstopData.clear();
- AZStd::unique_ptr<AssetHelper> 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_lastKnownMeshNode.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_lastKnownMeshNode) != m_meshNodeList.cend();
- if (foundNode)
- {
- m_config.m_meshNode = m_lastKnownMeshNode;
- }
- }
- // 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_lastKnownMeshNode = "";
- if (m_simulateInEditor)
- {
- m_clothComponentMesh = AZStd::make_unique<ClothComponentMesh>(GetEntityId(), m_config);
- }
- UpdateConfigMeshNodeData();
- // Refresh UI
- InvalidatePropertyDisplay(AzToolsFramework::Refresh_EntireTree);
- }
- void EditorClothComponent::OnModelPreDestroy()
- {
- if (m_config.m_meshNode != Internal::StatusMessageSelectNode &&
- m_config.m_meshNode != Internal::StatusMessageNoAsset &&
- m_config.m_meshNode != Internal::StatusMessageNoClothNodes)
- {
- m_lastKnownMeshNode = m_config.m_meshNode;
- }
- m_meshNodeList = { {Internal::StatusMessageNoAsset} };
- m_config.m_meshNode = Internal::StatusMessageNoAsset;
- m_clothComponentMesh.reset();
- m_meshNodesWithBackstopData.clear();
- UpdateConfigMeshNodeData();
- // Refresh UI
- InvalidatePropertyDisplay(AzToolsFramework::Refresh_EntireTree);
- }
- bool EditorClothComponent::IsSimulatedInEditor() const
- {
- return m_simulateInEditor;
- }
- AZ::u32 EditorClothComponent::OnSimulatedInEditorToggled()
- {
- m_simulateInEditor = !m_simulateInEditor;
- m_clothComponentMesh = AZStd::make_unique<ClothComponentMesh>(GetEntityId(), m_config);
- if (!m_simulateInEditor)
- {
- // Since the instance was just created this will restore the model
- // to its original position before cloth simulation.
- m_clothComponentMesh->CopyRenderDataToModel();
- m_clothComponentMesh.reset();
- }
- 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;
- });
- }
- void EditorClothComponent::UpdateConfigMeshNodeData()
- {
- // Update our config mesh node data based on changes to the associated Mesh component
- // This gets called after updating our internal data on OnModelReady and OnModelPreDestroy
- m_config.m_meshNodeList = m_meshNodeList;
- auto meshNodeIt = m_meshNodesWithBackstopData.find(m_config.m_meshNode);
- m_config.m_hasBackstopData = (meshNodeIt != m_meshNodesWithBackstopData.end());
- }
- } // namespace NvCloth
|