rokojori_action_library/Tools/mcp/Routes/ReadSceneFragmentRoute.cs

135 lines
4.4 KiB
C#

#if TOOLS
using Godot;
namespace Rokojori.Tools
{
using Rokojori;
public static class ReadSceneFragmentRoute
{
public static JSONObject ToolDefinition()
{
var filePathSchema = new JSONObject();
filePathSchema.Set( "type", "string" );
filePathSchema.Set( "description", "res:// path to the scene (.tscn)" );
var scenePathSchema = new JSONObject();
scenePathSchema.Set( "type", "array" );
scenePathSchema.Set( "description", "Child names from the scene root to the target node. Empty array = scene root." );
var levelSchema = new JSONObject();
levelSchema.Set( "type", "integer" );
levelSchema.Set( "description", "Descendant depth to include: 0 = all, 1 = direct children only, 2 = two levels, etc. Defaults to 0." );
var properties = new JSONObject();
properties.Set( "filePath", filePathSchema );
properties.Set( "scenePath", scenePathSchema );
properties.Set( "levelOfChildren", levelSchema );
var required = new JSONArray();
required.Push( "filePath" );
required.Push( "scenePath" );
var schema = new JSONObject();
schema.Set( "type", "object" );
schema.Set( "properties", properties );
schema.Set( "required", required );
var tool = new JSONObject();
tool.Set( "name", "read_scene_fragment" );
tool.Set( "description", "Read a node subtree out of a scene file without instantiating it." );
tool.Set( "inputSchema", schema );
return tool;
}
public static ToolCallOutcome Execute( JSONObject arguments )
{
var filePath = JsonUtil.GetStringOrNull( arguments, "filePath" );
var scenePathArray = arguments != null ? arguments.GetArray( "scenePath" ) : null;
var levelData = arguments != null ? arguments.Get( "levelOfChildren" ) : null;
var levelOfChildren = levelData != null && levelData.isNumber ? levelData.intValue : 0;
if ( string.IsNullOrEmpty( filePath ) )
{
return ToolCallOutcome.Error( "Missing required argument: filePath" );
}
if ( ! ResourceLoader.Exists( filePath, "PackedScene" ) )
{
return ToolCallOutcome.Error( "Scene not found: " + filePath );
}
var packedScene = ResourceLoader.Load<PackedScene>( filePath );
if ( packedScene == null )
{
return ToolCallOutcome.Error( "Failed to load scene: " + filePath );
}
var state = packedScene.GetState();
var scenePath = ScenePathResolver.ToStringArray( scenePathArray );
var targetRelativePath = ScenePathResolver.ToRelativePath( scenePath );
var targetIndex = ScenePathResolver.FindNodeIndex( state, targetRelativePath );
if ( targetIndex == -1 )
{
return ToolCallOutcome.Error( "Node not found at scenePath: " + targetRelativePath );
}
var startingLevels = levelOfChildren == 0 ? -1 : levelOfChildren;
var fragment = SerializeNode( state, targetIndex, targetRelativePath, startingLevels );
return ToolCallOutcome.Ok( JSON.Stringify( fragment ) );
}
static JSONObject SerializeNode( SceneState state, int index, string relativePath, int remainingLevels )
{
var obj = new JSONObject();
obj.Set( "name", state.GetNodeName( index ).ToString() );
obj.Set( "type", state.GetNodeType( index ).ToString() );
var properties = new JSONObject();
var propertyCount = state.GetNodePropertyCount( index );
for ( var i = 0; i < propertyCount; i++ )
{
var propName = state.GetNodePropertyName( index, i ).ToString();
var propValue = state.GetNodePropertyValue( index, i );
properties.Set( propName, VariantJson.ToJson( propValue ) );
}
obj.Set( "properties", properties );
if ( remainingLevels == 0 )
{
return obj;
}
var children = new JSONObject();
var nodeCount = state.GetNodeCount();
var nextLevels = remainingLevels == -1 ? -1 : remainingLevels - 1;
for ( var i = 0; i < nodeCount; i++ )
{
var candidatePath = state.GetNodePath( i, false ).ToString();
if ( ScenePathResolver.DepthOf( relativePath, candidatePath ) != 1 )
{
continue;
}
var childName = state.GetNodeName( i ).ToString();
children.Set( childName, SerializeNode( state, i, candidatePath, nextLevels ) );
}
obj.Set( "children", children );
return obj;
}
}
}
#endif