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
|
@@ -54,6 +54,10 @@ private:
|
|
|
54
54
|
static TSharedPtr<FJsonValue> DeleteVariable(const TSharedPtr<FJsonObject>& Params);
|
|
55
55
|
static TSharedPtr<FJsonValue> AddFunctionParameter(const TSharedPtr<FJsonObject>& Params);
|
|
56
56
|
static TSharedPtr<FJsonValue> SetVariableDefault(const TSharedPtr<FJsonObject>& Params);
|
|
57
|
+
// #902: read the RESOLVED default off the generated class CDO, so a
|
|
58
|
+
// write-compile-readback loop can verify itself. Reports whether that value
|
|
59
|
+
// has reached the package as well as what it is (#931).
|
|
60
|
+
static TSharedPtr<FJsonValue> GetVariableDefault(const TSharedPtr<FJsonObject>& Params);
|
|
57
61
|
|
|
58
62
|
// v0.7.8 - agent-ergonomics additions (stubs)
|
|
59
63
|
static TSharedPtr<FJsonValue> ReadBlueprintGraphSummary(const TSharedPtr<FJsonObject>& Params);
|
|
@@ -83,6 +87,7 @@ private:
|
|
|
83
87
|
static TSharedPtr<FJsonValue> ReparentBlueprint(const TSharedPtr<FJsonObject>& Params);
|
|
84
88
|
// #580 flush orphaned InheritableComponentHandler override records
|
|
85
89
|
static TSharedPtr<FJsonValue> FlushInheritableComponentHandler(const TSharedPtr<FJsonObject>& Params);
|
|
90
|
+
static TSharedPtr<FJsonValue> FlushComponentTemplates(const TSharedPtr<FJsonObject>& Params);
|
|
86
91
|
|
|
87
92
|
// issues #182/#183: C++ class CDO property access
|
|
88
93
|
static TSharedPtr<FJsonValue> SetCdoProperty(const TSharedPtr<FJsonObject>& Params);
|
|
@@ -97,6 +102,11 @@ private:
|
|
|
97
102
|
static TSharedPtr<FJsonValue> ConnectPinsBatch(const TSharedPtr<FJsonObject>& Params);
|
|
98
103
|
static TSharedPtr<FJsonValue> SetNodePosition(const TSharedPtr<FJsonObject>& Params);
|
|
99
104
|
static TSharedPtr<FJsonValue> AutoLayoutGraph(const TSharedPtr<FJsonObject>& Params);
|
|
105
|
+
// #945: project-wide search for authored function call sites, narrowed by
|
|
106
|
+
// the Asset Registry before any package is loaded. Defined in
|
|
107
|
+
// BlueprintHandlers_Search.cpp.
|
|
108
|
+
static TSharedPtr<FJsonValue> SearchCallSites(const TSharedPtr<FJsonObject>& Params);
|
|
109
|
+
|
|
100
110
|
// #419: SetCapsuleSize on CapsuleComponent BP templates (UFUNCTION setter
|
|
101
111
|
// path; raw property writes leave the visualizer stale)
|
|
102
112
|
static TSharedPtr<FJsonValue> SetCapsuleSize(const TSharedPtr<FJsonObject>& Params);
|
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.cpp
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
// Effective collision reads (#925). See BlueprintHandlers_Collision.h for why
|
|
2
|
+
// the existing property dumps cannot answer the question these two do.
|
|
3
|
+
//
|
|
4
|
+
// The whole file reads. Nothing here writes a package, spawns anything, or
|
|
5
|
+
// touches the open level.
|
|
6
|
+
|
|
7
|
+
#include "BlueprintHandlers_Collision.h"
|
|
8
|
+
|
|
9
|
+
#include "BlueprintHandlers_Internal.h"
|
|
10
|
+
#include "HandlerRegistry.h"
|
|
11
|
+
#include "HandlerUtils.h"
|
|
12
|
+
|
|
13
|
+
#include "Components/PrimitiveComponent.h"
|
|
14
|
+
#include "Engine/Blueprint.h"
|
|
15
|
+
#include "Engine/CollisionProfile.h"
|
|
16
|
+
#include "Engine/EngineTypes.h"
|
|
17
|
+
#include "GameFramework/Actor.h"
|
|
18
|
+
|
|
19
|
+
#include "Dom/JsonObject.h"
|
|
20
|
+
#include "Dom/JsonValue.h"
|
|
21
|
+
|
|
22
|
+
namespace
|
|
23
|
+
{
|
|
24
|
+
// The container has one byte per serialisable channel and ECC_GameTraceChannel50
|
|
25
|
+
// is the last of them, so the response table is exactly this wide. ECC_MAX is
|
|
26
|
+
// larger because it counts the deprecated non-serialised entry past the end.
|
|
27
|
+
constexpr int32 CollisionChannelCount = 64;
|
|
28
|
+
|
|
29
|
+
/** "Block" rather than "ECR_Block". The enum's DisplayName metadata says the
|
|
30
|
+
* same thing, but only in an editor build with metadata loaded, and a result
|
|
31
|
+
* field that silently degrades to an ordinal is worse than a switch. */
|
|
32
|
+
const TCHAR* CollisionResponseName(ECollisionResponse Response)
|
|
33
|
+
{
|
|
34
|
+
switch (Response)
|
|
35
|
+
{
|
|
36
|
+
case ECR_Ignore: return TEXT("Ignore");
|
|
37
|
+
case ECR_Overlap: return TEXT("Overlap");
|
|
38
|
+
case ECR_Block: return TEXT("Block");
|
|
39
|
+
default: return TEXT("Unknown");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The spelling the Collision details panel uses, for the same reason. */
|
|
44
|
+
const TCHAR* CollisionEnabledName(ECollisionEnabled::Type Enabled)
|
|
45
|
+
{
|
|
46
|
+
switch (Enabled)
|
|
47
|
+
{
|
|
48
|
+
case ECollisionEnabled::NoCollision: return TEXT("NoCollision");
|
|
49
|
+
case ECollisionEnabled::QueryOnly: return TEXT("QueryOnly");
|
|
50
|
+
case ECollisionEnabled::PhysicsOnly: return TEXT("PhysicsOnly");
|
|
51
|
+
case ECollisionEnabled::QueryAndPhysics: return TEXT("QueryAndPhysics");
|
|
52
|
+
case ECollisionEnabled::ProbeOnly: return TEXT("ProbeOnly");
|
|
53
|
+
case ECollisionEnabled::QueryAndProbe: return TEXT("QueryAndProbe");
|
|
54
|
+
default: return TEXT("Unknown");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The C++ enumerator for a container index: ECC_Camera for 4. Stable across
|
|
59
|
+
* projects, unlike the display name, so a caller can key on it. */
|
|
60
|
+
FString CollisionChannelEnumName(int32 Index)
|
|
61
|
+
{
|
|
62
|
+
if (Index >= 0 && Index < 8)
|
|
63
|
+
{
|
|
64
|
+
static const TCHAR* const Fixed[8] = {
|
|
65
|
+
TEXT("ECC_WorldStatic"), TEXT("ECC_WorldDynamic"), TEXT("ECC_Pawn"),
|
|
66
|
+
TEXT("ECC_Visibility"), TEXT("ECC_Camera"), TEXT("ECC_PhysicsBody"),
|
|
67
|
+
TEXT("ECC_Vehicle"), TEXT("ECC_Destructible")
|
|
68
|
+
};
|
|
69
|
+
return Fixed[Index];
|
|
70
|
+
}
|
|
71
|
+
if (Index >= 8 && Index < 14)
|
|
72
|
+
{
|
|
73
|
+
return FString::Printf(TEXT("ECC_EngineTraceChannel%d"), Index - 7);
|
|
74
|
+
}
|
|
75
|
+
if (Index >= 14 && Index < CollisionChannelCount)
|
|
76
|
+
{
|
|
77
|
+
return FString::Printf(TEXT("ECC_GameTraceChannel%d"), Index - 13);
|
|
78
|
+
}
|
|
79
|
+
return FString::Printf(TEXT("ECC_Unknown%d"), Index);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** The name a channel carries when the project has not renamed it. Comparing
|
|
83
|
+
* the configured name against this is what tells a project's own channel
|
|
84
|
+
* ("Weapon") apart from an unused slot ("GameTraceChannel7"). */
|
|
85
|
+
FString CollisionChannelDefaultName(int32 Index)
|
|
86
|
+
{
|
|
87
|
+
FString EnumName = CollisionChannelEnumName(Index);
|
|
88
|
+
EnumName.RemoveFromStart(TEXT("ECC_"));
|
|
89
|
+
return EnumName;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** One channel, described once so the component read and the profile read
|
|
93
|
+
* cannot disagree about what a channel is called. */
|
|
94
|
+
struct FMCPCollisionChannelInfo
|
|
95
|
+
{
|
|
96
|
+
int32 Index = 0;
|
|
97
|
+
ECollisionChannel Channel = ECC_WorldStatic;
|
|
98
|
+
FString EnumName;
|
|
99
|
+
FString DisplayName;
|
|
100
|
+
bool bCustomNamed = false;
|
|
101
|
+
bool bTraceChannel = false;
|
|
102
|
+
bool bObjectChannel = false;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** Build the channel table from the project's own collision settings, so a
|
|
106
|
+
* custom trace or object channel appears under the name the project gave it
|
|
107
|
+
* rather than as GameTraceChannel<n>. */
|
|
108
|
+
TArray<FMCPCollisionChannelInfo> BuildCollisionChannelTable()
|
|
109
|
+
{
|
|
110
|
+
TArray<FMCPCollisionChannelInfo> Table;
|
|
111
|
+
|
|
112
|
+
UCollisionProfile* Profile = UCollisionProfile::Get();
|
|
113
|
+
Table.Reserve(CollisionChannelCount);
|
|
114
|
+
for (int32 Index = 0; Index < CollisionChannelCount; ++Index)
|
|
115
|
+
{
|
|
116
|
+
FMCPCollisionChannelInfo Info;
|
|
117
|
+
Info.Index = Index;
|
|
118
|
+
Info.Channel = static_cast<ECollisionChannel>(Index);
|
|
119
|
+
Info.EnumName = CollisionChannelEnumName(Index);
|
|
120
|
+
|
|
121
|
+
const FString DefaultName = CollisionChannelDefaultName(Index);
|
|
122
|
+
Info.DisplayName = DefaultName;
|
|
123
|
+
if (Profile)
|
|
124
|
+
{
|
|
125
|
+
const FName Configured = Profile->ReturnChannelNameFromContainerIndex(Index);
|
|
126
|
+
if (!Configured.IsNone())
|
|
127
|
+
{
|
|
128
|
+
Info.DisplayName = Configured.ToString();
|
|
129
|
+
}
|
|
130
|
+
Info.bTraceChannel = Profile->ConvertToTraceType(Info.Channel) != TraceTypeQuery_MAX;
|
|
131
|
+
Info.bObjectChannel = Profile->ConvertToObjectType(Info.Channel) != ObjectTypeQuery_MAX;
|
|
132
|
+
}
|
|
133
|
+
Info.bCustomNamed = !Info.DisplayName.Equals(DefaultName, ESearchCase::CaseSensitive);
|
|
134
|
+
Table.Add(Info);
|
|
135
|
+
}
|
|
136
|
+
return Table;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Which channels a response list carries by default.
|
|
140
|
+
*
|
|
141
|
+
* All 64 would bury the answer in fifty unused GameTraceChannel slots, so the
|
|
142
|
+
* default is the eight engine channels every project has plus every channel
|
|
143
|
+
* the project actually configured. includeAllChannels=true asks for the rest. */
|
|
144
|
+
bool ShouldReportChannel(const FMCPCollisionChannelInfo& Info, bool bIncludeAll)
|
|
145
|
+
{
|
|
146
|
+
if (bIncludeAll) return true;
|
|
147
|
+
if (Info.Index < 8) return true;
|
|
148
|
+
return Info.bCustomNamed;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Match a caller's `channel` argument against the table. Accepts the
|
|
152
|
+
* configured display name ("Weapon"), the C++ enumerator ("ECC_Camera"), the
|
|
153
|
+
* bare enumerator ("Camera") and the container index as a string. Returns
|
|
154
|
+
* INDEX_NONE on a miss. */
|
|
155
|
+
int32 FindCollisionChannel(const TArray<FMCPCollisionChannelInfo>& Table, const FString& Spec)
|
|
156
|
+
{
|
|
157
|
+
if (Spec.IsEmpty()) return INDEX_NONE;
|
|
158
|
+
|
|
159
|
+
if (Spec.IsNumeric())
|
|
160
|
+
{
|
|
161
|
+
const int32 AsIndex = FCString::Atoi(*Spec);
|
|
162
|
+
return (AsIndex >= 0 && AsIndex < Table.Num()) ? AsIndex : INDEX_NONE;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (const FMCPCollisionChannelInfo& Info : Table)
|
|
166
|
+
{
|
|
167
|
+
if (Info.DisplayName.Equals(Spec, ESearchCase::IgnoreCase)) return Info.Index;
|
|
168
|
+
if (Info.EnumName.Equals(Spec, ESearchCase::IgnoreCase)) return Info.Index;
|
|
169
|
+
}
|
|
170
|
+
return INDEX_NONE;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The names a failed channel lookup should suggest: everything a caller could
|
|
174
|
+
* legitimately have meant, without the unused slots. */
|
|
175
|
+
FString DescribeKnownChannels(const TArray<FMCPCollisionChannelInfo>& Table)
|
|
176
|
+
{
|
|
177
|
+
TArray<FString> Names;
|
|
178
|
+
for (const FMCPCollisionChannelInfo& Info : Table)
|
|
179
|
+
{
|
|
180
|
+
if (ShouldReportChannel(Info, /*bIncludeAll=*/false))
|
|
181
|
+
{
|
|
182
|
+
Names.Add(Info.DisplayName);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return FString::Join(Names, TEXT(", "));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void WriteChannelIdentity(const TSharedPtr<FJsonObject>& Out, const FMCPCollisionChannelInfo& Info)
|
|
189
|
+
{
|
|
190
|
+
Out->SetStringField(TEXT("channel"), Info.DisplayName);
|
|
191
|
+
Out->SetStringField(TEXT("enumName"), Info.EnumName);
|
|
192
|
+
Out->SetNumberField(TEXT("channelIndex"), Info.Index);
|
|
193
|
+
Out->SetBoolField(TEXT("isTraceChannel"), Info.bTraceChannel);
|
|
194
|
+
Out->SetBoolField(TEXT("isObjectChannel"), Info.bObjectChannel);
|
|
195
|
+
Out->SetBoolField(TEXT("isCustomNamed"), Info.bCustomNamed);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Look a profile up by name, tolerating a renamed profile through the
|
|
199
|
+
* engine's own redirect table. */
|
|
200
|
+
bool LookUpProfileTemplate(const FString& ProfileName, FCollisionResponseTemplate& OutTemplate, FString& OutResolvedName)
|
|
201
|
+
{
|
|
202
|
+
OutResolvedName = ProfileName;
|
|
203
|
+
UCollisionProfile* Profile = UCollisionProfile::Get();
|
|
204
|
+
if (!Profile) return false;
|
|
205
|
+
|
|
206
|
+
FName Name(*ProfileName);
|
|
207
|
+
if (const FName* Redirect = Profile->LookForProfileRedirect(Name))
|
|
208
|
+
{
|
|
209
|
+
Name = *Redirect;
|
|
210
|
+
OutResolvedName = Name.ToString();
|
|
211
|
+
}
|
|
212
|
+
return Profile->GetProfileTemplate(Name, OutTemplate);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Every profile the project has, for a lookup that missed. */
|
|
216
|
+
TArray<FString> ListProfileNames()
|
|
217
|
+
{
|
|
218
|
+
TArray<FString> Names;
|
|
219
|
+
UCollisionProfile* Profile = UCollisionProfile::Get();
|
|
220
|
+
if (!Profile) return Names;
|
|
221
|
+
for (int32 Index = 0; Index < Profile->GetNumOfProfiles(); ++Index)
|
|
222
|
+
{
|
|
223
|
+
if (const FCollisionResponseTemplate* Template = Profile->GetProfileByIndex(Index))
|
|
224
|
+
{
|
|
225
|
+
Names.AddUnique(Template->Name.ToString());
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return Names;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Collect every component on an Actor CDO, which is where a native C++
|
|
232
|
+
* constructor's CreateDefaultSubobject lands. This is the case #925 was
|
|
233
|
+
* reported from: verifying that a rebuilt constructor's
|
|
234
|
+
* SetCollisionResponseToChannel actually reached the CDO. */
|
|
235
|
+
UActorComponent* FindComponentOnActorCDO(
|
|
236
|
+
AActor* CDO,
|
|
237
|
+
const FString& ComponentName,
|
|
238
|
+
TArray<FString>& OutAvailable)
|
|
239
|
+
{
|
|
240
|
+
if (!CDO) return nullptr;
|
|
241
|
+
|
|
242
|
+
UActorComponent* Found = nullptr;
|
|
243
|
+
for (UActorComponent* Component : CDO->GetComponents())
|
|
244
|
+
{
|
|
245
|
+
if (!Component) continue;
|
|
246
|
+
const FString Name = Component->GetName();
|
|
247
|
+
OutAvailable.AddUnique(Name);
|
|
248
|
+
if (!Found && Name.Equals(ComponentName, ESearchCase::IgnoreCase))
|
|
249
|
+
{
|
|
250
|
+
Found = Component;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return Found;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
void FCollisionQueryHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
|
|
258
|
+
{
|
|
259
|
+
Registry.RegisterHandler(TEXT("get_component_collision"), &GetComponentCollision);
|
|
260
|
+
Registry.RegisterHandler(TEXT("resolve_collision_profile"), &ResolveCollisionProfile);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
TSharedPtr<FJsonValue> FCollisionQueryHandlers::GetComponentCollision(const TSharedPtr<FJsonObject>& Params)
|
|
264
|
+
{
|
|
265
|
+
FString AssetPath;
|
|
266
|
+
if (auto Err = RequireStringAlt(Params, TEXT("assetPath"), TEXT("path"), AssetPath)) return Err;
|
|
267
|
+
|
|
268
|
+
FString ComponentName;
|
|
269
|
+
if (auto Err = RequireString(Params, TEXT("componentName"), ComponentName)) return Err;
|
|
270
|
+
|
|
271
|
+
const FString RequestedChannel = OptionalString(Params, TEXT("channel"));
|
|
272
|
+
const bool bIncludeAll = OptionalBool(Params, TEXT("includeAllChannels"), false);
|
|
273
|
+
|
|
274
|
+
// Two ways in, because the two things a caller wants to verify live in
|
|
275
|
+
// different places: a Blueprint's component template, and a native class's
|
|
276
|
+
// CDO component. A Blueprint path resolves as an asset; anything else is
|
|
277
|
+
// tried as a class.
|
|
278
|
+
UActorComponent* Component = nullptr;
|
|
279
|
+
TArray<FString> Available;
|
|
280
|
+
bool bInherited = false;
|
|
281
|
+
FString Source;
|
|
282
|
+
FString OwnerPath;
|
|
283
|
+
|
|
284
|
+
if (UBlueprint* Blueprint = Cast<UBlueprint>(MCPLoadAssetObject(AssetPath)))
|
|
285
|
+
{
|
|
286
|
+
Component = ResolveComponentTemplate(
|
|
287
|
+
Blueprint, ComponentName, /*bForWrite=*/false, bInherited, Available);
|
|
288
|
+
Source = TEXT("blueprint");
|
|
289
|
+
OwnerPath = Blueprint->GetPathName();
|
|
290
|
+
}
|
|
291
|
+
else
|
|
292
|
+
{
|
|
293
|
+
UClass* Class = MCPResolveClass(AssetPath);
|
|
294
|
+
if (!Class)
|
|
295
|
+
{
|
|
296
|
+
return MCPClassNotFoundError(AssetPath, TEXT("assetPath"));
|
|
297
|
+
}
|
|
298
|
+
if (!Class->IsChildOf(AActor::StaticClass()))
|
|
299
|
+
{
|
|
300
|
+
return MCPClassUnusableError(AssetPath, Class, TEXT("wrong_base"),
|
|
301
|
+
TEXT("it is not an Actor class, so it has no component to read collision from."));
|
|
302
|
+
}
|
|
303
|
+
AActor* CDO = Cast<AActor>(Class->GetDefaultObject());
|
|
304
|
+
Component = FindComponentOnActorCDO(CDO, ComponentName, Available);
|
|
305
|
+
Source = TEXT("class");
|
|
306
|
+
OwnerPath = Class->GetPathName();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (!Component)
|
|
310
|
+
{
|
|
311
|
+
Available.Sort([](const FString& A, const FString& B) { return A < B; });
|
|
312
|
+
return MCPError(FString::Printf(
|
|
313
|
+
TEXT("Component '%s' not found on '%s'. Available: [%s]"),
|
|
314
|
+
*ComponentName, *AssetPath, *FString::Join(Available, TEXT(", "))));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
UPrimitiveComponent* Primitive = Cast<UPrimitiveComponent>(Component);
|
|
318
|
+
if (!Primitive)
|
|
319
|
+
{
|
|
320
|
+
// A SceneComponent or a bare ActorComponent has no BodyInstance at all,
|
|
321
|
+
// and saying "not a PrimitiveComponent" is the difference between an
|
|
322
|
+
// answerable question and an empty response.
|
|
323
|
+
return MCPError(FString::Printf(
|
|
324
|
+
TEXT("Component '%s' on '%s' is a %s, which carries no collision. Only PrimitiveComponent ")
|
|
325
|
+
TEXT("subclasses (capsules, boxes, spheres, meshes) have a collision profile and per-channel responses."),
|
|
326
|
+
*ComponentName, *AssetPath, *Component->GetClass()->GetName()));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const TArray<FMCPCollisionChannelInfo> Table = BuildCollisionChannelTable();
|
|
330
|
+
|
|
331
|
+
int32 SingleChannel = INDEX_NONE;
|
|
332
|
+
if (!RequestedChannel.IsEmpty())
|
|
333
|
+
{
|
|
334
|
+
SingleChannel = FindCollisionChannel(Table, RequestedChannel);
|
|
335
|
+
if (SingleChannel == INDEX_NONE)
|
|
336
|
+
{
|
|
337
|
+
return MCPError(FString::Printf(
|
|
338
|
+
TEXT("Unknown collision channel '%s'. Pass a configured channel name, a C++ enumerator ")
|
|
339
|
+
TEXT("(ECC_Camera), or a container index. Known channels: %s"),
|
|
340
|
+
*RequestedChannel, *DescribeKnownChannels(Table)));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const FName ProfileName = Primitive->GetCollisionProfileName();
|
|
345
|
+
FCollisionResponseTemplate ProfileTemplate;
|
|
346
|
+
FString ResolvedProfileName;
|
|
347
|
+
const bool bProfileResolved =
|
|
348
|
+
LookUpProfileTemplate(ProfileName.ToString(), ProfileTemplate, ResolvedProfileName);
|
|
349
|
+
|
|
350
|
+
auto Result = MCPSuccess();
|
|
351
|
+
Result->SetStringField(TEXT("assetPath"), AssetPath);
|
|
352
|
+
Result->SetStringField(TEXT("resolvedPath"), OwnerPath);
|
|
353
|
+
Result->SetStringField(TEXT("source"), Source);
|
|
354
|
+
Result->SetStringField(TEXT("componentName"), Component->GetName());
|
|
355
|
+
Result->SetStringField(TEXT("componentClass"), Component->GetClass()->GetName());
|
|
356
|
+
Result->SetBoolField(TEXT("inherited"), bInherited);
|
|
357
|
+
|
|
358
|
+
Result->SetStringField(TEXT("collisionEnabled"), CollisionEnabledName(Primitive->GetCollisionEnabled()));
|
|
359
|
+
Result->SetBoolField(TEXT("collisionEnabledForQueries"), Primitive->IsQueryCollisionEnabled());
|
|
360
|
+
Result->SetBoolField(TEXT("collisionEnabledForPhysics"), Primitive->IsPhysicsCollisionEnabled());
|
|
361
|
+
|
|
362
|
+
const ECollisionChannel ObjectType = Primitive->GetCollisionObjectType();
|
|
363
|
+
const int32 ObjectTypeIndex = static_cast<int32>(ObjectType);
|
|
364
|
+
Result->SetStringField(TEXT("objectType"),
|
|
365
|
+
Table.IsValidIndex(ObjectTypeIndex) ? Table[ObjectTypeIndex].DisplayName : CollisionChannelEnumName(ObjectTypeIndex));
|
|
366
|
+
Result->SetStringField(TEXT("objectTypeEnumName"), CollisionChannelEnumName(ObjectTypeIndex));
|
|
367
|
+
Result->SetNumberField(TEXT("objectTypeIndex"), ObjectTypeIndex);
|
|
368
|
+
|
|
369
|
+
Result->SetStringField(TEXT("profileName"), ProfileName.ToString());
|
|
370
|
+
Result->SetBoolField(TEXT("profileResolved"), bProfileResolved);
|
|
371
|
+
if (bProfileResolved && !ResolvedProfileName.Equals(ProfileName.ToString(), ESearchCase::CaseSensitive))
|
|
372
|
+
{
|
|
373
|
+
Result->SetStringField(TEXT("profileRedirectedTo"), ResolvedProfileName);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// The effective response per channel. GetCollisionResponseToChannel is the
|
|
377
|
+
// evaluated answer: the profile's response with the component's own
|
|
378
|
+
// overrides already folded in. The profile's own response rides alongside
|
|
379
|
+
// so a caller can see WHERE the answer came from, which is what the
|
|
380
|
+
// ResponseArray text dump could never show for an inherited response.
|
|
381
|
+
TArray<TSharedPtr<FJsonValue>> Responses;
|
|
382
|
+
for (const FMCPCollisionChannelInfo& Info : Table)
|
|
383
|
+
{
|
|
384
|
+
if (SingleChannel != INDEX_NONE && Info.Index != SingleChannel) continue;
|
|
385
|
+
if (SingleChannel == INDEX_NONE && !ShouldReportChannel(Info, bIncludeAll)) continue;
|
|
386
|
+
|
|
387
|
+
const ECollisionResponse Effective = Primitive->GetCollisionResponseToChannel(Info.Channel);
|
|
388
|
+
|
|
389
|
+
TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
|
|
390
|
+
WriteChannelIdentity(Entry, Info);
|
|
391
|
+
Entry->SetStringField(TEXT("response"), CollisionResponseName(Effective));
|
|
392
|
+
if (bProfileResolved)
|
|
393
|
+
{
|
|
394
|
+
const ECollisionResponse FromProfile = ProfileTemplate.ResponseToChannels.GetResponse(Info.Channel);
|
|
395
|
+
Entry->SetStringField(TEXT("profileResponse"), CollisionResponseName(FromProfile));
|
|
396
|
+
Entry->SetBoolField(TEXT("overridesProfile"), Effective != FromProfile);
|
|
397
|
+
}
|
|
398
|
+
Responses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (SingleChannel != INDEX_NONE && Responses.Num() > 0)
|
|
402
|
+
{
|
|
403
|
+
// One channel asked for, one answer at the top level as well as in the
|
|
404
|
+
// list, so the caller does not have to index into an array of one.
|
|
405
|
+
Result->SetObjectField(TEXT("channel"), Responses[0]->AsObject());
|
|
406
|
+
}
|
|
407
|
+
Result->SetArrayField(TEXT("responses"), Responses);
|
|
408
|
+
Result->SetNumberField(TEXT("responseCount"), Responses.Num());
|
|
409
|
+
Result->SetBoolField(TEXT("includeAllChannels"), bIncludeAll);
|
|
410
|
+
return MCPResult(Result);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
TSharedPtr<FJsonValue> FCollisionQueryHandlers::ResolveCollisionProfile(const TSharedPtr<FJsonObject>& Params)
|
|
414
|
+
{
|
|
415
|
+
FString ProfileName;
|
|
416
|
+
if (auto Err = RequireString(Params, TEXT("profileName"), ProfileName)) return Err;
|
|
417
|
+
|
|
418
|
+
const FString RequestedChannel = OptionalString(Params, TEXT("channel"));
|
|
419
|
+
const bool bIncludeAll = OptionalBool(Params, TEXT("includeAllChannels"), false);
|
|
420
|
+
|
|
421
|
+
if (!UCollisionProfile::Get())
|
|
422
|
+
{
|
|
423
|
+
return MCPError(TEXT("Collision settings are not available in this process."));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
FCollisionResponseTemplate Template;
|
|
427
|
+
FString ResolvedProfileName;
|
|
428
|
+
if (!LookUpProfileTemplate(ProfileName, Template, ResolvedProfileName))
|
|
429
|
+
{
|
|
430
|
+
TArray<FString> Known = ListProfileNames();
|
|
431
|
+
Known.Sort([](const FString& A, const FString& B) { return A < B; });
|
|
432
|
+
|
|
433
|
+
TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
|
|
434
|
+
Obj->SetBoolField(TEXT("success"), false);
|
|
435
|
+
Obj->SetStringField(TEXT("error"), FString::Printf(
|
|
436
|
+
TEXT("No collision profile named '%s'. The project defines: %s"),
|
|
437
|
+
*ProfileName, *FString::Join(Known, TEXT(", "))));
|
|
438
|
+
Obj->SetStringField(TEXT("profileName"), ProfileName);
|
|
439
|
+
Obj->SetStringField(TEXT("reason"), TEXT("profile_not_found"));
|
|
440
|
+
TArray<TSharedPtr<FJsonValue>> KnownJson;
|
|
441
|
+
for (const FString& Name : Known) KnownJson.Add(MakeShared<FJsonValueString>(Name));
|
|
442
|
+
Obj->SetArrayField(TEXT("knownProfiles"), KnownJson);
|
|
443
|
+
return MakeShared<FJsonValueObject>(Obj);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const TArray<FMCPCollisionChannelInfo> Table = BuildCollisionChannelTable();
|
|
447
|
+
|
|
448
|
+
int32 SingleChannel = INDEX_NONE;
|
|
449
|
+
if (!RequestedChannel.IsEmpty())
|
|
450
|
+
{
|
|
451
|
+
SingleChannel = FindCollisionChannel(Table, RequestedChannel);
|
|
452
|
+
if (SingleChannel == INDEX_NONE)
|
|
453
|
+
{
|
|
454
|
+
return MCPError(FString::Printf(
|
|
455
|
+
TEXT("Unknown collision channel '%s'. Pass a configured channel name, a C++ enumerator ")
|
|
456
|
+
TEXT("(ECC_Camera), or a container index. Known channels: %s"),
|
|
457
|
+
*RequestedChannel, *DescribeKnownChannels(Table)));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
auto Result = MCPSuccess();
|
|
462
|
+
Result->SetStringField(TEXT("profileName"), Template.Name.ToString());
|
|
463
|
+
Result->SetStringField(TEXT("requestedProfileName"), ProfileName);
|
|
464
|
+
if (!ResolvedProfileName.Equals(ProfileName, ESearchCase::CaseSensitive))
|
|
465
|
+
{
|
|
466
|
+
Result->SetStringField(TEXT("profileRedirectedTo"), ResolvedProfileName);
|
|
467
|
+
}
|
|
468
|
+
Result->SetStringField(TEXT("collisionEnabled"), CollisionEnabledName(Template.CollisionEnabled));
|
|
469
|
+
|
|
470
|
+
const int32 ObjectTypeIndex = static_cast<int32>(Template.ObjectType.GetValue());
|
|
471
|
+
Result->SetStringField(TEXT("objectType"),
|
|
472
|
+
Table.IsValidIndex(ObjectTypeIndex) ? Table[ObjectTypeIndex].DisplayName : CollisionChannelEnumName(ObjectTypeIndex));
|
|
473
|
+
Result->SetStringField(TEXT("objectTypeEnumName"), CollisionChannelEnumName(ObjectTypeIndex));
|
|
474
|
+
Result->SetStringField(TEXT("objectTypeName"), Template.ObjectTypeName.ToString());
|
|
475
|
+
Result->SetNumberField(TEXT("objectTypeIndex"), ObjectTypeIndex);
|
|
476
|
+
Result->SetBoolField(TEXT("canModify"), Template.bCanModify);
|
|
477
|
+
#if WITH_EDITORONLY_DATA
|
|
478
|
+
Result->SetStringField(TEXT("helpMessage"), Template.HelpMessage);
|
|
479
|
+
#endif
|
|
480
|
+
|
|
481
|
+
TArray<TSharedPtr<FJsonValue>> Responses;
|
|
482
|
+
for (const FMCPCollisionChannelInfo& Info : Table)
|
|
483
|
+
{
|
|
484
|
+
if (SingleChannel != INDEX_NONE && Info.Index != SingleChannel) continue;
|
|
485
|
+
if (SingleChannel == INDEX_NONE && !ShouldReportChannel(Info, bIncludeAll)) continue;
|
|
486
|
+
|
|
487
|
+
TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
|
|
488
|
+
WriteChannelIdentity(Entry, Info);
|
|
489
|
+
Entry->SetStringField(TEXT("response"),
|
|
490
|
+
CollisionResponseName(Template.ResponseToChannels.GetResponse(Info.Channel)));
|
|
491
|
+
Responses.Add(MakeShared<FJsonValueObject>(Entry));
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (SingleChannel != INDEX_NONE && Responses.Num() > 0)
|
|
495
|
+
{
|
|
496
|
+
Result->SetObjectField(TEXT("channel"), Responses[0]->AsObject());
|
|
497
|
+
}
|
|
498
|
+
Result->SetArrayField(TEXT("responses"), Responses);
|
|
499
|
+
Result->SetNumberField(TEXT("responseCount"), Responses.Num());
|
|
500
|
+
Result->SetBoolField(TEXT("includeAllChannels"), bIncludeAll);
|
|
501
|
+
return MCPResult(Result);
|
|
502
|
+
}
|
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.h
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "CoreMinimal.h"
|
|
4
|
+
#include "Dom/JsonValue.h"
|
|
5
|
+
#include "Dom/JsonObject.h"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Effective collision reads (#925).
|
|
9
|
+
*
|
|
10
|
+
* What already existed reports the collision a component STORES, not the
|
|
11
|
+
* collision it HAS. blueprint(read_component_properties) exports BodyInstance
|
|
12
|
+
* as text, and that text carries CollisionProfileName plus the ResponseArray of
|
|
13
|
+
* overrides that DIFFER from the profile. A response inherited from the profile
|
|
14
|
+
* (the Pawn profile blocking Camera, say) appears nowhere in it, so "does this
|
|
15
|
+
* capsule block ECC_Camera" could not be answered from the dump.
|
|
16
|
+
* editor(get_object_properties) has the same limit: it exports property text,
|
|
17
|
+
* it does not evaluate the profile.
|
|
18
|
+
*
|
|
19
|
+
* That gap has teeth. A live-coded constructor change to
|
|
20
|
+
* SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore) LOOKED applied, because
|
|
21
|
+
* the Live Coding compile succeeded, and the CDO still answered ECR_BLOCK until
|
|
22
|
+
* a proper on-disk build and an editor restart. The text dump was byte for byte
|
|
23
|
+
* identical before and after. Only the effective response, which is what
|
|
24
|
+
* UPrimitiveComponent::GetCollisionResponseToChannel returns, showed it.
|
|
25
|
+
*
|
|
26
|
+
* A separate class rather than another FBlueprintHandlers partition, because
|
|
27
|
+
* these register themselves and the two actions land in two different wire
|
|
28
|
+
* categories (`blueprint` and `project`) while sharing one channel table. The
|
|
29
|
+
* actions still read as blueprint(get_component_collision) and
|
|
30
|
+
* project(resolve_collision_profile) to a caller.
|
|
31
|
+
*/
|
|
32
|
+
class FCollisionQueryHandlers
|
|
33
|
+
{
|
|
34
|
+
public:
|
|
35
|
+
static void RegisterHandlers(class FMCPHandlerRegistry& Registry);
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
/** Resolved collision state of one component template or CDO component. */
|
|
39
|
+
static TSharedPtr<FJsonValue> GetComponentCollision(const TSharedPtr<FJsonObject>& Params);
|
|
40
|
+
|
|
41
|
+
/** Per-channel responses of one named collision profile. */
|
|
42
|
+
static TSharedPtr<FJsonValue> ResolveCollisionProfile(const TSharedPtr<FJsonObject>& Params);
|
|
43
|
+
};
|