flockbay 0.10.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/bin/flockbay-mcp.mjs +56 -0
- package/bin/flockbay.mjs +78 -0
- package/dist/codex/flockbayMcpStdioBridge.cjs +383 -0
- package/dist/codex/flockbayMcpStdioBridge.d.cts +2 -0
- package/dist/codex/flockbayMcpStdioBridge.d.mts +2 -0
- package/dist/codex/flockbayMcpStdioBridge.mjs +381 -0
- package/dist/flockbayScreenshotGate-DJX3Is5d.mjs +136 -0
- package/dist/flockbayScreenshotGate-DkxU24cR.cjs +138 -0
- package/dist/index--o4BPz5o.cjs +10311 -0
- package/dist/index-CUp3juDS.mjs +10268 -0
- package/dist/index.cjs +43 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +40 -0
- package/dist/lib.cjs +33 -0
- package/dist/lib.d.cts +957 -0
- package/dist/lib.d.mts +957 -0
- package/dist/lib.mjs +23 -0
- package/dist/runCodex-D3eT-TvB.cjs +3449 -0
- package/dist/runCodex-o6PCbHQ7.mjs +3446 -0
- package/dist/runGemini-Bt0oEj_g.mjs +3183 -0
- package/dist/runGemini-CBxZp6I7.cjs +3185 -0
- package/dist/types-C-jnUdn_.cjs +4498 -0
- package/dist/types-DGd6ea2Z.mjs +4450 -0
- package/kits/kit.open_world/kit.json +59 -0
- package/package.json +130 -0
- package/scripts/claude_local_launcher.cjs +73 -0
- package/scripts/claude_remote_launcher.cjs +16 -0
- package/scripts/claude_version_utils.cjs +391 -0
- package/scripts/ripgrep_launcher.cjs +33 -0
- package/scripts/session_hook_forwarder.cjs +49 -0
- package/scripts/test-codex-abort-history.mjs +77 -0
- package/scripts/unpack-tools.cjs +222 -0
- package/tools/licenses/difftastic-LICENSE +21 -0
- package/tools/licenses/ripgrep-LICENSE +3 -0
- package/tools/unreal-mcp/UPSTREAM_VERSION.md +8 -0
- package/tools/unreal-mcp/upstream/Docs/README.md +8 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/README.md +7 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/actor_tools.md +184 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/blueprint_tools.md +268 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/editor_tools.md +104 -0
- package/tools/unreal-mcp/upstream/Docs/Tools/node_tools.md +274 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Config/FilterPlugin.ini +8 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintCommands.cpp +1160 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPBlueprintNodeCommands.cpp +924 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommonUtils.cpp +709 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +896 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPProjectCommands.cpp +72 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPUMGCommands.cpp +544 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/MCPServerRunnable.cpp +321 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPBridge.cpp +419 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/UnrealMCPModule.cpp +21 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintCommands.h +34 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPBlueprintNodeCommands.h +27 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPCommonUtils.h +59 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPEditorCommands.h +40 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPProjectCommands.h +20 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/Commands/UnrealMCPUMGCommands.h +82 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/MCPServerRunnable.h +34 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/UnrealMCPBridge.h +64 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Public/UnrealMCPModule.h +22 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +78 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/UnrealMCP.uplugin +36 -0
- package/tools/unreal-mcp/upstream/Python/README.md +40 -0
- package/tools/unreal-mcp/upstream/Python/pyproject.toml +22 -0
- package/tools/unreal-mcp/upstream/Python/scripts/actors/test_cube.py +203 -0
- package/tools/unreal-mcp/upstream/Python/scripts/blueprints/test_create_and_spawn_blueprints_with_different_components.py +497 -0
- package/tools/unreal-mcp/upstream/Python/scripts/blueprints/test_create_and_spawn_cube_blueprint.py +194 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_component_reference.py +267 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_create_bird_blueprint_with_input_and_camera.py +618 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_input_mapping.py +366 -0
- package/tools/unreal-mcp/upstream/Python/scripts/node/test_physics_variables.py +390 -0
- package/tools/unreal-mcp/upstream/Python/tools/blueprint_tools.py +420 -0
- package/tools/unreal-mcp/upstream/Python/tools/editor_tools.py +369 -0
- package/tools/unreal-mcp/upstream/Python/tools/node_tools.py +430 -0
- package/tools/unreal-mcp/upstream/Python/tools/project_tools.py +64 -0
- package/tools/unreal-mcp/upstream/Python/tools/umg_tools.py +333 -0
- package/tools/unreal-mcp/upstream/Python/unreal_mcp_server.py +398 -0
- package/tools/unreal-mcp/upstream/Python/uv.lock +521 -0
|
@@ -0,0 +1,1160 @@
|
|
|
1
|
+
#include "Commands/UnrealMCPBlueprintCommands.h"
|
|
2
|
+
#include "Commands/UnrealMCPCommonUtils.h"
|
|
3
|
+
#include "Engine/Blueprint.h"
|
|
4
|
+
#include "Engine/BlueprintGeneratedClass.h"
|
|
5
|
+
#include "Factories/BlueprintFactory.h"
|
|
6
|
+
#include "EdGraphSchema_K2.h"
|
|
7
|
+
#include "K2Node_Event.h"
|
|
8
|
+
#include "K2Node_VariableGet.h"
|
|
9
|
+
#include "K2Node_VariableSet.h"
|
|
10
|
+
#include "Components/StaticMeshComponent.h"
|
|
11
|
+
#include "Components/BoxComponent.h"
|
|
12
|
+
#include "Components/SphereComponent.h"
|
|
13
|
+
#include "Kismet2/BlueprintEditorUtils.h"
|
|
14
|
+
#include "Kismet2/KismetEditorUtilities.h"
|
|
15
|
+
#include "Engine/SimpleConstructionScript.h"
|
|
16
|
+
#include "Engine/SCS_Node.h"
|
|
17
|
+
#include "UObject/Field.h"
|
|
18
|
+
#include "UObject/FieldPath.h"
|
|
19
|
+
#include "EditorAssetLibrary.h"
|
|
20
|
+
#include "AssetRegistry/AssetRegistryModule.h"
|
|
21
|
+
#include "GameFramework/Actor.h"
|
|
22
|
+
#include "GameFramework/Pawn.h"
|
|
23
|
+
|
|
24
|
+
FUnrealMCPBlueprintCommands::FUnrealMCPBlueprintCommands()
|
|
25
|
+
{
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleCommand(const FString& CommandType, const TSharedPtr<FJsonObject>& Params)
|
|
29
|
+
{
|
|
30
|
+
if (CommandType == TEXT("create_blueprint"))
|
|
31
|
+
{
|
|
32
|
+
return HandleCreateBlueprint(Params);
|
|
33
|
+
}
|
|
34
|
+
else if (CommandType == TEXT("add_component_to_blueprint"))
|
|
35
|
+
{
|
|
36
|
+
return HandleAddComponentToBlueprint(Params);
|
|
37
|
+
}
|
|
38
|
+
else if (CommandType == TEXT("set_component_property"))
|
|
39
|
+
{
|
|
40
|
+
return HandleSetComponentProperty(Params);
|
|
41
|
+
}
|
|
42
|
+
else if (CommandType == TEXT("set_physics_properties"))
|
|
43
|
+
{
|
|
44
|
+
return HandleSetPhysicsProperties(Params);
|
|
45
|
+
}
|
|
46
|
+
else if (CommandType == TEXT("compile_blueprint"))
|
|
47
|
+
{
|
|
48
|
+
return HandleCompileBlueprint(Params);
|
|
49
|
+
}
|
|
50
|
+
else if (CommandType == TEXT("spawn_blueprint_actor"))
|
|
51
|
+
{
|
|
52
|
+
return HandleSpawnBlueprintActor(Params);
|
|
53
|
+
}
|
|
54
|
+
else if (CommandType == TEXT("set_blueprint_property"))
|
|
55
|
+
{
|
|
56
|
+
return HandleSetBlueprintProperty(Params);
|
|
57
|
+
}
|
|
58
|
+
else if (CommandType == TEXT("set_static_mesh_properties"))
|
|
59
|
+
{
|
|
60
|
+
return HandleSetStaticMeshProperties(Params);
|
|
61
|
+
}
|
|
62
|
+
else if (CommandType == TEXT("set_pawn_properties"))
|
|
63
|
+
{
|
|
64
|
+
return HandleSetPawnProperties(Params);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Unknown blueprint command: %s"), *CommandType));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleCreateBlueprint(const TSharedPtr<FJsonObject>& Params)
|
|
71
|
+
{
|
|
72
|
+
// Get required parameters
|
|
73
|
+
FString BlueprintName;
|
|
74
|
+
if (!Params->TryGetStringField(TEXT("name"), BlueprintName))
|
|
75
|
+
{
|
|
76
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'name' parameter"));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check if blueprint already exists
|
|
80
|
+
FString PackagePath = TEXT("/Game/Blueprints/");
|
|
81
|
+
FString AssetName = BlueprintName;
|
|
82
|
+
if (UEditorAssetLibrary::DoesAssetExist(PackagePath + AssetName))
|
|
83
|
+
{
|
|
84
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint already exists: %s"), *BlueprintName));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Create the blueprint factory
|
|
88
|
+
UBlueprintFactory* Factory = NewObject<UBlueprintFactory>();
|
|
89
|
+
|
|
90
|
+
// Handle parent class
|
|
91
|
+
FString ParentClass;
|
|
92
|
+
Params->TryGetStringField(TEXT("parent_class"), ParentClass);
|
|
93
|
+
|
|
94
|
+
// Default to Actor if no parent class specified
|
|
95
|
+
UClass* SelectedParentClass = AActor::StaticClass();
|
|
96
|
+
|
|
97
|
+
// Try to find the specified parent class
|
|
98
|
+
if (!ParentClass.IsEmpty())
|
|
99
|
+
{
|
|
100
|
+
FString ClassName = ParentClass;
|
|
101
|
+
if (!ClassName.StartsWith(TEXT("A")))
|
|
102
|
+
{
|
|
103
|
+
ClassName = TEXT("A") + ClassName;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// First try direct StaticClass lookup for common classes
|
|
107
|
+
UClass* FoundClass = nullptr;
|
|
108
|
+
if (ClassName == TEXT("APawn"))
|
|
109
|
+
{
|
|
110
|
+
FoundClass = APawn::StaticClass();
|
|
111
|
+
}
|
|
112
|
+
else if (ClassName == TEXT("AActor"))
|
|
113
|
+
{
|
|
114
|
+
FoundClass = AActor::StaticClass();
|
|
115
|
+
}
|
|
116
|
+
else
|
|
117
|
+
{
|
|
118
|
+
// Try loading the class using LoadClass which is more reliable than FindObject
|
|
119
|
+
const FString ClassPath = FString::Printf(TEXT("/Script/Engine.%s"), *ClassName);
|
|
120
|
+
FoundClass = LoadClass<AActor>(nullptr, *ClassPath);
|
|
121
|
+
|
|
122
|
+
if (!FoundClass)
|
|
123
|
+
{
|
|
124
|
+
// Try alternate paths if not found
|
|
125
|
+
const FString GameClassPath = FString::Printf(TEXT("/Script/Game.%s"), *ClassName);
|
|
126
|
+
FoundClass = LoadClass<AActor>(nullptr, *GameClassPath);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (FoundClass)
|
|
131
|
+
{
|
|
132
|
+
SelectedParentClass = FoundClass;
|
|
133
|
+
UE_LOG(LogTemp, Log, TEXT("Successfully set parent class to '%s'"), *ClassName);
|
|
134
|
+
}
|
|
135
|
+
else
|
|
136
|
+
{
|
|
137
|
+
UE_LOG(LogTemp, Warning, TEXT("Could not find specified parent class '%s' at paths: /Script/Engine.%s or /Script/Game.%s, defaulting to AActor"),
|
|
138
|
+
*ClassName, *ClassName, *ClassName);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
Factory->ParentClass = SelectedParentClass;
|
|
143
|
+
|
|
144
|
+
// Create the blueprint
|
|
145
|
+
UPackage* Package = CreatePackage(*(PackagePath + AssetName));
|
|
146
|
+
UBlueprint* NewBlueprint = Cast<UBlueprint>(Factory->FactoryCreateNew(UBlueprint::StaticClass(), Package, *AssetName, RF_Standalone | RF_Public, nullptr, GWarn));
|
|
147
|
+
|
|
148
|
+
if (NewBlueprint)
|
|
149
|
+
{
|
|
150
|
+
// Notify the asset registry
|
|
151
|
+
FAssetRegistryModule::AssetCreated(NewBlueprint);
|
|
152
|
+
|
|
153
|
+
// Mark the package dirty
|
|
154
|
+
Package->MarkPackageDirty();
|
|
155
|
+
|
|
156
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
157
|
+
ResultObj->SetStringField(TEXT("name"), AssetName);
|
|
158
|
+
ResultObj->SetStringField(TEXT("path"), PackagePath + AssetName);
|
|
159
|
+
return ResultObj;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to create blueprint"));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleAddComponentToBlueprint(const TSharedPtr<FJsonObject>& Params)
|
|
166
|
+
{
|
|
167
|
+
// Get required parameters
|
|
168
|
+
FString BlueprintName;
|
|
169
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
170
|
+
{
|
|
171
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
FString ComponentType;
|
|
175
|
+
if (!Params->TryGetStringField(TEXT("component_type"), ComponentType))
|
|
176
|
+
{
|
|
177
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'type' parameter"));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
FString ComponentName;
|
|
181
|
+
if (!Params->TryGetStringField(TEXT("component_name"), ComponentName))
|
|
182
|
+
{
|
|
183
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'name' parameter"));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Find the blueprint
|
|
187
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
188
|
+
if (!Blueprint)
|
|
189
|
+
{
|
|
190
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Create the component - dynamically find the component class by name
|
|
194
|
+
UClass* ComponentClass = nullptr;
|
|
195
|
+
|
|
196
|
+
// Try to find the class with exact name first
|
|
197
|
+
ComponentClass = FindObject<UClass>(ANY_PACKAGE, *ComponentType);
|
|
198
|
+
|
|
199
|
+
// If not found, try with "Component" suffix
|
|
200
|
+
if (!ComponentClass && !ComponentType.EndsWith(TEXT("Component")))
|
|
201
|
+
{
|
|
202
|
+
FString ComponentTypeWithSuffix = ComponentType + TEXT("Component");
|
|
203
|
+
ComponentClass = FindObject<UClass>(ANY_PACKAGE, *ComponentTypeWithSuffix);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// If still not found, try with "U" prefix
|
|
207
|
+
if (!ComponentClass && !ComponentType.StartsWith(TEXT("U")))
|
|
208
|
+
{
|
|
209
|
+
FString ComponentTypeWithPrefix = TEXT("U") + ComponentType;
|
|
210
|
+
ComponentClass = FindObject<UClass>(ANY_PACKAGE, *ComponentTypeWithPrefix);
|
|
211
|
+
|
|
212
|
+
// Try with both prefix and suffix
|
|
213
|
+
if (!ComponentClass && !ComponentType.EndsWith(TEXT("Component")))
|
|
214
|
+
{
|
|
215
|
+
FString ComponentTypeWithBoth = TEXT("U") + ComponentType + TEXT("Component");
|
|
216
|
+
ComponentClass = FindObject<UClass>(ANY_PACKAGE, *ComponentTypeWithBoth);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Verify that the class is a valid component type
|
|
221
|
+
if (!ComponentClass || !ComponentClass->IsChildOf(UActorComponent::StaticClass()))
|
|
222
|
+
{
|
|
223
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Unknown component type: %s"), *ComponentType));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Add the component to the blueprint
|
|
227
|
+
USCS_Node* NewNode = Blueprint->SimpleConstructionScript->CreateNode(ComponentClass, *ComponentName);
|
|
228
|
+
if (NewNode)
|
|
229
|
+
{
|
|
230
|
+
// Set transform if provided
|
|
231
|
+
USceneComponent* SceneComponent = Cast<USceneComponent>(NewNode->ComponentTemplate);
|
|
232
|
+
if (SceneComponent)
|
|
233
|
+
{
|
|
234
|
+
if (Params->HasField(TEXT("location")))
|
|
235
|
+
{
|
|
236
|
+
SceneComponent->SetRelativeLocation(FUnrealMCPCommonUtils::GetVectorFromJson(Params, TEXT("location")));
|
|
237
|
+
}
|
|
238
|
+
if (Params->HasField(TEXT("rotation")))
|
|
239
|
+
{
|
|
240
|
+
SceneComponent->SetRelativeRotation(FUnrealMCPCommonUtils::GetRotatorFromJson(Params, TEXT("rotation")));
|
|
241
|
+
}
|
|
242
|
+
if (Params->HasField(TEXT("scale")))
|
|
243
|
+
{
|
|
244
|
+
SceneComponent->SetRelativeScale3D(FUnrealMCPCommonUtils::GetVectorFromJson(Params, TEXT("scale")));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Add to root if no parent specified
|
|
249
|
+
Blueprint->SimpleConstructionScript->AddNode(NewNode);
|
|
250
|
+
|
|
251
|
+
// Compile the blueprint
|
|
252
|
+
FKismetEditorUtilities::CompileBlueprint(Blueprint);
|
|
253
|
+
|
|
254
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
255
|
+
ResultObj->SetStringField(TEXT("component_name"), ComponentName);
|
|
256
|
+
ResultObj->SetStringField(TEXT("component_type"), ComponentType);
|
|
257
|
+
return ResultObj;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to add component to blueprint"));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetComponentProperty(const TSharedPtr<FJsonObject>& Params)
|
|
264
|
+
{
|
|
265
|
+
// Get required parameters
|
|
266
|
+
FString BlueprintName;
|
|
267
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
268
|
+
{
|
|
269
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
FString ComponentName;
|
|
273
|
+
if (!Params->TryGetStringField(TEXT("component_name"), ComponentName))
|
|
274
|
+
{
|
|
275
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'component_name' parameter"));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
FString PropertyName;
|
|
279
|
+
if (!Params->TryGetStringField(TEXT("property_name"), PropertyName))
|
|
280
|
+
{
|
|
281
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'property_name' parameter"));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Log all input parameters for debugging
|
|
285
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Blueprint: %s, Component: %s, Property: %s"),
|
|
286
|
+
*BlueprintName, *ComponentName, *PropertyName);
|
|
287
|
+
|
|
288
|
+
// Log property_value if available
|
|
289
|
+
if (Params->HasField(TEXT("property_value")))
|
|
290
|
+
{
|
|
291
|
+
TSharedPtr<FJsonValue> JsonValue = Params->Values.FindRef(TEXT("property_value"));
|
|
292
|
+
FString ValueType;
|
|
293
|
+
|
|
294
|
+
switch(JsonValue->Type)
|
|
295
|
+
{
|
|
296
|
+
case EJson::Boolean: ValueType = FString::Printf(TEXT("Boolean: %s"), JsonValue->AsBool() ? TEXT("true") : TEXT("false")); break;
|
|
297
|
+
case EJson::Number: ValueType = FString::Printf(TEXT("Number: %f"), JsonValue->AsNumber()); break;
|
|
298
|
+
case EJson::String: ValueType = FString::Printf(TEXT("String: %s"), *JsonValue->AsString()); break;
|
|
299
|
+
case EJson::Array: ValueType = TEXT("Array"); break;
|
|
300
|
+
case EJson::Object: ValueType = TEXT("Object"); break;
|
|
301
|
+
default: ValueType = TEXT("Unknown"); break;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Value Type: %s"), *ValueType);
|
|
305
|
+
}
|
|
306
|
+
else
|
|
307
|
+
{
|
|
308
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - No property_value provided"));
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Find the blueprint
|
|
312
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
313
|
+
if (!Blueprint)
|
|
314
|
+
{
|
|
315
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Blueprint not found: %s"), *BlueprintName);
|
|
316
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
317
|
+
}
|
|
318
|
+
else
|
|
319
|
+
{
|
|
320
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Blueprint found: %s (Class: %s)"),
|
|
321
|
+
*BlueprintName,
|
|
322
|
+
Blueprint->GeneratedClass ? *Blueprint->GeneratedClass->GetName() : TEXT("NULL"));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Find the component
|
|
326
|
+
USCS_Node* ComponentNode = nullptr;
|
|
327
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Searching for component %s in blueprint nodes"), *ComponentName);
|
|
328
|
+
|
|
329
|
+
if (!Blueprint->SimpleConstructionScript)
|
|
330
|
+
{
|
|
331
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - SimpleConstructionScript is NULL for blueprint %s"), *BlueprintName);
|
|
332
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Invalid blueprint construction script"));
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
for (USCS_Node* Node : Blueprint->SimpleConstructionScript->GetAllNodes())
|
|
336
|
+
{
|
|
337
|
+
if (Node)
|
|
338
|
+
{
|
|
339
|
+
UE_LOG(LogTemp, Verbose, TEXT("SetComponentProperty - Found node: %s"), *Node->GetVariableName().ToString());
|
|
340
|
+
if (Node->GetVariableName().ToString() == ComponentName)
|
|
341
|
+
{
|
|
342
|
+
ComponentNode = Node;
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else
|
|
347
|
+
{
|
|
348
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Found NULL node in blueprint"));
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (!ComponentNode)
|
|
353
|
+
{
|
|
354
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Component not found: %s"), *ComponentName);
|
|
355
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Component not found: %s"), *ComponentName));
|
|
356
|
+
}
|
|
357
|
+
else
|
|
358
|
+
{
|
|
359
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Component found: %s (Class: %s)"),
|
|
360
|
+
*ComponentName,
|
|
361
|
+
ComponentNode->ComponentTemplate ? *ComponentNode->ComponentTemplate->GetClass()->GetName() : TEXT("NULL"));
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Get the component template
|
|
365
|
+
UObject* ComponentTemplate = ComponentNode->ComponentTemplate;
|
|
366
|
+
if (!ComponentTemplate)
|
|
367
|
+
{
|
|
368
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Component template is NULL for %s"), *ComponentName);
|
|
369
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Invalid component template"));
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Check if this is a Spring Arm component and log special debug info
|
|
373
|
+
if (ComponentTemplate->GetClass()->GetName().Contains(TEXT("SpringArm")))
|
|
374
|
+
{
|
|
375
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - SpringArm component detected! Class: %s"),
|
|
376
|
+
*ComponentTemplate->GetClass()->GetPathName());
|
|
377
|
+
|
|
378
|
+
// Log all properties of the SpringArm component class
|
|
379
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - SpringArm properties:"));
|
|
380
|
+
for (TFieldIterator<FProperty> PropIt(ComponentTemplate->GetClass()); PropIt; ++PropIt)
|
|
381
|
+
{
|
|
382
|
+
FProperty* Prop = *PropIt;
|
|
383
|
+
UE_LOG(LogTemp, Warning, TEXT(" - %s (%s)"), *Prop->GetName(), *Prop->GetCPPType());
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Special handling for Spring Arm properties
|
|
387
|
+
if (Params->HasField(TEXT("property_value")))
|
|
388
|
+
{
|
|
389
|
+
TSharedPtr<FJsonValue> JsonValue = Params->Values.FindRef(TEXT("property_value"));
|
|
390
|
+
|
|
391
|
+
// Get the property using the new FField system
|
|
392
|
+
FProperty* Property = FindFProperty<FProperty>(ComponentTemplate->GetClass(), *PropertyName);
|
|
393
|
+
if (!Property)
|
|
394
|
+
{
|
|
395
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Property %s not found on SpringArm component"), *PropertyName);
|
|
396
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
|
397
|
+
FString::Printf(TEXT("Property %s not found on SpringArm component"), *PropertyName));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Create a scope guard to ensure property cleanup
|
|
401
|
+
struct FScopeGuard
|
|
402
|
+
{
|
|
403
|
+
UObject* Object;
|
|
404
|
+
FScopeGuard(UObject* InObject) : Object(InObject)
|
|
405
|
+
{
|
|
406
|
+
if (Object)
|
|
407
|
+
{
|
|
408
|
+
Object->Modify();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
~FScopeGuard()
|
|
412
|
+
{
|
|
413
|
+
if (Object)
|
|
414
|
+
{
|
|
415
|
+
Object->PostEditChange();
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
} ScopeGuard(ComponentTemplate);
|
|
419
|
+
|
|
420
|
+
bool bSuccess = false;
|
|
421
|
+
FString ErrorMessage;
|
|
422
|
+
|
|
423
|
+
// Handle specific Spring Arm property types
|
|
424
|
+
if (FFloatProperty* FloatProp = CastField<FFloatProperty>(Property))
|
|
425
|
+
{
|
|
426
|
+
if (JsonValue->Type == EJson::Number)
|
|
427
|
+
{
|
|
428
|
+
const float Value = JsonValue->AsNumber();
|
|
429
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting float property %s to %f"), *PropertyName, Value);
|
|
430
|
+
FloatProp->SetPropertyValue_InContainer(ComponentTemplate, Value);
|
|
431
|
+
bSuccess = true;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
else if (FBoolProperty* BoolProp = CastField<FBoolProperty>(Property))
|
|
435
|
+
{
|
|
436
|
+
if (JsonValue->Type == EJson::Boolean)
|
|
437
|
+
{
|
|
438
|
+
const bool Value = JsonValue->AsBool();
|
|
439
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting bool property %s to %d"), *PropertyName, Value);
|
|
440
|
+
BoolProp->SetPropertyValue_InContainer(ComponentTemplate, Value);
|
|
441
|
+
bSuccess = true;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
else if (FStructProperty* StructProp = CastField<FStructProperty>(Property))
|
|
445
|
+
{
|
|
446
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Handling struct property %s of type %s"),
|
|
447
|
+
*PropertyName, *StructProp->Struct->GetName());
|
|
448
|
+
|
|
449
|
+
// Special handling for common Spring Arm struct properties
|
|
450
|
+
if (StructProp->Struct == TBaseStructure<FVector>::Get())
|
|
451
|
+
{
|
|
452
|
+
if (JsonValue->Type == EJson::Array)
|
|
453
|
+
{
|
|
454
|
+
const TArray<TSharedPtr<FJsonValue>>& Arr = JsonValue->AsArray();
|
|
455
|
+
if (Arr.Num() == 3)
|
|
456
|
+
{
|
|
457
|
+
FVector Vec(
|
|
458
|
+
Arr[0]->AsNumber(),
|
|
459
|
+
Arr[1]->AsNumber(),
|
|
460
|
+
Arr[2]->AsNumber()
|
|
461
|
+
);
|
|
462
|
+
void* PropertyAddr = StructProp->ContainerPtrToValuePtr<void>(ComponentTemplate);
|
|
463
|
+
StructProp->CopySingleValue(PropertyAddr, &Vec);
|
|
464
|
+
bSuccess = true;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
else if (StructProp->Struct == TBaseStructure<FRotator>::Get())
|
|
469
|
+
{
|
|
470
|
+
if (JsonValue->Type == EJson::Array)
|
|
471
|
+
{
|
|
472
|
+
const TArray<TSharedPtr<FJsonValue>>& Arr = JsonValue->AsArray();
|
|
473
|
+
if (Arr.Num() == 3)
|
|
474
|
+
{
|
|
475
|
+
FRotator Rot(
|
|
476
|
+
Arr[0]->AsNumber(),
|
|
477
|
+
Arr[1]->AsNumber(),
|
|
478
|
+
Arr[2]->AsNumber()
|
|
479
|
+
);
|
|
480
|
+
void* PropertyAddr = StructProp->ContainerPtrToValuePtr<void>(ComponentTemplate);
|
|
481
|
+
StructProp->CopySingleValue(PropertyAddr, &Rot);
|
|
482
|
+
bSuccess = true;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (bSuccess)
|
|
489
|
+
{
|
|
490
|
+
// Mark the blueprint as modified
|
|
491
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Successfully set SpringArm property %s"), *PropertyName);
|
|
492
|
+
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
|
493
|
+
|
|
494
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
495
|
+
ResultObj->SetStringField(TEXT("component"), ComponentName);
|
|
496
|
+
ResultObj->SetStringField(TEXT("property"), PropertyName);
|
|
497
|
+
ResultObj->SetBoolField(TEXT("success"), true);
|
|
498
|
+
return ResultObj;
|
|
499
|
+
}
|
|
500
|
+
else
|
|
501
|
+
{
|
|
502
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set SpringArm property %s"), *PropertyName);
|
|
503
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
|
504
|
+
FString::Printf(TEXT("Failed to set SpringArm property %s"), *PropertyName));
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Regular property handling for non-Spring Arm components continues...
|
|
510
|
+
|
|
511
|
+
// Set the property value
|
|
512
|
+
if (Params->HasField(TEXT("property_value")))
|
|
513
|
+
{
|
|
514
|
+
TSharedPtr<FJsonValue> JsonValue = Params->Values.FindRef(TEXT("property_value"));
|
|
515
|
+
|
|
516
|
+
// Get the property
|
|
517
|
+
FProperty* Property = FindFProperty<FProperty>(ComponentTemplate->GetClass(), *PropertyName);
|
|
518
|
+
if (!Property)
|
|
519
|
+
{
|
|
520
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Property %s not found on component %s"),
|
|
521
|
+
*PropertyName, *ComponentName);
|
|
522
|
+
|
|
523
|
+
// List all available properties for this component
|
|
524
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Available properties for %s:"), *ComponentName);
|
|
525
|
+
for (TFieldIterator<FProperty> PropIt(ComponentTemplate->GetClass()); PropIt; ++PropIt)
|
|
526
|
+
{
|
|
527
|
+
FProperty* Prop = *PropIt;
|
|
528
|
+
UE_LOG(LogTemp, Warning, TEXT(" - %s (%s)"), *Prop->GetName(), *Prop->GetCPPType());
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
|
532
|
+
FString::Printf(TEXT("Property %s not found on component %s"), *PropertyName, *ComponentName));
|
|
533
|
+
}
|
|
534
|
+
else
|
|
535
|
+
{
|
|
536
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property found: %s (Type: %s)"),
|
|
537
|
+
*PropertyName, *Property->GetCPPType());
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
bool bSuccess = false;
|
|
541
|
+
FString ErrorMessage;
|
|
542
|
+
|
|
543
|
+
// Handle different property types
|
|
544
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Attempting to set property %s"), *PropertyName);
|
|
545
|
+
|
|
546
|
+
// Add try-catch block to catch and log any crashes
|
|
547
|
+
try
|
|
548
|
+
{
|
|
549
|
+
if (FStructProperty* StructProp = CastField<FStructProperty>(Property))
|
|
550
|
+
{
|
|
551
|
+
// Handle vector properties
|
|
552
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property is a struct: %s"),
|
|
553
|
+
StructProp->Struct ? *StructProp->Struct->GetName() : TEXT("NULL"));
|
|
554
|
+
|
|
555
|
+
if (StructProp->Struct == TBaseStructure<FVector>::Get())
|
|
556
|
+
{
|
|
557
|
+
if (JsonValue->Type == EJson::Array)
|
|
558
|
+
{
|
|
559
|
+
// Handle array input [x, y, z]
|
|
560
|
+
const TArray<TSharedPtr<FJsonValue>>& Arr = JsonValue->AsArray();
|
|
561
|
+
if (Arr.Num() == 3)
|
|
562
|
+
{
|
|
563
|
+
FVector Vec(
|
|
564
|
+
Arr[0]->AsNumber(),
|
|
565
|
+
Arr[1]->AsNumber(),
|
|
566
|
+
Arr[2]->AsNumber()
|
|
567
|
+
);
|
|
568
|
+
void* PropertyAddr = StructProp->ContainerPtrToValuePtr<void>(ComponentTemplate);
|
|
569
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting Vector(%f, %f, %f)"),
|
|
570
|
+
Vec.X, Vec.Y, Vec.Z);
|
|
571
|
+
StructProp->CopySingleValue(PropertyAddr, &Vec);
|
|
572
|
+
bSuccess = true;
|
|
573
|
+
}
|
|
574
|
+
else
|
|
575
|
+
{
|
|
576
|
+
ErrorMessage = FString::Printf(TEXT("Vector property requires 3 values, got %d"), Arr.Num());
|
|
577
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else if (JsonValue->Type == EJson::Number)
|
|
581
|
+
{
|
|
582
|
+
// Handle scalar input (sets all components to same value)
|
|
583
|
+
float Value = JsonValue->AsNumber();
|
|
584
|
+
FVector Vec(Value, Value, Value);
|
|
585
|
+
void* PropertyAddr = StructProp->ContainerPtrToValuePtr<void>(ComponentTemplate);
|
|
586
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting Vector(%f, %f, %f) from scalar"),
|
|
587
|
+
Vec.X, Vec.Y, Vec.Z);
|
|
588
|
+
StructProp->CopySingleValue(PropertyAddr, &Vec);
|
|
589
|
+
bSuccess = true;
|
|
590
|
+
}
|
|
591
|
+
else
|
|
592
|
+
{
|
|
593
|
+
ErrorMessage = TEXT("Vector property requires either a single number or array of 3 numbers");
|
|
594
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
else
|
|
598
|
+
{
|
|
599
|
+
// Handle other struct properties using default handler
|
|
600
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Using generic struct handler for %s"),
|
|
601
|
+
*PropertyName);
|
|
602
|
+
bSuccess = FUnrealMCPCommonUtils::SetObjectProperty(ComponentTemplate, PropertyName, JsonValue, ErrorMessage);
|
|
603
|
+
if (!bSuccess)
|
|
604
|
+
{
|
|
605
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set struct property: %s"), *ErrorMessage);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
else if (FEnumProperty* EnumProp = CastField<FEnumProperty>(Property))
|
|
610
|
+
{
|
|
611
|
+
// Handle enum properties
|
|
612
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property is an enum"));
|
|
613
|
+
if (JsonValue->Type == EJson::String)
|
|
614
|
+
{
|
|
615
|
+
FString EnumValueName = JsonValue->AsString();
|
|
616
|
+
UEnum* Enum = EnumProp->GetEnum();
|
|
617
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting enum from string: %s"), *EnumValueName);
|
|
618
|
+
|
|
619
|
+
if (Enum)
|
|
620
|
+
{
|
|
621
|
+
int64 EnumValue = Enum->GetValueByNameString(EnumValueName);
|
|
622
|
+
|
|
623
|
+
if (EnumValue != INDEX_NONE)
|
|
624
|
+
{
|
|
625
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Found enum value: %lld"), EnumValue);
|
|
626
|
+
EnumProp->GetUnderlyingProperty()->SetIntPropertyValue(
|
|
627
|
+
ComponentTemplate,
|
|
628
|
+
EnumValue
|
|
629
|
+
);
|
|
630
|
+
bSuccess = true;
|
|
631
|
+
}
|
|
632
|
+
else
|
|
633
|
+
{
|
|
634
|
+
// List all possible enum values
|
|
635
|
+
UE_LOG(LogTemp, Warning, TEXT("SetComponentProperty - Available enum values for %s:"),
|
|
636
|
+
*Enum->GetName());
|
|
637
|
+
for (int32 i = 0; i < Enum->NumEnums(); i++)
|
|
638
|
+
{
|
|
639
|
+
UE_LOG(LogTemp, Warning, TEXT(" - %s (%lld)"),
|
|
640
|
+
*Enum->GetNameStringByIndex(i),
|
|
641
|
+
Enum->GetValueByIndex(i));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
ErrorMessage = FString::Printf(TEXT("Invalid enum value '%s' for property %s"),
|
|
645
|
+
*EnumValueName, *PropertyName);
|
|
646
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
else
|
|
650
|
+
{
|
|
651
|
+
ErrorMessage = TEXT("Enum object is NULL");
|
|
652
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
else if (JsonValue->Type == EJson::Number)
|
|
656
|
+
{
|
|
657
|
+
// Allow setting enum by integer value
|
|
658
|
+
int64 EnumValue = JsonValue->AsNumber();
|
|
659
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting enum from number: %lld"), EnumValue);
|
|
660
|
+
EnumProp->GetUnderlyingProperty()->SetIntPropertyValue(
|
|
661
|
+
ComponentTemplate,
|
|
662
|
+
EnumValue
|
|
663
|
+
);
|
|
664
|
+
bSuccess = true;
|
|
665
|
+
}
|
|
666
|
+
else
|
|
667
|
+
{
|
|
668
|
+
ErrorMessage = TEXT("Enum property requires either a string name or integer value");
|
|
669
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
else if (FNumericProperty* NumericProp = CastField<FNumericProperty>(Property))
|
|
673
|
+
{
|
|
674
|
+
// Handle numeric properties
|
|
675
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Property is numeric: IsInteger=%d, IsFloat=%d"),
|
|
676
|
+
NumericProp->IsInteger(), NumericProp->IsFloatingPoint());
|
|
677
|
+
|
|
678
|
+
if (JsonValue->Type == EJson::Number)
|
|
679
|
+
{
|
|
680
|
+
double Value = JsonValue->AsNumber();
|
|
681
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Setting numeric value: %f"), Value);
|
|
682
|
+
|
|
683
|
+
if (NumericProp->IsInteger())
|
|
684
|
+
{
|
|
685
|
+
NumericProp->SetIntPropertyValue(ComponentTemplate, (int64)Value);
|
|
686
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Set integer value: %lld"), (int64)Value);
|
|
687
|
+
bSuccess = true;
|
|
688
|
+
}
|
|
689
|
+
else if (NumericProp->IsFloatingPoint())
|
|
690
|
+
{
|
|
691
|
+
NumericProp->SetFloatingPointPropertyValue(ComponentTemplate, Value);
|
|
692
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Set float value: %f"), Value);
|
|
693
|
+
bSuccess = true;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
else
|
|
697
|
+
{
|
|
698
|
+
ErrorMessage = TEXT("Numeric property requires a number value");
|
|
699
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - %s"), *ErrorMessage);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
else
|
|
703
|
+
{
|
|
704
|
+
// Handle all other property types using default handler
|
|
705
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Using generic property handler for %s (Type: %s)"),
|
|
706
|
+
*PropertyName, *Property->GetCPPType());
|
|
707
|
+
bSuccess = FUnrealMCPCommonUtils::SetObjectProperty(ComponentTemplate, PropertyName, JsonValue, ErrorMessage);
|
|
708
|
+
if (!bSuccess)
|
|
709
|
+
{
|
|
710
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set property: %s"), *ErrorMessage);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
catch (const std::exception& Ex)
|
|
715
|
+
{
|
|
716
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - EXCEPTION: %s"), ANSI_TO_TCHAR(Ex.what()));
|
|
717
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
|
718
|
+
FString::Printf(TEXT("Exception while setting property %s: %s"), *PropertyName, ANSI_TO_TCHAR(Ex.what())));
|
|
719
|
+
}
|
|
720
|
+
catch (...)
|
|
721
|
+
{
|
|
722
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - UNKNOWN EXCEPTION occurred while setting property %s"), *PropertyName);
|
|
723
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(
|
|
724
|
+
FString::Printf(TEXT("Unknown exception while setting property %s"), *PropertyName));
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (bSuccess)
|
|
728
|
+
{
|
|
729
|
+
// Mark the blueprint as modified
|
|
730
|
+
UE_LOG(LogTemp, Log, TEXT("SetComponentProperty - Successfully set property %s on component %s"),
|
|
731
|
+
*PropertyName, *ComponentName);
|
|
732
|
+
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
|
733
|
+
|
|
734
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
735
|
+
ResultObj->SetStringField(TEXT("component"), ComponentName);
|
|
736
|
+
ResultObj->SetStringField(TEXT("property"), PropertyName);
|
|
737
|
+
ResultObj->SetBoolField(TEXT("success"), true);
|
|
738
|
+
return ResultObj;
|
|
739
|
+
}
|
|
740
|
+
else
|
|
741
|
+
{
|
|
742
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Failed to set property %s: %s"),
|
|
743
|
+
*PropertyName, *ErrorMessage);
|
|
744
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(ErrorMessage);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
UE_LOG(LogTemp, Error, TEXT("SetComponentProperty - Missing 'property_value' parameter"));
|
|
749
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'property_value' parameter"));
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetPhysicsProperties(const TSharedPtr<FJsonObject>& Params)
|
|
753
|
+
{
|
|
754
|
+
// Get required parameters
|
|
755
|
+
FString BlueprintName;
|
|
756
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
757
|
+
{
|
|
758
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
FString ComponentName;
|
|
762
|
+
if (!Params->TryGetStringField(TEXT("component_name"), ComponentName))
|
|
763
|
+
{
|
|
764
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'component_name' parameter"));
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Find the blueprint
|
|
768
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
769
|
+
if (!Blueprint)
|
|
770
|
+
{
|
|
771
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// Find the component
|
|
775
|
+
USCS_Node* ComponentNode = nullptr;
|
|
776
|
+
for (USCS_Node* Node : Blueprint->SimpleConstructionScript->GetAllNodes())
|
|
777
|
+
{
|
|
778
|
+
if (Node && Node->GetVariableName().ToString() == ComponentName)
|
|
779
|
+
{
|
|
780
|
+
ComponentNode = Node;
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (!ComponentNode)
|
|
786
|
+
{
|
|
787
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Component not found: %s"), *ComponentName));
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
UPrimitiveComponent* PrimComponent = Cast<UPrimitiveComponent>(ComponentNode->ComponentTemplate);
|
|
791
|
+
if (!PrimComponent)
|
|
792
|
+
{
|
|
793
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Component is not a primitive component"));
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
// Set physics properties
|
|
797
|
+
if (Params->HasField(TEXT("simulate_physics")))
|
|
798
|
+
{
|
|
799
|
+
PrimComponent->SetSimulatePhysics(Params->GetBoolField(TEXT("simulate_physics")));
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
if (Params->HasField(TEXT("mass")))
|
|
803
|
+
{
|
|
804
|
+
float Mass = Params->GetNumberField(TEXT("mass"));
|
|
805
|
+
// In UE5.5, use proper overrideMass instead of just scaling
|
|
806
|
+
PrimComponent->SetMassOverrideInKg(NAME_None, Mass);
|
|
807
|
+
UE_LOG(LogTemp, Display, TEXT("Set mass for component %s to %f kg"), *ComponentName, Mass);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
if (Params->HasField(TEXT("linear_damping")))
|
|
811
|
+
{
|
|
812
|
+
PrimComponent->SetLinearDamping(Params->GetNumberField(TEXT("linear_damping")));
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
if (Params->HasField(TEXT("angular_damping")))
|
|
816
|
+
{
|
|
817
|
+
PrimComponent->SetAngularDamping(Params->GetNumberField(TEXT("angular_damping")));
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Mark the blueprint as modified
|
|
821
|
+
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
|
822
|
+
|
|
823
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
824
|
+
ResultObj->SetStringField(TEXT("component"), ComponentName);
|
|
825
|
+
return ResultObj;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleCompileBlueprint(const TSharedPtr<FJsonObject>& Params)
|
|
829
|
+
{
|
|
830
|
+
// Get required parameters
|
|
831
|
+
FString BlueprintName;
|
|
832
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
833
|
+
{
|
|
834
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// Find the blueprint
|
|
838
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
839
|
+
if (!Blueprint)
|
|
840
|
+
{
|
|
841
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Compile the blueprint
|
|
845
|
+
FKismetEditorUtilities::CompileBlueprint(Blueprint);
|
|
846
|
+
|
|
847
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
848
|
+
ResultObj->SetStringField(TEXT("name"), BlueprintName);
|
|
849
|
+
ResultObj->SetBoolField(TEXT("compiled"), true);
|
|
850
|
+
return ResultObj;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSpawnBlueprintActor(const TSharedPtr<FJsonObject>& Params)
|
|
854
|
+
{
|
|
855
|
+
// Get required parameters
|
|
856
|
+
FString BlueprintName;
|
|
857
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
858
|
+
{
|
|
859
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
FString ActorName;
|
|
863
|
+
if (!Params->TryGetStringField(TEXT("actor_name"), ActorName))
|
|
864
|
+
{
|
|
865
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'actor_name' parameter"));
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// Find the blueprint
|
|
869
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
870
|
+
if (!Blueprint)
|
|
871
|
+
{
|
|
872
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// Get transform parameters
|
|
876
|
+
FVector Location(0.0f, 0.0f, 0.0f);
|
|
877
|
+
FRotator Rotation(0.0f, 0.0f, 0.0f);
|
|
878
|
+
|
|
879
|
+
if (Params->HasField(TEXT("location")))
|
|
880
|
+
{
|
|
881
|
+
Location = FUnrealMCPCommonUtils::GetVectorFromJson(Params, TEXT("location"));
|
|
882
|
+
}
|
|
883
|
+
if (Params->HasField(TEXT("rotation")))
|
|
884
|
+
{
|
|
885
|
+
Rotation = FUnrealMCPCommonUtils::GetRotatorFromJson(Params, TEXT("rotation"));
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// Spawn the actor
|
|
889
|
+
UWorld* World = GEditor->GetEditorWorldContext().World();
|
|
890
|
+
if (!World)
|
|
891
|
+
{
|
|
892
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get editor world"));
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
FTransform SpawnTransform;
|
|
896
|
+
SpawnTransform.SetLocation(Location);
|
|
897
|
+
SpawnTransform.SetRotation(FQuat(Rotation));
|
|
898
|
+
|
|
899
|
+
AActor* NewActor = World->SpawnActor<AActor>(Blueprint->GeneratedClass, SpawnTransform);
|
|
900
|
+
if (NewActor)
|
|
901
|
+
{
|
|
902
|
+
NewActor->SetActorLabel(*ActorName);
|
|
903
|
+
return FUnrealMCPCommonUtils::ActorToJsonObject(NewActor, true);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to spawn blueprint actor"));
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetBlueprintProperty(const TSharedPtr<FJsonObject>& Params)
|
|
910
|
+
{
|
|
911
|
+
// Get required parameters
|
|
912
|
+
FString BlueprintName;
|
|
913
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
914
|
+
{
|
|
915
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
FString PropertyName;
|
|
919
|
+
if (!Params->TryGetStringField(TEXT("property_name"), PropertyName))
|
|
920
|
+
{
|
|
921
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'property_name' parameter"));
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
// Find the blueprint
|
|
925
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
926
|
+
if (!Blueprint)
|
|
927
|
+
{
|
|
928
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Get the default object
|
|
932
|
+
UObject* DefaultObject = Blueprint->GeneratedClass->GetDefaultObject();
|
|
933
|
+
if (!DefaultObject)
|
|
934
|
+
{
|
|
935
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get default object"));
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Set the property value
|
|
939
|
+
if (Params->HasField(TEXT("property_value")))
|
|
940
|
+
{
|
|
941
|
+
TSharedPtr<FJsonValue> JsonValue = Params->Values.FindRef(TEXT("property_value"));
|
|
942
|
+
|
|
943
|
+
FString ErrorMessage;
|
|
944
|
+
if (FUnrealMCPCommonUtils::SetObjectProperty(DefaultObject, PropertyName, JsonValue, ErrorMessage))
|
|
945
|
+
{
|
|
946
|
+
// Mark the blueprint as modified
|
|
947
|
+
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
|
948
|
+
|
|
949
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
950
|
+
ResultObj->SetStringField(TEXT("property"), PropertyName);
|
|
951
|
+
ResultObj->SetBoolField(TEXT("success"), true);
|
|
952
|
+
return ResultObj;
|
|
953
|
+
}
|
|
954
|
+
else
|
|
955
|
+
{
|
|
956
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(ErrorMessage);
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'property_value' parameter"));
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetStaticMeshProperties(const TSharedPtr<FJsonObject>& Params)
|
|
964
|
+
{
|
|
965
|
+
// Get required parameters
|
|
966
|
+
FString BlueprintName;
|
|
967
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
968
|
+
{
|
|
969
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
FString ComponentName;
|
|
973
|
+
if (!Params->TryGetStringField(TEXT("component_name"), ComponentName))
|
|
974
|
+
{
|
|
975
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'component_name' parameter"));
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// Find the blueprint
|
|
979
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
980
|
+
if (!Blueprint)
|
|
981
|
+
{
|
|
982
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// Find the component
|
|
986
|
+
USCS_Node* ComponentNode = nullptr;
|
|
987
|
+
for (USCS_Node* Node : Blueprint->SimpleConstructionScript->GetAllNodes())
|
|
988
|
+
{
|
|
989
|
+
if (Node && Node->GetVariableName().ToString() == ComponentName)
|
|
990
|
+
{
|
|
991
|
+
ComponentNode = Node;
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
if (!ComponentNode)
|
|
997
|
+
{
|
|
998
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Component not found: %s"), *ComponentName));
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
UStaticMeshComponent* MeshComponent = Cast<UStaticMeshComponent>(ComponentNode->ComponentTemplate);
|
|
1002
|
+
if (!MeshComponent)
|
|
1003
|
+
{
|
|
1004
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Component is not a static mesh component"));
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// Set static mesh properties
|
|
1008
|
+
if (Params->HasField(TEXT("static_mesh")))
|
|
1009
|
+
{
|
|
1010
|
+
FString MeshPath = Params->GetStringField(TEXT("static_mesh"));
|
|
1011
|
+
UStaticMesh* Mesh = Cast<UStaticMesh>(UEditorAssetLibrary::LoadAsset(MeshPath));
|
|
1012
|
+
if (Mesh)
|
|
1013
|
+
{
|
|
1014
|
+
MeshComponent->SetStaticMesh(Mesh);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
if (Params->HasField(TEXT("material")))
|
|
1019
|
+
{
|
|
1020
|
+
FString MaterialPath = Params->GetStringField(TEXT("material"));
|
|
1021
|
+
UMaterialInterface* Material = Cast<UMaterialInterface>(UEditorAssetLibrary::LoadAsset(MaterialPath));
|
|
1022
|
+
if (Material)
|
|
1023
|
+
{
|
|
1024
|
+
MeshComponent->SetMaterial(0, Material);
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Mark the blueprint as modified
|
|
1029
|
+
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
|
1030
|
+
|
|
1031
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
1032
|
+
ResultObj->SetStringField(TEXT("component"), ComponentName);
|
|
1033
|
+
return ResultObj;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
TSharedPtr<FJsonObject> FUnrealMCPBlueprintCommands::HandleSetPawnProperties(const TSharedPtr<FJsonObject>& Params)
|
|
1037
|
+
{
|
|
1038
|
+
// Get required parameters
|
|
1039
|
+
FString BlueprintName;
|
|
1040
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
1041
|
+
{
|
|
1042
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// Find the blueprint
|
|
1046
|
+
UBlueprint* Blueprint = FUnrealMCPCommonUtils::FindBlueprint(BlueprintName);
|
|
1047
|
+
if (!Blueprint)
|
|
1048
|
+
{
|
|
1049
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Blueprint not found: %s"), *BlueprintName));
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// Get the default object
|
|
1053
|
+
UObject* DefaultObject = Blueprint->GeneratedClass->GetDefaultObject();
|
|
1054
|
+
if (!DefaultObject)
|
|
1055
|
+
{
|
|
1056
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get default object"));
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
// Track if any properties were set successfully
|
|
1060
|
+
bool bAnyPropertiesSet = false;
|
|
1061
|
+
TSharedPtr<FJsonObject> ResultsObj = MakeShared<FJsonObject>();
|
|
1062
|
+
|
|
1063
|
+
// Set auto possess player if specified
|
|
1064
|
+
if (Params->HasField(TEXT("auto_possess_player")))
|
|
1065
|
+
{
|
|
1066
|
+
TSharedPtr<FJsonValue> AutoPossessValue = Params->Values.FindRef(TEXT("auto_possess_player"));
|
|
1067
|
+
|
|
1068
|
+
FString ErrorMessage;
|
|
1069
|
+
if (FUnrealMCPCommonUtils::SetObjectProperty(DefaultObject, TEXT("AutoPossessPlayer"), AutoPossessValue, ErrorMessage))
|
|
1070
|
+
{
|
|
1071
|
+
bAnyPropertiesSet = true;
|
|
1072
|
+
TSharedPtr<FJsonObject> PropResultObj = MakeShared<FJsonObject>();
|
|
1073
|
+
PropResultObj->SetBoolField(TEXT("success"), true);
|
|
1074
|
+
ResultsObj->SetObjectField(TEXT("AutoPossessPlayer"), PropResultObj);
|
|
1075
|
+
}
|
|
1076
|
+
else
|
|
1077
|
+
{
|
|
1078
|
+
TSharedPtr<FJsonObject> PropResultObj = MakeShared<FJsonObject>();
|
|
1079
|
+
PropResultObj->SetBoolField(TEXT("success"), false);
|
|
1080
|
+
PropResultObj->SetStringField(TEXT("error"), ErrorMessage);
|
|
1081
|
+
ResultsObj->SetObjectField(TEXT("AutoPossessPlayer"), PropResultObj);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
// Set controller rotation properties
|
|
1086
|
+
const TCHAR* RotationProps[] = {
|
|
1087
|
+
TEXT("bUseControllerRotationYaw"),
|
|
1088
|
+
TEXT("bUseControllerRotationPitch"),
|
|
1089
|
+
TEXT("bUseControllerRotationRoll")
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
const TCHAR* ParamNames[] = {
|
|
1093
|
+
TEXT("use_controller_rotation_yaw"),
|
|
1094
|
+
TEXT("use_controller_rotation_pitch"),
|
|
1095
|
+
TEXT("use_controller_rotation_roll")
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1098
|
+
for (int32 i = 0; i < 3; i++)
|
|
1099
|
+
{
|
|
1100
|
+
if (Params->HasField(ParamNames[i]))
|
|
1101
|
+
{
|
|
1102
|
+
TSharedPtr<FJsonValue> Value = Params->Values.FindRef(ParamNames[i]);
|
|
1103
|
+
|
|
1104
|
+
FString ErrorMessage;
|
|
1105
|
+
if (FUnrealMCPCommonUtils::SetObjectProperty(DefaultObject, RotationProps[i], Value, ErrorMessage))
|
|
1106
|
+
{
|
|
1107
|
+
bAnyPropertiesSet = true;
|
|
1108
|
+
TSharedPtr<FJsonObject> PropResultObj = MakeShared<FJsonObject>();
|
|
1109
|
+
PropResultObj->SetBoolField(TEXT("success"), true);
|
|
1110
|
+
ResultsObj->SetObjectField(RotationProps[i], PropResultObj);
|
|
1111
|
+
}
|
|
1112
|
+
else
|
|
1113
|
+
{
|
|
1114
|
+
TSharedPtr<FJsonObject> PropResultObj = MakeShared<FJsonObject>();
|
|
1115
|
+
PropResultObj->SetBoolField(TEXT("success"), false);
|
|
1116
|
+
PropResultObj->SetStringField(TEXT("error"), ErrorMessage);
|
|
1117
|
+
ResultsObj->SetObjectField(RotationProps[i], PropResultObj);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// Set can be damaged property
|
|
1123
|
+
if (Params->HasField(TEXT("can_be_damaged")))
|
|
1124
|
+
{
|
|
1125
|
+
TSharedPtr<FJsonValue> Value = Params->Values.FindRef(TEXT("can_be_damaged"));
|
|
1126
|
+
|
|
1127
|
+
FString ErrorMessage;
|
|
1128
|
+
if (FUnrealMCPCommonUtils::SetObjectProperty(DefaultObject, TEXT("bCanBeDamaged"), Value, ErrorMessage))
|
|
1129
|
+
{
|
|
1130
|
+
bAnyPropertiesSet = true;
|
|
1131
|
+
TSharedPtr<FJsonObject> PropResultObj = MakeShared<FJsonObject>();
|
|
1132
|
+
PropResultObj->SetBoolField(TEXT("success"), true);
|
|
1133
|
+
ResultsObj->SetObjectField(TEXT("bCanBeDamaged"), PropResultObj);
|
|
1134
|
+
}
|
|
1135
|
+
else
|
|
1136
|
+
{
|
|
1137
|
+
TSharedPtr<FJsonObject> PropResultObj = MakeShared<FJsonObject>();
|
|
1138
|
+
PropResultObj->SetBoolField(TEXT("success"), false);
|
|
1139
|
+
PropResultObj->SetStringField(TEXT("error"), ErrorMessage);
|
|
1140
|
+
ResultsObj->SetObjectField(TEXT("bCanBeDamaged"), PropResultObj);
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
// Mark the blueprint as modified if any properties were set
|
|
1145
|
+
if (bAnyPropertiesSet)
|
|
1146
|
+
{
|
|
1147
|
+
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
|
1148
|
+
}
|
|
1149
|
+
else if (ResultsObj->Values.Num() == 0)
|
|
1150
|
+
{
|
|
1151
|
+
// No properties were specified
|
|
1152
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("No properties specified to set"));
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
TSharedPtr<FJsonObject> ResponseObj = MakeShared<FJsonObject>();
|
|
1156
|
+
ResponseObj->SetStringField(TEXT("blueprint"), BlueprintName);
|
|
1157
|
+
ResponseObj->SetBoolField(TEXT("success"), bAnyPropertiesSet);
|
|
1158
|
+
ResponseObj->SetObjectField(TEXT("results"), ResultsObj);
|
|
1159
|
+
return ResponseObj;
|
|
1160
|
+
}
|