unreal-engine-mcp-server 0.4.7 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +26 -0
- package/.env.production +38 -7
- package/.eslintrc.json +0 -54
- package/.eslintrc.override.json +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
- package/.github/copilot-instructions.md +478 -45
- package/.github/dependabot.yml +19 -0
- package/.github/labeler.yml +24 -0
- package/.github/labels.yml +70 -0
- package/.github/pull_request_template.md +42 -0
- package/.github/release-drafter.yml +148 -0
- package/.github/workflows/auto-merge.yml +38 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/dependency-review.yml +17 -0
- package/.github/workflows/gemini-issue-triage.yml +172 -0
- package/.github/workflows/greetings.yml +23 -0
- package/.github/workflows/labeler.yml +16 -0
- package/.github/workflows/links.yml +80 -0
- package/.github/workflows/pr-size-labeler.yml +137 -0
- package/.github/workflows/publish-mcp.yml +12 -7
- package/.github/workflows/release-drafter.yml +23 -0
- package/.github/workflows/release.yml +112 -0
- package/.github/workflows/semantic-pull-request.yml +35 -0
- package/.github/workflows/smoke-test.yml +36 -0
- package/.github/workflows/stale.yml +28 -0
- package/CHANGELOG.md +267 -31
- package/CONTRIBUTING.md +140 -0
- package/README.md +166 -71
- package/claude_desktop_config_example.json +7 -6
- package/dist/automation/bridge.d.ts +50 -0
- package/dist/automation/bridge.js +452 -0
- package/dist/automation/connection-manager.d.ts +23 -0
- package/dist/automation/connection-manager.js +107 -0
- package/dist/automation/handshake.d.ts +11 -0
- package/dist/automation/handshake.js +89 -0
- package/dist/automation/index.d.ts +3 -0
- package/dist/automation/index.js +3 -0
- package/dist/automation/message-handler.d.ts +12 -0
- package/dist/automation/message-handler.js +149 -0
- package/dist/automation/request-tracker.d.ts +25 -0
- package/dist/automation/request-tracker.js +98 -0
- package/dist/automation/types.d.ts +130 -0
- package/dist/automation/types.js +2 -0
- package/dist/cli.js +32 -5
- package/dist/config.d.ts +27 -0
- package/dist/config.js +60 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.js +12 -0
- package/dist/graphql/resolvers.d.ts +268 -0
- package/dist/graphql/resolvers.js +743 -0
- package/dist/graphql/schema.d.ts +5 -0
- package/dist/graphql/schema.js +437 -0
- package/dist/graphql/server.d.ts +26 -0
- package/dist/graphql/server.js +115 -0
- package/dist/graphql/types.d.ts +7 -0
- package/dist/graphql/types.js +2 -0
- package/dist/handlers/resource-handlers.d.ts +20 -0
- package/dist/handlers/resource-handlers.js +180 -0
- package/dist/index.d.ts +31 -18
- package/dist/index.js +119 -619
- package/dist/prompts/index.js +4 -4
- package/dist/resources/actors.d.ts +17 -12
- package/dist/resources/actors.js +56 -76
- package/dist/resources/assets.d.ts +6 -14
- package/dist/resources/assets.js +115 -147
- package/dist/resources/levels.d.ts +13 -13
- package/dist/resources/levels.js +25 -34
- package/dist/server/resource-registry.d.ts +20 -0
- package/dist/server/resource-registry.js +37 -0
- package/dist/server/tool-registry.d.ts +23 -0
- package/dist/server/tool-registry.js +322 -0
- package/dist/server-setup.d.ts +21 -0
- package/dist/server-setup.js +111 -0
- package/dist/services/health-monitor.d.ts +34 -0
- package/dist/services/health-monitor.js +105 -0
- package/dist/services/metrics-server.d.ts +11 -0
- package/dist/services/metrics-server.js +105 -0
- package/dist/tools/actors.d.ts +147 -9
- package/dist/tools/actors.js +350 -311
- package/dist/tools/animation.d.ts +135 -4
- package/dist/tools/animation.js +510 -411
- package/dist/tools/assets.d.ts +117 -19
- package/dist/tools/assets.js +259 -284
- package/dist/tools/audio.d.ts +102 -42
- package/dist/tools/audio.js +272 -685
- package/dist/tools/base-tool.d.ts +17 -0
- package/dist/tools/base-tool.js +46 -0
- package/dist/tools/behavior-tree.d.ts +94 -0
- package/dist/tools/behavior-tree.js +39 -0
- package/dist/tools/blueprint/helpers.d.ts +29 -0
- package/dist/tools/blueprint/helpers.js +182 -0
- package/dist/tools/blueprint.d.ts +228 -118
- package/dist/tools/blueprint.js +685 -832
- package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
- package/dist/tools/consolidated-tool-definitions.js +829 -496
- package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
- package/dist/tools/consolidated-tool-handlers.js +211 -1026
- package/dist/tools/debug.d.ts +143 -85
- package/dist/tools/debug.js +234 -180
- package/dist/tools/dynamic-handler-registry.d.ts +11 -0
- package/dist/tools/dynamic-handler-registry.js +101 -0
- package/dist/tools/editor.d.ts +139 -18
- package/dist/tools/editor.js +239 -244
- package/dist/tools/engine.d.ts +10 -4
- package/dist/tools/engine.js +13 -5
- package/dist/tools/environment.d.ts +36 -0
- package/dist/tools/environment.js +267 -0
- package/dist/tools/foliage.d.ts +105 -14
- package/dist/tools/foliage.js +219 -331
- package/dist/tools/handlers/actor-handlers.d.ts +3 -0
- package/dist/tools/handlers/actor-handlers.js +232 -0
- package/dist/tools/handlers/animation-handlers.d.ts +3 -0
- package/dist/tools/handlers/animation-handlers.js +185 -0
- package/dist/tools/handlers/argument-helper.d.ts +16 -0
- package/dist/tools/handlers/argument-helper.js +80 -0
- package/dist/tools/handlers/asset-handlers.d.ts +3 -0
- package/dist/tools/handlers/asset-handlers.js +496 -0
- package/dist/tools/handlers/audio-handlers.d.ts +3 -0
- package/dist/tools/handlers/audio-handlers.js +166 -0
- package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
- package/dist/tools/handlers/blueprint-handlers.js +358 -0
- package/dist/tools/handlers/common-handlers.d.ts +14 -0
- package/dist/tools/handlers/common-handlers.js +56 -0
- package/dist/tools/handlers/editor-handlers.d.ts +3 -0
- package/dist/tools/handlers/editor-handlers.js +119 -0
- package/dist/tools/handlers/effect-handlers.d.ts +3 -0
- package/dist/tools/handlers/effect-handlers.js +171 -0
- package/dist/tools/handlers/environment-handlers.d.ts +3 -0
- package/dist/tools/handlers/environment-handlers.js +170 -0
- package/dist/tools/handlers/graph-handlers.d.ts +3 -0
- package/dist/tools/handlers/graph-handlers.js +90 -0
- package/dist/tools/handlers/input-handlers.d.ts +3 -0
- package/dist/tools/handlers/input-handlers.js +21 -0
- package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
- package/dist/tools/handlers/inspect-handlers.js +383 -0
- package/dist/tools/handlers/level-handlers.d.ts +3 -0
- package/dist/tools/handlers/level-handlers.js +237 -0
- package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
- package/dist/tools/handlers/lighting-handlers.js +144 -0
- package/dist/tools/handlers/performance-handlers.d.ts +3 -0
- package/dist/tools/handlers/performance-handlers.js +130 -0
- package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
- package/dist/tools/handlers/pipeline-handlers.js +110 -0
- package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
- package/dist/tools/handlers/sequence-handlers.js +376 -0
- package/dist/tools/handlers/system-handlers.d.ts +4 -0
- package/dist/tools/handlers/system-handlers.js +506 -0
- package/dist/tools/input.d.ts +19 -0
- package/dist/tools/input.js +89 -0
- package/dist/tools/introspection.d.ts +103 -40
- package/dist/tools/introspection.js +425 -568
- package/dist/tools/landscape.d.ts +97 -36
- package/dist/tools/landscape.js +280 -409
- package/dist/tools/level.d.ts +130 -10
- package/dist/tools/level.js +639 -675
- package/dist/tools/lighting.d.ts +77 -38
- package/dist/tools/lighting.js +441 -943
- package/dist/tools/logs.d.ts +3 -3
- package/dist/tools/logs.js +5 -57
- package/dist/tools/materials.d.ts +91 -24
- package/dist/tools/materials.js +190 -118
- package/dist/tools/niagara.d.ts +149 -39
- package/dist/tools/niagara.js +232 -182
- package/dist/tools/performance.d.ts +27 -12
- package/dist/tools/performance.js +204 -122
- package/dist/tools/physics.d.ts +32 -77
- package/dist/tools/physics.js +171 -582
- package/dist/tools/property-dictionary.d.ts +13 -0
- package/dist/tools/property-dictionary.js +82 -0
- package/dist/tools/sequence.d.ts +73 -48
- package/dist/tools/sequence.js +196 -748
- package/dist/tools/tool-definition-utils.d.ts +59 -0
- package/dist/tools/tool-definition-utils.js +35 -0
- package/dist/tools/ui.d.ts +66 -34
- package/dist/tools/ui.js +134 -214
- package/dist/types/env.d.ts +0 -3
- package/dist/types/env.js +0 -7
- package/dist/types/tool-interfaces.d.ts +898 -0
- package/dist/types/tool-interfaces.js +2 -0
- package/dist/types/tool-types.d.ts +183 -19
- package/dist/types/tool-types.js +0 -4
- package/dist/unreal-bridge.d.ts +24 -131
- package/dist/unreal-bridge.js +364 -1506
- package/dist/utils/command-validator.d.ts +9 -0
- package/dist/utils/command-validator.js +67 -0
- package/dist/utils/elicitation.d.ts +1 -1
- package/dist/utils/elicitation.js +12 -15
- package/dist/utils/error-handler.d.ts +2 -51
- package/dist/utils/error-handler.js +11 -87
- package/dist/utils/ini-reader.d.ts +3 -0
- package/dist/utils/ini-reader.js +69 -0
- package/dist/utils/logger.js +9 -6
- package/dist/utils/normalize.d.ts +3 -0
- package/dist/utils/normalize.js +56 -0
- package/dist/utils/response-factory.d.ts +7 -0
- package/dist/utils/response-factory.js +33 -0
- package/dist/utils/response-validator.d.ts +3 -24
- package/dist/utils/response-validator.js +130 -81
- package/dist/utils/result-helpers.d.ts +4 -5
- package/dist/utils/result-helpers.js +15 -16
- package/dist/utils/safe-json.js +5 -11
- package/dist/utils/unreal-command-queue.d.ts +24 -0
- package/dist/utils/unreal-command-queue.js +120 -0
- package/dist/utils/validation.d.ts +0 -40
- package/dist/utils/validation.js +1 -78
- package/dist/wasm/index.d.ts +70 -0
- package/dist/wasm/index.js +535 -0
- package/docs/GraphQL-API.md +888 -0
- package/docs/Migration-Guide-v0.5.0.md +692 -0
- package/docs/Roadmap.md +53 -0
- package/docs/WebAssembly-Integration.md +628 -0
- package/docs/editor-plugin-extension.md +370 -0
- package/docs/handler-mapping.md +242 -0
- package/docs/native-automation-progress.md +128 -0
- package/docs/testing-guide.md +423 -0
- package/mcp-config-example.json +6 -6
- package/package.json +60 -27
- package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
- package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
- package/scripts/check-unreal-connection.mjs +19 -0
- package/scripts/clean-tmp.js +23 -0
- package/scripts/patch-wasm.js +26 -0
- package/scripts/run-all-tests.mjs +131 -0
- package/scripts/smoke-test.ts +94 -0
- package/scripts/sync-mcp-plugin.js +143 -0
- package/scripts/test-no-plugin-alternates.mjs +113 -0
- package/scripts/validate-server.js +46 -0
- package/scripts/verify-automation-bridge.js +200 -0
- package/server.json +57 -21
- package/src/automation/bridge.ts +558 -0
- package/src/automation/connection-manager.ts +130 -0
- package/src/automation/handshake.ts +99 -0
- package/src/automation/index.ts +2 -0
- package/src/automation/message-handler.ts +167 -0
- package/src/automation/request-tracker.ts +123 -0
- package/src/automation/types.ts +107 -0
- package/src/cli.ts +33 -6
- package/src/config.ts +73 -0
- package/src/constants.ts +12 -0
- package/src/graphql/resolvers.ts +1010 -0
- package/src/graphql/schema.ts +452 -0
- package/src/graphql/server.ts +154 -0
- package/src/graphql/types.ts +7 -0
- package/src/handlers/resource-handlers.ts +186 -0
- package/src/index.ts +152 -663
- package/src/prompts/index.ts +4 -4
- package/src/resources/actors.ts +58 -76
- package/src/resources/assets.ts +147 -134
- package/src/resources/levels.ts +28 -33
- package/src/server/resource-registry.ts +47 -0
- package/src/server/tool-registry.ts +354 -0
- package/src/server-setup.ts +148 -0
- package/src/services/health-monitor.ts +132 -0
- package/src/services/metrics-server.ts +142 -0
- package/src/tools/actors.ts +417 -322
- package/src/tools/animation.ts +671 -461
- package/src/tools/assets.ts +353 -289
- package/src/tools/audio.ts +323 -766
- package/src/tools/base-tool.ts +52 -0
- package/src/tools/behavior-tree.ts +45 -0
- package/src/tools/blueprint/helpers.ts +189 -0
- package/src/tools/blueprint.ts +787 -965
- package/src/tools/consolidated-tool-definitions.ts +993 -515
- package/src/tools/consolidated-tool-handlers.ts +272 -1139
- package/src/tools/debug.ts +292 -187
- package/src/tools/dynamic-handler-registry.ts +151 -0
- package/src/tools/editor.ts +309 -246
- package/src/tools/engine.ts +14 -3
- package/src/tools/environment.ts +287 -0
- package/src/tools/foliage.ts +314 -379
- package/src/tools/handlers/actor-handlers.ts +271 -0
- package/src/tools/handlers/animation-handlers.ts +237 -0
- package/src/tools/handlers/argument-helper.ts +142 -0
- package/src/tools/handlers/asset-handlers.ts +532 -0
- package/src/tools/handlers/audio-handlers.ts +194 -0
- package/src/tools/handlers/blueprint-handlers.ts +380 -0
- package/src/tools/handlers/common-handlers.ts +87 -0
- package/src/tools/handlers/editor-handlers.ts +123 -0
- package/src/tools/handlers/effect-handlers.ts +220 -0
- package/src/tools/handlers/environment-handlers.ts +183 -0
- package/src/tools/handlers/graph-handlers.ts +116 -0
- package/src/tools/handlers/input-handlers.ts +28 -0
- package/src/tools/handlers/inspect-handlers.ts +450 -0
- package/src/tools/handlers/level-handlers.ts +252 -0
- package/src/tools/handlers/lighting-handlers.ts +147 -0
- package/src/tools/handlers/performance-handlers.ts +132 -0
- package/src/tools/handlers/pipeline-handlers.ts +127 -0
- package/src/tools/handlers/sequence-handlers.ts +415 -0
- package/src/tools/handlers/system-handlers.ts +564 -0
- package/src/tools/input.ts +101 -0
- package/src/tools/introspection.ts +493 -584
- package/src/tools/landscape.ts +394 -489
- package/src/tools/level.ts +752 -694
- package/src/tools/lighting.ts +583 -984
- package/src/tools/logs.ts +9 -57
- package/src/tools/materials.ts +231 -121
- package/src/tools/niagara.ts +293 -168
- package/src/tools/performance.ts +320 -168
- package/src/tools/physics.ts +268 -613
- package/src/tools/property-dictionary.ts +98 -0
- package/src/tools/sequence.ts +255 -815
- package/src/tools/tool-definition-utils.ts +35 -0
- package/src/tools/ui.ts +207 -283
- package/src/types/env.ts +0 -10
- package/src/types/tool-interfaces.ts +250 -0
- package/src/types/tool-types.ts +243 -21
- package/src/unreal-bridge.ts +460 -1550
- package/src/utils/command-validator.ts +75 -0
- package/src/utils/elicitation.ts +10 -7
- package/src/utils/error-handler.ts +14 -90
- package/src/utils/ini-reader.ts +86 -0
- package/src/utils/logger.ts +8 -3
- package/src/utils/normalize.ts +60 -0
- package/src/utils/response-factory.ts +39 -0
- package/src/utils/response-validator.ts +176 -56
- package/src/utils/result-helpers.ts +21 -19
- package/src/utils/safe-json.ts +14 -11
- package/src/utils/unreal-command-queue.ts +152 -0
- package/src/utils/validation.ts +4 -1
- package/src/wasm/index.ts +838 -0
- package/test-server.mjs +100 -0
- package/tests/run-unreal-tool-tests.mjs +242 -14
- package/tests/test-animation.mjs +44 -0
- package/tests/test-asset-advanced.mjs +82 -0
- package/tests/test-asset-errors.mjs +35 -0
- package/tests/test-audio.mjs +219 -0
- package/tests/test-automation-timeouts.mjs +98 -0
- package/tests/test-behavior-tree.mjs +261 -0
- package/tests/test-blueprint-events.mjs +35 -0
- package/tests/test-blueprint-graph.mjs +79 -0
- package/tests/test-blueprint.mjs +577 -0
- package/tests/test-client-mode.mjs +86 -0
- package/tests/test-console-command.mjs +56 -0
- package/tests/test-control-actor.mjs +425 -0
- package/tests/test-control-editor.mjs +80 -0
- package/tests/test-extra-tools.mjs +38 -0
- package/tests/test-graphql.mjs +322 -0
- package/tests/test-inspect.mjs +72 -0
- package/tests/test-landscape.mjs +60 -0
- package/tests/test-manage-asset.mjs +438 -0
- package/tests/test-manage-level.mjs +70 -0
- package/tests/test-materials.mjs +356 -0
- package/tests/test-niagara.mjs +185 -0
- package/tests/test-no-inline-python.mjs +122 -0
- package/tests/test-plugin-handshake.mjs +82 -0
- package/tests/test-render.mjs +33 -0
- package/tests/test-runner.mjs +933 -0
- package/tests/test-search-assets.mjs +66 -0
- package/tests/test-sequence.mjs +68 -0
- package/tests/test-system.mjs +57 -0
- package/tests/test-wasm.mjs +193 -0
- package/tests/test-world-partition.mjs +215 -0
- package/tsconfig.json +3 -3
- package/wasm/Cargo.lock +363 -0
- package/wasm/Cargo.toml +42 -0
- package/wasm/LICENSE +21 -0
- package/wasm/README.md +253 -0
- package/wasm/src/dependency_resolver.rs +377 -0
- package/wasm/src/lib.rs +153 -0
- package/wasm/src/property_parser.rs +271 -0
- package/wasm/src/transform_math.rs +396 -0
- package/wasm/tests/integration.rs +109 -0
- package/.github/workflows/smithery-build.yml +0 -29
- package/dist/tools/build_environment_advanced.d.ts +0 -65
- package/dist/tools/build_environment_advanced.js +0 -633
- package/dist/tools/rc.d.ts +0 -110
- package/dist/tools/rc.js +0 -437
- package/dist/tools/visual.d.ts +0 -40
- package/dist/tools/visual.js +0 -282
- package/dist/utils/http.d.ts +0 -6
- package/dist/utils/http.js +0 -151
- package/dist/utils/python-output.d.ts +0 -18
- package/dist/utils/python-output.js +0 -290
- package/dist/utils/python.d.ts +0 -2
- package/dist/utils/python.js +0 -4
- package/dist/utils/stdio-redirect.d.ts +0 -2
- package/dist/utils/stdio-redirect.js +0 -20
- package/docs/unreal-tool-test-cases.md +0 -574
- package/smithery.yaml +0 -29
- package/src/tools/build_environment_advanced.ts +0 -732
- package/src/tools/rc.ts +0 -515
- package/src/tools/visual.ts +0 -281
- package/src/utils/http.ts +0 -187
- package/src/utils/python-output.ts +0 -351
- package/src/utils/python.ts +0 -3
- package/src/utils/stdio-redirect.ts +0 -18
package/src/tools/ui.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
// UI tools for Unreal Engine
|
|
2
2
|
import { UnrealBridge } from '../unreal-bridge.js';
|
|
3
|
+
import { AutomationBridge } from '../automation/index.js';
|
|
3
4
|
import { bestEffortInterpretedText, interpretStandardResult } from '../utils/result-helpers.js';
|
|
4
5
|
|
|
5
6
|
export class UITools {
|
|
6
|
-
|
|
7
|
+
private automationBridge?: AutomationBridge;
|
|
8
|
+
|
|
9
|
+
constructor(private bridge: UnrealBridge, automationBridge?: AutomationBridge) {
|
|
10
|
+
this.automationBridge = automationBridge;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
setAutomationBridge(automationBridge?: AutomationBridge) {
|
|
14
|
+
this.automationBridge = automationBridge;
|
|
15
|
+
}
|
|
7
16
|
|
|
8
17
|
// Create widget blueprint
|
|
9
18
|
async createWidget(params: {
|
|
@@ -12,60 +21,73 @@ export class UITools {
|
|
|
12
21
|
savePath?: string;
|
|
13
22
|
}) {
|
|
14
23
|
const path = params.savePath || '/Game/UI/Widgets';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
24
|
+
|
|
25
|
+
// Plugin-first: attempt to create the widget asset via the Automation Bridge.
|
|
26
|
+
if (this.automationBridge && typeof this.automationBridge.sendAutomationRequest === 'function') {
|
|
27
|
+
try {
|
|
28
|
+
const resp = await this.automationBridge.sendAutomationRequest('system_control', {
|
|
29
|
+
action: 'create_widget',
|
|
30
|
+
name: params.name,
|
|
31
|
+
widgetType: params.type,
|
|
32
|
+
savePath: path
|
|
33
|
+
});
|
|
34
|
+
if (resp && resp.success !== false) {
|
|
35
|
+
const result = resp.result ?? resp;
|
|
36
|
+
const resultObj = result && typeof result === 'object' ? (result as Record<string, unknown>) : undefined;
|
|
37
|
+
const widgetPath = typeof resultObj?.widgetPath === 'string' ? (resultObj.widgetPath as string) : `${path}/${params.name}`;
|
|
38
|
+
const message = resp.message || `Widget created at ${widgetPath}`;
|
|
39
|
+
return {
|
|
40
|
+
success: true,
|
|
41
|
+
message,
|
|
42
|
+
widgetPath,
|
|
43
|
+
exists: Boolean(resultObj?.exists),
|
|
44
|
+
...(resultObj || {})
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.warn('UITools.createWidget automation bridge request failed, falling back to editor function:', error);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Fallback: attempt to create the widget asset via the Automation
|
|
53
|
+
// Bridge plugin using the generic CREATE_ASSET function. If the plugin
|
|
54
|
+
// does not implement the action the bridge will fall back to executing
|
|
55
|
+
// the Python template (deprecated and gated by server opt-in).
|
|
46
56
|
try {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
const payload = {
|
|
58
|
+
asset_name: params.name,
|
|
59
|
+
package_path: path,
|
|
60
|
+
factory_class: 'WidgetBlueprintFactory',
|
|
61
|
+
asset_class: 'unreal.WidgetBlueprint'
|
|
62
|
+
} as Record<string, any>;
|
|
52
63
|
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
const resp = await this.bridge.executeEditorFunction('CREATE_ASSET', payload as any);
|
|
65
|
+
const result = resp && typeof resp === 'object' ? (resp.result ?? resp) : resp;
|
|
66
|
+
|
|
67
|
+
// Interpret common success shapes returned by plugin or Python template
|
|
68
|
+
if (result && (result.success === true || result.created === true || Boolean(result.path))) {
|
|
69
|
+
return { success: true, message: result.message ?? `Widget created at ${result.path ?? `${path}/${params.name}`}` };
|
|
55
70
|
}
|
|
56
71
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
error:
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
// If plugin/template returned a structured failure, surface it
|
|
73
|
+
if (result && result.success === false) {
|
|
74
|
+
return { success: false, error: result.error ?? result.message ?? 'Failed to create widget blueprint', details: result };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Fallback: if no structured response, return generic failure
|
|
78
|
+
return { success: false, error: 'Failed to create widget blueprint' };
|
|
62
79
|
} catch (e) {
|
|
63
80
|
return { success: false, error: `Failed to create widget blueprint: ${e}` };
|
|
64
81
|
}
|
|
65
82
|
}
|
|
66
83
|
|
|
84
|
+
// Show widget (convenience wrapper)
|
|
85
|
+
async showWidget(widgetPath: string) {
|
|
86
|
+
return this.addWidgetToViewport({ widgetClass: widgetPath });
|
|
87
|
+
}
|
|
88
|
+
|
|
67
89
|
// Add widget component
|
|
68
|
-
async addWidgetComponent(
|
|
90
|
+
async addWidgetComponent(_params: {
|
|
69
91
|
widgetName: string;
|
|
70
92
|
componentType: 'Button' | 'Text' | 'Image' | 'ProgressBar' | 'Slider' | 'CheckBox' | 'ComboBox' | 'TextBox' | 'ScrollBox' | 'Canvas' | 'VerticalBox' | 'HorizontalBox' | 'Grid' | 'Overlay';
|
|
71
93
|
componentName: string;
|
|
@@ -76,162 +98,135 @@ except Exception as e:
|
|
|
76
98
|
alignment?: [number, number];
|
|
77
99
|
};
|
|
78
100
|
}) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
if (!this.automationBridge) {
|
|
102
|
+
throw new Error('Automation bridge required for widget component operations');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// Map correctly to McpAutomationBridge_UiHandlers.cpp: add_widget_child
|
|
107
|
+
const response = await this.automationBridge.sendAutomationRequest('manage_ui', {
|
|
108
|
+
action: 'add_widget_child', // Use 'action' inside payload for subAction
|
|
109
|
+
widgetPath: _params.widgetName, // C++ expects 'widgetPath'
|
|
110
|
+
childClass: _params.componentType, // C++ expects 'childClass'
|
|
111
|
+
parentName: _params.slot ? 'Root' : undefined, // Rudimentary mapping
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return response.success
|
|
115
|
+
? { success: true, message: response.message || 'Widget component added', ...(response.result || {}) }
|
|
116
|
+
: { success: false, error: response.error || response.message || 'Failed to add widget component' };
|
|
117
|
+
} catch (error) {
|
|
118
|
+
return { success: false, error: `Failed to add widget component: ${error instanceof Error ? error.message : String(error)}` };
|
|
96
119
|
}
|
|
97
|
-
|
|
98
|
-
await this.bridge.executeConsoleCommands(commands);
|
|
99
|
-
|
|
100
|
-
return { success: true, message: `Component ${params.componentName} added to widget` };
|
|
101
120
|
}
|
|
102
121
|
|
|
103
|
-
// Set text
|
|
104
|
-
async setWidgetText(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
fontSize?: number;
|
|
109
|
-
color?: [number, number, number, number];
|
|
110
|
-
fontFamily?: string;
|
|
122
|
+
// Set text (requires C++ plugin)
|
|
123
|
+
async setWidgetText(_params: {
|
|
124
|
+
key: string; // The widget name to find
|
|
125
|
+
value: string; // The text to set
|
|
126
|
+
componentName?: string; // Legacy/Unused in new impl
|
|
111
127
|
}) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
commands.push(`SetWidgetText ${params.widgetName}.${params.componentName} "${params.text}"`);
|
|
115
|
-
|
|
116
|
-
if (params.fontSize !== undefined) {
|
|
117
|
-
commands.push(`SetWidgetFontSize ${params.widgetName}.${params.componentName} ${params.fontSize}`);
|
|
128
|
+
if (!this.automationBridge) {
|
|
129
|
+
throw new Error('Automation bridge required for setting widget text');
|
|
118
130
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
// Changed to 'system_control' with subAction
|
|
134
|
+
const response = await this.automationBridge.sendAutomationRequest('system_control', {
|
|
135
|
+
subAction: 'set_widget_text',
|
|
136
|
+
key: _params.key,
|
|
137
|
+
value: _params.value
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return response.success
|
|
141
|
+
? { success: true, message: response.message || 'Widget text set', ...(response.result || {}) }
|
|
142
|
+
: { success: false, error: response.error || response.message || 'Failed to set widget text' };
|
|
143
|
+
} catch (error) {
|
|
144
|
+
return { success: false, error: `Failed to set widget text: ${error instanceof Error ? error.message : String(error)}` };
|
|
126
145
|
}
|
|
127
|
-
|
|
128
|
-
await this.bridge.executeConsoleCommands(commands);
|
|
129
|
-
|
|
130
|
-
return { success: true, message: 'Widget text updated' };
|
|
131
146
|
}
|
|
132
147
|
|
|
133
|
-
// Set image
|
|
134
|
-
async setWidgetImage(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
tint?: [number, number, number, number];
|
|
139
|
-
sizeToContent?: boolean;
|
|
148
|
+
// Set image (requires C++ plugin)
|
|
149
|
+
async setWidgetImage(_params: {
|
|
150
|
+
key: string;
|
|
151
|
+
texturePath: string;
|
|
152
|
+
componentName?: string; // Unused
|
|
140
153
|
}) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
commands.push(`SetWidgetImage ${params.widgetName}.${params.componentName} ${params.imagePath}`);
|
|
144
|
-
|
|
145
|
-
if (params.tint) {
|
|
146
|
-
commands.push(`SetWidgetImageTint ${params.widgetName}.${params.componentName} ${params.tint.join(' ')}`);
|
|
154
|
+
if (!this.automationBridge) {
|
|
155
|
+
throw new Error('Automation bridge required for setting widget images');
|
|
147
156
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
const response = await this.automationBridge.sendAutomationRequest('system_control', {
|
|
160
|
+
subAction: 'set_widget_image',
|
|
161
|
+
key: _params.key,
|
|
162
|
+
texturePath: _params.texturePath
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return response.success
|
|
166
|
+
? { success: true, message: response.message || 'Widget image set', ...(response.result || {}) }
|
|
167
|
+
: { success: false, error: response.error || response.message || 'Failed to set widget image' };
|
|
168
|
+
} catch (error) {
|
|
169
|
+
return { success: false, error: `Failed to set widget image: ${error instanceof Error ? error.message : String(error)}` };
|
|
151
170
|
}
|
|
152
|
-
|
|
153
|
-
await this.bridge.executeConsoleCommands(commands);
|
|
154
|
-
|
|
155
|
-
return { success: true, message: 'Widget image updated' };
|
|
156
171
|
}
|
|
157
172
|
|
|
158
|
-
// Create HUD
|
|
159
|
-
async createHUD(
|
|
173
|
+
// Create HUD (requires C++ plugin)
|
|
174
|
+
async createHUD(_params: {
|
|
160
175
|
name: string;
|
|
161
|
-
elements?: Array<
|
|
162
|
-
type: 'HealthBar' | 'AmmoCounter' | 'Score' | 'Timer' | 'Minimap' | 'Crosshair';
|
|
163
|
-
position: [number, number];
|
|
164
|
-
size?: [number, number];
|
|
165
|
-
}>;
|
|
176
|
+
elements?: Array<any>;
|
|
166
177
|
}) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
if (!this.automationBridge) {
|
|
179
|
+
throw new Error('Automation bridge required for creating HUDs');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Default path assumption or require full path?
|
|
183
|
+
// C++ expects 'widgetPath'. If name is just "MyHUD", we might need to resolve it.
|
|
184
|
+
// For now, assume name is the path or user provides path.
|
|
185
|
+
const widgetPath = _params.name.startsWith('/Game') ? _params.name : `/Game/UI/${_params.name}`;
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const response = await this.automationBridge.sendAutomationRequest('system_control', {
|
|
189
|
+
subAction: 'create_hud',
|
|
190
|
+
widgetPath: widgetPath
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
return response.success
|
|
194
|
+
? { success: true, message: response.message || 'HUD created', widgetName: (response.result as any)?.widgetName, ...(response.result || {}) }
|
|
195
|
+
: { success: false, error: response.error || response.message || 'Failed to create HUD' };
|
|
196
|
+
} catch (error) {
|
|
197
|
+
return { success: false, error: `Failed to create HUD: ${error instanceof Error ? error.message : String(error)}` };
|
|
176
198
|
}
|
|
177
|
-
|
|
178
|
-
await this.bridge.executeConsoleCommands(commands);
|
|
179
|
-
|
|
180
|
-
return { success: true, message: `HUD ${params.name} created` };
|
|
181
199
|
}
|
|
182
200
|
|
|
183
|
-
// Show/Hide widget
|
|
184
201
|
async setWidgetVisibility(params: {
|
|
185
|
-
|
|
202
|
+
key: string;
|
|
186
203
|
visible: boolean;
|
|
187
|
-
playerIndex?: number;
|
|
188
204
|
}) {
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if name.startswith('/Game/'):
|
|
200
|
-
candidates.append(name)
|
|
201
|
-
else:
|
|
202
|
-
candidates.append(f"/Game/UI/Widgets/{name}")
|
|
203
|
-
candidates.append(f"/Game/{name}")
|
|
204
|
-
|
|
205
|
-
found_path = ''
|
|
206
|
-
for path in candidates:
|
|
207
|
-
if unreal.EditorAssetLibrary.does_asset_exist(path):
|
|
208
|
-
found_path = path
|
|
209
|
-
break
|
|
210
|
-
|
|
211
|
-
print('RESULT:' + json.dumps({'success': bool(found_path), 'path': found_path, 'candidates': candidates}))
|
|
212
|
-
`.trim();
|
|
213
|
-
|
|
214
|
-
const verify = await this.bridge.executePythonWithResult(verifyScript);
|
|
215
|
-
if (!verify?.success) {
|
|
216
|
-
return { success: false, error: `Widget asset not found for ${widgetName}` };
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const command = params.visible
|
|
220
|
-
? `ShowWidget ${widgetName} ${playerIndex}`
|
|
221
|
-
: `HideWidget ${widgetName} ${playerIndex}`;
|
|
222
|
-
|
|
223
|
-
const raw = await this.bridge.executeConsoleCommand(command);
|
|
224
|
-
const summary = this.bridge.summarizeConsoleCommand(command, raw);
|
|
205
|
+
if (!this.automationBridge) return { success: false, error: 'NO_BRIDGE' };
|
|
206
|
+
const response = await this.automationBridge.sendAutomationRequest('system_control', {
|
|
207
|
+
subAction: 'set_widget_visibility',
|
|
208
|
+
key: params.key,
|
|
209
|
+
visible: params.visible
|
|
210
|
+
});
|
|
211
|
+
return response.success
|
|
212
|
+
? { success: true, message: response.message || 'Widget visibility set', ...(response.result || {}) }
|
|
213
|
+
: { success: false, error: response.error || response.message || 'Failed to set widget visibility' };
|
|
214
|
+
}
|
|
225
215
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
216
|
+
async removeWidgetFromViewport(params: {
|
|
217
|
+
key?: string;
|
|
218
|
+
}) {
|
|
219
|
+
if (!this.automationBridge) return { success: false, error: 'NO_BRIDGE' };
|
|
220
|
+
const response = await this.automationBridge.sendAutomationRequest('system_control', {
|
|
221
|
+
subAction: 'remove_widget_from_viewport',
|
|
222
|
+
key: params.key
|
|
223
|
+
});
|
|
224
|
+
return response.success
|
|
225
|
+
? { success: true, message: response.message || 'Widget removed from viewport', ...(response.result || {}) }
|
|
226
|
+
: { success: false, error: response.error || response.message || 'Failed to remove widget from viewport' };
|
|
233
227
|
}
|
|
234
228
|
|
|
229
|
+
|
|
235
230
|
// Add widget to viewport
|
|
236
231
|
async addWidgetToViewport(params: {
|
|
237
232
|
widgetClass: string;
|
|
@@ -240,93 +235,22 @@ print('RESULT:' + json.dumps({'success': bool(found_path), 'path': found_path, '
|
|
|
240
235
|
}) {
|
|
241
236
|
const zOrder = params.zOrder ?? 0;
|
|
242
237
|
const playerIndex = params.playerIndex ?? 0;
|
|
243
|
-
|
|
244
|
-
// Use Python API to create and add widget to viewport
|
|
245
|
-
const py = `
|
|
246
|
-
import unreal
|
|
247
|
-
import json
|
|
248
|
-
widget_path = r"${params.widgetClass}"
|
|
249
|
-
z_order = ${zOrder}
|
|
250
|
-
player_index = ${playerIndex}
|
|
251
|
-
try:
|
|
252
|
-
# Load the widget blueprint class
|
|
253
|
-
if not unreal.EditorAssetLibrary.does_asset_exist(widget_path):
|
|
254
|
-
print('RESULT:' + json.dumps({'success': False, 'error': f'Widget class not found: {widget_path}'}))
|
|
255
|
-
else:
|
|
256
|
-
widget_bp = unreal.EditorAssetLibrary.load_asset(widget_path)
|
|
257
|
-
if not widget_bp:
|
|
258
|
-
print('RESULT:' + json.dumps({'success': False, 'error': 'Failed to load widget blueprint'}))
|
|
259
|
-
else:
|
|
260
|
-
# Get the generated class from the widget blueprint
|
|
261
|
-
widget_class = widget_bp.generated_class() if hasattr(widget_bp, 'generated_class') else widget_bp
|
|
262
|
-
|
|
263
|
-
# Get the world and player controller via modern subsystems
|
|
264
|
-
world = None
|
|
265
|
-
try:
|
|
266
|
-
world = unreal.EditorUtilityLibrary.get_editor_world()
|
|
267
|
-
except Exception:
|
|
268
|
-
pass
|
|
269
|
-
|
|
270
|
-
if not world:
|
|
271
|
-
editor_subsystem = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem)
|
|
272
|
-
if editor_subsystem and hasattr(editor_subsystem, 'get_editor_world'):
|
|
273
|
-
world = editor_subsystem.get_editor_world()
|
|
274
|
-
|
|
275
|
-
if not world:
|
|
276
|
-
print('RESULT:' + json.dumps({'success': False, 'error': 'No editor world available. Start a PIE session or enable Editor Scripting Utilities.'}))
|
|
277
|
-
else:
|
|
278
|
-
# Try to get player controller
|
|
279
|
-
try:
|
|
280
|
-
player_controller = unreal.GameplayStatics.get_player_controller(world, player_index)
|
|
281
|
-
except Exception:
|
|
282
|
-
player_controller = None
|
|
283
|
-
|
|
284
|
-
if not player_controller:
|
|
285
|
-
# If no player controller in PIE, try to get the first one or create a dummy
|
|
286
|
-
print('RESULT:' + json.dumps({'success': False, 'error': 'No player controller available. Run in PIE mode first.'}))
|
|
287
|
-
else:
|
|
288
|
-
# Create the widget
|
|
289
|
-
widget = unreal.WidgetBlueprintLibrary.create(world, widget_class, player_controller)
|
|
290
|
-
if widget:
|
|
291
|
-
# Add to viewport
|
|
292
|
-
widget.add_to_viewport(z_order)
|
|
293
|
-
print('RESULT:' + json.dumps({'success': True}))
|
|
294
|
-
else:
|
|
295
|
-
print('RESULT:' + json.dumps({'success': False, 'error': 'Failed to create widget instance'}))
|
|
296
|
-
except Exception as e:
|
|
297
|
-
print('RESULT:' + json.dumps({'success': False, 'error': str(e)}))
|
|
298
|
-
`.trim();
|
|
299
|
-
|
|
238
|
+
|
|
300
239
|
try {
|
|
301
|
-
const resp = await this.bridge.
|
|
240
|
+
const resp = await this.bridge.executeEditorFunction('ADD_WIDGET_TO_VIEWPORT', { widget_path: params.widgetClass, z_order: zOrder, player_index: playerIndex } as any);
|
|
302
241
|
const interpreted = interpretStandardResult(resp, {
|
|
303
242
|
successMessage: `Widget added to viewport with z-order ${zOrder}`,
|
|
304
243
|
failureMessage: 'Failed to add widget to viewport'
|
|
305
244
|
});
|
|
306
|
-
|
|
307
245
|
if (interpreted.success) {
|
|
308
246
|
return { success: true, message: interpreted.message };
|
|
309
247
|
}
|
|
310
|
-
|
|
311
|
-
return {
|
|
312
|
-
success: false,
|
|
313
|
-
error: interpreted.error ?? 'Failed to add widget to viewport',
|
|
314
|
-
details: bestEffortInterpretedText(interpreted)
|
|
315
|
-
};
|
|
248
|
+
return { success: false, error: interpreted.error ?? 'Failed to add widget to viewport', details: bestEffortInterpretedText(interpreted) };
|
|
316
249
|
} catch (e) {
|
|
317
250
|
return { success: false, error: `Failed to add widget to viewport: ${e}` };
|
|
318
251
|
}
|
|
319
252
|
}
|
|
320
253
|
|
|
321
|
-
// Remove widget from viewport
|
|
322
|
-
async removeWidgetFromViewport(params: {
|
|
323
|
-
widgetName: string;
|
|
324
|
-
playerIndex?: number;
|
|
325
|
-
}) {
|
|
326
|
-
const playerIndex = params.playerIndex ?? 0;
|
|
327
|
-
const command = `RemoveWidgetFromViewport ${params.widgetName} ${playerIndex}`;
|
|
328
|
-
return this.bridge.executeConsoleCommand(command);
|
|
329
|
-
}
|
|
330
254
|
|
|
331
255
|
// Create menu
|
|
332
256
|
async createMenu(params: {
|
|
@@ -338,19 +262,19 @@ except Exception as e:
|
|
|
338
262
|
position?: [number, number];
|
|
339
263
|
}>;
|
|
340
264
|
}) {
|
|
341
|
-
|
|
342
|
-
|
|
265
|
+
const commands: string[] = [];
|
|
266
|
+
|
|
343
267
|
commands.push(`CreateMenuWidget ${params.name} ${params.menuType}`);
|
|
344
|
-
|
|
268
|
+
|
|
345
269
|
if (params.buttons) {
|
|
346
270
|
for (const button of params.buttons) {
|
|
347
271
|
const pos = button.position || [0, 0];
|
|
348
272
|
commands.push(`AddMenuButton ${params.name} "${button.text}" ${button.action} ${pos.join(' ')}`);
|
|
349
273
|
}
|
|
350
274
|
}
|
|
351
|
-
|
|
275
|
+
|
|
352
276
|
await this.bridge.executeConsoleCommands(commands);
|
|
353
|
-
|
|
277
|
+
|
|
354
278
|
return { success: true, message: `Menu ${params.name} created` };
|
|
355
279
|
}
|
|
356
280
|
|
|
@@ -368,23 +292,23 @@ except Exception as e:
|
|
|
368
292
|
}>;
|
|
369
293
|
}>;
|
|
370
294
|
}) {
|
|
371
|
-
|
|
372
|
-
|
|
295
|
+
const commands: string[] = [];
|
|
296
|
+
|
|
373
297
|
commands.push(`CreateWidgetAnimation ${params.widgetName} ${params.animationName} ${params.duration}`);
|
|
374
|
-
|
|
298
|
+
|
|
375
299
|
if (params.tracks) {
|
|
376
300
|
for (const track of params.tracks) {
|
|
377
301
|
commands.push(`AddAnimationTrack ${params.widgetName}.${params.animationName} ${track.componentName} ${track.property}`);
|
|
378
|
-
|
|
302
|
+
|
|
379
303
|
for (const keyframe of track.keyframes) {
|
|
380
304
|
const value = Array.isArray(keyframe.value) ? keyframe.value.join(' ') : keyframe.value;
|
|
381
305
|
commands.push(`AddAnimationKeyframe ${params.widgetName}.${params.animationName} ${track.componentName} ${keyframe.time} ${value}`);
|
|
382
306
|
}
|
|
383
307
|
}
|
|
384
308
|
}
|
|
385
|
-
|
|
309
|
+
|
|
386
310
|
await this.bridge.executeConsoleCommands(commands);
|
|
387
|
-
|
|
311
|
+
|
|
388
312
|
return { success: true, message: `Animation ${params.animationName} created` };
|
|
389
313
|
}
|
|
390
314
|
|
|
@@ -397,7 +321,7 @@ except Exception as e:
|
|
|
397
321
|
}) {
|
|
398
322
|
const playMode = params.playMode || 'Forward';
|
|
399
323
|
const loops = params.loops ?? 1;
|
|
400
|
-
|
|
324
|
+
|
|
401
325
|
const command = `PlayWidgetAnimation ${params.widgetName} ${params.animationName} ${playMode} ${loops}`;
|
|
402
326
|
return this.bridge.executeConsoleCommand(command);
|
|
403
327
|
}
|
|
@@ -414,30 +338,30 @@ except Exception as e:
|
|
|
414
338
|
margin?: [number, number, number, number];
|
|
415
339
|
};
|
|
416
340
|
}) {
|
|
417
|
-
|
|
418
|
-
|
|
341
|
+
const commands: string[] = [];
|
|
342
|
+
|
|
419
343
|
if (params.style.backgroundColor) {
|
|
420
344
|
commands.push(`SetWidgetBackgroundColor ${params.widgetName}.${params.componentName} ${params.style.backgroundColor.join(' ')}`);
|
|
421
345
|
}
|
|
422
|
-
|
|
346
|
+
|
|
423
347
|
if (params.style.borderColor) {
|
|
424
348
|
commands.push(`SetWidgetBorderColor ${params.widgetName}.${params.componentName} ${params.style.borderColor.join(' ')}`);
|
|
425
349
|
}
|
|
426
|
-
|
|
350
|
+
|
|
427
351
|
if (params.style.borderWidth !== undefined) {
|
|
428
352
|
commands.push(`SetWidgetBorderWidth ${params.widgetName}.${params.componentName} ${params.style.borderWidth}`);
|
|
429
353
|
}
|
|
430
|
-
|
|
354
|
+
|
|
431
355
|
if (params.style.padding) {
|
|
432
356
|
commands.push(`SetWidgetPadding ${params.widgetName}.${params.componentName} ${params.style.padding.join(' ')}`);
|
|
433
357
|
}
|
|
434
|
-
|
|
358
|
+
|
|
435
359
|
if (params.style.margin) {
|
|
436
360
|
commands.push(`SetWidgetMargin ${params.widgetName}.${params.componentName} ${params.style.margin.join(' ')}`);
|
|
437
361
|
}
|
|
438
|
-
|
|
362
|
+
|
|
439
363
|
await this.bridge.executeConsoleCommands(commands);
|
|
440
|
-
|
|
364
|
+
|
|
441
365
|
return { success: true, message: 'Widget style updated' };
|
|
442
366
|
}
|
|
443
367
|
|
|
@@ -458,20 +382,20 @@ except Exception as e:
|
|
|
458
382
|
showCursor?: boolean;
|
|
459
383
|
lockCursor?: boolean;
|
|
460
384
|
}) {
|
|
461
|
-
|
|
462
|
-
|
|
385
|
+
const commands: string[] = [];
|
|
386
|
+
|
|
463
387
|
commands.push(`SetInputMode ${params.mode}`);
|
|
464
|
-
|
|
388
|
+
|
|
465
389
|
if (params.showCursor !== undefined) {
|
|
466
390
|
commands.push(`ShowMouseCursor ${params.showCursor}`);
|
|
467
391
|
}
|
|
468
|
-
|
|
392
|
+
|
|
469
393
|
if (params.lockCursor !== undefined) {
|
|
470
394
|
commands.push(`SetMouseLockMode ${params.lockCursor}`);
|
|
471
395
|
}
|
|
472
|
-
|
|
396
|
+
|
|
473
397
|
await this.bridge.executeConsoleCommands(commands);
|
|
474
|
-
|
|
398
|
+
|
|
475
399
|
return { success: true, message: `Input mode set to ${params.mode}` };
|
|
476
400
|
}
|
|
477
401
|
|
|
@@ -495,21 +419,21 @@ except Exception as e:
|
|
|
495
419
|
dropTargets?: string[];
|
|
496
420
|
}) {
|
|
497
421
|
const commands = [];
|
|
498
|
-
|
|
422
|
+
|
|
499
423
|
commands.push(`EnableDragDrop ${params.widgetName}.${params.componentName}`);
|
|
500
|
-
|
|
424
|
+
|
|
501
425
|
if (params.dragVisual) {
|
|
502
426
|
commands.push(`SetDragVisual ${params.widgetName}.${params.componentName} ${params.dragVisual}`);
|
|
503
427
|
}
|
|
504
|
-
|
|
428
|
+
|
|
505
429
|
if (params.dropTargets) {
|
|
506
430
|
for (const target of params.dropTargets) {
|
|
507
431
|
commands.push(`AddDropTarget ${params.widgetName}.${params.componentName} ${target}`);
|
|
508
432
|
}
|
|
509
433
|
}
|
|
510
|
-
|
|
434
|
+
|
|
511
435
|
await this.bridge.executeConsoleCommands(commands);
|
|
512
|
-
|
|
436
|
+
|
|
513
437
|
return { success: true, message: 'Drag and drop configured' };
|
|
514
438
|
}
|
|
515
439
|
|
|
@@ -523,7 +447,7 @@ except Exception as e:
|
|
|
523
447
|
const duration = params.duration ?? 3.0;
|
|
524
448
|
const type = params.type || 'Info';
|
|
525
449
|
const position = params.position || 'TopRight';
|
|
526
|
-
|
|
450
|
+
|
|
527
451
|
const command = `ShowNotification "${params.text}" ${duration} ${type} ${position}`;
|
|
528
452
|
return this.bridge.executeConsoleCommand(command);
|
|
529
453
|
}
|