ue-mcp 0.4.26 → 0.4.28

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.
@@ -19,6 +19,13 @@ export const animationTool = categoryTool("animation", "Animation assets, skelet
19
19
  get_bone_transforms: bp("get_bone_transforms"),
20
20
  set_montage_sequence: bp("set_montage_sequence"),
21
21
  set_montage_properties: bp("set_montage_properties"),
22
+ // State machine authoring
23
+ create_state_machine: bp("create_state_machine"),
24
+ add_state: bp("add_state"),
25
+ add_transition: bp("add_transition"),
26
+ set_state_animation: bp("set_state_animation"),
27
+ set_transition_blend: bp("set_transition_blend"),
28
+ read_state_machine: bp("read_state_machine"),
22
29
  }, `- read_anim_blueprint: Read AnimBP structure. Params: assetPath
23
30
  - read_montage: Read montage. Params: assetPath
24
31
  - read_sequence: Read anim sequence. Params: assetPath
@@ -36,7 +43,13 @@ export const animationTool = categoryTool("animation", "Animation assets, skelet
36
43
  - set_bone_keyframes: Set bone transform keyframes. Params: assetPath, boneName, keyframes (array of {frame, location?, rotation?, scale?})
37
44
  - get_bone_transforms: Read reference pose transforms. Params: skeletonPath, boneNames? (array filter)
38
45
  - set_montage_sequence: Replace animation sequence in a montage (auto-updates montage duration). Params: assetPath, animSequencePath, slotIndex?
39
- - set_montage_properties: Set montage properties directly. Params: assetPath, sequenceLength?, rateScale?, blendIn?, blendOut?`, {
46
+ - set_montage_properties: Set montage properties directly. Params: assetPath, sequenceLength?, rateScale?, blendIn?, blendOut?
47
+ - create_state_machine: Create state machine in AnimBP AnimGraph. Params: assetPath, name?, graphName?
48
+ - add_state: Add state to a state machine. Params: assetPath, stateMachineName, stateName
49
+ - add_transition: Add directed transition between states. Params: assetPath, stateMachineName, fromState, toState
50
+ - set_state_animation: Assign anim asset to state. Params: assetPath, stateMachineName, stateName, animAssetPath
51
+ - set_transition_blend: Set blend type/duration on transition. Params: assetPath, stateMachineName, fromState, toState, blendDuration?, blendLogic? (Standard|Inertialization)
52
+ - read_state_machine: Read state machine topology. Params: assetPath, stateMachineName`, {
40
53
  assetPath: z.string().optional(),
41
54
  directory: z.string().optional(),
42
55
  recursive: z.boolean().optional(),
@@ -59,6 +72,15 @@ export const animationTool = categoryTool("animation", "Animation assets, skelet
59
72
  boneName: z.string().optional(),
60
73
  boneNames: z.array(z.string()).optional(),
61
74
  parentClass: z.string().optional().describe("Parent AnimInstance class name for create_anim_blueprint"),
75
+ // State machine params
76
+ stateMachineName: z.string().optional(),
77
+ stateName: z.string().optional(),
78
+ fromState: z.string().optional(),
79
+ toState: z.string().optional(),
80
+ animAssetPath: z.string().optional().describe("Path to animation sequence or blendspace"),
81
+ blendDuration: z.number().optional(),
82
+ blendLogic: z.string().optional().describe("Standard or Inertialization"),
83
+ graphName: z.string().optional().describe("Target graph name (default: AnimGraph)"),
62
84
  keyframes: z.array(z.object({
63
85
  frame: z.number(),
64
86
  location: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),
@@ -1 +1 @@
1
- {"version":3,"file":"animation.js","sourceRoot":"","sources":["../../src/tools/animation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"animation.js","sourceRoot":"","sources":["../../src/tools/animation.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ export const blueprintTool = categoryTool("blueprint", "Blueprint reading, autho
17
17
  connect_pins: bp("connect_pins"),
18
18
  add_component: bp("add_component", (p) => ({ path: p.assetPath, componentClass: p.componentClass, componentName: p.componentName ?? p.componentClass })),
19
19
  set_component_property: bp("set_blueprint_component_property", (p) => ({ path: p.assetPath, componentName: p.componentName, propertyName: p.propertyName, value: p.value })),
20
+ set_class_default: bp("set_class_default", (p) => ({ path: p.assetPath, propertyName: p.propertyName, value: p.value })),
20
21
  compile: bp("compile_blueprint", (p) => ({ path: p.assetPath })),
21
22
  list_node_types: bp("list_node_types"),
22
23
  search_node_types: bp("search_node_types"),
@@ -41,6 +42,7 @@ export const blueprintTool = categoryTool("blueprint", "Blueprint reading, autho
41
42
  - connect_pins: Wire nodes. Params: sourceNode, sourcePin, targetNode, targetPin, assetPath, graphName?
42
43
  - add_component: Add BP component. Params: assetPath, componentClass, componentName?
43
44
  - set_component_property: Set property on SCS component template (supports dot paths, asset paths for object refs). Params: assetPath, componentName, propertyName, value
45
+ - set_class_default: Set UPROPERTY on Blueprint CDO (FName, object refs, soft refs, TArray, TMap via ImportText). Params: assetPath, propertyName, value
44
46
  - compile: Compile Blueprint. Params: assetPath
45
47
  - list_node_types: List node types. Params: category?, includeFunctions?
46
48
  - search_node_types: Search nodes. Params: query
@@ -1 +1 @@
1
- {"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../../src/tools/blueprint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../../src/tools/blueprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,EAAE,EAAgB,MAAM,aAAa,CAAC;AAE7D,MAAM,CAAC,MAAM,aAAa,GAAY,YAAY,CAChD,WAAW,EACX,2IAA2I,EAC3I;IACE,IAAI,EAAe,EAAE,CAAC,gBAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IACvE,cAAc,EAAK,EAAE,CAAC,0BAA0B,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IACjF,cAAc,EAAK,EAAE,CAAC,0BAA0B,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IACjF,UAAU,EAAS,EAAE,CAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IACrG,MAAM,EAAa,EAAE,CAAC,kBAAkB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACrG,YAAY,EAAO,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IACpG,uBAAuB,EAAE,EAAE,CAAC,yBAAyB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,EAAE,iBAAiB,EAAE,CAAC,CAAC,iBAAiB,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;IAChQ,eAAe,EAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;IACtG,eAAe,EAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;IACtG,eAAe,EAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAChH,QAAQ,EAAW,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,YAAY,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3J,WAAW,EAAQ,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClH,iBAAiB,EAAE,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACtK,YAAY,EAAO,EAAE,CAAC,cAAc,CAAC;IACrC,aAAa,EAAM,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;IAC5J,sBAAsB,EAAE,EAAE,CAAC,kCAAkC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC5K,iBAAiB,EAAE,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IACxH,OAAO,EAAY,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAC1E,eAAe,EAAI,EAAE,CAAC,iBAAiB,CAAC;IACxC,iBAAiB,EAAE,EAAE,CAAC,mBAAmB,CAAC;IAC1C,gBAAgB,EAAG,EAAE,CAAC,4BAA4B,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IACnF,aAAa,EAAM,EAAE,CAAC,yBAAyB,CAAC;IAChD,WAAW,EAAY,EAAE,CAAC,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAClF,oBAAoB,EAAE,EAAE,CAAC,sBAAsB,CAAC;CACjD,EACD;;;;;;;;;;;;;;;;;;;;;;;oEAuBkE,EAClE;IACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IACjE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;IACrF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/D,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9D,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC9E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3E,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACxC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC3E,CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ue-mcp",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "description": "Unreal Engine MCP server — 19 tools, 300+ actions for AI-driven editor control",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,6 +29,18 @@
29
29
  #include "Animation/AnimData/IAnimationDataModel.h"
30
30
  #include "Editor.h"
31
31
 
32
+ // State machine authoring
33
+ #include "AnimGraphNode_StateMachine.h"
34
+ #include "AnimStateNode.h"
35
+ #include "AnimStateTransitionNode.h"
36
+ #include "AnimStateEntryNode.h"
37
+ #include "AnimationStateMachineGraph.h"
38
+ #include "AnimGraphNode_SequencePlayer.h"
39
+ #include "AnimGraphNode_BlendSpacePlayer.h"
40
+ #include "AnimGraphNode_Inertialization.h"
41
+ #include "Kismet2/BlueprintEditorUtils.h"
42
+ #include "Kismet2/KismetEditorUtilities.h"
43
+
32
44
  void FAnimationHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
33
45
  {
34
46
  Registry.RegisterHandler(TEXT("list_anim_assets"), &ListAnimAssets);
@@ -51,6 +63,14 @@ void FAnimationHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
51
63
  Registry.RegisterHandler(TEXT("get_bone_transforms"), &GetBoneTransforms);
52
64
  Registry.RegisterHandler(TEXT("set_montage_sequence"), &SetMontageSequence);
53
65
  Registry.RegisterHandler(TEXT("set_montage_properties"), &SetMontageProperties);
66
+
67
+ // State machine authoring
68
+ Registry.RegisterHandler(TEXT("create_state_machine"), &CreateStateMachine);
69
+ Registry.RegisterHandler(TEXT("add_state"), &AddState);
70
+ Registry.RegisterHandler(TEXT("add_transition"), &AddTransition);
71
+ Registry.RegisterHandler(TEXT("set_state_animation"), &SetStateAnimation);
72
+ Registry.RegisterHandler(TEXT("set_transition_blend"), &SetTransitionBlend);
73
+ Registry.RegisterHandler(TEXT("read_state_machine"), &ReadStateMachine);
54
74
  }
55
75
 
56
76
  TSharedPtr<FJsonValue> FAnimationHandlers::ListAnimAssets(const TSharedPtr<FJsonObject>& Params)
@@ -1566,3 +1586,644 @@ TSharedPtr<FJsonValue> FAnimationHandlers::SetMontageProperties(const TSharedPtr
1566
1586
 
1567
1587
  return MakeShared<FJsonValueObject>(Result);
1568
1588
  }
1589
+
1590
+ // ─── State Machine Helpers ────────────────────────────────────────
1591
+
1592
+ static UAnimBlueprint* LoadAnimBP(const FString& Path)
1593
+ {
1594
+ return LoadObject<UAnimBlueprint>(nullptr, *Path);
1595
+ }
1596
+
1597
+ static UEdGraph* FindGraphByName(UBlueprint* BP, const FString& Name)
1598
+ {
1599
+ TArray<UEdGraph*> All;
1600
+ BP->GetAllGraphs(All);
1601
+ for (UEdGraph* G : All)
1602
+ {
1603
+ if (G && G->GetName() == Name) return G;
1604
+ }
1605
+ return nullptr;
1606
+ }
1607
+
1608
+ // Find the SM container node (UAnimGraphNode_StateMachine) by its machine name
1609
+ static UAnimGraphNode_StateMachine* FindStateMachineNode(UBlueprint* BP, const FString& MachineName)
1610
+ {
1611
+ TArray<UEdGraph*> All;
1612
+ BP->GetAllGraphs(All);
1613
+ for (UEdGraph* G : All)
1614
+ {
1615
+ for (UEdGraphNode* Node : G->Nodes)
1616
+ {
1617
+ if (UAnimGraphNode_StateMachine* SM = Cast<UAnimGraphNode_StateMachine>(Node))
1618
+ {
1619
+ if (UAnimationStateMachineGraph* SMGraph = Cast<UAnimationStateMachineGraph>(SM->EditorStateMachineGraph))
1620
+ {
1621
+ if (SMGraph->GetName() == MachineName || SM->GetNodeTitle(ENodeTitleType::FullTitle).ToString().Contains(MachineName))
1622
+ {
1623
+ return SM;
1624
+ }
1625
+ }
1626
+ }
1627
+ }
1628
+ }
1629
+ return nullptr;
1630
+ }
1631
+
1632
+ // Find a state node by name within a state machine graph
1633
+ static UAnimStateNode* FindStateNode(UAnimationStateMachineGraph* SMGraph, const FString& StateName)
1634
+ {
1635
+ for (UEdGraphNode* Node : SMGraph->Nodes)
1636
+ {
1637
+ if (UAnimStateNode* State = Cast<UAnimStateNode>(Node))
1638
+ {
1639
+ if (State->GetStateName() == StateName)
1640
+ {
1641
+ return State;
1642
+ }
1643
+ }
1644
+ }
1645
+ return nullptr;
1646
+ }
1647
+
1648
+ static void CompileAndSave(UBlueprint* BP)
1649
+ {
1650
+ FKismetEditorUtilities::CompileBlueprint(BP);
1651
+ UPackage* Package = BP->GetOutermost();
1652
+ if (Package)
1653
+ {
1654
+ Package->MarkPackageDirty();
1655
+ FString FileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
1656
+ FSavePackageArgs SaveArgs;
1657
+ SaveArgs.TopLevelFlags = RF_Standalone;
1658
+ UPackage::SavePackage(Package, nullptr, *FileName, SaveArgs);
1659
+ }
1660
+ }
1661
+
1662
+ // ─── State Machine Handlers ──────────────────────────────────────
1663
+
1664
+ TSharedPtr<FJsonValue> FAnimationHandlers::CreateStateMachine(const TSharedPtr<FJsonObject>& Params)
1665
+ {
1666
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1667
+
1668
+ FString AssetPath;
1669
+ if (!Params->TryGetStringField(TEXT("assetPath"), AssetPath) && !Params->TryGetStringField(TEXT("path"), AssetPath))
1670
+ {
1671
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath'"));
1672
+ Result->SetBoolField(TEXT("success"), false);
1673
+ return MakeShared<FJsonValueObject>(Result);
1674
+ }
1675
+
1676
+ FString Name = TEXT("NewStateMachine");
1677
+ Params->TryGetStringField(TEXT("name"), Name);
1678
+
1679
+ FString GraphName = TEXT("AnimGraph");
1680
+ Params->TryGetStringField(TEXT("graphName"), GraphName);
1681
+
1682
+ UAnimBlueprint* AnimBP = LoadAnimBP(AssetPath);
1683
+ if (!AnimBP)
1684
+ {
1685
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AnimBlueprint not found: %s"), *AssetPath));
1686
+ Result->SetBoolField(TEXT("success"), false);
1687
+ return MakeShared<FJsonValueObject>(Result);
1688
+ }
1689
+
1690
+ UEdGraph* TargetGraph = FindGraphByName(AnimBP, GraphName);
1691
+ if (!TargetGraph)
1692
+ {
1693
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Graph not found: %s"), *GraphName));
1694
+ Result->SetBoolField(TEXT("success"), false);
1695
+ return MakeShared<FJsonValueObject>(Result);
1696
+ }
1697
+
1698
+ // Create the state machine container node in the AnimGraph
1699
+ UAnimGraphNode_StateMachine* SMNode = NewObject<UAnimGraphNode_StateMachine>(TargetGraph);
1700
+ SMNode->GetStateMachineNode()->SetStateMachineName(FName(*Name));
1701
+ TargetGraph->AddNode(SMNode, false, false);
1702
+ SMNode->CreateNewGuid();
1703
+ SMNode->PostPlacedNewNode();
1704
+ SMNode->AllocateDefaultPins();
1705
+ SMNode->NodePosX = 200;
1706
+ SMNode->NodePosY = 0;
1707
+
1708
+ CompileAndSave(AnimBP);
1709
+
1710
+ Result->SetStringField(TEXT("assetPath"), AssetPath);
1711
+ Result->SetStringField(TEXT("name"), Name);
1712
+ Result->SetStringField(TEXT("graphName"), GraphName);
1713
+ Result->SetBoolField(TEXT("success"), true);
1714
+
1715
+ return MakeShared<FJsonValueObject>(Result);
1716
+ }
1717
+
1718
+ TSharedPtr<FJsonValue> FAnimationHandlers::AddState(const TSharedPtr<FJsonObject>& Params)
1719
+ {
1720
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1721
+
1722
+ FString AssetPath;
1723
+ if (!Params->TryGetStringField(TEXT("assetPath"), AssetPath) && !Params->TryGetStringField(TEXT("path"), AssetPath))
1724
+ {
1725
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath'"));
1726
+ Result->SetBoolField(TEXT("success"), false);
1727
+ return MakeShared<FJsonValueObject>(Result);
1728
+ }
1729
+
1730
+ FString SMName;
1731
+ if (!Params->TryGetStringField(TEXT("stateMachineName"), SMName))
1732
+ {
1733
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'stateMachineName'"));
1734
+ Result->SetBoolField(TEXT("success"), false);
1735
+ return MakeShared<FJsonValueObject>(Result);
1736
+ }
1737
+
1738
+ FString StateName;
1739
+ if (!Params->TryGetStringField(TEXT("stateName"), StateName))
1740
+ {
1741
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'stateName'"));
1742
+ Result->SetBoolField(TEXT("success"), false);
1743
+ return MakeShared<FJsonValueObject>(Result);
1744
+ }
1745
+
1746
+ UAnimBlueprint* AnimBP = LoadAnimBP(AssetPath);
1747
+ if (!AnimBP)
1748
+ {
1749
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AnimBlueprint not found: %s"), *AssetPath));
1750
+ Result->SetBoolField(TEXT("success"), false);
1751
+ return MakeShared<FJsonValueObject>(Result);
1752
+ }
1753
+
1754
+ UAnimGraphNode_StateMachine* SMNode = FindStateMachineNode(AnimBP, SMName);
1755
+ if (!SMNode)
1756
+ {
1757
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State machine '%s' not found"), *SMName));
1758
+ Result->SetBoolField(TEXT("success"), false);
1759
+ return MakeShared<FJsonValueObject>(Result);
1760
+ }
1761
+
1762
+ UAnimationStateMachineGraph* SMGraph = Cast<UAnimationStateMachineGraph>(SMNode->EditorStateMachineGraph);
1763
+ if (!SMGraph)
1764
+ {
1765
+ Result->SetStringField(TEXT("error"), TEXT("State machine has no editor graph"));
1766
+ Result->SetBoolField(TEXT("success"), false);
1767
+ return MakeShared<FJsonValueObject>(Result);
1768
+ }
1769
+
1770
+ // Check for duplicate
1771
+ if (FindStateNode(SMGraph, StateName))
1772
+ {
1773
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State '%s' already exists"), *StateName));
1774
+ Result->SetBoolField(TEXT("success"), false);
1775
+ return MakeShared<FJsonValueObject>(Result);
1776
+ }
1777
+
1778
+ // Create state node
1779
+ UAnimStateNode* NewState = NewObject<UAnimStateNode>(SMGraph);
1780
+ SMGraph->AddNode(NewState, false, false);
1781
+ NewState->CreateNewGuid();
1782
+ NewState->PostPlacedNewNode();
1783
+ NewState->AllocateDefaultPins();
1784
+
1785
+ // Set the state name via the BoundGraph (the state's internal graph)
1786
+ if (NewState->BoundGraph)
1787
+ {
1788
+ NewState->BoundGraph->Rename(*StateName);
1789
+ }
1790
+
1791
+ // Position states in a grid
1792
+ int32 StateCount = 0;
1793
+ for (UEdGraphNode* N : SMGraph->Nodes) { if (Cast<UAnimStateNode>(N)) StateCount++; }
1794
+ NewState->NodePosX = 300 + ((StateCount - 1) % 4) * 300;
1795
+ NewState->NodePosY = ((StateCount - 1) / 4) * 200;
1796
+
1797
+ CompileAndSave(AnimBP);
1798
+
1799
+ Result->SetStringField(TEXT("assetPath"), AssetPath);
1800
+ Result->SetStringField(TEXT("stateMachineName"), SMName);
1801
+ Result->SetStringField(TEXT("stateName"), StateName);
1802
+ Result->SetBoolField(TEXT("success"), true);
1803
+
1804
+ return MakeShared<FJsonValueObject>(Result);
1805
+ }
1806
+
1807
+ TSharedPtr<FJsonValue> FAnimationHandlers::AddTransition(const TSharedPtr<FJsonObject>& Params)
1808
+ {
1809
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1810
+
1811
+ FString AssetPath;
1812
+ if (!Params->TryGetStringField(TEXT("assetPath"), AssetPath) && !Params->TryGetStringField(TEXT("path"), AssetPath))
1813
+ {
1814
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath'"));
1815
+ Result->SetBoolField(TEXT("success"), false);
1816
+ return MakeShared<FJsonValueObject>(Result);
1817
+ }
1818
+
1819
+ FString SMName;
1820
+ if (!Params->TryGetStringField(TEXT("stateMachineName"), SMName))
1821
+ {
1822
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'stateMachineName'"));
1823
+ Result->SetBoolField(TEXT("success"), false);
1824
+ return MakeShared<FJsonValueObject>(Result);
1825
+ }
1826
+
1827
+ FString FromState, ToState;
1828
+ if (!Params->TryGetStringField(TEXT("fromState"), FromState))
1829
+ {
1830
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'fromState'"));
1831
+ Result->SetBoolField(TEXT("success"), false);
1832
+ return MakeShared<FJsonValueObject>(Result);
1833
+ }
1834
+ if (!Params->TryGetStringField(TEXT("toState"), ToState))
1835
+ {
1836
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'toState'"));
1837
+ Result->SetBoolField(TEXT("success"), false);
1838
+ return MakeShared<FJsonValueObject>(Result);
1839
+ }
1840
+
1841
+ UAnimBlueprint* AnimBP = LoadAnimBP(AssetPath);
1842
+ if (!AnimBP)
1843
+ {
1844
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AnimBlueprint not found: %s"), *AssetPath));
1845
+ Result->SetBoolField(TEXT("success"), false);
1846
+ return MakeShared<FJsonValueObject>(Result);
1847
+ }
1848
+
1849
+ UAnimGraphNode_StateMachine* SMNode = FindStateMachineNode(AnimBP, SMName);
1850
+ if (!SMNode)
1851
+ {
1852
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State machine '%s' not found"), *SMName));
1853
+ Result->SetBoolField(TEXT("success"), false);
1854
+ return MakeShared<FJsonValueObject>(Result);
1855
+ }
1856
+
1857
+ UAnimationStateMachineGraph* SMGraph = Cast<UAnimationStateMachineGraph>(SMNode->EditorStateMachineGraph);
1858
+ UAnimStateNode* From = FindStateNode(SMGraph, FromState);
1859
+ UAnimStateNode* To = FindStateNode(SMGraph, ToState);
1860
+ if (!From)
1861
+ {
1862
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State '%s' not found"), *FromState));
1863
+ Result->SetBoolField(TEXT("success"), false);
1864
+ return MakeShared<FJsonValueObject>(Result);
1865
+ }
1866
+ if (!To)
1867
+ {
1868
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State '%s' not found"), *ToState));
1869
+ Result->SetBoolField(TEXT("success"), false);
1870
+ return MakeShared<FJsonValueObject>(Result);
1871
+ }
1872
+
1873
+ // Create transition node
1874
+ UAnimStateTransitionNode* TransNode = NewObject<UAnimStateTransitionNode>(SMGraph);
1875
+ SMGraph->AddNode(TransNode, false, false);
1876
+ TransNode->CreateNewGuid();
1877
+ TransNode->PostPlacedNewNode();
1878
+ TransNode->AllocateDefaultPins();
1879
+
1880
+ // Position between the two states
1881
+ TransNode->NodePosX = (From->NodePosX + To->NodePosX) / 2;
1882
+ TransNode->NodePosY = (From->NodePosY + To->NodePosY) / 2;
1883
+
1884
+ // Wire: From output → Transition input, Transition output → To input
1885
+ UEdGraphPin* FromOut = From->GetOutputPin();
1886
+ UEdGraphPin* TransIn = TransNode->GetInputPin();
1887
+ UEdGraphPin* TransOut = TransNode->GetOutputPin();
1888
+ UEdGraphPin* ToIn = To->GetInputPin();
1889
+
1890
+ if (FromOut && TransIn)
1891
+ {
1892
+ FromOut->MakeLinkTo(TransIn);
1893
+ }
1894
+ if (TransOut && ToIn)
1895
+ {
1896
+ TransOut->MakeLinkTo(ToIn);
1897
+ }
1898
+
1899
+ CompileAndSave(AnimBP);
1900
+
1901
+ Result->SetStringField(TEXT("assetPath"), AssetPath);
1902
+ Result->SetStringField(TEXT("stateMachineName"), SMName);
1903
+ Result->SetStringField(TEXT("fromState"), FromState);
1904
+ Result->SetStringField(TEXT("toState"), ToState);
1905
+ Result->SetBoolField(TEXT("success"), true);
1906
+
1907
+ return MakeShared<FJsonValueObject>(Result);
1908
+ }
1909
+
1910
+ TSharedPtr<FJsonValue> FAnimationHandlers::SetStateAnimation(const TSharedPtr<FJsonObject>& Params)
1911
+ {
1912
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1913
+
1914
+ FString AssetPath;
1915
+ if (!Params->TryGetStringField(TEXT("assetPath"), AssetPath) && !Params->TryGetStringField(TEXT("path"), AssetPath))
1916
+ {
1917
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath'"));
1918
+ Result->SetBoolField(TEXT("success"), false);
1919
+ return MakeShared<FJsonValueObject>(Result);
1920
+ }
1921
+
1922
+ FString SMName, StateName, AnimAssetPath;
1923
+ if (!Params->TryGetStringField(TEXT("stateMachineName"), SMName) ||
1924
+ !Params->TryGetStringField(TEXT("stateName"), StateName) ||
1925
+ !Params->TryGetStringField(TEXT("animAssetPath"), AnimAssetPath))
1926
+ {
1927
+ Result->SetStringField(TEXT("error"), TEXT("Missing required params: stateMachineName, stateName, animAssetPath"));
1928
+ Result->SetBoolField(TEXT("success"), false);
1929
+ return MakeShared<FJsonValueObject>(Result);
1930
+ }
1931
+
1932
+ UAnimBlueprint* AnimBP = LoadAnimBP(AssetPath);
1933
+ if (!AnimBP)
1934
+ {
1935
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AnimBlueprint not found: %s"), *AssetPath));
1936
+ Result->SetBoolField(TEXT("success"), false);
1937
+ return MakeShared<FJsonValueObject>(Result);
1938
+ }
1939
+
1940
+ UAnimGraphNode_StateMachine* SMNode = FindStateMachineNode(AnimBP, SMName);
1941
+ if (!SMNode)
1942
+ {
1943
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State machine '%s' not found"), *SMName));
1944
+ Result->SetBoolField(TEXT("success"), false);
1945
+ return MakeShared<FJsonValueObject>(Result);
1946
+ }
1947
+
1948
+ UAnimationStateMachineGraph* SMGraph = Cast<UAnimationStateMachineGraph>(SMNode->EditorStateMachineGraph);
1949
+ UAnimStateNode* State = FindStateNode(SMGraph, StateName);
1950
+ if (!State)
1951
+ {
1952
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State '%s' not found"), *StateName));
1953
+ Result->SetBoolField(TEXT("success"), false);
1954
+ return MakeShared<FJsonValueObject>(Result);
1955
+ }
1956
+
1957
+ // Load the animation asset
1958
+ UAnimationAsset* AnimAsset = LoadObject<UAnimationAsset>(nullptr, *AnimAssetPath);
1959
+ if (!AnimAsset)
1960
+ {
1961
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Animation asset not found: %s"), *AnimAssetPath));
1962
+ Result->SetBoolField(TEXT("success"), false);
1963
+ return MakeShared<FJsonValueObject>(Result);
1964
+ }
1965
+
1966
+ // Get the state's bound graph (internal graph that plays the animation)
1967
+ UEdGraph* StateGraph = State->BoundGraph;
1968
+ if (!StateGraph)
1969
+ {
1970
+ Result->SetStringField(TEXT("error"), TEXT("State has no BoundGraph"));
1971
+ Result->SetBoolField(TEXT("success"), false);
1972
+ return MakeShared<FJsonValueObject>(Result);
1973
+ }
1974
+
1975
+ // Find or create the appropriate player node inside the state graph
1976
+ // Look for existing sequence player or blendspace player
1977
+ UAnimGraphNode_SequencePlayer* SeqPlayer = nullptr;
1978
+ UAnimGraphNode_BlendSpacePlayer* BSPlayer = nullptr;
1979
+ for (UEdGraphNode* Node : StateGraph->Nodes)
1980
+ {
1981
+ if (!SeqPlayer) SeqPlayer = Cast<UAnimGraphNode_SequencePlayer>(Node);
1982
+ if (!BSPlayer) BSPlayer = Cast<UAnimGraphNode_BlendSpacePlayer>(Node);
1983
+ }
1984
+
1985
+ if (UAnimSequence* Seq = Cast<UAnimSequence>(AnimAsset))
1986
+ {
1987
+ if (!SeqPlayer)
1988
+ {
1989
+ SeqPlayer = NewObject<UAnimGraphNode_SequencePlayer>(StateGraph);
1990
+ StateGraph->AddNode(SeqPlayer, false, false);
1991
+ SeqPlayer->CreateNewGuid();
1992
+ SeqPlayer->PostPlacedNewNode();
1993
+ SeqPlayer->AllocateDefaultPins();
1994
+ }
1995
+ SeqPlayer->GetSequencePlayerNode()->SetSequence(Seq);
1996
+ }
1997
+ else if (UBlendSpace* BS = Cast<UBlendSpace>(AnimAsset))
1998
+ {
1999
+ if (!BSPlayer)
2000
+ {
2001
+ BSPlayer = NewObject<UAnimGraphNode_BlendSpacePlayer>(StateGraph);
2002
+ StateGraph->AddNode(BSPlayer, false, false);
2003
+ BSPlayer->CreateNewGuid();
2004
+ BSPlayer->PostPlacedNewNode();
2005
+ BSPlayer->AllocateDefaultPins();
2006
+ }
2007
+ BSPlayer->GetBlendSpacePlayerNode()->SetBlendSpace(BS);
2008
+ }
2009
+ else
2010
+ {
2011
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Unsupported animation asset type: %s"), *AnimAsset->GetClass()->GetName()));
2012
+ Result->SetBoolField(TEXT("success"), false);
2013
+ return MakeShared<FJsonValueObject>(Result);
2014
+ }
2015
+
2016
+ CompileAndSave(AnimBP);
2017
+
2018
+ Result->SetStringField(TEXT("assetPath"), AssetPath);
2019
+ Result->SetStringField(TEXT("stateName"), StateName);
2020
+ Result->SetStringField(TEXT("animAssetPath"), AnimAssetPath);
2021
+ Result->SetBoolField(TEXT("success"), true);
2022
+
2023
+ return MakeShared<FJsonValueObject>(Result);
2024
+ }
2025
+
2026
+ TSharedPtr<FJsonValue> FAnimationHandlers::SetTransitionBlend(const TSharedPtr<FJsonObject>& Params)
2027
+ {
2028
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
2029
+
2030
+ FString AssetPath;
2031
+ if (!Params->TryGetStringField(TEXT("assetPath"), AssetPath) && !Params->TryGetStringField(TEXT("path"), AssetPath))
2032
+ {
2033
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath'"));
2034
+ Result->SetBoolField(TEXT("success"), false);
2035
+ return MakeShared<FJsonValueObject>(Result);
2036
+ }
2037
+
2038
+ FString SMName, FromState, ToState;
2039
+ if (!Params->TryGetStringField(TEXT("stateMachineName"), SMName) ||
2040
+ !Params->TryGetStringField(TEXT("fromState"), FromState) ||
2041
+ !Params->TryGetStringField(TEXT("toState"), ToState))
2042
+ {
2043
+ Result->SetStringField(TEXT("error"), TEXT("Missing required params: stateMachineName, fromState, toState"));
2044
+ Result->SetBoolField(TEXT("success"), false);
2045
+ return MakeShared<FJsonValueObject>(Result);
2046
+ }
2047
+
2048
+ UAnimBlueprint* AnimBP = LoadAnimBP(AssetPath);
2049
+ if (!AnimBP)
2050
+ {
2051
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AnimBlueprint not found: %s"), *AssetPath));
2052
+ Result->SetBoolField(TEXT("success"), false);
2053
+ return MakeShared<FJsonValueObject>(Result);
2054
+ }
2055
+
2056
+ UAnimGraphNode_StateMachine* SMNode = FindStateMachineNode(AnimBP, SMName);
2057
+ if (!SMNode)
2058
+ {
2059
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State machine '%s' not found"), *SMName));
2060
+ Result->SetBoolField(TEXT("success"), false);
2061
+ return MakeShared<FJsonValueObject>(Result);
2062
+ }
2063
+
2064
+ UAnimationStateMachineGraph* SMGraph = Cast<UAnimationStateMachineGraph>(SMNode->EditorStateMachineGraph);
2065
+
2066
+ // Find the transition between fromState and toState
2067
+ UAnimStateTransitionNode* TransNode = nullptr;
2068
+ for (UEdGraphNode* Node : SMGraph->Nodes)
2069
+ {
2070
+ if (UAnimStateTransitionNode* T = Cast<UAnimStateTransitionNode>(Node))
2071
+ {
2072
+ UAnimStateNode* Prev = Cast<UAnimStateNode>(T->GetPreviousState());
2073
+ UAnimStateNode* Next = Cast<UAnimStateNode>(T->GetNextState());
2074
+ if (Prev && Next && Prev->GetStateName() == FromState && Next->GetStateName() == ToState)
2075
+ {
2076
+ TransNode = T;
2077
+ break;
2078
+ }
2079
+ }
2080
+ }
2081
+
2082
+ if (!TransNode)
2083
+ {
2084
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("No transition from '%s' to '%s'"), *FromState, *ToState));
2085
+ Result->SetBoolField(TEXT("success"), false);
2086
+ return MakeShared<FJsonValueObject>(Result);
2087
+ }
2088
+
2089
+ // Set blend duration
2090
+ double BlendDuration = 0.2;
2091
+ if (Params->TryGetNumberField(TEXT("blendDuration"), BlendDuration))
2092
+ {
2093
+ TransNode->CrossfadeDuration = static_cast<float>(BlendDuration);
2094
+ }
2095
+
2096
+ // Set blend logic (Standard vs Inertialization)
2097
+ FString BlendLogic;
2098
+ if (Params->TryGetStringField(TEXT("blendLogic"), BlendLogic))
2099
+ {
2100
+ if (BlendLogic.Equals(TEXT("Inertialization"), ESearchCase::IgnoreCase))
2101
+ {
2102
+ TransNode->BlendMode = EAlphaBlendOption::Linear;
2103
+ TransNode->LogicType = ETransitionLogicType::TLT_Inertialization;
2104
+ }
2105
+ else // Standard
2106
+ {
2107
+ TransNode->LogicType = ETransitionLogicType::TLT_StandardBlend;
2108
+ }
2109
+ }
2110
+
2111
+ CompileAndSave(AnimBP);
2112
+
2113
+ Result->SetStringField(TEXT("assetPath"), AssetPath);
2114
+ Result->SetStringField(TEXT("fromState"), FromState);
2115
+ Result->SetStringField(TEXT("toState"), ToState);
2116
+ Result->SetNumberField(TEXT("blendDuration"), BlendDuration);
2117
+ Result->SetBoolField(TEXT("success"), true);
2118
+
2119
+ return MakeShared<FJsonValueObject>(Result);
2120
+ }
2121
+
2122
+ TSharedPtr<FJsonValue> FAnimationHandlers::ReadStateMachine(const TSharedPtr<FJsonObject>& Params)
2123
+ {
2124
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
2125
+
2126
+ FString AssetPath;
2127
+ if (!Params->TryGetStringField(TEXT("assetPath"), AssetPath) && !Params->TryGetStringField(TEXT("path"), AssetPath))
2128
+ {
2129
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath'"));
2130
+ Result->SetBoolField(TEXT("success"), false);
2131
+ return MakeShared<FJsonValueObject>(Result);
2132
+ }
2133
+
2134
+ FString SMName;
2135
+ if (!Params->TryGetStringField(TEXT("stateMachineName"), SMName))
2136
+ {
2137
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'stateMachineName'"));
2138
+ Result->SetBoolField(TEXT("success"), false);
2139
+ return MakeShared<FJsonValueObject>(Result);
2140
+ }
2141
+
2142
+ UAnimBlueprint* AnimBP = LoadAnimBP(AssetPath);
2143
+ if (!AnimBP)
2144
+ {
2145
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("AnimBlueprint not found: %s"), *AssetPath));
2146
+ Result->SetBoolField(TEXT("success"), false);
2147
+ return MakeShared<FJsonValueObject>(Result);
2148
+ }
2149
+
2150
+ UAnimGraphNode_StateMachine* SMNode = FindStateMachineNode(AnimBP, SMName);
2151
+ if (!SMNode)
2152
+ {
2153
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("State machine '%s' not found"), *SMName));
2154
+ Result->SetBoolField(TEXT("success"), false);
2155
+ return MakeShared<FJsonValueObject>(Result);
2156
+ }
2157
+
2158
+ UAnimationStateMachineGraph* SMGraph = Cast<UAnimationStateMachineGraph>(SMNode->EditorStateMachineGraph);
2159
+ if (!SMGraph)
2160
+ {
2161
+ Result->SetStringField(TEXT("error"), TEXT("State machine has no editor graph"));
2162
+ Result->SetBoolField(TEXT("success"), false);
2163
+ return MakeShared<FJsonValueObject>(Result);
2164
+ }
2165
+
2166
+ // Enumerate states
2167
+ TArray<TSharedPtr<FJsonValue>> StatesArray;
2168
+ for (UEdGraphNode* Node : SMGraph->Nodes)
2169
+ {
2170
+ if (UAnimStateNode* State = Cast<UAnimStateNode>(Node))
2171
+ {
2172
+ TSharedPtr<FJsonObject> StateObj = MakeShared<FJsonObject>();
2173
+ StateObj->SetStringField(TEXT("name"), State->GetStateName());
2174
+
2175
+ // Check for animation asset inside the state
2176
+ if (State->BoundGraph)
2177
+ {
2178
+ for (UEdGraphNode* Inner : State->BoundGraph->Nodes)
2179
+ {
2180
+ if (UAnimGraphNode_SequencePlayer* SP = Cast<UAnimGraphNode_SequencePlayer>(Inner))
2181
+ {
2182
+ if (UAnimSequence* Seq = SP->GetSequencePlayerNode()->GetSequence())
2183
+ {
2184
+ StateObj->SetStringField(TEXT("animAsset"), Seq->GetPathName());
2185
+ }
2186
+ }
2187
+ else if (UAnimGraphNode_BlendSpacePlayer* BSP = Cast<UAnimGraphNode_BlendSpacePlayer>(Inner))
2188
+ {
2189
+ if (UBlendSpace* BS = BSP->GetBlendSpacePlayerNode()->GetBlendSpace())
2190
+ {
2191
+ StateObj->SetStringField(TEXT("animAsset"), BS->GetPathName());
2192
+ }
2193
+ }
2194
+ }
2195
+ }
2196
+
2197
+ StatesArray.Add(MakeShared<FJsonValueObject>(StateObj));
2198
+ }
2199
+ }
2200
+ Result->SetArrayField(TEXT("states"), StatesArray);
2201
+
2202
+ // Enumerate transitions
2203
+ TArray<TSharedPtr<FJsonValue>> TransArray;
2204
+ for (UEdGraphNode* Node : SMGraph->Nodes)
2205
+ {
2206
+ if (UAnimStateTransitionNode* T = Cast<UAnimStateTransitionNode>(Node))
2207
+ {
2208
+ TSharedPtr<FJsonObject> TransObj = MakeShared<FJsonObject>();
2209
+
2210
+ UAnimStateNode* Prev = Cast<UAnimStateNode>(T->GetPreviousState());
2211
+ UAnimStateNode* Next = Cast<UAnimStateNode>(T->GetNextState());
2212
+ if (Prev) TransObj->SetStringField(TEXT("fromState"), Prev->GetStateName());
2213
+ if (Next) TransObj->SetStringField(TEXT("toState"), Next->GetStateName());
2214
+
2215
+ TransObj->SetNumberField(TEXT("blendDuration"), T->CrossfadeDuration);
2216
+ TransObj->SetStringField(TEXT("logicType"),
2217
+ T->LogicType == ETransitionLogicType::TLT_Inertialization ? TEXT("Inertialization") : TEXT("Standard"));
2218
+
2219
+ TransArray.Add(MakeShared<FJsonValueObject>(TransObj));
2220
+ }
2221
+ }
2222
+ Result->SetArrayField(TEXT("transitions"), TransArray);
2223
+
2224
+ Result->SetStringField(TEXT("assetPath"), AssetPath);
2225
+ Result->SetStringField(TEXT("stateMachineName"), SMName);
2226
+ Result->SetBoolField(TEXT("success"), true);
2227
+
2228
+ return MakeShared<FJsonValueObject>(Result);
2229
+ }
@@ -41,4 +41,12 @@ private:
41
41
  // Montage editing
42
42
  static TSharedPtr<FJsonValue> SetMontageSequence(const TSharedPtr<FJsonObject>& Params);
43
43
  static TSharedPtr<FJsonValue> SetMontageProperties(const TSharedPtr<FJsonObject>& Params);
44
+
45
+ // State machine authoring
46
+ static TSharedPtr<FJsonValue> CreateStateMachine(const TSharedPtr<FJsonObject>& Params);
47
+ static TSharedPtr<FJsonValue> AddState(const TSharedPtr<FJsonObject>& Params);
48
+ static TSharedPtr<FJsonValue> AddTransition(const TSharedPtr<FJsonObject>& Params);
49
+ static TSharedPtr<FJsonValue> SetStateAnimation(const TSharedPtr<FJsonObject>& Params);
50
+ static TSharedPtr<FJsonValue> SetTransitionBlend(const TSharedPtr<FJsonObject>& Params);
51
+ static TSharedPtr<FJsonValue> ReadStateMachine(const TSharedPtr<FJsonObject>& Params);
44
52
  };
@@ -1854,7 +1854,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::ReimportAsset(const TSharedPtr<FJsonObjec
1854
1854
  UAssetImportData* ImportData = nullptr;
1855
1855
  if (UStaticMesh* SM = Cast<UStaticMesh>(Asset))
1856
1856
  {
1857
- ImportData = SM->AssetImportData;
1857
+ ImportData = SM->GetAssetImportData();
1858
1858
  }
1859
1859
  else if (USkeletalMesh* SKM = Cast<USkeletalMesh>(Asset))
1860
1860
  {
@@ -93,6 +93,7 @@ void FBlueprintHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
93
93
  Registry.RegisterHandler(TEXT("set_node_property"), &SetNodeProperty);
94
94
  Registry.RegisterHandler(TEXT("list_blueprint_graphs"), &ListGraphs);
95
95
  Registry.RegisterHandler(TEXT("set_blueprint_component_property"), &SetComponentProperty);
96
+ Registry.RegisterHandler(TEXT("set_class_default"), &SetClassDefault);
96
97
  }
97
98
 
98
99
  UBlueprint* FBlueprintHandlers::LoadBlueprint(const FString& AssetPath)
@@ -2511,3 +2512,149 @@ TSharedPtr<FJsonValue> FBlueprintHandlers::SetComponentProperty(const TSharedPtr
2511
2512
 
2512
2513
  return MakeShared<FJsonValueObject>(Result);
2513
2514
  }
2515
+
2516
+ // ---------------------------------------------------------------------------
2517
+ // set_class_default — Set a UPROPERTY on a Blueprint's Class Default Object
2518
+ // Params: assetPath, propertyName, value
2519
+ // ---------------------------------------------------------------------------
2520
+ TSharedPtr<FJsonValue> FBlueprintHandlers::SetClassDefault(const TSharedPtr<FJsonObject>& Params)
2521
+ {
2522
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
2523
+
2524
+ FString AssetPath;
2525
+ if (!Params->TryGetStringField(TEXT("path"), AssetPath) && !Params->TryGetStringField(TEXT("assetPath"), AssetPath))
2526
+ {
2527
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'assetPath' parameter"));
2528
+ Result->SetBoolField(TEXT("success"), false);
2529
+ return MakeShared<FJsonValueObject>(Result);
2530
+ }
2531
+
2532
+ FString PropertyName;
2533
+ if (!Params->TryGetStringField(TEXT("propertyName"), PropertyName))
2534
+ {
2535
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'propertyName' parameter"));
2536
+ Result->SetBoolField(TEXT("success"), false);
2537
+ return MakeShared<FJsonValueObject>(Result);
2538
+ }
2539
+
2540
+ FString Value;
2541
+ if (!Params->TryGetStringField(TEXT("value"), Value))
2542
+ {
2543
+ Result->SetStringField(TEXT("error"), TEXT("Missing 'value' parameter"));
2544
+ Result->SetBoolField(TEXT("success"), false);
2545
+ return MakeShared<FJsonValueObject>(Result);
2546
+ }
2547
+
2548
+ UBlueprint* Blueprint = LoadBlueprint(AssetPath);
2549
+ if (!Blueprint)
2550
+ {
2551
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Blueprint not found: %s"), *AssetPath));
2552
+ Result->SetBoolField(TEXT("success"), false);
2553
+ return MakeShared<FJsonValueObject>(Result);
2554
+ }
2555
+
2556
+ UClass* GenClass = Blueprint->GeneratedClass;
2557
+ if (!GenClass)
2558
+ {
2559
+ Result->SetStringField(TEXT("error"), TEXT("Blueprint has no GeneratedClass (needs compilation first?)"));
2560
+ Result->SetBoolField(TEXT("success"), false);
2561
+ return MakeShared<FJsonValueObject>(Result);
2562
+ }
2563
+
2564
+ UObject* CDO = GenClass->GetDefaultObject();
2565
+ if (!CDO)
2566
+ {
2567
+ Result->SetStringField(TEXT("error"), TEXT("Could not get Class Default Object"));
2568
+ Result->SetBoolField(TEXT("success"), false);
2569
+ return MakeShared<FJsonValueObject>(Result);
2570
+ }
2571
+
2572
+ // Navigate dotted property paths (e.g. "EjectConfigs.Cork.Force")
2573
+ TArray<FString> PathParts;
2574
+ PropertyName.ParseIntoArray(PathParts, TEXT("."));
2575
+
2576
+ UStruct* CurrentStruct = GenClass;
2577
+ void* CurrentContainer = CDO;
2578
+ FProperty* FinalProp = nullptr;
2579
+
2580
+ for (int32 i = 0; i < PathParts.Num(); i++)
2581
+ {
2582
+ FProperty* Prop = CurrentStruct->FindPropertyByName(FName(*PathParts[i]));
2583
+ if (!Prop) break;
2584
+
2585
+ if (i < PathParts.Num() - 1)
2586
+ {
2587
+ FStructProperty* StructProp = CastField<FStructProperty>(Prop);
2588
+ if (!StructProp) break;
2589
+ CurrentContainer = StructProp->ContainerPtrToValuePtr<void>(CurrentContainer);
2590
+ CurrentStruct = StructProp->Struct;
2591
+ }
2592
+ else
2593
+ {
2594
+ FinalProp = Prop;
2595
+ }
2596
+ }
2597
+
2598
+ if (!FinalProp)
2599
+ {
2600
+ TArray<FString> PropNames;
2601
+ for (TFieldIterator<FProperty> It(GenClass); It; ++It)
2602
+ {
2603
+ PropNames.Add(It->GetName());
2604
+ }
2605
+ Result->SetStringField(TEXT("error"), FString::Printf(
2606
+ TEXT("Property '%s' not found on %s. Properties: [%s]"),
2607
+ *PropertyName, *GenClass->GetName(),
2608
+ *FString::Join(PropNames, TEXT(", "))));
2609
+ Result->SetBoolField(TEXT("success"), false);
2610
+ return MakeShared<FJsonValueObject>(Result);
2611
+ }
2612
+
2613
+ void* ValuePtr = FinalProp->ContainerPtrToValuePtr<void>(CurrentContainer);
2614
+
2615
+ if (FObjectPropertyBase* ObjProp = CastField<FObjectPropertyBase>(FinalProp))
2616
+ {
2617
+ UObject* LoadedObj = LoadObject<UObject>(nullptr, *Value);
2618
+ if (LoadedObj)
2619
+ {
2620
+ ObjProp->SetObjectPropertyValue(ValuePtr, LoadedObj);
2621
+ }
2622
+ else
2623
+ {
2624
+ Result->SetStringField(TEXT("error"), FString::Printf(
2625
+ TEXT("Could not load object at '%s' for property '%s'"), *Value, *PropertyName));
2626
+ Result->SetBoolField(TEXT("success"), false);
2627
+ return MakeShared<FJsonValueObject>(Result);
2628
+ }
2629
+ }
2630
+ else if (FSoftObjectProperty* SoftProp = CastField<FSoftObjectProperty>(FinalProp))
2631
+ {
2632
+ FSoftObjectPath SoftPath(Value);
2633
+ SoftProp->SetPropertyValue(ValuePtr, FSoftObjectPtr(SoftPath));
2634
+ }
2635
+ else
2636
+ {
2637
+ // Generic: ImportText handles FName, int, float, bool, FVector, TArray, TMap, etc.
2638
+ FinalProp->ImportText_Direct(*Value, ValuePtr, CDO, PPF_None);
2639
+ }
2640
+
2641
+ CDO->PostEditChange();
2642
+
2643
+ // Save
2644
+ UPackage* Package = Blueprint->GetOutermost();
2645
+ if (Package)
2646
+ {
2647
+ Package->MarkPackageDirty();
2648
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
2649
+ FSavePackageArgs SaveArgs;
2650
+ SaveArgs.TopLevelFlags = RF_Standalone;
2651
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
2652
+ }
2653
+
2654
+ Result->SetStringField(TEXT("path"), AssetPath);
2655
+ Result->SetStringField(TEXT("propertyName"), PropertyName);
2656
+ Result->SetStringField(TEXT("value"), Value);
2657
+ Result->SetBoolField(TEXT("success"), true);
2658
+
2659
+ return MakeShared<FJsonValueObject>(Result);
2660
+ }
@@ -37,6 +37,7 @@ private:
37
37
  static TSharedPtr<FJsonValue> SetNodeProperty(const TSharedPtr<FJsonObject>& Params);
38
38
  static TSharedPtr<FJsonValue> ListGraphs(const TSharedPtr<FJsonObject>& Params);
39
39
  static TSharedPtr<FJsonValue> SetComponentProperty(const TSharedPtr<FJsonObject>& Params);
40
+ static TSharedPtr<FJsonValue> SetClassDefault(const TSharedPtr<FJsonObject>& Params);
40
41
 
41
42
  // Helper functions
42
43
  static class UBlueprint* LoadBlueprint(const FString& AssetPath);
@@ -32,6 +32,7 @@ public class UE_MCP_Bridge : ModuleRules
32
32
  new string[]
33
33
  {
34
34
  "AIModule",
35
+ "AnimGraph",
35
36
  "AnimationEditor",
36
37
  "AssetRegistry",
37
38
  "AssetTools",