ue-mcp 1.0.44 → 1.0.46

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.
@@ -26,6 +26,6 @@
26
26
  "statetree": 35,
27
27
  "plugins": 2
28
28
  },
29
- "generatedAt": "2026-05-25T23:35:01.093Z",
30
- "version": "1.0.44"
29
+ "generatedAt": "2026-05-26T01:49:35.373Z",
30
+ "version": "1.0.46"
31
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ue-mcp",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "Unreal Engine MCP server - 21 tools, 556+ actions for AI-driven editor control",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,6 +22,9 @@
22
22
  #include "GameFramework/Pawn.h"
23
23
  #include "GameFramework/SpectatorPawn.h"
24
24
  #include "Engine/DebugCameraController.h"
25
+ #include "Engine/GameViewportClient.h"
26
+ #include "ImageUtils.h"
27
+ #include "Async/Async.h"
25
28
 
26
29
  namespace UEMCPPIE
27
30
  {
@@ -288,6 +291,7 @@ namespace UEMCPPIE
288
291
  ReplayActorCache.Reset();
289
292
  ActorDriftAccum.Reset();
290
293
  FramesCaptured = 0;
294
+ CaptureFrameCounter = 0;
291
295
  CaptureDir.Reset();
292
296
  NextStepIndex = 0;
293
297
  ExecutedSteps = 0;
@@ -594,13 +598,44 @@ namespace UEMCPPIE
594
598
  }
595
599
  IFileManager::Get().MakeDirectory(*CaptureDir, true);
596
600
  }
597
- const uint64 FrameIdx = static_cast<uint64>(FramesCompared);
601
+ const uint64 FrameIdx = static_cast<uint64>(CaptureFrameCounter);
598
602
  if ((FrameIdx % static_cast<uint64>(Pending.CaptureFrameEvery)) == 0)
599
603
  {
600
- const FString FullPath = CaptureDir / FString::Printf(TEXT("frame_%05llu.png"), FrameIdx);
601
- FScreenshotRequest::RequestScreenshot(FullPath, /*bShowUI*/false, /*bAddFilenameSuffix*/false);
602
- FramesCaptured++;
604
+ FViewport* Viewport = nullptr;
605
+ if (GEngine && GEngine->GameViewport)
606
+ {
607
+ Viewport = GEngine->GameViewport->Viewport;
608
+ }
609
+ if (Viewport && Viewport->GetSizeXY().X > 0)
610
+ {
611
+ const int32 W = Viewport->GetSizeXY().X;
612
+ const int32 H = Viewport->GetSizeXY().Y;
613
+ TArray<FColor> Pixels;
614
+ if (Viewport->ReadPixels(Pixels) && Pixels.Num() == W * H)
615
+ {
616
+ const FString FullPath = CaptureDir / FString::Printf(TEXT("frame_%05llu.png"), FrameIdx);
617
+ AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask,
618
+ [Pixels = MoveTemp(Pixels), W, H, FullPath]()
619
+ {
620
+ TArray64<uint8> PNG;
621
+ FImageUtils::PNGCompressImageArray(W, H, Pixels, PNG);
622
+ FFileHelper::SaveArrayToFile(PNG, *FullPath);
623
+ });
624
+ FramesCaptured++;
625
+ }
626
+ else
627
+ {
628
+ UE_LOG(LogMCPBridge, Warning, TEXT("[PIE-REP] ReadPixels failed: %dx%d pixels=%d"),
629
+ W, H, Pixels.Num());
630
+ }
631
+ }
632
+ else
633
+ {
634
+ UE_LOG(LogMCPBridge, Warning, TEXT("[PIE-REP] No viewport for capture (GEngine->GameViewport=%p Viewport=%p)"),
635
+ GEngine ? GEngine->GameViewport : nullptr, Viewport);
636
+ }
603
637
  }
638
+ CaptureFrameCounter++;
604
639
  }
605
640
 
606
641
  // Drift sampling: sample current pawn state + compare to source by
@@ -160,6 +160,7 @@ namespace UEMCPPIE
160
160
  TMap<FString, TWeakObjectPtr<AActor>> ReplayActorCache;
161
161
  TMap<FString, FActorDrift> ActorDriftAccum;
162
162
  int32 FramesCaptured = 0;
163
+ uint64 CaptureFrameCounter = 0;
163
164
  FString CaptureDir;
164
165
 
165
166
  // Eject state: controller unpossesses pawn on replay start.