Code/SliceDebugInput.cs
using Sandbox;
public sealed class SliceDebugInput : Component
{
[Property] public float TraceDistance { get; set; } = 5000.0f;
[Property] public bool IgnoreOwnerHierarchy { get; set; } = true;
protected override void OnUpdate()
{
if ( !Input.Pressed( "attack1" ) )
return;
if ( !TryGetSlicePlaneFromTrace( out var slicer, out var worldPoint, out var worldNormal ) )
return;
slicer.SliceAndSpawnWorld( worldPoint, worldNormal, autoCopyPhysics: true );
}
private bool TryGetSlicePlaneFromTrace( out MeshSlicerComponent slicer, out Vector3 worldPoint, out Vector3 worldNormal )
{
slicer = default;
worldPoint = default;
worldNormal = default;
var scene = Scene;
if ( scene is null )
return false;
var ray = BuildTraceRay( scene );
var trace = scene.Trace
.Ray( ray, TraceDistance > 1.0f ? TraceDistance : 1.0f )
.UseHitPosition( true );
if ( IgnoreOwnerHierarchy )
{
trace = trace.IgnoreGameObjectHierarchy( GameObject );
}
foreach ( var hit in trace.RunAll() )
{
if ( !hit.Hit || !hit.GameObject.IsValid() )
continue;
var resolvedSlicer = hit.GameObject.GetComponentInParent<MeshSlicerComponent>( true, true );
if ( resolvedSlicer is null )
continue;
var sourceObject = resolvedSlicer.Target?.GameObject ?? resolvedSlicer.GameObject;
var sourceUp = sourceObject?.WorldRotation.Up ?? Vector3.Up;
slicer = resolvedSlicer;
worldPoint = hit.HitPosition;
worldNormal = sourceUp;
return true;
}
return false;
}
private Ray BuildTraceRay( Scene scene )
{
var camera = scene.Camera;
if ( camera is not null )
{
return camera.ScreenNormalToRay( new Vector3( 0.5f, 0.5f, 0.0f ) );
}
return new Ray( WorldPosition, WorldRotation.Forward );
}
}