ue-mcp 0.4.0-alpha

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.
Files changed (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/dist/bridge.d.ts +25 -0
  4. package/dist/bridge.js +124 -0
  5. package/dist/bridge.js.map +1 -0
  6. package/dist/deployer.d.ts +18 -0
  7. package/dist/deployer.js +175 -0
  8. package/dist/deployer.js.map +1 -0
  9. package/dist/editor-control.d.ts +15 -0
  10. package/dist/editor-control.js +181 -0
  11. package/dist/editor-control.js.map +1 -0
  12. package/dist/github-app.d.ts +4 -0
  13. package/dist/github-app.js +94 -0
  14. package/dist/github-app.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +125 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/init.d.ts +2 -0
  19. package/dist/init.js +290 -0
  20. package/dist/init.js.map +1 -0
  21. package/dist/instructions.d.ts +1 -0
  22. package/dist/instructions.js +150 -0
  23. package/dist/instructions.js.map +1 -0
  24. package/dist/project.d.ts +32 -0
  25. package/dist/project.js +175 -0
  26. package/dist/project.js.map +1 -0
  27. package/dist/tools/animation.d.ts +2 -0
  28. package/dist/tools/animation.js +62 -0
  29. package/dist/tools/animation.js.map +1 -0
  30. package/dist/tools/asset.d.ts +2 -0
  31. package/dist/tools/asset.js +128 -0
  32. package/dist/tools/asset.js.map +1 -0
  33. package/dist/tools/audio.d.ts +2 -0
  34. package/dist/tools/audio.js +24 -0
  35. package/dist/tools/audio.js.map +1 -0
  36. package/dist/tools/blueprint.d.ts +2 -0
  37. package/dist/tools/blueprint.js +64 -0
  38. package/dist/tools/blueprint.js.map +1 -0
  39. package/dist/tools/demo.d.ts +2 -0
  40. package/dist/tools/demo.js +10 -0
  41. package/dist/tools/demo.js.map +1 -0
  42. package/dist/tools/editor.d.ts +2 -0
  43. package/dist/tools/editor.js +133 -0
  44. package/dist/tools/editor.js.map +1 -0
  45. package/dist/tools/feedback.d.ts +2 -0
  46. package/dist/tools/feedback.js +44 -0
  47. package/dist/tools/feedback.js.map +1 -0
  48. package/dist/tools/foliage.d.ts +2 -0
  49. package/dist/tools/foliage.js +29 -0
  50. package/dist/tools/foliage.js.map +1 -0
  51. package/dist/tools/gameplay.d.ts +2 -0
  52. package/dist/tools/gameplay.js +101 -0
  53. package/dist/tools/gameplay.js.map +1 -0
  54. package/dist/tools/gas.d.ts +2 -0
  55. package/dist/tools/gas.js +43 -0
  56. package/dist/tools/gas.js.map +1 -0
  57. package/dist/tools/landscape.d.ts +2 -0
  58. package/dist/tools/landscape.js +32 -0
  59. package/dist/tools/landscape.js.map +1 -0
  60. package/dist/tools/level.d.ts +2 -0
  61. package/dist/tools/level.js +66 -0
  62. package/dist/tools/level.js.map +1 -0
  63. package/dist/tools/material.d.ts +2 -0
  64. package/dist/tools/material.js +59 -0
  65. package/dist/tools/material.js.map +1 -0
  66. package/dist/tools/networking.d.ts +2 -0
  67. package/dist/tools/networking.js +42 -0
  68. package/dist/tools/networking.js.map +1 -0
  69. package/dist/tools/niagara.d.ts +2 -0
  70. package/dist/tools/niagara.js +42 -0
  71. package/dist/tools/niagara.js.map +1 -0
  72. package/dist/tools/pcg.d.ts +2 -0
  73. package/dist/tools/pcg.js +39 -0
  74. package/dist/tools/pcg.js.map +1 -0
  75. package/dist/tools/project.d.ts +2 -0
  76. package/dist/tools/project.js +282 -0
  77. package/dist/tools/project.js.map +1 -0
  78. package/dist/tools/reflection.d.ts +2 -0
  79. package/dist/tools/reflection.js +26 -0
  80. package/dist/tools/reflection.js.map +1 -0
  81. package/dist/tools/widget.d.ts +2 -0
  82. package/dist/tools/widget.js +34 -0
  83. package/dist/tools/widget.js.map +1 -0
  84. package/dist/types.d.ts +21 -0
  85. package/dist/types.js +38 -0
  86. package/dist/types.js.map +1 -0
  87. package/package.json +76 -0
  88. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +746 -0
  89. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.h +81 -0
  90. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +49 -0
  91. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +37 -0
  92. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +75 -0
  93. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +50 -0
  94. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +1418 -0
  95. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +43 -0
  96. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +1773 -0
  97. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +48 -0
  98. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.cpp +289 -0
  99. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.h +18 -0
  100. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +1982 -0
  101. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +44 -0
  102. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +1217 -0
  103. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +71 -0
  104. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.cpp +465 -0
  105. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.h +49 -0
  106. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +1676 -0
  107. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +53 -0
  108. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +876 -0
  109. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +22 -0
  110. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +2222 -0
  111. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +54 -0
  112. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +783 -0
  113. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +24 -0
  114. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +898 -0
  115. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +24 -0
  116. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +1270 -0
  117. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +34 -0
  118. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +2190 -0
  119. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +53 -0
  120. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +554 -0
  121. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +29 -0
  122. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +601 -0
  123. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.h +25 -0
  124. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +1024 -0
  125. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.h +25 -0
  126. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +370 -0
  127. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.h +19 -0
  128. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.cpp +499 -0
  129. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.h +27 -0
  130. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +426 -0
  131. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +19 -0
  132. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +303 -0
  133. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +18 -0
  134. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +985 -0
  135. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +27 -0
  136. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/JsonSerializer.cpp +181 -0
  137. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/JsonSerializer.h +42 -0
  138. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +39 -0
  139. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -0
  140. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
  141. package/plugin/ue_mcp_bridge/UE_MCP_Bridge.uplugin +55 -0
@@ -0,0 +1,303 @@
1
+ #include "SplineHandlers.h"
2
+ #include "HandlerRegistry.h"
3
+ #include "Components/SplineComponent.h"
4
+ #include "Engine/World.h"
5
+ #include "Editor.h"
6
+ #include "Editor/EditorEngine.h"
7
+ #include "GameFramework/Actor.h"
8
+ #include "EngineUtils.h"
9
+ #include "Dom/JsonObject.h"
10
+ #include "Dom/JsonValue.h"
11
+
12
+ void FSplineHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
13
+ {
14
+ Registry.RegisterHandler(TEXT("create_spline_actor"), &CreateSplineActor);
15
+ Registry.RegisterHandler(TEXT("read_spline"), &ReadSpline);
16
+ Registry.RegisterHandler(TEXT("get_spline_info"), &ReadSpline);
17
+ Registry.RegisterHandler(TEXT("set_spline_points"), &SetSplinePoints);
18
+ }
19
+
20
+ TSharedPtr<FJsonValue> FSplineHandlers::CreateSplineActor(const TSharedPtr<FJsonObject>& Params)
21
+ {
22
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
23
+
24
+ UWorld* World = GEditor->GetEditorWorldContext().World();
25
+ if (!World)
26
+ {
27
+ Result->SetStringField(TEXT("error"), TEXT("Editor world not available"));
28
+ Result->SetBoolField(TEXT("success"), false);
29
+ return MakeShared<FJsonValueObject>(Result);
30
+ }
31
+
32
+ // Get location
33
+ FVector Location = FVector::ZeroVector;
34
+ const TSharedPtr<FJsonObject>* LocationObj = nullptr;
35
+ if (Params->TryGetObjectField(TEXT("location"), LocationObj))
36
+ {
37
+ (*LocationObj)->TryGetNumberField(TEXT("x"), Location.X);
38
+ (*LocationObj)->TryGetNumberField(TEXT("y"), Location.Y);
39
+ (*LocationObj)->TryGetNumberField(TEXT("z"), Location.Z);
40
+ }
41
+
42
+ // Spawn an empty actor
43
+ FTransform SpawnTransform(FRotator::ZeroRotator, Location);
44
+ AActor* NewActor = World->SpawnActor<AActor>(AActor::StaticClass(), SpawnTransform);
45
+ if (!NewActor)
46
+ {
47
+ Result->SetStringField(TEXT("error"), TEXT("Failed to spawn actor"));
48
+ Result->SetBoolField(TEXT("success"), false);
49
+ return MakeShared<FJsonValueObject>(Result);
50
+ }
51
+
52
+ // Add a root scene component if none exists
53
+ USceneComponent* RootComp = NewObject<USceneComponent>(NewActor, TEXT("DefaultSceneRoot"));
54
+ RootComp->RegisterComponent();
55
+ NewActor->SetRootComponent(RootComp);
56
+
57
+ // Add the spline component
58
+ USplineComponent* SplineComp = NewObject<USplineComponent>(NewActor, TEXT("SplineComponent"));
59
+ SplineComp->SetupAttachment(RootComp);
60
+ SplineComp->RegisterComponent();
61
+ NewActor->AddInstanceComponent(SplineComp);
62
+
63
+ // Set label if provided
64
+ FString Label;
65
+ if (Params->TryGetStringField(TEXT("label"), Label))
66
+ {
67
+ NewActor->SetActorLabel(Label);
68
+ }
69
+
70
+ // Optionally set closed loop
71
+ bool bClosedLoop = false;
72
+ if (Params->TryGetBoolField(TEXT("closedLoop"), bClosedLoop))
73
+ {
74
+ SplineComp->SetClosedLoop(bClosedLoop);
75
+ }
76
+
77
+ // Optionally set initial points from array
78
+ const TArray<TSharedPtr<FJsonValue>>* PointsArray = nullptr;
79
+ if (Params->TryGetArrayField(TEXT("points"), PointsArray) && PointsArray->Num() > 0)
80
+ {
81
+ SplineComp->ClearSplinePoints(false);
82
+ for (int32 i = 0; i < PointsArray->Num(); ++i)
83
+ {
84
+ const TSharedPtr<FJsonObject>* PointObj = nullptr;
85
+ if ((*PointsArray)[i]->TryGetObject(PointObj))
86
+ {
87
+ FVector Point = FVector::ZeroVector;
88
+ (*PointObj)->TryGetNumberField(TEXT("x"), Point.X);
89
+ (*PointObj)->TryGetNumberField(TEXT("y"), Point.Y);
90
+ (*PointObj)->TryGetNumberField(TEXT("z"), Point.Z);
91
+ SplineComp->AddSplinePoint(Point, ESplineCoordinateSpace::World, false);
92
+ }
93
+ }
94
+ SplineComp->UpdateSpline();
95
+ }
96
+
97
+ Result->SetStringField(TEXT("actorLabel"), NewActor->GetActorLabel());
98
+ Result->SetStringField(TEXT("actorName"), NewActor->GetName());
99
+ Result->SetNumberField(TEXT("splinePointCount"), SplineComp->GetNumberOfSplinePoints());
100
+ Result->SetBoolField(TEXT("closedLoop"), SplineComp->IsClosedLoop());
101
+ Result->SetBoolField(TEXT("success"), true);
102
+
103
+ return MakeShared<FJsonValueObject>(Result);
104
+ }
105
+
106
+ TSharedPtr<FJsonValue> FSplineHandlers::ReadSpline(const TSharedPtr<FJsonObject>& Params)
107
+ {
108
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
109
+
110
+ FString ActorLabel;
111
+ if (!Params->TryGetStringField(TEXT("actorLabel"), ActorLabel))
112
+ {
113
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'actorLabel' parameter"));
114
+ Result->SetBoolField(TEXT("success"), false);
115
+ return MakeShared<FJsonValueObject>(Result);
116
+ }
117
+
118
+ UWorld* World = GEditor->GetEditorWorldContext().World();
119
+ if (!World)
120
+ {
121
+ Result->SetStringField(TEXT("error"), TEXT("Editor world not available"));
122
+ Result->SetBoolField(TEXT("success"), false);
123
+ return MakeShared<FJsonValueObject>(Result);
124
+ }
125
+
126
+ // Find actor by label
127
+ AActor* Actor = nullptr;
128
+ for (TActorIterator<AActor> ActorIt(World); ActorIt; ++ActorIt)
129
+ {
130
+ if ((*ActorIt)->GetActorLabel() == ActorLabel)
131
+ {
132
+ Actor = *ActorIt;
133
+ break;
134
+ }
135
+ }
136
+
137
+ if (!Actor)
138
+ {
139
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Actor not found: %s"), *ActorLabel));
140
+ Result->SetBoolField(TEXT("success"), false);
141
+ return MakeShared<FJsonValueObject>(Result);
142
+ }
143
+
144
+ // Find spline component
145
+ USplineComponent* SplineComp = Actor->FindComponentByClass<USplineComponent>();
146
+ if (!SplineComp)
147
+ {
148
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Actor '%s' does not have a SplineComponent"), *ActorLabel));
149
+ Result->SetBoolField(TEXT("success"), false);
150
+ return MakeShared<FJsonValueObject>(Result);
151
+ }
152
+
153
+ Result->SetStringField(TEXT("actorLabel"), ActorLabel);
154
+ Result->SetNumberField(TEXT("splinePointCount"), SplineComp->GetNumberOfSplinePoints());
155
+ Result->SetBoolField(TEXT("closedLoop"), SplineComp->IsClosedLoop());
156
+ Result->SetNumberField(TEXT("splineLength"), SplineComp->GetSplineLength());
157
+
158
+ // Return all control points with world-space locations
159
+ TArray<TSharedPtr<FJsonValue>> PointsArray;
160
+ for (int32 i = 0; i < SplineComp->GetNumberOfSplinePoints(); ++i)
161
+ {
162
+ TSharedPtr<FJsonObject> PointObj = MakeShared<FJsonObject>();
163
+ PointObj->SetNumberField(TEXT("index"), i);
164
+
165
+ FVector WorldPos = SplineComp->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::World);
166
+ TSharedPtr<FJsonObject> LocationObj = MakeShared<FJsonObject>();
167
+ LocationObj->SetNumberField(TEXT("x"), WorldPos.X);
168
+ LocationObj->SetNumberField(TEXT("y"), WorldPos.Y);
169
+ LocationObj->SetNumberField(TEXT("z"), WorldPos.Z);
170
+ PointObj->SetObjectField(TEXT("worldLocation"), LocationObj);
171
+
172
+ FVector LocalPos = SplineComp->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::Local);
173
+ TSharedPtr<FJsonObject> LocalObj = MakeShared<FJsonObject>();
174
+ LocalObj->SetNumberField(TEXT("x"), LocalPos.X);
175
+ LocalObj->SetNumberField(TEXT("y"), LocalPos.Y);
176
+ LocalObj->SetNumberField(TEXT("z"), LocalPos.Z);
177
+ PointObj->SetObjectField(TEXT("localLocation"), LocalObj);
178
+
179
+ FVector ArriveTangent = SplineComp->GetArriveTangentAtSplinePoint(i, ESplineCoordinateSpace::World);
180
+ TSharedPtr<FJsonObject> ArriveObj = MakeShared<FJsonObject>();
181
+ ArriveObj->SetNumberField(TEXT("x"), ArriveTangent.X);
182
+ ArriveObj->SetNumberField(TEXT("y"), ArriveTangent.Y);
183
+ ArriveObj->SetNumberField(TEXT("z"), ArriveTangent.Z);
184
+ PointObj->SetObjectField(TEXT("arriveTangent"), ArriveObj);
185
+
186
+ FVector LeaveTangent = SplineComp->GetLeaveTangentAtSplinePoint(i, ESplineCoordinateSpace::World);
187
+ TSharedPtr<FJsonObject> LeaveObj = MakeShared<FJsonObject>();
188
+ LeaveObj->SetNumberField(TEXT("x"), LeaveTangent.X);
189
+ LeaveObj->SetNumberField(TEXT("y"), LeaveTangent.Y);
190
+ LeaveObj->SetNumberField(TEXT("z"), LeaveTangent.Z);
191
+ PointObj->SetObjectField(TEXT("leaveTangent"), LeaveObj);
192
+
193
+ // Point type
194
+ ESplinePointType::Type PointType = SplineComp->GetSplinePointType(i);
195
+ FString PointTypeStr;
196
+ switch (PointType)
197
+ {
198
+ case ESplinePointType::Linear: PointTypeStr = TEXT("Linear"); break;
199
+ case ESplinePointType::Curve: PointTypeStr = TEXT("Curve"); break;
200
+ case ESplinePointType::Constant: PointTypeStr = TEXT("Constant"); break;
201
+ case ESplinePointType::CurveClamped: PointTypeStr = TEXT("CurveClamped"); break;
202
+ case ESplinePointType::CurveCustomTangent: PointTypeStr = TEXT("CurveCustomTangent"); break;
203
+ default: PointTypeStr = TEXT("Unknown"); break;
204
+ }
205
+ PointObj->SetStringField(TEXT("pointType"), PointTypeStr);
206
+
207
+ PointsArray.Add(MakeShared<FJsonValueObject>(PointObj));
208
+ }
209
+
210
+ Result->SetArrayField(TEXT("points"), PointsArray);
211
+ Result->SetBoolField(TEXT("success"), true);
212
+
213
+ return MakeShared<FJsonValueObject>(Result);
214
+ }
215
+
216
+ TSharedPtr<FJsonValue> FSplineHandlers::SetSplinePoints(const TSharedPtr<FJsonObject>& Params)
217
+ {
218
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
219
+
220
+ FString ActorLabel;
221
+ if (!Params->TryGetStringField(TEXT("actorLabel"), ActorLabel))
222
+ {
223
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'actorLabel' parameter"));
224
+ Result->SetBoolField(TEXT("success"), false);
225
+ return MakeShared<FJsonValueObject>(Result);
226
+ }
227
+
228
+ const TArray<TSharedPtr<FJsonValue>>* PointsArray = nullptr;
229
+ if (!Params->TryGetArrayField(TEXT("points"), PointsArray))
230
+ {
231
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'points' parameter (array of {x, y, z} objects)"));
232
+ Result->SetBoolField(TEXT("success"), false);
233
+ return MakeShared<FJsonValueObject>(Result);
234
+ }
235
+
236
+ UWorld* World = GEditor->GetEditorWorldContext().World();
237
+ if (!World)
238
+ {
239
+ Result->SetStringField(TEXT("error"), TEXT("Editor world not available"));
240
+ Result->SetBoolField(TEXT("success"), false);
241
+ return MakeShared<FJsonValueObject>(Result);
242
+ }
243
+
244
+ // Find actor by label
245
+ AActor* Actor = nullptr;
246
+ for (TActorIterator<AActor> ActorIt(World); ActorIt; ++ActorIt)
247
+ {
248
+ if ((*ActorIt)->GetActorLabel() == ActorLabel)
249
+ {
250
+ Actor = *ActorIt;
251
+ break;
252
+ }
253
+ }
254
+
255
+ if (!Actor)
256
+ {
257
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Actor not found: %s"), *ActorLabel));
258
+ Result->SetBoolField(TEXT("success"), false);
259
+ return MakeShared<FJsonValueObject>(Result);
260
+ }
261
+
262
+ // Find spline component
263
+ USplineComponent* SplineComp = Actor->FindComponentByClass<USplineComponent>();
264
+ if (!SplineComp)
265
+ {
266
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Actor '%s' does not have a SplineComponent"), *ActorLabel));
267
+ Result->SetBoolField(TEXT("success"), false);
268
+ return MakeShared<FJsonValueObject>(Result);
269
+ }
270
+
271
+ // Clear existing points and add new ones
272
+ SplineComp->ClearSplinePoints(false);
273
+
274
+ for (int32 i = 0; i < PointsArray->Num(); ++i)
275
+ {
276
+ const TSharedPtr<FJsonObject>* PointObj = nullptr;
277
+ if ((*PointsArray)[i]->TryGetObject(PointObj))
278
+ {
279
+ FVector Point = FVector::ZeroVector;
280
+ (*PointObj)->TryGetNumberField(TEXT("x"), Point.X);
281
+ (*PointObj)->TryGetNumberField(TEXT("y"), Point.Y);
282
+ (*PointObj)->TryGetNumberField(TEXT("z"), Point.Z);
283
+ SplineComp->AddSplinePoint(Point, ESplineCoordinateSpace::World, false);
284
+ }
285
+ }
286
+
287
+ // Optionally set closed loop
288
+ bool bClosedLoop = false;
289
+ if (Params->TryGetBoolField(TEXT("closedLoop"), bClosedLoop))
290
+ {
291
+ SplineComp->SetClosedLoop(bClosedLoop);
292
+ }
293
+
294
+ SplineComp->UpdateSpline();
295
+
296
+ Result->SetStringField(TEXT("actorLabel"), ActorLabel);
297
+ Result->SetNumberField(TEXT("splinePointCount"), SplineComp->GetNumberOfSplinePoints());
298
+ Result->SetBoolField(TEXT("closedLoop"), SplineComp->IsClosedLoop());
299
+ Result->SetNumberField(TEXT("splineLength"), SplineComp->GetSplineLength());
300
+ Result->SetBoolField(TEXT("success"), true);
301
+
302
+ return MakeShared<FJsonValueObject>(Result);
303
+ }
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "CoreMinimal.h"
4
+ #include "Dom/JsonValue.h"
5
+ #include "Dom/JsonObject.h"
6
+
7
+ class FSplineHandlers
8
+ {
9
+ public:
10
+ // Register all spline handlers
11
+ static void RegisterHandlers(class FMCPHandlerRegistry& Registry);
12
+
13
+ private:
14
+ // Handler implementations
15
+ static TSharedPtr<FJsonValue> CreateSplineActor(const TSharedPtr<FJsonObject>& Params);
16
+ static TSharedPtr<FJsonValue> ReadSpline(const TSharedPtr<FJsonObject>& Params);
17
+ static TSharedPtr<FJsonValue> SetSplinePoints(const TSharedPtr<FJsonObject>& Params);
18
+ };