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.
Files changed (243) hide show
  1. package/README.md +4 -3
  2. package/dist/action-class.js +56 -3
  3. package/dist/action-class.js.map +1 -1
  4. package/dist/bridge-timeouts.d.ts +64 -0
  5. package/dist/bridge-timeouts.js +118 -0
  6. package/dist/bridge-timeouts.js.map +1 -0
  7. package/dist/bridge.js +10 -2
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/editor-control.d.ts +72 -5
  10. package/dist/editor-control.js +164 -140
  11. package/dist/editor-control.js.map +1 -1
  12. package/dist/editor-target.d.ts +55 -1
  13. package/dist/editor-target.js +107 -10
  14. package/dist/editor-target.js.map +1 -1
  15. package/dist/engine-observer.d.ts +59 -5
  16. package/dist/engine-observer.js +249 -29
  17. package/dist/engine-observer.js.map +1 -1
  18. package/dist/engine-root.d.ts +91 -0
  19. package/dist/engine-root.js +448 -0
  20. package/dist/engine-root.js.map +1 -0
  21. package/dist/epic-enrich.js +16 -1
  22. package/dist/epic-enrich.js.map +1 -1
  23. package/dist/feedback-cli.js +4 -0
  24. package/dist/feedback-cli.js.map +1 -1
  25. package/dist/feedback-deferred.d.ts +9 -0
  26. package/dist/feedback-deferred.js +2 -0
  27. package/dist/feedback-deferred.js.map +1 -1
  28. package/dist/feedback-fallback.d.ts +99 -0
  29. package/dist/feedback-fallback.js +173 -0
  30. package/dist/feedback-fallback.js.map +1 -0
  31. package/dist/flow/write-methods.js +20 -0
  32. package/dist/flow/write-methods.js.map +1 -1
  33. package/dist/lean-context.js +8 -3
  34. package/dist/lean-context.js.map +1 -1
  35. package/dist/locking.js +11 -2
  36. package/dist/locking.js.map +1 -1
  37. package/dist/project.d.ts +11 -0
  38. package/dist/project.js +23 -2
  39. package/dist/project.js.map +1 -1
  40. package/dist/python-gate.d.ts +95 -0
  41. package/dist/python-gate.js +175 -0
  42. package/dist/python-gate.js.map +1 -0
  43. package/dist/tool-counts.json +16 -16
  44. package/dist/tools/animation.js +288 -24
  45. package/dist/tools/animation.js.map +1 -1
  46. package/dist/tools/asset.js +79 -14
  47. package/dist/tools/asset.js.map +1 -1
  48. package/dist/tools/audio.js +59 -5
  49. package/dist/tools/audio.js.map +1 -1
  50. package/dist/tools/blueprint.js +29 -12
  51. package/dist/tools/blueprint.js.map +1 -1
  52. package/dist/tools/chooser.js +4 -1
  53. package/dist/tools/chooser.js.map +1 -1
  54. package/dist/tools/editor.js +81 -43
  55. package/dist/tools/editor.js.map +1 -1
  56. package/dist/tools/feedback.js +214 -48
  57. package/dist/tools/feedback.js.map +1 -1
  58. package/dist/tools/foliage.js +27 -1
  59. package/dist/tools/foliage.js.map +1 -1
  60. package/dist/tools/gameplay.js +38 -11
  61. package/dist/tools/gameplay.js.map +1 -1
  62. package/dist/tools/gas.js +17 -5
  63. package/dist/tools/gas.js.map +1 -1
  64. package/dist/tools/landscape.js +22 -7
  65. package/dist/tools/landscape.js.map +1 -1
  66. package/dist/tools/level.js +322 -51
  67. package/dist/tools/level.js.map +1 -1
  68. package/dist/tools/material.js +10 -4
  69. package/dist/tools/material.js.map +1 -1
  70. package/dist/tools/niagara.js +3 -2
  71. package/dist/tools/niagara.js.map +1 -1
  72. package/dist/tools/pcg.js +6 -5
  73. package/dist/tools/pcg.js.map +1 -1
  74. package/dist/tools/project.js +47 -20
  75. package/dist/tools/project.js.map +1 -1
  76. package/dist/types.d.ts +21 -0
  77. package/dist/types.js +46 -3
  78. package/dist/types.js.map +1 -1
  79. package/dist/ue-mcp.default.yml +493 -125
  80. package/package.json +2 -2
  81. package/plugin/ue_mcp_bridge/NATIVE_RUNTIME_VISIBILITY.md +53 -0
  82. package/plugin/ue_mcp_bridge/NATIVE_STATIC_MESH_USAGE_PROGRESS.md +115 -0
  83. package/plugin/ue_mcp_bridge/README_MassHandlers.md +97 -0
  84. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +14 -0
  85. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +21 -4
  86. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
  87. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +395 -69
  88. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +79 -3
  89. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +25 -0
  90. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +3 -3
  91. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRigSequencer.cpp +3061 -0
  92. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRetargeterAuthoring.cpp +961 -0
  93. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRigAuthoring.cpp +900 -0
  94. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Pose.cpp +769 -0
  95. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +44 -3
  96. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_SkeletalLive.cpp +217 -11
  97. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +551 -24
  98. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Validation.cpp +735 -0
  99. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +352 -73
  100. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +8 -0
  101. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkProperties.cpp +1 -1
  102. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.cpp +503 -0
  103. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.h +21 -0
  104. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkUpsert.cpp +2 -2
  105. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Enum.cpp +2 -2
  106. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.cpp +902 -0
  107. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.h +33 -0
  108. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +478 -134
  109. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +5 -5
  110. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.cpp +933 -0
  111. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.h +35 -0
  112. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp +478 -0
  113. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp +1 -1
  114. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +4 -4
  115. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +2 -2
  116. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp +319 -0
  117. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp +3 -3
  118. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +482 -35
  119. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +10 -0
  120. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.cpp +502 -0
  121. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.h +43 -0
  122. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +89 -7
  123. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +17 -51
  124. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +107 -0
  125. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +10 -10
  126. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Search.cpp +648 -0
  127. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +5 -1
  128. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.cpp +252 -1
  129. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.h +10 -2
  130. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +252 -41
  131. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +4 -0
  132. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +250 -27
  133. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +303 -125
  134. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +73 -50
  135. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_RuntimeVisibility.cpp +757 -0
  136. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +11 -2
  137. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +3 -0
  138. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Batch.cpp +419 -0
  139. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +39 -161
  140. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +66 -1
  141. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTAuthoring.cpp +1323 -0
  142. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BehaviorTree.cpp +1211 -0
  143. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +2 -0
  144. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +60 -0
  145. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Runtime.cpp +363 -12
  146. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/HandlerEditorState.h +84 -0
  147. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +1288 -36
  148. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +3 -0
  149. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +41 -16
  150. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +959 -213
  151. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +66 -0
  152. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_BatchWrite.cpp +1571 -0
  153. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Convert.cpp +316 -0
  154. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Inspection.cpp +280 -0
  155. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection.cpp +666 -0
  156. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection_Internal.h +63 -0
  157. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +43 -12
  158. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +13 -47
  159. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_PostProcess.cpp +527 -0
  160. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Query.cpp +1169 -0
  161. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Refresh.cpp +723 -0
  162. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Save.cpp +325 -0
  163. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Spatial.cpp +360 -0
  164. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Trace.cpp +178 -58
  165. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Transient.cpp +337 -0
  166. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Volumes.cpp +25 -12
  167. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +10 -9
  168. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartitionSettings.cpp +686 -0
  169. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.cpp +467 -0
  170. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.h +22 -0
  171. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +452 -175
  172. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +5 -0
  173. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Build.cpp +597 -0
  174. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +17 -15
  175. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +38 -168
  176. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +39 -30
  177. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +392 -78
  178. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +2 -0
  179. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers_Internal.h +83 -0
  180. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.cpp +200 -0
  181. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.h +15 -0
  182. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +19 -12
  183. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.cpp +31 -1
  184. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +307 -69
  185. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +84 -0
  186. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +8 -41
  187. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +33 -52
  188. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/ActorSelectorTests.cpp +344 -0
  189. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationControlRigTimelineTests.cpp +60 -0
  190. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationPoseTests.cpp +115 -0
  191. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetBulkReadTests.cpp +177 -0
  192. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetDeleteGuardTests.cpp +276 -0
  193. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPathResolutionTests.cpp +243 -0
  194. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPropertyPersistTests.cpp +213 -0
  195. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetSubobjectTests.cpp +235 -0
  196. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AutomationRunnerTests.cpp +72 -0
  197. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeAuthoringTests.cpp +526 -0
  198. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeNodeTests.cpp +334 -0
  199. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BlueprintHandlerSurfaceTests.cpp +362 -0
  200. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BridgeProtocolTests.cpp +14 -0
  201. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/CollisionQueryTests.cpp +288 -0
  202. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/DataTableRowWriteTests.cpp +453 -0
  203. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/EditorFunctionCallTests.cpp +223 -0
  204. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/FoliageBatchTests.cpp +147 -0
  205. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GameThreadGateTests.cpp +82 -0
  206. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GasLiveAttributeTests.cpp +183 -0
  207. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LandscapeSampleTests.cpp +119 -0
  208. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelBatchWriteTests.cpp +176 -0
  209. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelComponentTreeInstanceCountTests.cpp +189 -0
  210. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelConvertBrushesTests.cpp +100 -0
  211. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelInstanceProjectionTests.cpp +265 -0
  212. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelPostProcessOverrideTests.cpp +258 -0
  213. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelQueryComponentsTests.cpp +195 -0
  214. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelRefreshTests.cpp +142 -0
  215. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelSaveReportTests.cpp +125 -0
  216. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelScriptHandlersTests.cpp +42 -0
  217. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelStaticMeshUsageTests.cpp +412 -0
  218. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTraceWorldScopeTests.cpp +133 -0
  219. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTransientActorTests.cpp +205 -0
  220. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelWorldPartitionSettingsTests.cpp +168 -0
  221. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTestTypes.h +51 -0
  222. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTests.cpp +379 -0
  223. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MaterialBuildTests.cpp +238 -0
  224. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshBooleanTests.cpp +170 -0
  225. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshGeometryTests.cpp +116 -0
  226. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageSaveExtensionTests.cpp +161 -0
  227. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageWriteGuardTests.cpp +253 -0
  228. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/RuntimeVisibilityTests.cpp +143 -0
  229. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerHandlerTests.cpp +660 -0
  230. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerScrubTests.cpp +50 -0
  231. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SkeletonDiffTests.cpp +685 -0
  232. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/WidgetBlueprintResolveTests.cpp +145 -0
  233. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +80 -0
  234. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerFunctionCall.h +509 -0
  235. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerQuery.h +407 -0
  236. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +1008 -77
  237. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
  238. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/MCPEngineStatus.cpp +152 -14
  239. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/Tests/MCPEngineStatusTests.cpp +65 -0
  240. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Public/MCPEngineStatus.h +32 -1
  241. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/UE_MCP_BridgeStatus.Build.cs +2 -0
  242. package/skills/ue-mcp-animation/SKILL.md +154 -0
  243. package/skills/ue-mcp-blueprint/SKILL.md +71 -0
@@ -0,0 +1,253 @@
1
+ // Regression coverage for #932.
2
+ //
3
+ // blueprint(reparent) reparents, recompiles AND saves, and the save is not
4
+ // optional. A .uasset that was never checked out of source control is read-only
5
+ // on disk; asking the engine to write it turned the failed save into a FATAL
6
+ // error that took the whole editor process down. The asset was undamaged and
7
+ // the call replayed cleanly after a checkout, so the only thing missing was the
8
+ // question asked here: can this package be written at all.
9
+ //
10
+ // The answer lives in one place, MCPPackageWriteBlocked, and SaveAssetPackage
11
+ // asks it before handing the file to UPackage::SavePackage. That is what makes
12
+ // the crash unreachable from every handler that saves as a side effect, not
13
+ // just from reparent. These assertions cover the guard itself and the three
14
+ // shapes built on it.
15
+ //
16
+ // The exercise happens under a private mount point in the system temp area:
17
+ // run_automation_tests dispatches every EditorContext test against whatever
18
+ // project the bridge is attached to, and nothing here may touch it.
19
+
20
+ #if WITH_DEV_AUTOMATION_TESTS
21
+
22
+ #include "HandlerUtils.h"
23
+
24
+ #include "Dom/JsonObject.h"
25
+ #include "Dom/JsonValue.h"
26
+ #include "Engine/DataTable.h"
27
+ #include "HAL/FileManager.h"
28
+ #include "HAL/PlatformFileManager.h"
29
+ #include "HAL/PlatformProcess.h"
30
+ #include "Misc/AutomationTest.h"
31
+ #include "Misc/Guid.h"
32
+ #include "Misc/PackageName.h"
33
+ #include "Misc/Paths.h"
34
+ #include "UObject/Package.h"
35
+ #include "UObject/PerPlatformProperties.h"
36
+
37
+ namespace
38
+ {
39
+ const TCHAR* const MCPWriteGuardTestRoot = TEXT("/UEMCPPackageWriteGuardTest/");
40
+
41
+ struct FScopedWriteGuardMount
42
+ {
43
+ FString RootPath;
44
+ FString ContentPath;
45
+
46
+ FScopedWriteGuardMount()
47
+ : RootPath(MCPWriteGuardTestRoot)
48
+ , ContentPath(FPaths::Combine(
49
+ FPaths::ConvertRelativePathToFull(FString(FPlatformProcess::UserTempDir())),
50
+ FString(TEXT("UEMCPPackageWriteGuardTest")),
51
+ FGuid::NewGuid().ToString(EGuidFormats::Digits)))
52
+ {
53
+ IFileManager::Get().MakeDirectory(*ContentPath, /*Tree=*/true);
54
+ FPackageName::RegisterMountPoint(RootPath, ContentPath);
55
+ }
56
+
57
+ ~FScopedWriteGuardMount()
58
+ {
59
+ FPackageName::UnRegisterMountPoint(RootPath, ContentPath);
60
+ IFileManager::Get().DeleteDirectory(*ContentPath, /*RequireExists=*/false, /*Tree=*/true);
61
+ }
62
+
63
+ FScopedWriteGuardMount(const FScopedWriteGuardMount&) = delete;
64
+ FScopedWriteGuardMount& operator=(const FScopedWriteGuardMount&) = delete;
65
+ };
66
+
67
+ /** Clear the read-only bit again however the test leaves, so the temp
68
+ * directory can be deleted on the way out. */
69
+ struct FScopedReadOnlyFile
70
+ {
71
+ FString FileName;
72
+ bool bApplied = false;
73
+
74
+ explicit FScopedReadOnlyFile(const FString& InFileName)
75
+ : FileName(InFileName)
76
+ {
77
+ bApplied = FPlatformFileManager::Get().GetPlatformFile().SetReadOnly(*FileName, true);
78
+ }
79
+
80
+ ~FScopedReadOnlyFile()
81
+ {
82
+ if (bApplied)
83
+ {
84
+ FPlatformFileManager::Get().GetPlatformFile().SetReadOnly(*FileName, false);
85
+ }
86
+ }
87
+
88
+ FScopedReadOnlyFile(const FScopedReadOnlyFile&) = delete;
89
+ FScopedReadOnlyFile& operator=(const FScopedReadOnlyFile&) = delete;
90
+ };
91
+ }
92
+
93
+ IMPLEMENT_SIMPLE_AUTOMATION_TEST(
94
+ FMCPReadOnlyPackageIsRefusedNotWrittenTest,
95
+ "UE.MCP.Asset.Save.ReadOnlyPackageIsRefusedBeforeTheWrite",
96
+ EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
97
+
98
+ bool FMCPReadOnlyPackageIsRefusedNotWrittenTest::RunTest(const FString& Parameters)
99
+ {
100
+ const FScopedWriteGuardMount Mount;
101
+
102
+ const FString PackageName = FString(MCPWriteGuardTestRoot) + TEXT("DT_WriteGuardProbe");
103
+ UPackage* Package = CreatePackage(*PackageName);
104
+ if (!TestNotNull(TEXT("probe package created"), Package)) return false;
105
+
106
+ UDataTable* Probe = NewObject<UDataTable>(
107
+ Package, FName(TEXT("DT_WriteGuardProbe")), RF_Public | RF_Standalone);
108
+ if (!TestNotNull(TEXT("probe asset created"), Probe))
109
+ {
110
+ Package->SetDirtyFlag(false);
111
+ return false;
112
+ }
113
+ Probe->RowStruct = FPerPlatformInt::StaticStruct();
114
+ const FGCRootScope KeepProbeAlive(Probe);
115
+
116
+ // A writable package is not blocked, and the first save is what puts a file
117
+ // on disk for the read-only half below to act on.
118
+ {
119
+ FString Reason;
120
+ TestFalse(TEXT("a writable package is not blocked"), MCPPackageWriteBlocked(Probe, Reason));
121
+ TestTrue(TEXT("no reason is given when nothing is blocked"), Reason.IsEmpty());
122
+ TestTrue(TEXT("the writable package saves"), SaveAssetPackage(Probe));
123
+ }
124
+
125
+ FString PackageFileName;
126
+ if (!TestTrue(TEXT("the probe package resolves to a file"),
127
+ ResolvePackageFileName(Package, PackageFileName)))
128
+ {
129
+ Package->SetDirtyFlag(false);
130
+ return false;
131
+ }
132
+ if (!TestTrue(TEXT("the probe package file exists on disk"),
133
+ IFileManager::Get().FileExists(*PackageFileName)))
134
+ {
135
+ Package->SetDirtyFlag(false);
136
+ return false;
137
+ }
138
+
139
+ {
140
+ const FScopedReadOnlyFile ReadOnly(PackageFileName);
141
+ if (!TestTrue(TEXT("the probe package file could be made read-only"), ReadOnly.bApplied))
142
+ {
143
+ Package->SetDirtyFlag(false);
144
+ return false;
145
+ }
146
+
147
+ FString Reason;
148
+ TestTrue(TEXT("a read-only package is blocked"), MCPPackageWriteBlocked(Probe, Reason));
149
+ TestTrue(TEXT("the block names the file on disk"), Reason.Contains(PackageFileName));
150
+ TestTrue(TEXT("the block says what to do about it"),
151
+ Reason.Contains(TEXT("read-only")));
152
+
153
+ // The #932 assertion. Before the guard this call reached
154
+ // UPackage::SavePackage on a file it could not open, and the process
155
+ // went down with it. A false is the whole point.
156
+ TestFalse(TEXT("saving a read-only package returns false rather than killing the editor"),
157
+ SaveAssetPackage(Probe));
158
+
159
+ FString CheckedReason;
160
+ TestFalse(TEXT("the checked save agrees"), SaveAssetPackageChecked(Probe, CheckedReason));
161
+ TestFalse(TEXT("the checked save carries the reason"), CheckedReason.IsEmpty());
162
+
163
+ // The refusal a handler returns instead of mutating anything.
164
+ const TSharedPtr<FJsonValue> Blocked =
165
+ MCPAssetWriteBlockedError(Probe, PackageName, TEXT("reparent this Blueprint"));
166
+ if (TestTrue(TEXT("a blocked write produces a refusal"), Blocked.IsValid()))
167
+ {
168
+ const TSharedPtr<FJsonObject> Obj = Blocked->AsObject();
169
+ if (TestTrue(TEXT("the refusal is an object"), Obj.IsValid()))
170
+ {
171
+ bool bSuccess = true;
172
+ Obj->TryGetBoolField(TEXT("success"), bSuccess);
173
+ TestFalse(TEXT("the refusal is not a success"), bSuccess);
174
+
175
+ FString ReasonField;
176
+ Obj->TryGetStringField(TEXT("reason"), ReasonField);
177
+ TestEqual(TEXT("the refusal names the cause"),
178
+ ReasonField, FString(TEXT("package_not_writable")));
179
+
180
+ FString ErrorField;
181
+ Obj->TryGetStringField(TEXT("error"), ErrorField);
182
+ TestTrue(TEXT("the refusal names the operation the caller asked for"),
183
+ ErrorField.Contains(TEXT("reparent this Blueprint")));
184
+ TestTrue(TEXT("the refusal says nothing was changed"),
185
+ ErrorField.Contains(TEXT("Nothing was changed")));
186
+ }
187
+ }
188
+ }
189
+
190
+ // With the read-only bit cleared again the same package writes, so the
191
+ // guard gates on the file's actual state rather than latching.
192
+ {
193
+ FString Reason;
194
+ TestFalse(TEXT("a package that is writable again is not blocked"),
195
+ MCPPackageWriteBlocked(Probe, Reason));
196
+ TestTrue(TEXT("the package saves once it is writable again"), SaveAssetPackage(Probe));
197
+ }
198
+
199
+ Package->SetDirtyFlag(false);
200
+ return true;
201
+ }
202
+
203
+ IMPLEMENT_SIMPLE_AUTOMATION_TEST(
204
+ FMCPSaveOutcomeIsReportedTest,
205
+ "UE.MCP.Asset.Save.AnUnwrittenSaveIsReportedAsAFailure",
206
+ EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
207
+
208
+ bool FMCPSaveOutcomeIsReportedTest::RunTest(const FString& Parameters)
209
+ {
210
+ // A save that did not reach disk used to read as a plain success, and the
211
+ // caller's next read came off the in-memory object and looked correct right
212
+ // up until the editor restarted.
213
+ {
214
+ TSharedPtr<FJsonObject> Result = MCPSuccess();
215
+ MCPNoteSaveOutcome(Result, TEXT("/Game/Probe/BP_Thing"), /*bSaved=*/true, FString());
216
+
217
+ bool bSaved = false;
218
+ Result->TryGetBoolField(TEXT("saved"), bSaved);
219
+ TestTrue(TEXT("a written save is reported as saved"), bSaved);
220
+
221
+ bool bSuccess = false;
222
+ Result->TryGetBoolField(TEXT("success"), bSuccess);
223
+ TestTrue(TEXT("a written save stays a success"), bSuccess);
224
+
225
+ TestFalse(TEXT("a written save adds no error"), Result->HasField(TEXT("saveError")));
226
+ }
227
+
228
+ {
229
+ TSharedPtr<FJsonObject> Result = MCPSuccess();
230
+ MCPNoteSaveOutcome(Result, TEXT("/Game/Probe/BP_Thing"), /*bSaved=*/false,
231
+ TEXT("'D:/Probe/BP_Thing.uasset' is read-only on disk."));
232
+
233
+ bool bSaved = true;
234
+ Result->TryGetBoolField(TEXT("saved"), bSaved);
235
+ TestFalse(TEXT("an unwritten save is reported as unsaved"), bSaved);
236
+
237
+ bool bSuccess = true;
238
+ Result->TryGetBoolField(TEXT("success"), bSuccess);
239
+ TestFalse(TEXT("an unwritten save is not a success"), bSuccess);
240
+
241
+ FString SaveError;
242
+ Result->TryGetStringField(TEXT("saveError"), SaveError);
243
+ TestTrue(TEXT("an unwritten save carries the reason"), SaveError.Contains(TEXT("read-only")));
244
+
245
+ FString Error;
246
+ Result->TryGetStringField(TEXT("error"), Error);
247
+ TestTrue(TEXT("the error names the asset"), Error.Contains(TEXT("/Game/Probe/BP_Thing")));
248
+ }
249
+
250
+ return true;
251
+ }
252
+
253
+ #endif
@@ -0,0 +1,143 @@
1
+ // Safe preflight coverage for the live PIE visibility batch.
2
+ //
3
+ // These Automation tests may run inside a user's editor, so they deliberately
4
+ // stop before resolving or mutating a live PIE world. Runtime state transitions
5
+ // belong in the dedicated bridge smoke project.
6
+
7
+ #if WITH_DEV_AUTOMATION_TESTS
8
+
9
+ #include "HandlerRegistry.h"
10
+ #include "Handlers/EditorHandlers.h"
11
+ #include "Misc/AutomationTest.h"
12
+
13
+ IMPLEMENT_SIMPLE_AUTOMATION_TEST(
14
+ FRuntimeVisibilityPreflightTest,
15
+ "UE.MCP.Editor.RuntimeVisibility.RegistrationAndPreflight",
16
+ EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
17
+
18
+ bool FRuntimeVisibilityPreflightTest::RunTest(const FString& Parameters)
19
+ {
20
+ FMCPHandlerRegistry Registry;
21
+ FEditorHandlers::RegisterHandlers(Registry);
22
+ TestTrue(TEXT("set handler is registered"), Registry.HasHandler(TEXT("set_runtime_visibility")));
23
+ TestTrue(TEXT("restore handler is registered"), Registry.HasHandler(TEXT("restore_runtime_visibility")));
24
+ const TArray<FString> HandlerNames = Registry.GetHandlerNames();
25
+ TestTrue(TEXT("set handler is capability-discoverable"),
26
+ HandlerNames.Contains(TEXT("set_runtime_visibility")));
27
+ TestTrue(TEXT("restore handler is capability-discoverable"),
28
+ HandlerNames.Contains(TEXT("restore_runtime_visibility")));
29
+
30
+ auto ExpectFailure = [this, &Registry](
31
+ const TCHAR* Description,
32
+ const TCHAR* Method,
33
+ const TSharedPtr<FJsonObject>& Request,
34
+ const TCHAR* ExpectedText)
35
+ {
36
+ const TSharedPtr<FJsonValue> Response = Registry.ExecuteHandler(Method, Request);
37
+ TestTrue(FString::Printf(TEXT("%s returns an object"), Description),
38
+ Response.IsValid() && Response->Type == EJson::Object);
39
+ if (Response.IsValid() && Response->Type == EJson::Object)
40
+ {
41
+ const TSharedPtr<FJsonObject> Object = Response->AsObject();
42
+ TestFalse(FString::Printf(TEXT("%s is unsuccessful"), Description),
43
+ Object->GetBoolField(TEXT("success")));
44
+ TestTrue(FString::Printf(TEXT("%s explains the rejection"), Description),
45
+ Object->GetStringField(TEXT("error")).Contains(ExpectedText));
46
+ }
47
+ };
48
+
49
+ TSharedPtr<FJsonObject> MissingHidden = MakeShared<FJsonObject>();
50
+ MissingHidden->SetArrayField(TEXT("actorLabels"),
51
+ { MakeShared<FJsonValueString>(TEXT("Example")) });
52
+ ExpectFailure(TEXT("missing hidden"), TEXT("set_runtime_visibility"),
53
+ MissingHidden, TEXT("hidden"));
54
+
55
+ TSharedPtr<FJsonObject> EditorWorld = MakeShared<FJsonObject>();
56
+ EditorWorld->SetBoolField(TEXT("hidden"), true);
57
+ EditorWorld->SetStringField(TEXT("world"), TEXT("editor"));
58
+ EditorWorld->SetArrayField(TEXT("actorLabels"),
59
+ { MakeShared<FJsonValueString>(TEXT("Example")) });
60
+ ExpectFailure(TEXT("editor world"), TEXT("set_runtime_visibility"),
61
+ EditorWorld, TEXT("PIE-only"));
62
+
63
+ TSharedPtr<FJsonObject> GameWorld = MakeShared<FJsonObject>();
64
+ GameWorld->SetBoolField(TEXT("hidden"), true);
65
+ GameWorld->SetStringField(TEXT("world"), TEXT("game"));
66
+ GameWorld->SetArrayField(TEXT("actorLabels"),
67
+ { MakeShared<FJsonValueString>(TEXT("Example")) });
68
+ ExpectFailure(TEXT("game world"), TEXT("set_runtime_visibility"),
69
+ GameWorld, TEXT("PIE-only"));
70
+
71
+ TSharedPtr<FJsonObject> FractionalPIEInstance = MakeShared<FJsonObject>();
72
+ FractionalPIEInstance->SetBoolField(TEXT("hidden"), true);
73
+ FractionalPIEInstance->SetStringField(TEXT("actorClass"), TEXT("AActor"));
74
+ FractionalPIEInstance->SetNumberField(TEXT("pieInstance"), 1.5);
75
+ ExpectFailure(TEXT("fractional PIE instance"), TEXT("set_runtime_visibility"),
76
+ FractionalPIEInstance, TEXT("integer"));
77
+
78
+ TSharedPtr<FJsonObject> MissingSelector = MakeShared<FJsonObject>();
79
+ MissingSelector->SetBoolField(TEXT("hidden"), true);
80
+ ExpectFailure(TEXT("missing selector"), TEXT("set_runtime_visibility"),
81
+ MissingSelector, TEXT("exactly one actor selector"));
82
+
83
+ TSharedPtr<FJsonObject> ConflictingSelectors = MakeShared<FJsonObject>();
84
+ ConflictingSelectors->SetBoolField(TEXT("hidden"), true);
85
+ ConflictingSelectors->SetStringField(TEXT("actorClass"), TEXT("Actor"));
86
+ ConflictingSelectors->SetArrayField(TEXT("actorLabels"),
87
+ { MakeShared<FJsonValueString>(TEXT("Example")) });
88
+ ExpectFailure(TEXT("conflicting selectors"), TEXT("set_runtime_visibility"),
89
+ ConflictingSelectors, TEXT("exactly one actor selector"));
90
+
91
+ TSharedPtr<FJsonObject> OversizedLabels = MakeShared<FJsonObject>();
92
+ OversizedLabels->SetBoolField(TEXT("hidden"), true);
93
+ TArray<TSharedPtr<FJsonValue>> Labels;
94
+ for (int32 Index = 0; Index < 65; ++Index)
95
+ {
96
+ Labels.Add(MakeShared<FJsonValueString>(FString::Printf(TEXT("Actor_%d"), Index)));
97
+ }
98
+ OversizedLabels->SetArrayField(TEXT("actorLabels"), Labels);
99
+ ExpectFailure(TEXT("oversized labels"), TEXT("set_runtime_visibility"),
100
+ OversizedLabels, TEXT("64"));
101
+
102
+ TSharedPtr<FJsonObject> OversizedBound = MakeShared<FJsonObject>();
103
+ OversizedBound->SetBoolField(TEXT("hidden"), true);
104
+ OversizedBound->SetNumberField(TEXT("maxTargets"), 257);
105
+ OversizedBound->SetStringField(TEXT("actorClass"), TEXT("Actor"));
106
+ ExpectFailure(TEXT("oversized maxTargets"), TEXT("set_runtime_visibility"),
107
+ OversizedBound, TEXT("256"));
108
+
109
+ TSharedPtr<FJsonObject> NoEffects = MakeShared<FJsonObject>();
110
+ NoEffects->SetBoolField(TEXT("hidden"), true);
111
+ NoEffects->SetStringField(TEXT("actorClass"), TEXT("Actor"));
112
+ NoEffects->SetBoolField(TEXT("affectActor"), false);
113
+ NoEffects->SetBoolField(TEXT("affectComponents"), false);
114
+ ExpectFailure(TEXT("disabled effects"), TEXT("set_runtime_visibility"),
115
+ NoEffects, TEXT("At least one"));
116
+
117
+ TSharedPtr<FJsonObject> UnknownActorClass = MakeShared<FJsonObject>();
118
+ UnknownActorClass->SetBoolField(TEXT("hidden"), true);
119
+ UnknownActorClass->SetStringField(
120
+ TEXT("actorClass"), TEXT("DefinitelyMissingRuntimeVisibilityActor"));
121
+ ExpectFailure(TEXT("unknown actor class"), TEXT("set_runtime_visibility"),
122
+ UnknownActorClass, TEXT("Class not found"));
123
+
124
+ TSharedPtr<FJsonObject> WrongComponentBase = MakeShared<FJsonObject>();
125
+ WrongComponentBase->SetBoolField(TEXT("hidden"), true);
126
+ WrongComponentBase->SetArrayField(TEXT("actorLabels"),
127
+ { MakeShared<FJsonValueString>(TEXT("Example")) });
128
+ WrongComponentBase->SetArrayField(TEXT("componentClasses"),
129
+ { MakeShared<FJsonValueString>(TEXT("AActor")) });
130
+ ExpectFailure(TEXT("wrong component base"), TEXT("set_runtime_visibility"),
131
+ WrongComponentBase, TEXT("does not derive from SceneComponent"));
132
+
133
+ ExpectFailure(TEXT("missing restore token"), TEXT("restore_runtime_visibility"),
134
+ MakeShared<FJsonObject>(), TEXT("rollbackToken"));
135
+
136
+ TSharedPtr<FJsonObject> UnknownRestoreToken = MakeShared<FJsonObject>();
137
+ UnknownRestoreToken->SetStringField(TEXT("rollbackToken"), TEXT("not-a-live-token"));
138
+ ExpectFailure(TEXT("unknown restore token"), TEXT("restore_runtime_visibility"),
139
+ UnknownRestoreToken, TEXT("not found or has expired"));
140
+ return true;
141
+ }
142
+
143
+ #endif