ue-mcp 1.2.3 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/action-class.js +56 -3
- package/dist/action-class.js.map +1 -1
- package/dist/bridge-timeouts.d.ts +64 -0
- package/dist/bridge-timeouts.js +118 -0
- package/dist/bridge-timeouts.js.map +1 -0
- package/dist/bridge.js +10 -2
- package/dist/bridge.js.map +1 -1
- package/dist/editor-control.d.ts +72 -5
- package/dist/editor-control.js +164 -140
- package/dist/editor-control.js.map +1 -1
- package/dist/editor-target.d.ts +55 -1
- package/dist/editor-target.js +107 -10
- package/dist/editor-target.js.map +1 -1
- package/dist/engine-observer.d.ts +59 -5
- package/dist/engine-observer.js +249 -29
- package/dist/engine-observer.js.map +1 -1
- package/dist/engine-root.d.ts +91 -0
- package/dist/engine-root.js +448 -0
- package/dist/engine-root.js.map +1 -0
- package/dist/epic-enrich.js +16 -1
- package/dist/epic-enrich.js.map +1 -1
- package/dist/feedback-cli.js +4 -0
- package/dist/feedback-cli.js.map +1 -1
- package/dist/feedback-deferred.d.ts +9 -0
- package/dist/feedback-deferred.js +2 -0
- package/dist/feedback-deferred.js.map +1 -1
- package/dist/feedback-fallback.d.ts +99 -0
- package/dist/feedback-fallback.js +173 -0
- package/dist/feedback-fallback.js.map +1 -0
- package/dist/flow/write-methods.js +20 -0
- package/dist/flow/write-methods.js.map +1 -1
- package/dist/index.js +41 -2
- package/dist/index.js.map +1 -1
- package/dist/lean-context.js +8 -3
- package/dist/lean-context.js.map +1 -1
- package/dist/locking.js +11 -2
- package/dist/locking.js.map +1 -1
- package/dist/plugin/loader.d.ts +4 -0
- package/dist/plugin/loader.js +22 -8
- package/dist/plugin/loader.js.map +1 -1
- package/dist/plugin/manifest.d.ts +72 -52
- package/dist/plugin/manifest.js +118 -21
- package/dist/plugin/manifest.js.map +1 -1
- package/dist/plugin-cli.js +16 -3
- package/dist/plugin-cli.js.map +1 -1
- package/dist/project.d.ts +11 -0
- package/dist/project.js +23 -2
- package/dist/project.js.map +1 -1
- package/dist/python-gate.d.ts +95 -0
- package/dist/python-gate.js +175 -0
- package/dist/python-gate.js.map +1 -0
- package/dist/tool-counts.json +16 -16
- package/dist/tools/animation.js +288 -24
- package/dist/tools/animation.js.map +1 -1
- package/dist/tools/asset.js +79 -14
- package/dist/tools/asset.js.map +1 -1
- package/dist/tools/audio.js +59 -5
- package/dist/tools/audio.js.map +1 -1
- package/dist/tools/blueprint.js +29 -12
- package/dist/tools/blueprint.js.map +1 -1
- package/dist/tools/chooser.js +4 -1
- package/dist/tools/chooser.js.map +1 -1
- package/dist/tools/editor.js +81 -43
- package/dist/tools/editor.js.map +1 -1
- package/dist/tools/feedback.js +214 -48
- package/dist/tools/feedback.js.map +1 -1
- package/dist/tools/foliage.js +27 -1
- package/dist/tools/foliage.js.map +1 -1
- package/dist/tools/gameplay.js +38 -11
- package/dist/tools/gameplay.js.map +1 -1
- package/dist/tools/gas.js +17 -5
- package/dist/tools/gas.js.map +1 -1
- package/dist/tools/landscape.js +22 -7
- package/dist/tools/landscape.js.map +1 -1
- package/dist/tools/level.js +322 -51
- package/dist/tools/level.js.map +1 -1
- package/dist/tools/material.js +10 -4
- package/dist/tools/material.js.map +1 -1
- package/dist/tools/niagara.js +3 -2
- package/dist/tools/niagara.js.map +1 -1
- package/dist/tools/pcg.js +6 -5
- package/dist/tools/pcg.js.map +1 -1
- package/dist/tools/plugins.js +2 -0
- package/dist/tools/plugins.js.map +1 -1
- package/dist/tools/project.js +47 -20
- package/dist/tools/project.js.map +1 -1
- package/dist/types.d.ts +24 -0
- package/dist/types.js +46 -3
- package/dist/types.js.map +1 -1
- package/dist/ue-mcp.default.yml +493 -125
- package/package.json +2 -2
- package/plugin/ue_mcp_bridge/NATIVE_RUNTIME_VISIBILITY.md +53 -0
- package/plugin/ue_mcp_bridge/NATIVE_STATIC_MESH_USAGE_PROGRESS.md +115 -0
- package/plugin/ue_mcp_bridge/README_MassHandlers.md +97 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +14 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +21 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +395 -69
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +79 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +25 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRigSequencer.cpp +3061 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRetargeterAuthoring.cpp +961 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRigAuthoring.cpp +900 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Pose.cpp +769 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +44 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_SkeletalLive.cpp +217 -11
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +551 -24
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Validation.cpp +735 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +352 -73
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +8 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkProperties.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.cpp +503 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.h +21 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkUpsert.cpp +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Enum.cpp +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.cpp +902 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.h +33 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +478 -134
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +5 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.cpp +933 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.h +35 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp +478 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +4 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp +319 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +482 -35
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +10 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.cpp +502 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.h +43 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +89 -7
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +17 -51
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +107 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +10 -10
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Search.cpp +648 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +5 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.cpp +252 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.h +10 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +252 -41
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +4 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +250 -27
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +303 -125
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +73 -50
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_RuntimeVisibility.cpp +757 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +11 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +3 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Batch.cpp +419 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +39 -161
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +66 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTAuthoring.cpp +1323 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BehaviorTree.cpp +1211 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +2 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +60 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Runtime.cpp +363 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/HandlerEditorState.h +84 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +1288 -36
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +3 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +41 -16
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +959 -213
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +66 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_BatchWrite.cpp +1571 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Convert.cpp +316 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Inspection.cpp +280 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection.cpp +666 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection_Internal.h +63 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +43 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +13 -47
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_PostProcess.cpp +527 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Query.cpp +1169 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Refresh.cpp +723 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Save.cpp +325 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Spatial.cpp +360 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Trace.cpp +178 -58
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Transient.cpp +337 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Volumes.cpp +25 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +10 -9
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartitionSettings.cpp +686 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.cpp +467 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.h +22 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +452 -175
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +5 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Build.cpp +597 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +17 -15
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +38 -168
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +39 -30
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +392 -78
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +2 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers_Internal.h +83 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.cpp +200 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.h +15 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +19 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.cpp +31 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +307 -69
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +84 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +8 -41
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +33 -52
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/ActorSelectorTests.cpp +344 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationControlRigTimelineTests.cpp +60 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationPoseTests.cpp +115 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetBulkReadTests.cpp +177 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetDeleteGuardTests.cpp +276 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPathResolutionTests.cpp +243 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPropertyPersistTests.cpp +213 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetSubobjectTests.cpp +235 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AutomationRunnerTests.cpp +72 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeAuthoringTests.cpp +526 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeNodeTests.cpp +334 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BlueprintHandlerSurfaceTests.cpp +362 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BridgeProtocolTests.cpp +14 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/CollisionQueryTests.cpp +288 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/DataTableRowWriteTests.cpp +453 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/EditorFunctionCallTests.cpp +223 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/FoliageBatchTests.cpp +147 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GameThreadGateTests.cpp +82 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GasLiveAttributeTests.cpp +183 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LandscapeSampleTests.cpp +119 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelBatchWriteTests.cpp +176 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelComponentTreeInstanceCountTests.cpp +189 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelConvertBrushesTests.cpp +100 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelInstanceProjectionTests.cpp +265 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelPostProcessOverrideTests.cpp +258 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelQueryComponentsTests.cpp +195 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelRefreshTests.cpp +142 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelSaveReportTests.cpp +125 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelScriptHandlersTests.cpp +42 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelStaticMeshUsageTests.cpp +412 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTraceWorldScopeTests.cpp +133 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTransientActorTests.cpp +205 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelWorldPartitionSettingsTests.cpp +168 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTestTypes.h +51 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTests.cpp +379 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MaterialBuildTests.cpp +238 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshBooleanTests.cpp +170 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshGeometryTests.cpp +116 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageSaveExtensionTests.cpp +161 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageWriteGuardTests.cpp +253 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/RuntimeVisibilityTests.cpp +143 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerHandlerTests.cpp +660 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerScrubTests.cpp +50 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SkeletonDiffTests.cpp +685 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/WidgetBlueprintResolveTests.cpp +145 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +80 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerFunctionCall.h +509 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerQuery.h +407 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +1008 -77
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/MCPEngineStatus.cpp +152 -14
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/Tests/MCPEngineStatusTests.cpp +65 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Public/MCPEngineStatus.h +32 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/UE_MCP_BridgeStatus.Build.cs +2 -0
- package/skills/ue-mcp-animation/SKILL.md +154 -0
- package/skills/ue-mcp-blueprint/SKILL.md +71 -0
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.h
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "CoreMinimal.h"
|
|
4
|
+
#include "Dom/JsonValue.h"
|
|
5
|
+
#include "Dom/JsonObject.h"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* StaticMesh boolean CSG: union, subtract, intersect (#916).
|
|
9
|
+
*
|
|
10
|
+
* A StaticMesh repair needed subtract/union/intersect and no native action
|
|
11
|
+
* exposed one, so the only route was execute_python introspecting the
|
|
12
|
+
* unreal.GeometryScript_* modules at runtime, converting to a DynamicMesh,
|
|
13
|
+
* running the boolean, validating the result and writing it back by hand. That
|
|
14
|
+
* is a lot of moving parts to get right in a script, and every step of it is
|
|
15
|
+
* something the bridge should own.
|
|
16
|
+
*
|
|
17
|
+
* A separate class and translation unit rather than another FAssetHandlers
|
|
18
|
+
* partition: AssetHandlers.cpp is already 3700 lines and this registers itself.
|
|
19
|
+
* The action still reads as asset(mesh_boolean) on the wire.
|
|
20
|
+
*
|
|
21
|
+
* GeometryScripting is an engine PLUGIN, so its classes are reached through
|
|
22
|
+
* reflection at runtime rather than linked in Build.cs, the way the Water
|
|
23
|
+
* handlers reach their optional modules. A project with the plugin disabled
|
|
24
|
+
* gets a clear "GeometryScripting plugin not available" answer naming what to
|
|
25
|
+
* enable, instead of the module failing to link for everyone.
|
|
26
|
+
*/
|
|
27
|
+
class FAssetMeshBooleanHandlers
|
|
28
|
+
{
|
|
29
|
+
public:
|
|
30
|
+
static void RegisterHandlers(class FMCPHandlerRegistry& Registry);
|
|
31
|
+
|
|
32
|
+
private:
|
|
33
|
+
/** Boolean two StaticMeshes into a third (or, opted into, back into one). */
|
|
34
|
+
static TSharedPtr<FJsonValue> MeshBoolean(const TSharedPtr<FJsonObject>& Params);
|
|
35
|
+
};
|
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp
ADDED
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
// asset(fixup_redirectors) (#908).
|
|
2
|
+
//
|
|
3
|
+
// bulk_rename moved 29 referenced assets and left 19 ObjectRedirector packages
|
|
4
|
+
// at the old paths, still pointed at by unloaded maps and assets. Nothing
|
|
5
|
+
// native could load and resave exactly those referencers, re-query the
|
|
6
|
+
// registry and delete only the redirectors that came out clean: UE 5.8's
|
|
7
|
+
// Python AssetTools does not expose fixup_referencers, and the blunt
|
|
8
|
+
// instrument, ResavePackages -FixupRedirects -ProjectOnly, started rewriting
|
|
9
|
+
// unrelated old packages.
|
|
10
|
+
//
|
|
11
|
+
// The shape of this action follows from that. It preflights the exact
|
|
12
|
+
// redirectors, their destinations and their hard and soft referencers, reports
|
|
13
|
+
// the exact packages it would touch, rewrites only those, re-queries the
|
|
14
|
+
// registry, and deletes a redirector only when nothing references it any more.
|
|
15
|
+
// A whole content root is refused unless the caller asks for it by name, so
|
|
16
|
+
// "fix these 19" cannot turn into "resave the project" by accident.
|
|
17
|
+
|
|
18
|
+
#include "AssetHandlers.h"
|
|
19
|
+
#include "HandlerRegistry.h"
|
|
20
|
+
#include "HandlerUtils.h"
|
|
21
|
+
|
|
22
|
+
#include "AssetRegistry/ARFilter.h"
|
|
23
|
+
#include "AssetRegistry/AssetRegistryModule.h"
|
|
24
|
+
#include "AssetRegistry/IAssetRegistry.h"
|
|
25
|
+
#include "AssetToolsModule.h"
|
|
26
|
+
#include "Dom/JsonObject.h"
|
|
27
|
+
#include "Dom/JsonValue.h"
|
|
28
|
+
#include "FileHelpers.h"
|
|
29
|
+
#include "IAssetTools.h"
|
|
30
|
+
#include "Misc/PackageName.h"
|
|
31
|
+
#include "Misc/Paths.h"
|
|
32
|
+
#include "ObjectTools.h"
|
|
33
|
+
#include "UObject/ObjectRedirector.h"
|
|
34
|
+
#include "UObject/Package.h"
|
|
35
|
+
#include "UObject/TopLevelAssetPath.h"
|
|
36
|
+
#include "UObject/UObjectGlobals.h"
|
|
37
|
+
|
|
38
|
+
namespace
|
|
39
|
+
{
|
|
40
|
+
const FTopLevelAssetPath MCPRedirectorClassPath(TEXT("/Script/CoreUObject"), TEXT("ObjectRedirector"));
|
|
41
|
+
|
|
42
|
+
/** One redirector and everything the preflight learned about it. */
|
|
43
|
+
struct FMCPRedirectorPlan
|
|
44
|
+
{
|
|
45
|
+
FString PackageName;
|
|
46
|
+
FString ObjectPath;
|
|
47
|
+
FString DestinationPath;
|
|
48
|
+
TArray<FString> HardReferencers;
|
|
49
|
+
TArray<FString> SoftReferencers;
|
|
50
|
+
FString PreflightError;
|
|
51
|
+
|
|
52
|
+
TArray<FString> AllReferencers() const
|
|
53
|
+
{
|
|
54
|
+
TArray<FString> All = HardReferencers;
|
|
55
|
+
for (const FString& Soft : SoftReferencers) All.AddUnique(Soft);
|
|
56
|
+
return All;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** The content roots. Naming one of these as a path is a project-wide
|
|
61
|
+
* operation, which this action refuses without an explicit opt-in. */
|
|
62
|
+
bool MCPIsWholeContentRoot(const FString& Path)
|
|
63
|
+
{
|
|
64
|
+
FString Trimmed = Path;
|
|
65
|
+
Trimmed.TrimStartAndEndInline();
|
|
66
|
+
while (Trimmed.EndsWith(TEXT("/")) && Trimmed.Len() > 1)
|
|
67
|
+
{
|
|
68
|
+
Trimmed.LeftChopInline(1);
|
|
69
|
+
}
|
|
70
|
+
if (Trimmed.IsEmpty() || Trimmed == TEXT("/")) return true;
|
|
71
|
+
// "/Game" and "/MyPlugin" have exactly one slash: they name a mount
|
|
72
|
+
// point rather than a folder inside one.
|
|
73
|
+
int32 SlashCount = 0;
|
|
74
|
+
for (TCHAR Char : Trimmed)
|
|
75
|
+
{
|
|
76
|
+
if (Char == TEXT('/')) ++SlashCount;
|
|
77
|
+
}
|
|
78
|
+
return SlashCount <= 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
TArray<TSharedPtr<FJsonValue>> MCPRedirectorStringsToJson(const TArray<FString>& Values)
|
|
82
|
+
{
|
|
83
|
+
TArray<TSharedPtr<FJsonValue>> Out;
|
|
84
|
+
Out.Reserve(Values.Num());
|
|
85
|
+
for (const FString& Value : Values) Out.Add(MakeShared<FJsonValueString>(Value));
|
|
86
|
+
return Out;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Package referencers of one package, split by whether the reference is
|
|
90
|
+
* hard. A soft referencer is the case the manual workaround kept missing:
|
|
91
|
+
* it does not force the package to load, so it never got rewritten. */
|
|
92
|
+
void MCPGatherReferencers(
|
|
93
|
+
IAssetRegistry& Registry,
|
|
94
|
+
const FName PackageName,
|
|
95
|
+
TArray<FString>& OutHard,
|
|
96
|
+
TArray<FString>& OutSoft)
|
|
97
|
+
{
|
|
98
|
+
TArray<FName> Hard;
|
|
99
|
+
Registry.GetReferencers(PackageName, Hard,
|
|
100
|
+
UE::AssetRegistry::EDependencyCategory::Package,
|
|
101
|
+
UE::AssetRegistry::EDependencyQuery::Hard);
|
|
102
|
+
TArray<FName> Soft;
|
|
103
|
+
Registry.GetReferencers(PackageName, Soft,
|
|
104
|
+
UE::AssetRegistry::EDependencyCategory::Package,
|
|
105
|
+
UE::AssetRegistry::EDependencyQuery::Soft);
|
|
106
|
+
|
|
107
|
+
for (const FName& Referencer : Hard)
|
|
108
|
+
{
|
|
109
|
+
if (Referencer != PackageName) OutHard.AddUnique(Referencer.ToString());
|
|
110
|
+
}
|
|
111
|
+
for (const FName& Referencer : Soft)
|
|
112
|
+
{
|
|
113
|
+
if (Referencer != PackageName) OutSoft.AddUnique(Referencer.ToString());
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
TSharedPtr<FJsonValue> FAssetHandlers::FixupRedirectors(const TSharedPtr<FJsonObject>& Params)
|
|
119
|
+
{
|
|
120
|
+
MCP_CHECK_GAME_THREAD();
|
|
121
|
+
|
|
122
|
+
const TArray<TSharedPtr<FJsonValue>>* PathsField = nullptr;
|
|
123
|
+
if (!Params->TryGetArrayField(TEXT("paths"), PathsField) || !PathsField)
|
|
124
|
+
{
|
|
125
|
+
return MCPError(TEXT("Missing 'paths' array: the redirector packages, or the folders holding them, to fix up."));
|
|
126
|
+
}
|
|
127
|
+
const TArray<FString> RequestedPaths = JsonArrayToStringList(PathsField);
|
|
128
|
+
if (RequestedPaths.Num() == 0)
|
|
129
|
+
{
|
|
130
|
+
return MCPError(TEXT("'paths' is empty. Name the redirector packages, or the folders holding them."));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const bool bDryRun = OptionalBool(Params, TEXT("dryRun"), false);
|
|
134
|
+
const bool bSave = OptionalBool(Params, TEXT("save"), true);
|
|
135
|
+
const bool bAllowProjectWide = OptionalBool(Params, TEXT("allowProjectWide"), false);
|
|
136
|
+
|
|
137
|
+
FAssetRegistryModule& RegistryModule =
|
|
138
|
+
FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
139
|
+
IAssetRegistry& Registry = RegistryModule.Get();
|
|
140
|
+
|
|
141
|
+
// ── Resolve the requested paths to an exact set of redirectors ──────────
|
|
142
|
+
TArray<FAssetData> Redirectors;
|
|
143
|
+
TArray<TSharedPtr<FJsonValue>> UnresolvedPaths;
|
|
144
|
+
for (const FString& RequestedPath : RequestedPaths)
|
|
145
|
+
{
|
|
146
|
+
if (MCPIsWholeContentRoot(RequestedPath) && !bAllowProjectWide)
|
|
147
|
+
{
|
|
148
|
+
return MCPError(FString::Printf(
|
|
149
|
+
TEXT("'%s' names a whole content root, which would resave the project. ")
|
|
150
|
+
TEXT("Name the redirector packages or the folders holding them, or pass allowProjectWide=true to mean it."),
|
|
151
|
+
*RequestedPath));
|
|
152
|
+
}
|
|
153
|
+
if (MCPIsProtectedAssetPath(RequestedPath))
|
|
154
|
+
{
|
|
155
|
+
return MCPError(FString::Printf(
|
|
156
|
+
TEXT("'%s' is on a protected mount (/Engine/, /Script/, /Memory/, /Temp/), which the bridge never rewrites or deletes."),
|
|
157
|
+
*RequestedPath));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const FMCPAssetPathForms Forms = MCPAssetPathForms(RequestedPath);
|
|
161
|
+
|
|
162
|
+
// A folder: every redirector under it, recursively.
|
|
163
|
+
FARFilter FolderFilter;
|
|
164
|
+
FolderFilter.PackagePaths.Add(FName(*Forms.PackagePath));
|
|
165
|
+
FolderFilter.bRecursivePaths = true;
|
|
166
|
+
FolderFilter.ClassPaths.Add(MCPRedirectorClassPath);
|
|
167
|
+
TArray<FAssetData> InFolder;
|
|
168
|
+
Registry.GetAssets(FolderFilter, InFolder);
|
|
169
|
+
|
|
170
|
+
// A package: the redirector living in it.
|
|
171
|
+
TArray<FAssetData> InPackage;
|
|
172
|
+
Registry.GetAssetsByPackageName(FName(*Forms.PackagePath), InPackage);
|
|
173
|
+
|
|
174
|
+
int32 FoundHere = 0;
|
|
175
|
+
for (const FAssetData& Candidate : InFolder)
|
|
176
|
+
{
|
|
177
|
+
if (!Candidate.IsRedirector()) continue;
|
|
178
|
+
Redirectors.AddUnique(Candidate);
|
|
179
|
+
++FoundHere;
|
|
180
|
+
}
|
|
181
|
+
for (const FAssetData& Candidate : InPackage)
|
|
182
|
+
{
|
|
183
|
+
if (!Candidate.IsRedirector()) continue;
|
|
184
|
+
Redirectors.AddUnique(Candidate);
|
|
185
|
+
++FoundHere;
|
|
186
|
+
}
|
|
187
|
+
if (FoundHere == 0)
|
|
188
|
+
{
|
|
189
|
+
// Not an error: a path with nothing to fix is the state this action
|
|
190
|
+
// is trying to reach. Reported so a typo is still visible.
|
|
191
|
+
TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
|
|
192
|
+
Entry->SetStringField(TEXT("path"), RequestedPath);
|
|
193
|
+
Entry->SetStringField(TEXT("reason"), TEXT("no_redirector_found"));
|
|
194
|
+
UnresolvedPaths.Add(MakeShared<FJsonValueObject>(Entry));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ── Preflight: destinations, referencers, and the packages to be written ─
|
|
199
|
+
TArray<FMCPRedirectorPlan> Plans;
|
|
200
|
+
TArray<UObjectRedirector*> RedirectorObjects;
|
|
201
|
+
TArray<FString> PackagesToLoad;
|
|
202
|
+
for (const FAssetData& Data : Redirectors)
|
|
203
|
+
{
|
|
204
|
+
FMCPRedirectorPlan Plan;
|
|
205
|
+
Plan.PackageName = Data.PackageName.ToString();
|
|
206
|
+
Plan.ObjectPath = Data.GetSoftObjectPath().ToString();
|
|
207
|
+
|
|
208
|
+
if (MCPIsProtectedAssetPath(Plan.PackageName))
|
|
209
|
+
{
|
|
210
|
+
Plan.PreflightError = TEXT("on a protected mount");
|
|
211
|
+
Plans.Add(MoveTemp(Plan));
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
UObjectRedirector* Redirector = Cast<UObjectRedirector>(MCPLoadAssetObject(Plan.ObjectPath));
|
|
216
|
+
if (!Redirector)
|
|
217
|
+
{
|
|
218
|
+
Plan.PreflightError = TEXT("the registry lists a redirector here but it would not load");
|
|
219
|
+
Plans.Add(MoveTemp(Plan));
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
Plan.DestinationPath = Redirector->DestinationObject
|
|
223
|
+
? Redirector->DestinationObject->GetPathName()
|
|
224
|
+
: FString();
|
|
225
|
+
if (Plan.DestinationPath.IsEmpty())
|
|
226
|
+
{
|
|
227
|
+
// A redirector with no destination cannot be followed, so rewriting
|
|
228
|
+
// its referencers would drop the reference rather than repoint it.
|
|
229
|
+
Plan.PreflightError = TEXT("the redirector has no destination object, so its referencers cannot be repointed");
|
|
230
|
+
Plans.Add(MoveTemp(Plan));
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
MCPGatherReferencers(Registry, Data.PackageName, Plan.HardReferencers, Plan.SoftReferencers);
|
|
235
|
+
for (const FString& Referencer : Plan.AllReferencers())
|
|
236
|
+
{
|
|
237
|
+
PackagesToLoad.AddUnique(Referencer);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
RedirectorObjects.Add(Redirector);
|
|
241
|
+
Plans.Add(MoveTemp(Plan));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// A referencer that is itself one of the redirectors being fixed is not a
|
|
245
|
+
// package to rewrite; it is one to delete.
|
|
246
|
+
for (const FMCPRedirectorPlan& Plan : Plans)
|
|
247
|
+
{
|
|
248
|
+
PackagesToLoad.Remove(Plan.PackageName);
|
|
249
|
+
}
|
|
250
|
+
PackagesToLoad.Sort();
|
|
251
|
+
|
|
252
|
+
TArray<TSharedPtr<FJsonValue>> PlanJson;
|
|
253
|
+
for (const FMCPRedirectorPlan& Plan : Plans)
|
|
254
|
+
{
|
|
255
|
+
TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
|
|
256
|
+
Entry->SetStringField(TEXT("packageName"), Plan.PackageName);
|
|
257
|
+
Entry->SetStringField(TEXT("objectPath"), Plan.ObjectPath);
|
|
258
|
+
Entry->SetStringField(TEXT("destinationPath"), Plan.DestinationPath);
|
|
259
|
+
Entry->SetArrayField(TEXT("hardReferencers"), MCPRedirectorStringsToJson(Plan.HardReferencers));
|
|
260
|
+
Entry->SetArrayField(TEXT("softReferencers"), MCPRedirectorStringsToJson(Plan.SoftReferencers));
|
|
261
|
+
Entry->SetNumberField(TEXT("referencerCount"), Plan.AllReferencers().Num());
|
|
262
|
+
if (!Plan.PreflightError.IsEmpty())
|
|
263
|
+
{
|
|
264
|
+
Entry->SetStringField(TEXT("status"), TEXT("skipped"));
|
|
265
|
+
Entry->SetStringField(TEXT("error"), Plan.PreflightError);
|
|
266
|
+
}
|
|
267
|
+
PlanJson.Add(MakeShared<FJsonValueObject>(Entry));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
auto Result = MCPSuccess();
|
|
271
|
+
Result->SetBoolField(TEXT("dryRun"), bDryRun);
|
|
272
|
+
Result->SetBoolField(TEXT("allowProjectWide"), bAllowProjectWide);
|
|
273
|
+
Result->SetNumberField(TEXT("redirectorCount"), Plans.Num());
|
|
274
|
+
Result->SetArrayField(TEXT("redirectors"), PlanJson);
|
|
275
|
+
Result->SetArrayField(TEXT("packagesToLoad"), MCPRedirectorStringsToJson(PackagesToLoad));
|
|
276
|
+
Result->SetArrayField(TEXT("packagesToSave"), MCPRedirectorStringsToJson(PackagesToLoad));
|
|
277
|
+
if (UnresolvedPaths.Num() > 0)
|
|
278
|
+
{
|
|
279
|
+
Result->SetArrayField(TEXT("unresolvedPaths"), UnresolvedPaths);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (bDryRun || RedirectorObjects.Num() == 0)
|
|
283
|
+
{
|
|
284
|
+
Result->SetNumberField(TEXT("rewrittenPackageCount"), 0);
|
|
285
|
+
Result->SetNumberField(TEXT("deletedRedirectorCount"), 0);
|
|
286
|
+
if (RedirectorObjects.Num() == 0 && !bDryRun)
|
|
287
|
+
{
|
|
288
|
+
Result->SetStringField(TEXT("note"),
|
|
289
|
+
TEXT("No redirector needed fixing at the paths given, so nothing was loaded, saved or deleted."));
|
|
290
|
+
}
|
|
291
|
+
return MCPResult(Result);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// ── Rewrite exactly those packages ─────────────────────────────────────
|
|
295
|
+
// The referencers are loaded first because a soft reference in an unloaded
|
|
296
|
+
// package is invisible to the rewriter, which is how 19 stubs survived the
|
|
297
|
+
// original rename.
|
|
298
|
+
TArray<UPackage*> LoadedReferencers;
|
|
299
|
+
TArray<TSharedPtr<FJsonValue>> PackageStatuses;
|
|
300
|
+
for (const FString& PackageName : PackagesToLoad)
|
|
301
|
+
{
|
|
302
|
+
TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
|
|
303
|
+
Entry->SetStringField(TEXT("packageName"), PackageName);
|
|
304
|
+
|
|
305
|
+
UPackage* Package = FindPackage(nullptr, *PackageName);
|
|
306
|
+
if (!Package)
|
|
307
|
+
{
|
|
308
|
+
Package = LoadPackage(nullptr, *PackageName, LOAD_None);
|
|
309
|
+
Entry->SetBoolField(TEXT("loadedByThisCall"), Package != nullptr);
|
|
310
|
+
}
|
|
311
|
+
else
|
|
312
|
+
{
|
|
313
|
+
Entry->SetBoolField(TEXT("loadedByThisCall"), false);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (!Package)
|
|
317
|
+
{
|
|
318
|
+
Entry->SetStringField(TEXT("status"), TEXT("load_failed"));
|
|
319
|
+
PackageStatuses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
LoadedReferencers.Add(Package);
|
|
323
|
+
Entry->SetStringField(TEXT("status"), TEXT("loaded"));
|
|
324
|
+
PackageStatuses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools")).Get();
|
|
328
|
+
// LeaveFixedUpRedirectors on purpose: the deletion below happens after the
|
|
329
|
+
// registry has been re-queried, so a redirector something still points at
|
|
330
|
+
// is never removed.
|
|
331
|
+
AssetTools.FixupReferencers(
|
|
332
|
+
RedirectorObjects,
|
|
333
|
+
/*bCheckoutDialogPrompt=*/false,
|
|
334
|
+
ERedirectFixupMode::LeaveFixedUpRedirectors);
|
|
335
|
+
|
|
336
|
+
const bool bFixupStillRunning = AssetTools.IsFixupReferencersInProgress();
|
|
337
|
+
Result->SetBoolField(TEXT("fixupInProgress"), bFixupStillRunning);
|
|
338
|
+
|
|
339
|
+
// ── Save exactly those packages ────────────────────────────────────────
|
|
340
|
+
// save=false skips this explicit pass only. The editor's own fix-up writes
|
|
341
|
+
// what it can on its own, so this is not a way to preview the change:
|
|
342
|
+
// dryRun is, and it returns before anything is loaded.
|
|
343
|
+
int32 SavedCount = 0;
|
|
344
|
+
if (!bSave)
|
|
345
|
+
{
|
|
346
|
+
Result->SetStringField(TEXT("saveNote"),
|
|
347
|
+
TEXT("save=false skipped the explicit save pass. The editor's referencer fix-up writes what it can regardless, ")
|
|
348
|
+
TEXT("so use dryRun=true to preview instead. Redirectors are still only deleted when the registry says nothing references them."));
|
|
349
|
+
}
|
|
350
|
+
if (bSave && !bFixupStillRunning)
|
|
351
|
+
{
|
|
352
|
+
TArray<UPackage*> ToSave;
|
|
353
|
+
for (UPackage* Package : LoadedReferencers)
|
|
354
|
+
{
|
|
355
|
+
if (Package && Package->IsDirty()) ToSave.Add(Package);
|
|
356
|
+
}
|
|
357
|
+
if (ToSave.Num() > 0)
|
|
358
|
+
{
|
|
359
|
+
UEditorLoadingAndSavingUtils::SavePackages(ToSave, /*bOnlyDirty=*/true);
|
|
360
|
+
}
|
|
361
|
+
TArray<FString> ModifiedFiles;
|
|
362
|
+
for (const TSharedPtr<FJsonValue>& Value : PackageStatuses)
|
|
363
|
+
{
|
|
364
|
+
const TSharedPtr<FJsonObject> Entry = Value->AsObject();
|
|
365
|
+
if (!Entry.IsValid()) continue;
|
|
366
|
+
FString PackageName;
|
|
367
|
+
Entry->TryGetStringField(TEXT("packageName"), PackageName);
|
|
368
|
+
UPackage* Package = FindPackage(nullptr, *PackageName);
|
|
369
|
+
if (!Package) continue;
|
|
370
|
+
const bool bStillDirty = Package->IsDirty();
|
|
371
|
+
Entry->SetBoolField(TEXT("stillDirty"), bStillDirty);
|
|
372
|
+
Entry->SetStringField(TEXT("status"), bStillDirty ? TEXT("save_failed") : TEXT("saved"));
|
|
373
|
+
if (!bStillDirty)
|
|
374
|
+
{
|
|
375
|
+
++SavedCount;
|
|
376
|
+
FString FileName;
|
|
377
|
+
if (FPackageName::DoesPackageExist(PackageName, &FileName))
|
|
378
|
+
{
|
|
379
|
+
ModifiedFiles.Add(FileName);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// Re-query: the registry's referencer graph is what decides which
|
|
384
|
+
// redirectors are safe to delete, and it is stale until the rewritten
|
|
385
|
+
// packages have been rescanned.
|
|
386
|
+
if (ModifiedFiles.Num() > 0)
|
|
387
|
+
{
|
|
388
|
+
Registry.ScanModifiedAssetFiles(ModifiedFiles);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
Result->SetNumberField(TEXT("rewrittenPackageCount"), SavedCount);
|
|
392
|
+
Result->SetArrayField(TEXT("packages"), PackageStatuses);
|
|
393
|
+
|
|
394
|
+
// ── Delete only the redirectors nothing points at any more ─────────────
|
|
395
|
+
TArray<UObject*> ToDelete;
|
|
396
|
+
TArray<TSharedPtr<FJsonValue>> RedirectorStatuses;
|
|
397
|
+
for (const FMCPRedirectorPlan& Plan : Plans)
|
|
398
|
+
{
|
|
399
|
+
TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
|
|
400
|
+
Entry->SetStringField(TEXT("packageName"), Plan.PackageName);
|
|
401
|
+
Entry->SetStringField(TEXT("objectPath"), Plan.ObjectPath);
|
|
402
|
+
Entry->SetStringField(TEXT("destinationPath"), Plan.DestinationPath);
|
|
403
|
+
Entry->SetArrayField(TEXT("hardReferencers"), MCPRedirectorStringsToJson(Plan.HardReferencers));
|
|
404
|
+
Entry->SetArrayField(TEXT("softReferencers"), MCPRedirectorStringsToJson(Plan.SoftReferencers));
|
|
405
|
+
|
|
406
|
+
if (!Plan.PreflightError.IsEmpty())
|
|
407
|
+
{
|
|
408
|
+
Entry->SetStringField(TEXT("status"), TEXT("skipped"));
|
|
409
|
+
Entry->SetStringField(TEXT("error"), Plan.PreflightError);
|
|
410
|
+
RedirectorStatuses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
TArray<FString> RemainingHard;
|
|
415
|
+
TArray<FString> RemainingSoft;
|
|
416
|
+
MCPGatherReferencers(Registry, FName(*Plan.PackageName), RemainingHard, RemainingSoft);
|
|
417
|
+
const int32 Remaining = RemainingHard.Num() + RemainingSoft.Num();
|
|
418
|
+
Entry->SetNumberField(TEXT("referencersBefore"), Plan.AllReferencers().Num());
|
|
419
|
+
Entry->SetNumberField(TEXT("referencersAfter"), Remaining);
|
|
420
|
+
Entry->SetArrayField(TEXT("remainingHardReferencers"), MCPRedirectorStringsToJson(RemainingHard));
|
|
421
|
+
Entry->SetArrayField(TEXT("remainingSoftReferencers"), MCPRedirectorStringsToJson(RemainingSoft));
|
|
422
|
+
|
|
423
|
+
if (Remaining > 0 || bFixupStillRunning)
|
|
424
|
+
{
|
|
425
|
+
Entry->SetStringField(TEXT("status"), TEXT("kept"));
|
|
426
|
+
Entry->SetStringField(TEXT("reason"), bFixupStillRunning
|
|
427
|
+
? TEXT("the editor's referencer fix-up is still running, so nothing was deleted this call")
|
|
428
|
+
: TEXT("something still references it; rerun once those packages are saved"));
|
|
429
|
+
RedirectorStatuses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (UObject* Redirector = MCPLoadAssetObject(Plan.ObjectPath))
|
|
434
|
+
{
|
|
435
|
+
ToDelete.Add(Redirector);
|
|
436
|
+
Entry->SetStringField(TEXT("status"), TEXT("deleting"));
|
|
437
|
+
}
|
|
438
|
+
else
|
|
439
|
+
{
|
|
440
|
+
// Already gone, which is the state this action is trying to reach.
|
|
441
|
+
Entry->SetStringField(TEXT("status"), TEXT("deleted"));
|
|
442
|
+
}
|
|
443
|
+
RedirectorStatuses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
int32 DeletedCount = 0;
|
|
447
|
+
if (ToDelete.Num() > 0)
|
|
448
|
+
{
|
|
449
|
+
DeletedCount = ObjectTools::DeleteObjects(
|
|
450
|
+
ToDelete, /*bShowConfirmation=*/false, ObjectTools::EAllowCancelDuringDelete::CancelNotAllowed);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// The deletion is reported from what is on disk afterwards, not from the
|
|
454
|
+
// return count, because a package the editor declined to remove is exactly
|
|
455
|
+
// the case that must not read as cleaned up.
|
|
456
|
+
int32 ConfirmedDeleted = 0;
|
|
457
|
+
for (const TSharedPtr<FJsonValue>& Value : RedirectorStatuses)
|
|
458
|
+
{
|
|
459
|
+
const TSharedPtr<FJsonObject> Entry = Value->AsObject();
|
|
460
|
+
if (!Entry.IsValid()) continue;
|
|
461
|
+
FString Status;
|
|
462
|
+
Entry->TryGetStringField(TEXT("status"), Status);
|
|
463
|
+
if (Status != TEXT("deleting") && Status != TEXT("deleted")) continue;
|
|
464
|
+
|
|
465
|
+
FString PackageName;
|
|
466
|
+
Entry->TryGetStringField(TEXT("packageName"), PackageName);
|
|
467
|
+
const bool bStillOnDisk = FPackageName::DoesPackageExist(PackageName);
|
|
468
|
+
Entry->SetStringField(TEXT("status"), bStillOnDisk ? TEXT("delete_failed") : TEXT("deleted"));
|
|
469
|
+
if (!bStillOnDisk) ++ConfirmedDeleted;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
Result->SetNumberField(TEXT("deleteAttemptedCount"), ToDelete.Num());
|
|
473
|
+
Result->SetNumberField(TEXT("deleteReportedCount"), DeletedCount);
|
|
474
|
+
Result->SetNumberField(TEXT("deletedRedirectorCount"), ConfirmedDeleted);
|
|
475
|
+
Result->SetArrayField(TEXT("redirectors"), RedirectorStatuses);
|
|
476
|
+
MCPSetUpdated(Result);
|
|
477
|
+
return MCPResult(Result);
|
|
478
|
+
}
|
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp
CHANGED
|
@@ -199,7 +199,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::CreateRenderTarget2D(const TSharedPtr<FJs
|
|
|
199
199
|
// Probe first so the idempotent hit can report the settings of the asset
|
|
200
200
|
// that is already on disk instead of the lean "existed" record.
|
|
201
201
|
const FString ObjectPath = PackageName + TEXT(".") + Name;
|
|
202
|
-
if (UObject* ExistingObject =
|
|
202
|
+
if (UObject* ExistingObject = MCPLoadAssetObject(ObjectPath))
|
|
203
203
|
{
|
|
204
204
|
if (OnConflict == TEXT("error"))
|
|
205
205
|
{
|
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp
CHANGED
|
@@ -49,7 +49,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::AddSocket(const TSharedPtr<FJsonObject>&
|
|
|
49
49
|
RelScale.Z = (*ScaleObj)->GetNumberField(TEXT("z"));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
UObject* Asset =
|
|
52
|
+
UObject* Asset = MCPLoadAssetObject(AssetPath);
|
|
53
53
|
if (!Asset)
|
|
54
54
|
{
|
|
55
55
|
return MCPError(FString::Printf(TEXT("Could not load asset '%s'"), *AssetPath));
|
|
@@ -306,7 +306,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::RemoveSocket(const TSharedPtr<FJsonObject
|
|
|
306
306
|
FString SocketName;
|
|
307
307
|
if (auto Err = RequireString(Params, TEXT("socketName"), SocketName)) return Err;
|
|
308
308
|
|
|
309
|
-
UObject* Asset =
|
|
309
|
+
UObject* Asset = MCPLoadAssetObject(AssetPath);
|
|
310
310
|
if (!Asset)
|
|
311
311
|
{
|
|
312
312
|
return MCPError(FString::Printf(TEXT("Could not load asset '%s'"), *AssetPath));
|
|
@@ -405,7 +405,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::ListSockets(const TSharedPtr<FJsonObject>
|
|
|
405
405
|
FString AssetPath;
|
|
406
406
|
if (auto Err = RequireString(Params, TEXT("assetPath"), AssetPath)) return Err;
|
|
407
407
|
|
|
408
|
-
UObject* Asset =
|
|
408
|
+
UObject* Asset = MCPLoadAssetObject(AssetPath);
|
|
409
409
|
if (!Asset)
|
|
410
410
|
{
|
|
411
411
|
return MCPError(FString::Printf(TEXT("Could not load asset '%s'"), *AssetPath));
|
|
@@ -545,7 +545,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::SetSocketTransform(const TSharedPtr<FJson
|
|
|
545
545
|
FString SocketName;
|
|
546
546
|
if (auto Err = RequireString(Params, TEXT("socketName"), SocketName)) return Err;
|
|
547
547
|
|
|
548
|
-
UObject* Asset =
|
|
548
|
+
UObject* Asset = MCPLoadAssetObject(AssetPath);
|
|
549
549
|
if (!Asset)
|
|
550
550
|
{
|
|
551
551
|
return MCPError(FString::Printf(TEXT("Could not load asset '%s'"), *AssetPath));
|
|
@@ -168,7 +168,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::ListStructFields(const TSharedPtr<FJsonOb
|
|
|
168
168
|
FString AssetPath;
|
|
169
169
|
if (auto Err = RequireStringAlt(Params, TEXT("assetPath"), TEXT("path"), AssetPath)) return Err;
|
|
170
170
|
|
|
171
|
-
UUserDefinedStruct* Struct =
|
|
171
|
+
UUserDefinedStruct* Struct = LoadAssetByPath<UUserDefinedStruct>(AssetPath);
|
|
172
172
|
if (!Struct) return MCPError(FString::Printf(TEXT("UserDefinedStruct not found (native structs are not editable): %s"), *AssetPath));
|
|
173
173
|
|
|
174
174
|
TSharedPtr<FJsonObject> Res = MCPSuccess();
|
|
@@ -193,7 +193,7 @@ TSharedPtr<FJsonValue> FAssetHandlers::EditUserDefinedStruct(const TSharedPtr<FJ
|
|
|
193
193
|
FString Op;
|
|
194
194
|
if (auto Err = RequireString(Params, TEXT("op"), Op)) return Err;
|
|
195
195
|
|
|
196
|
-
UUserDefinedStruct* Struct =
|
|
196
|
+
UUserDefinedStruct* Struct = LoadAssetByPath<UUserDefinedStruct>(AssetPath);
|
|
197
197
|
if (!Struct) return MCPError(FString::Printf(TEXT("UserDefinedStruct not found (native structs are not editable): %s"), *AssetPath));
|
|
198
198
|
|
|
199
199
|
TSharedPtr<FJsonObject> Res = MCPSuccess();
|