@alpsckr/unitycli 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/contracts/command-contract.json +109 -217
- package/contracts/package-files.json +374 -294
- package/contracts/stable-session/direct-call-semantics.json +8 -2
- package/contracts/tool-completion-contract.json +148 -672
- package/dist/bridge/admission.d.ts +17 -1
- package/dist/bridge/admission.js +2 -0
- package/dist/bridge/admission.js.map +1 -1
- package/dist/bridge/domains/asset.js +3 -1
- package/dist/bridge/domains/asset.js.map +1 -1
- package/dist/bridge/domains/camera.js +39 -7
- package/dist/bridge/domains/camera.js.map +1 -1
- package/dist/bridge/domains/console.js +2 -1
- package/dist/bridge/domains/console.js.map +1 -1
- package/dist/bridge/domains/doctor.d.ts +3 -0
- package/dist/bridge/domains/doctor.js +8 -0
- package/dist/bridge/domains/doctor.js.map +1 -0
- package/dist/bridge/domains/editor.js +0 -4
- package/dist/bridge/domains/editor.js.map +1 -1
- package/dist/bridge/domains/game-object.js +4 -12
- package/dist/bridge/domains/game-object.js.map +1 -1
- package/dist/bridge/domains/graphics.js +1 -16
- package/dist/bridge/domains/graphics.js.map +1 -1
- package/dist/bridge/domains/object.js +3 -0
- package/dist/bridge/domains/object.js.map +1 -1
- package/dist/bridge/domains/physics.js +1 -2
- package/dist/bridge/domains/physics.js.map +1 -1
- package/dist/bridge/domains/profiler.js +18 -7
- package/dist/bridge/domains/profiler.js.map +1 -1
- package/dist/bridge/domains/project-tool.js +4 -0
- package/dist/bridge/domains/project-tool.js.map +1 -1
- package/dist/bridge/domains/reflection.js +10 -2
- package/dist/bridge/domains/reflection.js.map +1 -1
- package/dist/bridge/domains/runtime-tool.js +3 -0
- package/dist/bridge/domains/runtime-tool.js.map +1 -1
- package/dist/bridge/domains/scene.js +3 -8
- package/dist/bridge/domains/scene.js.map +1 -1
- package/dist/bridge/domains/screenshot.js +30 -6
- package/dist/bridge/domains/screenshot.js.map +1 -1
- package/dist/bridge/domains/ui.js +3 -1
- package/dist/bridge/domains/ui.js.map +1 -1
- package/dist/bridge/index.d.ts +5 -5
- package/dist/bridge/index.js +6 -9
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/registry.js +3 -5
- package/dist/bridge/registry.js.map +1 -1
- package/dist/bridge/session-supervisor.d.ts +6 -3
- package/dist/bridge/session-supervisor.js +122 -34
- package/dist/bridge/session-supervisor.js.map +1 -1
- package/dist/bridge/types.d.ts +6 -5
- package/dist/bridge/types.js +16 -2
- package/dist/bridge/types.js.map +1 -1
- package/dist/catalog-protocol.d.ts +64 -0
- package/dist/catalog-protocol.js +460 -0
- package/dist/catalog-protocol.js.map +1 -0
- package/dist/cli-commands/command.js +84 -61
- package/dist/cli-commands/command.js.map +1 -1
- package/dist/cli-commands/extensions.js +70 -50
- package/dist/cli-commands/extensions.js.map +1 -1
- package/dist/cli-commands/instances.js +1 -1
- package/dist/cli-commands/instances.js.map +1 -1
- package/dist/cli-process-owners.d.ts +6 -0
- package/dist/cli-process-owners.js +27 -0
- package/dist/cli-process-owners.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +20 -5
- package/dist/cli.js.map +1 -1
- package/dist/contracts/command-contract.js +14 -4
- package/dist/contracts/command-contract.js.map +1 -1
- package/dist/doctor.d.ts +4 -6
- package/dist/doctor.js +429 -398
- package/dist/doctor.js.map +1 -1
- package/dist/editor-blocker-observer.d.ts +2 -1
- package/dist/editor-blocker-observer.js +40 -13
- package/dist/editor-blocker-observer.js.map +1 -1
- package/dist/extension-availability.d.ts +27 -9
- package/dist/extension-availability.js +96 -56
- package/dist/extension-availability.js.map +1 -1
- package/dist/extensions/descriptor-loader.d.ts +2 -2
- package/dist/extensions/descriptor-loader.js +3 -4
- package/dist/extensions/descriptor-loader.js.map +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.js +1 -1
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/installer.d.ts +24 -7
- package/dist/extensions/installer.js +142 -66
- package/dist/extensions/installer.js.map +1 -1
- package/dist/extensions/registry.js +3 -5
- package/dist/extensions/registry.js.map +1 -1
- package/dist/extensions/state-contract.d.ts +11 -0
- package/dist/extensions/state-contract.js +50 -0
- package/dist/extensions/state-contract.js.map +1 -0
- package/dist/instances.d.ts +13 -1
- package/dist/instances.js +26 -0
- package/dist/instances.js.map +1 -1
- package/dist/package-manager.d.ts +0 -24
- package/dist/package-manager.js +5 -58
- package/dist/package-manager.js.map +1 -1
- package/dist/project-tool-discovery.d.ts +5 -2
- package/dist/project-tool-discovery.js +22 -18
- package/dist/project-tool-discovery.js.map +1 -1
- package/dist/runtime-code.js +1 -1
- package/dist/runtime-code.js.map +1 -1
- package/dist/tool-name.d.ts +4 -0
- package/dist/tool-name.js +15 -0
- package/dist/tool-name.js.map +1 -0
- package/dist/tools/.generated-completion-registry.d.ts +2 -0
- package/dist/tools/.generated-completion-registry.js +763 -325
- package/dist/tools/.generated-completion-registry.js.map +1 -1
- package/dist/tools/.generated-registry.d.ts +6 -11
- package/dist/tools/.generated-registry.js +6 -11
- package/dist/tools/.generated-registry.js.map +1 -1
- package/dist/tools/.generated-schemas.js +11 -16
- package/dist/tools/.generated-schemas.js.map +1 -1
- package/dist/tools/asset/refresh-status.d.ts +3 -0
- package/dist/tools/asset/refresh-status.js +12 -0
- package/dist/tools/asset/refresh-status.js.map +1 -0
- package/dist/tools/asset/refresh.js +7 -3
- package/dist/tools/asset/refresh.js.map +1 -1
- package/dist/tools/build/player-status.d.ts +3 -0
- package/dist/tools/build/player-status.js +12 -0
- package/dist/tools/build/player-status.js.map +1 -0
- package/dist/tools/build/run.js +1 -1
- package/dist/tools/build/run.js.map +1 -1
- package/dist/tools/catalog-control.d.ts +22 -0
- package/dist/tools/catalog-control.js +335 -0
- package/dist/tools/catalog-control.js.map +1 -0
- package/dist/tools/catalog.d.ts +7 -9
- package/dist/tools/catalog.js +66 -45
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/commands.d.ts +1 -1
- package/dist/tools/commands.js +44 -11
- package/dist/tools/commands.js.map +1 -1
- package/dist/tools/define.js +3 -2
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/dispatcher.d.ts +53 -6
- package/dist/tools/dispatcher.js +277 -108
- package/dist/tools/dispatcher.js.map +1 -1
- package/dist/tools/editor/compile.js +1 -1
- package/dist/tools/editor/compile.js.map +1 -1
- package/dist/tools/editor/play-mode-status.d.ts +3 -0
- package/dist/tools/editor/play-mode-status.js +12 -0
- package/dist/tools/editor/play-mode-status.js.map +1 -0
- package/dist/tools/editor/readiness.d.ts +0 -1
- package/dist/tools/editor/readiness.js +0 -1
- package/dist/tools/editor/readiness.js.map +1 -1
- package/dist/tools/editor/refresh.d.ts +7 -3
- package/dist/tools/editor/refresh.js +20 -15
- package/dist/tools/editor/refresh.js.map +1 -1
- package/dist/tools/editor/state.d.ts +2 -2
- package/dist/tools/editor/state.js +13 -12
- package/dist/tools/editor/state.js.map +1 -1
- package/dist/tools/metadata/derived.js +1 -7
- package/dist/tools/metadata/derived.js.map +1 -1
- package/dist/tools/metadata/status.js +1 -12
- package/dist/tools/metadata/status.js.map +1 -1
- package/dist/tools/metadata/types.d.ts +0 -2
- package/dist/tools/navmesh/live.js +1 -1
- package/dist/tools/navmesh/live.js.map +1 -1
- package/dist/tools/occlusion/live.js +1 -1
- package/dist/tools/occlusion/live.js.map +1 -1
- package/dist/tools/package/deploy.js +2 -2
- package/dist/tools/package/deploy.js.map +1 -1
- package/dist/tools/package/embed.js +1 -1
- package/dist/tools/package/embed.js.map +1 -1
- package/dist/tools/package/install-status.d.ts +3 -0
- package/dist/tools/package/install-status.js +12 -0
- package/dist/tools/package/install-status.js.map +1 -0
- package/dist/tools/package/install.js +3 -3
- package/dist/tools/package/install.js.map +1 -1
- package/dist/tools/package/live-resolve.js +45 -12
- package/dist/tools/package/live-resolve.js.map +1 -1
- package/dist/tools/package/registry-clear.js.map +1 -1
- package/dist/tools/package/registry-set.js.map +1 -1
- package/dist/tools/package/remove-status.d.ts +3 -0
- package/dist/tools/package/remove-status.js +12 -0
- package/dist/tools/package/remove-status.js.map +1 -0
- package/dist/tools/package/remove.js +3 -3
- package/dist/tools/package/remove.js.map +1 -1
- package/dist/tools/package/resolve.js +3 -3
- package/dist/tools/package/resolve.js.map +1 -1
- package/dist/tools/package/restore.js +2 -2
- package/dist/tools/package/restore.js.map +1 -1
- package/dist/tools/package/scoped-registry-add.js.map +1 -1
- package/dist/tools/status/support.d.ts +13 -0
- package/dist/tools/status/support.js +28 -0
- package/dist/tools/status/support.js.map +1 -0
- package/dist/tools/test/cancel.js +2 -2
- package/dist/tools/test/cancel.js.map +1 -1
- package/dist/tools/test/run-status.d.ts +3 -0
- package/dist/tools/test/run-status.js +12 -0
- package/dist/tools/test/run-status.js.map +1 -0
- package/dist/tools/test/run.js +7 -4
- package/dist/tools/test/run.js.map +1 -1
- package/dist/tools/tools/group-summaries.js +10 -14
- package/dist/tools/tools/group-summaries.js.map +1 -1
- package/docs/architecture.md +4 -4
- package/docs/availability-differences.md +4 -4
- package/docs/command-execution.md +4 -3
- package/docs/error-codes.md +13 -5
- package/docs/extensions.md +1 -7
- package/docs/risk-and-side-effects.md +4 -3
- package/docs/safety-boundaries.md +3 -1
- package/docs/target-and-instance.md +1 -1
- package/docs/tool-discovery.md +17 -10
- package/docs/tool-execution.md +18 -7
- package/extensions/cinemachine/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/hdrp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/probuilder/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/urp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/vfx-graph/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/package.json +2 -4
- package/skills/unitycli/SKILL.md +11 -2
- package/skills/unitycli/manifest.json +1 -1
- package/skills/unitycli/references/operation-protocol.md +3 -3
- package/unitypkg/Editor/AssemblyInfo.cs +5 -0
- package/unitypkg/Editor/Bridge/BridgeCommandRegistry.cs +49 -14
- package/unitypkg/Editor/Bridge/BridgeHttpServer.cs +9 -35
- package/unitypkg/Editor/Bridge/BridgeQueueState.cs +672 -0
- package/unitypkg/Editor/Bridge/BridgeWorkQueue.cs +970 -120
- package/unitypkg/Editor/BridgeStartupStateMachine.cs +59 -1
- package/unitypkg/Editor/Commands/ProjectToolCommands.cs +4 -0
- package/unitypkg/Editor/Commands/RuntimeToolCommands.cs +3 -0
- package/unitypkg/Editor/Generated/UnityCliToolCompletionRegistry.g.cs +379 -14
- package/unitypkg/Editor/Infrastructure/CodeExecSupport.cs +28 -13
- package/unitypkg/Editor/Infrastructure/RegistryOwnershipResolver.cs +132 -105
- package/unitypkg/Editor/Infrastructure/UnityCliActiveOperation.cs +138 -29
- package/unitypkg/Editor/Infrastructure/UnityCliAdmission.cs +1856 -237
- package/unitypkg/Editor/Infrastructure/UnityCliDoctorDiagnostics.cs +220 -0
- package/unitypkg/Editor/Infrastructure/UnityCliDurableStatusCoordinator.cs +118 -0
- package/unitypkg/Editor/Infrastructure/UnityCliEditorStateSnapshot.cs +2 -1
- package/unitypkg/Editor/Infrastructure/UnityCliHierarchyPager.cs +203 -0
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceCleanup.cs +2 -1
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceRegistry.cs +201 -63
- package/unitypkg/Editor/Infrastructure/UnityCliJson.cs +2 -3
- package/unitypkg/Editor/Infrastructure/UnityCliLiveBuildCoordinator.cs +289 -46
- package/unitypkg/Editor/Infrastructure/UnityCliLiveRefreshCoordinator.cs +87 -53
- package/unitypkg/Editor/Infrastructure/UnityCliNavMeshBakeCoordinator.cs +4 -4
- package/unitypkg/Editor/Infrastructure/UnityCliObjectRef.cs +128 -25
- package/unitypkg/Editor/Infrastructure/UnityCliObjectSerializer.cs +435 -327
- package/unitypkg/Editor/Infrastructure/UnityCliOcclusionBakeCoordinator.cs +4 -4
- package/unitypkg/Editor/Infrastructure/UnityCliOperationCoordinator.cs +351 -53
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveCoordinator.cs +118 -18
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveState.cs +20 -1
- package/unitypkg/Editor/Infrastructure/UnityCliReadGeneration.cs +97 -0
- package/unitypkg/Editor/Infrastructure/UnityCliReflection.cs +644 -133
- package/unitypkg/Editor/Infrastructure/UnityCliReloadOperation.cs +128 -41
- package/unitypkg/Editor/Infrastructure/UnityCliRuntimeExecutor.cs +14 -84
- package/unitypkg/Editor/Infrastructure/UnityCliSerializer.cs +220 -0
- package/unitypkg/Editor/Infrastructure/UnityCliSessionMutationLease.cs +69 -29
- package/unitypkg/Editor/Infrastructure/UnityCliTestRunCoordinator.cs +440 -54
- package/unitypkg/Editor/Infrastructure/UnityCliWaiter.cs +128 -35
- package/unitypkg/Editor/ProjectTools/IUnityCliTool.cs +9 -1
- package/unitypkg/Editor/ProjectTools/OfficialAttributeToolRegistry.cs +32 -31
- package/unitypkg/Editor/ProjectTools/ProjectToolRegistry.cs +607 -458
- package/unitypkg/Editor/ProjectTools/ProjectToolSchemaValidator.cs +35 -7
- package/unitypkg/Editor/ProjectTools/RegisteredTool.cs +501 -60
- package/unitypkg/Editor/ProjectTools/UnityCliProjectToolContext.cs +21 -0
- package/unitypkg/Editor/ProjectTools/UnityCliSchemaDeriver.cs +36 -7
- package/unitypkg/Editor/ProjectTools/UnityCliToolName.cs +30 -0
- package/unitypkg/Editor/Properties/AssemblyInfo.cs +3 -0
- package/unitypkg/Editor/Tools/asset/get-data.cs +16 -7
- package/unitypkg/Editor/Tools/build/BuildSceneStateTool.cs +23 -3
- package/unitypkg/Editor/Tools/build/BuildToolDtos.cs +2 -1
- package/unitypkg/Editor/Tools/build/scene/add.cs +6 -3
- package/unitypkg/Editor/Tools/build/scene/disable.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/enable.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/list.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/remove.cs +13 -3
- package/unitypkg/Editor/Tools/camera/CameraToolSupport.cs +38 -38
- package/unitypkg/Editor/Tools/camera/multiview.cs +13 -6
- package/unitypkg/Editor/Tools/camera/screenshot.cs +14 -7
- package/unitypkg/Editor/Tools/component/get.cs +16 -9
- package/unitypkg/Editor/Tools/component/modify.cs +6 -4
- package/unitypkg/Editor/Tools/console/clear.cs +7 -6
- package/unitypkg/Editor/Tools/console/get.cs +48 -16
- package/unitypkg/Editor/Tools/editor/EditorToolSupport.cs +143 -28
- package/unitypkg/Editor/Tools/editor/menu-items.cs +1 -1
- package/unitypkg/Editor/Tools/editor/play.cs +2 -11
- package/unitypkg/Editor/Tools/editor/selection.cs +1 -1
- package/unitypkg/Editor/Tools/editor/stop.cs +2 -11
- package/unitypkg/Editor/Tools/editor/windows.cs +1 -1
- package/unitypkg/Editor/Tools/go/GameObjectToolSupport.cs +54 -4
- package/unitypkg/Editor/Tools/go/delete.cs +1 -1
- package/unitypkg/Editor/Tools/go/find.cs +167 -70
- package/unitypkg/Editor/Tools/graphics/GraphicsToolSupport.cs +25 -0
- package/unitypkg/Editor/Tools/graphics/light-probe-group.cs +9 -3
- package/unitypkg/Editor/Tools/graphics/pipeline-info.cs +1 -1
- package/unitypkg/Editor/Tools/graphics/pipeline-settings.cs +1 -1
- package/unitypkg/Editor/Tools/graphics/quality.cs +2 -2
- package/unitypkg/Editor/Tools/graphics/reflection-probe.cs +3 -3
- package/unitypkg/Editor/Tools/graphics/stats.cs +1 -1
- package/unitypkg/Editor/Tools/object/ObjectToolSupport.cs +4 -4
- package/unitypkg/Editor/Tools/object/get-data.cs +9 -7
- package/unitypkg/Editor/Tools/object/modify.cs +7 -5
- package/unitypkg/Editor/Tools/physics/raycast.cs +24 -6
- package/unitypkg/Editor/Tools/prefab/stage.cs +1 -1
- package/unitypkg/Editor/Tools/profiler/ProfilerFrameDebuggerSupport.cs +94 -21
- package/unitypkg/Editor/Tools/profiler/ProfilerMemorySnapshotSupport.cs +397 -10
- package/unitypkg/Editor/Tools/profiler/ProfilerToolSupport.cs +18 -4
- package/unitypkg/Editor/Tools/profiler/frame-debugger/enable.cs +1 -1
- package/unitypkg/Editor/Tools/profiler/frame-debugger/events.cs +88 -87
- package/unitypkg/Editor/Tools/profiler/hierarchy.cs +278 -112
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/compare.cs +9 -5
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/list.cs +37 -35
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/take.cs +99 -97
- package/unitypkg/Editor/Tools/project/info.cs +1 -1
- package/unitypkg/Editor/Tools/project/layers.cs +1 -1
- package/unitypkg/Editor/Tools/project/tags.cs +1 -1
- package/unitypkg/Editor/Tools/reflection/method/call.cs +9 -7
- package/unitypkg/Editor/Tools/reflection/method/find.cs +27 -37
- package/unitypkg/Editor/Tools/reflection/type/schema.cs +24 -28
- package/unitypkg/Editor/Tools/scene/gameobject/component.cs +8 -5
- package/unitypkg/Editor/Tools/scene/gameobject/components.cs +10 -7
- package/unitypkg/Editor/Tools/scene/gameobject-support.cs +104 -8
- package/unitypkg/Editor/Tools/scene/gameobject.cs +37 -16
- package/unitypkg/Editor/Tools/scene/hierarchy.cs +146 -142
- package/unitypkg/Editor/Tools/screenshot/EditorElementCaptureToolSupport.cs +77 -25
- package/unitypkg/Editor/Tools/screenshot/ScreenshotToolSupport.cs +315 -95
- package/unitypkg/Editor/Tools/screenshot/editor-element.cs +7 -5
- package/unitypkg/Editor/Tools/screenshot/game-view.cs +35 -21
- package/unitypkg/Editor/Tools/screenshot/isolated-object.cs +29 -23
- package/unitypkg/Editor/Tools/screenshot/orbit.cs +37 -25
- package/unitypkg/Editor/Tools/screenshot/scene-view.cs +25 -18
- package/unitypkg/Editor/Tools/screenshot/screen.cs +177 -17
- package/unitypkg/Editor/Tools/screenshot/surround.cs +83 -79
- package/unitypkg/Editor/Tools/ui/render-preview.cs +16 -11
- package/unitypkg/Editor/UnityCliBridge.cs +97 -34
- package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeBridge.cs +753 -122
- package/unitypkg/Runtime/Properties/AssemblyInfo.cs +5 -0
- package/unitypkg/Runtime/UnityCli.Runtime.asmdef +1 -1
- package/unitypkg/Shared/AssemblyInfo.cs +4 -0
- package/unitypkg/Shared/UnityCliAdmissionPool.cs +265 -75
- package/unitypkg/Shared/UnityCliBridgeQueuePolicy.cs +410 -0
- package/unitypkg/Shared/UnityCliBridgeWorkItemState.cs +47 -0
- package/unitypkg/Shared/UnityCliExceptionProjection.cs +151 -0
- package/unitypkg/Shared/UnityCliQueuePublication.cs +30 -0
- package/unitypkg/Shared/UnityCliRequestBudget.cs +352 -0
- package/unitypkg/Shared/UnityCliRuntimeRequestPublication.cs +107 -0
- package/unitypkg/Tests/Editor/UnityCli.Editor.Tests.asmdef +2 -2
- package/unitypkg/Tests/Editor/UnityCliAdmissionCoordinatorIntegrationTests.cs +1329 -0
- package/unitypkg/Tests/Editor/UnityCliAdmissionPoolTests.cs +311 -114
- package/unitypkg/Tests/Editor/UnityCliAdmissionRepairStateTests.cs +94 -0
- package/unitypkg/Tests/Editor/UnityCliBridgeAdmissionIntegrationTests.cs +1229 -0
- package/unitypkg/Tests/Editor/UnityCliBridgeQueuePolicyTests.cs +412 -0
- package/unitypkg/Tests/Editor/UnityCliContinuationIntegrationTests.cs +292 -0
- package/unitypkg/Tests/Editor/UnityCliDiagnosticBoundaryTests.cs +120 -0
- package/unitypkg/Tests/Editor/UnityCliDurableStatusTests.cs +84 -0
- package/unitypkg/Tests/Editor/UnityCliExceptionProjectionTests.cs +72 -0
- package/unitypkg/Tests/Editor/UnityCliInstancePublicationRetryTests.cs +180 -97
- package/unitypkg/Tests/Editor/UnityCliMemoryReflectionIntegrationTests.cs +434 -0
- package/unitypkg/Tests/Editor/UnityCliRequestBudgetTests.cs +615 -0
- package/unitypkg/Tests/Editor/UnityCliRuntimeBridgeIntegrationTests.cs +520 -0
- package/unitypkg/Tests/Editor/UnityCliToolCatalogTests.cs +562 -0
- package/unitypkg/Tests/Runtime/UnityCli.Runtime.Tests.asmdef +23 -0
- package/unitypkg/Tests/Runtime/UnityCliRuntimeCatalogValidationTests.cs +29 -0
- package/unitypkg/package.json +1 -1
- package/contracts/static-capability-catalog.json +0 -48226
- package/dist/bridge/domains/diagnose.d.ts +0 -2
- package/dist/bridge/domains/diagnose.js +0 -11
- package/dist/bridge/domains/diagnose.js.map +0 -1
- package/dist/bridge/domains/extension.d.ts +0 -8
- package/dist/bridge/domains/extension.js +0 -20
- package/dist/bridge/domains/extension.js.map +0 -1
- package/dist/capabilities.d.ts +0 -5
- package/dist/capabilities.js +0 -84
- package/dist/capabilities.js.map +0 -1
- package/dist/static-capability-catalog.d.ts +0 -13
- package/dist/static-capability-catalog.js +0 -41
- package/dist/static-capability-catalog.js.map +0 -1
- package/dist/tools/diagnose/capabilities.d.ts +0 -13
- package/dist/tools/diagnose/capabilities.js +0 -34
- package/dist/tools/diagnose/capabilities.js.map +0 -1
- package/dist/tools/package/info.d.ts +0 -19
- package/dist/tools/package/info.js +0 -27
- package/dist/tools/package/info.js.map +0 -1
- package/dist/tools/package/list.d.ts +0 -27
- package/dist/tools/package/list.js +0 -21
- package/dist/tools/package/list.js.map +0 -1
- package/dist/tools/package/registry-get.d.ts +0 -10
- package/dist/tools/package/registry-get.js +0 -22
- package/dist/tools/package/registry-get.js.map +0 -1
- package/dist/tools/package/scoped-registry-list.d.ts +0 -14
- package/dist/tools/package/scoped-registry-list.js +0 -22
- package/dist/tools/package/scoped-registry-list.js.map +0 -1
- package/dist/tools/package/search.d.ts +0 -17
- package/dist/tools/package/search.js +0 -39
- package/dist/tools/package/search.js.map +0 -1
- package/dist/tools/package/status.d.ts +0 -21
- package/dist/tools/package/status.js +0 -37
- package/dist/tools/package/status.js.map +0 -1
- package/dist/tools/tools/describe.d.ts +0 -27
- package/dist/tools/tools/describe.js +0 -35
- package/dist/tools/tools/describe.js.map +0 -1
- package/dist/tools/tools/group-list.d.ts +0 -16
- package/dist/tools/tools/group-list.js +0 -38
- package/dist/tools/tools/group-list.js.map +0 -1
- package/dist/tools/tools/group.d.ts +0 -13
- package/dist/tools/tools/group.js +0 -34
- package/dist/tools/tools/group.js.map +0 -1
- package/dist/tools/tools/pagination.d.ts +0 -17
- package/dist/tools/tools/pagination.js +0 -28
- package/dist/tools/tools/pagination.js.map +0 -1
- package/dist/tools/tools/search.d.ts +0 -15
- package/dist/tools/tools/search.js +0 -42
- package/dist/tools/tools/search.js.map +0 -1
- package/unitypkg/Editor/Tools/diagnose/preflight.cs +0 -269
- package/unitypkg/Editor/Tools/editor/console.cs +0 -26
- package/unitypkg/Editor/Tools/extension/status.cs +0 -87
- package/unitypkg/Editor/Tools/go/inspect.cs +0 -49
- package/unitypkg/Editor/Tools/graphics/pipeline-quality.cs +0 -24
- package/unitypkg/Editor/Tools/graphics/probe-positions.cs +0 -58
- package/unitypkg/Editor/Tools/graphics/settings.cs +0 -104
- package/unitypkg/Editor/Tools/graphics/stats-counters.cs +0 -28
- package/unitypkg/Editor/Tools/graphics/stats-memory.cs +0 -21
- package/unitypkg/Editor/Tools/instances/list.cs +0 -71
- package/unitypkg/Editor/Tools/physics/raycast-all.cs +0 -67
- package/unitypkg/Editor/Tools/scene/build-settings.cs +0 -69
- package/unitypkg/Editor/Tools/scene/data.cs +0 -125
- package/unitypkg/Editor/Tools/tests/list.cs +0 -98
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#if UNITY_EDITOR
|
|
2
2
|
using System;
|
|
3
|
+
using System.Collections.Generic;
|
|
3
4
|
using System.IO;
|
|
5
|
+
using System.Threading;
|
|
4
6
|
using UnityEngine;
|
|
5
7
|
|
|
6
8
|
namespace UnityCli
|
|
@@ -15,7 +17,9 @@ namespace UnityCli
|
|
|
15
17
|
[UnityCliRequired] public string Path { get; set; }
|
|
16
18
|
public bool Overwrite { get; set; }
|
|
17
19
|
public bool InlineBase64 { get; set; }
|
|
18
|
-
public int? SuperSize { get; set; }
|
|
20
|
+
[UnityCliRange(1L, 4L)] public int? SuperSize { get; set; }
|
|
21
|
+
public ScreenshotBudgetInput Limits { get; set; }
|
|
22
|
+
public UnityCliReadBudgetInput Budget { get; set; }
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
public sealed class Result : ScreenshotCaptureResult { }
|
|
@@ -24,7 +28,7 @@ namespace UnityCli
|
|
|
24
28
|
{
|
|
25
29
|
Name = "screenshot.screen",
|
|
26
30
|
Summary = "Capture the final composited screen including screen-space UI to a PNG file.",
|
|
27
|
-
Description = "Capture the final composited frame
|
|
31
|
+
Description = "Capture the final composited frame including screen-space UI. superSize is 1..4 and the resulting Game View dimensions must each be 1..8192 with at most 16777216 pixels. Before ScreenCapture, the plan must fit default ceilings of 33554432 total pixels, 128 MiB temporary memory and 64 MiB artifacts (public maxima 67108864, 256 MiB and 256 MiB). The file is produced at frame end; available in Edit and Play Mode but most reliable in Play Mode.",
|
|
28
32
|
Group = "screenshot",
|
|
29
33
|
DestructiveHint = true,
|
|
30
34
|
SideEffects = new[] { "asset-write" },
|
|
@@ -42,39 +46,195 @@ namespace UnityCli
|
|
|
42
46
|
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_FORMAT_UNSUPPORTED", "screenshot.screen only writes .png output.", "Pass a .png output path.");
|
|
43
47
|
if (File.Exists(outputPath) && !request.Overwrite)
|
|
44
48
|
throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_EXISTS", "Screenshot output already exists: " + outputPath, "Pass overwrite=true or choose a different output path.");
|
|
49
|
+
var requestBudget = ctx.UseReadBudget(request.Budget);
|
|
50
|
+
var superSize = request.SuperSize ?? 1;
|
|
51
|
+
if (!requestBudget.TryConsumeGetter() || !requestBudget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(requestBudget.ExhaustedDimension);
|
|
52
|
+
var width = checked(Screen.width * superSize);
|
|
53
|
+
var height = checked(Screen.height * superSize);
|
|
54
|
+
var captureBudget = ScreenshotToolSupport.PrepareCaptureBudget(width, height, 1, false, request.Limits, requestBudget);
|
|
45
55
|
ctx.CommitEffect();
|
|
46
56
|
ScreenshotToolSupport.CreateScreenshotDirectory(outputPath);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
captureBudget.BeginCapture(width, height);
|
|
58
|
+
ScreenshotArtifactProof artifact;
|
|
59
|
+
using (var publication = new PendingCapturePublication(outputPath))
|
|
60
|
+
{
|
|
61
|
+
// ScreenCapture 只写本请求的唯一 pending;旧 final 与并发请求都不能满足 fresh-write proof。
|
|
62
|
+
publication.BeginWrite();
|
|
63
|
+
ScreenCapture.CaptureScreenshot(publication.PendingPath, superSize);
|
|
64
|
+
var written = await ctx.Wait.Until(
|
|
65
|
+
() => File.Exists(publication.PendingPath) && new FileInfo(publication.PendingPath).Length > 0,
|
|
66
|
+
TimeSpan.FromMilliseconds(Math.Max(1, ctx.TimeoutMs)),
|
|
67
|
+
ct);
|
|
68
|
+
ctx.ReadBudget.ResumeAfterWait();
|
|
69
|
+
if (!written)
|
|
70
|
+
{
|
|
71
|
+
publication.TryFault();
|
|
72
|
+
throw new UnityCliBridge.BridgeCommandException("E_EXECUTION_TIMEOUT", "ScreenCapture did not write the screenshot before the deadline.", "Retry with a larger timeout, or use screenshot.game-view for camera-only capture.");
|
|
73
|
+
}
|
|
55
74
|
|
|
56
|
-
|
|
57
|
-
|
|
75
|
+
captureBudget.ChargeArtifact(new FileInfo(publication.PendingPath).Length);
|
|
76
|
+
artifact = ScreenshotToolSupport.VerifyScreenshotArtifact(publication.PendingPath, "png", captureBudget);
|
|
77
|
+
publication.Publish();
|
|
78
|
+
artifact.Path = outputPath;
|
|
79
|
+
}
|
|
80
|
+
var dimensions = ReadPngDimensions(outputPath);
|
|
58
81
|
var result = new Result
|
|
59
82
|
{
|
|
60
83
|
ScreenshotPath = outputPath, ArtifactPath = outputPath, Source = "screen",
|
|
61
|
-
SizeBytes = artifact.SizeBytes, Sha256 = artifact.Sha256
|
|
84
|
+
SizeBytes = artifact.SizeBytes, Sha256 = artifact.Sha256, CapturePlan = captureBudget.Plan
|
|
62
85
|
};
|
|
63
|
-
if (request.InlineBase64)
|
|
86
|
+
if (request.InlineBase64 && artifact.SizeBytes <= 512 * 1024)
|
|
64
87
|
{
|
|
65
88
|
var bytes = File.ReadAllBytes(outputPath);
|
|
66
|
-
ScreenshotToolSupport.MaybeAppendInline(result, bytes, (int)width, (int)height, "image/png", true);
|
|
89
|
+
ScreenshotToolSupport.MaybeAppendInline(result, bytes, (int)dimensions.width, (int)dimensions.height, "image/png", true, captureBudget);
|
|
67
90
|
}
|
|
68
91
|
return result;
|
|
69
92
|
}
|
|
70
93
|
|
|
94
|
+
private static readonly object PublicationLock = new object();
|
|
95
|
+
private static readonly object PendingLock = new object();
|
|
96
|
+
private static readonly HashSet<string> LivePending = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
97
|
+
private static readonly HashSet<string> LateWriterPending = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
98
|
+
private const int PendingOwnerLimit = 8;
|
|
99
|
+
private const int MaximumObservedPendingFiles = 1024;
|
|
100
|
+
|
|
101
|
+
/// <summary>每次 capture 都有唯一同目录 pending;迟到 writer 的 owner 不复用,当前启动最多保留8个。</summary>
|
|
102
|
+
internal sealed class PendingCapturePublication : IDisposable
|
|
103
|
+
{
|
|
104
|
+
private readonly string outputPath;
|
|
105
|
+
private int terminal;
|
|
106
|
+
private int writerStarted;
|
|
107
|
+
|
|
108
|
+
internal PendingCapturePublication(string outputPath)
|
|
109
|
+
{
|
|
110
|
+
if (string.IsNullOrWhiteSpace(outputPath)) throw new ArgumentException("Output path is required.", "outputPath");
|
|
111
|
+
this.outputPath = outputPath;
|
|
112
|
+
SweepObservedPending(Path.GetDirectoryName(outputPath));
|
|
113
|
+
PendingPath = outputPath + "." + Guid.NewGuid().ToString("N") + ".unitycli.pending";
|
|
114
|
+
lock (PendingLock)
|
|
115
|
+
{
|
|
116
|
+
if (LivePending.Count + LateWriterPending.Count >= PendingOwnerLimit)
|
|
117
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_PENDING_SLOTS_BUSY", "All 8 screenshot pending owners are waiting for capture or late-writer cleanup.", "Wait for prior ScreenCapture writes to settle, then retry.");
|
|
118
|
+
LivePending.Add(PendingPath);
|
|
119
|
+
}
|
|
120
|
+
try { DeletePendingStrict(PendingPath); }
|
|
121
|
+
catch
|
|
122
|
+
{
|
|
123
|
+
lock (PendingLock) LivePending.Remove(PendingPath);
|
|
124
|
+
throw;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
internal string PendingPath { get; private set; }
|
|
129
|
+
|
|
130
|
+
internal void BeginWrite()
|
|
131
|
+
{
|
|
132
|
+
if (Volatile.Read(ref terminal) != 0) throw new InvalidOperationException("Screenshot pending publication already reached a terminal state.");
|
|
133
|
+
Volatile.Write(ref writerStarted, 1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
internal void Publish()
|
|
137
|
+
{
|
|
138
|
+
if (Interlocked.CompareExchange(ref terminal, 1, 0) != 0)
|
|
139
|
+
throw new InvalidOperationException("Screenshot pending publication already reached a terminal state.");
|
|
140
|
+
try { PublishPending(PendingPath, outputPath); }
|
|
141
|
+
catch
|
|
142
|
+
{
|
|
143
|
+
DeletePendingStrict(PendingPath);
|
|
144
|
+
throw;
|
|
145
|
+
}
|
|
146
|
+
finally
|
|
147
|
+
{
|
|
148
|
+
lock (PendingLock) LivePending.Remove(PendingPath);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
internal bool TryFault()
|
|
153
|
+
{
|
|
154
|
+
if (Interlocked.CompareExchange(ref terminal, 2, 0) != 0) return false;
|
|
155
|
+
DeletePendingStrict(PendingPath);
|
|
156
|
+
lock (PendingLock)
|
|
157
|
+
{
|
|
158
|
+
LivePending.Remove(PendingPath);
|
|
159
|
+
if (Volatile.Read(ref writerStarted) != 0) LateWriterPending.Add(PendingPath);
|
|
160
|
+
}
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public void Dispose()
|
|
165
|
+
{
|
|
166
|
+
TryFault();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/// <summary>只观察最多1024个产品 pending;迟到文件出现后删除并释放对应 owner。</summary>
|
|
171
|
+
private static void SweepObservedPending(string directory)
|
|
172
|
+
{
|
|
173
|
+
if (string.IsNullOrWhiteSpace(directory) || !Directory.Exists(directory)) return;
|
|
174
|
+
var observed = 0;
|
|
175
|
+
foreach (var path in Directory.EnumerateFiles(directory, "*.unitycli.pending", SearchOption.TopDirectoryOnly))
|
|
176
|
+
{
|
|
177
|
+
observed++;
|
|
178
|
+
if (observed > MaximumObservedPendingFiles)
|
|
179
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_PENDING_SCAN_LIMIT", "Screenshot pending cleanup exceeded the 1024-file observation limit.", "Remove stale *.unitycli.pending files from the output directory and retry.");
|
|
180
|
+
var lateWriter = false;
|
|
181
|
+
var delete = false;
|
|
182
|
+
lock (PendingLock)
|
|
183
|
+
{
|
|
184
|
+
lateWriter = LateWriterPending.Contains(path);
|
|
185
|
+
delete = lateWriter || !LivePending.Contains(path);
|
|
186
|
+
}
|
|
187
|
+
if (!delete) continue;
|
|
188
|
+
DeletePendingStrict(path);
|
|
189
|
+
if (lateWriter)
|
|
190
|
+
{
|
|
191
|
+
lock (PendingLock) LateWriterPending.Remove(path);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// <summary>同目录唯一 pending 在进程内串行原子 rename;失败时保留原 final。</summary>
|
|
197
|
+
internal static void PublishPending(string pendingPath, string outputPath)
|
|
198
|
+
{
|
|
199
|
+
lock (PublicationLock)
|
|
200
|
+
{
|
|
201
|
+
try
|
|
202
|
+
{
|
|
203
|
+
if (File.Exists(outputPath)) File.Replace(pendingPath, outputPath, null, true);
|
|
204
|
+
else File.Move(pendingPath, outputPath);
|
|
205
|
+
}
|
|
206
|
+
catch (Exception exception)
|
|
207
|
+
{
|
|
208
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_PUBLISH_FAILED", "Failed to atomically publish screenshot output: " + exception.Message, "Inspect output permissions and retry after the pending file is clean.");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/// <summary>pending删除失败必须显式终止,不能积累或被后续capture复用。</summary>
|
|
214
|
+
internal static void DeletePendingStrict(string pendingPath)
|
|
215
|
+
{
|
|
216
|
+
try
|
|
217
|
+
{
|
|
218
|
+
if (File.Exists(pendingPath)) File.Delete(pendingPath);
|
|
219
|
+
if (File.Exists(pendingPath)) throw new IOException("pending path still exists after deletion");
|
|
220
|
+
}
|
|
221
|
+
catch (Exception exception)
|
|
222
|
+
{
|
|
223
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_PENDING_CLEANUP_FAILED", "Failed to clean screenshot pending output: " + exception.Message, "Remove the reported pending file after checking its exact path, then retry.");
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
71
227
|
// 从落盘 PNG 的 IHDR 读取实际宽高(大端),用于报告 Game View 实际分辨率。
|
|
72
228
|
private static (long width, long height) ReadPngDimensions(string path)
|
|
73
229
|
{
|
|
74
230
|
try
|
|
75
231
|
{
|
|
76
|
-
var bytes =
|
|
77
|
-
|
|
232
|
+
var bytes = new byte[24];
|
|
233
|
+
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
|
234
|
+
{
|
|
235
|
+
if (stream.Read(bytes, 0, bytes.Length) < bytes.Length) return (0, 0);
|
|
236
|
+
}
|
|
237
|
+
if (bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4e && bytes[3] == 0x47)
|
|
78
238
|
{
|
|
79
239
|
long width = ((long)bytes[16] << 24) | ((long)bytes[17] << 16) | ((long)bytes[18] << 8) | bytes[19];
|
|
80
240
|
long height = ((long)bytes[20] << 24) | ((long)bytes[21] << 16) | ((long)bytes[22] << 8) | bytes[23];
|
|
@@ -6,9 +6,7 @@ using UnityEngine;
|
|
|
6
6
|
|
|
7
7
|
namespace UnityCli
|
|
8
8
|
{
|
|
9
|
-
/// <summary>
|
|
10
|
-
/// screenshot.surround — 6 角度环绕截图并生成 contact sheet。破坏性(asset-write)。
|
|
11
|
-
/// </summary>
|
|
9
|
+
/// <summary>screenshot.surround — 六张逐次释放的捕获与一个 aggregate contact sheet。</summary>
|
|
12
10
|
public class ScreenshotSurroundTool : IUnityCliTool<ScreenshotSurroundTool.Request, ScreenshotSurroundTool.Result>
|
|
13
11
|
{
|
|
14
12
|
public sealed class Request
|
|
@@ -16,12 +14,14 @@ namespace UnityCli
|
|
|
16
14
|
[UnityCliRequired] public string Target { get; set; }
|
|
17
15
|
public string OutputDir { get; set; } = "Assets/Screenshots/Surround";
|
|
18
16
|
public string ContactSheetPath { get; set; }
|
|
19
|
-
public int? Width { get; set; }
|
|
20
|
-
public int? Height { get; set; }
|
|
17
|
+
[UnityCliRange(1L, 8192L)] public int? Width { get; set; }
|
|
18
|
+
[UnityCliRange(1L, 8192L)] public int? Height { get; set; }
|
|
21
19
|
public float? Radius { get; set; }
|
|
22
20
|
public float? Fov { get; set; }
|
|
23
21
|
public bool Overwrite { get; set; }
|
|
24
22
|
public bool InlineBase64 { get; set; }
|
|
23
|
+
public ScreenshotBudgetInput Limits { get; set; }
|
|
24
|
+
public UnityCliReadBudgetInput Budget { get; set; }
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
public sealed class Result
|
|
@@ -35,6 +35,7 @@ namespace UnityCli
|
|
|
35
35
|
public long? ImageWidth { get; set; }
|
|
36
36
|
public long? ImageHeight { get; set; }
|
|
37
37
|
public string ImageMimeType { get; set; }
|
|
38
|
+
public ScreenshotCapturePlan CapturePlan { get; set; }
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
public sealed class SurroundShot
|
|
@@ -47,134 +48,137 @@ namespace UnityCli
|
|
|
47
48
|
public ToolDescriptor Describe() => new()
|
|
48
49
|
{
|
|
49
50
|
Name = "screenshot.surround",
|
|
50
|
-
Summary = "Capture six fixed
|
|
51
|
-
Description = "Capture
|
|
52
|
-
Group = "screenshot",
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Target = "
|
|
56
|
-
PlayModeSupport = "editor-only",
|
|
57
|
-
SupportsDryRun = true,
|
|
58
|
-
DefaultTimeoutMs = 30000,
|
|
59
|
-
MaxTimeoutMs = 600000,
|
|
60
|
-
Examples = new[] { new ToolExample { Description = "Surround a target (dry-run)", Input = new Request { Target = "Player" }, Execution = new ToolExampleExecution { DryRun = true } } }
|
|
51
|
+
Summary = "Capture six fixed views and one bounded contact sheet while releasing every tile immediately.",
|
|
52
|
+
Description = "Capture front/back/left/right/top/bird_eye PNGs plus a 3x2 contact sheet. Tile and contact-sheet dimensions each must satisfy 1..8192 and 16777216 pixels per image. Before dry-run or the first effect, the seven-output aggregate plan must fit default ceilings of 33554432 total pixels, 128 MiB peak temporary memory and 64 MiB artifacts; public maxima are 67108864, 256 MiB and 256 MiB. radius must be positive and fov must be 10..120. Each tile is copied into the sheet, encoded, written and destroyed before the next capture. Editor-only; dry-run returns the same frozen plan without effects.",
|
|
53
|
+
Group = "screenshot", DestructiveHint = true, SideEffects = new[] { "asset-write" },
|
|
54
|
+
Target = "editor", PlayModeSupport = "editor-only", SupportsDryRun = true,
|
|
55
|
+
DefaultTimeoutMs = 30000, MaxTimeoutMs = 600000,
|
|
56
|
+
Examples = new[] { new ToolExample { Description = "Preview surround artifacts", Input = new Request { Target = "Player" }, Execution = new ToolExampleExecution { DryRun = true } } }
|
|
61
57
|
};
|
|
62
58
|
|
|
63
59
|
public System.Threading.Tasks.ValueTask<Result> ExecuteAsync(Request request, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
|
|
64
60
|
{
|
|
65
|
-
var
|
|
66
|
-
|
|
67
|
-
|
|
61
|
+
var requestBudget = ctx.UseReadBudget(request.Budget);
|
|
62
|
+
var gameObject = UnityCliBridge.ObjectRefResolver.FindGameObjectByExactPath(request.Target, requestBudget);
|
|
63
|
+
if (gameObject == null) throw new UnityCliBridge.BridgeCommandException("E_TARGET_NOT_FOUND", "screenshot.surround requires a target GameObject.", "Pass an exact hierarchy path.");
|
|
68
64
|
var outputDir = request.OutputDir ?? "Assets/Screenshots/Surround";
|
|
69
65
|
var outputFullDir = ScreenshotToolSupport.AssetFullPath(outputDir);
|
|
70
66
|
var contactSheetPath = ScreenshotToolSupport.ResolveScreenshotOutputPath(request.ContactSheetPath ?? Path.Combine(outputDir, "surround_contact_sheet.png"));
|
|
71
|
-
var width =
|
|
72
|
-
var height =
|
|
73
|
-
var bounds = ScreenshotToolSupport.TargetRenderBounds(
|
|
67
|
+
var width = request.Width ?? 512;
|
|
68
|
+
var height = request.Height ?? 512;
|
|
69
|
+
var bounds = ScreenshotToolSupport.TargetRenderBounds(gameObject, requestBudget);
|
|
74
70
|
var center = bounds.center;
|
|
75
71
|
var radius = request.Radius ?? Mathf.Max(bounds.extents.magnitude * 2.5f, 5f);
|
|
72
|
+
var fov = request.Fov ?? 60f;
|
|
73
|
+
if (float.IsNaN(radius) || float.IsInfinity(radius) || radius <= 0f)
|
|
74
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_LIMIT_INVALID", "radius must be finite and greater than zero.", "Pass a positive finite radius.");
|
|
75
|
+
if (float.IsNaN(fov) || float.IsInfinity(fov) || fov < 10f || fov > 120f)
|
|
76
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_LIMIT_INVALID", "fov must be finite in 10..120.", "Pass a supported field of view.");
|
|
77
|
+
var captureBudget = ScreenshotToolSupport.PrepareCaptureBudget(width, height, 6, true, request.Limits, requestBudget);
|
|
76
78
|
|
|
77
79
|
var labels = new[] { "front", "back", "left", "right", "top", "bird_eye" };
|
|
78
80
|
var positions = new[]
|
|
79
81
|
{
|
|
80
|
-
center + new Vector3(0, 0, -radius),
|
|
81
|
-
center + new Vector3(0, 0, radius),
|
|
82
|
-
center + new Vector3(
|
|
83
|
-
center + new Vector3(radius, 0, 0),
|
|
84
|
-
center + new Vector3(0, radius, 0),
|
|
85
|
-
center + new Vector3(radius * 0.7f, radius * 0.7f, -radius * 0.7f)
|
|
82
|
+
center + new Vector3(0, 0, -radius), center + new Vector3(0, 0, radius),
|
|
83
|
+
center + new Vector3(-radius, 0, 0), center + new Vector3(radius, 0, 0),
|
|
84
|
+
center + new Vector3(0, radius, 0), center + new Vector3(radius * 0.7f, radius * 0.7f, -radius * 0.7f)
|
|
86
85
|
};
|
|
87
86
|
var shotPaths = new List<string>();
|
|
88
|
-
for (var
|
|
87
|
+
for (var index = 0; index < labels.Length; index++)
|
|
89
88
|
{
|
|
90
|
-
var path = Path.Combine(outputFullDir, "surround_" + labels[
|
|
91
|
-
if (File.Exists(path) && !request.Overwrite)
|
|
92
|
-
throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_EXISTS", "Screenshot output already exists: " + path, "Pass overwrite=true or choose a different output-dir.");
|
|
89
|
+
var path = Path.Combine(outputFullDir, "surround_" + labels[index] + ".png");
|
|
90
|
+
if (File.Exists(path) && !request.Overwrite) throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_EXISTS", "Screenshot output already exists: " + path, "Pass overwrite=true or choose a different outputDir.");
|
|
93
91
|
shotPaths.Add(path);
|
|
94
92
|
}
|
|
95
|
-
if (File.Exists(contactSheetPath) && !request.Overwrite)
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
if (File.Exists(contactSheetPath) && !request.Overwrite) throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_EXISTS", "Contact sheet output already exists: " + contactSheetPath, "Pass overwrite=true or choose another path.");
|
|
94
|
+
var planned = BuildPlannedShots(labels, shotPaths, width, height, positions);
|
|
98
95
|
if (ctx.DryRun)
|
|
99
96
|
{
|
|
100
97
|
return new System.Threading.Tasks.ValueTask<Result>(new Result
|
|
101
98
|
{
|
|
102
|
-
DryRun = true,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
Artifacts = BuildPlannedShots(labels, shotPaths, width, height, positions)
|
|
99
|
+
DryRun = true, Center = new[] { (double)center.x, center.y, center.z }, Count = 6,
|
|
100
|
+
ContactSheet = new ScreenshotArtifactEntry { Source = "surround-contact-sheet", Path = contactSheetPath, Width = width * 3L, Height = height * 2L, Format = "png" },
|
|
101
|
+
Artifacts = planned, CapturePlan = captureBudget.Plan
|
|
106
102
|
});
|
|
107
103
|
}
|
|
108
104
|
|
|
109
105
|
ctx.CommitEffect();
|
|
110
106
|
Directory.CreateDirectory(outputFullDir);
|
|
111
107
|
ScreenshotToolSupport.CreateScreenshotDirectory(contactSheetPath);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
cam.nearClipPlane = 0.1f;
|
|
116
|
-
cam.farClipPlane = Mathf.Max(radius * 6f, 100f);
|
|
117
|
-
cam.clearFlags = CameraClearFlags.SolidColor;
|
|
118
|
-
cam.backgroundColor = new Color(0.18f, 0.18f, 0.18f, 1f);
|
|
119
|
-
var tiles = new List<Texture2D>();
|
|
108
|
+
GameObject cameraObject = null;
|
|
109
|
+
Camera camera = null;
|
|
110
|
+
Texture2D sheet = null;
|
|
120
111
|
var artifacts = new List<SurroundShot>();
|
|
121
112
|
byte[] contactBytes = null;
|
|
113
|
+
ScreenshotArtifactProof contactProof = null;
|
|
122
114
|
try
|
|
123
115
|
{
|
|
124
|
-
|
|
116
|
+
cameraObject = new GameObject("__unitycli_surround_cam__");
|
|
117
|
+
camera = cameraObject.AddComponent<Camera>();
|
|
118
|
+
camera.fieldOfView = fov;
|
|
119
|
+
camera.nearClipPlane = 0.1f;
|
|
120
|
+
camera.farClipPlane = Mathf.Max(radius * 6f, 100f);
|
|
121
|
+
camera.clearFlags = CameraClearFlags.SolidColor;
|
|
122
|
+
camera.backgroundColor = new Color(0.18f, 0.18f, 0.18f, 1f);
|
|
123
|
+
sheet = ScreenshotToolSupport.CreateContactSheet(width, height, captureBudget);
|
|
124
|
+
for (var index = 0; index < labels.Length; index++)
|
|
125
125
|
{
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
var tile = ScreenshotToolSupport.RenderScreenshotTexture(
|
|
129
|
-
|
|
130
|
-
var proof = ScreenshotToolSupport.WriteScreenshotBytes(shotPaths[i], tile.EncodeToPNG());
|
|
131
|
-
artifacts.Add(new SurroundShot
|
|
126
|
+
camera.transform.position = positions[index];
|
|
127
|
+
camera.transform.LookAt(center);
|
|
128
|
+
var tile = ScreenshotToolSupport.RenderScreenshotTexture(camera, width, height, captureBudget);
|
|
129
|
+
try
|
|
132
130
|
{
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
ScreenshotToolSupport.CopyContactSheetTile(sheet, tile, index, width, height);
|
|
132
|
+
var proof = ScreenshotToolSupport.WriteScreenshotBytes(shotPaths[index], tile.EncodeToPNG(), captureBudget);
|
|
133
|
+
artifacts.Add(new SurroundShot
|
|
134
|
+
{
|
|
135
|
+
Angle = labels[index],
|
|
136
|
+
Artifact = new ScreenshotArtifactEntry { Source = "surround", Path = shotPaths[index], Camera = "surround:" + labels[index], Width = width, Height = height, Format = "png", SizeBytes = proof.SizeBytes, Sha256 = proof.Sha256 },
|
|
137
|
+
CameraPosition = new[] { (double)positions[index].x, positions[index].y, positions[index].z }
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
finally { UnityEngine.Object.DestroyImmediate(tile); }
|
|
137
141
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
142
|
+
sheet.Apply(false, false);
|
|
143
|
+
contactBytes = sheet.EncodeToPNG();
|
|
144
|
+
contactProof = ScreenshotToolSupport.WriteScreenshotBytes(contactSheetPath, contactBytes, captureBudget);
|
|
141
145
|
}
|
|
142
146
|
finally
|
|
143
147
|
{
|
|
144
|
-
|
|
145
|
-
UnityEngine.Object.DestroyImmediate(
|
|
148
|
+
if (sheet != null) UnityEngine.Object.DestroyImmediate(sheet);
|
|
149
|
+
if (cameraObject != null) UnityEngine.Object.DestroyImmediate(cameraObject);
|
|
146
150
|
}
|
|
147
151
|
|
|
148
|
-
var contactProof = ScreenshotToolSupport.VerifyScreenshotArtifact(contactSheetPath, "png");
|
|
149
152
|
var result = new Result
|
|
150
153
|
{
|
|
151
|
-
Center = new
|
|
152
|
-
ContactSheet = new ScreenshotArtifactEntry { Source = "surround-contact-sheet", Path = contactSheetPath, Width = width *
|
|
153
|
-
Artifacts = artifacts
|
|
154
|
+
Center = new[] { (double)center.x, center.y, center.z }, Count = 6,
|
|
155
|
+
ContactSheet = new ScreenshotArtifactEntry { Source = "surround-contact-sheet", Path = contactSheetPath, Width = width * 3L, Height = height * 2L, Format = "png", SizeBytes = contactProof.SizeBytes, Sha256 = contactProof.Sha256 },
|
|
156
|
+
Artifacts = artifacts, CapturePlan = captureBudget.Plan
|
|
154
157
|
};
|
|
155
|
-
|
|
158
|
+
string encoded;
|
|
159
|
+
if (request.InlineBase64 && contactBytes != null && contactBytes.Length <= 512 * 1024 && captureBudget.TryCreateInlineBase64(contactBytes, out encoded))
|
|
156
160
|
{
|
|
157
|
-
result.ImageBase64 =
|
|
158
|
-
result.ImageWidth = width *
|
|
159
|
-
result.ImageHeight = height *
|
|
161
|
+
result.ImageBase64 = encoded;
|
|
162
|
+
result.ImageWidth = width * 3L;
|
|
163
|
+
result.ImageHeight = height * 2L;
|
|
160
164
|
result.ImageMimeType = "image/png";
|
|
161
165
|
}
|
|
162
166
|
return new System.Threading.Tasks.ValueTask<Result>(result);
|
|
163
167
|
}
|
|
164
168
|
|
|
165
|
-
private static List<SurroundShot> BuildPlannedShots(string[] labels, List<string>
|
|
169
|
+
private static List<SurroundShot> BuildPlannedShots(string[] labels, List<string> paths, int width, int height, Vector3[] positions)
|
|
166
170
|
{
|
|
167
|
-
var
|
|
168
|
-
for (var
|
|
171
|
+
var result = new List<SurroundShot>();
|
|
172
|
+
for (var index = 0; index < labels.Length; index++)
|
|
169
173
|
{
|
|
170
|
-
|
|
174
|
+
result.Add(new SurroundShot
|
|
171
175
|
{
|
|
172
|
-
Angle = labels[
|
|
173
|
-
Artifact = new ScreenshotArtifactEntry { Source = "surround", Path =
|
|
174
|
-
CameraPosition = new
|
|
176
|
+
Angle = labels[index],
|
|
177
|
+
Artifact = new ScreenshotArtifactEntry { Source = "surround", Path = paths[index], Camera = "surround:" + labels[index], Width = width, Height = height, Format = "png" },
|
|
178
|
+
CameraPosition = new[] { (double)positions[index].x, positions[index].y, positions[index].z }
|
|
175
179
|
});
|
|
176
180
|
}
|
|
177
|
-
return
|
|
181
|
+
return result;
|
|
178
182
|
}
|
|
179
183
|
}
|
|
180
184
|
}
|
|
@@ -15,9 +15,11 @@ namespace UnityCli
|
|
|
15
15
|
{
|
|
16
16
|
public string Target { get; set; }
|
|
17
17
|
public string Output { get; set; }
|
|
18
|
-
public int? Width { get; set; }
|
|
19
|
-
public int? Height { get; set; }
|
|
18
|
+
[UnityCliRange(1L, 8192L)] public int? Width { get; set; }
|
|
19
|
+
[UnityCliRange(1L, 8192L)] public int? Height { get; set; }
|
|
20
20
|
public bool Overwrite { get; set; }
|
|
21
|
+
public ScreenshotBudgetInput Limits { get; set; }
|
|
22
|
+
public UnityCliReadBudgetInput Budget { get; set; }
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
public sealed class Result
|
|
@@ -67,12 +69,13 @@ namespace UnityCli
|
|
|
67
69
|
var document = go.GetComponent<UIDocument>();
|
|
68
70
|
if (document == null) throw new UnityCliBridge.BridgeCommandException("E_UI_DOCUMENT_NOT_FOUND", "No UIDocument on target.", "Pass a GameObject containing UIDocument.");
|
|
69
71
|
|
|
70
|
-
var width =
|
|
71
|
-
var height =
|
|
72
|
+
var width = request.Width ?? 1280;
|
|
73
|
+
var height = request.Height ?? 720;
|
|
72
74
|
var outputPath = ScreenshotToolSupport.ResolveScreenshotOutputPath(request.Output ?? "Assets/UI/preview.png");
|
|
73
75
|
if (File.Exists(outputPath) && !request.Overwrite)
|
|
74
76
|
throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_EXISTS", "UI preview output already exists: " + outputPath, "Pass overwrite=true or choose a different output path.");
|
|
75
77
|
|
|
78
|
+
var captureBudget = ScreenshotToolSupport.PrepareCaptureBudget(width, height, 1, false, request.Limits, ctx.UseReadBudget(request.Budget));
|
|
76
79
|
var effects = new List<UiPlannedEffect> { new UiPlannedEffect { Type = "ui.render-preview", Target = request.Target, Path = outputPath } };
|
|
77
80
|
if (ctx.DryRun)
|
|
78
81
|
{
|
|
@@ -80,20 +83,24 @@ namespace UnityCli
|
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
ctx.CommitEffect();
|
|
86
|
+
captureBudget.BeginCapture(width, height);
|
|
83
87
|
var originalPanelSettings = document.panelSettings;
|
|
84
88
|
var originalEnabled = document.enabled;
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
RenderTexture renderTexture = null;
|
|
90
|
+
PanelSettings panelSettings = null;
|
|
87
91
|
Texture2D texture = null;
|
|
88
92
|
var previousActive = RenderTexture.active;
|
|
89
93
|
try
|
|
90
94
|
{
|
|
95
|
+
renderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
|
|
96
|
+
panelSettings = ScriptableObject.CreateInstance<PanelSettings>();
|
|
91
97
|
renderTexture.Create();
|
|
92
98
|
panelSettings.targetTexture = renderTexture;
|
|
93
99
|
panelSettings.scaleMode = PanelScaleMode.ConstantPixelSize;
|
|
94
100
|
document.panelSettings = panelSettings;
|
|
95
101
|
document.enabled = true;
|
|
96
102
|
await ctx.Wait.NextFrame(2, ct);
|
|
103
|
+
ctx.ReadBudget.ResumeAfterWait();
|
|
97
104
|
ct.ThrowIfCancellationRequested();
|
|
98
105
|
|
|
99
106
|
RenderTexture.active = renderTexture;
|
|
@@ -101,8 +108,7 @@ namespace UnityCli
|
|
|
101
108
|
texture.ReadPixels(new Rect(0, 0, width, height), 0, 0, false);
|
|
102
109
|
texture.Apply(false, false);
|
|
103
110
|
var bytes = texture.EncodeToPNG();
|
|
104
|
-
ScreenshotToolSupport.WriteScreenshotBytes(outputPath, bytes);
|
|
105
|
-
var artifact = ScreenshotToolSupport.VerifyScreenshotArtifact(outputPath, "png");
|
|
111
|
+
var artifact = ScreenshotToolSupport.WriteScreenshotBytes(outputPath, bytes, captureBudget);
|
|
106
112
|
return new Result
|
|
107
113
|
{
|
|
108
114
|
DryRun = false,
|
|
@@ -118,9 +124,8 @@ namespace UnityCli
|
|
|
118
124
|
document.panelSettings = originalPanelSettings;
|
|
119
125
|
document.enabled = originalEnabled;
|
|
120
126
|
if (texture != null) Object.DestroyImmediate(texture);
|
|
121
|
-
renderTexture.Release();
|
|
122
|
-
Object.DestroyImmediate(
|
|
123
|
-
Object.DestroyImmediate(panelSettings);
|
|
127
|
+
if (renderTexture != null) { renderTexture.Release(); Object.DestroyImmediate(renderTexture); }
|
|
128
|
+
if (panelSettings != null) Object.DestroyImmediate(panelSettings);
|
|
124
129
|
}
|
|
125
130
|
}
|
|
126
131
|
}
|