namespace Sandbox; /// /// Defines a capsule collider. /// [Expose] [Title( "Collider - Capsule" )] [Category( "Physics" )] [Icon( "rounded_corner" )] [Alias( "ColliderCapsuleComponent" )] public class CapsuleCollider : Collider { Vector3 _start = 0; Vector3 _end = Vector3.Up * 10; float _radius = 16; /// /// Bottom point of the capsule /// [Property, Group( "Capsule" )] public Vector3 Start { get => _start; set { if ( _start == value ) return; _start = value; UpdateShape(); } } /// /// Top point of the capsule /// [Property, Group( "Capsule" )] public Vector3 End { get => _end; set { if ( _end == value ) return; _end = value; UpdateShape(); } } /// /// Radius of the capsule /// [Property, Group( "Capsule" )] public float Radius { get => _radius; set { if ( _radius == value ) return; _radius = value; UpdateShape(); } } private PhysicsShape Shape; protected override void DrawGizmos() { if ( !Gizmo.IsSelected && !Gizmo.IsHovered ) return; Gizmo.Hitbox.DepthBias = 0.01f; Gizmo.Draw.IgnoreDepth = true; Gizmo.Draw.LineThickness = 1; Gizmo.Draw.Color = Gizmo.Colors.Green.WithAlpha( Gizmo.IsSelected ? 1.0f : 0.2f ); Gizmo.Draw.LineCapsule( new Capsule( Start, End, Radius ) ); } internal override void UpdateShape() { if ( !Shape.IsValid() ) return; var body = Rigidbody; var world = Transform.TargetWorld; var local = body.IsValid() ? body.Transform.TargetWorld.ToLocal( world ) : global::Transform.Zero; var scale = world.UniformScale; var center1 = local.PointToWorld( Start ) * scale; var center2 = local.PointToWorld( End ) * scale; var radius = Radius * scale; Shape.UpdateCapsuleShape( center1, center2, radius ); CalculateLocalBounds(); } protected override IEnumerable CreatePhysicsShapes( PhysicsBody targetBody, Transform local ) { var center1 = local.PointToWorld( Start ); var center2 = local.PointToWorld( End ); var radius = Radius * WorldScale.x; var shape = targetBody.AddCapsuleShape( center1, center2, radius ); Shape = shape; yield return shape; } }