Files
sbox-public/engine/Sandbox.Engine/Scene/Components/Collider/ModelCollider.cs
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

158 lines
3.4 KiB
C#

namespace Sandbox;
/// <summary>
/// Defines a collider based on a model.
/// </summary>
[Expose]
[Title( "Model Collider" )]
[Category( "Physics" )]
[Icon( "check_box_outline_blank" )]
public class ModelCollider : Collider, IHasModel
{
private Model _model;
[Property]
public Model Model
{
get => _model;
set
{
_model = value;
Rebuild();
}
}
protected override void OnAwake()
{
base.OnAwake();
if ( _model is null )
{
var renderer = GetComponent<ModelRenderer>();
if ( renderer.IsValid() )
{
_model = renderer.Model;
}
}
}
protected override void DrawGizmos()
{
if ( !Gizmo.IsSelected && !Gizmo.IsHovered )
return;
if ( Model is null ) return;
if ( Model.Physics is null ) return;
Gizmo.Draw.Color = Gizmo.Colors.Green;
foreach ( var part in Model.Physics.Parts )
{
using ( Gizmo.Scope( $"part {part.GetHashCode()}", part.Transform ) )
{
foreach ( var sphere in part.Spheres )
{
Gizmo.Draw.LineSphere( sphere.Sphere );
}
foreach ( var capsule in part.Capsules )
{
Gizmo.Draw.LineCapsule( capsule.Capsule );
}
foreach ( var hull in part.Hulls )
{
Gizmo.Draw.Lines( hull.GetLines() );
}
foreach ( var mesh in part.Meshes )
{
Gizmo.Draw.LineTriangles( mesh.GetTriangles() );
}
}
}
}
protected override IEnumerable<PhysicsShape> CreatePhysicsShapes( PhysicsBody targetBody, Transform local )
{
if ( Model is null || Model.Physics is null )
yield break;
if ( Model.Physics.Parts.Count == 0 )
yield break;
foreach ( var part in Model.Physics.Parts )
{
Assert.NotNull( part, "Physics part was null" );
var boneIndex = Model.Bones.GetBone( part.BoneName )?.Index ?? -1;
// Bone transform
var bx = local.ToWorld( part.Transform );
foreach ( var sphere in part.Spheres )
{
var shape = targetBody.AddSphereShape( bx.PointToWorld( sphere.Sphere.Center ), sphere.Sphere.Radius * bx.UniformScale );
Assert.NotNull( shape, "Sphere shape was null" );
shape.Surface = sphere.Surface;
shape.BoneIndex = boneIndex;
yield return shape;
}
foreach ( var capsule in part.Capsules )
{
var shape = targetBody.AddCapsuleShape( bx.PointToWorld( capsule.Capsule.CenterA ), bx.PointToWorld( capsule.Capsule.CenterB ), capsule.Capsule.Radius * bx.UniformScale );
Assert.NotNull( shape, "Capsule shape was null" );
shape.Surface = capsule.Surface;
shape.BoneIndex = boneIndex;
yield return shape;
}
foreach ( var hull in part.Hulls )
{
var shape = targetBody.AddShape( hull, bx );
Assert.NotNull( shape, "Hull shape was null" );
shape.Surface = hull.Surface;
shape.BoneIndex = boneIndex;
yield return shape;
}
foreach ( var mesh in part.Meshes )
{
var shape = targetBody.AddShape( mesh, bx, false, true );
Assert.NotNull( shape, "Mesh shape was null" );
shape.Surface = mesh.Surface;
shape.Surfaces = mesh.Surfaces;
shape.BoneIndex = boneIndex;
yield return shape;
}
if ( part.Mass > 0 )
targetBody.Mass = part.Mass;
if ( part.OverrideMassCenter )
targetBody.LocalMassCenter = part.MassCenterOverride;
if ( part.LinearDamping > 0 )
targetBody.LinearDamping = part.LinearDamping;
if ( part.AngularDamping > 0 )
targetBody.AngularDamping = part.AngularDamping;
}
}
internal void OnModelReloaded()
{
Rebuild();
}
void IHasModel.OnModelReloaded()
{
OnModelReloaded();
}
}