Editor/Mcp/BridgeGameObjectTools.cs
// AUTO-GENERATED by scripts/emit-mcp-wrappers.mjs — DO NOT EDIT.
// Regenerate: node scripts/extract-manifest.mjs && node scripts/emit-mcp-wrappers.mjs
// Source of truth: sbox-mcp-server/src/tools/ (zod schemas) → scripts/tools-manifest.json

using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Editor.Mcp;

/// <summary>
/// GameObject lifecycle, hierarchy, transforms, tags, selection, and bulk layout (align,
/// distribute, scatter, snap-to-ground, grid duplicate) in the open scene. Objects are referenced
/// by GUID from get_scene_hierarchy or find_objects.
/// </summary>
[McpToolset( "bridge_gameobject", "GameObject lifecycle, hierarchy, transforms, tags, selection, and bulk layout (align, distribute, scatter, snap-to-ground, grid duplicate) in the open scene. Objects are referenced by GUID from get_scene_hierarchy or find_objects." )]
public static class BridgeGameObjectTools
{
	/// <summary>
	/// Align several GameObjects on one axis so they share a coordinate. mode = first (match the first
	/// object), min, max, or average; defaults to first. Returns { aligned, axis, mode, target } —
	/// aligned is the object count and target the shared coordinate; verify positions with
	/// get_scene_hierarchy or a screenshot.
	/// </summary>
	/// <param name="ids">GUIDs of the GameObjects to align (&gt;= 2).</param>
	/// <param name="axis">Axis to align on. One of: x | y | z.</param>
	/// <param name="mode">Target coordinate to align to (default first). One of: first | min | max | average.</param>
	[McpTool( "align_objects" )]
	public static Task<object> AlignObjects( string[] ids, string axis, string mode = null )
		=> McpGate.Run( "align_objects", McpGate.Args( ( "ids", ids ), ( "axis", axis ), ( "mode", mode ) ) );

	/// <summary>
	/// Commit a dry-run plan returned by place_along_path, grid_duplicate, or scatter_props. Plans are
	/// scene-scoped, capped, and expire after 10 minutes. Success consumes the plan; a complete
	/// rollback restores it for retry. The stored transforms are applied without rerolling randomness
	/// or repeating ground traces. Creation rolls back on failure; grid commits reject a
	/// changed/missing source before creating anything. Returns slot-to-GUID receipts.
	/// </summary>
	/// <param name="planId">Plan id returned by a placement tool with dryRun:true.</param>
	[McpTool( "commit_placement_plan" )]
	public static Task<object> CommitPlacementPlan( string planId )
		=> McpGate.Run( "commit_placement_plan", McpGate.Args( ( "planId", planId ) ) );

	/// <summary>
	/// Create a new GameObject in the active scene. Returns its GUID for future reference.
	/// </summary>
	/// <param name="name">Display name (e.g. 'Player', 'Enemy Spawn Point'). Defaults to 'New Object'.</param>
	/// <param name="position">World position. As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="rotation">World rotation. As "pitch,yaw,roll" degrees.</param>
	/// <param name="scale">Uniform scale (number) or per-axis scale — object {x,y,z} or comma string "x,y,z". As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="parent">GUID of parent GameObject. Omit for scene root.</param>
	[McpTool( "create_gameobject" )]
	public static Task<object> CreateGameobject( string name = null, string position = null, string rotation = null, string scale = null, string parent = null )
		=> McpGate.Run( "create_gameobject", McpGate.Args( ( "name", name ), ( "position", position ), ( "rotation", rotation ), ( "scale", scale ), ( "parent", parent ) ) );

	/// <summary>
	/// Delete a GameObject from the active scene by its GUID.
	/// </summary>
	/// <param name="id">GUID of the GameObject to delete.</param>
	[McpTool( "delete_gameobject" )]
	public static Task<object> DeleteGameobject( string id )
		=> McpGate.Run( "delete_gameobject", McpGate.Args( ( "id", id ) ) );

	/// <summary>
	/// Evenly space GameObjects along an axis between the lowest and highest (keeps the two ends fixed,
	/// spreads the rest evenly). Returns { distributed, axis, from, to } — the object count and the
	/// fixed end coordinates the rest were spread between.
	/// </summary>
	/// <param name="ids">GUIDs of the GameObjects to distribute (&gt;= 3).</param>
	/// <param name="axis">Axis to distribute along. One of: x | y | z.</param>
	[McpTool( "distribute_objects" )]
	public static Task<object> DistributeObjects( string[] ids, string axis )
		=> McpGate.Run( "distribute_objects", McpGate.Args( ( "ids", ids ), ( "axis", axis ) ) );

	/// <summary>
	/// Clone a GameObject with all its components. Returns { duplicated, original, gameObject } —
	/// gameObject.id is the clone's new GUID; pass it to set_transform / add_component_with_properties.
	/// If offset is omitted the clone lands exactly on top of the original.
	/// </summary>
	/// <param name="id">GUID of the GameObject to duplicate.</param>
	/// <param name="name">New name for the clone.</param>
	/// <param name="offset">Position offset from original so the clone doesn't overlap. As "x,y,z" (or JSON {x,y,z}).</param>
	[McpTool( "duplicate_gameobject" )]
	public static Task<object> DuplicateGameobject( string id, string name = null, string offset = null )
		=> McpGate.Run( "duplicate_gameobject", McpGate.Args( ( "id", id ), ( "name", name ), ( "offset", offset ) ) );

	/// <summary>
	/// Query the scene for GameObjects by name (case-insensitive substring), component type name,
	/// and/or tag — combine filters (AND). Returns { count, total, showing, truncated,
	/// objects:[{id,name}] } — total is EVERY match in the scene, showing/count how many rows were
	/// returned (limit default 50, max 500), truncated:true when rows were cut so you can raise limit
	/// or narrow the filter. Read-only; works during play. Use it to get GUIDs to feed into
	/// align/distribute/set_tint/group/delete/etc.
	/// </summary>
	/// <param name="name">Name substring (case-insensitive).</param>
	/// <param name="component">Component type name, e.g. 'PointLight', 'SkinnedModelRenderer'.</param>
	/// <param name="tag">Tag the object must have.</param>
	/// <param name="limit">Max results (default 50, max 500).</param>
	[McpTool.ReadOnly( "find_objects" )]
	public static Task<object> FindObjects( string name = null, string component = null, string tag = null, int? limit = null )
		=> McpGate.Run( "find_objects", McpGate.Args( ( "name", name ), ( "component", component ), ( "tag", tag ), ( "limit", limit ) ) );

	/// <summary>
	/// Find GameObjects within a world-space radius of exactly one explicit position or originId,
	/// sorted nearest first. Optional name/component/tag filters are applied before the capped result,
	/// and the Scene root is excluded. Returns pivot-distance results plus
	/// requestedRadius/radiusClamped and total/showing/truncated/scanned; it deliberately does not
	/// pretend render or collider overlap is pivot distance. Read-only and play-aware.
	/// </summary>
	/// <param name="position">World-space search center; use instead of originId. As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="originId">GameObject GUID whose world position is the center.</param>
	/// <param name="radius">Search radius in world units (default 256, max 1,000,000).</param>
	/// <param name="limit">Maximum results (default 50).</param>
	/// <param name="name">Case-insensitive GameObject name substring.</param>
	/// <param name="component">Required component type name.</param>
	/// <param name="tag">Required GameObject tag.</param>
	/// <param name="includeOrigin">Include originId itself (default false).</param>
	[McpTool.ReadOnly( "find_objects_near" )]
	public static Task<object> FindObjectsNear( string position = null, string originId = null, double? radius = null, int? limit = null, string name = null, string component = null, string tag = null, bool? includeOrigin = null )
		=> McpGate.Run( "find_objects_near", McpGate.Args( ( "position", position ), ( "originId", originId ), ( "radius", radius ), ( "limit", limit ), ( "name", name ), ( "component", component ), ( "tag", tag ), ( "includeOrigin", includeOrigin ) ) );

	/// <summary>
	/// Highlight a GameObject by selecting it in the editor. NOTE: s&amp;box exposes no dedicated focus
	/// API, so this only sets the selection — it does NOT move any camera (returns { focused, id, note
	/// } saying so). To actually point the viewport at an object use frame_camera; to aim a screenshot
	/// use screenshot_from.
	/// </summary>
	/// <param name="id">GUID of the GameObject to focus.</param>
	[McpTool( "focus_object" )]
	public static Task<object> FocusObject( string id )
		=> McpGate.Run( "focus_object", McpGate.Args( ( "id", id ) ) );

	/// <summary>
	/// Get provenance-rich world bounds for a GameObject. Preserves legacy top-level
	/// center/size/extents/mins/maxs/radius/position/empty for compatibility, and adds render plus
	/// independent physics and solidPhysics aggregates. Collider outputs include trigger policy, capped
	/// contributor GameObject IDs and component type names, unsupported counts, and the exact API
	/// source. Read-only and play-aware.
	/// </summary>
	/// <param name="id">GUID of the GameObject to measure.</param>
	[McpTool.ReadOnly( "get_bounds" )]
	public static Task<object> GetBounds( string id )
		=> McpGate.Run( "get_bounds", McpGate.Args( ( "id", id ) ) );

	/// <summary>
	/// Get the scene tree — GameObjects with their names, GUIDs, components, and parent/child
	/// relationships. Pair maxDepth with rootId to drill into a subtree without paying for the whole
	/// scene. On a dressed scene (hundreds of objects) pass namesOnly:true first — it returns just
	/// {id,name,childCount} per object (no components/enabled) for a lighter 'what is in this scene'
	/// overview (~30% smaller; size still scales with object count, so keep maxDepth low); then drill
	/// into one subtree with rootId.
	/// </summary>
	/// <param name="maxDepth">Maximum recursion depth. Defaults to 10. Use 1 or 2 for cheap top-level overviews.</param>
	/// <param name="rootId">Optional GUID of a GameObject to start traversal from. Omit to walk from the scene roots.</param>
	/// <param name="namesOnly">true = compact tree: {id, name, childCount, children} only, no components or enabled flags. Default false.</param>
	[McpTool.ReadOnly( "get_scene_hierarchy" )]
	public static Task<object> GetSceneHierarchy( int? maxDepth = null, string rootId = null, bool? namesOnly = null )
		=> McpGate.Run( "get_scene_hierarchy", McpGate.Args( ( "maxDepth", maxDepth ), ( "rootId", rootId ), ( "namesOnly", namesOnly ) ) );

	/// <summary>
	/// Get the GameObjects currently selected by the user in the s&amp;box editor. Returns { count,
	/// selected } where each entry is a serialized GameObject (id, name, enabled, position, rotation,
	/// scale, components, childCount) — use the ids with set_transform, add_component_with_properties,
	/// etc. Handy for 'do X to what I have selected' requests.
	/// </summary>
	[McpTool.ReadOnly( "get_selected_objects" )]
	public static Task<object> GetSelectedObjects()
		=> McpGate.Run( "get_selected_objects", McpGate.Args() );

	/// <summary>
	/// Read the tags currently on a GameObject. (Pair with set_tags to add/remove/clear, and
	/// find_objects to query by tag.).
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	[McpTool.ReadOnly( "get_tags" )]
	public static Task<object> GetTags( string id )
		=> McpGate.Run( "get_tags", McpGate.Args( ( "id", id ) ) );

	/// <summary>
	/// Clone a GameObject into an X/Y/Z grid. Existing calls mutate immediately and keep the legacy
	/// result. Use dryRun:true to preview exact capped transforms and receive a planId;
	/// commit_placement_plan then clones atomically and rejects the commit if the source transform or
	/// parent changed after preview.
	/// </summary>
	/// <param name="id">GUID of the GameObject to clone.</param>
	/// <param name="countX">Copies along X (default 1).</param>
	/// <param name="countY">Copies along Y (default 1).</param>
	/// <param name="countZ">Copies along Z (default 1).</param>
	/// <param name="spacing">Spacing between copies per axis (default 100,100,100). As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="dryRun">Preview only: return deterministic transforms and planId without cloning.</param>
	[McpTool( "grid_duplicate" )]
	public static Task<object> GridDuplicate( string id, int? countX = null, int? countY = null, int? countZ = null, string spacing = null, bool? dryRun = null )
		=> McpGate.Run( "grid_duplicate", McpGate.Args( ( "id", id ), ( "countX", countX ), ( "countY", countY ), ( "countZ", countZ ), ( "spacing", spacing ), ( "dryRun", dryRun ) ) );

	/// <summary>
	/// Parent a set of GameObjects under a new empty group object (placed at their centroid) — tidies
	/// the hierarchy and lets you move/rotate them together.
	/// </summary>
	/// <param name="ids">GUIDs of the GameObjects to group.</param>
	/// <param name="name">Name for the group object (default 'Group').</param>
	[McpTool( "group_objects" )]
	public static Task<object> GroupObjects( string[] ids, string name = null )
		=> McpGate.Run( "group_objects", McpGate.Args( ( "ids", ids ), ( "name", name ) ) );

	/// <summary>
	/// Measure the distance between two points or two GameObjects. Provide a/b as {x,y,z} or idA/idB as
	/// GUIDs. Returns straight-line distance, horizontal (ground) distance, and the delta vector.
	/// Read-only (works during play).
	/// </summary>
	/// <param name="a">First point {x,y,z}. As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="b">Second point {x,y,z}. As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="idA">First GameObject GUID (overrides a).</param>
	/// <param name="idB">Second GameObject GUID (overrides b).</param>
	[McpTool.ReadOnly( "measure_distance" )]
	public static Task<object> MeasureDistance( string a = null, string b = null, string idA = null, string idB = null )
		=> McpGate.Run( "measure_distance", McpGate.Args( ( "a", a ), ( "b", b ), ( "idA", idA ), ( "idB", idB ) ) );

	/// <summary>
	/// Add natural variation to existing objects: random yaw and/or random uniform scale within a
	/// range. Great for breaking up repetition in placed foliage/rocks/crates. Seeded — the same seed
	/// reproduces the same layout. Returns { randomized, seed } (the count of objects changed); scale
	/// only varies when scaleMax &gt; scaleMin.
	/// </summary>
	/// <param name="ids">GUIDs of the GameObjects to randomize.</param>
	/// <param name="randomYaw">Randomize Z rotation (default true).</param>
	/// <param name="scaleMin">Min uniform scale (default 1).</param>
	/// <param name="scaleMax">Max uniform scale (default 1; set &gt;min to vary).</param>
	/// <param name="seed">PRNG seed (default 1).</param>
	[McpTool( "randomize_transforms" )]
	public static Task<object> RandomizeTransforms( string[] ids, bool? randomYaw = null, double? scaleMin = null, double? scaleMax = null, int? seed = null )
		=> McpGate.Run( "randomize_transforms", McpGate.Args( ( "ids", ids ), ( "randomYaw", randomYaw ), ( "scaleMin", scaleMin ), ( "scaleMax", scaleMax ), ( "seed", seed ) ) );

	/// <summary>
	/// Change the display name of a GameObject identified by its GUID (the GUID itself never changes,
	/// so existing references stay valid). Returns { renamed, id, oldName, newName }. Name-based
	/// lookups (e.g. find_objects) will see the new name immediately.
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	/// <param name="name">New display name.</param>
	[McpTool( "rename_gameobject" )]
	public static Task<object> RenameGameobject( string id, string name )
		=> McpGate.Run( "rename_gameobject", McpGate.Args( ( "id", id ), ( "name", name ) ) );

	/// <summary>
	/// Swap the model on one object (id) or many (ids) — e.g. retheme a row of props in one call.
	/// </summary>
	/// <param name="model">New model path, e.g. 'models/dev/sphere.vmdl'.</param>
	/// <param name="id">Single GameObject GUID.</param>
	/// <param name="ids">Multiple GameObject GUIDs.</param>
	[McpTool( "replace_model" )]
	public static Task<object> ReplaceModel( string model, string id = null, string[] ids = null )
		=> McpGate.Run( "replace_model", McpGate.Args( ( "model", model ), ( "id", id ), ( "ids", ids ) ) );

	/// <summary>
	/// Scatter seeded model copies inside a radius. Existing calls mutate immediately and keep the
	/// legacy { scattered, groupId, seed } result. Use dryRun:true to resolve random transforms and
	/// ground traces once, returning per-slot transforms, ground status, warnings, model bounds, and
	/// planId; commit_placement_plan creates exactly that preview with rollback on failure.
	/// </summary>
	/// <param name="model">Model path to scatter, e.g. 'models/dev/box.vmdl'.</param>
	/// <param name="center">Centre of the scatter area (default origin). As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="radius">Scatter radius in units (default 256).</param>
	/// <param name="count">How many to place (default 10, max 300).</param>
	/// <param name="randomYaw">Randomly rotate each around Z (default true).</param>
	/// <param name="snapToGround">Raycast each onto the surface below (default true).</param>
	/// <param name="scaleMin">Min uniform scale (default 1).</param>
	/// <param name="scaleMax">Max uniform scale (default 1; set &gt;min for size variation).</param>
	/// <param name="tint">Tint applied to every copy — object {r,g,b,a} or comma string "r,g,b,a". As "r,g,b[,a]" (0-1 floats).</param>
	/// <param name="seed">PRNG seed for a reproducible layout (default 1).</param>
	/// <param name="group">Parent all copies under one group object (default true).</param>
	/// <param name="name">Base name for the props/group (default 'Prop').</param>
	/// <param name="dryRun">Preview only: return deterministic transforms and planId without creating props.</param>
	[McpTool( "scatter_props" )]
	public static Task<object> ScatterProps( string model, string center = null, double? radius = null, int? count = null, bool? randomYaw = null, bool? snapToGround = null, double? scaleMin = null, double? scaleMax = null, string tint = null, int? seed = null, bool? group = null, string name = null, bool? dryRun = null )
		=> McpGate.Run( "scatter_props", McpGate.Args( ( "model", model ), ( "center", center ), ( "radius", radius ), ( "count", count ), ( "randomYaw", randomYaw ), ( "snapToGround", snapToGround ), ( "scaleMin", scaleMin ), ( "scaleMax", scaleMax ), ( "tint", tint ), ( "seed", seed ), ( "group", group ), ( "name", name ), ( "dryRun", dryRun ) ) );

	/// <summary>
	/// Select a GameObject in the editor (highlights it in the hierarchy and scene view). Replaces the
	/// current selection unless addToSelection=true. Returns { selected, id }; confirm the result with
	/// get_selected_objects.
	/// </summary>
	/// <param name="id">GUID of the GameObject to select.</param>
	/// <param name="addToSelection">If true, adds to current selection instead of replacing it.</param>
	[McpTool( "select_object" )]
	public static Task<object> SelectObject( string id, bool? addToSelection = null )
		=> McpGate.Run( "select_object", McpGate.Args( ( "id", id ), ( "addToSelection", addToSelection ) ) );

	/// <summary>
	/// Enable or disable a GameObject (disabled objects are invisible and inactive, including their
	/// components and children). Returns { id, enabled } confirming the new state.
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	/// <param name="enabled">true to enable, false to disable.</param>
	[McpTool( "set_enabled" )]
	public static Task<object> SetEnabled( string id, bool enabled )
		=> McpGate.Run( "set_enabled", McpGate.Args( ( "id", id ), ( "enabled", enabled ) ) );

	/// <summary>
	/// Reparent a GameObject. Set parentId to null or omit to move to scene root.
	/// </summary>
	/// <param name="id">GUID of the GameObject to reparent.</param>
	/// <param name="parentId">GUID of the new parent. Null or omitted = scene root.</param>
	[McpTool( "set_parent" )]
	public static Task<object> SetParent( string id, string parentId = null )
		=> McpGate.Run( "set_parent", McpGate.Args( ( "id", id ), ( "parentId", parentId ) ) );

	/// <summary>
	/// Add, remove, and/or clear gameplay tags on one object (id) or many (ids). Tags drive collision
	/// groups, queries, and triggers.
	/// </summary>
	/// <param name="id">Single GameObject GUID.</param>
	/// <param name="ids">Multiple GameObject GUIDs.</param>
	/// <param name="add">Tags to add.</param>
	/// <param name="remove">Tags to remove.</param>
	/// <param name="clear">Remove all existing tags first.</param>
	[McpTool( "set_tags" )]
	public static Task<object> SetTags( string id = null, string[] ids = null, string[] add = null, string[] remove = null, bool? clear = null )
		=> McpGate.Run( "set_tags", McpGate.Args( ( "id", id ), ( "ids", ids ), ( "add", add ), ( "remove", remove ), ( "clear", clear ) ) );

	/// <summary>
	/// Set the renderer tint colour on one object (id) or many (ids) at once. Works on any
	/// ModelRenderer/SkinnedModelRenderer. Pass the colour as "tint" (or its alias "color"); each
	/// accepts an object {r,g,b,a} OR a comma string "r,g,b,a".
	/// </summary>
	/// <param name="id">Single GameObject GUID.</param>
	/// <param name="ids">Multiple GameObject GUIDs.</param>
	/// <param name="tint">Tint colour to apply (object or comma string). As "r,g,b[,a]" (0-1 floats).</param>
	/// <param name="color">Alias for "tint" (object or comma string). As "r,g,b[,a]" (0-1 floats).</param>
	[McpTool( "set_tint" )]
	public static Task<object> SetTint( string id = null, string[] ids = null, string tint = null, string color = null )
		=> McpGate.Run( "set_tint", McpGate.Args( ( "id", id ), ( "ids", ids ), ( "tint", tint ), ( "color", color ) ) );

	/// <summary>
	/// Atomically set position, rotation, and/or scale on a GameObject. All supplied values are parsed
	/// before mutation; values apply in world space by default. Prefer space='local' or space='world';
	/// local remains a legacy alias. Returns legacy { transformed, gameObject } plus before/after
	/// transform and bounds receipts.
	/// </summary>
	/// <param name="id">GUID of the GameObject.</param>
	/// <param name="position">New position. As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="rotation">New rotation. As "pitch,yaw,roll" degrees.</param>
	/// <param name="scale">New scale — uniform number, per-axis object {x,y,z}, or comma string "x,y,z". As "x,y,z" (or JSON {x,y,z}).</param>
	/// <param name="local">Legacy alias: true selects local space and false selects world space.</param>
	/// <param name="space">Explicit transform space. If supplied with local, both values must agree. One of: world | local.</param>
	[McpTool( "set_transform" )]
	public static Task<object> SetTransform( string id, string position = null, string rotation = null, string scale = null, bool? local = null, string space = null )
		=> McpGate.Run( "set_transform", McpGate.Args( ( "id", id ), ( "position", position ), ( "rotation", rotation ), ( "scale", scale ), ( "local", local ), ( "space", space ) ) );

	/// <summary>
	/// Drop a GameObject straight down onto the surface below it (physics raycast). Works best on
	/// collider-less props (an object with its own collider may self-hit). Optional offset lifts it off
	/// the surface. Returns { snapped, groundZ, gameObject } with the object's updated transform — or {
	/// snapped: false, reason } (not an error) when no ground was hit below.
	/// </summary>
	/// <param name="id">GUID of the GameObject to snap.</param>
	/// <param name="offset">Height above the surface to place it (default 0).</param>
	/// <param name="startHeight">How far above the object to start the trace (default 2000).</param>
	/// <param name="maxDistance">Max trace distance downward (default 20000).</param>
	[McpTool( "snap_to_ground" )]
	public static Task<object> SnapToGround( string id, double? offset = null, double? startHeight = null, double? maxDistance = null )
		=> McpGate.Run( "snap_to_ground", McpGate.Args( ( "id", id ), ( "offset", offset ), ( "startHeight", startHeight ), ( "maxDistance", maxDistance ) ) );
}