ue-mcp 0.4.28 → 0.4.30

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.
@@ -27,8 +27,8 @@ export const materialTool = categoryTool("material", "Materials: create, read, p
27
27
  - set_blend_mode: Set blend mode. Params: assetPath, blendMode (Opaque|Masked|Translucent|Additive|Modulate|AlphaComposite|AlphaHoldout)
28
28
  - set_base_color: Set base color. Params: assetPath, color {r,g,b,a?}
29
29
  - connect_texture: Connect texture to property. Params: materialPath, texturePath, property
30
- - add_expression: Add expression node. Params: materialPath, expressionType, x?, y?, properties?
31
- - connect_expressions: Wire two expressions. Params: materialPath, sourceExpression, sourceOutput?, targetExpression, targetInput?
30
+ - add_expression: Add expression node. Returns nodeId (use as sourceExpression/targetExpression). Params: materialPath, expressionType, name?, parameterName?, positionX?, positionY?
31
+ - connect_expressions: Wire two expressions. Use nodeId from add_expression, or expression name/index/class. Params: materialPath, sourceExpression, sourceOutput?, targetExpression, targetInput?
32
32
  - connect_to_property: Wire expression to material output. Params: materialPath, expressionName, outputName?, property (BaseColor|Normal|Roughness|Metallic|Emissive|...)
33
33
  - list_expressions: List expression nodes. Params: materialPath
34
34
  - delete_expression: Remove expression. Params: materialPath, expressionName
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ue-mcp",
3
- "version": "0.4.28",
3
+ "version": "0.4.30",
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",
@@ -35,9 +35,9 @@
35
35
  #include "AnimStateTransitionNode.h"
36
36
  #include "AnimStateEntryNode.h"
37
37
  #include "AnimationStateMachineGraph.h"
38
+ #include "AnimGraphNode_AssetPlayerBase.h"
38
39
  #include "AnimGraphNode_SequencePlayer.h"
39
40
  #include "AnimGraphNode_BlendSpacePlayer.h"
40
- #include "AnimGraphNode_Inertialization.h"
41
41
  #include "Kismet2/BlueprintEditorUtils.h"
42
42
  #include "Kismet2/KismetEditorUtilities.h"
43
43
 
@@ -1697,14 +1697,19 @@ TSharedPtr<FJsonValue> FAnimationHandlers::CreateStateMachine(const TSharedPtr<F
1697
1697
 
1698
1698
  // Create the state machine container node in the AnimGraph
1699
1699
  UAnimGraphNode_StateMachine* SMNode = NewObject<UAnimGraphNode_StateMachine>(TargetGraph);
1700
- SMNode->GetStateMachineNode()->SetStateMachineName(FName(*Name));
1701
1700
  TargetGraph->AddNode(SMNode, false, false);
1702
1701
  SMNode->CreateNewGuid();
1703
- SMNode->PostPlacedNewNode();
1702
+ SMNode->PostPlacedNewNode(); // This creates the EditorStateMachineGraph sub-graph
1704
1703
  SMNode->AllocateDefaultPins();
1705
1704
  SMNode->NodePosX = 200;
1706
1705
  SMNode->NodePosY = 0;
1707
1706
 
1707
+ // Rename the state machine graph to the desired name
1708
+ if (SMNode->EditorStateMachineGraph)
1709
+ {
1710
+ SMNode->EditorStateMachineGraph->Rename(*Name);
1711
+ }
1712
+
1708
1713
  CompileAndSave(AnimBP);
1709
1714
 
1710
1715
  Result->SetStringField(TEXT("assetPath"), AssetPath);
@@ -1992,7 +1997,7 @@ TSharedPtr<FJsonValue> FAnimationHandlers::SetStateAnimation(const TSharedPtr<FJ
1992
1997
  SeqPlayer->PostPlacedNewNode();
1993
1998
  SeqPlayer->AllocateDefaultPins();
1994
1999
  }
1995
- SeqPlayer->GetSequencePlayerNode()->SetSequence(Seq);
2000
+ SeqPlayer->SetAnimationAsset(Seq);
1996
2001
  }
1997
2002
  else if (UBlendSpace* BS = Cast<UBlendSpace>(AnimAsset))
1998
2003
  {
@@ -2004,7 +2009,7 @@ TSharedPtr<FJsonValue> FAnimationHandlers::SetStateAnimation(const TSharedPtr<FJ
2004
2009
  BSPlayer->PostPlacedNewNode();
2005
2010
  BSPlayer->AllocateDefaultPins();
2006
2011
  }
2007
- BSPlayer->GetBlendSpacePlayerNode()->SetBlendSpace(BS);
2012
+ BSPlayer->SetAnimationAsset(BS);
2008
2013
  }
2009
2014
  else
2010
2015
  {
@@ -2177,18 +2182,11 @@ TSharedPtr<FJsonValue> FAnimationHandlers::ReadStateMachine(const TSharedPtr<FJs
2177
2182
  {
2178
2183
  for (UEdGraphNode* Inner : State->BoundGraph->Nodes)
2179
2184
  {
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))
2185
+ if (UAnimGraphNode_AssetPlayerBase* AssetNode = Cast<UAnimGraphNode_AssetPlayerBase>(Inner))
2188
2186
  {
2189
- if (UBlendSpace* BS = BSP->GetBlendSpacePlayerNode()->GetBlendSpace())
2187
+ if (UAnimationAsset* Asset = AssetNode->GetAnimationAsset())
2190
2188
  {
2191
- StateObj->SetStringField(TEXT("animAsset"), BS->GetPathName());
2189
+ StateObj->SetStringField(TEXT("animAsset"), Asset->GetPathName());
2192
2190
  }
2193
2191
  }
2194
2192
  }
@@ -615,11 +615,67 @@ TSharedPtr<FJsonValue> FMaterialHandlers::AddMaterialExpression(const TSharedPtr
615
615
  UMaterialExpression* NewExpression = NewObject<UMaterialExpression>(Material, ExpressionClass);
616
616
  Material->GetExpressionCollection().AddExpression(NewExpression);
617
617
 
618
+ // Apply optional properties
619
+ FString ExpressionName;
620
+ if (Params->TryGetStringField(TEXT("name"), ExpressionName) || Params->TryGetStringField(TEXT("expressionName"), ExpressionName))
621
+ {
622
+ NewExpression->Desc = ExpressionName;
623
+ }
624
+
625
+ // Set parameter name for parameter expressions
626
+ FString ParameterName;
627
+ if (Params->TryGetStringField(TEXT("parameterName"), ParameterName))
628
+ {
629
+ if (UMaterialExpressionScalarParameter* ScalarParam = Cast<UMaterialExpressionScalarParameter>(NewExpression))
630
+ {
631
+ ScalarParam->ParameterName = FName(*ParameterName);
632
+ }
633
+ else if (UMaterialExpressionVectorParameter* VectorParam = Cast<UMaterialExpressionVectorParameter>(NewExpression))
634
+ {
635
+ VectorParam->ParameterName = FName(*ParameterName);
636
+ }
637
+ else if (UMaterialExpressionTextureObjectParameter* TexParam = Cast<UMaterialExpressionTextureObjectParameter>(NewExpression))
638
+ {
639
+ TexParam->ParameterName = FName(*ParameterName);
640
+ }
641
+ // If name not set via Desc, use parameterName as the description too
642
+ if (NewExpression->Desc.IsEmpty())
643
+ {
644
+ NewExpression->Desc = ParameterName;
645
+ }
646
+ }
647
+
648
+ // Set position
649
+ double PosX = 0, PosY = 0;
650
+ if (Params->TryGetNumberField(TEXT("positionX"), PosX))
651
+ {
652
+ NewExpression->MaterialExpressionEditorX = static_cast<int32>(PosX);
653
+ }
654
+ if (Params->TryGetNumberField(TEXT("positionY"), PosY))
655
+ {
656
+ NewExpression->MaterialExpressionEditorY = static_cast<int32>(PosY);
657
+ }
658
+
618
659
  Material->PostEditChange();
619
- Material->MarkPackageDirty();
660
+
661
+ // Save the package so subsequent list/connect calls see the expression
662
+ UPackage* Package = Material->GetOutermost();
663
+ if (Package)
664
+ {
665
+ Package->MarkPackageDirty();
666
+ FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension());
667
+ FSavePackageArgs SaveArgs;
668
+ SaveArgs.TopLevelFlags = RF_Standalone;
669
+ UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs);
670
+ }
671
+
672
+ // Return the index as nodeId for use with connect_expressions and other operations
673
+ int32 NodeIndex = Material->GetExpressions().Num() - 1;
620
674
 
621
675
  Result->SetStringField(TEXT("expressionType"), ExpressionType);
622
676
  Result->SetStringField(TEXT("expressionClass"), NewExpression->GetClass()->GetName());
677
+ Result->SetStringField(TEXT("nodeId"), FString::FromInt(NodeIndex));
678
+ Result->SetStringField(TEXT("description"), NewExpression->GetDescription());
623
679
  Result->SetStringField(TEXT("materialPath"), Material->GetPathName());
624
680
  Result->SetNumberField(TEXT("expressionCount"), Material->GetExpressions().Num());
625
681
  Result->SetBoolField(TEXT("success"), true);
@@ -648,16 +704,30 @@ TSharedPtr<FJsonValue> FMaterialHandlers::ListMaterialExpressions(const TSharedP
648
704
  }
649
705
 
650
706
  TArray<TSharedPtr<FJsonValue>> ExpressionsArray;
651
- for (UMaterialExpression* Expression : Material->GetExpressions())
707
+ auto Expressions = Material->GetExpressions();
708
+ for (int32 i = 0; i < Expressions.Num(); i++)
652
709
  {
710
+ UMaterialExpression* Expression = Expressions[i];
653
711
  if (!Expression) continue;
654
712
 
655
713
  TSharedPtr<FJsonObject> ExprObj = MakeShared<FJsonObject>();
714
+ ExprObj->SetStringField(TEXT("nodeId"), FString::FromInt(i));
656
715
  ExprObj->SetStringField(TEXT("class"), Expression->GetClass()->GetName());
657
716
  ExprObj->SetStringField(TEXT("description"), Expression->GetDescription());
717
+ ExprObj->SetStringField(TEXT("name"), Expression->Desc);
658
718
  ExprObj->SetNumberField(TEXT("positionX"), Expression->MaterialExpressionEditorX);
659
719
  ExprObj->SetNumberField(TEXT("positionY"), Expression->MaterialExpressionEditorY);
660
720
 
721
+ // Include parameter name if applicable
722
+ if (UMaterialExpressionScalarParameter* SP = Cast<UMaterialExpressionScalarParameter>(Expression))
723
+ {
724
+ ExprObj->SetStringField(TEXT("parameterName"), SP->ParameterName.ToString());
725
+ }
726
+ else if (UMaterialExpressionVectorParameter* VP = Cast<UMaterialExpressionVectorParameter>(Expression))
727
+ {
728
+ ExprObj->SetStringField(TEXT("parameterName"), VP->ParameterName.ToString());
729
+ }
730
+
661
731
  ExpressionsArray.Add(MakeShared<FJsonValueObject>(ExprObj));
662
732
  }
663
733