Editor utility that creates simple procedural GameObjects in the editor scene. It can generate basic shapes (box/plane/sphere) with optional material and collider, and create a mapping primitive (block) with size and collider, returning a ToolOutcome with metadata.
#nullable enable
using System;
using Sandbox;
namespace Editor.Mcp
{
internal static class ProceduralMeshDriver
{
public static ToolOutcome<object> GenerateMesh( string? targetName, string shape = "box", float width = 100f, float height = 100f, float depth = 100f, string? materialPath = null, bool addCollider = true )
{
var scene = EditorRuntime.ResolveActiveScene();
if ( scene == null )
{
return ToolOutcome<object>.Failure( null, ToolStatus.Unavailable, "mesh.no_scene", "No active scene loaded." );
}
var name = string.IsNullOrWhiteSpace( targetName ) ? $"Procedural {shape}" : targetName;
var go = new GameObject( true, name );
var renderer = go.Components.Create<ModelRenderer>();
renderer.Model = shape.ToLowerInvariant() switch
{
"sphere" => Model.Sphere,
"plane" => Model.Plane,
_ => Model.Cube
};
if ( !string.IsNullOrWhiteSpace( materialPath ) )
{
var mat = Material.Load( materialPath );
if ( mat != null )
{
renderer.MaterialOverride = mat;
}
}
go.WorldScale = new Vector3( width / 100f, height / 100f, depth / 100f );
if ( addCollider )
{
go.Components.Create<BoxCollider>();
}
return ToolOutcome<object>.Ready( new
{
GameObject = go.Name,
Id = go.Id.ToString(),
Shape = shape,
Dimensions = new { Width = width, Height = height, Depth = depth },
HasRenderer = true,
HasCollider = addCollider
} );
}
public static ToolOutcome<object> CreateMappingPrimitive( string primitiveType = "block", float sizeX = 128f, float sizeY = 128f, float sizeZ = 128f )
{
var scene = EditorRuntime.ResolveActiveScene();
if ( scene == null )
{
return ToolOutcome<object>.Failure( null, ToolStatus.Unavailable, "mapping.no_scene", "No active scene loaded." );
}
var go = new GameObject( true, $"Brush_{primitiveType}" );
var renderer = go.Components.Create<ModelRenderer>();
renderer.Model = Model.Cube;
go.WorldScale = new Vector3( sizeX / 100f, sizeY / 100f, sizeZ / 100f );
go.Components.Create<BoxCollider>();
return ToolOutcome<object>.Ready( new
{
GameObject = go.Name,
Primitive = primitiveType,
Extents = new { sizeX, sizeY, sizeZ }
} );
}
}
}