@caperjs/core 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/LICENSE +22 -0
- package/README.md +62 -0
- package/cli/add.mjs +197 -0
- package/cli/audio/cc.mjs +128 -0
- package/cli/audio/index.mjs +42 -0
- package/cli/audio/utils.mjs +56 -0
- package/cli/create-caper.mjs +8 -0
- package/cli/create.mjs +351 -0
- package/cli/install-peerdeps.mjs +57 -0
- package/cli/update.mjs +9 -0
- package/cli/utils.mjs +81 -0
- package/cli/vite.mjs +55 -0
- package/cli/voiceover/generateVoiceoverCSV.mjs +158 -0
- package/cli/voiceover/index.mjs +1 -0
- package/cli.mjs +157 -0
- package/client.d.ts +7 -0
- package/config/assetpack.mjs +212 -0
- package/config/tsconfig.base.json +28 -0
- package/config/vite.mjs +2464 -0
- package/extras/css/accessibility.css +9 -0
- package/extras/css/fullscreen.css +28 -0
- package/extras/css/loader.css +67 -0
- package/extras/llms.txt +1602 -0
- package/lib/CaptionsPlugin-Dc8fIrjy.js +277 -0
- package/lib/CaptionsPlugin-Dc8fIrjy.js.map +1 -0
- package/lib/DataAdapter-BY2114sp.js +84 -0
- package/lib/DataAdapter-BY2114sp.js.map +1 -0
- package/lib/DebugRenderer-BJMLILqI.js +1385 -0
- package/lib/DebugRenderer-BJMLILqI.js.map +1 -0
- package/lib/DevToolsPlugin-wQ5rOkn0.js +31 -0
- package/lib/DevToolsPlugin-wQ5rOkn0.js.map +1 -0
- package/lib/GSAPPlugin-DHhSZKv8.js +350 -0
- package/lib/GSAPPlugin-DHhSZKv8.js.map +1 -0
- package/lib/LayoutPlugin-B-DF9SYM.js +1271 -0
- package/lib/LayoutPlugin-B-DF9SYM.js.map +1 -0
- package/lib/SpinePlugin-Dz_3dljz.js +6077 -0
- package/lib/SpinePlugin-Dz_3dljz.js.map +1 -0
- package/lib/StatsPlugin-Cg82JMBD.js +70 -0
- package/lib/StatsPlugin-Cg82JMBD.js.map +1 -0
- package/lib/VoiceOverPlugin-BR3ImT8C.js +114 -0
- package/lib/VoiceOverPlugin-BR3ImT8C.js.map +1 -0
- package/lib/caper.mjs +1233 -0
- package/lib/caper.mjs.map +1 -0
- package/lib/core/Application.d.ts +268 -0
- package/lib/core/Application.d.ts.map +1 -0
- package/lib/core/config.d.ts +39 -0
- package/lib/core/config.d.ts.map +1 -0
- package/lib/core/create.d.ts +41 -0
- package/lib/core/create.d.ts.map +1 -0
- package/lib/core/globals.d.ts +51 -0
- package/lib/core/globals.d.ts.map +1 -0
- package/lib/core/index.d.ts +7 -0
- package/lib/core/index.d.ts.map +1 -0
- package/lib/core/interfaces/IApplication.d.ts +566 -0
- package/lib/core/interfaces/IApplication.d.ts.map +1 -0
- package/lib/core/interfaces/IApplicationOptions.d.ts +65 -0
- package/lib/core/interfaces/IApplicationOptions.d.ts.map +1 -0
- package/lib/core/interfaces/ICoreFunctions.d.ts +49 -0
- package/lib/core/interfaces/ICoreFunctions.d.ts.map +1 -0
- package/lib/core/interfaces/ICoreSignals.d.ts +57 -0
- package/lib/core/interfaces/ICoreSignals.d.ts.map +1 -0
- package/lib/core/interfaces/IStorageCapability.d.ts +20 -0
- package/lib/core/interfaces/IStorageCapability.d.ts.map +1 -0
- package/lib/core/interfaces/IStorageCapability.test.d.ts +2 -0
- package/lib/core/interfaces/IStorageCapability.test.d.ts.map +1 -0
- package/lib/core/interfaces/index.d.ts +7 -0
- package/lib/core/interfaces/index.d.ts.map +1 -0
- package/lib/core/registries.d.ts +8 -0
- package/lib/core/registries.d.ts.map +1 -0
- package/lib/core/types.d.ts +12 -0
- package/lib/core/types.d.ts.map +1 -0
- package/lib/display/AnimatedSprite.d.ts +40 -0
- package/lib/display/AnimatedSprite.d.ts.map +1 -0
- package/lib/display/Camera.d.ts +102 -0
- package/lib/display/Camera.d.ts.map +1 -0
- package/lib/display/Container.d.ts +115 -0
- package/lib/display/Container.d.ts.map +1 -0
- package/lib/display/Entity.d.ts +46 -0
- package/lib/display/Entity.d.ts.map +1 -0
- package/lib/display/ParticleContainer.d.ts +58 -0
- package/lib/display/ParticleContainer.d.ts.map +1 -0
- package/lib/display/Scene.d.ts +250 -0
- package/lib/display/Scene.d.ts.map +1 -0
- package/lib/display/SceneTransition.d.ts +41 -0
- package/lib/display/SceneTransition.d.ts.map +1 -0
- package/lib/display/SpineAnimation.d.ts +76 -0
- package/lib/display/SpineAnimation.d.ts.map +1 -0
- package/lib/display/Svg.d.ts +5 -0
- package/lib/display/Svg.d.ts.map +1 -0
- package/lib/display/index.d.ts +10 -0
- package/lib/display/index.d.ts.map +1 -0
- package/lib/env.d.ts +6 -0
- package/lib/hello.d.ts +2 -0
- package/lib/hello.d.ts.map +1 -0
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/mixins/animated.d.ts +53 -0
- package/lib/mixins/animated.d.ts.map +1 -0
- package/lib/mixins/factory/Factory.d.ts +8 -0
- package/lib/mixins/factory/Factory.d.ts.map +1 -0
- package/lib/mixins/factory/const.d.ts +67 -0
- package/lib/mixins/factory/const.d.ts.map +1 -0
- package/lib/mixins/factory/index.d.ts +8 -0
- package/lib/mixins/factory/index.d.ts.map +1 -0
- package/lib/mixins/factory/methods.d.ts +3 -0
- package/lib/mixins/factory/methods.d.ts.map +1 -0
- package/lib/mixins/factory/props.d.ts +160 -0
- package/lib/mixins/factory/props.d.ts.map +1 -0
- package/lib/mixins/factory/registry.d.ts +27 -0
- package/lib/mixins/factory/registry.d.ts.map +1 -0
- package/lib/mixins/factory/registry.test.d.ts +2 -0
- package/lib/mixins/factory/registry.test.d.ts.map +1 -0
- package/lib/mixins/factory/schema.d.ts +71 -0
- package/lib/mixins/factory/schema.d.ts.map +1 -0
- package/lib/mixins/factory/ui-registry.d.ts +20 -0
- package/lib/mixins/factory/ui-registry.d.ts.map +1 -0
- package/lib/mixins/factory/utils.d.ts +11 -0
- package/lib/mixins/factory/utils.d.ts.map +1 -0
- package/lib/mixins/focus.d.ts +15 -0
- package/lib/mixins/focus.d.ts.map +1 -0
- package/lib/mixins/index.d.ts +6 -0
- package/lib/mixins/index.d.ts.map +1 -0
- package/lib/mixins/interaction.d.ts +20 -0
- package/lib/mixins/interaction.d.ts.map +1 -0
- package/lib/mixins/signals.d.ts +15 -0
- package/lib/mixins/signals.d.ts.map +1 -0
- package/lib/plugins/AssetsPlugin.d.ts +79 -0
- package/lib/plugins/AssetsPlugin.d.ts.map +1 -0
- package/lib/plugins/DataAdapter.d.ts +95 -0
- package/lib/plugins/DataAdapter.d.ts.map +1 -0
- package/lib/plugins/DevToolsPlugin.d.ts +97 -0
- package/lib/plugins/DevToolsPlugin.d.ts.map +1 -0
- package/lib/plugins/FullScreenPlugin.d.ts +240 -0
- package/lib/plugins/FullScreenPlugin.d.ts.map +1 -0
- package/lib/plugins/GSAPPlugin.d.ts +634 -0
- package/lib/plugins/GSAPPlugin.d.ts.map +1 -0
- package/lib/plugins/KeyboardPlugin.d.ts +53 -0
- package/lib/plugins/KeyboardPlugin.d.ts.map +1 -0
- package/lib/plugins/LayoutPlugin.d.ts +100 -0
- package/lib/plugins/LayoutPlugin.d.ts.map +1 -0
- package/lib/plugins/LookupPlugin.d.ts +223 -0
- package/lib/plugins/LookupPlugin.d.ts.map +1 -0
- package/lib/plugins/Plugin.d.ts +132 -0
- package/lib/plugins/Plugin.d.ts.map +1 -0
- package/lib/plugins/Plugin.test.d.ts +2 -0
- package/lib/plugins/Plugin.test.d.ts.map +1 -0
- package/lib/plugins/PopupManagerPlugin.d.ts +108 -0
- package/lib/plugins/PopupManagerPlugin.d.ts.map +1 -0
- package/lib/plugins/ResizerPlugin.d.ts +62 -0
- package/lib/plugins/ResizerPlugin.d.ts.map +1 -0
- package/lib/plugins/SceneManagerPlugin.d.ts +122 -0
- package/lib/plugins/SceneManagerPlugin.d.ts.map +1 -0
- package/lib/plugins/StatsPlugin.d.ts +8 -0
- package/lib/plugins/StatsPlugin.d.ts.map +1 -0
- package/lib/plugins/TimerPlugin.d.ts +401 -0
- package/lib/plugins/TimerPlugin.d.ts.map +1 -0
- package/lib/plugins/WebEventsPlugin.d.ts +60 -0
- package/lib/plugins/WebEventsPlugin.d.ts.map +1 -0
- package/lib/plugins/actions/ActionsPlugin.d.ts +39 -0
- package/lib/plugins/actions/ActionsPlugin.d.ts.map +1 -0
- package/lib/plugins/actions/constants.d.ts +52 -0
- package/lib/plugins/actions/constants.d.ts.map +1 -0
- package/lib/plugins/actions/index.d.ts +5 -0
- package/lib/plugins/actions/index.d.ts.map +1 -0
- package/lib/plugins/actions/methods.d.ts +11 -0
- package/lib/plugins/actions/methods.d.ts.map +1 -0
- package/lib/plugins/actions/types.d.ts +25 -0
- package/lib/plugins/actions/types.d.ts.map +1 -0
- package/lib/plugins/audio/AudioChannel.d.ts +46 -0
- package/lib/plugins/audio/AudioChannel.d.ts.map +1 -0
- package/lib/plugins/audio/AudioChannel.test.d.ts +2 -0
- package/lib/plugins/audio/AudioChannel.test.d.ts.map +1 -0
- package/lib/plugins/audio/AudioInstance.d.ts +79 -0
- package/lib/plugins/audio/AudioInstance.d.ts.map +1 -0
- package/lib/plugins/audio/AudioManagerPlugin.d.ts +323 -0
- package/lib/plugins/audio/AudioManagerPlugin.d.ts.map +1 -0
- package/lib/plugins/audio/VoiceOverPlugin.d.ts +69 -0
- package/lib/plugins/audio/VoiceOverPlugin.d.ts.map +1 -0
- package/lib/plugins/audio/index.d.ts +4 -0
- package/lib/plugins/audio/index.d.ts.map +1 -0
- package/lib/plugins/breakpoints/BreakpointPlugin.d.ts +109 -0
- package/lib/plugins/breakpoints/BreakpointPlugin.d.ts.map +1 -0
- package/lib/plugins/breakpoints/BreakpointPlugin.test.d.ts +2 -0
- package/lib/plugins/breakpoints/BreakpointPlugin.test.d.ts.map +1 -0
- package/lib/plugins/breakpoints/evaluate.d.ts +53 -0
- package/lib/plugins/breakpoints/evaluate.d.ts.map +1 -0
- package/lib/plugins/breakpoints/evaluate.test.d.ts +2 -0
- package/lib/plugins/breakpoints/evaluate.test.d.ts.map +1 -0
- package/lib/plugins/breakpoints/index.d.ts +4 -0
- package/lib/plugins/breakpoints/index.d.ts.map +1 -0
- package/lib/plugins/breakpoints/methods.d.ts +23 -0
- package/lib/plugins/breakpoints/methods.d.ts.map +1 -0
- package/lib/plugins/breakpoints/types.d.ts +70 -0
- package/lib/plugins/breakpoints/types.d.ts.map +1 -0
- package/lib/plugins/captions/CaptionsPlugin.d.ts +150 -0
- package/lib/plugins/captions/CaptionsPlugin.d.ts.map +1 -0
- package/lib/plugins/captions/CaptionsRenderer.d.ts +37 -0
- package/lib/plugins/captions/CaptionsRenderer.d.ts.map +1 -0
- package/lib/plugins/captions/index.d.ts +3 -0
- package/lib/plugins/captions/index.d.ts.map +1 -0
- package/lib/plugins/defaults.d.ts +4 -0
- package/lib/plugins/defaults.d.ts.map +1 -0
- package/lib/plugins/focus/FocusManagerPlugin.d.ts +148 -0
- package/lib/plugins/focus/FocusManagerPlugin.d.ts.map +1 -0
- package/lib/plugins/focus/FocusOutliner.d.ts +32 -0
- package/lib/plugins/focus/FocusOutliner.d.ts.map +1 -0
- package/lib/plugins/focus/index.d.ts +3 -0
- package/lib/plugins/focus/index.d.ts.map +1 -0
- package/lib/plugins/i18nPlugin.d.ts +128 -0
- package/lib/plugins/i18nPlugin.d.ts.map +1 -0
- package/lib/plugins/index.d.ts +18 -0
- package/lib/plugins/index.d.ts.map +1 -0
- package/lib/plugins/input/AbstractControls.d.ts +8 -0
- package/lib/plugins/input/AbstractControls.d.ts.map +1 -0
- package/lib/plugins/input/Controls.d.ts +16 -0
- package/lib/plugins/input/Controls.d.ts.map +1 -0
- package/lib/plugins/input/InputPlugin.d.ts +52 -0
- package/lib/plugins/input/InputPlugin.d.ts.map +1 -0
- package/lib/plugins/input/constants.d.ts +8 -0
- package/lib/plugins/input/constants.d.ts.map +1 -0
- package/lib/plugins/input/index.d.ts +10 -0
- package/lib/plugins/input/index.d.ts.map +1 -0
- package/lib/plugins/input/interfaces.d.ts +30 -0
- package/lib/plugins/input/interfaces.d.ts.map +1 -0
- package/lib/plugins/input/keyboard/KeyboardContols.d.ts +28 -0
- package/lib/plugins/input/keyboard/KeyboardContols.d.ts.map +1 -0
- package/lib/plugins/input/keyboard/index.d.ts +3 -0
- package/lib/plugins/input/keyboard/index.d.ts.map +1 -0
- package/lib/plugins/input/keyboard/interfaces.d.ts +18 -0
- package/lib/plugins/input/keyboard/interfaces.d.ts.map +1 -0
- package/lib/plugins/input/methods.d.ts +4 -0
- package/lib/plugins/input/methods.d.ts.map +1 -0
- package/lib/plugins/input/touch/TouchControls.d.ts +35 -0
- package/lib/plugins/input/touch/TouchControls.d.ts.map +1 -0
- package/lib/plugins/input/touch/constants.d.ts +14 -0
- package/lib/plugins/input/touch/constants.d.ts.map +1 -0
- package/lib/plugins/input/touch/index.d.ts +4 -0
- package/lib/plugins/input/touch/index.d.ts.map +1 -0
- package/lib/plugins/input/touch/interfaces.d.ts +15 -0
- package/lib/plugins/input/touch/interfaces.d.ts.map +1 -0
- package/lib/plugins/input/types.d.ts +32 -0
- package/lib/plugins/input/types.d.ts.map +1 -0
- package/lib/plugins/input/utils.d.ts +23 -0
- package/lib/plugins/input/utils.d.ts.map +1 -0
- package/lib/plugins/spine/SpinePlugin.d.ts +6 -0
- package/lib/plugins/spine/SpinePlugin.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/BatchableSpineSlot.d.ts +31 -0
- package/lib/plugins/spine/pixi-spine/BatchableSpineSlot.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/Spine.d.ts +211 -0
- package/lib/plugins/spine/pixi-spine/Spine.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/SpineDebugRenderer.d.ts +81 -0
- package/lib/plugins/spine/pixi-spine/SpineDebugRenderer.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/SpinePipe.d.ts +21 -0
- package/lib/plugins/spine/pixi-spine/SpinePipe.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/SpineTexture.d.ts +16 -0
- package/lib/plugins/spine/pixi-spine/SpineTexture.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/assets/atlasLoader.d.ts +10 -0
- package/lib/plugins/spine/pixi-spine/assets/atlasLoader.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/assets/skeletonLoader.d.ts +6 -0
- package/lib/plugins/spine/pixi-spine/assets/skeletonLoader.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/darktint/DarkTintBatchGeometry.d.ts +5 -0
- package/lib/plugins/spine/pixi-spine/darktint/DarkTintBatchGeometry.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/darktint/DarkTintBatcher.d.ts +22 -0
- package/lib/plugins/spine/pixi-spine/darktint/DarkTintBatcher.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/darktint/DarkTintShader.d.ts +5 -0
- package/lib/plugins/spine/pixi-spine/darktint/DarkTintShader.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/darktint/darkTintBit.d.ts +51 -0
- package/lib/plugins/spine/pixi-spine/darktint/darkTintBit.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/index.d.ts +9 -0
- package/lib/plugins/spine/pixi-spine/index.d.ts.map +1 -0
- package/lib/plugins/spine/pixi-spine/require-shim.d.ts +34 -0
- package/lib/plugins/spine/pixi-spine/require-shim.d.ts.map +1 -0
- package/lib/registries-CYCaYKZI.js +6885 -0
- package/lib/registries-CYCaYKZI.js.map +1 -0
- package/lib/signals/Signal.d.ts +16 -0
- package/lib/signals/Signal.d.ts.map +1 -0
- package/lib/signals/Signal.test.d.ts +2 -0
- package/lib/signals/Signal.test.d.ts.map +1 -0
- package/lib/signals/index.d.ts +3 -0
- package/lib/signals/index.d.ts.map +1 -0
- package/lib/store/Store.d.ts +56 -0
- package/lib/store/Store.d.ts.map +1 -0
- package/lib/store/Store.test.d.ts +2 -0
- package/lib/store/Store.test.d.ts.map +1 -0
- package/lib/store/index.d.ts +2 -0
- package/lib/store/index.d.ts.map +1 -0
- package/lib/types/framework.d.ts +46 -0
- package/lib/types/gsap.d.ts +23 -0
- package/lib/ui/Button.d.ts +162 -0
- package/lib/ui/Button.d.ts.map +1 -0
- package/lib/ui/FlexContainer.d.ts +109 -0
- package/lib/ui/FlexContainer.d.ts.map +1 -0
- package/lib/ui/Input.d.ts +384 -0
- package/lib/ui/Input.d.ts.map +1 -0
- package/lib/ui/Joystick.d.ts +61 -0
- package/lib/ui/Joystick.d.ts.map +1 -0
- package/lib/ui/Popup.d.ts +109 -0
- package/lib/ui/Popup.d.ts.map +1 -0
- package/lib/ui/Toast.d.ts +131 -0
- package/lib/ui/Toast.d.ts.map +1 -0
- package/lib/ui/Toaster.d.ts +188 -0
- package/lib/ui/Toaster.d.ts.map +1 -0
- package/lib/ui/UICanvas.d.ts +155 -0
- package/lib/ui/UICanvas.d.ts.map +1 -0
- package/lib/ui/index.d.ts +9 -0
- package/lib/ui/index.d.ts.map +1 -0
- package/lib/utils/array.d.ts +11 -0
- package/lib/utils/array.d.ts.map +1 -0
- package/lib/utils/bind.d.ts +21 -0
- package/lib/utils/bind.d.ts.map +1 -0
- package/lib/utils/canvas.d.ts +2 -0
- package/lib/utils/canvas.d.ts.map +1 -0
- package/lib/utils/color.d.ts +66 -0
- package/lib/utils/color.d.ts.map +1 -0
- package/lib/utils/console/Logger.d.ts +15 -0
- package/lib/utils/console/Logger.d.ts.map +1 -0
- package/lib/utils/console/index.d.ts +2 -0
- package/lib/utils/console/index.d.ts.map +1 -0
- package/lib/utils/debug.d.ts +34 -0
- package/lib/utils/debug.d.ts.map +1 -0
- package/lib/utils/define.d.ts +100 -0
- package/lib/utils/define.d.ts.map +1 -0
- package/lib/utils/env.d.ts +4 -0
- package/lib/utils/env.d.ts.map +1 -0
- package/lib/utils/events.d.ts +12 -0
- package/lib/utils/events.d.ts.map +1 -0
- package/lib/utils/framework.d.ts +12 -0
- package/lib/utils/framework.d.ts.map +1 -0
- package/lib/utils/index.d.ts +28 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/map.d.ts +31 -0
- package/lib/utils/map.d.ts.map +1 -0
- package/lib/utils/math.d.ts +15 -0
- package/lib/utils/math.d.ts.map +1 -0
- package/lib/utils/misc.d.ts +13 -0
- package/lib/utils/misc.d.ts.map +1 -0
- package/lib/utils/number.d.ts +2 -0
- package/lib/utils/number.d.ts.map +1 -0
- package/lib/utils/object.d.ts +21 -0
- package/lib/utils/object.d.ts.map +1 -0
- package/lib/utils/padding.d.ts +4 -0
- package/lib/utils/padding.d.ts.map +1 -0
- package/lib/utils/pixi.d.ts +42 -0
- package/lib/utils/pixi.d.ts.map +1 -0
- package/lib/utils/platform.d.ts +20 -0
- package/lib/utils/platform.d.ts.map +1 -0
- package/lib/utils/point.d.ts +66 -0
- package/lib/utils/point.d.ts.map +1 -0
- package/lib/utils/promise/Queue.d.ts +60 -0
- package/lib/utils/promise/Queue.d.ts.map +1 -0
- package/lib/utils/promise/functions.d.ts +14 -0
- package/lib/utils/promise/functions.d.ts.map +1 -0
- package/lib/utils/promise/index.d.ts +3 -0
- package/lib/utils/promise/index.d.ts.map +1 -0
- package/lib/utils/random.d.ts +42 -0
- package/lib/utils/random.d.ts.map +1 -0
- package/lib/utils/rect.d.ts +26 -0
- package/lib/utils/rect.d.ts.map +1 -0
- package/lib/utils/set.d.ts +15 -0
- package/lib/utils/set.d.ts.map +1 -0
- package/lib/utils/string.d.ts +3 -0
- package/lib/utils/string.d.ts.map +1 -0
- package/lib/utils/text.d.ts +3 -0
- package/lib/utils/text.d.ts.map +1 -0
- package/lib/utils/typefilters.d.ts +4 -0
- package/lib/utils/typefilters.d.ts.map +1 -0
- package/lib/utils/types.d.ts +209 -0
- package/lib/utils/types.d.ts.map +1 -0
- package/lib/utils/vite.d.ts +25 -0
- package/lib/utils/vite.d.ts.map +1 -0
- package/lib/utils/web.d.ts +3 -0
- package/lib/utils/web.d.ts.map +1 -0
- package/lib/version.d.ts +3 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/webgl-check.d.ts +2 -0
- package/lib/webgl-check.d.ts.map +1 -0
- package/package.json +138 -0
- package/src/core/Application.ts +1091 -0
- package/src/core/config.ts +168 -0
- package/src/core/create.ts +186 -0
- package/src/core/globals.ts +299 -0
- package/src/core/index.ts +6 -0
- package/src/core/interfaces/IApplication.ts +628 -0
- package/src/core/interfaces/IApplicationOptions.ts +81 -0
- package/src/core/interfaces/ICoreFunctions.ts +86 -0
- package/src/core/interfaces/ICoreSignals.ts +77 -0
- package/src/core/interfaces/IStorageCapability.test.ts +27 -0
- package/src/core/interfaces/IStorageCapability.ts +26 -0
- package/src/core/interfaces/index.ts +6 -0
- package/src/core/registries.ts +7 -0
- package/src/core/types.ts +13 -0
- package/src/display/AnimatedSprite.ts +227 -0
- package/src/display/Camera.ts +371 -0
- package/src/display/Container.ts +240 -0
- package/src/display/Entity.ts +50 -0
- package/src/display/ParticleContainer.ts +107 -0
- package/src/display/Scene.ts +305 -0
- package/src/display/SceneTransition.ts +108 -0
- package/src/display/SpineAnimation.ts +170 -0
- package/src/display/Svg.ts +9 -0
- package/src/display/index.ts +11 -0
- package/src/env.d.ts +6 -0
- package/src/hello.ts +20 -0
- package/src/index.ts +17 -0
- package/src/mixins/animated.ts +340 -0
- package/src/mixins/factory/Factory.ts +24 -0
- package/src/mixins/factory/const.ts +363 -0
- package/src/mixins/factory/index.ts +7 -0
- package/src/mixins/factory/methods.ts +21 -0
- package/src/mixins/factory/props.ts +207 -0
- package/src/mixins/factory/registry.test.ts +83 -0
- package/src/mixins/factory/registry.ts +61 -0
- package/src/mixins/factory/schema.ts +153 -0
- package/src/mixins/factory/ui-registry.ts +54 -0
- package/src/mixins/factory/utils.ts +130 -0
- package/src/mixins/focus.ts +124 -0
- package/src/mixins/index.ts +5 -0
- package/src/mixins/interaction.ts +74 -0
- package/src/mixins/signals.ts +49 -0
- package/src/plugins/AssetsPlugin.ts +407 -0
- package/src/plugins/DataAdapter.ts +259 -0
- package/src/plugins/DevToolsPlugin.ts +103 -0
- package/src/plugins/FullScreenPlugin.ts +359 -0
- package/src/plugins/GSAPPlugin.ts +811 -0
- package/src/plugins/KeyboardPlugin.ts +160 -0
- package/src/plugins/LayoutPlugin.ts +127 -0
- package/src/plugins/LookupPlugin.ts +308 -0
- package/src/plugins/Plugin.test.ts +73 -0
- package/src/plugins/Plugin.ts +200 -0
- package/src/plugins/PopupManagerPlugin.ts +263 -0
- package/src/plugins/ResizerPlugin.ts +220 -0
- package/src/plugins/SceneManagerPlugin.ts +669 -0
- package/src/plugins/StatsPlugin.ts +24 -0
- package/src/plugins/TimerPlugin.ts +841 -0
- package/src/plugins/WebEventsPlugin.ts +132 -0
- package/src/plugins/actions/ActionsPlugin.ts +113 -0
- package/src/plugins/actions/constants.ts +45 -0
- package/src/plugins/actions/index.ts +4 -0
- package/src/plugins/actions/methods.ts +28 -0
- package/src/plugins/actions/types.ts +47 -0
- package/src/plugins/audio/AudioChannel.test.ts +101 -0
- package/src/plugins/audio/AudioChannel.ts +164 -0
- package/src/plugins/audio/AudioInstance.ts +228 -0
- package/src/plugins/audio/AudioManagerPlugin.ts +903 -0
- package/src/plugins/audio/VoiceOverPlugin.ts +354 -0
- package/src/plugins/audio/index.ts +3 -0
- package/src/plugins/breakpoints/BreakpointPlugin.test.ts +228 -0
- package/src/plugins/breakpoints/BreakpointPlugin.ts +293 -0
- package/src/plugins/breakpoints/evaluate.test.ts +239 -0
- package/src/plugins/breakpoints/evaluate.ts +201 -0
- package/src/plugins/breakpoints/index.ts +3 -0
- package/src/plugins/breakpoints/methods.ts +22 -0
- package/src/plugins/breakpoints/types.ts +86 -0
- package/src/plugins/captions/CaptionsPlugin.ts +468 -0
- package/src/plugins/captions/CaptionsRenderer.ts +184 -0
- package/src/plugins/captions/font/Sans.fnt +116 -0
- package/src/plugins/captions/font/Sans.png +0 -0
- package/src/plugins/captions/index.ts +2 -0
- package/src/plugins/defaults.ts +95 -0
- package/src/plugins/focus/FocusManagerPlugin.ts +773 -0
- package/src/plugins/focus/FocusOutliner.ts +111 -0
- package/src/plugins/focus/index.ts +2 -0
- package/src/plugins/i18nPlugin.ts +284 -0
- package/src/plugins/index.ts +17 -0
- package/src/plugins/input/AbstractControls.ts +15 -0
- package/src/plugins/input/Controls.ts +55 -0
- package/src/plugins/input/InputPlugin.ts +168 -0
- package/src/plugins/input/constants.ts +12 -0
- package/src/plugins/input/index.ts +9 -0
- package/src/plugins/input/interfaces.ts +37 -0
- package/src/plugins/input/keyboard/KeyboardContols.ts +182 -0
- package/src/plugins/input/keyboard/index.ts +2 -0
- package/src/plugins/input/keyboard/interfaces.ts +21 -0
- package/src/plugins/input/methods.ts +9 -0
- package/src/plugins/input/touch/TouchControls.ts +237 -0
- package/src/plugins/input/touch/constants.ts +34 -0
- package/src/plugins/input/touch/index.ts +3 -0
- package/src/plugins/input/touch/interfaces.ts +15 -0
- package/src/plugins/input/types.ts +41 -0
- package/src/plugins/input/utils.ts +10 -0
- package/src/plugins/spine/SpinePlugin.ts +14 -0
- package/src/plugins/spine/pixi-spine/BatchableSpineSlot.ts +138 -0
- package/src/plugins/spine/pixi-spine/Spine.ts +897 -0
- package/src/plugins/spine/pixi-spine/SpineDebugRenderer.ts +615 -0
- package/src/plugins/spine/pixi-spine/SpinePipe.ts +197 -0
- package/src/plugins/spine/pixi-spine/SpineTexture.ts +143 -0
- package/src/plugins/spine/pixi-spine/assets/atlasLoader.ts +156 -0
- package/src/plugins/spine/pixi-spine/assets/skeletonLoader.ts +80 -0
- package/src/plugins/spine/pixi-spine/darktint/DarkTintBatchGeometry.ts +92 -0
- package/src/plugins/spine/pixi-spine/darktint/DarkTintBatcher.ts +186 -0
- package/src/plugins/spine/pixi-spine/darktint/DarkTintShader.ts +74 -0
- package/src/plugins/spine/pixi-spine/darktint/darkTintBit.ts +77 -0
- package/src/plugins/spine/pixi-spine/index.ts +43 -0
- package/src/plugins/spine/pixi-spine/require-shim.ts +43 -0
- package/src/signals/Signal.test.ts +54 -0
- package/src/signals/Signal.ts +68 -0
- package/src/signals/index.ts +10 -0
- package/src/store/Store.test.ts +146 -0
- package/src/store/Store.ts +192 -0
- package/src/store/index.ts +1 -0
- package/src/types/framework.d.ts +47 -0
- package/src/types/gsap.d.ts +26 -0
- package/src/ui/Button.ts +454 -0
- package/src/ui/FlexContainer.ts +526 -0
- package/src/ui/Input.ts +1274 -0
- package/src/ui/Joystick.ts +288 -0
- package/src/ui/Popup.ts +242 -0
- package/src/ui/Toast.ts +399 -0
- package/src/ui/Toaster.ts +409 -0
- package/src/ui/UICanvas.ts +812 -0
- package/src/ui/index.ts +8 -0
- package/src/utils/array.ts +24 -0
- package/src/utils/bind.ts +79 -0
- package/src/utils/canvas.ts +26 -0
- package/src/utils/color.ts +126 -0
- package/src/utils/console/Logger.ts +86 -0
- package/src/utils/console/index.ts +1 -0
- package/src/utils/debug.ts +69 -0
- package/src/utils/define.ts +120 -0
- package/src/utils/env.ts +3 -0
- package/src/utils/events.ts +10 -0
- package/src/utils/framework.ts +45 -0
- package/src/utils/index.ts +27 -0
- package/src/utils/map.ts +59 -0
- package/src/utils/math.ts +19 -0
- package/src/utils/misc.ts +45 -0
- package/src/utils/number.ts +3 -0
- package/src/utils/object.ts +43 -0
- package/src/utils/padding.ts +43 -0
- package/src/utils/pixi.ts +116 -0
- package/src/utils/platform.ts +33 -0
- package/src/utils/point.ts +123 -0
- package/src/utils/promise/Queue.ts +125 -0
- package/src/utils/promise/functions.ts +16 -0
- package/src/utils/promise/index.ts +2 -0
- package/src/utils/random.ts +69 -0
- package/src/utils/rect.ts +50 -0
- package/src/utils/set.ts +32 -0
- package/src/utils/string.ts +9 -0
- package/src/utils/text.ts +30 -0
- package/src/utils/typefilters.ts +29 -0
- package/src/utils/types.ts +426 -0
- package/src/utils/vite.ts +41 -0
- package/src/utils/web.ts +7 -0
- package/src/version.ts +3 -0
- package/src/webgl-check.ts +12 -0
- package/templates/app/default/.eslintrc.json +21 -0
- package/templates/app/default/.meta.json +4 -0
- package/templates/app/default/.nvmrc +1 -0
- package/templates/app/default/.prettierrc.json +7 -0
- package/templates/app/default/README.md +8 -0
- package/templates/app/default/assets/audio{m}/music/Cheerful Annoyance.ogg +0 -0
- package/templates/app/default/assets/audio{m}/music/Drumming Sticks.ogg +0 -0
- package/templates/app/default/assets/audio{m}/music/Game Over.ogg +0 -0
- package/templates/app/default/assets/audio{m}/music/Mishief Stroll.ogg +0 -0
- package/templates/app/default/assets/audio{m}/music/Night at the Beach.ogg +0 -0
- package/templates/app/default/assets/audio{m}/sfx/click.ogg +0 -0
- package/templates/app/default/assets/audio{m}/sfx/hover.ogg +0 -0
- package/templates/app/default/assets/required{m}/caper.png +0 -0
- package/templates/app/default/assets/required{m}/fonts{fix}/SpaceGrotesk-Bold{family=Space Grotesk}{wf}.ttf +0 -0
- package/templates/app/default/assets/required{m}/fonts{fix}/SpaceGrotesk-Medium{family=Space Grotesk}{wf}.ttf +0 -0
- package/templates/app/default/assets/required{m}/fonts{fix}/SpaceGrotesk-Regular{family=Space Grotesk}{wf}.ttf +0 -0
- package/templates/app/default/assets/required{m}/fonts{fix}/Syncopate-Bold{family=Syncopate}{wf}.ttf +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/blue.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/green.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/grey.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/orange.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/purple.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/red.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn/yellow.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn_a/down.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn_a/over.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn_a/up.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn_b/down.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn_b/over.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/btn_b/up.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/joystick/base.png +0 -0
- package/templates/app/default/assets/required{m}/ui{tps}/joystick/handle.png +0 -0
- package/templates/app/default/assets/required{m}/wordmark.svg +1 -0
- package/templates/app/default/assets/spine{m}/spineboy-pro.png +0 -0
- package/templates/app/default/assets/spine{m}/spineboy-pro.skel +0 -0
- package/templates/app/default/assets/spine{m}/spineboy-pro{fix}.atlas +94 -0
- package/templates/app/default/caper.config.ts +60 -0
- package/templates/app/default/index.html +23 -0
- package/templates/app/default/package.template.json +17 -0
- package/templates/app/default/public/favicon.ico +0 -0
- package/templates/app/default/src/__APPLICATION_NAME__.ts +3 -0
- package/templates/app/default/src/main.ts +9 -0
- package/templates/app/default/src/scenes/Base.ts +39 -0
- package/templates/app/default/src/scenes/Game.ts +34 -0
- package/templates/app/default/src/scenes/Splash.ts +70 -0
- package/templates/app/default/src/scenes/Start.ts +90 -0
- package/templates/app/default/src/utils/Constants.ts +3 -0
- package/templates/app/default/tsconfig.json +1 -0
- package/templates/plugin/package.template.json +33 -0
- package/templates/plugin/src/Plugin.template.ts +24 -0
- package/templates/plugin/src/index.template.ts +3 -0
- package/templates/plugin/tsconfig.template.json +43 -0
- package/templates/plugin/vite-env.template.d.ts +16 -0
- package/templates/plugin/vite.config.template.ts +19 -0
|
@@ -0,0 +1,903 @@
|
|
|
1
|
+
import { Options, PlayOptions, Sound, sound, SoundMap, SoundSourceMap } from '@pixi/sound';
|
|
2
|
+
import { gsap } from 'gsap';
|
|
3
|
+
import { Assets, AssetsManifest, UnresolvedAsset } from 'pixi.js';
|
|
4
|
+
import { Signal } from '../../signals';
|
|
5
|
+
import { AudioAsset, Logger } from '../../utils';
|
|
6
|
+
import type { IPlugin } from '../Plugin';
|
|
7
|
+
import { Plugin } from '../Plugin';
|
|
8
|
+
|
|
9
|
+
import { IApplication } from '../../core';
|
|
10
|
+
import { AudioChannel, IAudioChannel } from './AudioChannel';
|
|
11
|
+
import { AudioInstance, IAudioInstance } from './AudioInstance';
|
|
12
|
+
import TweenVars = gsap.TweenVars;
|
|
13
|
+
|
|
14
|
+
export type SoundDetail = { id: string; instance: IAudioInstance; channelName: string };
|
|
15
|
+
export type ChannelVolumeDetail = { channel: IAudioChannel; volume: number };
|
|
16
|
+
export type ChannelMutedDetail = { channel: IAudioChannel; muted: boolean };
|
|
17
|
+
export type ChannelName = 'music' | 'sfx' | 'voiceover' | (string & {});
|
|
18
|
+
|
|
19
|
+
// patch sound.add to fix console.assert error
|
|
20
|
+
sound.add = function (
|
|
21
|
+
source: string | SoundSourceMap,
|
|
22
|
+
sourceOptions?: Options | string | ArrayBuffer | AudioBuffer | HTMLAudioElement | Sound,
|
|
23
|
+
): any {
|
|
24
|
+
if (typeof source === 'object') {
|
|
25
|
+
const results: SoundMap = {};
|
|
26
|
+
|
|
27
|
+
for (const alias in source) {
|
|
28
|
+
// @ts-expect-error _getOptions is private
|
|
29
|
+
const options: Options = this._getOptions(source[alias], sourceOptions as Options);
|
|
30
|
+
|
|
31
|
+
results[alias] = this.add(alias, options);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if (sourceOptions instanceof Sound) {
|
|
40
|
+
// @ts-expect-error _sounds is private
|
|
41
|
+
this._sounds[source] = sourceOptions;
|
|
42
|
+
|
|
43
|
+
return sourceOptions;
|
|
44
|
+
}
|
|
45
|
+
// @ts-expect-error _getOptions is private
|
|
46
|
+
const options: Options = this._getOptions(sourceOptions);
|
|
47
|
+
const sound: Sound = Sound.from(options);
|
|
48
|
+
// @ts-expect-error _sounds is private
|
|
49
|
+
this._sounds[source] = sound;
|
|
50
|
+
|
|
51
|
+
return sound;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export interface IAudioManagerPlugin<C extends ChannelName = ChannelName> extends IPlugin {
|
|
55
|
+
onSoundStarted: Signal<(detail: SoundDetail) => void>;
|
|
56
|
+
onSoundEnded: Signal<(detail: SoundDetail) => void>;
|
|
57
|
+
onMasterVolumeChanged: Signal<(volume: number) => void>;
|
|
58
|
+
onChannelVolumeChanged: Signal<(detail: ChannelVolumeDetail) => void>;
|
|
59
|
+
onMuted: Signal<(muted: boolean) => void>;
|
|
60
|
+
onChannelMuted: Signal<(detail: ChannelMutedDetail) => void>;
|
|
61
|
+
|
|
62
|
+
masterVolume: number;
|
|
63
|
+
muted: boolean;
|
|
64
|
+
channels: Map<string, IAudioChannel>;
|
|
65
|
+
music: IAudioChannel;
|
|
66
|
+
sfx: IAudioChannel;
|
|
67
|
+
voiceover: IAudioChannel;
|
|
68
|
+
vo: IAudioChannel;
|
|
69
|
+
|
|
70
|
+
readonly paused: boolean;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The WebAudio context sounds are actually played on. Anything building
|
|
74
|
+
* `PlayOptions.filters` MUST create its nodes on this context: WebAudio
|
|
75
|
+
* refuses to connect nodes across contexts, and caper may not share a
|
|
76
|
+
* `@pixi/sound` instance (and therefore a context) with the consuming app.
|
|
77
|
+
* `undefined` under the htmlaudio fallback, where filters do not apply.
|
|
78
|
+
*/
|
|
79
|
+
readonly audioContext: AudioContext | undefined;
|
|
80
|
+
|
|
81
|
+
createChannel(name: string): void;
|
|
82
|
+
|
|
83
|
+
play(soundId: AudioAsset, channelName: C, options?: PlayOptions): Promise<IAudioInstance>;
|
|
84
|
+
|
|
85
|
+
isPlaying(soundId: AudioAsset, channelName: C): boolean;
|
|
86
|
+
|
|
87
|
+
load(soundId: AudioAsset | AudioAsset[], channelName: C, options?: PlayOptions): void;
|
|
88
|
+
|
|
89
|
+
stop(soundId: AudioAsset, channelName: C): IAudioInstance | undefined;
|
|
90
|
+
|
|
91
|
+
setChannelVolume(channelName: C | C[], volume: number): void;
|
|
92
|
+
|
|
93
|
+
getChannel(name: C): IAudioChannel | undefined;
|
|
94
|
+
|
|
95
|
+
addAllFromManifest(manifest: AssetsManifest): void;
|
|
96
|
+
|
|
97
|
+
addAllFromBundle(bundleName: string, manifest?: AssetsManifest | string | undefined): void;
|
|
98
|
+
|
|
99
|
+
add(soundAsset: UnresolvedAsset): void;
|
|
100
|
+
|
|
101
|
+
fade(soundId: AudioAsset, channelName: C, props?: gsap.TweenVars): Promise<gsap.core.Tween | null>;
|
|
102
|
+
|
|
103
|
+
fadeIn(soundId: AudioAsset, channelName: C, props?: gsap.TweenVars): Promise<gsap.core.Tween | null>;
|
|
104
|
+
|
|
105
|
+
fadeOut(soundId: AudioAsset, channelName: C, props?: gsap.TweenVars): Promise<gsap.core.Tween | null>;
|
|
106
|
+
|
|
107
|
+
crossFade(
|
|
108
|
+
outSoundId: AudioAsset,
|
|
109
|
+
inSoundId: AudioAsset,
|
|
110
|
+
channelName: C,
|
|
111
|
+
duration?: number,
|
|
112
|
+
): Promise<gsap.core.Tween | null>;
|
|
113
|
+
|
|
114
|
+
mute(): void;
|
|
115
|
+
|
|
116
|
+
unmute(): void;
|
|
117
|
+
|
|
118
|
+
pause(): void;
|
|
119
|
+
|
|
120
|
+
resume(): void;
|
|
121
|
+
|
|
122
|
+
suspend(): void;
|
|
123
|
+
|
|
124
|
+
restore(): Promise<void>;
|
|
125
|
+
|
|
126
|
+
getAudioInstance(soundId: AudioAsset, channelName: C): IAudioInstance | undefined;
|
|
127
|
+
|
|
128
|
+
stopAll(fade?: boolean, duration?: number, props?: TweenVars): void;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* AudioManager is a class that manages audio playback in the application.
|
|
133
|
+
* It provides methods to play, stop, fade in/out, and crossfade sounds.
|
|
134
|
+
* It also allows you to create and manage audio channels.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* const audioManager = new AudioManager();
|
|
138
|
+
* audioManager.play('soundId', 'music');
|
|
139
|
+
*/
|
|
140
|
+
export class AudioManagerPlugin<C extends ChannelName = ChannelName> extends Plugin implements IAudioManagerPlugin<C> {
|
|
141
|
+
// signals
|
|
142
|
+
/**
|
|
143
|
+
* Signal that is emitted when a sound starts playing.
|
|
144
|
+
* The callback function receives a SoundDetail object.
|
|
145
|
+
*/
|
|
146
|
+
public onSoundStarted: Signal<(detail: SoundDetail) => void> = new Signal<(detail: SoundDetail) => void>();
|
|
147
|
+
/**
|
|
148
|
+
* Signal that is emitted when a sound ends.
|
|
149
|
+
* The callback function receives a SoundDetail object.
|
|
150
|
+
*/
|
|
151
|
+
public onSoundEnded: Signal<(detail: SoundDetail) => void> = new Signal<(detail: SoundDetail) => void>();
|
|
152
|
+
/**
|
|
153
|
+
* Signal that is emitted when the system is muted or unmuted.
|
|
154
|
+
*/
|
|
155
|
+
public onMuted: Signal<(muted: boolean) => void> = new Signal<(muted: boolean) => void>();
|
|
156
|
+
/**
|
|
157
|
+
* Signal that is emitted when the master volume changes.
|
|
158
|
+
* The callback function receives the new volume as a number.
|
|
159
|
+
*/
|
|
160
|
+
public onMasterVolumeChanged: Signal<(volume: number) => void> = new Signal<(volume: number) => void>();
|
|
161
|
+
/**
|
|
162
|
+
* Signal that is emitted when a channel's volume changes.
|
|
163
|
+
* The callback function receives a ChannelVolumeDetail object.
|
|
164
|
+
*/
|
|
165
|
+
public onChannelVolumeChanged: Signal<(detail: ChannelVolumeDetail) => void> = new Signal<
|
|
166
|
+
(detail: ChannelVolumeDetail) => void
|
|
167
|
+
>();
|
|
168
|
+
/**
|
|
169
|
+
* Signal that is emitted when a channel is muted or unmuted.
|
|
170
|
+
* The callback function receives a ChannelMutedDetail object.
|
|
171
|
+
*/
|
|
172
|
+
public onChannelMuted: Signal<(detail: ChannelMutedDetail) => void> = new Signal<
|
|
173
|
+
(detail: ChannelMutedDetail) => void
|
|
174
|
+
>();
|
|
175
|
+
|
|
176
|
+
private _storedVolume: number | undefined = undefined;
|
|
177
|
+
private _paused: boolean = false;
|
|
178
|
+
private _idMap: Map<string, string> = new Map();
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Creates a new AudioManager instance.
|
|
182
|
+
* @param {string} id - The ID of the AudioManager. Default is 'AudioManager'.
|
|
183
|
+
*/
|
|
184
|
+
public constructor(id: string = 'audio') {
|
|
185
|
+
super(id);
|
|
186
|
+
|
|
187
|
+
this.createChannel('music');
|
|
188
|
+
this.createChannel('sfx');
|
|
189
|
+
this.createChannel('voiceover');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private _masterVolume: number = 1;
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* The WebAudio context sounds actually play on — see
|
|
196
|
+
* {@link IAudioManagerPlugin.audioContext}. Exposed so consumers can build
|
|
197
|
+
* `PlayOptions.filters` on the right context instead of guessing.
|
|
198
|
+
*/
|
|
199
|
+
get audioContext(): AudioContext | undefined {
|
|
200
|
+
return sound.context?.audioContext;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Gets the master volume.
|
|
205
|
+
* @returns {number} The master volume.
|
|
206
|
+
*/
|
|
207
|
+
get masterVolume(): number {
|
|
208
|
+
return this._masterVolume;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Sets the master volume.
|
|
213
|
+
* @param {number} value - The new master volume.
|
|
214
|
+
*/
|
|
215
|
+
set masterVolume(value: number) {
|
|
216
|
+
this._masterVolume = value;
|
|
217
|
+
this._channels.forEach((channel) => channel.updateVolume());
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private _muted: boolean = false;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Gets whether the audio is muted.
|
|
224
|
+
* @returns {boolean} True if the audio is muted, false otherwise.
|
|
225
|
+
*/
|
|
226
|
+
get muted(): boolean {
|
|
227
|
+
return this._muted;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Sets whether the audio is muted.
|
|
232
|
+
* @param {boolean} value - True to mute the audio, false to unmute.
|
|
233
|
+
*/
|
|
234
|
+
set muted(value: boolean) {
|
|
235
|
+
this._muted = value;
|
|
236
|
+
this._setMuted();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private _channels: Map<C, IAudioChannel> = new Map();
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Gets the map of audio channels.
|
|
243
|
+
* @returns {Map<string, IAudioChannel>} The map of audio channels.
|
|
244
|
+
*/
|
|
245
|
+
get channels(): Map<string, IAudioChannel> {
|
|
246
|
+
return this._channels;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
get music(): IAudioChannel {
|
|
250
|
+
return this._channels.get('music' as C)!;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
get sfx(): IAudioChannel {
|
|
254
|
+
return this._channels.get('sfx' as C)!;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
get voiceover(): IAudioChannel {
|
|
258
|
+
return this._channels.get('voiceover' as C)!;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
get vo(): IAudioChannel {
|
|
262
|
+
return this._channels.get('voiceover' as C)!;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
public destroy(): void {
|
|
266
|
+
this._channels.forEach((channel) => {
|
|
267
|
+
channel.destroy();
|
|
268
|
+
});
|
|
269
|
+
this._channels.clear();
|
|
270
|
+
this.onSoundStarted.disconnectAll();
|
|
271
|
+
this.onSoundEnded.disconnectAll();
|
|
272
|
+
this.onMuted.disconnectAll();
|
|
273
|
+
this.onMasterVolumeChanged.disconnectAll();
|
|
274
|
+
this.onChannelVolumeChanged.disconnectAll();
|
|
275
|
+
|
|
276
|
+
super.destroy();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Initializes the AudioManager.
|
|
281
|
+
* @param {IApplication} app
|
|
282
|
+
* @returns {Promise<void>}
|
|
283
|
+
*/
|
|
284
|
+
public initialize(_options: any, app: IApplication): Promise<void> {
|
|
285
|
+
sound.disableAutoPause = true;
|
|
286
|
+
if (typeof app?.manifest === 'object') {
|
|
287
|
+
this.addAllFromManifest(app.manifest);
|
|
288
|
+
}
|
|
289
|
+
return Promise.resolve();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Creates a new audio channel.
|
|
294
|
+
* @param {string} name
|
|
295
|
+
*/
|
|
296
|
+
public createChannel(name: string): void {
|
|
297
|
+
if (this._channels.has(name as C)) {
|
|
298
|
+
throw new Error(`Channel with name ${name} already exists.`);
|
|
299
|
+
}
|
|
300
|
+
const channel = new AudioChannel<C>(name as C, this);
|
|
301
|
+
this._channels.set(name as C, channel);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Sets the volume of the specified channel.
|
|
306
|
+
* @param {ChannelName|ChannelName[]} channelName
|
|
307
|
+
* @param {number} volume
|
|
308
|
+
*/
|
|
309
|
+
public setChannelVolume(channelName: C | C[], volume: number): void {
|
|
310
|
+
if (!Array.isArray(channelName)) {
|
|
311
|
+
channelName = [channelName];
|
|
312
|
+
}
|
|
313
|
+
channelName.forEach((name) => this._setChannelVolume(name as C, volume));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Gets the audio channel with the specified name.
|
|
318
|
+
* @param {C} name
|
|
319
|
+
* @returns {IAudioChannel | undefined}
|
|
320
|
+
*/
|
|
321
|
+
public getChannel(name: C): IAudioChannel | undefined {
|
|
322
|
+
return this._channels.get(name);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Mutes the audio.
|
|
327
|
+
*/
|
|
328
|
+
public mute() {
|
|
329
|
+
this._muted = true;
|
|
330
|
+
this._setMuted();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Unmutes the audio.
|
|
335
|
+
*/
|
|
336
|
+
public unmute() {
|
|
337
|
+
this._muted = false;
|
|
338
|
+
this._setMuted();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Pauses the audio.
|
|
343
|
+
*/
|
|
344
|
+
public pause(): void {
|
|
345
|
+
this._paused = true;
|
|
346
|
+
this._setPaused();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Resumes the audio.
|
|
351
|
+
*/
|
|
352
|
+
public resume(): void {
|
|
353
|
+
this._paused = false;
|
|
354
|
+
this._setPaused();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
get paused(): boolean {
|
|
358
|
+
return this._paused;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Adds all sound assets from the specified manifest.
|
|
363
|
+
* @param {AssetsManifest} manifest
|
|
364
|
+
*/
|
|
365
|
+
public addAllFromManifest(manifest: AssetsManifest) {
|
|
366
|
+
manifest.bundles.forEach((bundle) => {
|
|
367
|
+
this.addAllFromBundle(bundle.name, manifest);
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private _addPrefix(asset: UnresolvedAsset): void {
|
|
372
|
+
const prefix = Assets.resolver.basePath.replace('./', '');
|
|
373
|
+
if (Array.isArray(asset.src)) {
|
|
374
|
+
const mappedSrc = asset.src.map((s) => {
|
|
375
|
+
return (s as string).startsWith(prefix) ? s : `${prefix}/${s}`;
|
|
376
|
+
});
|
|
377
|
+
asset.src = mappedSrc;
|
|
378
|
+
} else {
|
|
379
|
+
asset.src = asset.src?.startsWith(prefix) ? asset.src : `${prefix}/${asset.src}`;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Adds all sound assets from the specified bundle.
|
|
385
|
+
* @param {string} bundleName
|
|
386
|
+
* @param {AssetsManifest | string | undefined} manifest
|
|
387
|
+
*/
|
|
388
|
+
public addAllFromBundle(bundleName: string, manifest?: AssetsManifest | string | undefined) {
|
|
389
|
+
if (!manifest) {
|
|
390
|
+
manifest = this.app.manifest;
|
|
391
|
+
}
|
|
392
|
+
if (manifest === undefined || typeof manifest === 'string') {
|
|
393
|
+
throw new Error('Manifest is not available');
|
|
394
|
+
}
|
|
395
|
+
const bundle = manifest.bundles.find((b) => b.name === bundleName);
|
|
396
|
+
if (bundle === undefined) {
|
|
397
|
+
throw new Error(`Bundle with name ${bundleName} does not exist.`);
|
|
398
|
+
}
|
|
399
|
+
if (!Array.isArray(bundle?.assets)) {
|
|
400
|
+
bundle.assets = [bundle.assets];
|
|
401
|
+
}
|
|
402
|
+
bundle.assets.forEach((asset) => {
|
|
403
|
+
this._addPrefix(asset);
|
|
404
|
+
// detect sound assets by asset.src extension
|
|
405
|
+
let src = asset.src;
|
|
406
|
+
if (Array.isArray(src)) {
|
|
407
|
+
src = src[0];
|
|
408
|
+
}
|
|
409
|
+
const ext = (src as string).split('.').pop();
|
|
410
|
+
if (ext === 'mp3' || ext === 'ogg' || ext === 'wav' || ext === 'webm') {
|
|
411
|
+
this.add(asset);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Adds a sound asset to the AudioManager.
|
|
418
|
+
* @param {UnresolvedAsset} soundAsset
|
|
419
|
+
*/
|
|
420
|
+
public add(soundAsset: UnresolvedAsset): void {
|
|
421
|
+
let alias = soundAsset.alias;
|
|
422
|
+
if (!Array.isArray(soundAsset.alias)) {
|
|
423
|
+
alias = [soundAsset.alias as string];
|
|
424
|
+
}
|
|
425
|
+
if (!alias) return;
|
|
426
|
+
|
|
427
|
+
const obj: SoundSourceMap = {};
|
|
428
|
+
let hasNew = false;
|
|
429
|
+
(alias as string[]).forEach((a: string) => {
|
|
430
|
+
if (a === undefined || sound.exists(a)) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
// @ts-expect-error soundAsset is not a string error
|
|
434
|
+
obj[a] = soundAsset.src;
|
|
435
|
+
hasNew = true;
|
|
436
|
+
});
|
|
437
|
+
// Skip the sound.add() call if every alias is already registered.
|
|
438
|
+
// Calling sound.add({}) trips a console.assert inside @pixi/sound,
|
|
439
|
+
// which fires on every scene load that re-processes an already-added bundle.
|
|
440
|
+
if (hasNew) sound.add(obj);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
isPlaying(soundId: string, channelName: C): boolean {
|
|
444
|
+
const channel = this._channels.get(channelName);
|
|
445
|
+
if (channel) {
|
|
446
|
+
return channel.get(soundId)?.isPlaying === true;
|
|
447
|
+
}
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Plays a sound with the specified ID in the specified channel.
|
|
453
|
+
* @param {string} soundId
|
|
454
|
+
* @param {C} channelName
|
|
455
|
+
* @param {PlayOptions} options
|
|
456
|
+
* @returns {Promise<IAudioInstance>}
|
|
457
|
+
*/
|
|
458
|
+
/**
|
|
459
|
+
* Drops any filter whose nodes belong to a different `AudioContext` than the
|
|
460
|
+
* one playback runs on.
|
|
461
|
+
*
|
|
462
|
+
* WebAudio refuses cross-context `connect()`, and @pixi/sound wires filters
|
|
463
|
+
* deep inside `WebAudioInstance.play()` — so one foreign filter throws
|
|
464
|
+
* `InvalidAccessError` from a place the caller cannot catch, and the sound
|
|
465
|
+
* never plays AT ALL. Silent-and-unattributable is the worst failure mode we
|
|
466
|
+
* can hand an app, so prefer dry audio plus a pointed error: the sound is
|
|
467
|
+
* still heard, and the log says exactly how to fix it. This is easy to hit
|
|
468
|
+
* because an app bundling its own `@pixi/sound` gets a different context than
|
|
469
|
+
* caper's — build filters on {@link audioContext}.
|
|
470
|
+
*/
|
|
471
|
+
private _usableFilters(filters?: PlayOptions['filters']): PlayOptions['filters'] {
|
|
472
|
+
if (!filters?.length) {
|
|
473
|
+
return filters;
|
|
474
|
+
}
|
|
475
|
+
const context = this.audioContext;
|
|
476
|
+
if (!context) {
|
|
477
|
+
return filters;
|
|
478
|
+
}
|
|
479
|
+
const usable = filters.filter((filter) => {
|
|
480
|
+
// A Filter exposes its input as `destination` and its output as `source`.
|
|
481
|
+
const node = (filter as unknown as { destination?: AudioNode; source?: AudioNode })?.destination;
|
|
482
|
+
return !node?.context || node.context === context;
|
|
483
|
+
});
|
|
484
|
+
if (usable.length !== filters.length) {
|
|
485
|
+
Logger.error(
|
|
486
|
+
'AudioManager: ignoring filter(s) built on a different AudioContext — playing dry. ' +
|
|
487
|
+
'Build filter nodes on `app.audio.audioContext` (an app bundling its own copy of ' +
|
|
488
|
+
'@pixi/sound gets a separate context).',
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
return usable.length ? usable : undefined;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
public async play(soundId: AudioAsset, channelName: C = 'sfx' as C, options?: PlayOptions): Promise<IAudioInstance> {
|
|
495
|
+
if (this._idMap.has(soundId)) {
|
|
496
|
+
soundId = this._idMap.get(soundId) as string;
|
|
497
|
+
}
|
|
498
|
+
const channel = this._channels.get(channelName);
|
|
499
|
+
if (channel) {
|
|
500
|
+
soundId = this._verifySoundId(soundId);
|
|
501
|
+
const audioInstance = channel.add(
|
|
502
|
+
soundId,
|
|
503
|
+
new AudioInstance<C>(soundId, channel, this as IAudioManagerPlugin<C>),
|
|
504
|
+
);
|
|
505
|
+
// @pixi/sound starts playback at options.volume the instant sound.play()
|
|
506
|
+
// is called, synchronously and before the await below resolves. The
|
|
507
|
+
// channel × masterVolume correction previously only landed via
|
|
508
|
+
// audioInstance.media/volume AFTER the await, a microtask too late —
|
|
509
|
+
// producing an audible click/pop transient even when the correct
|
|
510
|
+
// steady-state volume is 0 (master muted or channel muted). Compute the
|
|
511
|
+
// real effective volume/mute state up front and hand it to sound.play
|
|
512
|
+
// so the very first sample already plays at the right level.
|
|
513
|
+
const startVolume = (options?.volume ?? 1) * channel.volume * this.masterVolume;
|
|
514
|
+
const mediaInstance = await sound.play(soundId, {
|
|
515
|
+
...options,
|
|
516
|
+
filters: this._usableFilters(options?.filters),
|
|
517
|
+
volume: channel.muted ? 0 : startVolume,
|
|
518
|
+
muted: channel.muted,
|
|
519
|
+
});
|
|
520
|
+
audioInstance.media = mediaInstance;
|
|
521
|
+
if (options?.volume !== undefined) {
|
|
522
|
+
// Route the per-play volume through AudioInstance's setter so the
|
|
523
|
+
// channel × masterVolume math applies. Writing mediaInstance.volume
|
|
524
|
+
// directly bypassed it — any explicit PlayOptions.volume ignored the
|
|
525
|
+
// master volume entirely (master 0 never silenced SFX).
|
|
526
|
+
audioInstance.volume = options.volume;
|
|
527
|
+
}
|
|
528
|
+
audioInstance.onStart.connect(() => {
|
|
529
|
+
this._soundStarted(soundId, audioInstance, channelName);
|
|
530
|
+
});
|
|
531
|
+
audioInstance.onEnd.connect(() => {
|
|
532
|
+
channel.removeInstance(audioInstance);
|
|
533
|
+
this._soundEnded(soundId, audioInstance, channelName);
|
|
534
|
+
});
|
|
535
|
+
audioInstance.onStop.connect(() => {
|
|
536
|
+
channel.removeInstance(audioInstance);
|
|
537
|
+
});
|
|
538
|
+
audioInstance.isPlaying = true;
|
|
539
|
+
return audioInstance;
|
|
540
|
+
} else {
|
|
541
|
+
throw new Error(`Channel ${channelName} does not exist.`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Stops a sound with the specified ID in the specified channel.
|
|
547
|
+
* @param {AudioAsset} soundId
|
|
548
|
+
* @param {C} channelName
|
|
549
|
+
* @returns {IAudioInstance | undefined}
|
|
550
|
+
*/
|
|
551
|
+
public stop(soundId: AudioAsset, channelName: C = 'sfx' as C): IAudioInstance | undefined {
|
|
552
|
+
const channel = this._channels.get(channelName);
|
|
553
|
+
if (channel) {
|
|
554
|
+
return channel.remove(soundId);
|
|
555
|
+
} else {
|
|
556
|
+
throw new Error(`Channel ${channelName} does not exist.`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Fades in a sound with the specified ID in the specified channel.
|
|
562
|
+
* @param {AudioAsset} soundId
|
|
563
|
+
* @param {C} channelName
|
|
564
|
+
* @param {gsap.TweenVars} props
|
|
565
|
+
* @returns {Promise<gsap.core.Tween | null>}
|
|
566
|
+
*/
|
|
567
|
+
public async fadeIn(
|
|
568
|
+
soundId: AudioAsset,
|
|
569
|
+
channelName: C = 'music' as C,
|
|
570
|
+
props: gsap.TweenVars,
|
|
571
|
+
): Promise<gsap.core.Tween | null> {
|
|
572
|
+
const channel = this._channels.get(channelName);
|
|
573
|
+
if (channel) {
|
|
574
|
+
soundId = this._verifySoundId(soundId);
|
|
575
|
+
}
|
|
576
|
+
if (!channel?.get(soundId)) {
|
|
577
|
+
await this.play(soundId, channelName, { volume: 0 });
|
|
578
|
+
}
|
|
579
|
+
if (props?.volume === 0) {
|
|
580
|
+
Logger.warn('fadeIn volume is 0', soundId, channelName, props);
|
|
581
|
+
}
|
|
582
|
+
const fadeProps = Object.assign({ volume: props?.volume ?? 1, duration: 1, ease: 'linear.easeNone' }, props);
|
|
583
|
+
return this.fade(soundId, channelName, fadeProps);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Fades out a sound with the specified ID in the specified channel.
|
|
588
|
+
* @param {AudioAsset} soundId
|
|
589
|
+
* @param {C} channelName
|
|
590
|
+
* @param {Partial<gsap.TweenVars>} props
|
|
591
|
+
* @returns {Promise<gsap.core.Tween | null>}
|
|
592
|
+
*/
|
|
593
|
+
public async fadeOut(
|
|
594
|
+
soundId: AudioAsset,
|
|
595
|
+
channelName: C = 'music' as C,
|
|
596
|
+
props: Partial<gsap.TweenVars> = { volume: 0 },
|
|
597
|
+
): Promise<gsap.core.Tween | null> {
|
|
598
|
+
if (!props) {
|
|
599
|
+
props = {};
|
|
600
|
+
}
|
|
601
|
+
if (props?.volume === undefined) {
|
|
602
|
+
props.volume = 0;
|
|
603
|
+
}
|
|
604
|
+
if (props?.volume > 0) {
|
|
605
|
+
Logger.warn('fadeOut volume should probably be 0', soundId, channelName, props);
|
|
606
|
+
}
|
|
607
|
+
const fadeProps = Object.assign({ volume: 0, duration: 1, ease: 'linear.easeNone' }, props);
|
|
608
|
+
return this.fade(soundId, channelName, fadeProps, true);
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Crossfades between two sounds in the specified channel.
|
|
613
|
+
* @param {AudioAsset} outSoundId
|
|
614
|
+
* @param {AudioAsset} inSoundId
|
|
615
|
+
* @param {ChannelName} channelName
|
|
616
|
+
* @param {number} duration
|
|
617
|
+
* @returns {Promise<gsap.core.Tween | null>}
|
|
618
|
+
*/
|
|
619
|
+
public async crossFade(
|
|
620
|
+
outSoundId: AudioAsset,
|
|
621
|
+
inSoundId: AudioAsset,
|
|
622
|
+
channelName: ChannelName = 'music',
|
|
623
|
+
duration: number = 2,
|
|
624
|
+
): Promise<gsap.core.Tween | null> {
|
|
625
|
+
const crossFadeProps = { duration, ease: 'linear.easeNone' };
|
|
626
|
+
void this.fadeOut(outSoundId, channelName as C, crossFadeProps);
|
|
627
|
+
return this.fadeIn(inSoundId, channelName as C, crossFadeProps);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Fades a sound with the specified ID in the specified channel.
|
|
632
|
+
* @param {AudioAsset} soundId
|
|
633
|
+
* @param {ChannelName} channelName
|
|
634
|
+
* @param {gsap.TweenVars} props
|
|
635
|
+
* @param {boolean} stopOnComplete
|
|
636
|
+
* @returns {Promise<gsap.core.Tween | null>}
|
|
637
|
+
*/
|
|
638
|
+
public async fade(
|
|
639
|
+
soundId: AudioAsset,
|
|
640
|
+
channelName: ChannelName = 'music',
|
|
641
|
+
props: gsap.TweenVars,
|
|
642
|
+
stopOnComplete: boolean = false,
|
|
643
|
+
): Promise<gsap.core.Tween | null> {
|
|
644
|
+
const channel = this._channels.get(channelName as C);
|
|
645
|
+
if (channel) {
|
|
646
|
+
soundId = this._verifySoundId(soundId);
|
|
647
|
+
}
|
|
648
|
+
const soundInstance = channel?.get(soundId);
|
|
649
|
+
if (soundInstance) {
|
|
650
|
+
const tween = gsap.to(soundInstance, props);
|
|
651
|
+
tween.eventCallback('onComplete', () => {
|
|
652
|
+
if (stopOnComplete) {
|
|
653
|
+
this.stop(soundId, channelName as C);
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
return tween;
|
|
657
|
+
}
|
|
658
|
+
return null;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Restores the audio state after it has been suspended.
|
|
663
|
+
*/
|
|
664
|
+
public async restore() {
|
|
665
|
+
const ctx = sound?.context?.audioContext;
|
|
666
|
+
if (ctx) {
|
|
667
|
+
await ctx.resume();
|
|
668
|
+
}
|
|
669
|
+
this.resume();
|
|
670
|
+
if (this._storedVolume !== undefined) {
|
|
671
|
+
this.masterVolume = this._storedVolume;
|
|
672
|
+
}
|
|
673
|
+
this._channels.forEach((channel) => {
|
|
674
|
+
channel.restore();
|
|
675
|
+
});
|
|
676
|
+
this.muted = this._muted;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Suspends the audio by setting the master volume to 0 and pausing all sounds.
|
|
681
|
+
*/
|
|
682
|
+
public suspend() {
|
|
683
|
+
this._storedVolume = this._masterVolume;
|
|
684
|
+
this.masterVolume = 0;
|
|
685
|
+
this.pause();
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
public getAudioInstance(soundId: AudioAsset, channelName: C = 'sfx' as C): IAudioInstance | undefined {
|
|
689
|
+
const channel = this._channels.get(channelName);
|
|
690
|
+
soundId = this._verifySoundId(soundId);
|
|
691
|
+
if (channel) {
|
|
692
|
+
return channel.get(soundId);
|
|
693
|
+
} else {
|
|
694
|
+
throw new Error(`Channel ${channelName} does not exist.`);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
public load(soundId: AudioAsset | AudioAsset[], channelName: C = 'sfx' as C, options?: PlayOptions): void {
|
|
699
|
+
if (!Array.isArray(soundId)) {
|
|
700
|
+
soundId = [soundId];
|
|
701
|
+
}
|
|
702
|
+
for (let id of soundId) {
|
|
703
|
+
if (this._idMap.has(id)) {
|
|
704
|
+
soundId = this._idMap.get(id) as string;
|
|
705
|
+
}
|
|
706
|
+
const channel = this._channels.get(channelName);
|
|
707
|
+
if (channel) {
|
|
708
|
+
id = this._verifySoundId(id);
|
|
709
|
+
// const audioInstance = new AudioInstance(id, channel, this);
|
|
710
|
+
const soundInstance = sound.find(id);
|
|
711
|
+
soundInstance.options = { ...options, autoPlay: false };
|
|
712
|
+
const audioInstance = channel.add(id, new AudioInstance<C>(id, channel, this as IAudioManagerPlugin<C>));
|
|
713
|
+
audioInstance.media = soundInstance.instances[0];
|
|
714
|
+
audioInstance.pause();
|
|
715
|
+
} else {
|
|
716
|
+
throw new Error(`Channel ${channelName} does not exist.`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
public stopAll(fade: boolean = false, duration: number = 1, props: TweenVars = {}) {
|
|
722
|
+
if (fade) {
|
|
723
|
+
// get all playing sounds
|
|
724
|
+
const playingSounds: IAudioInstance[] = [];
|
|
725
|
+
this._channels.forEach((channel) => {
|
|
726
|
+
channel.instances.forEach((instance) => {
|
|
727
|
+
if (instance.isPlaying) {
|
|
728
|
+
instance.storedVolume = instance.volume;
|
|
729
|
+
playingSounds.push(instance);
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
if (playingSounds.length > 0) {
|
|
734
|
+
gsap.to(playingSounds, {
|
|
735
|
+
volume: 0,
|
|
736
|
+
duration,
|
|
737
|
+
...props,
|
|
738
|
+
onComplete: () => {
|
|
739
|
+
playingSounds.forEach((instance) => {
|
|
740
|
+
instance.stop();
|
|
741
|
+
instance.volume = instance.storedVolume;
|
|
742
|
+
});
|
|
743
|
+
},
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
sound.stopAll();
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
protected getCoreSignals(): string[] {
|
|
752
|
+
return [
|
|
753
|
+
'onSoundStarted',
|
|
754
|
+
'onSoundEnded',
|
|
755
|
+
'onMuted',
|
|
756
|
+
'onMasterVolumeChanged',
|
|
757
|
+
'onChannelVolumeChanged',
|
|
758
|
+
'onChannelMuted',
|
|
759
|
+
];
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
private _verifySoundId(soundId: AudioAsset): string {
|
|
763
|
+
const originalSoundId = soundId;
|
|
764
|
+
if (this._idMap.has(soundId)) {
|
|
765
|
+
return this._idMap.get(soundId) as string;
|
|
766
|
+
}
|
|
767
|
+
// try appending .mp3 or .ogg
|
|
768
|
+
if (!sound.exists(soundId)) {
|
|
769
|
+
// Logger.log(`Sound with ID ${soundId} does not exist. Trying different extensions.`);
|
|
770
|
+
if (sound.exists(soundId + '.mp3')) {
|
|
771
|
+
soundId += '.mp3';
|
|
772
|
+
} else if (sound.exists(soundId + '.ogg')) {
|
|
773
|
+
soundId += '.ogg';
|
|
774
|
+
} else if (sound.exists(soundId + '.wav')) {
|
|
775
|
+
soundId += '.wav';
|
|
776
|
+
} else {
|
|
777
|
+
soundId = originalSoundId;
|
|
778
|
+
let sound = Assets.get(soundId);
|
|
779
|
+
if (!sound) {
|
|
780
|
+
soundId = originalSoundId + '.mp3';
|
|
781
|
+
sound = Assets.get(soundId);
|
|
782
|
+
}
|
|
783
|
+
if (!sound) {
|
|
784
|
+
soundId = originalSoundId + '.ogg';
|
|
785
|
+
sound = Assets.get(soundId);
|
|
786
|
+
}
|
|
787
|
+
if (!sound) {
|
|
788
|
+
soundId = originalSoundId + '.wav';
|
|
789
|
+
sound = Assets.get(soundId);
|
|
790
|
+
}
|
|
791
|
+
if (sound) {
|
|
792
|
+
this._findAndAddFromManifest(soundId, sound);
|
|
793
|
+
} else {
|
|
794
|
+
throw new Error(`Sound with ID ${soundId} does not exist.`);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
this._idMap.set(soundId, soundId);
|
|
799
|
+
return soundId;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
private _findAndAddFromManifest(soundId: AudioAsset, sound: Sound) {
|
|
803
|
+
const manifest = this.app.manifest;
|
|
804
|
+
if (manifest === undefined || typeof manifest === 'string') {
|
|
805
|
+
throw new Error('Manifest is not available');
|
|
806
|
+
}
|
|
807
|
+
for (let i = 0; i < manifest.bundles.length; i++) {
|
|
808
|
+
const bundle = manifest.bundles[i];
|
|
809
|
+
if (!Array.isArray(bundle?.assets)) {
|
|
810
|
+
bundle.assets = [bundle.assets];
|
|
811
|
+
}
|
|
812
|
+
for (let j = 0; j < bundle.assets.length; j++) {
|
|
813
|
+
const asset = bundle.assets[j];
|
|
814
|
+
this._addPrefix(asset);
|
|
815
|
+
// detect sound assets by asset.src extension
|
|
816
|
+
const src = asset.src;
|
|
817
|
+
const filename = sound.url.split('/').pop() ?? '';
|
|
818
|
+
if (Array.isArray(src)) {
|
|
819
|
+
for (let s = 0; s < src.length; s++) {
|
|
820
|
+
const urlOrResolvedSrc = src[s];
|
|
821
|
+
let url: string;
|
|
822
|
+
if (typeof urlOrResolvedSrc !== 'string') {
|
|
823
|
+
url = urlOrResolvedSrc.src!;
|
|
824
|
+
} else {
|
|
825
|
+
url = urlOrResolvedSrc as string;
|
|
826
|
+
}
|
|
827
|
+
if (url.includes(filename)) {
|
|
828
|
+
this.add(asset);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
} else {
|
|
833
|
+
if (src?.includes(filename)) {
|
|
834
|
+
this.add(asset);
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* @private
|
|
844
|
+
*/
|
|
845
|
+
private _setMuted(): void {
|
|
846
|
+
if (this._muted) {
|
|
847
|
+
sound.muteAll();
|
|
848
|
+
} else {
|
|
849
|
+
sound.unmuteAll();
|
|
850
|
+
}
|
|
851
|
+
this.onMuted.emit(this._muted);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* @private
|
|
856
|
+
*/
|
|
857
|
+
private _setPaused(): void {
|
|
858
|
+
if (this._paused) {
|
|
859
|
+
sound.pauseAll();
|
|
860
|
+
} else {
|
|
861
|
+
sound.resumeAll();
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Sets the volume of the specified channel.
|
|
867
|
+
* @param {C} channelName
|
|
868
|
+
* @param {number} volume
|
|
869
|
+
* @private
|
|
870
|
+
*/
|
|
871
|
+
private _setChannelVolume(channelName: C, volume: number): void {
|
|
872
|
+
const channel = this._channels.get(channelName);
|
|
873
|
+
if (channel) {
|
|
874
|
+
channel.volume = volume;
|
|
875
|
+
} else {
|
|
876
|
+
throw new Error(`Channel ${channelName} does not exist.`);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Sound started event handler. Emit the onSoundStarted signal.
|
|
882
|
+
* @param {string} id
|
|
883
|
+
* @param {IAudioInstance} instance
|
|
884
|
+
* @param {C} channelName
|
|
885
|
+
* @private
|
|
886
|
+
*/
|
|
887
|
+
private _soundStarted(id: string, instance: IAudioInstance, channelName: C): void {
|
|
888
|
+
// Logger.log(`${id} started in ${channelName} channel`);
|
|
889
|
+
this.onSoundStarted.emit({ id, instance, channelName });
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Sound ended event handler. Emit the onSoundEnded signal.
|
|
894
|
+
* @param {string} id
|
|
895
|
+
* @param {IAudioInstance} instance
|
|
896
|
+
* @param {C} channelName
|
|
897
|
+
* @private
|
|
898
|
+
*/
|
|
899
|
+
private _soundEnded(id: string, instance: IAudioInstance, channelName: C): void {
|
|
900
|
+
// Logger.log(`${id} ended in ${channelName} channel`);
|
|
901
|
+
this.onSoundEnded.emit({ id, instance, channelName });
|
|
902
|
+
}
|
|
903
|
+
}
|