adding "init claude code" fonctionality
This commit is contained in:
1 parent
291030de43
commit
219c1ab7b0
25 files changed
+1041
-421
No files matched your search
+12
-2
@@ -147,5 +147,15 @@ J'aimerais automatiser le processus à la création d'un projet unreal en ajouta
|
||||
|
||||
|
||||
|
||||
reprenons avec ce que nous savons :
|
||||
Hier dans l'aprés-midi, nous avons, avec l'ancienne organization de dossier (cloné depuis https://github.com/chongdashu/unreal-mcp), réussi à faire fonctionner le server mcp. maintenant que nous avons modifié cette suructure, nous n'arrivons claude code ne lance plus le server mcp. L'ancienne structure se trouve ici : C:\UE_5.7\unreal-mcp\claude-unreal-mcp. le lock.
|
||||
l'objectif de cette session de travail est de modifier le code du plugin afin que l'utilisateur puisse dans unreal initialiser le projet unreal complet pour être prêt à utiliser claude code. Donc il faut créer en c++ le bouton "init claude code" dont on a parlé hier. Je veux que le code soit bien découpé (pas tous dans un seul fichier). Nous pouvons même créer dans le plugin un nouveau module pour ces fonctionnalités.
|
||||
Les étapes utilisateur souhaités:
|
||||
- clone du repo dans le dossier plugin du projet unreal cible.
|
||||
- l'utilisateur lance unreal (le plugin compile automatiquement)
|
||||
- Un menu "Claude code" dans la menu bar est présent maintenant dans l'interface unreal.
|
||||
- Un bouton "Init Claude Code" avec l'infobulle "Initialisation de claude code pour ce projet" est présent dans ce menu. Il permet à l'utilisateur d'initialiser le projet pour l'utilisation de Claude Code.
|
||||
- Quand l'utilisateur clique ce bouton, une fenêtre de validation s'affiche pour demander : "étes-vous sûr de vouloir initialiser claude code pour ce projet ?". A noter que claude code ne peux être utilisé qu'avec des projet c++. Si ce n'est pas le cas, afficher un message "Claude Code ne peut être initialisé que dans un projet cpp".
|
||||
- si l'utilisateur valide l'initialisation, le plugin copie le dossier .claude, ainsi que le .mcp.json à la racine du projet unreal en adaptant les chemins en relatif.
|
||||
- si l'utilisateur ne valide pas. On ne fait rien.
|
||||
- Le plugin initialise uv et attend que le venv soit prés avant de continuer.
|
||||
- Quand tout est fini, il affiche une fenêtre (même en cas d'echec) recapitulant les modifications apportées et le status de l'instalattion (si tout c'est bien passé ou si il y a eu un/des problèmes).
|
||||
Peux tu faire ce travail ?
|
||||
@@ -1,59 +0,0 @@
|
||||
2026-04-24 09:21:44,597 - mcp.server.lowlevel.server - DEBUG - [server.py:145] - Initializing server 'UnrealMCP'
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:384] - Registering handler for ListToolsRequest
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:406] - Registering handler for CallToolRequest
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:252] - Registering handler for ListResourcesRequest
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:286] - Registering handler for ReadResourceRequest
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:222] - Registering handler for PromptListRequest
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:239] - Registering handler for GetPromptRequest
|
||||
2026-04-24 09:21:44,598 - mcp.server.lowlevel.server - DEBUG - [server.py:267] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-24 09:21:44,614 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-24 09:21:44,626 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-24 09:21:44,649 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-24 09:21:44,650 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-24 09:21:44,657 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-24 09:21:44,659 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-24 09:21:44,666 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-24 09:21:44,668 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-24 09:21:44,668 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-24 09:21:44,669 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-24 09:21:44,669 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-24 09:21:44,685 - mcp.server.lowlevel.server - DEBUG - [server.py:491] - Received message: root=InitializedNotification(method='notifications/initialized', params=None, jsonrpc='2.0')
|
||||
2026-04-24 09:21:44,685 - mcp.server.lowlevel.server - DEBUG - [server.py:491] - Received message: <mcp.shared.session.RequestResponder object at 0x000001F81A508440>
|
||||
2026-04-24 09:21:44,686 - mcp.server.lowlevel.server - INFO - [server.py:534] - Processing request of type ListToolsRequest
|
||||
2026-04-24 09:21:44,686 - mcp.server.lowlevel.server - DEBUG - [server.py:537] - Dispatching request of type ListToolsRequest
|
||||
2026-04-24 09:21:44,686 - mcp.server.lowlevel.server - DEBUG - [server.py:572] - Response sent
|
||||
2026-04-24 09:21:44,687 - mcp.server.lowlevel.server - DEBUG - [server.py:491] - Received message: <mcp.shared.session.RequestResponder object at 0x000001F81A1B2BA0>
|
||||
2026-04-24 09:21:44,688 - mcp.server.lowlevel.server - INFO - [server.py:534] - Processing request of type ListPromptsRequest
|
||||
2026-04-24 09:21:44,688 - mcp.server.lowlevel.server - DEBUG - [server.py:537] - Dispatching request of type ListPromptsRequest
|
||||
2026-04-24 09:21:44,688 - mcp.server.lowlevel.server - DEBUG - [server.py:572] - Response sent
|
||||
2026-04-24 09:21:44,688 - mcp.server.lowlevel.server - DEBUG - [server.py:491] - Received message: <mcp.shared.session.RequestResponder object at 0x000001F81A45D820>
|
||||
2026-04-24 09:21:44,689 - mcp.server.lowlevel.server - INFO - [server.py:534] - Processing request of type ListResourcesRequest
|
||||
2026-04-24 09:21:44,689 - mcp.server.lowlevel.server - DEBUG - [server.py:537] - Dispatching request of type ListResourcesRequest
|
||||
2026-04-24 09:21:44,689 - mcp.server.fastmcp.resources.resource_manager - DEBUG - [resource_manager.py:89] - Listing resources
|
||||
2026-04-24 09:21:44,689 - mcp.server.lowlevel.server - DEBUG - [server.py:572] - Response sent
|
||||
2026-04-24 09:21:59,189 - mcp.server.lowlevel.server - DEBUG - [server.py:491] - Received message: <mcp.shared.session.RequestResponder object at 0x000001F81A583050>
|
||||
2026-04-24 09:21:59,189 - mcp.server.lowlevel.server - INFO - [server.py:534] - Processing request of type CallToolRequest
|
||||
2026-04-24 09:21:59,189 - mcp.server.lowlevel.server - DEBUG - [server.py:537] - Dispatching request of type CallToolRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:145] - Initializing server 'UnrealMCP'
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:384] - Registering handler for ListToolsRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:406] - Registering handler for CallToolRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:252] - Registering handler for ListResourcesRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:286] - Registering handler for ReadResourceRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:222] - Registering handler for PromptListRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:239] - Registering handler for GetPromptRequest
|
||||
2026-04-24 09:21:59,191 - mcp.server.lowlevel.server - DEBUG - [server.py:267] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-24 09:21:59,198 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-24 09:21:59,204 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-24 09:21:59,213 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-24 09:21:59,214 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-24 09:21:59,220 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-24 09:21:59,220 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-24 09:21:59,221 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-24 09:21:59,221 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-24 09:21:59,221 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-24 09:21:59,221 - UnrealMCP - INFO - [unreal_mcp_server.py:151] - Sending command: {"type": "get_actors_in_level", "params": {}}
|
||||
2026-04-24 09:21:59,377 - UnrealMCP - INFO - [unreal_mcp_server.py:101] - Received complete response (3465 bytes)
|
||||
2026-04-24 09:21:59,377 - UnrealMCP - INFO - [unreal_mcp_server.py:159] - Complete response from Unreal: {'status': 'success', 'result': {'actors': [{'name': 'WorldSettings_1', 'class': 'WorldSettings', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'Brush_1', 'class': 'Brush', 'location': [-90, 110, 20], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'DirectionalLight_0', 'class': 'DirectionalLight', 'location': [0, 0, 400], 'rotation': [-49.51711035415601, -10.308600787602971, 112.36067200001975], 'scale': [1, 1.0000000149011612, 1.0000000149011612]}, {'name': 'SkyAtmosphere_0', 'class': 'SkyAtmosphere', 'location': [0, 0, -6000], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'SkyLight_0', 'class': 'SkyLight', 'location': [0, 0, 600], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'ExponentialHeightFog_0', 'class': 'ExponentialHeightFog', 'location': [-5600, -50, -6850], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'VolumetricCloud_0', 'class': 'VolumetricCloud', 'location': [0, 0, 700], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'PlayerStart_0', 'class': 'PlayerStart', 'location': [0, 0, 92], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'StaticMeshActor_0', 'class': 'StaticMeshActor', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [400, 400, 400]}, {'name': 'Floor_0', 'class': 'StaticMeshActor', 'location': [0, 0, -0.5], 'rotation': [0, 0, 0], 'scale': [8, 8, 8]}, {'name': 'DefaultPhysicsVolume_0', 'class': 'DefaultPhysicsVolume', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'GameplayDebuggerPlayerManager_0', 'class': 'GameplayDebuggerPlayerManager', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'ChaosDebugDrawActor', 'class': 'Actor', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'AbstractNavData-Default', 'class': 'AbstractNavData', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}]}}
|
||||
2026-04-24 09:21:59,377 - UnrealMCP - INFO - [editor_tools.py:35] - Complete response from Unreal: {'status': 'success', 'result': {'actors': [{'name': 'WorldSettings_1', 'class': 'WorldSettings', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'Brush_1', 'class': 'Brush', 'location': [-90, 110, 20], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'DirectionalLight_0', 'class': 'DirectionalLight', 'location': [0, 0, 400], 'rotation': [-49.51711035415601, -10.308600787602971, 112.36067200001975], 'scale': [1, 1.0000000149011612, 1.0000000149011612]}, {'name': 'SkyAtmosphere_0', 'class': 'SkyAtmosphere', 'location': [0, 0, -6000], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'SkyLight_0', 'class': 'SkyLight', 'location': [0, 0, 600], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'ExponentialHeightFog_0', 'class': 'ExponentialHeightFog', 'location': [-5600, -50, -6850], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'VolumetricCloud_0', 'class': 'VolumetricCloud', 'location': [0, 0, 700], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'PlayerStart_0', 'class': 'PlayerStart', 'location': [0, 0, 92], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'StaticMeshActor_0', 'class': 'StaticMeshActor', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [400, 400, 400]}, {'name': 'Floor_0', 'class': 'StaticMeshActor', 'location': [0, 0, -0.5], 'rotation': [0, 0, 0], 'scale': [8, 8, 8]}, {'name': 'DefaultPhysicsVolume_0', 'class': 'DefaultPhysicsVolume', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'GameplayDebuggerPlayerManager_0', 'class': 'GameplayDebuggerPlayerManager', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'ChaosDebugDrawActor', 'class': 'Actor', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}, {'name': 'AbstractNavData-Default', 'class': 'AbstractNavData', 'location': [0, 0, 0], 'rotation': [0, 0, 0], 'scale': [1, 1, 1]}]}}
|
||||
2026-04-24 09:21:59,377 - UnrealMCP - INFO - [editor_tools.py:40] - Found 14 actors in level
|
||||
2026-04-24 09:21:59,378 - mcp.server.lowlevel.server - DEBUG - [server.py:572] - Response sent
|
||||
@@ -1,194 +0,0 @@
|
||||
2026-04-23 19:18:15,190 - mcp.server.lowlevel.server - DEBUG - [server.py:162] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 19:18:15,190 - mcp.server.lowlevel.server - DEBUG - [server.py:439] - Registering handler for ListToolsRequest
|
||||
2026-04-23 19:18:15,191 - mcp.server.lowlevel.server - DEBUG - [server.py:519] - Registering handler for CallToolRequest
|
||||
2026-04-23 19:18:15,191 - mcp.server.lowlevel.server - DEBUG - [server.py:301] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 19:18:15,191 - mcp.server.lowlevel.server - DEBUG - [server.py:336] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 19:18:15,191 - mcp.server.lowlevel.server - DEBUG - [server.py:263] - Registering handler for PromptListRequest
|
||||
2026-04-23 19:18:15,195 - mcp.server.lowlevel.server - DEBUG - [server.py:285] - Registering handler for GetPromptRequest
|
||||
2026-04-23 19:18:15,195 - mcp.server.lowlevel.server - DEBUG - [server.py:321] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 19:18:15,216 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 19:18:15,222 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 19:18:15,230 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 19:18:15,231 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 19:18:15,237 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 19:18:15,237 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 19:18:15,254 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 19:18:15,256 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 19:18:15,256 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 19:18:17,259 - UnrealMCP - ERROR - [unreal_mcp_server.py:67] - Failed to connect to Unreal: [WinError 10061] Aucune connexion n’a pu être établie car l’ordinateur cible l’a expressément refusée
|
||||
2026-04-23 19:18:17,259 - UnrealMCP - WARNING - [unreal_mcp_server.py:213] - Could not connect to Unreal Engine
|
||||
2026-04-23 19:18:17,259 - UnrealMCP - WARNING - [unreal_mcp_server.py:248] - Could not connect to Unreal Engine on startup
|
||||
2026-04-23 19:18:17,261 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 19:28:11,152 - mcp.server.lowlevel.server - DEBUG - [server.py:162] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 19:28:11,152 - mcp.server.lowlevel.server - DEBUG - [server.py:439] - Registering handler for ListToolsRequest
|
||||
2026-04-23 19:28:11,152 - mcp.server.lowlevel.server - DEBUG - [server.py:519] - Registering handler for CallToolRequest
|
||||
2026-04-23 19:28:11,153 - mcp.server.lowlevel.server - DEBUG - [server.py:301] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 19:28:11,153 - mcp.server.lowlevel.server - DEBUG - [server.py:336] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 19:28:11,153 - mcp.server.lowlevel.server - DEBUG - [server.py:263] - Registering handler for PromptListRequest
|
||||
2026-04-23 19:28:11,153 - mcp.server.lowlevel.server - DEBUG - [server.py:285] - Registering handler for GetPromptRequest
|
||||
2026-04-23 19:28:11,153 - mcp.server.lowlevel.server - DEBUG - [server.py:321] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 19:28:11,162 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 19:28:11,168 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 19:28:11,174 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 19:28:11,175 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 19:28:11,181 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 19:28:11,181 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 19:28:11,184 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 19:28:11,185 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 19:28:11,185 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 19:28:11,196 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 19:28:11,196 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 19:28:11,197 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 20:43:13,141 - mcp.server.lowlevel.server - DEBUG - [server.py:162] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 20:43:13,141 - mcp.server.lowlevel.server - DEBUG - [server.py:439] - Registering handler for ListToolsRequest
|
||||
2026-04-23 20:43:13,142 - mcp.server.lowlevel.server - DEBUG - [server.py:519] - Registering handler for CallToolRequest
|
||||
2026-04-23 20:43:13,142 - mcp.server.lowlevel.server - DEBUG - [server.py:301] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 20:43:13,142 - mcp.server.lowlevel.server - DEBUG - [server.py:336] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 20:43:13,142 - mcp.server.lowlevel.server - DEBUG - [server.py:263] - Registering handler for PromptListRequest
|
||||
2026-04-23 20:43:13,142 - mcp.server.lowlevel.server - DEBUG - [server.py:285] - Registering handler for GetPromptRequest
|
||||
2026-04-23 20:43:13,142 - mcp.server.lowlevel.server - DEBUG - [server.py:321] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 20:43:13,163 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 20:43:13,176 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 20:43:13,189 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 20:43:13,191 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 20:43:13,204 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 20:44:41,613 - mcp.server.lowlevel.server - DEBUG - [server.py:162] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:439] - Registering handler for ListToolsRequest
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:519] - Registering handler for CallToolRequest
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:301] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:336] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:263] - Registering handler for PromptListRequest
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:285] - Registering handler for GetPromptRequest
|
||||
2026-04-23 20:44:41,614 - mcp.server.lowlevel.server - DEBUG - [server.py:321] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 20:44:41,634 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 20:44:41,650 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 20:44:41,667 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 20:44:41,668 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 20:44:41,682 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 20:44:41,683 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 20:44:41,689 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 20:44:41,692 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 20:44:41,692 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 20:44:41,693 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 20:44:41,693 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 20:44:41,695 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 21:49:21,797 - mcp.server.lowlevel.server - DEBUG - [server.py:162] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:439] - Registering handler for ListToolsRequest
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:519] - Registering handler for CallToolRequest
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:301] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:336] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:263] - Registering handler for PromptListRequest
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:285] - Registering handler for GetPromptRequest
|
||||
2026-04-23 21:49:21,798 - mcp.server.lowlevel.server - DEBUG - [server.py:321] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 21:49:21,815 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 21:49:21,830 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 21:49:21,844 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 21:49:21,846 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 21:49:21,858 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 21:49:21,859 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 21:49:21,865 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 21:49:21,868 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 21:49:21,868 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 21:49:21,868 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 21:49:21,868 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 21:49:21,870 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 21:52:38,233 - mcp.server.lowlevel.server - DEBUG - [server.py:162] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 21:52:38,233 - mcp.server.lowlevel.server - DEBUG - [server.py:439] - Registering handler for ListToolsRequest
|
||||
2026-04-23 21:52:38,234 - mcp.server.lowlevel.server - DEBUG - [server.py:519] - Registering handler for CallToolRequest
|
||||
2026-04-23 21:52:38,234 - mcp.server.lowlevel.server - DEBUG - [server.py:301] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 21:52:38,234 - mcp.server.lowlevel.server - DEBUG - [server.py:336] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 21:52:38,234 - mcp.server.lowlevel.server - DEBUG - [server.py:263] - Registering handler for PromptListRequest
|
||||
2026-04-23 21:52:38,234 - mcp.server.lowlevel.server - DEBUG - [server.py:285] - Registering handler for GetPromptRequest
|
||||
2026-04-23 21:52:38,234 - mcp.server.lowlevel.server - DEBUG - [server.py:321] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 21:52:38,251 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 21:52:38,263 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 21:52:38,278 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 21:52:38,279 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 21:52:38,291 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 21:52:38,292 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 21:52:38,296 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 21:52:38,299 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 21:52:38,299 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 21:52:38,300 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 21:52:38,300 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 21:52:40,398 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:145] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:384] - Registering handler for ListToolsRequest
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:406] - Registering handler for CallToolRequest
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:252] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:286] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:222] - Registering handler for PromptListRequest
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:239] - Registering handler for GetPromptRequest
|
||||
2026-04-23 22:06:00,164 - mcp.server.lowlevel.server - DEBUG - [server.py:267] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 22:06:00,175 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 22:06:00,183 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 22:06:00,192 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 22:06:00,193 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 22:06:00,213 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 22:06:00,215 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 22:06:00,219 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 22:06:00,220 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 22:06:00,220 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 22:06:00,221 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 22:06:00,221 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 22:06:02,502 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:145] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:384] - Registering handler for ListToolsRequest
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:406] - Registering handler for CallToolRequest
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:252] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:286] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:222] - Registering handler for PromptListRequest
|
||||
2026-04-23 22:12:35,787 - mcp.server.lowlevel.server - DEBUG - [server.py:239] - Registering handler for GetPromptRequest
|
||||
2026-04-23 22:12:35,788 - mcp.server.lowlevel.server - DEBUG - [server.py:267] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 22:12:35,800 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 22:12:35,807 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 22:12:35,830 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 22:12:35,831 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 22:12:35,839 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 22:12:35,840 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 22:12:35,844 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 22:12:35,846 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 22:12:35,846 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 22:12:35,847 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 22:12:35,847 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 22:12:35,849 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:145] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:384] - Registering handler for ListToolsRequest
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:406] - Registering handler for CallToolRequest
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:252] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:286] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:222] - Registering handler for PromptListRequest
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:239] - Registering handler for GetPromptRequest
|
||||
2026-04-23 22:15:02,964 - mcp.server.lowlevel.server - DEBUG - [server.py:267] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 22:15:02,976 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 22:15:02,985 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 22:15:03,006 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 22:15:03,007 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 22:15:03,014 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 22:15:03,015 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 22:15:03,020 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 22:15:03,022 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 22:15:03,023 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 22:15:03,023 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 22:15:03,023 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 22:15:03,025 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
2026-04-23 22:18:00,708 - mcp.server.lowlevel.server - DEBUG - [server.py:145] - Initializing server 'UnrealMCP'
|
||||
2026-04-23 22:18:00,708 - mcp.server.lowlevel.server - DEBUG - [server.py:384] - Registering handler for ListToolsRequest
|
||||
2026-04-23 22:18:00,709 - mcp.server.lowlevel.server - DEBUG - [server.py:406] - Registering handler for CallToolRequest
|
||||
2026-04-23 22:18:00,709 - mcp.server.lowlevel.server - DEBUG - [server.py:252] - Registering handler for ListResourcesRequest
|
||||
2026-04-23 22:18:00,709 - mcp.server.lowlevel.server - DEBUG - [server.py:286] - Registering handler for ReadResourceRequest
|
||||
2026-04-23 22:18:00,709 - mcp.server.lowlevel.server - DEBUG - [server.py:222] - Registering handler for PromptListRequest
|
||||
2026-04-23 22:18:00,709 - mcp.server.lowlevel.server - DEBUG - [server.py:239] - Registering handler for GetPromptRequest
|
||||
2026-04-23 22:18:00,709 - mcp.server.lowlevel.server - DEBUG - [server.py:267] - Registering handler for ListResourceTemplatesRequest
|
||||
2026-04-23 22:18:00,720 - UnrealMCP - INFO - [editor_tools.py:369] - Editor tools registered successfully
|
||||
2026-04-23 22:18:00,729 - UnrealMCP - INFO - [blueprint_tools.py:420] - Blueprint tools registered successfully
|
||||
2026-04-23 22:18:00,749 - UnrealMCP - INFO - [node_tools.py:430] - Blueprint node tools registered successfully
|
||||
2026-04-23 22:18:00,752 - UnrealMCP - INFO - [project_tools.py:64] - Project tools registered successfully
|
||||
2026-04-23 22:18:00,760 - UnrealMCP - INFO - [umg_tools.py:333] - UMG tools registered successfully
|
||||
2026-04-23 22:18:00,760 - UnrealMCP - INFO - [unreal_mcp_server.py:375] - Starting MCP server with stdio transport
|
||||
2026-04-23 22:18:00,763 - asyncio - DEBUG - [proactor_events.py:634] - Using proactor: IocpProactor
|
||||
2026-04-23 22:18:00,766 - UnrealMCP - INFO - [unreal_mcp_server.py:242] - UnrealMCP server starting up
|
||||
2026-04-23 22:18:00,766 - UnrealMCP - INFO - [unreal_mcp_server.py:49] - Connecting to Unreal at 127.0.0.1:55557...
|
||||
2026-04-23 22:18:00,778 - UnrealMCP - INFO - [unreal_mcp_server.py:63] - Connected to Unreal Engine
|
||||
2026-04-23 22:18:00,778 - UnrealMCP - INFO - [unreal_mcp_server.py:246] - Connected to Unreal Engine on startup
|
||||
2026-04-23 22:18:00,782 - UnrealMCP - INFO - [unreal_mcp_server.py:259] - Unreal MCP server shut down
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Commands/UnrealMCPBlueprintCommands.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "Engine/BlueprintGeneratedClass.h"
|
||||
@@ -130,11 +131,11 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleCreateBlueprint(const
|
||||
if (FoundClass)
|
||||
{
|
||||
SelectedParentClass = FoundClass;
|
||||
UE_LOG(LogTemp, Log, TEXT("Successfully set parent class to '%s'"), *ClassName);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("Successfully set parent class to '%s'"), *ClassName);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Could not find specified parent class '%s' at paths: /Script/Engine.%s or /Script/Game.%s, defaulting to AActor"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("Could not find specified parent class '%s' at paths: /Script/Engine.%s or /Script/Game.%s, defaulting to AActor"),
|
||||
*ClassName, *ClassName, *ClassName);
|
||||
}
|
||||
}
|
||||
@@ -283,7 +284,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
}
|
||||
|
||||
// Log all input parameters for debugging
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Blueprint: %s, Component: %s, Property: %s"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - Blueprint: %s, Component: %s, Property: %s"),
|
||||
*BlueprintName, *ComponentName, *PropertyName);
|
||||
|
||||
// Log property_value if available
|
||||
@@ -302,34 +303,34 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
default: ValueType = TEXT("Unknown"); break;
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Value Type: %s"), *ValueType);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - Value Type: %s"), *ValueType);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - No property_value provided"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - No property_value provided"));
|
||||
}
|
||||
|
||||
// Find the blueprint
|
||||
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
||||
if (!Blueprint)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Blueprint not found: %s"), *BlueprintName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Blueprint not found: %s"), *BlueprintName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Blueprint found: %s (Class: %s)"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Blueprint found: %s (Class: %s)"),
|
||||
*BlueprintName,
|
||||
Blueprint->GeneratedClass ? *Blueprint->GeneratedClass->GetName() : TEXT("NULL"));
|
||||
}
|
||||
|
||||
// Find the component
|
||||
USCS_Node* ComponentNode = nullptr;
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Searching for component %s in blueprint nodes"), *ComponentName);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Searching for component %s in blueprint nodes"), *ComponentName);
|
||||
|
||||
if (!Blueprint->SimpleConstructionScript)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - SimpleConstructionScript is NULL for blueprint %s"), *BlueprintName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - SimpleConstructionScript is NULL for blueprint %s"), *BlueprintName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Invalid blueprint construction script"));
|
||||
}
|
||||
|
||||
@@ -337,7 +338,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
{
|
||||
if (Node)
|
||||
{
|
||||
UE_LOG(LogTemp, Verbose, TEXT("SetComponentProperty - Found node: %s"), *Node->GetVariableName().ToString());
|
||||
UE_LOG(LogUnrealMCP, Verbose, TEXT("SetComponentProperty - Found node: %s"), *Node->GetVariableName().ToString());
|
||||
if (Node->GetVariableName().ToString() == ComponentName)
|
||||
{
|
||||
ComponentNode = Node;
|
||||
@@ -346,18 +347,18 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Found NULL node in blueprint"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - Found NULL node in blueprint"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!ComponentNode)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Component not found: %s"), *ComponentName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Component not found: %s"), *ComponentName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Component not found: %s"), *ComponentName));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Component found: %s (Class: %s)"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Component found: %s (Class: %s)"),
|
||||
*ComponentName,
|
||||
ComponentNode->ComponentTemplate ? *ComponentNode->ComponentTemplate->GetClass()->GetName() : TEXT("NULL"));
|
||||
}
|
||||
@@ -366,22 +367,22 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
UObject* ComponentTemplate = ComponentNode->ComponentTemplate;
|
||||
if (!ComponentTemplate)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Component template is NULL for %s"), *ComponentName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Component template is NULL for %s"), *ComponentName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Invalid component template"));
|
||||
}
|
||||
|
||||
// Check if this is a Spring Arm component and log special debug info
|
||||
if (ComponentTemplate->GetClass()->GetName().Contains(TEXT("SpringArm")))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - SpringArm component detected! Class: %s"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - SpringArm component detected! Class: %s"),
|
||||
*ComponentTemplate->GetClass()->GetPathName());
|
||||
|
||||
// Log all properties of the SpringArm component class
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - SpringArm properties:"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - SpringArm properties:"));
|
||||
for (TFieldIterator<FProperty> PropIt(ComponentTemplate->GetClass()); PropIt; ++PropIt)
|
||||
{
|
||||
FProperty* Prop = *PropIt;
|
||||
UE_LOG(LogTemp, Warning, TEXT(" - %s (%s)"), *Prop->GetName(), *Prop->GetCPPType());
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT(" - %s (%s)"), *Prop->GetName(), *Prop->GetCPPType());
|
||||
}
|
||||
|
||||
// Special handling for Spring Arm properties
|
||||
@@ -393,7 +394,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
FProperty* Property = FindFProperty<FProperty>(ComponentTemplate->GetClass(), *PropertyName);
|
||||
if (!Property)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Property %s not found on SpringArm component"), *PropertyName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Property %s not found on SpringArm component"), *PropertyName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
||||
FString::Printf(TEXT("Property %s not found on SpringArm component"), *PropertyName));
|
||||
}
|
||||
@@ -427,7 +428,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
if (JsonValue->Type == EJson::Number)
|
||||
{
|
||||
const float Value = JsonValue->AsNumber();
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting float property %s to %f"), *PropertyName, Value);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting float property %s to %f"), *PropertyName, Value);
|
||||
FloatProp->SetPropertyValue_InContainer(ComponentTemplate, Value);
|
||||
bSuccess = true;
|
||||
}
|
||||
@@ -437,14 +438,14 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
if (JsonValue->Type == EJson::Boolean)
|
||||
{
|
||||
const bool Value = JsonValue->AsBool();
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting bool property %s to %d"), *PropertyName, Value);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting bool property %s to %d"), *PropertyName, Value);
|
||||
BoolProp->SetPropertyValue_InContainer(ComponentTemplate, Value);
|
||||
bSuccess = true;
|
||||
}
|
||||
}
|
||||
else if (FStructProperty* StructProp = CastField<FStructProperty>(Property))
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Handling struct property %s of type %s"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Handling struct property %s of type %s"),
|
||||
*PropertyName, *StructProp->Struct->GetName());
|
||||
|
||||
// Special handling for common Spring Arm struct properties
|
||||
@@ -489,7 +490,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
if (bSuccess)
|
||||
{
|
||||
// Mark the blueprint as modified
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Successfully set SpringArm property %s"), *PropertyName);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Successfully set SpringArm property %s"), *PropertyName);
|
||||
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
||||
|
||||
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
||||
@@ -500,7 +501,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set SpringArm property %s"), *PropertyName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Failed to set SpringArm property %s"), *PropertyName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
||||
FString::Printf(TEXT("Failed to set SpringArm property %s"), *PropertyName));
|
||||
}
|
||||
@@ -518,15 +519,15 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
FProperty* Property = FindFProperty<FProperty>(ComponentTemplate->GetClass(), *PropertyName);
|
||||
if (!Property)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Property %s not found on component %s"),
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Property %s not found on component %s"),
|
||||
*PropertyName, *ComponentName);
|
||||
|
||||
// List all available properties for this component
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Available properties for %s:"), *ComponentName);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - Available properties for %s:"), *ComponentName);
|
||||
for (TFieldIterator<FProperty> PropIt(ComponentTemplate->GetClass()); PropIt; ++PropIt)
|
||||
{
|
||||
FProperty* Prop = *PropIt;
|
||||
UE_LOG(LogTemp, Warning, TEXT(" - %s (%s)"), *Prop->GetName(), *Prop->GetCPPType());
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT(" - %s (%s)"), *Prop->GetName(), *Prop->GetCPPType());
|
||||
}
|
||||
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
||||
@@ -534,7 +535,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property found: %s (Type: %s)"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Property found: %s (Type: %s)"),
|
||||
*PropertyName, *Property->GetCPPType());
|
||||
}
|
||||
|
||||
@@ -542,7 +543,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
FString ErrorMessage;
|
||||
|
||||
// Handle different property types
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Attempting to set property %s"), *PropertyName);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Attempting to set property %s"), *PropertyName);
|
||||
|
||||
// Add try-catch block to catch and log any crashes
|
||||
try
|
||||
@@ -550,7 +551,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
if (FStructProperty* StructProp = CastField<FStructProperty>(Property))
|
||||
{
|
||||
// Handle vector properties
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property is a struct: %s"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Property is a struct: %s"),
|
||||
StructProp->Struct ? *StructProp->Struct->GetName() : TEXT("NULL"));
|
||||
|
||||
if (StructProp->Struct == TBaseStructure<FVector>::Get())
|
||||
@@ -567,7 +568,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
Arr[2]->AsNumber()
|
||||
);
|
||||
void* PropertyAddr = StructProp->ContainerPtrToValuePtr<void>(ComponentTemplate);
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting Vector(%f, %f, %f)"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting Vector(%f, %f, %f)"),
|
||||
Vec.X, Vec.Y, Vec.Z);
|
||||
StructProp->CopySingleValue(PropertyAddr, &Vec);
|
||||
bSuccess = true;
|
||||
@@ -575,7 +576,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
else
|
||||
{
|
||||
ErrorMessage = FString::Printf(TEXT("Vector property requires 3 values, got %d"), Arr.Num());
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
else if (JsonValue->Type == EJson::Number)
|
||||
@@ -584,7 +585,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
float Value = JsonValue->AsNumber();
|
||||
FVector Vec(Value, Value, Value);
|
||||
void* PropertyAddr = StructProp->ContainerPtrToValuePtr<void>(ComponentTemplate);
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting Vector(%f, %f, %f) from scalar"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting Vector(%f, %f, %f) from scalar"),
|
||||
Vec.X, Vec.Y, Vec.Z);
|
||||
StructProp->CopySingleValue(PropertyAddr, &Vec);
|
||||
bSuccess = true;
|
||||
@@ -592,30 +593,30 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
else
|
||||
{
|
||||
ErrorMessage = TEXT("Vector property requires either a single number or array of 3 numbers");
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle other struct properties using default handler
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Using generic struct handler for %s"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Using generic struct handler for %s"),
|
||||
*PropertyName);
|
||||
bSuccess = FUnrealMCPCommonUtils::SetObjectProperty(ComponentTemplate, PropertyName, JsonValue, ErrorMessage);
|
||||
if (!bSuccess)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set struct property: %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Failed to set struct property: %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (FEnumProperty* EnumProp = CastField<FEnumProperty>(Property))
|
||||
{
|
||||
// Handle enum properties
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property is an enum"));
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Property is an enum"));
|
||||
if (JsonValue->Type == EJson::String)
|
||||
{
|
||||
FString EnumValueName = JsonValue->AsString();
|
||||
UEnum* Enum = EnumProp->GetEnum();
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting enum from string: %s"), *EnumValueName);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting enum from string: %s"), *EnumValueName);
|
||||
|
||||
if (Enum)
|
||||
{
|
||||
@@ -623,7 +624,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
|
||||
if (EnumValue != INDEX_NONE)
|
||||
{
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Found enum value: %lld"), EnumValue);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Found enum value: %lld"), EnumValue);
|
||||
EnumProp->GetUnderlyingProperty()->SetIntPropertyValue(
|
||||
ComponentTemplate,
|
||||
EnumValue
|
||||
@@ -633,31 +634,31 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
else
|
||||
{
|
||||
// List all possible enum values
|
||||
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Available enum values for %s:"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("SetComponentProperty - Available enum values for %s:"),
|
||||
*Enum->GetName());
|
||||
for (int32 i = 0; i < Enum->NumEnums(); i++)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT(" - %s (%lld)"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT(" - %s (%lld)"),
|
||||
*Enum->GetNameStringByIndex(i),
|
||||
Enum->GetValueByIndex(i));
|
||||
}
|
||||
|
||||
ErrorMessage = FString::Printf(TEXT("Invalid enum value '%s' for property %s"),
|
||||
*EnumValueName, *PropertyName);
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorMessage = TEXT("Enum object is NULL");
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
else if (JsonValue->Type == EJson::Number)
|
||||
{
|
||||
// Allow setting enum by integer value
|
||||
int64 EnumValue = JsonValue->AsNumber();
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting enum from number: %lld"), EnumValue);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting enum from number: %lld"), EnumValue);
|
||||
EnumProp->GetUnderlyingProperty()->SetIntPropertyValue(
|
||||
ComponentTemplate,
|
||||
EnumValue
|
||||
@@ -667,60 +668,60 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
else
|
||||
{
|
||||
ErrorMessage = TEXT("Enum property requires either a string name or integer value");
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
else if (FNumericProperty* NumericProp = CastField<FNumericProperty>(Property))
|
||||
{
|
||||
// Handle numeric properties
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property is numeric: IsInteger=%d, IsFloat=%d"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Property is numeric: IsInteger=%d, IsFloat=%d"),
|
||||
NumericProp->IsInteger(), NumericProp->IsFloatingPoint());
|
||||
|
||||
if (JsonValue->Type == EJson::Number)
|
||||
{
|
||||
double Value = JsonValue->AsNumber();
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting numeric value: %f"), Value);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Setting numeric value: %f"), Value);
|
||||
|
||||
if (NumericProp->IsInteger())
|
||||
{
|
||||
NumericProp->SetIntPropertyValue(ComponentTemplate, (int64)Value);
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Set integer value: %lld"), (int64)Value);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Set integer value: %lld"), (int64)Value);
|
||||
bSuccess = true;
|
||||
}
|
||||
else if (NumericProp->IsFloatingPoint())
|
||||
{
|
||||
NumericProp->SetFloatingPointPropertyValue(ComponentTemplate, Value);
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Set float value: %f"), Value);
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Set float value: %f"), Value);
|
||||
bSuccess = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorMessage = TEXT("Numeric property requires a number value");
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle all other property types using default handler
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Using generic property handler for %s (Type: %s)"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Using generic property handler for %s (Type: %s)"),
|
||||
*PropertyName, *Property->GetCPPType());
|
||||
bSuccess = FUnrealMCPCommonUtils::SetObjectProperty(ComponentTemplate, PropertyName, JsonValue, ErrorMessage);
|
||||
if (!bSuccess)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set property: %s"), *ErrorMessage);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Failed to set property: %s"), *ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& Ex)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - EXCEPTION: %s"), ANSI_TO_TCHAR(Ex.what()));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - EXCEPTION: %s"), ANSI_TO_TCHAR(Ex.what()));
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
||||
FString::Printf(TEXT("Exception while setting property %s: %s"), *PropertyName, ANSI_TO_TCHAR(Ex.what())));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - UNKNOWN EXCEPTION occurred while setting property %s"), *PropertyName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - UNKNOWN EXCEPTION occurred while setting property %s"), *PropertyName);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
||||
FString::Printf(TEXT("Unknown exception while setting property %s"), *PropertyName));
|
||||
}
|
||||
@@ -728,7 +729,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
if (bSuccess)
|
||||
{
|
||||
// Mark the blueprint as modified
|
||||
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Successfully set property %s on component %s"),
|
||||
UE_LOG(LogUnrealMCP, Log, TEXT("SetComponentProperty - Successfully set property %s on component %s"),
|
||||
*PropertyName, *ComponentName);
|
||||
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
||||
|
||||
@@ -740,13 +741,13 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set property %s: %s"),
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Failed to set property %s: %s"),
|
||||
*PropertyName, *ErrorMessage);
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Missing 'property_value' parameter"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("SetComponentProperty - Missing 'property_value' parameter"));
|
||||
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'property_value' parameter"));
|
||||
}
|
||||
|
||||
@@ -805,7 +806,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetPhysicsProperties(
|
||||
float Mass = Params->GetNumberField(TEXT("mass"));
|
||||
// In UE5.5, use proper overrideMass instead of just scaling
|
||||
PrimComponent->SetMassOverrideInKg(NAME_None, Mass);
|
||||
UE_LOG(LogTemp, Display, TEXT("Set mass for component %s to %f kg"), *ComponentName, Mass);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Set mass for component %s to %f kg"), *ComponentName, Mass);
|
||||
}
|
||||
|
||||
if (Params->HasField(TEXT("linear_damping")))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Commands/UnrealMCPBlueprintNodeCommands.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "Engine/BlueprintGeneratedClass.h"
|
||||
@@ -17,9 +18,6 @@
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "EdGraphSchema_K2.h"
|
||||
|
||||
// Declare the log category
|
||||
DEFINE_LOG_CATEGORY_STATIC(LogUnrealMCP, Log, All);
|
||||
|
||||
FUnrealMCPBlueprintNodeCommands::FUnrealMCPBlueprintNodeCommands()
|
||||
{
|
||||
}
|
||||
@@ -310,7 +308,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
UK2Node_CallFunction* FunctionNode = nullptr;
|
||||
|
||||
// Add extensive logging for debugging
|
||||
UE_LOG(LogTemp, Display, TEXT("Looking for function '%s' in target '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Looking for function '%s' in target '%s'"),
|
||||
*FunctionName, Target.IsEmpty() ? TEXT("Blueprint") : *Target);
|
||||
|
||||
// Check if we have a target class specified
|
||||
@@ -321,7 +319,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
|
||||
// First try without a prefix
|
||||
TargetClass = FindFirstObject<UClass>(*Target);
|
||||
UE_LOG(LogTemp, Display, TEXT("Tried to find class '%s': %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Tried to find class '%s': %s"),
|
||||
*Target, TargetClass ? TEXT("Found") : TEXT("Not found"));
|
||||
|
||||
// If not found, try with U prefix (common convention for UE classes)
|
||||
@@ -329,7 +327,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
{
|
||||
FString TargetWithPrefix = FString(TEXT("U")) + Target;
|
||||
TargetClass = FindFirstObject<UClass>(*TargetWithPrefix);
|
||||
UE_LOG(LogTemp, Display, TEXT("Tried to find class '%s': %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Tried to find class '%s': %s"),
|
||||
*TargetWithPrefix, TargetClass ? TEXT("Found") : TEXT("Not found"));
|
||||
}
|
||||
|
||||
@@ -346,7 +344,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
TargetClass = FindFirstObject<UClass>(*ClassName);
|
||||
if (TargetClass)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Found class using alternative name '%s'"), *ClassName);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Found class using alternative name '%s'"), *ClassName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -361,7 +359,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
{
|
||||
// Try loading it from its known package
|
||||
TargetClass = LoadObject<UClass>(nullptr, TEXT("/Script/Engine.GameplayStatics"));
|
||||
UE_LOG(LogTemp, Display, TEXT("Explicitly loading GameplayStatics: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Explicitly loading GameplayStatics: %s"),
|
||||
TargetClass ? TEXT("Success") : TEXT("Failed"));
|
||||
}
|
||||
}
|
||||
@@ -369,7 +367,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
// If we found a target class, look for the function there
|
||||
if (TargetClass)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Looking for function '%s' in class '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Looking for function '%s' in class '%s'"),
|
||||
*FunctionName, *TargetClass->GetName());
|
||||
|
||||
// First try exact name
|
||||
@@ -379,7 +377,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
UClass* CurrentClass = TargetClass;
|
||||
while (!Function && CurrentClass)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Searching in class: %s"), *CurrentClass->GetName());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Searching in class: %s"), *CurrentClass->GetName());
|
||||
|
||||
// Try exact match
|
||||
Function = CurrentClass->FindFunctionByName(*FunctionName);
|
||||
@@ -390,11 +388,11 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
for (TFieldIterator<UFunction> FuncIt(CurrentClass); FuncIt; ++FuncIt)
|
||||
{
|
||||
UFunction* AvailableFunc = *FuncIt;
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Available function: %s"), *AvailableFunc->GetName());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Available function: %s"), *AvailableFunc->GetName());
|
||||
|
||||
if (AvailableFunc->GetName().Equals(FunctionName, ESearchCase::IgnoreCase))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Found case-insensitive match: %s"), *AvailableFunc->GetName());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Found case-insensitive match: %s"), *AvailableFunc->GetName());
|
||||
Function = AvailableFunc;
|
||||
break;
|
||||
}
|
||||
@@ -411,7 +409,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
if (TargetClass->GetName() == TEXT("GameplayStatics") &&
|
||||
(FunctionName == TEXT("GetActorOfClass") || FunctionName.Equals(TEXT("GetActorOfClass"), ESearchCase::IgnoreCase)))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Using special case handling for GameplayStatics::GetActorOfClass"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Using special case handling for GameplayStatics::GetActorOfClass"));
|
||||
|
||||
// Create the function node directly
|
||||
FunctionNode = NewObject<UK2Node_CallFunction>(EventGraph);
|
||||
@@ -430,12 +428,12 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
FunctionNode->PostPlacedNewNode();
|
||||
FunctionNode->AllocateDefaultPins();
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Created GetActorOfClass node directly"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Created GetActorOfClass node directly"));
|
||||
|
||||
// List all pins
|
||||
for (UEdGraphPin* Pin : FunctionNode->Pins)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Pin: %s, Direction: %d, Category: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Pin: %s, Direction: %d, Category: %s"),
|
||||
*Pin->PinName.ToString(), (int32)Pin->Direction, *Pin->PinType.PinCategory.ToString());
|
||||
}
|
||||
}
|
||||
@@ -447,7 +445,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
// If we still haven't found the function, try in the blueprint's class
|
||||
if (!Function && !FunctionNode)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Trying to find function in blueprint class"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Trying to find function in blueprint class"));
|
||||
Function = Blueprint->GeneratedClass->FindFunctionByName(*FunctionName);
|
||||
}
|
||||
|
||||
@@ -478,12 +476,12 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
UEdGraphPin* ParamPin = FUnrealMCPCommonUtils::FindPin(FunctionNode, ParamName, EGPD_Input);
|
||||
if (ParamPin)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Found parameter pin '%s' of category '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Found parameter pin '%s' of category '%s'"),
|
||||
*ParamName, *ParamPin->PinType.PinCategory.ToString());
|
||||
UE_LOG(LogTemp, Display, TEXT(" Current default value: '%s'"), *ParamPin->DefaultValue);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Current default value: '%s'"), *ParamPin->DefaultValue);
|
||||
if (ParamPin->PinType.PinSubCategoryObject.IsValid())
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" Pin subcategory: '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Pin subcategory: '%s'"),
|
||||
*ParamPin->PinType.PinSubCategoryObject->GetName());
|
||||
}
|
||||
|
||||
@@ -491,7 +489,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
if (ParamValue->Type == EJson::String)
|
||||
{
|
||||
FString StringVal = ParamValue->AsString();
|
||||
UE_LOG(LogTemp, Display, TEXT(" Setting string parameter '%s' to: '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Setting string parameter '%s' to: '%s'"),
|
||||
*ParamName, *StringVal);
|
||||
|
||||
// Handle class reference parameters (e.g., ActorClass in GetActorOfClass)
|
||||
@@ -547,7 +545,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
// Ensure we're using an integer value (no decimal)
|
||||
int32 IntValue = FMath::RoundToInt(ParamValue->AsNumber());
|
||||
ParamPin->DefaultValue = FString::FromInt(IntValue);
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set integer parameter '%s' to: %d (string: '%s')"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set integer parameter '%s' to: %d (string: '%s')"),
|
||||
*ParamName, IntValue, *ParamPin->DefaultValue);
|
||||
}
|
||||
else if (ParamPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Float)
|
||||
@@ -555,14 +553,14 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
// For other numeric types
|
||||
float FloatValue = ParamValue->AsNumber();
|
||||
ParamPin->DefaultValue = FString::SanitizeFloat(FloatValue);
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set float parameter '%s' to: %f (string: '%s')"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set float parameter '%s' to: %f (string: '%s')"),
|
||||
*ParamName, FloatValue, *ParamPin->DefaultValue);
|
||||
}
|
||||
else if (ParamPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Boolean)
|
||||
{
|
||||
bool BoolValue = ParamValue->AsBool();
|
||||
ParamPin->DefaultValue = BoolValue ? TEXT("true") : TEXT("false");
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set boolean parameter '%s' to: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set boolean parameter '%s' to: %s"),
|
||||
*ParamName, *ParamPin->DefaultValue);
|
||||
}
|
||||
else if (ParamPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Struct && ParamPin->PinType.PinSubCategoryObject == TBaseStructure<FVector>::Get())
|
||||
@@ -582,14 +580,14 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
FString VectorString = FString::Printf(TEXT("(X=%f,Y=%f,Z=%f)"), X, Y, Z);
|
||||
ParamPin->DefaultValue = VectorString;
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set vector parameter '%s' to: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set vector parameter '%s' to: %s"),
|
||||
*ParamName, *VectorString);
|
||||
UE_LOG(LogTemp, Display, TEXT(" Final pin value: '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Final pin value: '%s'"),
|
||||
*ParamPin->DefaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Array parameter type not fully supported yet"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("Array parameter type not fully supported yet"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -602,7 +600,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
// Ensure we're using an integer value (no decimal)
|
||||
int32 IntValue = FMath::RoundToInt(ParamValue->AsNumber());
|
||||
ParamPin->DefaultValue = FString::FromInt(IntValue);
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set integer parameter '%s' to: %d (string: '%s')"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set integer parameter '%s' to: %d (string: '%s')"),
|
||||
*ParamName, IntValue, *ParamPin->DefaultValue);
|
||||
}
|
||||
else
|
||||
@@ -610,7 +608,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
// For other numeric types
|
||||
float FloatValue = ParamValue->AsNumber();
|
||||
ParamPin->DefaultValue = FString::SanitizeFloat(FloatValue);
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set float parameter '%s' to: %f (string: '%s')"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set float parameter '%s' to: %f (string: '%s')"),
|
||||
*ParamName, FloatValue, *ParamPin->DefaultValue);
|
||||
}
|
||||
}
|
||||
@@ -618,12 +616,12 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
{
|
||||
bool BoolValue = ParamValue->AsBool();
|
||||
ParamPin->DefaultValue = BoolValue ? TEXT("true") : TEXT("false");
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set boolean parameter '%s' to: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set boolean parameter '%s' to: %s"),
|
||||
*ParamName, *ParamPin->DefaultValue);
|
||||
}
|
||||
else if (ParamValue->Type == EJson::Array)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" Processing array parameter '%s'"), *ParamName);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Processing array parameter '%s'"), *ParamName);
|
||||
// Handle array parameters - like Vector parameters
|
||||
const TArray<TSharedPtr<FJsonValue>>* ArrayValue;
|
||||
if (ParamValue->TryGetArray(ArrayValue))
|
||||
@@ -641,14 +639,14 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
FString VectorString = FString::Printf(TEXT("(X=%f,Y=%f,Z=%f)"), X, Y, Z);
|
||||
ParamPin->DefaultValue = VectorString;
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT(" Set vector parameter '%s' to: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Set vector parameter '%s' to: %s"),
|
||||
*ParamName, *VectorString);
|
||||
UE_LOG(LogTemp, Display, TEXT(" Final pin value: '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" Final pin value: '%s'"),
|
||||
*ParamPin->DefaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Array parameter type not fully supported yet"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("Array parameter type not fully supported yet"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -656,7 +654,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleAddBlueprintFunct
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("Parameter pin '%s' not found"), *ParamName);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("Parameter pin '%s' not found"), *ParamName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,7 +908,7 @@ TSharedPtr<FJsonObject> FUnrealMCPBlueprintNodeCommands::HandleFindBlueprintNode
|
||||
UK2Node_Event* EventNode = Cast<UK2Node_Event>(Node);
|
||||
if (EventNode && EventNode->EventReference.GetMemberName() == FName(*EventName))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Found event node with name %s: %s"), *EventName, *EventNode->NodeGuid.ToString());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Found event node with name %s: %s"), *EventName, *EventNode->NodeGuid.ToString());
|
||||
NodeGuidArray.Add(MakeShared<FJsonValueString>(EventNode->NodeGuid.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "EdGraph/EdGraph.h"
|
||||
@@ -199,7 +200,7 @@ UK2Node_Event* FUnrealMCPCommonUtils::CreateEventNode(UEdGraph* Graph, const FSt
|
||||
UK2Node_Event* EventNode = Cast<UK2Node_Event>(Node);
|
||||
if (EventNode && EventNode->EventReference.GetMemberName() == FName(*EventName))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Using existing event node with name %s (ID: %s)"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Using existing event node with name %s (ID: %s)"),
|
||||
*EventName, *EventNode->NodeGuid.ToString());
|
||||
return EventNode;
|
||||
}
|
||||
@@ -221,12 +222,12 @@ UK2Node_Event* FUnrealMCPCommonUtils::CreateEventNode(UEdGraph* Graph, const FSt
|
||||
Graph->AddNode(EventNode, true);
|
||||
EventNode->PostPlacedNewNode();
|
||||
EventNode->AllocateDefaultPins();
|
||||
UE_LOG(LogTemp, Display, TEXT("Created new event node with name %s (ID: %s)"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Created new event node with name %s (ID: %s)"),
|
||||
*EventName, *EventNode->NodeGuid.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("Failed to find function for event name: %s"), *EventName);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("Failed to find function for event name: %s"), *EventName);
|
||||
}
|
||||
|
||||
return EventNode;
|
||||
@@ -370,12 +371,12 @@ UEdGraphPin* FUnrealMCPCommonUtils::FindPin(UEdGraphNode* Node, const FString& P
|
||||
}
|
||||
|
||||
// Log all pins for debugging
|
||||
UE_LOG(LogTemp, Display, TEXT("FindPin: Looking for pin '%s' (Direction: %d) in node '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("FindPin: Looking for pin '%s' (Direction: %d) in node '%s'"),
|
||||
*PinName, (int32)Direction, *Node->GetName());
|
||||
|
||||
for (UEdGraphPin* Pin : Node->Pins)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Available pin: '%s', Direction: %d, Category: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Available pin: '%s', Direction: %d, Category: %s"),
|
||||
*Pin->PinName.ToString(), (int32)Pin->Direction, *Pin->PinType.PinCategory.ToString());
|
||||
}
|
||||
|
||||
@@ -384,7 +385,7 @@ UEdGraphPin* FUnrealMCPCommonUtils::FindPin(UEdGraphNode* Node, const FString& P
|
||||
{
|
||||
if (Pin->PinName.ToString() == PinName && (Direction == EGPD_MAX || Pin->Direction == Direction))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Found exact matching pin: '%s'"), *Pin->PinName.ToString());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Found exact matching pin: '%s'"), *Pin->PinName.ToString());
|
||||
return Pin;
|
||||
}
|
||||
}
|
||||
@@ -395,7 +396,7 @@ UEdGraphPin* FUnrealMCPCommonUtils::FindPin(UEdGraphNode* Node, const FString& P
|
||||
if (Pin->PinName.ToString().Equals(PinName, ESearchCase::IgnoreCase) &&
|
||||
(Direction == EGPD_MAX || Pin->Direction == Direction))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Found case-insensitive matching pin: '%s'"), *Pin->PinName.ToString());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Found case-insensitive matching pin: '%s'"), *Pin->PinName.ToString());
|
||||
return Pin;
|
||||
}
|
||||
}
|
||||
@@ -407,13 +408,13 @@ UEdGraphPin* FUnrealMCPCommonUtils::FindPin(UEdGraphNode* Node, const FString& P
|
||||
{
|
||||
if (Pin->Direction == EGPD_Output && Pin->PinType.PinCategory != UEdGraphSchema_K2::PC_Exec)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT(" - Found fallback data output pin: '%s'"), *Pin->PinName.ToString());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT(" - Found fallback data output pin: '%s'"), *Pin->PinName.ToString());
|
||||
return Pin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Warning, TEXT(" - No matching pin found for '%s'"), *PinName);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT(" - No matching pin found for '%s'"), *PinName);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -501,7 +502,7 @@ UK2Node_Event* FUnrealMCPCommonUtils::FindExistingEventNode(UEdGraph* Graph, con
|
||||
UK2Node_Event* EventNode = Cast<UK2Node_Event>(Node);
|
||||
if (EventNode && EventNode->EventReference.GetMemberName() == FName(*EventName))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Found existing event node with name: %s"), *EventName);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Found existing event node with name: %s"), *EventName);
|
||||
return EventNode;
|
||||
}
|
||||
}
|
||||
@@ -567,7 +568,7 @@ bool FUnrealMCPCommonUtils::SetObjectProperty(UObject* Object, const FString& Pr
|
||||
uint8 ByteValue = static_cast<uint8>(Value->AsNumber());
|
||||
ByteProp->SetPropertyValue(PropertyAddr, ByteValue);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Setting enum property %s to numeric value: %d"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Setting enum property %s to numeric value: %d"),
|
||||
*PropertyName, ByteValue);
|
||||
return true;
|
||||
}
|
||||
@@ -582,7 +583,7 @@ bool FUnrealMCPCommonUtils::SetObjectProperty(UObject* Object, const FString& Pr
|
||||
uint8 ByteValue = FCString::Atoi(*EnumValueName);
|
||||
ByteProp->SetPropertyValue(PropertyAddr, ByteValue);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Setting enum property %s to numeric string value: %s -> %d"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Setting enum property %s to numeric string value: %s -> %d"),
|
||||
*PropertyName, *EnumValueName, ByteValue);
|
||||
return true;
|
||||
}
|
||||
@@ -604,17 +605,17 @@ bool FUnrealMCPCommonUtils::SetObjectProperty(UObject* Object, const FString& Pr
|
||||
{
|
||||
ByteProp->SetPropertyValue(PropertyAddr, static_cast<uint8>(EnumValue));
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Setting enum property %s to name value: %s -> %lld"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Setting enum property %s to name value: %s -> %lld"),
|
||||
*PropertyName, *EnumValueName, EnumValue);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log all possible enum values for debugging
|
||||
UE_LOG(LogTemp, Warning, TEXT("Could not find enum value for '%s'. Available options:"), *EnumValueName);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("Could not find enum value for '%s'. Available options:"), *EnumValueName);
|
||||
for (int32 i = 0; i < EnumDef->NumEnums(); i++)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT(" - %s (value: %d)"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT(" - %s (value: %d)"),
|
||||
*EnumDef->GetNameStringByIndex(i), EnumDef->GetValueByIndex(i));
|
||||
}
|
||||
|
||||
@@ -645,7 +646,7 @@ bool FUnrealMCPCommonUtils::SetObjectProperty(UObject* Object, const FString& Pr
|
||||
int64 EnumValue = static_cast<int64>(Value->AsNumber());
|
||||
UnderlyingNumericProp->SetIntPropertyValue(PropertyAddr, EnumValue);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Setting enum property %s to numeric value: %lld"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Setting enum property %s to numeric value: %lld"),
|
||||
*PropertyName, EnumValue);
|
||||
return true;
|
||||
}
|
||||
@@ -660,7 +661,7 @@ bool FUnrealMCPCommonUtils::SetObjectProperty(UObject* Object, const FString& Pr
|
||||
int64 EnumValue = FCString::Atoi64(*EnumValueName);
|
||||
UnderlyingNumericProp->SetIntPropertyValue(PropertyAddr, EnumValue);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Setting enum property %s to numeric string value: %s -> %lld"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Setting enum property %s to numeric string value: %s -> %lld"),
|
||||
*PropertyName, *EnumValueName, EnumValue);
|
||||
return true;
|
||||
}
|
||||
@@ -682,17 +683,17 @@ bool FUnrealMCPCommonUtils::SetObjectProperty(UObject* Object, const FString& Pr
|
||||
{
|
||||
UnderlyingNumericProp->SetIntPropertyValue(PropertyAddr, EnumValue);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("Setting enum property %s to name value: %s -> %lld"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Setting enum property %s to name value: %s -> %lld"),
|
||||
*PropertyName, *EnumValueName, EnumValue);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log all possible enum values for debugging
|
||||
UE_LOG(LogTemp, Warning, TEXT("Could not find enum value for '%s'. Available options:"), *EnumValueName);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("Could not find enum value for '%s'. Available options:"), *EnumValueName);
|
||||
for (int32 i = 0; i < EnumDef->NumEnums(); i++)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT(" - %s (value: %d)"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT(" - %s (value: %d)"),
|
||||
*EnumDef->GetNameStringByIndex(i), EnumDef->GetValueByIndex(i));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Commands/UnrealMCPEditorCommands.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "Editor.h"
|
||||
#include "EditorViewportClient.h"
|
||||
@@ -40,7 +41,7 @@ TSharedPtr<FJsonObject> FUnrealMCPEditorCommands::HandleCommand(const FString& C
|
||||
{
|
||||
if (CommandType == TEXT("create_actor"))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("'create_actor' command is deprecated and will be removed in a future version. Please use 'spawn_actor' instead."));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("'create_actor' command is deprecated and will be removed in a future version. Please use 'spawn_actor' instead."));
|
||||
}
|
||||
return HandleSpawnActor(Params);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Commands/UnrealMCPProjectCommands.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "GameFramework/InputSettings.h"
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Commands/UnrealMCPUMGCommands.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "Commands/UnrealMCPCommonUtils.h"
|
||||
#include "Editor.h"
|
||||
#include "EditorAssetLibrary.h"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "MCPServerRunnable.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "UnrealMCPBridge.h"
|
||||
#include "Sockets.h"
|
||||
#include "SocketSubsystem.h"
|
||||
@@ -19,7 +20,7 @@ FMCPServerRunnable::FMCPServerRunnable(UUnrealMCPBridge* InBridge, TSharedPtr<FS
|
||||
, ListenerSocket(InListenerSocket)
|
||||
, bRunning(true)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Created server runnable"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Created server runnable"));
|
||||
}
|
||||
|
||||
FMCPServerRunnable::~FMCPServerRunnable()
|
||||
@@ -34,21 +35,21 @@ bool FMCPServerRunnable::Init()
|
||||
|
||||
uint32 FMCPServerRunnable::Run()
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Server thread starting..."));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Server thread starting..."));
|
||||
|
||||
while (bRunning)
|
||||
{
|
||||
// UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Waiting for client connection..."));
|
||||
// UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Waiting for client connection..."));
|
||||
|
||||
bool bPending = false;
|
||||
if (ListenerSocket->HasPendingConnection(bPending) && bPending)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Client connection pending, accepting..."));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Client connection pending, accepting..."));
|
||||
|
||||
ClientSocket = MakeShareable(ListenerSocket->Accept(TEXT("MCPClient")));
|
||||
if (ClientSocket.IsValid())
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Client connection accepted"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Client connection accepted"));
|
||||
|
||||
// Set socket options to improve connection stability
|
||||
ClientSocket->SetNoDelay(true);
|
||||
@@ -64,14 +65,14 @@ uint32 FMCPServerRunnable::Run()
|
||||
{
|
||||
if (BytesRead == 0)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Client disconnected (zero bytes)"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Client disconnected (zero bytes)"));
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert received data to string
|
||||
Buffer[BytesRead] = '\0';
|
||||
FString ReceivedText = UTF8_TO_TCHAR(Buffer);
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Received: %s"), *ReceivedText);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Received: %s"), *ReceivedText);
|
||||
|
||||
// Parse JSON
|
||||
TSharedPtr<FJsonObject> JsonObject;
|
||||
@@ -87,26 +88,26 @@ uint32 FMCPServerRunnable::Run()
|
||||
FString Response = Bridge->ExecuteCommand(CommandType, JsonObject->GetObjectField(TEXT("params")));
|
||||
|
||||
// Log response for debugging
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Sending response: %s"), *Response);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Sending response: %s"), *Response);
|
||||
|
||||
// Send response
|
||||
int32 BytesSent = 0;
|
||||
if (!ClientSocket->Send((uint8*)TCHAR_TO_UTF8(*Response), Response.Len(), BytesSent))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Failed to send response"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Failed to send response"));
|
||||
}
|
||||
else {
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Response sent successfully, bytes: %d"), BytesSent);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Response sent successfully, bytes: %d"), BytesSent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Missing 'type' field in command"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Missing 'type' field in command"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Failed to parse JSON from: %s"), *ReceivedText);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Failed to parse JSON from: %s"), *ReceivedText);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -118,7 +119,7 @@ uint32 FMCPServerRunnable::Run()
|
||||
// Check for "would block" error which isn't a real error for non-blocking sockets
|
||||
if (LastError == SE_EWOULDBLOCK)
|
||||
{
|
||||
UE_LOG(LogTemp, Verbose, TEXT("MCPServerRunnable: Socket would block, continuing..."));
|
||||
UE_LOG(LogUnrealMCP, Verbose, TEXT("MCPServerRunnable: Socket would block, continuing..."));
|
||||
bShouldBreak = false;
|
||||
// Small sleep to prevent tight loop when no data
|
||||
FPlatformProcess::Sleep(0.01f);
|
||||
@@ -126,12 +127,12 @@ uint32 FMCPServerRunnable::Run()
|
||||
// Check for other transient errors we might want to tolerate
|
||||
else if (LastError == SE_EINTR) // Interrupted system call
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Socket read interrupted, continuing..."));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Socket read interrupted, continuing..."));
|
||||
bShouldBreak = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Client disconnected or error. Last error code: %d"), LastError);
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Client disconnected or error. Last error code: %d"), LastError);
|
||||
}
|
||||
|
||||
if (bShouldBreak)
|
||||
@@ -143,7 +144,7 @@ uint32 FMCPServerRunnable::Run()
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Failed to accept client connection"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Failed to accept client connection"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +152,7 @@ uint32 FMCPServerRunnable::Run()
|
||||
FPlatformProcess::Sleep(0.1f);
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Server thread stopping"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Server thread stopping"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -168,44 +169,44 @@ void FMCPServerRunnable::HandleClientConnection(TSharedPtr<FSocket> InClientSock
|
||||
{
|
||||
if (!InClientSocket.IsValid())
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("MCPServerRunnable: Invalid client socket passed to HandleClientConnection"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("MCPServerRunnable: Invalid client socket passed to HandleClientConnection"));
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Starting to handle client connection"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Starting to handle client connection"));
|
||||
|
||||
// Set socket options for better connection stability
|
||||
InClientSocket->SetNonBlocking(false);
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Set socket to blocking mode"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Set socket to blocking mode"));
|
||||
|
||||
// Properly read full message with timeout
|
||||
const int32 MaxBufferSize = 4096;
|
||||
uint8 Buffer[MaxBufferSize];
|
||||
FString MessageBuffer;
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Starting message receive loop"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Starting message receive loop"));
|
||||
|
||||
while (bRunning && InClientSocket.IsValid())
|
||||
{
|
||||
// Log socket state
|
||||
bool bIsConnected = InClientSocket->GetConnectionState() == SCS_Connected;
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Socket state - Connected: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Socket state - Connected: %s"),
|
||||
bIsConnected ? TEXT("true") : TEXT("false"));
|
||||
|
||||
// Log pending data status before receive
|
||||
uint32 PendingDataSize = 0;
|
||||
bool HasPendingData = InClientSocket->HasPendingData(PendingDataSize);
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Before Recv - HasPendingData=%s, Size=%d"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Before Recv - HasPendingData=%s, Size=%d"),
|
||||
HasPendingData ? TEXT("true") : TEXT("false"), PendingDataSize);
|
||||
|
||||
// Try to receive data with timeout
|
||||
int32 BytesRead = 0;
|
||||
bool bReadSuccess = false;
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Attempting to receive data..."));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Attempting to receive data..."));
|
||||
bReadSuccess = InClientSocket->Recv(Buffer, MaxBufferSize, BytesRead, ESocketReceiveFlags::None);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Recv attempt complete - Success=%s, BytesRead=%d"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Recv attempt complete - Success=%s, BytesRead=%d"),
|
||||
bReadSuccess ? TEXT("true") : TEXT("false"), BytesRead);
|
||||
|
||||
if (BytesRead > 0)
|
||||
@@ -216,13 +217,13 @@ void FMCPServerRunnable::HandleClientConnection(TSharedPtr<FSocket> InClientSock
|
||||
{
|
||||
HexData += FString::Printf(TEXT("%02X "), Buffer[i]);
|
||||
}
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Raw data (first 50 bytes hex): %s%s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Raw data (first 50 bytes hex): %s%s"),
|
||||
*HexData, BytesRead > 50 ? TEXT("...") : TEXT(""));
|
||||
|
||||
// Convert and log received data
|
||||
Buffer[BytesRead] = 0; // Null terminate
|
||||
FString ReceivedData = UTF8_TO_TCHAR(Buffer);
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Received data as string: '%s'"), *ReceivedData);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Received data as string: '%s'"), *ReceivedData);
|
||||
|
||||
// Append to message buffer
|
||||
MessageBuffer.Append(ReceivedData);
|
||||
@@ -230,34 +231,34 @@ void FMCPServerRunnable::HandleClientConnection(TSharedPtr<FSocket> InClientSock
|
||||
// Process complete messages (messages are terminated with newline)
|
||||
if (MessageBuffer.Contains(TEXT("\n")))
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Newline detected in buffer, processing messages"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Newline detected in buffer, processing messages"));
|
||||
|
||||
TArray<FString> Messages;
|
||||
MessageBuffer.ParseIntoArray(Messages, TEXT("\n"), true);
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Found %d message(s) in buffer"), Messages.Num());
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Found %d message(s) in buffer"), Messages.Num());
|
||||
|
||||
// Process all complete messages
|
||||
for (int32 i = 0; i < Messages.Num() - 1; ++i)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Processing message %d: '%s'"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Processing message %d: '%s'"),
|
||||
i + 1, *Messages[i]);
|
||||
ProcessMessage(InClientSocket, Messages[i]);
|
||||
}
|
||||
|
||||
// Keep any incomplete message in the buffer
|
||||
MessageBuffer = Messages.Last();
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Remaining buffer after processing: %s"),
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Remaining buffer after processing: %s"),
|
||||
*MessageBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: No complete message yet (no newline detected)"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: No complete message yet (no newline detected)"));
|
||||
}
|
||||
}
|
||||
else if (!bReadSuccess)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Connection closed or error occurred - Last error: %d"),
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Connection closed or error occurred - Last error: %d"),
|
||||
(int32)ISocketSubsystem::Get()->GetLastErrorCode());
|
||||
break;
|
||||
}
|
||||
@@ -266,12 +267,12 @@ void FMCPServerRunnable::HandleClientConnection(TSharedPtr<FSocket> InClientSock
|
||||
FPlatformProcess::Sleep(0.01f);
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Exited message receive loop"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Exited message receive loop"));
|
||||
}
|
||||
|
||||
void FMCPServerRunnable::ProcessMessage(TSharedPtr<FSocket> Client, const FString& Message)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Processing message: %s"), *Message);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Processing message: %s"), *Message);
|
||||
|
||||
// Parse message as JSON
|
||||
TSharedPtr<FJsonObject> JsonMessage;
|
||||
@@ -279,7 +280,7 @@ void FMCPServerRunnable::ProcessMessage(TSharedPtr<FSocket> Client, const FStrin
|
||||
|
||||
if (!FJsonSerializer::Deserialize(Reader, JsonMessage) || !JsonMessage.IsValid())
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Failed to parse message as JSON"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Failed to parse message as JSON"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -289,7 +290,7 @@ void FMCPServerRunnable::ProcessMessage(TSharedPtr<FSocket> Client, const FStrin
|
||||
|
||||
if (!JsonMessage->TryGetStringField(TEXT("command"), CommandType))
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("MCPServerRunnable: Message missing 'command' field"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("MCPServerRunnable: Message missing 'command' field"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -303,7 +304,7 @@ void FMCPServerRunnable::ProcessMessage(TSharedPtr<FSocket> Client, const FStrin
|
||||
}
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Executing command: %s"), *CommandType);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Executing command: %s"), *CommandType);
|
||||
|
||||
// Execute command
|
||||
FString Response = Bridge->ExecuteCommand(CommandType, Params);
|
||||
@@ -312,10 +313,10 @@ void FMCPServerRunnable::ProcessMessage(TSharedPtr<FSocket> Client, const FStrin
|
||||
Response += TEXT("\n");
|
||||
int32 BytesSent = 0;
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("MCPServerRunnable: Sending response: %s"), *Response);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("MCPServerRunnable: Sending response: %s"), *Response);
|
||||
|
||||
if (!Client->Send((uint8*)TCHAR_TO_UTF8(*Response), Response.Len(), BytesSent))
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("MCPServerRunnable: Failed to send response"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("MCPServerRunnable: Failed to send response"));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "UnrealMCPBridge.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "MCPServerRunnable.h"
|
||||
#include "Sockets.h"
|
||||
#include "SocketSubsystem.h"
|
||||
@@ -83,7 +84,7 @@ UUnrealMCPBridge::~UUnrealMCPBridge()
|
||||
// Initialize subsystem
|
||||
void UUnrealMCPBridge::Initialize(FSubsystemCollectionBase& Collection)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("UnrealMCPBridge: Initializing"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("UnrealMCPBridge: Initializing"));
|
||||
|
||||
bIsRunning = false;
|
||||
ListenerSocket = nullptr;
|
||||
@@ -99,7 +100,7 @@ void UUnrealMCPBridge::Initialize(FSubsystemCollectionBase& Collection)
|
||||
// Clean up resources when subsystem is destroyed
|
||||
void UUnrealMCPBridge::Deinitialize()
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("UnrealMCPBridge: Shutting down"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("UnrealMCPBridge: Shutting down"));
|
||||
StopServer();
|
||||
}
|
||||
|
||||
@@ -108,7 +109,7 @@ void UUnrealMCPBridge::StartServer()
|
||||
{
|
||||
if (bIsRunning)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("UnrealMCPBridge: Server is already running"));
|
||||
UE_LOG(LogUnrealMCP, Warning, TEXT("UnrealMCPBridge: Server is already running"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ void UUnrealMCPBridge::StartServer()
|
||||
ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
|
||||
if (!SocketSubsystem)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("UnrealMCPBridge: Failed to get socket subsystem"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("UnrealMCPBridge: Failed to get socket subsystem"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ void UUnrealMCPBridge::StartServer()
|
||||
TSharedPtr<FSocket> NewListenerSocket = MakeShareable(SocketSubsystem->CreateSocket(NAME_Stream, TEXT("UnrealMCPListener"), false));
|
||||
if (!NewListenerSocket.IsValid())
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("UnrealMCPBridge: Failed to create listener socket"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("UnrealMCPBridge: Failed to create listener socket"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,20 +137,20 @@ void UUnrealMCPBridge::StartServer()
|
||||
FIPv4Endpoint Endpoint(ServerAddress, Port);
|
||||
if (!NewListenerSocket->Bind(*Endpoint.ToInternetAddr()))
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("UnrealMCPBridge: Failed to bind listener socket to %s:%d"), *ServerAddress.ToString(), Port);
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("UnrealMCPBridge: Failed to bind listener socket to %s:%d"), *ServerAddress.ToString(), Port);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start listening
|
||||
if (!NewListenerSocket->Listen(5))
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("UnrealMCPBridge: Failed to start listening"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("UnrealMCPBridge: Failed to start listening"));
|
||||
return;
|
||||
}
|
||||
|
||||
ListenerSocket = NewListenerSocket;
|
||||
bIsRunning = true;
|
||||
UE_LOG(LogTemp, Display, TEXT("UnrealMCPBridge: Server started on %s:%d"), *ServerAddress.ToString(), Port);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("UnrealMCPBridge: Server started on %s:%d"), *ServerAddress.ToString(), Port);
|
||||
|
||||
// Start server thread
|
||||
ServerThread = FRunnableThread::Create(
|
||||
@@ -160,7 +161,7 @@ void UUnrealMCPBridge::StartServer()
|
||||
|
||||
if (!ServerThread)
|
||||
{
|
||||
UE_LOG(LogTemp, Error, TEXT("UnrealMCPBridge: Failed to create server thread"));
|
||||
UE_LOG(LogUnrealMCP, Error, TEXT("UnrealMCPBridge: Failed to create server thread"));
|
||||
StopServer();
|
||||
return;
|
||||
}
|
||||
@@ -197,13 +198,13 @@ void UUnrealMCPBridge::StopServer()
|
||||
ListenerSocket.Reset();
|
||||
}
|
||||
|
||||
UE_LOG(LogTemp, Display, TEXT("UnrealMCPBridge: Server stopped"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("UnrealMCPBridge: Server stopped"));
|
||||
}
|
||||
|
||||
// Execute a command received from a client
|
||||
FString UUnrealMCPBridge::ExecuteCommand(const FString& CommandType, const TSharedPtr<FJsonObject>& Params)
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("UnrealMCPBridge: Executing command: %s"), *CommandType);
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("UnrealMCPBridge: Executing command: %s"), *CommandType);
|
||||
|
||||
// Create a promise to wait for the result
|
||||
TPromise<FString> Promise;
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
#include "UnrealMCPModule.h"
|
||||
#include "UnrealMCPLog.h"
|
||||
#include "UnrealMCPBridge.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "EditorSubsystem.h"
|
||||
#include "Editor.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogUnrealMCP);
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FUnrealMCPModule"
|
||||
|
||||
void FUnrealMCPModule::StartupModule()
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Unreal MCP Module has started"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Unreal MCP Module has started"));
|
||||
}
|
||||
|
||||
void FUnrealMCPModule::ShutdownModule()
|
||||
{
|
||||
UE_LOG(LogTemp, Display, TEXT("Unreal MCP Module has shut down"));
|
||||
UE_LOG(LogUnrealMCP, Display, TEXT("Unreal MCP Module has shut down"));
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Logging/LogMacros.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogUnrealMCP, Log, All);
|
||||
@@ -0,0 +1,487 @@
|
||||
#include "ClaudeCodeInitializer.h"
|
||||
#include "UnrealMCPSetupLog.h"
|
||||
#include "ClaudeCodeResultDialog.h"
|
||||
#include "Dom/JsonObject.h"
|
||||
#include "HAL/FileManager.h"
|
||||
#include "HAL/PlatformFileManager.h"
|
||||
#include "HAL/PlatformProcess.h"
|
||||
#include "Misc/App.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Misc/MessageDialog.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/ScopedSlowTask.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "Serialization/JsonSerializer.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FClaudeCodeInitializer"
|
||||
|
||||
void FClaudeCodeInitializer::Run()
|
||||
{
|
||||
if (!IsCppProject())
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Warning, TEXT("Init aborted: not a C++ project (no .Build.cs found)"));
|
||||
FMessageDialog::Open(EAppMsgType::Ok,
|
||||
LOCTEXT("NotCppError", "Claude Code ne peut être initialisé que dans un projet C++."));
|
||||
return;
|
||||
}
|
||||
|
||||
const EAppReturnType::Type Answer = FMessageDialog::Open(EAppMsgType::YesNo,
|
||||
LOCTEXT("ConfirmInit", "Êtes-vous sûr de vouloir initialiser Claude Code pour ce projet ?"));
|
||||
if (Answer != EAppReturnType::Yes)
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("Init cancelled by user"));
|
||||
return;
|
||||
}
|
||||
|
||||
TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(TEXT("UnrealMCP"));
|
||||
if (!Plugin.IsValid())
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("Plugin 'UnrealMCP' not found via IPluginManager"));
|
||||
FMessageDialog::Open(EAppMsgType::Ok,
|
||||
LOCTEXT("PluginNotFound", "Plugin UnrealMCP introuvable."));
|
||||
return;
|
||||
}
|
||||
|
||||
const FString PluginDir = Plugin->GetBaseDir();
|
||||
const FString ProjectDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir());
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("Starting Claude Code init — PluginDir: %s | ProjectDir: %s"), *PluginDir, *ProjectDir);
|
||||
|
||||
FInitResult Result;
|
||||
{
|
||||
FScopedSlowTask SlowTask(5.0f, LOCTEXT("Working", "Initialisation de Claude Code..."));
|
||||
SlowTask.MakeDialog(false, false);
|
||||
|
||||
SlowTask.EnterProgressFrame(1.0f, LOCTEXT("StepCopy", "Vérification du serveur Python..."));
|
||||
Result.Steps.Add(CopyPythonServer(PluginDir, ProjectDir));
|
||||
|
||||
SlowTask.EnterProgressFrame(1.0f, LOCTEXT("StepClaudeAssets", "Copie des commandes et skills Claude Code..."));
|
||||
Result.Steps.Add(CopyClaudeAssets(PluginDir, ProjectDir));
|
||||
|
||||
SlowTask.EnterProgressFrame(1.0f, LOCTEXT("StepMcp", "Vérification de .mcp.json..."));
|
||||
Result.Steps.Add(WriteMcpJson(ProjectDir));
|
||||
|
||||
SlowTask.EnterProgressFrame(1.0f, LOCTEXT("StepSettings", "Vérification des permissions MCP..."));
|
||||
Result.Steps.Add(WriteClaudeLocalSettings(ProjectDir));
|
||||
|
||||
SlowTask.EnterProgressFrame(1.0f, LOCTEXT("StepUv", "Initialisation de l'environnement Python (uv sync)..."));
|
||||
Result.Steps.Add(RunUvSync(ProjectDir));
|
||||
}
|
||||
|
||||
Result.bOverallSuccess = true;
|
||||
for (const FInitStep& Step : Result.Steps)
|
||||
{
|
||||
if (!Step.bSuccess)
|
||||
{
|
||||
Result.bOverallSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Result.bOverallSuccess)
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("Claude Code init completed successfully"));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("Claude Code init finished with errors — check Output Log for details"));
|
||||
}
|
||||
|
||||
FClaudeCodeResultDialog::Show(Result);
|
||||
}
|
||||
|
||||
bool FClaudeCodeInitializer::IsCppProject()
|
||||
{
|
||||
const FString BuildCs = FPaths::ProjectDir()
|
||||
/ TEXT("Source")
|
||||
/ FApp::GetProjectName()
|
||||
/ (FString(FApp::GetProjectName()) + TEXT(".Build.cs"));
|
||||
return FPaths::FileExists(BuildCs);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Validation helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool FClaudeCodeInitializer::IsMcpJsonValid(const FString& ProjectDir)
|
||||
{
|
||||
const FString FilePath = ProjectDir / TEXT(".mcp.json");
|
||||
FString RawContent;
|
||||
if (!FFileHelper::LoadFileToString(RawContent, *FilePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TSharedPtr<FJsonObject> Root;
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(RawContent);
|
||||
if (!FJsonSerializer::Deserialize(Reader, Root) || !Root.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const TSharedPtr<FJsonObject>* McpServers;
|
||||
if (!Root->TryGetObjectField(TEXT("mcpServers"), McpServers))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const TSharedPtr<FJsonObject>* UnrealMCP;
|
||||
if (!(*McpServers)->TryGetObjectField(TEXT("unrealMCP"), UnrealMCP))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FString Command;
|
||||
if (!(*UnrealMCP)->TryGetStringField(TEXT("command"), Command) || Command != TEXT("uv"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const TArray<TSharedPtr<FJsonValue>>* Args;
|
||||
if (!(*UnrealMCP)->TryGetArrayField(TEXT("args"), Args))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const TSharedPtr<FJsonValue>& Arg : *Args)
|
||||
{
|
||||
if (Arg->AsString() == TEXT("unreal_mcp_server.py"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FClaudeCodeInitializer::IsMcpServerFolderValid(const FString& ProjectDir)
|
||||
{
|
||||
const FString EntryPoint = ProjectDir / TEXT(".claude/mcp-server/unreal_mcp_server.py");
|
||||
return FPaths::FileExists(EntryPoint);
|
||||
}
|
||||
|
||||
bool FClaudeCodeInitializer::IsClaudeLocalSettingsValid(const FString& ProjectDir)
|
||||
{
|
||||
const FString FilePath = ProjectDir / TEXT(".claude/settings.local.json");
|
||||
FString RawContent;
|
||||
if (!FFileHelper::LoadFileToString(RawContent, *FilePath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TSharedPtr<FJsonObject> Root;
|
||||
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(RawContent);
|
||||
if (!FJsonSerializer::Deserialize(Reader, Root) || !Root.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const TSharedPtr<FJsonObject>* Permissions;
|
||||
if (!Root->TryGetObjectField(TEXT("permissions"), Permissions))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const TArray<TSharedPtr<FJsonValue>>* Allow;
|
||||
if (!(*Permissions)->TryGetArrayField(TEXT("allow"), Allow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const TSharedPtr<FJsonValue>& Entry : *Allow)
|
||||
{
|
||||
if (Entry->AsString().StartsWith(TEXT("mcp__unrealMCP__")))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Init steps — validate first, act only if needed
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool FClaudeCodeInitializer::CopyDirectoryFiltered(const FString& Src, const FString& Dst)
|
||||
{
|
||||
static const TArray<FString> SkippedDirs = { TEXT(".venv"), TEXT("__pycache__"), TEXT("unreal_mcp.egg-info") };
|
||||
static const TArray<FString> SkippedExts = { TEXT(".log"), TEXT(".bck") };
|
||||
|
||||
IPlatformFile& PF = FPlatformFileManager::Get().GetPlatformFile();
|
||||
PF.CreateDirectoryTree(*Dst);
|
||||
|
||||
bool bAllOk = true;
|
||||
PF.IterateDirectory(*Src, [&](const TCHAR* Path, bool bIsDirectory) -> bool
|
||||
{
|
||||
const FString Name = FPaths::GetCleanFilename(Path);
|
||||
const FString DstPath = Dst / Name;
|
||||
|
||||
if (bIsDirectory)
|
||||
{
|
||||
if (!SkippedDirs.Contains(Name))
|
||||
{
|
||||
bAllOk &= CopyDirectoryFiltered(Path, DstPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const FString Ext = FPaths::GetExtension(Name, /*bIncludeDot*/ true).ToLower();
|
||||
if (!SkippedExts.Contains(Ext))
|
||||
{
|
||||
if (!PF.CopyFile(*DstPath, Path))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Warning, TEXT("[Copy] Failed to copy file: %s"), Path);
|
||||
bAllOk = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return bAllOk;
|
||||
}
|
||||
|
||||
FInitStep FClaudeCodeInitializer::CopyPythonServer(const FString& PluginDir, const FString& ProjectDir)
|
||||
{
|
||||
FInitStep Step;
|
||||
Step.Name = LOCTEXT("StepNameCopy", "Serveur Python (.claude/mcp-server)");
|
||||
|
||||
if (IsMcpServerFolderValid(ProjectDir))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[PythonServer] Already valid — skipping copy"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = TEXT("Déjà présent et valide — aucune modification.");
|
||||
return Step;
|
||||
}
|
||||
|
||||
const FString Src = PluginDir / TEXT("PythonServer");
|
||||
const FString Dst = ProjectDir / TEXT(".claude/mcp-server");
|
||||
|
||||
if (!FPaths::DirectoryExists(Src))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[PythonServer] Source folder not found: %s"), *Src);
|
||||
Step.bSuccess = false;
|
||||
Step.Details = FString::Printf(TEXT("Dossier source introuvable : %s"), *Src);
|
||||
return Step;
|
||||
}
|
||||
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[PythonServer] Copying %s → %s (skipping .venv, __pycache__, egg-info)"), *Src, *Dst);
|
||||
if (CopyDirectoryFiltered(Src, Dst))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[PythonServer] Copy successful"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = FString::Printf(TEXT("Copié : %s → %s"), *Src, *Dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[PythonServer] Copy failed to %s"), *Dst);
|
||||
Step.bSuccess = false;
|
||||
Step.Details = FString::Printf(TEXT("Échec de la copie vers %s"), *Dst);
|
||||
}
|
||||
return Step;
|
||||
}
|
||||
|
||||
FInitStep FClaudeCodeInitializer::CopyClaudeAssets(const FString& PluginDir, const FString& ProjectDir)
|
||||
{
|
||||
FInitStep Step;
|
||||
Step.Name = LOCTEXT("StepNameClaudeAssets", "Commandes & Skills (.claude/commands, .claude/skills)");
|
||||
|
||||
const FString ClaudeSrc = PluginDir / TEXT(".claude");
|
||||
const FString ClaudeDst = ProjectDir / TEXT(".claude");
|
||||
|
||||
// Check if both directories are already present
|
||||
const bool bCommandsOk = FPaths::DirectoryExists(ClaudeDst / TEXT("commands"));
|
||||
const bool bSkillsOk = FPaths::DirectoryExists(ClaudeDst / TEXT("skills"));
|
||||
if (bCommandsOk && bSkillsOk)
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[ClaudeAssets] commands/ and skills/ already present — skipping"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = TEXT("Déjà présents — aucune modification.");
|
||||
return Step;
|
||||
}
|
||||
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[ClaudeAssets] Copying commands/ and skills/ from %s → %s"), *ClaudeSrc, *ClaudeDst);
|
||||
|
||||
bool bAllOk = true;
|
||||
for (const FString& SubDir : { FString(TEXT("commands")), FString(TEXT("skills")) })
|
||||
{
|
||||
const FString Src = ClaudeSrc / SubDir;
|
||||
const FString Dst = ClaudeDst / SubDir;
|
||||
if (FPaths::DirectoryExists(Src))
|
||||
{
|
||||
if (!CopyDirectoryFiltered(Src, Dst))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[ClaudeAssets] Failed to copy %s"), *Src);
|
||||
bAllOk = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Warning, TEXT("[ClaudeAssets] Source not found, skipping: %s"), *Src);
|
||||
}
|
||||
}
|
||||
|
||||
Step.bSuccess = bAllOk;
|
||||
Step.Details = bAllOk
|
||||
? FString::Printf(TEXT("Copié : commands/ et skills/ → %s"), *ClaudeDst)
|
||||
: FString::Printf(TEXT("Échec partiel — voir Output Log pour les détails"));
|
||||
return Step;
|
||||
}
|
||||
|
||||
FInitStep FClaudeCodeInitializer::WriteMcpJson(const FString& ProjectDir)
|
||||
{
|
||||
FInitStep Step;
|
||||
Step.Name = LOCTEXT("StepNameMcp", ".mcp.json");
|
||||
|
||||
if (IsMcpJsonValid(ProjectDir))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[.mcp.json] Already valid — skipping write"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = TEXT("Déjà configuré et valide — aucune modification.");
|
||||
return Step;
|
||||
}
|
||||
|
||||
const FString FilePath = ProjectDir / TEXT(".mcp.json");
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[.mcp.json] Writing %s"), *FilePath);
|
||||
const FString Content =
|
||||
TEXT("{\n")
|
||||
TEXT(" \"mcpServers\": {\n")
|
||||
TEXT(" \"unrealMCP\": {\n")
|
||||
TEXT(" \"type\": \"stdio\",\n")
|
||||
TEXT(" \"command\": \"uv\",\n")
|
||||
TEXT(" \"args\": [\"--directory\", \".claude/mcp-server\", \"run\", \"unreal_mcp_server.py\"]\n")
|
||||
TEXT(" }\n")
|
||||
TEXT(" }\n")
|
||||
TEXT("}\n");
|
||||
|
||||
if (FFileHelper::SaveStringToFile(Content, *FilePath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[.mcp.json] Written successfully"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = FString::Printf(TEXT("Créé : %s"), *FilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[.mcp.json] Failed to write %s"), *FilePath);
|
||||
Step.bSuccess = false;
|
||||
Step.Details = FString::Printf(TEXT("Impossible d'écrire %s"), *FilePath);
|
||||
}
|
||||
return Step;
|
||||
}
|
||||
|
||||
FInitStep FClaudeCodeInitializer::WriteClaudeLocalSettings(const FString& ProjectDir)
|
||||
{
|
||||
FInitStep Step;
|
||||
Step.Name = LOCTEXT("StepNameSettings", "Permissions MCP (.claude/settings.local.json)");
|
||||
|
||||
if (IsClaudeLocalSettingsValid(ProjectDir))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[settings.local.json] Already valid — skipping write"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = TEXT("Déjà configuré et valide — aucune modification.");
|
||||
return Step;
|
||||
}
|
||||
|
||||
const FString ClaudeDir = ProjectDir / TEXT(".claude");
|
||||
const FString FilePath = ClaudeDir / TEXT("settings.local.json");
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[settings.local.json] Writing %s"), *FilePath);
|
||||
|
||||
IPlatformFile& PF = FPlatformFileManager::Get().GetPlatformFile();
|
||||
if (!PF.DirectoryExists(*ClaudeDir))
|
||||
{
|
||||
PF.CreateDirectoryTree(*ClaudeDir);
|
||||
}
|
||||
|
||||
const FString Content =
|
||||
TEXT("{\n")
|
||||
TEXT(" \"permissions\": {\n")
|
||||
TEXT(" \"allow\": [\n")
|
||||
TEXT(" \"mcp__unrealMCP__get_actors_in_level\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__find_actors_by_name\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__spawn_actor\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__delete_actor\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_actor_transform\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__get_actor_properties\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_actor_property\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__spawn_blueprint_actor\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__create_blueprint\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_component_to_blueprint\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_static_mesh_properties\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_component_property\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_physics_properties\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_blueprint_property\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__compile_blueprint\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__find_blueprint_nodes\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_blueprint_event_node\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_blueprint_input_action_node\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_blueprint_function_node\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_blueprint_variable\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_blueprint_self_reference\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_blueprint_get_self_component_reference\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__connect_blueprint_nodes\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__create_input_mapping\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__create_umg_widget_blueprint\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_text_block_to_widget\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_button_to_widget\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__bind_widget_event\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__set_text_block_binding\",\n")
|
||||
TEXT(" \"mcp__unrealMCP__add_widget_to_viewport\"\n")
|
||||
TEXT(" ]\n")
|
||||
TEXT(" }\n")
|
||||
TEXT("}\n");
|
||||
|
||||
if (FFileHelper::SaveStringToFile(Content, *FilePath, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM))
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[settings.local.json] Written successfully"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = FString::Printf(TEXT("Créé : %s"), *FilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[settings.local.json] Failed to write %s"), *FilePath);
|
||||
Step.bSuccess = false;
|
||||
Step.Details = FString::Printf(TEXT("Impossible d'écrire %s"), *FilePath);
|
||||
}
|
||||
return Step;
|
||||
}
|
||||
|
||||
FInitStep FClaudeCodeInitializer::RunUvSync(const FString& ProjectDir)
|
||||
{
|
||||
FInitStep Step;
|
||||
Step.Name = LOCTEXT("StepNameUv", "Environnement Python (uv sync)");
|
||||
|
||||
const FString McpServerDir = ProjectDir / TEXT(".claude/mcp-server");
|
||||
// --no-install-project: install dependencies only, skip building the local package.
|
||||
// Building it spawns a grandchild Python process that inherits invalid pipe handles
|
||||
// from FPlatformProcess::ExecProcess on Windows (os error 6 / ERROR_INVALID_HANDLE).
|
||||
// unreal_mcp_server.py is a plain script — it doesn't need to be installed as a package.
|
||||
const FString Args = FString::Printf(TEXT("sync --directory \"%s\" --no-install-project"), *McpServerDir);
|
||||
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[uv sync] Running: uv %s"), *Args);
|
||||
|
||||
int32 ReturnCode = 0;
|
||||
FString StdOut, StdErr;
|
||||
const bool bLaunched = FPlatformProcess::ExecProcess(
|
||||
TEXT("uv"), *Args, &ReturnCode, &StdOut, &StdErr);
|
||||
|
||||
if (!bLaunched)
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[uv sync] 'uv' not found in PATH"));
|
||||
Step.bSuccess = false;
|
||||
Step.Details = TEXT("uv introuvable dans le PATH. Installez uv (https://docs.astral.sh/uv/) puis relancez.");
|
||||
}
|
||||
else if (ReturnCode == 0)
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("[uv sync] Completed successfully"));
|
||||
Step.bSuccess = true;
|
||||
Step.Details = TEXT("Environnement Python prêt.");
|
||||
}
|
||||
else
|
||||
{
|
||||
const FString ErrorMsg = StdErr.IsEmpty() ? StdOut : StdErr;
|
||||
UE_LOG(LogUnrealMCPSetup, Error, TEXT("[uv sync] Failed (code %d): %s"), ReturnCode, *ErrorMsg);
|
||||
Step.bSuccess = false;
|
||||
Step.Details = ErrorMsg;
|
||||
}
|
||||
return Step;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "ClaudeCodeMenuExtender.h"
|
||||
#include "UnrealMCPSetupLog.h"
|
||||
#include "ClaudeCodeInitializer.h"
|
||||
#include "ToolMenus.h"
|
||||
#include "ToolMenu.h"
|
||||
#include "ToolMenuSection.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FClaudeCodeMenuExtender"
|
||||
|
||||
void FClaudeCodeMenuExtender::Register()
|
||||
{
|
||||
// Pattern from UE5 source (LevelEditorMenu.cpp ExtendMenuBar):
|
||||
// - ExtendMenu + FindOrAddSection(NAME_None)
|
||||
// - InsertPosition on the ENTRY, not the section
|
||||
// - Anchor name is "Help" (short form, not the full qualified name)
|
||||
UToolMenu* MenuBar = UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu");
|
||||
FToolMenuSection& Section = MenuBar->FindOrAddSection(NAME_None);
|
||||
|
||||
FToolMenuEntry& SubMenu = Section.AddSubMenu(
|
||||
"ClaudeCodeMenu",
|
||||
LOCTEXT("MenuLabel", "Claude Code"),
|
||||
LOCTEXT("MenuTooltip", "Claude Code tools for this project"),
|
||||
FNewToolMenuDelegate::CreateStatic(&FClaudeCodeMenuExtender::BuildMenu)
|
||||
);
|
||||
// "Actor" in the menu bar is the entry named "Actions" (dynamic label, see LevelEditorMenu.cpp).
|
||||
// Using After("Actions") places Claude Code between Actor and Help.
|
||||
SubMenu.InsertPosition = FToolMenuInsert("Actions", EToolMenuInsertType::After);
|
||||
}
|
||||
|
||||
void FClaudeCodeMenuExtender::BuildMenu(UToolMenu* Menu)
|
||||
{
|
||||
FToolMenuSection& Section = Menu->FindOrAddSection("ClaudeCodeActions");
|
||||
Section.AddMenuEntry(
|
||||
"InitClaudeCode",
|
||||
LOCTEXT("InitLabel", "Init Claude Code"),
|
||||
LOCTEXT("InitTooltip", "Initialisation de Claude Code pour ce projet"),
|
||||
FSlateIcon(),
|
||||
FUIAction(FExecuteAction::CreateStatic(&FClaudeCodeMenuExtender::OnInitClaudeCodeClicked))
|
||||
);
|
||||
}
|
||||
|
||||
void FClaudeCodeMenuExtender::OnInitClaudeCodeClicked()
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("User clicked 'Init Claude Code'"));
|
||||
FClaudeCodeInitializer::Run();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,138 @@
|
||||
#include "ClaudeCodeResultDialog.h"
|
||||
#include "Framework/Application/SlateApplication.h"
|
||||
#include "Widgets/SBoxPanel.h"
|
||||
#include "Widgets/SWindow.h"
|
||||
#include "Widgets/Input/SButton.h"
|
||||
#include "Widgets/Layout/SBorder.h"
|
||||
#include "Widgets/Layout/SScrollBox.h"
|
||||
#include "Widgets/Layout/SSeparator.h"
|
||||
#include "Widgets/Text/STextBlock.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FClaudeCodeResultDialog"
|
||||
|
||||
void FClaudeCodeResultDialog::Show(const FInitResult& Result)
|
||||
{
|
||||
TSharedRef<SWindow> Window = SNew(SWindow)
|
||||
.Title(LOCTEXT("DialogTitle", "Claude Code — Résultat de l'initialisation"))
|
||||
.ClientSize(FVector2D(540, 340))
|
||||
.SupportsMaximize(false)
|
||||
.SupportsMinimize(false)
|
||||
.IsTopmostWindow(true);
|
||||
|
||||
Window->SetContent(
|
||||
SNew(SClaudeCodeResultDialog)
|
||||
.InitResult(Result)
|
||||
.ParentWindow(Window)
|
||||
);
|
||||
|
||||
FSlateApplication::Get().AddModalWindow(Window, FSlateApplication::Get().GetActiveTopLevelWindow());
|
||||
}
|
||||
|
||||
void SClaudeCodeResultDialog::Construct(const FArguments& InArgs)
|
||||
{
|
||||
ParentWindow = InArgs._ParentWindow;
|
||||
const FInitResult& Result = InArgs._InitResult;
|
||||
|
||||
TSharedRef<SVerticalBox> StepsList = SNew(SVerticalBox);
|
||||
|
||||
for (const FInitStep& Step : Result.Steps)
|
||||
{
|
||||
const FString Icon = Step.bSuccess ? TEXT("✓") : TEXT("✗");
|
||||
const FSlateColor IconColor = Step.bSuccess
|
||||
? FSlateColor(FLinearColor(0.2f, 0.85f, 0.2f))
|
||||
: FSlateColor(FLinearColor(0.9f, 0.2f, 0.2f));
|
||||
|
||||
StepsList->AddSlot()
|
||||
.AutoHeight()
|
||||
.Padding(4.f, 4.f)
|
||||
[
|
||||
SNew(SHorizontalBox)
|
||||
+ SHorizontalBox::Slot()
|
||||
.AutoWidth()
|
||||
.VAlign(VAlign_Top)
|
||||
.Padding(0.f, 1.f, 10.f, 0.f)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString(Icon))
|
||||
.ColorAndOpacity(IconColor)
|
||||
]
|
||||
+ SHorizontalBox::Slot()
|
||||
.FillWidth(1.f)
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(Step.Name)
|
||||
]
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(0.f, 2.f, 0.f, 0.f)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(FText::FromString(Step.Details))
|
||||
.ColorAndOpacity(FSlateColor(FLinearColor(0.55f, 0.55f, 0.55f)))
|
||||
.AutoWrapText(true)
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
const FText StatusText = Result.bOverallSuccess
|
||||
? LOCTEXT("StatusOk", "Initialisation réussie. Redémarrez Claude Code pour activer le serveur MCP.")
|
||||
: LOCTEXT("StatusFail", "L'initialisation a rencontré des erreurs. Consultez les détails ci-dessus.");
|
||||
|
||||
const FSlateColor StatusColor = Result.bOverallSuccess
|
||||
? FSlateColor(FLinearColor(0.2f, 0.85f, 0.2f))
|
||||
: FSlateColor(FLinearColor(0.9f, 0.2f, 0.2f));
|
||||
|
||||
ChildSlot
|
||||
[
|
||||
SNew(SVerticalBox)
|
||||
+ SVerticalBox::Slot()
|
||||
.FillHeight(1.f)
|
||||
.Padding(14.f, 12.f)
|
||||
[
|
||||
SNew(SScrollBox)
|
||||
+ SScrollBox::Slot()
|
||||
[
|
||||
StepsList
|
||||
]
|
||||
]
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
[
|
||||
SNew(SSeparator)
|
||||
]
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.Padding(14.f, 8.f)
|
||||
[
|
||||
SNew(STextBlock)
|
||||
.Text(StatusText)
|
||||
.ColorAndOpacity(StatusColor)
|
||||
.AutoWrapText(true)
|
||||
]
|
||||
+ SVerticalBox::Slot()
|
||||
.AutoHeight()
|
||||
.HAlign(HAlign_Right)
|
||||
.Padding(14.f, 4.f, 14.f, 14.f)
|
||||
[
|
||||
SNew(SButton)
|
||||
.Text(LOCTEXT("CloseBtn", "Fermer"))
|
||||
.OnClicked(this, &SClaudeCodeResultDialog::OnCloseClicked)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
FReply SClaudeCodeResultDialog::OnCloseClicked()
|
||||
{
|
||||
if (ParentWindow.IsValid())
|
||||
{
|
||||
ParentWindow->RequestDestroyWindow();
|
||||
}
|
||||
return FReply::Handled();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "UnrealMCPSetupModule.h"
|
||||
#include "UnrealMCPSetupLog.h"
|
||||
#include "ClaudeCodeMenuExtender.h"
|
||||
#include "ToolMenus.h"
|
||||
#include "Editor.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogUnrealMCPSetup);
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FUnrealMCPSetupModule"
|
||||
|
||||
void FUnrealMCPSetupModule::StartupModule()
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("UnrealMCPSetup module started"));
|
||||
if (GEditor)
|
||||
{
|
||||
UToolMenus::RegisterStartupCallback(
|
||||
FSimpleMulticastDelegate::FDelegate::CreateRaw(
|
||||
this, &FUnrealMCPSetupModule::RegisterMenus));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Warning, TEXT("GEditor not available — Claude Code menu will not be registered"));
|
||||
}
|
||||
}
|
||||
|
||||
void FUnrealMCPSetupModule::ShutdownModule()
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("UnrealMCPSetup module shut down"));
|
||||
UToolMenus::UnRegisterStartupCallback(this);
|
||||
}
|
||||
|
||||
void FUnrealMCPSetupModule::RegisterMenus()
|
||||
{
|
||||
UE_LOG(LogUnrealMCPSetup, Display, TEXT("Registering Claude Code menu"));
|
||||
FClaudeCodeMenuExtender::Register();
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FUnrealMCPSetupModule, UnrealMCPSetup)
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ClaudeCodeTypes.h"
|
||||
|
||||
class FClaudeCodeInitializer
|
||||
{
|
||||
public:
|
||||
static void Run();
|
||||
|
||||
private:
|
||||
static bool IsCppProject();
|
||||
|
||||
static FInitStep CopyPythonServer(const FString& PluginDir, const FString& ProjectDir);
|
||||
static FInitStep CopyClaudeAssets(const FString& PluginDir, const FString& ProjectDir);
|
||||
static FInitStep WriteMcpJson(const FString& ProjectDir);
|
||||
static FInitStep WriteClaudeLocalSettings(const FString& ProjectDir);
|
||||
static FInitStep RunUvSync(const FString& ProjectDir);
|
||||
|
||||
// Validation helpers (used when .claude/ already exists)
|
||||
static bool IsMcpJsonValid(const FString& ProjectDir);
|
||||
static bool IsMcpServerFolderValid(const FString& ProjectDir);
|
||||
static bool IsClaudeLocalSettingsValid(const FString& ProjectDir);
|
||||
|
||||
// Recursive copy that skips .venv, __pycache__, *.egg-info (locked / generated files)
|
||||
static bool CopyDirectoryFiltered(const FString& Src, const FString& Dst);
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
class UToolMenu;
|
||||
|
||||
class FClaudeCodeMenuExtender
|
||||
{
|
||||
public:
|
||||
static void Register();
|
||||
|
||||
private:
|
||||
static void BuildMenu(UToolMenu* Menu);
|
||||
static void OnInitClaudeCodeClicked();
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "ClaudeCodeTypes.h"
|
||||
#include "Widgets/SCompoundWidget.h"
|
||||
|
||||
class FClaudeCodeResultDialog
|
||||
{
|
||||
public:
|
||||
static void Show(const FInitResult& Result);
|
||||
};
|
||||
|
||||
class SClaudeCodeResultDialog : public SCompoundWidget
|
||||
{
|
||||
public:
|
||||
SLATE_BEGIN_ARGS(SClaudeCodeResultDialog) {}
|
||||
SLATE_ARGUMENT(FInitResult, InitResult)
|
||||
SLATE_ARGUMENT(TSharedPtr<SWindow>, ParentWindow)
|
||||
SLATE_END_ARGS()
|
||||
|
||||
void Construct(const FArguments& InArgs);
|
||||
|
||||
private:
|
||||
FReply OnCloseClicked();
|
||||
|
||||
TSharedPtr<SWindow> ParentWindow;
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
struct FInitStep
|
||||
{
|
||||
FText Name;
|
||||
bool bSuccess = false;
|
||||
FString Details;
|
||||
};
|
||||
|
||||
struct FInitResult
|
||||
{
|
||||
bool bOverallSuccess = false;
|
||||
TArray<FInitStep> Steps;
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "Logging/LogMacros.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogUnrealMCPSetup, Log, All);
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FUnrealMCPSetupModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
private:
|
||||
void RegisterMenus();
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class UnrealMCPSetup : ModuleRules
|
||||
{
|
||||
public UnrealMCPSetup(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
IWYUSupport = IWYUSupport.Full;
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[]
|
||||
{
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"Slate",
|
||||
"SlateCore",
|
||||
"UnrealEd",
|
||||
"ToolMenus",
|
||||
"Projects",
|
||||
"Json",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,16 @@
|
||||
"Mac",
|
||||
"Linux"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "UnrealMCPSetup",
|
||||
"Type": "Editor",
|
||||
"LoadingPhase": "PostEngineInit",
|
||||
"WhitelistPlatforms": [
|
||||
"Win64",
|
||||
"Mac",
|
||||
"Linux"
|
||||
]
|
||||
}
|
||||
],
|
||||
"Plugins": [
|
||||
|
||||
Reference in new issue
Block a user