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.
- package/dist/tools/animation.js +23 -1
- package/dist/tools/animation.js.map +1 -1
- package/dist/tools/blueprint.js +2 -0
- package/dist/tools/blueprint.js.map +1 -1
- package/package.json +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +661 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +8 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +147 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +1 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +1 -0
package/dist/tools/animation.js
CHANGED
|
@@ -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":"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,sFAAsF,EACtF;IACE,mBAAmB,EAAG,EAAE,CAAC,qBAAqB,CAAC;IAC/C,YAAY,EAAU,EAAE,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAClF,aAAa,EAAS,EAAE,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IACnF,eAAe,EAAO,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;IAChF,IAAI,EAAkB,EAAE,CAAC,kBAAkB,CAAC;IAC5C,cAAc,EAAQ,EAAE,CAAC,qBAAqB,CAAC;IAC/C,qBAAqB,EAAE,EAAE,CAAC,uBAAuB,CAAC;IAClD,iBAAiB,EAAK,EAAE,CAAC,mBAAmB,CAAC;IAC7C,UAAU,EAAY,EAAE,CAAC,iBAAiB,CAAC;IAC3C,iBAAiB,EAAK,EAAE,CAAC,mBAAmB,CAAC;IAC7C,YAAY,EAAU,EAAE,CAAC,cAAc,CAAC;IACxC,oBAAoB,EAAE,EAAE,CAAC,sBAAsB,CAAC;IAChD,iBAAiB,EAAK,EAAE,CAAC,wBAAwB,CAAC;IAClD,eAAe,EAAO,EAAE,CAAC,iBAAiB,CAAC;IAC3C,kBAAkB,EAAI,EAAE,CAAC,oBAAoB,CAAC;IAC9C,mBAAmB,EAAG,EAAE,CAAC,qBAAqB,CAAC;IAC/C,oBAAoB,EAAE,EAAE,CAAC,sBAAsB,CAAC;IAChD,sBAAsB,EAAE,EAAE,CAAC,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"animation.js","sourceRoot":"","sources":["../../src/tools/animation.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/blueprint.js
CHANGED
|
@@ -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":"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"}
|
package/package.json
CHANGED
|
@@ -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->
|
|
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);
|