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
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
// asset(create_subobject) (#975).
|
|
2
|
+
//
|
|
3
|
+
// Some plugin data assets store their payload as named subobjects that live
|
|
4
|
+
// inside the asset's own package and are referenced from a struct array.
|
|
5
|
+
// Editing an existing entry already worked through set_property,
|
|
6
|
+
// bulk_set_properties and append_array_elements with dotted paths, but ADDING
|
|
7
|
+
// one needs a brand-new subobject and nothing native could make one:
|
|
8
|
+
// create_asset_by_class refuses component classes outright and otherwise puts
|
|
9
|
+
// the new object in a package of its own.
|
|
10
|
+
//
|
|
11
|
+
// Two things bit the reporter and both are handled here.
|
|
12
|
+
//
|
|
13
|
+
// 1. A freshly created object that nothing references is collected within
|
|
14
|
+
// roughly one bridge call, so they had to create one object and reference
|
|
15
|
+
// it in the very next call, and an intermediate read lost it. The new
|
|
16
|
+
// object is created RF_Standalone, which is the engine's own "keep this
|
|
17
|
+
// even though nothing points at it yet", and the owning package is written
|
|
18
|
+
// in the same call by default. RF_Standalone is also what makes
|
|
19
|
+
// UPackage::SavePackage harvest an otherwise unreferenced object as an
|
|
20
|
+
// export, so the subobject is on disk and reachable by path from the next
|
|
21
|
+
// call onwards whatever the collector decides to do in between.
|
|
22
|
+
//
|
|
23
|
+
// 2. Plugin classes are frequently absent from the Python `unreal` module, so
|
|
24
|
+
// the class has to be named by object path. className goes through the
|
|
25
|
+
// shared class resolver, which accepts /Script/Module.Class, the
|
|
26
|
+
// Module.Class shorthand and the bare name alike.
|
|
27
|
+
|
|
28
|
+
#include "AssetHandlers.h"
|
|
29
|
+
#include "HandlerRegistry.h"
|
|
30
|
+
#include "HandlerUtils.h"
|
|
31
|
+
#include "HandlerJsonProperty.h"
|
|
32
|
+
|
|
33
|
+
#include "Dom/JsonObject.h"
|
|
34
|
+
#include "Dom/JsonValue.h"
|
|
35
|
+
#include "GameFramework/Actor.h"
|
|
36
|
+
#include "Misc/PackageName.h"
|
|
37
|
+
#include "UObject/Package.h"
|
|
38
|
+
#include "UObject/UObjectGlobals.h"
|
|
39
|
+
|
|
40
|
+
namespace
|
|
41
|
+
{
|
|
42
|
+
/** Apply a properties object to one object, dotted paths and all. Returns
|
|
43
|
+
* the number applied; every failure lands in OutErrors. */
|
|
44
|
+
int32 MCPApplySubobjectProperties(
|
|
45
|
+
UObject* Target,
|
|
46
|
+
const TSharedPtr<FJsonObject>& Properties,
|
|
47
|
+
TArray<FString>& OutApplied,
|
|
48
|
+
TArray<FString>& OutErrors)
|
|
49
|
+
{
|
|
50
|
+
if (!Target || !Properties.IsValid()) return 0;
|
|
51
|
+
|
|
52
|
+
int32 Applied = 0;
|
|
53
|
+
for (const auto& Pair : Properties->Values)
|
|
54
|
+
{
|
|
55
|
+
// The key type is not FString on every engine the plugin builds
|
|
56
|
+
// against, so materialise it before it is used as one.
|
|
57
|
+
const FString PropertyPath(*Pair.Key);
|
|
58
|
+
FString SetError;
|
|
59
|
+
if (MCPJsonProperty::SetDottedPropertyFromJson(Target, PropertyPath, Pair.Value, SetError))
|
|
60
|
+
{
|
|
61
|
+
OutApplied.Add(PropertyPath);
|
|
62
|
+
++Applied;
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
{
|
|
66
|
+
OutErrors.Add(FString::Printf(TEXT("%s: %s"), *PropertyPath, *SetError));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return Applied;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
TArray<TSharedPtr<FJsonValue>> MCPSubobjectStringsToJson(const TArray<FString>& Values)
|
|
73
|
+
{
|
|
74
|
+
TArray<TSharedPtr<FJsonValue>> Out;
|
|
75
|
+
Out.Reserve(Values.Num());
|
|
76
|
+
for (const FString& Value : Values) Out.Add(MakeShared<FJsonValueString>(Value));
|
|
77
|
+
return Out;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
TSharedPtr<FJsonValue> FAssetHandlers::CreateSubobject(const TSharedPtr<FJsonObject>& Params)
|
|
82
|
+
{
|
|
83
|
+
MCP_CHECK_GAME_THREAD();
|
|
84
|
+
|
|
85
|
+
FString AssetPath;
|
|
86
|
+
if (auto Err = RequireStringAlt(Params, TEXT("assetPath"), TEXT("path"), AssetPath)) return Err;
|
|
87
|
+
FString ClassName;
|
|
88
|
+
if (auto Err = RequireString(Params, TEXT("className"), ClassName)) return Err;
|
|
89
|
+
FString Name;
|
|
90
|
+
if (auto Err = RequireString(Params, TEXT("name"), Name)) return Err;
|
|
91
|
+
Name.TrimStartAndEndInline();
|
|
92
|
+
if (Name.IsEmpty())
|
|
93
|
+
{
|
|
94
|
+
return MCPError(TEXT("'name' must not be empty: the subobject is addressed by name from the next call onwards."));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// This writes into an existing package, so the mount guardrail applies
|
|
98
|
+
// before anything is resolved or created.
|
|
99
|
+
if (MCPIsProtectedAssetPath(AssetPath))
|
|
100
|
+
{
|
|
101
|
+
return MCPError(FString::Printf(
|
|
102
|
+
TEXT("'%s' is on a protected mount (/Engine/, /Script/, /Memory/, /Temp/), which the bridge never writes to."),
|
|
103
|
+
*AssetPath));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
TSharedPtr<FJsonValue> LoadError;
|
|
107
|
+
UObject* OwnerAsset = MCPRequireAssetObject(AssetPath, LoadError);
|
|
108
|
+
if (!OwnerAsset) return LoadError;
|
|
109
|
+
|
|
110
|
+
UPackage* OwnerPackage = OwnerAsset->GetOutermost();
|
|
111
|
+
if (!OwnerPackage)
|
|
112
|
+
{
|
|
113
|
+
return MCPError(FString::Printf(TEXT("Asset '%s' has no package to own a subobject."), *AssetPath));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
UClass* Class = MCPResolveClass(ClassName);
|
|
117
|
+
if (auto Err = MCPCheckClassUsable(ClassName, Class)) return Err;
|
|
118
|
+
|
|
119
|
+
// An Actor is created by spawning it into a level, and NewObject on one
|
|
120
|
+
// outside a level is not a supported construction. Say so rather than
|
|
121
|
+
// letting the engine decide how to fail. Components are deliberately NOT
|
|
122
|
+
// refused: they are the case this action exists for.
|
|
123
|
+
if (Class->IsChildOf(AActor::StaticClass()))
|
|
124
|
+
{
|
|
125
|
+
return MCPClassUnusableError(ClassName, Class, TEXT("actor_class"),
|
|
126
|
+
TEXT("an Actor is spawned into a level, not created inside an asset package. Use level(spawn_actor)."));
|
|
127
|
+
}
|
|
128
|
+
if (Class->IsChildOf(UClass::StaticClass()))
|
|
129
|
+
{
|
|
130
|
+
return MCPClassUnusableError(ClassName, Class, TEXT("class_object"),
|
|
131
|
+
TEXT("it is a class object rather than an instantiable type. Pass the class you want an INSTANCE of."));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// outer=asset gives "/Game/Foo/DA_Thing.DA_Thing:Name", the ordinary
|
|
135
|
+
// subobject-of-the-asset form. outer=package gives
|
|
136
|
+
// "/Game/Foo/DA_Thing.Name", which is what a plugin that keeps its payload
|
|
137
|
+
// as siblings of the asset inside one package expects.
|
|
138
|
+
const FString OuterSpec = OptionalString(Params, TEXT("outer"), TEXT("asset")).ToLower();
|
|
139
|
+
if (OuterSpec != TEXT("asset") && OuterSpec != TEXT("package"))
|
|
140
|
+
{
|
|
141
|
+
return MCPError(FString::Printf(
|
|
142
|
+
TEXT("'outer' must be 'asset' (default) or 'package', got '%s'."), *OuterSpec));
|
|
143
|
+
}
|
|
144
|
+
UObject* Outer = (OuterSpec == TEXT("package"))
|
|
145
|
+
? static_cast<UObject*>(OwnerPackage)
|
|
146
|
+
: OwnerAsset;
|
|
147
|
+
|
|
148
|
+
// A class can declare the outer type it must live under. Checking it here
|
|
149
|
+
// turns an engine assertion into an answer.
|
|
150
|
+
if (Class->ClassWithin && !Outer->IsA(Class->ClassWithin))
|
|
151
|
+
{
|
|
152
|
+
return MCPClassUnusableError(ClassName, Class, TEXT("class_within"), FString::Printf(
|
|
153
|
+
TEXT("it must be created inside a %s, and the chosen outer '%s' is a %s. Try the other 'outer' value."),
|
|
154
|
+
*Class->ClassWithin->GetName(), *Outer->GetPathName(), *Outer->GetClass()->GetName()));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const FName SubobjectName(*Name);
|
|
158
|
+
const FString OnConflict = OptionalString(Params, TEXT("onConflict"), TEXT("reuse")).ToLower();
|
|
159
|
+
if (OnConflict != TEXT("reuse") && OnConflict != TEXT("error"))
|
|
160
|
+
{
|
|
161
|
+
return MCPError(FString::Printf(
|
|
162
|
+
TEXT("'onConflict' must be 'reuse' (default) or 'error', got '%s'."), *OnConflict));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const TSharedPtr<FJsonObject>* PropertiesField = nullptr;
|
|
166
|
+
TSharedPtr<FJsonObject> Properties;
|
|
167
|
+
if (Params->TryGetObjectField(TEXT("properties"), PropertiesField) && PropertiesField && (*PropertiesField).IsValid())
|
|
168
|
+
{
|
|
169
|
+
Properties = *PropertiesField;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Every property is applied to a throwaway instance first, so a bad path or
|
|
173
|
+
// a bad value rejects the call before the target package is touched. This
|
|
174
|
+
// is the same preflight bulk_upsert_data_assets uses.
|
|
175
|
+
if (Properties.IsValid() && Properties->Values.Num() > 0)
|
|
176
|
+
{
|
|
177
|
+
UObject* Probe = NewObject<UObject>(GetTransientPackage(), Class, NAME_None, RF_Transient);
|
|
178
|
+
if (!Probe)
|
|
179
|
+
{
|
|
180
|
+
return MCPError(FString::Printf(
|
|
181
|
+
TEXT("Could not instantiate '%s' even in the transient package."), *Class->GetPathName()));
|
|
182
|
+
}
|
|
183
|
+
const FGCRootScope KeepProbeAlive(Probe);
|
|
184
|
+
|
|
185
|
+
TArray<FString> ProbeApplied;
|
|
186
|
+
TArray<FString> ProbeErrors;
|
|
187
|
+
MCPApplySubobjectProperties(Probe, Properties, ProbeApplied, ProbeErrors);
|
|
188
|
+
if (ProbeErrors.Num() > 0)
|
|
189
|
+
{
|
|
190
|
+
TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
|
|
191
|
+
Obj->SetBoolField(TEXT("success"), false);
|
|
192
|
+
Obj->SetStringField(TEXT("error"), FString::Printf(
|
|
193
|
+
TEXT("%d of %d properties would not apply to a %s, so nothing was created: %s"),
|
|
194
|
+
ProbeErrors.Num(), Properties->Values.Num(), *Class->GetName(),
|
|
195
|
+
*FString::Join(ProbeErrors, TEXT("; "))));
|
|
196
|
+
Obj->SetStringField(TEXT("reason"), TEXT("property_preflight_failed"));
|
|
197
|
+
Obj->SetArrayField(TEXT("propertyErrors"), MCPSubobjectStringsToJson(ProbeErrors));
|
|
198
|
+
return MakeShared<FJsonValueObject>(Obj);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
auto Result = MCPSuccess();
|
|
203
|
+
Result->SetStringField(TEXT("assetPath"), AssetPath);
|
|
204
|
+
Result->SetStringField(TEXT("name"), Name);
|
|
205
|
+
Result->SetStringField(TEXT("className"), Class->GetName());
|
|
206
|
+
Result->SetStringField(TEXT("classPath"), Class->GetPathName());
|
|
207
|
+
Result->SetStringField(TEXT("outer"), OuterSpec);
|
|
208
|
+
Result->SetStringField(TEXT("outerPath"), Outer->GetPathName());
|
|
209
|
+
Result->SetStringField(TEXT("packageName"), OwnerPackage->GetName());
|
|
210
|
+
|
|
211
|
+
UObject* Subobject = StaticFindObjectFast(UObject::StaticClass(), Outer, SubobjectName);
|
|
212
|
+
const bool bExisted = Subobject != nullptr;
|
|
213
|
+
if (bExisted)
|
|
214
|
+
{
|
|
215
|
+
if (OnConflict == TEXT("error"))
|
|
216
|
+
{
|
|
217
|
+
return MCPError(FString::Printf(
|
|
218
|
+
TEXT("A subobject named '%s' already exists at '%s' (a %s). Pass onConflict='reuse' to configure it in place."),
|
|
219
|
+
*Name, *Subobject->GetPathName(), *Subobject->GetClass()->GetName()));
|
|
220
|
+
}
|
|
221
|
+
if (Subobject->GetClass() != Class)
|
|
222
|
+
{
|
|
223
|
+
return MCPError(FString::Printf(
|
|
224
|
+
TEXT("'%s' already exists as a %s, not a %s. Pick another name, or address the existing object directly."),
|
|
225
|
+
*Subobject->GetPathName(), *Subobject->GetClass()->GetName(), *Class->GetName()));
|
|
226
|
+
}
|
|
227
|
+
MCPSetExisted(Result);
|
|
228
|
+
}
|
|
229
|
+
else
|
|
230
|
+
{
|
|
231
|
+
OwnerAsset->Modify();
|
|
232
|
+
// #975: RF_Standalone is what keeps the object alive with nothing
|
|
233
|
+
// referencing it yet, and what makes the save below harvest it as a
|
|
234
|
+
// package export. RF_Public lets the struct array that will reference
|
|
235
|
+
// it hold an ordinary object reference rather than an instanced one.
|
|
236
|
+
Subobject = NewObject<UObject>(
|
|
237
|
+
Outer, Class, SubobjectName, RF_Public | RF_Standalone | RF_Transactional);
|
|
238
|
+
if (!Subobject)
|
|
239
|
+
{
|
|
240
|
+
return MCPError(FString::Printf(
|
|
241
|
+
TEXT("Could not create a '%s' named '%s' inside '%s'."),
|
|
242
|
+
*Class->GetPathName(), *Name, *Outer->GetPathName()));
|
|
243
|
+
}
|
|
244
|
+
MCPSetCreated(Result);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Belt and braces for the window between this call and the next one: the
|
|
248
|
+
// object is rooted for the rest of this handler, and standalone plus saved
|
|
249
|
+
// after it.
|
|
250
|
+
const FGCRootScope KeepSubobjectAlive(Subobject);
|
|
251
|
+
|
|
252
|
+
TArray<FString> Applied;
|
|
253
|
+
TArray<FString> PropertyErrors;
|
|
254
|
+
if (Properties.IsValid())
|
|
255
|
+
{
|
|
256
|
+
Subobject->Modify();
|
|
257
|
+
MCPApplySubobjectProperties(Subobject, Properties, Applied, PropertyErrors);
|
|
258
|
+
Subobject->PostEditChange();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
Result->SetStringField(TEXT("objectPath"), Subobject->GetPathName());
|
|
262
|
+
Result->SetArrayField(TEXT("propertiesSet"), MCPSubobjectStringsToJson(Applied));
|
|
263
|
+
if (PropertyErrors.Num() > 0)
|
|
264
|
+
{
|
|
265
|
+
Result->SetArrayField(TEXT("propertyErrors"), MCPSubobjectStringsToJson(PropertyErrors));
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
OwnerAsset->PostEditChange();
|
|
269
|
+
OwnerPackage->MarkPackageDirty();
|
|
270
|
+
|
|
271
|
+
// Saving in the same call is what closes the garbage-collection window the
|
|
272
|
+
// issue is about: after this the subobject is an export on disk, so a later
|
|
273
|
+
// call resolves it by path even if the in-memory copy is collected.
|
|
274
|
+
const bool bSave = OptionalBool(Params, TEXT("save"), true);
|
|
275
|
+
bool bPersisted = false;
|
|
276
|
+
FString PersistReason;
|
|
277
|
+
if (bSave)
|
|
278
|
+
{
|
|
279
|
+
bPersisted = SaveAssetPackage(OwnerAsset);
|
|
280
|
+
if (!bPersisted)
|
|
281
|
+
{
|
|
282
|
+
PersistReason = FString::Printf(
|
|
283
|
+
TEXT("The editor refused to write '%s'. The subobject exists in memory and is kept alive, but it is not on disk yet."),
|
|
284
|
+
*OwnerPackage->GetName());
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
else
|
|
288
|
+
{
|
|
289
|
+
PersistReason = FString::Printf(
|
|
290
|
+
TEXT("save=false was requested, so '%s' is dirty in memory only. The subobject survives garbage collection while the editor runs, but it is not on disk until the package is saved."),
|
|
291
|
+
*OwnerPackage->GetName());
|
|
292
|
+
}
|
|
293
|
+
Result->SetBoolField(TEXT("persisted"), bPersisted);
|
|
294
|
+
Result->SetBoolField(TEXT("saved"), bPersisted);
|
|
295
|
+
Result->SetBoolField(TEXT("packageDirty"), OwnerPackage->IsDirty());
|
|
296
|
+
if (!bPersisted)
|
|
297
|
+
{
|
|
298
|
+
Result->SetStringField(TEXT("persistError"), PersistReason);
|
|
299
|
+
if (bSave)
|
|
300
|
+
{
|
|
301
|
+
Result->SetBoolField(TEXT("success"), false);
|
|
302
|
+
Result->SetStringField(TEXT("error"), PersistReason);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (PropertyErrors.Num() > 0)
|
|
307
|
+
{
|
|
308
|
+
// The preflight passed and the write did not, which means the object is
|
|
309
|
+
// half configured. Loud, not a footnote.
|
|
310
|
+
Result->SetBoolField(TEXT("success"), false);
|
|
311
|
+
Result->SetStringField(TEXT("error"), FString::Printf(
|
|
312
|
+
TEXT("Created '%s' but %d propert%s would not apply: %s"),
|
|
313
|
+
*Subobject->GetPathName(), PropertyErrors.Num(),
|
|
314
|
+
PropertyErrors.Num() == 1 ? TEXT("y") : TEXT("ies"),
|
|
315
|
+
*FString::Join(PropertyErrors, TEXT("; "))));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return MCPResult(Result);
|
|
319
|
+
}
|
package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
namespace
|
|
31
31
|
{
|
|
32
|
-
USoundNode*
|
|
32
|
+
USoundNode* FindSoundCueNodeByName(USoundCue* Cue, const FString& NodeName)
|
|
33
33
|
{
|
|
34
34
|
#if WITH_EDITORONLY_DATA
|
|
35
35
|
for (USoundNode* N : Cue->AllNodes)
|
|
@@ -121,7 +121,7 @@ TSharedPtr<FJsonValue> FAudioHandlers::SoundCueConnect(const TSharedPtr<FJsonObj
|
|
|
121
121
|
USoundCue* Cue = Cast<USoundCue>(UEditorAssetLibrary::LoadAsset(CuePath));
|
|
122
122
|
if (!Cue) return MCPError(FString::Printf(TEXT("SoundCue not found: %s"), *CuePath));
|
|
123
123
|
|
|
124
|
-
USoundNode* Child =
|
|
124
|
+
USoundNode* Child = FindSoundCueNodeByName(Cue, ChildNodeId);
|
|
125
125
|
if (!Child) return MCPError(FString::Printf(TEXT("Child node '%s' not found in cue."), *ChildNodeId));
|
|
126
126
|
|
|
127
127
|
const FString ParentNodeId = OptionalString(Params, TEXT("parentNodeId"));
|
|
@@ -132,7 +132,7 @@ TSharedPtr<FJsonValue> FAudioHandlers::SoundCueConnect(const TSharedPtr<FJsonObj
|
|
|
132
132
|
}
|
|
133
133
|
else
|
|
134
134
|
{
|
|
135
|
-
USoundNode* Parent =
|
|
135
|
+
USoundNode* Parent = FindSoundCueNodeByName(Cue, ParentNodeId);
|
|
136
136
|
if (!Parent) return MCPError(FString::Printf(TEXT("Parent node '%s' not found in cue."), *ParentNodeId));
|
|
137
137
|
|
|
138
138
|
int32 Index = Params->HasField(TEXT("childIndex"))
|