physics: capsule/cylinder/compound collider shapes
- ColliderType + Capsule/Cylinder/Compound; CompoundChild list (Box/ Sphere/Capsule, local pos/quat, non-recursive) - CreateBody: CapsuleShape/CylinderShape (ctor param orders differ) + StaticCompoundShape; empty/failed compound falls back to Box - BodyRecord caches radius/halfHeight/compound; SyncScene rebuilds on change (per-collider param extraction) - Inspector: combo entries + shape params + compound child list editor - Serialization: new fields with as<T> fallback, compound seq round-trip
This commit is contained in:
@@ -236,7 +236,8 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
||||
rb->type = static_cast<Engine::ECS::RigidBodyComponent::BodyType>(type);
|
||||
}
|
||||
int collider = static_cast<int>(rb->collider);
|
||||
if (ImGui::Combo("collider", &collider, "Box\0Sphere\0Mesh\0"))
|
||||
if (ImGui::Combo("collider", &collider,
|
||||
"Box\0Sphere\0Mesh\0Capsule\0Cylinder\0Compound\0"))
|
||||
{
|
||||
rb->collider = static_cast<Engine::ECS::RigidBodyComponent::ColliderType>(collider);
|
||||
}
|
||||
@@ -248,6 +249,61 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
||||
{
|
||||
ImGui::DragFloat("radius", &rb->sphereRadius, 0.05f, 0.01f, 500.0f);
|
||||
}
|
||||
else if (rb->collider == Engine::ECS::RigidBodyComponent::ColliderType::Capsule)
|
||||
{
|
||||
// 半高 = 圆柱段半高(不含半球端盖),总高 = 2*(halfHeight + radius)
|
||||
ImGui::DragFloat("radius", &rb->capsuleRadius, 0.05f, 0.01f, 500.0f);
|
||||
ImGui::DragFloat("halfHeight", &rb->capsuleHalfHeight, 0.05f, 0.0f, 500.0f);
|
||||
}
|
||||
else if (rb->collider == Engine::ECS::RigidBodyComponent::ColliderType::Cylinder)
|
||||
{
|
||||
ImGui::DragFloat("radius", &rb->cylinderRadius, 0.05f, 0.01f, 500.0f);
|
||||
ImGui::DragFloat("halfHeight", &rb->cylinderHalfHeight, 0.05f, 0.01f, 500.0f);
|
||||
}
|
||||
else if (rb->collider == Engine::ECS::RigidBodyComponent::ColliderType::Compound)
|
||||
{
|
||||
// 子形状列表:尺寸/位置变更 → PhysicsWorld 重建 body(既有模式)
|
||||
ImGui::Text("children: %d", static_cast<int>(rb->compound.size()));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("+ add"))
|
||||
{
|
||||
rb->compound.emplace_back();
|
||||
}
|
||||
int remove = -1;
|
||||
for (int i = 0; i < static_cast<int>(rb->compound.size()); ++i)
|
||||
{
|
||||
auto& c = rb->compound[i];
|
||||
ImGui::PushID(i);
|
||||
ImGui::Separator();
|
||||
int sh = static_cast<int>(c.shape);
|
||||
if (ImGui::Combo("shape", &sh, "Box\0Sphere\0Capsule\0"))
|
||||
{
|
||||
c.shape = static_cast<Engine::ECS::RigidBodyComponent::CompoundChild::Shape>(sh);
|
||||
}
|
||||
if (c.shape == Engine::ECS::RigidBodyComponent::CompoundChild::Shape::Box)
|
||||
{
|
||||
ImGui::DragFloat3("halfExtents", &c.boxHalfExtents.x, 0.05f, 0.01f, 500.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::DragFloat("radius", &c.radius, 0.05f, 0.01f, 500.0f);
|
||||
if (c.shape == Engine::ECS::RigidBodyComponent::CompoundChild::Shape::Capsule)
|
||||
{
|
||||
ImGui::DragFloat("halfHeight", &c.capsuleHalfHeight, 0.05f, 0.0f, 500.0f);
|
||||
}
|
||||
}
|
||||
ImGui::DragFloat3("offset", &c.position.x, 0.05f);
|
||||
if (ImGui::Button("remove"))
|
||||
{
|
||||
remove = i;
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
if (remove >= 0)
|
||||
{
|
||||
rb->compound.erase(rb->compound.begin() + remove);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mesh:跟随 MeshRenderer 视觉网格(Static=精确网格,
|
||||
|
||||
Reference in New Issue
Block a user