@alpsckr/unitycli 0.4.2 → 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 +35 -42
- 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
|
@@ -3,162 +3,382 @@ using System;
|
|
|
3
3
|
using System.Collections.Generic;
|
|
4
4
|
using System.Globalization;
|
|
5
5
|
using System.IO;
|
|
6
|
-
using System.Linq;
|
|
7
6
|
using System.Security.Cryptography;
|
|
8
|
-
using UnityEditor;
|
|
9
7
|
using UnityEngine;
|
|
10
8
|
|
|
11
9
|
namespace UnityCli
|
|
12
10
|
{
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
public sealed class ScreenshotBudgetInput
|
|
12
|
+
{
|
|
13
|
+
[UnityCliRange(1L, ScreenshotToolSupport.AbsoluteMaxTotalPixels)] public long? MaxTotalPixels { get; set; }
|
|
14
|
+
[UnityCliRange(1L, ScreenshotToolSupport.AbsoluteMaxTemporaryBytes)] public long? MaxTemporaryBytes { get; set; }
|
|
15
|
+
[UnityCliRange(1024L, ScreenshotToolSupport.AbsoluteMaxArtifactBytes)] public long? MaxArtifactBytes { get; set; }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// <summary>首个捕获 effect 前冻结的 aggregate 资源计划。</summary>
|
|
19
|
+
public sealed class ScreenshotCapturePlan
|
|
20
|
+
{
|
|
21
|
+
public long CaptureCount { get; set; }
|
|
22
|
+
public long TotalPixels { get; set; }
|
|
23
|
+
public long PeakTemporaryBytes { get; set; }
|
|
24
|
+
public long ArtifactByteCeiling { get; set; }
|
|
25
|
+
public long PlannedWorstCaseArtifactBytes { get; set; }
|
|
26
|
+
public long MaxPixelsPerCapture { get; set; }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// <summary>截图域的尺寸、内存、捕获次数和 artifact byte 统一 owner。</summary>
|
|
17
30
|
public static class ScreenshotToolSupport
|
|
18
31
|
{
|
|
19
|
-
|
|
20
|
-
public
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
public const int MaxImageDimension = 8192;
|
|
33
|
+
public const long MaxPixelsPerImage = 16777216L;
|
|
34
|
+
public const int MaxCaptureCount = 36;
|
|
35
|
+
public const long DefaultMaxTotalPixels = 33554432L;
|
|
36
|
+
public const long AbsoluteMaxTotalPixels = 67108864L;
|
|
37
|
+
public const long DefaultMaxTemporaryBytes = 128L * 1024L * 1024L;
|
|
38
|
+
public const long AbsoluteMaxTemporaryBytes = 256L * 1024L * 1024L;
|
|
39
|
+
public const long DefaultMaxArtifactBytes = 64L * 1024L * 1024L;
|
|
40
|
+
public const long AbsoluteMaxArtifactBytes = 256L * 1024L * 1024L;
|
|
41
|
+
private const int InlineImageMaxBytes = 512 * 1024;
|
|
24
42
|
|
|
25
|
-
|
|
26
|
-
public static string AssetFullPath(string assetPath)
|
|
27
|
-
{
|
|
28
|
-
return Path.Combine(ProjectRoot(), assetPath.Replace('/', Path.DirectorySeparatorChar));
|
|
29
|
-
}
|
|
43
|
+
public static string ProjectRoot() { return Directory.GetParent(Application.dataPath).FullName; }
|
|
44
|
+
public static string AssetFullPath(string assetPath) { return Path.Combine(ProjectRoot(), assetPath.Replace('/', Path.DirectorySeparatorChar)); }
|
|
30
45
|
|
|
31
|
-
/// <summary>解析截图输出绝对路径;相对路径解析到 Unity 工程根目录下。</summary>
|
|
32
46
|
public static string ResolveScreenshotOutputPath(string rawPath)
|
|
33
47
|
{
|
|
34
|
-
if (string.IsNullOrEmpty(rawPath))
|
|
35
|
-
{
|
|
36
|
-
throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_PATH_REQUIRED", "Screenshot requires a path.", "Pass --output <path> or a positional screenshot path.");
|
|
37
|
-
}
|
|
48
|
+
if (string.IsNullOrEmpty(rawPath)) throw new UnityCliBridge.BridgeCommandException("E_OUTPUT_PATH_REQUIRED", "Screenshot requires a path.", "Pass a non-empty screenshot output path.");
|
|
38
49
|
var normalized = rawPath.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar);
|
|
39
50
|
return Path.GetFullPath(Path.IsPathRooted(normalized) ? normalized : Path.Combine(ProjectRoot(), normalized));
|
|
40
51
|
}
|
|
41
52
|
|
|
42
|
-
/// <summary>创建截图输出目录(缺失时)。</summary>
|
|
43
53
|
public static void CreateScreenshotDirectory(string outputPath)
|
|
44
54
|
{
|
|
45
55
|
try { Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); }
|
|
46
56
|
catch (Exception exception) { throw new UnityCliBridge.BridgeCommandException("E_IO_ERROR", "Failed to create screenshot output directory: " + exception.Message); }
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
/// <summary
|
|
50
|
-
public static
|
|
59
|
+
/// <summary>按所有图片合计值冻结计划;任何无效或超限输入都在 caller CommitEffect 前失败。</summary>
|
|
60
|
+
public static ScreenshotCaptureBudget PrepareCaptureBudget(int width, int height, int captureCount, bool contactSheet, ScreenshotBudgetInput input, UnityCliRequestBudget requestBudget)
|
|
51
61
|
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
62
|
+
input = input ?? new ScreenshotBudgetInput();
|
|
63
|
+
var maxTotalPixels = input.MaxTotalPixels ?? DefaultMaxTotalPixels;
|
|
64
|
+
var maxTemporaryBytes = input.MaxTemporaryBytes ?? DefaultMaxTemporaryBytes;
|
|
65
|
+
var maxArtifactBytes = input.MaxArtifactBytes ?? DefaultMaxArtifactBytes;
|
|
66
|
+
ValidateLimit(maxTotalPixels, 1L, AbsoluteMaxTotalPixels, "maxTotalPixels");
|
|
67
|
+
ValidateLimit(maxTemporaryBytes, 1L, AbsoluteMaxTemporaryBytes, "maxTemporaryBytes");
|
|
68
|
+
ValidateLimit(maxArtifactBytes, 1024L, AbsoluteMaxArtifactBytes, "maxArtifactBytes");
|
|
69
|
+
ValidateDimensions(width, height, "capture");
|
|
70
|
+
if (captureCount < 1 || captureCount > MaxCaptureCount) throw Limit("capture count must be between 1 and 36.");
|
|
71
|
+
var imagePixels = checked((long)width * height);
|
|
72
|
+
var sheetPixels = contactSheet ? checked(imagePixels * 6L) : 0L;
|
|
73
|
+
if (contactSheet) ValidateDimensions(checked(width * 3), checked(height * 2), "contact sheet");
|
|
74
|
+
var totalPixels = checked(imagePixels * captureCount + sheetPixels);
|
|
75
|
+
// 同时覆盖 RenderTexture/depth、readable texture、编码缓冲与 contact-sheet copy 缓冲。
|
|
76
|
+
var peakTemporaryBytes = contactSheet
|
|
77
|
+
? checked(imagePixels * 12L + sheetPixels * 8L + 65536L)
|
|
78
|
+
: checked(imagePixels * 12L + 65536L);
|
|
79
|
+
var worstCaseArtifacts = checked(totalPixels * 4L + (captureCount + (contactSheet ? 1 : 0)) * 65536L);
|
|
80
|
+
if (totalPixels > maxTotalPixels) throw Limit("aggregate totalPixels " + totalPixels.ToString(CultureInfo.InvariantCulture) + " exceeds maxTotalPixels.");
|
|
81
|
+
if (peakTemporaryBytes > maxTemporaryBytes) throw Limit("peak temporary bytes " + peakTemporaryBytes.ToString(CultureInfo.InvariantCulture) + " exceeds maxTemporaryBytes.");
|
|
82
|
+
if (worstCaseArtifacts > maxArtifactBytes) throw Limit("planned worst-case artifact bytes " + worstCaseArtifacts.ToString(CultureInfo.InvariantCulture) + " exceeds maxArtifactBytes.");
|
|
83
|
+
return new ScreenshotCaptureBudget(new ScreenshotCapturePlan
|
|
84
|
+
{
|
|
85
|
+
CaptureCount = captureCount + (contactSheet ? 1 : 0), TotalPixels = totalPixels,
|
|
86
|
+
PeakTemporaryBytes = peakTemporaryBytes, ArtifactByteCeiling = maxArtifactBytes,
|
|
87
|
+
PlannedWorstCaseArtifactBytes = worstCaseArtifacts,
|
|
88
|
+
MaxPixelsPerCapture = contactSheet ? sheetPixels : imagePixels
|
|
89
|
+
}, requestBudget);
|
|
57
90
|
}
|
|
58
91
|
|
|
59
|
-
|
|
60
|
-
public static ScreenshotArtifactProof VerifyScreenshotArtifact(string outputPath, string format)
|
|
92
|
+
public static void ValidateDimensions(int width, int height, string owner)
|
|
61
93
|
{
|
|
62
|
-
if (
|
|
63
|
-
throw
|
|
64
|
-
var
|
|
65
|
-
|
|
66
|
-
var valid = normalized == "png"
|
|
67
|
-
? bytes.Length >= 8 && bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4e && bytes[3] == 0x47 && bytes[4] == 0x0d && bytes[5] == 0x0a && bytes[6] == 0x1a && bytes[7] == 0x0a
|
|
68
|
-
: bytes.Length >= 3 && bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff;
|
|
69
|
-
if (!valid)
|
|
70
|
-
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_ARTIFACT_INVALID", "Screenshot artifact is empty or does not match its requested format: " + outputPath, "Use a .png or .jpg output path and retry the capture.");
|
|
71
|
-
using (var sha = SHA256.Create())
|
|
72
|
-
return new ScreenshotArtifactProof { Path = outputPath, SizeBytes = bytes.LongLength, Sha256 = string.Concat(Array.ConvertAll(sha.ComputeHash(bytes), value => value.ToString("x2"))), Format = normalized };
|
|
94
|
+
if (width < 1 || width > MaxImageDimension || height < 1 || height > MaxImageDimension)
|
|
95
|
+
throw Limit(owner + " dimensions must each be between 1 and 8192 pixels.");
|
|
96
|
+
var pixels = checked((long)width * height);
|
|
97
|
+
if (pixels > MaxPixelsPerImage) throw Limit(owner + " image pixels must not exceed 16777216.");
|
|
73
98
|
}
|
|
74
99
|
|
|
75
|
-
|
|
76
|
-
public static string NormalizeFormat(string rawFormat, string outputPath)
|
|
100
|
+
public static ScreenshotArtifactProof WriteScreenshotBytes(string outputPath, byte[] bytes, ScreenshotCaptureBudget budget)
|
|
77
101
|
{
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
102
|
+
if (bytes == null || bytes.Length == 0) throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_ARTIFACT_EMPTY", "Screenshot encoder produced no image data.", "Check the camera and render settings, then retry.");
|
|
103
|
+
budget.ChargeArtifact(bytes.LongLength);
|
|
104
|
+
try
|
|
105
|
+
{
|
|
106
|
+
using (var stream = new FileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
|
107
|
+
{
|
|
108
|
+
const int chunkSize = 64 * 1024;
|
|
109
|
+
for (var offset = 0; offset < bytes.Length; offset += chunkSize)
|
|
110
|
+
{
|
|
111
|
+
budget.Checkpoint();
|
|
112
|
+
var count = Math.Min(chunkSize, bytes.Length - offset);
|
|
113
|
+
stream.Write(bytes, offset, count);
|
|
114
|
+
}
|
|
115
|
+
stream.Flush(true);
|
|
116
|
+
}
|
|
117
|
+
var proof = VerifyScreenshotArtifact(outputPath, Path.GetExtension(outputPath).TrimStart('.'), budget);
|
|
118
|
+
if (proof.SizeBytes != bytes.LongLength)
|
|
119
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_ARTIFACT_INVALID", "Persisted screenshot size differs from the encoded artifact.", "Inspect output storage before retrying.");
|
|
120
|
+
return proof;
|
|
121
|
+
}
|
|
122
|
+
catch (UnityCliBridge.BridgeCommandException) { DeleteArtifactNoThrow(outputPath); throw; }
|
|
123
|
+
catch (UnityCliRequestBudgetExceededException) { DeleteArtifactNoThrow(outputPath); throw; }
|
|
124
|
+
catch (OperationCanceledException) { DeleteArtifactNoThrow(outputPath); throw; }
|
|
125
|
+
catch (Exception exception)
|
|
82
126
|
{
|
|
83
|
-
|
|
127
|
+
DeleteArtifactNoThrow(outputPath);
|
|
128
|
+
throw new UnityCliBridge.BridgeCommandException("E_IO_ERROR", "Failed to write screenshot output: " + exception.Message);
|
|
84
129
|
}
|
|
85
|
-
return fmt;
|
|
86
130
|
}
|
|
87
131
|
|
|
88
|
-
/// <summary
|
|
89
|
-
public static
|
|
132
|
+
/// <summary>fresh proof 使用 bounded stream header/hash,并在每个固定块检查同一 deadline/cancel。</summary>
|
|
133
|
+
public static ScreenshotArtifactProof VerifyScreenshotArtifact(string outputPath, string format, ScreenshotCaptureBudget budget)
|
|
90
134
|
{
|
|
135
|
+
if (!File.Exists(outputPath)) throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_ARTIFACT_MISSING", "Screenshot artifact was not written: " + outputPath, "Check output permissions before retrying.");
|
|
136
|
+
var info = new FileInfo(outputPath);
|
|
137
|
+
budget.EnsureArtifactSize(info.Length);
|
|
138
|
+
var normalized = NormalizeFormat(format, outputPath);
|
|
139
|
+
var header = new byte[8];
|
|
140
|
+
string hash;
|
|
141
|
+
using (var stream = new FileStream(outputPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
|
142
|
+
{
|
|
143
|
+
budget.Checkpoint();
|
|
144
|
+
var read = stream.Read(header, 0, header.Length);
|
|
145
|
+
var valid = normalized == "png"
|
|
146
|
+
? read == 8 && header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4e && header[3] == 0x47 && header[4] == 0x0d && header[5] == 0x0a && header[6] == 0x1a && header[7] == 0x0a
|
|
147
|
+
: read >= 3 && header[0] == 0xff && header[1] == 0xd8 && header[2] == 0xff;
|
|
148
|
+
if (!valid) throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_ARTIFACT_INVALID", "Screenshot artifact does not match its requested format: " + outputPath, "Use a .png or .jpg output path and retry.");
|
|
149
|
+
stream.Position = 0L;
|
|
150
|
+
using (var sha = SHA256.Create())
|
|
151
|
+
{
|
|
152
|
+
var buffer = new byte[64 * 1024];
|
|
153
|
+
int count;
|
|
154
|
+
while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
|
|
155
|
+
{
|
|
156
|
+
budget.Checkpoint();
|
|
157
|
+
sha.TransformBlock(buffer, 0, count, buffer, 0);
|
|
158
|
+
}
|
|
159
|
+
sha.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
|
|
160
|
+
hash = string.Concat(Array.ConvertAll(sha.Hash, value => value.ToString("x2", CultureInfo.InvariantCulture)));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
budget.Checkpoint();
|
|
164
|
+
return new ScreenshotArtifactProof { Path = outputPath, SizeBytes = info.Length, Sha256 = hash, Format = normalized };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public static string NormalizeFormat(string rawFormat, string outputPath)
|
|
168
|
+
{
|
|
169
|
+
var format = string.IsNullOrEmpty(rawFormat) ? Path.GetExtension(outputPath).TrimStart('.').ToLowerInvariant() : rawFormat.ToLowerInvariant();
|
|
170
|
+
if (string.IsNullOrEmpty(format)) format = "png";
|
|
171
|
+
if (format == "jpeg") format = "jpg";
|
|
172
|
+
if (format != "png" && format != "jpg") throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_FORMAT_UNSUPPORTED", "Screenshot format must be png or jpg.");
|
|
173
|
+
return format;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
public static Texture2D RenderScreenshotTexture(Camera camera, int width, int height, ScreenshotCaptureBudget budget)
|
|
177
|
+
{
|
|
178
|
+
budget.BeginCapture(width, height);
|
|
91
179
|
var previousTarget = camera.targetTexture;
|
|
92
180
|
var previousActive = RenderTexture.active;
|
|
93
|
-
RenderTexture
|
|
94
|
-
Texture2D texture = null;
|
|
181
|
+
RenderTexture renderTexture = null;
|
|
95
182
|
try
|
|
96
183
|
{
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
camera.targetTexture = rt;
|
|
184
|
+
renderTexture = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
|
|
185
|
+
camera.targetTexture = renderTexture;
|
|
100
186
|
camera.Render();
|
|
101
|
-
RenderTexture.active =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
187
|
+
RenderTexture.active = renderTexture;
|
|
188
|
+
return CreateTextureWithOwnership(
|
|
189
|
+
() => new Texture2D(width, height, TextureFormat.RGB24, false),
|
|
190
|
+
texture =>
|
|
191
|
+
{
|
|
192
|
+
texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
|
|
193
|
+
texture.Apply();
|
|
194
|
+
},
|
|
195
|
+
texture => UnityEngine.Object.DestroyImmediate(texture));
|
|
105
196
|
}
|
|
106
197
|
finally
|
|
107
198
|
{
|
|
108
199
|
RenderTexture.active = previousActive;
|
|
109
200
|
camera.targetTexture = previousTarget;
|
|
110
|
-
if (
|
|
201
|
+
if (renderTexture != null) { renderTexture.Release(); UnityEngine.Object.DestroyImmediate(renderTexture); }
|
|
111
202
|
}
|
|
112
203
|
}
|
|
113
204
|
|
|
114
|
-
|
|
115
|
-
|
|
205
|
+
public static Texture2D CreateContactSheet(int tileWidth, int tileHeight, ScreenshotCaptureBudget budget)
|
|
206
|
+
{
|
|
207
|
+
budget.BeginCapture(tileWidth * 3, tileHeight * 2);
|
|
208
|
+
var sheet = new Texture2D(tileWidth * 3, tileHeight * 2, TextureFormat.RGB24, false);
|
|
209
|
+
return sheet;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/// <summary>只有完整populate成功才转移texture ownership;任何异常都同步销毁新资源。</summary>
|
|
213
|
+
internal static Texture2D CreateTextureWithOwnership(
|
|
214
|
+
Func<Texture2D> create,
|
|
215
|
+
Action<Texture2D> populate,
|
|
216
|
+
Action<Texture2D> destroy)
|
|
116
217
|
{
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
218
|
+
if (create == null) throw new ArgumentNullException("create");
|
|
219
|
+
if (populate == null) throw new ArgumentNullException("populate");
|
|
220
|
+
if (destroy == null) throw new ArgumentNullException("destroy");
|
|
221
|
+
var texture = create();
|
|
222
|
+
var ownershipTransferred = false;
|
|
223
|
+
try
|
|
224
|
+
{
|
|
225
|
+
populate(texture);
|
|
226
|
+
ownershipTransferred = true;
|
|
227
|
+
return texture;
|
|
228
|
+
}
|
|
229
|
+
finally
|
|
121
230
|
{
|
|
122
|
-
if (
|
|
231
|
+
if (!ownershipTransferred && texture != null) destroy(texture);
|
|
123
232
|
}
|
|
124
|
-
return bounds;
|
|
125
233
|
}
|
|
126
234
|
|
|
127
|
-
/// <summary
|
|
128
|
-
public static
|
|
235
|
+
/// <summary>逐 tile 写入 sheet 后 caller 立即释放 tile,避免同时持有全部捕获纹理。</summary>
|
|
236
|
+
public static void CopyContactSheetTile(Texture2D sheet, Texture2D tile, int index, int tileWidth, int tileHeight)
|
|
237
|
+
{
|
|
238
|
+
var column = index % 3;
|
|
239
|
+
var row = 1 - index / 3;
|
|
240
|
+
var pixels = tile.GetPixels32();
|
|
241
|
+
sheet.SetPixels32(column * tileWidth, row * tileHeight, tileWidth, tileHeight, pixels);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// <summary>逐节点和逐child读取渲染边界,组件数组仅在已验证cardinality与剩余预算后创建。</summary>
|
|
245
|
+
public static Bounds TargetRenderBounds(GameObject gameObject, UnityCliRequestBudget budget)
|
|
129
246
|
{
|
|
130
|
-
|
|
131
|
-
var
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
247
|
+
if (!budget.TryConsumeGetters(2)) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
248
|
+
var root = gameObject.transform;
|
|
249
|
+
var stack = new Stack<TransformTraversalFrame>();
|
|
250
|
+
stack.Push(new TransformTraversalFrame(root));
|
|
251
|
+
var found = false;
|
|
252
|
+
var bounds = new Bounds(root.position, Vector3.one);
|
|
253
|
+
while (stack.Count > 0)
|
|
136
254
|
{
|
|
137
|
-
var
|
|
138
|
-
|
|
139
|
-
|
|
255
|
+
var frame = stack.Peek();
|
|
256
|
+
if (!frame.Entered)
|
|
257
|
+
{
|
|
258
|
+
if (!budget.TryCheckpoint() || !budget.TryConsumeScannedRecord() || !budget.TryConsumeNode() || !budget.TryConsumeGetters(2))
|
|
259
|
+
throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
260
|
+
frame.Entered = true;
|
|
261
|
+
frame.ChildCount = frame.Transform.childCount;
|
|
262
|
+
var components = UnityCliBridge.ObjectRefResolver.BoundedComponents(frame.Transform.gameObject, budget);
|
|
263
|
+
foreach (var component in components)
|
|
264
|
+
{
|
|
265
|
+
var renderer = component as Renderer;
|
|
266
|
+
if (renderer == null) continue;
|
|
267
|
+
if (!budget.TryConsumeGetters(2)) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
268
|
+
if (!renderer.gameObject.activeInHierarchy) continue;
|
|
269
|
+
var rendererBounds = renderer.bounds;
|
|
270
|
+
if (!found) { bounds = rendererBounds; found = true; }
|
|
271
|
+
else bounds.Encapsulate(rendererBounds);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (frame.NextChildIndex >= frame.ChildCount)
|
|
275
|
+
{
|
|
276
|
+
stack.Pop();
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (!budget.TryCheckpoint() || !budget.TryConsumeGetter()) throw new UnityCliRequestBudgetExceededException(budget.ExhaustedDimension);
|
|
280
|
+
stack.Push(new TransformTraversalFrame(frame.Transform.GetChild(frame.NextChildIndex++)));
|
|
140
281
|
}
|
|
141
|
-
|
|
142
|
-
return sheet;
|
|
282
|
+
return bounds;
|
|
143
283
|
}
|
|
144
284
|
|
|
145
|
-
|
|
146
|
-
private const int InlineImageMaxBytes = 512 * 1024;
|
|
147
|
-
|
|
148
|
-
/// <summary>在图片字节小于上限时附带 inline base64 数据。</summary>
|
|
149
|
-
public static void MaybeAppendInline(ScreenshotCaptureResult result, byte[] bytes, int width, int height, string mimeType, bool inlineBase64)
|
|
285
|
+
private sealed class TransformTraversalFrame
|
|
150
286
|
{
|
|
151
|
-
|
|
287
|
+
internal readonly Transform Transform;
|
|
288
|
+
internal bool Entered;
|
|
289
|
+
internal int ChildCount;
|
|
290
|
+
internal int NextChildIndex;
|
|
291
|
+
|
|
292
|
+
internal TransformTraversalFrame(Transform transform)
|
|
152
293
|
{
|
|
153
|
-
|
|
154
|
-
result.ImageWidth = width;
|
|
155
|
-
result.ImageHeight = height;
|
|
156
|
-
result.ImageMimeType = mimeType;
|
|
294
|
+
Transform = transform;
|
|
157
295
|
}
|
|
158
296
|
}
|
|
297
|
+
|
|
298
|
+
public static void MaybeAppendInline(ScreenshotCaptureResult result, byte[] bytes, int width, int height, string mimeType, bool inlineBase64, ScreenshotCaptureBudget budget)
|
|
299
|
+
{
|
|
300
|
+
if (!inlineBase64 || bytes == null || bytes.Length > InlineImageMaxBytes) return;
|
|
301
|
+
string encoded;
|
|
302
|
+
if (!budget.TryCreateInlineBase64(bytes, out encoded)) return;
|
|
303
|
+
result.ImageBase64 = encoded;
|
|
304
|
+
result.ImageWidth = width;
|
|
305
|
+
result.ImageHeight = height;
|
|
306
|
+
result.ImageMimeType = mimeType;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private static void DeleteArtifactNoThrow(string outputPath)
|
|
310
|
+
{
|
|
311
|
+
try { if (File.Exists(outputPath)) File.Delete(outputPath); } catch { }
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private static void ValidateLimit(long value, long minimum, long maximum, string name)
|
|
315
|
+
{
|
|
316
|
+
if (value < minimum || value > maximum) throw Limit(name + " must be between " + minimum.ToString(CultureInfo.InvariantCulture) + " and " + maximum.ToString(CultureInfo.InvariantCulture) + ".");
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
private static UnityCliBridge.BridgeCommandException Limit(string message)
|
|
320
|
+
{
|
|
321
|
+
return new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_LIMIT_INVALID", message, "Reduce dimensions/capture count or pass a documented positive aggregate ceiling before retrying.");
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
public sealed class ScreenshotCaptureBudget
|
|
326
|
+
{
|
|
327
|
+
private readonly UnityCliRequestBudget requestBudget;
|
|
328
|
+
private long captures;
|
|
329
|
+
private long capturedPixels;
|
|
330
|
+
private long artifactBytes;
|
|
331
|
+
|
|
332
|
+
internal ScreenshotCaptureBudget(ScreenshotCapturePlan plan, UnityCliRequestBudget requestBudget)
|
|
333
|
+
{
|
|
334
|
+
Plan = plan ?? throw new ArgumentNullException("plan");
|
|
335
|
+
this.requestBudget = requestBudget ?? throw new ArgumentNullException("requestBudget");
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
public ScreenshotCapturePlan Plan { get; private set; }
|
|
339
|
+
|
|
340
|
+
public void BeginCapture(int width, int height)
|
|
341
|
+
{
|
|
342
|
+
requestBudget.CheckpointOrThrow();
|
|
343
|
+
ScreenshotToolSupport.ValidateDimensions(width, height, "capture");
|
|
344
|
+
var pixels = checked((long)width * height);
|
|
345
|
+
captures++;
|
|
346
|
+
capturedPixels = checked(capturedPixels + pixels);
|
|
347
|
+
if (captures > Plan.CaptureCount || pixels > Plan.MaxPixelsPerCapture || capturedPixels > Plan.TotalPixels)
|
|
348
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_LIMIT_EXCEEDED", "Capture count or pixels exceeded the frozen aggregate plan.", "Submit a new request with a valid aggregate plan.");
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
public void Checkpoint()
|
|
352
|
+
{
|
|
353
|
+
requestBudget.CheckpointOrThrow();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
public void ChargeArtifact(long bytes)
|
|
357
|
+
{
|
|
358
|
+
requestBudget.CheckpointOrThrow();
|
|
359
|
+
if (bytes <= 0L || bytes > Plan.ArtifactByteCeiling - artifactBytes)
|
|
360
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_LIMIT_EXCEEDED", "Encoded artifact bytes exceed the frozen request ceiling.", "Reduce dimensions or capture count.");
|
|
361
|
+
artifactBytes += bytes;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
public void EnsureArtifactSize(long bytes)
|
|
365
|
+
{
|
|
366
|
+
requestBudget.CheckpointOrThrow();
|
|
367
|
+
if (bytes <= 0L || bytes > Plan.ArtifactByteCeiling)
|
|
368
|
+
throw new UnityCliBridge.BridgeCommandException("E_SCREENSHOT_LIMIT_EXCEEDED", "Persisted artifact size exceeds the frozen request ceiling.", "Reduce dimensions or capture count.");
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
public bool TryCreateInlineBase64(byte[] bytes, out string value)
|
|
372
|
+
{
|
|
373
|
+
value = null;
|
|
374
|
+
if (bytes == null) return false;
|
|
375
|
+
var encodedBytes = checked(((bytes.LongLength + 2L) / 3L) * 4L);
|
|
376
|
+
if (!requestBudget.TryReserveSerializedUtf8Bytes(encodedBytes)) return false;
|
|
377
|
+
value = Convert.ToBase64String(bytes);
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
159
380
|
}
|
|
160
381
|
|
|
161
|
-
/// <summary>screenshot 域截图捕获结果 DTO。</summary>
|
|
162
382
|
public class ScreenshotCaptureResult
|
|
163
383
|
{
|
|
164
384
|
public string ScreenshotPath { get; set; }
|
|
@@ -170,9 +390,9 @@ namespace UnityCli
|
|
|
170
390
|
public string ImageMimeType { get; set; }
|
|
171
391
|
public long SizeBytes { get; set; }
|
|
172
392
|
public string Sha256 { get; set; }
|
|
393
|
+
public ScreenshotCapturePlan CapturePlan { get; set; }
|
|
173
394
|
}
|
|
174
395
|
|
|
175
|
-
/// <summary>screenshot 域 artifact 条目 DTO(orbit/surround 多图输出)。</summary>
|
|
176
396
|
public sealed class ScreenshotArtifactEntry
|
|
177
397
|
{
|
|
178
398
|
public string Source { get; set; }
|
|
@@ -10,7 +10,7 @@ namespace UnityCli
|
|
|
10
10
|
{
|
|
11
11
|
Name = "screenshot.editor-element",
|
|
12
12
|
Summary = "Capture one bounded Unity Editor UI Toolkit element as a verified PNG artifact.",
|
|
13
|
-
Description = "Unity 6000.7+ only. Selects an attached EditorWindow by exact type
|
|
13
|
+
Description = "Unity 6000.7+ only. Selects an attached EditorWindow by exact type/title and resolves up to 16 type/#id/.class segments without materializing descendant lists. Window/element scans share the request scan/node/reflection/time/UTF-8 budget and remain capped at 10000 elements. maxWidth/maxHeight default 2048 and are 1..4096; maxBytes defaults 8 MiB and is 1024..32 MiB. The complete dimension/pixel/temp/artifact plan is frozen before capture. The artifact is written only to the request artifact directory; Editor-only.",
|
|
14
14
|
Group = "screenshot",
|
|
15
15
|
DestructiveHint = false,
|
|
16
16
|
SupportsDryRun = true,
|
|
@@ -31,7 +31,7 @@ namespace UnityCli
|
|
|
31
31
|
public System.Threading.Tasks.ValueTask<EditorElementCaptureResult> ExecuteAsync(EditorElementCaptureRequest request, UnityCliProjectToolContext ctx, System.Threading.CancellationToken ct = default)
|
|
32
32
|
{
|
|
33
33
|
ct.ThrowIfCancellationRequested();
|
|
34
|
-
var plan = EditorElementCaptureToolSupport.Prepare(request);
|
|
34
|
+
var plan = EditorElementCaptureToolSupport.Prepare(request, ctx.UseReadBudget(request.Budget));
|
|
35
35
|
if (ctx.DryRun) return new System.Threading.Tasks.ValueTask<EditorElementCaptureResult>(EditorElementCaptureToolSupport.Preview(plan));
|
|
36
36
|
ctx.CommitEffect();
|
|
37
37
|
return new System.Threading.Tasks.ValueTask<EditorElementCaptureResult>(EditorElementCaptureToolSupport.Capture(plan, ctx));
|
|
@@ -44,9 +44,10 @@ namespace UnityCli
|
|
|
44
44
|
public string Window { get; set; }
|
|
45
45
|
[UnityCliRequired]
|
|
46
46
|
public string Selector { get; set; }
|
|
47
|
-
public long? MaxWidth { get; set; }
|
|
48
|
-
public long? MaxHeight { get; set; }
|
|
49
|
-
public long? MaxBytes { get; set; }
|
|
47
|
+
[UnityCliRange(1L, 4096L)] public long? MaxWidth { get; set; }
|
|
48
|
+
[UnityCliRange(1L, 4096L)] public long? MaxHeight { get; set; }
|
|
49
|
+
[UnityCliRange(1024L, 33554432L)] public long? MaxBytes { get; set; }
|
|
50
|
+
public UnityCliReadBudgetInput Budget { get; set; }
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
public sealed class EditorElementWindowIdentity
|
|
@@ -71,6 +72,7 @@ namespace UnityCli
|
|
|
71
72
|
public long Width { get; set; }
|
|
72
73
|
public long Height { get; set; }
|
|
73
74
|
public long MaxBytes { get; set; }
|
|
75
|
+
public ScreenshotCapturePlan CapturePlan { get; set; }
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
public sealed class EditorElementCaptureResult
|