ue-mcp 1.2.4 → 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/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/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/project.js +47 -20
- package/dist/tools/project.js.map +1 -1
- package/dist/types.d.ts +21 -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
|
@@ -26,6 +26,10 @@ void FFoliageHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
|
|
|
26
26
|
Registry.RegisterHandler(TEXT("get_foliage_type_settings"), &GetFoliageSettings);
|
|
27
27
|
Registry.RegisterHandler(TEXT("set_foliage_type_settings"), &SetFoliageTypeSettings);
|
|
28
28
|
Registry.RegisterHandler(TEXT("create_foliage_type"), &CreateFoliageType);
|
|
29
|
+
// #988: predicate-driven batch. Scanning and saving hundreds of FoliageType
|
|
30
|
+
// assets outlives the default handler timeout.
|
|
31
|
+
Registry.RegisterHandlerWithTimeout(
|
|
32
|
+
TEXT("batch_set_foliage_settings_where"), &BatchSetFoliageSettingsWhere, 300.0f);
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
TSharedPtr<FJsonValue> FFoliageHandlers::ListFoliageTypes(const TSharedPtr<FJsonObject>& Params)
|
|
@@ -150,7 +154,12 @@ TSharedPtr<FJsonValue> FFoliageHandlers::SampleFoliage(const TSharedPtr<FJsonObj
|
|
|
150
154
|
TSharedPtr<FJsonValue> FFoliageHandlers::GetFoliageSettings(const TSharedPtr<FJsonObject>& Params)
|
|
151
155
|
{
|
|
152
156
|
FString FoliageTypePath;
|
|
153
|
-
if (
|
|
157
|
+
if (!Params->TryGetStringField(TEXT("foliageTypePath"), FoliageTypePath) || FoliageTypePath.IsEmpty())
|
|
158
|
+
{
|
|
159
|
+
// #988: a caller who reaches this error usually wants the whole set,
|
|
160
|
+
// not one asset, so the error names the action that answers that.
|
|
161
|
+
return MCPError(TEXT("Missing required parameter 'foliageTypePath'. To read or filter many types at once use foliage(list_types) or asset(bulk_read_properties); to WRITE settings to every type matching a predicate use foliage(batch_set_settings_where)."));
|
|
162
|
+
}
|
|
154
163
|
|
|
155
164
|
UFoliageType* FoliageType = LoadObject<UFoliageType>(nullptr, *FoliageTypePath);
|
|
156
165
|
if (!FoliageType)
|
|
@@ -227,7 +236,7 @@ TSharedPtr<FJsonValue> FFoliageHandlers::SetFoliageTypeSettings(const TSharedPtr
|
|
|
227
236
|
}
|
|
228
237
|
if (FoliageTypePath.IsEmpty())
|
|
229
238
|
{
|
|
230
|
-
return MCPError(TEXT("Missing 'foliageTypePath' or 'foliageTypeName' parameter"));
|
|
239
|
+
return MCPError(TEXT("Missing 'foliageTypePath' or 'foliageTypeName' parameter. To write the same settings to every type matching a predicate on an existing value, use foliage(batch_set_settings_where) instead of calling this once per asset (#988)."));
|
|
231
240
|
}
|
|
232
241
|
|
|
233
242
|
const TSharedPtr<FJsonObject>* SettingsObj = nullptr;
|
|
@@ -15,4 +15,7 @@ private:
|
|
|
15
15
|
static TSharedPtr<FJsonValue> GetFoliageSettings(const TSharedPtr<FJsonObject>& Params);
|
|
16
16
|
static TSharedPtr<FJsonValue> SetFoliageTypeSettings(const TSharedPtr<FJsonObject>& Params);
|
|
17
17
|
static TSharedPtr<FJsonValue> CreateFoliageType(const TSharedPtr<FJsonObject>& Params);
|
|
18
|
+
// #988: write settings to every FoliageType matching a predicate on an
|
|
19
|
+
// EXISTING property value. Lives in FoliageHandlers_Batch.cpp.
|
|
20
|
+
static TSharedPtr<FJsonValue> BatchSetFoliageSettingsWhere(const TSharedPtr<FJsonObject>& Params);
|
|
18
21
|
};
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
// foliage(batch_set_settings_where) (#988).
|
|
2
|
+
//
|
|
3
|
+
// The reporter needed include_in_hlod=false on every FoliageType whose cull
|
|
4
|
+
// distance was set, which was 36 of 201. foliage(set_settings) is one asset per
|
|
5
|
+
// call, and there was no way to express the predicate at all, so the match had
|
|
6
|
+
// to be computed client-side from 201 separate reads and then written back with
|
|
7
|
+
// 36 more calls.
|
|
8
|
+
//
|
|
9
|
+
// The predicate runs here, over the CURRENT value of a property on each
|
|
10
|
+
// candidate, using the same operator vocabulary as level(query_components) and
|
|
11
|
+
// asset(bulk_read_properties). Translation-unit partition of FFoliageHandlers;
|
|
12
|
+
// registration stays in FoliageHandlers.cpp.
|
|
13
|
+
|
|
14
|
+
#include "FoliageHandlers.h"
|
|
15
|
+
|
|
16
|
+
#include "AssetRegistry/AssetRegistryModule.h"
|
|
17
|
+
#include "AssetRegistry/IAssetRegistry.h"
|
|
18
|
+
#include "Dom/JsonObject.h"
|
|
19
|
+
#include "Dom/JsonValue.h"
|
|
20
|
+
#include "Editor.h"
|
|
21
|
+
#include "Engine/World.h"
|
|
22
|
+
#include "EngineUtils.h"
|
|
23
|
+
#include "FoliageType.h"
|
|
24
|
+
#include "HandlerJsonProperty.h"
|
|
25
|
+
#include "HandlerQuery.h"
|
|
26
|
+
#include "HandlerRegistry.h"
|
|
27
|
+
#include "HandlerUtils.h"
|
|
28
|
+
#include "InstancedFoliageActor.h"
|
|
29
|
+
#include "UObject/Package.h"
|
|
30
|
+
|
|
31
|
+
namespace
|
|
32
|
+
{
|
|
33
|
+
constexpr int32 MCPFoliageBatchMaxTypes = 2000;
|
|
34
|
+
constexpr int32 MCPFoliageBatchMaxPredicates = 16;
|
|
35
|
+
constexpr int32 MCPFoliageBatchMaxSettings = 32;
|
|
36
|
+
constexpr int32 MCPFoliageBatchMaxResultRows = 500;
|
|
37
|
+
|
|
38
|
+
/** One candidate, with everything needed to report it whether or not it
|
|
39
|
+
* ends up matching. */
|
|
40
|
+
struct FMCPFoliageBatchCandidate
|
|
41
|
+
{
|
|
42
|
+
UFoliageType* Type = nullptr;
|
|
43
|
+
FString Path;
|
|
44
|
+
FString Name;
|
|
45
|
+
FString Source;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
void MCPFoliageBatchAddCandidate(
|
|
49
|
+
TArray<FMCPFoliageBatchCandidate>& Candidates,
|
|
50
|
+
TSet<FString>& Seen,
|
|
51
|
+
UFoliageType* Type,
|
|
52
|
+
const TCHAR* Source)
|
|
53
|
+
{
|
|
54
|
+
if (!Type)
|
|
55
|
+
{
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const FString Path = Type->GetPathName();
|
|
59
|
+
if (Seen.Contains(Path))
|
|
60
|
+
{
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
Seen.Add(Path);
|
|
64
|
+
FMCPFoliageBatchCandidate Candidate;
|
|
65
|
+
Candidate.Type = Type;
|
|
66
|
+
Candidate.Path = Path;
|
|
67
|
+
Candidate.Name = Type->GetName();
|
|
68
|
+
Candidate.Source = Source;
|
|
69
|
+
Candidates.Add(MoveTemp(Candidate));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
TSharedPtr<FJsonValue> FFoliageHandlers::BatchSetFoliageSettingsWhere(const TSharedPtr<FJsonObject>& Params)
|
|
74
|
+
{
|
|
75
|
+
MCP_CHECK_GAME_THREAD();
|
|
76
|
+
|
|
77
|
+
// ── What to write ───────────────────────────────────────────────────────
|
|
78
|
+
const TSharedPtr<FJsonObject>* SettingsObject = nullptr;
|
|
79
|
+
if (!Params->TryGetObjectField(TEXT("settings"), SettingsObject) ||
|
|
80
|
+
!SettingsObject || !(*SettingsObject).IsValid() || (*SettingsObject)->Values.Num() == 0)
|
|
81
|
+
{
|
|
82
|
+
return MCPError(TEXT("Missing 'settings' (an object of propertyName -> value; dotted paths such as 'CullDistance.Max' are supported)"));
|
|
83
|
+
}
|
|
84
|
+
if ((*SettingsObject)->Values.Num() > MCPFoliageBatchMaxSettings)
|
|
85
|
+
{
|
|
86
|
+
return MCPError(FString::Printf(
|
|
87
|
+
TEXT("'settings' exceeds the maximum of %d entries"), MCPFoliageBatchMaxSettings));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── The predicate, which is the point of the action ─────────────────────
|
|
91
|
+
TArray<MCPQuery::FPredicate> Predicates;
|
|
92
|
+
{
|
|
93
|
+
const TArray<TSharedPtr<FJsonValue>>* WhereValues = nullptr;
|
|
94
|
+
Params->TryGetArrayField(TEXT("where"), WhereValues);
|
|
95
|
+
FString ParseError;
|
|
96
|
+
if (!MCPQuery::ParsePredicates(WhereValues, MCPFoliageBatchMaxPredicates, Predicates, ParseError))
|
|
97
|
+
{
|
|
98
|
+
return MCPError(ParseError);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (Predicates.IsEmpty())
|
|
102
|
+
{
|
|
103
|
+
// Without a predicate this is "write these settings to every foliage
|
|
104
|
+
// type in the project", which is not what anybody means by a
|
|
105
|
+
// conditional batch and is not worth guessing at.
|
|
106
|
+
return MCPError(TEXT("Missing 'where' ([{field, op, value}] over the current property values, e.g. [{field:'props.CullDistance.Max', op:'gt', value:0}]). Use foliage(set_settings) for a single known asset."));
|
|
107
|
+
}
|
|
108
|
+
const FString WhereMode = OptionalString(Params, TEXT("whereMode"), TEXT("all")).ToLower();
|
|
109
|
+
if (WhereMode != TEXT("all") && WhereMode != TEXT("any"))
|
|
110
|
+
{
|
|
111
|
+
return MCPError(TEXT("'whereMode' must be either 'all' or 'any'"));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Properties the predicate reads. Derived from the predicate fields so a
|
|
115
|
+
// caller does not have to list them twice, plus anything explicitly asked
|
|
116
|
+
// for so the report can show context it does not filter on.
|
|
117
|
+
TArray<FString> ReadPaths;
|
|
118
|
+
for (MCPQuery::FPredicate& Predicate : Predicates)
|
|
119
|
+
{
|
|
120
|
+
if (Predicate.Field.StartsWith(TEXT("props.")))
|
|
121
|
+
{
|
|
122
|
+
ReadPaths.AddUnique(Predicate.Field.RightChop(6));
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
// A bare field name is read as a property too, so
|
|
126
|
+
// {field:'CullDistance.Max'} and {field:'props.CullDistance.Max'} mean
|
|
127
|
+
// the same thing rather than one of them silently matching nothing.
|
|
128
|
+
ReadPaths.AddUnique(Predicate.Field);
|
|
129
|
+
Predicate.Field = FString::Printf(TEXT("props.%s"), *Predicate.Field);
|
|
130
|
+
}
|
|
131
|
+
{
|
|
132
|
+
const TArray<TSharedPtr<FJsonValue>>* ExtraValues = nullptr;
|
|
133
|
+
if (Params->TryGetArrayField(TEXT("propertyNames"), ExtraValues) && ExtraValues)
|
|
134
|
+
{
|
|
135
|
+
for (const FString& Path : JsonArrayToStringList(ExtraValues))
|
|
136
|
+
{
|
|
137
|
+
ReadPaths.AddUnique(Path);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const bool bDryRun = OptionalBool(Params, TEXT("dryRun"), true);
|
|
143
|
+
const bool bSave = OptionalBool(Params, TEXT("save"), true);
|
|
144
|
+
const int32 MaxTypes = FMath::Clamp(
|
|
145
|
+
OptionalInt(Params, TEXT("maxTypes"), MCPFoliageBatchMaxTypes), 1, MCPFoliageBatchMaxTypes);
|
|
146
|
+
|
|
147
|
+
// ── Candidates ──────────────────────────────────────────────────────────
|
|
148
|
+
TArray<FMCPFoliageBatchCandidate> Candidates;
|
|
149
|
+
TSet<FString> Seen;
|
|
150
|
+
|
|
151
|
+
TArray<FString> ExplicitPaths;
|
|
152
|
+
{
|
|
153
|
+
const TArray<TSharedPtr<FJsonValue>>* PathValues = nullptr;
|
|
154
|
+
if (Params->TryGetArrayField(TEXT("foliageTypePaths"), PathValues) && PathValues)
|
|
155
|
+
{
|
|
156
|
+
ExplicitPaths = JsonArrayToStringList(PathValues);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
TArray<FString> UnloadablePaths;
|
|
160
|
+
for (const FString& Path : ExplicitPaths)
|
|
161
|
+
{
|
|
162
|
+
UFoliageType* Type = LoadObject<UFoliageType>(nullptr, *Path);
|
|
163
|
+
if (!Type)
|
|
164
|
+
{
|
|
165
|
+
UnloadablePaths.Add(Path);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
MCPFoliageBatchAddCandidate(Candidates, Seen, Type, TEXT("explicit"));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const FString Directory = OptionalString(Params, TEXT("directory"));
|
|
172
|
+
const bool bFromLevel = OptionalBool(Params, TEXT("fromLevel"), false);
|
|
173
|
+
if (ExplicitPaths.IsEmpty() && Directory.IsEmpty() && !bFromLevel)
|
|
174
|
+
{
|
|
175
|
+
return MCPError(TEXT("Pass one of 'foliageTypePaths' (explicit), 'directory' (scan FoliageType assets) or fromLevel=true (types placed in the open level)"));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!Directory.IsEmpty())
|
|
179
|
+
{
|
|
180
|
+
FAssetRegistryModule& AssetRegistryModule =
|
|
181
|
+
FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));
|
|
182
|
+
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
|
|
183
|
+
|
|
184
|
+
FARFilter Filter;
|
|
185
|
+
Filter.PackagePaths.Add(FName(*Directory));
|
|
186
|
+
Filter.bRecursivePaths = OptionalBool(Params, TEXT("recursive"), true);
|
|
187
|
+
Filter.ClassPaths.Add(UFoliageType::StaticClass()->GetClassPathName());
|
|
188
|
+
Filter.bRecursiveClasses = true;
|
|
189
|
+
|
|
190
|
+
TArray<FAssetData> Found;
|
|
191
|
+
AssetRegistry.GetAssets(Filter, Found);
|
|
192
|
+
for (const FAssetData& Data : Found)
|
|
193
|
+
{
|
|
194
|
+
if (Candidates.Num() >= MaxTypes) break;
|
|
195
|
+
UFoliageType* Type = Cast<UFoliageType>(Data.GetAsset());
|
|
196
|
+
if (!Type)
|
|
197
|
+
{
|
|
198
|
+
UnloadablePaths.Add(Data.GetObjectPathString());
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
MCPFoliageBatchAddCandidate(Candidates, Seen, Type, TEXT("directory"));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (bFromLevel)
|
|
206
|
+
{
|
|
207
|
+
if (UWorld* World = GetEditorWorld())
|
|
208
|
+
{
|
|
209
|
+
for (TActorIterator<AInstancedFoliageActor> It(World); It; ++It)
|
|
210
|
+
{
|
|
211
|
+
AInstancedFoliageActor* FoliageActor = *It;
|
|
212
|
+
if (!FoliageActor) continue;
|
|
213
|
+
for (const auto& Pair : FoliageActor->GetFoliageInfos())
|
|
214
|
+
{
|
|
215
|
+
if (Candidates.Num() >= MaxTypes) break;
|
|
216
|
+
MCPFoliageBatchAddCandidate(Candidates, Seen, Pair.Key, TEXT("level"));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
Candidates.Sort([](const FMCPFoliageBatchCandidate& A, const FMCPFoliageBatchCandidate& B)
|
|
223
|
+
{
|
|
224
|
+
return A.Path < B.Path;
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// ── Evaluate and write ──────────────────────────────────────────────────
|
|
228
|
+
TArray<TSharedPtr<FJsonValue>> Rows;
|
|
229
|
+
TArray<FString> MatchedPaths;
|
|
230
|
+
TArray<FString> SavedPaths;
|
|
231
|
+
int32 Matched = 0;
|
|
232
|
+
int32 Updated = 0;
|
|
233
|
+
int32 Failed = 0;
|
|
234
|
+
int32 SaveFailures = 0;
|
|
235
|
+
|
|
236
|
+
for (const FMCPFoliageBatchCandidate& Candidate : Candidates)
|
|
237
|
+
{
|
|
238
|
+
TSharedPtr<FJsonObject> Props = MakeShared<FJsonObject>();
|
|
239
|
+
TArray<FString> MissingProperties;
|
|
240
|
+
for (const FString& Path : ReadPaths)
|
|
241
|
+
{
|
|
242
|
+
FString ResolvedType;
|
|
243
|
+
const TSharedPtr<FJsonValue> Value =
|
|
244
|
+
MCPQuery::ReadDottedProperty(Candidate.Type, Path, ResolvedType);
|
|
245
|
+
if (!Value.IsValid())
|
|
246
|
+
{
|
|
247
|
+
MissingProperties.Add(Path);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
Props->SetField(Path, Value);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
TSharedPtr<FJsonObject> Row = MakeShared<FJsonObject>();
|
|
254
|
+
Row->SetStringField(TEXT("foliageTypePath"), Candidate.Path);
|
|
255
|
+
Row->SetStringField(TEXT("name"), Candidate.Name);
|
|
256
|
+
Row->SetStringField(TEXT("className"), Candidate.Type->GetClass()->GetName());
|
|
257
|
+
Row->SetStringField(TEXT("source"), Candidate.Source);
|
|
258
|
+
Row->SetObjectField(TEXT("props"), Props);
|
|
259
|
+
if (MissingProperties.Num() > 0)
|
|
260
|
+
{
|
|
261
|
+
// A property the predicate reads that this class does not have is
|
|
262
|
+
// reported rather than treated as a non-match, because "does not
|
|
263
|
+
// apply" and "did not match" are different answers.
|
|
264
|
+
Row->SetArrayField(TEXT("missingProperties"), MCPStringListToJson(MissingProperties));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (!MCPQuery::EvaluateAll(Predicates, Row, WhereMode == TEXT("all")))
|
|
268
|
+
{
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
++Matched;
|
|
272
|
+
MatchedPaths.Add(Candidate.Path);
|
|
273
|
+
|
|
274
|
+
TArray<TSharedPtr<FJsonValue>> SettingRows;
|
|
275
|
+
bool bTypeOk = true;
|
|
276
|
+
bool bTypeChanged = false;
|
|
277
|
+
for (const TPair<FString, TSharedPtr<FJsonValue>>& Pair : (*SettingsObject)->Values)
|
|
278
|
+
{
|
|
279
|
+
TSharedPtr<FJsonObject> SettingRow = MakeShared<FJsonObject>();
|
|
280
|
+
SettingRow->SetStringField(TEXT("propertyName"), Pair.Key);
|
|
281
|
+
|
|
282
|
+
FString ResolvedType;
|
|
283
|
+
const TSharedPtr<FJsonValue> Before =
|
|
284
|
+
MCPQuery::ReadDottedProperty(Candidate.Type, Pair.Key, ResolvedType);
|
|
285
|
+
if (Before.IsValid())
|
|
286
|
+
{
|
|
287
|
+
SettingRow->SetField(TEXT("previousValue"), Before);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (bDryRun)
|
|
291
|
+
{
|
|
292
|
+
// The preview still resolves the path, so an unwritable
|
|
293
|
+
// property is reported now rather than after the commit.
|
|
294
|
+
SettingRow->SetBoolField(TEXT("ok"), Before.IsValid());
|
|
295
|
+
if (!Before.IsValid())
|
|
296
|
+
{
|
|
297
|
+
SettingRow->SetStringField(TEXT("error"), FString::Printf(
|
|
298
|
+
TEXT("Property '%s' does not resolve on %s"),
|
|
299
|
+
*Pair.Key, *Candidate.Type->GetClass()->GetName()));
|
|
300
|
+
bTypeOk = false;
|
|
301
|
+
}
|
|
302
|
+
SettingRows.Add(MakeShared<FJsonValueObject>(SettingRow));
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
FString Error;
|
|
307
|
+
const bool bOk = MCPJsonProperty::SetDottedPropertyFromJson(
|
|
308
|
+
Candidate.Type, Pair.Key, Pair.Value, Error);
|
|
309
|
+
SettingRow->SetBoolField(TEXT("ok"), bOk);
|
|
310
|
+
if (!bOk)
|
|
311
|
+
{
|
|
312
|
+
SettingRow->SetStringField(TEXT("error"), Error);
|
|
313
|
+
bTypeOk = false;
|
|
314
|
+
}
|
|
315
|
+
else
|
|
316
|
+
{
|
|
317
|
+
FString AfterType;
|
|
318
|
+
const TSharedPtr<FJsonValue> After =
|
|
319
|
+
MCPQuery::ReadDottedProperty(Candidate.Type, Pair.Key, AfterType);
|
|
320
|
+
if (After.IsValid())
|
|
321
|
+
{
|
|
322
|
+
SettingRow->SetField(TEXT("value"), After);
|
|
323
|
+
// Read back rather than echoing the request, so a value the
|
|
324
|
+
// property coerced is visible instead of assumed.
|
|
325
|
+
if (MCPQuery::ValueKey(Before) != MCPQuery::ValueKey(After))
|
|
326
|
+
{
|
|
327
|
+
bTypeChanged = true;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
SettingRows.Add(MakeShared<FJsonValueObject>(SettingRow));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (!bDryRun && bTypeOk)
|
|
335
|
+
{
|
|
336
|
+
Candidate.Type->MarkPackageDirty();
|
|
337
|
+
++Updated;
|
|
338
|
+
if (bSave)
|
|
339
|
+
{
|
|
340
|
+
if (SaveAssetPackage(Candidate.Type))
|
|
341
|
+
{
|
|
342
|
+
SavedPaths.Add(Candidate.Path);
|
|
343
|
+
}
|
|
344
|
+
else
|
|
345
|
+
{
|
|
346
|
+
++SaveFailures;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (!bTypeOk) ++Failed;
|
|
351
|
+
|
|
352
|
+
if (Rows.Num() < MCPFoliageBatchMaxResultRows)
|
|
353
|
+
{
|
|
354
|
+
Row->SetBoolField(TEXT("ok"), bTypeOk);
|
|
355
|
+
Row->SetBoolField(TEXT("changed"), !bDryRun && bTypeChanged);
|
|
356
|
+
Row->SetArrayField(TEXT("settings"), SettingRows);
|
|
357
|
+
Rows.Add(MakeShared<FJsonValueObject>(Row));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
auto Result = MCPSuccess();
|
|
362
|
+
Result->SetBoolField(TEXT("success"), Failed == 0 && UnloadablePaths.IsEmpty());
|
|
363
|
+
if (Failed > 0)
|
|
364
|
+
{
|
|
365
|
+
Result->SetStringField(TEXT("error"), FString::Printf(
|
|
366
|
+
TEXT("%d of %d matched foliage types had a setting that did not apply; see results[]."),
|
|
367
|
+
Failed, Matched));
|
|
368
|
+
}
|
|
369
|
+
else if (!UnloadablePaths.IsEmpty())
|
|
370
|
+
{
|
|
371
|
+
Result->SetStringField(TEXT("error"), FString::Printf(
|
|
372
|
+
TEXT("%d requested path(s) could not be loaded as a FoliageType; see unloadablePaths."),
|
|
373
|
+
UnloadablePaths.Num()));
|
|
374
|
+
}
|
|
375
|
+
Result->SetBoolField(TEXT("dryRun"), bDryRun);
|
|
376
|
+
Result->SetNumberField(TEXT("scanned"), Candidates.Num());
|
|
377
|
+
Result->SetNumberField(TEXT("matched"), Matched);
|
|
378
|
+
Result->SetNumberField(bDryRun ? TEXT("wouldUpdate") : TEXT("updated"), bDryRun ? Matched : Updated);
|
|
379
|
+
Result->SetNumberField(TEXT("failed"), Failed);
|
|
380
|
+
Result->SetArrayField(TEXT("matchedPaths"), MCPStringListToJson(MatchedPaths));
|
|
381
|
+
Result->SetArrayField(TEXT("unloadablePaths"), MCPStringListToJson(UnloadablePaths));
|
|
382
|
+
Result->SetNumberField(TEXT("returnedResults"), Rows.Num());
|
|
383
|
+
Result->SetBoolField(TEXT("resultsTruncated"), Rows.Num() < Matched);
|
|
384
|
+
Result->SetArrayField(TEXT("results"), Rows);
|
|
385
|
+
|
|
386
|
+
if (Candidates.IsEmpty())
|
|
387
|
+
{
|
|
388
|
+
Result->SetStringField(TEXT("zeroMatchNote"),
|
|
389
|
+
TEXT("No FoliageType was found to test. Check 'directory' against where the assets actually live, or pass fromLevel=true to take the types placed in the open level."));
|
|
390
|
+
}
|
|
391
|
+
else if (Matched == 0)
|
|
392
|
+
{
|
|
393
|
+
Result->SetStringField(TEXT("zeroMatchNote"), FString::Printf(
|
|
394
|
+
TEXT("%d foliage types were read and none matched the predicate. Note that a numeric comparison needs a numeric property: CullDistance is an interval, so the field is CullDistance.Max rather than CullDistance."),
|
|
395
|
+
Candidates.Num()));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (!bDryRun)
|
|
399
|
+
{
|
|
400
|
+
Result->SetNumberField(TEXT("saved"), SavedPaths.Num());
|
|
401
|
+
Result->SetNumberField(TEXT("saveFailures"), SaveFailures);
|
|
402
|
+
Result->SetArrayField(TEXT("savedPaths"), MCPStringListToJson(SavedPaths));
|
|
403
|
+
if (Updated > 0)
|
|
404
|
+
{
|
|
405
|
+
MCPSetUpdated(Result);
|
|
406
|
+
}
|
|
407
|
+
if (!bSave && Updated > 0)
|
|
408
|
+
{
|
|
409
|
+
Result->SetStringField(TEXT("saveNote"),
|
|
410
|
+
TEXT("save=false: the FoliageType packages are dirty and NOT saved."));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else
|
|
414
|
+
{
|
|
415
|
+
Result->SetStringField(TEXT("dryRunNote"),
|
|
416
|
+
TEXT("dryRun defaults to TRUE for this action because it writes to many assets at once. Pass dryRun=false to commit."));
|
|
417
|
+
}
|
|
418
|
+
return MCPResult(Result);
|
|
419
|
+
}
|