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,72 @@
|
|
|
1
|
+
#include "Commands/UnrealMCPProjectCommands.h"
|
|
2
|
+
#include "Commands/UnrealMCPCommonUtils.h"
|
|
3
|
+
#include "GameFramework/InputSettings.h"
|
|
4
|
+
|
|
5
|
+
FUnrealMCPProjectCommands::FUnrealMCPProjectCommands()
|
|
6
|
+
{
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
TSharedPtr<FJsonObject> FUnrealMCPProjectCommands::HandleCommand(const FString& CommandType, const TSharedPtr<FJsonObject>& Params)
|
|
10
|
+
{
|
|
11
|
+
if (CommandType == TEXT("create_input_mapping"))
|
|
12
|
+
{
|
|
13
|
+
return HandleCreateInputMapping(Params);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Unknown project command: %s"), *CommandType));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
TSharedPtr<FJsonObject> FUnrealMCPProjectCommands::HandleCreateInputMapping(const TSharedPtr<FJsonObject>& Params)
|
|
20
|
+
{
|
|
21
|
+
// Get required parameters
|
|
22
|
+
FString ActionName;
|
|
23
|
+
if (!Params->TryGetStringField(TEXT("action_name"), ActionName))
|
|
24
|
+
{
|
|
25
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'action_name' parameter"));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
FString Key;
|
|
29
|
+
if (!Params->TryGetStringField(TEXT("key"), Key))
|
|
30
|
+
{
|
|
31
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'key' parameter"));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Get the input settings
|
|
35
|
+
UInputSettings* InputSettings = GetMutableDefault<UInputSettings>();
|
|
36
|
+
if (!InputSettings)
|
|
37
|
+
{
|
|
38
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get input settings"));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Create the input action mapping
|
|
42
|
+
FInputActionKeyMapping ActionMapping;
|
|
43
|
+
ActionMapping.ActionName = FName(*ActionName);
|
|
44
|
+
ActionMapping.Key = FKey(*Key);
|
|
45
|
+
|
|
46
|
+
// Add modifiers if provided
|
|
47
|
+
if (Params->HasField(TEXT("shift")))
|
|
48
|
+
{
|
|
49
|
+
ActionMapping.bShift = Params->GetBoolField(TEXT("shift"));
|
|
50
|
+
}
|
|
51
|
+
if (Params->HasField(TEXT("ctrl")))
|
|
52
|
+
{
|
|
53
|
+
ActionMapping.bCtrl = Params->GetBoolField(TEXT("ctrl"));
|
|
54
|
+
}
|
|
55
|
+
if (Params->HasField(TEXT("alt")))
|
|
56
|
+
{
|
|
57
|
+
ActionMapping.bAlt = Params->GetBoolField(TEXT("alt"));
|
|
58
|
+
}
|
|
59
|
+
if (Params->HasField(TEXT("cmd")))
|
|
60
|
+
{
|
|
61
|
+
ActionMapping.bCmd = Params->GetBoolField(TEXT("cmd"));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add the mapping
|
|
65
|
+
InputSettings->AddActionMapping(ActionMapping);
|
|
66
|
+
InputSettings->SaveConfig();
|
|
67
|
+
|
|
68
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
69
|
+
ResultObj->SetStringField(TEXT("action_name"), ActionName);
|
|
70
|
+
ResultObj->SetStringField(TEXT("key"), Key);
|
|
71
|
+
return ResultObj;
|
|
72
|
+
}
|
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
#include "Commands/UnrealMCPUMGCommands.h"
|
|
2
|
+
#include "Commands/UnrealMCPCommonUtils.h"
|
|
3
|
+
#include "Editor.h"
|
|
4
|
+
#include "EditorAssetLibrary.h"
|
|
5
|
+
#include "AssetRegistry/AssetRegistryModule.h"
|
|
6
|
+
#include "Blueprint/UserWidget.h"
|
|
7
|
+
#include "Components/TextBlock.h"
|
|
8
|
+
#include "WidgetBlueprint.h"
|
|
9
|
+
// We'll create widgets using regular Factory classes
|
|
10
|
+
#include "Factories/Factory.h"
|
|
11
|
+
// Remove problematic includes that don't exist in UE 5.5
|
|
12
|
+
// #include "UMGEditorSubsystem.h"
|
|
13
|
+
// #include "WidgetBlueprintFactory.h"
|
|
14
|
+
#include "WidgetBlueprintEditor.h"
|
|
15
|
+
#include "Blueprint/WidgetTree.h"
|
|
16
|
+
#include "Components/CanvasPanel.h"
|
|
17
|
+
#include "Components/CanvasPanelSlot.h"
|
|
18
|
+
#include "JsonObjectConverter.h"
|
|
19
|
+
#include "Kismet2/BlueprintEditorUtils.h"
|
|
20
|
+
#include "Components/Button.h"
|
|
21
|
+
#include "K2Node_FunctionEntry.h"
|
|
22
|
+
#include "K2Node_CallFunction.h"
|
|
23
|
+
#include "K2Node_VariableGet.h"
|
|
24
|
+
#include "K2Node_VariableSet.h"
|
|
25
|
+
#include "Kismet/GameplayStatics.h"
|
|
26
|
+
#include "Kismet2/KismetEditorUtilities.h"
|
|
27
|
+
#include "K2Node_Event.h"
|
|
28
|
+
|
|
29
|
+
FUnrealMCPUMGCommands::FUnrealMCPUMGCommands()
|
|
30
|
+
{
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleCommand(const FString& CommandName, const TSharedPtr<FJsonObject>& Params)
|
|
34
|
+
{
|
|
35
|
+
if (CommandName == TEXT("create_umg_widget_blueprint"))
|
|
36
|
+
{
|
|
37
|
+
return HandleCreateUMGWidgetBlueprint(Params);
|
|
38
|
+
}
|
|
39
|
+
else if (CommandName == TEXT("add_text_block_to_widget"))
|
|
40
|
+
{
|
|
41
|
+
return HandleAddTextBlockToWidget(Params);
|
|
42
|
+
}
|
|
43
|
+
else if (CommandName == TEXT("add_widget_to_viewport"))
|
|
44
|
+
{
|
|
45
|
+
return HandleAddWidgetToViewport(Params);
|
|
46
|
+
}
|
|
47
|
+
else if (CommandName == TEXT("add_button_to_widget"))
|
|
48
|
+
{
|
|
49
|
+
return HandleAddButtonToWidget(Params);
|
|
50
|
+
}
|
|
51
|
+
else if (CommandName == TEXT("bind_widget_event"))
|
|
52
|
+
{
|
|
53
|
+
return HandleBindWidgetEvent(Params);
|
|
54
|
+
}
|
|
55
|
+
else if (CommandName == TEXT("set_text_block_binding"))
|
|
56
|
+
{
|
|
57
|
+
return HandleSetTextBlockBinding(Params);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Unknown UMG command: %s"), *CommandName));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleCreateUMGWidgetBlueprint(const TSharedPtr<FJsonObject>& Params)
|
|
64
|
+
{
|
|
65
|
+
// Get required parameters
|
|
66
|
+
FString BlueprintName;
|
|
67
|
+
if (!Params->TryGetStringField(TEXT("name"), BlueprintName))
|
|
68
|
+
{
|
|
69
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'name' parameter"));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Create the full asset path
|
|
73
|
+
FString PackagePath = TEXT("/Game/Widgets/");
|
|
74
|
+
FString AssetName = BlueprintName;
|
|
75
|
+
FString FullPath = PackagePath + AssetName;
|
|
76
|
+
|
|
77
|
+
// Check if asset already exists
|
|
78
|
+
if (UEditorAssetLibrary::DoesAssetExist(FullPath))
|
|
79
|
+
{
|
|
80
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Widget Blueprint '%s' already exists"), *BlueprintName));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Create package
|
|
84
|
+
UPackage* Package = CreatePackage(*FullPath);
|
|
85
|
+
if (!Package)
|
|
86
|
+
{
|
|
87
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to create package"));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Create Widget Blueprint using KismetEditorUtilities
|
|
91
|
+
UBlueprint* NewBlueprint = FKismetEditorUtilities::CreateBlueprint(
|
|
92
|
+
UUserWidget::StaticClass(), // Parent class
|
|
93
|
+
Package, // Outer package
|
|
94
|
+
FName(*AssetName), // Blueprint name
|
|
95
|
+
BPTYPE_Normal, // Blueprint type
|
|
96
|
+
UBlueprint::StaticClass(), // Blueprint class
|
|
97
|
+
UBlueprintGeneratedClass::StaticClass(), // Generated class
|
|
98
|
+
FName("CreateUMGWidget") // Creation method name
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Make sure the Blueprint was created successfully
|
|
102
|
+
UWidgetBlueprint* WidgetBlueprint = Cast<UWidgetBlueprint>(NewBlueprint);
|
|
103
|
+
if (!WidgetBlueprint)
|
|
104
|
+
{
|
|
105
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to create Widget Blueprint"));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Add a default Canvas Panel if one doesn't exist
|
|
109
|
+
if (!WidgetBlueprint->WidgetTree->RootWidget)
|
|
110
|
+
{
|
|
111
|
+
UCanvasPanel* RootCanvas = WidgetBlueprint->WidgetTree->ConstructWidget<UCanvasPanel>(UCanvasPanel::StaticClass());
|
|
112
|
+
WidgetBlueprint->WidgetTree->RootWidget = RootCanvas;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Mark the package dirty and notify asset registry
|
|
116
|
+
Package->MarkPackageDirty();
|
|
117
|
+
FAssetRegistryModule::AssetCreated(WidgetBlueprint);
|
|
118
|
+
|
|
119
|
+
// Compile the blueprint
|
|
120
|
+
FKismetEditorUtilities::CompileBlueprint(WidgetBlueprint);
|
|
121
|
+
|
|
122
|
+
// Create success response
|
|
123
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
124
|
+
ResultObj->SetStringField(TEXT("name"), BlueprintName);
|
|
125
|
+
ResultObj->SetStringField(TEXT("path"), FullPath);
|
|
126
|
+
return ResultObj;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleAddTextBlockToWidget(const TSharedPtr<FJsonObject>& Params)
|
|
130
|
+
{
|
|
131
|
+
// Get required parameters
|
|
132
|
+
FString BlueprintName;
|
|
133
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
134
|
+
{
|
|
135
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
FString WidgetName;
|
|
139
|
+
if (!Params->TryGetStringField(TEXT("widget_name"), WidgetName))
|
|
140
|
+
{
|
|
141
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'widget_name' parameter"));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Find the Widget Blueprint
|
|
145
|
+
FString FullPath = TEXT("/Game/Widgets/") + BlueprintName;
|
|
146
|
+
UWidgetBlueprint* WidgetBlueprint = Cast<UWidgetBlueprint>(UEditorAssetLibrary::LoadAsset(FullPath));
|
|
147
|
+
if (!WidgetBlueprint)
|
|
148
|
+
{
|
|
149
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Widget Blueprint '%s' not found"), *BlueprintName));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Get optional parameters
|
|
153
|
+
FString InitialText = TEXT("New Text Block");
|
|
154
|
+
Params->TryGetStringField(TEXT("text"), InitialText);
|
|
155
|
+
|
|
156
|
+
FVector2D Position(0.0f, 0.0f);
|
|
157
|
+
if (Params->HasField(TEXT("position")))
|
|
158
|
+
{
|
|
159
|
+
const TArray<TSharedPtr<FJsonValue>>* PosArray;
|
|
160
|
+
if (Params->TryGetArrayField(TEXT("position"), PosArray) && PosArray->Num() >= 2)
|
|
161
|
+
{
|
|
162
|
+
Position.X = (*PosArray)[0]->AsNumber();
|
|
163
|
+
Position.Y = (*PosArray)[1]->AsNumber();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Create Text Block widget
|
|
168
|
+
UTextBlock* TextBlock = WidgetBlueprint->WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), *WidgetName);
|
|
169
|
+
if (!TextBlock)
|
|
170
|
+
{
|
|
171
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to create Text Block widget"));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Set initial text
|
|
175
|
+
TextBlock->SetText(FText::FromString(InitialText));
|
|
176
|
+
|
|
177
|
+
// Add to canvas panel
|
|
178
|
+
UCanvasPanel* RootCanvas = Cast<UCanvasPanel>(WidgetBlueprint->WidgetTree->RootWidget);
|
|
179
|
+
if (!RootCanvas)
|
|
180
|
+
{
|
|
181
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Root Canvas Panel not found"));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
UCanvasPanelSlot* PanelSlot = RootCanvas->AddChildToCanvas(TextBlock);
|
|
185
|
+
PanelSlot->SetPosition(Position);
|
|
186
|
+
|
|
187
|
+
// Mark the package dirty and compile
|
|
188
|
+
WidgetBlueprint->MarkPackageDirty();
|
|
189
|
+
FKismetEditorUtilities::CompileBlueprint(WidgetBlueprint);
|
|
190
|
+
|
|
191
|
+
// Create success response
|
|
192
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
193
|
+
ResultObj->SetStringField(TEXT("widget_name"), WidgetName);
|
|
194
|
+
ResultObj->SetStringField(TEXT("text"), InitialText);
|
|
195
|
+
return ResultObj;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleAddWidgetToViewport(const TSharedPtr<FJsonObject>& Params)
|
|
199
|
+
{
|
|
200
|
+
// Get required parameters
|
|
201
|
+
FString BlueprintName;
|
|
202
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
203
|
+
{
|
|
204
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Missing 'blueprint_name' parameter"));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Find the Widget Blueprint
|
|
208
|
+
FString FullPath = TEXT("/Game/Widgets/") + BlueprintName;
|
|
209
|
+
UWidgetBlueprint* WidgetBlueprint = Cast<UWidgetBlueprint>(UEditorAssetLibrary::LoadAsset(FullPath));
|
|
210
|
+
if (!WidgetBlueprint)
|
|
211
|
+
{
|
|
212
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Widget Blueprint '%s' not found"), *BlueprintName));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Get optional Z-order parameter
|
|
216
|
+
int32 ZOrder = 0;
|
|
217
|
+
Params->TryGetNumberField(TEXT("z_order"), ZOrder);
|
|
218
|
+
|
|
219
|
+
// Create widget instance
|
|
220
|
+
UClass* WidgetClass = WidgetBlueprint->GeneratedClass;
|
|
221
|
+
if (!WidgetClass)
|
|
222
|
+
{
|
|
223
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get widget class"));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Note: This creates the widget but doesn't add it to viewport
|
|
227
|
+
// The actual addition to viewport should be done through Blueprint nodes
|
|
228
|
+
// as it requires a game context
|
|
229
|
+
|
|
230
|
+
// Create success response with instructions
|
|
231
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
232
|
+
ResultObj->SetStringField(TEXT("blueprint_name"), BlueprintName);
|
|
233
|
+
ResultObj->SetStringField(TEXT("class_path"), WidgetClass->GetPathName());
|
|
234
|
+
ResultObj->SetNumberField(TEXT("z_order"), ZOrder);
|
|
235
|
+
ResultObj->SetStringField(TEXT("note"), TEXT("Widget class ready. Use CreateWidget and AddToViewport nodes in Blueprint to display in game."));
|
|
236
|
+
return ResultObj;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleAddButtonToWidget(const TSharedPtr<FJsonObject>& Params)
|
|
240
|
+
{
|
|
241
|
+
TSharedPtr<FJsonObject> Response = MakeShared<FJsonObject>();
|
|
242
|
+
|
|
243
|
+
// Get required parameters
|
|
244
|
+
FString BlueprintName;
|
|
245
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
246
|
+
{
|
|
247
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing blueprint_name parameter"));
|
|
248
|
+
return Response;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
FString WidgetName;
|
|
252
|
+
if (!Params->TryGetStringField(TEXT("widget_name"), WidgetName))
|
|
253
|
+
{
|
|
254
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing widget_name parameter"));
|
|
255
|
+
return Response;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
FString ButtonText;
|
|
259
|
+
if (!Params->TryGetStringField(TEXT("text"), ButtonText))
|
|
260
|
+
{
|
|
261
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing text parameter"));
|
|
262
|
+
return Response;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Load the Widget Blueprint
|
|
266
|
+
const FString BlueprintPath = FString::Printf(TEXT("/Game/Widgets/%s.%s"), *BlueprintName, *BlueprintName);
|
|
267
|
+
UWidgetBlueprint* WidgetBlueprint = Cast<UWidgetBlueprint>(UEditorAssetLibrary::LoadAsset(BlueprintPath));
|
|
268
|
+
if (!WidgetBlueprint)
|
|
269
|
+
{
|
|
270
|
+
Response->SetStringField(TEXT("error"), FString::Printf(TEXT("Failed to load Widget Blueprint: %s"), *BlueprintPath));
|
|
271
|
+
return Response;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Create Button widget
|
|
275
|
+
UButton* Button = NewObject<UButton>(WidgetBlueprint->GeneratedClass->GetDefaultObject(), UButton::StaticClass(), *WidgetName);
|
|
276
|
+
if (!Button)
|
|
277
|
+
{
|
|
278
|
+
Response->SetStringField(TEXT("error"), TEXT("Failed to create Button widget"));
|
|
279
|
+
return Response;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Set button text
|
|
283
|
+
UTextBlock* ButtonTextBlock = NewObject<UTextBlock>(Button, UTextBlock::StaticClass(), *(WidgetName + TEXT("_Text")));
|
|
284
|
+
if (ButtonTextBlock)
|
|
285
|
+
{
|
|
286
|
+
ButtonTextBlock->SetText(FText::FromString(ButtonText));
|
|
287
|
+
Button->AddChild(ButtonTextBlock);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Get canvas panel and add button
|
|
291
|
+
UCanvasPanel* RootCanvas = Cast<UCanvasPanel>(WidgetBlueprint->WidgetTree->RootWidget);
|
|
292
|
+
if (!RootCanvas)
|
|
293
|
+
{
|
|
294
|
+
Response->SetStringField(TEXT("error"), TEXT("Root widget is not a Canvas Panel"));
|
|
295
|
+
return Response;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Add to canvas and set position
|
|
299
|
+
UCanvasPanelSlot* ButtonSlot = RootCanvas->AddChildToCanvas(Button);
|
|
300
|
+
if (ButtonSlot)
|
|
301
|
+
{
|
|
302
|
+
const TArray<TSharedPtr<FJsonValue>>* Position;
|
|
303
|
+
if (Params->TryGetArrayField(TEXT("position"), Position) && Position->Num() >= 2)
|
|
304
|
+
{
|
|
305
|
+
FVector2D Pos(
|
|
306
|
+
(*Position)[0]->AsNumber(),
|
|
307
|
+
(*Position)[1]->AsNumber()
|
|
308
|
+
);
|
|
309
|
+
ButtonSlot->SetPosition(Pos);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Save the Widget Blueprint
|
|
314
|
+
FKismetEditorUtilities::CompileBlueprint(WidgetBlueprint);
|
|
315
|
+
UEditorAssetLibrary::SaveAsset(BlueprintPath, false);
|
|
316
|
+
|
|
317
|
+
Response->SetBoolField(TEXT("success"), true);
|
|
318
|
+
Response->SetStringField(TEXT("widget_name"), WidgetName);
|
|
319
|
+
return Response;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleBindWidgetEvent(const TSharedPtr<FJsonObject>& Params)
|
|
323
|
+
{
|
|
324
|
+
TSharedPtr<FJsonObject> Response = MakeShared<FJsonObject>();
|
|
325
|
+
|
|
326
|
+
// Get required parameters
|
|
327
|
+
FString BlueprintName;
|
|
328
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
329
|
+
{
|
|
330
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing blueprint_name parameter"));
|
|
331
|
+
return Response;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
FString WidgetName;
|
|
335
|
+
if (!Params->TryGetStringField(TEXT("widget_name"), WidgetName))
|
|
336
|
+
{
|
|
337
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing widget_name parameter"));
|
|
338
|
+
return Response;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
FString EventName;
|
|
342
|
+
if (!Params->TryGetStringField(TEXT("event_name"), EventName))
|
|
343
|
+
{
|
|
344
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing event_name parameter"));
|
|
345
|
+
return Response;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Load the Widget Blueprint
|
|
349
|
+
const FString BlueprintPath = FString::Printf(TEXT("/Game/Widgets/%s.%s"), *BlueprintName, *BlueprintName);
|
|
350
|
+
UWidgetBlueprint* WidgetBlueprint = Cast<UWidgetBlueprint>(UEditorAssetLibrary::LoadAsset(BlueprintPath));
|
|
351
|
+
if (!WidgetBlueprint)
|
|
352
|
+
{
|
|
353
|
+
Response->SetStringField(TEXT("error"), FString::Printf(TEXT("Failed to load Widget Blueprint: %s"), *BlueprintPath));
|
|
354
|
+
return Response;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Create the event graph if it doesn't exist
|
|
358
|
+
UEdGraph* EventGraph = FBlueprintEditorUtils::FindEventGraph(WidgetBlueprint);
|
|
359
|
+
if (!EventGraph)
|
|
360
|
+
{
|
|
361
|
+
Response->SetStringField(TEXT("error"), TEXT("Failed to find or create event graph"));
|
|
362
|
+
return Response;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Find the widget in the blueprint
|
|
366
|
+
UWidget* Widget = WidgetBlueprint->WidgetTree->FindWidget(*WidgetName);
|
|
367
|
+
if (!Widget)
|
|
368
|
+
{
|
|
369
|
+
Response->SetStringField(TEXT("error"), FString::Printf(TEXT("Failed to find widget: %s"), *WidgetName));
|
|
370
|
+
return Response;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Create the event node (e.g., OnClicked for buttons)
|
|
374
|
+
UK2Node_Event* EventNode = nullptr;
|
|
375
|
+
|
|
376
|
+
// Find existing nodes first
|
|
377
|
+
TArray<UK2Node_Event*> AllEventNodes;
|
|
378
|
+
FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Event>(WidgetBlueprint, AllEventNodes);
|
|
379
|
+
|
|
380
|
+
for (UK2Node_Event* Node : AllEventNodes)
|
|
381
|
+
{
|
|
382
|
+
if (Node->CustomFunctionName == FName(*EventName) && Node->EventReference.GetMemberParentClass() == Widget->GetClass())
|
|
383
|
+
{
|
|
384
|
+
EventNode = Node;
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// If no existing node, create a new one
|
|
390
|
+
if (!EventNode)
|
|
391
|
+
{
|
|
392
|
+
// Calculate position - place it below existing nodes
|
|
393
|
+
float MaxHeight = 0.0f;
|
|
394
|
+
for (UEdGraphNode* Node : EventGraph->Nodes)
|
|
395
|
+
{
|
|
396
|
+
MaxHeight = FMath::Max(MaxHeight, Node->NodePosY);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const FVector2D NodePos(200, MaxHeight + 200);
|
|
400
|
+
|
|
401
|
+
// Call CreateNewBoundEventForClass, which returns void, so we can't capture the return value directly
|
|
402
|
+
// We'll need to find the node after creating it
|
|
403
|
+
FKismetEditorUtilities::CreateNewBoundEventForClass(
|
|
404
|
+
Widget->GetClass(),
|
|
405
|
+
FName(*EventName),
|
|
406
|
+
WidgetBlueprint,
|
|
407
|
+
nullptr // We don't need a specific property binding
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
// Now find the newly created node
|
|
411
|
+
TArray<UK2Node_Event*> UpdatedEventNodes;
|
|
412
|
+
FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Event>(WidgetBlueprint, UpdatedEventNodes);
|
|
413
|
+
|
|
414
|
+
for (UK2Node_Event* Node : UpdatedEventNodes)
|
|
415
|
+
{
|
|
416
|
+
if (Node->CustomFunctionName == FName(*EventName) && Node->EventReference.GetMemberParentClass() == Widget->GetClass())
|
|
417
|
+
{
|
|
418
|
+
EventNode = Node;
|
|
419
|
+
|
|
420
|
+
// Set position of the node
|
|
421
|
+
EventNode->NodePosX = NodePos.X;
|
|
422
|
+
EventNode->NodePosY = NodePos.Y;
|
|
423
|
+
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (!EventNode)
|
|
430
|
+
{
|
|
431
|
+
Response->SetStringField(TEXT("error"), TEXT("Failed to create event node"));
|
|
432
|
+
return Response;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Save the Widget Blueprint
|
|
436
|
+
FKismetEditorUtilities::CompileBlueprint(WidgetBlueprint);
|
|
437
|
+
UEditorAssetLibrary::SaveAsset(BlueprintPath, false);
|
|
438
|
+
|
|
439
|
+
Response->SetBoolField(TEXT("success"), true);
|
|
440
|
+
Response->SetStringField(TEXT("event_name"), EventName);
|
|
441
|
+
return Response;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
TSharedPtr<FJsonObject> FUnrealMCPUMGCommands::HandleSetTextBlockBinding(const TSharedPtr<FJsonObject>& Params)
|
|
445
|
+
{
|
|
446
|
+
TSharedPtr<FJsonObject> Response = MakeShared<FJsonObject>();
|
|
447
|
+
|
|
448
|
+
// Get required parameters
|
|
449
|
+
FString BlueprintName;
|
|
450
|
+
if (!Params->TryGetStringField(TEXT("blueprint_name"), BlueprintName))
|
|
451
|
+
{
|
|
452
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing blueprint_name parameter"));
|
|
453
|
+
return Response;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
FString WidgetName;
|
|
457
|
+
if (!Params->TryGetStringField(TEXT("widget_name"), WidgetName))
|
|
458
|
+
{
|
|
459
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing widget_name parameter"));
|
|
460
|
+
return Response;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
FString BindingName;
|
|
464
|
+
if (!Params->TryGetStringField(TEXT("binding_name"), BindingName))
|
|
465
|
+
{
|
|
466
|
+
Response->SetStringField(TEXT("error"), TEXT("Missing binding_name parameter"));
|
|
467
|
+
return Response;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Load the Widget Blueprint
|
|
471
|
+
const FString BlueprintPath = FString::Printf(TEXT("/Game/Widgets/%s.%s"), *BlueprintName, *BlueprintName);
|
|
472
|
+
UWidgetBlueprint* WidgetBlueprint = Cast<UWidgetBlueprint>(UEditorAssetLibrary::LoadAsset(BlueprintPath));
|
|
473
|
+
if (!WidgetBlueprint)
|
|
474
|
+
{
|
|
475
|
+
Response->SetStringField(TEXT("error"), FString::Printf(TEXT("Failed to load Widget Blueprint: %s"), *BlueprintPath));
|
|
476
|
+
return Response;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Create a variable for binding if it doesn't exist
|
|
480
|
+
FBlueprintEditorUtils::AddMemberVariable(
|
|
481
|
+
WidgetBlueprint,
|
|
482
|
+
FName(*BindingName),
|
|
483
|
+
FEdGraphPinType(UEdGraphSchema_K2::PC_Text, NAME_None, nullptr, EPinContainerType::None, false, FEdGraphTerminalType())
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
// Find the TextBlock widget
|
|
487
|
+
UTextBlock* TextBlock = Cast<UTextBlock>(WidgetBlueprint->WidgetTree->FindWidget(FName(*WidgetName)));
|
|
488
|
+
if (!TextBlock)
|
|
489
|
+
{
|
|
490
|
+
Response->SetStringField(TEXT("error"), FString::Printf(TEXT("Failed to find TextBlock widget: %s"), *WidgetName));
|
|
491
|
+
return Response;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// Create binding function
|
|
495
|
+
const FString FunctionName = FString::Printf(TEXT("Get%s"), *BindingName);
|
|
496
|
+
UEdGraph* FuncGraph = FBlueprintEditorUtils::CreateNewGraph(
|
|
497
|
+
WidgetBlueprint,
|
|
498
|
+
FName(*FunctionName),
|
|
499
|
+
UEdGraph::StaticClass(),
|
|
500
|
+
UEdGraphSchema_K2::StaticClass()
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
if (FuncGraph)
|
|
504
|
+
{
|
|
505
|
+
// Add the function to the blueprint with proper template parameter
|
|
506
|
+
// Template requires null for last parameter when not using a signature-source
|
|
507
|
+
FBlueprintEditorUtils::AddFunctionGraph<UClass>(WidgetBlueprint, FuncGraph, false, nullptr);
|
|
508
|
+
|
|
509
|
+
// Create entry node
|
|
510
|
+
UK2Node_FunctionEntry* EntryNode = nullptr;
|
|
511
|
+
|
|
512
|
+
// Create entry node - use the API that exists in UE 5.5
|
|
513
|
+
EntryNode = NewObject<UK2Node_FunctionEntry>(FuncGraph);
|
|
514
|
+
FuncGraph->AddNode(EntryNode, false, false);
|
|
515
|
+
EntryNode->NodePosX = 0;
|
|
516
|
+
EntryNode->NodePosY = 0;
|
|
517
|
+
EntryNode->FunctionReference.SetExternalMember(FName(*FunctionName), WidgetBlueprint->GeneratedClass);
|
|
518
|
+
EntryNode->AllocateDefaultPins();
|
|
519
|
+
|
|
520
|
+
// Create get variable node
|
|
521
|
+
UK2Node_VariableGet* GetVarNode = NewObject<UK2Node_VariableGet>(FuncGraph);
|
|
522
|
+
GetVarNode->VariableReference.SetSelfMember(FName(*BindingName));
|
|
523
|
+
FuncGraph->AddNode(GetVarNode, false, false);
|
|
524
|
+
GetVarNode->NodePosX = 200;
|
|
525
|
+
GetVarNode->NodePosY = 0;
|
|
526
|
+
GetVarNode->AllocateDefaultPins();
|
|
527
|
+
|
|
528
|
+
// Connect nodes
|
|
529
|
+
UEdGraphPin* EntryThenPin = EntryNode->FindPin(UEdGraphSchema_K2::PN_Then);
|
|
530
|
+
UEdGraphPin* GetVarOutPin = GetVarNode->FindPin(UEdGraphSchema_K2::PN_ReturnValue);
|
|
531
|
+
if (EntryThenPin && GetVarOutPin)
|
|
532
|
+
{
|
|
533
|
+
EntryThenPin->MakeLinkTo(GetVarOutPin);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Save the Widget Blueprint
|
|
538
|
+
FKismetEditorUtilities::CompileBlueprint(WidgetBlueprint);
|
|
539
|
+
UEditorAssetLibrary::SaveAsset(BlueprintPath, false);
|
|
540
|
+
|
|
541
|
+
Response->SetBoolField(TEXT("success"), true);
|
|
542
|
+
Response->SetStringField(TEXT("binding_name"), BindingName);
|
|
543
|
+
return Response;
|
|
544
|
+
}
|