Editor tool for placing checkpoint objects in the scene. It ensures a CheckpointManager object exists, shows a preview sphere at the gizmo ray hit, and creates checkpoint GameObjects with collider, visual model and CheckpointRing component when left-clicked.
using Editor;
using Sandbox;
[EditorTool]
[Title( "Checkpoint Placer" )]
[Icon( "add_location" )]
public class CheckpointPlacer : EditorTool
{
int _nextIndex = 0;
GameObject _manager;
public override void OnEnabled()
{
EnsureManager();
RecalculateIndex();
Log.Info( "[CheckpointPlacer] Active. Next index: " + _nextIndex );
}
void EnsureManager()
{
foreach ( var go in Scene.GetAllObjects( true ) )
{
if ( go.Name == "CheckpointManager" )
{
_manager = go;
return;
}
}
_manager = new GameObject();
_manager.Name = "CheckpointManager";
_manager.Components.Create<CheckpointManager>();
Log.Info( "[CheckpointPlacer] Created CheckpointManager" );
}
void RecalculateIndex()
{
if ( _manager == null ) return;
int count = 0;
foreach ( var child in _manager.Children )
{
var cp = child.Components.Get<CheckpointRing>();
if ( cp is not null )
count++;
}
_nextIndex = count;
}
public override void OnUpdate()
{
base.OnUpdate();
var ray = Gizmo.CurrentRay;
var tr = Scene.Trace.Ray( ray, 10000f ).WithoutTags( "trigger" ).Run();
if ( !tr.Hit ) return;
var pos = tr.HitPosition + Vector3.Up * 10f;
Gizmo.Draw.Color = Color.Cyan.WithAlpha( 0.5f );
Gizmo.Draw.SolidSphere( pos, 80f );
Gizmo.Draw.Color = Color.White;
Gizmo.Draw.ScreenText( "Left click to place checkpoint " + _nextIndex, new Vector2( 10, 10 ) );
if ( Gizmo.WasLeftMousePressed )
{
EnsureManager();
RecalculateIndex();
PlaceCheckpoint( pos );
}
}
void PlaceCheckpoint( Vector3 position )
{
var go = new GameObject();
go.Parent = _manager;
go.WorldPosition = position;
go.Name = "Checkpoint_" + _nextIndex;
var col = go.Components.Create<SphereCollider>();
col.Radius = 150f;
col.IsTrigger = true;
go.Tags.Add( "trigger" );
var cp = go.Components.Create<CheckpointRing>();
cp.CheckpointIndex = _nextIndex;
cp.IsFinishLine = false;
cp.IsLastCheckpoint = false;
var model = go.Components.Create<ModelRenderer>();
model.Model = Model.Load( "models/primitives/sphere.vmdl" );
model.Tint = Color.Cyan;
go.WorldScale = new Vector3( 0.8f, 0.8f, 3f );
_nextIndex++;
Log.Info( "[CheckpointPlacer] Placed Checkpoint_" + (_nextIndex - 1) );
}
}