unreal-engine-mcp-server 0.5.4 → 0.5.6

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 (561) hide show
  1. package/CHANGELOG.md +350 -0
  2. package/dist/automation/bridge.d.ts.map +1 -0
  3. package/dist/automation/bridge.js +5 -4
  4. package/dist/automation/bridge.js.map +1 -0
  5. package/dist/automation/connection-manager.d.ts.map +1 -0
  6. package/dist/automation/connection-manager.js.map +1 -0
  7. package/dist/automation/handshake.d.ts.map +1 -0
  8. package/dist/automation/handshake.js.map +1 -0
  9. package/dist/automation/index.d.ts.map +1 -0
  10. package/dist/automation/index.js.map +1 -0
  11. package/dist/automation/message-handler.d.ts.map +1 -0
  12. package/dist/automation/message-handler.js.map +1 -0
  13. package/dist/automation/request-tracker.d.ts.map +1 -0
  14. package/dist/automation/request-tracker.js.map +1 -0
  15. package/dist/automation/types.d.ts +7 -0
  16. package/dist/automation/types.d.ts.map +1 -0
  17. package/dist/automation/types.js.map +1 -0
  18. package/dist/cli.d.ts.map +1 -0
  19. package/dist/cli.js +6 -4
  20. package/dist/cli.js.map +1 -0
  21. package/dist/config/class-aliases.d.ts.map +1 -0
  22. package/dist/config/class-aliases.js.map +1 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js.map +1 -0
  25. package/dist/constants.d.ts.map +1 -0
  26. package/dist/constants.js.map +1 -0
  27. package/dist/graphql/loaders.d.ts.map +1 -0
  28. package/dist/graphql/loaders.js.map +1 -0
  29. package/dist/graphql/resolvers.d.ts +174 -69
  30. package/dist/graphql/resolvers.d.ts.map +1 -0
  31. package/dist/graphql/resolvers.js +82 -67
  32. package/dist/graphql/resolvers.js.map +1 -0
  33. package/dist/graphql/schema.d.ts.map +1 -0
  34. package/dist/graphql/schema.js.map +1 -0
  35. package/dist/graphql/server.d.ts.map +1 -0
  36. package/dist/graphql/server.js.map +1 -0
  37. package/dist/graphql/types.d.ts.map +1 -0
  38. package/dist/graphql/types.js.map +1 -0
  39. package/dist/handlers/resource-handlers.d.ts.map +1 -0
  40. package/dist/handlers/resource-handlers.js.map +1 -0
  41. package/dist/index.d.ts +2 -1
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +70 -9
  44. package/dist/index.js.map +1 -0
  45. package/dist/resources/actors.d.ts +7 -4
  46. package/dist/resources/actors.d.ts.map +1 -0
  47. package/dist/resources/actors.js +15 -12
  48. package/dist/resources/actors.js.map +1 -0
  49. package/dist/resources/assets.d.ts +43 -2
  50. package/dist/resources/assets.d.ts.map +1 -0
  51. package/dist/resources/assets.js +21 -12
  52. package/dist/resources/assets.js.map +1 -0
  53. package/dist/resources/levels.d.ts.map +1 -0
  54. package/dist/resources/levels.js +7 -5
  55. package/dist/resources/levels.js.map +1 -0
  56. package/dist/schemas/index.d.ts +4 -0
  57. package/dist/schemas/index.d.ts.map +1 -0
  58. package/dist/schemas/index.js +4 -0
  59. package/dist/schemas/index.js.map +1 -0
  60. package/dist/schemas/parser.d.ts +20 -0
  61. package/dist/schemas/parser.d.ts.map +1 -0
  62. package/dist/schemas/parser.js +61 -0
  63. package/dist/schemas/parser.js.map +1 -0
  64. package/dist/schemas/primitives.d.ts +221 -0
  65. package/dist/schemas/primitives.d.ts.map +1 -0
  66. package/dist/schemas/primitives.js +115 -0
  67. package/dist/schemas/primitives.js.map +1 -0
  68. package/dist/schemas/responses.d.ts +362 -0
  69. package/dist/schemas/responses.d.ts.map +1 -0
  70. package/dist/schemas/responses.js +252 -0
  71. package/dist/schemas/responses.js.map +1 -0
  72. package/dist/server/resource-registry.d.ts.map +1 -0
  73. package/dist/server/resource-registry.js.map +1 -0
  74. package/dist/server/tool-registry.d.ts.map +1 -0
  75. package/dist/server/tool-registry.js +22 -17
  76. package/dist/server/tool-registry.js.map +1 -0
  77. package/dist/server-setup.d.ts.map +1 -0
  78. package/dist/server-setup.js.map +1 -0
  79. package/dist/services/health-monitor.d.ts +1 -1
  80. package/dist/services/health-monitor.d.ts.map +1 -0
  81. package/dist/services/health-monitor.js +4 -3
  82. package/dist/services/health-monitor.js.map +1 -0
  83. package/dist/services/metrics-server.d.ts.map +1 -0
  84. package/dist/services/metrics-server.js.map +1 -0
  85. package/dist/tools/actors.d.ts +27 -27
  86. package/dist/tools/actors.d.ts.map +1 -0
  87. package/dist/tools/actors.js +14 -10
  88. package/dist/tools/actors.js.map +1 -0
  89. package/dist/tools/animation.d.ts +15 -23
  90. package/dist/tools/animation.d.ts.map +1 -0
  91. package/dist/tools/animation.js +17 -13
  92. package/dist/tools/animation.js.map +1 -0
  93. package/dist/tools/assets.d.ts.map +1 -0
  94. package/dist/tools/assets.js +18 -12
  95. package/dist/tools/assets.js.map +1 -0
  96. package/dist/tools/audio.d.ts +10 -10
  97. package/dist/tools/audio.d.ts.map +1 -0
  98. package/dist/tools/audio.js.map +1 -0
  99. package/dist/tools/base-tool.d.ts.map +1 -0
  100. package/dist/tools/base-tool.js.map +1 -0
  101. package/dist/tools/behavior-tree.d.ts +24 -24
  102. package/dist/tools/behavior-tree.d.ts.map +1 -0
  103. package/dist/tools/behavior-tree.js.map +1 -0
  104. package/dist/tools/blueprint.d.ts +14 -3
  105. package/dist/tools/blueprint.d.ts.map +1 -0
  106. package/dist/tools/blueprint.js +5 -3
  107. package/dist/tools/blueprint.js.map +1 -0
  108. package/dist/tools/consolidated-tool-definitions.d.ts +32 -32
  109. package/dist/tools/consolidated-tool-definitions.d.ts.map +1 -0
  110. package/dist/tools/consolidated-tool-definitions.js.map +1 -0
  111. package/dist/tools/consolidated-tool-handlers.d.ts +1 -1
  112. package/dist/tools/consolidated-tool-handlers.d.ts.map +1 -0
  113. package/dist/tools/consolidated-tool-handlers.js +26 -21
  114. package/dist/tools/consolidated-tool-handlers.js.map +1 -0
  115. package/dist/tools/debug.d.ts +25 -7
  116. package/dist/tools/debug.d.ts.map +1 -0
  117. package/dist/tools/debug.js +3 -1
  118. package/dist/tools/debug.js.map +1 -0
  119. package/dist/tools/dynamic-handler-registry.d.ts +1 -1
  120. package/dist/tools/dynamic-handler-registry.d.ts.map +1 -0
  121. package/dist/tools/dynamic-handler-registry.js +3 -1
  122. package/dist/tools/dynamic-handler-registry.js.map +1 -0
  123. package/dist/tools/editor.d.ts.map +1 -0
  124. package/dist/tools/editor.js +8 -6
  125. package/dist/tools/editor.js.map +1 -0
  126. package/dist/tools/engine.d.ts +1 -1
  127. package/dist/tools/engine.d.ts.map +1 -0
  128. package/dist/tools/engine.js +4 -2
  129. package/dist/tools/engine.js.map +1 -0
  130. package/dist/tools/environment.d.ts.map +1 -0
  131. package/dist/tools/environment.js +4 -3
  132. package/dist/tools/environment.js.map +1 -0
  133. package/dist/tools/foliage.d.ts.map +1 -0
  134. package/dist/tools/foliage.js +8 -8
  135. package/dist/tools/foliage.js.map +1 -0
  136. package/dist/tools/handlers/actor-handlers.d.ts +2 -1
  137. package/dist/tools/handlers/actor-handlers.d.ts.map +1 -0
  138. package/dist/tools/handlers/actor-handlers.js +56 -33
  139. package/dist/tools/handlers/actor-handlers.js.map +1 -0
  140. package/dist/tools/handlers/animation-handlers.d.ts +2 -1
  141. package/dist/tools/handlers/animation-handlers.d.ts.map +1 -0
  142. package/dist/tools/handlers/animation-handlers.js +74 -67
  143. package/dist/tools/handlers/animation-handlers.js.map +1 -0
  144. package/dist/tools/handlers/argument-helper.d.ts +24 -4
  145. package/dist/tools/handlers/argument-helper.d.ts.map +1 -0
  146. package/dist/tools/handlers/argument-helper.js +139 -4
  147. package/dist/tools/handlers/argument-helper.js.map +1 -0
  148. package/dist/tools/handlers/asset-handlers.d.ts +2 -1
  149. package/dist/tools/handlers/asset-handlers.d.ts.map +1 -0
  150. package/dist/tools/handlers/asset-handlers.js +155 -94
  151. package/dist/tools/handlers/asset-handlers.js.map +1 -0
  152. package/dist/tools/handlers/audio-handlers.d.ts +2 -1
  153. package/dist/tools/handlers/audio-handlers.d.ts.map +1 -0
  154. package/dist/tools/handlers/audio-handlers.js +82 -80
  155. package/dist/tools/handlers/audio-handlers.js.map +1 -0
  156. package/dist/tools/handlers/blueprint-handlers.d.ts +3 -5
  157. package/dist/tools/handlers/blueprint-handlers.d.ts.map +1 -0
  158. package/dist/tools/handlers/blueprint-handlers.js +150 -142
  159. package/dist/tools/handlers/blueprint-handlers.js.map +1 -0
  160. package/dist/tools/handlers/common-handlers.d.ts +2 -3
  161. package/dist/tools/handlers/common-handlers.d.ts.map +1 -0
  162. package/dist/tools/handlers/common-handlers.js.map +1 -0
  163. package/dist/tools/handlers/editor-handlers.d.ts.map +1 -0
  164. package/dist/tools/handlers/editor-handlers.js +12 -2
  165. package/dist/tools/handlers/editor-handlers.js.map +1 -0
  166. package/dist/tools/handlers/effect-handlers.d.ts +2 -1
  167. package/dist/tools/handlers/effect-handlers.d.ts.map +1 -0
  168. package/dist/tools/handlers/effect-handlers.js +70 -68
  169. package/dist/tools/handlers/effect-handlers.js.map +1 -0
  170. package/dist/tools/handlers/environment-handlers.d.ts +2 -1
  171. package/dist/tools/handlers/environment-handlers.d.ts.map +1 -0
  172. package/dist/tools/handlers/environment-handlers.js +86 -74
  173. package/dist/tools/handlers/environment-handlers.js.map +1 -0
  174. package/dist/tools/handlers/graph-handlers.d.ts +1 -1
  175. package/dist/tools/handlers/graph-handlers.d.ts.map +1 -0
  176. package/dist/tools/handlers/graph-handlers.js +63 -2
  177. package/dist/tools/handlers/graph-handlers.js.map +1 -0
  178. package/dist/tools/handlers/input-handlers.d.ts +2 -5
  179. package/dist/tools/handlers/input-handlers.d.ts.map +1 -0
  180. package/dist/tools/handlers/input-handlers.js +5 -4
  181. package/dist/tools/handlers/input-handlers.js.map +1 -0
  182. package/dist/tools/handlers/inspect-handlers.d.ts +2 -1
  183. package/dist/tools/handlers/inspect-handlers.d.ts.map +1 -0
  184. package/dist/tools/handlers/inspect-handlers.js +61 -37
  185. package/dist/tools/handlers/inspect-handlers.js.map +1 -0
  186. package/dist/tools/handlers/level-handlers.d.ts +2 -2
  187. package/dist/tools/handlers/level-handlers.d.ts.map +1 -0
  188. package/dist/tools/handlers/level-handlers.js +43 -39
  189. package/dist/tools/handlers/level-handlers.js.map +1 -0
  190. package/dist/tools/handlers/lighting-handlers.d.ts +12 -1
  191. package/dist/tools/handlers/lighting-handlers.d.ts.map +1 -0
  192. package/dist/tools/handlers/lighting-handlers.js +90 -47
  193. package/dist/tools/handlers/lighting-handlers.js.map +1 -0
  194. package/dist/tools/handlers/performance-handlers.d.ts +2 -1
  195. package/dist/tools/handlers/performance-handlers.d.ts.map +1 -0
  196. package/dist/tools/handlers/performance-handlers.js +55 -40
  197. package/dist/tools/handlers/performance-handlers.js.map +1 -0
  198. package/dist/tools/handlers/pipeline-handlers.d.ts.map +1 -0
  199. package/dist/tools/handlers/pipeline-handlers.js.map +1 -0
  200. package/dist/tools/handlers/sequence-handlers.d.ts.map +1 -0
  201. package/dist/tools/handlers/sequence-handlers.js.map +1 -0
  202. package/dist/tools/handlers/system-handlers.d.ts +3 -2
  203. package/dist/tools/handlers/system-handlers.d.ts.map +1 -0
  204. package/dist/tools/handlers/system-handlers.js +105 -52
  205. package/dist/tools/handlers/system-handlers.js.map +1 -0
  206. package/dist/tools/input.d.ts.map +1 -0
  207. package/dist/tools/input.js +3 -1
  208. package/dist/tools/input.js.map +1 -0
  209. package/dist/tools/introspection.d.ts +14 -14
  210. package/dist/tools/introspection.d.ts.map +1 -0
  211. package/dist/tools/introspection.js +54 -45
  212. package/dist/tools/introspection.js.map +1 -0
  213. package/dist/tools/landscape.d.ts.map +1 -0
  214. package/dist/tools/landscape.js +15 -13
  215. package/dist/tools/landscape.js.map +1 -0
  216. package/dist/tools/level.d.ts.map +1 -0
  217. package/dist/tools/level.js +3 -2
  218. package/dist/tools/level.js.map +1 -0
  219. package/dist/tools/lighting.d.ts +32 -59
  220. package/dist/tools/lighting.d.ts.map +1 -0
  221. package/dist/tools/lighting.js +56 -19
  222. package/dist/tools/lighting.js.map +1 -0
  223. package/dist/tools/logs.d.ts.map +1 -0
  224. package/dist/tools/logs.js +2 -1
  225. package/dist/tools/logs.js.map +1 -0
  226. package/dist/tools/materials.d.ts +42 -14
  227. package/dist/tools/materials.d.ts.map +1 -0
  228. package/dist/tools/materials.js +15 -9
  229. package/dist/tools/materials.js.map +1 -0
  230. package/dist/tools/niagara.d.ts +63 -39
  231. package/dist/tools/niagara.d.ts.map +1 -0
  232. package/dist/tools/niagara.js +43 -33
  233. package/dist/tools/niagara.js.map +1 -0
  234. package/dist/tools/performance.d.ts +12 -11
  235. package/dist/tools/performance.d.ts.map +1 -0
  236. package/dist/tools/performance.js +3 -2
  237. package/dist/tools/performance.js.map +1 -0
  238. package/dist/tools/physics.d.ts +37 -20
  239. package/dist/tools/physics.d.ts.map +1 -0
  240. package/dist/tools/physics.js +37 -30
  241. package/dist/tools/physics.js.map +1 -0
  242. package/dist/tools/property-dictionary.d.ts.map +1 -0
  243. package/dist/tools/property-dictionary.js.map +1 -0
  244. package/dist/tools/sequence.d.ts +1 -1
  245. package/dist/tools/sequence.d.ts.map +1 -0
  246. package/dist/tools/sequence.js +8 -4
  247. package/dist/tools/sequence.js.map +1 -0
  248. package/dist/tools/tool-definition-utils.d.ts.map +1 -0
  249. package/dist/tools/tool-definition-utils.js.map +1 -0
  250. package/dist/tools/ui.d.ts +11 -11
  251. package/dist/tools/ui.d.ts.map +1 -0
  252. package/dist/tools/ui.js +7 -3
  253. package/dist/tools/ui.js.map +1 -0
  254. package/dist/types/automation-responses.d.ts.map +1 -0
  255. package/dist/types/automation-responses.js.map +1 -0
  256. package/dist/types/env.d.ts.map +1 -0
  257. package/dist/types/env.js.map +1 -0
  258. package/dist/types/handler-types.d.ts +112 -3
  259. package/dist/types/handler-types.d.ts.map +1 -0
  260. package/dist/types/handler-types.js.map +1 -0
  261. package/dist/types/tool-interfaces.d.ts +39 -21
  262. package/dist/types/tool-interfaces.d.ts.map +1 -0
  263. package/dist/types/tool-interfaces.js.map +1 -0
  264. package/dist/types/tool-types.d.ts +8 -8
  265. package/dist/types/tool-types.d.ts.map +1 -0
  266. package/dist/types/tool-types.js.map +1 -0
  267. package/dist/unreal-bridge.d.ts +8 -6
  268. package/dist/unreal-bridge.d.ts.map +1 -0
  269. package/dist/unreal-bridge.js +16 -3
  270. package/dist/unreal-bridge.js.map +1 -0
  271. package/dist/utils/command-validator.d.ts.map +1 -0
  272. package/dist/utils/command-validator.js.map +1 -0
  273. package/dist/utils/elicitation.d.ts +2 -5
  274. package/dist/utils/elicitation.d.ts.map +1 -0
  275. package/dist/utils/elicitation.js +3 -2
  276. package/dist/utils/elicitation.js.map +1 -0
  277. package/dist/utils/error-handler.d.ts.map +1 -0
  278. package/dist/utils/error-handler.js.map +1 -0
  279. package/dist/utils/ini-reader.d.ts +1 -1
  280. package/dist/utils/ini-reader.d.ts.map +1 -0
  281. package/dist/utils/ini-reader.js.map +1 -0
  282. package/dist/utils/logger.d.ts +4 -4
  283. package/dist/utils/logger.d.ts.map +1 -0
  284. package/dist/utils/logger.js.map +1 -0
  285. package/dist/utils/normalize.d.ts +2 -2
  286. package/dist/utils/normalize.d.ts.map +1 -0
  287. package/dist/utils/normalize.js +4 -3
  288. package/dist/utils/normalize.js.map +1 -0
  289. package/dist/utils/path-security.d.ts.map +1 -0
  290. package/dist/utils/path-security.js.map +1 -0
  291. package/dist/utils/response-factory.d.ts +2 -2
  292. package/dist/utils/response-factory.d.ts.map +1 -0
  293. package/dist/utils/response-factory.js +3 -1
  294. package/dist/utils/response-factory.js.map +1 -0
  295. package/dist/utils/response-validator.d.ts +4 -4
  296. package/dist/utils/response-validator.d.ts.map +1 -0
  297. package/dist/utils/response-validator.js +31 -23
  298. package/dist/utils/response-validator.js.map +1 -0
  299. package/dist/utils/result-helpers.d.ts.map +1 -0
  300. package/dist/utils/result-helpers.js.map +1 -0
  301. package/dist/utils/safe-json.d.ts.map +1 -0
  302. package/dist/utils/safe-json.js.map +1 -0
  303. package/dist/utils/unreal-command-queue.d.ts +2 -2
  304. package/dist/utils/unreal-command-queue.d.ts.map +1 -0
  305. package/dist/utils/unreal-command-queue.js +4 -3
  306. package/dist/utils/unreal-command-queue.js.map +1 -0
  307. package/dist/utils/validation.d.ts +1 -1
  308. package/dist/utils/validation.d.ts.map +1 -0
  309. package/dist/utils/validation.js.map +1 -0
  310. package/dist/wasm/index.d.ts +2 -2
  311. package/dist/wasm/index.d.ts.map +1 -0
  312. package/dist/wasm/index.js +11 -7
  313. package/dist/wasm/index.js.map +1 -0
  314. package/package.json +12 -34
  315. package/server.json +2 -2
  316. package/.dockerignore +0 -57
  317. package/.env.example +0 -26
  318. package/.env.production +0 -61
  319. package/.eslintrc.json +0 -0
  320. package/.eslintrc.override.json +0 -8
  321. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -94
  322. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  323. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -56
  324. package/.github/copilot-instructions.md +0 -478
  325. package/.github/dependabot.yml +0 -19
  326. package/.github/labeler.yml +0 -24
  327. package/.github/labels.yml +0 -70
  328. package/.github/pull_request_template.md +0 -42
  329. package/.github/release-drafter-config.yml +0 -51
  330. package/.github/workflows/auto-merge.yml +0 -38
  331. package/.github/workflows/ci.yml +0 -38
  332. package/.github/workflows/dependency-review.yml +0 -17
  333. package/.github/workflows/gemini-issue-triage.yml +0 -172
  334. package/.github/workflows/greetings.yml +0 -27
  335. package/.github/workflows/labeler.yml +0 -17
  336. package/.github/workflows/links.yml +0 -80
  337. package/.github/workflows/pr-size-labeler.yml +0 -137
  338. package/.github/workflows/publish-mcp.yml +0 -79
  339. package/.github/workflows/release-drafter.yml +0 -24
  340. package/.github/workflows/release.yml +0 -112
  341. package/.github/workflows/semantic-pull-request.yml +0 -35
  342. package/.github/workflows/smoke-test.yml +0 -36
  343. package/.github/workflows/stale.yml +0 -28
  344. package/CONTRIBUTING.md +0 -140
  345. package/Dockerfile +0 -37
  346. package/GEMINI.md +0 -115
  347. package/Public/Plugin_setup_guide.mp4 +0 -0
  348. package/Public/icon.png +0 -0
  349. package/claude_desktop_config_example.json +0 -15
  350. package/dist/types/responses.d.ts +0 -249
  351. package/dist/types/responses.js +0 -2
  352. package/docs/GraphQL-API.md +0 -888
  353. package/docs/Migration-Guide-v0.5.0.md +0 -684
  354. package/docs/Roadmap.md +0 -53
  355. package/docs/WebAssembly-Integration.md +0 -628
  356. package/docs/editor-plugin-extension.md +0 -370
  357. package/docs/handler-mapping.md +0 -249
  358. package/docs/native-automation-progress.md +0 -128
  359. package/docs/testing-guide.md +0 -423
  360. package/eslint.config.mjs +0 -68
  361. package/mcp-config-example.json +0 -14
  362. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +0 -8
  363. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +0 -64
  364. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +0 -189
  365. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +0 -22
  366. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +0 -30
  367. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +0 -1983
  368. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +0 -72
  369. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +0 -46
  370. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +0 -846
  371. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +0 -2393
  372. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +0 -300
  373. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +0 -2807
  374. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +0 -1087
  375. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +0 -488
  376. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +0 -643
  377. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +0 -31
  378. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +0 -1094
  379. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +0 -5750
  380. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +0 -152
  381. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +0 -2614
  382. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +0 -42
  383. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +0 -1237
  384. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +0 -1725
  385. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +0 -2265
  386. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +0 -954
  387. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +0 -209
  388. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +0 -41
  389. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +0 -1164
  390. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +0 -762
  391. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +0 -663
  392. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +0 -136
  393. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +0 -494
  394. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +0 -278
  395. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +0 -625
  396. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +0 -401
  397. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +0 -67
  398. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +0 -472
  399. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +0 -2634
  400. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +0 -189
  401. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +0 -917
  402. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +0 -39
  403. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +0 -2706
  404. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +0 -519
  405. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +0 -38
  406. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +0 -668
  407. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +0 -346
  408. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +0 -1345
  409. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +0 -149
  410. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +0 -782
  411. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +0 -115
  412. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +0 -796
  413. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +0 -117
  414. package/scripts/check-unreal-connection.mjs +0 -19
  415. package/scripts/clean-tmp.js +0 -23
  416. package/scripts/patch-wasm.js +0 -26
  417. package/scripts/run-all-tests.mjs +0 -136
  418. package/scripts/smoke-test.ts +0 -94
  419. package/scripts/sync-mcp-plugin.js +0 -143
  420. package/scripts/test-no-plugin-alternates.mjs +0 -113
  421. package/scripts/validate-server.js +0 -46
  422. package/scripts/verify-automation-bridge.js +0 -200
  423. package/src/automation/bridge.ts +0 -630
  424. package/src/automation/connection-manager.ts +0 -148
  425. package/src/automation/handshake.ts +0 -99
  426. package/src/automation/index.ts +0 -2
  427. package/src/automation/message-handler.ts +0 -192
  428. package/src/automation/request-tracker.ts +0 -155
  429. package/src/automation/types.ts +0 -108
  430. package/src/cli.ts +0 -34
  431. package/src/config/class-aliases.ts +0 -65
  432. package/src/config.ts +0 -73
  433. package/src/constants.ts +0 -29
  434. package/src/graphql/loaders.ts +0 -244
  435. package/src/graphql/resolvers.ts +0 -1008
  436. package/src/graphql/schema.ts +0 -452
  437. package/src/graphql/server.ts +0 -156
  438. package/src/graphql/types.ts +0 -10
  439. package/src/handlers/resource-handlers.ts +0 -186
  440. package/src/index.ts +0 -243
  441. package/src/resources/actors.ts +0 -127
  442. package/src/resources/assets.ts +0 -286
  443. package/src/resources/levels.ts +0 -68
  444. package/src/server/resource-registry.ts +0 -47
  445. package/src/server/tool-registry.ts +0 -354
  446. package/src/server-setup.ts +0 -114
  447. package/src/services/health-monitor.ts +0 -132
  448. package/src/services/metrics-server.ts +0 -176
  449. package/src/tools/actors.ts +0 -564
  450. package/src/tools/animation.ts +0 -941
  451. package/src/tools/assets.ts +0 -394
  452. package/src/tools/audio.ts +0 -499
  453. package/src/tools/base-tool.ts +0 -52
  454. package/src/tools/behavior-tree.ts +0 -45
  455. package/src/tools/blueprint.ts +0 -940
  456. package/src/tools/consolidated-tool-definitions.ts +0 -1256
  457. package/src/tools/consolidated-tool-handlers.ts +0 -302
  458. package/src/tools/debug.ts +0 -622
  459. package/src/tools/dynamic-handler-registry.ts +0 -33
  460. package/src/tools/editor.ts +0 -435
  461. package/src/tools/engine.ts +0 -43
  462. package/src/tools/environment.ts +0 -281
  463. package/src/tools/foliage.ts +0 -596
  464. package/src/tools/handlers/actor-handlers.ts +0 -244
  465. package/src/tools/handlers/animation-handlers.ts +0 -237
  466. package/src/tools/handlers/argument-helper.ts +0 -142
  467. package/src/tools/handlers/asset-handlers.ts +0 -550
  468. package/src/tools/handlers/audio-handlers.ts +0 -194
  469. package/src/tools/handlers/blueprint-handlers.ts +0 -380
  470. package/src/tools/handlers/common-handlers.ts +0 -108
  471. package/src/tools/handlers/editor-handlers.ts +0 -124
  472. package/src/tools/handlers/effect-handlers.ts +0 -224
  473. package/src/tools/handlers/environment-handlers.ts +0 -183
  474. package/src/tools/handlers/graph-handlers.ts +0 -117
  475. package/src/tools/handlers/input-handlers.ts +0 -28
  476. package/src/tools/handlers/inspect-handlers.ts +0 -450
  477. package/src/tools/handlers/level-handlers.ts +0 -253
  478. package/src/tools/handlers/lighting-handlers.ts +0 -151
  479. package/src/tools/handlers/performance-handlers.ts +0 -132
  480. package/src/tools/handlers/pipeline-handlers.ts +0 -194
  481. package/src/tools/handlers/sequence-handlers.ts +0 -438
  482. package/src/tools/handlers/system-handlers.ts +0 -564
  483. package/src/tools/input.ts +0 -160
  484. package/src/tools/introspection.ts +0 -689
  485. package/src/tools/landscape.ts +0 -649
  486. package/src/tools/level.ts +0 -989
  487. package/src/tools/lighting.ts +0 -1052
  488. package/src/tools/logs.ts +0 -219
  489. package/src/tools/materials.ts +0 -295
  490. package/src/tools/niagara.ts +0 -485
  491. package/src/tools/performance.ts +0 -661
  492. package/src/tools/physics.ts +0 -679
  493. package/src/tools/property-dictionary.ts +0 -98
  494. package/src/tools/sequence.ts +0 -385
  495. package/src/tools/tool-definition-utils.ts +0 -35
  496. package/src/tools/ui.ts +0 -452
  497. package/src/types/automation-responses.ts +0 -119
  498. package/src/types/env.ts +0 -17
  499. package/src/types/handler-types.ts +0 -442
  500. package/src/types/responses.ts +0 -355
  501. package/src/types/tool-interfaces.ts +0 -250
  502. package/src/types/tool-types.ts +0 -575
  503. package/src/unreal-bridge.ts +0 -693
  504. package/src/utils/command-validator.ts +0 -139
  505. package/src/utils/elicitation.ts +0 -132
  506. package/src/utils/error-handler.ts +0 -287
  507. package/src/utils/ini-reader.ts +0 -86
  508. package/src/utils/logger.ts +0 -35
  509. package/src/utils/normalize.test.ts +0 -162
  510. package/src/utils/normalize.ts +0 -146
  511. package/src/utils/path-security.ts +0 -43
  512. package/src/utils/response-factory.ts +0 -44
  513. package/src/utils/response-validator.ts +0 -395
  514. package/src/utils/result-helpers.ts +0 -195
  515. package/src/utils/safe-json.test.ts +0 -90
  516. package/src/utils/safe-json.ts +0 -70
  517. package/src/utils/unreal-command-queue.ts +0 -166
  518. package/src/utils/validation.test.ts +0 -184
  519. package/src/utils/validation.ts +0 -312
  520. package/src/wasm/index.ts +0 -838
  521. package/test-server.mjs +0 -100
  522. package/tests/test-animation.mjs +0 -369
  523. package/tests/test-asset-advanced.mjs +0 -82
  524. package/tests/test-asset-graph.mjs +0 -311
  525. package/tests/test-audio.mjs +0 -417
  526. package/tests/test-automation-timeouts.mjs +0 -98
  527. package/tests/test-behavior-tree.mjs +0 -444
  528. package/tests/test-blueprint-graph.mjs +0 -410
  529. package/tests/test-blueprint.mjs +0 -577
  530. package/tests/test-client-mode.mjs +0 -86
  531. package/tests/test-console-command.mjs +0 -56
  532. package/tests/test-control-actor.mjs +0 -425
  533. package/tests/test-control-editor.mjs +0 -112
  534. package/tests/test-graphql.mjs +0 -372
  535. package/tests/test-input.mjs +0 -349
  536. package/tests/test-inspect.mjs +0 -302
  537. package/tests/test-landscape.mjs +0 -316
  538. package/tests/test-lighting.mjs +0 -428
  539. package/tests/test-manage-asset.mjs +0 -438
  540. package/tests/test-manage-level.mjs +0 -89
  541. package/tests/test-materials.mjs +0 -356
  542. package/tests/test-niagara.mjs +0 -185
  543. package/tests/test-no-inline-python.mjs +0 -122
  544. package/tests/test-performance.mjs +0 -539
  545. package/tests/test-plugin-handshake.mjs +0 -82
  546. package/tests/test-runner.mjs +0 -993
  547. package/tests/test-sequence.mjs +0 -104
  548. package/tests/test-system.mjs +0 -96
  549. package/tests/test-wasm.mjs +0 -283
  550. package/tests/test-world-partition.mjs +0 -215
  551. package/tsconfig.json +0 -56
  552. package/vitest.config.ts +0 -35
  553. package/wasm/Cargo.lock +0 -363
  554. package/wasm/Cargo.toml +0 -42
  555. package/wasm/LICENSE +0 -21
  556. package/wasm/README.md +0 -253
  557. package/wasm/src/dependency_resolver.rs +0 -377
  558. package/wasm/src/lib.rs +0 -153
  559. package/wasm/src/property_parser.rs +0 -271
  560. package/wasm/src/transform_math.rs +0 -396
  561. package/wasm/tests/integration.rs +0 -109
@@ -1,1094 +0,0 @@
1
- #include "McpAutomationBridgeGlobals.h"
2
- #include "McpAutomationBridgeHelpers.h"
3
- #include "McpAutomationBridgeSubsystem.h"
4
- #include "Misc/ScopeExit.h"
5
-
6
- #if WITH_EDITOR
7
- #include "EdGraph/EdGraph.h"
8
- #include "EdGraph/EdGraphNode.h"
9
- #include "EdGraph/EdGraphPin.h"
10
- #include "EdGraph/EdGraphSchema.h"
11
- #include "EdGraphNode_Comment.h"
12
- #include "Engine/Blueprint.h"
13
- #include "K2Node_BreakStruct.h"
14
- #include "K2Node_CallFunction.h"
15
- #include "K2Node_CommutativeAssociativeBinaryOperator.h"
16
- #include "K2Node_CustomEvent.h"
17
- #include "K2Node_DynamicCast.h"
18
- #include "K2Node_Event.h"
19
- #include "K2Node_ExecutionSequence.h"
20
- #include "K2Node_FunctionEntry.h"
21
- #include "K2Node_FunctionResult.h"
22
- #include "K2Node_IfThenElse.h"
23
- #include "K2Node_InputAxisEvent.h"
24
- #include "K2Node_Knot.h"
25
- #include "K2Node_Literal.h"
26
- #include "K2Node_MakeArray.h"
27
- #include "K2Node_MakeStruct.h"
28
- #include "K2Node_PromotableOperator.h"
29
- #include "K2Node_Select.h"
30
- #include "K2Node_Self.h"
31
- #include "K2Node_Timeline.h"
32
- #include "K2Node_VariableGet.h"
33
- #include "K2Node_VariableSet.h"
34
- #include "Kismet/GameplayStatics.h"
35
- #include "Kismet/KismetMathLibrary.h"
36
- #include "Kismet/KismetSystemLibrary.h"
37
- #include "Kismet2/BlueprintEditorUtils.h"
38
- #include "Kismet2/KismetEditorUtilities.h"
39
-
40
- #endif
41
-
42
- /**
43
- * Process a "manage_blueprint_graph" automation request to inspect or modify a
44
- * Blueprint graph.
45
- *
46
- * The Payload JSON controls the specific operation via the "subAction" field
47
- * (examples: create_node, connect_pins, get_nodes, break_pin_links,
48
- * delete_node, create_reroute_node, set_node_property, get_node_details,
49
- * get_graph_details, get_pin_details). In editor builds this function performs
50
- * graph/blueprint lookups and edits; in non-editor builds it reports an
51
- * editor-only error.
52
- *
53
- * @param RequestId Unique identifier for the automation request (used in
54
- * responses).
55
- * @param Action The requested action name; this handler only processes
56
- * "manage_blueprint_graph".
57
- * @param Payload JSON object containing action options such as
58
- * "assetPath"/"blueprintPath", "graphName", "subAction" and subaction-specific
59
- * fields (nodeType, nodeId, pin names, positions, etc.).
60
- * @param RequestingSocket WebSocket used to send responses and errors back to
61
- * the requester.
62
- * @return `true` if the request was handled by this function (Action ==
63
- * "manage_blueprint_graph"), `false` otherwise.
64
- */
65
- bool UMcpAutomationBridgeSubsystem::HandleBlueprintGraphAction(
66
- const FString &RequestId, const FString &Action,
67
- const TSharedPtr<FJsonObject> &Payload,
68
- TSharedPtr<FMcpBridgeWebSocket> RequestingSocket) {
69
- if (Action != TEXT("manage_blueprint_graph")) {
70
- return false;
71
- }
72
-
73
- #if WITH_EDITOR
74
- if (!Payload.IsValid()) {
75
- SendAutomationError(RequestingSocket, RequestId,
76
- TEXT("Missing payload for blueprint graph action."),
77
- TEXT("INVALID_PAYLOAD"));
78
- return true;
79
- }
80
-
81
- FString AssetPath;
82
- if (!Payload->TryGetStringField(TEXT("assetPath"), AssetPath) ||
83
- AssetPath.IsEmpty()) {
84
- // Allow callers to use "blueprintPath" (as exposed by the consolidated
85
- // tool schema) as an alias for assetPath so tests and tools do not need
86
- // to duplicate the same value under two keys.
87
- FString BlueprintPath;
88
- Payload->TryGetStringField(TEXT("blueprintPath"), BlueprintPath);
89
- if (!BlueprintPath.IsEmpty()) {
90
- AssetPath = BlueprintPath;
91
- }
92
- }
93
-
94
- if (AssetPath.IsEmpty()) {
95
- SendAutomationError(
96
- RequestingSocket, RequestId,
97
- TEXT("Missing 'assetPath' or 'blueprintPath' in payload."),
98
- TEXT("INVALID_ARGUMENT"));
99
- return true;
100
- }
101
-
102
- UBlueprint *Blueprint = LoadObject<UBlueprint>(nullptr, *AssetPath);
103
- if (!Blueprint) {
104
- SendAutomationError(
105
- RequestingSocket, RequestId,
106
- FString::Printf(TEXT("Could not load blueprint at path: %s"),
107
- *AssetPath),
108
- TEXT("ASSET_NOT_FOUND"));
109
- return true;
110
- }
111
-
112
- FString GraphName;
113
- Payload->TryGetStringField(TEXT("graphName"), GraphName);
114
- UEdGraph *TargetGraph = nullptr;
115
-
116
- // Find the target graph
117
- if (GraphName.IsEmpty() ||
118
- GraphName.Equals(TEXT("EventGraph"), ESearchCase::IgnoreCase)) {
119
- // Default to the main ubergraph/event graph
120
- if (Blueprint->UbergraphPages.Num() > 0) {
121
- TargetGraph = Blueprint->UbergraphPages[0];
122
- }
123
- } else {
124
- // Search in FunctionGraphs and UbergraphPages
125
- for (UEdGraph *Graph : Blueprint->FunctionGraphs) {
126
- if (Graph->GetName() == GraphName) {
127
- TargetGraph = Graph;
128
- break;
129
- }
130
- }
131
- if (!TargetGraph) {
132
- for (UEdGraph *Graph : Blueprint->UbergraphPages) {
133
- if (Graph->GetName() == GraphName) {
134
- TargetGraph = Graph;
135
- break;
136
- }
137
- }
138
- }
139
- }
140
-
141
- if (!TargetGraph) {
142
- // Fallback: try finding by name in all graphs
143
- TArray<UEdGraph *> AllGraphs;
144
- Blueprint->GetAllGraphs(AllGraphs);
145
- for (UEdGraph *Graph : AllGraphs) {
146
- if (Graph->GetName() == GraphName) {
147
- TargetGraph = Graph;
148
- break;
149
- }
150
- }
151
- }
152
-
153
- if (!TargetGraph) {
154
- SendAutomationError(
155
- RequestingSocket, RequestId,
156
- FString::Printf(TEXT("Could not find graph '%s' in blueprint."),
157
- *GraphName),
158
- TEXT("GRAPH_NOT_FOUND"));
159
- return true;
160
- }
161
-
162
- const FString SubAction = Payload->GetStringField(TEXT("subAction"));
163
-
164
- // Node identifier interoperability:
165
- // - Prefer NodeGuid strings for stable references.
166
- // - Accept node UObject names (e.g. "K2Node_Event_0") for clients that
167
- // mistakenly pass nodeName where nodeId is expected.
168
- auto FindNodeByIdOrName = [&](const FString &Id) -> UEdGraphNode * {
169
- if (Id.IsEmpty()) {
170
- return nullptr;
171
- }
172
-
173
- for (UEdGraphNode *Node : TargetGraph->Nodes) {
174
- if (!Node) {
175
- continue;
176
- }
177
-
178
- if (Node->NodeGuid.ToString().Equals(Id, ESearchCase::IgnoreCase) ||
179
- Node->GetName().Equals(Id, ESearchCase::IgnoreCase)) {
180
- return Node;
181
- }
182
- }
183
-
184
- return nullptr;
185
- };
186
-
187
- if (SubAction == TEXT("create_node")) {
188
- const FScopedTransaction Transaction(
189
- FText::FromString(TEXT("Create Blueprint Node")));
190
- Blueprint->Modify();
191
- TargetGraph->Modify();
192
-
193
- FString NodeType;
194
- Payload->TryGetStringField(TEXT("nodeType"), NodeType);
195
- float X = 0.0f;
196
- float Y = 0.0f;
197
- Payload->TryGetNumberField(TEXT("x"), X);
198
- Payload->TryGetNumberField(TEXT("y"), Y);
199
-
200
- // Helper to finalize and report
201
- auto FinalizeAndReport = [&](auto &NodeCreator, UEdGraphNode *NewNode) {
202
- if (NewNode) {
203
- // Set position BEFORE finalization per FGraphNodeCreator pattern
204
- NewNode->NodePosX = X;
205
- NewNode->NodePosY = Y;
206
-
207
- // Finalize() calls CreateNewGuid(), PostPlacedNewNode(), and
208
- // AllocateDefaultPins() if pins are empty. Do NOT call
209
- // AllocateDefaultPins() again after this!
210
- NodeCreator.Finalize();
211
-
212
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
213
-
214
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
215
- Result->SetStringField(TEXT("nodeId"), NewNode->NodeGuid.ToString());
216
- Result->SetStringField(TEXT("nodeName"), NewNode->GetName());
217
- SendAutomationResponse(RequestingSocket, RequestId, true,
218
- TEXT("Node created."), Result);
219
- } else {
220
- SendAutomationError(
221
- RequestingSocket, RequestId,
222
- TEXT("Failed to create node (unsupported type or internal error)."),
223
- TEXT("CREATE_FAILED"));
224
- }
225
- };
226
-
227
- // Map common Blueprint node names to their CallFunction equivalents
228
- // This allows users to use nodeType="PrintString" instead of CallFunction
229
- static TMap<FString, TTuple<FString, FString>> CommonFunctionNodes = {
230
- {TEXT("PrintString"),
231
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("PrintString"))},
232
- {TEXT("Print"),
233
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("PrintString"))},
234
- {TEXT("PrintText"),
235
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("PrintText"))},
236
- {TEXT("SetActorLocation"),
237
- MakeTuple(TEXT("AActor"), TEXT("K2_SetActorLocation"))},
238
- {TEXT("GetActorLocation"),
239
- MakeTuple(TEXT("AActor"), TEXT("K2_GetActorLocation"))},
240
- {TEXT("SetActorRotation"),
241
- MakeTuple(TEXT("AActor"), TEXT("K2_SetActorRotation"))},
242
- {TEXT("GetActorRotation"),
243
- MakeTuple(TEXT("AActor"), TEXT("K2_GetActorRotation"))},
244
- {TEXT("SetActorTransform"),
245
- MakeTuple(TEXT("AActor"), TEXT("K2_SetActorTransform"))},
246
- {TEXT("GetActorTransform"),
247
- MakeTuple(TEXT("AActor"), TEXT("K2_GetActorTransform"))},
248
- {TEXT("AddActorLocalOffset"),
249
- MakeTuple(TEXT("AActor"), TEXT("K2_AddActorLocalOffset"))},
250
- {TEXT("Delay"), MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("Delay"))},
251
- {TEXT("DestroyActor"),
252
- MakeTuple(TEXT("AActor"), TEXT("K2_DestroyActor"))},
253
- {TEXT("SpawnActor"),
254
- MakeTuple(TEXT("UGameplayStatics"),
255
- TEXT("BeginDeferredActorSpawnFromClass"))},
256
- {TEXT("GetPlayerPawn"),
257
- MakeTuple(TEXT("UGameplayStatics"), TEXT("GetPlayerPawn"))},
258
- {TEXT("GetPlayerController"),
259
- MakeTuple(TEXT("UGameplayStatics"), TEXT("GetPlayerController"))},
260
- {TEXT("PlaySound"),
261
- MakeTuple(TEXT("UGameplayStatics"), TEXT("PlaySound2D"))},
262
- {TEXT("PlaySound2D"),
263
- MakeTuple(TEXT("UGameplayStatics"), TEXT("PlaySound2D"))},
264
- {TEXT("PlaySoundAtLocation"),
265
- MakeTuple(TEXT("UGameplayStatics"), TEXT("PlaySoundAtLocation"))},
266
- {TEXT("GetWorldDeltaSeconds"),
267
- MakeTuple(TEXT("UGameplayStatics"), TEXT("GetWorldDeltaSeconds"))},
268
- {TEXT("SetTimerByFunctionName"),
269
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("K2_SetTimer"))},
270
- {TEXT("ClearTimer"),
271
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("K2_ClearTimer"))},
272
- {TEXT("IsValid"),
273
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("IsValid"))},
274
- {TEXT("IsValidClass"),
275
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("IsValidClass"))},
276
- // Math Nodes
277
- {TEXT("Add_IntInt"),
278
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Add_IntInt"))},
279
- {TEXT("Subtract_IntInt"),
280
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Subtract_IntInt"))},
281
- {TEXT("Multiply_IntInt"),
282
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Multiply_IntInt"))},
283
- {TEXT("Divide_IntInt"),
284
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Divide_IntInt"))},
285
- {TEXT("Add_DoubleDouble"),
286
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Add_DoubleDouble"))},
287
- {TEXT("Subtract_DoubleDouble"),
288
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Subtract_DoubleDouble"))},
289
- {TEXT("Multiply_DoubleDouble"),
290
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Multiply_DoubleDouble"))},
291
- {TEXT("Divide_DoubleDouble"),
292
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("Divide_DoubleDouble"))},
293
- {TEXT("FTrunc"), MakeTuple(TEXT("UKismetMathLibrary"), TEXT("FTrunc"))},
294
- // Vector Ops
295
- {TEXT("MakeVector"),
296
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("MakeVector"))},
297
- {TEXT("BreakVector"),
298
- MakeTuple(TEXT("UKismetMathLibrary"), TEXT("BreakVector"))},
299
- // Actor/Component Ops
300
- {TEXT("GetComponentByClass"),
301
- MakeTuple(TEXT("AActor"), TEXT("GetComponentByClass"))},
302
- // Timer
303
- {TEXT("GetWorldTimerManager"),
304
- MakeTuple(TEXT("UKismetSystemLibrary"), TEXT("K2_GetTimerManager"))}};
305
-
306
- // Check if this is a common function node shortcut
307
- if (const auto *FuncInfo = CommonFunctionNodes.Find(NodeType)) {
308
- FString ClassName = FuncInfo->Get<0>();
309
- FString FuncName = FuncInfo->Get<1>();
310
-
311
- // Find the class and function BEFORE creating NodeCreator
312
- // (FGraphNodeCreator asserts in destructor if not finalized)
313
- UClass *Class = nullptr;
314
- if (ClassName == TEXT("UKismetSystemLibrary")) {
315
- Class = UKismetSystemLibrary::StaticClass();
316
- } else if (ClassName == TEXT("UGameplayStatics")) {
317
- Class = UGameplayStatics::StaticClass();
318
- } else if (ClassName == TEXT("AActor")) {
319
- Class = AActor::StaticClass();
320
- } else if (ClassName == TEXT("UKismetMathLibrary")) {
321
- Class = UKismetMathLibrary::StaticClass();
322
- } else {
323
- Class = ResolveUClass(ClassName);
324
- }
325
-
326
- UFunction *Func = nullptr;
327
- if (Class) {
328
- Func = Class->FindFunctionByName(*FuncName);
329
- }
330
-
331
- // Return early with error if function not found (before NodeCreator)
332
- if (!Func) {
333
- SendAutomationError(
334
- RequestingSocket, RequestId,
335
- FString::Printf(
336
- TEXT("Could not find function '%s::%s' for node type '%s'"),
337
- *ClassName, *FuncName, *NodeType),
338
- TEXT("FUNCTION_NOT_FOUND"));
339
- return true;
340
- }
341
-
342
- // Now safe to create NodeCreator since we know we'll finalize it
343
- FGraphNodeCreator<UK2Node_CallFunction> NodeCreator(*TargetGraph);
344
- UK2Node_CallFunction *CallFuncNode = NodeCreator.CreateNode(false);
345
- CallFuncNode->SetFromFunction(Func);
346
- FinalizeAndReport(NodeCreator, CallFuncNode);
347
- return true;
348
- }
349
-
350
- // ========================================================================
351
- // DYNAMIC NODE CREATION - Find node classes at runtime
352
- // ========================================================================
353
-
354
- // Helper: Try to find a UK2Node subclass by name
355
- auto FindNodeClassByName = [](const FString &TypeName) -> UClass * {
356
- TArray<FString> NamesToTry;
357
- NamesToTry.Add(TypeName);
358
- NamesToTry.Add(FString::Printf(TEXT("K2Node_%s"), *TypeName));
359
- NamesToTry.Add(FString::Printf(TEXT("UK2Node_%s"), *TypeName));
360
-
361
- for (TObjectIterator<UClass> It; It; ++It) {
362
- if (!It->IsChildOf(UEdGraphNode::StaticClass()))
363
- continue;
364
- if (It->HasAnyClassFlags(CLASS_Abstract))
365
- continue;
366
-
367
- FString ClassName = It->GetName();
368
- for (const FString &NameToMatch : NamesToTry) {
369
- if (ClassName.Equals(NameToMatch, ESearchCase::IgnoreCase)) {
370
- return *It;
371
- }
372
- }
373
- }
374
- return nullptr;
375
- };
376
-
377
- // Special nodes requiring extra parameters
378
- if (NodeType == TEXT("VariableGet") ||
379
- NodeType == TEXT("K2Node_VariableGet")) {
380
- FString VarName;
381
- Payload->TryGetStringField(TEXT("variableName"), VarName);
382
- FName VarFName(*VarName);
383
- bool bFound = false;
384
- for (const FBPVariableDescription &VarDesc : Blueprint->NewVariables) {
385
- if (VarDesc.VarName == VarFName) {
386
- bFound = true;
387
- break;
388
- }
389
- }
390
- if (!bFound && Blueprint->GeneratedClass &&
391
- Blueprint->GeneratedClass->FindPropertyByName(VarFName)) {
392
- bFound = true;
393
- }
394
- if (!bFound) {
395
- SendAutomationError(
396
- RequestingSocket, RequestId,
397
- FString::Printf(TEXT("Variable '%s' not found"), *VarName),
398
- TEXT("VARIABLE_NOT_FOUND"));
399
- return true;
400
- }
401
- FGraphNodeCreator<UK2Node_VariableGet> NodeCreator(*TargetGraph);
402
- UK2Node_VariableGet *VarGet = NodeCreator.CreateNode(false);
403
- VarGet->VariableReference.SetSelfMember(VarFName);
404
- FinalizeAndReport(NodeCreator, VarGet);
405
- return true;
406
- }
407
-
408
- if (NodeType == TEXT("VariableSet") ||
409
- NodeType == TEXT("K2Node_VariableSet")) {
410
- FString VarName;
411
- Payload->TryGetStringField(TEXT("variableName"), VarName);
412
- FName VarFName(*VarName);
413
- bool bFound = false;
414
- for (const FBPVariableDescription &VarDesc : Blueprint->NewVariables) {
415
- if (VarDesc.VarName == VarFName) {
416
- bFound = true;
417
- break;
418
- }
419
- }
420
- if (!bFound && Blueprint->GeneratedClass &&
421
- Blueprint->GeneratedClass->FindPropertyByName(VarFName)) {
422
- bFound = true;
423
- }
424
- if (!bFound) {
425
- SendAutomationError(
426
- RequestingSocket, RequestId,
427
- FString::Printf(TEXT("Variable '%s' not found"), *VarName),
428
- TEXT("VARIABLE_NOT_FOUND"));
429
- return true;
430
- }
431
- FGraphNodeCreator<UK2Node_VariableSet> NodeCreator(*TargetGraph);
432
- UK2Node_VariableSet *VarSet = NodeCreator.CreateNode(false);
433
- VarSet->VariableReference.SetSelfMember(VarFName);
434
- FinalizeAndReport(NodeCreator, VarSet);
435
- return true;
436
- }
437
-
438
- if (NodeType == TEXT("CallFunction") ||
439
- NodeType == TEXT("K2Node_CallFunction") ||
440
- NodeType == TEXT("FunctionCall")) {
441
- FString MemberName, MemberClass;
442
- Payload->TryGetStringField(TEXT("memberName"), MemberName);
443
- Payload->TryGetStringField(TEXT("memberClass"), MemberClass);
444
- UFunction *Func = nullptr;
445
- if (!MemberClass.IsEmpty()) {
446
- if (UClass *Class = ResolveUClass(MemberClass))
447
- Func = Class->FindFunctionByName(*MemberName);
448
- } else {
449
- Func = Blueprint->GeneratedClass->FindFunctionByName(*MemberName);
450
- if (!Func) {
451
- if (UClass *KSL = UKismetSystemLibrary::StaticClass())
452
- Func = KSL->FindFunctionByName(*MemberName);
453
- if (!Func)
454
- if (UClass *GPS = UGameplayStatics::StaticClass())
455
- Func = GPS->FindFunctionByName(*MemberName);
456
- if (!Func)
457
- if (UClass *KML = UKismetMathLibrary::StaticClass())
458
- Func = KML->FindFunctionByName(*MemberName);
459
- }
460
- }
461
- if (Func) {
462
- FGraphNodeCreator<UK2Node_CallFunction> NodeCreator(*TargetGraph);
463
- UK2Node_CallFunction *CallFuncNode = NodeCreator.CreateNode(false);
464
- CallFuncNode->SetFromFunction(Func);
465
- FinalizeAndReport(NodeCreator, CallFuncNode);
466
- } else {
467
- SendAutomationError(
468
- RequestingSocket, RequestId,
469
- FString::Printf(TEXT("Function '%s' not found"), *MemberName),
470
- TEXT("FUNCTION_NOT_FOUND"));
471
- }
472
- return true;
473
- }
474
-
475
- if (NodeType == TEXT("Event") || NodeType == TEXT("K2Node_Event")) {
476
- FString EventName, MemberClass;
477
- Payload->TryGetStringField(TEXT("eventName"), EventName);
478
- Payload->TryGetStringField(TEXT("memberClass"), MemberClass);
479
- if (EventName.IsEmpty()) {
480
- SendAutomationError(RequestingSocket, RequestId,
481
- TEXT("eventName required"),
482
- TEXT("INVALID_ARGUMENT"));
483
- return true;
484
- }
485
- static TMap<FString, FString> Aliases = {
486
- {TEXT("BeginPlay"), TEXT("ReceiveBeginPlay")},
487
- {TEXT("Tick"), TEXT("ReceiveTick")},
488
- {TEXT("EndPlay"), TEXT("ReceiveEndPlay")}};
489
- if (const FString *A = Aliases.Find(EventName))
490
- EventName = *A;
491
-
492
- UClass *TargetClass = nullptr;
493
- UFunction *EventFunc = nullptr;
494
- if (!MemberClass.IsEmpty()) {
495
- TargetClass = ResolveUClass(MemberClass);
496
- if (TargetClass)
497
- EventFunc = TargetClass->FindFunctionByName(*EventName);
498
- } else {
499
- for (UClass *C = Blueprint->ParentClass; C && !EventFunc;
500
- C = C->GetSuperClass()) {
501
- EventFunc = C->FindFunctionByName(*EventName,
502
- EIncludeSuperFlag::ExcludeSuper);
503
- if (EventFunc)
504
- TargetClass = C;
505
- }
506
- }
507
- if (EventFunc && TargetClass) {
508
- FGraphNodeCreator<UK2Node_Event> NodeCreator(*TargetGraph);
509
- UK2Node_Event *EventNode = NodeCreator.CreateNode(false);
510
- EventNode->EventReference.SetFromField<UFunction>(EventFunc, false);
511
- EventNode->bOverrideFunction = true;
512
- FinalizeAndReport(NodeCreator, EventNode);
513
- } else {
514
- SendAutomationError(
515
- RequestingSocket, RequestId,
516
- FString::Printf(TEXT("Event '%s' not found"), *EventName),
517
- TEXT("EVENT_NOT_FOUND"));
518
- }
519
- return true;
520
- }
521
-
522
- if (NodeType == TEXT("CustomEvent") ||
523
- NodeType == TEXT("K2Node_CustomEvent")) {
524
- FString EventName;
525
- Payload->TryGetStringField(TEXT("eventName"), EventName);
526
- FGraphNodeCreator<UK2Node_CustomEvent> NodeCreator(*TargetGraph);
527
- UK2Node_CustomEvent *EventNode = NodeCreator.CreateNode(false);
528
- EventNode->CustomFunctionName = FName(*EventName);
529
- FinalizeAndReport(NodeCreator, EventNode);
530
- return true;
531
- }
532
-
533
- if (NodeType == TEXT("Cast") || NodeType.StartsWith(TEXT("CastTo"))) {
534
- FString TargetClassName;
535
- Payload->TryGetStringField(TEXT("targetClass"), TargetClassName);
536
- if (TargetClassName.IsEmpty() && NodeType.StartsWith(TEXT("CastTo")))
537
- TargetClassName = NodeType.Mid(6);
538
- UClass *TargetClass = ResolveUClass(TargetClassName);
539
- if (!TargetClass) {
540
- SendAutomationError(
541
- RequestingSocket, RequestId,
542
- FString::Printf(TEXT("Class '%s' not found"), *TargetClassName),
543
- TEXT("CLASS_NOT_FOUND"));
544
- return true;
545
- }
546
- FGraphNodeCreator<UK2Node_DynamicCast> NodeCreator(*TargetGraph);
547
- UK2Node_DynamicCast *CastNode = NodeCreator.CreateNode(false);
548
- CastNode->TargetType = TargetClass;
549
- FinalizeAndReport(NodeCreator, CastNode);
550
- return true;
551
- }
552
-
553
- if (NodeType == TEXT("InputAxisEvent") ||
554
- NodeType == TEXT("K2Node_InputAxisEvent")) {
555
- FString InputAxisName;
556
- Payload->TryGetStringField(TEXT("inputAxisName"), InputAxisName);
557
- if (InputAxisName.IsEmpty()) {
558
- SendAutomationError(RequestingSocket, RequestId,
559
- TEXT("inputAxisName required"),
560
- TEXT("INVALID_ARGUMENT"));
561
- return true;
562
- }
563
- FGraphNodeCreator<UK2Node_InputAxisEvent> NodeCreator(*TargetGraph);
564
- UK2Node_InputAxisEvent *InputNode = NodeCreator.CreateNode(false);
565
- InputNode->InputAxisName = FName(*InputAxisName);
566
- FinalizeAndReport(NodeCreator, InputNode);
567
- return true;
568
- }
569
-
570
- // ========== DYNAMIC FALLBACK: Create ANY node class by name ==========
571
- UClass *NodeClass = FindNodeClassByName(NodeType);
572
- if (NodeClass) {
573
- UEdGraphNode *NewNode = NewObject<UEdGraphNode>(TargetGraph, NodeClass);
574
- if (NewNode) {
575
- TargetGraph->AddNode(NewNode, false, false);
576
- NewNode->CreateNewGuid();
577
- NewNode->PostPlacedNewNode();
578
- NewNode->AllocateDefaultPins();
579
- NewNode->NodePosX = X;
580
- NewNode->NodePosY = Y;
581
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
582
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
583
- Result->SetStringField(TEXT("nodeId"), NewNode->NodeGuid.ToString());
584
- Result->SetStringField(TEXT("nodeName"), NewNode->GetName());
585
- Result->SetStringField(TEXT("nodeClass"), NodeClass->GetName());
586
- SendAutomationResponse(RequestingSocket, RequestId, true,
587
- TEXT("Node created."), Result);
588
- } else {
589
- SendAutomationError(RequestingSocket, RequestId,
590
- TEXT("Failed to instantiate node."),
591
- TEXT("CREATE_FAILED"));
592
- }
593
- } else {
594
- SendAutomationError(
595
- RequestingSocket, RequestId,
596
- FString::Printf(TEXT("Node type '%s' not found. Use list_node_types "
597
- "to see available types."),
598
- *NodeType),
599
- TEXT("NODE_TYPE_NOT_FOUND"));
600
- }
601
- return true;
602
- } else if (SubAction == TEXT("connect_pins")) {
603
- const FScopedTransaction Transaction(
604
- FText::FromString(TEXT("Connect Blueprint Pins")));
605
- Blueprint->Modify();
606
- TargetGraph->Modify();
607
-
608
- FString FromNodeId, FromPinName, ToNodeId, ToPinName;
609
- Payload->TryGetStringField(TEXT("fromNodeId"), FromNodeId);
610
- Payload->TryGetStringField(TEXT("fromPinName"), FromPinName);
611
- Payload->TryGetStringField(TEXT("toNodeId"), ToNodeId);
612
- Payload->TryGetStringField(TEXT("toPinName"), ToPinName);
613
-
614
- UEdGraphNode *FromNode = FindNodeByIdOrName(FromNodeId);
615
- UEdGraphNode *ToNode = FindNodeByIdOrName(ToNodeId);
616
-
617
- if (!FromNode || !ToNode) {
618
- SendAutomationError(RequestingSocket, RequestId,
619
- TEXT("Could not find source or target node."),
620
- TEXT("NODE_NOT_FOUND"));
621
- return true;
622
- }
623
-
624
- // Handle PinName in format "NodeName.PinName"
625
- FString FromPinClean = FromPinName;
626
- if (FromPinName.Contains(TEXT("."))) {
627
- FromPinName.Split(TEXT("."), nullptr, &FromPinClean);
628
- }
629
- FString ToPinClean = ToPinName;
630
- if (ToPinName.Contains(TEXT("."))) {
631
- ToPinName.Split(TEXT("."), nullptr, &ToPinClean);
632
- }
633
-
634
- UEdGraphPin *FromPin = FromNode->FindPin(*FromPinClean);
635
- UEdGraphPin *ToPin = ToNode->FindPin(*ToPinClean);
636
-
637
- if (!FromPin || !ToPin) {
638
- SendAutomationError(RequestingSocket, RequestId,
639
- TEXT("Could not find source or target pin."),
640
- TEXT("PIN_NOT_FOUND"));
641
- return true;
642
- }
643
-
644
- FromNode->Modify();
645
- ToNode->Modify();
646
-
647
- if (TargetGraph->GetSchema()->TryCreateConnection(FromPin, ToPin)) {
648
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
649
- SendAutomationResponse(RequestingSocket, RequestId, true,
650
- TEXT("Pins connected."));
651
- } else {
652
- SendAutomationError(RequestingSocket, RequestId,
653
- TEXT("Failed to connect pins (schema rejection)."),
654
- TEXT("CONNECTION_FAILED"));
655
- }
656
- return true;
657
- } else if (SubAction == TEXT("get_nodes")) {
658
- TArray<TSharedPtr<FJsonValue>> NodesArray;
659
-
660
- for (UEdGraphNode *Node : TargetGraph->Nodes) {
661
- if (!Node)
662
- continue;
663
-
664
- TSharedPtr<FJsonObject> NodeObj = MakeShared<FJsonObject>();
665
- NodeObj->SetStringField(TEXT("nodeId"), Node->NodeGuid.ToString());
666
- NodeObj->SetStringField(TEXT("nodeName"), Node->GetName());
667
- NodeObj->SetStringField(TEXT("nodeType"), Node->GetClass()->GetName());
668
- NodeObj->SetStringField(
669
- TEXT("nodeTitle"),
670
- Node->GetNodeTitle(ENodeTitleType::ListView).ToString());
671
- NodeObj->SetStringField(TEXT("comment"), Node->NodeComment);
672
- NodeObj->SetNumberField(TEXT("x"), Node->NodePosX);
673
- NodeObj->SetNumberField(TEXT("y"), Node->NodePosY);
674
-
675
- TArray<TSharedPtr<FJsonValue>> PinsArray;
676
- for (UEdGraphPin *Pin : Node->Pins) {
677
- if (!Pin)
678
- continue;
679
-
680
- TSharedPtr<FJsonObject> PinObj = MakeShared<FJsonObject>();
681
- PinObj->SetStringField(TEXT("pinName"), Pin->PinName.ToString());
682
- PinObj->SetStringField(TEXT("pinType"),
683
- Pin->PinType.PinCategory.ToString());
684
- PinObj->SetStringField(TEXT("direction"), Pin->Direction == EGPD_Input
685
- ? TEXT("Input")
686
- : TEXT("Output"));
687
-
688
- // Add pin sub-category object type if applicable
689
- if (Pin->PinType.PinCategory == TEXT("object") ||
690
- Pin->PinType.PinCategory == TEXT("class") ||
691
- Pin->PinType.PinCategory == TEXT("struct")) {
692
- if (Pin->PinType.PinSubCategoryObject.IsValid()) {
693
- PinObj->SetStringField(
694
- TEXT("pinSubType"),
695
- Pin->PinType.PinSubCategoryObject->GetName());
696
- }
697
- }
698
-
699
- TArray<TSharedPtr<FJsonValue>> LinkedToFileArray;
700
- for (UEdGraphPin *LinkedPin : Pin->LinkedTo) {
701
- if (LinkedPin && LinkedPin->GetOwningNode()) {
702
- TSharedPtr<FJsonObject> LinkObj = MakeShared<FJsonObject>();
703
- LinkObj->SetStringField(
704
- TEXT("nodeId"),
705
- LinkedPin->GetOwningNode()->NodeGuid.ToString());
706
- LinkObj->SetStringField(TEXT("pinName"),
707
- LinkedPin->PinName.ToString());
708
- LinkedToFileArray.Add(MakeShared<FJsonValueObject>(LinkObj));
709
- }
710
- }
711
- PinObj->SetArrayField(TEXT("linkedTo"), LinkedToFileArray);
712
- PinsArray.Add(MakeShared<FJsonValueObject>(PinObj));
713
- }
714
- NodeObj->SetArrayField(TEXT("pins"), PinsArray);
715
-
716
- NodesArray.Add(MakeShared<FJsonValueObject>(NodeObj));
717
- }
718
-
719
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
720
- Result->SetArrayField(TEXT("nodes"), NodesArray);
721
- Result->SetStringField(TEXT("graphName"), TargetGraph->GetName());
722
-
723
- SendAutomationResponse(RequestingSocket, RequestId, true,
724
- TEXT("Nodes retrieved."), Result);
725
- return true;
726
- } else if (SubAction == TEXT("break_pin_links")) {
727
- const FScopedTransaction Transaction(
728
- FText::FromString(TEXT("Break Blueprint Pin Links")));
729
- Blueprint->Modify();
730
- TargetGraph->Modify();
731
-
732
- FString NodeId, PinName;
733
- Payload->TryGetStringField(TEXT("nodeId"), NodeId);
734
- Payload->TryGetStringField(TEXT("pinName"), PinName);
735
-
736
- UEdGraphNode *TargetNode = FindNodeByIdOrName(NodeId);
737
-
738
- if (!TargetNode) {
739
- SendAutomationError(RequestingSocket, RequestId, TEXT("Node not found."),
740
- TEXT("NODE_NOT_FOUND"));
741
- return true;
742
- }
743
-
744
- UEdGraphPin *Pin = TargetNode->FindPin(*PinName);
745
- if (!Pin) {
746
- SendAutomationError(RequestingSocket, RequestId, TEXT("Pin not found."),
747
- TEXT("PIN_NOT_FOUND"));
748
- return true;
749
- }
750
-
751
- TargetNode->Modify();
752
- TargetGraph->GetSchema()->BreakPinLinks(*Pin, true);
753
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
754
- SendAutomationResponse(RequestingSocket, RequestId, true,
755
- TEXT("Pin links broken."));
756
- return true;
757
- }
758
-
759
- else if (SubAction == TEXT("delete_node")) {
760
- const FScopedTransaction Transaction(
761
- FText::FromString(TEXT("Delete Blueprint Node")));
762
- Blueprint->Modify();
763
- TargetGraph->Modify();
764
-
765
- FString NodeId;
766
- Payload->TryGetStringField(TEXT("nodeId"), NodeId);
767
-
768
- UEdGraphNode *TargetNode = FindNodeByIdOrName(NodeId);
769
-
770
- if (TargetNode) {
771
- FBlueprintEditorUtils::RemoveNode(Blueprint, TargetNode, true);
772
- SendAutomationResponse(RequestingSocket, RequestId, true,
773
- TEXT("Node deleted."));
774
- } else {
775
- SendAutomationError(RequestingSocket, RequestId, TEXT("Node not found."),
776
- TEXT("NODE_NOT_FOUND"));
777
- }
778
- return true;
779
- } else if (SubAction == TEXT("create_reroute_node")) {
780
- const FScopedTransaction Transaction(
781
- FText::FromString(TEXT("Create Reroute Node")));
782
- Blueprint->Modify();
783
- TargetGraph->Modify();
784
-
785
- float X = 0.0f;
786
- float Y = 0.0f;
787
- Payload->TryGetNumberField(TEXT("x"), X);
788
- Payload->TryGetNumberField(TEXT("y"), Y);
789
-
790
- FGraphNodeCreator<UK2Node_Knot> NodeCreator(*TargetGraph);
791
- UK2Node_Knot *RerouteNode = NodeCreator.CreateNode(false);
792
-
793
- RerouteNode->NodePosX = X;
794
- RerouteNode->NodePosY = Y;
795
-
796
- NodeCreator.Finalize();
797
-
798
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
799
-
800
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
801
- Result->SetStringField(TEXT("nodeId"), RerouteNode->NodeGuid.ToString());
802
- SendAutomationResponse(RequestingSocket, RequestId, true,
803
- TEXT("Reroute node created."), Result);
804
- return true;
805
- } else if (SubAction == TEXT("set_node_property")) {
806
- const FScopedTransaction Transaction(
807
- FText::FromString(TEXT("Set Blueprint Node Property")));
808
- Blueprint->Modify();
809
- TargetGraph->Modify();
810
-
811
- // Generic property setter for common node properties used by tools.
812
- FString NodeId;
813
- Payload->TryGetStringField(TEXT("nodeId"), NodeId);
814
- FString PropertyName;
815
- Payload->TryGetStringField(TEXT("propertyName"), PropertyName);
816
- FString Value;
817
- Payload->TryGetStringField(TEXT("value"), Value);
818
-
819
- UEdGraphNode *TargetNode = FindNodeByIdOrName(NodeId);
820
-
821
- if (TargetNode) {
822
- TargetNode->Modify();
823
- bool bHandled = false;
824
-
825
- if (PropertyName.Equals(TEXT("Comment"), ESearchCase::IgnoreCase) ||
826
- PropertyName.Equals(TEXT("NodeComment"), ESearchCase::IgnoreCase)) {
827
- TargetNode->NodeComment = Value;
828
- bHandled = true;
829
- } else if (PropertyName.Equals(TEXT("X"), ESearchCase::IgnoreCase) ||
830
- PropertyName.Equals(TEXT("NodePosX"),
831
- ESearchCase::IgnoreCase)) {
832
- double NumValue = 0.0;
833
- if (!Payload->TryGetNumberField(TEXT("value"), NumValue)) {
834
- NumValue = FCString::Atod(*Value);
835
- }
836
- TargetNode->NodePosX = static_cast<float>(NumValue);
837
- bHandled = true;
838
- } else if (PropertyName.Equals(TEXT("Y"), ESearchCase::IgnoreCase) ||
839
- PropertyName.Equals(TEXT("NodePosY"),
840
- ESearchCase::IgnoreCase)) {
841
- double NumValue = 0.0;
842
- if (!Payload->TryGetNumberField(TEXT("value"), NumValue)) {
843
- NumValue = FCString::Atod(*Value);
844
- }
845
- TargetNode->NodePosY = static_cast<float>(NumValue);
846
- bHandled = true;
847
- } else if (PropertyName.Equals(TEXT("bCommentBubbleVisible"),
848
- ESearchCase::IgnoreCase)) {
849
- TargetNode->bCommentBubbleVisible = Value.ToBool();
850
- bHandled = true;
851
- } else if (PropertyName.Equals(TEXT("bCommentBubblePinned"),
852
- ESearchCase::IgnoreCase)) {
853
- TargetNode->bCommentBubblePinned = Value.ToBool();
854
- bHandled = true;
855
- }
856
-
857
- if (bHandled) {
858
- TargetGraph->NotifyGraphChanged();
859
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
860
- SendAutomationResponse(RequestingSocket, RequestId, true,
861
- TEXT("Node property updated."));
862
- } else {
863
- SendAutomationError(
864
- RequestingSocket, RequestId,
865
- FString::Printf(TEXT("Unsupported node property '%s'"),
866
- *PropertyName),
867
- TEXT("PROPERTY_NOT_SUPPORTED"));
868
- }
869
- } else {
870
- SendAutomationError(RequestingSocket, RequestId, TEXT("Node not found."),
871
- TEXT("NODE_NOT_FOUND"));
872
- }
873
- return true;
874
- } else if (SubAction == TEXT("get_node_details")) {
875
- FString NodeId;
876
- Payload->TryGetStringField(TEXT("nodeId"), NodeId);
877
-
878
- UEdGraphNode *TargetNode = FindNodeByIdOrName(NodeId);
879
-
880
- if (TargetNode) {
881
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
882
- Result->SetStringField(TEXT("nodeName"), TargetNode->GetName());
883
- Result->SetStringField(
884
- TEXT("nodeTitle"),
885
- TargetNode->GetNodeTitle(ENodeTitleType::ListView).ToString());
886
- Result->SetStringField(TEXT("nodeComment"), TargetNode->NodeComment);
887
- Result->SetNumberField(TEXT("x"), TargetNode->NodePosX);
888
- Result->SetNumberField(TEXT("y"), TargetNode->NodePosY);
889
-
890
- TArray<TSharedPtr<FJsonValue>> Pins;
891
- for (UEdGraphPin *Pin : TargetNode->Pins) {
892
- TSharedPtr<FJsonObject> PinObj = MakeShared<FJsonObject>();
893
- PinObj->SetStringField(TEXT("pinName"), Pin->PinName.ToString());
894
- PinObj->SetStringField(TEXT("direction"), Pin->Direction == EGPD_Input
895
- ? TEXT("Input")
896
- : TEXT("Output"));
897
- PinObj->SetStringField(TEXT("pinType"),
898
- Pin->PinType.PinCategory.ToString());
899
- Pins.Add(MakeShared<FJsonValueObject>(PinObj));
900
- }
901
- Result->SetArrayField(TEXT("pins"), Pins);
902
-
903
- SendAutomationResponse(RequestingSocket, RequestId, true,
904
- TEXT("Node details retrieved."), Result);
905
- } else {
906
- SendAutomationError(RequestingSocket, RequestId, TEXT("Node not found."),
907
- TEXT("NODE_NOT_FOUND"));
908
- }
909
- return true;
910
- } else if (SubAction == TEXT("get_graph_details")) {
911
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
912
- Result->SetStringField(TEXT("graphName"), TargetGraph->GetName());
913
- Result->SetNumberField(TEXT("nodeCount"), TargetGraph->Nodes.Num());
914
-
915
- TArray<TSharedPtr<FJsonValue>> Nodes;
916
- for (UEdGraphNode *Node : TargetGraph->Nodes) {
917
- TSharedPtr<FJsonObject> NodeObj = MakeShared<FJsonObject>();
918
- NodeObj->SetStringField(TEXT("nodeId"), Node->NodeGuid.ToString());
919
- NodeObj->SetStringField(TEXT("nodeName"), Node->GetName());
920
- NodeObj->SetStringField(
921
- TEXT("nodeTitle"),
922
- Node->GetNodeTitle(ENodeTitleType::ListView).ToString());
923
- Nodes.Add(MakeShared<FJsonValueObject>(NodeObj));
924
- }
925
- Result->SetArrayField(TEXT("nodes"), Nodes);
926
-
927
- SendAutomationResponse(RequestingSocket, RequestId, true,
928
- TEXT("Graph details retrieved."), Result);
929
- return true;
930
- } else if (SubAction == TEXT("get_pin_details")) {
931
- FString NodeId;
932
- Payload->TryGetStringField(TEXT("nodeId"), NodeId);
933
- FString PinName;
934
- Payload->TryGetStringField(TEXT("pinName"), PinName);
935
-
936
- UEdGraphNode *TargetNode = FindNodeByIdOrName(NodeId);
937
-
938
- if (!TargetNode) {
939
- SendAutomationError(RequestingSocket, RequestId, TEXT("Node not found."),
940
- TEXT("NODE_NOT_FOUND"));
941
- return true;
942
- }
943
-
944
- TArray<UEdGraphPin *> PinsToReport;
945
- if (!PinName.IsEmpty()) {
946
- UEdGraphPin *Pin = TargetNode->FindPin(*PinName);
947
- if (!Pin) {
948
- SendAutomationError(RequestingSocket, RequestId, TEXT("Pin not found."),
949
- TEXT("PIN_NOT_FOUND"));
950
- return true;
951
- }
952
- PinsToReport.Add(Pin);
953
- } else {
954
- PinsToReport = TargetNode->Pins;
955
- }
956
-
957
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
958
- Result->SetStringField(TEXT("nodeId"), NodeId);
959
-
960
- TArray<TSharedPtr<FJsonValue>> PinsJson;
961
- for (UEdGraphPin *Pin : PinsToReport) {
962
- if (!Pin) {
963
- continue;
964
- }
965
-
966
- TSharedPtr<FJsonObject> PinObj = MakeShared<FJsonObject>();
967
- PinObj->SetStringField(TEXT("pinName"), Pin->PinName.ToString());
968
- PinObj->SetStringField(TEXT("direction"), Pin->Direction == EGPD_Input
969
- ? TEXT("Input")
970
- : TEXT("Output"));
971
- PinObj->SetStringField(TEXT("pinType"),
972
- Pin->PinType.PinCategory.ToString());
973
-
974
- if (Pin->LinkedTo.Num() > 0) {
975
- TArray<TSharedPtr<FJsonValue>> LinkedArray;
976
- for (UEdGraphPin *LinkedPin : Pin->LinkedTo) {
977
- if (!LinkedPin) {
978
- continue;
979
- }
980
- FString LinkedNodeId =
981
- LinkedPin->GetOwningNode()
982
- ? LinkedPin->GetOwningNode()->NodeGuid.ToString()
983
- : FString();
984
- const FString LinkedLabel =
985
- LinkedNodeId.IsEmpty()
986
- ? LinkedPin->PinName.ToString()
987
- : FString::Printf(TEXT("%s:%s"), *LinkedNodeId,
988
- *LinkedPin->PinName.ToString());
989
- LinkedArray.Add(MakeShared<FJsonValueString>(LinkedLabel));
990
- }
991
- PinObj->SetArrayField(TEXT("linkedTo"), LinkedArray);
992
- }
993
-
994
- if (!Pin->DefaultValue.IsEmpty()) {
995
- PinObj->SetStringField(TEXT("defaultValue"), Pin->DefaultValue);
996
- } else if (!Pin->DefaultTextValue.IsEmptyOrWhitespace()) {
997
- PinObj->SetStringField(TEXT("defaultTextValue"),
998
- Pin->DefaultTextValue.ToString());
999
- } else if (Pin->DefaultObject) {
1000
- PinObj->SetStringField(TEXT("defaultObjectPath"),
1001
- Pin->DefaultObject->GetPathName());
1002
- }
1003
-
1004
- PinsJson.Add(MakeShared<FJsonValueObject>(PinObj));
1005
- }
1006
-
1007
- Result->SetArrayField(TEXT("pins"), PinsJson);
1008
-
1009
- SendAutomationResponse(RequestingSocket, RequestId, true,
1010
- TEXT("Pin details retrieved."), Result);
1011
- return true;
1012
- } else if (SubAction == TEXT("list_node_types")) {
1013
- // List all available UK2Node types for AI discoverability
1014
- TArray<TSharedPtr<FJsonValue>> NodeTypes;
1015
- for (TObjectIterator<UClass> It; It; ++It) {
1016
- if (!It->IsChildOf(UK2Node::StaticClass()))
1017
- continue;
1018
- if (It->HasAnyClassFlags(CLASS_Abstract))
1019
- continue;
1020
-
1021
- TSharedPtr<FJsonObject> TypeObj = MakeShared<FJsonObject>();
1022
- TypeObj->SetStringField(TEXT("className"), It->GetName());
1023
- TypeObj->SetStringField(TEXT("displayName"),
1024
- It->GetDisplayNameText().ToString());
1025
- NodeTypes.Add(MakeShared<FJsonValueObject>(TypeObj));
1026
- }
1027
-
1028
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1029
- Result->SetArrayField(TEXT("nodeTypes"), NodeTypes);
1030
- Result->SetNumberField(TEXT("count"), NodeTypes.Num());
1031
- SendAutomationResponse(RequestingSocket, RequestId, true,
1032
- TEXT("Node types listed."), Result);
1033
- return true;
1034
- } else if (SubAction == TEXT("set_pin_default_value")) {
1035
- // Set a default value on a node's input pin
1036
- FString NodeId, PinName, Value;
1037
- Payload->TryGetStringField(TEXT("nodeId"), NodeId);
1038
- Payload->TryGetStringField(TEXT("pinName"), PinName);
1039
- Payload->TryGetStringField(TEXT("value"), Value);
1040
-
1041
- UEdGraphNode *TargetNode = FindNodeByIdOrName(NodeId);
1042
- if (!TargetNode) {
1043
- SendAutomationError(RequestingSocket, RequestId, TEXT("Node not found."),
1044
- TEXT("NODE_NOT_FOUND"));
1045
- return true;
1046
- }
1047
-
1048
- UEdGraphPin *Pin = TargetNode->FindPin(*PinName);
1049
- if (!Pin) {
1050
- SendAutomationError(RequestingSocket, RequestId, TEXT("Pin not found."),
1051
- TEXT("PIN_NOT_FOUND"));
1052
- return true;
1053
- }
1054
-
1055
- if (Pin->Direction != EGPD_Input) {
1056
- SendAutomationError(RequestingSocket, RequestId,
1057
- TEXT("Can only set default values on input pins."),
1058
- TEXT("INVALID_PIN_DIRECTION"));
1059
- return true;
1060
- }
1061
-
1062
- const FScopedTransaction Transaction(
1063
- FText::FromString(TEXT("Set Pin Default Value")));
1064
- Blueprint->Modify();
1065
- TargetGraph->Modify();
1066
- TargetNode->Modify();
1067
-
1068
- // Use the schema to properly set the default value
1069
- const UEdGraphSchema *Schema = TargetGraph->GetSchema();
1070
- Schema->TrySetDefaultValue(*Pin, Value);
1071
-
1072
- FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
1073
-
1074
- TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
1075
- Result->SetStringField(TEXT("nodeId"), NodeId);
1076
- Result->SetStringField(TEXT("pinName"), PinName);
1077
- Result->SetStringField(TEXT("value"), Value);
1078
- SendAutomationResponse(RequestingSocket, RequestId, true,
1079
- TEXT("Pin default value set."), Result);
1080
- return true;
1081
- }
1082
-
1083
- SendAutomationError(
1084
- RequestingSocket, RequestId,
1085
- FString::Printf(TEXT("Unknown subAction: %s"), *SubAction),
1086
- TEXT("INVALID_SUBACTION"));
1087
- return true;
1088
- #else
1089
- SendAutomationError(RequestingSocket, RequestId,
1090
- TEXT("Blueprint graph actions are editor-only."),
1091
- TEXT("EDITOR_ONLY"));
1092
- return true;
1093
- #endif
1094
- }