ue-mcp 1.3.0 → 1.3.1-beta.2

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 (301) hide show
  1. package/README.md +5 -3
  2. package/dist/action-class.js +141 -3
  3. package/dist/action-class.js.map +1 -1
  4. package/dist/action-schema.d.ts +157 -0
  5. package/dist/action-schema.js +731 -0
  6. package/dist/action-schema.js.map +1 -0
  7. package/dist/bridge-timeouts.js +23 -0
  8. package/dist/bridge-timeouts.js.map +1 -1
  9. package/dist/bridge.js +28 -11
  10. package/dist/bridge.js.map +1 -1
  11. package/dist/call-pipeline.d.ts +126 -0
  12. package/dist/call-pipeline.js +144 -0
  13. package/dist/call-pipeline.js.map +1 -0
  14. package/dist/content-index.d.ts +41 -0
  15. package/dist/content-index.js +149 -0
  16. package/dist/content-index.js.map +1 -0
  17. package/dist/cpp-correctness.d.ts +165 -0
  18. package/dist/cpp-correctness.js +562 -0
  19. package/dist/cpp-correctness.js.map +1 -0
  20. package/dist/dialog-cli.d.ts +15 -0
  21. package/dist/dialog-cli.js +146 -0
  22. package/dist/dialog-cli.js.map +1 -0
  23. package/dist/editor-control.d.ts +268 -18
  24. package/dist/editor-control.js +789 -54
  25. package/dist/editor-control.js.map +1 -1
  26. package/dist/editor-target.d.ts +31 -0
  27. package/dist/editor-target.js +34 -0
  28. package/dist/editor-target.js.map +1 -1
  29. package/dist/engine-analysis.d.ts +286 -0
  30. package/dist/engine-analysis.js +874 -0
  31. package/dist/engine-analysis.js.map +1 -0
  32. package/dist/engine-index.d.ts +159 -0
  33. package/dist/engine-index.js +496 -0
  34. package/dist/engine-index.js.map +1 -0
  35. package/dist/epic-enrich.js +2 -2
  36. package/dist/epic-enrich.js.map +1 -1
  37. package/dist/field-select.d.ts +57 -0
  38. package/dist/field-select.js +204 -0
  39. package/dist/field-select.js.map +1 -0
  40. package/dist/flow/bridge-task.d.ts +5 -0
  41. package/dist/flow/bridge-task.js +11 -1
  42. package/dist/flow/bridge-task.js.map +1 -1
  43. package/dist/flow/flow-tool.js +207 -34
  44. package/dist/flow/flow-tool.js.map +1 -1
  45. package/dist/flow/guarded-bridge.js +23 -7
  46. package/dist/flow/guarded-bridge.js.map +1 -1
  47. package/dist/flow/handler-outcome.d.ts +97 -0
  48. package/dist/flow/handler-outcome.js +127 -0
  49. package/dist/flow/handler-outcome.js.map +1 -0
  50. package/dist/flow/journal-actions.d.ts +24 -0
  51. package/dist/flow/journal-actions.js +364 -0
  52. package/dist/flow/journal-actions.js.map +1 -0
  53. package/dist/flow/registry.js +18 -2
  54. package/dist/flow/registry.js.map +1 -1
  55. package/dist/flow/schema.d.ts +30 -30
  56. package/dist/flow/skill-actions.d.ts +14 -0
  57. package/dist/flow/skill-actions.js +269 -0
  58. package/dist/flow/skill-actions.js.map +1 -0
  59. package/dist/flow/task-factory.d.ts +9 -3
  60. package/dist/flow/task-factory.js +55 -11
  61. package/dist/flow/task-factory.js.map +1 -1
  62. package/dist/index.js +169 -13
  63. package/dist/index.js.map +1 -1
  64. package/dist/init.js +14 -0
  65. package/dist/init.js.map +1 -1
  66. package/dist/install-check.d.ts +101 -0
  67. package/dist/install-check.js +366 -0
  68. package/dist/install-check.js.map +1 -0
  69. package/dist/journal.d.ts +212 -0
  70. package/dist/journal.js +406 -0
  71. package/dist/journal.js.map +1 -0
  72. package/dist/lean-context.js +22 -5
  73. package/dist/lean-context.js.map +1 -1
  74. package/dist/offline.d.ts +162 -0
  75. package/dist/offline.js +303 -0
  76. package/dist/offline.js.map +1 -0
  77. package/dist/pagination.d.ts +99 -0
  78. package/dist/pagination.js +175 -0
  79. package/dist/pagination.js.map +1 -0
  80. package/dist/path-params.d.ts +61 -0
  81. package/dist/path-params.js +120 -0
  82. package/dist/path-params.js.map +1 -0
  83. package/dist/plugin/injection.js +2 -2
  84. package/dist/plugin/injection.js.map +1 -1
  85. package/dist/plugin/manifest.d.ts +15 -15
  86. package/dist/plugin/provision.js +2 -2
  87. package/dist/plugin/provision.js.map +1 -1
  88. package/dist/project.d.ts +35 -0
  89. package/dist/project.js +72 -8
  90. package/dist/project.js.map +1 -1
  91. package/dist/session-env.js +12 -0
  92. package/dist/session-env.js.map +1 -1
  93. package/dist/session-surface.js +2 -19
  94. package/dist/session-surface.js.map +1 -1
  95. package/dist/session.d.ts +29 -0
  96. package/dist/session.js +54 -1
  97. package/dist/session.js.map +1 -1
  98. package/dist/skill-packs.d.ts +141 -0
  99. package/dist/skill-packs.js +478 -0
  100. package/dist/skill-packs.js.map +1 -0
  101. package/dist/skills.d.ts +14 -11
  102. package/dist/skills.js +38 -65
  103. package/dist/skills.js.map +1 -1
  104. package/dist/tool-counts.json +20 -20
  105. package/dist/tools/animation.js +81 -17
  106. package/dist/tools/animation.js.map +1 -1
  107. package/dist/tools/asset.js +237 -39
  108. package/dist/tools/asset.js.map +1 -1
  109. package/dist/tools/audio.js +43 -8
  110. package/dist/tools/audio.js.map +1 -1
  111. package/dist/tools/blueprint.js +76 -10
  112. package/dist/tools/blueprint.js.map +1 -1
  113. package/dist/tools/demo.js +3 -3
  114. package/dist/tools/demo.js.map +1 -1
  115. package/dist/tools/editor.js +159 -42
  116. package/dist/tools/editor.js.map +1 -1
  117. package/dist/tools/fab.js +7 -7
  118. package/dist/tools/fab.js.map +1 -1
  119. package/dist/tools/feedback.js +14 -4
  120. package/dist/tools/feedback.js.map +1 -1
  121. package/dist/tools/foliage.js +50 -4
  122. package/dist/tools/foliage.js.map +1 -1
  123. package/dist/tools/gameplay.js +137 -51
  124. package/dist/tools/gameplay.js.map +1 -1
  125. package/dist/tools/gas.js +74 -9
  126. package/dist/tools/gas.js.map +1 -1
  127. package/dist/tools/landscape.js +158 -10
  128. package/dist/tools/landscape.js.map +1 -1
  129. package/dist/tools/level.js +37 -18
  130. package/dist/tools/level.js.map +1 -1
  131. package/dist/tools/material.js +43 -8
  132. package/dist/tools/material.js.map +1 -1
  133. package/dist/tools/networking.js +10 -10
  134. package/dist/tools/networking.js.map +1 -1
  135. package/dist/tools/niagara.js +44 -8
  136. package/dist/tools/niagara.js.map +1 -1
  137. package/dist/tools/pcg.js +25 -8
  138. package/dist/tools/pcg.js.map +1 -1
  139. package/dist/tools/plugins.js +1 -1
  140. package/dist/tools/plugins.js.map +1 -1
  141. package/dist/tools/project.d.ts +17 -1
  142. package/dist/tools/project.js +571 -17
  143. package/dist/tools/project.js.map +1 -1
  144. package/dist/tools/reflection.js +15 -5
  145. package/dist/tools/reflection.js.map +1 -1
  146. package/dist/tools/statetree.js +44 -3
  147. package/dist/tools/statetree.js.map +1 -1
  148. package/dist/tools/widget.js +70 -4
  149. package/dist/tools/widget.js.map +1 -1
  150. package/dist/types.d.ts +75 -10
  151. package/dist/types.js +95 -20
  152. package/dist/types.js.map +1 -1
  153. package/dist/ue-mcp.default.yml +1571 -201
  154. package/dist/user-state.d.ts +42 -0
  155. package/dist/user-state.js +366 -38
  156. package/dist/user-state.js.map +1 -1
  157. package/dist/version-check.js +46 -5
  158. package/dist/version-check.js.map +1 -1
  159. package/package.json +4 -4
  160. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +130 -24
  161. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.h +44 -8
  162. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.cpp +22 -0
  163. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +135 -66
  164. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
  165. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +117 -0
  166. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerPoseSearchSchema.h +92 -0
  167. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerStateTreeSchema.h +224 -0
  168. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +467 -13
  169. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +36 -0
  170. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +4 -5
  171. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRigSequencer.cpp +132 -0
  172. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Depth.cpp +1432 -0
  173. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRetargeterAuthoring.cpp +41 -0
  174. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRigAuthoring.cpp +45 -0
  175. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_MotionMatching.cpp +186 -15
  176. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +319 -4
  177. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_SkeletalLive.cpp +45 -4
  178. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Skeleton.cpp +2866 -0
  179. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +547 -10
  180. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Validation.cpp +28 -0
  181. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +551 -57
  182. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +40 -0
  183. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_GeometryScript.cpp +2697 -0
  184. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Hygiene.cpp +1700 -0
  185. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +494 -57
  186. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +121 -3
  187. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp +11 -0
  188. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +55 -0
  189. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp +12 -0
  190. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_UV.cpp +2972 -0
  191. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.cpp +55 -22
  192. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.h +32 -0
  193. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_Depth.cpp +1559 -0
  194. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_MetaSound.cpp +562 -67
  195. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_MetaSoundRead.cpp +1415 -0
  196. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_Mixing.cpp +210 -1
  197. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp +61 -0
  198. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +506 -25
  199. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +43 -0
  200. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Depth.cpp +2579 -0
  201. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +162 -13
  202. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +694 -25
  203. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +96 -0
  204. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +124 -11
  205. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Search.cpp +73 -24
  206. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_UserTypes.cpp +1344 -0
  207. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers.cpp +136 -1
  208. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers_Nested.cpp +14 -0
  209. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +120 -0
  210. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.cpp +588 -133
  211. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.h +65 -5
  212. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +679 -26
  213. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +50 -0
  214. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +70 -0
  215. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +261 -4
  216. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +270 -23
  217. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Profiling.cpp +1665 -0
  218. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_RuntimeVisibility.cpp +41 -2
  219. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_ViewportControl.cpp +1229 -0
  220. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EpicHandlers.cpp +22 -0
  221. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FabHandlers.cpp +103 -0
  222. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +120 -12
  223. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +14 -0
  224. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Batch.cpp +87 -0
  225. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Depth.cpp +1482 -0
  226. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +954 -168
  227. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +63 -0
  228. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTAuthoring.cpp +12 -0
  229. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTRuntime.cpp +1556 -0
  230. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_EQS.cpp +760 -0
  231. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_Input.cpp +1297 -4
  232. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_Mass.cpp +1303 -0
  233. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_Perception.cpp +1493 -0
  234. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +164 -3
  235. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +77 -0
  236. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Abilities.cpp +1392 -0
  237. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Runtime.cpp +882 -3
  238. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Snapshot.cpp +1002 -0
  239. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +113 -3
  240. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +31 -0
  241. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +3778 -2
  242. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +790 -44
  243. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_BatchWrite.cpp +44 -1
  244. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Convert.cpp +6 -0
  245. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection.cpp +37 -0
  246. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +64 -1
  247. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +13 -0
  248. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_PostProcess.cpp +156 -2
  249. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Query.cpp +1 -1
  250. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Refresh.cpp +18 -3
  251. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Save.cpp +9 -0
  252. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Transient.cpp +79 -11
  253. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Volumes.cpp +174 -5
  254. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +77 -14
  255. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartitionSettings.cpp +79 -1
  256. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +591 -32
  257. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +16 -0
  258. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Advanced.cpp +168 -8
  259. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Build.cpp +30 -0
  260. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Function.cpp +106 -1
  261. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Graph.cpp +156 -23
  262. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_RVT.cpp +1510 -0
  263. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +232 -13
  264. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +471 -45
  265. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.h +23 -0
  266. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers_Advanced.cpp +1936 -0
  267. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers_Compile.cpp +300 -0
  268. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +520 -5
  269. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +369 -13
  270. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ProjectHandlers.cpp +44 -5
  271. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ProjectHandlers.h +13 -0
  272. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ProjectHandlers_Plugins.cpp +482 -0
  273. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.cpp +346 -31
  274. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.h +5 -0
  275. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers_Schema.cpp +842 -0
  276. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +270 -0
  277. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.cpp +65 -3
  278. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.cpp +912 -23
  279. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.h +22 -0
  280. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers_Depth.cpp +1782 -0
  281. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +579 -185
  282. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +37 -0
  283. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Animation.cpp +2691 -0
  284. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_CommonUI.cpp +612 -0
  285. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +14 -11
  286. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +253 -7
  287. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_RuntimeState.cpp +1 -1
  288. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/DataTableRowWriteTests.cpp +352 -0
  289. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +48 -25
  290. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerPagination.h +404 -0
  291. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +593 -18
  292. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/JsonSerializer.cpp +19 -0
  293. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +31 -0
  294. package/plugin/ue_mcp_bridge/UE_MCP_Bridge.uplugin +2 -2
  295. package/skills/ue-mcp-animation/ue-mcp.yml +14 -0
  296. package/skills/ue-mcp-blueprint/ue-mcp.yml +8 -0
  297. package/skills/ue-mcp-epic-routing/ue-mcp.yml +6 -0
  298. package/skills/ue-mcp-native-cpp/ue-mcp.yml +7 -0
  299. package/skills/ue-mcp-niagara/ue-mcp.yml +9 -0
  300. package/skills/ue-mcp-workflow/SKILL.md +3 -2
  301. package/skills/ue-mcp-workflow/ue-mcp.yml +3 -0
@@ -0,0 +1,612 @@
1
+ // CommonUI support, and the BindWidget contract it depends on. A translation-unit
2
+ // partition of FWidgetHandlers; registration stays in WidgetHandlers.cpp.
3
+ //
4
+ // ── Why so little is here ────────────────────────────────────────────────────
5
+ //
6
+ // An audit came first, because most of CommonUI turned out to be reachable
7
+ // already and a handler that duplicates a property write is a liability. What
8
+ // was checked, and where the existing route is:
9
+ //
10
+ // Adding a CommonUI widget widget(add_widget). ResolveWidgetClass
11
+ // (WidgetHandlers.cpp) resolves a full path and,
12
+ // as of this ticket, an unambiguous short name
13
+ // over every loaded UWidget subclass.
14
+ // Discovering the class names widget(list_classes), which this ticket turned
15
+ // from a hardcoded 21-entry UMG array into a real
16
+ // enumeration grouped by module.
17
+ // Runtime push / pop UCommonActivatableWidgetContainerBase::
18
+ // BP_AddWidget and RemoveWidget are
19
+ // BlueprintCallable (CommonActivatableWidgetContainer.h:156,
20
+ // :72), so editor(invoke_object_function) calls them.
21
+ // Tab registration UCommonTabListWidgetBase::RegisterTab /
22
+ // RemoveTab / SelectTabByID are BlueprintCallable
23
+ // (CommonTabListWidgetBase.h:107, :111, :123).
24
+ // Every style, border, text, Plain UPROPERTYs: UCommonButtonBase::Style
25
+ // lazy-image and load-guard (CommonButtonBase.h:826), UCommonBorder::Style
26
+ // setting (CommonBorder.h:46), UCommonTextBlock::Style
27
+ // (CommonTextBlock.h:207),
28
+ // UCommonBoundActionBar::ActionButtonClass
29
+ // (CommonBoundActionBar.h:68). widget(set_property)
30
+ // and widget(set_style) already write all of them.
31
+ // Style asset creation blueprint(create) resolves any parent class, and
32
+ // UCommonButtonStyle / UCommonTextStyle are plain
33
+ // UObject subclasses.
34
+ // Input action data UCommonInputSettings is config=Game, so
35
+ // project(set_config) writes it.
36
+ //
37
+ // That left exactly two things no existing action can answer:
38
+ //
39
+ // 1. BindWidget metadata. A native UUserWidget subclass states its contract in
40
+ // UPROPERTY meta, and metadata is not a property value. reflection(reflect_class)
41
+ // reports a fixed allowlist of meta keys (ReflectionHandlers.cpp:350-357:
42
+ // Category, DisplayName, EditCondition, Clamp*, UI*, Units) and BindWidget is
43
+ // not among them. So a caller subclassing CommonButtonBase had no way to learn
44
+ // which child widgets it must name, and found out from a compile error.
45
+ // This generalises well past CommonUI: it is the contract of ANY native
46
+ // UserWidget parent.
47
+ // 2. The CommonUI wiring rules. They are relationships between a project
48
+ // setting, an engine class override and a widget tree, evaluated together.
49
+ // Each half is readable; nothing joins them, and every one of them fails
50
+ // silently at runtime rather than at compile time.
51
+ //
52
+ // ── Why nothing here links CommonUI ──────────────────────────────────────────
53
+ //
54
+ // CommonUI ships disabled. A Build.cs dependency on it would fail to link the
55
+ // whole bridge in every project that has it off, which is most of them, so every
56
+ // CommonUI class below is reached by path at runtime through FindObject and every
57
+ // property by name through FindFProperty. When the plugin is off the actions say
58
+ // so, and say how to turn it on, rather than failing to load.
59
+
60
+ #include "WidgetHandlers.h"
61
+ #include "HandlerRegistry.h"
62
+ #include "HandlerUtils.h"
63
+
64
+ #include "WidgetBlueprint.h"
65
+ #include "Blueprint/UserWidget.h"
66
+ #include "Blueprint/WidgetTree.h"
67
+ #include "Animation/WidgetAnimation.h"
68
+ #include "Components/Widget.h"
69
+ #include "Components/PanelWidget.h"
70
+
71
+ #include "Interfaces/IPluginManager.h"
72
+
73
+ #include "Engine/Engine.h"
74
+ #include "Engine/Blueprint.h"
75
+ #include "UObject/Class.h"
76
+ #include "UObject/UnrealType.h"
77
+ #include "UObject/SoftObjectPtr.h"
78
+ #include "Dom/JsonObject.h"
79
+ #include "Dom/JsonValue.h"
80
+
81
+ // ─────────────────────────────────────────────────────────────────────────────
82
+ // File-local helpers.
83
+ //
84
+ // The module is a unity build, so two .cpp files in one blob share their
85
+ // anonymous namespace and a duplicated helper is a redefinition (C2084). Every
86
+ // name below is prefixed WCui_ inside a named namespace and exists nowhere else
87
+ // in the tree; nothing was copied out of WidgetHandlers.cpp or
88
+ // WidgetHandlers_Animation.cpp, both of which are neighbours in this module.
89
+ // ─────────────────────────────────────────────────────────────────────────────
90
+ namespace MCPWidgetCommonUI
91
+ {
92
+
93
+ /** The four BindWidget meta keys, and what each one means. */
94
+ struct FWCui_BindKind
95
+ {
96
+ const TCHAR* MetaKey;
97
+ bool bOptional;
98
+ bool bAnimation;
99
+ };
100
+
101
+ static const FWCui_BindKind WCui_BindKinds[] = {
102
+ { TEXT("BindWidget"), false, false },
103
+ { TEXT("BindWidgetOptional"), true, false },
104
+ { TEXT("BindWidgetAnim"), false, true },
105
+ { TEXT("BindWidgetAnimOptional"), true, true },
106
+ };
107
+
108
+ /**
109
+ * Is this property part of a UserWidget's bind contract, and how strict is it?
110
+ *
111
+ * `meta=(BindWidget, OptionalWidget=true)` is the older spelling of
112
+ * BindWidgetOptional and the engine still honours it, so both are read here.
113
+ * Missing that would report a property as required when the compiler does not.
114
+ */
115
+ static bool WCui_ReadBindKind(const FProperty* Prop, bool& bOutOptional, bool& bOutAnimation)
116
+ {
117
+ // WITH_METADATA, not WITH_EDITOR: metadata is what this reads and that macro
118
+ // is what gates the API. Both are on in an editor build; only one of them
119
+ // says why this code needs the guard.
120
+ #if WITH_METADATA
121
+ for (const FWCui_BindKind& Kind : WCui_BindKinds)
122
+ {
123
+ if (!Prop->HasMetaData(Kind.MetaKey)) continue;
124
+ bOutAnimation = Kind.bAnimation;
125
+ bOutOptional = Kind.bOptional
126
+ || Prop->GetBoolMetaData(TEXT("OptionalWidget"))
127
+ || Prop->HasMetaData(TEXT("BindWidgetOptional"))
128
+ || Prop->HasMetaData(TEXT("BindWidgetAnimOptional"));
129
+ return true;
130
+ }
131
+ #endif // WITH_METADATA
132
+ return false;
133
+ }
134
+
135
+ /** Resolve a class spec: short name, /Script path, or a Widget Blueprint path. */
136
+ static UClass* WCui_ResolveWidgetClassSpec(const FString& Spec)
137
+ {
138
+ if (Spec.IsEmpty()) return nullptr;
139
+
140
+ if (UClass* Direct = MCPResolveClass(Spec, /*bAllowLoad*/ true))
141
+ {
142
+ if (Direct->IsChildOf(UWidget::StaticClass())) return Direct;
143
+ }
144
+ // A Widget Blueprint path names the asset; its contract lives on the class.
145
+ if (UObject* Asset = LoadObject<UObject>(nullptr, *Spec))
146
+ {
147
+ if (UBlueprint* BP = Cast<UBlueprint>(Asset))
148
+ {
149
+ if (BP->GeneratedClass && BP->GeneratedClass->IsChildOf(UWidget::StaticClass()))
150
+ {
151
+ return BP->GeneratedClass;
152
+ }
153
+ }
154
+ }
155
+ return nullptr;
156
+ }
157
+
158
+ /** A CommonUI class by name, or null when the plugin is not loaded. */
159
+ static UClass* WCui_CommonClass(const TCHAR* Module, const TCHAR* ClassName)
160
+ {
161
+ const FString Path = FString::Printf(TEXT("/Script/%s.%s"), Module, ClassName);
162
+ return FindObject<UClass>(nullptr, *Path);
163
+ }
164
+
165
+ static bool WCui_PluginLoaded()
166
+ {
167
+ return IPluginManager::Get().FindEnabledPlugin(TEXT("CommonUI")).IsValid();
168
+ }
169
+
170
+ /** Every widget in the tree, parents before children. */
171
+ static void WCui_CollectWidgets(UWidgetTree* Tree, TArray<UWidget*>& Out)
172
+ {
173
+ if (!Tree) return;
174
+ Tree->ForEachWidget([&Out](UWidget* W) { if (W) Out.Add(W); });
175
+ }
176
+
177
+ /** The class a TSubclassOf property currently points at, or null. */
178
+ static UClass* WCui_ReadClassProperty(UObject* Object, const TCHAR* PropertyName)
179
+ {
180
+ FClassProperty* Prop = FindFProperty<FClassProperty>(Object->GetClass(), PropertyName);
181
+ if (!Prop) return nullptr;
182
+ return Cast<UClass>(Prop->GetObjectPropertyValue_InContainer(Object));
183
+ }
184
+
185
+ /** True when the named TSubclassOf property exists on the object AND is unset. */
186
+ static bool WCui_ClassPropertyIsUnset(UObject* Object, const TCHAR* PropertyName)
187
+ {
188
+ FClassProperty* Prop = FindFProperty<FClassProperty>(Object->GetClass(), PropertyName);
189
+ if (!Prop) return false; // Property absent: a different engine version, not a fault.
190
+ return WCui_ReadClassProperty(Object, PropertyName) == nullptr;
191
+ }
192
+
193
+ /** One entry in the audit's problems array, in one shape for every rule. */
194
+ static TSharedPtr<FJsonValue> WCui_Problem(
195
+ const TCHAR* Rule, const FString& Where, const FString& What, const FString& Fix)
196
+ {
197
+ TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
198
+ Obj->SetStringField(TEXT("rule"), Rule);
199
+ Obj->SetStringField(TEXT("where"), Where);
200
+ Obj->SetStringField(TEXT("problem"), What);
201
+ Obj->SetStringField(TEXT("fix"), Fix);
202
+ return MakeShared<FJsonValueObject>(Obj);
203
+ }
204
+
205
+ static TSharedPtr<FJsonValue> WCui_Note(const TCHAR* Rule, const FString& Why)
206
+ {
207
+ TSharedPtr<FJsonObject> Obj = MakeShared<FJsonObject>();
208
+ Obj->SetStringField(TEXT("rule"), Rule);
209
+ Obj->SetStringField(TEXT("reason"), Why);
210
+ return MakeShared<FJsonValueObject>(Obj);
211
+ }
212
+
213
+ } // namespace MCPWidgetCommonUI
214
+
215
+ using namespace MCPWidgetCommonUI;
216
+
217
+ // ═════════════════════════════════════════════════════════════════════════════
218
+ // get_bind_widget_contract
219
+ //
220
+ // What a native UserWidget parent requires of the Widget Blueprint below it.
221
+ // ═════════════════════════════════════════════════════════════════════════════
222
+
223
+ TSharedPtr<FJsonValue> FWidgetHandlers::GetBindWidgetContract(const TSharedPtr<FJsonObject>& Params)
224
+ {
225
+ const FString ClassName = OptionalString(Params, TEXT("className"));
226
+ const FString AssetPath = OptionalString(Params, TEXT("assetPath"));
227
+
228
+ if (ClassName.IsEmpty() && AssetPath.IsEmpty())
229
+ {
230
+ return MCPError(TEXT(
231
+ "Pass className to read a parent class's contract (a short name like CommonButtonBase, a full "
232
+ "path like /Script/CommonUI.CommonButtonBase, or a Widget Blueprint path), or assetPath to read "
233
+ "a Widget Blueprint's contract AND check its own tree against it. Neither was given."));
234
+ }
235
+
236
+ // ── Resolve the class whose contract this is.
237
+ UWidgetBlueprint* WidgetBP = nullptr;
238
+ UClass* ContractClass = nullptr;
239
+
240
+ if (!AssetPath.IsEmpty())
241
+ {
242
+ TSharedPtr<FJsonValue> ResolveError;
243
+ WidgetBP = MCPWidget::ResolveWidgetBlueprintOrError(AssetPath, ResolveError);
244
+ if (!WidgetBP) return ResolveError;
245
+ // The contract is what the PARENT demands. Reading the generated class
246
+ // would also pick up the Blueprint's own widget variables, which are the
247
+ // answer rather than the question.
248
+ ContractClass = WidgetBP->ParentClass;
249
+ if (!ContractClass)
250
+ {
251
+ return MCPError(FString::Printf(
252
+ TEXT("Widget Blueprint '%s' has no parent class, which means the asset is broken."), *AssetPath));
253
+ }
254
+ }
255
+
256
+ if (!ClassName.IsEmpty())
257
+ {
258
+ UClass* Named = WCui_ResolveWidgetClassSpec(ClassName);
259
+ if (!Named)
260
+ {
261
+ return MCPError(FString::Printf(
262
+ TEXT("'%s' does not name a loaded UWidget subclass. Short names of loaded classes resolve, as "
263
+ "does a full path (/Script/CommonUI.CommonButtonBase) or a Widget Blueprint path. List "
264
+ "what this editor has with widget(list_classes). A class from a plugin that is off does "
265
+ "not exist until project(enable_plugin) and an editor restart."), *ClassName));
266
+ }
267
+ ContractClass = Named;
268
+ }
269
+
270
+ // ── Gather the contract, walking up so an inherited requirement is reported
271
+ // with the class that actually declares it.
272
+ TArray<TSharedPtr<FJsonValue>> Requirements;
273
+ int32 RequiredCount = 0;
274
+ int32 OptionalCount = 0;
275
+
276
+ for (TFieldIterator<FProperty> It(ContractClass); It; ++It)
277
+ {
278
+ FProperty* Prop = *It;
279
+ bool bOptional = false;
280
+ bool bAnimation = false;
281
+ if (!WCui_ReadBindKind(Prop, bOptional, bAnimation)) continue;
282
+
283
+ FString ExpectedType;
284
+ if (FObjectPropertyBase* ObjProp = CastField<FObjectPropertyBase>(Prop))
285
+ {
286
+ ExpectedType = ObjProp->PropertyClass ? ObjProp->PropertyClass->GetName() : FString();
287
+ }
288
+
289
+ TSharedPtr<FJsonObject> Entry = MakeShared<FJsonObject>();
290
+ Entry->SetStringField(TEXT("widgetName"), Prop->GetName());
291
+ Entry->SetStringField(TEXT("expectedClass"), ExpectedType);
292
+ Entry->SetStringField(TEXT("declaredBy"),
293
+ Prop->GetOwnerClass() ? Prop->GetOwnerClass()->GetName() : FString());
294
+ Entry->SetBoolField(TEXT("optional"), bOptional);
295
+ Entry->SetStringField(TEXT("kind"), bAnimation ? TEXT("animation") : TEXT("widget"));
296
+ Entry->SetStringField(TEXT("satisfyWith"), bAnimation
297
+ ? TEXT("widget(create_animation) with animationName set to widgetName")
298
+ : TEXT("widget(add_widget) with widgetName set to widgetName and widgetClass to expectedClass"));
299
+
300
+ if (bOptional) ++OptionalCount; else ++RequiredCount;
301
+ Requirements.Add(MakeShared<FJsonValueObject>(Entry));
302
+ }
303
+
304
+ auto Result = MCPSuccess();
305
+ Result->SetStringField(TEXT("className"), ContractClass->GetName());
306
+ Result->SetStringField(TEXT("classPath"), ContractClass->GetPathName());
307
+ Result->SetArrayField(TEXT("requirements"), Requirements);
308
+ Result->SetNumberField(TEXT("requiredCount"), RequiredCount);
309
+ Result->SetNumberField(TEXT("optionalCount"), OptionalCount);
310
+
311
+ // ── When a Blueprint was named, say which requirements it already meets.
312
+ // A contract with no way to check it against an asset is only half an answer.
313
+ if (WidgetBP)
314
+ {
315
+ TArray<UWidget*> Tree;
316
+ WCui_CollectWidgets(WidgetBP->WidgetTree, Tree);
317
+
318
+ TArray<FString> AnimationNames;
319
+ for (UWidgetAnimation* Anim : WidgetBP->Animations)
320
+ {
321
+ if (Anim) AnimationNames.Add(Anim->GetName());
322
+ }
323
+
324
+ TArray<TSharedPtr<FJsonValue>> Missing;
325
+ TArray<TSharedPtr<FJsonValue>> WrongType;
326
+ int32 Satisfied = 0;
327
+
328
+ for (const TSharedPtr<FJsonValue>& Entry : Requirements)
329
+ {
330
+ const TSharedPtr<FJsonObject>* Obj = nullptr;
331
+ if (!Entry->TryGetObject(Obj) || !Obj) continue;
332
+ FString Name, Expected;
333
+ bool bOptional = false;
334
+ bool bAnimation = false;
335
+ (*Obj)->TryGetStringField(TEXT("widgetName"), Name);
336
+ (*Obj)->TryGetStringField(TEXT("expectedClass"), Expected);
337
+ (*Obj)->TryGetBoolField(TEXT("optional"), bOptional);
338
+ FString Kind;
339
+ (*Obj)->TryGetStringField(TEXT("kind"), Kind);
340
+ bAnimation = Kind == TEXT("animation");
341
+
342
+ if (bAnimation)
343
+ {
344
+ if (AnimationNames.Contains(Name)) { ++Satisfied; continue; }
345
+ if (!bOptional) Missing.Add(MakeShared<FJsonValueObject>(*Obj));
346
+ continue;
347
+ }
348
+
349
+ UWidget* Found = nullptr;
350
+ for (UWidget* W : Tree)
351
+ {
352
+ if (W->GetName() == Name) { Found = W; break; }
353
+ }
354
+ if (!Found)
355
+ {
356
+ if (!bOptional) Missing.Add(MakeShared<FJsonValueObject>(*Obj));
357
+ continue;
358
+ }
359
+
360
+ // A widget of the right name but the wrong class fails the compile
361
+ // exactly as loudly as a missing one, and is far harder to spot.
362
+ UClass* ExpectedClass = Expected.IsEmpty() ? nullptr : MCPResolveClass(Expected, false);
363
+ if (ExpectedClass && !Found->GetClass()->IsChildOf(ExpectedClass))
364
+ {
365
+ TSharedPtr<FJsonObject> Bad = MakeShared<FJsonObject>();
366
+ Bad->SetStringField(TEXT("widgetName"), Name);
367
+ Bad->SetStringField(TEXT("expectedClass"), Expected);
368
+ Bad->SetStringField(TEXT("actualClass"), Found->GetClass()->GetName());
369
+ Bad->SetBoolField(TEXT("optional"), bOptional);
370
+ WrongType.Add(MakeShared<FJsonValueObject>(Bad));
371
+ continue;
372
+ }
373
+ ++Satisfied;
374
+ }
375
+
376
+ TSharedPtr<FJsonObject> Check = MakeShared<FJsonObject>();
377
+ Check->SetStringField(TEXT("assetPath"), AssetPath);
378
+ Check->SetStringField(TEXT("parentClass"), ContractClass->GetName());
379
+ Check->SetNumberField(TEXT("satisfied"), Satisfied);
380
+ Check->SetArrayField(TEXT("missing"), Missing);
381
+ Check->SetArrayField(TEXT("wrongType"), WrongType);
382
+ Check->SetBoolField(TEXT("compiles"), Missing.Num() == 0 && WrongType.Num() == 0);
383
+ Result->SetObjectField(TEXT("check"), Check);
384
+ }
385
+
386
+ Result->SetStringField(TEXT("note"), TEXT(
387
+ "A required entry with no widget of that exact name and a compatible class fails the Widget "
388
+ "Blueprint compile. The name is the property name, matched exactly and case-sensitively."));
389
+
390
+ return MCPResult(Result);
391
+ }
392
+
393
+ // ═════════════════════════════════════════════════════════════════════════════
394
+ // audit_commonui
395
+ //
396
+ // The wiring rules that fail silently at runtime instead of loudly at compile.
397
+ // ═════════════════════════════════════════════════════════════════════════════
398
+
399
+ TSharedPtr<FJsonValue> FWidgetHandlers::AuditCommonUI(const TSharedPtr<FJsonObject>& Params)
400
+ {
401
+ const FString AssetPath = OptionalString(Params, TEXT("assetPath"));
402
+
403
+ TArray<TSharedPtr<FJsonValue>> Problems;
404
+ TArray<TSharedPtr<FJsonValue>> NotChecked;
405
+ TArray<FString> Checked;
406
+
407
+ // ── Rule 1: the plugin itself.
408
+ const bool bPluginLoaded = WCui_PluginLoaded();
409
+ Checked.Add(TEXT("plugin_enabled"));
410
+ if (!bPluginLoaded)
411
+ {
412
+ Problems.Add(WCui_Problem(
413
+ TEXT("plugin_enabled"), TEXT("project"),
414
+ TEXT("The CommonUI plugin is not enabled in this editor, so no CommonUI class exists and no "
415
+ "CommonUI widget can be added or configured."),
416
+ TEXT("project(enable_plugin, pluginName=\"CommonUI\") then editor(restart_editor). Everything "
417
+ "below is unknowable until then.")));
418
+
419
+ auto Early = MCPSuccess();
420
+ Early->SetBoolField(TEXT("pluginEnabled"), false);
421
+ Early->SetArrayField(TEXT("problems"), Problems);
422
+ Early->SetNumberField(TEXT("problemCount"), Problems.Num());
423
+ Early->SetArrayField(TEXT("checked"), MCPStringListToJson(Checked));
424
+ Early->SetArrayField(TEXT("notChecked"), NotChecked);
425
+ return MCPResult(Early);
426
+ }
427
+
428
+ // ── Rule 2: the game viewport client.
429
+ // CommonUI routes input to the UI before the game through its own viewport
430
+ // client. With the engine default in place, gamepad navigation and the Back
431
+ // action do nothing, and nothing anywhere reports why.
432
+ Checked.Add(TEXT("game_viewport_client"));
433
+ UClass* CommonViewport = WCui_CommonClass(TEXT("CommonUI"), TEXT("CommonGameViewportClient"));
434
+ if (!CommonViewport)
435
+ {
436
+ NotChecked.Add(WCui_Note(TEXT("game_viewport_client"),
437
+ TEXT("UCommonGameViewportClient is not loaded even though the plugin is enabled.")));
438
+ }
439
+ else if (GEngine)
440
+ {
441
+ UClass* Current = GEngine->GameViewportClientClass;
442
+ if (!Current || !Current->IsChildOf(CommonViewport))
443
+ {
444
+ Problems.Add(WCui_Problem(
445
+ TEXT("game_viewport_client"), TEXT("project"),
446
+ FString::Printf(
447
+ TEXT("GameViewportClientClass is %s, which is not a CommonGameViewportClient. CommonUI "
448
+ "input routing, the Back action and gamepad navigation are inactive."),
449
+ Current ? *Current->GetName() : TEXT("unset")),
450
+ TEXT("project(set_config, configName=\"Engine\", section=\"/Script/Engine.Engine\", "
451
+ "key=\"GameViewportClientClassName\", "
452
+ "value=\"/Script/CommonUI.CommonGameViewportClient\") then restart the editor.")));
453
+ }
454
+ }
455
+ else
456
+ {
457
+ NotChecked.Add(WCui_Note(TEXT("game_viewport_client"), TEXT("GEngine is not available.")));
458
+ }
459
+
460
+ // ── Rule 3: the input action data.
461
+ // Without it, every CommonUI input action resolves to nothing, so bound
462
+ // action bars come up empty and Back is unhandled.
463
+ Checked.Add(TEXT("input_action_data"));
464
+ UClass* InputSettingsClass = WCui_CommonClass(TEXT("CommonInput"), TEXT("CommonInputSettings"));
465
+ if (!InputSettingsClass)
466
+ {
467
+ NotChecked.Add(WCui_Note(TEXT("input_action_data"),
468
+ TEXT("UCommonInputSettings is not loaded, so the project's CommonUI input data cannot be read.")));
469
+ }
470
+ else
471
+ {
472
+ UObject* SettingsCDO = InputSettingsClass->GetDefaultObject();
473
+ FSoftObjectProperty* InputData =
474
+ FindFProperty<FSoftObjectProperty>(InputSettingsClass, TEXT("InputData"));
475
+ if (!SettingsCDO || !InputData)
476
+ {
477
+ NotChecked.Add(WCui_Note(TEXT("input_action_data"),
478
+ TEXT("UCommonInputSettings has no InputData property in this engine version.")));
479
+ }
480
+ else
481
+ {
482
+ const FSoftObjectPtr* Value = InputData->ContainerPtrToValuePtr<FSoftObjectPtr>(SettingsCDO);
483
+ if (!Value || Value->IsNull())
484
+ {
485
+ Problems.Add(WCui_Problem(
486
+ TEXT("input_action_data"), TEXT("project"),
487
+ TEXT("CommonInputSettings.InputData is unset, so no CommonUI input action resolves. "
488
+ "Bound action bars render empty and the Back action is never handled."),
489
+ TEXT("Create a UCommonUIInputData subclass with blueprint(create), then "
490
+ "project(set_config, configName=\"Game\", "
491
+ "section=\"/Script/CommonInput.CommonInputSettings\", key=\"InputData\", "
492
+ "value=\"<the class path>\").")));
493
+ }
494
+ }
495
+ }
496
+
497
+ // ── Per-asset rules. Everything above is about the project; these are about
498
+ // one widget tree, and they only run when a caller names one.
499
+ if (AssetPath.IsEmpty())
500
+ {
501
+ NotChecked.Add(WCui_Note(TEXT("widget_tree"),
502
+ TEXT("No assetPath was given, so the per-widget rules (activatable focus target, bound action "
503
+ "bar button class, unstyled CommonUI widgets) did not run. Pass assetPath to include them.")));
504
+ }
505
+ else
506
+ {
507
+ TSharedPtr<FJsonValue> ResolveError;
508
+ UWidgetBlueprint* WidgetBP = MCPWidget::ResolveWidgetBlueprintOrError(AssetPath, ResolveError);
509
+ if (!WidgetBP) return ResolveError;
510
+ if (!WidgetBP->WidgetTree) return MCPWidget::MissingWidgetTreeError(AssetPath);
511
+
512
+ // Rule 4: an activatable widget with nothing to focus. On gamepad,
513
+ // activating it leaves focus wherever it was, which reads as the UI
514
+ // being dead rather than as a missing setting.
515
+ Checked.Add(TEXT("activatable_focus_target"));
516
+ UClass* ActivatableClass = WCui_CommonClass(TEXT("CommonUI"), TEXT("CommonActivatableWidget"));
517
+ if (ActivatableClass && WidgetBP->ParentClass && WidgetBP->ParentClass->IsChildOf(ActivatableClass))
518
+ {
519
+ UClass* GeneratedClass = WidgetBP->GeneratedClass;
520
+ UObject* CDO = GeneratedClass ? GeneratedClass->GetDefaultObject() : nullptr;
521
+ FStructProperty* FocusProp = CDO
522
+ ? FindFProperty<FStructProperty>(CDO->GetClass(), TEXT("DesiredFocusWidget"))
523
+ : nullptr;
524
+ if (!CDO || !FocusProp)
525
+ {
526
+ NotChecked.Add(WCui_Note(TEXT("activatable_focus_target"),
527
+ TEXT("DesiredFocusWidget is not a property of UUserWidget in this engine version.")));
528
+ }
529
+ else
530
+ {
531
+ const void* FocusValue = FocusProp->ContainerPtrToValuePtr<void>(CDO);
532
+ FNameProperty* NameProp =
533
+ FindFProperty<FNameProperty>(FocusProp->Struct, TEXT("WidgetName"));
534
+ const FName FocusName = NameProp
535
+ ? NameProp->GetPropertyValue_InContainer(FocusValue)
536
+ : NAME_None;
537
+ if (FocusName.IsNone())
538
+ {
539
+ Problems.Add(WCui_Problem(
540
+ TEXT("activatable_focus_target"), AssetPath,
541
+ TEXT("This is a CommonActivatableWidget with no DesiredFocusWidget, so activating it "
542
+ "on a gamepad hands focus to nothing and the screen appears unresponsive."),
543
+ TEXT("asset(set_property, assetPath=<this asset>, "
544
+ "propertyName=\"DesiredFocusWidget.WidgetName\", value=<a focusable widget "
545
+ "name from widget(read_tree)>).")));
546
+ }
547
+ }
548
+ }
549
+
550
+ // Rules 5 and 6 walk the tree once.
551
+ Checked.Add(TEXT("bound_action_bar_button_class"));
552
+ Checked.Add(TEXT("commonui_widget_style"));
553
+ UClass* ActionBarClass = WCui_CommonClass(TEXT("CommonUI"), TEXT("CommonBoundActionBar"));
554
+
555
+ // Every CommonUI widget whose look comes entirely from a Style class:
556
+ // unset, they render as nothing at all, which looks like a layout bug.
557
+ struct FStyled { const TCHAR* ClassName; const TCHAR* PropertyName; };
558
+ static const FStyled StyledClasses[] = {
559
+ { TEXT("CommonButtonBase"), TEXT("Style") },
560
+ { TEXT("CommonBorder"), TEXT("Style") },
561
+ { TEXT("CommonTextBlock"), TEXT("Style") },
562
+ };
563
+
564
+ TArray<UWidget*> Tree;
565
+ WCui_CollectWidgets(WidgetBP->WidgetTree, Tree);
566
+ for (UWidget* Widget : Tree)
567
+ {
568
+ if (ActionBarClass && Widget->IsA(ActionBarClass)
569
+ && WCui_ClassPropertyIsUnset(Widget, TEXT("ActionButtonClass")))
570
+ {
571
+ Problems.Add(WCui_Problem(
572
+ TEXT("bound_action_bar_button_class"), FString::Printf(TEXT("%s.%s"), *AssetPath, *Widget->GetName()),
573
+ TEXT("CommonBoundActionBar has no ActionButtonClass, so it has nothing to build its "
574
+ "entries from and renders empty however many actions are bound."),
575
+ FString::Printf(TEXT("widget(set_property, assetPath=%s, widgetName=%s, "
576
+ "propertyName=\"ActionButtonClass\", value=<a CommonButtonBase subclass that "
577
+ "implements CommonBoundActionButtonInterface>)."), *AssetPath, *Widget->GetName())));
578
+ }
579
+
580
+ for (const FStyled& Styled : StyledClasses)
581
+ {
582
+ UClass* StyledClass = WCui_CommonClass(TEXT("CommonUI"), Styled.ClassName);
583
+ if (!StyledClass || !Widget->IsA(StyledClass)) continue;
584
+ if (!WCui_ClassPropertyIsUnset(Widget, Styled.PropertyName)) continue;
585
+ Problems.Add(WCui_Problem(
586
+ TEXT("commonui_widget_style"), FString::Printf(TEXT("%s.%s"), *AssetPath, *Widget->GetName()),
587
+ FString::Printf(
588
+ TEXT("%s '%s' has no %s set. A CommonUI widget draws entirely from its style class, "
589
+ "so with none it renders as nothing and reads as a layout fault."),
590
+ Styled.ClassName, *Widget->GetName(), Styled.PropertyName),
591
+ FString::Printf(TEXT("widget(set_property, assetPath=%s, widgetName=%s, "
592
+ "propertyName=\"%s\", value=<a style asset path>). Create one with "
593
+ "blueprint(create) on the matching Common*Style parent class."),
594
+ *AssetPath, *Widget->GetName(), Styled.PropertyName)));
595
+ }
596
+ }
597
+ }
598
+
599
+ auto Result = MCPSuccess();
600
+ Result->SetBoolField(TEXT("pluginEnabled"), true);
601
+ if (!AssetPath.IsEmpty()) Result->SetStringField(TEXT("assetPath"), AssetPath);
602
+ Result->SetArrayField(TEXT("problems"), Problems);
603
+ Result->SetNumberField(TEXT("problemCount"), Problems.Num());
604
+ Result->SetArrayField(TEXT("checked"), MCPStringListToJson(Checked));
605
+ Result->SetArrayField(TEXT("notChecked"), NotChecked);
606
+ Result->SetStringField(TEXT("note"), TEXT(
607
+ "Every rule here fails silently at runtime rather than at compile time, which is why they are "
608
+ "worth a report. Authored values only: this reads the asset and the project settings, not a "
609
+ "running game."));
610
+
611
+ return MCPResult(Result);
612
+ }
@@ -510,22 +510,24 @@ TSharedPtr<FJsonValue> FWidgetHandlers::ExtractWidgetSubtree(const TSharedPtr<FJ
510
510
  ++CopiedBindings;
511
511
  }
512
512
 
513
- // WidgetVariableNameToGuidMap keeps external references stable when a
514
- // widget variable is later renamed. It landed in 5.5, so gate on the
515
- // shared macro rather than an ad-hoc version expression.
516
- #if UE_MCP_HAS_5_5_API
517
- for (const FExtractedWidgetPlanEntry& Entry : Plan)
513
+ FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Destination);
514
+
515
+ // WidgetVariableNameToGuidMap keeps external references stable when a widget
516
+ // variable is later renamed, and the compiler reports a failure for any
517
+ // widget variable it generates without an entry (#728). The entries are
518
+ // written off the widgets the destination tree actually owns rather than off
519
+ // the plan, because the importer renames a widget whose name was already
520
+ // taken while the plan still holds the name that was asked for.
521
+ const MCPWidgetGuidMap::FSyncReport GuidSync = MCPWidgetGuidMap::CompileChecked(Destination);
522
+ if (!GuidSync.bCompiled)
518
523
  {
519
- const FName WidgetName(*Entry.DestinationName);
520
- if (!Destination->WidgetVariableNameToGuidMap.Contains(WidgetName))
524
+ if (bCreatedDestination)
521
525
  {
522
- Destination->WidgetVariableNameToGuidMap.Add(WidgetName, FGuid::NewGuid());
526
+ UEditorAssetLibrary::DeleteAsset(DestinationAssetPath);
523
527
  }
528
+ return MCPWidgetGuidMap::BlockedError(DestinationAssetPath, GuidSync);
524
529
  }
525
- #endif
526
530
 
527
- FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Destination);
528
- FKismetEditorUtilities::CompileBlueprint(Destination);
529
531
  if (Destination->Status == BS_Error)
530
532
  {
531
533
  if (bCreatedDestination)
@@ -561,5 +563,6 @@ TSharedPtr<FJsonValue> FWidgetHandlers::ExtractWidgetSubtree(const TSharedPtr<FJ
561
563
  Result->SetBoolField(TEXT("sourcePackageDirtyBefore"), bSourceDirtyBefore);
562
564
  Result->SetBoolField(TEXT("sourcePackageDirtyAfter"), Source->GetOutermost()->IsDirty());
563
565
  Result->SetBoolField(TEXT("sourceUnchanged"), bSourceDirtyBefore == Source->GetOutermost()->IsDirty());
566
+ MCPSetWidgetGuidOutcome(Result, GuidSync, Destination->GetPathName());
564
567
  return MCPResult(Result);
565
568
  }