mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 11:28:19 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
189 lines
3.3 KiB
C#
189 lines
3.3 KiB
C#
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Hitboxes from a model
|
|
/// </summary>
|
|
[Expose]
|
|
[Title( "Hitboxes From Model" )]
|
|
[Category( "Game" )]
|
|
[Icon( "psychology_alt" )]
|
|
public sealed class ModelHitboxes : Component, Component.ExecuteInEditor
|
|
{
|
|
HitboxSystem system;
|
|
|
|
SkinnedModelRenderer _renderer;
|
|
|
|
/// <summary>
|
|
/// The target SkinnedModelRenderer that holds the model/skeleton you want to
|
|
/// take the hitboxes from.
|
|
/// </summary>
|
|
[Property]
|
|
public SkinnedModelRenderer Renderer
|
|
{
|
|
get => _renderer;
|
|
set
|
|
{
|
|
if ( _renderer == value ) return;
|
|
|
|
Clear();
|
|
|
|
_renderer = value;
|
|
|
|
AddFrom( Renderer );
|
|
}
|
|
}
|
|
|
|
GameObject _target;
|
|
|
|
/// <summary>
|
|
/// The target GameObject to report in trace hits. If this is unset we'll defaault to the gameobject on which this component is.
|
|
/// </summary>
|
|
[Property]
|
|
public GameObject Target
|
|
{
|
|
get => _target;
|
|
set
|
|
{
|
|
if ( _target == value ) return;
|
|
|
|
_target = value;
|
|
|
|
Rebuild();
|
|
}
|
|
}
|
|
|
|
protected override void OnAwake()
|
|
{
|
|
Scene.GetSystem( out system );
|
|
}
|
|
|
|
protected override void OnEnabled()
|
|
{
|
|
Rebuild();
|
|
}
|
|
|
|
protected override void OnDisabled()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
protected override void OnDestroy()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
public void Rebuild()
|
|
{
|
|
Clear();
|
|
AddFrom( Renderer );
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
if ( Renderer.IsValid() )
|
|
{
|
|
Renderer.ModelChanged -= Rebuild;
|
|
}
|
|
|
|
foreach ( var h in Hitboxes )
|
|
{
|
|
h.Dispose();
|
|
}
|
|
|
|
Hitboxes.Clear();
|
|
}
|
|
|
|
private void AddFrom( SkinnedModelRenderer anim )
|
|
{
|
|
if ( system is null ) return;
|
|
if ( !Active ) return;
|
|
if ( !anim.IsValid() ) return;
|
|
|
|
anim.ModelChanged += Rebuild;
|
|
|
|
if ( anim.Model is null ) return;
|
|
|
|
foreach ( var hb in anim.Model.HitboxSet.All )
|
|
{
|
|
if ( hb.Bone is null )
|
|
continue;
|
|
|
|
anim.TryGetBoneTransform( hb.Bone, out var tx );
|
|
|
|
var body = new PhysicsBody( system.PhysicsWorld );
|
|
PhysicsShape shape = null;
|
|
|
|
var hitbox = new Hitbox( Target ?? GameObject, hb.Bone, hb.Tags, body );
|
|
|
|
if ( hb.Shape is Sphere sphere )
|
|
{
|
|
shape = body.AddSphereShape( sphere.Center, sphere.Radius );
|
|
}
|
|
else if ( hb.Shape is Capsule capsule )
|
|
{
|
|
shape = body.AddCapsuleShape( capsule.CenterA, capsule.CenterB, capsule.Radius );
|
|
shape.Tags.SetFrom( GameObject.Tags );
|
|
}
|
|
else if ( hb.Shape is BBox box )
|
|
{
|
|
shape = body.AddBoxShape( box.Center, Rotation.Identity, box.Extents );
|
|
shape.Tags.SetFrom( GameObject.Tags );
|
|
hitbox.Bounds = box;
|
|
}
|
|
|
|
if ( shape is not null )
|
|
{
|
|
shape.SurfaceMaterial = hb.SurfaceName;
|
|
shape.Tags.SetFrom( GameObject.Tags );
|
|
shape.BoneIndex = hb.Bone.Index;
|
|
|
|
body.Transform = tx;
|
|
body.Component = this;
|
|
|
|
AddHitbox( hitbox );
|
|
}
|
|
else
|
|
{
|
|
body.Remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdatePositions()
|
|
{
|
|
if ( Renderer is null ) return;
|
|
|
|
foreach ( var hitbox in Hitboxes )
|
|
{
|
|
if ( Renderer.TryGetBoneTransform( hitbox.Bone, out var tx ) )
|
|
{
|
|
hitbox.Body.Transform = tx;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal readonly List<Hitbox> Hitboxes = new();
|
|
|
|
public void AddHitbox( Hitbox hitbox )
|
|
{
|
|
Hitboxes.Add( hitbox );
|
|
}
|
|
|
|
/// <summary>
|
|
/// The gameobject tags have changed, update collision tags on the target objects
|
|
/// </summary>
|
|
protected override void OnTagsChanged()
|
|
{
|
|
foreach ( var box in Hitboxes )
|
|
{
|
|
if ( box is null ) continue;
|
|
|
|
foreach ( var shape in box.Body.Shapes )
|
|
{
|
|
shape.Tags.SetFrom( GameObject.Tags );
|
|
}
|
|
}
|
|
}
|
|
}
|