@auraindustry/aurajs 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -7
- package/benchmarks/perf-thresholds.json +54 -0
- package/package.json +4 -7
- package/src/asset-pack.mjs +5 -1
- package/src/authored-project.mjs +1449 -0
- package/src/authored-runtime.mjs +2016 -0
- package/src/authoring/avatar-animation-graph.mjs +648 -0
- package/src/bin-integrity.mjs +272 -0
- package/src/build-contract/assets.mjs +130 -0
- package/src/build-contract/capabilities.mjs +116 -0
- package/src/build-contract/constants.mjs +6 -0
- package/src/build-contract/helpers.mjs +44 -0
- package/src/build-contract/web-templates.mjs +5993 -0
- package/src/build-contract.mjs +27 -2910
- package/src/bundler.mjs +188 -55
- package/src/cli.mjs +4825 -1512
- package/src/commands/project-authoring.mjs +434 -0
- package/src/config.mjs +27 -0
- package/src/conformance/cases/app-and-ui-runtime-cases.mjs +3309 -0
- package/src/conformance/cases/core-runtime-cases.mjs +1431 -0
- package/src/conformance/cases/index.mjs +11 -0
- package/src/conformance/cases/scene3d-and-media-cases.mjs +2094 -0
- package/src/conformance/cases/systems-and-gameplay-cases.mjs +1776 -0
- package/src/conformance/shared.mjs +27 -0
- package/src/conformance-runner.mjs +25 -13
- package/src/conformance.mjs +619 -4020
- package/src/cutscene.mjs +362 -5
- package/src/dev-cli-action.mjs +249 -0
- package/src/dev-cli-inspect.mjs +92 -0
- package/src/dev-cli-state.mjs +80 -0
- package/src/external-asset-cache.mjs +587 -0
- package/src/external-asset-policy.mjs +217 -0
- package/src/external-package-surface.mjs +206 -0
- package/src/game-action-runtime.mjs +869 -0
- package/src/game-state-runtime.mjs +206 -6
- package/src/headless-action.mjs +186 -0
- package/src/headless-test/runtime-animation.mjs +1173 -0
- package/src/headless-test/runtime-coordinator.mjs +1514 -0
- package/src/headless-test/runtime-primitives.mjs +320 -0
- package/src/headless-test/runtime-world.mjs +2253 -0
- package/src/headless-test.mjs +392 -4298
- package/src/host-binary.mjs +342 -14
- package/src/icon-discovery.mjs +64 -0
- package/src/make-catalog.mjs +109 -0
- package/src/make.mjs +197 -0
- package/src/package-integrity.mjs +586 -0
- package/src/perf-benchmark.mjs +353 -0
- package/src/postinstall.mjs +5 -5
- package/src/prefabs/index.mjs +34 -0
- package/src/prefabs/scene-serialization.mjs +184 -0
- package/src/project-importer.mjs +620 -0
- package/src/project-registry.mjs +24 -0
- package/src/publish-command.mjs +195 -0
- package/src/publish-env-example.mjs +83 -0
- package/src/publish-validation.mjs +708 -0
- package/src/retro/assets/compile.mjs +232 -0
- package/src/retro/backend-gba/authoring.mjs +1029 -0
- package/src/retro/backend-gba/rom.mjs +363 -0
- package/src/retro/backend-gbc/rom.mjs +85 -0
- package/src/retro/build.mjs +278 -0
- package/src/retro/cli/commands.mjs +292 -0
- package/src/retro/cli/templates.mjs +84 -0
- package/src/retro/diagnostics/catalog.mjs +110 -0
- package/src/retro/diagnostics/emit.mjs +72 -0
- package/src/retro/emulator/case-overlay.mjs +64 -0
- package/src/retro/emulator/discovery.mjs +158 -0
- package/src/retro/emulator/macos-case-overlay.swift +220 -0
- package/src/retro/emulator/profiles.mjs +146 -0
- package/src/retro/emulator/runner.mjs +289 -0
- package/src/retro/frontend/load-project.mjs +98 -0
- package/src/retro/index.mjs +30 -0
- package/src/retro/ir/build-ir.mjs +108 -0
- package/src/retro/runtime-gba/contract.mjs +151 -0
- package/src/retro/runtime-gbc/contract.mjs +117 -0
- package/src/retro/shared/span.mjs +26 -0
- package/src/retro/shared/targets.mjs +64 -0
- package/src/retro/validator/check-project.mjs +114 -0
- package/src/runtime-hotspot-audit.mjs +707 -0
- package/src/scaffold/config.mjs +1000 -0
- package/src/scaffold/fs.mjs +56 -0
- package/src/scaffold/layout.mjs +318 -0
- package/src/scaffold/project-docs.mjs +438 -0
- package/src/scaffold.mjs +93 -596
- package/src/scene-composition/index.mjs +326 -0
- package/src/scene-composition/runtime.mjs +751 -0
- package/src/self-hosted-assets.mjs +604 -0
- package/src/session-client.mjs +750 -0
- package/src/session-native-launcher.mjs +74 -0
- package/src/session-protocol.mjs +75 -0
- package/src/session-runtime.mjs +321 -0
- package/src/session-server.mjs +360 -0
- package/src/shader-kits/index.mjs +773 -0
- package/src/starter-content-registry.mjs +292 -0
- package/src/state-artifacts.mjs +662 -24
- package/src/state-dev-reload.mjs +99 -2
- package/src/terminal-ui.mjs +245 -0
- package/src/web-conformance.mjs +219 -0
- package/templates/create/2d/config/gameplay/shooter.config.js +26 -0
- package/templates/create/2d/content/gameplay/waves.json +26 -0
- package/templates/create/2d/content/registries/.gitkeep +1 -0
- package/templates/create/2d/docs/design/.gitkeep +1 -0
- package/templates/create/2d/docs/design/loop.md +5 -0
- package/templates/create/2d/prefabs/enemies.prefab.js +90 -0
- package/templates/create/2d/prefabs/enemy-basic.prefab.js +18 -0
- package/templates/create/2d/prefabs/player.prefab.js +36 -0
- package/templates/create/2d/prefabs/projectiles.prefab.js +35 -0
- package/templates/create/2d/scenes/boot.scene.js +12 -0
- package/templates/create/2d/scenes/gameplay.scene.js +230 -0
- package/templates/create/2d/scenes/menu.scene.js +9 -0
- package/templates/create/2d/src/main.js +6 -185
- package/templates/create/2d/src/runtime/app.js +49 -0
- package/templates/create/2d/src/runtime/capabilities.js +35 -0
- package/templates/create/2d/ui/hud.screen.js +40 -0
- package/templates/create/2d/ui/pause.screen.js +149 -0
- package/templates/create/2d/ui/settings.screen.js +347 -0
- package/templates/create/2d/ui/title.screen.js +13 -0
- package/templates/create/2d-adventure/aura.config.json +28 -0
- package/templates/create/2d-adventure/config/gameplay/adventure.config.js +14 -0
- package/templates/create/2d-adventure/content/gameplay/world.js +46 -0
- package/templates/create/2d-adventure/content/registries/.gitkeep +1 -0
- package/templates/create/2d-adventure/docs/design/loop.md +5 -0
- package/templates/create/2d-adventure/prefabs/player.prefab.js +54 -0
- package/templates/create/2d-adventure/prefabs/relic.prefab.js +38 -0
- package/templates/create/2d-adventure/prefabs/world.prefab.js +125 -0
- package/templates/create/2d-adventure/scenes/gameplay.scene.js +256 -0
- package/templates/create/2d-adventure/src/runtime/capabilities.js +34 -0
- package/templates/create/2d-adventure/ui/hud.screen.js +60 -0
- package/templates/create/2d-survivor/config/gameplay/survivor.config.js +33 -0
- package/templates/create/2d-survivor/content/gameplay/spawn-zones.json +29 -0
- package/templates/create/2d-survivor/content/registries/.gitkeep +1 -0
- package/templates/create/2d-survivor/docs/design/.gitkeep +1 -0
- package/templates/create/2d-survivor/docs/design/loop.md +5 -0
- package/templates/create/2d-survivor/prefabs/enemies.prefab.js +178 -0
- package/templates/create/2d-survivor/prefabs/enemy-swarm.prefab.js +18 -0
- package/templates/create/2d-survivor/prefabs/player.prefab.js +42 -0
- package/templates/create/2d-survivor/prefabs/projectiles.prefab.js +56 -0
- package/templates/create/2d-survivor/scenes/boot.scene.js +12 -0
- package/templates/create/2d-survivor/scenes/gameplay.scene.js +314 -0
- package/templates/create/2d-survivor/scenes/menu.scene.js +9 -0
- package/templates/create/2d-survivor/src/main.js +5 -332
- package/templates/create/2d-survivor/src/runtime/app.js +49 -0
- package/templates/create/2d-survivor/src/runtime/capabilities.js +35 -0
- package/templates/create/2d-survivor/ui/hud.screen.js +45 -0
- package/templates/create/2d-survivor/ui/title.screen.js +13 -0
- package/templates/create/3d/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d/config/gameplay/.gitkeep +1 -0
- package/templates/create/3d/content/gameplay/checkpoints.json +33 -0
- package/templates/create/3d/content/gameplay/course.js +40 -0
- package/templates/create/3d/content/registries/.gitkeep +1 -0
- package/templates/create/3d/docs/design/.gitkeep +1 -0
- package/templates/create/3d/docs/design/loop.md +5 -0
- package/templates/create/3d/prefabs/checkpoint.prefab.js +15 -0
- package/templates/create/3d/prefabs/player.prefab.js +204 -0
- package/templates/create/3d/prefabs/world.prefab.js +112 -0
- package/templates/create/3d/scenes/boot.scene.js +12 -0
- package/templates/create/3d/scenes/checkpoint.scene.js +9 -0
- package/templates/create/3d/scenes/gameplay.scene.js +292 -0
- package/templates/create/3d/src/main.js +6 -295
- package/templates/create/3d/src/runtime/app.js +49 -0
- package/templates/create/3d/src/runtime/capabilities.js +53 -0
- package/templates/create/3d/src/runtime/materials.js +34 -0
- package/templates/create/3d/src/runtime/state.js +39 -0
- package/templates/create/3d/ui/hud.screen.js +75 -0
- package/templates/create/3d/ui/pause.screen.js +166 -0
- package/templates/create/3d/ui/settings.screen.js +387 -0
- package/templates/create/3d-adventure/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d-adventure/aura.config.json +28 -0
- package/templates/create/3d-adventure/config/gameplay/adventure.config.js +9 -0
- package/templates/create/3d-adventure/content/gameplay/course.js +62 -0
- package/templates/create/3d-adventure/content/registries/.gitkeep +1 -0
- package/templates/create/3d-adventure/docs/design/loop.md +5 -0
- package/templates/create/3d-adventure/prefabs/player.prefab.js +168 -0
- package/templates/create/3d-adventure/prefabs/relic.prefab.js +35 -0
- package/templates/create/3d-adventure/prefabs/world.prefab.js +119 -0
- package/templates/create/3d-adventure/scenes/gameplay.scene.js +358 -0
- package/templates/create/3d-adventure/src/runtime/capabilities.js +56 -0
- package/templates/create/3d-adventure/src/runtime/materials.js +39 -0
- package/templates/create/3d-adventure/src/runtime/state.js +31 -0
- package/templates/create/3d-adventure/ui/hud.screen.js +70 -0
- package/templates/create/3d-adventure/ui/pause.screen.js +437 -0
- package/templates/create/3d-collectathon/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d-collectathon/config/gameplay/.gitkeep +1 -0
- package/templates/create/3d-collectathon/content/gameplay/collectibles.json +26 -0
- package/templates/create/3d-collectathon/content/gameplay/course.js +46 -0
- package/templates/create/3d-collectathon/content/registries/.gitkeep +1 -0
- package/templates/create/3d-collectathon/docs/design/.gitkeep +1 -0
- package/templates/create/3d-collectathon/docs/design/loop.md +5 -0
- package/templates/create/3d-collectathon/prefabs/collectible.prefab.js +15 -0
- package/templates/create/3d-collectathon/prefabs/player.prefab.js +207 -0
- package/templates/create/3d-collectathon/prefabs/world.prefab.js +112 -0
- package/templates/create/3d-collectathon/scenes/boot.scene.js +12 -0
- package/templates/create/3d-collectathon/scenes/checkpoint.scene.js +9 -0
- package/templates/create/3d-collectathon/scenes/gameplay.scene.js +200 -0
- package/templates/create/3d-collectathon/src/main.js +5 -355
- package/templates/create/3d-collectathon/src/runtime/app.js +49 -0
- package/templates/create/3d-collectathon/src/runtime/capabilities.js +53 -0
- package/templates/create/3d-collectathon/src/runtime/materials.js +34 -0
- package/templates/create/3d-collectathon/src/runtime/state.js +27 -0
- package/templates/create/3d-collectathon/ui/hud.screen.js +66 -0
- package/templates/create/3d-collectathon/ui/pause.screen.js +13 -0
- package/templates/create/blank/config/gameplay/.gitkeep +1 -0
- package/templates/create/blank/content/gameplay/.gitkeep +1 -0
- package/templates/create/blank/content/registries/.gitkeep +1 -0
- package/templates/create/blank/docs/design/.gitkeep +1 -0
- package/templates/create/blank/docs/design/loop.md +5 -0
- package/templates/create/blank/prefabs/.gitkeep +1 -0
- package/templates/create/blank/scenes/.gitkeep +1 -0
- package/templates/create/blank/src/runtime/.gitkeep +1 -0
- package/templates/create/blank/ui/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/audio/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/fonts/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/sprites/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/starter/README.md +11 -0
- package/templates/create/deckbuilder-2d/assets/ui/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/aura.config.json +28 -0
- package/templates/create/deckbuilder-2d/config/gameplay/deckbuilder.config.js +26 -0
- package/templates/create/deckbuilder-2d/content/cards/guard.card.js +19 -0
- package/templates/create/deckbuilder-2d/content/cards/spark.card.js +20 -0
- package/templates/create/deckbuilder-2d/content/cards/starter.deck.js +69 -0
- package/templates/create/deckbuilder-2d/content/cards/strike.card.js +19 -0
- package/templates/create/deckbuilder-2d/content/cards/survey.card.js +20 -0
- package/templates/create/deckbuilder-2d/content/encounters/training-battle.encounter.js +14 -0
- package/templates/create/deckbuilder-2d/content/encounters/training-battle.js +65 -0
- package/templates/create/deckbuilder-2d/content/enemies/training-automaton.enemy.js +48 -0
- package/templates/create/deckbuilder-2d/content/gameplay/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/content/registries/cards.registry.js +26 -0
- package/templates/create/deckbuilder-2d/content/registries/encounters.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/registries/enemies.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/registries/relics.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/relics/ember-charm.relic.js +18 -0
- package/templates/create/deckbuilder-2d/docs/design/loop.md +12 -0
- package/templates/create/deckbuilder-2d/prefabs/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/scenes/boot.scene.js +84 -0
- package/templates/create/deckbuilder-2d/scenes/gameplay.scene.js +641 -0
- package/templates/create/deckbuilder-2d/src/components/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/src/main.js +17 -0
- package/templates/create/deckbuilder-2d/src/runtime/capabilities.js +22 -0
- package/templates/create/deckbuilder-2d/src/shared/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/src/systems/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/tests/smoke/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/ui/hud.screen.js +80 -0
- package/templates/create/deckbuilder-2d/ui/pause.screen.js +146 -0
- package/templates/create/deckbuilder-2d/ui/settings.screen.js +342 -0
- package/templates/create/local-multiplayer/aura.config.json +40 -0
- package/templates/create/local-multiplayer/config/gameplay/local-multiplayer.config.js +26 -0
- package/templates/create/local-multiplayer/content/gameplay/room-layout.js +13 -0
- package/templates/create/local-multiplayer/content/registries/.gitkeep +1 -0
- package/templates/create/local-multiplayer/docs/design/loop.md +14 -0
- package/templates/create/local-multiplayer/prefabs/player.prefab.js +99 -0
- package/templates/create/local-multiplayer/scenes/boot.scene.js +12 -0
- package/templates/create/local-multiplayer/scenes/gameplay.scene.js +443 -0
- package/templates/create/local-multiplayer/src/main.js +17 -0
- package/templates/create/local-multiplayer/src/runtime/capabilities.js +28 -0
- package/templates/create/local-multiplayer/ui/hud.screen.js +60 -0
- package/templates/create/shared/src/runtime/project-inspector.js +105 -0
- package/templates/create/shared/src/runtime/scene-flow.js +290 -0
- package/templates/create/shared/src/runtime/screen-shell.js +222 -0
- package/templates/create/shared/src/runtime/ui-forms.js +209 -0
- package/templates/create/shared/src/runtime/ui-settings.js +237 -0
- package/templates/create/shared/src/runtime/ui-theme.js +352 -0
- package/templates/create/shared/src/starter-utils/adventure-objectives.js +102 -0
- package/templates/create/shared/src/starter-utils/animation-2d.js +337 -0
- package/templates/create/shared/src/starter-utils/avatar-3d.js +404 -0
- package/templates/create/shared/src/starter-utils/combat-feedback-2d.js +320 -0
- package/templates/create/shared/src/starter-utils/core.js +39 -3
- package/templates/create/shared/src/starter-utils/index.js +8 -2
- package/templates/create/shared/src/starter-utils/platformer-3d.js +34 -3
- package/templates/create/shared/src/starter-utils/triggers.js +662 -0
- package/templates/create/shared/src/starter-utils/tween-2d.js +615 -0
- package/templates/create/video-cutscene/assets/video/.gitkeep +0 -0
- package/templates/create/video-cutscene/aura.config.json +28 -0
- package/templates/create/video-cutscene/config/gameplay/.gitkeep +0 -0
- package/templates/create/video-cutscene/content/gameplay/.gitkeep +0 -0
- package/templates/create/video-cutscene/content/registries/.gitkeep +0 -0
- package/templates/create/video-cutscene/docs/design/loop.md +22 -0
- package/templates/create/video-cutscene/prefabs/.gitkeep +0 -0
- package/templates/create/video-cutscene/scenes/boot.scene.js +11 -0
- package/templates/create/video-cutscene/scenes/cutscene.scene.js +113 -0
- package/templates/create/video-cutscene/scenes/gameplay.scene.js +50 -0
- package/templates/create/video-cutscene/src/main.js +17 -0
- package/templates/create/video-cutscene/src/runtime/app.js +52 -0
- package/templates/create/video-cutscene/src/runtime/capabilities.js +35 -0
- package/templates/create/video-cutscene/src/runtime/state.js +13 -0
- package/templates/create/video-cutscene/ui/.gitkeep +0 -0
- package/templates/create-bin/play.js +1187 -0
- package/templates/make/README.md +46 -0
- package/templates/make/catalog.json +51 -0
- package/templates/make/component/files/{{MAKE_NAME}}.component.js +20 -0
- package/templates/make/component/manifest.json +9 -0
- package/templates/make/data/files/{{MAKE_NAME}}.json +14 -0
- package/templates/make/data/manifest.json +9 -0
- package/templates/make/material/files/{{MAKE_NAME}}.material.json +17 -0
- package/templates/make/material/manifest.json +9 -0
- package/templates/make/prefab/files/{{MAKE_NAME}}.prefab.js +20 -0
- package/templates/make/prefab/manifest.json +9 -0
- package/templates/make/scene/files/{{MAKE_NAME}}.scene.js +31 -0
- package/templates/make/scene/manifest.json +9 -0
- package/templates/make/shader/files/{{MAKE_NAME}}.shader.js +23 -0
- package/templates/make/shader/manifest.json +9 -0
- package/templates/make/system/files/{{MAKE_NAME}}.system.js +15 -0
- package/templates/make/system/manifest.json +9 -0
- package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.js +16 -0
- package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.json +23 -0
- package/templates/make/ui-screen/manifest.json +10 -0
- package/templates/make-starters/deckbuilder-2d/card/files/{{MAKE_NAME}}.card.js +22 -0
- package/templates/make-starters/deckbuilder-2d/card/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/catalog.json +34 -0
- package/templates/make-starters/deckbuilder-2d/encounter/files/{{MAKE_NAME}}.encounter.js +18 -0
- package/templates/make-starters/deckbuilder-2d/encounter/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/enemy/files/{{MAKE_NAME}}.enemy.js +28 -0
- package/templates/make-starters/deckbuilder-2d/enemy/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/relic/files/{{MAKE_NAME}}.relic.js +23 -0
- package/templates/make-starters/deckbuilder-2d/relic/manifest.json +9 -0
- package/templates/retro/platformer/README.md +10 -0
- package/templates/retro/platformer/assets/retro/assets.json +91 -0
- package/templates/retro/platformer/aura.config.json +7 -0
- package/templates/retro/platformer/package.json +5 -0
- package/templates/retro/platformer/src/main.js +40 -0
- package/templates/retro/puzzle-grid/README.md +10 -0
- package/templates/retro/puzzle-grid/assets/retro/assets.json +90 -0
- package/templates/retro/puzzle-grid/aura.config.json +7 -0
- package/templates/retro/puzzle-grid/package.json +5 -0
- package/templates/retro/puzzle-grid/src/main.js +29 -0
- package/templates/retro/tactics-grid/README.md +10 -0
- package/templates/retro/tactics-grid/assets/retro/assets.json +90 -0
- package/templates/retro/tactics-grid/aura.config.json +7 -0
- package/templates/retro/tactics-grid/package.json +5 -0
- package/templates/retro/tactics-grid/src/main.js +35 -0
- package/templates/retro/topdown-adventure/README.md +10 -0
- package/templates/retro/topdown-adventure/assets/retro/assets.json +95 -0
- package/templates/retro/topdown-adventure/aura.config.json +7 -0
- package/templates/retro/topdown-adventure/package.json +5 -0
- package/templates/retro/topdown-adventure/src/main.js +29 -0
- package/templates/skills/aurajs/SKILL.md +61 -5
|
@@ -0,0 +1,1431 @@
|
|
|
1
|
+
export const CORE_RUNTIME_CONFORMANCE_CASES = [
|
|
2
|
+
{
|
|
3
|
+
id: 'lifecycle-window',
|
|
4
|
+
namespaces: ['lifecycle', 'window'],
|
|
5
|
+
functions: [
|
|
6
|
+
'aura.setup',
|
|
7
|
+
'aura.update',
|
|
8
|
+
'aura.draw',
|
|
9
|
+
'aura.onResize',
|
|
10
|
+
'aura.onFocus',
|
|
11
|
+
'aura.onBlur',
|
|
12
|
+
'aura.window.setTitle',
|
|
13
|
+
'aura.window.setSize',
|
|
14
|
+
'aura.window.setFullscreen',
|
|
15
|
+
'aura.window.setCursorVisible',
|
|
16
|
+
'aura.window.setCursorLocked',
|
|
17
|
+
'aura.window.getSize',
|
|
18
|
+
'aura.window.getPixelRatio',
|
|
19
|
+
'aura.window.getFPS',
|
|
20
|
+
],
|
|
21
|
+
nativeChecks: [
|
|
22
|
+
{ id: 'window.setTitle', expression: "typeof aura.window?.setTitle === 'function'" },
|
|
23
|
+
{ id: 'window.setSize', expression: "typeof aura.window?.setSize === 'function'" },
|
|
24
|
+
{ id: 'window.setFullscreen', expression: "typeof aura.window?.setFullscreen === 'function'" },
|
|
25
|
+
{ id: 'window.setCursorVisible', expression: "typeof aura.window?.setCursorVisible === 'function'" },
|
|
26
|
+
{ id: 'window.setCursorLocked', expression: "typeof aura.window?.setCursorLocked === 'function'" },
|
|
27
|
+
{ id: 'window.getSize', expression: "typeof aura.window?.getSize === 'function'" },
|
|
28
|
+
{ id: 'window.getPixelRatio', expression: "typeof aura.window?.getPixelRatio === 'function'" },
|
|
29
|
+
{ id: 'window.getFPS', expression: "typeof aura.window?.getFPS === 'function'" },
|
|
30
|
+
{
|
|
31
|
+
id: 'lifecycle.onResize.numericArgs',
|
|
32
|
+
expression: "(() => { let calls = 0; let seen = null; aura.onResize = function (w, h) { calls += 1; seen = [typeof w, typeof h, w, h]; }; aura.onResize(1280, 720); return calls === 1 && Array.isArray(seen) && seen[0] === 'number' && seen[1] === 'number' && seen[2] === 1280 && seen[3] === 720; })()",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'lifecycle.onFocus.callable',
|
|
36
|
+
expression: "(() => { let calls = 0; aura.onFocus = function () { calls += 1; }; aura.onFocus(); return calls === 1; })()",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'lifecycle.onBlur.callable',
|
|
40
|
+
expression: "(() => { let calls = 0; aura.onBlur = function () { calls += 1; }; aura.onBlur(); return calls === 1; })()",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
nativePostChecks: [
|
|
44
|
+
{ id: 'lifecycle.setup.calledOnce', expression: '__setupCalls === 1' },
|
|
45
|
+
{ id: 'lifecycle.update.calledPerFrame', expression: '__updateCalls === 3' },
|
|
46
|
+
{ id: 'lifecycle.draw.calledPerFrame', expression: '__drawCalls === 3' },
|
|
47
|
+
{
|
|
48
|
+
id: 'lifecycle.update.dtPositiveNumber',
|
|
49
|
+
expression: "typeof __lastDt === 'number' && Number.isFinite(__lastDt) && __lastDt > 0",
|
|
50
|
+
},
|
|
51
|
+
{ id: 'lifecycle.update.afterSetup', expression: '__updateBeforeSetup === false' },
|
|
52
|
+
{ id: 'lifecycle.draw.afterSetup', expression: '__drawBeforeSetup === false' },
|
|
53
|
+
],
|
|
54
|
+
frames: 3,
|
|
55
|
+
nativeFrames: 3,
|
|
56
|
+
source: `
|
|
57
|
+
let setupCount = 0;
|
|
58
|
+
let updateCount = 0;
|
|
59
|
+
let drawCount = 0;
|
|
60
|
+
let resizeCount = 0;
|
|
61
|
+
let focusCount = 0;
|
|
62
|
+
let blurCount = 0;
|
|
63
|
+
let resizeArgs = null;
|
|
64
|
+
|
|
65
|
+
aura.setup = function () {
|
|
66
|
+
setupCount += 1;
|
|
67
|
+
aura.window.setTitle('Conformance');
|
|
68
|
+
aura.window.setSize(640, 360);
|
|
69
|
+
aura.window.setFullscreen(false);
|
|
70
|
+
aura.window.setCursorVisible(true);
|
|
71
|
+
aura.window.setCursorLocked(false);
|
|
72
|
+
|
|
73
|
+
const windowSize = aura.window.getSize();
|
|
74
|
+
aura.test.assert(typeof aura.window.width === 'number', 'window.width should be numeric');
|
|
75
|
+
aura.test.assert(typeof aura.window.height === 'number', 'window.height should be numeric');
|
|
76
|
+
aura.test.equal(windowSize.width, aura.window.width, 'window.getSize width should match snapshot');
|
|
77
|
+
aura.test.equal(windowSize.height, aura.window.height, 'window.getSize height should match snapshot');
|
|
78
|
+
aura.test.assert(typeof aura.window.pixelRatio === 'number', 'window.pixelRatio should be numeric');
|
|
79
|
+
aura.test.assert(typeof aura.window.fps === 'number', 'window.fps should be numeric');
|
|
80
|
+
aura.test.assert(typeof aura.window.close === 'function', 'window.close should exist');
|
|
81
|
+
aura.test.assert(typeof aura.window.setCursorVisible === 'function', 'window.setCursorVisible should exist');
|
|
82
|
+
aura.test.assert(typeof aura.window.setCursorLocked === 'function', 'window.setCursorLocked should exist');
|
|
83
|
+
|
|
84
|
+
aura.onResize = function (width, height) {
|
|
85
|
+
resizeCount += 1;
|
|
86
|
+
resizeArgs = [width, height];
|
|
87
|
+
};
|
|
88
|
+
aura.onFocus = function () {
|
|
89
|
+
focusCount += 1;
|
|
90
|
+
};
|
|
91
|
+
aura.onBlur = function () {
|
|
92
|
+
blurCount += 1;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
aura.onResize(640, 360);
|
|
96
|
+
aura.onFocus();
|
|
97
|
+
aura.onBlur();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
aura.update = function (dt) {
|
|
101
|
+
updateCount += 1;
|
|
102
|
+
aura.test.assert(dt > 0, 'dt should be positive');
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
aura.draw = function () {
|
|
106
|
+
drawCount += 1;
|
|
107
|
+
aura.draw2d.clear(10, 20, 30);
|
|
108
|
+
|
|
109
|
+
if (drawCount === 3) {
|
|
110
|
+
aura.test.equal(setupCount, 1, 'setup called once');
|
|
111
|
+
aura.test.equal(updateCount, 3, 'update called once per frame');
|
|
112
|
+
aura.test.equal(resizeCount, 1, 'onResize should be callable');
|
|
113
|
+
aura.test.equal(focusCount, 1, 'onFocus should be callable');
|
|
114
|
+
aura.test.equal(blurCount, 1, 'onBlur should be callable');
|
|
115
|
+
aura.test.equal(resizeArgs[0], 640, 'onResize width arg');
|
|
116
|
+
aura.test.equal(resizeArgs[1], 360, 'onResize height arg');
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
`,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'input-surface',
|
|
123
|
+
namespaces: ['input'],
|
|
124
|
+
functions: [
|
|
125
|
+
'aura.input.isKeyDown',
|
|
126
|
+
'aura.input.isKeyPressed',
|
|
127
|
+
'aura.input.isKeyReleased',
|
|
128
|
+
'aura.input.getMousePosition',
|
|
129
|
+
'aura.input.getMouseDelta',
|
|
130
|
+
'aura.input.isMouseDown',
|
|
131
|
+
'aura.input.isMousePressed',
|
|
132
|
+
'aura.input.getMouseWheel',
|
|
133
|
+
'aura.input.isGamepadConnected',
|
|
134
|
+
'aura.input.getGamepadAxis',
|
|
135
|
+
'aura.input.isGamepadButtonDown',
|
|
136
|
+
],
|
|
137
|
+
nativeChecks: [
|
|
138
|
+
{ id: 'input.isKeyDown', expression: "typeof aura.input?.isKeyDown === 'function'" },
|
|
139
|
+
{ id: 'input.isKeyPressed', expression: "typeof aura.input?.isKeyPressed === 'function'" },
|
|
140
|
+
{ id: 'input.isKeyReleased', expression: "typeof aura.input?.isKeyReleased === 'function'" },
|
|
141
|
+
{ id: 'input.getMousePosition', expression: "typeof aura.input?.getMousePosition === 'function'" },
|
|
142
|
+
{ id: 'input.getMouseDelta', expression: "typeof aura.input?.getMouseDelta === 'function'" },
|
|
143
|
+
{ id: 'input.isMouseDown', expression: "typeof aura.input?.isMouseDown === 'function'" },
|
|
144
|
+
{ id: 'input.isMousePressed', expression: "typeof aura.input?.isMousePressed === 'function'" },
|
|
145
|
+
{ id: 'input.getMouseWheel', expression: "typeof aura.input?.getMouseWheel === 'function'" },
|
|
146
|
+
{ id: 'input.isGamepadConnected', expression: "typeof aura.input?.isGamepadConnected === 'function'" },
|
|
147
|
+
{ id: 'input.getGamepadAxis', expression: "typeof aura.input?.getGamepadAxis === 'function'" },
|
|
148
|
+
{ id: 'input.isGamepadButtonDown', expression: "typeof aura.input?.isGamepadButtonDown === 'function'" },
|
|
149
|
+
{
|
|
150
|
+
id: 'input.key.invalid-input.safe-false',
|
|
151
|
+
expression: "(() => { const invalid = [42, {}, null, undefined, ['space']]; return invalid.every((key) => aura.input.isKeyDown(key) === false && aura.input.isKeyPressed(key) === false && aura.input.isKeyReleased(key) === false); })()",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
frames: 1,
|
|
155
|
+
source: `
|
|
156
|
+
aura.setup = function () {
|
|
157
|
+
aura.test.equal(aura.input.isDown('space'), false, 'keyboard isDown default false');
|
|
158
|
+
aura.test.equal(aura.input.isPressed('space'), false, 'keyboard isPressed default false');
|
|
159
|
+
aura.test.equal(aura.input.isReleased('space'), false, 'keyboard isReleased default false');
|
|
160
|
+
|
|
161
|
+
const delta = aura.input.getMouseDelta();
|
|
162
|
+
aura.test.assert(typeof aura.input.mouse.x === 'number', 'mouse.x should be numeric');
|
|
163
|
+
aura.test.assert(typeof aura.input.mouse.y === 'number', 'mouse.y should be numeric');
|
|
164
|
+
aura.test.assert(typeof aura.input.mouse.scroll === 'number', 'mouse.scroll should be numeric');
|
|
165
|
+
aura.test.assert(typeof delta.x === 'number', 'mouse delta x should be numeric');
|
|
166
|
+
aura.test.assert(typeof delta.y === 'number', 'mouse delta y should be numeric');
|
|
167
|
+
aura.test.equal(aura.input.mouse.isDown('left'), false, 'mouse isDown default false');
|
|
168
|
+
aura.test.equal(aura.input.mouse.isPressed('left'), false, 'mouse isPressed default false');
|
|
169
|
+
aura.test.equal(aura.input.mouse.isReleased('left'), false, 'mouse isReleased default false');
|
|
170
|
+
|
|
171
|
+
aura.test.equal(aura.input.gamepad.connected, false, 'gamepad default disconnected');
|
|
172
|
+
aura.test.assert(typeof aura.input.gamepad.axis('leftX') === 'number', 'gamepad axis should return number');
|
|
173
|
+
aura.test.equal(aura.input.gamepad.isDown('a'), false, 'gamepad isDown default false');
|
|
174
|
+
aura.test.equal(aura.input.gamepad.isPressed('a'), false, 'gamepad isPressed default false');
|
|
175
|
+
aura.test.equal(aura.input.gamepad.isReleased('a'), false, 'gamepad isReleased default false');
|
|
176
|
+
aura.input.gamepad.rumble(0.2, 20);
|
|
177
|
+
};
|
|
178
|
+
`,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
id: 'rust-host-native-readiness-smoke',
|
|
182
|
+
modes: ['native'],
|
|
183
|
+
namespaces: ['lifecycle', 'input', 'draw2d', 'assets', 'audio', 'net', 'debug'],
|
|
184
|
+
functions: [
|
|
185
|
+
'aura.setup',
|
|
186
|
+
'aura.update',
|
|
187
|
+
'aura.draw',
|
|
188
|
+
'aura.onResize',
|
|
189
|
+
'aura.input.isKeyDown',
|
|
190
|
+
'aura.input.isKeyPressed',
|
|
191
|
+
'aura.input.isKeyReleased',
|
|
192
|
+
'aura.draw2d.clear',
|
|
193
|
+
'aura.draw2d.rect',
|
|
194
|
+
'aura.debug.inspectorStats',
|
|
195
|
+
'aura.assets.load',
|
|
196
|
+
'aura.assets.getFormatSupport',
|
|
197
|
+
'aura.audio.setBusVolume',
|
|
198
|
+
'aura.audio.fadeTrack',
|
|
199
|
+
'aura.net.connect',
|
|
200
|
+
'aura.net.websocket',
|
|
201
|
+
'aura.net.fetch',
|
|
202
|
+
'aura.net.get',
|
|
203
|
+
'aura.net.post',
|
|
204
|
+
],
|
|
205
|
+
nativeChecks: [
|
|
206
|
+
{
|
|
207
|
+
id: 'smoke.lifecycle-input.readiness.deterministic',
|
|
208
|
+
expression: "(() => { const runSample = () => { let resizeSeen = null; aura.onResize = (w, h) => { resizeSeen = [typeof w, typeof h, w, h]; }; aura.onResize(640, 360); const setupOk = typeof aura.setup === 'function'; const updateOk = typeof aura.update === 'function'; const drawOk = typeof aura.draw === 'function'; const hasInputFns = typeof aura.input?.isKeyDown === 'function' && typeof aura.input?.isKeyPressed === 'function' && typeof aura.input?.isKeyReleased === 'function'; const keySnapshot = {}; if (hasInputFns) { for (const key of ['left', 'right', 'up', 'down', 'arrowup', 'arrowdown', 'space']) { keySnapshot[key] = { down: aura.input.isKeyDown(key), pressed: aura.input.isKeyPressed(key), released: aura.input.isKeyReleased(key) }; } } const keyBooleans = Object.values(keySnapshot).every((row) => typeof row.down === 'boolean' && typeof row.pressed === 'boolean' && typeof row.released === 'boolean'); const aliasStable = hasInputFns && aura.input.isKeyDown('up') === aura.input.isKeyDown('arrowup') && aura.input.isKeyPressed('up') === aura.input.isKeyPressed('arrowup') && aura.input.isKeyReleased('up') === aura.input.isKeyReleased('arrowup'); const invalidSafe = hasInputFns && [42, {}, null, undefined, ['space']].every((key) => aura.input.isKeyDown(key) === false && aura.input.isKeyPressed(key) === false && aura.input.isKeyReleased(key) === false); return { setupOk, updateOk, drawOk, resizeSeen, hasInputFns, keyBooleans, aliasStable, invalidSafe, keySnapshot }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.setupOk === true && first.updateOk === true && first.drawOk === true && Array.isArray(first.resizeSeen) && first.resizeSeen[0] === 'number' && first.resizeSeen[1] === 'number' && first.resizeSeen[2] === 640 && first.resizeSeen[3] === 360 && first.hasInputFns === true && first.keyBooleans === true && first.aliasStable === true && first.invalidSafe === true; })()",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
id: 'smoke.render.queue.readiness.deterministic',
|
|
212
|
+
expression: "(() => { const runSample = () => { const inspector = aura.debug?.inspectorStats; if (typeof inspector !== 'function') return null; const before = inspector(); const beforeDraw2d = Number(before?.queues?.draw2dPending); const beforeDraw3d = Number(before?.queues?.draw3dPending); const beforeOverlay = Number(before?.queues?.debugOverlayPending); const beforeNumeric = [beforeDraw2d, beforeDraw3d, beforeOverlay].every((value) => Number.isFinite(value)); let drawCallsAccepted = true; try { const white = aura.Color?.WHITE || aura.colors?.white || (typeof aura.rgba === 'function' ? aura.rgba(1, 1, 1, 1) : null); aura.draw2d.clear(0, 0, 0); aura.draw2d.rect(4, 6, 8, 10, white); aura.draw2d.rect(12, 9, 6, 4, white); } catch (_) { drawCallsAccepted = false; } const after = inspector(); const afterDraw2d = Number(after?.queues?.draw2dPending); const afterDraw3d = Number(after?.queues?.draw3dPending); const afterOverlay = Number(after?.queues?.debugOverlayPending); const afterNumeric = [afterDraw2d, afterDraw3d, afterOverlay].every((value) => Number.isFinite(value)); const draw2dDelta = beforeNumeric && afterNumeric ? (afterDraw2d - beforeDraw2d) : NaN; const draw3dDelta = beforeNumeric && afterNumeric ? (afterDraw3d - beforeDraw3d) : NaN; const overlayDelta = beforeNumeric && afterNumeric ? (afterOverlay - beforeOverlay) : NaN; return { drawCallsAccepted, beforeNumeric, afterNumeric, beforeDraw2d, afterDraw2d, draw2dDelta, draw3dDelta, overlayDelta }; }; const first = runSample(); const second = runSample(); return !!first && !!second && JSON.stringify(first) === JSON.stringify(second) && first.drawCallsAccepted === true && first.beforeNumeric === true && first.afterNumeric === true && Number.isFinite(first.draw2dDelta) && Number.isFinite(first.draw3dDelta) && Number.isFinite(first.overlayDelta) && first.draw2dDelta === 0 && first.draw3dDelta === 0 && first.overlayDelta === 0 && first.afterDraw2d === first.beforeDraw2d; })()",
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
id: 'smoke.assets-audio.reason-codes.deterministic',
|
|
216
|
+
expression: "(() => { const runSample = () => { const formatInvalidRaw = (() => { try { return aura.assets.getFormatSupport(42); } catch (_) { return null; } })(); const formatSupportedRaw = (() => { try { return aura.assets.getFormatSupport('native-smoke.png'); } catch (_) { return null; } })(); const loadMissing = (() => { try { const result = aura.assets.load('__missing__/native-smoke-missing.png'); return { threw: false, reasonCode: result?.reasonCode || null, message: null, taggedReason: null }; } catch (err) { const message = String(err); const match = /\\[reason:([^\\]]+)\\]/.exec(message); return { threw: true, reasonCode: null, message, taggedReason: match ? match[1] : null }; } })(); const invalidBusRaw = (() => { try { return aura.audio.setBusVolume('', 0.5); } catch (_) { return null; } })(); const invalidTrackRaw = (() => { try { return aura.audio.fadeTrack('invalid', { to: 0.2, duration: 0.1 }); } catch (_) { return null; } })(); return { formatInvalid: { ok: formatInvalidRaw?.ok === false, status: formatInvalidRaw?.status || null, reasonCode: formatInvalidRaw?.reasonCode || null }, formatSupported: { ok: !!formatSupportedRaw && formatSupportedRaw.ok === true, status: formatSupportedRaw?.status || null, reasonCode: formatSupportedRaw?.reasonCode || null }, loadMissing, invalidBus: { ok: invalidBusRaw?.ok === false, reasonCode: invalidBusRaw?.reasonCode || null }, invalidTrack: { ok: invalidTrackRaw?.ok === false, reasonCode: invalidTrackRaw?.reasonCode || null } }; }; const first = runSample(); const second = runSample(); const loadMissingOk = first.loadMissing?.threw === true && typeof first.loadMissing?.message === 'string' && first.loadMissing.message.includes('Asset not found: __missing__/native-smoke-missing.png') && (first.loadMissing.taggedReason === null || first.loadMissing.taggedReason === 'missing_asset'); return JSON.stringify(first) === JSON.stringify(second) && first.formatInvalid.ok === true && first.formatInvalid.status === 'unsupported' && first.formatInvalid.reasonCode === 'invalid_format_probe' && first.formatSupported.ok === true && first.formatSupported.status === 'supported' && first.formatSupported.reasonCode === 'asset_format_supported' && loadMissingOk && first.invalidBus.ok === true && first.invalidBus.reasonCode === 'invalid_bus' && first.invalidTrack.ok === true && first.invalidTrack.reasonCode === 'invalid_track_handle'; })()",
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
id: 'smoke.network.readiness.reason-codes.deterministic',
|
|
220
|
+
expression: "(() => { const parseReason = (msg) => { const match = /\\[reason:([^\\]]+)\\]/.exec(msg); return match ? match[1] : null; }; const classifyInvalidConnect = () => { try { aura.net.connect('tcp', '127.0.0.1', 0); return 'unexpected_no_throw'; } catch (err) { const msg = String(err); if (parseReason(msg) === 'optional_module_net_disabled') return 'optional_module_net_disabled'; if (msg.includes('port must be an integer in range 1..65535')) return 'invalid_connect_port'; return 'unexpected_error'; } }; const classifyInvalidWebSocket = () => { try { aura.net.websocket(42); return 'unexpected_no_throw'; } catch (err) { const msg = String(err); if (parseReason(msg) === 'optional_module_net_disabled') return 'optional_module_net_disabled'; if (msg.includes('url must be a websocket URL string')) return 'invalid_websocket_url'; return 'unexpected_error'; } }; const classifyInvalidFetch = () => { try { aura.net.fetch(42); return 'unexpected_no_throw'; } catch (err) { const msg = String(err); if (parseReason(msg) === 'optional_module_net_disabled') return 'optional_module_net_disabled'; if (msg.includes('url must be a string') || msg.includes('url must be an HTTP URL string')) return 'invalid_fetch_url'; return 'unexpected_error'; } }; const classifyRuntimeMode = () => { try { const handle = aura.net.connect('tcp', '127.0.0.1', 7777); const handleLike = !!handle && typeof handle === 'object' && typeof handle.send === 'function' && typeof handle.close === 'function'; if (handleLike) { try { handle.close(); } catch (_) {} return 'enabled_runtime'; } return 'enabled_nonstandard'; } catch (err) { const msg = String(err); if (parseReason(msg) === 'optional_module_net_disabled') return 'disabled'; return 'enabled_runtime_error'; } }; const runSample = () => { const methodsOk = typeof aura.net?.connect === 'function' && typeof aura.net?.websocket === 'function' && typeof aura.net?.fetch === 'function' && typeof aura.net?.get === 'function' && typeof aura.net?.post === 'function'; const mode = classifyRuntimeMode(); const connectReason = classifyInvalidConnect(); const websocketReason = classifyInvalidWebSocket(); const fetchReason = classifyInvalidFetch(); const consistency = mode === 'disabled' ? (connectReason === 'optional_module_net_disabled' && websocketReason === 'optional_module_net_disabled' && fetchReason === 'optional_module_net_disabled') : (connectReason === 'invalid_connect_port' && websocketReason === 'invalid_websocket_url' && fetchReason === 'invalid_fetch_url'); return { methodsOk, mode, connectReason, websocketReason, fetchReason, consistency }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.methodsOk === true && first.consistency === true && ['disabled', 'enabled_runtime', 'enabled_runtime_error', 'enabled_nonstandard'].includes(first.mode); })()",
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
nativeFrames: 1,
|
|
224
|
+
frames: 1,
|
|
225
|
+
source: `aura.setup = function () {};`,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
id: 'draw-audio-assets-storage',
|
|
229
|
+
namespaces: ['draw2d', 'audio', 'assets', 'storage'],
|
|
230
|
+
functions: [
|
|
231
|
+
'aura.draw2d.clear',
|
|
232
|
+
'aura.draw2d.rect',
|
|
233
|
+
'aura.draw2d.rectFill',
|
|
234
|
+
'aura.draw2d.circle',
|
|
235
|
+
'aura.draw2d.circleFill',
|
|
236
|
+
'aura.draw2d.line',
|
|
237
|
+
'aura.draw2d.sprite',
|
|
238
|
+
'aura.draw2d.text',
|
|
239
|
+
'aura.draw2d.measureText',
|
|
240
|
+
'aura.draw2d.pushTransform',
|
|
241
|
+
'aura.draw2d.popTransform',
|
|
242
|
+
'aura.draw2d.translate',
|
|
243
|
+
'aura.draw2d.rotate',
|
|
244
|
+
'aura.draw2d.scale',
|
|
245
|
+
'aura.audio.play',
|
|
246
|
+
'aura.audio.pause',
|
|
247
|
+
'aura.audio.resume',
|
|
248
|
+
'aura.audio.stop',
|
|
249
|
+
'aura.audio.setVolume',
|
|
250
|
+
'aura.audio.setMasterVolume',
|
|
251
|
+
'aura.audio.stopAll',
|
|
252
|
+
'aura.audio.setBusVolume',
|
|
253
|
+
'aura.audio.assignBus',
|
|
254
|
+
'aura.audio.fadeTrack',
|
|
255
|
+
'aura.audio.fadeBus',
|
|
256
|
+
'aura.audio.crossfade',
|
|
257
|
+
'aura.audio.update',
|
|
258
|
+
'aura.audio.clearEnvelopes',
|
|
259
|
+
'aura.audio.getMixerState',
|
|
260
|
+
'aura.assets.load',
|
|
261
|
+
'aura.assets.exists',
|
|
262
|
+
'aura.assets.loadJson',
|
|
263
|
+
'aura.assets.loadText',
|
|
264
|
+
'aura.assets.loadFont',
|
|
265
|
+
'aura.assets.loadBitmapFont',
|
|
266
|
+
'aura.assets.getFormatSupport',
|
|
267
|
+
'aura.assets.getState',
|
|
268
|
+
'aura.assets.getStateHistory',
|
|
269
|
+
'aura.assets.evict',
|
|
270
|
+
'aura.assets.getCachePolicy',
|
|
271
|
+
'aura.assets.setCachePolicy',
|
|
272
|
+
'aura.assets.preload2d',
|
|
273
|
+
'aura.assets.preload3d',
|
|
274
|
+
'aura.storage.save',
|
|
275
|
+
'aura.storage.load',
|
|
276
|
+
'aura.storage.delete',
|
|
277
|
+
'aura.storage.keys',
|
|
278
|
+
],
|
|
279
|
+
nativeChecks: [
|
|
280
|
+
{ id: 'draw2d.clear', expression: "typeof aura.draw2d?.clear === 'function'" },
|
|
281
|
+
{ id: 'draw2d.rect', expression: "typeof aura.draw2d?.rect === 'function'" },
|
|
282
|
+
{ id: 'draw2d.rectFill', expression: "typeof aura.draw2d?.rectFill === 'function'" },
|
|
283
|
+
{ id: 'draw2d.circle', expression: "typeof aura.draw2d?.circle === 'function'" },
|
|
284
|
+
{ id: 'draw2d.circleFill', expression: "typeof aura.draw2d?.circleFill === 'function'" },
|
|
285
|
+
{ id: 'draw2d.line', expression: "typeof aura.draw2d?.line === 'function'" },
|
|
286
|
+
{ id: 'draw2d.sprite', expression: "typeof aura.draw2d?.sprite === 'function'" },
|
|
287
|
+
{ id: 'draw2d.text', expression: "typeof aura.draw2d?.text === 'function'" },
|
|
288
|
+
{ id: 'draw2d.measureText', expression: "typeof aura.draw2d?.measureText === 'function'" },
|
|
289
|
+
{ id: 'draw2d.pushTransform', expression: "typeof aura.draw2d?.pushTransform === 'function'" },
|
|
290
|
+
{ id: 'draw2d.popTransform', expression: "typeof aura.draw2d?.popTransform === 'function'" },
|
|
291
|
+
{ id: 'draw2d.translate', expression: "typeof aura.draw2d?.translate === 'function'" },
|
|
292
|
+
{ id: 'draw2d.rotate', expression: "typeof aura.draw2d?.rotate === 'function'" },
|
|
293
|
+
{ id: 'draw2d.scale', expression: "typeof aura.draw2d?.scale === 'function'" },
|
|
294
|
+
{ id: 'audio.play', expression: "typeof aura.audio?.play === 'function'" },
|
|
295
|
+
{ id: 'audio.pause', expression: "typeof aura.audio?.pause === 'function'" },
|
|
296
|
+
{ id: 'audio.resume', expression: "typeof aura.audio?.resume === 'function'" },
|
|
297
|
+
{ id: 'audio.stop', expression: "typeof aura.audio?.stop === 'function'" },
|
|
298
|
+
{ id: 'audio.setVolume', expression: "typeof aura.audio?.setVolume === 'function'" },
|
|
299
|
+
{ id: 'audio.setMasterVolume', expression: "typeof aura.audio?.setMasterVolume === 'function'" },
|
|
300
|
+
{ id: 'audio.stopAll', expression: "typeof aura.audio?.stopAll === 'function'" },
|
|
301
|
+
{ id: 'audio.setBusVolume', expression: "typeof aura.audio?.setBusVolume === 'function'" },
|
|
302
|
+
{ id: 'audio.assignBus', expression: "typeof aura.audio?.assignBus === 'function'" },
|
|
303
|
+
{ id: 'audio.fadeTrack', expression: "typeof aura.audio?.fadeTrack === 'function'" },
|
|
304
|
+
{ id: 'audio.fadeBus', expression: "typeof aura.audio?.fadeBus === 'function'" },
|
|
305
|
+
{ id: 'audio.crossfade', expression: "typeof aura.audio?.crossfade === 'function'" },
|
|
306
|
+
{ id: 'audio.update', expression: "typeof aura.audio?.update === 'function'" },
|
|
307
|
+
{ id: 'audio.clearEnvelopes', expression: "typeof aura.audio?.clearEnvelopes === 'function'" },
|
|
308
|
+
{ id: 'audio.getMixerState', expression: "typeof aura.audio?.getMixerState === 'function'" },
|
|
309
|
+
{ id: 'assets.load', expression: "typeof aura.assets?.load === 'function'" },
|
|
310
|
+
{ id: 'assets.exists', expression: "typeof aura.assets?.exists === 'function'" },
|
|
311
|
+
{ id: 'assets.loadJson', expression: "typeof aura.assets?.loadJson === 'function'" },
|
|
312
|
+
{ id: 'assets.loadText', expression: "typeof aura.assets?.loadText === 'function'" },
|
|
313
|
+
{ id: 'assets.loadFont', expression: "typeof aura.assets?.loadFont === 'function'" },
|
|
314
|
+
{ id: 'assets.loadBitmapFont', expression: "typeof aura.assets?.loadBitmapFont === 'function'" },
|
|
315
|
+
{ id: 'assets.getFormatSupport', expression: "typeof aura.assets?.getFormatSupport === 'function'" },
|
|
316
|
+
{
|
|
317
|
+
id: 'assets.streaming.surface.methods',
|
|
318
|
+
expression: "(() => ['load','getFormatSupport','getState','getStateHistory','evict','getCachePolicy','setCachePolicy','preload2d','preload3d'].every((name) => typeof aura.assets?.[name] === 'function'))()",
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: 'assets.streaming.lifecycle.preload.deterministic',
|
|
322
|
+
expression: "(() => { const reasonOf = (entry) => (entry && (entry.reasonCode || entry.reason)) || null; const normalizePreload = (entry) => ({ ok: !!entry && entry.ok === true, reasonCode: reasonOf(entry), requested: Number(entry?.requested || 0), loaded: Number(entry?.loaded || 0), failed: Number(entry?.failed || 0), failureReasonCodes: Array.isArray(entry?.failures) ? entry.failures.map((row) => reasonOf(row) || '').join('|') : '' }); const normalizeState = (entry) => entry ? { state: entry.state || null, reasonCode: reasonOf(entry) } : null; const normalizeHistory = (rows) => Array.isArray(rows) ? rows.map((row) => `${row.state || ''}:${reasonOf(row) || ''}`).join('|') : ''; const runSample = (tag) => { const missing2d = `__missing__/stream-2d-${tag}.png`; const missing3d = `__missing__/stream-3d-${tag}.glb`; const preload2d = aura.assets.preload2d([missing2d]); const preload3d = aura.assets.preload3d([missing3d]); const state2d = aura.assets.getState(missing2d); const state3d = aura.assets.getState(missing3d); const history2d = aura.assets.getStateHistory(missing2d); const history3d = aura.assets.getStateHistory(missing3d); return { preload2d: normalizePreload(preload2d), preload3d: normalizePreload(preload3d), state2d: normalizeState(state2d), state3d: normalizeState(state3d), history2d: normalizeHistory(history2d), history3d: normalizeHistory(history3d) }; }; const first = runSample('a'); const second = runSample('b'); return JSON.stringify(first) === JSON.stringify(second) && first.preload2d.reasonCode === 'assets_preload_partial_failure' && first.preload2d.requested === 1 && first.preload2d.failed === 1 && first.preload2d.failureReasonCodes === 'missing_asset' && first.preload3d.reasonCode === 'assets_preload_partial_failure' && first.preload3d.requested === 1 && first.preload3d.failed === 1 && first.preload3d.failureReasonCodes === 'missing_asset' && first.state2d?.state === 'failed' && first.state2d?.reasonCode === 'missing_asset' && first.state3d?.state === 'failed' && first.state3d?.reasonCode === 'missing_asset' && first.history2d.startsWith('queued:') && first.history2d.includes('|loading:') && first.history2d.includes('|failed:') && first.history3d.startsWith('queued:') && first.history3d.includes('|loading:') && first.history3d.includes('|failed:missing_asset'); })()",
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
id: 'assets.deferred-format.reason-codes.deterministic',
|
|
326
|
+
expression: "(() => { const norm = (entry) => entry ? { ok: entry.ok === true, status: entry.status || null, reasonCode: entry.reasonCode || null, extension: entry.extension || null, kindHint: entry.kindHint || null, supported: entry.supported === true, deferred: entry.deferred === true } : null; const runSample = () => { const supported = norm(aura.assets.getFormatSupport('atlas.png')); const promotedImage = norm(aura.assets.getFormatSupport('future.webp')); const deferredImage = norm(aura.assets.getFormatSupport('future.bmp')); const supportedWoff2 = norm(aura.assets.getFormatSupport('future.woff2')); const deferredFont = norm(aura.assets.getFormatSupport('future.woff')); const promotedModel = norm(aura.assets.getFormatSupport('future.glb')); const nativeVideo = norm(aura.assets.getFormatSupport('future.mp4')); const unsupported = norm(aura.assets.getFormatSupport('blob.xyz')); const invalidRaw = aura.assets.getFormatSupport(42); const invalid = invalidRaw ? { ok: invalidRaw.ok === true, status: invalidRaw.status || null, reasonCode: invalidRaw.reasonCode || null } : null; const loadReason = (() => { try { aura.assets.load('future.bmp'); } catch (err) { return String(err); } return ''; })(); const audioReason = (() => { try { aura.audio.play('future.aac'); } catch (err) { return String(err); } return ''; })(); const fontResult = aura.assets.loadFont('future.woff2'); return { supported, promotedImage, deferredImage, supportedWoff2, deferredFont, promotedModel, nativeVideo, unsupported, invalid, loadReason, audioReason, fontReason: fontResult?.reason || null }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.supported?.ok === true && first.supported?.status === 'supported' && first.supported?.reasonCode === 'asset_format_supported' && first.supported?.supported === true && first.supported?.deferred === false && first.promotedImage?.ok === true && first.promotedImage?.status === 'supported' && first.promotedImage?.reasonCode === 'asset_format_supported' && first.promotedImage?.deferred === false && first.deferredImage?.ok === true && first.deferredImage?.status === 'unsupported' && first.deferredImage?.reasonCode === 'asset_format_unsupported' && first.deferredImage?.deferred === false && first.supportedWoff2?.status === 'supported' && first.supportedWoff2?.reasonCode === 'asset_format_supported' && first.supportedWoff2?.deferred === false && first.deferredFont?.status === 'unsupported' && first.deferredFont?.reasonCode === 'asset_format_unsupported' && first.deferredFont?.deferred === false && first.promotedModel?.status === 'supported' && first.promotedModel?.reasonCode === 'asset_format_supported' && first.nativeVideo?.status === 'supported' && first.nativeVideo?.reasonCode === 'asset_format_supported' && first.nativeVideo?.extension === 'mp4' && first.unsupported?.status === 'unsupported' && first.unsupported?.reasonCode === 'asset_format_unsupported' && first.invalid?.ok === false && first.invalid?.status === 'unsupported' && first.invalid?.reasonCode === 'invalid_format_probe' && first.loadReason.includes('[reason:asset_format_unsupported]') && first.audioReason.includes('[reason:asset_format_unsupported]') && first.fontReason === 'asset_not_found'; })()",
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: 'assets.streaming.cache-policy.reason-codes.stable',
|
|
330
|
+
expression: "(() => { const reasonOf = (entry) => (entry && (entry.reasonCode || entry.reason)) || null; const sample = () => { const invalidPaths = aura.assets.preload2d('bad'); const invalidPath = aura.assets.preload3d(['../bad.glb']); const invalidMaxEntries = aura.assets.setCachePolicy({ maxEntries: 0 }); const invalidMaxBytes = aura.assets.setCachePolicy({ maxBytes: 0 }); const invalidMode = aura.assets.setCachePolicy({ evictionMode: 'fifo' }); const updated = aura.assets.setCachePolicy({ maxEntries: 4, maxBytes: null, evictionMode: 'oldest' }); const policy = aura.assets.getCachePolicy(); const missingEvict = aura.assets.evict('__missing__/ghost.png'); const invalidEvict = aura.assets.evict('../ghost.png'); return { invalidPaths: reasonOf(invalidPaths), invalidPath: reasonOf(invalidPath), invalidMaxEntries: reasonOf(invalidMaxEntries), invalidMaxBytes: reasonOf(invalidMaxBytes), invalidMode: reasonOf(invalidMode), updatedOk: !!updated && updated.ok === true, updatedReason: reasonOf(updated), policyMaxEntries: policy?.maxEntries, policyMaxBytes: policy?.maxBytes ?? null, policyEvictionMode: policy?.evictionMode, missingEvict: reasonOf(missingEvict), invalidEvict: reasonOf(invalidEvict) }; }; const first = sample(); const second = sample(); return JSON.stringify(first) === JSON.stringify(second) && first.invalidPaths === 'invalid_preload_paths' && first.invalidPath === 'invalid_preload_path' && first.invalidMaxEntries === 'invalid_max_entries' && first.invalidMaxBytes === 'invalid_max_bytes' && first.invalidMode === 'invalid_eviction_mode' && first.updatedOk === true && first.updatedReason === 'cache_policy_updated' && first.policyMaxEntries === 4 && first.policyMaxBytes === null && first.policyEvictionMode === 'oldest' && first.missingEvict === 'missing_asset' && first.invalidEvict === 'invalid_path'; })()",
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
id: 'audio.invalid-input.no-throw.reason-codes',
|
|
334
|
+
expression: "(() => { const runSample = () => { let threw = false; try { aura.audio.stop(-1); aura.audio.pause('x'); aura.audio.resume(99999); aura.audio.setVolume('x', 0.5); } catch (_) { threw = true; } const invalidBus = aura.audio.setBusVolume('', 0.5); const invalidTrackHandle = aura.audio.fadeTrack('oops', { to: 0.2, duration: 0.5 }); const missingBus = aura.audio.fadeBus('missing', { to: 0.2, duration: 0.5 }); const invalidCrossfade = aura.audio.crossfade('oops', 'bad', { duration: 0.5 }); return { threw, invalidBus: invalidBus?.reasonCode || null, invalidTrackHandle: invalidTrackHandle?.reasonCode || null, missingBus: missingBus?.reasonCode || null, invalidCrossfade: invalidCrossfade?.reasonCode || null }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.threw === false && first.invalidBus === 'invalid_bus' && first.invalidTrackHandle === 'invalid_track_handle' && first.missingBus === 'missing_bus' && typeof first.invalidCrossfade === 'string' && first.invalidCrossfade.length > 0; })()",
|
|
335
|
+
},
|
|
336
|
+
{ id: 'storage.save', expression: "typeof aura.storage?.save === 'function'" },
|
|
337
|
+
{ id: 'storage.load', expression: "typeof aura.storage?.load === 'function'" },
|
|
338
|
+
{ id: 'storage.delete', expression: "typeof aura.storage?.delete === 'function'" },
|
|
339
|
+
{ id: 'storage.keys', expression: "typeof aura.storage?.keys === 'function'" },
|
|
340
|
+
],
|
|
341
|
+
frames: 2,
|
|
342
|
+
source: `
|
|
343
|
+
let img;
|
|
344
|
+
let snd;
|
|
345
|
+
|
|
346
|
+
aura.setup = async function () {
|
|
347
|
+
await aura.assets.load(['player.png', 'coin.wav', 'level.json']);
|
|
348
|
+
img = aura.assets.image('player.png');
|
|
349
|
+
snd = aura.assets.sound('coin.wav');
|
|
350
|
+
|
|
351
|
+
aura.test.equal(aura.assets.mesh('cube.glb').kind, 'mesh');
|
|
352
|
+
aura.test.assert(typeof aura.assets.text('dialogue.txt') === 'string');
|
|
353
|
+
const bytes = aura.assets.bytes('blob.bin');
|
|
354
|
+
aura.test.assert(typeof bytes.byteLength === 'number', 'bytes should expose byteLength');
|
|
355
|
+
aura.test.assert(typeof aura.assets.json('level.json') === 'object');
|
|
356
|
+
|
|
357
|
+
aura.storage.set('highscore', 42);
|
|
358
|
+
aura.test.equal(aura.storage.get('highscore'), 42, 'storage get should return stored value');
|
|
359
|
+
aura.storage.delete('highscore');
|
|
360
|
+
aura.test.equal(aura.storage.get('highscore', 0), 0, 'storage fallback should apply after delete');
|
|
361
|
+
|
|
362
|
+
const handle = aura.audio.play(snd, { loop: true });
|
|
363
|
+
aura.audio.pause(handle);
|
|
364
|
+
aura.audio.resume(handle);
|
|
365
|
+
aura.audio.setVolume(handle, 0.5);
|
|
366
|
+
aura.audio.stop(handle);
|
|
367
|
+
aura.audio.stopAll();
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
aura.draw = function () {
|
|
371
|
+
aura.draw2d.clear(0, 0, 0);
|
|
372
|
+
aura.draw2d.rect(10, 10, 40, 20, aura.colors.red);
|
|
373
|
+
aura.draw2d.rectOutline(10, 40, 40, 20, aura.colors.white, 1);
|
|
374
|
+
aura.draw2d.circle(80, 20, 10, aura.colors.white);
|
|
375
|
+
aura.draw2d.circleOutline(80, 50, 10, aura.colors.white, 1);
|
|
376
|
+
aura.draw2d.line(0, 0, 100, 100, aura.colors.white, 1);
|
|
377
|
+
aura.draw2d.triangle(0, 0, 20, 0, 10, 20, aura.colors.white);
|
|
378
|
+
aura.draw2d.image(img, 30, 30);
|
|
379
|
+
aura.draw2d.sprite(img, 30, 30, { frameX: 0, frameY: 0, frameW: 16, frameH: 16 });
|
|
380
|
+
aura.draw2d.text('ok', 8, 8, { size: 12, color: aura.colors.white });
|
|
381
|
+
aura.draw2d.push();
|
|
382
|
+
aura.draw2d.translate(4, 5);
|
|
383
|
+
aura.draw2d.rotate(0.2);
|
|
384
|
+
aura.draw2d.scale(1.2, 1.2);
|
|
385
|
+
aura.draw2d.pop();
|
|
386
|
+
};
|
|
387
|
+
`,
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
id: 'compute-runtime-native',
|
|
391
|
+
modes: ['native'],
|
|
392
|
+
namespaces: ['compute'],
|
|
393
|
+
functions: [
|
|
394
|
+
'aura.compute.createPipeline',
|
|
395
|
+
'aura.compute.createBuffer',
|
|
396
|
+
'aura.compute.writeBuffer',
|
|
397
|
+
'aura.compute.createBindGroup',
|
|
398
|
+
'aura.compute.dispatch',
|
|
399
|
+
'aura.compute.readBuffer',
|
|
400
|
+
'aura.compute.destroyPipeline',
|
|
401
|
+
'aura.compute.destroyBuffer',
|
|
402
|
+
'aura.compute.destroyBindGroup',
|
|
403
|
+
'aura.compute.getError',
|
|
404
|
+
],
|
|
405
|
+
nativeChecks: [
|
|
406
|
+
{
|
|
407
|
+
id: 'compute.surface.methods',
|
|
408
|
+
expression: "(() => ['createPipeline','createBuffer','writeBuffer','createBindGroup','dispatch','readBuffer','destroyPipeline','destroyBuffer','destroyBindGroup','getError'].every((name) => typeof aura.compute?.[name] === 'function'))()",
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
id: 'compute.dispatch.readback.queued',
|
|
412
|
+
expression: "(() => { const shader = '@group(0) @binding(0) var<storage, read_write> values: array<f32>;\\n@compute @workgroup_size(1)\\nfn main() {\\n values[0] = values[0] + 1.0;\\n}'; const pipeline = aura.compute.createPipeline(shader); const buffer = aura.compute.createBuffer(4, 'storage-read'); aura.compute.writeBuffer(buffer, new Float32Array([2])); const bindGroup = aura.compute.createBindGroup(pipeline, [{ binding: 0, buffer }]); aura.compute.dispatch(pipeline, bindGroup, 1, 1, 1); const queued = aura.compute.readBuffer(buffer, 0, 4); globalThis.__computeNative = { pipeline, buffer, bindGroup, queuedWasNull: queued === null }; return Number.isInteger(pipeline) && pipeline > 0 && Number.isInteger(buffer) && buffer > 0 && Number.isInteger(bindGroup) && bindGroup > 0 && queued === null && aura.compute.getError(pipeline) === null && aura.compute.getError(bindGroup) === null && aura.compute.getError(buffer) === null; })()",
|
|
413
|
+
},
|
|
414
|
+
],
|
|
415
|
+
nativePostChecks: [
|
|
416
|
+
{
|
|
417
|
+
id: 'compute.dispatch.readback.deterministic',
|
|
418
|
+
expression: "(() => { const state = globalThis.__computeNative || {}; const result = aura.compute.readBuffer(state.buffer); const second = aura.compute.readBuffer(state.buffer); const values = ArrayBuffer.isView(result) ? Array.from(result).map((value) => Number(value.toFixed(6))) : []; const pipelineError = aura.compute.getError(state.pipeline); const bindGroupError = aura.compute.getError(state.bindGroup); const bufferError = aura.compute.getError(state.buffer); aura.compute.destroyBindGroup(state.bindGroup); aura.compute.destroyPipeline(state.pipeline); aura.compute.destroyBuffer(state.buffer); return state.queuedWasNull === true && result instanceof Float32Array && result.length === 1 && values.length === 1 && values[0] === 3 && second === null && pipelineError === null && bindGroupError === null && bufferError === null; })()",
|
|
419
|
+
},
|
|
420
|
+
],
|
|
421
|
+
nativeFrames: 2,
|
|
422
|
+
frames: 1,
|
|
423
|
+
source: `
|
|
424
|
+
globalThis.__computeNative = {
|
|
425
|
+
pipeline: 0,
|
|
426
|
+
buffer: 0,
|
|
427
|
+
bindGroup: 0,
|
|
428
|
+
queuedWasNull: false,
|
|
429
|
+
};
|
|
430
|
+
`,
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
id: 'camera-2d-runtime-surface',
|
|
434
|
+
modes: ['native'],
|
|
435
|
+
namespaces: ['camera', 'draw2d', 'debug'],
|
|
436
|
+
functions: [
|
|
437
|
+
'aura.camera.x',
|
|
438
|
+
'aura.camera.y',
|
|
439
|
+
'aura.camera.zoom',
|
|
440
|
+
'aura.camera.rotation',
|
|
441
|
+
'aura.camera.follow',
|
|
442
|
+
'aura.camera.setDeadzone',
|
|
443
|
+
'aura.camera.setBounds',
|
|
444
|
+
'aura.camera.pan',
|
|
445
|
+
'aura.camera.zoomTo',
|
|
446
|
+
'aura.camera.shake',
|
|
447
|
+
'aura.camera.fade',
|
|
448
|
+
'aura.camera.flash',
|
|
449
|
+
'aura.camera.onEffectComplete',
|
|
450
|
+
'aura.camera.update',
|
|
451
|
+
'aura.camera.getState',
|
|
452
|
+
'aura.draw2d.rectFill',
|
|
453
|
+
'aura.draw2d.line',
|
|
454
|
+
'aura.draw2d.circleFill',
|
|
455
|
+
'aura.debug.inspectorStats',
|
|
456
|
+
],
|
|
457
|
+
nativeChecks: [
|
|
458
|
+
{
|
|
459
|
+
id: 'camera.surface.exists',
|
|
460
|
+
expression: "typeof aura.camera === 'object' && ['x', 'y', 'zoom', 'rotation'].every((key) => typeof aura.camera[key] === 'number')",
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
id: 'camera.surface.validation',
|
|
464
|
+
expression: "(() => { const original = aura.camera; aura.camera.x = 12.5; aura.camera.y = -3.25; aura.camera.zoom = 2; aura.camera.rotation = 0.5; aura.camera.x = Number.NaN; aura.camera.y = 'oops'; aura.camera.zoom = 0; aura.camera.zoom = -1; aura.camera.rotation = Number.POSITIVE_INFINITY; try { aura.camera = { x: 999 }; } catch (_) {} return aura.camera === original && aura.camera.x === 12.5 && aura.camera.y === -3.25 && aura.camera.zoom === 2 && aura.camera.rotation === 0.5; })()",
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
id: 'camera.surface.methods',
|
|
468
|
+
expression: "(() => ['follow','stopFollow','setDeadzone','clearDeadzone','setBounds','clearBounds','pan','panTo','zoomTo','rotateTo','shake','fade','flash','clearEffects','onEffectComplete','offEffectComplete','update','getState'].every((name) => typeof aura.camera?.[name] === 'function'))()",
|
|
469
|
+
},
|
|
470
|
+
],
|
|
471
|
+
nativePostChecks: [
|
|
472
|
+
{
|
|
473
|
+
id: 'camera.draw2d.pan-zoom-rotation.deterministic',
|
|
474
|
+
expression: "(() => { const sample = () => { const before = aura.debug.inspectorStats(); const start = before && before.queues ? before.queues.draw2dPending : NaN; aura.camera.x = 10; aura.camera.y = 20; aura.camera.zoom = 2; aura.camera.rotation = 0.25; aura.draw2d.rectFill(1, 2, 3, 4, aura.Color.WHITE); aura.camera.zoom = 1; aura.draw2d.line(0, 0, 4, 4, aura.Color.WHITE, 1); aura.camera.x = 0; aura.camera.y = 0; aura.camera.rotation = 0; aura.draw2d.circleFill(8, 8, 2, aura.Color.WHITE); const after = aura.debug.inspectorStats(); const end = after && after.queues ? after.queues.draw2dPending : NaN; return Number.isFinite(start) && Number.isFinite(end) ? (end - start) : NaN; }; const first = sample(); const second = sample(); return first === 12 && second === 12; })()",
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
id: 'camera.follow.deadzone.bounds.deterministic',
|
|
478
|
+
expression: "(() => { const target = { x: 0, y: 0 }; const bounded = aura.camera.setBounds({ x: -100, y: -100, width: 200, height: 200 }); const dz = aura.camera.setDeadzone({ x: -5, y: -5, width: 10, height: 10 }); const follow = aura.camera.follow(target, { lerpX: 1, lerpY: 1 }); target.x = 20; target.y = 0; const stepA = aura.camera.update(1 / 60); const stateA = aura.camera.getState(); target.x = 150; target.y = 150; const stepB = aura.camera.update(1 / 60); const stateB = aura.camera.getState(); const stop = aura.camera.stopFollow(); aura.camera.clearDeadzone(); aura.camera.clearBounds(); return bounded && bounded.ok === true && dz && dz.ok === true && follow && follow.ok === true && stepA && stepA.ok === true && stepB && stepB.ok === true && stateA && stateA.x === 15 && stateA.y === 0 && stateB && stateB.x === 100 && stateB.y === 100 && stop && stop.ok === true && stop.stopped === true; })()",
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
id: 'camera.effects.callback-ordering.deterministic',
|
|
482
|
+
expression: "(() => { aura.camera.x = 0; aura.camera.y = 0; aura.camera.zoom = 1; aura.camera.rotation = 0; aura.camera.clearEffects(); const calls = []; const late = aura.camera.onEffectComplete((evt) => calls.push(`late:${evt.effectType}:${evt.effectId}`), 10); const early = aura.camera.onEffectComplete((evt) => calls.push(`early:${evt.effectType}:${evt.effectId}`), 1); const pan = aura.camera.pan(20, 10, { duration: 0.5 }); const zoom = aura.camera.zoomTo(2, { duration: 0.5 }); const shake = aura.camera.shake({ duration: 0.5, intensity: 4, frequency: 8 }); const step = aura.camera.update(0.5); const invalidDt = aura.camera.update(0); const state = aura.camera.getState(); const removed = aura.camera.offEffectComplete(late.listenerId) === true && aura.camera.offEffectComplete(early.listenerId) === true; const expected = `early:pan:${pan.effectId}|late:pan:${pan.effectId}|early:zoom:${zoom.effectId}|late:zoom:${zoom.effectId}|early:shake:${shake.effectId}|late:shake:${shake.effectId}`; return pan && pan.ok === true && zoom && zoom.ok === true && shake && shake.ok === true && step && step.ok === true && state && Number(state.x.toFixed(6)) === 20 && Number(state.y.toFixed(6)) === 10 && Number(state.zoom.toFixed(6)) === 2 && state.activeEffects === 0 && invalidDt && invalidDt.ok === false && invalidDt.reasonCode === 'invalid_dt' && calls.join('|') === expected && removed; })()",
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
id: 'camera.effects.fade-flash.overlay-deterministic',
|
|
486
|
+
expression: "(() => { aura.camera.clearEffects(); const badFade = aura.camera.fade('bad'); const badDuration = aura.camera.fade({ duration: 0 }); const badColor = aura.camera.fade({ color: { r: 'x', g: 0, b: 0 } }); const badFlash = aura.camera.flash({ alpha: 2 }); const fade = aura.camera.fade({ duration: 0.5, fromAlpha: 0.2, toAlpha: 0.8, color: aura.rgba(0.2, 0.3, 0.4, 1) }); const start = aura.camera.getState(); const midStep = aura.camera.update(0.25); const mid = aura.camera.getState(); const flash = aura.camera.flash({ duration: 0.25, alpha: 0.6, color: aura.rgba(1, 1, 1, 1) }); const flashStart = aura.camera.getState(); const endStep = aura.camera.update(0.25); const end = aura.camera.getState(); aura.camera.clearEffects(); const cleared = aura.camera.getState(); return badFade && badFade.ok === false && badFade.reasonCode === 'invalid_fade_options' && badDuration && badDuration.ok === false && badDuration.reasonCode === 'invalid_fade_duration' && badColor && badColor.ok === false && badColor.reasonCode === 'invalid_fade_color' && badFlash && badFlash.ok === false && badFlash.reasonCode === 'invalid_flash_alpha' && fade && fade.ok === true && start && start.overlay && start.overlay.effectType === 'fade' && Number(start.overlay.alpha.toFixed(6)) === 0.2 && midStep && midStep.ok === true && mid && mid.overlay && mid.overlay.effectType === 'fade' && Number(mid.overlay.alpha.toFixed(6)) === 0.5 && flash && flash.ok === true && flash.reasonCode === 'camera_flash_started' && flashStart && flashStart.overlay && flashStart.overlay.effectType === 'flash' && Number(flashStart.overlay.alpha.toFixed(6)) === 0.6 && endStep && endStep.ok === true && end && end.overlay && end.overlay.effectType === 'fade' && Number(end.overlay.alpha.toFixed(6)) === 0.8 && cleared && cleared.overlay === null; })()",
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
nativeFrames: 2,
|
|
490
|
+
frames: 1,
|
|
491
|
+
source: `
|
|
492
|
+
aura.setup = function () {};
|
|
493
|
+
`,
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
id: 'draw2d-product-ui-composition-native',
|
|
497
|
+
modes: ['native'],
|
|
498
|
+
namespaces: ['draw2d', 'camera', 'debug'],
|
|
499
|
+
functions: [
|
|
500
|
+
'aura.draw2d.createRenderTarget',
|
|
501
|
+
'aura.draw2d.resizeRenderTarget',
|
|
502
|
+
'aura.draw2d.destroyRenderTarget',
|
|
503
|
+
'aura.draw2d.withRenderTarget',
|
|
504
|
+
'aura.draw2d.pushClipRect',
|
|
505
|
+
'aura.draw2d.popClipRect',
|
|
506
|
+
'aura.draw2d.sprite',
|
|
507
|
+
'aura.draw2d.tileSprite',
|
|
508
|
+
'aura.draw2d.nineSlice',
|
|
509
|
+
'aura.draw2d.text',
|
|
510
|
+
'aura.camera.fade',
|
|
511
|
+
'aura.camera.flash',
|
|
512
|
+
'aura.camera.clearEffects',
|
|
513
|
+
'aura.camera.update',
|
|
514
|
+
'aura.camera.getState',
|
|
515
|
+
'aura.debug.inspectorStats',
|
|
516
|
+
],
|
|
517
|
+
nativeChecks: [
|
|
518
|
+
{
|
|
519
|
+
id: 'draw2d.product-ui.surface.methods',
|
|
520
|
+
expression: "(() => ['createRenderTarget','resizeRenderTarget','destroyRenderTarget','withRenderTarget','pushClipRect','popClipRect','sprite','tileSprite','nineSlice','text'].every((name) => typeof aura.draw2d?.[name] === 'function') && ['fade','flash','clearEffects','update','getState'].every((name) => typeof aura.camera?.[name] === 'function') && typeof aura.debug?.inspectorStats === 'function')()",
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
id: 'draw2d.product-ui.runtime.setup',
|
|
524
|
+
expression: `(() => { try { const white = aura.Color?.WHITE || aura.colors?.white || aura.rgba(1, 1, 1, 1); const target = aura.draw2d.createRenderTarget(96, 48); const resize = aura.draw2d.resizeRenderTarget(target, 128, 64); aura.camera.clearEffects(); const fade = aura.camera.fade({ duration: 0.5, fromAlpha: 0.1, toAlpha: 0.7, color: aura.rgba(0.05, 0.08, 0.12, 1) }); globalThis.__draw2dProductUiProbe = { white, target, resize, fadeReason: fade?.reasonCode || null, frames: [], updates: [] }; aura.update = function () { const probe = globalThis.__draw2dProductUiProbe || {}; const updateIndex = Array.isArray(probe.updates) ? probe.updates.length : 0; let flash = null; let before = aura.camera.getState(); if (updateIndex === 1) { flash = aura.camera.flash({ duration: 0.25, alpha: 0.6, color: aura.rgba(1, 1, 1, 1) }); before = aura.camera.getState(); } const step = aura.camera.update(0.25); const after = aura.camera.getState(); probe.updates.push({ updateIndex, flashReason: flash?.reasonCode || null, beforeType: before?.overlay?.effectType || null, beforeAlpha: before?.overlay ? Number(before.overlay.alpha.toFixed(6)) : null, afterType: after?.overlay?.effectType || null, afterAlpha: after?.overlay ? Number(after.overlay.alpha.toFixed(6)) : null, stepReason: step?.reasonCode || null, activeEffects: Number(after?.activeEffects || 0) }); }; aura.draw = function () { const probe = globalThis.__draw2dProductUiProbe || {}; const frameIndex = Array.isArray(probe.frames) ? probe.frames.length : 0; aura.draw2d.clear(4, 6, 10); const invalidClip = aura.draw2d.pushClipRect(0, 0, 0, 10); let offscreenPush = null; let offscreenPop = null; let nestedCapture = null; const capture = aura.draw2d.withRenderTarget(probe.target, () => { aura.draw2d.clear(0, 0, 0, 0); offscreenPush = aura.draw2d.pushClipRect(4, 4, 120, 56); nestedCapture = aura.draw2d.withRenderTarget(probe.target, () => {}); aura.draw2d.rect(6, 6, 116, 52, aura.rgba(0.14, 0.18, 0.25, 0.95)); aura.draw2d.rect(10, 38, 96, 10, aura.rgba(0.4, 0.85, 1, 0.7)); aura.draw2d.text('HP 72 SCORE 1800', 14, 28, { size: 12, color: white }); offscreenPop = aura.draw2d.popClipRect(); }); const bgClip = aura.draw2d.pushClipRect(0, 0, 160, 96); aura.draw2d.tileSprite(probe.target, 0, 0, 160, 96, { tileScaleX: 1.5, tileScaleY: 1.5, tileOffsetX: frameIndex * 6, tileOffsetY: frameIndex * 3, tint: aura.rgba(0.16, 0.2, 0.26, 0.65) }); const bgPop = aura.draw2d.popClipRect(); aura.draw2d.sprite(probe.target, 12, 14, { width: 192, height: 96 }); const hudPush = aura.draw2d.pushClipRect(24, 22, 168, 72); aura.draw2d.nineSlice(probe.target, 24, 22, 168, 72, { slice: 4, tint: aura.rgba(0.18, 0.22, 0.3, 0.92) }); aura.draw2d.text('ENERGY', 36, 40, { size: 12, color: white }); aura.draw2d.tileSprite(probe.target, 36, 52, 120, 10, { tileScaleX: 0.3, tileScaleY: 0.6, tileOffsetX: frameIndex * 2, tileOffsetY: 0, tint: aura.rgba(0.4, 0.85, 1, 0.7) }); const hudPop = aura.draw2d.popClipRect(); const state = aura.camera.getState(); const inspector = aura.debug.inspectorStats(); probe.frames.push({ frameIndex, bgClip: bgClip?.reasonCode || null, bgPop: bgPop?.reasonCode || null, invalidClip: invalidClip?.reasonCode || null, captureReason: capture?.reasonCode || null, captureCommandCount: Number(capture?.commandCount || 0), offscreenPush: offscreenPush?.reasonCode || null, offscreenPop: offscreenPop?.reasonCode || null, nestedCapture: nestedCapture?.reasonCode || null, hudPush: hudPush?.reasonCode || null, hudPop: hudPop?.reasonCode || null, overlayType: state?.overlay?.effectType || null, overlayAlpha: state?.overlay ? Number(state.overlay.alpha.toFixed(6)) : null, draw2dPendingNumeric: Number.isFinite(Number(inspector?.queues?.draw2dPending)), debugOverlayPendingNumeric: Number.isFinite(Number(inspector?.queues?.debugOverlayPending)) }); }; return target?.ok === true && target?.type === 'renderTarget' && target?.__renderTarget === true && Number.isInteger(target?.handle) && target.handle > 0 && resize?.ok === true && resize?.reasonCode === 'draw2d_render_target_resized' && resize?.width === 128 && resize?.height === 64 && fade?.ok === true && fade?.reasonCode === 'camera_fade_started'; } catch (_) { return false; } })()`,
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
nativePostChecks: [
|
|
528
|
+
{
|
|
529
|
+
id: 'draw2d.product-ui.runtime.evidence',
|
|
530
|
+
expression: `(() => { try { const probe = globalThis.__draw2dProductUiProbe || {}; const frames = Array.isArray(probe.frames) ? probe.frames : []; const updates = Array.isArray(probe.updates) ? probe.updates : []; const frame0 = frames[0] || {}; const frame1 = frames[1] || {}; const frame2 = frames[2] || {}; const update0 = updates[0] || {}; const update1 = updates[1] || {}; const update2 = updates[2] || {}; const target = probe.target; const destroyed = aura.draw2d.destroyRenderTarget(target); const missingDestroy = aura.draw2d.destroyRenderTarget(target); aura.camera.clearEffects(); const cleared = aura.camera.getState(); return probe.fadeReason === 'camera_fade_started' && target?.ok === true && Number.isInteger(target?.handle) && target.handle > 0 && probe.resize?.ok === true && probe.resize?.width === 128 && probe.resize?.height === 64 && frames.length === 3 && updates.length === 3 && frame0.bgClip === 'draw2d_clip_pushed' && frame0.bgPop === 'draw2d_clip_popped' && frame0.invalidClip === 'invalid_clip_rect' && frame0.captureReason === 'draw2d_render_target_captured' && frame0.captureCommandCount === 6 && frame0.offscreenPush === 'draw2d_clip_pushed' && frame0.offscreenPop === 'draw2d_clip_popped' && frame0.nestedCapture === 'nested_render_target_capture' && frame0.hudPush === 'draw2d_clip_pushed' && frame0.hudPop === 'draw2d_clip_popped' && frame0.overlayType === 'fade' && frame0.overlayAlpha === 0.4 && frame0.draw2dPendingNumeric === true && frame0.debugOverlayPendingNumeric === true && frame1.captureReason === 'draw2d_render_target_captured' && frame1.captureCommandCount === 6 && frame1.overlayType === 'fade' && frame1.overlayAlpha === 0.7 && frame2.captureReason === 'draw2d_render_target_captured' && frame2.captureCommandCount === 6 && frame2.overlayType === 'fade' && frame2.overlayAlpha === 0.7 && update0.flashReason === null && update0.beforeType === 'fade' && update0.beforeAlpha === 0.1 && update0.afterType === 'fade' && update0.afterAlpha === 0.4 && update0.stepReason === 'camera_updated' && update1.flashReason === 'camera_flash_started' && update1.beforeType === 'flash' && update1.beforeAlpha === 0.6 && update1.afterType === 'fade' && update1.afterAlpha === 0.7 && update1.stepReason === 'camera_updated' && update2.flashReason === null && update2.beforeType === 'fade' && update2.beforeAlpha === 0.7 && update2.afterType === 'fade' && update2.afterAlpha === 0.7 && update2.stepReason === 'camera_updated' && destroyed?.ok === true && destroyed?.reasonCode === 'draw2d_render_target_destroyed' && missingDestroy?.ok === false && missingDestroy?.reasonCode === 'missing_render_target' && cleared?.overlay === null; } catch (_) { return false; } })()`,
|
|
531
|
+
},
|
|
532
|
+
],
|
|
533
|
+
nativeFrames: 3,
|
|
534
|
+
source: `
|
|
535
|
+
globalThis.__draw2dProductUiProbe = {
|
|
536
|
+
target: null,
|
|
537
|
+
resize: null,
|
|
538
|
+
fadeReason: null,
|
|
539
|
+
frames: [],
|
|
540
|
+
updates: [],
|
|
541
|
+
};
|
|
542
|
+
`,
|
|
543
|
+
nativeSource: `
|
|
544
|
+
const __checks = [];
|
|
545
|
+
let __reported = false;
|
|
546
|
+
|
|
547
|
+
function __toErrorString(value) {
|
|
548
|
+
return String(value && value.message ? value.message : value);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function __record(id, pass, detail, trace = null) {
|
|
552
|
+
const row = { id, pass: !!pass, detail: detail || null };
|
|
553
|
+
if (!row.pass && trace !== null && trace !== undefined) {
|
|
554
|
+
row.trace = trace;
|
|
555
|
+
}
|
|
556
|
+
__checks.push(row);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function __finish() {
|
|
560
|
+
if (__reported) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
const __failedChecks = __checks.filter((check) => !check.pass);
|
|
564
|
+
console.log('__AURA_CONFORMANCE_NATIVE__' + JSON.stringify({
|
|
565
|
+
caseId: 'draw2d-product-ui-composition-native',
|
|
566
|
+
ok: __failedChecks.length === 0,
|
|
567
|
+
checks: __checks,
|
|
568
|
+
failed: __failedChecks.length,
|
|
569
|
+
passed: __checks.length - __failedChecks.length,
|
|
570
|
+
runtimeCacheDiagnostics: null,
|
|
571
|
+
runtimeInspectorSnapshot: null,
|
|
572
|
+
}));
|
|
573
|
+
__reported = true;
|
|
574
|
+
if (aura.window && typeof aura.window.close === 'function') {
|
|
575
|
+
aura.window.close();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
globalThis.__draw2dProductUiProbe = {
|
|
580
|
+
target: null,
|
|
581
|
+
resize: null,
|
|
582
|
+
fadeReason: null,
|
|
583
|
+
frames: [],
|
|
584
|
+
updates: [],
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
aura.setup = function () {
|
|
588
|
+
try {
|
|
589
|
+
const methodsOk = ['createRenderTarget','resizeRenderTarget','destroyRenderTarget','withRenderTarget','pushClipRect','popClipRect','sprite','tileSprite','nineSlice','text'].every((name) => typeof aura.draw2d?.[name] === 'function')
|
|
590
|
+
&& ['fade','flash','clearEffects','update','getState'].every((name) => typeof aura.camera?.[name] === 'function')
|
|
591
|
+
&& typeof aura.debug?.inspectorStats === 'function';
|
|
592
|
+
__record('draw2d.product-ui.surface.methods', methodsOk, methodsOk ? null : 'required_methods_missing');
|
|
593
|
+
|
|
594
|
+
const white = aura.Color?.WHITE || aura.colors?.white || aura.rgba(1, 1, 1, 1);
|
|
595
|
+
const target = aura.draw2d.createRenderTarget(96, 48);
|
|
596
|
+
const resize = aura.draw2d.resizeRenderTarget(target, 128, 64);
|
|
597
|
+
aura.camera.clearEffects();
|
|
598
|
+
const fade = aura.camera.fade({
|
|
599
|
+
duration: 0.5,
|
|
600
|
+
fromAlpha: 0.1,
|
|
601
|
+
toAlpha: 0.7,
|
|
602
|
+
color: aura.rgba(0.05, 0.08, 0.12, 1),
|
|
603
|
+
});
|
|
604
|
+
globalThis.__draw2dProductUiProbe = {
|
|
605
|
+
white,
|
|
606
|
+
target,
|
|
607
|
+
resize,
|
|
608
|
+
fadeReason: fade?.reasonCode || null,
|
|
609
|
+
frames: [],
|
|
610
|
+
updates: [],
|
|
611
|
+
};
|
|
612
|
+
const setupOk = target?.ok === true
|
|
613
|
+
&& target?.type === 'renderTarget'
|
|
614
|
+
&& target?.__renderTarget === true
|
|
615
|
+
&& Number.isInteger(target?.handle)
|
|
616
|
+
&& target.handle > 0
|
|
617
|
+
&& resize?.ok === true
|
|
618
|
+
&& resize?.reasonCode === 'draw2d_render_target_resized'
|
|
619
|
+
&& resize?.width === 128
|
|
620
|
+
&& resize?.height === 64
|
|
621
|
+
&& fade?.ok === true
|
|
622
|
+
&& fade?.reasonCode === 'camera_fade_started';
|
|
623
|
+
__record('draw2d.product-ui.runtime.setup', setupOk, setupOk ? null : 'draw2d_product_ui_setup_failed');
|
|
624
|
+
} catch (__error) {
|
|
625
|
+
__record('draw2d.product-ui.runtime.setup', false, __toErrorString(__error));
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
aura.update = function () {
|
|
630
|
+
if (__reported) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
try {
|
|
634
|
+
const probe = globalThis.__draw2dProductUiProbe || {};
|
|
635
|
+
const updateIndex = Array.isArray(probe.updates) ? probe.updates.length : 0;
|
|
636
|
+
let flash = null;
|
|
637
|
+
let before = aura.camera.getState();
|
|
638
|
+
if (updateIndex === 1) {
|
|
639
|
+
flash = aura.camera.flash({ duration: 0.25, alpha: 0.6, color: aura.rgba(1, 1, 1, 1) });
|
|
640
|
+
before = aura.camera.getState();
|
|
641
|
+
}
|
|
642
|
+
const step = aura.camera.update(0.25);
|
|
643
|
+
const after = aura.camera.getState();
|
|
644
|
+
probe.updates.push({
|
|
645
|
+
updateIndex,
|
|
646
|
+
flashReason: flash?.reasonCode || null,
|
|
647
|
+
beforeType: before?.overlay?.effectType || null,
|
|
648
|
+
beforeAlpha: before?.overlay ? Number(before.overlay.alpha.toFixed(6)) : null,
|
|
649
|
+
afterType: after?.overlay?.effectType || null,
|
|
650
|
+
afterAlpha: after?.overlay ? Number(after.overlay.alpha.toFixed(6)) : null,
|
|
651
|
+
stepReason: step?.reasonCode || null,
|
|
652
|
+
activeEffects: Number(after?.activeEffects || 0),
|
|
653
|
+
});
|
|
654
|
+
} catch (__error) {
|
|
655
|
+
__record('draw2d.product-ui.runtime.evidence', false, __toErrorString(__error));
|
|
656
|
+
__finish();
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
aura.draw = function () {
|
|
661
|
+
if (__reported) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
try {
|
|
665
|
+
const probe = globalThis.__draw2dProductUiProbe || {};
|
|
666
|
+
const frameIndex = Array.isArray(probe.frames) ? probe.frames.length : 0;
|
|
667
|
+
aura.draw2d.clear(4, 6, 10);
|
|
668
|
+
const invalidClip = aura.draw2d.pushClipRect(0, 0, 0, 10);
|
|
669
|
+
let offscreenPush = null;
|
|
670
|
+
let offscreenPop = null;
|
|
671
|
+
let nestedCapture = null;
|
|
672
|
+
const capture = aura.draw2d.withRenderTarget(probe.target, () => {
|
|
673
|
+
aura.draw2d.clear(0, 0, 0, 0);
|
|
674
|
+
offscreenPush = aura.draw2d.pushClipRect(4, 4, 120, 56);
|
|
675
|
+
nestedCapture = aura.draw2d.withRenderTarget(probe.target, () => {});
|
|
676
|
+
aura.draw2d.rect(6, 6, 116, 52, aura.rgba(0.14, 0.18, 0.25, 0.95));
|
|
677
|
+
aura.draw2d.rect(10, 38, 96, 10, aura.rgba(0.4, 0.85, 1, 0.7));
|
|
678
|
+
aura.draw2d.text('HP 72 SCORE 1800', 14, 28, { size: 12, color: probe.white });
|
|
679
|
+
offscreenPop = aura.draw2d.popClipRect();
|
|
680
|
+
});
|
|
681
|
+
const bgClip = aura.draw2d.pushClipRect(0, 0, 160, 96);
|
|
682
|
+
aura.draw2d.tileSprite(probe.target, 0, 0, 160, 96, {
|
|
683
|
+
tileScaleX: 1.5,
|
|
684
|
+
tileScaleY: 1.5,
|
|
685
|
+
tileOffsetX: frameIndex * 6,
|
|
686
|
+
tileOffsetY: frameIndex * 3,
|
|
687
|
+
tint: aura.rgba(0.16, 0.2, 0.26, 0.65),
|
|
688
|
+
});
|
|
689
|
+
const bgPop = aura.draw2d.popClipRect();
|
|
690
|
+
aura.draw2d.sprite(probe.target, 12, 14, { width: 192, height: 96 });
|
|
691
|
+
const hudPush = aura.draw2d.pushClipRect(24, 22, 168, 72);
|
|
692
|
+
aura.draw2d.nineSlice(probe.target, 24, 22, 168, 72, {
|
|
693
|
+
slice: 4,
|
|
694
|
+
tint: aura.rgba(0.18, 0.22, 0.3, 0.92),
|
|
695
|
+
});
|
|
696
|
+
aura.draw2d.text('ENERGY', 36, 40, { size: 12, color: probe.white });
|
|
697
|
+
aura.draw2d.tileSprite(probe.target, 36, 52, 120, 10, {
|
|
698
|
+
tileScaleX: 0.3,
|
|
699
|
+
tileScaleY: 0.6,
|
|
700
|
+
tileOffsetX: frameIndex * 2,
|
|
701
|
+
tileOffsetY: 0,
|
|
702
|
+
tint: aura.rgba(0.4, 0.85, 1, 0.7),
|
|
703
|
+
});
|
|
704
|
+
const hudPop = aura.draw2d.popClipRect();
|
|
705
|
+
const state = aura.camera.getState();
|
|
706
|
+
const inspector = aura.debug.inspectorStats();
|
|
707
|
+
probe.frames.push({
|
|
708
|
+
frameIndex,
|
|
709
|
+
bgClip: bgClip?.reasonCode || null,
|
|
710
|
+
bgPop: bgPop?.reasonCode || null,
|
|
711
|
+
invalidClip: invalidClip?.reasonCode || null,
|
|
712
|
+
captureReason: capture?.reasonCode || null,
|
|
713
|
+
captureCommandCount: Number(capture?.commandCount || 0),
|
|
714
|
+
offscreenPush: offscreenPush?.reasonCode || null,
|
|
715
|
+
offscreenPop: offscreenPop?.reasonCode || null,
|
|
716
|
+
nestedCapture: nestedCapture?.reasonCode || null,
|
|
717
|
+
hudPush: hudPush?.reasonCode || null,
|
|
718
|
+
hudPop: hudPop?.reasonCode || null,
|
|
719
|
+
overlayType: state?.overlay?.effectType || null,
|
|
720
|
+
overlayAlpha: state?.overlay ? Number(state.overlay.alpha.toFixed(6)) : null,
|
|
721
|
+
draw2dPendingNumeric: Number.isFinite(Number(inspector?.queues?.draw2dPending)),
|
|
722
|
+
debugOverlayPendingNumeric: Number.isFinite(Number(inspector?.queues?.debugOverlayPending)),
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
if (probe.frames.length < 3) {
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
const frames = Array.isArray(probe.frames) ? probe.frames : [];
|
|
730
|
+
const updates = Array.isArray(probe.updates) ? probe.updates : [];
|
|
731
|
+
const frame0 = frames[0] || {};
|
|
732
|
+
const frame1 = frames[1] || {};
|
|
733
|
+
const frame2 = frames[2] || {};
|
|
734
|
+
const update0 = updates[0] || {};
|
|
735
|
+
const update1 = updates[1] || {};
|
|
736
|
+
const update2 = updates[2] || {};
|
|
737
|
+
const target = probe.target;
|
|
738
|
+
const destroyed = aura.draw2d.destroyRenderTarget(target);
|
|
739
|
+
const missingDestroy = aura.draw2d.destroyRenderTarget(target);
|
|
740
|
+
aura.camera.clearEffects();
|
|
741
|
+
const cleared = aura.camera.getState();
|
|
742
|
+
const evidenceOk = probe.fadeReason === 'camera_fade_started'
|
|
743
|
+
&& target?.ok === true
|
|
744
|
+
&& Number.isInteger(target?.handle)
|
|
745
|
+
&& target.handle > 0
|
|
746
|
+
&& probe.resize?.ok === true
|
|
747
|
+
&& probe.resize?.width === 128
|
|
748
|
+
&& probe.resize?.height === 64
|
|
749
|
+
&& frames.length === 3
|
|
750
|
+
&& updates.length === 3
|
|
751
|
+
&& frame0.bgClip === 'draw2d_clip_pushed'
|
|
752
|
+
&& frame0.bgPop === 'draw2d_clip_popped'
|
|
753
|
+
&& frame0.invalidClip === 'invalid_clip_rect'
|
|
754
|
+
&& frame0.captureReason === 'draw2d_render_target_captured'
|
|
755
|
+
&& frame0.captureCommandCount === 6
|
|
756
|
+
&& frame0.offscreenPush === 'draw2d_clip_pushed'
|
|
757
|
+
&& frame0.offscreenPop === 'draw2d_clip_popped'
|
|
758
|
+
&& frame0.nestedCapture === 'nested_render_target_capture'
|
|
759
|
+
&& frame0.hudPush === 'draw2d_clip_pushed'
|
|
760
|
+
&& frame0.hudPop === 'draw2d_clip_popped'
|
|
761
|
+
&& frame0.overlayType === 'fade'
|
|
762
|
+
&& frame0.overlayAlpha === 0.4
|
|
763
|
+
&& frame0.draw2dPendingNumeric === true
|
|
764
|
+
&& frame0.debugOverlayPendingNumeric === true
|
|
765
|
+
&& frame1.captureReason === 'draw2d_render_target_captured'
|
|
766
|
+
&& frame1.captureCommandCount === 6
|
|
767
|
+
&& frame1.overlayType === 'fade'
|
|
768
|
+
&& frame1.overlayAlpha === 0.7
|
|
769
|
+
&& frame2.captureReason === 'draw2d_render_target_captured'
|
|
770
|
+
&& frame2.captureCommandCount === 6
|
|
771
|
+
&& frame2.overlayType === 'fade'
|
|
772
|
+
&& frame2.overlayAlpha === 0.7
|
|
773
|
+
&& update0.flashReason === null
|
|
774
|
+
&& update0.beforeType === 'fade'
|
|
775
|
+
&& update0.beforeAlpha === 0.1
|
|
776
|
+
&& update0.afterType === 'fade'
|
|
777
|
+
&& update0.afterAlpha === 0.4
|
|
778
|
+
&& update0.stepReason === 'camera_updated'
|
|
779
|
+
&& update1.flashReason === 'camera_flash_started'
|
|
780
|
+
&& update1.beforeType === 'flash'
|
|
781
|
+
&& update1.beforeAlpha === 0.6
|
|
782
|
+
&& update1.afterType === 'fade'
|
|
783
|
+
&& update1.afterAlpha === 0.7
|
|
784
|
+
&& update1.stepReason === 'camera_updated'
|
|
785
|
+
&& update2.flashReason === null
|
|
786
|
+
&& update2.beforeType === 'fade'
|
|
787
|
+
&& update2.beforeAlpha === 0.7
|
|
788
|
+
&& update2.afterType === 'fade'
|
|
789
|
+
&& update2.afterAlpha === 0.7
|
|
790
|
+
&& update2.stepReason === 'camera_updated'
|
|
791
|
+
&& destroyed?.ok === true
|
|
792
|
+
&& destroyed?.reasonCode === 'draw2d_render_target_destroyed'
|
|
793
|
+
&& missingDestroy?.ok === false
|
|
794
|
+
&& missingDestroy?.reasonCode === 'missing_render_target'
|
|
795
|
+
&& cleared?.overlay === null;
|
|
796
|
+
__record(
|
|
797
|
+
'draw2d.product-ui.runtime.evidence',
|
|
798
|
+
evidenceOk,
|
|
799
|
+
evidenceOk ? null : 'draw2d_product_ui_evidence_failed',
|
|
800
|
+
evidenceOk ? null : { frames, updates, destroyed, missingDestroy, cleared },
|
|
801
|
+
);
|
|
802
|
+
} catch (__error) {
|
|
803
|
+
__record('draw2d.product-ui.runtime.evidence', false, __toErrorString(__error));
|
|
804
|
+
}
|
|
805
|
+
__finish();
|
|
806
|
+
};
|
|
807
|
+
`,
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
id: 'draw2d-mask-runtime-native',
|
|
811
|
+
modes: ['native'],
|
|
812
|
+
namespaces: ['draw2d', 'debug'],
|
|
813
|
+
functions: [
|
|
814
|
+
'aura.draw2d.createRenderTarget',
|
|
815
|
+
'aura.draw2d.destroyRenderTarget',
|
|
816
|
+
'aura.draw2d.withRenderTarget',
|
|
817
|
+
'aura.draw2d.withMask',
|
|
818
|
+
'aura.draw2d.circleFill',
|
|
819
|
+
'aura.draw2d.rectFill',
|
|
820
|
+
'aura.draw2d.line',
|
|
821
|
+
'aura.debug.inspectorStats',
|
|
822
|
+
],
|
|
823
|
+
nativeChecks: [
|
|
824
|
+
{
|
|
825
|
+
id: 'draw2d.mask-runtime.surface.methods',
|
|
826
|
+
expression: "(() => ['createRenderTarget','destroyRenderTarget','withRenderTarget','withMask','circleFill','rectFill','line'].every((name) => typeof aura.draw2d?.[name] === 'function') && typeof aura.debug?.inspectorStats === 'function')()",
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
id: 'draw2d.mask-runtime.setup',
|
|
830
|
+
expression: `(() => { try { const white = aura.Color?.WHITE || aura.colors?.white || aura.rgba(1, 1, 1, 1); const maskTarget = aura.draw2d.createRenderTarget(64, 64); globalThis.__draw2dMaskProbe = { maskTarget, frames: [] }; aura.update = function () {}; aura.draw = function () { const probe = globalThis.__draw2dMaskProbe || {}; const frameIndex = Array.isArray(probe.frames) ? probe.frames.length : 0; aura.draw2d.clear(2, 3, 5); let nestedUnsupported = null; const renderTargetCapture = aura.draw2d.withRenderTarget(maskTarget, () => { aura.draw2d.clear(0, 0, 0, 0); aura.draw2d.circleFill(32, 32, 20, white); nestedUnsupported = aura.draw2d.withMask(maskTarget, 0, 0, 8, 8, () => {}); }); const invalidHandle = aura.draw2d.withMask({ type: 'renderTarget', handle: 9999 }, 0, 0, 8, 8, () => {}); let masked = null; if (frameIndex === 0) { masked = aura.draw2d.withMask(maskTarget, 16, 12, 48, 48, () => { aura.draw2d.rectFill(12, 10, 72, 56, aura.rgba(0.18, 0.32, 0.55, 1)); aura.draw2d.line(12, 10, 84, 66, white, 2); }); } const stats = aura.debug.inspectorStats() || {}; const masking = stats.draw2dRuntime?.masking || {}; const queues = stats.queues || {}; probe.frames.push({ frameIndex, renderTargetCapture: renderTargetCapture?.reasonCode || null, nestedUnsupported: nestedUnsupported?.reasonCode || null, invalidHandle: invalidHandle?.reasonCode || null, maskedReason: masked?.reasonCode || null, maskedCommandCount: Number(masked?.commandCount || 0), pendingPassCount: Number(masking.pendingPassCount || 0), lastSubmittedPassCount: Number(masking.lastSubmittedPassCount || 0), lastExecutedPassCount: Number(masking.lastExecutedPassCount || 0), lastSubmittedCommandCount: Number(masking.lastSubmittedCommandCount || 0), lastReasonCode: masking.lastReasonCode || null, lastOk: masking.lastOk === true, queuePending: Number(queues.draw2dMaskPending || 0) }); }; return maskTarget?.ok === true && maskTarget?.type === 'renderTarget' && maskTarget?.__renderTarget === true && Number.isInteger(maskTarget?.handle) && maskTarget.handle > 0; } catch (_) { return false; } })()`,
|
|
831
|
+
},
|
|
832
|
+
],
|
|
833
|
+
nativePostChecks: [
|
|
834
|
+
{
|
|
835
|
+
id: 'draw2d.mask-runtime.evidence',
|
|
836
|
+
expression: `(() => { try { const probe = globalThis.__draw2dMaskProbe || {}; const frames = Array.isArray(probe.frames) ? probe.frames : []; const frame0 = frames[0] || {}; const frame1 = frames[1] || {}; const frame2 = frames[2] || {}; const target = probe.maskTarget; const destroyed = aura.draw2d.destroyRenderTarget(target); const missingDestroy = aura.draw2d.destroyRenderTarget(target); return target?.ok === true && Number.isInteger(target?.handle) && target.handle > 0 && frames.length === 3 && frame0.renderTargetCapture === 'draw2d_render_target_captured' && frame0.nestedUnsupported === 'mask_capture_inside_render_target_unsupported' && frame0.invalidHandle === 'invalid_mask_source_handle' && frame0.maskedReason === 'draw2d_mask_captured' && frame0.maskedCommandCount === 2 && frame0.pendingPassCount === 1 && frame0.queuePending === 1 && frame0.lastSubmittedPassCount === 0 && frame0.lastExecutedPassCount === 0 && frame0.lastSubmittedCommandCount === 0 && frame0.lastReasonCode === 'draw2d_mask_idle' && frame0.lastOk === true && frame1.renderTargetCapture === 'draw2d_render_target_captured' && frame1.maskedReason === null && frame1.pendingPassCount === 0 && frame1.queuePending === 0 && frame1.lastSubmittedPassCount === 1 && frame1.lastExecutedPassCount === 1 && frame1.lastSubmittedCommandCount === 2 && frame1.lastReasonCode === 'draw2d_mask_executed' && frame1.lastOk === true && frame2.renderTargetCapture === 'draw2d_render_target_captured' && frame2.maskedReason === null && frame2.pendingPassCount === 0 && frame2.queuePending === 0 && frame2.lastSubmittedPassCount === 0 && frame2.lastExecutedPassCount === 0 && frame2.lastSubmittedCommandCount === 0 && frame2.lastReasonCode === 'draw2d_mask_idle' && frame2.lastOk === true && destroyed?.ok === true && destroyed?.reasonCode === 'draw2d_render_target_destroyed' && missingDestroy?.ok === false && missingDestroy?.reasonCode === 'missing_render_target'; } catch (_) { return false; } })()`,
|
|
837
|
+
debugExpression: "(() => { try { const stats = aura.debug.inspectorStats() || {}; return { probe: globalThis.__draw2dMaskProbe || null, draw2dRuntime: stats.draw2dRuntime || null, queues: stats.queues || null }; } catch (error) { return { debugError: String(error && error.message ? error.message : error) }; } })()",
|
|
838
|
+
},
|
|
839
|
+
],
|
|
840
|
+
nativeFrames: 3,
|
|
841
|
+
source: `
|
|
842
|
+
globalThis.__draw2dMaskProbe = {
|
|
843
|
+
maskTarget: null,
|
|
844
|
+
frames: [],
|
|
845
|
+
};
|
|
846
|
+
`,
|
|
847
|
+
nativeSource: `
|
|
848
|
+
const __checks = [];
|
|
849
|
+
let __reported = false;
|
|
850
|
+
|
|
851
|
+
function __toErrorString(value) {
|
|
852
|
+
return String(value && value.message ? value.message : value);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
function __record(id, pass, detail, trace = null) {
|
|
856
|
+
const row = { id, pass: !!pass, detail: detail || null };
|
|
857
|
+
if (!row.pass && trace !== null && trace !== undefined) {
|
|
858
|
+
row.trace = trace;
|
|
859
|
+
}
|
|
860
|
+
__checks.push(row);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function __finish() {
|
|
864
|
+
if (__reported) {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const __failedChecks = __checks.filter((check) => !check.pass);
|
|
868
|
+
console.log('__AURA_CONFORMANCE_NATIVE__' + JSON.stringify({
|
|
869
|
+
caseId: 'draw2d-mask-runtime-native',
|
|
870
|
+
ok: __failedChecks.length === 0,
|
|
871
|
+
checks: __checks,
|
|
872
|
+
failed: __failedChecks.length,
|
|
873
|
+
passed: __checks.length - __failedChecks.length,
|
|
874
|
+
runtimeCacheDiagnostics: null,
|
|
875
|
+
runtimeInspectorSnapshot: null,
|
|
876
|
+
}));
|
|
877
|
+
__reported = true;
|
|
878
|
+
if (aura.window && typeof aura.window.close === 'function') {
|
|
879
|
+
aura.window.close();
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
globalThis.__draw2dMaskProbe = {
|
|
884
|
+
maskTarget: null,
|
|
885
|
+
frames: [],
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
aura.setup = function () {
|
|
889
|
+
try {
|
|
890
|
+
const methodsOk = ['createRenderTarget','destroyRenderTarget','withRenderTarget','withMask','circleFill','rectFill','line']
|
|
891
|
+
.every((name) => typeof aura.draw2d?.[name] === 'function')
|
|
892
|
+
&& typeof aura.debug?.inspectorStats === 'function';
|
|
893
|
+
__record('draw2d.mask-runtime.surface.methods', methodsOk, methodsOk ? null : 'required_methods_missing');
|
|
894
|
+
|
|
895
|
+
const maskTarget = aura.draw2d.createRenderTarget(64, 64);
|
|
896
|
+
globalThis.__draw2dMaskProbe = {
|
|
897
|
+
maskTarget,
|
|
898
|
+
frames: [],
|
|
899
|
+
};
|
|
900
|
+
|
|
901
|
+
const setupOk = maskTarget?.ok === true
|
|
902
|
+
&& maskTarget?.type === 'renderTarget'
|
|
903
|
+
&& maskTarget?.__renderTarget === true
|
|
904
|
+
&& Number.isInteger(maskTarget?.handle)
|
|
905
|
+
&& maskTarget.handle > 0;
|
|
906
|
+
__record('draw2d.mask-runtime.setup', setupOk, setupOk ? null : 'draw2d_mask_setup_failed');
|
|
907
|
+
} catch (__error) {
|
|
908
|
+
__record('draw2d.mask-runtime.setup', false, __toErrorString(__error));
|
|
909
|
+
__finish();
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
aura.update = function () {};
|
|
914
|
+
|
|
915
|
+
aura.draw = function () {
|
|
916
|
+
if (__reported) {
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
try {
|
|
920
|
+
const probe = globalThis.__draw2dMaskProbe || {};
|
|
921
|
+
const frameIndex = Array.isArray(probe.frames) ? probe.frames.length : 0;
|
|
922
|
+
const white = aura.Color?.WHITE || aura.colors?.white || aura.rgba(1, 1, 1, 1);
|
|
923
|
+
|
|
924
|
+
aura.draw2d.clear(2, 3, 5);
|
|
925
|
+
let nestedUnsupported = null;
|
|
926
|
+
const renderTargetCapture = aura.draw2d.withRenderTarget(probe.maskTarget, () => {
|
|
927
|
+
aura.draw2d.clear(0, 0, 0, 0);
|
|
928
|
+
aura.draw2d.circleFill(32, 32, 20, white);
|
|
929
|
+
nestedUnsupported = aura.draw2d.withMask(probe.maskTarget, 0, 0, 8, 8, () => {});
|
|
930
|
+
});
|
|
931
|
+
const invalidHandle = aura.draw2d.withMask({ type: 'renderTarget', handle: 9999 }, 0, 0, 8, 8, () => {});
|
|
932
|
+
let masked = null;
|
|
933
|
+
if (frameIndex === 0) {
|
|
934
|
+
masked = aura.draw2d.withMask(probe.maskTarget, 16, 12, 48, 48, () => {
|
|
935
|
+
aura.draw2d.rectFill(12, 10, 72, 56, aura.rgba(0.18, 0.32, 0.55, 1));
|
|
936
|
+
aura.draw2d.line(12, 10, 84, 66, white, 2);
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
const stats = aura.debug.inspectorStats() || {};
|
|
941
|
+
const masking = stats.draw2dRuntime?.masking || {};
|
|
942
|
+
const queues = stats.queues || {};
|
|
943
|
+
probe.frames.push({
|
|
944
|
+
frameIndex,
|
|
945
|
+
renderTargetCapture: renderTargetCapture?.reasonCode || null,
|
|
946
|
+
nestedUnsupported: nestedUnsupported?.reasonCode || null,
|
|
947
|
+
invalidHandle: invalidHandle?.reasonCode || null,
|
|
948
|
+
maskedReason: masked?.reasonCode || null,
|
|
949
|
+
maskedCommandCount: Number(masked?.commandCount || 0),
|
|
950
|
+
pendingPassCount: Number(masking.pendingPassCount || 0),
|
|
951
|
+
lastSubmittedPassCount: Number(masking.lastSubmittedPassCount || 0),
|
|
952
|
+
lastExecutedPassCount: Number(masking.lastExecutedPassCount || 0),
|
|
953
|
+
lastSubmittedCommandCount: Number(masking.lastSubmittedCommandCount || 0),
|
|
954
|
+
lastReasonCode: masking.lastReasonCode || null,
|
|
955
|
+
lastOk: masking.lastOk === true,
|
|
956
|
+
queuePending: Number(queues.draw2dMaskPending || 0),
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
if (probe.frames.length < 3) {
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const frames = Array.isArray(probe.frames) ? probe.frames : [];
|
|
964
|
+
const frame0 = frames[0] || {};
|
|
965
|
+
const frame1 = frames[1] || {};
|
|
966
|
+
const frame2 = frames[2] || {};
|
|
967
|
+
const target = probe.maskTarget;
|
|
968
|
+
const destroyed = aura.draw2d.destroyRenderTarget(target);
|
|
969
|
+
const missingDestroy = aura.draw2d.destroyRenderTarget(target);
|
|
970
|
+
const evidenceOk = target?.ok === true
|
|
971
|
+
&& Number.isInteger(target?.handle)
|
|
972
|
+
&& target.handle > 0
|
|
973
|
+
&& frames.length === 3
|
|
974
|
+
&& frame0.renderTargetCapture === 'draw2d_render_target_captured'
|
|
975
|
+
&& frame0.nestedUnsupported === 'mask_capture_inside_render_target_unsupported'
|
|
976
|
+
&& frame0.invalidHandle === 'invalid_mask_source_handle'
|
|
977
|
+
&& frame0.maskedReason === 'draw2d_mask_captured'
|
|
978
|
+
&& frame0.maskedCommandCount === 2
|
|
979
|
+
&& frame0.pendingPassCount === 1
|
|
980
|
+
&& frame0.queuePending === 1
|
|
981
|
+
&& frame0.lastSubmittedPassCount === 0
|
|
982
|
+
&& frame0.lastExecutedPassCount === 0
|
|
983
|
+
&& frame0.lastSubmittedCommandCount === 0
|
|
984
|
+
&& frame0.lastReasonCode === 'draw2d_mask_idle'
|
|
985
|
+
&& frame0.lastOk === true
|
|
986
|
+
&& frame1.renderTargetCapture === 'draw2d_render_target_captured'
|
|
987
|
+
&& frame1.maskedReason === null
|
|
988
|
+
&& frame1.pendingPassCount === 0
|
|
989
|
+
&& frame1.queuePending === 0
|
|
990
|
+
&& frame1.lastSubmittedPassCount === 1
|
|
991
|
+
&& frame1.lastExecutedPassCount === 1
|
|
992
|
+
&& frame1.lastSubmittedCommandCount === 2
|
|
993
|
+
&& frame1.lastReasonCode === 'draw2d_mask_executed'
|
|
994
|
+
&& frame1.lastOk === true
|
|
995
|
+
&& frame2.renderTargetCapture === 'draw2d_render_target_captured'
|
|
996
|
+
&& frame2.maskedReason === null
|
|
997
|
+
&& frame2.pendingPassCount === 0
|
|
998
|
+
&& frame2.queuePending === 0
|
|
999
|
+
&& frame2.lastSubmittedPassCount === 0
|
|
1000
|
+
&& frame2.lastExecutedPassCount === 0
|
|
1001
|
+
&& frame2.lastSubmittedCommandCount === 0
|
|
1002
|
+
&& frame2.lastReasonCode === 'draw2d_mask_idle'
|
|
1003
|
+
&& frame2.lastOk === true
|
|
1004
|
+
&& destroyed?.ok === true
|
|
1005
|
+
&& destroyed?.reasonCode === 'draw2d_render_target_destroyed'
|
|
1006
|
+
&& missingDestroy?.ok === false
|
|
1007
|
+
&& missingDestroy?.reasonCode === 'missing_render_target';
|
|
1008
|
+
__record(
|
|
1009
|
+
'draw2d.mask-runtime.evidence',
|
|
1010
|
+
evidenceOk,
|
|
1011
|
+
evidenceOk ? null : 'draw2d_mask_runtime_evidence_failed',
|
|
1012
|
+
evidenceOk ? null : { frames, destroyed, missingDestroy, draw2dRuntime: stats.draw2dRuntime || null, queues },
|
|
1013
|
+
);
|
|
1014
|
+
} catch (__error) {
|
|
1015
|
+
__record('draw2d.mask-runtime.evidence', false, __toErrorString(__error));
|
|
1016
|
+
}
|
|
1017
|
+
__finish();
|
|
1018
|
+
};
|
|
1019
|
+
`,
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
id: 'runtime-behavior-native',
|
|
1023
|
+
modes: ['native'],
|
|
1024
|
+
namespaces: ['draw2d', 'audio', 'assets', 'debug', 'storage'],
|
|
1025
|
+
functions: [
|
|
1026
|
+
'aura.draw2d.sprite',
|
|
1027
|
+
'aura.draw2d.text',
|
|
1028
|
+
'aura.draw2d.measureText',
|
|
1029
|
+
'aura.audio.play',
|
|
1030
|
+
'aura.audio.stop',
|
|
1031
|
+
'aura.audio.pause',
|
|
1032
|
+
'aura.audio.resume',
|
|
1033
|
+
'aura.audio.setVolume',
|
|
1034
|
+
'aura.assets.load',
|
|
1035
|
+
'aura.assets.exists',
|
|
1036
|
+
'aura.storage.save',
|
|
1037
|
+
'aura.storage.load',
|
|
1038
|
+
'aura.storage.delete',
|
|
1039
|
+
'aura.debug.log',
|
|
1040
|
+
'aura.debug.drawRect',
|
|
1041
|
+
'aura.debug.drawCircle',
|
|
1042
|
+
'aura.debug.drawText',
|
|
1043
|
+
'aura.debug.enableInspector',
|
|
1044
|
+
'aura.debug.inspectorStats',
|
|
1045
|
+
],
|
|
1046
|
+
nativeChecks: [
|
|
1047
|
+
{
|
|
1048
|
+
id: 'draw2d.measureText.scalesWithSize',
|
|
1049
|
+
expression: "(() => { const small = aura.draw2d.measureText('Hello', { size: 8 }); const large = aura.draw2d.measureText('Hello', { size: 24 }); return Number.isFinite(small.width) && Number.isFinite(large.width) && large.width > small.width && large.height >= small.height; })()",
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
id: 'draw2d.measureText.emptyStringZeroWidth',
|
|
1053
|
+
expression: "(() => { const metrics = aura.draw2d.measureText('', { size: 24 }); return metrics.width === 0 && metrics.height === 0; })()",
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
id: 'draw2d.spriteAndText.acceptCalls',
|
|
1057
|
+
expression: "(() => { try { aura.draw2d.sprite({ path: 'player.png' }, 10, 20, { width: 16 }); aura.draw2d.text('ok', 5, 5, { size: 12, align: 'center', color: aura.rgba(1, 1, 1, 1) }); return true; } catch (_) { return false; } })()",
|
|
1058
|
+
},
|
|
1059
|
+
{
|
|
1060
|
+
id: 'assets.exists.missingIsFalse',
|
|
1061
|
+
expression: "aura.assets.exists('__missing__/ghost.png') === false",
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
id: 'assets.load.missingThrowsDeterministicError',
|
|
1065
|
+
expression: "(() => { try { aura.assets.load('__missing__/ghost.png'); return false; } catch (e) { return String(e).includes('Asset not found: __missing__/ghost.png'); } })()",
|
|
1066
|
+
},
|
|
1067
|
+
{
|
|
1068
|
+
id: 'audio.play.missingAssetThrows',
|
|
1069
|
+
expression: "(() => { try { aura.audio.play('__missing__/ghost.wav'); return false; } catch (e) { return String(e).includes('Asset not found: __missing__/ghost.wav'); } })()",
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
id: 'audio.invalidHandle.noThrow',
|
|
1073
|
+
expression: "(() => { try { aura.audio.stop(-1); aura.audio.pause('x'); aura.audio.resume(99999); aura.audio.setVolume('x', 0.5); return true; } catch (_) { return false; } })()",
|
|
1074
|
+
},
|
|
1075
|
+
{
|
|
1076
|
+
id: 'debug.devHelpers.callable',
|
|
1077
|
+
expression: "(() => { try { aura.debug.log('conformance'); aura.debug.drawRect(1, 2, 3, 4); aura.debug.drawCircle(5, 6, 7); aura.debug.drawText('dbg', 8, 9); return true; } catch (_) { return false; } })()",
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
id: 'debug.inspector.stats-shape',
|
|
1081
|
+
expression: "(() => { try { const enabled = aura.debug.enableInspector(true); const stats = aura.debug.inspectorStats(); const disabled = aura.debug.enableInspector(false); const phase2 = stats.phase2 || {}; const rows = [phase2.animation, phase2.tilemap, phase2.scene3d, phase2.particles]; const phase2Ok = rows.every((row) => row && Number.isFinite(row.active) && Number.isFinite(row.total) && Number.isFinite(row.callbackQueueDepth) && row.active >= 0 && row.total >= 0 && row.callbackQueueDepth >= 0); const scene3dRuntime = stats.scene3dRuntime || {}; const submission = scene3dRuntime.submission || {}; const camera = scene3dRuntime.camera || {}; const resources = scene3dRuntime.resources || {}; const cameraVectorsOk = Number.isFinite(camera.position?.x) && Number.isFinite(camera.position?.y) && Number.isFinite(camera.position?.z) && Number.isFinite(camera.target?.x) && Number.isFinite(camera.target?.y) && Number.isFinite(camera.target?.z); const billboardOk = Number.isFinite(submission.billboardCommandsPending) && Number.isFinite(submission.billboardUniqueTextureHandles) && Number.isFinite(submission.billboardLastCommandCount) && Number.isFinite(submission.billboardLastRenderedCount) && Number.isFinite(submission.billboardLastBatchCount) && typeof submission.billboardLastReasonCode === 'string'; const morphOk = Number.isFinite(submission.morphCandidateDrawCount) && Number.isFinite(submission.morphCustomPipelineDrawCount) && Number.isFinite(submission.morphMissingBufferDrawCount) && Number.isFinite(submission.morphPreparedBindGroupCount) && Number.isFinite(submission.morphExecutedBindGroupCount) && Number.isFinite(submission.morphExecutedMeshCount) && Number.isFinite(submission.morphExecutedNonZeroWeightDrawCount) && Number.isFinite(submission.morphExecutedNonZeroWeightMeshCount) && typeof submission.morphLastReasonCode === 'string' && Number.isFinite(resources.morphTrackedMeshCount) && Number.isFinite(resources.morphPendingUploadCount); const scene3dRuntimeOk = Number.isFinite(submission.drawMeshPending) && Number.isFinite(submission.uniqueMeshHandles) && Number.isFinite(submission.uniqueMaterialHandles) && Number.isFinite(submission.nonDefaultTransforms) && billboardOk && morphOk && typeof submission.skyboxRequested === 'boolean' && typeof submission.clearRequested === 'boolean' && typeof camera.mode === 'string' && camera.mode.length > 0 && Number.isFinite(camera.aspect) && Number.isFinite(camera.fovDegrees) && Number.isFinite(camera.near) && Number.isFinite(camera.far) && cameraVectorsOk && Number.isFinite(resources.meshHandlesRegistered) && Number.isFinite(resources.meshUploadsPending) && Number.isFinite(resources.materialHandlesKnown) && Number.isFinite(resources.materialCommandsPending) && Number.isFinite(resources.lightPointCount) && typeof resources.lightDirectionalActive === 'boolean'; return enabled === true && disabled === false && Number.isFinite(stats.frameCount) && Number.isFinite(stats.frame.fps) && Number.isFinite(stats.frame.deltaSeconds) && Number.isFinite(stats.frame.elapsedSeconds) && Number.isFinite(stats.window.width) && Number.isFinite(stats.window.height) && Number.isFinite(stats.window.pixelRatio) && Number.isFinite(stats.queues.draw2dPending) && Number.isFinite(stats.queues.draw3dPending) && Number.isFinite(stats.queues.debugOverlayPending) && phase2Ok && scene3dRuntimeOk; } catch (_) { return false; } })()",
|
|
1082
|
+
debugExpression: "(() => { try { const enabled = aura.debug.enableInspector(true); const stats = aura.debug.inspectorStats(); const disabled = aura.debug.enableInspector(false); const phase2 = stats.phase2 || {}; const rows = [phase2.animation, phase2.tilemap, phase2.scene3d, phase2.particles]; const phase2Rows = rows.map((row) => ({ present: !!row, active: row?.active, total: row?.total, callbackQueueDepth: row?.callbackQueueDepth })); const phase2Ok = rows.every((row) => row && Number.isFinite(row.active) && Number.isFinite(row.total) && Number.isFinite(row.callbackQueueDepth) && row.active >= 0 && row.total >= 0 && row.callbackQueueDepth >= 0); const scene3dRuntime = stats.scene3dRuntime || {}; const submission = scene3dRuntime.submission || {}; const camera = scene3dRuntime.camera || {}; const resources = scene3dRuntime.resources || {}; const cameraVectorsOk = Number.isFinite(camera.position?.x) && Number.isFinite(camera.position?.y) && Number.isFinite(camera.position?.z) && Number.isFinite(camera.target?.x) && Number.isFinite(camera.target?.y) && Number.isFinite(camera.target?.z); const billboardOk = Number.isFinite(submission.billboardCommandsPending) && Number.isFinite(submission.billboardUniqueTextureHandles) && Number.isFinite(submission.billboardLastCommandCount) && Number.isFinite(submission.billboardLastRenderedCount) && Number.isFinite(submission.billboardLastBatchCount) && typeof submission.billboardLastReasonCode === 'string'; const morphOk = Number.isFinite(submission.morphCandidateDrawCount) && Number.isFinite(submission.morphCustomPipelineDrawCount) && Number.isFinite(submission.morphMissingBufferDrawCount) && Number.isFinite(submission.morphPreparedBindGroupCount) && Number.isFinite(submission.morphExecutedBindGroupCount) && Number.isFinite(submission.morphExecutedMeshCount) && Number.isFinite(submission.morphExecutedNonZeroWeightDrawCount) && Number.isFinite(submission.morphExecutedNonZeroWeightMeshCount) && typeof submission.morphLastReasonCode === 'string' && Number.isFinite(resources.morphTrackedMeshCount) && Number.isFinite(resources.morphPendingUploadCount); const scene3dRuntimeOk = Number.isFinite(submission.drawMeshPending) && Number.isFinite(submission.uniqueMeshHandles) && Number.isFinite(submission.uniqueMaterialHandles) && Number.isFinite(submission.nonDefaultTransforms) && billboardOk && morphOk && typeof submission.skyboxRequested === 'boolean' && typeof submission.clearRequested === 'boolean' && typeof submission.environmentMapConfigured === 'boolean' && Number.isFinite(submission.pointShadowLightCount) && Number.isFinite(submission.spotShadowLightCount) && Number.isFinite(submission.pointShadowPassCount) && Number.isFinite(submission.spotShadowPassCount) && typeof camera.mode === 'string' && camera.mode.length > 0 && Number.isFinite(camera.aspect) && Number.isFinite(camera.fovDegrees) && Number.isFinite(camera.near) && Number.isFinite(camera.far) && cameraVectorsOk && Number.isFinite(resources.meshHandlesRegistered) && Number.isFinite(resources.meshUploadsPending) && Number.isFinite(resources.materialHandlesKnown) && Number.isFinite(resources.materialCommandsPending) && Number.isFinite(resources.lightPointCount) && Number.isFinite(resources.lightSpotCount) && typeof resources.lightDirectionalActive === 'boolean'; return { enabled, disabled, frameCount: stats?.frameCount, frame: stats?.frame || null, window: stats?.window || null, queues: stats?.queues || null, phase2Ok, phase2Rows, scene3dRuntimeOk, cameraMode: camera?.mode, cameraAspect: camera?.aspect, cameraVectorsOk, submission, resources }; } catch (error) { return { traceError: String(error && error.message ? error.message : error) }; } })()",
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
id: 'debug.inspector.scene3d-animation-shape',
|
|
1086
|
+
expression: "(() => { try { aura.debug.enableInspector(true); const stats = aura.debug.inspectorStats(); aura.debug.enableInspector(false); const animation = stats?.scene3dRuntime?.animation || {}; return Number.isFinite(animation.clipCount) && Number.isFinite(animation.playingClipCount) && Number.isFinite(animation.transitionCount) && Number.isFinite(animation.activeWeightSum) && Number.isFinite(animation.loopEventsDispatched) && Number.isFinite(animation.completeEventsDispatched) && Number.isFinite(animation.blendEventsDispatched) && Number.isFinite(animation.skinnedClipCount) && Number.isFinite(animation.totalBoneCount) && Number.isFinite(animation.skinningInfluenceSum) && Number.isFinite(animation.skinningUpdates); } catch (_) { return false; } })()",
|
|
1087
|
+
},
|
|
1088
|
+
{
|
|
1089
|
+
id: 'storage.saveLoadDelete.roundTrip',
|
|
1090
|
+
expression: "(() => { const key = '__conformance_roundtrip__'; aura.storage.save(key, { score: 99 }); const loaded = aura.storage.load(key); const listed = aura.storage.keys(); aura.storage.delete(key); return !!loaded && loaded.score === 99 && Array.isArray(listed) && listed.includes(key) && aura.storage.load(key) === null; })()",
|
|
1091
|
+
},
|
|
1092
|
+
{
|
|
1093
|
+
id: 'optional.modules.steam.not-exposed',
|
|
1094
|
+
expression: "typeof aura.steam === 'undefined' && !Object.prototype.hasOwnProperty.call(aura, 'steam')",
|
|
1095
|
+
},
|
|
1096
|
+
],
|
|
1097
|
+
nativeFrames: 2,
|
|
1098
|
+
source: `
|
|
1099
|
+
aura.setup = function () {};
|
|
1100
|
+
`,
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
id: 'audio-mixer-fade-bus-controls',
|
|
1104
|
+
modes: ['shim', 'native'],
|
|
1105
|
+
namespaces: ['audio', 'assets'],
|
|
1106
|
+
functions: [
|
|
1107
|
+
'aura.audio.setBusVolume',
|
|
1108
|
+
'aura.audio.assignBus',
|
|
1109
|
+
'aura.audio.fadeTrack',
|
|
1110
|
+
'aura.audio.fadeBus',
|
|
1111
|
+
'aura.audio.crossfade',
|
|
1112
|
+
'aura.audio.update',
|
|
1113
|
+
'aura.audio.clearEnvelopes',
|
|
1114
|
+
'aura.audio.getMixerState',
|
|
1115
|
+
],
|
|
1116
|
+
nativeChecks: [
|
|
1117
|
+
{
|
|
1118
|
+
id: 'audio.mixer.surface.methods',
|
|
1119
|
+
expression: "(() => ['setBusVolume','assignBus','fadeTrack','fadeBus','crossfade','update','clearEnvelopes','getMixerState'].every((name) => typeof aura.audio?.[name] === 'function'))()",
|
|
1120
|
+
},
|
|
1121
|
+
{
|
|
1122
|
+
id: 'audio.mixer.reason-codes.deterministic',
|
|
1123
|
+
expression: "(() => { const runSample = () => { const invalidBus = aura.audio.setBusVolume('', 0.5); const invalidTrackHandle = aura.audio.fadeTrack('oops', { to: 0.2, duration: 0.5 }); const missingTrack = aura.audio.fadeTrack(999999, { to: 0.2, duration: 0.5 }); const missingBus = aura.audio.fadeBus('missing', { to: 0.2, duration: 0.5 }); const invalidDt = aura.audio.update(0); return { invalidBus: invalidBus?.reasonCode || null, invalidTrackHandle: invalidTrackHandle?.reasonCode || null, missingTrack: missingTrack?.reasonCode || null, missingBus: missingBus?.reasonCode || null, invalidDt: invalidDt?.reasonCode || null }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.invalidBus === 'invalid_bus' && first.invalidTrackHandle === 'invalid_track_handle' && first.missingTrack === 'missing_track' && first.missingBus === 'missing_bus' && first.invalidDt === 'invalid_dt'; })()",
|
|
1124
|
+
},
|
|
1125
|
+
],
|
|
1126
|
+
frames: 1,
|
|
1127
|
+
nativeFrames: 1,
|
|
1128
|
+
source: `
|
|
1129
|
+
aura.setup = async function () {
|
|
1130
|
+
if (aura.assets && typeof aura.assets.load === 'function') {
|
|
1131
|
+
await aura.assets.load(['coin.wav']);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
const runSample = () => {
|
|
1135
|
+
const h1 = aura.audio.play('coin.wav', { volume: 1, bus: 'music' });
|
|
1136
|
+
const h2 = aura.audio.play('coin.wav', { volume: 1, bus: 'sfx' });
|
|
1137
|
+
const h3 = aura.audio.play('coin.wav', { volume: 0.5, bus: 'music' });
|
|
1138
|
+
|
|
1139
|
+
const invalidBus = aura.audio.setBusVolume('', 0.5);
|
|
1140
|
+
const invalidTrackHandle = aura.audio.fadeTrack('oops', { to: 0.2, duration: 0.5 });
|
|
1141
|
+
const missingTrack = aura.audio.fadeTrack(999999, { to: 0.2, duration: 0.5 });
|
|
1142
|
+
const missingBus = aura.audio.fadeBus('missing', { to: 0.2, duration: 0.5 });
|
|
1143
|
+
|
|
1144
|
+
const setMusic = aura.audio.setBusVolume('music', 0.6);
|
|
1145
|
+
const setSfx = aura.audio.setBusVolume('sfx', 0.8);
|
|
1146
|
+
const moveTrack = aura.audio.assignBus(h2, 'music');
|
|
1147
|
+
const fadeTrack = aura.audio.fadeTrack(h3, { to: 0.1, duration: 0.5 });
|
|
1148
|
+
const fadeBus = aura.audio.fadeBus('music', { to: 0.4, duration: 0.5 });
|
|
1149
|
+
const crossfade = aura.audio.crossfade(h1, h2, { duration: 0.5, toStartVolume: 0, toVolume: 0.9, stopFrom: true });
|
|
1150
|
+
|
|
1151
|
+
const stepA = aura.audio.update(0.25);
|
|
1152
|
+
const stateA = aura.audio.getMixerState();
|
|
1153
|
+
const invalidDt = aura.audio.update(0);
|
|
1154
|
+
const stepB = aura.audio.update(0.25);
|
|
1155
|
+
const stateB = aura.audio.getMixerState();
|
|
1156
|
+
const cleared = aura.audio.clearEnvelopes();
|
|
1157
|
+
|
|
1158
|
+
const musicBus = stateB && Array.isArray(stateB.buses)
|
|
1159
|
+
? stateB.buses.find((entry) => entry.bus === 'music')
|
|
1160
|
+
: null;
|
|
1161
|
+
const trackTwo = stateB && Array.isArray(stateB.tracks)
|
|
1162
|
+
? stateB.tracks.find((entry) => entry.handle === h2)
|
|
1163
|
+
: null;
|
|
1164
|
+
const trackThree = stateB && Array.isArray(stateB.tracks)
|
|
1165
|
+
? stateB.tracks.find((entry) => entry.handle === h3)
|
|
1166
|
+
: null;
|
|
1167
|
+
|
|
1168
|
+
const snapshot = {
|
|
1169
|
+
invalidBus: invalidBus && invalidBus.reasonCode,
|
|
1170
|
+
invalidTrackHandle: invalidTrackHandle && invalidTrackHandle.reasonCode,
|
|
1171
|
+
missingTrack: missingTrack && missingTrack.reasonCode,
|
|
1172
|
+
missingBus: missingBus && missingBus.reasonCode,
|
|
1173
|
+
setMusicOk: !!setMusic && setMusic.ok === true,
|
|
1174
|
+
setSfxOk: !!setSfx && setSfx.ok === true,
|
|
1175
|
+
moveTrackOk: !!moveTrack && moveTrack.ok === true,
|
|
1176
|
+
fadeTrackOk: !!fadeTrack && fadeTrack.ok === true,
|
|
1177
|
+
fadeBusOk: !!fadeBus && fadeBus.ok === true,
|
|
1178
|
+
crossfadeOk: !!crossfade && crossfade.ok === true,
|
|
1179
|
+
stepAOk: !!stepA && stepA.ok === true,
|
|
1180
|
+
stepBOk: !!stepB && stepB.ok === true,
|
|
1181
|
+
invalidDt: invalidDt && invalidDt.reasonCode,
|
|
1182
|
+
stateAEnvelopes: stateA && Array.isArray(stateA.envelopes) ? stateA.envelopes.length : -1,
|
|
1183
|
+
stateBEnvelopes: stateB && Array.isArray(stateB.envelopes) ? stateB.envelopes.length : -1,
|
|
1184
|
+
stateBTracks: stateB && Array.isArray(stateB.tracks) ? stateB.tracks.length : -1,
|
|
1185
|
+
musicBusVolume: musicBus ? Number(musicBus.volume.toFixed(6)) : null,
|
|
1186
|
+
trackTwoVolume: trackTwo ? Number(trackTwo.effectiveVolume.toFixed(6)) : null,
|
|
1187
|
+
trackThreeVolume: trackThree ? Number(trackThree.effectiveVolume.toFixed(6)) : null,
|
|
1188
|
+
cleared: cleared && cleared.cleared,
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
aura.audio.stopAll();
|
|
1192
|
+
return JSON.stringify(snapshot);
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1195
|
+
const first = runSample();
|
|
1196
|
+
const second = runSample();
|
|
1197
|
+
aura.test.equal(first, second, 'audio mixer sample must be deterministic across reruns');
|
|
1198
|
+
|
|
1199
|
+
const parsed = JSON.parse(first);
|
|
1200
|
+
aura.test.equal(parsed.invalidBus, 'invalid_bus', 'invalid bus should be reason-coded');
|
|
1201
|
+
aura.test.equal(parsed.invalidTrackHandle, 'invalid_track_handle', 'invalid track handle should be reason-coded');
|
|
1202
|
+
aura.test.equal(parsed.missingTrack, 'missing_track', 'missing track should be reason-coded');
|
|
1203
|
+
aura.test.equal(parsed.missingBus, 'missing_bus', 'missing bus should be reason-coded');
|
|
1204
|
+
aura.test.equal(parsed.invalidDt, 'invalid_dt', 'invalid dt should be reason-coded');
|
|
1205
|
+
aura.test.assert(parsed.setMusicOk && parsed.setSfxOk && parsed.moveTrackOk, 'bus transitions should succeed');
|
|
1206
|
+
aura.test.assert(parsed.fadeTrackOk && parsed.fadeBusOk && parsed.crossfadeOk, 'fade helpers should succeed');
|
|
1207
|
+
aura.test.assert(parsed.stepAOk && parsed.stepBOk, 'audio update steps should succeed');
|
|
1208
|
+
aura.test.equal(parsed.stateAEnvelopes, 4, 'mid-step should retain all envelopes');
|
|
1209
|
+
aura.test.equal(parsed.stateBEnvelopes, 0, 'final step should complete envelopes');
|
|
1210
|
+
aura.test.equal(parsed.stateBTracks, 2, 'crossfade should stop source track after completion');
|
|
1211
|
+
aura.test.equal(parsed.musicBusVolume, 0.4, 'music bus should settle at deterministic target');
|
|
1212
|
+
aura.test.equal(parsed.trackTwoVolume, 0.36, 'crossfade target track effective volume should be deterministic');
|
|
1213
|
+
aura.test.equal(parsed.trackThreeVolume, 0.04, 'faded track effective volume should be deterministic');
|
|
1214
|
+
aura.test.equal(parsed.cleared, 0, 'clearEnvelopes should report zero after completion');
|
|
1215
|
+
};
|
|
1216
|
+
`,
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
id: 'tilemap-query-bridge',
|
|
1220
|
+
namespaces: ['tilemap'],
|
|
1221
|
+
functions: [
|
|
1222
|
+
'aura.tilemap.queryPoint',
|
|
1223
|
+
'aura.tilemap.queryAABB',
|
|
1224
|
+
'aura.tilemap.queryRay',
|
|
1225
|
+
'aura.tilemap.queryRaycast',
|
|
1226
|
+
],
|
|
1227
|
+
nativeChecks: [
|
|
1228
|
+
{ id: 'tilemap.queryPoint', expression: "typeof aura.tilemap?.queryPoint === 'function'" },
|
|
1229
|
+
{ id: 'tilemap.queryAABB', expression: "typeof aura.tilemap?.queryAABB === 'function'" },
|
|
1230
|
+
{ id: 'tilemap.queryRay', expression: "typeof aura.tilemap?.queryRay === 'function'" },
|
|
1231
|
+
{ id: 'tilemap.queryRaycast', expression: "typeof aura.tilemap?.queryRaycast === 'function'" },
|
|
1232
|
+
{ id: 'tilemap.query.invalid-handle.reason-code', expression: "(() => { const result = aura.tilemap.queryPoint(999999, { x: 0, y: 0 }); return result && result.ok === false && result.reasonCode === 'invalid_map_handle'; })()" },
|
|
1233
|
+
{
|
|
1234
|
+
id: 'tilemap.query.reason-codes.expanded',
|
|
1235
|
+
expression: "(() => { const runSample = () => { const fixture = { width: 2, height: 2, tilewidth: 16, tileheight: 16, layers: [ { name: 'ground', type: 'tilelayer', width: 2, height: 2, data: [1, 0, 0, 0], properties: { solid: true } } ], tilesets: [ { firstgid: 1, image: 'tiles.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 } ] }; const mapId = aura.tilemap.import(fixture); const invalidPoint = aura.tilemap.queryPoint(mapId, { x: 'bad', y: 0 }); const invalidAabb = aura.tilemap.queryAABB(mapId, { x: 0, y: 0, w: 0, h: 1 }); const invalidRay = aura.tilemap.queryRay(mapId, { x: 0, y: 0, dx: 0, dy: 0, maxDistance: 10 }); const invalidModel = aura.tilemap.queryPoint({ width: 4 }, 1, 1); const invalidHandle = aura.tilemap.queryPoint(999999, { x: 0, y: 0 }); let threw = false; try { aura.tilemap.queryRay(mapId, { x: 0, y: 0, dx: 'bad', dy: 0, maxDistance: 10 }); } catch (_) { threw = true; } aura.tilemap.unload(mapId); return { invalidPoint: invalidPoint?.reasonCode || null, invalidAabb: invalidAabb?.reasonCode || null, invalidRay: invalidRay?.reasonCode || null, invalidModel: invalidModel?.reasonCode || null, invalidHandle: invalidHandle?.reasonCode || null, threw }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.invalidPoint === 'invalid_point_args' && first.invalidAabb === 'invalid_aabb_args' && first.invalidRay === 'invalid_ray_args' && first.invalidModel === 'invalid_model' && first.invalidHandle === 'invalid_map_handle' && first.threw === false; })()",
|
|
1236
|
+
},
|
|
1237
|
+
{
|
|
1238
|
+
id: 'tilemap.query.model-schema.deterministic',
|
|
1239
|
+
expression: "(() => { const runSample = () => { const model = { width: 2, height: 2, tilewidth: 16, tileheight: 16, solidLayerNames: ['solid'], layers: [ { name: 'solid', width: 2, height: 2, data: [1, 0, 0, 0], properties: { solid: true } }, { name: 'dynamic', width: 2, height: 2, data: [0, 1, 0, 0], queryEnabled: true } ], solidCells: [ { x: 1, y: 0, layerIndex: 5, layerName: 'manual' }, { x: 1, y: 0, layerIndex: 5, layerName: 'manual' } ] }; const point = aura.tilemap.queryPoint(model, { x: 16.5, y: 0.5 }); const aabb = aura.tilemap.queryAABB(model, { x: 0, y: 0, w: 32, h: 16 }); const ray = aura.tilemap.queryRay(model, { x: 0.5, y: 0.5, dx: 1, dy: 0, maxDistance: 64 }); return { pointLayers: Array.isArray(point?.hits) ? point.hits.map((hit) => hit.layerIndex).join(',') : '', aabbLayers: Array.isArray(aabb?.hits) ? aabb.hits.map((hit) => hit.layerIndex).join(',') : '', rayLayer: Number(ray?.hitCell?.layerIndex ?? -1), pointOk: point?.ok === true, aabbOk: aabb?.ok === true, rayOk: ray?.ok === true, pointHit: point?.hit === true, aabbHit: aabb?.hit === true, rayHit: ray?.hit === true, invalidModelReason: aura.tilemap.queryPoint({ width: 2 }, { x: 0, y: 0 })?.reasonCode, invalidAabbReason: aura.tilemap.queryAABB(model, { x: 0, y: 0, w: 0, h: 1 })?.reasonCode }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.pointOk === true && first.aabbOk === true && first.rayOk === true && first.pointHit === true && first.aabbHit === true && first.rayHit === true && first.pointLayers === '1,5' && first.aabbLayers === '0,1,5' && first.rayLayer === 0 && first.invalidModelReason === 'invalid_model' && first.invalidAabbReason === 'invalid_aabb_args'; })()",
|
|
1240
|
+
},
|
|
1241
|
+
],
|
|
1242
|
+
frames: 1,
|
|
1243
|
+
source: `
|
|
1244
|
+
aura.setup = function () {
|
|
1245
|
+
const mkLayer = (name, hits) => {
|
|
1246
|
+
const data = new Array(16).fill(0);
|
|
1247
|
+
for (const [x, y] of hits) data[(y * 4) + x] = 1;
|
|
1248
|
+
return {
|
|
1249
|
+
name,
|
|
1250
|
+
type: 'tilelayer',
|
|
1251
|
+
width: 4,
|
|
1252
|
+
height: 4,
|
|
1253
|
+
data,
|
|
1254
|
+
properties: { solid: name.startsWith('walls-') },
|
|
1255
|
+
};
|
|
1256
|
+
};
|
|
1257
|
+
const fixture = {
|
|
1258
|
+
width: 4,
|
|
1259
|
+
height: 4,
|
|
1260
|
+
tilewidth: 16,
|
|
1261
|
+
tileheight: 16,
|
|
1262
|
+
solidLayerNames: ['walls-a', 'walls-b'],
|
|
1263
|
+
layers: [
|
|
1264
|
+
mkLayer('ground', [[0, 0], [3, 3]]),
|
|
1265
|
+
mkLayer('walls-a', [[1, 1], [2, 1]]),
|
|
1266
|
+
mkLayer('walls-b', [[1, 1]]),
|
|
1267
|
+
],
|
|
1268
|
+
tilesets: [
|
|
1269
|
+
{ firstgid: 1, image: 'tiles.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 },
|
|
1270
|
+
],
|
|
1271
|
+
};
|
|
1272
|
+
const mapHandle = aura.tilemap.import(fixture);
|
|
1273
|
+
|
|
1274
|
+
const point = aura.tilemap.queryPoint(mapHandle, { x: 16.5, y: 16.5 });
|
|
1275
|
+
const pointRepeat = aura.tilemap.queryPoint(mapHandle, { x: 16.5, y: 16.5 });
|
|
1276
|
+
const aabb = aura.tilemap.queryAABB(mapHandle, { x: 0, y: 0, w: 48, h: 32 });
|
|
1277
|
+
const ray = aura.tilemap.queryRay(mapHandle, { x: 0.5, y: 16.5, dx: 1, dy: 0, maxDistance: 96 });
|
|
1278
|
+
const rayAlias = aura.tilemap.queryRaycast(mapHandle, { x: 0.5, y: 16.5, dx: 1, dy: 0, maxDistance: 96 });
|
|
1279
|
+
|
|
1280
|
+
aura.test.assert(point && point.ok === true && point.hit === true, 'tilemap point query should hit');
|
|
1281
|
+
aura.test.assert(Array.isArray(point.hits) && point.hits.length === 2, 'tilemap point should return deterministic layered hits');
|
|
1282
|
+
aura.test.assert(point.hits[0].layerIndex === 1 && point.hits[1].layerIndex === 2, 'tilemap point ordering should be deterministic');
|
|
1283
|
+
aura.test.assert(JSON.stringify(point.hits) === JSON.stringify(pointRepeat.hits), 'tilemap point ordering should be stable across reruns');
|
|
1284
|
+
|
|
1285
|
+
aura.test.assert(aabb && aabb.ok === true && aabb.hit === true, 'tilemap aabb query should hit');
|
|
1286
|
+
aura.test.assert(Array.isArray(aabb.hits) && aabb.hits.length === 3, 'tilemap aabb should include deterministic hit set');
|
|
1287
|
+
aura.test.assert(aabb.hits[0].layerIndex === 1 && aabb.hits[0].x === 1 && aabb.hits[0].y === 1, 'tilemap aabb hit ordering start');
|
|
1288
|
+
aura.test.assert(aabb.hits[1].layerIndex === 1 && aabb.hits[1].x === 2 && aabb.hits[1].y === 1, 'tilemap aabb hit ordering middle');
|
|
1289
|
+
aura.test.assert(aabb.hits[2].layerIndex === 2 && aabb.hits[2].x === 1 && aabb.hits[2].y === 1, 'tilemap aabb hit ordering end');
|
|
1290
|
+
|
|
1291
|
+
aura.test.assert(ray && ray.ok === true && ray.hit === true && ray.hitCell && ray.hitCell.x === 1 && ray.hitCell.y === 1, 'tilemap ray query should return first deterministic hit');
|
|
1292
|
+
aura.test.assert(rayAlias && rayAlias.ok === true && rayAlias.hit === true && rayAlias.hitCell && rayAlias.hitCell.x === ray.hitCell.x && rayAlias.hitCell.y === ray.hitCell.y, 'tilemap ray alias should match queryRay');
|
|
1293
|
+
|
|
1294
|
+
const invalidPoint = aura.tilemap.queryPoint(mapHandle, { x: 'bad', y: 0 });
|
|
1295
|
+
const invalidAabb = aura.tilemap.queryAABB(mapHandle, { x: 0, y: 0, w: 0, h: 1 });
|
|
1296
|
+
const invalidRay = aura.tilemap.queryRay(mapHandle, { x: 0, y: 0, dx: 0, dy: 0, maxDistance: 10 });
|
|
1297
|
+
const invalidHandle = aura.tilemap.queryPoint(999999, { x: 0, y: 0 });
|
|
1298
|
+
const invalidModel = aura.tilemap.queryPoint({ width: 4 }, 1, 1);
|
|
1299
|
+
const unloadResult = aura.tilemap.unload(mapHandle);
|
|
1300
|
+
|
|
1301
|
+
aura.test.assert(invalidPoint && invalidPoint.ok === false && invalidPoint.reasonCode === 'invalid_point_args', 'tilemap invalid point input should be reason-coded');
|
|
1302
|
+
aura.test.assert(invalidAabb && invalidAabb.ok === false && invalidAabb.reasonCode === 'invalid_aabb_args', 'tilemap invalid aabb input should be reason-coded');
|
|
1303
|
+
aura.test.assert(invalidRay && invalidRay.ok === false && invalidRay.reasonCode === 'invalid_ray_args', 'tilemap invalid ray input should be reason-coded');
|
|
1304
|
+
aura.test.assert(invalidHandle && invalidHandle.ok === false && invalidHandle.reasonCode === 'invalid_map_handle', 'tilemap invalid handle should be reason-coded');
|
|
1305
|
+
aura.test.assert(invalidModel && invalidModel.ok === false && invalidModel.reasonCode === 'invalid_model', 'tilemap invalid model should be reason-coded');
|
|
1306
|
+
aura.test.assert(unloadResult === true, 'tilemap handle should unload cleanly after query checks');
|
|
1307
|
+
};
|
|
1308
|
+
`,
|
|
1309
|
+
},
|
|
1310
|
+
{
|
|
1311
|
+
id: 'tilemap-runtime-mutation-layer-controls',
|
|
1312
|
+
modes: ['shim', 'native'],
|
|
1313
|
+
namespaces: ['tilemap'],
|
|
1314
|
+
functions: [
|
|
1315
|
+
'aura.tilemap.setTile',
|
|
1316
|
+
'aura.tilemap.setRegion',
|
|
1317
|
+
'aura.tilemap.removeRegion',
|
|
1318
|
+
'aura.tilemap.replaceRegion',
|
|
1319
|
+
'aura.tilemap.setTileCollision',
|
|
1320
|
+
'aura.tilemap.setLayerFlags',
|
|
1321
|
+
'aura.tilemap.setLayerVisibility',
|
|
1322
|
+
'aura.tilemap.setLayerCollision',
|
|
1323
|
+
'aura.tilemap.queryObjects',
|
|
1324
|
+
'aura.tilemap.queryObjectsAtPoint',
|
|
1325
|
+
'aura.tilemap.queryObjectsInAABB',
|
|
1326
|
+
],
|
|
1327
|
+
nativeChecks: [
|
|
1328
|
+
{ id: 'tilemap.mutation.setTile', expression: "typeof aura.tilemap?.setTile === 'function'" },
|
|
1329
|
+
{ id: 'tilemap.mutation.setRegion', expression: "typeof aura.tilemap?.setRegion === 'function'" },
|
|
1330
|
+
{ id: 'tilemap.mutation.removeRegion', expression: "typeof aura.tilemap?.removeRegion === 'function'" },
|
|
1331
|
+
{ id: 'tilemap.mutation.replaceRegion', expression: "typeof aura.tilemap?.replaceRegion === 'function'" },
|
|
1332
|
+
{ id: 'tilemap.mutation.setTileCollision', expression: "typeof aura.tilemap?.setTileCollision === 'function'" },
|
|
1333
|
+
{ id: 'tilemap.layer.setLayerFlags', expression: "typeof aura.tilemap?.setLayerFlags === 'function'" },
|
|
1334
|
+
{ id: 'tilemap.layer.setLayerVisibility', expression: "typeof aura.tilemap?.setLayerVisibility === 'function'" },
|
|
1335
|
+
{ id: 'tilemap.layer.setLayerCollision', expression: "typeof aura.tilemap?.setLayerCollision === 'function'" },
|
|
1336
|
+
{ id: 'tilemap.query.queryObjects', expression: "typeof aura.tilemap?.queryObjects === 'function'" },
|
|
1337
|
+
{ id: 'tilemap.query.queryObjectsAtPoint', expression: "typeof aura.tilemap?.queryObjectsAtPoint === 'function'" },
|
|
1338
|
+
{ id: 'tilemap.query.queryObjectsInAABB', expression: "typeof aura.tilemap?.queryObjectsInAABB === 'function'" },
|
|
1339
|
+
{
|
|
1340
|
+
id: 'tilemap.mutation.reason-codes.expanded',
|
|
1341
|
+
expression: "(() => { const runSample = () => { const fixture = { width: 2, height: 2, tilewidth: 16, tileheight: 16, layers: [ { name: 'ground', type: 'tilelayer', width: 2, height: 2, data: [1, 1, 1, 1] } ], tilesets: [ { firstgid: 1, image: 'tiles-a.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 }, { firstgid: 5, image: 'tiles-b.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 } ] }; const mapId = aura.tilemap.import(fixture); const invalidGidArgs = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 'bad'); const unmappedBoundary = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 2); const validBoundary = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 5); const invalidReplaceArgs = aura.tilemap.replaceRegion(mapId, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 1, 'bad'); const invalidLayerFlags = aura.tilemap.setLayerFlags(mapId, 'ground', {}); const invalidVisibility = aura.tilemap.setLayerVisibility(mapId, 'ground', 'yes'); const invalidCollision = aura.tilemap.setLayerCollision(mapId, 'ground', 'yes'); const invalidLayer = aura.tilemap.removeRegion(mapId, 'missing', { x: 0, y: 0, w: 1, h: 1 }); const invalidHandle = aura.tilemap.setRegion(999999, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 1); aura.tilemap.unload(mapId); return { invalidGidArgs: invalidGidArgs?.reasonCode, unmappedBoundary: unmappedBoundary?.reasonCode, validBoundaryOk: validBoundary?.ok === true, validBoundaryChanged: Number(validBoundary?.changedTiles || 0), invalidReplaceArgs: invalidReplaceArgs?.reasonCode, invalidLayerFlags: invalidLayerFlags?.reasonCode, invalidVisibility: invalidVisibility?.reasonCode, invalidCollision: invalidCollision?.reasonCode, invalidLayer: invalidLayer?.reasonCode, invalidHandle: invalidHandle?.reasonCode }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.invalidGidArgs === 'invalid_gid_args' && first.unmappedBoundary === 'unmapped_layer_gid' && first.validBoundaryOk === true && first.validBoundaryChanged === 1 && first.invalidReplaceArgs === 'invalid_replace_args' && first.invalidLayerFlags === 'invalid_layer_flags' && first.invalidVisibility === 'invalid_visibility_flag' && first.invalidCollision === 'invalid_collision_flag' && first.invalidLayer === 'invalid_layer_ref' && first.invalidHandle === 'invalid_map_handle'; })()",
|
|
1342
|
+
},
|
|
1343
|
+
{
|
|
1344
|
+
id: 'tilemap.mutation.layer-controls.deterministic',
|
|
1345
|
+
expression: "(() => { const runSample = () => { const fixture = { width: 4, height: 4, tilewidth: 16, tileheight: 16, solidLayerNames: ['ground', 'hazards'], layers: [ { name: 'ground', type: 'tilelayer', width: 4, height: 4, data: Array.from({ length: 16 }, () => 1) }, { name: 'hazards', type: 'tilelayer', width: 4, height: 4, data: [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] } ], tilesets: [ { firstgid: 1, image: 'tiles.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 } ] }; const mapId = aura.tilemap.import(fixture); const initial = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const setRegion = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 2, h: 1 }, 0); const topRow = aura.tilemap.queryAABB(mapId, { x: 0, y: 0, w: 32, h: 16 }); const removeRegion = aura.tilemap.removeRegion(mapId, 'hazards', { x: 1, y: 1, w: 1, h: 1 }); const afterRemove = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const replaceRegion = aura.tilemap.replaceRegion(mapId, 'ground', { x: 1, y: 1, w: 1, h: 1 }, 1, 0); const afterReplace = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const collisionOff = aura.tilemap.setLayerCollision(mapId, 'ground', false); const hazardsPoint = aura.tilemap.queryPoint(mapId, { x: 32.5, y: 16.5 }); const visibilityOff = aura.tilemap.setLayerVisibility(mapId, 'hazards', false); const hiddenDraw = aura.tilemap.draw(mapId, { cull: false }); const flags = aura.tilemap.setLayerFlags(mapId, 'hazards', { visible: true, collision: false }); const shownDraw = aura.tilemap.draw(mapId, { cull: false }); const queryMuted = aura.tilemap.queryPoint(mapId, { x: 32.5, y: 16.5 }); const groundCollisionOn = aura.tilemap.setLayerFlags(mapId, 'ground', { collision: true }); const hazardsCollisionOn = aura.tilemap.setLayerCollision(mapId, 'hazards', true); const queryRestored = aura.tilemap.queryPoint(mapId, { x: 32.5, y: 16.5 }); const invalidRegion = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 0, h: 1 }, 1); const invalidGid = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 999); const invalidFlags = aura.tilemap.setLayerFlags(mapId, 'ground', { collision: 'yes' }); const invalidLayer = aura.tilemap.setLayerVisibility(mapId, 'missing', true); aura.tilemap.unload(mapId); return { initialHits: Array.isArray(initial?.hits) ? initial.hits.length : -1, topRowHits: Array.isArray(topRow?.hits) ? topRow.hits.length : -1, afterRemoveHits: Array.isArray(afterRemove?.hits) ? afterRemove.hits.length : -1, afterReplaceHits: Array.isArray(afterReplace?.hits) ? afterReplace.hits.length : -1, hazardsHits: Array.isArray(hazardsPoint?.hits) ? hazardsPoint.hits.length : -1, queryMutedHits: Array.isArray(queryMuted?.hits) ? queryMuted.hits.length : -1, queryRestoredHits: Array.isArray(queryRestored?.hits) ? queryRestored.hits.length : -1, setChanged: setRegion?.changedTiles, removeChanged: removeRegion?.changedTiles, replaceChanged: replaceRegion?.changedTiles, collisionOff: collisionOff?.collision, visibilityOff: visibilityOff?.visible, hiddenOrder: hiddenDraw?.layerOrder?.join(','), shownOrder: shownDraw?.layerOrder?.join(','), flagsVisible: flags?.visible, flagsCollision: flags?.collision, groundCollisionOn: groundCollisionOn?.collision, hazardsCollisionOn: hazardsCollisionOn?.collision, invalidRegion: invalidRegion?.reasonCode, invalidGid: invalidGid?.reasonCode, invalidFlags: invalidFlags?.reasonCode, invalidLayer: invalidLayer?.reasonCode }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.initialHits === 2 && first.topRowHits === 0 && first.afterRemoveHits === 1 && first.afterReplaceHits === 0 && first.hazardsHits === 1 && first.queryMutedHits === 0 && first.queryRestoredHits === 2 && first.setChanged === 2 && first.removeChanged === 1 && first.replaceChanged === 1 && first.collisionOff === false && first.visibilityOff === false && first.hiddenOrder === 'ground' && first.shownOrder === 'ground,hazards' && first.flagsVisible === true && first.flagsCollision === false && first.groundCollisionOn === true && first.hazardsCollisionOn === true && first.invalidRegion === 'invalid_region_args' && first.invalidGid === 'unmapped_layer_gid' && first.invalidFlags === 'invalid_collision_flag' && first.invalidLayer === 'invalid_layer_ref'; })()",
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
id: 'tilemap.object-query-and-tile-mutation.expanded.deterministic',
|
|
1349
|
+
expression: "(() => { const runSample = () => { const fixture = { width: 4, height: 4, tilewidth: 16, tileheight: 16, layers: [ { name: 'ground', type: 'tilelayer', width: 4, height: 4, data: [1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], properties: { solid: true } }, { name: 'objects-main', type: 'objectgroup', objects: [ { id: 1, name: 'spawn', type: 'spawn', class: 'player', x: 16, y: 16, point: true, properties: { team: 'blue' } }, { id: 2, name: 'coin', type: 'pickup', x: 32, y: 16, width: 16, height: 16, properties: { kind: 'coin', value: 5 } }, { id: 3, name: 'secret', type: 'trigger', x: 48, y: 16, width: 16, height: 16, visible: false, properties: { kind: 'secret' } } ] }, { name: 'objects-props', type: 'objectgroup', objects: [ { id: 5, name: 'barrel', type: 'prop', class: 'breakable', x: 16, y: 32, width: 16, height: 16, properties: { kind: 'destructible', hp: 3 } } ] } ], tilesets: [ { firstgid: 1, image: 'tiles.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 } ] }; const mapId = aura.tilemap.import(fixture); const all = aura.tilemap.queryObjects(mapId); const allRepeat = aura.tilemap.queryObjects(mapId); const withHidden = aura.tilemap.queryObjects(mapId, { includeHidden: true }); const byLayer = aura.tilemap.queryObjects(mapId, { layer: 'objects-main' }); const byProperty = aura.tilemap.queryObjects(mapId, { property: { name: 'kind', value: 'coin' } }); const byProperties = aura.tilemap.queryObjects(mapId, { properties: { kind: 'destructible', hp: 3 } }); const pointObjects = aura.tilemap.queryObjectsAtPoint(mapId, { x: 32.5, y: 16.5 }); const pointRepeat = aura.tilemap.queryObjectsAtPoint(mapId, { x: 32.5, y: 16.5 }); const aabbObjects = aura.tilemap.queryObjectsInAABB(mapId, { x: 0, y: 0, w: 64, h: 32 }); const invalidLayer = aura.tilemap.queryObjects(mapId, { layer: 'missing' }); const invalidProperty = aura.tilemap.queryObjects(mapId, { property: { name: '' } }); const invalidPoint = aura.tilemap.queryObjectsAtPoint(mapId, { x: 'bad', y: 0 }); const invalidAabb = aura.tilemap.queryObjectsInAABB(mapId, { x: 0, y: 0, w: 0, h: 1 }); const beforePoint = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const setTileClear = aura.tilemap.setTile(mapId, 'ground', { x: 1, y: 1 }, 0); const afterClearPoint = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const setTileRestore = aura.tilemap.setTile(mapId, 'ground', 1, 1, 1); const afterRestorePoint = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const collisionOff = aura.tilemap.setTileCollision(mapId, 'ground', { x: 1, y: 1 }, false); const afterCollisionOff = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const collisionOn = aura.tilemap.setTileCollision(mapId, 'ground', 1, 1, true); const afterCollisionOn = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 }); const collisionRegion = aura.tilemap.setTileCollision(mapId, 'ground', 0, 0, 2, 1, false); const topRow = aura.tilemap.queryAABB(mapId, { x: 0, y: 0, w: 32, h: 16 }); const invalidSetTile = aura.tilemap.setTile(mapId, 'ground', { x: 1, y: 1 }, 'bad'); const outOfBoundsSetTile = aura.tilemap.setTile(mapId, 'ground', { x: 99, y: 99 }, 1); const invalidSetTileCollision = aura.tilemap.setTileCollision(mapId, 'ground', { x: 1, y: 1 }, 'yes'); aura.tilemap.unload(mapId); return { allNames: Array.isArray(all?.hits) ? all.hits.map((entry) => entry.name).join(',') : '', allRepeatNames: Array.isArray(allRepeat?.hits) ? allRepeat.hits.map((entry) => entry.name).join(',') : '', hiddenNames: Array.isArray(withHidden?.hits) ? withHidden.hits.map((entry) => entry.name).join(',') : '', layerNames: Array.isArray(byLayer?.hits) ? byLayer.hits.map((entry) => entry.name).join(',') : '', propertyNames: Array.isArray(byProperty?.hits) ? byProperty.hits.map((entry) => entry.name).join(',') : '', propertiesNames: Array.isArray(byProperties?.hits) ? byProperties.hits.map((entry) => entry.name).join(',') : '', pointNames: Array.isArray(pointObjects?.hits) ? pointObjects.hits.map((entry) => entry.name).join(',') : '', pointRepeatNames: Array.isArray(pointRepeat?.hits) ? pointRepeat.hits.map((entry) => entry.name).join(',') : '', aabbCount: Number(aabbObjects?.count || 0), invalidLayer: invalidLayer?.reasonCode || null, invalidProperty: invalidProperty?.reasonCode || null, invalidPoint: invalidPoint?.reasonCode || null, invalidAabb: invalidAabb?.reasonCode || null, beforeHits: Array.isArray(beforePoint?.hits) ? beforePoint.hits.length : -1, afterClearHits: Array.isArray(afterClearPoint?.hits) ? afterClearPoint.hits.length : -1, afterRestoreHits: Array.isArray(afterRestorePoint?.hits) ? afterRestorePoint.hits.length : -1, afterCollisionOffHits: Array.isArray(afterCollisionOff?.hits) ? afterCollisionOff.hits.length : -1, afterCollisionOnHits: Array.isArray(afterCollisionOn?.hits) ? afterCollisionOn.hits.length : -1, topRowHits: Array.isArray(topRow?.hits) ? topRow.hits.length : -1, setTileClearChanged: Number(setTileClear?.changedTiles || 0), setTileRestoreChanged: Number(setTileRestore?.changedTiles || 0), collisionOffChanged: Number(collisionOff?.changedTiles || 0), collisionOnChanged: Number(collisionOn?.changedTiles || 0), collisionRegionChanged: Number(collisionRegion?.changedTiles || 0), invalidSetTile: invalidSetTile?.reasonCode || null, outOfBoundsSetTile: outOfBoundsSetTile?.reasonCode || null, invalidSetTileCollision: invalidSetTileCollision?.reasonCode || null }; }; const first = runSample(); const second = runSample(); return JSON.stringify(first) === JSON.stringify(second) && first.allNames === 'spawn,coin,barrel' && first.allNames === first.allRepeatNames && first.hiddenNames === 'spawn,coin,secret,barrel' && first.layerNames === 'spawn,coin' && first.propertyNames === 'coin' && first.propertiesNames === 'barrel' && first.pointNames === 'coin' && first.pointNames === first.pointRepeatNames && first.aabbCount === 2 && first.invalidLayer === 'invalid_object_layer_ref' && first.invalidProperty === 'invalid_object_property_filter' && first.invalidPoint === 'invalid_object_point_args' && first.invalidAabb === 'invalid_object_aabb_args' && first.beforeHits === 1 && first.afterClearHits === 0 && first.afterRestoreHits === 1 && first.afterCollisionOffHits === 0 && first.afterCollisionOnHits === 1 && first.topRowHits === 0 && first.setTileClearChanged === 1 && first.setTileRestoreChanged === 1 && first.collisionOffChanged === 1 && first.collisionOnChanged === 1 && first.collisionRegionChanged === 2 && first.invalidSetTile === 'invalid_gid_args' && first.outOfBoundsSetTile === 'tile_out_of_bounds' && first.invalidSetTileCollision === 'invalid_collision_flag'; })()",
|
|
1350
|
+
},
|
|
1351
|
+
],
|
|
1352
|
+
frames: 1,
|
|
1353
|
+
source: `
|
|
1354
|
+
aura.setup = function () {
|
|
1355
|
+
const fixture = {
|
|
1356
|
+
width: 4,
|
|
1357
|
+
height: 4,
|
|
1358
|
+
tilewidth: 16,
|
|
1359
|
+
tileheight: 16,
|
|
1360
|
+
solidLayerNames: ['ground', 'hazards'],
|
|
1361
|
+
layers: [
|
|
1362
|
+
{
|
|
1363
|
+
name: 'ground',
|
|
1364
|
+
type: 'tilelayer',
|
|
1365
|
+
width: 4,
|
|
1366
|
+
height: 4,
|
|
1367
|
+
data: Array.from({ length: 16 }, () => 1),
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
name: 'hazards',
|
|
1371
|
+
type: 'tilelayer',
|
|
1372
|
+
width: 4,
|
|
1373
|
+
height: 4,
|
|
1374
|
+
data: [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
1375
|
+
},
|
|
1376
|
+
],
|
|
1377
|
+
tilesets: [
|
|
1378
|
+
{ firstgid: 1, image: 'tiles.png', tilewidth: 16, tileheight: 16, tilecount: 1, columns: 1 },
|
|
1379
|
+
],
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
const mapId = aura.tilemap.import(fixture);
|
|
1383
|
+
const initial = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 });
|
|
1384
|
+
const setRegion = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 2, h: 1 }, 0);
|
|
1385
|
+
const topRow = aura.tilemap.queryAABB(mapId, { x: 0, y: 0, w: 32, h: 16 });
|
|
1386
|
+
const removeRegion = aura.tilemap.removeRegion(mapId, 'hazards', { x: 1, y: 1, w: 1, h: 1 });
|
|
1387
|
+
const afterRemove = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 });
|
|
1388
|
+
const replaceRegion = aura.tilemap.replaceRegion(mapId, 'ground', { x: 1, y: 1, w: 1, h: 1 }, 1, 0);
|
|
1389
|
+
const afterReplace = aura.tilemap.queryPoint(mapId, { x: 16.5, y: 16.5 });
|
|
1390
|
+
const collisionOff = aura.tilemap.setLayerCollision(mapId, 'ground', false);
|
|
1391
|
+
const hazardsPoint = aura.tilemap.queryPoint(mapId, { x: 32.5, y: 16.5 });
|
|
1392
|
+
const visibilityOff = aura.tilemap.setLayerVisibility(mapId, 'hazards', false);
|
|
1393
|
+
const hiddenDraw = aura.tilemap.draw(mapId, { cull: false });
|
|
1394
|
+
const flags = aura.tilemap.setLayerFlags(mapId, 'hazards', { visible: true, collision: false });
|
|
1395
|
+
const shownDraw = aura.tilemap.draw(mapId, { cull: false });
|
|
1396
|
+
const queryMuted = aura.tilemap.queryPoint(mapId, { x: 32.5, y: 16.5 });
|
|
1397
|
+
const groundCollisionOn = aura.tilemap.setLayerFlags(mapId, 'ground', { collision: true });
|
|
1398
|
+
const hazardsCollisionOn = aura.tilemap.setLayerCollision(mapId, 'hazards', true);
|
|
1399
|
+
const queryRestored = aura.tilemap.queryPoint(mapId, { x: 32.5, y: 16.5 });
|
|
1400
|
+
const invalidRegion = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 0, h: 1 }, 1);
|
|
1401
|
+
const invalidGid = aura.tilemap.setRegion(mapId, 'ground', { x: 0, y: 0, w: 1, h: 1 }, 999);
|
|
1402
|
+
const invalidFlags = aura.tilemap.setLayerFlags(mapId, 'ground', { collision: 'yes' });
|
|
1403
|
+
const invalidLayer = aura.tilemap.setLayerVisibility(mapId, 'missing', true);
|
|
1404
|
+
const unload = aura.tilemap.unload(mapId);
|
|
1405
|
+
|
|
1406
|
+
aura.test.assert(Array.isArray(initial.hits) && initial.hits.length === 2, 'tilemap initial layered query should hit both layers');
|
|
1407
|
+
aura.test.assert(setRegion && setRegion.ok === true && setRegion.changedTiles === 2, 'tilemap setRegion should mutate deterministic tile count');
|
|
1408
|
+
aura.test.assert(Array.isArray(topRow.hits) && topRow.hits.length === 0, 'tilemap setRegion should affect deterministic top-row query hits');
|
|
1409
|
+
aura.test.assert(removeRegion && removeRegion.ok === true && removeRegion.changedTiles === 1, 'tilemap removeRegion should clear deterministic tile count');
|
|
1410
|
+
aura.test.assert(Array.isArray(afterRemove.hits) && afterRemove.hits.length === 1, 'tilemap removeRegion should reduce layered hits');
|
|
1411
|
+
aura.test.assert(replaceRegion && replaceRegion.ok === true && replaceRegion.changedTiles === 1, 'tilemap replaceRegion should deterministically swap target gid');
|
|
1412
|
+
aura.test.assert(Array.isArray(afterReplace.hits) && afterReplace.hits.length === 0, 'tilemap replaceRegion should affect point query deterministically');
|
|
1413
|
+
aura.test.assert(collisionOff && collisionOff.ok === true && collisionOff.collision === false, 'tilemap setLayerCollision should disable query collision');
|
|
1414
|
+
aura.test.assert(Array.isArray(hazardsPoint.hits) && hazardsPoint.hits.length === 1, 'tilemap collision toggle should isolate hazard layer hits');
|
|
1415
|
+
aura.test.assert(visibilityOff && visibilityOff.ok === true && visibilityOff.visible === false, 'tilemap setLayerVisibility should update visibility deterministically');
|
|
1416
|
+
aura.test.assert(hiddenDraw && hiddenDraw.layerOrder.join(',') === 'ground', 'tilemap hidden layer should be omitted from draw ordering');
|
|
1417
|
+
aura.test.assert(flags && flags.ok === true && flags.visible === true && flags.collision === false, 'tilemap setLayerFlags should update visible/collision together');
|
|
1418
|
+
aura.test.assert(shownDraw && shownDraw.layerOrder.join(',') === 'ground,hazards', 'tilemap setLayerFlags should restore draw ordering deterministically');
|
|
1419
|
+
aura.test.assert(Array.isArray(queryMuted.hits) && queryMuted.hits.length === 0, 'tilemap collision-off flags should mute query hits');
|
|
1420
|
+
aura.test.assert(groundCollisionOn && groundCollisionOn.collision === true, 'tilemap ground collision flag should restore deterministically');
|
|
1421
|
+
aura.test.assert(hazardsCollisionOn && hazardsCollisionOn.collision === true, 'tilemap hazard collision toggle should restore deterministically');
|
|
1422
|
+
aura.test.assert(Array.isArray(queryRestored.hits) && queryRestored.hits.length === 2, 'tilemap collision flags should restore layered query hits');
|
|
1423
|
+
aura.test.assert(invalidRegion && invalidRegion.ok === false && invalidRegion.reasonCode === 'invalid_region_args', 'tilemap invalid region args should be reason-coded');
|
|
1424
|
+
aura.test.assert(invalidGid && invalidGid.ok === false && invalidGid.reasonCode === 'unmapped_layer_gid', 'tilemap unmapped gid mutation should be reason-coded');
|
|
1425
|
+
aura.test.assert(invalidFlags && invalidFlags.ok === false && invalidFlags.reasonCode === 'invalid_collision_flag', 'tilemap invalid collision flag should be reason-coded');
|
|
1426
|
+
aura.test.assert(invalidLayer && invalidLayer.ok === false && invalidLayer.reasonCode === 'invalid_layer_ref', 'tilemap invalid layer ref should be reason-coded');
|
|
1427
|
+
aura.test.equal(unload, true, 'tilemap handle should unload after mutation checks');
|
|
1428
|
+
};
|
|
1429
|
+
`,
|
|
1430
|
+
}
|
|
1431
|
+
];
|