diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..7b19f2d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Preserve the exact bytes checked against upstream SHA-256 hashes. +/src/live2d/vendor/pixi.min.js -text +/src/live2d/vendor/cubism4.min.js -text diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 06e6d8f..c0f6b6a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,6 +62,22 @@ jobs: - name: Build run: npm run build -- --publish never + - name: Packaged resources smoke test (Linux) + if: runner.os == 'Linux' + run: xvfb-run -a npm run test:smoke -- --packaged --no-sandbox + + - name: Packaged resources smoke test (Windows and macOS) + if: runner.os != 'Linux' + run: npm run test:smoke -- --packaged + + - name: Upload packaged smoke screenshots + if: always() + uses: actions/upload-artifact@v4 + with: + name: smoke-packaged-${{ runner.os }} + path: out/smoke-packaged/*.png + if-no-files-found: ignore + - name: Upload artifacts uses: actions/upload-artifact@v4 with: diff --git a/.gitignore b/.gitignore index affaa88..71fcefe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules/ +node_modules dist/ out/ .DS_Store diff --git a/README.ja.md b/README.ja.md index 9ea24a3..2a084bd 100644 --- a/README.ja.md +++ b/README.ja.md @@ -2,14 +2,16 @@ [English](README.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) -**0.4.5 デスクトップ操作の改善:**ペットの位置を記憶し、メニューバーやシステムトレイから再表示できます。終了をキャンセルした場合はすべてのウィンドウを保持します。[更新内容](docs/releases/v0.4.5.md)。[0.4.3 の吹き出し操作](docs/releases/v0.4.3.md)と [0.4.1 の安全性修正](docs/releases/v0.4.1.md)も含みます。 +**0.5.0 コンパニオン更新:**Live2D キャラクターを追加し、ペットのそばで会話できます。触れ合いの反応や返答時の動作も選べます。既存の画像キャラクター、設定、位置の復元はそのまま使えます。[更新内容](docs/releases/v0.5.0.md)。 + +**Live2D は任意の機能です。**対応する書き出し済みモデルと Core ファイルを端末に導入してください。Core とサンプルモデルは同梱されません。[モデル導入・互換性・利用条件](docs/live2d.md#日本語)。 [![Build](https://github.com/TonyNa-code/desktop-pet/actions/workflows/build.yml/badge.svg)](https://github.com/TonyNa-code/desktop-pet/actions/workflows/build.yml) [![Latest Release](https://img.shields.io/github/v/release/TonyNa-code/desktop-pet?label=latest%20release)](https://github.com/TonyNa-code/desktop-pet/releases/latest) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) ![Platforms](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-blue) -Windows / macOS / Linux で動くアニメ風デスクトップペットです。キャラクターパック、多言語UI、チャットモデル連携、任意の音声読み上げに対応しています。Electron で透明な常時手前表示ウィンドウを作り、各キャラクターは spritesheet、プレビュー画像、`character.json` から読み込みます。 +Windows / macOS / Linux で動くアニメ風デスクトップペットです。画像キャラクターパック、任意の Live2D モデル、多言語UI、チャットモデル連携、音声読み上げに対応しています。Electron で透明な常時手前表示ウィンドウを作ります。画像キャラクターは spritesheet と `character.json`、Live2D は `.model3.json` と関連ファイルから読み込みます。

Desktop Pet animated preview @@ -51,6 +53,7 @@ macOS で開発元を確認できないと表示された場合は、app を右 ## 機能 - 透明、フレームなし、常に手前の小さなペットウィンドウ +- Live2D の追加、まばたき・呼吸・触れ合いの反応・返答時の動作の設定 - 表示言語:システムに合わせる、簡体字中国語、English、日本語 - ドラッグ移動中に移動アニメーションを再生 - クリック、ダブルクリック、長押し、マウスホバーに反応 @@ -67,6 +70,7 @@ macOS で開発元を確認できないと表示された場合は、app を右 - 25分集中リマインダー - 30 / 60分休憩リマインダー - 会話機能: + - ペット横の入力欄と上部の吹き出し。横のメニューから設定や終了を選択 - 返信をペットの吹き出しに表示するクイック入力ウィンドウ - 小さなフローティングチャットウィンドウ - 独立した会話設定ウィンドウ @@ -178,7 +182,7 @@ API key はこの端末だけに保存されます。利用できる場合はOS 自動表情モードでは、頭をなでる・長押しする、体を軽くクリックする、ドラッグして置く操作に、それぞれ異なるローカルの反応があります。既存の表情を使い、組み込みキャラクターごとの一言と設定した呼び名で応えます。モデルや音声サービスは呼び出さず、好感度も増えません。表示中の返信や通知を上書きせず、会話や音声を中断しません。**一般 > ふれあいの一言** をオフにすると従来の動作のみになります。 -クリック限定モードは手動のままです。1回のクリックで表情が1つ進み、ダブルクリック・長押しでは追加変更せず、ドラッグ後は選んでいた表情に戻ります。画像の変更やLive2Dの追加はありません。 +クリック限定モードは手動のままです。1回のクリックで表情が1つ進み、ダブルクリック・長押しでは追加変更せず、ドラッグ後は選んでいた表情に戻ります。既存の画像は変更していません。追加モデルの操作は [Live2D ガイド](docs/live2d.md#日本語)をご覧ください。 ## キャラクターパック @@ -233,3 +237,5 @@ assets/characters/ ## License Code is released under the MIT License. See [ASSET_NOTICE.md](ASSET_NOTICE.md) before publicly redistributing artwork assets. + +同梱の中国語・日本語フォントには SIL Open Font License 1.1 が適用されます。[フォントの利用条件](assets/fonts/NOTICE.md)をご覧ください。 diff --git a/README.md b/README.md index f8b14aa..e040fe0 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,16 @@ [English](README.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) -**0.4.5 desktop update:** remember the pet's position, find it from the menu bar or system tray, and keep all windows open when cancelling Quit. [Release notes](docs/releases/v0.4.5.md). Includes the [0.4.3 reply bubble controls](docs/releases/v0.4.3.md) and [0.4.1 safety fixes](docs/releases/v0.4.1.md). +**0.5.0 companion update:** import a Live2D character, talk beside the pet, and customize touch reactions and reply gestures. Existing sprite characters, settings and window recovery remain available. [Release notes](docs/releases/v0.5.0.md). + +**Live2D is optional.** Bring your own compatible exported model and install the supported Core file locally. Neither Core nor sample models are bundled. [Model import, compatibility and licensing](docs/live2d.md). [![Build](https://github.com/TonyNa-code/desktop-pet/actions/workflows/build.yml/badge.svg)](https://github.com/TonyNa-code/desktop-pet/actions/workflows/build.yml) [![Latest Release](https://img.shields.io/github/v/release/TonyNa-code/desktop-pet?label=latest%20release)](https://github.com/TonyNa-code/desktop-pet/releases/latest) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) ![Platforms](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-blue) -A cross-platform anime desktop pet for Windows, macOS, and Linux, with character packs, multilingual UI, chat model integration, and optional voice replies. It uses Electron for a transparent always-on-top pet window, and loads each character from a spritesheet plus a small `character.json` action manifest. +A cross-platform anime desktop pet for Windows, macOS, and Linux, with sprite character packs, optional Live2D models, multilingual UI, chat model integration, and optional voice replies. It uses Electron for a transparent always-on-top pet window. Sprite packs use a spritesheet and a small `character.json` action manifest; Live2D imports use `.model3.json` and its associated files.

Desktop Pet animated preview @@ -51,6 +53,7 @@ If you only want to download and run the app, see [快速上手指南.md](快速 ## Features - Transparent, frameless, always-on-top pet window +- Optional Live2D import with blinking, breathing, touch reactions and configurable reply gestures - Interface language: follow system, Simplified Chinese, English, Japanese - Drag to move, with movement animation while dragging - Click, double-click, long press, and mouse hover reactions @@ -67,6 +70,7 @@ If you only want to download and run the app, see [快速上手指南.md](快速 - 25-minute focus reminder - 30 / 60-minute break reminder - Chat: + - Input beside the character, with replies above it and a visible menu for settings or quitting - Minimal quick input window with replies shown in the pet bubble - Small floating chat window - Separate chat settings window @@ -185,7 +189,7 @@ You can edit or remove any line, or clear the list, then save. Each character ha In automatic expression mode, a head touch or long press, a body tap, and putting the character down after dragging give different local responses using the pack's existing expressions. Built-in characters have distinct short lines, with your preferred name when set. These interactions do not contact a model, play TTS, or increase affection. Short lines do not replace visible replies or reminders, and touches do not interrupt a conversation or voice playback. Turn off **General > Touch responses** for the previous gesture-only behavior. -Click-to-change mode stays manual: one click advances one expression, double-clicks and long presses do not add changes, and dragging restores the expression you selected before the move. Character graphics are unchanged; this is not Live2D. +Click-to-change mode stays manual: one click advances one expression, double-clicks and long presses do not add changes, and dragging restores the expression you selected before the move. Existing sprite artwork is unchanged. For imported models, see the [Live2D guide](docs/live2d.md). ## Character Packs @@ -240,3 +244,5 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, pull request checks, and ## License Code is released under the MIT License. See [ASSET_NOTICE.md](ASSET_NOTICE.md) before publicly redistributing artwork assets. + +Bundled Chinese and Japanese fallback fonts use the SIL Open Font License 1.1. See the [font notices](assets/fonts/NOTICE.md). diff --git a/README.zh-CN.md b/README.zh-CN.md index 97b9096..226eb96 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,14 +2,16 @@ [English](README.md) | [简体中文](README.zh-CN.md) | [日本語](README.ja.md) -**0.4.5 桌面体验更新:**记住桌宠位置,可从菜单栏或系统托盘找回桌宠;取消退出时保留所有窗口。[更新说明](docs/releases/v0.4.5.md)。包含 [0.4.3 气泡交互](docs/releases/v0.4.3.md)与 [0.4.1 安全修复](docs/releases/v0.4.1.md)。 +**0.5.0 陪伴体验更新:**导入 Live2D 角色,在人物身旁对话,自定义触碰反应与回复动作。原有图片角色、设置和窗口找回功能继续保留。[更新说明](docs/releases/v0.5.0.md)。 + +**Live2D 是可选功能。**需要自行导入兼容的导出模型,并在本机安装受支持的 Core 文件。安装包不附带 Core 或示例模型。[模型导入、兼容性与许可说明](docs/live2d.md#简体中文)。 [![Build](https://github.com/TonyNa-code/desktop-pet/actions/workflows/build.yml/badge.svg)](https://github.com/TonyNa-code/desktop-pet/actions/workflows/build.yml) [![Latest Release](https://img.shields.io/github/v/release/TonyNa-code/desktop-pet?label=latest%20release)](https://github.com/TonyNa-code/desktop-pet/releases/latest) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) ![Platforms](https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-blue) -一个可以在 Windows / macOS / Linux 上运行的二次元桌宠项目,支持角色包、多语言界面、聊天模型接入和可选语音朗读。它使用 Electron 做透明置顶窗口,每个角色由 spritesheet、预览图和 `character.json` 动作配置加载。 +一个可以在 Windows / macOS / Linux 上运行的二次元桌宠项目,支持图片角色包、可选 Live2D 模型、多语言界面、聊天模型接入和可选语音朗读。它使用 Electron 做透明置顶窗口;图片角色由 spritesheet、预览图和 `character.json` 动作配置加载,Live2D 角色使用 `.model3.json` 及其配套文件。

Desktop Pet animated preview @@ -51,6 +53,7 @@ macOS 如果提示无法验证开发者,右键 app 选择 `打开`,再确认 ## 功能 - 透明、无边框、置顶小窗口 +- 可选 Live2D 模型导入,支持眨眼、呼吸、触碰反应与自定义回复动作 - 界面语言支持跟随系统、简体中文、English、日本語 - 鼠标拖拽移动,拖动时自动播放移动动画 - 左键点击、双击、长按、鼠标靠近都会触发不同反应 @@ -67,6 +70,7 @@ macOS 如果提示无法验证开发者,右键 app 选择 `打开`,再确认 - 25 分钟专注提醒 - 30 / 60 分钟休息提醒 - 对话功能: + - 人物旁展开输入框,回复显示在人物上方;旁边的菜单可打开设置或退出 - 极简快速输入窗,回复直接显示到桌宠气泡 - 右键打开小型悬浮聊天窗口 - 单独的对话设置窗口 @@ -180,7 +184,7 @@ API key 只保存在本机。应用会优先用系统安全存储加密;如果 自动表情模式下,摸头或长按、轻点身体打招呼、拖动后放下会有不同的本地回应,使用角色已有表情。内置角色各有自己的短句,也会使用你设置的称呼。不调用模型、不朗读、不增加好感度;短句不会覆盖已有回复或提醒,也不会打断对话和语音。在 **通用 > 互动短句** 中可关闭短句,保留原来的动作反馈。 -点击换表情模式保持手动:一次点击只换一个表情,双击和长按不会额外改变,拖动后恢复原先选中的表情。本次不改动角色图片,也不是 Live2D。 +点击换表情模式保持手动:一次点击只换一个表情,双击和长按不会额外改变,拖动后恢复原先选中的表情。原有角色图片保持不变,导入模型的使用方式见 [Live2D 指南](docs/live2d.md#简体中文)。 ## 角色包 @@ -237,3 +241,5 @@ assets/characters/ ## 许可证 Code is released under the MIT License. See [ASSET_NOTICE.md](ASSET_NOTICE.md) before publicly redistributing artwork assets. + +内置中日文备用字体采用 SIL Open Font License 1.1,详见[字体许可说明](assets/fonts/NOTICE.md)。 diff --git a/assets/fonts/NOTICE.md b/assets/fonts/NOTICE.md new file mode 100644 index 0000000..d4eae20 --- /dev/null +++ b/assets/fonts/NOTICE.md @@ -0,0 +1,12 @@ +# Noto Sans CJK + +The unmodified Noto Sans SC Regular and Noto Sans JP Regular fonts are distributed under the [SIL Open Font License 1.1](OFL.txt), not the project's MIT license. Copyright notices are embedded in each font's name table. + +Source: [notofonts/noto-cjk](https://github.com/notofonts/noto-cjk/tree/f8d157532fbfaeda587e826d4cd5b21a49186f7c/Sans/SubsetOTF), revision `f8d157532fbfaeda587e826d4cd5b21a49186f7c`. + +| File | Upstream Git blob | +| --- | --- | +| `NotoSansSC-Regular.otf` | `fc0fda9394367c16c1af7555a2ae4d5e2e6a6f02` | +| `NotoSansJP-Regular.otf` | `4af556abb9cc42e585aab777b01857246a110746` | + +These local fallback fonts provide Chinese and Japanese glyphs when the operating system has no suitable font. They are loaded from the app package without contacting a font service. diff --git a/assets/fonts/NotoSansJP-Regular.otf b/assets/fonts/NotoSansJP-Regular.otf new file mode 100644 index 0000000..4af556a Binary files /dev/null and b/assets/fonts/NotoSansJP-Regular.otf differ diff --git a/assets/fonts/NotoSansSC-Regular.otf b/assets/fonts/NotoSansSC-Regular.otf new file mode 100644 index 0000000..fc0fda9 Binary files /dev/null and b/assets/fonts/NotoSansSC-Regular.otf differ diff --git a/assets/fonts/OFL.txt b/assets/fonts/OFL.txt new file mode 100644 index 0000000..d952d62 --- /dev/null +++ b/assets/fonts/OFL.txt @@ -0,0 +1,92 @@ +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to +provide a free and open framework in which fonts may be shared and +improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software +components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, +deleting, or substituting -- in part or in whole -- any of the +components of the Original Version, by changing formats or by porting +the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, +modify, redistribute, and sell modified and unmodified copies of the +Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in +Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the +corresponding Copyright Holder. This restriction only applies to the +primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created using +the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/live2d.md b/docs/live2d.md new file mode 100644 index 0000000..84fb9ff --- /dev/null +++ b/docs/live2d.md @@ -0,0 +1,125 @@ +# Live2D Companion + +[English](#english) | [简体中文](#简体中文) | [日本語](#日本語) + +## English + +Live2D is available as an optional feature from 0.5.0. Sprite characters remain available and keep their existing controls. Install Core and import a compatible model to use it. + +### Import a Model + +1. Open **Companion Settings > Character > Import Live2D**. +2. Select a `.model3.json` file with its accompanying files still in their original folders, or a ZIP containing exactly one model. A `.moc3` file alone is not sufficient. +3. Confirm the import and select the new character. +4. For the first Live2D character, use **Download Core 5.2**, save the official `live2dcubismcore.min.js`, and choose it with **Install Core**. Only the recognized official file is accepted. Core is stored locally, not in the project. +5. Use the expression and motion menus to preview the model's own artwork. Assign its expressions to **Happy**, **Shy**, **Thoughtful** and **Sad**, then save. The default mapping is neutral because names such as `F01` have no universal meaning. + +**Click expression mode:** one click selects the next native expression, including neutral. Idle motions and pointer tracking stop; blinking and breathing continue. Double clicks and long presses do not start an automatic expression loop. Motion preview is unavailable in this mode. + +**Automatic mode:** subtle pointer tracking, local touch reactions and the model's idle motion at roughly 45-60 second intervals. A chat reply holds its assigned expression. Idle gestures pause while a reply is displayed or spoken. Turn off pointer tracking or interaction phrases independently in settings. + +**Head pats and gentle taps:** assign separate expressions and optional motions in Character settings. A touch eases in and out and returns to the previous expression; repeated taps do not stack. Typing, dragging and a new reply interrupt the reaction. Models with native hit areas use those regions. Other models use their visible silhouette and a height-based head/body split. Empty space does not trigger a reaction. Older imports need reimporting to gain their native hit areas; this adds a separate character without deleting the old one. + +Turn off **Occasional idle gestures** for quiet company. Blinking, breathing, touch reactions and reply gestures still work. Pointer tracking has its own switch. Touch phrases can be disabled without disabling touch animation, and touches do not call an API or increase affection. + +**Voice:** external TTS audio drives mouth opening from its volume. This is not phoneme-level lip synchronization. System voices have no audio analyser and do not drive this mouth animation. A model needs mouth parameters for the effect to appear. + +For a closer companion tone, choose **Relationship > Partner**, set your preferred name, and describe the character's personality. Partner touch phrases remain local and make no model request. Affection, saved chat history and shared memories remain off by default. + +### Talking Beside Your Character + +The speech icon opens a small input beside the character. Enter sends your message and folds the input away; replies appear just above the character. Escape closes the input without losing its draft. The book icon opens the full conversation, sharing the same draft and history. A failed request keeps your unsent text for another attempt. + +The menu button beside the speech icon opens character selection, size, full chat, chat settings, and **Quit**. The same menu is available by right-clicking the character. + +In automatic mode, a Live2D character gently centers its gaze while you type or wait for a reply. Its own blink and breath continue; random idle gestures wait until the conversation settles. Click expression mode keeps the expression you selected. External voice playback has a compact stop/replay control beside the character. + +Under **Reply gestures**, you can also assign a native motion to each reply mood. All start with **No gesture**. A completed reply can play one selected motion, not one per streamed text chunk. Gestures are spaced apart during quick exchanges, and a new message interrupts the previous gesture. Starting voice playback does not cancel the current reply gesture. Click expression mode disables reply gestures. + +### Compatibility + +- Cubism 3/4 `.model3.json` exports with `.moc3`, PNG textures, `.exp3.json`, `.motion3.json`, physics and pose files. +- Some newer exports may work with Core 5.2, but this renderer does not promise all Cubism 5.x features. Cubism 5.3 extended blend modes, `.model.json`/Cubism 2, editable `.cmo3`, PSD, VRM and 3D models are not supported. +- Maximum 128 MiB per import, 256 files, 8 textures, 8192 pixels per texture dimension and 64 million total texture pixels. Each JSON file must be under 2 MiB. +- No embedded scripts, model audio, remote textures, external URLs or symbolic links are installed. Only the model's required files are copied. Removing a character does not delete its original folder. +- Animation quality depends on the rig and textures provided with the model. Importing a flat illustration does not create a rig. + +### Test Model and Terms + +The local test uses **Haru**, an official Live2D sample from [CubismWebSamples 4-r.7](https://github.com/Live2D/CubismWebSamples/tree/4-r.7/Samples/Resources/Haru), revision `de9eb4bec4326b81fe67a54e84322fdc39bc7446`. Haru is copyright Live2D Inc. and is available under the [Free Material License](https://www.live2d.com/eula/live2d-free-material-license-agreement_en.html), with the [sample model terms](https://www.live2d.com/eula/live2d-sample-model-terms_en.html). It is a test fixture, not a bundled character or a model covered by this repository's MIT license. + +Local runtime checks also cover **Epsilon FREE** and **Mao PRO** samples: visible canvas content, native blinking and breathing, pointer tracking, expressions, motion preview, inline conversation, and audio-driven mouth movement. These sample assets are not included in this repository. + +Live2D rendering and interaction have been tested on macOS. Windows and Linux pass automated app, restart and packaging checks; their Live2D graphics still need device-level verification. TTS playback is checked with local test audio, not every external voice service. + +Cubism Core is proprietary. The Framework and model assets also have their own licenses. Applications with user-loadable models are subject to the [official SDK publication terms](https://www.live2d.com/en/sdk/license/expandable/). The repository's MIT license does not cover those components or grant an SDK publication license. Neither Core nor sample models are bundled. [Third-party notices](../src/live2d/vendor/NOTICE.md). + +### Privacy + +Imported models render in a separate sandboxed frame with no settings, chat history, API key or filesystem bridge. The frame only receives model selection, gesture controls and numeric audio levels. It cannot contact external servers. Model importing itself does not call an LLM or TTS service. + +Chat and spoken text still go to the services you explicitly configure. Returned TTS audio links must share the configured service's origin; redirects and cross-origin audio links are rejected. A provider using a separate CDN must return audio bytes/base64 directly or provide a same-origin audio endpoint. + +## 简体中文 + +从 0.5.0 起可以选择使用 Live2D。原有图片桌宠和设置保持不变;安装 Core 并导入兼容模型后即可切换。 + +1. 打开 **陪伴设置 > 角色 > 导入 Live2D**,选择模型的 `.model3.json`,或仅含一个模型的 ZIP。纹理、动作等文件需保留原有目录结构;单独的 `.moc3` 无法使用。 +2. 确认导入并切换到新角色。首次使用时点 **下载 Core 5.2**,保存官方 `live2dcubismcore.min.js`,再通过 **安装 Core** 选择这个文件。程序只接受已核验的官方文件,运行库保存在本机数据目录。 +3. 预览模型自带的表情、动作,将合适的表情分配给开心、害羞、思考和难过,保存后随聊天回复变化。默认不猜测 `F01` 等名称的含义。 +4. 右键切换表情模式或人物大小。点击模式下一次点击换一个表情,不会变成自动轮播;眨眼和呼吸保留,注视和待机动作关闭。自动模式下才会有鼠标注视、触碰反应和低频待机动作,回复展示或朗读期间暂停待机动作。 +5. 外部 TTS 的实际音量可以驱动张嘴,停止朗读后收口。它不是逐音素口型;系统语音暂不驱动口型,模型也需要对应的嘴部参数。 + +想要更亲近的口吻,可以将人物关系设为 **恋人**,填写希望被称呼的名字和人物性格。恋人关系的触碰短句在本地运行,不调用 API。好感度、保存聊天记录、共同记忆依旧默认关闭。 + +角色设置中的 **摸摸头** 和 **轻轻碰一下** 可以分别指定表情、动作。触碰会平滑开始、结束并恢复原表情,连续点击不会叠加;开始输入、拖动或收到新回复时会结束触碰反馈。优先使用模型自带的触碰区域;没有区域的模型按可见轮廓和上下位置区分,点空白处不回应。旧版已导入的模型需重新导入才能使用原生区域,会新增一个角色,原角色和记录保留。 + +关闭 **偶尔播放待机动作** 后,呼吸、眨眼、触碰和回复动作仍然保留。鼠标注视、互动短句各有独立开关,关掉短句也可以保留触碰动画。触碰不调用 API,也不增加好感度。 + +点人物旁的对话图标即可展开小输入框,按回车发送后自动收起,回复显示在人物上方。按 Esc 可收起并保留草稿;点书本图标可看完整聊天记录,两处共用草稿。请求失败时也会保留未发送的文字。自动模式下,输入和等待回复时人物会轻轻看向你,保持眨眼、呼吸,暂缓待机动作。点击模式不改变手动选中的表情。朗读的停止、重播按钮在人物身旁。 + +对话图标旁的菜单按钮可以切换角色、调整大小、打开完整聊天和对话设置,或选择 **退出**。右键点击人物也能打开同一个菜单。 + +在 **回复动作** 中可以为各个情绪选择模型自带动作,默认均不播放。一条完整回复最多触发一次,逐字输出时不会重复触发;连续短回复也不会让动作连着播放。开始朗读会保留当前回复动作,发出新消息则会中止上一动作。点击表情模式不播放回复动作。 + +支持 Cubism 3/4 导出的模型、PNG、表情、动作、物理和姿态文件。不能把一张立绘自动变成 Live2D,也不支持 Cubism 2、编辑工程 `.cmo3`、PSD、VRM 或 Cubism 5.3 的扩展混合模式。单包上限 128 MiB、256 文件、8 张纹理,单张最长边 8192,纹理总像素不超过 6400 万,单个 JSON 不超过 2 MiB。 + +测试使用的是官方 Haru 示例,版权属于 Live2D Inc.,不是 MIT 角色素材;下载来源和许可见上方链接。Core 也不是开源库。允许用户加载模型的应用适用 Live2D 的公开发布条款,仓库的 MIT 许可不替代这些条款。仓库和安装包均不附带 Core 或测试模型。 + +本地也已用 Epsilon FREE 和 Mao PRO 验证显示、眨眼、呼吸、注视、表情、动作、人物旁对话和音量口型。这些模型文件不会随仓库一起发布。 + +Live2D 画面与交互在 macOS 上实测。Windows、Linux 通过应用、重启与打包自动检查,Live2D 图形效果仍需对应设备实测。TTS 播放使用本地测试音频验证,未逐一验证所有外部语音服务。 + +模型只在隔离窗口中接收动作参数和音量,不会拿到密钥、聊天记录或文件系统权限,也不能联网加载素材。导入不会覆盖原始文件。聊天和 TTS 仍只使用你配置的服务;服务返回的音频链接必须与服务地址同来源,否则应改为直接返回音频。 + +## 日本語 + +0.5.0 から任意の機能として使えます。Core と対応モデルを導入してください。既存のスプライトキャラクターはそのまま使えます。 + +1. **付き添い設定 > キャラクター > Live2D を追加** から `.model3.json`、またはモデルが一つだけ入った ZIP を選びます。関連ファイルのフォルダー構成を保ってください。`.moc3` 単体では使えません。 +2. 追加したキャラクターを選択します。初回は **Core 5.2 をダウンロード** から公式の `live2dcubismcore.min.js` を保存し、**Core を導入** で選びます。確認済みの公式ファイルのみ受け付けます。 +3. 表情とモーションを試し、返答時の「うれしい・照れる・考え中・悲しい」に割り当てて保存します。`F01` などの意味はモデルごとに異なるため、初期値は自然な表情です。 +4. クリック表情モードでは一回のクリックで一つ進みます。自動切り替えや視線追従は止まりますが、まばたきと呼吸は続きます。自動モードの待機動作は低頻度で、返答表示中や読み上げ中は止まります。 +5. 外部 TTS の音量で口を動かします。音素単位のリップシンクではありません。システム音声は口の動きに対応していません。 + +関係を「恋人」にし、呼び名と性格を設定すると、会話やローカルの触れ合い短文も親しみのある口調になります。好感度、履歴保存、共通の記憶は初期状態では無効です。 + +**頭をなでる** と **そっと触れる** に別々の表情・モーションを設定できます。反応は滑らかに始まり、元の表情に戻ります。連打で重ならず、入力・ドラッグ・新しい返答で中断します。モデルの当たり判定を優先し、ない場合は表示部分と上下の位置で判定します。空白には反応しません。以前のインポートで当たり判定を利用するには再インポートが必要です。別のキャラクターとして追加され、元の設定や履歴は残ります。 + +**ときどき待機モーションを再生** を無効にしても、まばたき・呼吸・触れ合い・返答時の動作は続きます。視線追従と触れ合いの一言は別々に切り替えられます。触れ合いでは API を呼び出さず、好感度も増えません。 + +キャラクター横の会話アイコンで小さな入力欄が開きます。Enter で送信すると閉じ、返答はキャラクターのすぐ上に表示されます。Esc で閉じても下書きは残ります。本のアイコンから開く会話履歴とも下書きを共有します。送信失敗時も入力内容は保持されます。自動モードでは入力中や返答待ちに視線をそっと中央に戻し、まばたきと呼吸を続けます。クリック表情モードでは選んだ表情を保ちます。音声の停止・再生はキャラクター横の小さなボタンで操作できます。 + +会話アイコン横のメニューボタンから、キャラクター・サイズの変更、チャット画面、会話設定、**終了**を選べます。キャラクターを右クリックしても同じメニューが開きます。 + +**返答時のモーション** では、感情ごとにモデルの動作を選べます。初期値はすべて「モーションなし」です。一つの返答につき一度だけ再生し、文字の逐次表示や短い返答の連続で動作を繰り返しません。読み上げ開始時も動作を保ち、新しいメッセージで前の動作を中断します。クリック表情モードでは再生しません。 + +Cubism 3/4 の書き出しモデルに対応します。Cubism 2、`.cmo3` 編集ファイル、PSD、VRM、Cubism 5.3 の拡張ブレンドは非対応です。128 MiB・256 ファイル・PNG 8 枚まで、各辺 8192 ピクセル以下、合計 6400 万ピクセル以下、JSON は一つ 2 MiB 以下です。 + +テストには Live2D Inc. の公式 Haru を使用しました。MIT 素材ではなく、上記の専用利用規約が適用されます。Core はプロプライエタリです。ユーザーモデルを読み込むアプリには Live2D の公開条件が適用され、リポジトリの MIT ライセンスで代替できません。Core とテストモデルは同梱されません。 + +Epsilon FREE と Mao PRO でも表示、まばたき、呼吸、視線、表情、モーション、会話、音量による口の動きをローカルで確認しています。これらのモデルはリポジトリに含まれません。 + +Live2D の描画と操作は macOS で確認済みです。Windows と Linux はアプリ・再起動・パッケージの自動検証を通過していますが、Live2D の描画は各端末での検証が残っています。TTS 再生はローカルのテスト音声で確認しており、すべての外部音声サービスを検証したものではありません。 + +モデルは設定・会話・API キー・ファイル操作の権限を持たない隔離フレームで表示され、外部通信もできません。会話と TTS だけは設定したサービスに送信されます。音声の返却リンクは TTS サービスと同一オリジンである必要があります。 diff --git a/docs/releases/v0.5.0.md b/docs/releases/v0.5.0.md new file mode 100644 index 0000000..7b8bcae --- /dev/null +++ b/docs/releases/v0.5.0.md @@ -0,0 +1,40 @@ +# Desktop Pet 0.5.0 + +## English + +- Import a Live2D character from `.model3.json` or a ZIP, with the model's own expressions, motions, blinking and breathing. +- Talk beside your character. The compact input folds away after sending, replies appear above the pet, and drafts stay in sync with the full chat window. +- Choose expressions and motions for head pats, gentle taps and reply moods. Touch reactions settle back smoothly; typing or dragging interrupts them. Quiet idle and pointer tracking have separate switches. +- Use the visible menu beside the speech button for character selection, size, chat, settings and Quit. Click expression mode advances once per click, without extra changes on double clicks or long holds. +- External TTS audio can drive mouth movement, with stop and replay controls beside the character. Existing sprite characters, preferences and window recovery remain compatible. +- Include Chinese and Japanese fallback fonts so text stays readable on systems without CJK fonts, including minimal Linux installations. Fonts load locally without network requests. + +**Live2D setup:** install the supported Core file locally and import your own compatible exported model. Core and sample models are not included. See the [setup and compatibility guide](https://github.com/TonyNa-code/desktop-pet/blob/v0.5.0/docs/live2d.md). + +Voice, saved history, shared memories and experimental affection stay off by default. Touch reactions do not call a model service or increase affection. Chat and spoken text go only to the services you configure. + +## 简体中文 + +- 支持从 `.model3.json` 或 ZIP 导入 Live2D 角色,使用模型自带的表情、动作、眨眼和呼吸。 +- 在人物身旁直接对话。小输入框发送后收起,回复显示在人物上方,草稿与完整聊天窗同步。 +- 为摸摸头、轻碰和不同回复情绪选择表情与动作。触碰结束后平滑恢复,输入或拖动会中断;低频待机动作和鼠标注视可以分别关闭。 +- 对话按钮旁增加常驻菜单,可切换角色、调整大小、打开聊天或设置、退出。点击表情模式仍是一点换一个,双击和长按不会多跳。 +- 外部 TTS 音量可驱动口型,人物旁可停止或重播语音。原有图片角色、设置和窗口找回功能保持兼容。 +- 内置中日文备用字体,修复精简 Linux 等缺少字体的系统上文字显示为方框的问题。字体从本机加载,不联网请求。 + +**使用 Live2D:**在本机安装受支持的 Core 文件,再导入兼容的导出模型。安装包不附带 Core 或示例模型,操作步骤见[导入与兼容性指南](https://github.com/TonyNa-code/desktop-pet/blob/v0.5.0/docs/live2d.md#简体中文)。 + +朗读、保存聊天记录、共同记忆和实验性好感度仍默认关闭。触碰不调用模型服务,也不增加好感度。聊天与朗读文本只发送给你配置的服务。 + +## 日本語 + +- `.model3.json` または ZIP から Live2D キャラクターを追加できます。モデルの表情、モーション、まばたき、呼吸を使用します。 +- ペットのそばで会話できます。送信後は小さな入力欄が閉じ、返答はキャラクターの上に表示されます。下書きはチャット画面と同期します。 +- 頭をなでる、そっと触れる、返答の感情に表情とモーションを割り当てられます。反応後は滑らかに元へ戻り、入力やドラッグで中断します。待機動作と視線追従は別々に切り替えられます。 +- 会話ボタンの横のメニューから、キャラクター、サイズ、チャット、設定、終了を選べます。クリック表情モードは一回につき一つ進み、ダブルクリックや長押しでも余分に進みません。 +- 外部 TTS の音量で口を動かし、ペットのそばで停止・再生できます。既存の画像キャラクター、設定、位置の復元も引き続き利用できます。 +- 中国語・日本語の代替フォントを同梱し、CJK フォントのない Linux などでも文字を表示します。フォントは端末内から読み込み、通信しません。 + +**Live2D の準備:**対応する Core ファイルを端末に導入し、書き出し済みモデルを追加してください。Core とサンプルモデルは同梱されません。[導入・互換性ガイド](https://github.com/TonyNa-code/desktop-pet/blob/v0.5.0/docs/live2d.md#日本語)をご覧ください。 + +音声、履歴保存、共通の記憶、実験的な好感度は初期状態ではオフです。触れ合いでは API を呼び出さず、好感度も増えません。会話と読み上げテキストは、設定したサービスに送信されます。 diff --git a/package-lock.json b/package-lock.json index 4d128bd..b35a1b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "desktop-pet", - "version": "0.4.5", + "version": "0.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "desktop-pet", - "version": "0.4.5", + "version": "0.5.0", "license": "MIT", "dependencies": { "fflate": "0.8.3" diff --git a/package.json b/package.json index af3d519..b9a873c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "desktop-pet", - "version": "0.4.5", + "version": "0.5.0", "description": "A cross-platform anime desktop pet with character packs, chat, TTS, and multilingual UI.", "author": "Desktop Pet Contributors", "license": "MIT", @@ -17,7 +17,7 @@ "scripts": { "start": "electron .", "dev": "electron . --dev", - "check": "node --check src/main.js && node --check src/i18n.js && node --check src/preload.js && node --check src/renderer.js && node --check src/chat.js && node --check src/quick-chat.js && node --check src/chat-draft.js && node --check src/settings.js && node --check src/config-validation.js && node --check src/chat-response.js && node --check src/character-import.js && node --check src/speech-text.js && node --check src/voice-controls.js && node --check src/network-safety.js && node --check src/window-placement.js && npm test && node scripts/validate-assets.js && node scripts/privacy-check.js", + "check": "node --check src/main.js && node --check src/i18n.js && node --check src/preload.js && node --check src/renderer.js && node --check src/chat.js && node --check src/quick-chat.js && node --check src/chat-draft.js && node --check src/settings.js && node --check src/config-validation.js && node --check src/chat-response.js && node --check src/character-import.js && node --check src/speech-text.js && node --check src/voice-controls.js && node --check src/network-safety.js && node --check src/window-placement.js && node --check src/live2d-import.js && node --check src/live2d-host.js && node --check src/live2d-bridge.js && node --check src/live2d/viewer.js && node --check src/companion-input.js && npm test && node scripts/validate-assets.js && node scripts/privacy-check.js", "test": "node --test tests/*.test.js", "test:smoke": "node tests/run-electron-smoke.cjs", "privacy:check": "node scripts/privacy-check.js", diff --git a/src/chat-draft.js b/src/chat-draft.js index bb554cf..3b66cd7 100644 --- a/src/chat-draft.js +++ b/src/chat-draft.js @@ -1,6 +1,6 @@ (() => { window.DesktopPetDraft = { - create(input) { + create(input, { autofocus = true } = {}) { input.disabled = true; let context = null; let composing = false; @@ -50,7 +50,7 @@ replace(draft.text); if (earlyUpdate) { receive(earlyUpdate); earlyUpdate = null; } input.disabled = false; - if (initial && document.activeElement === document.body) input.focus(); + if (initial && autofocus && document.activeElement === document.body) input.focus(); }, clearIfMatches(text) { if (input.value.trim() !== text.trim()) return; diff --git a/src/chat.css b/src/chat.css index 63ef6e1..1e49d19 100644 --- a/src/chat.css +++ b/src/chat.css @@ -5,7 +5,7 @@ body { margin: 0; background: #f6f7f9; color: #25282d; - font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font: 14px/1.45 var(--pet-font); } body { diff --git a/src/chat.html b/src/chat.html index 644e38c..a4d018c 100644 --- a/src/chat.html +++ b/src/chat.html @@ -2,8 +2,10 @@ + Companion Chat + diff --git a/src/companion-input.js b/src/companion-input.js new file mode 100644 index 0000000..0474097 --- /dev/null +++ b/src/companion-input.js @@ -0,0 +1,104 @@ +(() => { + const form = document.querySelector("#companion-input"); + const input = document.querySelector("#companion-text"); + const send = document.querySelector("#companion-send"); + const close = document.querySelector("#companion-close"); + const stop = document.querySelector("#companion-stop"); + const presence = document.querySelector("#companion-presence"); + const feedback = document.querySelector("#companion-feedback"); + const talk = document.querySelector("#talk"); + const api = window.desktopPet; + const draft = window.DesktopPetDraft.create(input, { autofocus: false }); + let open = false; + let state = {}; + let sending = false; + let sendToken = 0; + let revision = 0; + let receivedState = false; + let opening = 0; + const t = (key, values) => window.DesktopPetI18n.t(key, values || {}, state.resolvedLanguage || "en-US"); + function update() { + const busy = sending || state.busy === true; + const speaking = ["preparing", "playing"].includes(state.voice?.status); + send.disabled = busy || input.disabled || !input.value.trim(); + stop.hidden = !busy; + presence.hidden = !busy; + presence.setAttribute("aria-label", t("pet.thinking")); + for (const [button, key] of [[send, "quick.send"], [close, "quick.close"], [stop, "chat.stop"]]) { + button.title = t(key); button.setAttribute("aria-label", button.title); + } + input.placeholder = t("quick.toCharacter", { name: state.config?.persona?.name || state.character?.name || "Desktop Pet" }); + input.setAttribute("aria-label", input.placeholder); + const attention = busy ? "thinking" : speaking ? "speaking" : open ? "attentive" : "idle"; + window.DesktopPetModel?.presence(attention); + document.body.dataset.companionState = attention; + } + async function setOpen(value, focus = true) { + const ticket = ++opening; + open = value; + form.hidden = !open; + document.body.dataset.companionOpen = String(open); + talk.setAttribute("aria-expanded", String(open)); + if (!open) input.blur(); + update(); + try { + await api.setCompanionInputOpen(open); + if (ticket !== opening) return; + window.dispatchEvent(new Event("resize")); + if (open && focus) input.focus(); + } catch { + if (ticket !== opening) return; + open = false; form.hidden = true; document.body.dataset.companionOpen = "false"; + talk.setAttribute("aria-expanded", "false"); update(); + } + } + function applyState(next) { + if (Number.isFinite(next.revision) && next.revision < revision) return; + if (Number.isFinite(next.revision) && next.revision > revision) { revision = next.revision; sendToken++; sending = false; } + state = next; + draft.applyState(next); + update(); + } + async function submit() { + if (sending || state.busy || input.disabled) return; + const text = input.value.trim(); + if (!text) return; + const context = draft.context(); + const token = ++sendToken; + sending = true; + feedback.hidden = true; + draft.clearIfMatches(text); + update(); + setOpen(false, false); + try { + const result = await api.sendChatMessage(text, context); + if (token !== sendToken || result.cancelled || result.revision < revision) return; + if (!result.ok) { + draft.restore(text, context); + feedback.textContent = t("quick.replyFailed"); feedback.hidden = false; + } + } catch { + if (token !== sendToken) return; + draft.restore(text, context); + feedback.textContent = t("quick.sendFailed"); feedback.hidden = false; + } finally { + if (token === sendToken) { sending = false; update(); } + } + } + form.addEventListener("submit", event => { event.preventDefault(); submit(); }); + input.addEventListener("input", update); + input.addEventListener("keydown", event => { + if (event.isComposing || event.keyCode === 229) return; + if (event.key === "Enter" && !event.shiftKey) { event.preventDefault(); submit(); } + if (event.key === "Escape") { event.preventDefault(); setOpen(false); talk.focus(); } + }); + close.addEventListener("click", () => { setOpen(false); talk.focus(); }); + stop.addEventListener("click", async () => { + try { applyState(await api.stopChat()); } + catch { feedback.textContent = t("quick.sendFailed"); feedback.hidden = false; } + }); + api.onChatStateUpdated(next => { receivedState = true; applyState(next); }); + api.onChatDraftUpdated(() => update()); + api.getChatState().then(next => { if (!receivedState) applyState(next); }).catch(() => {}); + window.DesktopPetCompanionInput = { open: () => setOpen(true), toggle: () => setOpen(!open), isOpen: () => open }; +})(); diff --git a/src/companion-response.js b/src/companion-response.js index c469212..895e079 100644 --- a/src/companion-response.js +++ b/src/companion-response.js @@ -1,6 +1,6 @@ function expressionInstruction(states) { const allowed = Object.keys(states).filter((name) => /^[a-zA-Z][a-zA-Z0-9]{0,40}$/.test(name)); - return `You are speaking as the character beside the user's desktop. Reply naturally in character, usually in one to three sentences unless the user asks for more. Do not narrate software status or numeric energy. Start with exactly one expression marker chosen from: ${allowed.map((name) => `[expression:${name}]`).join(" ")}. Then write the spoken reply. The marker controls the character's expression and is not spoken. Do not invent other markers.`; + return `You are speaking as the character beside the user's desktop. Reply naturally in character, usually in one to three sentences unless the user asks for more. Respond to the specific thing they shared; avoid support-agent introductions, routine offers of help, and a question at the end of every reply. Keep warmth consistent with the chosen personality and relationship, without inventing shared memories, claiming to see their screen, or pressuring them to stay. Do not narrate software status or numeric energy. Start with exactly one expression marker chosen from: ${allowed.map((name) => `[expression:${name}]`).join(" ")}. Then write the spoken reply. The marker controls the character's expression and is not spoken. Do not invent other markers.`; } function parseCompanionReply(raw, states, partial = false) { diff --git a/src/fonts.css b/src/fonts.css new file mode 100644 index 0000000..091118a --- /dev/null +++ b/src/fonts.css @@ -0,0 +1,25 @@ +@font-face { + font-family: "Desktop Pet CJK SC"; + src: url("../assets/fonts/NotoSansSC-Regular.otf") format("opentype"); + font-style: normal; + font-weight: 400; + font-display: swap; + unicode-range: U+2000-206F, U+2E80-9FFF, U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+20000-3FFFF; +} + +@font-face { + font-family: "Desktop Pet CJK JP"; + src: url("../assets/fonts/NotoSansJP-Regular.otf") format("opentype"); + font-style: normal; + font-weight: 400; + font-display: swap; + unicode-range: U+2000-206F, U+2E80-9FFF, U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+20000-3FFFF; +} + +:root { + --pet-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Desktop Pet CJK SC", "Desktop Pet CJK JP", sans-serif; +} + +:root:lang(ja) { + --pet-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Desktop Pet CJK JP", "Desktop Pet CJK SC", sans-serif; +} diff --git a/src/i18n.js b/src/i18n.js index c32a62d..81afb52 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -17,8 +17,41 @@ const DICTIONARIES = { "zh-CN": { "chat.latest": "最新回复", + "live2d.import": "导入 Live2D", + "live2d.loading": "角色载入中…", + "live2d.runtimeMissing": "尚未安装 Cubism Core。打开角色设置", + "live2d.loadFailed": "模型无法载入。打开角色设置", + "live2d.downloadCore": "下载 Core 5.2", + "live2d.importCore": "安装 Core", + "live2d.runtimeReady": "Core 已就绪", + "live2d.runtimeNeeded": "需要 Cubism Core 5.2", + "live2d.runtimeFailed": "文件不匹配,请选择官方 Core 5.2 文件", + "live2d.gaze": "自动模式下看向鼠标", + "live2d.idle": "偶尔播放待机动作", + "live2d.headTouch": "摸摸头", + "live2d.bodyTouch": "轻轻碰一下", + "live2d.expression": "表情", + "live2d.motion": "动作", + "live2d.previewExpression": "预览表情", + "live2d.previewMotion": "预览动作", + "live2d.replyExpressions": "回复表情", + "live2d.replyMotions": "回复动作", + "live2d.noMotion": "不播放动作", + "live2d.happy": "开心", + "live2d.shy": "害羞", + "live2d.review": "思考", + "live2d.failed": "难过", + "live2d.neutral": "自然表情", + "live2d.modelMeta": "{count} 个模型表情", + "live2d.actionFailed": "动作不可用;请检查当前角色和表情模式", "tts.audioOrigin": "语音链接与服务地址不属于同一来源,请让服务直接返回音频或同来源链接。", "tts.responseTooLarge": "语音响应过大,请缩短文本或调整服务输出。", + "pet.interaction.partner.head.0": "嗯……这样就很舒服。", + "pet.interaction.partner.head.1": "再陪我待一小会儿吧。", + "pet.interaction.partner.greet.0": "在呢,想和我说什么?", + "pet.interaction.partner.greet.1": "看到你过来,我有点开心。", + "pet.interaction.partner.drop.0": "好,就坐在你旁边。", + "pet.interaction.partner.drop.1": "这里不错,能离你近一点。", "settings.tabs.general": "通用", "settings.tabs.memory": "共同记忆", "settings.interactions": "互动短句(自动表情模式)", @@ -93,6 +126,7 @@ "voice.ready": "最近的回复", "voice.failed": "语音未能播放", "pet.talk": "对话", + "pet.menu": "桌宠菜单", "quick.toCharacter": "和{name}说点什么…", "quick.history": "记录", "quick.responding": "正在回应…", @@ -362,8 +396,41 @@ "en-US": { "chat.latest": "Latest reply", + "live2d.import": "Import Live2D", + "live2d.loading": "Loading character…", + "live2d.runtimeMissing": "Cubism Core is not installed. Open character settings", + "live2d.loadFailed": "Could not load this model. Open character settings", + "live2d.downloadCore": "Download Core 5.2", + "live2d.importCore": "Install Core", + "live2d.runtimeReady": "Core is ready", + "live2d.runtimeNeeded": "Cubism Core 5.2 required", + "live2d.runtimeFailed": "File mismatch. Choose the official Core 5.2 file", + "live2d.gaze": "Follow the pointer in automatic mode", + "live2d.idle": "Occasional idle gestures", + "live2d.headTouch": "Head pats", + "live2d.bodyTouch": "Gentle taps", + "live2d.expression": "Expression", + "live2d.motion": "Motion", + "live2d.previewExpression": "Preview expression", + "live2d.previewMotion": "Preview motion", + "live2d.replyExpressions": "Reply expressions", + "live2d.replyMotions": "Reply gestures", + "live2d.noMotion": "No gesture", + "live2d.happy": "Happy", + "live2d.shy": "Shy", + "live2d.review": "Thoughtful", + "live2d.failed": "Sad", + "live2d.neutral": "Neutral", + "live2d.modelMeta": "{count} model expressions", + "live2d.actionFailed": "Action unavailable; check the character and expression mode", "tts.audioOrigin": "The audio link must use the same origin as the voice service. Use direct audio or a same-origin link.", "tts.responseTooLarge": "The voice response is too large. Shorten the text or adjust the service output.", + "pet.interaction.partner.head.0": "Mm… that's nice.", + "pet.interaction.partner.head.1": "Stay here with me a little?", + "pet.interaction.partner.greet.0": "I'm here. What's on your mind?", + "pet.interaction.partner.greet.1": "It's nice to see you over here.", + "pet.interaction.partner.drop.0": "Right here, beside you.", + "pet.interaction.partner.drop.1": "I like this spot. A little closer to you.", "settings.tabs.general": "General", "settings.tabs.memory": "Memories", "settings.interactions": "Touch responses (automatic expression mode)", @@ -438,6 +505,7 @@ "voice.ready": "Latest reply", "voice.failed": "Voice unavailable", "pet.talk": "Talk", + "pet.menu": "Pet menu", "quick.toCharacter": "Talk to {name}…", "quick.history": "History", "quick.responding": "Replying…", @@ -707,8 +775,41 @@ "ja-JP": { "chat.latest": "最新の返信", + "live2d.import": "Live2D を追加", + "live2d.loading": "キャラクターを読み込み中…", + "live2d.runtimeMissing": "Cubism Core が未導入です。キャラクター設定を開く", + "live2d.loadFailed": "モデルを読み込めません。キャラクター設定を開く", + "live2d.downloadCore": "Core 5.2 をダウンロード", + "live2d.importCore": "Core を導入", + "live2d.runtimeReady": "Core の準備完了", + "live2d.runtimeNeeded": "Cubism Core 5.2 が必要です", + "live2d.runtimeFailed": "ファイルが一致しません。公式 Core 5.2 を選んでください", + "live2d.gaze": "自動モードでマウスを目で追う", + "live2d.idle": "ときどき待機モーションを再生", + "live2d.headTouch": "頭をなでる", + "live2d.bodyTouch": "そっと触れる", + "live2d.expression": "表情", + "live2d.motion": "モーション", + "live2d.previewExpression": "表情を試す", + "live2d.previewMotion": "モーションを試す", + "live2d.replyExpressions": "返答時の表情", + "live2d.replyMotions": "返答時のモーション", + "live2d.noMotion": "モーションなし", + "live2d.happy": "うれしい", + "live2d.shy": "照れる", + "live2d.review": "考え中", + "live2d.failed": "悲しい", + "live2d.neutral": "自然な表情", + "live2d.modelMeta": "表情 {count} 種類", + "live2d.actionFailed": "実行できません。キャラクターと表情モードを確認してください", "tts.audioOrigin": "音声リンクはサービスと同じオリジンである必要があります。音声を直接返すか、同一オリジンのリンクを使用してください。", "tts.responseTooLarge": "音声応答が大きすぎます。文章を短くするか、サービスの出力を調整してください。", + "pet.interaction.partner.head.0": "ん……気持ちいい。", + "pet.interaction.partner.head.1": "もう少し、一緒にいて?", + "pet.interaction.partner.greet.0": "いるよ。何か話したいことある?", + "pet.interaction.partner.greet.1": "こっちに来てくれて、ちょっとうれしい。", + "pet.interaction.partner.drop.0": "うん、隣にいるね。", + "pet.interaction.partner.drop.1": "ここ、いいね。少し近くにいられる。", "settings.tabs.general": "一般", "settings.tabs.memory": "思い出", "settings.interactions": "ふれあいの一言(自動表情モード)", @@ -783,6 +884,7 @@ "voice.ready": "直近の返信", "voice.failed": "音声を再生できません", "pet.talk": "話す", + "pet.menu": "デスクトップペットのメニュー", "quick.toCharacter": "{name}に話しかける…", "quick.history": "履歴", "quick.responding": "返信中…", diff --git a/src/icons/square.svg b/src/icons/square.svg new file mode 100644 index 0000000..6e31678 --- /dev/null +++ b/src/icons/square.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/icons/volume-2.svg b/src/icons/volume-2.svg new file mode 100644 index 0000000..381c662 --- /dev/null +++ b/src/icons/volume-2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/index.html b/src/index.html index 686449b..c876209 100644 --- a/src/index.html +++ b/src/index.html @@ -2,8 +2,10 @@ + Desktop Pet + @@ -19,18 +21,34 @@

- + +
+ + + - + +
+ + + + diff --git a/src/live2d-bridge.js b/src/live2d-bridge.js new file mode 100644 index 0000000..034e92a --- /dev/null +++ b/src/live2d-bridge.js @@ -0,0 +1,147 @@ +(() => { + const ORIGIN = "pet-live2d://viewer"; + const CHANNEL = "desktop-pet-model"; + const stage = document.querySelector("#model-stage"); + const status = document.querySelector("#model-status"); + let frame; + let current; + let ready = false; + let loaded = false; + let desiredExpression = -1; + let presence = "idle"; + let audioTicket = 0; + let ticket = 0; + let language = "en"; + let audioContext; + let audioSource; + let analyser; + let audioTimer; + let loadTimer; + let locationRequest = 0; + const locations = new Map(); + + function settleLocation(request, kind = null) { + const pending = locations.get(request); + if (!pending) return; + clearTimeout(pending.timer); + locations.delete(request); + pending.resolve(kind); + } + + function locate(x, y) { + if (!loaded || !Number.isFinite(x) || !Number.isFinite(y)) return Promise.resolve(null); + for (const request of locations.keys()) settleLocation(request); + const request = ++locationRequest; + return new Promise(resolve => { + const timer = setTimeout(() => settleLocation(request), 400); + locations.set(request, { resolve, timer }); + send("locate", { x, y, request }); + }); + } + + function send(type, extra = {}) { + if (frame && ready && current) frame.contentWindow.postMessage({ channel: CHANNEL, type, id: current.id, ...extra }, ORIGIN); + } + function message(key) { + status.textContent = window.DesktopPetI18n.t(key, {}, language); + status.hidden = !key; + } + function stopMouth() { + audioTicket++; + clearInterval(audioTimer); + audioSource?.disconnect(); + analyser?.disconnect(); + audioSource = analyser = null; + send("mouth", { value: 0 }); + } + async function attachAudio(audio) { + stopMouth(); + const token = audioTicket; + if (!current) return; + try { + audioContext ||= new AudioContext(); + await audioContext.resume(); + if (token !== audioTicket || !current || audio.paused) return; + audioSource = audioContext.createMediaElementSource(audio); + analyser = audioContext.createAnalyser(); + analyser.fftSize = 512; + audioSource.connect(analyser); + analyser.connect(audioContext.destination); + const samples = new Float32Array(analyser.fftSize); + audioTimer = setInterval(() => { + if (!analyser) return; + analyser.getFloatTimeDomainData(samples); + const rms = Math.sqrt(samples.reduce((sum, value) => sum + value * value, 0) / samples.length); + send("mouth", { value: audio.paused || audio.ended ? 0 : Math.min(1, Math.max(0, (rms - 0.008) * 7)) }); + }, 40); + } catch { if (token === audioTicket) stopMouth(); } + } + async function apply(character, settings, busy = false) { + const next = character.type === "live2d" ? { + id: character.id, automatic: settings.expressionMode === "automatic", + gaze: settings.persona?.live2dGaze !== false, idle: settings.persona?.live2dIdle !== false, + touches: settings.persona?.live2dTouches || {}, busy, dragging: current?.id === character.id && current.dragging === true, + } : null; + language = settings.resolvedLanguage; + if (next && current?.id === next.id && frame) { + current = next; + send("options", next); + return; + } + const token = ++ticket; + for (const request of locations.keys()) settleLocation(request); + stopMouth(); + clearTimeout(loadTimer); + frame?.remove(); frame = null; ready = loaded = false; + desiredExpression = -1; + current = next; + stage.hidden = !next; + status.hidden = !next; + if (!next) return; + message("live2d.loading"); + try { + const runtime = await window.desktopPet.getLive2DRuntime(); + if (ticket !== token) return; + if (!runtime.ready) { message("live2d.runtimeMissing"); return; } + frame = document.createElement("iframe"); + frame.title = "Live2D"; + frame.setAttribute("sandbox", "allow-scripts allow-same-origin"); + frame.src = `${ORIGIN}/index.html`; + stage.replaceChildren(frame); + loadTimer = setTimeout(() => message("live2d.loadFailed"), 30000); + } catch { if (ticket === token) message("live2d.loadFailed"); } + } + window.addEventListener("message", (event) => { + if (!frame || event.source !== frame.contentWindow || event.origin !== ORIGIN || event.data?.channel !== CHANNEL) return; + if (event.data.type === "boot") { ready = true; send("load", current); } + if (event.data.type === "loaded") { + loaded = true; clearTimeout(loadTimer); status.hidden = true; + send("options", current); + send("expression", { index: desiredExpression }); + send("presence", { state: presence }); + } + if (event.data.type === "error") { clearTimeout(loadTimer); message("live2d.loadFailed"); } + if (event.data.type === "location") { + const kind = event.data.kind; + settleLocation(event.data.request, ["head", "greet"].includes(kind) ? kind : null); + } + }); + window.desktopPet.onModelAction((action) => { + if (current?.id === action.id) { + if (action.type === "expression") desiredExpression = action.index; + if (loaded) send(action.type, { index: action.index, group: action.group }); + } + }); + status.addEventListener("click", () => window.desktopPet.openCompanionSettings()); + window.DesktopPetModel = { + apply, attachAudio, stopMouth, locate, + cycle: () => { if (loaded) send("cycle"); }, + expression: (index) => { desiredExpression = index; if (loaded) send("expression", { index }); }, + touch: (kind = "greet") => { if (loaded) send("touch", { kind }); }, + replyMotion: (motion) => { if (loaded) send("reply-motion", { group: motion.group, index: motion.index }); }, + presence: (state) => { presence = state; if (loaded) send("presence", { state }); }, + gaze: (x, y) => send("gaze", { x, y }), + busy: (busy) => { if (current) { current.busy = busy; send("options", current); } }, + dragging: (dragging) => { if (current) { current.dragging = dragging; send("options", current); } }, + }; +})(); diff --git a/src/live2d-host.js b/src/live2d-host.js new file mode 100644 index 0000000..cb43912 --- /dev/null +++ b/src/live2d-host.js @@ -0,0 +1,72 @@ +const fs = require("node:fs"); +const path = require("node:path"); +const { createHash } = require("node:crypto"); +const { readLocal, resourceName } = require("./live2d-import"); + +const ORIGIN = "pet-live2d://viewer"; +const CORE_URL = "https://cubism.live2d.com/sdk-web/core/05/live2dcubismcore.min.js"; +const CORE_SHA256 = "25ae938cb4fe282ce189b357bcc97e603d1e1f7ec78bf04150d401c23cdc792f"; +const CORE_LIMIT = 4 * 1024 * 1024; +const POLICY = "default-src 'none'; script-src 'self' 'unsafe-eval' 'wasm-unsafe-eval'; style-src 'self'; img-src 'self' data: blob:; connect-src 'self'; media-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none'; frame-src 'none'"; + +function corePath(userData) { return path.join(userData, "live2d-runtime", "live2dcubismcore.min.js"); } +function validCore(bytes) { + return bytes.length <= CORE_LIMIT && createHash("sha256").update(bytes).digest("hex") === CORE_SHA256; +} +function runtimeReady(userData) { + try { return validCore(readLocal(path.dirname(corePath(userData)), path.basename(corePath(userData)), CORE_LIMIT)); } + catch { return false; } +} +function installCore(source, userData) { + const stat = fs.lstatSync(source); + if (stat.isSymbolicLink() || !stat.isFile() || stat.size > CORE_LIMIT) throw new Error("invalid_runtime"); + const bytes = fs.readFileSync(source); + if (!validCore(bytes)) throw new Error("unrecognized_runtime"); + const target = corePath(userData); + fs.mkdirSync(path.dirname(target), { recursive: true }); + fs.writeFileSync(`${target}.tmp`, bytes); + fs.renameSync(`${target}.tmp`, target); +} + +function createModelHandler({ userData, sourceDir, getActiveCharacter }) { + const viewerFiles = new Map([ + ["/index.html", ["index.html", "text/html"]], + ["/viewer.js", ["viewer.js", "text/javascript"]], + ["/rig.js", ["rig.js", "text/javascript"]], + ["/viewer.css", ["viewer.css", "text/css"]], + ["/pixi.min.js", ["vendor/pixi.min.js", "text/javascript"]], + ["/cubism4.min.js", ["vendor/cubism4.min.js", "text/javascript"]], + ]); + return (request) => { + const headers = { "Content-Security-Policy": POLICY, "X-Content-Type-Options": "nosniff", "Cache-Control": "no-store" }; + try { + const url = new URL(request.url); + if (url.protocol !== "pet-live2d:" || url.hostname !== "viewer" || url.port || url.username || url.password + || url.search || request.method !== "GET") throw new Error(); + let bytes; + let mime; + if (viewerFiles.has(url.pathname)) { + const [file, type] = viewerFiles.get(url.pathname); + bytes = readLocal(path.join(sourceDir, "live2d"), file, 8 * 1024 * 1024); mime = type; + } else if (url.pathname === "/core.js") { + bytes = readLocal(path.dirname(corePath(userData)), path.basename(corePath(userData)), CORE_LIMIT); + if (!validCore(bytes)) throw new Error(); + mime = "text/javascript"; + } else { + const match = /^\/models\/(imported-[a-f0-9]{24})\/(.+)$/.exec(url.pathname); + const pack = getActiveCharacter(); + if (!match || pack?.type !== "live2d" || pack.id !== match[1]) throw new Error(); + const name = resourceName(decodeURIComponent(match[2])); + const root = path.join(userData, "characters", pack.id); + const manifest = JSON.parse(readLocal(root, "character.json", 262144).toString("utf8")); + if (!Array.isArray(manifest.resources) || !manifest.resources.includes(name)) throw new Error(); + mime = name.endsWith(".png") ? "image/png" : name.endsWith(".json") ? "application/json" : name.endsWith(".moc3") ? "application/octet-stream" : null; + if (!mime) throw new Error(); + bytes = readLocal(root, name, 128 * 1024 * 1024); + } + return new Response(bytes, { headers: { ...headers, "Content-Type": mime } }); + } catch { return new Response("Unavailable", { status: 404, headers }); } + }; +} + +module.exports = { ORIGIN, CORE_URL, CORE_SHA256, POLICY, validCore, runtimeReady, installCore, createModelHandler }; diff --git a/src/live2d-import.js b/src/live2d-import.js new file mode 100644 index 0000000..932a99d --- /dev/null +++ b/src/live2d-import.js @@ -0,0 +1,195 @@ +const fs = require("node:fs"); +const path = require("node:path"); +const { createHash } = require("node:crypto"); +const { unzipSync } = require("fflate"); +const { pngSize } = require("./character-import"); + +const MAX_BYTES = 128 * 1024 * 1024; +const MAX_FILES = 256; +const MAX_JSON = 2 * 1024 * 1024; + +function resourceName(value) { + if (typeof value !== "string" || !value || value.length > 240 + || /[\\:%?#\x00-\x1f\x7f]/.test(value) || value.startsWith("/")) throw new Error("invalid_path"); + const parts = value.split("/"); + if (parts.length > 10 || parts.some((part) => !part || part === "." || part === ".." + || /[. ]$/.test(part) || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part))) throw new Error("invalid_path"); + return value; +} + +function readLocal(root, name, limit) { + const parts = resourceName(name).split("/"); + let current = root; + for (const part of parts) { + current = path.join(current, part); + if (fs.lstatSync(current).isSymbolicLink()) throw new Error("symlink"); + } + const stat = fs.statSync(current); + if (!stat.isFile() || stat.size > limit) throw new Error("invalid_size"); + return fs.readFileSync(current); +} + +function readJson(bytes) { + if (!bytes || bytes.length > MAX_JSON) throw new Error("invalid_json"); + const value = JSON.parse(Buffer.from(bytes).toString("utf8")); + const pending = [[value, 0]]; + let count = 0; + while (pending.length) { + const [item, depth] = pending.pop(); + if (++count > 150000 || depth > 24) throw new Error("complex_json"); + if (item && typeof item === "object") { + for (const [key, child] of Object.entries(item)) { + if (["__proto__", "constructor", "prototype"].includes(key)) throw new Error("invalid_json"); + pending.push([child, depth + 1]); + } + } + } + return value; +} + +function readLive2DPack(source, decodeImage) { + const stat = fs.lstatSync(source); + if (stat.isSymbolicLink()) throw new Error("symlink"); + let modelName; + let read; + if (stat.isFile() && source.endsWith(".zip")) { + if (stat.size > MAX_BYTES) throw new Error("archive_too_large"); + let total = 0; + let count = 0; + const seen = new Set(); + const zip = unzipSync(fs.readFileSync(source), { filter(entry) { + const name = entry.name.replace(/\/$/, ""); + resourceName(name); + const folded = name.normalize("NFC").toLowerCase(); + if (seen.has(folded) || ++count > MAX_FILES) throw new Error("invalid_archive"); + seen.add(folded); + if (!Number.isSafeInteger(entry.originalSize) || entry.originalSize < 0) throw new Error("invalid_size"); + total += entry.originalSize; + if (total > MAX_BYTES || (/\.json$/i.test(name) && entry.originalSize > MAX_JSON)) throw new Error("archive_too_large"); + return /\.(moc3|png|json)$/i.test(name); + } }); + const models = Object.keys(zip).filter((name) => name.endsWith(".model3.json")); + if (models.length !== 1) throw new Error("model_count"); + const prefix = models[0].slice(0, models[0].lastIndexOf("/") + 1); + modelName = models[0].slice(prefix.length); + read = (name, limit) => { + const bytes = zip[prefix + resourceName(name)]; + if (!bytes || bytes.length > limit) throw new Error("missing_resource"); + return Buffer.from(bytes); + }; + } else { + let root = source; + if (stat.isFile() && source.endsWith(".model3.json")) { + root = path.dirname(source); + modelName = path.basename(source); + } else if (stat.isDirectory()) { + const models = fs.readdirSync(root).filter((name) => name.endsWith(".model3.json")); + if (models.length !== 1) throw new Error("model_count"); + modelName = models[0]; + } else throw new Error("invalid_model"); + read = (name, limit) => readLocal(root, name, limit); + } + + const raw = readJson(read(modelName, MAX_JSON)); + const refs = raw.FileReferences; + if (raw.Version !== 3 || !refs || !Array.isArray(refs.Textures) + || !refs.Textures.length || refs.Textures.length > 8) throw new Error("invalid_model"); + const files = Object.create(null); + let bytesUsed = 0; + let pixels = 0; + const add = (name, extension) => { + resourceName(name); + if (!name.endsWith(extension)) throw new Error("invalid_resource"); + if (files[name]) return name; + const bytes = read(name, extension.endsWith("json") ? MAX_JSON : MAX_BYTES); + bytesUsed += bytes.length; + if (bytesUsed > MAX_BYTES || Object.keys(files).length >= MAX_FILES) throw new Error("model_too_large"); + if (extension === ".png") { + const size = pngSize(bytes); + pixels += size.width * size.height; + if (size.width > 8192 || size.height > 8192 || pixels > 64000000) throw new Error("image_too_large"); + if (decodeImage && !decodeImage(bytes)) throw new Error("image_decode_failed"); + } else if (extension.endsWith("json")) readJson(bytes); + files[name] = bytes; + return name; + }; + const cleanRefs = { Moc: add(refs.Moc, ".moc3"), Textures: refs.Textures.map((name) => add(name, ".png")) }; + if (files[cleanRefs.Moc].length < 64 || files[cleanRefs.Moc].subarray(0, 4).toString() !== "MOC3") throw new Error("invalid_moc"); + for (const key of ["Physics", "Pose"]) if (refs[key]) cleanRefs[key] = add(refs[key], key === "Physics" ? ".physics3.json" : ".pose3.json"); + if (refs.Expressions !== undefined) { + if (!Array.isArray(refs.Expressions) || refs.Expressions.length > 64) throw new Error("invalid_expressions"); + cleanRefs.Expressions = refs.Expressions.map((entry, index) => ({ + Name: String(entry.Name || `Expression ${index + 1}`).slice(0, 80), File: add(entry.File, ".exp3.json"), + })); + } + cleanRefs.Motions = {}; + if (refs.Motions !== undefined) { + if (!refs.Motions || Array.isArray(refs.Motions) || typeof refs.Motions !== "object" + || Object.keys(refs.Motions).length > 32) throw new Error("invalid_motions"); + for (const [group, motions] of Object.entries(refs.Motions)) { + if (group.length > 80 || !Array.isArray(motions) || motions.length > 64) throw new Error("invalid_motions"); + cleanRefs.Motions[group] = motions.map((entry) => { + // Model audio is deliberately excluded: only the user's TTS may speak. + const result = { File: add(entry.File, ".motion3.json") }; + for (const key of ["FadeInTime", "FadeOutTime"]) if (Number.isFinite(entry[key])) result[key] = Math.min(10, Math.max(0, entry[key])); + return result; + }); + } + } + const model = { Version: 3, FileReferences: cleanRefs }; + if (raw.HitAreas !== undefined) { + if (!Array.isArray(raw.HitAreas) || raw.HitAreas.length > 64) throw new Error("invalid_hit_areas"); + const usedNames = new Set(); + model.HitAreas = raw.HitAreas.map((area, index) => { + if (!area || typeof area.Id !== "string" || !area.Id.length || area.Id.length > 128 + || /[\u0000-\u001f\u007f]/.test(area.Id)) throw new Error("invalid_hit_areas"); + let name = typeof area.Name === "string" ? area.Name.trim().slice(0, 80) : ""; + if (!name || usedNames.has(name) || /[\u0000-\u001f\u007f]/.test(name) + || ["__proto__", "constructor", "prototype"].includes(name)) name = `${area.Id} ${index + 1}`; + while (usedNames.has(name)) name += "_"; + usedNames.add(name); + return { Id: area.Id, Name: name }; + }); + } + if (raw.Groups) { + if (!Array.isArray(raw.Groups) || raw.Groups.length > 8) throw new Error("invalid_groups"); + model.Groups = raw.Groups.filter((group) => group.Target === "Parameter" && ["EyeBlink", "LipSync"].includes(group.Name)) + .map((group) => ({ Target: "Parameter", Name: group.Name, + Ids: Array.isArray(group.Ids) ? group.Ids.slice(0, 64).filter((id) => typeof id === "string" && id.length <= 80) : [] })); + } + if (raw.Layout && typeof raw.Layout === "object") { + model.Layout = Object.fromEntries(Object.entries(raw.Layout).filter(([key, value]) => + ["CenterX", "CenterY", "X", "Y", "Width", "Height", "Top", "Bottom", "Left", "Right"].includes(key) + && Number.isFinite(value) && Math.abs(value) <= 100)); + } + // Only this reconstructed resource graph is installed; no scripts, URLs or unrelated files. + files["model.model3.json"] = Buffer.from(JSON.stringify(model)); + const digest = createHash("sha256"); + for (const name of Object.keys(files).sort()) digest.update(name).update(files[name]); + const manifest = { + schemaVersion: 1, type: "live2d", id: `imported-${digest.digest("hex").slice(0, 24)}`, + name: modelName.replace(/\.model3\.json$/, "").slice(0, 80), description: "", + model: "model.model3.json", resources: Object.keys(files), + expressions: (cleanRefs.Expressions || []).map((item) => item.Name), + motions: Object.fromEntries(Object.entries(cleanRefs.Motions).map(([group, items]) => [group, items.length])), + }; + return { manifest, files }; +} + +function installLive2DPack(pack, root) { + const target = path.join(root, pack.manifest.id); + if (fs.existsSync(target)) return; + fs.mkdirSync(root, { recursive: true }); + const staging = fs.mkdtempSync(path.join(root, ".import-")); + try { + for (const [name, bytes] of Object.entries(pack.files)) { + const dest = path.join(staging, resourceName(name)); + fs.mkdirSync(path.dirname(dest), { recursive: true }); + fs.writeFileSync(dest, bytes); + } + fs.writeFileSync(path.join(staging, "character.json"), JSON.stringify(pack.manifest, null, 2)); + fs.renameSync(staging, target); + } finally { fs.rmSync(staging, { recursive: true, force: true }); } +} + +module.exports = { readLive2DPack, installLive2DPack, resourceName, readLocal, MAX_BYTES }; diff --git a/src/live2d/index.html b/src/live2d/index.html new file mode 100644 index 0000000..41241d7 --- /dev/null +++ b/src/live2d/index.html @@ -0,0 +1,17 @@ + + + + + + Character + + + + + + + + + + + diff --git a/src/live2d/rig.js b/src/live2d/rig.js new file mode 100644 index 0000000..d8968a4 --- /dev/null +++ b/src/live2d/rig.js @@ -0,0 +1,39 @@ +((root) => { + const aliases = { ParamAngleX: "PARAM_ANGLE_X", ParamAngleY: "PARAM_ANGLE_Y", ParamAngleZ: "PARAM_ANGLE_Z", + ParamEyeBallX: "PARAM_EYE_BALL_X", ParamEyeBallY: "PARAM_EYE_BALL_Y", ParamBodyAngleX: "PARAM_BODY_ANGLE_X", ParamBreath: "PARAM_BREATH", + ParamMouthOpenY: "PARAM_MOUTH_OPEN_Y" }; + function configure(internal) { + const ids = new Set(internal.coreModel.getModel().parameters.ids); + const resolve = (name) => ids.has(name) ? name : ids.has(aliases[name]) ? aliases[name] : name; + for (const key of ["AngleX", "AngleY", "AngleZ", "EyeBallX", "EyeBallY", "BodyAngleX", "Breath"]) internal[`idParam${key}`] = resolve(`Param${key}`); + for (const parameter of internal.breath.getParameters()) { + parameter.parameterId = resolve(parameter.parameterId); + if (parameter.parameterId !== resolve("ParamBreath")) parameter.peak *= 0.45; + } + internal.eyeBlink?.setBlinkingInterval(4); + return { ids, resolve }; + } + function measure(application, model) { + const { width, height } = application.screen; + const zoom = Math.min(width / model.internalModel.width, height / model.internalModel.height) * 0.25; + model.anchor.set(0.5, 0.5); model.scale.set(zoom); model.position.set(width / 2, height / 2); + model.update(16); application.renderer.render(application.stage); + const gl = application.renderer.gl; + const canvas = application.view; + const pixels = new Uint8Array(canvas.width * canvas.height * 4); + gl.readPixels(0, 0, canvas.width, canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + let left = canvas.width, top = canvas.height, right = -1, bottom = -1; + for (let i = 3; i < pixels.length; i += 4) if (pixels[i] > 8) { + const x = ((i - 3) / 4) % canvas.width, y = Math.floor((i - 3) / 4 / canvas.width); + left = Math.min(left, x); right = Math.max(right, x); top = Math.min(top, y); bottom = Math.max(bottom, y); + } + if (right < left) return null; + const ratio = application.renderer.resolution; + return { width: (right - left + 1) / ratio / zoom, height: (bottom - top + 1) / ratio / zoom, + x: ((left + right + 1) / 2 / ratio - width / 2) / zoom, + y: (height / 2 - (top + bottom + 1) / 2 / ratio) / zoom }; + } + const api = { configure, measure }; + if (typeof module === "object" && module.exports) module.exports = api; + else root.DesktopPetRig = api; +})(globalThis); diff --git a/src/live2d/vendor/CUBISM-FRAMEWORK-LICENSE.md b/src/live2d/vendor/CUBISM-FRAMEWORK-LICENSE.md new file mode 100644 index 0000000..bd0be75 --- /dev/null +++ b/src/live2d/vendor/CUBISM-FRAMEWORK-LICENSE.md @@ -0,0 +1,45 @@ +## Definitions + +### Live2D Cubism Components + +Cubism Web Framework is included in Live2D Cubism Components. + +Cubism Web Framework は Live2D Cubism Components に含まれます。 + +Cubism Web Framework 包括在 Live2D Cubism Components 中。 + +## Cubism SDK Release License + +*All business* users must obtain a Cubism SDK Release License. "Business" means an entity with the annual gross revenue more than ten million (10,000,000) JPY for the most recent fiscal year. + +* [Cubism SDK Release License](https://www.live2d.com/en/download/cubism-sdk/release-license/) + +直近会計年度の売上高が 1000 万円以上の事業者様がご利用になる場合は、Cubism SDK リリースライセンス(出版許諾契約)に同意していただく必要がございます。 + +* [Cubism SDK リリースライセンス](https://www.live2d.com/ja/download/cubism-sdk/release-license/) + +如果您的企业在最近一个会计年度的销售额达到或超过1000万日元,您必须得到Cubism SDK的出版授权许可(出版许可协议)。 + +* [Cubism SDK发行许可证](https://www.live2d.com/zh-CHS/download/cubism-sdk/release-license/) + +## Live2D Open Software License + +Live2D Cubism Components is available under Live2D Open Software License. + +* [Live2D Open Software License](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html) +* [Live2D Open Software 使用許諾契約書](https://www.live2d.com/eula/live2d-open-software-license-agreement_jp.html) +* [Live2D Open Software 使用授权协议](https://www.live2d.com/eula/live2d-open-software-license-agreement_cn.html) + + +## Live2D Proprietary Software License + +Live2D Cubism Core is available under Live2D Proprietary Software License. + +* [Live2D Proprietary Software License Agreement](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html) +* [Live2D Proprietary Software 使用許諾契約書](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_jp.html) +* [Live2D Proprietary Software 使用授权协议](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_cn.html) + + +--- + +Please contact us from [here](https://www.live2d.jp/contact/) for more license information. diff --git a/src/live2d/vendor/NOTICE.md b/src/live2d/vendor/NOTICE.md new file mode 100644 index 0000000..0fb45a1 --- /dev/null +++ b/src/live2d/vendor/NOTICE.md @@ -0,0 +1,20 @@ +# Third-Party Runtime Notices + +These files are unmodified browser distributions. They are served locally; no CDN is contacted at runtime. + +| File | Version | Source | SHA-256 | +| --- | --- | --- | --- | +| `pixi.min.js` | PixiJS 6.5.10 | https://cdn.jsdelivr.net/npm/pixi.js@6.5.10/dist/browser/pixi.min.js | `403f2f2ee8145fa17f60c5c89403056efe2680e5096ec2762036486914ed19c5` | +| `cubism4.min.js` | pixi-live2d-display 0.4.0 | https://cdn.jsdelivr.net/npm/pixi-live2d-display@0.4.0/dist/cubism4.min.js | `af1267e6d52759b245766c578d905bfa025b532d5c3cc727c370957c4409e21b` | + +PixiJS is MIT licensed, copyright its contributors. See `PIXI-LICENSE.txt`. + +pixi-live2d-display is MIT licensed, copyright Guan. See `PIXI-LIVE2D-LICENSE.txt`. + +The Cubism display bundle also contains Live2D Cubism Framework components, copyright Live2D Inc., under the [Live2D Open Software License](https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html). See the upstream `CUBISM-FRAMEWORK-LICENSE.md` notice. The surrounding library's MIT license does not replace Live2D's terms. + +Cubism Core is proprietary and is not included. The optional local importer recognizes the official Core 5.2 file at https://cubism.live2d.com/sdk-web/core/05/live2dcubismcore.min.js, SHA-256 `25ae938cb4fe282ce189b357bcc97e603d1e1f7ec78bf04150d401c23cdc792f`. Its use is subject to the [Live2D Proprietary Software License](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html). + +Applications which load user-supplied models are subject to Live2D's [expandable-application publication terms](https://www.live2d.com/en/sdk/license/expandable/). The repository's MIT license does not replace those terms or grant an SDK publication license. + +No Live2D sample or user model is included in this directory or in the application's character assets. diff --git a/src/live2d/vendor/PIXI-LICENSE.txt b/src/live2d/vendor/PIXI-LICENSE.txt new file mode 100644 index 0000000..d9de993 --- /dev/null +++ b/src/live2d/vendor/PIXI-LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2013-2017 Mathew Groves, Chad Engler + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/live2d/vendor/PIXI-LIVE2D-LICENSE.txt b/src/live2d/vendor/PIXI-LIVE2D-LICENSE.txt new file mode 100644 index 0000000..dbc2166 --- /dev/null +++ b/src/live2d/vendor/PIXI-LIVE2D-LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Guan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/live2d/vendor/cubism4.min.js b/src/live2d/vendor/cubism4.min.js new file mode 100644 index 0000000..f0e4a50 --- /dev/null +++ b/src/live2d/vendor/cubism4.min.js @@ -0,0 +1 @@ +var __pow=Math.pow,__async=(t,e,i)=>new Promise(((s,r)=>{var a=t=>{try{n(i.next(t))}catch(e){r(e)}},o=t=>{try{n(i.throw(t))}catch(e){r(e)}},n=t=>t.done?s(t.value):Promise.resolve(t.value).then(a,o);n((i=i.apply(t,e)).next())}));!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@pixi/utils"),require("@pixi/math"),require("@pixi/core"),require("@pixi/display")):"function"==typeof define&&define.amd?define(["exports","@pixi/utils","@pixi/math","@pixi/core","@pixi/display"],e):e(((t="undefined"!=typeof globalThis?globalThis:t||self).PIXI=t.PIXI||{},t.PIXI.live2d=t.PIXI.live2d||{}),t.PIXI.utils,t.PIXI,t.PIXI,t.PIXI)}(this,(function(t,e,i,s,r){"use strict";class a{constructor(){this._breathParameters=[],this._currentTime=0}static create(){return new a}setParameters(t){this._breathParameters=t}getParameters(){return this._breathParameters}updateParameters(t,e){this._currentTime+=e;const i=2*this._currentTime*3.14159;for(let s=0;s=1&&(s=1,this._blinkingState=h.EyeState_Closed,this._stateStartTimeSeconds=this._userTimeSeconds),i=1-s;break;case h.EyeState_Closed:s=(this._userTimeSeconds-this._stateStartTimeSeconds)/this._closedSeconds,s>=1&&(this._blinkingState=h.EyeState_Opening,this._stateStartTimeSeconds=this._userTimeSeconds),i=0;break;case h.EyeState_Opening:s=(this._userTimeSeconds-this._stateStartTimeSeconds)/this._openingSeconds,s>=1&&(s=1,this._blinkingState=h.EyeState_Interval,this._nextBlinkingTime=this.determinNextBlinkingTiming()),i=s;break;case h.EyeState_Interval:this._nextBlinkingTime(t[t.EyeState_First=0]="EyeState_First",t[t.EyeState_Interval=1]="EyeState_Interval",t[t.EyeState_Closing=2]="EyeState_Closing",t[t.EyeState_Closed=3]="EyeState_Closed",t[t.EyeState_Opening=4]="EyeState_Opening",t))(h||{});class u{static create(t){const e=new u;"number"==typeof t.FadeInTime&&(e._fadeTimeSeconds=t.FadeInTime,e._fadeTimeSeconds<=0&&(e._fadeTimeSeconds=.5));const i=t.Groups,s=i.length;for(let r=0;r.001){if(r>=0)break;r=n,a=t.getPartOpacityByIndex(i),a+=e/this._fadeTimeSeconds,a>1&&(a=1)}}r<0&&(r=0,a=1);for(let n=i;n.15&&(i=1-.15/(1-a)),s>i&&(s=i),t.setPartOpacityByIndex(e,s)}}}constructor(){this._fadeTimeSeconds=.5,this._lastModel=void 0,this._partGroups=[],this._partGroupCounts=[]}}class d{constructor(t){this.parameterIndex=0,this.partIndex=0,this.partId="",this.link=[],null!=t&&this.assignment(t)}assignment(t){return this.partId=t.partId,this.link=t.link.map((t=>t.clone())),this}initialize(t){this.parameterIndex=t.getParameterIndex(this.partId),this.partIndex=t.getPartIndex(this.partId),t.setParameterValueByIndex(this.parameterIndex,1)}clone(){const t=new d;return t.partId=this.partId,t.parameterIndex=this.parameterIndex,t.partIndex=this.partIndex,t.link=this.link.map((t=>t.clone())),t}}class c{constructor(t,e){this.x=t||0,this.y=e||0}add(t){const e=new c(0,0);return e.x=this.x+t.x,e.y=this.y+t.y,e}substract(t){const e=new c(0,0);return e.x=this.x-t.x,e.y=this.y-t.y,e}multiply(t){const e=new c(0,0);return e.x=this.x*t.x,e.y=this.y*t.y,e}multiplyByScaler(t){return this.multiply(new c(t,t))}division(t){const e=new c(0,0);return e.x=this.x/t.x,e.y=this.y/t.y,e}divisionByScalar(t){return this.division(new c(t,t))}getLength(){return Math.sqrt(this.x*this.x+this.y*this.y)}getDistanceWith(t){return Math.sqrt((this.x-t.x)*(this.x-t.x)+(this.y-t.y)*(this.y-t.y))}dot(t){return this.x*t.x+this.y*t.y}normalize(){const t=Math.pow(this.x*this.x+this.y*this.y,.5);this.x=this.x/t,this.y=this.y/t}isEqual(t){return this.x==t.x&&this.y==t.y}isNotEqual(t){return!this.isEqual(t)}}const m=class{static range(t,e,i){return ti&&(t=i),t}static sin(t){return Math.sin(t)}static cos(t){return Math.cos(t)}static abs(t){return Math.abs(t)}static sqrt(t){return Math.sqrt(t)}static cbrt(t){if(0===t)return t;let e=t;const i=e<0;let s;return i&&(e=-e),e===1/0?s=1/0:(s=Math.exp(Math.log(e)/3),s=(e/(s*s)+2*s)/3),i?-s:s}static getEasingSine(t){return t<0?0:t>1?1:.5-.5*this.cos(t*Math.PI)}static max(t,e){return t>e?t:e}static min(t,e){return t>e?e:t}static degreesToRadian(t){return t/180*Math.PI}static radianToDegrees(t){return 180*t/Math.PI}static directionToRadian(t,e){let i=Math.atan2(e.y,e.x)-Math.atan2(t.y,t.x);for(;i<-Math.PI;)i+=2*Math.PI;for(;i>Math.PI;)i-=2*Math.PI;return i}static directionToDegrees(t,e){const i=this.directionToRadian(t,e);let s=this.radianToDegrees(i);return e.x-t.x>0&&(s=-s),s}static radianToDirection(t){const e=new c;return e.x=this.sin(t),e.y=this.cos(t),e}static quadraticEquation(t,e,i){return this.abs(t)1&&(t=1),e<0?e=0:e>1&&(e=1),i<0?i=0:i>1&&(i=1),s<0?s=0:s>1&&(s=1),this._modelColor.R=t,this._modelColor.G=e,this._modelColor.B=i,this._modelColor.A=s}getModelColor(){return Object.assign({},this._modelColor)}setIsPremultipliedAlpha(t){this._isPremultipliedAlpha=t}isPremultipliedAlpha(){return this._isPremultipliedAlpha}setIsCulling(t){this._isCulling=t}isCulling(){return this._isCulling}setAnisotropy(t){this._anisortopy=t}getAnisotropy(){return this._anisortopy}getModel(){return this._model}constructor(){this._isCulling=!1,this._isPremultipliedAlpha=!1,this._anisortopy=0,this._modelColor=new y,this._mvpMatrix4x4=new p,this._mvpMatrix4x4.loadIdentity()}}var f=(t=>(t[t.CubismBlendMode_Normal=0]="CubismBlendMode_Normal",t[t.CubismBlendMode_Additive=1]="CubismBlendMode_Additive",t[t.CubismBlendMode_Multiplicative=2]="CubismBlendMode_Multiplicative",t))(f||{});class y{constructor(){this.R=1,this.G=1,this.B=1,this.A=1}}let x,v=!1,M=!1;const P={vertexOffset:0,vertexStep:2};class C{static startUp(t){if(v)return I("CubismFramework.startUp() is already done."),v;if(Live2DCubismCore._isStarted)return v=!0,!0;if(Live2DCubismCore._isStarted=!0,x=t,x&&Live2DCubismCore.Logging.csmSetLogFunction(x.logFunction),v=!0,v){const t=Live2DCubismCore.Version.csmGetVersion(),e=(16711680&t)>>16,i=65535&t,s=t;I("Live2D Cubism Core version: {0}.{1}.{2} ({3})",("00"+((4278190080&t)>>24)).slice(-2),("00"+e).slice(-2),("0000"+i).slice(-4),s)}return I("CubismFramework.startUp() is complete."),v}static cleanUp(){v=!1,M=!1,x=void 0}static initialize(){v?M?L("CubismFramework.initialize() skipped, already initialized."):(M=!0,I("CubismFramework.initialize() is complete.")):L("CubismFramework is not started.")}static dispose(){v?M?(_.staticRelease(),M=!1,I("CubismFramework.dispose() is complete.")):L("CubismFramework.dispose() skipped, not initialized."):L("CubismFramework is not started.")}static isStarted(){return v}static isInitialized(){return M}static coreLogFunction(t){Live2DCubismCore.Logging.csmGetLogFunction()&&Live2DCubismCore.Logging.csmGetLogFunction()(t)}static getLoggingLevel(){return null!=x?x.loggingLevel:S.LogLevel_Off}constructor(){}}var S=(t=>(t[t.LogLevel_Verbose=0]="LogLevel_Verbose",t[t.LogLevel_Debug=1]="LogLevel_Debug",t[t.LogLevel_Info=2]="LogLevel_Info",t[t.LogLevel_Warning=3]="LogLevel_Warning",t[t.LogLevel_Error=4]="LogLevel_Error",t[t.LogLevel_Off=5]="LogLevel_Off",t))(S||{});const b=()=>{};function w(t,...e){E.print(S.LogLevel_Debug,"[CSM][D]"+t+"\n",e)}function I(t,...e){E.print(S.LogLevel_Info,"[CSM][I]"+t+"\n",e)}function L(t,...e){E.print(S.LogLevel_Warning,"[CSM][W]"+t+"\n",e)}function T(t,...e){E.print(S.LogLevel_Error,"[CSM][E]"+t+"\n",e)}class E{static print(t,e,i){if(ti[e])))}static dumpBytes(t,e,i){for(let s=0;s0?this.print(t,"\n"):s%8==0&&s>0&&this.print(t," "),this.print(t,"{0} ",[255&e[s]]);this.print(t,"\n")}constructor(){}}class D{update(){this._model.update(),this._model.drawables.resetDynamicFlags()}getCanvasWidth(){return null==this._model?0:this._model.canvasinfo.CanvasWidth/this._model.canvasinfo.PixelsPerUnit}getCanvasHeight(){return null==this._model?0:this._model.canvasinfo.CanvasHeight/this._model.canvasinfo.PixelsPerUnit}saveParameters(){const t=this._model.parameters.count,e=this._savedParameters.length;for(let i=0;ie&&(e=this._model.parameters.minimumValues[t]),this._parameterValues[t]=1==i?e:this._parameterValues[t]=this._parameterValues[t]*(1-i)+e*i)}setParameterValueById(t,e,i=1){const s=this.getParameterIndex(t);this.setParameterValueByIndex(s,e,i)}addParameterValueByIndex(t,e,i=1){this.setParameterValueByIndex(t,this.getParameterValueByIndex(t)+e*i)}addParameterValueById(t,e,i=1){const s=this.getParameterIndex(t);this.addParameterValueByIndex(s,e,i)}multiplyParameterValueById(t,e,i=1){const s=this.getParameterIndex(t);this.multiplyParameterValueByIndex(s,e,i)}multiplyParameterValueByIndex(t,e,i=1){this.setParameterValueByIndex(t,this.getParameterValueByIndex(t)*(1+(e-1)*i))}getDrawableIds(){return this._drawableIds.slice()}getDrawableIndex(t){const e=this._model.drawables.count;for(let i=0;ie&&(t=e);for(let i=0;i0&&e.getEndTime()(t[t.ExpressionBlendType_Add=0]="ExpressionBlendType_Add",t[t.ExpressionBlendType_Multiply=1]="ExpressionBlendType_Multiply",t[t.ExpressionBlendType_Overwrite=2]="ExpressionBlendType_Overwrite",t))(U||{});t.CubismConfig=void 0,(k=t.CubismConfig||(t.CubismConfig={})).supportMoreMaskDivisions=!0,k.setOpacityFromMotion=!1;var N=(t=>(t[t.CubismMotionCurveTarget_Model=0]="CubismMotionCurveTarget_Model",t[t.CubismMotionCurveTarget_Parameter=1]="CubismMotionCurveTarget_Parameter",t[t.CubismMotionCurveTarget_PartOpacity=2]="CubismMotionCurveTarget_PartOpacity",t))(N||{}),V=(t=>(t[t.CubismMotionSegmentType_Linear=0]="CubismMotionSegmentType_Linear",t[t.CubismMotionSegmentType_Bezier=1]="CubismMotionSegmentType_Bezier",t[t.CubismMotionSegmentType_Stepped=2]="CubismMotionSegmentType_Stepped",t[t.CubismMotionSegmentType_InverseStepped=3]="CubismMotionSegmentType_InverseStepped",t))(V||{});class j{constructor(t=0,e=0){this.time=t,this.value=e}}class G{constructor(){this.basePointIndex=0,this.segmentType=0}}class X{constructor(){this.id="",this.type=0,this.segmentCount=0,this.baseSegmentIndex=0,this.fadeInTime=0,this.fadeOutTime=0}}class z{constructor(){this.fireTime=0,this.value=""}}class W{constructor(){this.duration=0,this.loop=!1,this.curveCount=0,this.eventCount=0,this.fps=0,this.curves=[],this.segments=[],this.points=[],this.events=[]}}class H{constructor(t){this._json=t}release(){this._json=void 0}getMotionDuration(){return this._json.Meta.Duration}isMotionLoop(){return this._json.Meta.Loop||!1}getEvaluationOptionFlag(t){return Y.EvaluationOptionFlag_AreBeziersRistricted==t&&!!this._json.Meta.AreBeziersRestricted}getMotionCurveCount(){return this._json.Meta.CurveCount}getMotionFps(){return this._json.Meta.Fps}getMotionTotalSegmentCount(){return this._json.Meta.TotalSegmentCount}getMotionTotalPointCount(){return this._json.Meta.TotalPointCount}getMotionFadeInTime(){return this._json.Meta.FadeInTime}getMotionFadeOutTime(){return this._json.Meta.FadeOutTime}getMotionCurveTarget(t){return this._json.Curves[t].Target}getMotionCurveId(t){return this._json.Curves[t].Id}getMotionCurveFadeInTime(t){return this._json.Curves[t].FadeInTime}getMotionCurveFadeOutTime(t){return this._json.Curves[t].FadeOutTime}getMotionCurveSegmentCount(t){return this._json.Curves[t].Segments.length}getMotionCurveSegment(t,e){return this._json.Curves[t].Segments[e]}getEventCount(){return this._json.Meta.UserDataCount||0}getTotalEventValueSize(){return this._json.Meta.TotalUserDataSize}getEventTime(t){return this._json.UserData[t].Time}getEventValue(t){return this._json.UserData[t].Value}}var Y=(t=>(t[t.EvaluationOptionFlag_AreBeziersRistricted=0]="EvaluationOptionFlag_AreBeziersRistricted",t))(Y||{});function q(t,e,i){const s=new j;return s.time=t.time+(e.time-t.time)*i,s.value=t.value+(e.value-t.value)*i,s}function $(t,e){let i=(e-t[0].time)/(t[1].time-t[0].time);return i<0&&(i=0),t[0].value+(t[1].value-t[0].value)*i}function Z(t,e){let i=(e-t[0].time)/(t[3].time-t[0].time);i<0&&(i=0);const s=q(t[0],t[1],i),r=q(t[1],t[2],i),a=q(t[2],t[3],i),o=q(s,r,i),n=q(r,a,i);return q(o,n,i).value}function J(t,e){const i=e,s=t[0].time,r=t[3].time,a=t[1].time,o=t[2].time,n=r-3*o+3*a-s,l=3*o-6*a+3*s,h=3*a-3*s,u=s-i,d=g.cardanoAlgorithmForBezier(n,l,h,u),c=q(t[0],t[1],d),m=q(t[1],t[2],d),p=q(t[2],t[3],d),_=q(c,m,d),f=q(m,p,d);return q(_,f,d).value}function Q(t,e){return t[0].value}function K(t,e){return t[1].value}function tt(t,e,i){const s=t.curves[e];let r=-1;const a=s.baseSegmentIndex+s.segmentCount;let o=0;for(let l=s.baseSegmentIndex;li){r=l;break}if(-1==r)return t.points[o].value;const n=t.segments[r];return n.evaluate(t.points.slice(n.basePointIndex),i)}class et extends R{constructor(){super(),this._eyeBlinkParameterIds=[],this._lipSyncParameterIds=[],this._sourceFrameRate=30,this._loopDurationSeconds=-1,this._isLoop=!1,this._isLoopFadeIn=!0,this._lastWeight=0}static create(t,e){const i=new et;return i.parse(t),i._sourceFrameRate=i._motionData.fps,i._loopDurationSeconds=i._motionData.duration,i._onFinishedMotion=e,i}doUpdateParameters(e,i,s,r){null==this._modelCurveIdEyeBlink&&(this._modelCurveIdEyeBlink="EyeBlink"),null==this._modelCurveIdLipSync&&(this._modelCurveIdLipSync="LipSync");let a=i-r.getStartTime();a<0&&(a=0);let o=Number.MAX_VALUE,n=Number.MAX_VALUE;const l=64;let h=0,u=0;this._eyeBlinkParameterIds.length>l&&w("too many eye blink targets : {0}",this._eyeBlinkParameterIds.length),this._lipSyncParameterIds.length>l&&w("too many lip sync targets : {0}",this._lipSyncParameterIds.length);const d=this._fadeInSeconds<=0?1:g.getEasingSine((i-r.getFadeInStartTime())/this._fadeInSeconds),c=this._fadeOutSeconds<=0||r.getEndTime()<0?1:g.getEasingSine((r.getEndTime()-i)/this._fadeOutSeconds);let m,p,_,f=a;if(this._isLoop)for(;f>this._motionData.duration;)f-=this._motionData.duration;const y=this._motionData.curves;for(p=0;p>t&1)continue;const r=i+(n-i)*s;e.setParameterValueById(this._eyeBlinkParameterIds[t],r)}if(o!=Number.MAX_VALUE)for(let t=0;t>t&1)continue;const r=i+(o-i)*s;e.setParameterValueById(this._lipSyncParameterIds[t],r)}for(;p=this._motionData.duration&&(this._isLoop?(r.setStartTime(i),this._isLoopFadeIn&&r.setFadeInStartTime(i)):(this._onFinishedMotion&&this._onFinishedMotion(this),r.setIsFinished(!0))),this._lastWeight=s}setIsLoop(t){this._isLoop=t}isLoop(){return this._isLoop}setIsLoopFadeIn(t){this._isLoopFadeIn=t}isLoopFadeIn(){return this._isLoopFadeIn}getDuration(){return this._isLoop?-1:this._loopDurationSeconds}getLoopDuration(){return this._loopDurationSeconds}setParameterFadeInTime(t,e){const i=this._motionData.curves;for(let s=0;snew X)),this._motionData.segments=Array.from({length:e.getMotionTotalSegmentCount()}).map((()=>new G)),this._motionData.events=Array.from({length:this._motionData.eventCount}).map((()=>new z)),this._motionData.points=[];let a=0,o=0;for(let n=0;nt&&this._motionData.events[i].fireTime<=e&&this._firedEventValues.push(this._motionData.events[i].value);return this._firedEventValues}}class it{constructor(){this._autoDelete=!1,this._available=!0,this._finished=!1,this._started=!1,this._startTimeSeconds=-1,this._fadeInStartTimeSeconds=0,this._endTimeSeconds=-1,this._stateTimeSeconds=0,this._stateWeight=0,this._lastEventCheckSeconds=0,this._motionQueueEntryHandle=this,this._fadeOutSeconds=0,this._isTriggeredFadeOut=!1}release(){this._autoDelete&&this._motion&&this._motion.release()}setFadeOut(t){this._fadeOutSeconds=t,this._isTriggeredFadeOut=!0}startFadeOut(t,e){const i=e+t;this._isTriggeredFadeOut=!0,(this._endTimeSeconds<0||inull!=e&&e._motionQueueEntryHandle==t))}setEventCallback(t,e=null){this._eventCallBack=t,this._eventCustomData=e}doUpdateMotion(t,e){let i=!1,s=0;for(;s(t[t.CubismPhysicsTargetType_Parameter=0]="CubismPhysicsTargetType_Parameter",t))(at||{}),ot=(t=>(t[t.CubismPhysicsSource_X=0]="CubismPhysicsSource_X",t[t.CubismPhysicsSource_Y=1]="CubismPhysicsSource_Y",t[t.CubismPhysicsSource_Angle=2]="CubismPhysicsSource_Angle",t))(ot||{});class nt{constructor(){this.initialPosition=new c(0,0),this.position=new c(0,0),this.lastPosition=new c(0,0),this.lastGravity=new c(0,0),this.force=new c(0,0),this.velocity=new c(0,0)}}class lt{constructor(){this.normalizationPosition={},this.normalizationAngle={}}}class ht{constructor(){this.source={}}}class ut{constructor(){this.destination={},this.translationScale=new c(0,0)}}class dt{constructor(){this.settings=[],this.inputs=[],this.outputs=[],this.particles=[],this.gravity=new c(0,0),this.wind=new c(0,0)}}class ct{constructor(t){this._json=t}release(){this._json=void 0}getGravity(){const t=new c(0,0);return t.x=this._json.Meta.EffectiveForces.Gravity.X,t.y=this._json.Meta.EffectiveForces.Gravity.Y,t}getWind(){const t=new c(0,0);return t.x=this._json.Meta.EffectiveForces.Wind.X,t.y=this._json.Meta.EffectiveForces.Wind.Y,t}getSubRigCount(){return this._json.Meta.PhysicsSettingCount}getTotalInputCount(){return this._json.Meta.TotalInputCount}getTotalOutputCount(){return this._json.Meta.TotalOutputCount}getVertexCount(){return this._json.Meta.VertexCount}getNormalizationPositionMinimumValue(t){return this._json.PhysicsSettings[t].Normalization.Position.Minimum}getNormalizationPositionMaximumValue(t){return this._json.PhysicsSettings[t].Normalization.Position.Maximum}getNormalizationPositionDefaultValue(t){return this._json.PhysicsSettings[t].Normalization.Position.Default}getNormalizationAngleMinimumValue(t){return this._json.PhysicsSettings[t].Normalization.Angle.Minimum}getNormalizationAngleMaximumValue(t){return this._json.PhysicsSettings[t].Normalization.Angle.Maximum}getNormalizationAngleDefaultValue(t){return this._json.PhysicsSettings[t].Normalization.Angle.Default}getInputCount(t){return this._json.PhysicsSettings[t].Input.length}getInputWeight(t,e){return this._json.PhysicsSettings[t].Input[e].Weight}getInputReflect(t,e){return this._json.PhysicsSettings[t].Input[e].Reflect}getInputType(t,e){return this._json.PhysicsSettings[t].Input[e].Type}getInputSourceId(t,e){return this._json.PhysicsSettings[t].Input[e].Source.Id}getOutputCount(t){return this._json.PhysicsSettings[t].Output.length}getOutputVertexIndex(t,e){return this._json.PhysicsSettings[t].Output[e].VertexIndex}getOutputAngleScale(t,e){return this._json.PhysicsSettings[t].Output[e].Scale}getOutputWeight(t,e){return this._json.PhysicsSettings[t].Output[e].Weight}getOutputDestinationId(t,e){return this._json.PhysicsSettings[t].Output[e].Destination.Id}getOutputType(t,e){return this._json.PhysicsSettings[t].Output[e].Type}getOutputReflect(t,e){return this._json.PhysicsSettings[t].Output[e].Reflect}getParticleCount(t){return this._json.PhysicsSettings[t].Vertices.length}getParticleMobility(t,e){return this._json.PhysicsSettings[t].Vertices[e].Mobility}getParticleDelay(t,e){return this._json.PhysicsSettings[t].Vertices[e].Delay}getParticleAcceleration(t,e){return this._json.PhysicsSettings[t].Vertices[e].Acceleration}getParticleRadius(t,e){return this._json.PhysicsSettings[t].Vertices[e].Radius}getParticlePosition(t,e){const i=new c(0,0);return i.x=this._json.PhysicsSettings[t].Vertices[e].Position.X,i.y=this._json.PhysicsSettings[t].Vertices[e].Position.Y,i}}const mt="Angle";class gt{static create(t){const e=new gt;return e.parse(t),e._physicsRig.gravity.y=0,e}evaluate(t,e){let i,s,r,a;const o=new c;let n,l,h,u,d,m,p,_;d=t.getModel().parameters.values,m=t.getModel().parameters.maximumValues,p=t.getModel().parameters.minimumValues,_=t.getModel().parameters.defaultValues;for(let f=0;f=n.particleCount)break;-1==h[e].destinationParameterIndex&&(h[e].destinationParameterIndex=t.getParameterIndex(h[e].destination.id));const s=new c;s.x=u[i].position.x-u[i-1].position.x,s.y=u[i].position.y-u[i-1].position.y,a=h[e].getValue(s,u,i,h[e].reflect,this._options.gravity);const r=h[e].destinationParameterIndex,o=!Float32Array.prototype.slice&&"subarray"in Float32Array.prototype?JSON.parse(JSON.stringify(d.subarray(r))):d.slice(r);It(o,p[r],m[r],a,h[e]);for(let t=r,e=0;t=2?e[i-1].position.substract(e[i-2].position):r.multiplyByScaler(-1),a=g.directionToRadian(r,t),s&&(a*=-1),a}function Pt(t,e){return Math.min(t,e)+function(t,e){return Math.abs(Math.max(t,e)-Math.min(t,e))}(t,e)/2}function Ct(t,e){return t.x}function St(t,e){return t.y}function bt(t,e){return e}function wt(t,e,i,s,r,a,o,n){let l,h,u,d,m=new c(0,0),p=new c(0,0),_=new c(0,0),f=new c(0,0);t[0].position=new c(i.x,i.y),l=g.degreesToRadian(s),d=g.radianToDirection(l),d.normalize();for(let y=1;yi&&(o>r.valueExceededMaximum&&(r.valueExceededMaximum=o),o=i),n=r.weight/100,n>=1||(o=t[0]*(1-n)+o*n),t[0]=o}function Lt(t,e,i,s,r,a,o,n){let l=0;const h=g.max(i,e);ht&&(t=u);const d=g.min(r,a),c=g.max(r,a),m=o,p=Pt(u,h),_=t-p;switch(Math.sign(_)){case 1:{const t=c-m,e=h-p;0!=e&&(l=_*(t/e),l+=m);break}case-1:{const t=d-m,e=u-p;0!=e&&(l=_*(t/e),l+=m);break}case 0:l=m}return n?l:-1*l}class Tt{constructor(t=0,e=0,i=0,s=0){this.x=t,this.y=e,this.width=i,this.height=s}getCenterX(){return this.x+.5*this.width}getCenterY(){return this.y+.5*this.height}getRight(){return this.x+this.width}getBottom(){return this.y+this.height}setRect(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height}expand(t,e){this.x-=t,this.y-=e,this.width+=2*t,this.height+=2*e}}let Et,Dt,Ft;class At{getChannelFlagAsColor(t){return this._channelColors[t]}getMaskRenderTexture(){let t=0;if(this._maskTexture&&0!=this._maskTexture.texture&&(this._maskTexture.frameNo=this._currentFrameNo,t=this._maskTexture.texture),0==t){const e=this._clippingMaskBufferSize;this._colorBuffer=this.gl.createTexture(),this.gl.bindTexture(this.gl.TEXTURE_2D,this._colorBuffer),this.gl.texImage2D(this.gl.TEXTURE_2D,0,this.gl.RGBA,e,e,0,this.gl.RGBA,this.gl.UNSIGNED_BYTE,null),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,this.gl.CLAMP_TO_EDGE),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MIN_FILTER,this.gl.LINEAR),this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_MAG_FILTER,this.gl.LINEAR),this.gl.bindTexture(this.gl.TEXTURE_2D,null),t=this.gl.createFramebuffer(),this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,t),this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER,this.gl.COLOR_ATTACHMENT0,this.gl.TEXTURE_2D,this._colorBuffer,0),this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,Ft),this._maskTexture=new Bt(this._currentFrameNo,t)}return t}setGL(t){this.gl=t}calcClippedDrawTotalBounds(t,e){let i=Number.MAX_VALUE,s=Number.MAX_VALUE,r=Number.MIN_VALUE,a=Number.MIN_VALUE;const o=e._clippedDrawableIndexList.length;for(let n=0;nc&&(c=e),im&&(m=i)}if(u!=Number.MAX_VALUE)if(ur&&(r=c),m>a&&(a=m),i==Number.MAX_VALUE)e._allClippedDrawRect.x=0,e._allClippedDrawRect.y=0,e._allClippedDrawRect.width=0,e._allClippedDrawRect.height=0,e._isUsing=!1;else{e._isUsing=!0;const t=r-i,o=a-s;e._allClippedDrawRect.x=i,e._allClippedDrawRect.y=s,e._allClippedDrawRect.width=t,e._allClippedDrawRect.height=o}}}constructor(){this._maskRenderTexture=null,this._colorBuffer=null,this._currentFrameNo=0,this._clippingMaskBufferSize=256,this._clippingContextListForMask=[],this._clippingContextListForDraw=[],this._channelColors=[],this._tmpBoundsOnModel=new Tt,this._tmpMatrix=new p,this._tmpMatrixForMask=new p,this._tmpMatrixForDraw=new p;let t=new y;t.R=1,t.G=0,t.B=0,t.A=0,this._channelColors.push(t),t=new y,t.R=0,t.G=1,t.B=0,t.A=0,this._channelColors.push(t),t=new y,t.R=0,t.G=0,t.B=1,t.A=0,this._channelColors.push(t),t=new y,t.R=0,t.G=0,t.B=0,t.A=1,this._channelColors.push(t)}release(){var t,e,i;const s=this;for(let r=0;r0){this.gl.viewport(0,0,this._clippingMaskBufferSize,this._clippingMaskBufferSize),this._maskRenderTexture=this.getMaskRenderTexture(),e.getMvpMatrix(),e.preDraw(),this.setupLayoutBounds(i),this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,this._maskRenderTexture),this.gl.clearColor(1,1,1,1),this.gl.clear(this.gl.COLOR_BUFFER_BIT);for(let i=0;i(t[t.ShaderNames_SetupMask=0]="ShaderNames_SetupMask",t[t.ShaderNames_NormalPremultipliedAlpha=1]="ShaderNames_NormalPremultipliedAlpha",t[t.ShaderNames_NormalMaskedPremultipliedAlpha=2]="ShaderNames_NormalMaskedPremultipliedAlpha",t[t.ShaderNames_NomralMaskedInvertedPremultipliedAlpha=3]="ShaderNames_NomralMaskedInvertedPremultipliedAlpha",t[t.ShaderNames_AddPremultipliedAlpha=4]="ShaderNames_AddPremultipliedAlpha",t[t.ShaderNames_AddMaskedPremultipliedAlpha=5]="ShaderNames_AddMaskedPremultipliedAlpha",t[t.ShaderNames_AddMaskedPremultipliedAlphaInverted=6]="ShaderNames_AddMaskedPremultipliedAlphaInverted",t[t.ShaderNames_MultPremultipliedAlpha=7]="ShaderNames_MultPremultipliedAlpha",t[t.ShaderNames_MultMaskedPremultipliedAlpha=8]="ShaderNames_MultMaskedPremultipliedAlpha",t[t.ShaderNames_MultMaskedPremultipliedAlphaInverted=9]="ShaderNames_MultMaskedPremultipliedAlphaInverted",t))(kt||{});const Ut="attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;varying vec4 v_myPos;uniform mat4 u_clipMatrix;void main(){ gl_Position = u_clipMatrix * a_position; v_myPos = u_clipMatrix * a_position; v_texCoord = a_texCoord; v_texCoord.y = 1.0 - v_texCoord.y;}",Nt="precision mediump float;varying vec2 v_texCoord;varying vec4 v_myPos;uniform vec4 u_baseColor;uniform vec4 u_channelFlag;uniform sampler2D s_texture0;void main(){ float isInside = step(u_baseColor.x, v_myPos.x/v_myPos.w) * step(u_baseColor.y, v_myPos.y/v_myPos.w) * step(v_myPos.x/v_myPos.w, u_baseColor.z) * step(v_myPos.y/v_myPos.w, u_baseColor.w); gl_FragColor = u_channelFlag * texture2D(s_texture0, v_texCoord).a * isInside;}",Vt="attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;uniform mat4 u_matrix;void main(){ gl_Position = u_matrix * a_position; v_texCoord = a_texCoord; v_texCoord.y = 1.0 - v_texCoord.y;}",jt="attribute vec4 a_position;attribute vec2 a_texCoord;varying vec2 v_texCoord;varying vec4 v_clipPos;uniform mat4 u_matrix;uniform mat4 u_clipMatrix;void main(){ gl_Position = u_matrix * a_position; v_clipPos = u_clipMatrix * a_position; v_texCoord = a_texCoord; v_texCoord.y = 1.0 - v_texCoord.y;}",Gt="precision mediump float;varying vec2 v_texCoord;uniform vec4 u_baseColor;uniform sampler2D s_texture0;void main(){ gl_FragColor = texture2D(s_texture0 , v_texCoord) * u_baseColor;}",Xt="precision mediump float;varying vec2 v_texCoord;varying vec4 v_clipPos;uniform vec4 u_baseColor;uniform vec4 u_channelFlag;uniform sampler2D s_texture0;uniform sampler2D s_texture1;void main(){ vec4 col_formask = texture2D(s_texture0 , v_texCoord) * u_baseColor; vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag; float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a; col_formask = col_formask * maskVal; gl_FragColor = col_formask;}",zt="precision mediump float;varying vec2 v_texCoord;varying vec4 v_clipPos;uniform sampler2D s_texture0;uniform sampler2D s_texture1;uniform vec4 u_channelFlag;uniform vec4 u_baseColor;void main(){vec4 col_formask = texture2D(s_texture0, v_texCoord) * u_baseColor;vec4 clipMask = (1.0 - texture2D(s_texture1, v_clipPos.xy / v_clipPos.w)) * u_channelFlag;float maskVal = clipMask.r + clipMask.g + clipMask.b + clipMask.a;col_formask = col_formask * (1.0 - maskVal);gl_FragColor = col_formask;}";class Wt extends _{constructor(){super(),this._clippingContextBufferForMask=null,this._clippingContextBufferForDraw=null,this._clippingManager=new At,this.firstDraw=!0,this._textures={},this._sortedDrawableIndexList=[],this._bufferData={vertex:null,uv:null,index:null}}initialize(t){t.isUsingMasking()&&(this._clippingManager=new At,this._clippingManager.initialize(t,t.getDrawableCount(),t.getDrawableMasks(),t.getDrawableMaskCounts()));for(let e=t.getDrawableCount()-1;e>=0;e--)this._sortedDrawableIndexList[e]=0;super.initialize(t)}bindTexture(t,e){this._textures[t]=e}getBindedTextures(){return this._textures}setClippingMaskBufferSize(t){this._clippingManager.release(),this._clippingManager=new At,this._clippingManager.setClippingMaskBufferSize(t),this._clippingManager.initialize(this.getModel(),this.getModel().getDrawableCount(),this.getModel().getDrawableMasks(),this.getModel().getDrawableMaskCounts())}getClippingMaskBufferSize(){return this._clippingManager.getClippingMaskBufferSize()}release(){var t,e,i;const s=this;this._clippingManager.release(),s._clippingManager=void 0,null==(t=this.gl)||t.deleteBuffer(this._bufferData.vertex),this._bufferData.vertex=null,null==(e=this.gl)||e.deleteBuffer(this._bufferData.uv),this._bufferData.uv=null,null==(i=this.gl)||i.deleteBuffer(this._bufferData.index),this._bufferData.index=null,s._bufferData=void 0,s._textures=void 0}doDrawModel(){this.preDraw(),null!=this._clippingManager&&this._clippingManager.setupClippingContext(this.getModel(),this);const t=this.getModel().getDrawableCount(),e=this.getModel().getDrawableRenderOrders();for(let i=0;i{Wt.doStaticRelease()};class Ht{constructor(t){this.groups=t.Groups,this.hitAreas=t.HitAreas,this.layout=t.Layout,this.moc=t.FileReferences.Moc,this.expressions=t.FileReferences.Expressions,this.motions=t.FileReferences.Motions,this.textures=t.FileReferences.Textures,this.physics=t.FileReferences.Physics,this.pose=t.FileReferences.Pose}getEyeBlinkParameters(){var t,e;return null==(e=null==(t=this.groups)?void 0:t.find((t=>"EyeBlink"===t.Name)))?void 0:e.Ids}getLipSyncParameters(){var t,e;return null==(e=null==(t=this.groups)?void 0:t.find((t=>"LipSync"===t.Name)))?void 0:e.Ids}}const Yt="ParamAngleX",qt="ParamAngleY",$t="ParamAngleZ",Zt="ParamEyeBallX",Jt="ParamEyeBallY",Qt="ParamBodyAngleX",Kt="ParamBreath";var te;t.config=void 0,(te=t.config||(t.config={})).LOG_LEVEL_VERBOSE=0,te.LOG_LEVEL_WARNING=1,te.LOG_LEVEL_ERROR=2,te.LOG_LEVEL_NONE=999,te.logLevel=te.LOG_LEVEL_WARNING,te.sound=!0,te.motionSync=!0,te.motionFadingDuration=500,te.idleMotionFadingDuration=2e3,te.expressionFadingDuration=500,te.preserveExpressionOnMotion=!0,te.cubism4=t.CubismConfig;const ee={log(e,...i){t.config.logLevel<=t.config.LOG_LEVEL_VERBOSE&&console.log(`[${e}]`,...i)},warn(e,...i){t.config.logLevel<=t.config.LOG_LEVEL_WARNING&&console.warn(`[${e}]`,...i)},error(e,...i){t.config.logLevel<=t.config.LOG_LEVEL_ERROR&&console.error(`[${e}]`,...i)}};function ie(t,e,i){return ti?i:t}function se(t,e){e.forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((i=>{"constructor"!==i&&Object.defineProperty(t.prototype,i,Object.getOwnPropertyDescriptor(e.prototype,i))}))}))}function re(t){let e=t.lastIndexOf("/");return-1!=e&&(t=t.slice(0,e)),e=t.lastIndexOf("/"),-1!==e&&(t=t.slice(e+1)),t}function ae(t,e){const i=t.indexOf(e);-1!==i&&t.splice(i,1)}class oe extends e.EventEmitter{constructor(t,e){super(),this.expressions=[],this.reserveExpressionIndex=-1,this.destroyed=!1,this.settings=t,this.tag=`ExpressionManager(${t.name})`}init(){this.defaultExpression=this.createExpression({},void 0),this.currentExpression=this.defaultExpression,this.stopAllExpressions()}loadExpression(t){return __async(this,null,(function*(){if(!this.definitions[t])return void ee.warn(this.tag,`Undefined expression at [${t}]`);if(null===this.expressions[t])return void ee.warn(this.tag,`Cannot set expression at [${t}] because it's already failed in loading.`);if(this.expressions[t])return this.expressions[t];const e=yield this._loadExpression(t);return this.expressions[t]=e,e}))}_loadExpression(t){throw new Error("Not implemented.")}setRandomExpression(){return __async(this,null,(function*(){if(this.definitions.length){const t=[];for(let e=0;e-1&&tl&&(a*=l/n,o*=l/n),this.vx+=a,this.vy+=o;const h=Math.sqrt(__pow(this.vx,2)+__pow(this.vy,2)),u=.5*(Math.sqrt(__pow(l,2)+8*l*s)-l);h>u&&(this.vx*=u/h,this.vy*=u/h),this.x+=this.vx,this.y+=this.vy}}class le{constructor(t){this.json=t;let e=t.url;if("string"!=typeof e)throw new TypeError("The `url` field in settings JSON must be defined as a string.");this.url=e,this.name=re(this.url)}resolveURL(t){return e.url.resolve(this.url,t)}replaceFiles(t){this.moc=t(this.moc,"moc"),void 0!==this.pose&&(this.pose=t(this.pose,"pose")),void 0!==this.physics&&(this.physics=t(this.physics,"physics"));for(let e=0;e(t.push(e),e))),t}validateFiles(t){const e=(e,i)=>{const s=this.resolveURL(e);if(!t.includes(s)){if(i)throw new Error(`File "${e}" is defined in settings, but doesn't exist in given files`);return!1}return!0};[this.moc,...this.textures].forEach((t=>e(t,!0)));return this.getDefinedFiles().filter((t=>e(t,!1)))}}var he=(t=>(t[t.NONE=0]="NONE",t[t.IDLE=1]="IDLE",t[t.NORMAL=2]="NORMAL",t[t.FORCE=3]="FORCE",t))(he||{});class ue{constructor(){this.debug=!1,this.currentPriority=0,this.reservePriority=0}reserve(t,e,i){if(i<=0)return ee.log(this.tag,"Cannot start a motion with MotionPriority.NONE."),!1;if(t===this.currentGroup&&e===this.currentIndex)return ee.log(this.tag,"Motion is already playing.",this.dump(t,e)),!1;if(t===this.reservedGroup&&e===this.reservedIndex||t===this.reservedIdleGroup&&e===this.reservedIdleIndex)return ee.log(this.tag,"Motion is already reserved.",this.dump(t,e)),!1;if(1===i){if(0!==this.currentPriority)return ee.log(this.tag,"Cannot start idle motion because another motion is playing.",this.dump(t,e)),!1;if(void 0!==this.reservedIdleGroup)return ee.log(this.tag,"Cannot start idle motion because another idle motion has reserved.",this.dump(t,e)),!1;this.setReservedIdle(t,e)}else{if(i<3){if(i<=this.currentPriority)return ee.log(this.tag,"Cannot start motion because another motion is playing as an equivalent or higher priority.",this.dump(t,e)),!1;if(i<=this.reservePriority)return ee.log(this.tag,"Cannot start motion because another motion has reserved as an equivalent or higher priority.",this.dump(t,e)),!1}this.setReserved(t,e,i)}return!0}start(t,e,i,s){if(1===s){if(this.setReservedIdle(void 0,void 0),0!==this.currentPriority)return ee.log(this.tag,"Cannot start idle motion because another motion is playing.",this.dump(e,i)),!1}else{if(e!==this.reservedGroup||i!==this.reservedIndex)return ee.log(this.tag,"Cannot start motion because another motion has taken the place.",this.dump(e,i)),!1;this.setReserved(void 0,void 0,0)}return!!t&&(this.setCurrent(e,i,s),!0)}complete(){this.setCurrent(void 0,void 0,0)}setCurrent(t,e,i){this.currentPriority=i,this.currentGroup=t,this.currentIndex=e}setReserved(t,e,i){this.reservePriority=i,this.reservedGroup=t,this.reservedIndex=e}setReservedIdle(t,e){this.reservedIdleGroup=t,this.reservedIdleIndex=e}isActive(t,e){return t===this.currentGroup&&e===this.currentIndex||t===this.reservedGroup&&e===this.reservedIndex||t===this.reservedIdleGroup&&e===this.reservedIdleIndex}reset(){this.setCurrent(void 0,void 0,0),this.setReserved(void 0,void 0,0),this.setReservedIdle(void 0,void 0)}shouldRequestIdleMotion(){return void 0===this.currentGroup&&void 0===this.reservedIdleGroup}shouldOverrideExpression(){return!t.config.preserveExpressionOnMotion&&this.currentPriority>1}dump(t,e){if(this.debug){return`\n group = "${t}", index = ${e}\n`+["currentPriority","reservePriority","currentGroup","currentIndex","reservedGroup","reservedIndex","reservedIdleGroup","reservedIdleIndex"].map((t=>"["+t+"] "+this[t])).join("\n")}return""}}class de{static get volume(){return this._volume}static set volume(t){this._volume=(t>1?1:t<0?0:t)||0,this.audios.forEach((t=>t.volume=this._volume))}static add(t,e,i){const s=new Audio(t);return s.volume=this._volume,s.preload="auto",s.addEventListener("ended",(()=>{this.dispose(s),null==e||e()})),s.addEventListener("error",(e=>{this.dispose(s),ee.warn("SoundManager",`Error occurred on "${t}"`,e.error),null==i||i(e.error)})),this.audios.push(s),s}static play(t){return new Promise(((e,i)=>{var s;null==(s=t.play())||s.catch((e=>{t.dispatchEvent(new ErrorEvent("error",{error:e})),i(e)})),t.readyState===t.HAVE_ENOUGH_DATA?e():t.addEventListener("canplaythrough",e)}))}static dispose(t){t.pause(),t.removeAttribute("src"),ae(this.audios,t)}static destroy(){for(let t=this.audios.length-1;t>=0;t--)this.dispose(this.audios[t])}}de.audios=[],de._volume=.5;var ce=(t=>(t.ALL="ALL",t.IDLE="IDLE",t.NONE="NONE",t))(ce||{});class me extends e.EventEmitter{constructor(t,e){super(),this.motionGroups={},this.state=new ue,this.playing=!1,this.destroyed=!1,this.settings=t,this.tag=`MotionManager(${t.name})`,this.state.tag=this.tag}init(t){(null==t?void 0:t.idleMotionGroup)&&(this.groups.idle=t.idleMotionGroup),this.setupMotions(t),this.stopAllMotions()}setupMotions(t){for(const i of Object.keys(this.definitions))this.motionGroups[i]=[];let e;switch(null==t?void 0:t.motionPreload){case"NONE":return;case"ALL":e=Object.keys(this.definitions);break;default:e=[this.groups.idle]}for(const i of e)if(this.definitions[i])for(let t=0;tthis.currentAudio=void 0),(()=>this.currentAudio=void 0)),this.currentAudio=o}catch(l){ee.warn(this.tag,"Failed to create audio",t,l)}}const n=yield this.loadMotion(e,i);if(o){const e=de.play(o).catch((t=>ee.warn(this.tag,"Failed to play audio",o.src,t)));t.config.motionSync&&(yield e)}return this.state.start(n,e,i,s)?(ee.log(this.tag,"Start motion:",this.getMotionName(a)),this.emit("motionStart",e,i,o),this.state.shouldOverrideExpression()&&this.expressionManager&&this.expressionManager.resetExpression(),this.playing=!0,this._startMotion(n),!0):(o&&(de.dispose(o),this.currentAudio=void 0),!1)}))}startRandomMotion(t,e){return __async(this,null,(function*(){const i=this.definitions[t];if(null==i?void 0:i.length){const s=[];for(let e=0;et.index>=0));for(const e of t)this.hitAreas[e.name]=e}hitTest(t,e){return Object.keys(this.hitAreas).filter((i=>this.isHit(i,t,e)))}isHit(t,e,i){if(!this.hitAreas[t])return!1;const s=this.hitAreas[t].index,r=this.getDrawableBounds(s,ge);return r.x<=e&&e<=r.x+r.width&&r.y<=i&&i<=r.y+r.height}getDrawableBounds(t,e){const i=this.getDrawableVertices(t);let s=i[0],r=i[0],a=i[1],o=i[1];for(let n=0;n{200!==a.status&&0!==a.status||!a.response?a.onerror():s(a.response)},a.onerror=()=>{ee.warn("XHRLoader",`Failed to load resource as ${a.responseType} (Status ${a.status}): ${e}`),r(new _e("Network error.",e,a.status))},a.onabort=()=>r(new _e("Aborted.",e,a.status,!0)),a.onloadend=()=>{var e;fe.allXhrSet.delete(a),t&&(null==(e=fe.xhrMap.get(t))||e.delete(a))},a}static cancelXHRs(){var t;null==(t=fe.xhrMap.get(this))||t.forEach((t=>{t.abort(),fe.allXhrSet.delete(t)})),fe.xhrMap.delete(this)}static release(){fe.allXhrSet.forEach((t=>t.abort())),fe.allXhrSet.clear(),fe.xhrMap=new WeakMap}};let ye=fe;function xe(t,e){let i=-1;return function s(r,a){if(a)return Promise.reject(a);if(r<=i)return Promise.reject(new Error("next() called multiple times"));i=r;const o=t[r];if(!o)return Promise.resolve();try{return Promise.resolve(o(e,s.bind(null,r+1)))}catch(n){return Promise.reject(n)}}(0)}ye.xhrMap=new WeakMap,ye.allXhrSet=new Set,ye.loader=(t,e)=>new Promise(((e,i)=>{fe.createXHR(t.target,t.settings?t.settings.resolveURL(t.url):t.url,t.type,(i=>{t.result=i,e()}),i).send()}));class ve{static load(t){return xe(this.middlewares,t).then((()=>t.result))}}ve.middlewares=[ye.loader];const Me="Live2DFactory",Pe=(t,e)=>__async(this,null,(function*(){if("string"==typeof t.source){const e=yield ve.load({url:t.source,type:"json",target:t.live2dModel});e.url=t.source,t.source=e,t.live2dModel.emit("settingsJSONLoaded",e)}return e()})),Ce=(t,e)=>__async(this,null,(function*(){if(t.source instanceof le)return t.settings=t.source,e();if("object"==typeof t.source){const i=Te.findRuntime(t.source);if(i){const s=i.createModelSettings(t.source);return t.settings=s,t.live2dModel.emit("settingsLoaded",s),e()}}throw new TypeError("Unknown settings format.")})),Se=(t,e)=>{if(t.settings){const i=Te.findRuntime(t.settings);if(i)return i.ready().then(e)}return e()},be=(t,e)=>__async(this,null,(function*(){yield e();const i=t.internalModel;if(i){const e=t.settings,s=Te.findRuntime(e);if(s){const r=[];e.pose&&r.push(ve.load({settings:e,url:e.pose,type:"json",target:i}).then((e=>{i.pose=s.createPose(i.coreModel,e),t.live2dModel.emit("poseLoaded",i.pose)})).catch((e=>{t.live2dModel.emit("poseLoadError",e),ee.warn(Me,"Failed to load pose.",e)}))),e.physics&&r.push(ve.load({settings:e,url:e.physics,type:"json",target:i}).then((e=>{i.physics=s.createPhysics(i.coreModel,e),t.live2dModel.emit("physicsLoaded",i.physics)})).catch((e=>{t.live2dModel.emit("physicsLoadError",e),ee.warn(Me,"Failed to load physics.",e)}))),r.length&&(yield Promise.all(r))}}})),we=(t,e)=>__async(this,null,(function*(){if(!t.settings)throw new TypeError("Missing settings.");{const i=t.live2dModel,r=t.settings.textures.map((e=>function(t,e={}){const i={resourceOptions:{crossorigin:e.crossOrigin}};if(s.Texture.fromURL)return s.Texture.fromURL(t,i).catch((t=>{if(t instanceof Error)throw t;const e=new Error("Texture loading error");throw e.event=t,e}));i.resourceOptions.autoLoad=!1;const r=s.Texture.from(t,i);if(r.baseTexture.valid)return Promise.resolve(r);const a=r.baseTexture.resource;return null!=a._live2d_load||(a._live2d_load=new Promise(((t,e)=>{const i=t=>{a.source.removeEventListener("error",i);const s=new Error("Texture loading error");s.event=t,e(s)};a.source.addEventListener("error",i),a.load().then((()=>t(r))).catch(i)}))),a._live2d_load}(t.settings.resolveURL(e),{crossOrigin:t.options.crossOrigin})));if(yield e(),!t.internalModel)throw new TypeError("Missing internal model.");i.internalModel=t.internalModel,i.emit("modelLoaded",t.internalModel),i.textures=yield Promise.all(r),i.emit("textureLoaded",i.textures)}})),Ie=(t,e)=>__async(this,null,(function*(){const i=t.settings;if(i instanceof le){const s=Te.findRuntime(i);if(!s)throw new TypeError("Unknown model settings.");const r=yield ve.load({settings:i,url:i.moc,type:"arraybuffer",target:t.live2dModel});if(!s.isValidMoc(r))throw new Error("Invalid moc data");const a=s.createCoreModel(r);return t.internalModel=s.createInternalModel(a,i,t.options),e()}throw new TypeError("Missing settings.")})),Le=class{static registerRuntime(t){Le.runtimes.push(t),Le.runtimes.sort(((t,e)=>e.version-t.version))}static findRuntime(t){for(const e of Le.runtimes)if(e.test(t))return e}static setupLive2DModel(t,e,i){return __async(this,null,(function*(){const s=new Promise((e=>t.once("textureLoaded",e))),r=new Promise((e=>t.once("modelLoaded",e))),a=Promise.all([s,r]).then((()=>t.emit("ready")));yield xe(Le.live2DModelMiddlewares,{live2dModel:t,source:e,options:i||{}}),yield a,t.emit("load")}))}static loadMotion(t,e,i){var s;const r=s=>t.emit("motionLoadError",e,i,s);try{const a=null==(s=t.definitions[e])?void 0:s[i];if(!a)return Promise.resolve(void 0);t.listeners("destroy").includes(Le.releaseTasks)||t.once("destroy",Le.releaseTasks);let o=Le.motionTasksMap.get(t);o||(o={},Le.motionTasksMap.set(t,o));let n=o[e];n||(n=[],o[e]=n);const l=t.getMotionFile(a);return null!=n[i]||(n[i]=ve.load({url:l,settings:t.settings,type:t.motionDataType,target:t}).then((s=>{var r;const o=null==(r=Le.motionTasksMap.get(t))?void 0:r[e];o&&delete o[i];const n=t.createMotion(s,e,a);return t.emit("motionLoaded",e,i,n),n})).catch((e=>{ee.warn(t.tag,`Failed to load motion: ${l}\n`,e),r(e)}))),n[i]}catch(a){ee.warn(t.tag,`Failed to load motion at "${e}"[${i}]\n`,a),r(a)}return Promise.resolve(void 0)}static loadExpression(t,e){const i=i=>t.emit("expressionLoadError",e,i);try{const s=t.definitions[e];if(!s)return Promise.resolve(void 0);t.listeners("destroy").includes(Le.releaseTasks)||t.once("destroy",Le.releaseTasks);let r=Le.expressionTasksMap.get(t);r||(r=[],Le.expressionTasksMap.set(t,r));const a=t.getExpressionFile(s);return null!=r[e]||(r[e]=ve.load({url:a,settings:t.settings,type:"json",target:t}).then((i=>{const r=Le.expressionTasksMap.get(t);r&&delete r[e];const a=t.createExpression(i,s);return t.emit("expressionLoaded",e,a),a})).catch((e=>{ee.warn(t.tag,`Failed to load expression: ${a}\n`,e),i(e)}))),r[e]}catch(s){ee.warn(t.tag,`Failed to load expression at [${e}]\n`,s),i(s)}return Promise.resolve(void 0)}static releaseTasks(){this instanceof me?Le.motionTasksMap.delete(this):Le.expressionTasksMap.delete(this)}};let Te=Le;Te.runtimes=[],Te.urlToJSON=Pe,Te.jsonToSettings=Ce,Te.waitUntilReady=Se,Te.setupOptionals=be,Te.setupEssentials=we,Te.createInternalModel=Ie,Te.live2DModelMiddlewares=[Pe,Ce,Se,be,we,Ie],Te.motionTasksMap=new WeakMap,Te.expressionTasksMap=new WeakMap,me.prototype._loadMotion=function(t,e){return Te.loadMotion(this,t,e)},oe.prototype._loadExpression=function(t){return Te.loadExpression(this,t)};class Ee{constructor(){this._autoInteract=!1}get autoInteract(){return this._autoInteract}set autoInteract(t){t!==this._autoInteract&&(t?this.on("pointertap",De,this):this.off("pointertap",De,this),this._autoInteract=t)}registerInteraction(t){t!==this.interactionManager&&(this.unregisterInteraction(),this._autoInteract&&t&&(this.interactionManager=t,t.on("pointermove",Fe,this)))}unregisterInteraction(){var t;this.interactionManager&&(null==(t=this.interactionManager)||t.off("pointermove",Fe,this),this.interactionManager=void 0)}}function De(t){this.tap(t.data.global.x,t.data.global.y)}function Fe(t){this.focus(t.data.global.x,t.data.global.y)}class Ae extends i.Transform{}const Be=new i.Point,Re=new i.Matrix;let Oe;class ke extends r.Container{constructor(t){super(),this.tag="Live2DModel(uninitialized)",this.textures=[],this.transform=new Ae,this.anchor=new i.ObservablePoint(this.onAnchorChange,this,0,0),this.glContextID=-1,this.elapsedTime=performance.now(),this.deltaTime=0,this._autoUpdate=!1,this.once("modelLoaded",(()=>this.init(t)))}static from(t,e){const i=new this(e);return Te.setupLive2DModel(i,t,e).then((()=>i))}static fromSync(t,e){const i=new this(e);return Te.setupLive2DModel(i,t,e).then(null==e?void 0:e.onLoad).catch(null==e?void 0:e.onError),i}static registerTicker(t){Oe=t}get autoUpdate(){return this._autoUpdate}set autoUpdate(t){var e;Oe||(Oe=null==(e=window.PIXI)?void 0:e.Ticker),t?this._destroyed||(Oe?(Oe.shared.add(this.onTickerUpdate,this),this._autoUpdate=!0):ee.warn(this.tag,"No Ticker registered, please call Live2DModel.registerTicker(Ticker).")):(null==Oe||Oe.shared.remove(this.onTickerUpdate,this),this._autoUpdate=!1)}init(t){this.tag=`Live2DModel(${this.internalModel.settings.name})`;const e=Object.assign({autoUpdate:!0,autoInteract:!0},t);e.autoInteract&&(this.interactive=!0),this.autoInteract=e.autoInteract,this.autoUpdate=e.autoUpdate}onAnchorChange(){this.pivot.set(this.anchor.x*this.internalModel.width,this.anchor.y*this.internalModel.height)}motion(t,e,i){return void 0===e?this.internalModel.motionManager.startRandomMotion(t,i):this.internalModel.motionManager.startMotion(t,e,i)}expression(t){return this.internalModel.motionManager.expressionManager?void 0===t?this.internalModel.motionManager.expressionManager.setRandomExpression():this.internalModel.motionManager.expressionManager.setExpression(t):Promise.resolve(!1)}focus(t,e,i=!1){Be.x=t,Be.y=e,this.toModelPosition(Be,Be,!0);let s=Be.x/this.internalModel.originalWidth*2-1,r=Be.y/this.internalModel.originalHeight*2-1,a=Math.atan2(r,s);this.internalModel.focusController.focus(Math.cos(a),-Math.sin(a),i)}tap(t,e){const i=this.hitTest(t,e);i.length&&(ee.log(this.tag,"Hit",i),this.emit("hit",i))}hitTest(t,e){return Be.x=t,Be.y=e,this.toModelPosition(Be,Be),this.internalModel.hitTest(Be.x,Be.y)}toModelPosition(t,e=t.clone(),i){return i||(this._recursivePostUpdateTransform(),this.parent?this.displayObjectUpdateTransform():(this.parent=this._tempDisplayObjectParent,this.displayObjectUpdateTransform(),this.parent=null)),this.transform.worldTransform.applyInverse(t,e),this.internalModel.localTransform.applyInverse(e,e),e}containsPoint(t){return this.getBounds(!0).contains(t.x,t.y)}_calculateBounds(){this._bounds.addFrame(this.transform,0,0,this.internalModel.width,this.internalModel.height)}onTickerUpdate(){this.update(Oe.shared.deltaMS)}update(t){this.deltaTime+=t,this.elapsedTime+=t}_render(t){this.registerInteraction(t.plugins.interaction),t.batch.reset(),t.geometry.reset(),t.shader.reset(),t.state.reset();let e=!1;this.glContextID!==t.CONTEXT_UID&&(this.glContextID=t.CONTEXT_UID,this.internalModel.updateWebGLContext(t.gl,this.glContextID),e=!0);for(let r=0;re.destroy(t.baseTexture))),this.internalModel.destroy(),super.destroy(t)}}se(ke,[Ee]);const Ue=class{static resolveURL(t,e){var i;const s=null==(i=Ue.filesMap[t])?void 0:i[e];if(void 0===s)throw new Error("Cannot find this file from uploaded files: "+e);return s}static upload(t,i){return __async(this,null,(function*(){const s={};for(const r of i.getDefinedFiles()){const a=decodeURI(e.url.resolve(i.url,r)),o=t.find((t=>t.webkitRelativePath===a));o&&(s[r]=URL.createObjectURL(o))}Ue.filesMap[i._objectURL]=s}))}static createSettings(t){return __async(this,null,(function*(){const e=t.find((t=>t.name.endsWith("model.json")||t.name.endsWith("model3.json")));if(!e)throw new TypeError("Settings file not found");const i=yield Ue.readText(e),s=JSON.parse(i);s.url=e.webkitRelativePath;const r=Te.findRuntime(s);if(!r)throw new Error("Unknown settings JSON");const a=r.createModelSettings(s);return a._objectURL=URL.createObjectURL(e),a}))}static readText(t){return __async(this,null,(function*(){return new Promise(((e,i)=>{const s=new FileReader;s.onload=()=>e(s.result),s.onerror=i,s.readAsText(t,"utf8")}))}))}};let Ne=Ue;Ne.filesMap={},Ne.factory=(t,e)=>__async(this,null,(function*(){if(Array.isArray(t.source)&&t.source[0]instanceof File){const e=t.source;let i=e.settings;if(i){if(!i._objectURL)throw new Error('"_objectURL" must be specified in ModelSettings')}else i=yield Ue.createSettings(e);i.validateFiles(e.map((t=>encodeURI(t.webkitRelativePath)))),yield Ue.upload(e,i),i.resolveURL=function(t){return Ue.resolveURL(this._objectURL,t)},t.source=i,t.live2dModel.once("modelLoaded",(t=>{t.once("destroy",(function(){const t=this.settings._objectURL;if(URL.revokeObjectURL(t),Ue.filesMap[t])for(const e of Object.values(Ue.filesMap[t]))URL.revokeObjectURL(e);delete Ue.filesMap[t]}))}))}return e()})),Te.live2DModelMiddlewares.unshift(Ne.factory);const Ve=class{static unzip(t,i){return __async(this,null,(function*(){const s=yield Ve.getFilePaths(t),r=[];for(const t of i.getDefinedFiles()){const a=decodeURI(e.url.resolve(i.url,t));s.includes(a)&&r.push(a)}const a=yield Ve.getFiles(t,r);for(let t=0;tt.endsWith("model.json")||t.endsWith("model3.json")));if(!e)throw new Error("Settings file not found");const i=yield Ve.readText(t,e);if(!i)throw new Error("Empty settings file: "+e);const s=JSON.parse(i);s.url=e;const r=Te.findRuntime(s);if(!r)throw new Error("Unknown settings JSON");return r.createModelSettings(s)}))}static zipReader(t,e){return __async(this,null,(function*(){throw new Error("Not implemented")}))}static getFilePaths(t){return __async(this,null,(function*(){throw new Error("Not implemented")}))}static getFiles(t,e){return __async(this,null,(function*(){throw new Error("Not implemented")}))}static readText(t,e){return __async(this,null,(function*(){throw new Error("Not implemented")}))}static releaseReader(t){}};let je=Ve;if(je.ZIP_PROTOCOL="zip://",je.uid=0,je.factory=(t,e)=>__async(this,null,(function*(){const i=t.source;let s,r,a;if("string"==typeof i&&(i.endsWith(".zip")||i.startsWith(Ve.ZIP_PROTOCOL))?(s=i.startsWith(Ve.ZIP_PROTOCOL)?i.slice(Ve.ZIP_PROTOCOL.length):i,r=yield ve.load({url:s,type:"blob",target:t.live2dModel})):Array.isArray(i)&&1===i.length&&i[0]instanceof File&&i[0].name.endsWith(".zip")&&(r=i[0],s=URL.createObjectURL(r),a=i.settings),r){if(!r.size)throw new Error("Empty zip file");const e=yield Ve.zipReader(r,s);a||(a=yield Ve.createSettings(e)),a._objectURL=Ve.ZIP_PROTOCOL+Ve.uid+"/"+a.url;const i=yield Ve.unzip(e,a);i.settings=a,t.source=i,s.startsWith("blob:")&&t.live2dModel.once("modelLoaded",(t=>{t.once("destroy",(function(){URL.revokeObjectURL(s)}))})),Ve.releaseReader(e)}return e()})),Te.live2DModelMiddlewares.unshift(je.factory),!window.Live2DCubismCore)throw new Error("Could not find Cubism 4 runtime. This plugin requires live2dcubismcore.js to be loaded.");class Ge extends oe{constructor(t,e){var i;super(t,e),this.queueManager=new st,this.definitions=null!=(i=t.expressions)?i:[],this.init()}isFinished(){return this.queueManager.isFinished()}getExpressionIndex(t){return this.definitions.findIndex((e=>e.Name===t))}getExpressionFile(t){return t.File}createExpression(t,e){return O.create(t)}_setExpression(t){return this.queueManager.startMotion(t,!1,performance.now())}stopAllExpressions(){this.queueManager.stopAllMotions()}updateParameters(t,e){return this.queueManager.doUpdateMotion(t,e)}}class Xe extends le{constructor(t){if(super(t),!Xe.isValidJSON(t))throw new TypeError("Invalid JSON.");Object.assign(this,new Ht(t))}static isValidJSON(t){var e;return!!(null==t?void 0:t.FileReferences)&&"string"==typeof t.FileReferences.Moc&&(null==(e=t.FileReferences.Textures)?void 0:e.length)>0&&t.FileReferences.Textures.every((t=>"string"==typeof t))}replaceFiles(t){if(super.replaceFiles(t),this.motions)for(const[e,i]of Object.entries(this.motions))for(let s=0;s{this.emit("motion:"+e)}))}isFinished(){return this.queueManager.isFinished()}_startMotion(t,e){return t.setFinishedMotionHandler(e),this.queueManager.stopAllMotions(),this.queueManager.startMotion(t,!1,performance.now())}_stopAllMotions(){this.queueManager.stopAllMotions()}createMotion(e,i,s){const r=et.create(e),a=new H(e),o=(i===this.groups.idle?t.config.idleMotionFadingDuration:t.config.motionFadingDuration)/1e3;return void 0===a.getMotionFadeInTime()&&r.setFadeInTime(s.FadeInTime>0?s.FadeInTime:o),void 0===a.getMotionFadeOutTime()&&r.setFadeOutTime(s.FadeOutTime>0?s.FadeOutTime:o),r.setEffectIds(this.eyeBlinkIds,this.lipSyncIds),r}getMotionFile(t){return t.File}getMotionName(t){return t.File}getSoundFile(t){return t.Sound}updateParameters(t,e){return this.queueManager.doUpdateMotion(t,e)}destroy(){super.destroy(),this.queueManager.release(),this.queueManager=void 0}}const We=new p;class He extends pe{constructor(t,e,s){super(),this.lipSync=!0,this.breath=a.create(),this.renderer=new Wt,this.idParamAngleX=Yt,this.idParamAngleY=qt,this.idParamAngleZ=$t,this.idParamEyeBallX=Zt,this.idParamEyeBallY=Jt,this.idParamBodyAngleX=Qt,this.idParamBreath=Kt,this.pixelsPerUnit=1,this.centeringTransform=new i.Matrix,this.coreModel=t,this.settings=e,this.motionManager=new ze(e,s),this.init()}init(){var t;super.init(),(null==(t=this.settings.getEyeBlinkParameters())?void 0:t.length)>0&&(this.eyeBlink=l.create(this.settings)),this.breath.setParameters([new o(this.idParamAngleX,0,15,6.5345,.5),new o(this.idParamAngleY,0,8,3.5345,.5),new o(this.idParamAngleZ,0,10,5.5345,.5),new o(this.idParamBodyAngleX,0,4,15.5345,.5),new o(this.idParamBreath,0,.5,3.2345,.5)]),this.renderer.initialize(this.coreModel),this.renderer.setIsPremultipliedAlpha(!0)}getSize(){return[this.coreModel.getModel().canvasinfo.CanvasWidth,this.coreModel.getModel().canvasinfo.CanvasHeight]}getLayout(){const t={};if(this.settings.layout)for(const e of Object.keys(this.settings.layout)){t[e.charAt(0).toLowerCase()+e.slice(1)]=this.settings.layout[e]}return t}setupLayout(){super.setupLayout(),this.pixelsPerUnit=this.coreModel.getModel().canvasinfo.PixelsPerUnit,this.centeringTransform.scale(this.pixelsPerUnit,this.pixelsPerUnit).translate(this.originalWidth/2,this.originalHeight/2)}updateWebGLContext(t,e){this.renderer.firstDraw=!0,this.renderer._bufferData={vertex:null,uv:null,index:null},this.renderer.startUp(t),this.renderer._clippingManager._currentFrameNo=e,this.renderer._clippingManager._maskTexture=void 0,Ot.getInstance()._shaderSets=[]}bindTexture(t,e){this.renderer.bindTexture(t,e)}getHitAreaDefs(){var t,e;return null!=(e=null==(t=this.settings.hitAreas)?void 0:t.map((t=>({id:t.Id,name:t.Name,index:this.coreModel.getDrawableIndex(t.Id)}))))?e:[]}getDrawableIDs(){return this.coreModel.getDrawableIds()}getDrawableIndex(t){return this.coreModel.getDrawableIndex(t)}getDrawableVertices(t){if("string"==typeof t&&-1===(t=this.coreModel.getDrawableIndex(t)))throw new TypeError("Unable to find drawable ID: "+t);const e=this.coreModel.getDrawableVertices(t).slice();for(let i=0;i{!function i(){try{Ze(),t()}catch(s){if(qe--,qe<0){const t=new Error("Failed to start up Cubism 4 framework.");return t.cause=s,void e(t)}ee.log("Cubism4","Startup failed, retrying 10ms later..."),setTimeout(i,10)}}()}))),Ye)}function Ze(t){t=Object.assign({logFunction:console.log,loggingLevel:S.LogLevel_Verbose},t),C.startUp(t),C.initialize()}function Je(){var t;null==(t=this.__moc)||t.release()}Te.registerRuntime({version:4,ready:$e,test:t=>t instanceof Xe||Xe.isValidJSON(t),isValidMoc(t){if(t.byteLength<4)return!1;const e=new Int8Array(t,0,4);return"MOC3"===String.fromCharCode(...e)},createModelSettings:t=>new Xe(t),createCoreModel(t){const e=F.create(t);try{const t=e.createModel();return t.__moc=e,t}catch(i){try{e.release()}catch(s){}throw i}},createInternalModel(t,e,i){const s=new He(t,e,i),r=t;return r.__moc&&(s.__moc=r.__moc,delete r.__moc,s.once("destroy",Je)),s},createPhysics:(t,e)=>gt.create(e),createPose:(t,e)=>u.create(e)}),t.ACubismMotion=R,t.BreathParameterData=o,t.CSM_ASSERT=b,t.Constant=P,t.Cubism4ExpressionManager=Ge,t.Cubism4InternalModel=He,t.Cubism4ModelSettings=Xe,t.Cubism4MotionManager=ze,t.CubismBlendMode=f,t.CubismBreath=a,t.CubismClippingContext=Rt,t.CubismClippingManager_WebGL=At,t.CubismDebug=E,t.CubismExpressionMotion=O,t.CubismEyeBlink=l,t.CubismFramework=C,t.CubismLogDebug=w,t.CubismLogError=T,t.CubismLogInfo=I,t.CubismLogVerbose=function(t,...e){E.print(S.LogLevel_Verbose,"[CSM][V]"+t+"\n",e)},t.CubismLogWarning=L,t.CubismMath=g,t.CubismMatrix44=p,t.CubismMoc=F,t.CubismModel=D,t.CubismModelSettingsJson=Ht,t.CubismModelUserData=B,t.CubismModelUserDataJson=A,t.CubismMotion=et,t.CubismMotionCurve=X,t.CubismMotionCurveTarget=N,t.CubismMotionData=W,t.CubismMotionEvent=z,t.CubismMotionJson=H,t.CubismMotionManager=class extends st{constructor(){super(),this._currentPriority=0,this._reservePriority=0}getCurrentPriority(){return this._currentPriority}getReservePriority(){return this._reservePriority}setReservePriority(t){this._reservePriority=t}startMotionPriority(t,e,i){return i==this._reservePriority&&(this._reservePriority=0),this._currentPriority=i,super.startMotion(t,e,this._userTimeSeconds)}updateMotion(t,e){this._userTimeSeconds+=e;const i=super.doUpdateMotion(t,this._userTimeSeconds);return this.isFinished()&&(this._currentPriority=0),i}reserveMotion(t){return!(t<=this._reservePriority||t<=this._currentPriority)&&(this._reservePriority=t,!0)}},t.CubismMotionPoint=j,t.CubismMotionQueueEntry=it,t.CubismMotionQueueManager=st,t.CubismMotionSegment=G,t.CubismMotionSegmentType=V,t.CubismPhysics=gt,t.CubismPhysicsInput=ht,t.CubismPhysicsJson=ct,t.CubismPhysicsOutput=ut,t.CubismPhysicsParticle=nt,t.CubismPhysicsRig=dt,t.CubismPhysicsSource=ot,t.CubismPhysicsSubRig=lt,t.CubismPhysicsTargetType=at,t.CubismPose=u,t.CubismRenderTextureResource=Bt,t.CubismRenderer=_,t.CubismRenderer_WebGL=Wt,t.CubismShader_WebGL=Ot,t.CubismTextureColor=y,t.CubismVector2=c,t.EvaluationOptionFlag=Y,t.ExpressionBlendType=U,t.ExpressionManager=oe,t.EyeState=h,t.FileLoader=Ne,t.FocusController=ne,t.HitAreaBody="Body",t.HitAreaHead="Head",t.HitAreaPrefix="HitArea",t.InteractionMixin=Ee,t.InternalModel=pe,t.InvalidMotionQueueEntryHandleValue=rt,t.LOGICAL_HEIGHT=2,t.LOGICAL_WIDTH=2,t.Live2DFactory=Te,t.Live2DLoader=ve,t.Live2DModel=ke,t.Live2DTransform=Ae,t.LogLevel=S,t.ModelSettings=le,t.MotionManager=me,t.MotionPreloadStrategy=ce,t.MotionPriority=he,t.MotionState=ue,t.Options=pt,t.ParamAngleX=Yt,t.ParamAngleY=qt,t.ParamAngleZ=$t,t.ParamArmLA="ParamArmLA",t.ParamArmLB="ParamArmLB",t.ParamArmRA="ParamArmRA",t.ParamArmRB="ParamArmRB",t.ParamBaseX="ParamBaseX",t.ParamBaseY="ParamBaseY",t.ParamBodyAngleX=Qt,t.ParamBodyAngleY="ParamBodyAngleY",t.ParamBodyAngleZ="ParamBodyAngleZ",t.ParamBreath=Kt,t.ParamBrowLAngle="ParamBrowLAngle",t.ParamBrowLForm="ParamBrowLForm",t.ParamBrowLX="ParamBrowLX",t.ParamBrowLY="ParamBrowLY",t.ParamBrowRAngle="ParamBrowRAngle",t.ParamBrowRForm="ParamBrowRForm",t.ParamBrowRX="ParamBrowRX",t.ParamBrowRY="ParamBrowRY",t.ParamBustX="ParamBustX",t.ParamBustY="ParamBustY",t.ParamCheek="ParamCheek",t.ParamEyeBallForm="ParamEyeBallForm",t.ParamEyeBallX=Zt,t.ParamEyeBallY=Jt,t.ParamEyeLOpen="ParamEyeLOpen",t.ParamEyeLSmile="ParamEyeLSmile",t.ParamEyeROpen="ParamEyeROpen",t.ParamEyeRSmile="ParamEyeRSmile",t.ParamHairBack="ParamHairBack",t.ParamHairFluffy="ParamHairFluffy",t.ParamHairFront="ParamHairFront",t.ParamHairSide="ParamHairSide",t.ParamHandL="ParamHandL",t.ParamHandR="ParamHandR",t.ParamMouthForm="ParamMouthForm",t.ParamMouthOpenY="ParamMouthOpenY",t.ParamNONE="NONE:",t.ParamShoulderY="ParamShoulderY",t.PartData=d,t.PartsArmLPrefix="Parts01ArmL_",t.PartsArmPrefix="Parts01Arm_",t.PartsArmRPrefix="Parts01ArmR_",t.PartsIdCore="Parts01Core",t.PhysicsJsonEffectiveForces=class{constructor(){this.gravity=new c(0,0),this.wind=new c(0,0)}},t.ShaderNames=kt,t.SoundManager=de,t.VERSION="0.4.0",t.XHRLoader=ye,t.ZipLoader=je,t.applyMixins=se,t.clamp=ie,t.copyArray=function(t,e,i,s,r){const a=e[s];Array.isArray(a)&&(i[r]=a.filter((e=>null!==e&&typeof e===t)))},t.copyProperty=function(t,e,i,s,r){const a=e[s];null!==a&&typeof a===t&&(i[r]=a)},t.csmRect=Tt,t.cubism4Ready=$e,t.folderName=re,t.fragmentShaderSrcMaskInvertedPremultipliedAlpha=zt,t.fragmentShaderSrcMaskPremultipliedAlpha=Xt,t.fragmentShaderSrcPremultipliedAlpha=Gt,t.fragmentShaderSrcsetupMask=Nt,t.logger=ee,t.rand=function(t,e){return Math.random()*(e-t)+t},t.remove=ae,t.startUpCubism4=Ze,t.vertexShaderSrc=Vt,t.vertexShaderSrcMasked=jt,t.vertexShaderSrcSetupMask=Ut,Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})); diff --git a/src/live2d/vendor/pixi.min.js b/src/live2d/vendor/pixi.min.js new file mode 100644 index 0000000..02f7b62 --- /dev/null +++ b/src/live2d/vendor/pixi.min.js @@ -0,0 +1,9 @@ +/*! + * pixi.js - v6.5.10 + * Compiled Thu, 06 Jul 2023 15:25:11 UTC + * + * pixi.js is licensed under the MIT License. + * http://www.opensource.org/licenses/mit-license + */ +var PIXI=function(t){"use strict";var e=setTimeout;function r(t){return Boolean(t&&void 0!==t.length)}function i(){}function n(t){if(!(this instanceof n))throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],l(t,this)}function o(t,e){for(;3===t._state;)t=t._value;0!==t._state?(t._handled=!0,n._immediateFn((function(){var r=1===t._state?e.onFulfilled:e.onRejected;if(null!==r){var i;try{i=r(t._value)}catch(t){return void a(e.promise,t)}s(e.promise,i)}else(1===t._state?s:a)(e.promise,t._value)}))):t._deferreds.push(e)}function s(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var r=e.then;if(e instanceof n)return t._state=3,t._value=e,void h(t);if("function"==typeof r)return void l((i=r,o=e,function(){i.apply(o,arguments)}),t)}t._state=1,t._value=e,h(t)}catch(e){a(t,e)}var i,o}function a(t,e){t._state=2,t._value=e,h(t)}function h(t){2===t._state&&0===t._deferreds.length&&n._immediateFn((function(){t._handled||n._unhandledRejectionFn(t._value)}));for(var e=0,r=t._deferreds.length;e0?1:-1}),Number.isInteger||(Number.isInteger=function(t){return"number"==typeof t&&isFinite(t)&&Math.floor(t)===t}),globalThis.ArrayBuffer||(globalThis.ArrayBuffer=Array),globalThis.Float32Array||(globalThis.Float32Array=Array),globalThis.Uint32Array||(globalThis.Uint32Array=Array),globalThis.Uint16Array||(globalThis.Uint16Array=Array),globalThis.Uint8Array||(globalThis.Uint8Array=Array),globalThis.Int32Array||(globalThis.Int32Array=Array),t.ENV=void 0,t.RENDERER_TYPE=void 0,t.BUFFER_BITS=void 0,t.BLEND_MODES=void 0,t.DRAW_MODES=void 0,t.FORMATS=void 0,t.TARGETS=void 0,t.TYPES=void 0,t.SAMPLER_TYPES=void 0,t.SCALE_MODES=void 0,t.WRAP_MODES=void 0,t.MIPMAP_MODES=void 0,t.ALPHA_MODES=void 0,t.CLEAR_MODES=void 0,t.GC_MODES=void 0,t.PRECISION=void 0,t.MASK_TYPES=void 0,t.COLOR_MASK_BITS=void 0,t.MSAA_QUALITY=void 0,t.BUFFER_TYPE=void 0,function(t){t[t.WEBGL_LEGACY=0]="WEBGL_LEGACY",t[t.WEBGL=1]="WEBGL",t[t.WEBGL2=2]="WEBGL2"}(t.ENV||(t.ENV={})),function(t){t[t.UNKNOWN=0]="UNKNOWN",t[t.WEBGL=1]="WEBGL",t[t.CANVAS=2]="CANVAS"}(t.RENDERER_TYPE||(t.RENDERER_TYPE={})),function(t){t[t.COLOR=16384]="COLOR",t[t.DEPTH=256]="DEPTH",t[t.STENCIL=1024]="STENCIL"}(t.BUFFER_BITS||(t.BUFFER_BITS={})),function(t){t[t.NORMAL=0]="NORMAL",t[t.ADD=1]="ADD",t[t.MULTIPLY=2]="MULTIPLY",t[t.SCREEN=3]="SCREEN",t[t.OVERLAY=4]="OVERLAY",t[t.DARKEN=5]="DARKEN",t[t.LIGHTEN=6]="LIGHTEN",t[t.COLOR_DODGE=7]="COLOR_DODGE",t[t.COLOR_BURN=8]="COLOR_BURN",t[t.HARD_LIGHT=9]="HARD_LIGHT",t[t.SOFT_LIGHT=10]="SOFT_LIGHT",t[t.DIFFERENCE=11]="DIFFERENCE",t[t.EXCLUSION=12]="EXCLUSION",t[t.HUE=13]="HUE",t[t.SATURATION=14]="SATURATION",t[t.COLOR=15]="COLOR",t[t.LUMINOSITY=16]="LUMINOSITY",t[t.NORMAL_NPM=17]="NORMAL_NPM",t[t.ADD_NPM=18]="ADD_NPM",t[t.SCREEN_NPM=19]="SCREEN_NPM",t[t.NONE=20]="NONE",t[t.SRC_OVER=0]="SRC_OVER",t[t.SRC_IN=21]="SRC_IN",t[t.SRC_OUT=22]="SRC_OUT",t[t.SRC_ATOP=23]="SRC_ATOP",t[t.DST_OVER=24]="DST_OVER",t[t.DST_IN=25]="DST_IN",t[t.DST_OUT=26]="DST_OUT",t[t.DST_ATOP=27]="DST_ATOP",t[t.ERASE=26]="ERASE",t[t.SUBTRACT=28]="SUBTRACT",t[t.XOR=29]="XOR"}(t.BLEND_MODES||(t.BLEND_MODES={})),function(t){t[t.POINTS=0]="POINTS",t[t.LINES=1]="LINES",t[t.LINE_LOOP=2]="LINE_LOOP",t[t.LINE_STRIP=3]="LINE_STRIP",t[t.TRIANGLES=4]="TRIANGLES",t[t.TRIANGLE_STRIP=5]="TRIANGLE_STRIP",t[t.TRIANGLE_FAN=6]="TRIANGLE_FAN"}(t.DRAW_MODES||(t.DRAW_MODES={})),function(t){t[t.RGBA=6408]="RGBA",t[t.RGB=6407]="RGB",t[t.RG=33319]="RG",t[t.RED=6403]="RED",t[t.RGBA_INTEGER=36249]="RGBA_INTEGER",t[t.RGB_INTEGER=36248]="RGB_INTEGER",t[t.RG_INTEGER=33320]="RG_INTEGER",t[t.RED_INTEGER=36244]="RED_INTEGER",t[t.ALPHA=6406]="ALPHA",t[t.LUMINANCE=6409]="LUMINANCE",t[t.LUMINANCE_ALPHA=6410]="LUMINANCE_ALPHA",t[t.DEPTH_COMPONENT=6402]="DEPTH_COMPONENT",t[t.DEPTH_STENCIL=34041]="DEPTH_STENCIL"}(t.FORMATS||(t.FORMATS={})),function(t){t[t.TEXTURE_2D=3553]="TEXTURE_2D",t[t.TEXTURE_CUBE_MAP=34067]="TEXTURE_CUBE_MAP",t[t.TEXTURE_2D_ARRAY=35866]="TEXTURE_2D_ARRAY",t[t.TEXTURE_CUBE_MAP_POSITIVE_X=34069]="TEXTURE_CUBE_MAP_POSITIVE_X",t[t.TEXTURE_CUBE_MAP_NEGATIVE_X=34070]="TEXTURE_CUBE_MAP_NEGATIVE_X",t[t.TEXTURE_CUBE_MAP_POSITIVE_Y=34071]="TEXTURE_CUBE_MAP_POSITIVE_Y",t[t.TEXTURE_CUBE_MAP_NEGATIVE_Y=34072]="TEXTURE_CUBE_MAP_NEGATIVE_Y",t[t.TEXTURE_CUBE_MAP_POSITIVE_Z=34073]="TEXTURE_CUBE_MAP_POSITIVE_Z",t[t.TEXTURE_CUBE_MAP_NEGATIVE_Z=34074]="TEXTURE_CUBE_MAP_NEGATIVE_Z"}(t.TARGETS||(t.TARGETS={})),function(t){t[t.UNSIGNED_BYTE=5121]="UNSIGNED_BYTE",t[t.UNSIGNED_SHORT=5123]="UNSIGNED_SHORT",t[t.UNSIGNED_SHORT_5_6_5=33635]="UNSIGNED_SHORT_5_6_5",t[t.UNSIGNED_SHORT_4_4_4_4=32819]="UNSIGNED_SHORT_4_4_4_4",t[t.UNSIGNED_SHORT_5_5_5_1=32820]="UNSIGNED_SHORT_5_5_5_1",t[t.UNSIGNED_INT=5125]="UNSIGNED_INT",t[t.UNSIGNED_INT_10F_11F_11F_REV=35899]="UNSIGNED_INT_10F_11F_11F_REV",t[t.UNSIGNED_INT_2_10_10_10_REV=33640]="UNSIGNED_INT_2_10_10_10_REV",t[t.UNSIGNED_INT_24_8=34042]="UNSIGNED_INT_24_8",t[t.UNSIGNED_INT_5_9_9_9_REV=35902]="UNSIGNED_INT_5_9_9_9_REV",t[t.BYTE=5120]="BYTE",t[t.SHORT=5122]="SHORT",t[t.INT=5124]="INT",t[t.FLOAT=5126]="FLOAT",t[t.FLOAT_32_UNSIGNED_INT_24_8_REV=36269]="FLOAT_32_UNSIGNED_INT_24_8_REV",t[t.HALF_FLOAT=36193]="HALF_FLOAT"}(t.TYPES||(t.TYPES={})),function(t){t[t.FLOAT=0]="FLOAT",t[t.INT=1]="INT",t[t.UINT=2]="UINT"}(t.SAMPLER_TYPES||(t.SAMPLER_TYPES={})),function(t){t[t.NEAREST=0]="NEAREST",t[t.LINEAR=1]="LINEAR"}(t.SCALE_MODES||(t.SCALE_MODES={})),function(t){t[t.CLAMP=33071]="CLAMP",t[t.REPEAT=10497]="REPEAT",t[t.MIRRORED_REPEAT=33648]="MIRRORED_REPEAT"}(t.WRAP_MODES||(t.WRAP_MODES={})),function(t){t[t.OFF=0]="OFF",t[t.POW2=1]="POW2",t[t.ON=2]="ON",t[t.ON_MANUAL=3]="ON_MANUAL"}(t.MIPMAP_MODES||(t.MIPMAP_MODES={})),function(t){t[t.NPM=0]="NPM",t[t.UNPACK=1]="UNPACK",t[t.PMA=2]="PMA",t[t.NO_PREMULTIPLIED_ALPHA=0]="NO_PREMULTIPLIED_ALPHA",t[t.PREMULTIPLY_ON_UPLOAD=1]="PREMULTIPLY_ON_UPLOAD",t[t.PREMULTIPLY_ALPHA=2]="PREMULTIPLY_ALPHA",t[t.PREMULTIPLIED_ALPHA=2]="PREMULTIPLIED_ALPHA"}(t.ALPHA_MODES||(t.ALPHA_MODES={})),function(t){t[t.NO=0]="NO",t[t.YES=1]="YES",t[t.AUTO=2]="AUTO",t[t.BLEND=0]="BLEND",t[t.CLEAR=1]="CLEAR",t[t.BLIT=2]="BLIT"}(t.CLEAR_MODES||(t.CLEAR_MODES={})),function(t){t[t.AUTO=0]="AUTO",t[t.MANUAL=1]="MANUAL"}(t.GC_MODES||(t.GC_MODES={})),function(t){t.LOW="lowp",t.MEDIUM="mediump",t.HIGH="highp"}(t.PRECISION||(t.PRECISION={})),function(t){t[t.NONE=0]="NONE",t[t.SCISSOR=1]="SCISSOR",t[t.STENCIL=2]="STENCIL",t[t.SPRITE=3]="SPRITE",t[t.COLOR=4]="COLOR"}(t.MASK_TYPES||(t.MASK_TYPES={})),function(t){t[t.RED=1]="RED",t[t.GREEN=2]="GREEN",t[t.BLUE=4]="BLUE",t[t.ALPHA=8]="ALPHA"}(t.COLOR_MASK_BITS||(t.COLOR_MASK_BITS={})),function(t){t[t.NONE=0]="NONE",t[t.LOW=2]="LOW",t[t.MEDIUM=4]="MEDIUM",t[t.HIGH=8]="HIGH"}(t.MSAA_QUALITY||(t.MSAA_QUALITY={})),function(t){t[t.ELEMENT_ARRAY_BUFFER=34963]="ELEMENT_ARRAY_BUFFER",t[t.ARRAY_BUFFER=34962]="ARRAY_BUFFER",t[t.UNIFORM_BUFFER=35345]="UNIFORM_BUFFER"}(t.BUFFER_TYPE||(t.BUFFER_TYPE={}));var E={createCanvas:function(t,e){var r=document.createElement("canvas");return r.width=t,r.height=e,r},getWebGLRenderingContext:function(){return WebGLRenderingContext},getNavigator:function(){return navigator},getBaseUrl:function(){var t;return null!==(t=document.baseURI)&&void 0!==t?t:window.location.href},fetch:function(t,e){return fetch(t,e)}},b=/iPhone/i,x=/iPod/i,A=/iPad/i,S=/\biOS-universal(?:.+)Mac\b/i,R=/\bAndroid(?:.+)Mobile\b/i,O=/Android/i,M=/(?:SD4930UR|\bSilk(?:.+)Mobile\b)/i,P=/Silk/i,I=/Windows Phone/i,D=/\bWindows(?:.+)ARM\b/i,w=/BlackBerry/i,C=/BB10/i,N=/Opera Mini/i,F=/\b(CriOS|Chrome)(?:.+)Mobile/i,L=/Mobile(?:.+)Firefox\b/i,B=function(t){return void 0!==t&&"MacIntel"===t.platform&&"number"==typeof t.maxTouchPoints&&t.maxTouchPoints>1&&"undefined"==typeof MSStream},G=function(t){var e={userAgent:"",platform:"",maxTouchPoints:0};t||"undefined"==typeof navigator?"string"==typeof t?e.userAgent=t:t&&t.userAgent&&(e={userAgent:t.userAgent,platform:t.platform,maxTouchPoints:t.maxTouchPoints||0}):e={userAgent:navigator.userAgent,platform:navigator.platform,maxTouchPoints:navigator.maxTouchPoints||0};var r=e.userAgent,i=r.split("[FBAN");void 0!==i[1]&&(r=i[0]),void 0!==(i=r.split("Twitter"))[1]&&(r=i[0]);var n=function(t){return function(e){return e.test(t)}}(r),o={apple:{phone:n(b)&&!n(I),ipod:n(x),tablet:!n(b)&&(n(A)||B(e))&&!n(I),universal:n(S),device:(n(b)||n(x)||n(A)||n(S)||B(e))&&!n(I)},amazon:{phone:n(M),tablet:!n(M)&&n(P),device:n(M)||n(P)},android:{phone:!n(I)&&n(M)||!n(I)&&n(R),tablet:!n(I)&&!n(M)&&!n(R)&&(n(P)||n(O)),device:!n(I)&&(n(M)||n(P)||n(R)||n(O))||n(/\bokhttp\b/i)},windows:{phone:n(I),tablet:n(D),device:n(I)||n(D)},other:{blackberry:n(w),blackberry10:n(C),opera:n(N),firefox:n(L),chrome:n(F),device:n(w)||n(C)||n(N)||n(L)||n(F)},any:!1,phone:!1,tablet:!1};return o.any=o.apple.device||o.android.device||o.windows.device||o.other.device,o.phone=o.apple.phone||o.android.phone||o.windows.phone,o.tablet=o.apple.tablet||o.android.tablet||o.windows.tablet,o}(globalThis.navigator),U={ADAPTER:E,MIPMAP_TEXTURES:t.MIPMAP_MODES.POW2,ANISOTROPIC_LEVEL:0,RESOLUTION:1,FILTER_RESOLUTION:1,FILTER_MULTISAMPLE:t.MSAA_QUALITY.NONE,SPRITE_MAX_TEXTURES:function(t){var e,r=!0;(G.tablet||G.phone)&&(G.apple.device&&(e=navigator.userAgent.match(/OS (\d+)_(\d+)?/))&&parseInt(e[1],10)<11&&(r=!1),G.android.device&&(e=navigator.userAgent.match(/Android\s([0-9.]*)/))&&parseInt(e[1],10)<7&&(r=!1));return r?32:4}(),SPRITE_BATCH_SIZE:4096,RENDER_OPTIONS:{view:null,width:800,height:600,autoDensity:!1,backgroundColor:0,backgroundAlpha:1,useContextAlpha:!0,clearBeforeRender:!0,antialias:!1,preserveDrawingBuffer:!1},GC_MODE:t.GC_MODES.AUTO,GC_MAX_IDLE:3600,GC_MAX_CHECK_COUNT:600,WRAP_MODE:t.WRAP_MODES.CLAMP,SCALE_MODE:t.SCALE_MODES.LINEAR,PRECISION_VERTEX:t.PRECISION.HIGH,PRECISION_FRAGMENT:G.apple.device?t.PRECISION.HIGH:t.PRECISION.MEDIUM,CAN_UPLOAD_SAME_BUFFER:!G.apple.device,CREATE_IMAGE_BITMAP:!1,ROUND_PIXELS:!1},k="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function X(t,e,r){return t(r={path:e,exports:{},require:function(t,e){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==e&&r.path)}},r.exports),r.exports}var j=X((function(t){var e=Object.prototype.hasOwnProperty,r="~";function i(){}function n(t,e,r){this.fn=t,this.context=e,this.once=r||!1}function o(t,e,i,o,s){if("function"!=typeof i)throw new TypeError("The listener must be a function");var a=new n(i,o||t,s),h=r?r+e:e;return t._events[h]?t._events[h].fn?t._events[h]=[t._events[h],a]:t._events[h].push(a):(t._events[h]=a,t._eventsCount++),t}function s(t,e){0==--t._eventsCount?t._events=new i:delete t._events[e]}function a(){this._events=new i,this._eventsCount=0}Object.create&&(i.prototype=Object.create(null),(new i).__proto__||(r=!1)),a.prototype.eventNames=function(){var t,i,n=[];if(0===this._eventsCount)return n;for(i in t=this._events)e.call(t,i)&&n.push(r?i.slice(1):i);return Object.getOwnPropertySymbols?n.concat(Object.getOwnPropertySymbols(t)):n},a.prototype.listeners=function(t){var e=r?r+t:t,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var n=0,o=i.length,s=new Array(o);n80*r){i=o=t[0],n=s=t[1];for(var p=r;po&&(o=a),h>s&&(s=h);u=0!==(u=Math.max(o-i,s-n))?32767/u:0}return q(d,f,r,i,n,u,0),f}function z(t,e,r,i,n){var o,s;if(n===vt(t,e,r,i)>0)for(o=e;o=e;o-=i)s=ft(o,t[o],t[o+1],s);return s&&at(s,s.next)&&(pt(s),s=s.next),s}function W(t,e){if(!t)return t;e||(e=t);var r,i=t;do{if(r=!1,i.steiner||!at(i,i.next)&&0!==st(i.prev,i,i.next))i=i.next;else{if(pt(i),(i=e=i.prev)===i.next)break;r=!0}}while(r||i!==e);return e}function q(t,e,r,i,n,o,s){if(t){!s&&o&&function(t,e,r,i){var n=t;do{0===n.z&&(n.z=rt(n.x,n.y,e,r,i)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==t);n.prevZ.nextZ=null,n.prevZ=null,function(t){var e,r,i,n,o,s,a,h,u=1;do{for(r=t,t=null,o=null,s=0;r;){for(s++,i=r,a=0,e=0;e0||h>0&&i;)0!==a&&(0===h||!i||r.z<=i.z)?(n=r,r=r.nextZ,a--):(n=i,i=i.nextZ,h--),o?o.nextZ=n:t=n,n.prevZ=o,o=n;r=i}o.nextZ=null,u*=2}while(s>1)}(n)}(t,i,n,o);for(var a,h,u=t;t.prev!==t.next;)if(a=t.prev,h=t.next,o?Z(t,i,n,o):K(t))e.push(a.i/r|0),e.push(t.i/r|0),e.push(h.i/r|0),pt(t),t=h.next,u=h.next;else if((t=h)===u){s?1===s?q(t=Q(W(t),e,r),e,r,i,n,o,2):2===s&&J(t,e,r,i,n,o):q(W(t),e,r,i,n,o,1);break}}}function K(t){var e=t.prev,r=t,i=t.next;if(st(e,r,i)>=0)return!1;for(var n=e.x,o=r.x,s=i.x,a=e.y,h=r.y,u=i.y,l=no?n>s?n:s:o>s?o:s,f=a>h?a>u?a:u:h>u?h:u,p=i.next;p!==e;){if(p.x>=l&&p.x<=d&&p.y>=c&&p.y<=f&&nt(n,a,o,h,s,u,p.x,p.y)&&st(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function Z(t,e,r,i){var n=t.prev,o=t,s=t.next;if(st(n,o,s)>=0)return!1;for(var a=n.x,h=o.x,u=s.x,l=n.y,c=o.y,d=s.y,f=ah?a>u?a:u:h>u?h:u,v=l>c?l>d?l:d:c>d?c:d,m=rt(f,p,e,r,i),y=rt(_,v,e,r,i),g=t.prevZ,T=t.nextZ;g&&g.z>=m&&T&&T.z<=y;){if(g.x>=f&&g.x<=_&&g.y>=p&&g.y<=v&&g!==n&&g!==s&&nt(a,l,h,c,u,d,g.x,g.y)&&st(g.prev,g,g.next)>=0)return!1;if(g=g.prevZ,T.x>=f&&T.x<=_&&T.y>=p&&T.y<=v&&T!==n&&T!==s&&nt(a,l,h,c,u,d,T.x,T.y)&&st(T.prev,T,T.next)>=0)return!1;T=T.nextZ}for(;g&&g.z>=m;){if(g.x>=f&&g.x<=_&&g.y>=p&&g.y<=v&&g!==n&&g!==s&&nt(a,l,h,c,u,d,g.x,g.y)&&st(g.prev,g,g.next)>=0)return!1;g=g.prevZ}for(;T&&T.z<=y;){if(T.x>=f&&T.x<=_&&T.y>=p&&T.y<=v&&T!==n&&T!==s&&nt(a,l,h,c,u,d,T.x,T.y)&&st(T.prev,T,T.next)>=0)return!1;T=T.nextZ}return!0}function Q(t,e,r){var i=t;do{var n=i.prev,o=i.next.next;!at(n,o)&&ht(n,i,i.next,o)&&ct(n,o)&&ct(o,n)&&(e.push(n.i/r|0),e.push(i.i/r|0),e.push(o.i/r|0),pt(i),pt(i.next),i=t=o),i=i.next}while(i!==t);return W(i)}function J(t,e,r,i,n,o){var s=t;do{for(var a=s.next.next;a!==s.prev;){if(s.i!==a.i&&ot(s,a)){var h=dt(s,a);return s=W(s,s.next),h=W(h,h.next),q(s,e,r,i,n,o,0),void q(h,e,r,i,n,o,0)}a=a.next}s=s.next}while(s!==t)}function $(t,e){return t.x-e.x}function tt(t,e){var r=function(t,e){var r,i=e,n=t.x,o=t.y,s=-1/0;do{if(o<=i.y&&o>=i.next.y&&i.next.y!==i.y){var a=i.x+(o-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(a<=n&&a>s&&(s=a,r=i.x=i.x&&i.x>=l&&n!==i.x&&nt(or.x||i.x===r.x&&et(r,i)))&&(r=i,d=h)),i=i.next}while(i!==u);return r}(t,e);if(!r)return e;var i=dt(r,t);return W(i,i.next),W(r,r.next)}function et(t,e){return st(t.prev,t,e.prev)<0&&st(e.next,t,t.next)<0}function rt(t,e,r,i,n){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-r)*n|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*n|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function it(t){var e=t,r=t;do{(e.x=(t-s)*(o-a)&&(t-s)*(i-a)>=(r-s)*(e-a)&&(r-s)*(o-a)>=(n-s)*(i-a)}function ot(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&ht(r,r.next,t,e))return!0;r=r.next}while(r!==t);return!1}(t,e)&&(ct(t,e)&&ct(e,t)&&function(t,e){var r=t,i=!1,n=(t.x+e.x)/2,o=(t.y+e.y)/2;do{r.y>o!=r.next.y>o&&r.next.y!==r.y&&n<(r.next.x-r.x)*(o-r.y)/(r.next.y-r.y)+r.x&&(i=!i),r=r.next}while(r!==t);return i}(t,e)&&(st(t.prev,t,e.prev)||st(t,e.prev,e))||at(t,e)&&st(t.prev,t,t.next)>0&&st(e.prev,e,e.next)>0)}function st(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function at(t,e){return t.x===e.x&&t.y===e.y}function ht(t,e,r,i){var n=lt(st(t,e,r)),o=lt(st(t,e,i)),s=lt(st(r,i,t)),a=lt(st(r,i,e));return n!==o&&s!==a||(!(0!==n||!ut(t,r,e))||(!(0!==o||!ut(t,i,e))||(!(0!==s||!ut(r,t,i))||!(0!==a||!ut(r,e,i)))))}function ut(t,e,r){return e.x<=Math.max(t.x,r.x)&&e.x>=Math.min(t.x,r.x)&&e.y<=Math.max(t.y,r.y)&&e.y>=Math.min(t.y,r.y)}function lt(t){return t>0?1:t<0?-1:0}function ct(t,e){return st(t.prev,t,t.next)<0?st(t,e,t.next)>=0&&st(t,t.prev,e)>=0:st(t,e,t.prev)<0||st(t,t.next,e)<0}function dt(t,e){var r=new _t(t.i,t.x,t.y),i=new _t(e.i,e.x,e.y),n=t.next,o=e.prev;return t.next=e,e.prev=t,r.next=n,n.prev=r,i.next=r,r.prev=i,o.next=i,i.prev=o,i}function ft(t,e,r,i){var n=new _t(t,e,r);return i?(n.next=i.next,n.prev=i,i.next.prev=n,i.next=n):(n.prev=n,n.next=n),n}function pt(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function _t(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}function vt(t,e,r,i){for(var n=0,o=e,s=r-i;o0&&(i+=t[n-1].length,r.holes.push(i))}return r},H.default=Y;var mt=X((function(t,e){!function(r){var i=e&&!e.nodeType&&e,n=t&&!t.nodeType&&t,o="object"==typeof k&&k;o.global!==o&&o.window!==o&&o.self!==o||(r=o);var s,a,h=2147483647,u=36,l=/^xn--/,c=/[^\x20-\x7E]/,d=/[\x2E\u3002\uFF0E\uFF61]/g,f={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},p=Math.floor,_=String.fromCharCode;function v(t){throw RangeError(f[t])}function m(t,e){for(var r=t.length,i=[];r--;)i[r]=e(t[r]);return i}function y(t,e){var r=t.split("@"),i="";return r.length>1&&(i=r[0]+"@",t=r[1]),i+m((t=t.replace(d,".")).split("."),e).join(".")}function g(t){for(var e,r,i=[],n=0,o=t.length;n=55296&&e<=56319&&n65535&&(e+=_((t-=65536)>>>10&1023|55296),t=56320|1023&t),e+=_(t)})).join("")}function E(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function b(t,e,r){var i=0;for(t=r?p(t/700):t>>1,t+=p(t/e);t>455;i+=u)t=p(t/35);return p(i+36*t/(t+38))}function x(t){var e,r,i,n,o,s,a,l,c,d,f,_=[],m=t.length,y=0,g=128,E=72;for((r=t.lastIndexOf("-"))<0&&(r=0),i=0;i=128&&v("not-basic"),_.push(t.charCodeAt(i));for(n=r>0?r+1:0;n=m&&v("invalid-input"),((l=(f=t.charCodeAt(n++))-48<10?f-22:f-65<26?f-65:f-97<26?f-97:u)>=u||l>p((h-y)/s))&&v("overflow"),y+=l*s,!(l<(c=a<=E?1:a>=E+26?26:a-E));a+=u)s>p(h/(d=u-c))&&v("overflow"),s*=d;E=b(y-o,e=_.length+1,0==o),p(y/e)>h-g&&v("overflow"),g+=p(y/e),y%=e,_.splice(y++,0,g)}return T(_)}function A(t){var e,r,i,n,o,s,a,l,c,d,f,m,y,T,x,A=[];for(m=(t=g(t)).length,e=128,r=0,o=72,s=0;s=e&&fp((h-r)/(y=i+1))&&v("overflow"),r+=(a-e)*y,e=a,s=0;sh&&v("overflow"),f==e){for(l=r,c=u;!(l<(d=c<=o?1:c>=o+26?26:c-o));c+=u)x=l-d,T=u-d,A.push(_(E(d+x%T,0))),l=p(x/T);A.push(_(E(l,0))),o=b(r,y,i==n),r=0,++i}++r,++e}return A.join("")}if(s={version:"1.3.2",ucs2:{decode:g,encode:T},decode:x,encode:A,toASCII:function(t){return y(t,(function(t){return c.test(t)?"xn--"+A(t):t}))},toUnicode:function(t){return y(t,(function(t){return l.test(t)?x(t.slice(4).toLowerCase()):t}))}},i&&n)if(t.exports==i)n.exports=s;else for(a in s)s.hasOwnProperty(a)&&(i[a]=s[a]);else r.punycode=s}(k)})),yt=function(t){return"string"==typeof t},gt=function(t){return"object"==typeof t&&null!==t},Tt=function(t){return null===t},Et=function(t){return null==t};function bt(t,e){return Object.prototype.hasOwnProperty.call(t,e)}var xt=function(t,e,r,i){e=e||"&",r=r||"=";var n={};if("string"!=typeof t||0===t.length)return n;var o=/\+/g;t=t.split(e);var s=1e3;i&&"number"==typeof i.maxKeys&&(s=i.maxKeys);var a=t.length;s>0&&a>s&&(a=s);for(var h=0;h=0?(u=f.substr(0,p),l=f.substr(p+1)):(u=f,l=""),c=decodeURIComponent(u),d=decodeURIComponent(l),bt(n,c)?Array.isArray(n[c])?n[c].push(d):n[c]=[n[c],d]:n[c]=d}return n},At=function(t){switch(typeof t){case"string":return t;case"boolean":return t?"true":"false";case"number":return isFinite(t)?t:"";default:return""}},St=function(t,e,r,i){return e=e||"&",r=r||"=",null===t&&(t=void 0),"object"==typeof t?Object.keys(t).map((function(i){var n=encodeURIComponent(At(i))+r;return Array.isArray(t[i])?t[i].map((function(t){return n+encodeURIComponent(At(t))})).join(e):n+encodeURIComponent(At(t[i]))})).join(e):i?encodeURIComponent(At(i))+r+encodeURIComponent(At(t)):""},Rt=X((function(t,e){e.decode=e.parse=xt,e.encode=e.stringify=St})),Ot=Ht,Mt=function(t,e){return Ht(t,!1,!0).resolve(e)},Pt=function(t){yt(t)&&(t=Ht(t));if(!(t instanceof It))return It.prototype.format.call(t);return t.format()};function It(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}var Dt=/^([a-z0-9.+-]+:)/i,wt=/:[0-9]*$/,Ct=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,Nt=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),Ft=["'"].concat(Nt),Lt=["%","/","?",";","#"].concat(Ft),Bt=["/","?","#"],Gt=/^[+a-z0-9A-Z_-]{0,63}$/,Ut=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,kt={javascript:!0,"javascript:":!0},Xt={javascript:!0,"javascript:":!0},jt={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0};function Ht(t,e,r){if(t&>(t)&&t instanceof It)return t;var i=new It;return i.parse(t,e,r),i}It.prototype.parse=function(t,e,r){if(!yt(t))throw new TypeError("Parameter 'url' must be a string, not "+typeof t);var i=t.indexOf("?"),n=-1!==i&&i127?T+="x":T+=g[E];if(!T.match(Gt)){var x=m.slice(0,p),A=m.slice(p+1),S=g.match(Ut);S&&(x.push(S[1]),A.unshift(S[2])),A.length&&(s="/"+A.join(".")+s),this.hostname=x.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),v||(this.hostname=mt.toASCII(this.hostname));var R=this.port?":"+this.port:"",O=this.hostname||"";this.host=O+R,this.href+=this.host,v&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==s[0]&&(s="/"+s))}if(!kt[u])for(p=0,y=Ft.length;p0)&&r.host.split("@"))&&(r.auth=S.shift(),r.host=r.hostname=S.shift());return r.search=t.search,r.query=t.query,Tt(r.pathname)&&Tt(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!g.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var E=g.slice(-1)[0],b=(r.host||t.host||g.length>1)&&("."===E||".."===E)||""===E,x=0,A=g.length;A>=0;A--)"."===(E=g[A])?g.splice(A,1):".."===E?(g.splice(A,1),x++):x&&(g.splice(A,1),x--);if(!m&&!y)for(;x--;x)g.unshift("..");!m||""===g[0]||g[0]&&"/"===g[0].charAt(0)||g.unshift(""),b&&"/"!==g.join("/").substr(-1)&&g.push("");var S,R=""===g[0]||g[0]&&"/"===g[0].charAt(0);T&&(r.hostname=r.host=R?"":g.length?g.shift():"",(S=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@"))&&(r.auth=S.shift(),r.host=r.hostname=S.shift()));return(m=m||r.host&&g.length)&&!R&&g.unshift(""),g.length?r.pathname=g.join("/"):(r.pathname=null,r.path=null),Tt(r.pathname)&&Tt(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=t.auth||r.auth,r.slashes=r.slashes||t.slashes,r.href=r.format(),r},It.prototype.parseHost=function(){var t=this.host,e=wt.exec(t);e&&(":"!==(e=e[0])&&(this.port=e.substr(1)),t=t.substr(0,t.length-e.length)),t&&(this.hostname=t)};var Yt={parse:Ot,format:Pt,resolve:Mt};function Vt(t){if("string"!=typeof t)throw new TypeError("Path must be a string. Received "+JSON.stringify(t))}function zt(t){return t.split("?")[0].split("#")[0]}var Wt={toPosix:function(t){return"\\","/",t.replace(new RegExp("\\".replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),"/")},isUrl:function(t){return/^https?:/.test(this.toPosix(t))},isDataUrl:function(t){return/^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()_|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s<>]*?)$/i.test(t)},hasProtocol:function(t){return/^[^/:]+:\//.test(this.toPosix(t))},getProtocol:function(t){Vt(t),t=this.toPosix(t);var e="",r=/^file:\/\/\//.exec(t),i=/^[^/:]+:\/\//.exec(t),n=/^[^/:]+:\//.exec(t);if(r||i||n){var o=(null==r?void 0:r[0])||(null==i?void 0:i[0])||(null==n?void 0:n[0]);e=o,t=t.slice(o.length)}return e},toAbsolute:function(t,e,r){if(this.isDataUrl(t))return t;var i=zt(this.toPosix(null!=e?e:U.ADAPTER.getBaseUrl())),n=zt(this.toPosix(null!=r?r:this.rootname(i)));return Vt(t),(t=this.toPosix(t)).startsWith("/")?Wt.join(n,t.slice(1)):this.isAbsolute(t)?t:this.join(i,t)},normalize:function(t){if(Vt(t=this.toPosix(t)),0===t.length)return".";var e="",r=t.startsWith("/");this.hasProtocol(t)&&(e=this.rootname(t),t=t.slice(e.length));var i=t.endsWith("/");return(t=function(t,e){for(var r,i="",n=0,o=-1,s=0,a=0;a<=t.length;++a){if(a2){var h=i.lastIndexOf("/");if(h!==i.length-1){-1===h?(i="",n=0):n=(i=i.slice(0,h)).length-1-i.lastIndexOf("/"),o=a,s=0;continue}}else if(2===i.length||1===i.length){i="",n=0,o=a,s=0;continue}}else i.length>0?i+="/"+t.slice(o+1,a):i=t.slice(o+1,a),n=a-o-1;o=a,s=0}else 46===r&&-1!==s?++s:s=-1}return i}(t)).length>0&&i&&(t+="/"),r?"/"+t:e+t},isAbsolute:function(t){return Vt(t),t=this.toPosix(t),!!this.hasProtocol(t)||t.startsWith("/")},join:function(){for(var t,e,r=arguments,i=[],n=0;n0)if(void 0===e)e=s;else{var a=null!==(t=i[o-1])&&void 0!==t?t:"";this.extname(a)?e+="/../"+s:e+="/"+s}}return void 0===e?".":this.normalize(e)},dirname:function(t){if(Vt(t),0===t.length)return".";for(var e=(t=this.toPosix(t)).charCodeAt(0),r=47===e,i=-1,n=!0,o=this.getProtocol(t),s=t,a=(t=t.slice(o.length)).length-1;a>=1;--a)if(47===(e=t.charCodeAt(a))){if(!n){i=a;break}}else n=!1;return-1===i?r?"/":this.isUrl(s)?o+t:o:r&&1===i?"//":o+t.slice(0,i)},rootname:function(t){Vt(t);var e="";if(e=(t=this.toPosix(t)).startsWith("/")?"/":this.getProtocol(t),this.isUrl(t)){var r=t.indexOf("/",e.length);(e=-1!==r?t.slice(0,r):t).endsWith("/")||(e+="/")}return e},basename:function(t,e){Vt(t),e&&Vt(e),t=this.toPosix(t);var r,i=0,n=-1,o=!0;if(void 0!==e&&e.length>0&&e.length<=t.length){if(e.length===t.length&&e===t)return"";var s=e.length-1,a=-1;for(r=t.length-1;r>=0;--r){var h=t.charCodeAt(r);if(47===h){if(!o){i=r+1;break}}else-1===a&&(o=!1,a=r+1),s>=0&&(h===e.charCodeAt(s)?-1==--s&&(n=r):(s=-1,n=a))}return i===n?n=a:-1===n&&(n=t.length),t.slice(i,n)}for(r=t.length-1;r>=0;--r)if(47===t.charCodeAt(r)){if(!o){i=r+1;break}}else-1===n&&(o=!1,n=r+1);return-1===n?"":t.slice(i,n)},extname:function(t){Vt(t);for(var e=-1,r=0,i=-1,n=!0,o=0,s=(t=this.toPosix(t)).length-1;s>=0;--s){var a=t.charCodeAt(s);if(47!==a)-1===i&&(n=!1,i=s+1),46===a?-1===e?e=s:1!==o&&(o=1):-1!==e&&(o=-1);else if(!n){r=s+1;break}}return-1===e||-1===i||0===o||1===o&&e===i-1&&e===r+1?"":t.slice(e,i)},parse:function(t){Vt(t);var e={root:"",dir:"",base:"",ext:"",name:""};if(0===t.length)return e;var r,i=(t=this.toPosix(t)).charCodeAt(0),n=this.isAbsolute(t);e.root=this.rootname(t),r=n||this.hasProtocol(t)?1:0;for(var o=-1,s=0,a=-1,h=!0,u=t.length-1,l=0;u>=r;--u)if(47!==(i=t.charCodeAt(u)))-1===a&&(h=!1,a=u+1),46===i?-1===o?o=u:1!==l&&(l=1):-1!==o&&(l=-1);else if(!h){s=u+1;break}return-1===o||-1===a||0===l||1===l&&o===a-1&&o===s+1?-1!==a&&(e.base=e.name=0===s&&n?t.slice(1,a):t.slice(s,a)):(0===s&&n?(e.name=t.slice(1,o),e.base=t.slice(1,a)):(e.name=t.slice(s,o),e.base=t.slice(s,a)),e.ext=t.slice(o,a)),e.dir=this.dirname(t),e},sep:"/",delimiter:":"};U.RETINA_PREFIX=/@([0-9\.]+)x/,U.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT=!1;var qt,Kt=!1;function Zt(t){var e;if(!Kt){if(U.ADAPTER.getNavigator().userAgent.toLowerCase().indexOf("chrome")>-1){var r=["\n %c %c %c PixiJS 6.5.10 - ✰ "+t+" ✰ %c %c http://www.pixijs.com/ %c %c ♥%c♥%c♥ \n\n","background: #ff66a5; padding:5px 0;","background: #ff66a5; padding:5px 0;","color: #ff66a5; background: #030307; padding:5px 0;","background: #ff66a5; padding:5px 0;","background: #ffc3dc; padding:5px 0;","background: #ff66a5; padding:5px 0;","color: #ff2424; background: #fff; padding:5px 0;","color: #ff2424; background: #fff; padding:5px 0;","color: #ff2424; background: #fff; padding:5px 0;"];(e=globalThis.console).log.apply(e,r)}else globalThis.console&&globalThis.console.log("PixiJS 6.5.10 - "+t+" - http://www.pixijs.com/");Kt=!0}}function Qt(){return void 0===qt&&(qt=function(){var t={stencil:!0,failIfMajorPerformanceCaveat:U.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT};try{if(!U.ADAPTER.getWebGLRenderingContext())return!1;var e=U.ADAPTER.createCanvas(),r=e.getContext("webgl",t)||e.getContext("experimental-webgl",t),i=!(!r||!r.getContextAttributes().stencil);if(r){var n=r.getExtension("WEBGL_lose_context");n&&n.loseContext()}return r=null,i}catch(t){return!1}}()),qt}var Jt={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",goldenrod:"#daa520",gold:"#ffd700",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavenderblush:"#fff0f5",lavender:"#e6e6fa",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};function $t(t,e){return void 0===e&&(e=[]),e[0]=(t>>16&255)/255,e[1]=(t>>8&255)/255,e[2]=(255&t)/255,e}function te(t){var e=t.toString(16);return"#"+("000000".substring(0,6-e.length)+e)}function ee(t){return"string"==typeof t&&"#"===(t=Jt[t.toLowerCase()]||t)[0]&&(t=t.slice(1)),parseInt(t,16)}var re=function(){for(var e=[],r=[],i=0;i<32;i++)e[i]=i,r[i]=i;e[t.BLEND_MODES.NORMAL_NPM]=t.BLEND_MODES.NORMAL,e[t.BLEND_MODES.ADD_NPM]=t.BLEND_MODES.ADD,e[t.BLEND_MODES.SCREEN_NPM]=t.BLEND_MODES.SCREEN,r[t.BLEND_MODES.NORMAL]=t.BLEND_MODES.NORMAL_NPM,r[t.BLEND_MODES.ADD]=t.BLEND_MODES.ADD_NPM,r[t.BLEND_MODES.SCREEN]=t.BLEND_MODES.SCREEN_NPM;var n=[];return n.push(r),n.push(e),n}();function ie(t,e){return re[e?1:0][t]}function ne(t,e,r,i){return r=r||new Float32Array(4),i||void 0===i?(r[0]=t[0]*e,r[1]=t[1]*e,r[2]=t[2]*e):(r[0]=t[0],r[1]=t[1],r[2]=t[2]),r[3]=e,r}function oe(t,e){if(1===e)return(255*e<<24)+t;if(0===e)return 0;var r=t>>16&255,i=t>>8&255,n=255&t;return(255*e<<24)+((r=r*e+.5|0)<<16)+((i=i*e+.5|0)<<8)+(n*e+.5|0)}function se(t,e,r,i){return(r=r||new Float32Array(4))[0]=(t>>16&255)/255,r[1]=(t>>8&255)/255,r[2]=(255&t)/255,(i||void 0===i)&&(r[0]*=e,r[1]*=e,r[2]*=e),r[3]=e,r}function ae(t,e){void 0===e&&(e=null);var r=6*t;if((e=e||new Uint16Array(r)).length!==r)throw new Error("Out buffer length is incorrect, got "+e.length+" and expected "+r);for(var i=0,n=0;i>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,1+(t|=t>>>16)}function ce(t){return!(t&t-1||!t)}function de(t){var e=(t>65535?1:0)<<4,r=((t>>>=e)>255?1:0)<<3;return e|=r,e|=r=((t>>>=r)>15?1:0)<<2,(e|=r=((t>>>=r)>3?1:0)<<1)|(t>>>=r)>>1}function fe(t,e,r){var i,n=t.length;if(!(e>=n||0===r)){var o=n-(r=e+r>n?n-e:r);for(i=e;i=this.x&&t=this.y&&et.right?t.right:this.right)<=r)return!1;var i=this.yt.bottom?t.bottom:this.bottom)>i}var n=this.left,o=this.right,s=this.top,a=this.bottom;if(o<=n||a<=s)return!1;var h=we[0].set(t.left,t.top),u=we[1].set(t.left,t.bottom),l=we[2].set(t.right,t.top),c=we[3].set(t.right,t.bottom);if(l.x<=h.x||u.y<=h.y)return!1;var d=Math.sign(e.a*e.d-e.b*e.c);if(0===d)return!1;if(e.apply(h,h),e.apply(u,u),e.apply(l,l),e.apply(c,c),Math.max(h.x,u.x,l.x,c.x)<=n||Math.min(h.x,u.x,l.x,c.x)>=o||Math.max(h.y,u.y,l.y,c.y)<=s||Math.min(h.y,u.y,l.y,c.y)>=a)return!1;var f=d*(u.y-h.y),p=d*(h.x-u.x),_=f*n+p*s,v=f*o+p*s,m=f*n+p*a,y=f*o+p*a;if(Math.max(_,v,m,y)<=f*h.x+p*h.y||Math.min(_,v,m,y)>=f*c.x+p*c.y)return!1;var g=d*(h.y-l.y),T=d*(l.x-h.x),E=g*n+T*s,b=g*o+T*s,x=g*n+T*a,A=g*o+T*a;return!(Math.max(E,b,x,A)<=g*h.x+T*h.y||Math.min(E,b,x,A)>=g*c.x+T*c.y)},e.prototype.pad=function(t,e){return void 0===t&&(t=0),void 0===e&&(e=t),this.x-=t,this.y-=e,this.width+=2*t,this.height+=2*e,this},e.prototype.fit=function(t){var e=Math.max(this.x,t.x),r=Math.min(this.x+this.width,t.x+t.width),i=Math.max(this.y,t.y),n=Math.min(this.y+this.height,t.y+t.height);return this.x=e,this.width=Math.max(r-e,0),this.y=i,this.height=Math.max(n-i,0),this},e.prototype.ceil=function(t,e){void 0===t&&(t=1),void 0===e&&(e=.001);var r=Math.ceil((this.x+this.width-e)*t)/t,i=Math.ceil((this.y+this.height-e)*t)/t;return this.x=Math.floor((this.x+e)*t)/t,this.y=Math.floor((this.y+e)*t)/t,this.width=r-this.x,this.height=i-this.y,this},e.prototype.enlarge=function(t){var e=Math.min(this.x,t.x),r=Math.max(this.x+this.width,t.x+t.width),i=Math.min(this.y,t.y),n=Math.max(this.y+this.height,t.y+t.height);return this.x=e,this.width=r-e,this.y=i,this.height=n-i,this},e}(),Ne=function(){function e(e,r,i){void 0===e&&(e=0),void 0===r&&(r=0),void 0===i&&(i=0),this.x=e,this.y=r,this.radius=i,this.type=t.SHAPES.CIRC}return e.prototype.clone=function(){return new e(this.x,this.y,this.radius)},e.prototype.contains=function(t,e){if(this.radius<=0)return!1;var r=this.radius*this.radius,i=this.x-t,n=this.y-e;return(i*=i)+(n*=n)<=r},e.prototype.getBounds=function(){return new Ce(this.x-this.radius,this.y-this.radius,2*this.radius,2*this.radius)},e}(),Fe=function(){function e(e,r,i,n){void 0===e&&(e=0),void 0===r&&(r=0),void 0===i&&(i=0),void 0===n&&(n=0),this.x=e,this.y=r,this.width=i,this.height=n,this.type=t.SHAPES.ELIP}return e.prototype.clone=function(){return new e(this.x,this.y,this.width,this.height)},e.prototype.contains=function(t,e){if(this.width<=0||this.height<=0)return!1;var r=(t-this.x)/this.width,i=(e-this.y)/this.height;return(r*=r)+(i*=i)<=1},e.prototype.getBounds=function(){return new Ce(this.x-this.width,this.y-this.height,this.width,this.height)},e}(),Le=function(){function e(){for(var e=arguments,r=[],i=0;ie!=u>e&&t<(e-a)/(u-a)*(h-s)+s&&(r=!r)}return r},e}(),Be=function(){function e(e,r,i,n,o){void 0===e&&(e=0),void 0===r&&(r=0),void 0===i&&(i=0),void 0===n&&(n=0),void 0===o&&(o=20),this.x=e,this.y=r,this.width=i,this.height=n,this.radius=o,this.type=t.SHAPES.RREC}return e.prototype.clone=function(){return new e(this.x,this.y,this.width,this.height,this.radius)},e.prototype.contains=function(t,e){if(this.width<=0||this.height<=0)return!1;if(t>=this.x&&t<=this.x+this.width&&e>=this.y&&e<=this.y+this.height){var r=Math.max(0,Math.min(this.radius,Math.min(this.width,this.height)/2));if(e>=this.y+r&&e<=this.y+this.height-r||t>=this.x+r&&t<=this.x+this.width-r)return!0;var i=t-(this.x+r),n=e-(this.y+r),o=r*r;if(i*i+n*n<=o)return!0;if((i=t-(this.x+this.width-r))*i+n*n<=o)return!0;if(i*i+(n=e-(this.y+this.height-r))*n<=o)return!0;if((i=t-(this.x+r))*i+n*n<=o)return!0}return!1},e}(),Ge=function(){function t(t,e,r,i){void 0===r&&(r=0),void 0===i&&(i=0),this._x=r,this._y=i,this.cb=t,this.scope=e}return t.prototype.clone=function(e,r){return void 0===e&&(e=this.cb),void 0===r&&(r=this.scope),new t(e,r,this._x,this._y)},t.prototype.set=function(t,e){return void 0===t&&(t=0),void 0===e&&(e=t),this._x===t&&this._y===e||(this._x=t,this._y=e,this.cb.call(this.scope)),this},t.prototype.copyFrom=function(t){return this._x===t.x&&this._y===t.y||(this._x=t.x,this._y=t.y,this.cb.call(this.scope)),this},t.prototype.copyTo=function(t){return t.set(this._x,this._y),t},t.prototype.equals=function(t){return t.x===this._x&&t.y===this._y},Object.defineProperty(t.prototype,"x",{get:function(){return this._x},set:function(t){this._x!==t&&(this._x=t,this.cb.call(this.scope))},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"y",{get:function(){return this._y},set:function(t){this._y!==t&&(this._y=t,this.cb.call(this.scope))},enumerable:!1,configurable:!0}),t}(),Ue=function(){function t(t,e,r,i,n,o){void 0===t&&(t=1),void 0===e&&(e=0),void 0===r&&(r=0),void 0===i&&(i=1),void 0===n&&(n=0),void 0===o&&(o=0),this.array=null,this.a=t,this.b=e,this.c=r,this.d=i,this.tx=n,this.ty=o}return t.prototype.fromArray=function(t){this.a=t[0],this.b=t[1],this.c=t[3],this.d=t[4],this.tx=t[2],this.ty=t[5]},t.prototype.set=function(t,e,r,i,n,o){return this.a=t,this.b=e,this.c=r,this.d=i,this.tx=n,this.ty=o,this},t.prototype.toArray=function(t,e){this.array||(this.array=new Float32Array(9));var r=e||this.array;return t?(r[0]=this.a,r[1]=this.b,r[2]=0,r[3]=this.c,r[4]=this.d,r[5]=0,r[6]=this.tx,r[7]=this.ty,r[8]=1):(r[0]=this.a,r[1]=this.c,r[2]=this.tx,r[3]=this.b,r[4]=this.d,r[5]=this.ty,r[6]=0,r[7]=0,r[8]=1),r},t.prototype.apply=function(t,e){e=e||new De;var r=t.x,i=t.y;return e.x=this.a*r+this.c*i+this.tx,e.y=this.b*r+this.d*i+this.ty,e},t.prototype.applyInverse=function(t,e){e=e||new De;var r=1/(this.a*this.d+this.c*-this.b),i=t.x,n=t.y;return e.x=this.d*r*i+-this.c*r*n+(this.ty*this.c-this.tx*this.d)*r,e.y=this.a*r*n+-this.b*r*i+(-this.ty*this.a+this.tx*this.b)*r,e},t.prototype.translate=function(t,e){return this.tx+=t,this.ty+=e,this},t.prototype.scale=function(t,e){return this.a*=t,this.d*=e,this.c*=t,this.b*=e,this.tx*=t,this.ty*=e,this},t.prototype.rotate=function(t){var e=Math.cos(t),r=Math.sin(t),i=this.a,n=this.c,o=this.tx;return this.a=i*e-this.b*r,this.b=i*r+this.b*e,this.c=n*e-this.d*r,this.d=n*r+this.d*e,this.tx=o*e-this.ty*r,this.ty=o*r+this.ty*e,this},t.prototype.append=function(t){var e=this.a,r=this.b,i=this.c,n=this.d;return this.a=t.a*e+t.b*i,this.b=t.a*r+t.b*n,this.c=t.c*e+t.d*i,this.d=t.c*r+t.d*n,this.tx=t.tx*e+t.ty*i+this.tx,this.ty=t.tx*r+t.ty*n+this.ty,this},t.prototype.setTransform=function(t,e,r,i,n,o,s,a,h){return this.a=Math.cos(s+h)*n,this.b=Math.sin(s+h)*n,this.c=-Math.sin(s-a)*o,this.d=Math.cos(s-a)*o,this.tx=t-(r*this.a+i*this.c),this.ty=e-(r*this.b+i*this.d),this},t.prototype.prepend=function(t){var e=this.tx;if(1!==t.a||0!==t.b||0!==t.c||1!==t.d){var r=this.a,i=this.c;this.a=r*t.a+this.b*t.c,this.b=r*t.b+this.b*t.d,this.c=i*t.a+this.d*t.c,this.d=i*t.b+this.d*t.d}return this.tx=e*t.a+this.ty*t.c+t.tx,this.ty=e*t.b+this.ty*t.d+t.ty,this},t.prototype.decompose=function(t){var e=this.a,r=this.b,i=this.c,n=this.d,o=t.pivot,s=-Math.atan2(-i,n),a=Math.atan2(r,e),h=Math.abs(s+a);return h<1e-5||Math.abs(Me-h)<1e-5?(t.rotation=a,t.skew.x=t.skew.y=0):(t.rotation=0,t.skew.x=s,t.skew.y=a),t.scale.x=Math.sqrt(e*e+r*r),t.scale.y=Math.sqrt(i*i+n*n),t.position.x=this.tx+(o.x*e+o.y*i),t.position.y=this.ty+(o.x*r+o.y*n),t},t.prototype.invert=function(){var t=this.a,e=this.b,r=this.c,i=this.d,n=this.tx,o=t*i-e*r;return this.a=i/o,this.b=-e/o,this.c=-r/o,this.d=t/o,this.tx=(r*this.ty-i*n)/o,this.ty=-(t*this.ty-e*n)/o,this},t.prototype.identity=function(){return this.a=1,this.b=0,this.c=0,this.d=1,this.tx=0,this.ty=0,this},t.prototype.clone=function(){var e=new t;return e.a=this.a,e.b=this.b,e.c=this.c,e.d=this.d,e.tx=this.tx,e.ty=this.ty,e},t.prototype.copyTo=function(t){return t.a=this.a,t.b=this.b,t.c=this.c,t.d=this.d,t.tx=this.tx,t.ty=this.ty,t},t.prototype.copyFrom=function(t){return this.a=t.a,this.b=t.b,this.c=t.c,this.d=t.d,this.tx=t.tx,this.ty=t.ty,this},Object.defineProperty(t,"IDENTITY",{get:function(){return new t},enumerable:!1,configurable:!0}),Object.defineProperty(t,"TEMP_MATRIX",{get:function(){return new t},enumerable:!1,configurable:!0}),t}(),ke=[1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1,-1,0,1],Xe=[0,1,1,1,0,-1,-1,-1,0,1,1,1,0,-1,-1,-1],je=[0,-1,-1,-1,0,1,1,1,0,1,1,1,0,-1,-1,-1],He=[1,1,0,-1,-1,-1,0,1,-1,-1,0,1,1,1,0,-1],Ye=[],Ve=[],ze=Math.sign;!function(){for(var t=0;t<16;t++){var e=[];Ye.push(e);for(var r=0;r<16;r++)for(var i=ze(ke[t]*ke[r]+je[t]*Xe[r]),n=ze(Xe[t]*ke[r]+He[t]*Xe[r]),o=ze(ke[t]*je[r]+je[t]*He[r]),s=ze(Xe[t]*je[r]+He[t]*He[r]),a=0;a<16;a++)if(ke[a]===i&&Xe[a]===n&&je[a]===o&&He[a]===s){e.push(a);break}}for(t=0;t<16;t++){var h=new Ue;h.set(ke[t],Xe[t],je[t],He[t],0,0),Ve.push(h)}}();var We={E:0,SE:1,S:2,SW:3,W:4,NW:5,N:6,NE:7,MIRROR_VERTICAL:8,MAIN_DIAGONAL:10,MIRROR_HORIZONTAL:12,REVERSE_DIAGONAL:14,uX:function(t){return ke[t]},uY:function(t){return Xe[t]},vX:function(t){return je[t]},vY:function(t){return He[t]},inv:function(t){return 8&t?15&t:7&-t},add:function(t,e){return Ye[t][e]},sub:function(t,e){return Ye[t][We.inv(e)]},rotate180:function(t){return 4^t},isVertical:function(t){return 2==(3&t)},byDirection:function(t,e){return 2*Math.abs(t)<=Math.abs(e)?e>=0?We.S:We.N:2*Math.abs(e)<=Math.abs(t)?t>0?We.E:We.W:e>0?t>0?We.SE:We.SW:t>0?We.NE:We.NW},matrixAppendRotationInv:function(t,e,r,i){void 0===r&&(r=0),void 0===i&&(i=0);var n=Ve[We.inv(e)];n.tx=r,n.ty=i,t.append(n)}},qe=function(){function t(){this.worldTransform=new Ue,this.localTransform=new Ue,this.position=new Ge(this.onChange,this,0,0),this.scale=new Ge(this.onChange,this,1,1),this.pivot=new Ge(this.onChange,this,0,0),this.skew=new Ge(this.updateSkew,this,0,0),this._rotation=0,this._cx=1,this._sx=0,this._cy=0,this._sy=1,this._localID=0,this._currentLocalID=0,this._worldID=0,this._parentID=0}return t.prototype.onChange=function(){this._localID++},t.prototype.updateSkew=function(){this._cx=Math.cos(this._rotation+this.skew.y),this._sx=Math.sin(this._rotation+this.skew.y),this._cy=-Math.sin(this._rotation-this.skew.x),this._sy=Math.cos(this._rotation-this.skew.x),this._localID++},t.prototype.updateLocalTransform=function(){var t=this.localTransform;this._localID!==this._currentLocalID&&(t.a=this._cx*this.scale.x,t.b=this._sx*this.scale.x,t.c=this._cy*this.scale.y,t.d=this._sy*this.scale.y,t.tx=this.position.x-(this.pivot.x*t.a+this.pivot.y*t.c),t.ty=this.position.y-(this.pivot.x*t.b+this.pivot.y*t.d),this._currentLocalID=this._localID,this._parentID=-1)},t.prototype.updateTransform=function(t){var e=this.localTransform;if(this._localID!==this._currentLocalID&&(e.a=this._cx*this.scale.x,e.b=this._sx*this.scale.x,e.c=this._cy*this.scale.y,e.d=this._sy*this.scale.y,e.tx=this.position.x-(this.pivot.x*e.a+this.pivot.y*e.c),e.ty=this.position.y-(this.pivot.x*e.b+this.pivot.y*e.d),this._currentLocalID=this._localID,this._parentID=-1),this._parentID!==t._worldID){var r=t.worldTransform,i=this.worldTransform;i.a=e.a*r.a+e.b*r.c,i.b=e.a*r.b+e.b*r.d,i.c=e.c*r.a+e.d*r.c,i.d=e.c*r.b+e.d*r.d,i.tx=e.tx*r.a+e.ty*r.c+r.tx,i.ty=e.tx*r.b+e.ty*r.d+r.ty,this._parentID=t._worldID,this._worldID++}},t.prototype.setFromMatrix=function(t){t.decompose(this),this._localID++},Object.defineProperty(t.prototype,"rotation",{get:function(){return this._rotation},set:function(t){this._rotation!==t&&(this._rotation=t,this.updateSkew())},enumerable:!1,configurable:!0}),t.IDENTITY=new t,t}();U.SORTABLE_CHILDREN=!1;var Ke=function(){function t(){this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0,this.rect=null,this.updateID=-1}return t.prototype.isEmpty=function(){return this.minX>this.maxX||this.minY>this.maxY},t.prototype.clear=function(){this.minX=1/0,this.minY=1/0,this.maxX=-1/0,this.maxY=-1/0},t.prototype.getRectangle=function(t){return this.minX>this.maxX||this.minY>this.maxY?Ce.EMPTY:((t=t||new Ce(0,0,1,1)).x=this.minX,t.y=this.minY,t.width=this.maxX-this.minX,t.height=this.maxY-this.minY,t)},t.prototype.addPoint=function(t){this.minX=Math.min(this.minX,t.x),this.maxX=Math.max(this.maxX,t.x),this.minY=Math.min(this.minY,t.y),this.maxY=Math.max(this.maxY,t.y)},t.prototype.addPointMatrix=function(t,e){var r=t.a,i=t.b,n=t.c,o=t.d,s=t.tx,a=t.ty,h=r*e.x+n*e.y+s,u=i*e.x+o*e.y+a;this.minX=Math.min(this.minX,h),this.maxX=Math.max(this.maxX,h),this.minY=Math.min(this.minY,u),this.maxY=Math.max(this.maxY,u)},t.prototype.addQuad=function(t){var e=this.minX,r=this.minY,i=this.maxX,n=this.maxY,o=t[0],s=t[1];e=oi?o:i,n=s>n?s:n,e=(o=t[2])i?o:i,n=s>n?s:n,e=(o=t[4])i?o:i,n=s>n?s:n,e=(o=t[6])i?o:i,n=s>n?s:n,this.minX=e,this.minY=r,this.maxX=i,this.maxY=n},t.prototype.addFrame=function(t,e,r,i,n){this.addFrameMatrix(t.worldTransform,e,r,i,n)},t.prototype.addFrameMatrix=function(t,e,r,i,n){var o=t.a,s=t.b,a=t.c,h=t.d,u=t.tx,l=t.ty,c=this.minX,d=this.minY,f=this.maxX,p=this.maxY,_=o*e+a*r+u,v=s*e+h*r+l;c=_f?_:f,p=v>p?v:p,c=(_=o*i+a*r+u)f?_:f,p=v>p?v:p,c=(_=o*e+a*n+u)f?_:f,p=v>p?v:p,c=(_=o*i+a*n+u)f?_:f,p=v>p?v:p,this.minX=c,this.minY=d,this.maxX=f,this.maxY=p},t.prototype.addVertexData=function(t,e,r){for(var i=this.minX,n=this.minY,o=this.maxX,s=this.maxY,a=e;ao?h:o,s=u>s?u:s}this.minX=i,this.minY=n,this.maxX=o,this.maxY=s},t.prototype.addVertices=function(t,e,r,i){this.addVerticesMatrix(t.worldTransform,e,r,i)},t.prototype.addVerticesMatrix=function(t,e,r,i,n,o){void 0===n&&(n=0),void 0===o&&(o=n);for(var s=t.a,a=t.b,h=t.c,u=t.d,l=t.tx,c=t.ty,d=this.minX,f=this.minY,p=this.maxX,_=this.maxY,v=r;vi?t.maxX:i,this.maxY=t.maxY>n?t.maxY:n},t.prototype.addBoundsMask=function(t,e){var r=t.minX>e.minX?t.minX:e.minX,i=t.minY>e.minY?t.minY:e.minY,n=t.maxXh?n:h,this.maxY=o>u?o:u}},t.prototype.addBoundsMatrix=function(t,e){this.addFrameMatrix(e,t.minX,t.minY,t.maxX,t.maxY)},t.prototype.addBoundsArea=function(t,e){var r=t.minX>e.x?t.minX:e.x,i=t.minY>e.y?t.minY:e.y,n=t.maxXh?n:h,this.maxY=o>u?o:u}},t.prototype.pad=function(t,e){void 0===t&&(t=0),void 0===e&&(e=t),this.isEmpty()||(this.minX-=t,this.maxX+=t,this.minY-=e,this.maxY+=e)},t.prototype.addFramePad=function(t,e,r,i,n,o){t-=n,e-=o,r+=n,i+=o,this.minX=this.minXr?this.maxX:r,this.minY=this.minYi?this.maxY:i},t}(),Ze=function(t,e){return Ze=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},Ze(t,e)};function Qe(t,e){function r(){this.constructor=t}Ze(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}var Je=function(t){function e(){var e=t.call(this)||this;return e.tempDisplayObjectParent=null,e.transform=new qe,e.alpha=1,e.visible=!0,e.renderable=!0,e.cullable=!1,e.cullArea=null,e.parent=null,e.worldAlpha=1,e._lastSortedIndex=0,e._zIndex=0,e.filterArea=null,e.filters=null,e._enabledFilters=null,e._bounds=new Ke,e._localBounds=null,e._boundsID=0,e._boundsRect=null,e._localBoundsRect=null,e._mask=null,e._maskRefCount=0,e._destroyed=!1,e.isSprite=!1,e.isMask=!1,e}return Qe(e,t),e.mixin=function(t){for(var r=Object.keys(t),i=0;i1)for(var i=0;ithis.children.length)throw new Error(t+"addChildAt: The index "+e+" supplied is out of bounds "+this.children.length);return t.parent&&t.parent.removeChild(t),t.parent=this,this.sortDirty=!0,t.transform._parentID=-1,this.children.splice(e,0,t),this._boundsID++,this.onChildrenChange(e),t.emit("added",this),this.emit("childAdded",t,this,e),t},r.prototype.swapChildren=function(t,e){if(t!==e){var r=this.getChildIndex(t),i=this.getChildIndex(e);this.children[r]=e,this.children[i]=t,this.onChildrenChange(r=this.children.length)throw new Error("The index "+e+" supplied is out of bounds "+this.children.length);var r=this.getChildIndex(t);fe(this.children,r,1),this.children.splice(e,0,t),this.onChildrenChange(e)},r.prototype.getChildAt=function(t){if(t<0||t>=this.children.length)throw new Error("getChildAt: Index ("+t+") does not exist.");return this.children[t]},r.prototype.removeChild=function(){for(var t=arguments,e=[],r=0;r1)for(var i=0;i0&&n<=e){r=this.children.splice(i,n);for(var o=0;o1&&this.children.sort(tr),this.sortDirty=!1},r.prototype.updateTransform=function(){this.sortableChildren&&this.sortDirty&&this.sortChildren(),this._boundsID++,this.transform.updateTransform(this.parent.transform),this.worldAlpha=this.alpha*this.parent.worldAlpha;for(var t=0,e=this.children.length;t0&&e.height>0){var i,n;if(this.cullArea?(i=this.cullArea,n=this.worldTransform):this._render!==r.prototype._render&&(i=this.getBounds(!0)),i&&e.intersects(i,n))this._render(t);else if(this.cullArea)return;for(var o=0,s=this.children.length;o8)throw new Error("max arguments reached");var h=this,u=h.name,l=h.items;this._aliasCount++;for(var c=0,d=l.length;c0&&this.items.length>1&&(this._aliasCount=0,this.items=this.items.slice(0))},t.prototype.add=function(t){return t[this._name]&&(this.ensureNonAliasedItems(),this.remove(t),this.items.push(t)),this},t.prototype.remove=function(t){var e=this.items.indexOf(t);return-1!==e&&(this.ensureNonAliasedItems(),this.items.splice(e,1)),this},t.prototype.contains=function(t){return-1!==this.items.indexOf(t)},t.prototype.removeAll=function(){return this.ensureNonAliasedItems(),this.items.length=0,this},t.prototype.destroy=function(){this.removeAll(),this.items=null,this._name=null},Object.defineProperty(t.prototype,"empty",{get:function(){return 0===this.items.length},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"name",{get:function(){return this._name},enumerable:!1,configurable:!0}),t}();Object.defineProperties(or.prototype,{dispatch:{value:or.prototype.emit},run:{value:or.prototype.emit}}),t.UPDATE_PRIORITY=void 0,U.TARGET_FPMS=.06,function(t){t[t.INTERACTION=50]="INTERACTION",t[t.HIGH=25]="HIGH",t[t.NORMAL=0]="NORMAL",t[t.LOW=-25]="LOW",t[t.UTILITY=-50]="UTILITY"}(t.UPDATE_PRIORITY||(t.UPDATE_PRIORITY={}));var sr=function(){function t(t,e,r,i){void 0===e&&(e=null),void 0===r&&(r=0),void 0===i&&(i=!1),this.next=null,this.previous=null,this._destroyed=!1,this.fn=t,this.context=e,this.priority=r,this.once=i}return t.prototype.match=function(t,e){return void 0===e&&(e=null),this.fn===t&&this.context===e},t.prototype.emit=function(t){this.fn&&(this.context?this.fn.call(this.context,t):this.fn(t));var e=this.next;return this.once&&this.destroy(!0),this._destroyed&&(this.next=null),e},t.prototype.connect=function(t){this.previous=t,t.next&&(t.next.previous=this),this.next=t.next,t.next=this},t.prototype.destroy=function(t){void 0===t&&(t=!1),this._destroyed=!0,this.fn=null,this.context=null,this.previous&&(this.previous.next=this.next),this.next&&(this.next.previous=this.previous);var e=this.next;return this.next=t?null:e,this.previous=null,e},t}(),ar=function(){function e(){var t=this;this.autoStart=!1,this.deltaTime=1,this.lastTime=-1,this.speed=1,this.started=!1,this._requestId=null,this._maxElapsedMS=100,this._minElapsedMS=0,this._protected=!1,this._lastFrame=-1,this._head=new sr(null,null,1/0),this.deltaMS=1/U.TARGET_FPMS,this.elapsedMS=1/U.TARGET_FPMS,this._tick=function(e){t._requestId=null,t.started&&(t.update(e),t.started&&null===t._requestId&&t._head.next&&(t._requestId=requestAnimationFrame(t._tick)))}}return e.prototype._requestIfNeeded=function(){null===this._requestId&&this._head.next&&(this.lastTime=performance.now(),this._lastFrame=this.lastTime,this._requestId=requestAnimationFrame(this._tick))},e.prototype._cancelIfNeeded=function(){null!==this._requestId&&(cancelAnimationFrame(this._requestId),this._requestId=null)},e.prototype._startIfPossible=function(){this.started?this._requestIfNeeded():this.autoStart&&this.start()},e.prototype.add=function(e,r,i){return void 0===i&&(i=t.UPDATE_PRIORITY.NORMAL),this._addListener(new sr(e,r,i))},e.prototype.addOnce=function(e,r,i){return void 0===i&&(i=t.UPDATE_PRIORITY.NORMAL),this._addListener(new sr(e,r,i,!0))},e.prototype._addListener=function(t){var e=this._head.next,r=this._head;if(e){for(;e;){if(t.priority>e.priority){t.connect(r);break}r=e,e=e.next}t.previous||t.connect(r)}else t.connect(r);return this._startIfPossible(),this},e.prototype.remove=function(t,e){for(var r=this._head.next;r;)r=r.match(t,e)?r.destroy():r.next;return this._head.next||this._cancelIfNeeded(),this},Object.defineProperty(e.prototype,"count",{get:function(){if(!this._head)return 0;for(var t=0,e=this._head;e=e.next;)t++;return t},enumerable:!1,configurable:!0}),e.prototype.start=function(){this.started||(this.started=!0,this._requestIfNeeded())},e.prototype.stop=function(){this.started&&(this.started=!1,this._cancelIfNeeded())},e.prototype.destroy=function(){if(!this._protected){this.stop();for(var t=this._head.next;t;)t=t.destroy(!0);this._head.destroy(),this._head=null}},e.prototype.update=function(t){var e;if(void 0===t&&(t=performance.now()),t>this.lastTime){if((e=this.elapsedMS=t-this.lastTime)>this._maxElapsedMS&&(e=this._maxElapsedMS),e*=this.speed,this._minElapsedMS){var r=t-this._lastFrame|0;if(r=0;--n){var o=ur[n];if(o.test&&o.test(t,r))return new o(t,e)}throw new Error("Unrecognized source type to auto-detect Resource")}var cr=function(t,e){return cr=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},cr(t,e)};function dr(t,e){function r(){this.constructor=t}cr(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}var fr=function(){return fr=Object.assign||function(t){for(var e,r=arguments,i=1,n=arguments.length;i0&&l>0,n.textureCacheIds=[],n.destroyed=!1,n.resource=null,n._batchEnabled=0,n._batchLocation=0,n.parentTextureArray=null,n.setResource(r),n}return dr(r,e),Object.defineProperty(r.prototype,"realWidth",{get:function(){return Math.round(this.width*this.resolution)},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"realHeight",{get:function(){return Math.round(this.height*this.resolution)},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"mipmap",{get:function(){return this._mipmap},set:function(t){this._mipmap!==t&&(this._mipmap=t,this.dirtyStyleId++)},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"scaleMode",{get:function(){return this._scaleMode},set:function(t){this._scaleMode!==t&&(this._scaleMode=t,this.dirtyStyleId++)},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"wrapMode",{get:function(){return this._wrapMode},set:function(t){this._wrapMode!==t&&(this._wrapMode=t,this.dirtyStyleId++)},enumerable:!1,configurable:!0}),r.prototype.setStyle=function(t,e){var r;return void 0!==t&&t!==this.scaleMode&&(this.scaleMode=t,r=!0),void 0!==e&&e!==this.mipmap&&(this.mipmap=e,r=!0),r&&this.dirtyStyleId++,this},r.prototype.setSize=function(t,e,r){return r=r||this.resolution,this.setRealSize(t*r,e*r,r)},r.prototype.setRealSize=function(t,e,r){return this.resolution=r||this.resolution,this.width=Math.round(t)/this.resolution,this.height=Math.round(e)/this.resolution,this._refreshPOT(),this.update(),this},r.prototype._refreshPOT=function(){this.isPowerOfTwo=ce(this.realWidth)&&ce(this.realHeight)},r.prototype.setResolution=function(t){var e=this.resolution;return e===t||(this.resolution=t,this.valid&&(this.width=Math.round(this.width*e)/t,this.height=Math.round(this.height*e)/t,this.emit("update",this)),this._refreshPOT()),this},r.prototype.setResource=function(t){if(this.resource===t)return this;if(this.resource)throw new Error("Resource can be set only once");return t.bind(this),this.resource=t,this},r.prototype.update=function(){this.valid?(this.dirtyId++,this.dirtyStyleId++,this.emit("update",this)):this.width>0&&this.height>0&&(this.valid=!0,this.emit("loaded",this),this.emit("update",this))},r.prototype.onError=function(t){this.emit("error",this,t)},r.prototype.destroy=function(){this.resource&&(this.resource.unbind(this),this.resource.internal&&this.resource.destroy(),this.resource=null),this.cacheId&&(delete Te[this.cacheId],delete ge[this.cacheId],this.cacheId=null),this.dispose(),r.removeFromCache(this),this.textureCacheIds=null,this.destroyed=!0},r.prototype.dispose=function(){this.emit("dispose",this)},r.prototype.castToBaseTexture=function(){return this},r.from=function(t,e,i){void 0===i&&(i=U.STRICT_TEXTURE_CACHE);var n="string"==typeof t,o=null;if(n)o=t;else{if(!t._pixiId){var s=e&&e.pixiIdPrefix||"pixiid";t._pixiId=s+"_"+ve()}o=t._pixiId}var a=Te[o];if(n&&i&&!a)throw new Error('The cacheId "'+o+'" does not exist in BaseTextureCache.');return a||((a=new r(t,e)).cacheId=o,r.addToCache(a,o)),a},r.fromBuffer=function(e,i,n,o){e=e||new Float32Array(i*n*4);var s=new _r(e,{width:i,height:n}),a=e instanceof Float32Array?t.TYPES.FLOAT:t.TYPES.UNSIGNED_BYTE;return new r(s,Object.assign({},vr,o||{width:i,height:n,type:a}))},r.addToCache=function(t,e){e&&(-1===t.textureCacheIds.indexOf(e)&&t.textureCacheIds.push(e),Te[e]&&console.warn("BaseTexture added to the cache with an id ["+e+"] that already had an entry"),Te[e]=t)},r.removeFromCache=function(t){if("string"==typeof t){var e=Te[t];if(e){var r=e.textureCacheIds.indexOf(t);return r>-1&&e.textureCacheIds.splice(r,1),delete Te[t],e}}else if(t&&t.textureCacheIds){for(var i=0;i0){if(!e.resource)throw new Error("CubeResource does not support copying of renderTexture.");this.addResourceAt(e.resource,r)}else e.target=t.TARGETS.TEXTURE_CUBE_MAP_POSITIVE_X+r,e.parentTextureArray=this.baseTexture,this.items[r]=e;return e.valid&&!this.valid&&this.resize(e.realWidth,e.realHeight),this.items[r]=e,this},r.prototype.upload=function(t,e,i){for(var n=this.itemDirtyIds,o=0;o)?\s*()]*-->)?\s*\]*(?:\s(width|height)=('|")(\d*(?:\.\d+)?)(?:px)?('|"))[^>]*(?:\s(width|height)=('|")(\d*(?:\.\d+)?)(?:px)?('|"))[^>]*>/i,e}(Tr),Sr=function(t){function e(r,i){var n=this;if(i=i||{},!(r instanceof HTMLVideoElement)){var o=document.createElement("video");o.setAttribute("preload","auto"),o.setAttribute("webkit-playsinline",""),o.setAttribute("playsinline",""),"string"==typeof r&&(r=[r]);var s=r[0].src||r[0];Tr.crossOrigin(o,s,i.crossorigin);for(var a=0;a2},e.prototype._onPlayStart=function(){this.valid||this._onCanPlay(),this.autoUpdate&&!this._isConnectedToTicker&&(ar.shared.add(this.update,this),this._isConnectedToTicker=!0)},e.prototype._onPlayStop=function(){this._isConnectedToTicker&&(ar.shared.remove(this.update,this),this._isConnectedToTicker=!1)},e.prototype._onCanPlay=function(){var t=this.source;t.removeEventListener("canplay",this._onCanPlay),t.removeEventListener("canplaythrough",this._onCanPlay);var e=this.valid;this.resize(t.videoWidth,t.videoHeight),!e&&this._resolve&&(this._resolve(this),this._resolve=null),this._isSourcePlaying()?this._onPlayStart():this.autoPlay&&t.play()},e.prototype.dispose=function(){this._isConnectedToTicker&&(ar.shared.remove(this.update,this),this._isConnectedToTicker=!1);var e=this.source;e&&(e.removeEventListener("error",this._onError,!0),e.pause(),e.src="",e.load()),t.prototype.dispose.call(this)},Object.defineProperty(e.prototype,"autoUpdate",{get:function(){return this._autoUpdate},set:function(t){t!==this._autoUpdate&&(this._autoUpdate=t,!this._autoUpdate&&this._isConnectedToTicker?(ar.shared.remove(this.update,this),this._isConnectedToTicker=!1):this._autoUpdate&&!this._isConnectedToTicker&&this._isSourcePlaying()&&(ar.shared.add(this.update,this),this._isConnectedToTicker=!0))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"updateFPS",{get:function(){return this._updateFPS},set:function(t){t!==this._updateFPS&&(this._updateFPS=t)},enumerable:!1,configurable:!0}),e.test=function(t,r){return globalThis.HTMLVideoElement&&t instanceof HTMLVideoElement||e.TYPES.indexOf(r)>-1},e.TYPES=["mp4","m4v","webm","ogg","ogv","h264","avi","mov"],e.MIME_TYPES={ogv:"video/ogg",mov:"video/quicktime",m4v:"video/mp4"},e}(Tr),Rr=function(t){function e(e){return t.call(this,e)||this}return dr(e,t),e.test=function(t){return!!globalThis.createImageBitmap&&"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap},e}(Tr);ur.push(xr,Rr,Er,Sr,Ar,_r,br,gr);var Or={__proto__:null,Resource:pr,BaseImageResource:Tr,INSTALLED:ur,autoDetectResource:lr,AbstractMultiResource:yr,ArrayResource:gr,BufferResource:_r,CanvasResource:Er,CubeResource:br,ImageResource:xr,SVGResource:Ar,VideoResource:Sr,ImageBitmapResource:Rr},Mr=function(e){function r(){return null!==e&&e.apply(this,arguments)||this}return dr(r,e),r.prototype.upload=function(e,r,i){var n=e.gl;n.pixelStorei(n.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.alphaMode===t.ALPHA_MODES.UNPACK);var o=r.realWidth,s=r.realHeight;return i.width===o&&i.height===s?n.texSubImage2D(r.target,0,0,0,o,s,r.format,i.type,this.data):(i.width=o,i.height=s,n.texImage2D(r.target,0,i.internalFormat,o,s,0,r.format,i.type,this.data)),!0},r}(_r),Pr=function(){function e(e,r){this.width=Math.round(e||100),this.height=Math.round(r||100),this.stencil=!1,this.depth=!1,this.dirtyId=0,this.dirtyFormat=0,this.dirtySize=0,this.depthTexture=null,this.colorTextures=[],this.glFramebuffers={},this.disposeRunner=new or("disposeFramebuffer"),this.multisample=t.MSAA_QUALITY.NONE}return Object.defineProperty(e.prototype,"colorTexture",{get:function(){return this.colorTextures[0]},enumerable:!1,configurable:!0}),e.prototype.addColorTexture=function(e,r){return void 0===e&&(e=0),this.colorTextures[e]=r||new mr(null,{scaleMode:t.SCALE_MODES.NEAREST,resolution:1,mipmap:t.MIPMAP_MODES.OFF,width:this.width,height:this.height}),this.dirtyId++,this.dirtyFormat++,this},e.prototype.addDepthTexture=function(e){return this.depthTexture=e||new mr(new Mr(null,{width:this.width,height:this.height}),{scaleMode:t.SCALE_MODES.NEAREST,resolution:1,width:this.width,height:this.height,mipmap:t.MIPMAP_MODES.OFF,format:t.FORMATS.DEPTH_COMPONENT,type:t.TYPES.UNSIGNED_SHORT}),this.dirtyId++,this.dirtyFormat++,this},e.prototype.enableDepth=function(){return this.depth=!0,this.dirtyId++,this.dirtyFormat++,this},e.prototype.enableStencil=function(){return this.stencil=!0,this.dirtyId++,this.dirtyFormat++,this},e.prototype.resize=function(t,e){if(t=Math.round(t),e=Math.round(e),t!==this.width||e!==this.height){this.width=t,this.height=e,this.dirtyId++,this.dirtySize++;for(var r=0;r-1&&e.textureCacheIds.splice(r,1),delete ge[t],e}}else if(t&&t.textureCacheIds){for(var i=0;ithis.baseTexture.width,s=r+n>this.baseTexture.height;if(o||s){var a=o&&s?"and":"or",h="X: "+e+" + "+i+" = "+(e+i)+" > "+this.baseTexture.width,u="Y: "+r+" + "+n+" = "+(r+n)+" > "+this.baseTexture.height;throw new Error("Texture Error: frame does not fit inside the base Texture dimensions: "+h+" "+a+" "+u)}this.valid=i&&n&&this.baseTexture.valid,this.trim||this.rotate||(this.orig=t),this.valid&&this.updateUvs()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"rotate",{get:function(){return this._rotate},set:function(t){this._rotate=t,this.valid&&this.updateUvs()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"width",{get:function(){return this.orig.width},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"height",{get:function(){return this.orig.height},enumerable:!1,configurable:!0}),e.prototype.castToBaseTexture=function(){return this.baseTexture},Object.defineProperty(e,"EMPTY",{get:function(){return e._EMPTY||(e._EMPTY=new e(new mr),Cr(e._EMPTY),Cr(e._EMPTY.baseTexture)),e._EMPTY},enumerable:!1,configurable:!0}),Object.defineProperty(e,"WHITE",{get:function(){if(!e._WHITE){var t=U.ADAPTER.createCanvas(16,16),r=t.getContext("2d");t.width=16,t.height=16,r.fillStyle="white",r.fillRect(0,0,16,16),e._WHITE=new e(mr.from(t)),Cr(e._WHITE),Cr(e._WHITE.baseTexture)}return e._WHITE},enumerable:!1,configurable:!0}),e}(j),Fr=function(t){function e(e,r){var i=t.call(this,e,r)||this;return i.valid=!0,i.filterFrame=null,i.filterPoolKey=null,i.updateUvs(),i}return dr(e,t),Object.defineProperty(e.prototype,"framebuffer",{get:function(){return this.baseTexture.framebuffer},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"multisample",{get:function(){return this.framebuffer.multisample},set:function(t){this.framebuffer.multisample=t},enumerable:!1,configurable:!0}),e.prototype.resize=function(t,e,r){void 0===r&&(r=!0);var i=this.baseTexture.resolution,n=Math.round(t*i)/i,o=Math.round(e*i)/i;this.valid=n>0&&o>0,this._frame.width=this.orig.width=n,this._frame.height=this.orig.height=o,r&&this.baseTexture.resize(n,o),this.updateUvs()},e.prototype.setResolution=function(t){var e=this.baseTexture;e.resolution!==t&&(e.setResolution(t),this.resize(e.width,e.height,!1))},e.create=function(t){for(var r=arguments,i=[],n=1;n1?-n:-1:(o=((65535&(e=le(e)))<<16|65535&(r=le(r)))>>>0,n>1&&(o+=4294967296*n)),this.texturePool[o]||(this.texturePool[o]=[]);var s=this.texturePool[o].pop();return s||(s=this.createTexture(e,r,n)),s.filterPoolKey=o,s.setResolution(i),s},e.prototype.getFilterTexture=function(e,r,i){var n=this.getOptimalTexture(e.width,e.height,r||e.resolution,i||t.MSAA_QUALITY.NONE);return n.filterFrame=e.filterFrame,n},e.prototype.returnTexture=function(t){var e=t.filterPoolKey;t.filterFrame=null,this.texturePool[e].push(t)},e.prototype.returnFilterTexture=function(t){this.returnTexture(t)},e.prototype.clear=function(t){if(t=!1!==t)for(var e in this.texturePool){var r=this.texturePool[e];if(r)for(var i=0;i0&&t.height>0,this.texturePool)if(Number(e)<0){var r=this.texturePool[e];if(r)for(var i=0;i1){for(var u=0;u1&&((c=this.getOptimalFilterTexture(l.width,l.height,r.resolution)).filterFrame=l.filterFrame),i[d].apply(this,l,c,t.CLEAR_MODES.CLEAR,r);var f=l;l=c,c=f}i[d].apply(this,l,u.renderTexture,t.CLEAR_MODES.BLEND,r),d>1&&r.multisample>1&&this.returnFilterTexture(r.renderTexture),this.returnFilterTexture(l),this.returnFilterTexture(c)}r.clear(),this.statePool.push(r)},e.prototype.bindAndClear=function(e,r){void 0===r&&(r=t.CLEAR_MODES.CLEAR);var i=this.renderer,n=i.renderTexture,o=i.state;if(e===this.defaultFilterStack[this.defaultFilterStack.length-1].renderTexture?this.renderer.projection.transform=this.activeState.transform:this.renderer.projection.transform=null,e&&e.filterFrame){var s=this.tempRect;s.x=0,s.y=0,s.width=e.filterFrame.width,s.height=e.filterFrame.height,n.bind(e,e.filterFrame,s)}else e!==this.defaultFilterStack[this.defaultFilterStack.length-1].renderTexture?n.bind(e):this.renderer.renderTexture.bind(e,this.activeState.bindingSourceFrame,this.activeState.bindingDestinationFrame);var a=1&o.stateId||this.forceClear;(r===t.CLEAR_MODES.CLEAR||r===t.CLEAR_MODES.BLIT&&a)&&this.renderer.framebuffer.clear(0,0,0,0)},e.prototype.applyFilter=function(e,r,i,n){var o=this.renderer;o.state.set(e.state),this.bindAndClear(i,n),e.uniforms.uSampler=r,e.uniforms.filterGlobals=this.globalUniforms,o.shader.bind(e),e.legacy=!!e.program.attributeData.aTextureCoord,e.legacy?(this.quadUv.map(r._frame,r.filterFrame),o.geometry.bind(this.quadUv),o.geometry.draw(t.DRAW_MODES.TRIANGLES)):(o.geometry.bind(this.quad),o.geometry.draw(t.DRAW_MODES.TRIANGLE_STRIP))},e.prototype.calculateSpriteMatrix=function(t,e){var r=this.activeState,i=r.sourceFrame,n=r.destinationFrame,o=e._texture.orig,s=t.set(n.width,0,0,n.height,i.x,i.y),a=e.worldTransform.copyTo(Ue.TEMP_MATRIX);return a.invert(),s.prepend(a),s.scale(1/o.width,1/o.height),s.translate(e.anchor.x,e.anchor.y),s},e.prototype.destroy=function(){this.renderer=null,this.texturePool.clear(!1)},e.prototype.getOptimalFilterTexture=function(e,r,i,n){return void 0===i&&(i=1),void 0===n&&(n=t.MSAA_QUALITY.NONE),this.texturePool.getOptimalTexture(e,r,i,n)},e.prototype.getFilterTexture=function(e,r,i){if("number"==typeof e){var n=e;e=r,r=n}e=e||this.activeState.renderTexture;var o=this.texturePool.getOptimalTexture(e.width,e.height,r||e.resolution,i||t.MSAA_QUALITY.NONE);return o.filterFrame=e.filterFrame,o},e.prototype.returnFilterTexture=function(t){this.texturePool.returnTexture(t)},e.prototype.emptyPool=function(){this.texturePool.clear(!0)},e.prototype.resize=function(){this.texturePool.setScreenSize(this.renderer.view)},e.prototype.transformAABB=function(t,e){var r=Zr[0],i=Zr[1],n=Zr[2],o=Zr[3];r.set(e.left,e.top),i.set(e.left,e.bottom),n.set(e.right,e.top),o.set(e.right,e.bottom),t.apply(r,r),t.apply(i,i),t.apply(n,n),t.apply(o,o);var s=Math.min(r.x,i.x,n.x,o.x),a=Math.min(r.y,i.y,n.y,o.y),h=Math.max(r.x,i.x,n.x,o.x),u=Math.max(r.y,i.y,n.y,o.y);e.x=s,e.y=a,e.width=h-s,e.height=u-a},e.prototype.roundFrame=function(t,e,r,i,n){if(!(t.width<=0||t.height<=0||r.width<=0||r.height<=0)){if(n){var o=n.a,s=n.b,a=n.c,h=n.d;if((Math.abs(s)>1e-4||Math.abs(a)>1e-4)&&(Math.abs(o)>1e-4||Math.abs(h)>1e-4))return}(n=n?Qr.copyFrom(n):Qr.identity()).translate(-r.x,-r.y).scale(i.width/r.width,i.height/r.height).translate(i.x,i.y),this.transformAABB(n,t),t.ceil(e),this.transformAABB(n.invert(),t)}},e}(),$r=function(){function t(t){this.renderer=t}return t.prototype.flush=function(){},t.prototype.destroy=function(){this.renderer=null},t.prototype.start=function(){},t.prototype.stop=function(){this.flush()},t.prototype.render=function(t){},t}(),ti=function(){function t(t){this.renderer=t,this.emptyRenderer=new $r(t),this.currentRenderer=this.emptyRenderer}return t.prototype.setObjectRenderer=function(t){this.currentRenderer!==t&&(this.currentRenderer.stop(),this.currentRenderer=t,this.currentRenderer.start())},t.prototype.flush=function(){this.setObjectRenderer(this.emptyRenderer)},t.prototype.reset=function(){this.setObjectRenderer(this.emptyRenderer)},t.prototype.copyBoundTextures=function(t,e){for(var r=this.renderer.texture.boundTextures,i=e-1;i>=0;--i)t[i]=r[i]||null,t[i]&&(t[i]._batchLocation=i)},t.prototype.boundArray=function(t,e,r,i){for(var n=t.elements,o=t.ids,s=t.count,a=0,h=0;h=0&&l=t.ENV.WEBGL2&&(i=e.getContext("webgl2",r)),i)this.webGLVersion=2;else if(this.webGLVersion=1,!(i=e.getContext("webgl",r)||e.getContext("experimental-webgl",r)))throw new Error("This browser does not support WebGL. Try using the canvas renderer");return this.gl=i,this.getExtensions(),this.gl},e.prototype.getExtensions=function(){var t=this.gl,e={loseContext:t.getExtension("WEBGL_lose_context"),anisotropicFiltering:t.getExtension("EXT_texture_filter_anisotropic"),floatTextureLinear:t.getExtension("OES_texture_float_linear"),s3tc:t.getExtension("WEBGL_compressed_texture_s3tc"),s3tc_sRGB:t.getExtension("WEBGL_compressed_texture_s3tc_srgb"),etc:t.getExtension("WEBGL_compressed_texture_etc"),etc1:t.getExtension("WEBGL_compressed_texture_etc1"),pvrtc:t.getExtension("WEBGL_compressed_texture_pvrtc")||t.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc"),atc:t.getExtension("WEBGL_compressed_texture_atc"),astc:t.getExtension("WEBGL_compressed_texture_astc")};1===this.webGLVersion?Object.assign(this.extensions,e,{drawBuffers:t.getExtension("WEBGL_draw_buffers"),depthTexture:t.getExtension("WEBGL_depth_texture"),vertexArrayObject:t.getExtension("OES_vertex_array_object")||t.getExtension("MOZ_OES_vertex_array_object")||t.getExtension("WEBKIT_OES_vertex_array_object"),uint32ElementIndex:t.getExtension("OES_element_index_uint"),floatTexture:t.getExtension("OES_texture_float"),floatTextureLinear:t.getExtension("OES_texture_float_linear"),textureHalfFloat:t.getExtension("OES_texture_half_float"),textureHalfFloatLinear:t.getExtension("OES_texture_half_float_linear")}):2===this.webGLVersion&&Object.assign(this.extensions,e,{colorBufferFloat:t.getExtension("EXT_color_buffer_float")})},e.prototype.handleContextLost=function(t){var e=this;t.preventDefault(),setTimeout((function(){e.gl.isContextLost()&&e.extensions.loseContext&&e.extensions.loseContext.restoreContext()}),0)},e.prototype.handleContextRestored=function(){this.renderer.runners.contextChange.emit(this.gl)},e.prototype.destroy=function(){var t=this.renderer.view;this.renderer=null,t.removeEventListener("webglcontextlost",this.handleContextLost),t.removeEventListener("webglcontextrestored",this.handleContextRestored),this.gl.useProgram(null),this.extensions.loseContext&&this.extensions.loseContext.loseContext()},e.prototype.postrender=function(){this.renderer.renderingToScreen&&this.gl.flush()},e.prototype.validateContext=function(t){var e=t.getContextAttributes(),r="WebGL2RenderingContext"in globalThis&&t instanceof globalThis.WebGL2RenderingContext;r&&(this.webGLVersion=2),e&&!e.stencil&&console.warn("Provided WebGL context does not have a stencil buffer, masks may not render correctly");var i=r||!!t.getExtension("OES_element_index_uint");this.supports.uint32Indices=i,i||console.warn("Provided WebGL context does not support 32 index buffer, complex graphics may not render correctly")},e}(),ii=function(e){this.framebuffer=e,this.stencil=null,this.dirtyId=-1,this.dirtyFormat=-1,this.dirtySize=-1,this.multisample=t.MSAA_QUALITY.NONE,this.msaaBuffer=null,this.blitFramebuffer=null,this.mipLevel=0},ni=new Ce,oi=function(){function e(t){this.renderer=t,this.managedFramebuffers=[],this.unknownFramebuffer=new Pr(10,10),this.msaaSamples=null}return e.prototype.contextChange=function(){this.disposeAll(!0);var e=this.gl=this.renderer.gl;if(this.CONTEXT_UID=this.renderer.CONTEXT_UID,this.current=this.unknownFramebuffer,this.viewport=new Ce,this.hasMRT=!0,this.writeDepthTexture=!0,1===this.renderer.context.webGLVersion){var r=this.renderer.context.extensions.drawBuffers,i=this.renderer.context.extensions.depthTexture;U.PREFER_ENV===t.ENV.WEBGL_LEGACY&&(r=null,i=null),r?e.drawBuffers=function(t){return r.drawBuffersWEBGL(t)}:(this.hasMRT=!1,e.drawBuffers=function(){}),i||(this.writeDepthTexture=!1)}else this.msaaSamples=e.getInternalformatParameter(e.RENDERBUFFER,e.RGBA8,e.SAMPLES)},e.prototype.bind=function(t,e,r){void 0===r&&(r=0);var i=this.gl;if(t){var n=t.glFramebuffers[this.CONTEXT_UID]||this.initFramebuffer(t);this.current!==t&&(this.current=t,i.bindFramebuffer(i.FRAMEBUFFER,n.framebuffer)),n.mipLevel!==r&&(t.dirtyId++,t.dirtyFormat++,n.mipLevel=r),n.dirtyId!==t.dirtyId&&(n.dirtyId=t.dirtyId,n.dirtyFormat!==t.dirtyFormat?(n.dirtyFormat=t.dirtyFormat,n.dirtySize=t.dirtySize,this.updateFramebuffer(t,r)):n.dirtySize!==t.dirtySize&&(n.dirtySize=t.dirtySize,this.resizeFramebuffer(t)));for(var o=0;o>r,h=e.height>>r,u=a/e.width;this.setViewport(e.x*u,e.y*u,a,h)}else a=t.width>>r,h=t.height>>r,this.setViewport(0,0,a,h)}else this.current&&(this.current=null,i.bindFramebuffer(i.FRAMEBUFFER,null)),e?this.setViewport(e.x,e.y,e.width,e.height):this.setViewport(0,0,this.renderer.width,this.renderer.height)},e.prototype.setViewport=function(t,e,r,i){var n=this.viewport;t=Math.round(t),e=Math.round(e),r=Math.round(r),i=Math.round(i),n.width===r&&n.height===i&&n.x===t&&n.y===e||(n.x=t,n.y=e,n.width=r,n.height=i,this.gl.viewport(t,e,r,i))},Object.defineProperty(e.prototype,"size",{get:function(){return this.current?{x:0,y:0,width:this.current.width,height:this.current.height}:{x:0,y:0,width:this.renderer.width,height:this.renderer.height}},enumerable:!1,configurable:!0}),e.prototype.clear=function(e,r,i,n,o){void 0===o&&(o=t.BUFFER_BITS.COLOR|t.BUFFER_BITS.DEPTH);var s=this.gl;s.clearColor(e,r,i,n),s.clear(o)},e.prototype.initFramebuffer=function(t){var e=this.gl,r=new ii(e.createFramebuffer());return r.multisample=this.detectSamples(t.multisample),t.glFramebuffers[this.CONTEXT_UID]=r,this.managedFramebuffers.push(t),t.disposeRunner.add(this),r},e.prototype.resizeFramebuffer=function(t){var e=this.gl,r=t.glFramebuffers[this.CONTEXT_UID];r.msaaBuffer&&(e.bindRenderbuffer(e.RENDERBUFFER,r.msaaBuffer),e.renderbufferStorageMultisample(e.RENDERBUFFER,r.multisample,e.RGBA8,t.width,t.height)),r.stencil&&(e.bindRenderbuffer(e.RENDERBUFFER,r.stencil),r.msaaBuffer?e.renderbufferStorageMultisample(e.RENDERBUFFER,r.multisample,e.DEPTH24_STENCIL8,t.width,t.height):e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,t.width,t.height));var i=t.colorTextures,n=i.length;e.drawBuffers||(n=Math.min(n,1));for(var o=0;o1&&this.canMultisampleFramebuffer(t)?(i.msaaBuffer=i.msaaBuffer||r.createRenderbuffer(),r.bindRenderbuffer(r.RENDERBUFFER,i.msaaBuffer),r.renderbufferStorageMultisample(r.RENDERBUFFER,i.multisample,r.RGBA8,t.width,t.height),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.RENDERBUFFER,i.msaaBuffer)):i.msaaBuffer&&(r.deleteRenderbuffer(i.msaaBuffer),i.msaaBuffer=null,i.blitFramebuffer&&(i.blitFramebuffer.dispose(),i.blitFramebuffer=null));for(var s=[],a=0;a1&&r.drawBuffers(s),t.depthTexture&&this.writeDepthTexture){var l=t.depthTexture;this.renderer.texture.bind(l,0),r.framebufferTexture2D(r.FRAMEBUFFER,r.DEPTH_ATTACHMENT,r.TEXTURE_2D,l._glTextures[this.CONTEXT_UID].texture,e)}!t.stencil&&!t.depth||t.depthTexture&&this.writeDepthTexture?i.stencil&&(r.deleteRenderbuffer(i.stencil),i.stencil=null):(i.stencil=i.stencil||r.createRenderbuffer(),r.bindRenderbuffer(r.RENDERBUFFER,i.stencil),i.msaaBuffer?r.renderbufferStorageMultisample(r.RENDERBUFFER,i.multisample,r.DEPTH24_STENCIL8,t.width,t.height):r.renderbufferStorage(r.RENDERBUFFER,r.DEPTH_STENCIL,t.width,t.height),r.framebufferRenderbuffer(r.FRAMEBUFFER,r.DEPTH_STENCIL_ATTACHMENT,r.RENDERBUFFER,i.stencil))},e.prototype.canMultisampleFramebuffer=function(t){return 1!==this.renderer.context.webGLVersion&&t.colorTextures.length<=1&&!t.depthTexture},e.prototype.detectSamples=function(e){var r=this.msaaSamples,i=t.MSAA_QUALITY.NONE;if(e<=1||null===r)return i;for(var n=0;n=0&&this.managedFramebuffers.splice(n,1),t.disposeRunner.remove(this),e||(i.deleteFramebuffer(r.framebuffer),r.msaaBuffer&&i.deleteRenderbuffer(r.msaaBuffer),r.stencil&&i.deleteRenderbuffer(r.stencil)),r.blitFramebuffer&&r.blitFramebuffer.dispose()}},e.prototype.disposeAll=function(t){var e=this.managedFramebuffers;this.managedFramebuffers=[];for(var r=0;r=t.ENV.WEBGL2&&(r=e.getContext("webgl2",{})),r||((r=e.getContext("webgl",{})||e.getContext("experimental-webgl",{}))?r.getExtension("WEBGL_draw_buffers"):r=null),_i=r}return _i}function mi(e,r,i){if("precision"!==e.substring(0,9)){var n=r;return r===t.PRECISION.HIGH&&i!==t.PRECISION.HIGH&&(n=t.PRECISION.MEDIUM),"precision "+n+" float;\n"+e}return i!==t.PRECISION.HIGH&&"precision highp"===e.substring(0,15)?e.replace("precision highp","precision mediump"):e}var yi={float:1,vec2:2,vec3:3,vec4:4,int:1,ivec2:2,ivec3:3,ivec4:4,uint:1,uvec2:2,uvec3:3,uvec4:4,bool:1,bvec2:2,bvec3:3,bvec4:4,mat2:4,mat3:9,mat4:16,sampler2D:1};function gi(t){return yi[t]}var Ti=null,Ei={FLOAT:"float",FLOAT_VEC2:"vec2",FLOAT_VEC3:"vec3",FLOAT_VEC4:"vec4",INT:"int",INT_VEC2:"ivec2",INT_VEC3:"ivec3",INT_VEC4:"ivec4",UNSIGNED_INT:"uint",UNSIGNED_INT_VEC2:"uvec2",UNSIGNED_INT_VEC3:"uvec3",UNSIGNED_INT_VEC4:"uvec4",BOOL:"bool",BOOL_VEC2:"bvec2",BOOL_VEC3:"bvec3",BOOL_VEC4:"bvec4",FLOAT_MAT2:"mat2",FLOAT_MAT3:"mat3",FLOAT_MAT4:"mat4",SAMPLER_2D:"sampler2D",INT_SAMPLER_2D:"sampler2D",UNSIGNED_INT_SAMPLER_2D:"sampler2D",SAMPLER_CUBE:"samplerCube",INT_SAMPLER_CUBE:"samplerCube",UNSIGNED_INT_SAMPLER_CUBE:"samplerCube",SAMPLER_2D_ARRAY:"sampler2DArray",INT_SAMPLER_2D_ARRAY:"sampler2DArray",UNSIGNED_INT_SAMPLER_2D_ARRAY:"sampler2DArray"};function bi(t,e){if(!Ti){var r=Object.keys(Ei);Ti={};for(var i=0;i0&&(e+="\nelse "),r0?this.maskStack[this.maskStack.length-1]._colorMask:15;r!==e&&this.renderer.gl.colorMask(0!=(1&r),0!=(2&r),0!=(4&r),0!=(8&r))},e.prototype.destroy=function(){this.renderer=null},e}(),ki=function(){function t(t){this.renderer=t,this.maskStack=[],this.glConst=0}return t.prototype.getStackLength=function(){return this.maskStack.length},t.prototype.setMaskStack=function(t){var e=this.renderer.gl,r=this.getStackLength();this.maskStack=t;var i=this.getStackLength();i!==r&&(0===i?e.disable(this.glConst):(e.enable(this.glConst),this._useCurrent()))},t.prototype._useCurrent=function(){},t.prototype.destroy=function(){this.renderer=null,this.maskStack=null},t}(),Xi=new Ue,ji=[],Hi=function(t){function e(e){var r=t.call(this,e)||this;return r.glConst=U.ADAPTER.getWebGLRenderingContext().SCISSOR_TEST,r}return dr(e,t),e.prototype.getStackLength=function(){var t=this.maskStack[this.maskStack.length-1];return t?t._scissorCounter:0},e.prototype.calcScissorRect=function(t){var e;if(!t._scissorRectLocal){var r=t._scissorRect,i=t.maskObject,n=this.renderer,o=n.renderTexture,s=i.getBounds(!0,null!==(e=ji.pop())&&void 0!==e?e:new Ce);this.roundFrameToPixels(s,o.current?o.current.resolution:n.resolution,o.sourceFrame,o.destinationFrame,n.projection.transform),r&&s.fit(r),t._scissorRectLocal=s}},e.isMatrixRotated=function(t){if(!t)return!1;var e=t.a,r=t.b,i=t.c,n=t.d;return(Math.abs(r)>1e-4||Math.abs(i)>1e-4)&&(Math.abs(e)>1e-4||Math.abs(n)>1e-4)},e.prototype.testScissor=function(t){var r=t.maskObject;if(!r.isFastRect||!r.isFastRect())return!1;if(e.isMatrixRotated(r.worldTransform))return!1;if(e.isMatrixRotated(this.renderer.projection.transform))return!1;this.calcScissorRect(t);var i=t._scissorRectLocal;return i.width>0&&i.height>0},e.prototype.roundFrameToPixels=function(t,r,i,n,o){e.isMatrixRotated(o)||((o=o?Xi.copyFrom(o):Xi.identity()).translate(-i.x,-i.y).scale(n.width/i.width,n.height/i.height).translate(n.x,n.y),this.renderer.filter.transformAABB(o,t),t.fit(n),t.x=Math.round(t.x*r),t.y=Math.round(t.y*r),t.width=Math.round(t.width*r),t.height=Math.round(t.height*r))},e.prototype.push=function(t){t._scissorRectLocal||this.calcScissorRect(t);var e=this.renderer.gl;t._scissorRect||e.enable(e.SCISSOR_TEST),t._scissorCounter++,t._scissorRect=t._scissorRectLocal,this._useCurrent()},e.prototype.pop=function(t){var e=this.renderer.gl;t&&ji.push(t._scissorRectLocal),this.getStackLength()>0?this._useCurrent():e.disable(e.SCISSOR_TEST)},e.prototype._useCurrent=function(){var t,e=this.maskStack[this.maskStack.length-1]._scissorRect;t=this.renderer.renderTexture.current?e.y:this.renderer.height-e.height-e.y,this.renderer.gl.scissor(e.x,t,e.width,e.height)},e}(ki),Yi=function(t){function e(e){var r=t.call(this,e)||this;return r.glConst=U.ADAPTER.getWebGLRenderingContext().STENCIL_TEST,r}return dr(e,t),e.prototype.getStackLength=function(){var t=this.maskStack[this.maskStack.length-1];return t?t._stencilCounter:0},e.prototype.push=function(t){var e=t.maskObject,r=this.renderer.gl,i=t._stencilCounter;0===i&&(this.renderer.framebuffer.forceStencil(),r.clearStencil(0),r.clear(r.STENCIL_BUFFER_BIT),r.enable(r.STENCIL_TEST)),t._stencilCounter++;var n=t._colorMask;0!==n&&(t._colorMask=0,r.colorMask(!1,!1,!1,!1)),r.stencilFunc(r.EQUAL,i,4294967295),r.stencilOp(r.KEEP,r.KEEP,r.INCR),e.renderable=!0,e.render(this.renderer),this.renderer.batch.flush(),e.renderable=!1,0!==n&&(t._colorMask=n,r.colorMask(0!=(1&n),0!=(2&n),0!=(4&n),0!=(8&n))),this._useCurrent()},e.prototype.pop=function(t){var e=this.renderer.gl;if(0===this.getStackLength())e.disable(e.STENCIL_TEST);else{var r=0!==this.maskStack.length?this.maskStack[this.maskStack.length-1]:null,i=r?r._colorMask:15;0!==i&&(r._colorMask=0,e.colorMask(!1,!1,!1,!1)),e.stencilOp(e.KEEP,e.KEEP,e.DECR),t.renderable=!0,t.render(this.renderer),this.renderer.batch.flush(),t.renderable=!1,0!==i&&(r._colorMask=i,e.colorMask(0!=(1&i),0!=(2&i),0!=(4&i),0!=(8&i))),this._useCurrent()}},e.prototype._useCurrent=function(){var t=this.renderer.gl;t.stencilFunc(t.EQUAL,this.getStackLength(),4294967295),t.stencilOp(t.KEEP,t.KEEP,t.KEEP)},e}(ki),Vi=function(){function t(t){this.renderer=t,this.destinationFrame=null,this.sourceFrame=null,this.defaultFrame=null,this.projectionMatrix=new Ue,this.transform=null}return t.prototype.update=function(t,e,r,i){this.destinationFrame=t||this.destinationFrame||this.defaultFrame,this.sourceFrame=e||this.sourceFrame||t,this.calculateProjection(this.destinationFrame,this.sourceFrame,r,i),this.transform&&this.projectionMatrix.append(this.transform);var n=this.renderer;n.globalUniforms.uniforms.projectionMatrix=this.projectionMatrix,n.globalUniforms.update(),n.shader.shader&&n.shader.syncUniformGroup(n.shader.shader.uniforms.globals)},t.prototype.calculateProjection=function(t,e,r,i){var n=this.projectionMatrix,o=i?-1:1;n.identity(),n.a=1/e.width*2,n.d=o*(1/e.height*2),n.tx=-1-e.x*n.a,n.ty=-o-e.y*n.d},t.prototype.setTransform=function(t){},t.prototype.destroy=function(){this.renderer=null},t}(),zi=new Ce,Wi=new Ce,qi=function(){function t(t){this.renderer=t,this.clearColor=t._backgroundColorRgba,this.defaultMaskStack=[],this.current=null,this.sourceFrame=new Ce,this.destinationFrame=new Ce,this.viewportFrame=new Ce}return t.prototype.bind=function(t,e,r){void 0===t&&(t=null);var i,n,o,s=this.renderer;this.current=t,t?(o=(i=t.baseTexture).resolution,e||(zi.width=t.frame.width,zi.height=t.frame.height,e=zi),r||(Wi.x=t.frame.x,Wi.y=t.frame.y,Wi.width=e.width,Wi.height=e.height,r=Wi),n=i.framebuffer):(o=s.resolution,e||(zi.width=s.screen.width,zi.height=s.screen.height,e=zi),r||((r=zi).width=e.width,r.height=e.height));var a=this.viewportFrame;a.x=r.x*o,a.y=r.y*o,a.width=r.width*o,a.height=r.height*o,t||(a.y=s.view.height-(a.y+a.height)),a.ceil(),this.renderer.framebuffer.bind(n,a),this.renderer.projection.update(r,e,o,!n),t?this.renderer.mask.setMaskStack(i.maskStack):this.renderer.mask.setMaskStack(this.defaultMaskStack),this.sourceFrame.copyFrom(e),this.destinationFrame.copyFrom(r)},t.prototype.clear=function(t,e){t=this.current?t||this.current.baseTexture.clearColor:t||this.clearColor;var r=this.destinationFrame,i=this.current?this.current.baseTexture:this.renderer.screen,n=r.width!==i.width||r.height!==i.height;if(n){var o=this.viewportFrame,s=o.x,a=o.y,h=o.width,u=o.height;s=Math.round(s),a=Math.round(a),h=Math.round(h),u=Math.round(u),this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST),this.renderer.gl.scissor(s,a,h,u)}this.renderer.framebuffer.clear(t[0],t[1],t[2],t[3],e),n&&this.renderer.scissor.pop()},t.prototype.resize=function(){this.bind(null)},t.prototype.reset=function(){this.bind(null)},t.prototype.destroy=function(){this.renderer=null},t}();function Ki(t,e,r,i,n){r.buffer.update(n)}var Zi={float:"\n data[offset] = v;\n ",vec2:"\n data[offset] = v[0];\n data[offset+1] = v[1];\n ",vec3:"\n data[offset] = v[0];\n data[offset+1] = v[1];\n data[offset+2] = v[2];\n\n ",vec4:"\n data[offset] = v[0];\n data[offset+1] = v[1];\n data[offset+2] = v[2];\n data[offset+3] = v[3];\n ",mat2:"\n data[offset] = v[0];\n data[offset+1] = v[1];\n\n data[offset+4] = v[2];\n data[offset+5] = v[3];\n ",mat3:"\n data[offset] = v[0];\n data[offset+1] = v[1];\n data[offset+2] = v[2];\n\n data[offset + 4] = v[3];\n data[offset + 5] = v[4];\n data[offset + 6] = v[5];\n\n data[offset + 8] = v[6];\n data[offset + 9] = v[7];\n data[offset + 10] = v[8];\n ",mat4:"\n for(var i = 0; i < 16; i++)\n {\n data[offset + i] = v[i];\n }\n "},Qi={float:4,vec2:8,vec3:12,vec4:16,int:4,ivec2:8,ivec3:12,ivec4:16,uint:4,uvec2:8,uvec3:12,uvec4:16,bool:4,bvec2:8,bvec3:12,bvec4:16,mat2:32,mat3:48,mat4:64};function Ji(t){for(var e=t.map((function(t){return{data:t,offset:0,dataLen:0,dirty:0}})),r=0,i=0,n=0,o=0;o1&&(r=Math.max(r,16)*s.data.size),s.dataLen=r,i%r!=0&&i<16){var a=i%r%16;i+=a,n+=a}i+r>16?(n=16*Math.ceil(n/16),s.offset=n,n+=r,i=r):(s.offset=n,i+=r,n+=r)}return{uboElements:e,size:n=16*Math.ceil(n/16)}}function $i(t,e){var r=[];for(var i in t)e[i]&&r.push(e[i]);return r.sort((function(t,e){return t.index-e.index})),r}function tn(t,e){if(!t.autoManage)return{size:0,syncFunc:Ki};for(var r=Ji($i(t.uniforms,e)),i=r.uboElements,n=r.size,o=["\n var v = null;\n var v2 = null;\n var cv = null;\n var t = 0;\n var gl = renderer.gl\n var index = 0;\n var data = buffer.data;\n "],s=0;s1){var f=gi(a.data.type),p=Math.max(Qi[a.data.type]/16,1),_=f/p,v=(4-_%4)%4;o.push("\n cv = ud."+u+".value;\n v = uv."+u+";\n offset = "+a.offset/4+";\n\n t = 0;\n\n for(var i=0; i < "+a.data.size*p+"; i++)\n {\n for(var j = 0; j < "+_+"; j++)\n {\n data[offset++] = v[t++];\n }\n offset += "+v+";\n }\n\n ")}else{var m=Zi[a.data.type];o.push("\n cv = ud."+u+".value;\n v = uv."+u+";\n offset = "+a.offset/4+";\n "+m+";\n ")}}return o.push("\n renderer.buffer.update(buffer);\n "),{size:n,syncFunc:new Function("ud","uv","renderer","syncData","buffer",o.join("\n"))}}var en=function(){function t(t,e){this.program=t,this.uniformData=e,this.uniformGroups={},this.uniformDirtyGroups={},this.uniformBufferBindings={}}return t.prototype.destroy=function(){this.uniformData=null,this.uniformGroups=null,this.uniformDirtyGroups=null,this.uniformBufferBindings=null,this.program=null},t}();function rn(t,e){var r=ui(t,t.VERTEX_SHADER,e.vertexSrc),i=ui(t,t.FRAGMENT_SHADER,e.fragmentSrc),n=t.createProgram();if(t.attachShader(n,r),t.attachShader(n,i),t.linkProgram(n),t.getProgramParameter(n,t.LINK_STATUS)||function(t,e,r,i){t.getProgramParameter(e,t.LINK_STATUS)||(t.getShaderParameter(r,t.COMPILE_STATUS)||li(t,r),t.getShaderParameter(i,t.COMPILE_STATUS)||li(t,i),console.error("PixiJS Error: Could not initialize shader."),""!==t.getProgramInfoLog(e)&&console.warn("PixiJS Warning: gl.getProgramInfoLog()",t.getProgramInfoLog(e)))}(t,n,r,i),e.attributeData=function(t,e){for(var r={},i=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;ne?1:-1}));for(var s=0;s>=1,r++;this.stateId=t.data}for(r=0;rthis.checkCountMax&&(this.checkCount=0,this.run())))},e.prototype.run=function(){for(var t=this.renderer.texture,e=t.managedTextures,r=!1,i=0;ithis.maxIdle&&(t.destroyTexture(n,!0),e[i]=null,r=!0)}if(r){var o=0;for(i=0;i=0;i--)this.unload(t.children[i])},e.prototype.destroy=function(){this.renderer=null},e}(),un=function(e){this.texture=e,this.width=-1,this.height=-1,this.dirtyId=-1,this.dirtyStyleId=-1,this.mipmap=!1,this.wrapMode=33071,this.type=t.TYPES.UNSIGNED_BYTE,this.internalFormat=t.FORMATS.RGBA,this.samplerType=0},ln=function(){function e(t){this.renderer=t,this.boundTextures=[],this.currentLocation=-1,this.managedTextures=[],this._unknownBoundTextures=!1,this.unknownTexture=new mr,this.hasIntegerTextures=!1}return e.prototype.contextChange=function(){var e=this.gl=this.renderer.gl;this.CONTEXT_UID=this.renderer.CONTEXT_UID,this.webGLVersion=this.renderer.context.webGLVersion,this.internalFormats=function(e){var r,i,n,o,s,a,h,u,l,c,d,f,p,_,v,m,y,g,T,E,b,x,A;return"WebGL2RenderingContext"in globalThis&&e instanceof globalThis.WebGL2RenderingContext?((r={})[t.TYPES.UNSIGNED_BYTE]=((i={})[t.FORMATS.RGBA]=e.RGBA8,i[t.FORMATS.RGB]=e.RGB8,i[t.FORMATS.RG]=e.RG8,i[t.FORMATS.RED]=e.R8,i[t.FORMATS.RGBA_INTEGER]=e.RGBA8UI,i[t.FORMATS.RGB_INTEGER]=e.RGB8UI,i[t.FORMATS.RG_INTEGER]=e.RG8UI,i[t.FORMATS.RED_INTEGER]=e.R8UI,i[t.FORMATS.ALPHA]=e.ALPHA,i[t.FORMATS.LUMINANCE]=e.LUMINANCE,i[t.FORMATS.LUMINANCE_ALPHA]=e.LUMINANCE_ALPHA,i),r[t.TYPES.BYTE]=((n={})[t.FORMATS.RGBA]=e.RGBA8_SNORM,n[t.FORMATS.RGB]=e.RGB8_SNORM,n[t.FORMATS.RG]=e.RG8_SNORM,n[t.FORMATS.RED]=e.R8_SNORM,n[t.FORMATS.RGBA_INTEGER]=e.RGBA8I,n[t.FORMATS.RGB_INTEGER]=e.RGB8I,n[t.FORMATS.RG_INTEGER]=e.RG8I,n[t.FORMATS.RED_INTEGER]=e.R8I,n),r[t.TYPES.UNSIGNED_SHORT]=((o={})[t.FORMATS.RGBA_INTEGER]=e.RGBA16UI,o[t.FORMATS.RGB_INTEGER]=e.RGB16UI,o[t.FORMATS.RG_INTEGER]=e.RG16UI,o[t.FORMATS.RED_INTEGER]=e.R16UI,o[t.FORMATS.DEPTH_COMPONENT]=e.DEPTH_COMPONENT16,o),r[t.TYPES.SHORT]=((s={})[t.FORMATS.RGBA_INTEGER]=e.RGBA16I,s[t.FORMATS.RGB_INTEGER]=e.RGB16I,s[t.FORMATS.RG_INTEGER]=e.RG16I,s[t.FORMATS.RED_INTEGER]=e.R16I,s),r[t.TYPES.UNSIGNED_INT]=((a={})[t.FORMATS.RGBA_INTEGER]=e.RGBA32UI,a[t.FORMATS.RGB_INTEGER]=e.RGB32UI,a[t.FORMATS.RG_INTEGER]=e.RG32UI,a[t.FORMATS.RED_INTEGER]=e.R32UI,a[t.FORMATS.DEPTH_COMPONENT]=e.DEPTH_COMPONENT24,a),r[t.TYPES.INT]=((h={})[t.FORMATS.RGBA_INTEGER]=e.RGBA32I,h[t.FORMATS.RGB_INTEGER]=e.RGB32I,h[t.FORMATS.RG_INTEGER]=e.RG32I,h[t.FORMATS.RED_INTEGER]=e.R32I,h),r[t.TYPES.FLOAT]=((u={})[t.FORMATS.RGBA]=e.RGBA32F,u[t.FORMATS.RGB]=e.RGB32F,u[t.FORMATS.RG]=e.RG32F,u[t.FORMATS.RED]=e.R32F,u[t.FORMATS.DEPTH_COMPONENT]=e.DEPTH_COMPONENT32F,u),r[t.TYPES.HALF_FLOAT]=((l={})[t.FORMATS.RGBA]=e.RGBA16F,l[t.FORMATS.RGB]=e.RGB16F,l[t.FORMATS.RG]=e.RG16F,l[t.FORMATS.RED]=e.R16F,l),r[t.TYPES.UNSIGNED_SHORT_5_6_5]=((c={})[t.FORMATS.RGB]=e.RGB565,c),r[t.TYPES.UNSIGNED_SHORT_4_4_4_4]=((d={})[t.FORMATS.RGBA]=e.RGBA4,d),r[t.TYPES.UNSIGNED_SHORT_5_5_5_1]=((f={})[t.FORMATS.RGBA]=e.RGB5_A1,f),r[t.TYPES.UNSIGNED_INT_2_10_10_10_REV]=((p={})[t.FORMATS.RGBA]=e.RGB10_A2,p[t.FORMATS.RGBA_INTEGER]=e.RGB10_A2UI,p),r[t.TYPES.UNSIGNED_INT_10F_11F_11F_REV]=((_={})[t.FORMATS.RGB]=e.R11F_G11F_B10F,_),r[t.TYPES.UNSIGNED_INT_5_9_9_9_REV]=((v={})[t.FORMATS.RGB]=e.RGB9_E5,v),r[t.TYPES.UNSIGNED_INT_24_8]=((m={})[t.FORMATS.DEPTH_STENCIL]=e.DEPTH24_STENCIL8,m),r[t.TYPES.FLOAT_32_UNSIGNED_INT_24_8_REV]=((y={})[t.FORMATS.DEPTH_STENCIL]=e.DEPTH32F_STENCIL8,y),A=r):((g={})[t.TYPES.UNSIGNED_BYTE]=((T={})[t.FORMATS.RGBA]=e.RGBA,T[t.FORMATS.RGB]=e.RGB,T[t.FORMATS.ALPHA]=e.ALPHA,T[t.FORMATS.LUMINANCE]=e.LUMINANCE,T[t.FORMATS.LUMINANCE_ALPHA]=e.LUMINANCE_ALPHA,T),g[t.TYPES.UNSIGNED_SHORT_5_6_5]=((E={})[t.FORMATS.RGB]=e.RGB,E),g[t.TYPES.UNSIGNED_SHORT_4_4_4_4]=((b={})[t.FORMATS.RGBA]=e.RGBA,b),g[t.TYPES.UNSIGNED_SHORT_5_5_5_1]=((x={})[t.FORMATS.RGBA]=e.RGBA,x),A=g),A}(e);var r=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS);this.boundTextures.length=r;for(var i=0;i=0;--s){var a=i[s];a&&a._glTextures[o].samplerType!==t.SAMPLER_TYPES.FLOAT&&this.renderer.texture.unbind(a)}},e.prototype.initTexture=function(t){var e=new un(this.gl.createTexture());return e.dirtyId=-1,t._glTextures[this.CONTEXT_UID]=e,this.managedTextures.push(t),t.on("dispose",this.destroyTexture,this),e},e.prototype.initTextureType=function(e,r){var i,n;r.internalFormat=null!==(n=null===(i=this.internalFormats[e.type])||void 0===i?void 0:i[e.format])&&void 0!==n?n:e.format,2===this.webGLVersion&&e.type===t.TYPES.HALF_FLOAT?r.type=this.gl.HALF_FLOAT:r.type=e.type},e.prototype.updateTexture=function(e){var r=e._glTextures[this.CONTEXT_UID];if(r){var i=this.renderer;if(this.initTextureType(e,r),e.resource&&e.resource.upload(i,e,r))r.samplerType!==t.SAMPLER_TYPES.FLOAT&&(this.hasIntegerTextures=!0);else{var n=e.realWidth,o=e.realHeight,s=i.gl;(r.width!==n||r.height!==o||r.dirtyId<0)&&(r.width=n,r.height=o,s.texImage2D(e.target,0,r.internalFormat,n,o,0,e.format,r.type,null))}e.dirtyStyleId!==r.dirtyStyleId&&this.updateTextureStyle(e),r.dirtyId=e.dirtyId}},e.prototype.destroyTexture=function(t,e){var r=this.gl;if((t=t.castToBaseTexture())._glTextures[this.CONTEXT_UID]&&(this.unbind(t),r.deleteTexture(t._glTextures[this.CONTEXT_UID].texture),t.off("dispose",this.destroyTexture,this),delete t._glTextures[this.CONTEXT_UID],!e)){var i=this.managedTextures.indexOf(t);-1!==i&&fe(this.managedTextures,i,1)}},e.prototype.updateTextureStyle=function(e){var r=e._glTextures[this.CONTEXT_UID];r&&(e.mipmap!==t.MIPMAP_MODES.POW2&&2===this.webGLVersion||e.isPowerOfTwo?r.mipmap=e.mipmap>=1:r.mipmap=!1,2===this.webGLVersion||e.isPowerOfTwo?r.wrapMode=e.wrapMode:r.wrapMode=t.WRAP_MODES.CLAMP,e.resource&&e.resource.style(this.renderer,e,r)||this.setStyle(e,r),r.dirtyStyleId=e.dirtyStyleId)},e.prototype.setStyle=function(e,r){var i=this.gl;if(r.mipmap&&e.mipmap!==t.MIPMAP_MODES.ON_MANUAL&&i.generateMipmap(e.target),i.texParameteri(e.target,i.TEXTURE_WRAP_S,r.wrapMode),i.texParameteri(e.target,i.TEXTURE_WRAP_T,r.wrapMode),r.mipmap){i.texParameteri(e.target,i.TEXTURE_MIN_FILTER,e.scaleMode===t.SCALE_MODES.LINEAR?i.LINEAR_MIPMAP_LINEAR:i.NEAREST_MIPMAP_NEAREST);var n=this.renderer.context.extensions.anisotropicFiltering;if(n&&e.anisotropicLevel>0&&e.scaleMode===t.SCALE_MODES.LINEAR){var o=Math.min(e.anisotropicLevel,i.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT));i.texParameterf(e.target,n.TEXTURE_MAX_ANISOTROPY_EXT,o)}}else i.texParameteri(e.target,i.TEXTURE_MIN_FILTER,e.scaleMode===t.SCALE_MODES.LINEAR?i.LINEAR:i.NEAREST);i.texParameteri(e.target,i.TEXTURE_MAG_FILTER,e.scaleMode===t.SCALE_MODES.LINEAR?i.LINEAR:i.NEAREST)},e.prototype.destroy=function(){this.renderer=null},e}(),cn={__proto__:null,FilterSystem:Jr,BatchSystem:ti,ContextSystem:ri,FramebufferSystem:oi,GeometrySystem:ai,MaskSystem:Ui,ScissorSystem:Hi,StencilSystem:Yi,ProjectionSystem:Vi,RenderTextureSystem:qi,ShaderSystem:sn,StateSystem:an,TextureGCSystem:hn,TextureSystem:ln},dn=new Ue,fn=function(e){function r(r,i){void 0===r&&(r=t.RENDERER_TYPE.UNKNOWN);var n=e.call(this)||this;return i=Object.assign({},U.RENDER_OPTIONS,i),n.options=i,n.type=r,n.screen=new Ce(0,0,i.width,i.height),n.view=i.view||U.ADAPTER.createCanvas(),n.resolution=i.resolution||U.RESOLUTION,n.useContextAlpha=i.useContextAlpha,n.autoDensity=!!i.autoDensity,n.preserveDrawingBuffer=i.preserveDrawingBuffer,n.clearBeforeRender=i.clearBeforeRender,n._backgroundColor=0,n._backgroundColorRgba=[0,0,0,1],n._backgroundColorString="#000000",n.backgroundColor=i.backgroundColor||n._backgroundColor,n.backgroundAlpha=i.backgroundAlpha,void 0!==i.transparent&&(n.useContextAlpha=i.transparent,n.backgroundAlpha=i.transparent?0:1),n._lastObjectRendered=null,n.plugins={},n}return dr(r,e),r.prototype.initPlugins=function(t){for(var e in t)this.plugins[e]=new t[e](this)},Object.defineProperty(r.prototype,"width",{get:function(){return this.view.width},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"height",{get:function(){return this.view.height},enumerable:!1,configurable:!0}),r.prototype.resize=function(t,e){this.view.width=Math.round(t*this.resolution),this.view.height=Math.round(e*this.resolution);var r=this.view.width/this.resolution,i=this.view.height/this.resolution;this.screen.width=r,this.screen.height=i,this.autoDensity&&(this.view.style.width=r+"px",this.view.style.height=i+"px"),this.emit("resize",r,i)},r.prototype.generateTexture=function(t,e,r,i){void 0===e&&(e={}),"number"==typeof e&&(e={scaleMode:e,resolution:r,region:i});var n=e.region,o=function(t,e){var r={};for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&e.indexOf(i)<0&&(r[i]=t[i]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(i=Object.getOwnPropertySymbols(t);n=t.data.byteLength)e.bufferSubData(t.type,0,t.data);else{var n=t.static?e.STATIC_DRAW:e.DYNAMIC_DRAW;i.byteLength=t.data.byteLength,e.bufferData(t.type,t.data,n)}},t.prototype.dispose=function(t,e){if(this.managedBuffers[t.id]){delete this.managedBuffers[t.id];var r=t._glBuffers[this.CONTEXT_UID],i=this.gl;t.disposeRunner.remove(this),r&&(e||i.deleteBuffer(r.buffer),delete t._glBuffers[this.CONTEXT_UID])}},t.prototype.disposeAll=function(t){for(var e=Object.keys(this.managedBuffers),r=0;r=t.MSAA_QUALITY.HIGH?this.multisample=t.MSAA_QUALITY.HIGH:e>=t.MSAA_QUALITY.MEDIUM?this.multisample=t.MSAA_QUALITY.MEDIUM:e>=t.MSAA_QUALITY.LOW?this.multisample=t.MSAA_QUALITY.LOW:this.multisample=t.MSAA_QUALITY.NONE},r.prototype.addSystem=function(t,e){var r=new t(this);if(this[e])throw new Error('Whoops! The name "'+e+'" is already in use');for(var i in this[e]=r,this.runners)this.runners[i].add(r);return this},r.prototype.render=function(t,e){var r,i,n,o;if(e&&(e instanceof Fr?(r=e,i=arguments[2],n=arguments[3],o=arguments[4]):(r=e.renderTexture,i=e.clear,n=e.transform,o=e.skipUpdateTransform)),this.renderingToScreen=!r,this.runners.prerender.emit(),this.emit("prerender"),this.projection.transform=n,!this.context.isLost){if(r||(this._lastObjectRendered=t),!o){var s=t.enableTempParent();t.updateTransform(),t.disableTempParent(s)}this.renderTexture.bind(r),this.batch.currentRenderer.start(),(void 0!==i?i:this.clearBeforeRender)&&this.renderTexture.clear(),t.render(this),this.batch.currentRenderer.flush(),r&&r.baseTexture.update(),this.runners.postrender.emit(),this.projection.transform=null,this.emit("postrender")}},r.prototype.generateTexture=function(t,r,i,n){void 0===r&&(r={});var o=e.prototype.generateTexture.call(this,t,r,i,n);return this.framebuffer.blit(),o},r.prototype.resize=function(t,r){e.prototype.resize.call(this,t,r),this.runners.resize.emit(this.screen.height,this.screen.width)},r.prototype.reset=function(){return this.runners.reset.emit(),this},r.prototype.clear=function(){this.renderTexture.bind(),this.renderTexture.clear()},r.prototype.destroy=function(t){for(var r in this.runners.destroy.emit(),this.runners)this.runners[r].destroy();e.prototype.destroy.call(this,t),this.gl=null},Object.defineProperty(r.prototype,"extract",{get:function(){return this.plugins.extract},enumerable:!1,configurable:!0}),r.registerPlugin=function(e,r){nr.add({name:e,type:t.ExtensionType.RendererPlugin,ref:r})},r.__plugins={},r}(fn);function mn(t){return vn.create(t)}nr.handleByMap(t.ExtensionType.RendererPlugin,vn.__plugins);var yn="attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}",gn="attribute vec2 aVertexPosition;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nuniform vec4 inputSize;\nuniform vec4 outputFrame;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;\n\n return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n return aVertexPosition * (outputFrame.zw * inputSize.zw);\n}\n\nvoid main(void)\n{\n gl_Position = filterVertexPosition();\n vTextureCoord = filterTextureCoord();\n}\n",Tn=function(){function t(t){this.renderer=t}return t.prototype.destroy=function(){this.renderer=null},t}(),En=function(){this.texArray=null,this.blend=0,this.type=t.DRAW_MODES.TRIANGLES,this.start=0,this.size=0,this.data=null},bn=function(){function t(){this.elements=[],this.ids=[],this.count=0}return t.prototype.clear=function(){for(var t=0;tthis.size&&this.flush(),this._vertexCount+=t.vertexData.length/2,this._indexCount+=t.indices.length,this._bufferedTextures[this._bufferSize]=t._texture.baseTexture,this._bufferedElements[this._bufferSize++]=t)},r.prototype.buildTexturesAndDrawCalls=function(){var t=this._bufferedTextures,e=this.MAX_TEXTURES,i=r._textureArrayPool,n=this.renderer.batch,o=this._tempBoundTextures,s=this.renderer.textureGC.count,a=++mr._globalBatch,h=0,u=i[0],l=0;n.copyBoundTextures(o,e);for(var c=0;c=e&&(n.boundArray(u,o,a,e),this.buildDrawCalls(u,l,c),l=c,u=i[++h],++a),d._batchEnabled=a,d.touched=s,u.elements[u.count++]=d)}for(u.count>0&&(n.boundArray(u,o,a,e),this.buildDrawCalls(u,l,this._bufferSize),++h,++a),c=0;c0&&(e+="\nelse "),r title : "+t.title+"
tabIndex: "+t.tabIndex},e.prototype.capHitArea=function(t){t.x<0&&(t.width+=t.x,t.x=0),t.y<0&&(t.height+=t.y,t.y=0);var e=this.renderer,r=e.width,i=e.height;t.x+t.width>r&&(t.width=r-t.x),t.y+t.height>i&&(t.height=i-t.y)},e.prototype.addChild=function(t){var e=this.pool.pop();e||((e=document.createElement("button")).style.width="100px",e.style.height="100px",e.style.backgroundColor=this.debug?"rgba(255,255,255,0.5)":"transparent",e.style.position="absolute",e.style.zIndex=2..toString(),e.style.borderStyle="none",navigator.userAgent.toLowerCase().indexOf("chrome")>-1?e.setAttribute("aria-live","off"):e.setAttribute("aria-live","polite"),navigator.userAgent.match(/rv:.*Gecko\//)?e.setAttribute("aria-relevant","additions"):e.setAttribute("aria-relevant","text"),e.addEventListener("click",this._onClick.bind(this)),e.addEventListener("focus",this._onFocus.bind(this)),e.addEventListener("focusout",this._onFocusOut.bind(this))),e.style.pointerEvents=t.accessiblePointerEvents,e.type=t.accessibleType,t.accessibleTitle&&null!==t.accessibleTitle?e.title=t.accessibleTitle:t.accessibleHint&&null!==t.accessibleHint||(e.title="displayObject "+t.tabIndex),t.accessibleHint&&null!==t.accessibleHint&&e.setAttribute("aria-label",t.accessibleHint),this.debug&&this.updateDebugHTML(e),t._accessibleActive=!0,t._accessibleDiv=e,e.displayObject=t,this.children.push(t),this.div.appendChild(t._accessibleDiv),t._accessibleDiv.tabIndex=t.tabIndex},e.prototype._onClick=function(t){var e=this.renderer.plugins.interaction,r=t.target.displayObject,i=e.eventData;e.dispatchEvent(r,"click",i),e.dispatchEvent(r,"pointertap",i),e.dispatchEvent(r,"tap",i)},e.prototype._onFocus=function(t){t.target.getAttribute("aria-live")||t.target.setAttribute("aria-live","assertive");var e=this.renderer.plugins.interaction,r=t.target.displayObject,i=e.eventData;e.dispatchEvent(r,"mouseover",i)},e.prototype._onFocusOut=function(t){t.target.getAttribute("aria-live")||t.target.setAttribute("aria-live","polite");var e=this.renderer.plugins.interaction,r=t.target.displayObject,i=e.eventData;e.dispatchEvent(r,"mouseout",i)},e.prototype._onKeyDown=function(t){9===t.keyCode&&this.activate()},e.prototype._onMouseMove=function(t){0===t.movementX&&0===t.movementY||this.deactivate()},e.prototype.destroy=function(){this.destroyTouchHook(),this.div=null,globalThis.document.removeEventListener("mousemove",this._onMouseMove,!0),globalThis.removeEventListener("keydown",this._onKeyDown),this.pool=null,this.children=null,this.renderer=null},e.extension={name:"accessibility",type:[t.ExtensionType.RendererPlugin,t.ExtensionType.CanvasRendererPlugin]},e}(),Gn=function(){function t(){this.pressure=0,this.rotationAngle=0,this.twist=0,this.tangentialPressure=0,this.global=new De,this.target=null,this.originalEvent=null,this.identifier=null,this.isPrimary=!1,this.button=0,this.buttons=0,this.width=0,this.height=0,this.tiltX=0,this.tiltY=0,this.pointerType=null,this.pressure=0,this.rotationAngle=0,this.twist=0,this.tangentialPressure=0}return Object.defineProperty(t.prototype,"pointerId",{get:function(){return this.identifier},enumerable:!1,configurable:!0}),t.prototype.getLocalPosition=function(t,e,r){return t.worldTransform.applyInverse(r||this.global,e)},t.prototype.copyEvent=function(t){"isPrimary"in t&&t.isPrimary&&(this.isPrimary=!0),this.button="button"in t&&t.button;var e="buttons"in t&&t.buttons;this.buttons=Number.isInteger(e)?e:"which"in t&&t.which,this.width="width"in t&&t.width,this.height="height"in t&&t.height,this.tiltX="tiltX"in t&&t.tiltX,this.tiltY="tiltY"in t&&t.tiltY,this.pointerType="pointerType"in t&&t.pointerType,this.pressure="pressure"in t&&t.pressure,this.rotationAngle="rotationAngle"in t&&t.rotationAngle,this.twist="twist"in t&&t.twist||0,this.tangentialPressure="tangentialPressure"in t&&t.tangentialPressure||0},t.prototype.reset=function(){this.isPrimary=!1},t}(),Un=function(t,e){return Un=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},Un(t,e)},kn=function(){function t(){this.stopped=!1,this.stopsPropagatingAt=null,this.stopPropagationHint=!1,this.target=null,this.currentTarget=null,this.type=null,this.data=null}return t.prototype.stopPropagation=function(){this.stopped=!0,this.stopPropagationHint=!0,this.stopsPropagatingAt=this.currentTarget},t.prototype.reset=function(){this.stopped=!1,this.stopsPropagatingAt=null,this.stopPropagationHint=!1,this.currentTarget=null,this.target=null},t}(),Xn=function(){function t(e){this._pointerId=e,this._flags=t.FLAGS.NONE}return t.prototype._doSet=function(t,e){this._flags=e?this._flags|t:this._flags&~t},Object.defineProperty(t.prototype,"pointerId",{get:function(){return this._pointerId},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"flags",{get:function(){return this._flags},set:function(t){this._flags=t},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"none",{get:function(){return this._flags===t.FLAGS.NONE},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"over",{get:function(){return 0!=(this._flags&t.FLAGS.OVER)},set:function(e){this._doSet(t.FLAGS.OVER,e)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"rightDown",{get:function(){return 0!=(this._flags&t.FLAGS.RIGHT_DOWN)},set:function(e){this._doSet(t.FLAGS.RIGHT_DOWN,e)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"leftDown",{get:function(){return 0!=(this._flags&t.FLAGS.LEFT_DOWN)},set:function(e){this._doSet(t.FLAGS.LEFT_DOWN,e)},enumerable:!1,configurable:!0}),t.FLAGS=Object.freeze({NONE:0,OVER:1,LEFT_DOWN:2,RIGHT_DOWN:4}),t}(),jn=function(){function t(){this._tempPoint=new De}return t.prototype.recursiveFindHit=function(t,e,r,i,n){var o;if(!e||!e.visible)return!1;var s=t.data.global,a=!1,h=n=e.interactive||n,u=!0;if(e.hitArea)i&&(e.worldTransform.applyInverse(s,this._tempPoint),e.hitArea.contains(this._tempPoint.x,this._tempPoint.y)?a=!0:(i=!1,u=!1)),h=!1;else if(e._mask&&i){var l=e._mask.isMaskData?e._mask.maskObject:e._mask;l&&!(null===(o=l.containsPoint)||void 0===o?void 0:o.call(l,s))&&(i=!1)}if(u&&e.interactiveChildren&&e.children)for(var c=e.children,d=c.length-1;d>=0;d--){var f=c[d],p=this.recursiveFindHit(t,f,r,i,h);if(p){if(!f.parent)continue;h=!1,p&&(t.target&&(i=!1),a=!0)}}return n&&(i&&!t.target&&!e.hitArea&&e.containsPoint&&e.containsPoint(s)&&(a=!0),e.interactive&&(a&&!t.target&&(t.target=e),r&&r(t,e,!!a))),a},t.prototype.findHit=function(t,e,r,i){this.recursiveFindHit(t,e,r,i,!1)},t}(),Hn={interactive:!1,interactiveChildren:!0,hitArea:null,get buttonMode(){return"pointer"===this.cursor},set buttonMode(t){t?this.cursor="pointer":"pointer"===this.cursor&&(this.cursor=null)},cursor:null,get trackedPointers(){return void 0===this._trackedPointers&&(this._trackedPointers={}),this._trackedPointers},_trackedPointers:void 0};Je.mixin(Hn);var Yn={target:null,data:{global:null}},Vn=function(e){function r(t,r){var i=e.call(this)||this;return r=r||{},i.renderer=t,i.autoPreventDefault=void 0===r.autoPreventDefault||r.autoPreventDefault,i.interactionFrequency=r.interactionFrequency||10,i.mouse=new Gn,i.mouse.identifier=1,i.mouse.global.set(-999999),i.activeInteractionData={},i.activeInteractionData[1]=i.mouse,i.interactionDataPool=[],i.eventData=new kn,i.interactionDOMElement=null,i.moveWhenInside=!1,i.eventsAdded=!1,i.tickerAdded=!1,i.mouseOverRenderer=!("PointerEvent"in globalThis),i.supportsTouchEvents="ontouchstart"in globalThis,i.supportsPointerEvents=!!globalThis.PointerEvent,i.onPointerUp=i.onPointerUp.bind(i),i.processPointerUp=i.processPointerUp.bind(i),i.onPointerCancel=i.onPointerCancel.bind(i),i.processPointerCancel=i.processPointerCancel.bind(i),i.onPointerDown=i.onPointerDown.bind(i),i.processPointerDown=i.processPointerDown.bind(i),i.onPointerMove=i.onPointerMove.bind(i),i.processPointerMove=i.processPointerMove.bind(i),i.onPointerOut=i.onPointerOut.bind(i),i.processPointerOverOut=i.processPointerOverOut.bind(i),i.onPointerOver=i.onPointerOver.bind(i),i.cursorStyles={default:"inherit",pointer:"pointer"},i.currentCursorMode=null,i.cursor=null,i.resolution=1,i.delayedEvents=[],i.search=new jn,i._tempDisplayObject=new $e,i._eventListenerOptions={capture:!0,passive:!1},i._useSystemTicker=void 0===r.useSystemTicker||r.useSystemTicker,i.setTargetElement(i.renderer.view,i.renderer.resolution),i}return function(t,e){function r(){this.constructor=t}Un(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(r,e),Object.defineProperty(r.prototype,"useSystemTicker",{get:function(){return this._useSystemTicker},set:function(t){this._useSystemTicker=t,t?this.addTickerListener():this.removeTickerListener()},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"lastObjectRendered",{get:function(){return this.renderer._lastObjectRendered||this._tempDisplayObject},enumerable:!1,configurable:!0}),r.prototype.hitTest=function(t,e){return Yn.target=null,Yn.data.global=t,e||(e=this.lastObjectRendered),this.processInteractive(Yn,e,null,!0),Yn.target},r.prototype.setTargetElement=function(t,e){void 0===e&&(e=1),this.removeTickerListener(),this.removeEvents(),this.interactionDOMElement=t,this.resolution=e,this.addEvents(),this.addTickerListener()},r.prototype.addTickerListener=function(){!this.tickerAdded&&this.interactionDOMElement&&this._useSystemTicker&&(ar.system.add(this.tickerUpdate,this,t.UPDATE_PRIORITY.INTERACTION),this.tickerAdded=!0)},r.prototype.removeTickerListener=function(){this.tickerAdded&&(ar.system.remove(this.tickerUpdate,this),this.tickerAdded=!1)},r.prototype.addEvents=function(){if(!this.eventsAdded&&this.interactionDOMElement){var t=this.interactionDOMElement.style;globalThis.navigator.msPointerEnabled?(t.msContentZooming="none",t.msTouchAction="none"):this.supportsPointerEvents&&(t.touchAction="none"),this.supportsPointerEvents?(globalThis.document.addEventListener("pointermove",this.onPointerMove,this._eventListenerOptions),this.interactionDOMElement.addEventListener("pointerdown",this.onPointerDown,this._eventListenerOptions),this.interactionDOMElement.addEventListener("pointerleave",this.onPointerOut,this._eventListenerOptions),this.interactionDOMElement.addEventListener("pointerover",this.onPointerOver,this._eventListenerOptions),globalThis.addEventListener("pointercancel",this.onPointerCancel,this._eventListenerOptions),globalThis.addEventListener("pointerup",this.onPointerUp,this._eventListenerOptions)):(globalThis.document.addEventListener("mousemove",this.onPointerMove,this._eventListenerOptions),this.interactionDOMElement.addEventListener("mousedown",this.onPointerDown,this._eventListenerOptions),this.interactionDOMElement.addEventListener("mouseout",this.onPointerOut,this._eventListenerOptions),this.interactionDOMElement.addEventListener("mouseover",this.onPointerOver,this._eventListenerOptions),globalThis.addEventListener("mouseup",this.onPointerUp,this._eventListenerOptions)),this.supportsTouchEvents&&(this.interactionDOMElement.addEventListener("touchstart",this.onPointerDown,this._eventListenerOptions),this.interactionDOMElement.addEventListener("touchcancel",this.onPointerCancel,this._eventListenerOptions),this.interactionDOMElement.addEventListener("touchend",this.onPointerUp,this._eventListenerOptions),this.interactionDOMElement.addEventListener("touchmove",this.onPointerMove,this._eventListenerOptions)),this.eventsAdded=!0}},r.prototype.removeEvents=function(){if(this.eventsAdded&&this.interactionDOMElement){var t=this.interactionDOMElement.style;globalThis.navigator.msPointerEnabled?(t.msContentZooming="",t.msTouchAction=""):this.supportsPointerEvents&&(t.touchAction=""),this.supportsPointerEvents?(globalThis.document.removeEventListener("pointermove",this.onPointerMove,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("pointerdown",this.onPointerDown,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("pointerleave",this.onPointerOut,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("pointerover",this.onPointerOver,this._eventListenerOptions),globalThis.removeEventListener("pointercancel",this.onPointerCancel,this._eventListenerOptions),globalThis.removeEventListener("pointerup",this.onPointerUp,this._eventListenerOptions)):(globalThis.document.removeEventListener("mousemove",this.onPointerMove,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("mousedown",this.onPointerDown,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("mouseout",this.onPointerOut,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("mouseover",this.onPointerOver,this._eventListenerOptions),globalThis.removeEventListener("mouseup",this.onPointerUp,this._eventListenerOptions)),this.supportsTouchEvents&&(this.interactionDOMElement.removeEventListener("touchstart",this.onPointerDown,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("touchcancel",this.onPointerCancel,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("touchend",this.onPointerUp,this._eventListenerOptions),this.interactionDOMElement.removeEventListener("touchmove",this.onPointerMove,this._eventListenerOptions)),this.interactionDOMElement=null,this.eventsAdded=!1}},r.prototype.tickerUpdate=function(t){this._deltaTime+=t,this._deltaTime0&&(o=t.composedPath()[0]);for(var s=o!==this.interactionDOMElement?"outside":"",a=0;a=2?o.multisample:t.MSAA_QUALITY.NONE;if(n=this.renderer.generateTexture(e,{multisample:h}),h!==t.MSAA_QUALITY.NONE){var u=Fr.create({width:n.width,height:n.height});o.framebuffer.bind(n.framebuffer),o.framebuffer.blit(u.framebuffer),o.framebuffer.bind(null),n.destroy(!0),n=u}a=!0}n?(i=n.baseTexture.resolution,r=null!=r?r:n.frame,s=!1,o.renderTexture.bind(n)):(i=o.resolution,r||((r=zn).width=o.width,r.height=o.height),s=!0,o.renderTexture.bind(null));var l=Math.round(r.width*i),c=Math.round(r.height*i),d=new Uint8Array(4*l*c),f=o.gl;return f.readPixels(Math.round(r.x*i),Math.round(r.y*i),l,c,f.RGBA,f.UNSIGNED_BYTE,d),a&&n.destroy(!0),{pixels:d,width:l,height:c,flipY:s}},e.prototype.destroy=function(){this.renderer=null},e.arrayPostDivide=function(t,e){for(var r=0;r0||e.responseType===t.XHR_RESPONSE_TYPE.BUFFER)?i=200:1223===i&&(i=204),2==(i/100|0)){if(this.xhrType===t.XHR_RESPONSE_TYPE.TEXT)this.data=r,this.type=t.TYPE.TEXT;else if(this.xhrType===t.XHR_RESPONSE_TYPE.JSON)try{this.data=JSON.parse(r),this.type=t.TYPE.JSON}catch(t){return void this.abort("Error trying to parse loaded json: "+t)}else if(this.xhrType===t.XHR_RESPONSE_TYPE.DOCUMENT)try{if(globalThis.DOMParser){var n=new DOMParser;this.data=n.parseFromString(r,"text/xml")}else{var o=document.createElement("div");o.innerHTML=r,this.data=o}this.type=t.TYPE.XML}catch(t){return void this.abort("Error trying to parse loaded xml: "+t)}else this.data=e.response||r;this.complete()}else this.abort("["+e.status+"] "+e.statusText+": "+e.responseURL)},t.prototype._determineCrossOrigin=function(t,e){if(0===t.indexOf("data:"))return"";if(globalThis.origin!==globalThis.location.origin)return"anonymous";e=e||globalThis.location,$n||($n=document.createElement("a")),$n.href=t;var r=Jn($n.href,{strictMode:!0}),i=!r.port&&""===e.port||r.port===e.port,n=r.protocol?r.protocol+":":"";return r.host===e.hostname&&i&&n===e.protocol?"":"anonymous"},t.prototype._determineXhrType=function(){return t._xhrTypeMap[this.extension]||t.XHR_RESPONSE_TYPE.TEXT},t.prototype._determineLoadType=function(){return t._loadTypeMap[this.extension]||t.LOAD_TYPE.XHR},t.prototype._getExtension=function(t){void 0===t&&(t=this.url);var e="";if(this.isDataUrl){var r=t.indexOf("/");e=t.substring(r+1,t.indexOf(";",r))}else{var i=t.indexOf("?"),n=t.indexOf("#"),o=Math.min(i>-1?i:t.length,n>-1?n:t.length);e=(t=t.substring(0,o)).substring(t.lastIndexOf(".")+1)}return e.toLowerCase()},t.prototype._getMimeFromXhrType=function(e){switch(e){case t.XHR_RESPONSE_TYPE.BUFFER:return"application/octet-binary";case t.XHR_RESPONSE_TYPE.BLOB:return"application/blob";case t.XHR_RESPONSE_TYPE.DOCUMENT:return"application/xml";case t.XHR_RESPONSE_TYPE.JSON:return"application/json";case t.XHR_RESPONSE_TYPE.DEFAULT:case t.XHR_RESPONSE_TYPE.TEXT:default:return"text/plain"}},t}(),function(t){var e,r,i,n;(e=t.STATUS_FLAGS||(t.STATUS_FLAGS={}))[e.NONE=0]="NONE",e[e.DATA_URL=1]="DATA_URL",e[e.COMPLETE=2]="COMPLETE",e[e.LOADING=4]="LOADING",(r=t.TYPE||(t.TYPE={}))[r.UNKNOWN=0]="UNKNOWN",r[r.JSON=1]="JSON",r[r.XML=2]="XML",r[r.IMAGE=3]="IMAGE",r[r.AUDIO=4]="AUDIO",r[r.VIDEO=5]="VIDEO",r[r.TEXT=6]="TEXT",(i=t.LOAD_TYPE||(t.LOAD_TYPE={}))[i.XHR=1]="XHR",i[i.IMAGE=2]="IMAGE",i[i.AUDIO=3]="AUDIO",i[i.VIDEO=4]="VIDEO",(n=t.XHR_RESPONSE_TYPE||(t.XHR_RESPONSE_TYPE={})).DEFAULT="text",n.BUFFER="arraybuffer",n.BLOB="blob",n.DOCUMENT="document",n.JSON="json",n.TEXT="text",t._loadTypeMap={gif:t.LOAD_TYPE.IMAGE,png:t.LOAD_TYPE.IMAGE,bmp:t.LOAD_TYPE.IMAGE,jpg:t.LOAD_TYPE.IMAGE,jpeg:t.LOAD_TYPE.IMAGE,tif:t.LOAD_TYPE.IMAGE,tiff:t.LOAD_TYPE.IMAGE,webp:t.LOAD_TYPE.IMAGE,tga:t.LOAD_TYPE.IMAGE,avif:t.LOAD_TYPE.IMAGE,svg:t.LOAD_TYPE.IMAGE,"svg+xml":t.LOAD_TYPE.IMAGE,mp3:t.LOAD_TYPE.AUDIO,ogg:t.LOAD_TYPE.AUDIO,wav:t.LOAD_TYPE.AUDIO,mp4:t.LOAD_TYPE.VIDEO,webm:t.LOAD_TYPE.VIDEO},t._xhrTypeMap={xhtml:t.XHR_RESPONSE_TYPE.DOCUMENT,html:t.XHR_RESPONSE_TYPE.DOCUMENT,htm:t.XHR_RESPONSE_TYPE.DOCUMENT,xml:t.XHR_RESPONSE_TYPE.DOCUMENT,tmx:t.XHR_RESPONSE_TYPE.DOCUMENT,svg:t.XHR_RESPONSE_TYPE.DOCUMENT,tsx:t.XHR_RESPONSE_TYPE.DOCUMENT,gif:t.XHR_RESPONSE_TYPE.BLOB,png:t.XHR_RESPONSE_TYPE.BLOB,bmp:t.XHR_RESPONSE_TYPE.BLOB,jpg:t.XHR_RESPONSE_TYPE.BLOB,jpeg:t.XHR_RESPONSE_TYPE.BLOB,tif:t.XHR_RESPONSE_TYPE.BLOB,tiff:t.XHR_RESPONSE_TYPE.BLOB,webp:t.XHR_RESPONSE_TYPE.BLOB,tga:t.XHR_RESPONSE_TYPE.BLOB,avif:t.XHR_RESPONSE_TYPE.BLOB,json:t.XHR_RESPONSE_TYPE.JSON,text:t.XHR_RESPONSE_TYPE.TEXT,txt:t.XHR_RESPONSE_TYPE.TEXT,ttf:t.XHR_RESPONSE_TYPE.BUFFER,otf:t.XHR_RESPONSE_TYPE.BUFFER},t.EMPTY_GIF="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="}(t.LoaderResource||(t.LoaderResource={}));var oo=function(t,e){this.data=t,this.callback=e},so=function(){function t(t,e){var r=this;if(void 0===e&&(e=1),this.workers=0,this.saturated=io,this.unsaturated=io,this.empty=io,this.drain=io,this.error=io,this.started=!1,this.paused=!1,this._tasks=[],this._insert=function(t,e,i){if(i&&"function"!=typeof i)throw new Error("task callback must be a function");if(r.started=!0,null==t&&r.idle())setTimeout((function(){return r.drain()}),1);else{var n=new oo(t,"function"==typeof i?i:io);e?r._tasks.unshift(n):r._tasks.push(n),setTimeout(r.process,1)}},this.process=function(){for(;!r.paused&&r.workers>2,n[1]=(3&i[0])<<4|i[1]>>4,n[2]=(15&i[1])<<2|i[2]>>6,n[3]=63&i[2],r-(t.length-1)){case 2:n[3]=64,n[2]=64;break;case 1:n[3]=64}for(o=0;o0&&n[n.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!n||o[1]>n[0]&&o[1]=33776&&t<=33779)return"s3tc";if(t>=37488&&t<=37497)return"etc";if(t>=35840&&t<=35843)return"pvrtc";if(t>=36196)return"etc1";if(t>=35986&&t<=34798)return"atc";throw new Error("Invalid (compressed) texture format given!")},e._createLevelBuffers=function(t,e,r,i,n,o,s){for(var a=new Array(r),h=t.byteOffset,u=o,l=s,c=u+i-1&~(i-1),d=l+n-1&~(n-1),f=c*d*_o[e],p=0;p1?u:c,levelHeight:r>1?l:d,levelBuffer:new Uint8Array(t.buffer,h,f)},h+=f,f=(c=(u=u>>1||1)+i-1&~(i-1))*(d=(l=l>>1||1)+n-1&~(n-1))*_o[e];return a},e}(To),bo=function(){function e(){}return e.use=function(r,i){var n=r.data;if(r.type===t.LoaderResource.TYPE.JSON&&n&&n.cacheID&&n.textures){for(var o=n.textures,s=void 0,a=void 0,h=0,u=o.length;h>>=1,E>>>=1;var x=148;for(b=0;b<_;b++)m.push(new Uint8Array(t,x,g)),x+=g}return m.map((function(t){return new Eo(t,{format:v,width:n,height:i,levels:o})}))}if(64&a)throw new Error("DDSParser does not support uncompressed texture data.");if(512&a)throw new Error("DDSParser does not supported YUV uncompressed texture data.");if(131072&a)throw new Error("DDSParser does not support single-channel (lumninance) texture data!");if(2&a)throw new Error("DDSParser does not support single-channel (alpha) texture data!");throw new Error("DDSParser failed to load a texture file due to an unknown reason!")}var wo=[171,75,84,88,32,49,49,187,13,10,26,10],Co=((Ro={})[t.TYPES.UNSIGNED_BYTE]=1,Ro[t.TYPES.UNSIGNED_SHORT]=2,Ro[t.TYPES.INT]=4,Ro[t.TYPES.UNSIGNED_INT]=4,Ro[t.TYPES.FLOAT]=4,Ro[t.TYPES.HALF_FLOAT]=8,Ro),No=((Oo={})[t.FORMATS.RGBA]=4,Oo[t.FORMATS.RGB]=3,Oo[t.FORMATS.RG]=2,Oo[t.FORMATS.RED]=1,Oo[t.FORMATS.LUMINANCE]=1,Oo[t.FORMATS.LUMINANCE_ALPHA]=2,Oo[t.FORMATS.ALPHA]=1,Oo),Fo=((Mo={})[t.TYPES.UNSIGNED_SHORT_4_4_4_4]=2,Mo[t.TYPES.UNSIGNED_SHORT_5_5_5_1]=2,Mo[t.TYPES.UNSIGNED_SHORT_5_6_5]=2,Mo);function Lo(e,r,i){void 0===i&&(i=!1);var n=new DataView(r);if(!function(t,e){for(var r=0;re-n){console.error("KTXLoader: keyAndValueByteSize out of bounds");break}for(var h=0;h1||0!==s?x:S,levelHeight:p>1||0!==s?A:R,levelBuffer:new Uint8Array(r,I,b)},I+=b}O=(O+=P+4)%4!=0?O+4-O%4:O,b=(S=(x=x>>1||1)+4-1&-4)*(R=(A=A>>1||1)+4-1&-4)*v}return 0!==s?{uncompressed:g.map((function(e){var r=e[0].levelBuffer,i=!1;return s===t.TYPES.FLOAT?r=new Float32Array(e[0].levelBuffer.buffer,e[0].levelBuffer.byteOffset,e[0].levelBuffer.byteLength/4):s===t.TYPES.UNSIGNED_INT?(i=!0,r=new Uint32Array(e[0].levelBuffer.buffer,e[0].levelBuffer.byteOffset,e[0].levelBuffer.byteLength/4)):s===t.TYPES.INT&&(i=!0,r=new Int32Array(e[0].levelBuffer.buffer,e[0].levelBuffer.byteOffset,e[0].levelBuffer.byteLength/4)),{resource:new _r(r,{width:e[0].levelWidth,height:e[0].levelHeight}),type:s,format:i?Bo(a):a}})),kvData:E}:{compressed:g.map((function(t){return new Eo(null,{format:h,width:u,height:l,levels:p,levelBuffers:t})})),kvData:E}}function Bo(e){switch(e){case t.FORMATS.RGBA:return t.FORMATS.RGBA_INTEGER;case t.FORMATS.RGB:return t.FORMATS.RGB_INTEGER;case t.FORMATS.RG:return t.FORMATS.RG_INTEGER;case t.FORMATS.RED:return t.FORMATS.RED_INTEGER;default:return e}}t.LoaderResource.setExtensionXhrType("dds",t.LoaderResource.XHR_RESPONSE_TYPE.BUFFER);var Go=function(){function e(){}return e.use=function(t,e){if("dds"===t.extension&&t.data)try{Object.assign(t,xo(t.name||t.url,Do(t.data),t.metadata))}catch(t){return void e(t)}e()},e.extension=t.ExtensionType.Loader,e}();t.LoaderResource.setExtensionXhrType("ktx",t.LoaderResource.XHR_RESPONSE_TYPE.BUFFER);var Uo=function(){function e(){}return e.use=function(e,r){if("ktx"===e.extension&&e.data)try{var i=e.name||e.url,n=Lo(0,e.data,this.loadKeyValueData),o=n.compressed,s=n.uncompressed,a=n.kvData;if(o){var h=xo(i,o,e.metadata);if(a&&h.textures)for(var u in h.textures)h.textures[u].baseTexture.ktxKeyValueData=a;Object.assign(e,h)}else if(s){var l={};s.forEach((function(e,r){var n=new Nr(new mr(e.resource,{mipmap:t.MIPMAP_MODES.OFF,alphaMode:t.ALPHA_MODES.NO_PREMULTIPLIED_ALPHA,type:e.type,format:e.format})),o=i+"-"+(r+1);a&&(n.baseTexture.ktxKeyValueData=a),mr.addToCache(n.baseTexture,o),Nr.addToCache(n,o),0===r&&(l[i]=n,mr.addToCache(n.baseTexture,i),Nr.addToCache(n,i)),l[o]=n})),Object.assign(e,{textures:l})}}catch(t){return void r(t)}r()},e.extension=t.ExtensionType.Loader,e.loadKeyValueData=!1,e}(),ko=function(t,e){return ko=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},ko(t,e)};function Xo(t,e){function r(){this.constructor=t}ko(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}var jo=function(e){function r(r,i,n,o){void 0===r&&(r=1500),void 0===n&&(n=16384),void 0===o&&(o=!1);var s=e.call(this)||this;return n>16384&&(n=16384),s._properties=[!1,!0,!1,!1,!1],s._maxSize=r,s._batchSize=n,s._buffers=null,s._bufferUpdateIDs=[],s._updateID=0,s.interactiveChildren=!1,s.blendMode=t.BLEND_MODES.NORMAL,s.autoResize=o,s.roundPixels=!0,s.baseTexture=null,s.setProperties(i),s._tint=0,s.tintRgb=new Float32Array(4),s.tint=16777215,s}return Xo(r,e),r.prototype.setProperties=function(t){t&&(this._properties[0]="vertices"in t||"scale"in t?!!t.vertices||!!t.scale:this._properties[0],this._properties[1]="position"in t?!!t.position:this._properties[1],this._properties[2]="rotation"in t?!!t.rotation:this._properties[2],this._properties[3]="uvs"in t?!!t.uvs:this._properties[3],this._properties[4]="tint"in t||"alpha"in t?!!t.tint||!!t.alpha:this._properties[4])},r.prototype.updateTransform=function(){this.displayObjectUpdateTransform()},Object.defineProperty(r.prototype,"tint",{get:function(){return this._tint},set:function(t){this._tint=t,$t(t,this.tintRgb)},enumerable:!1,configurable:!0}),r.prototype.render=function(t){var e=this;this.visible&&!(this.worldAlpha<=0)&&this.children.length&&this.renderable&&(this.baseTexture||(this.baseTexture=this.children[0]._texture.baseTexture,this.baseTexture.valid||this.baseTexture.once("update",(function(){return e.onChildrenChange(0)}))),t.batch.setObjectRenderer(t.plugins.particle),t.plugins.particle.render(this))},r.prototype.onChildrenChange=function(t){for(var e=Math.floor(t/this._batchSize);this._bufferUpdateIDs.lengthr&&!t.autoResize&&(o=r);var s=t._buffers;s||(s=t._buffers=this.generateBuffers(t));var a=e[0]._texture.baseTexture,h=a.alphaMode>0;this.state.blendMode=ie(t.blendMode,h),n.state.set(this.state);var u=n.gl,l=t.worldTransform.copyTo(this.tempMatrix);l.prepend(n.globalUniforms.uniforms.projectionMatrix),this.shader.uniforms.translationMatrix=l.toArray(!0),this.shader.uniforms.uColor=ne(t.tintRgb,t.worldAlpha,this.shader.uniforms.uColor,h),this.shader.uniforms.uSampler=a,this.renderer.shader.bind(this.shader);for(var c=!1,d=0,f=0;di&&(p=i),f>=s.length&&s.push(this._generateOneMoreBuffer(t));var _=s[f];_.uploadDynamic(e,d,p);var v=t._bufferUpdateIDs[f]||0;(c=c||_._updateID0,u=a.alpha,l=u<1&&h?oe(a._tintRGB,u):a._tintRGB+(255*u<<24);i[o]=l,i[o+n]=l,i[o+2*n]=l,i[o+3*n]=l,o+=4*n}},r.prototype.destroy=function(){e.prototype.destroy.call(this),this.shader&&(this.shader.destroy(),this.shader=null),this.tempMatrix=null},r.extension={name:"particle",type:t.ExtensionType.RendererPlugin},r}($r);t.LINE_JOIN=void 0,t.LINE_CAP=void 0,function(t){t.MITER="miter",t.BEVEL="bevel",t.ROUND="round"}(t.LINE_JOIN||(t.LINE_JOIN={})),function(t){t.BUTT="butt",t.ROUND="round",t.SQUARE="square"}(t.LINE_CAP||(t.LINE_CAP={}));var Vo={adaptive:!0,maxLength:10,minSegments:8,maxSegments:2048,epsilon:1e-4,_segmentsCount:function(t,e){if(void 0===e&&(e=20),!this.adaptive||!t||isNaN(t))return e;var r=Math.ceil(t/this.maxLength);return rthis.maxSegments&&(r=this.maxSegments),r}},zo=function(){function t(){this.color=16777215,this.alpha=1,this.texture=Nr.WHITE,this.matrix=null,this.visible=!1,this.reset()}return t.prototype.clone=function(){var e=new t;return e.color=this.color,e.alpha=this.alpha,e.texture=this.texture,e.matrix=this.matrix,e.visible=this.visible,e},t.prototype.reset=function(){this.color=16777215,this.alpha=1,this.texture=Nr.WHITE,this.matrix=null,this.visible=!1},t.prototype.destroy=function(){this.texture=null,this.matrix=null},t}(),Wo=function(t,e){return Wo=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},Wo(t,e)};function qo(t,e){function r(){this.constructor=t}Wo(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}function Ko(t,e){var r,i;void 0===e&&(e=!1);var n=t.length;if(!(n<6)){for(var o=0,s=0,a=t[n-2],h=t[n-1];s0||e&&o<=0){var c=n/2;for(s=c+c%2;s=6){Ko(r,!1);for(var s=[],a=0;a=0&&a>=0&&n>=0&&o>=0){var p=Math.ceil(2.3*Math.sqrt(s+a)),_=8*p+(n?4:0)+(o?4:0);if(h.length=_,0!==_){if(0===p)return h.length=8,h[0]=h[6]=r+n,h[1]=h[3]=i+o,h[2]=h[4]=r-n,void(h[5]=h[7]=i-o);var v,m,y=0,g=4*p+(n?2:0)+2,T=g,E=_,b=r+(v=n+s),x=r-v,A=i+(m=o);if(h[y++]=b,h[y++]=A,h[--g]=A,h[--g]=x,o){var S=i-m;h[T++]=x,h[T++]=S,h[--E]=S,h[--E]=b}for(var R=1;Rc&&(c+=2*Math.PI);var d=l,f=c-l,p=Math.abs(f),_=Math.sqrt(h*h+u*u),v=1+(15*p*Math.sqrt(_)/Math.PI>>0),m=f/v;if(d+=m,a){s.push(t,e),s.push(r,i);for(var y=1,g=d;y=0&&(s.join===t.LINE_JOIN.ROUND?_+=is(b,x,b-R*w,x-O*w,b-M*w,x-P*w,f,!1)+4:_+=2,f.push(b-M*C,x-P*C),f.push(b+M*w,x+P*w));else{var j=(-R+T)*(-O+x)-(-R+b)*(-O+E),H=(-M+A)*(-P+x)-(-M+b)*(-P+S),Y=(F*H-B*j)/k,V=(G*j-L*H)/k,z=(Y-b)*(Y-b)+(V-x)*(V-x),W=b+(Y-b)*w,q=x+(V-x)*w,K=b-(Y-b)*C,Z=x-(V-x)*C,Q=X?w:C;z<=Math.min(F*F+L*L,B*B+G*G)+Q*Q*y?s.join===t.LINE_JOIN.BEVEL||z/y>g?(X?(f.push(W,q),f.push(b+R*C,x+O*C),f.push(W,q),f.push(b+M*C,x+P*C)):(f.push(b-R*w,x-O*w),f.push(K,Z),f.push(b-M*w,x-P*w),f.push(K,Z)),_+=2):s.join===t.LINE_JOIN.ROUND?X?(f.push(W,q),f.push(b+R*C,x+O*C),_+=is(b,x,b+R*C,x+O*C,b+M*C,x+P*C,f,!0)+4,f.push(W,q),f.push(b+M*C,x+P*C)):(f.push(b-R*w,x-O*w),f.push(K,Z),_+=is(b,x,b-R*w,x-O*w,b-M*w,x-P*w,f,!1)+4,f.push(b-M*w,x-P*w),f.push(K,Z)):(f.push(W,q),f.push(K,Z)):(f.push(b-R*w,x-O*w),f.push(b+R*C,x+O*C),s.join===t.LINE_JOIN.ROUND?_+=X?is(b,x,b+R*C,x+O*C,b+M*C,x+P*C,f,!0)+2:is(b,x,b-R*w,x-O*w,b-M*w,x-P*w,f,!1)+2:s.join===t.LINE_JOIN.MITER&&z/y<=g&&(X?(f.push(K,Z),f.push(K,Z)):(f.push(W,q),f.push(W,q)),_+=2),f.push(b-M*w,x-P*w),f.push(b+M*C,x+P*C),_+=2)}}T=n[2*(p-2)],E=n[2*(p-2)+1],b=n[2*(p-1)],R=-(E-(x=n[2*(p-1)+1])),O=T-b,R/=I=Math.sqrt(R*R+O*O),O/=I,R*=m,O*=m,f.push(b-R*w,x-O*w),f.push(b+R*C,x+O*C),u||(s.cap===t.LINE_CAP.ROUND?_+=is(b-R*(w-C)*.5,x-O*(w-C)*.5,b-R*w,x-O*w,b+R*C,x+O*C,f,!1)+2:s.cap===t.LINE_CAP.SQUARE&&(_+=rs(b,x,R,O,w,C,!1,f)));var J=r.indices,$=Vo.epsilon*Vo.epsilon;for(N=v;N<_+v-2;++N)T=f[2*N],E=f[2*N+1],b=f[2*(N+1)],x=f[2*(N+1)+1],A=f[2*(N+2)],S=f[2*(N+2)+1],Math.abs(T*(x-S)+b*(S-E)+A*(E-x))<$||J.push(N,N+1,N+2)}}(e,r)}var os,ss=function(){function t(){}return t.curveTo=function(t,e,r,i,n,o){var s=o[o.length-2],a=o[o.length-1]-e,h=s-t,u=i-e,l=r-t,c=Math.abs(a*l-h*u);if(c<1e-8||0===n)return o[o.length-2]===t&&o[o.length-1]===e||o.push(t,e),null;var d=a*a+h*h,f=u*u+l*l,p=a*u+h*l,_=n*Math.sqrt(d)/c,v=n*Math.sqrt(f)/c,m=_*p/d,y=v*p/f,g=_*l+v*h,T=_*u+v*a,E=h*(v+m),b=a*(v+m),x=l*(_+y),A=u*(_+y);return{cx:g+t,cy:T+e,radius:n,startAngle:Math.atan2(b-T,E-g),endAngle:Math.atan2(A-T,x-g),anticlockwise:h*u>l*a}},t.arc=function(t,e,r,i,n,o,s,a,h){for(var u=s-o,l=Vo._segmentsCount(Math.abs(u)*n,40*Math.ceil(Math.abs(u)/Me)),c=u/(2*l),d=2*c,f=Math.cos(c),p=Math.sin(c),_=l-1,v=_%1/_,m=0;m<=_;++m){var y=c+o+d*(m+v*m),g=Math.cos(y),T=-Math.sin(y);h.push((f*g+p*T)*n+r,(f*-T+p*g)*n+i)}},t}(),as=function(){function t(){}return t.curveLength=function(t,e,r,i,n,o,s,a){for(var h=0,u=0,l=0,c=0,d=0,f=0,p=0,_=0,v=0,m=0,y=0,g=t,T=e,E=1;E<=10;++E)m=g-(_=(p=(f=(d=1-(u=E/10))*d)*d)*t+3*f*u*r+3*d*(l=u*u)*n+(c=l*u)*s),y=T-(v=p*e+3*f*u*i+3*d*l*o+c*a),g=_,T=v,h+=Math.sqrt(m*m+y*y);return h},t.curveTo=function(e,r,i,n,o,s,a){var h=a[a.length-2],u=a[a.length-1];a.length-=2;var l=Vo._segmentsCount(t.curveLength(h,u,e,r,i,n,o,s)),c=0,d=0,f=0,p=0,_=0;a.push(h,u);for(var v=1,m=0;v<=l;++v)f=(d=(c=1-(m=v/l))*c)*c,_=(p=m*m)*m,a.push(f*h+3*d*m*e+3*c*p*i+_*o,f*u+3*d*m*r+3*c*p*n+_*s)},t}(),hs=function(){function t(){}return t.curveLength=function(t,e,r,i,n,o){var s=t-2*r+n,a=e-2*i+o,h=2*r-2*t,u=2*i-2*e,l=4*(s*s+a*a),c=4*(s*h+a*u),d=h*h+u*u,f=2*Math.sqrt(l+c+d),p=Math.sqrt(l),_=2*l*p,v=2*Math.sqrt(d),m=c/p;return(_*f+p*c*(f-v)+(4*d*l-c*c)*Math.log((2*p+m+f)/(m+v)))/(4*_)},t.curveTo=function(e,r,i,n,o){for(var s=o[o.length-2],a=o[o.length-1],h=Vo._segmentsCount(t.curveLength(s,a,e,r,i,n)),u=0,l=0,c=1;c<=h;++c){var d=c/h;u=s+(e-s)*d,l=a+(r-a)*d,o.push(u+(e+(i-e)*d-u)*d,l+(r+(n-r)*d-l)*d)}},t}(),us=function(){function t(){this.reset()}return t.prototype.begin=function(t,e,r){this.reset(),this.style=t,this.start=e,this.attribStart=r},t.prototype.end=function(t,e){this.attribSize=e-this.attribStart,this.size=t-this.start},t.prototype.reset=function(){this.style=null,this.size=0,this.start=0,this.attribStart=0,this.attribSize=0},t}(),ls=((os={})[t.SHAPES.POLY]=Zo,os[t.SHAPES.CIRC]=Qo,os[t.SHAPES.ELIP]=Qo,os[t.SHAPES.RECT]=Jo,os[t.SHAPES.RREC]=es,os),cs=[],ds=[],fs=function(){function t(t,e,r,i){void 0===e&&(e=null),void 0===r&&(r=null),void 0===i&&(i=null),this.points=[],this.holes=[],this.shape=t,this.lineStyle=r,this.fillStyle=e,this.matrix=i,this.type=t.type}return t.prototype.clone=function(){return new t(this.shape,this.fillStyle,this.lineStyle,this.matrix)},t.prototype.destroy=function(){this.shape=null,this.holes.length=0,this.holes=null,this.points.length=0,this.points=null,this.lineStyle=null,this.fillStyle=null},t}(),ps=new De,_s=function(e){function r(){var t=e.call(this)||this;return t.closePointEps=1e-4,t.boundsPadding=0,t.uvsFloat32=null,t.indicesUint16=null,t.batchable=!1,t.points=[],t.colors=[],t.uvs=[],t.indices=[],t.textureIds=[],t.graphicsData=[],t.drawCalls=[],t.batchDirty=-1,t.batches=[],t.dirty=0,t.cacheDirty=-1,t.clearDirty=0,t.shapeIndex=0,t._bounds=new Ke,t.boundsDirty=-1,t}return qo(r,e),Object.defineProperty(r.prototype,"bounds",{get:function(){return this.updateBatches(),this.boundsDirty!==this.dirty&&(this.boundsDirty=this.dirty,this.calculateBounds()),this._bounds},enumerable:!1,configurable:!0}),r.prototype.invalidate=function(){this.boundsDirty=-1,this.dirty++,this.batchDirty++,this.shapeIndex=0,this.points.length=0,this.colors.length=0,this.uvs.length=0,this.indices.length=0,this.textureIds.length=0;for(var t=0;t0&&(this.invalidate(),this.clearDirty++,this.graphicsData.length=0),this},r.prototype.drawShape=function(t,e,r,i){void 0===e&&(e=null),void 0===r&&(r=null),void 0===i&&(i=null);var n=new fs(t,e,r,i);return this.graphicsData.push(n),this.dirty++,this},r.prototype.drawHole=function(t,e){if(void 0===e&&(e=null),!this.graphicsData.length)return null;var r=new fs(t,null,null,e),i=this.graphicsData[this.graphicsData.length-1];return r.lineStyle=i.lineStyle,i.holes.push(r),this.dirty++,this},r.prototype.destroy=function(){e.prototype.destroy.call(this);for(var t=0;t0&&(n=(i=this.batches[this.batches.length-1]).style);for(var o=this.shapeIndex;o65535;this.indicesUint16&&this.indices.length===this.indicesUint16.length&&m===this.indicesUint16.BYTES_PER_ELEMENT>2?this.indicesUint16.set(this.indices):this.indicesUint16=m?new Uint32Array(this.indices):new Uint16Array(this.indices),this.batchable=this.isBatchable(),this.batchable?this.packBatches():this.buildDrawCalls()}else this.batchable=!0}}else this.batchable=!0},r.prototype._compareStyles=function(t,e){return!(!t||!e)&&t.texture.baseTexture===e.texture.baseTexture&&t.color+t.alpha===e.color+e.alpha&&!!t.native==!!e.native},r.prototype.validateBatching=function(){if(this.dirty===this.cacheDirty||!this.graphicsData.length)return!1;for(var t=0,e=this.graphicsData.length;t131070)return!1;for(var t=this.batches,e=0;e0&&((o=ds.pop())||((o=new En).texArray=new bn),this.drawCalls.push(o)),o.start=c,o.size=0,o.texArray.count=0,o.type=l),p.touched=1,p._batchEnabled=e,p._batchLocation=s,p.wrapMode=t.WRAP_MODES.REPEAT,o.texArray.elements[o.texArray.count++]=p,s++)),o.size+=d.size,c+=d.size,h=p._batchLocation,this.addColors(i,f.color,f.alpha,d.attribSize,d.attribStart),this.addTextureIds(n,h,d.attribSize,d.attribStart)}mr._globalBatch=e,this.packAttributes()},r.prototype.packAttributes=function(){for(var t=this.points,e=this.uvs,r=this.colors,i=this.textureIds,n=new ArrayBuffer(3*t.length*4),o=new Float32Array(n),s=new Uint32Array(n),a=0,h=0;h>16)+(65280&e)+((255&e)<<16),r);t.length=Math.max(t.length,n+i);for(var s=0;s0&&e.alpha>0;return r?(e.matrix&&(e.matrix=e.matrix.clone(),e.matrix.invert()),Object.assign(this._lineStyle,{visible:r},e)):this._lineStyle.reset(),this},r.prototype.startPoly=function(){if(this.currentPath){var t=this.currentPath.points,e=this.currentPath.points.length;e>2&&(this.drawShape(this.currentPath),this.currentPath=new Le,this.currentPath.closeStroke=!1,this.currentPath.points.push(t[e-2],t[e-1]))}else this.currentPath=new Le,this.currentPath.closeStroke=!1},r.prototype.finishPoly=function(){this.currentPath&&(this.currentPath.points.length>2?(this.drawShape(this.currentPath),this.currentPath=null):this.currentPath.points.length=0)},r.prototype.moveTo=function(t,e){return this.startPoly(),this.currentPath.points[0]=t,this.currentPath.points[1]=e,this},r.prototype.lineTo=function(t,e){this.currentPath||this.moveTo(0,0);var r=this.currentPath.points,i=r[r.length-2],n=r[r.length-1];return i===t&&n===e||r.push(t,e),this},r.prototype._initCurve=function(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this.currentPath?0===this.currentPath.points.length&&(this.currentPath.points=[t,e]):this.moveTo(t,e)},r.prototype.quadraticCurveTo=function(t,e,r,i){this._initCurve();var n=this.currentPath.points;return 0===n.length&&this.moveTo(0,0),hs.curveTo(t,e,r,i,n),this},r.prototype.bezierCurveTo=function(t,e,r,i,n,o){return this._initCurve(),as.curveTo(t,e,r,i,n,o,this.currentPath.points),this},r.prototype.arcTo=function(t,e,r,i,n){this._initCurve(t,e);var o=this.currentPath.points,s=ss.curveTo(t,e,r,i,n,o);if(s){var a=s.cx,h=s.cy,u=s.radius,l=s.startAngle,c=s.endAngle,d=s.anticlockwise;this.arc(a,h,u,l,c,d)}return this},r.prototype.arc=function(t,e,r,i,n,o){if(void 0===o&&(o=!1),i===n)return this;if(!o&&n<=i?n+=Me:o&&i<=n&&(i+=Me),0==n-i)return this;var s=t+Math.cos(i)*r,a=e+Math.sin(i)*r,h=this._geometry.closePointEps,u=this.currentPath?this.currentPath.points:null;if(u){var l=Math.abs(u[u.length-2]-s),c=Math.abs(u[u.length-1]-a);l0;return e?(t.matrix&&(t.matrix=t.matrix.clone(),t.matrix.invert()),Object.assign(this._fillStyle,{visible:e},t)):this._fillStyle.reset(),this},r.prototype.endFill=function(){return this.finishPoly(),this._fillStyle.reset(),this},r.prototype.drawRect=function(t,e,r,i){return this.drawShape(new Ce(t,e,r,i))},r.prototype.drawRoundedRect=function(t,e,r,i,n){return this.drawShape(new Be(t,e,r,i,n))},r.prototype.drawCircle=function(t,e,r){return this.drawShape(new Ne(t,e,r))},r.prototype.drawEllipse=function(t,e,r,i){return this.drawShape(new Fe(t,e,r,i))},r.prototype.drawPolygon=function(){for(var t,e=arguments,r=[],i=0;i>16&255)/255*n,o.tint[1]=(i>>8&255)/255*n,o.tint[2]=(255&i)/255*n,o.tint[3]=n,t.shader.bind(e),t.geometry.bind(r,e),t.state.set(this.state);for(var a=0,h=s.length;a>16)+(65280&n)+((255&n)<<16)}}},r.prototype.calculateVertices=function(){var t=this.transform._worldID;if(this._transformID!==t){this._transformID=t;for(var e=this.transform.worldTransform,r=e.a,i=e.b,n=e.c,o=e.d,s=e.tx,a=e.ty,h=this._geometry.points,u=this.vertexData,l=0,c=0;c=i&&bs.x=n&&bs.y>16)+(65280&t)+((255&t)<<16)},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"texture",{get:function(){return this._texture},set:function(t){this._texture!==t&&(this._texture&&this._texture.off("update",this._onTextureUpdate,this),this._texture=t||Nr.EMPTY,this._cachedTint=16777215,this._textureID=-1,this._textureTrimmedID=-1,t&&(t.baseTexture.valid?this._onTextureUpdate():t.once("update",this._onTextureUpdate,this)))},enumerable:!1,configurable:!0}),r}(er);t.TEXT_GRADIENT=void 0;var Ss=function(t,e){return Ss=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},Ss(t,e)};!function(t){t[t.LINEAR_VERTICAL=0]="LINEAR_VERTICAL",t[t.LINEAR_HORIZONTAL=1]="LINEAR_HORIZONTAL"}(t.TEXT_GRADIENT||(t.TEXT_GRADIENT={}));var Rs={align:"left",breakWords:!1,dropShadow:!1,dropShadowAlpha:1,dropShadowAngle:Math.PI/6,dropShadowBlur:0,dropShadowColor:"black",dropShadowDistance:5,fill:"black",fillGradientType:t.TEXT_GRADIENT.LINEAR_VERTICAL,fillGradientStops:[],fontFamily:"Arial",fontSize:26,fontStyle:"normal",fontVariant:"normal",fontWeight:"normal",letterSpacing:0,lineHeight:0,lineJoin:"miter",miterLimit:10,padding:0,stroke:"black",strokeThickness:0,textBaseline:"alphabetic",trim:!1,whiteSpace:"pre",wordWrap:!1,wordWrapWidth:100,leading:0},Os=["serif","sans-serif","monospace","cursive","fantasy","system-ui"],Ms=function(){function t(t){this.styleID=0,this.reset(),Ds(this,t,t)}return t.prototype.clone=function(){var e={};return Ds(e,this,Rs),new t(e)},t.prototype.reset=function(){Ds(this,Rs,Rs)},Object.defineProperty(t.prototype,"align",{get:function(){return this._align},set:function(t){this._align!==t&&(this._align=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"breakWords",{get:function(){return this._breakWords},set:function(t){this._breakWords!==t&&(this._breakWords=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"dropShadow",{get:function(){return this._dropShadow},set:function(t){this._dropShadow!==t&&(this._dropShadow=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"dropShadowAlpha",{get:function(){return this._dropShadowAlpha},set:function(t){this._dropShadowAlpha!==t&&(this._dropShadowAlpha=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"dropShadowAngle",{get:function(){return this._dropShadowAngle},set:function(t){this._dropShadowAngle!==t&&(this._dropShadowAngle=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"dropShadowBlur",{get:function(){return this._dropShadowBlur},set:function(t){this._dropShadowBlur!==t&&(this._dropShadowBlur=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"dropShadowColor",{get:function(){return this._dropShadowColor},set:function(t){var e=Is(t);this._dropShadowColor!==e&&(this._dropShadowColor=e,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"dropShadowDistance",{get:function(){return this._dropShadowDistance},set:function(t){this._dropShadowDistance!==t&&(this._dropShadowDistance=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"fill",{get:function(){return this._fill},set:function(t){var e=Is(t);this._fill!==e&&(this._fill=e,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"fillGradientType",{get:function(){return this._fillGradientType},set:function(t){this._fillGradientType!==t&&(this._fillGradientType=t,this.styleID++)},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"fillGradientStops",{get:function(){return this._fillGradientStops},set:function(t){(function(t,e){if(!Array.isArray(t)||!Array.isArray(e))return!1;if(t.length!==e.length)return!1;for(var r=0;r=0;r--){var i=e[r].trim();!/([\"\'])[^\'\"]+\1/.test(i)&&Os.indexOf(i)<0&&(i='"'+i+'"'),e[r]=i}return this.fontStyle+" "+this.fontVariant+" "+this.fontWeight+" "+t+" "+e.join(",")},t}();function Ps(t){return"number"==typeof t?te(t):("string"==typeof t&&0===t.indexOf("0x")&&(t=t.replace("0x","#")),t)}function Is(t){if(Array.isArray(t)){for(var e=0;ep)if(""!==s&&(a+=t.addLine(s),s="",o=0),t.canBreakWords(m,r.breakWords))for(var E=t.wordWrapSplit(m),b=0;bp&&(a+=t.addLine(s),f=!1,s="",o=0),s+=x,o+=O}else{s.length>0&&(a+=t.addLine(s),s="",o=0);var M=v===_.length-1;a+=t.addLine(m,!M),f=!1,s="",o=0}else T+o>p&&(f=!1,a+=t.addLine(s),s="",o=0),(s.length>0||!t.isBreakingSpace(m)||f)&&(s+=m,o+=T)}return a+t.addLine(s,!1)},t.addLine=function(e,r){return void 0===r&&(r=!0),e=t.trimRight(e),r?e+"\n":e},t.getFromCache=function(t,e,r,i){var n=r[t];if("number"!=typeof n){var o=t.length*e;n=i.measureText(t).width+o,r[t]=n}return n},t.collapseSpaces=function(t){return"normal"===t||"pre-line"===t},t.collapseNewlines=function(t){return"normal"===t},t.trimRight=function(e){if("string"!=typeof e)return"";for(var r=e.length-1;r>=0;r--){var i=e[r];if(!t.isBreakingSpace(i))break;e=e.slice(0,-1)}return e},t.isNewline=function(e){return"string"==typeof e&&t._newlines.indexOf(e.charCodeAt(0))>=0},t.isBreakingSpace=function(e,r){return"string"==typeof e&&t._breakingSpaces.indexOf(e.charCodeAt(0))>=0},t.tokenize=function(e){var r=[],i="";if("string"!=typeof e)return r;for(var n=0;na;--d){for(_=0;_0&&_>v&&(m=(v+_)/2);var y=v+p,g=i.lineHeight*(f+1),T=y;f+10},t}();function Gs(t,e){var r=!1;if(t&&t._textures&&t._textures.length)for(var i=0;i=0;e--)this.add(t.children[e]);return this},e.prototype.destroy=function(){this.ticking&&ar.system.remove(this.tick,this),this.ticking=!1,this.addHooks=null,this.uploadHooks=null,this.renderer=null,this.completes=null,this.queue=null,this.limiter=null,this.uploadHookHelper=null},e}();function zs(t,e){return e instanceof mr&&(e._glTextures[t.CONTEXT_UID]||t.texture.bind(e),!0)}function Ws(t,e){if(!(e instanceof gs))return!1;var r=e.geometry;e.finishPoly(),r.updateBatches();for(var i=r.batches,n=0;n=i&&ea.x=n&&ea.y1?Ci.from("#version 300 es\n#define SHADER_NAME Tiling-Sprite-300\n\nprecision lowp float;\n\nin vec2 aVertexPosition;\nin vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nuniform mat3 translationMatrix;\nuniform mat3 uTransform;\n\nout vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = (uTransform * vec3(aTextureCoord, 1.0)).xy;\n}\n","#version 300 es\n#define SHADER_NAME Tiling-Sprite-100\n\nprecision lowp float;\n\nin vec2 vTextureCoord;\n\nout vec4 fragmentColor;\n\nuniform sampler2D uSampler;\nuniform vec4 uColor;\nuniform mat3 uMapCoord;\nuniform vec4 uClampFrame;\nuniform vec2 uClampOffset;\n\nvoid main(void)\n{\n vec2 coord = vTextureCoord + ceil(uClampOffset - vTextureCoord);\n coord = (uMapCoord * vec3(coord, 1.0)).xy;\n vec2 unclamped = coord;\n coord = clamp(coord, uClampFrame.xy, uClampFrame.zw);\n\n vec4 texSample = texture(uSampler, coord, unclamped == coord ? 0.0f : -32.0f);// lod-bias very negative to force lod 0\n\n fragmentColor = texSample * uColor;\n}\n",e):Ci.from(ia,"#version 100\n#ifdef GL_EXT_shader_texture_lod\n #extension GL_EXT_shader_texture_lod : enable\n#endif\n#define SHADER_NAME Tiling-Sprite-100\n\nprecision lowp float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform vec4 uColor;\nuniform mat3 uMapCoord;\nuniform vec4 uClampFrame;\nuniform vec2 uClampOffset;\n\nvoid main(void)\n{\n vec2 coord = vTextureCoord + ceil(uClampOffset - vTextureCoord);\n coord = (uMapCoord * vec3(coord, 1.0)).xy;\n vec2 unclamped = coord;\n coord = clamp(coord, uClampFrame.xy, uClampFrame.zw);\n\n #ifdef GL_EXT_shader_texture_lod\n vec4 texSample = unclamped == coord\n ? texture2D(uSampler, coord) \n : texture2DLodEXT(uSampler, coord, 0);\n #else\n vec4 texSample = texture2D(uSampler, coord);\n #endif\n\n gl_FragColor = texSample * uColor;\n}\n",e)},r.prototype.render=function(e){var r=this.renderer,i=this.quad,n=i.vertices;n[0]=n[6]=e._width*-e.anchor.x,n[1]=n[3]=e._height*-e.anchor.y,n[2]=n[4]=e._width*(1-e.anchor.x),n[5]=n[7]=e._height*(1-e.anchor.y);var o=e.uvRespectAnchor?e.anchor.x:0,s=e.uvRespectAnchor?e.anchor.y:0;(n=i.uvs)[0]=n[6]=-o,n[1]=n[3]=-s,n[2]=n[4]=1-o,n[5]=n[7]=1-s,i.invalidate();var a=e._texture,h=a.baseTexture,u=h.alphaMode>0,l=e.tileTransform.localTransform,c=e.uvMatrix,d=h.isPowerOfTwo&&a.frame.width===h.width&&a.frame.height===h.height;d&&(h._glTextures[r.CONTEXT_UID]?d=h.wrapMode!==t.WRAP_MODES.CLAMP:h.wrapMode===t.WRAP_MODES.CLAMP&&(h.wrapMode=t.WRAP_MODES.REPEAT));var f=d?this.simpleShader:this.shader,p=a.width,_=a.height,v=e._width,m=e._height;na.set(l.a*p/v,l.b*p/m,l.c*_/v,l.d*_/m,l.tx/v,l.ty/m),na.invert(),d?na.prepend(c.mapCoord):(f.uniforms.uMapCoord=c.mapCoord.toArray(!0),f.uniforms.uClampFrame=c.uClampFrame,f.uniforms.uClampOffset=c.uClampOffset),f.uniforms.uTransform=na.toArray(!0),f.uniforms.uColor=se(e.tint,e.worldAlpha,f.uniforms.uColor,u),f.uniforms.translationMatrix=e.transform.worldTransform.toArray(!0),f.uniforms.uSampler=a,r.shader.bind(f),r.geometry.bind(i),this.state.blendMode=ie(e.blendMode,u),r.state.set(this.state),r.geometry.draw(this.renderer.gl.TRIANGLES,6,0)},r.extension={name:"tilingSprite",type:t.ExtensionType.RendererPlugin},r}($r),sa=function(t,e){return sa=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},sa(t,e)};function aa(t,e){function r(){this.constructor=t}sa(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}var ha=function(){function t(t,e){this.uvBuffer=t,this.uvMatrix=e,this.data=null,this._bufferUpdateId=-1,this._textureUpdateId=-1,this._updateID=0}return t.prototype.update=function(t){if(t||this._bufferUpdateId!==this.uvBuffer._updateID||this._textureUpdateId!==this.uvMatrix._updateID){this._bufferUpdateId=this.uvBuffer._updateID,this._textureUpdateId=this.uvMatrix._updateID;var e=this.uvBuffer.data;this.data&&this.data.length===e.length||(this.data=new Float32Array(e.length)),this.uvMatrix.multiplyUvs(e,this.data),this._updateID++}},t}(),ua=new De,la=new Le,ca=function(e){function r(r,i,n,o){void 0===o&&(o=t.DRAW_MODES.TRIANGLES);var s=e.call(this)||this;return s.geometry=r,s.shader=i,s.state=n||Ni.for2d(),s.drawMode=o,s.start=0,s.size=0,s.uvs=null,s.indices=null,s.vertexData=new Float32Array(1),s.vertexDirty=-1,s._transformID=-1,s._roundPixels=U.ROUND_PIXELS,s.batchUvs=null,s}return aa(r,e),Object.defineProperty(r.prototype,"geometry",{get:function(){return this._geometry},set:function(t){this._geometry!==t&&(this._geometry&&(this._geometry.refCount--,0===this._geometry.refCount&&this._geometry.dispose()),this._geometry=t,this._geometry&&this._geometry.refCount++,this.vertexDirty=-1)},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"uvBuffer",{get:function(){return this.geometry.buffers[1]},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"verticesBuffer",{get:function(){return this.geometry.buffers[0]},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"material",{get:function(){return this.shader},set:function(t){this.shader=t},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"blendMode",{get:function(){return this.state.blendMode},set:function(t){this.state.blendMode=t},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"roundPixels",{get:function(){return this._roundPixels},set:function(t){this._roundPixels!==t&&(this._transformID=-1),this._roundPixels=t},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"tint",{get:function(){return"tint"in this.shader?this.shader.tint:null},set:function(t){this.shader.tint=t},enumerable:!1,configurable:!0}),Object.defineProperty(r.prototype,"texture",{get:function(){return"texture"in this.shader?this.shader.texture:null},set:function(t){this.shader.texture=t},enumerable:!1,configurable:!0}),r.prototype._render=function(e){var i=this.geometry.buffers[0].data;this.shader.batchable&&this.drawMode===t.DRAW_MODES.TRIANGLES&&i.length<2*r.BATCHABLE_SIZE?this._renderToBatch(e):this._renderDefault(e)},r.prototype._renderDefault=function(t){var e=this.shader;e.alpha=this.worldAlpha,e.update&&e.update(),t.batch.flush(),e.uniforms.translationMatrix=this.transform.worldTransform.toArray(!0),t.shader.bind(e),t.state.set(this.state),t.geometry.bind(this.geometry,e),t.geometry.draw(this.drawMode,this.size,this.start,this.geometry.instanceCount)},r.prototype._renderToBatch=function(t){var e=this.geometry,r=this.shader;r.uvMatrix&&(r.uvMatrix.update(),this.calculateUvs()),this.calculateVertices(),this.indices=e.indexBuffer.data,this._tintRGB=r._tintRGB,this._texture=r.texture;var i=this.material.pluginName;t.batch.setObjectRenderer(t.plugins[i]),t.plugins[i].render(this)},r.prototype.calculateVertices=function(){var t=this.geometry.buffers[0],e=t.data,r=t._updateID;if(r!==this.vertexDirty||this._transformID!==this.transform._worldID){this._transformID=this.transform._worldID,this.vertexData.length!==e.length&&(this.vertexData=new Float32Array(e.length));for(var i=this.transform.worldTransform,n=i.a,o=i.b,s=i.c,a=i.d,h=i.tx,u=i.ty,l=this.vertexData,c=0;c>16)+(65280&t)+((255&t)<<16),this._colorDirty=!0)},enumerable:!1,configurable:!0}),e.prototype.update=function(){if(this._colorDirty){this._colorDirty=!1;var t=this.texture.baseTexture;se(this._tint,this._alpha,this.uniforms.uColor,t.alphaMode)}this.uvMatrix.update()&&(this.uniforms.uTextureMatrix=this.uvMatrix.mapCoord)},e}(Ci),fa=function(e){function r(r,i,n){var o=e.call(this)||this,s=new Ur(r),a=new Ur(i,!0),h=new Ur(n,!0,!0);return o.addAttribute("aVertexPosition",s,2,!1,t.TYPES.FLOAT).addAttribute("aTextureCoord",a,2,!1,t.TYPES.FLOAT).addIndex(h),o._updateId=-1,o}return aa(r,e),Object.defineProperty(r.prototype,"vertexDirtyId",{get:function(){return this.buffers[0]._updateID},enumerable:!1,configurable:!0}),r}(Yr),pa=function(t,e){return pa=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},pa(t,e)},_a=function(){this.info=[],this.common=[],this.page=[],this.char=[],this.kerning=[],this.distanceField=[]},va=function(){function t(){}return t.test=function(t){return"string"==typeof t&&0===t.indexOf("info face=")},t.parse=function(t){var e=t.match(/^[a-z]+\s+.+$/gm),r={info:[],common:[],page:[],char:[],chars:[],kerning:[],kernings:[],distanceField:[]};for(var i in e){var n=e[i].match(/^[a-z]+/gm)[0],o=e[i].match(/[a-zA-Z]+=([^\s"']+|"([^"]*)")/gm),s={};for(var a in o){var h=o[a].split("="),u=h[0],l=h[1].replace(/"/gm,""),c=parseFloat(l),d=isNaN(c)?l:c;s[u]=d}r[n].push(s)}var f=new _a;return r.info.forEach((function(t){return f.info.push({face:t.face,size:parseInt(t.size,10)})})),r.common.forEach((function(t){return f.common.push({lineHeight:parseInt(t.lineHeight,10)})})),r.page.forEach((function(t){return f.page.push({id:parseInt(t.id,10),file:t.file})})),r.char.forEach((function(t){return f.char.push({id:parseInt(t.id,10),page:parseInt(t.page,10),x:parseInt(t.x,10),y:parseInt(t.y,10),width:parseInt(t.width,10),height:parseInt(t.height,10),xoffset:parseInt(t.xoffset,10),yoffset:parseInt(t.yoffset,10),xadvance:parseInt(t.xadvance,10)})})),r.kerning.forEach((function(t){return f.kerning.push({first:parseInt(t.first,10),second:parseInt(t.second,10),amount:parseInt(t.amount,10)})})),r.distanceField.forEach((function(t){return f.distanceField.push({distanceRange:parseInt(t.distanceRange,10),fieldType:t.fieldType})})),f},t}(),ma=function(){function t(){}return t.test=function(t){return t instanceof XMLDocument&&t.getElementsByTagName("page").length&&null!==t.getElementsByTagName("info")[0].getAttribute("face")},t.parse=function(t){for(var e=new _a,r=t.getElementsByTagName("info"),i=t.getElementsByTagName("common"),n=t.getElementsByTagName("page"),o=t.getElementsByTagName("char"),s=t.getElementsByTagName("kerning"),a=t.getElementsByTagName("distanceField"),h=0;h")>-1){var e=(new globalThis.DOMParser).parseFromString(t,"text/xml");return ma.test(e)}return!1},t.parse=function(t){var e=(new globalThis.DOMParser).parseFromString(t,"text/xml");return ma.parse(e)},t}(),ga=[va,ma,ya];function Ta(t){for(var e=0;e=u-S*a){if(0===y)throw new Error("[BitmapFont] textureHeight "+u+"px is too small (fontFamily: '"+c.fontFamily+"', fontSize: "+c.fontSize+"px, char: '"+b+"')");--E,p=null,_=null,v=null,y=0,m=0,g=0}else if(g=Math.max(S+x.fontProperties.descent,g),R*a+m>=d){if(0===m)throw new Error("[BitmapFont] textureWidth "+h+"px is too small (fontFamily: '"+c.fontFamily+"', fontSize: "+c.fontSize+"px, char: '"+b+"')");--E,y+=g*a,y=Math.ceil(y),m=0,g=0}else{Ea(p,_,x,m,y,a,c);var O=xa(x.text);f.char.push({id:O,page:T.length-1,x:m/a,y:y/a,width:R,height:S,xoffset:0,yoffset:0,xadvance:Math.ceil(A-(c.dropShadow?c.dropShadowDistance:0)-(c.stroke?c.strokeThickness:0))}),m+=(R+2*s)*a,m=Math.ceil(m)}}if(!(null==i?void 0:i.skipKerning)){E=0;for(var M=l.length;E0&&o.x>l&&(fe(s,1+v-++y,1+E-v),E=v,v=-1,a.push(m),h.push(s.length>0?s[s.length-1].prevSpaces:0),p=Math.max(p,m),_++,o.x=0,o.y+=r.lineHeight,d=null,T=0)}}else a.push(f),h.push(-1),p=Math.max(p,f),++_,++y,o.x=0,o.y+=r.lineHeight,d=null,T=0}var S=u[u.length-1];"\r"!==S&&"\n"!==S&&(/(?:\s)/.test(S)&&(f=m),a.push(f),p=Math.max(p,f),h.push(-1));var R=[];for(E=0;E<=_;E++){var O=0;"right"===this._align?O=p-a[E]:"center"===this._align?O=(p-a[E])/2:"justify"===this._align&&(O=h[E]<0?0:(p-a[E])/h[E]),R.push(O)}var M=s.length,P={},I=[],D=this._activePagesMeshData;for(c.push.apply(c,D),E=0;E 0.99) {\r\n alpha = 1.0;\r\n }\r\n\r\n // NPM Textures, NPM outputs\r\n gl_FragColor = vec4(uColor.rgb, uColor.a * alpha);\r\n\r\n}\r\n"),uniforms:{uFWidth:0}}),F=t.BLEND_MODES.NORMAL_NPM);var L=new ca(C,N);L.blendMode=F,Q={index:0,indexCount:0,vertexCount:0,uvsCount:0,total:0,mesh:L,vertices:null,uvs:null,indices:null}}Q.index=0,Q.indexCount=0,Q.vertexCount=0,Q.uvsCount=0,Q.total=0;var B=this._textureCache;B[w]=B[w]||new Nr(Y.baseTexture),Q.mesh.texture=B[w],Q.mesh.tint=this._tint,I.push(Q),P[w]=Q}P[w].total++}for(E=0;E6*G)||Q.vertices.length<2*ca.BATCHABLE_SIZE)Q.vertices=new Float32Array(8*G),Q.uvs=new Float32Array(8*G),Q.indices=new Uint16Array(6*G);else for(var U=Q.total,k=Q.vertices,X=4*U*2;X=i&&(e=t-s-1),o+=a=a.replace("%value%",r[e].toString()),o+="\n"}return(n=n.replace("%blur%",o)).replace("%size%",t.toString())}(o);return(s=e.call(this,a,h)||this).horizontal=t,s.resolution=n,s._quality=0,s.quality=i,s.blur=r,s}return Ca(r,e),r.prototype.apply=function(e,r,i,n){if(i?this.horizontal?this.uniforms.strength=1/i.width*(i.width/r.width):this.uniforms.strength=1/i.height*(i.height/r.height):this.horizontal?this.uniforms.strength=1/e.renderer.width*(e.renderer.width/r.width):this.uniforms.strength=1/e.renderer.height*(e.renderer.height/r.height),this.uniforms.strength*=this.strength,this.uniforms.strength/=this.passes,1===this.passes)e.applyFilter(this,r,i,n);else{var o=e.getFilterTexture(),s=e.renderer,a=r,h=o;this.state.blend=!1,e.applyFilter(this,a,h,t.CLEAR_MODES.CLEAR);for(var u=1;u 0.0) {\n c.rgb /= c.a;\n }\n\n vec4 result;\n\n result.r = (m[0] * c.r);\n result.r += (m[1] * c.g);\n result.r += (m[2] * c.b);\n result.r += (m[3] * c.a);\n result.r += m[4];\n\n result.g = (m[5] * c.r);\n result.g += (m[6] * c.g);\n result.g += (m[7] * c.b);\n result.g += (m[8] * c.a);\n result.g += m[9];\n\n result.b = (m[10] * c.r);\n result.b += (m[11] * c.g);\n result.b += (m[12] * c.b);\n result.b += (m[13] * c.a);\n result.b += m[14];\n\n result.a = (m[15] * c.r);\n result.a += (m[16] * c.g);\n result.a += (m[17] * c.b);\n result.a += (m[18] * c.a);\n result.a += m[19];\n\n vec3 rgb = mix(c.rgb, result.rgb, uAlpha);\n\n // Premultiply alpha again.\n rgb *= result.a;\n\n gl_FragColor = vec4(rgb, result.a);\n}\n",r)||this).alpha=1,e}return function(t,e){function r(){this.constructor=t}Ga(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(e,t),e.prototype._loadMatrix=function(t,e){void 0===e&&(e=!1);var r=t;e&&(this._multiply(r,this.uniforms.m,t),r=this._colorMatrix(r)),this.uniforms.m=r},e.prototype._multiply=function(t,e,r){return t[0]=e[0]*r[0]+e[1]*r[5]+e[2]*r[10]+e[3]*r[15],t[1]=e[0]*r[1]+e[1]*r[6]+e[2]*r[11]+e[3]*r[16],t[2]=e[0]*r[2]+e[1]*r[7]+e[2]*r[12]+e[3]*r[17],t[3]=e[0]*r[3]+e[1]*r[8]+e[2]*r[13]+e[3]*r[18],t[4]=e[0]*r[4]+e[1]*r[9]+e[2]*r[14]+e[3]*r[19]+e[4],t[5]=e[5]*r[0]+e[6]*r[5]+e[7]*r[10]+e[8]*r[15],t[6]=e[5]*r[1]+e[6]*r[6]+e[7]*r[11]+e[8]*r[16],t[7]=e[5]*r[2]+e[6]*r[7]+e[7]*r[12]+e[8]*r[17],t[8]=e[5]*r[3]+e[6]*r[8]+e[7]*r[13]+e[8]*r[18],t[9]=e[5]*r[4]+e[6]*r[9]+e[7]*r[14]+e[8]*r[19]+e[9],t[10]=e[10]*r[0]+e[11]*r[5]+e[12]*r[10]+e[13]*r[15],t[11]=e[10]*r[1]+e[11]*r[6]+e[12]*r[11]+e[13]*r[16],t[12]=e[10]*r[2]+e[11]*r[7]+e[12]*r[12]+e[13]*r[17],t[13]=e[10]*r[3]+e[11]*r[8]+e[12]*r[13]+e[13]*r[18],t[14]=e[10]*r[4]+e[11]*r[9]+e[12]*r[14]+e[13]*r[19]+e[14],t[15]=e[15]*r[0]+e[16]*r[5]+e[17]*r[10]+e[18]*r[15],t[16]=e[15]*r[1]+e[16]*r[6]+e[17]*r[11]+e[18]*r[16],t[17]=e[15]*r[2]+e[16]*r[7]+e[17]*r[12]+e[18]*r[17],t[18]=e[15]*r[3]+e[16]*r[8]+e[17]*r[13]+e[18]*r[18],t[19]=e[15]*r[4]+e[16]*r[9]+e[17]*r[14]+e[18]*r[19]+e[19],t},e.prototype._colorMatrix=function(t){var e=new Float32Array(t);return e[4]/=255,e[9]/=255,e[14]/=255,e[19]/=255,e},e.prototype.brightness=function(t,e){var r=[t,0,0,0,0,0,t,0,0,0,0,0,t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.tint=function(t,e){var r=[(t>>16&255)/255,0,0,0,0,0,(t>>8&255)/255,0,0,0,0,0,(255&t)/255,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.greyscale=function(t,e){var r=[t,t,t,0,0,t,t,t,0,0,t,t,t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.blackAndWhite=function(t){this._loadMatrix([.3,.6,.1,0,0,.3,.6,.1,0,0,.3,.6,.1,0,0,0,0,0,1,0],t)},e.prototype.hue=function(t,e){t=(t||0)/180*Math.PI;var r=Math.cos(t),i=Math.sin(t),n=1/3,o=(0,Math.sqrt)(n),s=[r+(1-r)*n,n*(1-r)-o*i,n*(1-r)+o*i,0,0,n*(1-r)+o*i,r+n*(1-r),n*(1-r)-o*i,0,0,n*(1-r)-o*i,n*(1-r)+o*i,r+n*(1-r),0,0,0,0,0,1,0];this._loadMatrix(s,e)},e.prototype.contrast=function(t,e){var r=(t||0)+1,i=-.5*(r-1),n=[r,0,0,0,i,0,r,0,0,i,0,0,r,0,i,0,0,0,1,0];this._loadMatrix(n,e)},e.prototype.saturate=function(t,e){void 0===t&&(t=0);var r=2*t/3+1,i=-.5*(r-1),n=[r,i,i,0,0,i,r,i,0,0,i,i,r,0,0,0,0,0,1,0];this._loadMatrix(n,e)},e.prototype.desaturate=function(){this.saturate(-1)},e.prototype.negative=function(t){this._loadMatrix([-1,0,0,1,0,0,-1,0,1,0,0,0,-1,1,0,0,0,0,1,0],t)},e.prototype.sepia=function(t){this._loadMatrix([.393,.7689999,.18899999,0,0,.349,.6859999,.16799999,0,0,.272,.5339999,.13099999,0,0,0,0,0,1,0],t)},e.prototype.technicolor=function(t){this._loadMatrix([1.9125277891456083,-.8545344976951645,-.09155508482755585,0,11.793603434377337,-.3087833385928097,1.7658908555458428,-.10601743074722245,0,-70.35205161461398,-.231103377548616,-.7501899197440212,1.847597816108189,0,30.950940869491138,0,0,0,1,0],t)},e.prototype.polaroid=function(t){this._loadMatrix([1.438,-.062,-.062,0,0,-.122,1.378,-.122,0,0,-.016,-.016,1.483,0,0,0,0,0,1,0],t)},e.prototype.toBGR=function(t){this._loadMatrix([0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0],t)},e.prototype.kodachrome=function(t){this._loadMatrix([1.1285582396593525,-.3967382283601348,-.03992559172921793,0,63.72958762196502,-.16404339962244616,1.0835251566291304,-.05498805115633132,0,24.732407896706203,-.16786010706155763,-.5603416277695248,1.6014850761964943,0,35.62982807460946,0,0,0,1,0],t)},e.prototype.browni=function(t){this._loadMatrix([.5997023498159715,.34553243048391263,-.2708298674538042,0,47.43192855600873,-.037703249837783157,.8609577587992641,.15059552388459913,0,-36.96841498319127,.24113635128153335,-.07441037908422492,.44972182064877153,0,-7.562075277591283,0,0,0,1,0],t)},e.prototype.vintage=function(t){this._loadMatrix([.6279345635605994,.3202183420819367,-.03965408211312453,0,9.651285835294123,.02578397704808868,.6441188644374771,.03259127616149294,0,7.462829176470591,.0466055556782719,-.0851232987247891,.5241648018700465,0,5.159190588235296,0,0,0,1,0],t)},e.prototype.colorTone=function(t,e,r,i,n){var o=((r=r||16770432)>>16&255)/255,s=(r>>8&255)/255,a=(255&r)/255,h=((i=i||3375104)>>16&255)/255,u=(i>>8&255)/255,l=(255&i)/255,c=[.3,.59,.11,0,0,o,s,a,t=t||.2,0,h,u,l,e=e||.15,0,o-h,s-u,a-l,0,0];this._loadMatrix(c,n)},e.prototype.night=function(t,e){var r=[-2*(t=t||.1),-t,0,0,0,-t,0,t,0,0,0,t,2*t,0,0,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.predator=function(t,e){var r=[11.224130630493164*t,-4.794486999511719*t,-2.8746118545532227*t,0*t,.40342438220977783*t,-3.6330697536468506*t,9.193157196044922*t,-2.951810836791992*t,0*t,-1.316135048866272*t,-3.2184197902679443*t,-4.2375030517578125*t,7.476448059082031*t,0*t,.8044459223747253*t,0,0,0,1,0];this._loadMatrix(r,e)},e.prototype.lsd=function(t){this._loadMatrix([2,-.4,.5,0,0,-.5,2,-.4,0,0,-.4,-.5,3,0,0,0,0,0,1,0],t)},e.prototype.reset=function(){this._loadMatrix([1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],!1)},Object.defineProperty(e.prototype,"matrix",{get:function(){return this.uniforms.m},set:function(t){this.uniforms.m=t},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"alpha",{get:function(){return this.uniforms.uAlpha},set:function(t){this.uniforms.uAlpha=t},enumerable:!1,configurable:!0}),e}(Fi);Ua.prototype.grayscale=Ua.prototype.greyscale;var ka=function(t,e){return ka=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},ka(t,e)},Xa=function(t){function e(e,r){var i=this,n=new Ue;return e.renderable=!1,(i=t.call(this,"attribute vec2 aVertexPosition;\n\nuniform mat3 projectionMatrix;\nuniform mat3 filterMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec2 vFilterCoord;\n\nuniform vec4 inputSize;\nuniform vec4 outputFrame;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;\n\n return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n return aVertexPosition * (outputFrame.zw * inputSize.zw);\n}\n\nvoid main(void)\n{\n\tgl_Position = filterVertexPosition();\n\tvTextureCoord = filterTextureCoord();\n\tvFilterCoord = ( filterMatrix * vec3( vTextureCoord, 1.0) ).xy;\n}\n","varying vec2 vFilterCoord;\nvarying vec2 vTextureCoord;\n\nuniform vec2 scale;\nuniform mat2 rotation;\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nuniform highp vec4 inputSize;\nuniform vec4 inputClamp;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vFilterCoord);\n\n map -= 0.5;\n map.xy = scale * inputSize.zw * (rotation * map.xy);\n\n gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), inputClamp.xy, inputClamp.zw));\n}\n",{mapSampler:e._texture,filterMatrix:n,scale:{x:1,y:1},rotation:new Float32Array([1,0,0,1])})||this).maskSprite=e,i.maskMatrix=n,null==r&&(r=20),i.scale=new De(r,r),i}return function(t,e){function r(){this.constructor=t}ka(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(e,t),e.prototype.apply=function(t,e,r,i){this.uniforms.filterMatrix=t.calculateSpriteMatrix(this.maskMatrix,this.maskSprite),this.uniforms.scale.x=this.scale.x,this.uniforms.scale.y=this.scale.y;var n=this.maskSprite.worldTransform,o=Math.sqrt(n.a*n.a+n.b*n.b),s=Math.sqrt(n.c*n.c+n.d*n.d);0!==o&&0!==s&&(this.uniforms.rotation[0]=n.a/o,this.uniforms.rotation[1]=n.b/o,this.uniforms.rotation[2]=n.c/s,this.uniforms.rotation[3]=n.d/s),t.applyFilter(this,e,r,i)},Object.defineProperty(e.prototype,"map",{get:function(){return this.uniforms.mapSampler},set:function(t){this.uniforms.mapSampler=t},enumerable:!1,configurable:!0}),e}(Fi),ja=function(t,e){return ja=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},ja(t,e)},Ha=function(t){function e(){return t.call(this,"\nattribute vec2 aVertexPosition;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 v_rgbNW;\nvarying vec2 v_rgbNE;\nvarying vec2 v_rgbSW;\nvarying vec2 v_rgbSE;\nvarying vec2 v_rgbM;\n\nvarying vec2 vFragCoord;\n\nuniform vec4 inputSize;\nuniform vec4 outputFrame;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aVertexPosition * max(outputFrame.zw, vec2(0.)) + outputFrame.xy;\n\n return vec4((projectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);\n}\n\nvoid texcoords(vec2 fragCoord, vec2 inverseVP,\n out vec2 v_rgbNW, out vec2 v_rgbNE,\n out vec2 v_rgbSW, out vec2 v_rgbSE,\n out vec2 v_rgbM) {\n v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;\n v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;\n v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;\n v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;\n v_rgbM = vec2(fragCoord * inverseVP);\n}\n\nvoid main(void) {\n\n gl_Position = filterVertexPosition();\n\n vFragCoord = aVertexPosition * outputFrame.zw;\n\n texcoords(vFragCoord, inputSize.zw, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\n}\n",'varying vec2 v_rgbNW;\nvarying vec2 v_rgbNE;\nvarying vec2 v_rgbSW;\nvarying vec2 v_rgbSE;\nvarying vec2 v_rgbM;\n\nvarying vec2 vFragCoord;\nuniform sampler2D uSampler;\nuniform highp vec4 inputSize;\n\n\n/**\n Basic FXAA implementation based on the code on geeks3d.com with the\n modification that the texture2DLod stuff was removed since it\'s\n unsupported by WebGL.\n\n --\n\n From:\n https://github.com/mitsuhiko/webgl-meincraft\n\n Copyright (c) 2011 by Armin Ronacher.\n\n Some rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are\n met:\n\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials provided\n with the distribution.\n\n * The names of the contributors may not be used to endorse or\n promote products derived from this software without specific\n prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef FXAA_REDUCE_MIN\n#define FXAA_REDUCE_MIN (1.0/ 128.0)\n#endif\n#ifndef FXAA_REDUCE_MUL\n#define FXAA_REDUCE_MUL (1.0 / 8.0)\n#endif\n#ifndef FXAA_SPAN_MAX\n#define FXAA_SPAN_MAX 8.0\n#endif\n\n//optimized version for mobile, where dependent\n//texture reads can be a bottleneck\nvec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 inverseVP,\n vec2 v_rgbNW, vec2 v_rgbNE,\n vec2 v_rgbSW, vec2 v_rgbSE,\n vec2 v_rgbM) {\n vec4 color;\n vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;\n vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;\n vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;\n vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;\n vec4 texColor = texture2D(tex, v_rgbM);\n vec3 rgbM = texColor.xyz;\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot(rgbM, luma);\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n\n mediump vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n\n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\n (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n\n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * inverseVP;\n\n vec3 rgbA = 0.5 * (\n texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * 0.5 + 0.25 * (\n texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +\n texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\n float lumaB = dot(rgbB, luma);\n if ((lumaB < lumaMin) || (lumaB > lumaMax))\n color = vec4(rgbA, texColor.a);\n else\n color = vec4(rgbB, texColor.a);\n return color;\n}\n\nvoid main() {\n\n vec4 color;\n\n color = fxaa(uSampler, vFragCoord, inputSize.zw, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\n\n gl_FragColor = color;\n}\n')||this}return function(t,e){function r(){this.constructor=t}ja(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(e,t),e}(Fi),Ya=function(t,e){return Ya=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},Ya(t,e)},Va=function(t){function e(e,r){void 0===e&&(e=.5),void 0===r&&(r=Math.random());var i=t.call(this,gn,"precision highp float;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform float uNoise;\nuniform float uSeed;\nuniform sampler2D uSampler;\n\nfloat rand(vec2 co)\n{\n return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);\n}\n\nvoid main()\n{\n vec4 color = texture2D(uSampler, vTextureCoord);\n float randomValue = rand(gl_FragCoord.xy * uSeed);\n float diff = (randomValue - 0.5) * uNoise;\n\n // Un-premultiply alpha before applying the color matrix. See issue #3539.\n if (color.a > 0.0) {\n color.rgb /= color.a;\n }\n\n color.r += diff;\n color.g += diff;\n color.b += diff;\n\n // Premultiply alpha again.\n color.rgb *= color.a;\n\n gl_FragColor = color;\n}\n",{uNoise:0,uSeed:0})||this;return i.noise=e,i.seed=r,i}return function(t,e){function r(){this.constructor=t}Ya(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(e,t),Object.defineProperty(e.prototype,"noise",{get:function(){return this.uniforms.uNoise},set:function(t){this.uniforms.uNoise=t},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"seed",{get:function(){return this.uniforms.uSeed},set:function(t){this.uniforms.uSeed=t},enumerable:!1,configurable:!0}),e}(Fi),za=new Ue;Je.prototype._cacheAsBitmap=!1,Je.prototype._cacheData=null,Je.prototype._cacheAsBitmapResolution=null,Je.prototype._cacheAsBitmapMultisample=t.MSAA_QUALITY.NONE;var Wa=function(){this.textureCacheId=null,this.originalRender=null,this.originalRenderCanvas=null,this.originalCalculateBounds=null,this.originalGetLocalBounds=null,this.originalUpdateTransform=null,this.originalDestroy=null,this.originalMask=null,this.originalFilterArea=null,this.originalContainsPoint=null,this.sprite=null};Object.defineProperties(Je.prototype,{cacheAsBitmapResolution:{get:function(){return this._cacheAsBitmapResolution},set:function(t){t!==this._cacheAsBitmapResolution&&(this._cacheAsBitmapResolution=t,this.cacheAsBitmap&&(this.cacheAsBitmap=!1,this.cacheAsBitmap=!0))}},cacheAsBitmapMultisample:{get:function(){return this._cacheAsBitmapMultisample},set:function(t){t!==this._cacheAsBitmapMultisample&&(this._cacheAsBitmapMultisample=t,this.cacheAsBitmap&&(this.cacheAsBitmap=!1,this.cacheAsBitmap=!0))}},cacheAsBitmap:{get:function(){return this._cacheAsBitmap},set:function(t){var e;this._cacheAsBitmap!==t&&(this._cacheAsBitmap=t,t?(this._cacheData||(this._cacheData=new Wa),(e=this._cacheData).originalRender=this.render,e.originalRenderCanvas=this.renderCanvas,e.originalUpdateTransform=this.updateTransform,e.originalCalculateBounds=this.calculateBounds,e.originalGetLocalBounds=this.getLocalBounds,e.originalDestroy=this.destroy,e.originalContainsPoint=this.containsPoint,e.originalMask=this._mask,e.originalFilterArea=this.filterArea,this.render=this._renderCached,this.renderCanvas=this._renderCachedCanvas,this.destroy=this._cacheAsBitmapDestroy):((e=this._cacheData).sprite&&this._destroyCachedDisplayObject(),this.render=e.originalRender,this.renderCanvas=e.originalRenderCanvas,this.calculateBounds=e.originalCalculateBounds,this.getLocalBounds=e.originalGetLocalBounds,this.destroy=e.originalDestroy,this.updateTransform=e.originalUpdateTransform,this.containsPoint=e.originalContainsPoint,this._mask=e.originalMask,this.filterArea=e.originalFilterArea))}}}),Je.prototype._renderCached=function(t){!this.visible||this.worldAlpha<=0||!this.renderable||(this._initCachedDisplayObject(t),this._cacheData.sprite.transform._worldID=this.transform._worldID,this._cacheData.sprite.worldAlpha=this.worldAlpha,this._cacheData.sprite._render(t))},Je.prototype._initCachedDisplayObject=function(t){var e;if(!this._cacheData||!this._cacheData.sprite){var r=this.alpha;this.alpha=1,t.batch.flush();var i=this.getLocalBounds(null,!0).clone();if(this.filters&&this.filters.length){var n=this.filters[0].padding;i.pad(n)}i.ceil(U.RESOLUTION);var o=t.renderTexture.current,s=t.renderTexture.sourceFrame.clone(),a=t.renderTexture.destinationFrame.clone(),h=t.projection.transform,u=Fr.create({width:i.width,height:i.height,resolution:this.cacheAsBitmapResolution||t.resolution,multisample:null!==(e=this.cacheAsBitmapMultisample)&&void 0!==e?e:t.multisample}),l="cacheAsBitmap_"+ve();this._cacheData.textureCacheId=l,mr.addToCache(u.baseTexture,l),Nr.addToCache(u,l);var c=this.transform.localTransform.copyTo(za).invert().translate(-i.x,-i.y);this.render=this._cacheData.originalRender,t.render(this,{renderTexture:u,clear:!0,transform:c,skipUpdateTransform:!1}),t.framebuffer.blit(),t.projection.transform=h,t.renderTexture.bind(o,s,a),this.render=this._renderCached,this.updateTransform=this.displayObjectUpdateTransform,this.calculateBounds=this._calculateCachedBounds,this.getLocalBounds=this._getCachedLocalBounds,this._mask=null,this.filterArea=null,this.alpha=r;var d=new As(u);d.transform.worldTransform=this.transform.worldTransform,d.anchor.x=-i.x/i.width,d.anchor.y=-i.y/i.height,d.alpha=r,d._bounds=this._bounds,this._cacheData.sprite=d,this.transform._parentID=-1,this.parent?this.updateTransform():(this.enableTempParent(),this.updateTransform(),this.disableTempParent(null)),this.containsPoint=d.containsPoint.bind(d)}},Je.prototype._renderCachedCanvas=function(t){!this.visible||this.worldAlpha<=0||!this.renderable||(this._initCachedDisplayObjectCanvas(t),this._cacheData.sprite.worldAlpha=this.worldAlpha,this._cacheData.sprite._renderCanvas(t))},Je.prototype._initCachedDisplayObjectCanvas=function(t){if(!this._cacheData||!this._cacheData.sprite){var e=this.getLocalBounds(null,!0),r=this.alpha;this.alpha=1;var i=t.context,n=t._projTransform;e.ceil(U.RESOLUTION);var o=Fr.create({width:e.width,height:e.height}),s="cacheAsBitmap_"+ve();this._cacheData.textureCacheId=s,mr.addToCache(o.baseTexture,s),Nr.addToCache(o,s);var a=za;this.transform.localTransform.copyTo(a),a.invert(),a.tx-=e.x,a.ty-=e.y,this.renderCanvas=this._cacheData.originalRenderCanvas,t.render(this,{renderTexture:o,clear:!0,transform:a,skipUpdateTransform:!1}),t.context=i,t._projTransform=n,this.renderCanvas=this._renderCachedCanvas,this.updateTransform=this.displayObjectUpdateTransform,this.calculateBounds=this._calculateCachedBounds,this.getLocalBounds=this._getCachedLocalBounds,this._mask=null,this.filterArea=null,this.alpha=r;var h=new As(o);h.transform.worldTransform=this.transform.worldTransform,h.anchor.x=-e.x/e.width,h.anchor.y=-e.y/e.height,h.alpha=r,h._bounds=this._bounds,this._cacheData.sprite=h,this.transform._parentID=-1,this.parent?this.updateTransform():(this.parent=t._tempDisplayObjectParent,this.updateTransform(),this.parent=null),this.containsPoint=h.containsPoint.bind(h)}},Je.prototype._calculateCachedBounds=function(){this._bounds.clear(),this._cacheData.sprite.transform._worldID=this.transform._worldID,this._cacheData.sprite._calculateBounds(),this._bounds.updateID=this._boundsID},Je.prototype._getCachedLocalBounds=function(){return this._cacheData.sprite.getLocalBounds(null)},Je.prototype._destroyCachedDisplayObject=function(){this._cacheData.sprite._texture.destroy(!0),this._cacheData.sprite=null,mr.removeFromCache(this._cacheData.textureCacheId),Nr.removeFromCache(this._cacheData.textureCacheId),this._cacheData.textureCacheId=null},Je.prototype._cacheAsBitmapDestroy=function(t){this.cacheAsBitmap=!1,this.destroy(t)},Je.prototype.name=null,er.prototype.getChildByName=function(t,e){for(var r=0,i=this.children.length;r0){var d=a.x-t[l].x,f=a.y-t[l].y,p=Math.sqrt(d*d+f*f);a=t[l],s+=p/h}else s=l/(u-1);n[c]=s,n[c+1]=0,n[c+2]=s,n[c+3]=1}var _=0;for(l=0;l0?this.textureScale*this._width/2:this._width/2;i/=l,n/=l,i*=c,n*=c,o[u]=h.x+i,o[u+1]=h.y+n,o[u+2]=h.x-i,o[u+3]=h.y-n,r=h}this.buffers[0].update()}},e.prototype.update=function(){this.textureScale>0?this.build():this.updateVertices()},e}(fa),th=function(e){function r(r,i,n){void 0===n&&(n=0);var o=this,s=new $a(r.height,i,n),a=new da(r);return n>0&&(r.baseTexture.wrapMode=t.WRAP_MODES.REPEAT),(o=e.call(this,s,a)||this).autoUpdate=!0,o}return Qa(r,e),r.prototype._render=function(t){var r=this.geometry;(this.autoUpdate||r._width!==this.shader.texture.height)&&(r._width=this.shader.texture.height,r.update()),e.prototype._render.call(this,t)},r}(ca),eh=function(t){function e(e,r,i){var n=this,o=new Ja(e.width,e.height,r,i),s=new da(Nr.WHITE);return(n=t.call(this,o,s)||this).texture=e,n.autoResize=!0,n}return Qa(e,t),e.prototype.textureUpdated=function(){this._textureID=this.shader.texture._updateID;var t=this.geometry,e=this.shader.texture,r=e.width,i=e.height;!this.autoResize||t.width===r&&t.height===i||(t.width=this.shader.texture.width,t.height=this.shader.texture.height,t.build())},Object.defineProperty(e.prototype,"texture",{get:function(){return this.shader.texture},set:function(t){this.shader.texture!==t&&(this.shader.texture=t,this._textureID=-1,t.baseTexture.valid?this.textureUpdated():t.once("update",this.textureUpdated,this))},enumerable:!1,configurable:!0}),e.prototype._render=function(e){this._textureID!==this.shader.texture._updateID&&this.textureUpdated(),t.prototype._render.call(this,e)},e.prototype.destroy=function(e){this.shader.texture.off("update",this.textureUpdated,this),t.prototype.destroy.call(this,e)},e}(ca),rh=function(t){function e(e,r,i,n,o){void 0===e&&(e=Nr.EMPTY);var s=this,a=new fa(r,i,n);a.getBuffer("aVertexPosition").static=!1;var h=new da(e);return(s=t.call(this,a,h,null,o)||this).autoUpdate=!0,s}return Qa(e,t),Object.defineProperty(e.prototype,"vertices",{get:function(){return this.geometry.getBuffer("aVertexPosition").data},set:function(t){this.geometry.getBuffer("aVertexPosition").data=t},enumerable:!1,configurable:!0}),e.prototype._render=function(e){this.autoUpdate&&this.geometry.getBuffer("aVertexPosition").update(),t.prototype._render.call(this,e)},e}(ca),ih=function(t){function e(e,r,i,n,o){void 0===r&&(r=10),void 0===i&&(i=10),void 0===n&&(n=10),void 0===o&&(o=10);var s=t.call(this,Nr.WHITE,4,4)||this;return s._origWidth=e.orig.width,s._origHeight=e.orig.height,s._width=s._origWidth,s._height=s._origHeight,s._leftWidth=r,s._rightWidth=n,s._topHeight=i,s._bottomHeight=o,s.texture=e,s}return Qa(e,t),e.prototype.textureUpdated=function(){this._textureID=this.shader.texture._updateID,this._refresh()},Object.defineProperty(e.prototype,"vertices",{get:function(){return this.geometry.getBuffer("aVertexPosition").data},set:function(t){this.geometry.getBuffer("aVertexPosition").data=t},enumerable:!1,configurable:!0}),e.prototype.updateHorizontalVertices=function(){var t=this.vertices,e=this._getMinScale();t[9]=t[11]=t[13]=t[15]=this._topHeight*e,t[17]=t[19]=t[21]=t[23]=this._height-this._bottomHeight*e,t[25]=t[27]=t[29]=t[31]=this._height},e.prototype.updateVerticalVertices=function(){var t=this.vertices,e=this._getMinScale();t[2]=t[10]=t[18]=t[26]=this._leftWidth*e,t[4]=t[12]=t[20]=t[28]=this._width-this._rightWidth*e,t[6]=t[14]=t[22]=t[30]=this._width},e.prototype._getMinScale=function(){var t=this._leftWidth+this._rightWidth,e=this._width>t?1:this._width/t,r=this._topHeight+this._bottomHeight,i=this._height>r?1:this._height/r;return Math.min(e,i)},Object.defineProperty(e.prototype,"width",{get:function(){return this._width},set:function(t){this._width=t,this._refresh()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"height",{get:function(){return this._height},set:function(t){this._height=t,this._refresh()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"leftWidth",{get:function(){return this._leftWidth},set:function(t){this._leftWidth=t,this._refresh()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"rightWidth",{get:function(){return this._rightWidth},set:function(t){this._rightWidth=t,this._refresh()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"topHeight",{get:function(){return this._topHeight},set:function(t){this._topHeight=t,this._refresh()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"bottomHeight",{get:function(){return this._bottomHeight},set:function(t){this._bottomHeight=t,this._refresh()},enumerable:!1,configurable:!0}),e.prototype._refresh=function(){var t=this.texture,e=this.geometry.buffers[1].data;this._origWidth=t.orig.width,this._origHeight=t.orig.height;var r=1/this._origWidth,i=1/this._origHeight;e[0]=e[8]=e[16]=e[24]=0,e[1]=e[3]=e[5]=e[7]=0,e[6]=e[14]=e[22]=e[30]=1,e[25]=e[27]=e[29]=e[31]=1,e[2]=e[10]=e[18]=e[26]=r*this._leftWidth,e[4]=e[12]=e[20]=e[28]=1-r*this._rightWidth,e[9]=e[11]=e[13]=e[15]=i*this._topHeight,e[17]=e[19]=e[21]=e[23]=1-i*this._bottomHeight,this.updateHorizontalVertices(),this.updateVerticalVertices(),this.geometry.buffers[0].update(),this.geometry.buffers[1].update()},e}(eh),nh=function(t,e){return nh=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])},nh(t,e)},oh=function(e){function r(t,r){void 0===r&&(r=!0);var i=e.call(this,t[0]instanceof Nr?t[0]:t[0].texture)||this;return i._textures=null,i._durations=null,i._autoUpdate=r,i._isConnectedToTicker=!1,i.animationSpeed=1,i.loop=!0,i.updateAnchor=!1,i.onComplete=null,i.onFrameChange=null,i.onLoop=null,i._currentTime=0,i._playing=!1,i._previousFrame=null,i.textures=t,i}return function(t,e){function r(){this.constructor=t}nh(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(r,e),r.prototype.stop=function(){this._playing&&(this._playing=!1,this._autoUpdate&&this._isConnectedToTicker&&(ar.shared.remove(this.update,this),this._isConnectedToTicker=!1))},r.prototype.play=function(){this._playing||(this._playing=!0,this._autoUpdate&&!this._isConnectedToTicker&&(ar.shared.add(this.update,this,t.UPDATE_PRIORITY.HIGH),this._isConnectedToTicker=!0))},r.prototype.gotoAndStop=function(t){this.stop();var e=this.currentFrame;this._currentTime=t,e!==this.currentFrame&&this.updateTexture()},r.prototype.gotoAndPlay=function(t){var e=this.currentFrame;this._currentTime=t,e!==this.currentFrame&&this.updateTexture(),this.play()},r.prototype.update=function(t){if(this._playing){var e=this.animationSpeed*t,r=this.currentFrame;if(null!==this._durations){var i=this._currentTime%1*this._durations[this.currentFrame];for(i+=e/60*1e3;i<0;)this._currentTime--,i+=this._durations[this.currentFrame];var n=Math.sign(this.animationSpeed*t);for(this._currentTime=Math.floor(this._currentTime);i>=this._durations[this.currentFrame];)i-=this._durations[this.currentFrame]*n,this._currentTime+=n;this._currentTime+=i/this._durations[this.currentFrame]}else this._currentTime+=e;this._currentTime<0&&!this.loop?(this.gotoAndStop(0),this.onComplete&&this.onComplete()):this._currentTime>=this._textures.length&&!this.loop?(this.gotoAndStop(this._textures.length-1),this.onComplete&&this.onComplete()):r!==this.currentFrame&&(this.loop&&this.onLoop&&(this.animationSpeed>0&&this.currentFramer)&&this.onLoop(),this.updateTexture())}},r.prototype.updateTexture=function(){var t=this.currentFrame;this._previousFrame!==t&&(this._previousFrame=t,this._texture=this._textures[t],this._textureID=-1,this._textureTrimmedID=-1,this._cachedTint=16777215,this.uvs=this._texture._uvs.uvsFloat32,this.updateAnchor&&this._anchor.copyFrom(this._texture.defaultAnchor),this.onFrameChange&&this.onFrameChange(this.currentFrame))},r.prototype.destroy=function(t){this.stop(),e.prototype.destroy.call(this,t),this.onComplete=null,this.onFrameChange=null,this.onLoop=null},r.fromFrames=function(t){for(var e=[],i=0;i { + const CHANNEL = "desktop-pet-model"; + const canvas = document.querySelector("#model"); + let application; + let model; + let artBounds; + let presence = "idle"; + let attentionWeight = 0; + let modelId = ""; + let generation = 0; + let automatic = true; + let gazeEnabled = true; + let idleEnabled = true; + let busy = false; + let dragging = false; + let expressionIndex = -1; + let expressionQueue = Promise.resolve(); + let mouthTarget = 0; + let mouthValue = 0; + let mouthAt = 0; + let touchState = null; + let touchAt = -Infinity; + let touches = {}; + let nextMotionAt = 0; + let replyMotionActive = false; + let replyMotionAt = -Infinity; + let metadata = { expressions: [], motions: {} }; + + function notify(type, extra = {}) { parent.postMessage({ channel: CHANNEL, type, ...extra }, "*"); } + function fit() { + if (!application || !model) return; + const width = Math.max(1, innerWidth); + const height = Math.max(1, innerHeight); + application.renderer.resize(width, height); + const bounds = artBounds || model.internalModel; + const scale = Math.min(width / bounds.width, height / bounds.height) * 0.88; + model.scale.set(scale); + model.anchor.set(0.5, 0.5); + model.position.set(width / 2 - (bounds.x || 0) * scale, height / 2 - (bounds.y || 0) * scale); + } + + function stopMotions() { + if (!model) return; + replyMotionActive = false; + model.internalModel.motionManager.stopAllMotions(); + // Breathing and blinking remain active; large idle motions are explicitly paced below. + model.internalModel.motionManager.groups.idle = "__desktop_pet_no_automatic_motion__"; + } + + function expression(index) { + const target = model; + const token = generation; + expressionIndex = index; + expressionQueue = expressionQueue.then(async () => { + if (!target || model !== target || generation !== token) return; + const manager = target.internalModel.motionManager.expressionManager; + if (index < 0 && manager) { + // The library restores currentExpression after motions; neutral must persist too. + manager.currentExpression = manager.defaultExpression; + manager.resetExpression(); + } else if (manager && !(await manager.setExpression(index))) { notify("action-error"); return; } + if (model === target) notify("expression", { index }); + }).catch(() => notify("action-error")); + } + + function cancelTouch(restore = true) { + const previous = touchState; + touchState = null; + if (restore && previous?.expressionChanged) expression(previous.expression); + } + + function touch(kind) { + const now = performance.now(); + if (!automatic || busy || dragging || presence !== "idle" || now - touchAt < 2400) return; + if (!["head", "greet", "drop"].includes(kind)) return; + cancelTouch(); + stopMotions(); + const mapping = touches[kind]; + const index = mapping?.expression; + const expressionChanged = Number.isInteger(index) && index >= 0 && index < metadata.expressions.length; + touchState = { kind, start: now, expression: expressionIndex, expressionChanged }; + touchAt = now; + if (expressionChanged) expression(index); + touchState.nativeMotion = mapping?.motion ? motion(mapping.motion.group, mapping.motion.index) : false; + nextMotionAt = now + 45000; + notify("touch", { kind }); + } + + function locate(x, y) { + if (!Number.isFinite(x) || !Number.isFinite(y) || x < 0 || x >= 1 || y < 0 || y >= 1) return null; + const gl = application.renderer.gl; + const pixel = new Uint8Array(4); + gl.readPixels(Math.floor(x * canvas.width), canvas.height - 1 - Math.floor(y * canvas.height), 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); + if (pixel[3] <= 8) return null; + const areas = model.internalModel.hitAreas; + if (areas && Object.keys(areas).length) { + const hits = model.hitTest(x * innerWidth, y * innerHeight); + if (hits.some(name => /head|face/i.test(`${name} ${areas[name]?.id || ""}`))) return "head"; + return hits.length ? "greet" : null; + } + // Without named regions, use a height split inside the visible silhouette. + return y < 0.46 ? "head" : "greet"; + } + + function motion(group, index = 0, reply = false) { + if (!automatic || !model || !Object.hasOwn(metadata.motions, group)) return false; + if (!Number.isInteger(index) || index < 0 || index >= metadata.motions[group]) return false; + replyMotionActive = reply; + const target = model; + target.motion(group, index, 3).then((started) => { if (target === model) notify(started ? "motion" : "action-error", { group, index }); }) + .catch(() => notify("action-error")); + nextMotionAt = performance.now() + 45000; + return true; + } + + async function load(data) { + const token = ++generation; + modelId = data.id; + automatic = data.automatic !== false; + gazeEnabled = data.gaze !== false; + idleEnabled = data.idle !== false; + touches = data.touches || {}; + busy = data.busy === true; + dragging = data.dragging === true; + presence = "idle"; + attentionWeight = 0; + artBounds = null; + expressionIndex = -1; + mouthTarget = mouthValue = 0; + replyMotionAt = -Infinity; + touchState = null; + touchAt = -Infinity; + model?.destroy({ children: true, texture: true, baseTexture: true }); + model = null; + try { + if (!window.Live2DCubismCore || !window.PIXI?.live2d) throw new Error(); + if (!application) { + application = new PIXI.Application({ view: canvas, backgroundAlpha: 0, antialias: true, + autoDensity: true, resolution: Math.min(devicePixelRatio || 1, 2), preserveDrawingBuffer: true }); + application.ticker.maxFPS = 60; + application.ticker.add(() => model?.update(Math.min(50, application.ticker.elapsedMS))); + } + application.renderer.resize(Math.max(1, innerWidth), Math.max(1, innerHeight)); + const url = `/models/${modelId}/model.model3.json`; + const descriptor = await (await fetch(url)).json(); + const refs = descriptor.FileReferences; + const nextMetadata = { expressions: (refs.Expressions || []).map((entry) => entry.Name), + motions: Object.fromEntries(Object.entries(refs.Motions || {}).map(([group, entries]) => [group, entries.length])) }; + const loaded = await PIXI.live2d.Live2DModel.from(url, { autoUpdate: false, autoInteract: false, idleMotionGroup: "__desktop_pet_no_automatic_motion__" }); + if (generation !== token) { loaded.destroy({ children: true, texture: true, baseTexture: true }); return; } + model = loaded; + metadata = nextMetadata; + application.stage.addChild(model); + stopMotions(); + const internal = model.internalModel; + internal.motionManager.on("motionFinish", () => { if (internal === model?.internalModel) replyMotionActive = false; }); + const core = internal.coreModel; + const { ids, resolve } = window.DesktopPetRig.configure(internal); + artBounds = window.DesktopPetRig.measure(application, model); + fit(); + nextMotionAt = performance.now() + 35000; + const lips = (descriptor.Groups?.find((group) => group.Name === "LipSync")?.Ids || []).filter(id => ids.has(id)); + if (!lips.length && ids.has(resolve("ParamMouthOpenY"))) lips.push(resolve("ParamMouthOpenY")); + internal.on("beforeModelUpdate", () => { + const now = performance.now(); + if (now - mouthAt > 300) mouthTarget = 0; + const wasOpen = mouthValue > 0.005; + mouthValue += (mouthTarget - mouthValue) * 0.25; + if (mouthTarget > 0 || wasOpen) { + for (const id of lips) if (ids.has(id)) core.setParameterValueById(id, mouthValue < 0.005 ? 0 : mouthValue); + } + attentionWeight += ((automatic && presence !== "idle" ? 1 : 0) - attentionWeight) * 0.08; + if (attentionWeight > 0.005) { + if (ids.has(resolve("ParamAngleZ"))) core.addParameterValueById(resolve("ParamAngleZ"), (presence === "thinking" ? 2 : -1.5) * attentionWeight); + } + if (touchState) { + const progress = Math.min(1, (now - touchState.start) / 2200); + const weight = Math.sin(Math.PI * progress) ** 2; + if (automatic && !touchState.nativeMotion && ids.has(resolve("ParamAngleZ"))) { + core.addParameterValueById(resolve("ParamAngleZ"), (touchState.kind === "head" ? -5 : 2) * weight); + } + if (progress >= 1) cancelTouch(); + } + if (automatic && idleEnabled && !busy && !dragging && presence === "idle" && now > nextMotionAt) { + const group = Object.keys(metadata.motions).find((key) => /^idle$/i.test(key)); + nextMotionAt = now + 45000 + Math.random() * 15000; + if (group && metadata.motions[group]) model.motion(group, 0, 1).catch(() => {}); + } + }); + if (document.hidden) application.ticker.stop(); + notify("loaded", { expressions: metadata.expressions, motions: metadata.motions }); + } catch { + if (generation === token) notify("error"); + } + } + + window.addEventListener("message", (event) => { + const data = event.data; + if (event.source !== parent || event.origin !== "null" || !data || data.channel !== CHANNEL) return; + if (data.type === "load" && /^imported-[a-f0-9]{24}$/.test(data.id)) { load(data); return; } + if (!model || data.id !== modelId) return; + if (data.type === "options") { + const changed = automatic !== (data.automatic !== false); + automatic = data.automatic !== false; + gazeEnabled = data.gaze !== false; + const interrupt = (data.busy === true && !busy) || (data.dragging === true && !dragging) + || (data.idle === false && idleEnabled) || changed; + if (interrupt) { cancelTouch(); stopMotions(); nextMotionAt = performance.now() + 45000; } + busy = data.busy === true; + dragging = data.dragging === true; + idleEnabled = data.idle !== false; + touches = data.touches || {}; + if (!gazeEnabled || !automatic) model.internalModel.focusController.focus(0, 0); + } else if (data.type === "presence" && ["idle", "attentive", "thinking", "speaking"].includes(data.state)) { + if (presence === data.state) return; + presence = data.state; + if (presence !== "idle") cancelTouch(); + if (presence !== "idle" && !(presence === "speaking" && replyMotionActive)) stopMotions(); + nextMotionAt = performance.now() + 45000; + if (automatic && gazeEnabled) model.internalModel.focusController.focus(0, presence === "idle" ? 0 : 0.08); + } else if (data.type === "gaze") { + if (!automatic || !gazeEnabled || dragging || presence !== "idle" || !Number.isFinite(data.x) || !Number.isFinite(data.y)) return; + model.internalModel.focusController.focus(Math.max(-0.35, Math.min(0.35, data.x)), Math.max(-0.25, Math.min(0.25, data.y))); + } else if (data.type === "mouth" && Number.isFinite(data.value)) { + mouthTarget = Math.max(0, Math.min(1, data.value)); mouthAt = performance.now(); + } else if (data.type === "cycle") { + cancelTouch(false); + expression((expressionIndex + 2) % (metadata.expressions.length + 1) - 1); + } else if (data.type === "expression" && Number.isInteger(data.index) && data.index >= -1 && data.index < metadata.expressions.length) { + cancelTouch(false); + expression(data.index); + } else if (data.type === "motion") { + cancelTouch(); + motion(data.group, data.index); + } else if (data.type === "reply-motion") { + const now = performance.now(); + if (now - replyMotionAt >= 12000 && motion(data.group, data.index, true)) replyMotionAt = now; + } else if (data.type === "touch") { + touch(data.kind); + } else if (data.type === "locate" && Number.isSafeInteger(data.request)) { + notify("location", { request: data.request, kind: locate(data.x, data.y) }); + } + }); + window.addEventListener("resize", fit); + document.addEventListener("visibilitychange", () => { + if (document.hidden) { + cancelTouch(); stopMotions(); + mouthTarget = 0; + application?.ticker.stop(); + } else { + nextMotionAt = performance.now() + 45000; + application?.ticker.start(); + } + }); + notify("boot"); +})(); diff --git a/src/main.js b/src/main.js index a3c5cd4..c2833a7 100644 --- a/src/main.js +++ b/src/main.js @@ -10,6 +10,9 @@ const { dialog, Tray, powerMonitor, + protocol, + session, + shell, } = require("electron"); const fs = require("node:fs"); const path = require("node:path"); @@ -23,10 +26,15 @@ const { normalizePlacement, fitBounds, capturePlacement, defaultBounds, restoreP const { modelsEndpoint, readModelList } = require("./model-list"); const { readPack, installPack } = require("./character-import"); const { pathToFileURL } = require("node:url"); +const { readLive2DPack, installLive2DPack } = require("./live2d-import"); +const live2dHost = require("./live2d-host"); + +protocol?.registerSchemesAsPrivileged([{ scheme: "pet-live2d", privileges: { standard: true, secure: true, supportFetchAPI: true, corsEnabled: true } }]); const BASE_SIZE = { width: 192, height: 208 }; const BUBBLE_HEIGHT = 160; const MIN_BUBBLE_WIDTH = 320; +let companionInputOpen = false; const DEFAULT_CHARACTER_ID = "default"; const CHARACTERS_DIR = path.join(__dirname, "..", "assets", "characters"); const SIZE_PRESETS = [0.75, 1, 1.25, 1.5, 1.75, 2]; @@ -245,28 +253,54 @@ function importedCharactersDir() { return path.join(app.getPath("userData"), "ch async function previewCharacterImport(event, kind) { const owner = BrowserWindow.fromWebContents(event.sender); + const live2d = kind === "live2d"; const result = await dialog.showOpenDialog(owner, kind === "folder" ? { properties: ["openDirectory"] } - : { properties: ["openFile"], filters: [{ name: "ZIP", extensions: ["zip"] }] }); + : { properties: ["openFile"], filters: [{ name: live2d ? "Live2D" : "ZIP", extensions: live2d ? ["json", "zip"] : ["zip"] }] }); if (result.canceled || !result.filePaths.length) return { cancelled: true }; try { - const pack = readPack(result.filePaths[0], (bytes) => !nativeImage.createFromBuffer(bytes).isEmpty()); + const pack = (live2d ? readLive2DPack : readPack)(result.filePaths[0], (bytes) => !nativeImage.createFromBuffer(bytes).isEmpty()); const token = require("node:crypto").randomUUID(); pendingImport = { pack, token, sender: event.sender.id, expires: Date.now() + 600000 }; - return { token, name: pack.manifest.name, description: pack.manifest.description, - preview: `data:image/png;base64,${pack.files[pack.manifest.preview].toString("base64")}` }; + return { token, name: pack.manifest.name, description: pack.manifest.description, type: pack.manifest.type || "sprite", + preview: live2d ? "" : `data:image/png;base64,${pack.files[pack.manifest.preview].toString("base64")}` }; } catch { return { error: "invalid_pack" }; } } function confirmCharacterImport(event, token) { if (!pendingImport || pendingImport.token !== token || pendingImport.sender !== event.sender.id || pendingImport.expires < Date.now()) return { error: "expired" }; try { - installPack(pendingImport.pack, importedCharactersDir()); + (pendingImport.pack.manifest.type === "live2d" ? installLive2DPack : installPack)(pendingImport.pack, importedCharactersDir()); pendingImport = null; return { ok: true, ...chatState() }; } catch { return { error: "import_failed" }; } } +async function importLive2DRuntime(event) { + const result = await dialog.showOpenDialog(BrowserWindow.fromWebContents(event.sender), { + properties: ["openFile"], filters: [{ name: "Cubism Core", extensions: ["js"] }], + }); + if (result.canceled || !result.filePaths.length) return { cancelled: true }; + try { + live2dHost.installCore(result.filePaths[0], app.getPath("userData")); + mainWindow?.webContents.send("app-state-updated", appState()); + return { ok: true }; + } catch { return { error: "invalid_runtime" }; } +} + +function performModelAction(_event, action) { + const pack = getCharacterPack(); + if (pack?.type !== "live2d" || !mainWindow || !action) return false; + if (action.type === "motion" && settings.expressionMode === "clickOnly") return false; + const valid = action.type === "expression" + ? Number.isInteger(action.index) && action.index >= -1 && action.index < pack.expressions.length + : action.type === "motion" && Object.hasOwn(pack.motions, action.group) + && Number.isInteger(action.index) && action.index >= 0 && action.index < pack.motions[action.group]; + if (!valid) return false; + mainWindow.webContents.send("model-action", { type: action.type, index: action.index, group: action.group, id: pack.id }); + return true; +} + async function removeCharacterImport(event, id) { if (!/^imported-[a-f0-9]{24}$/.test(id)) return { error: "invalid_id" }; const result = await dialog.showMessageBox(BrowserWindow.fromWebContents(event.sender), { @@ -418,6 +452,16 @@ function listCharacterPacks() { try { const root = path.join(importedCharactersDir(), id); const raw = JSON.parse(fs.readFileSync(path.join(root, "character.json"), "utf8")); + if (raw.type === "live2d") { + if (raw.model !== "model.model3.json" || !Array.isArray(raw.resources)) return null; + return { id, type: "live2d", name: String(raw.name || "Character").slice(0, 80), description: "", imported: true, + frame: { width: 768, height: 832 }, columns: 1, + states: Object.fromEntries(["idle", "happy", "shy", "review", "failed", "waving"].map((key) => [key, { row: 0, frames: 1, interval: 1000 }])), + automaticActions: [], clickActions: [], staticExpressions: [], + expressions: Array.isArray(raw.expressions) ? raw.expressions.slice(0, 64).map((name) => String(name).slice(0, 80)) : [], + motions: raw.motions && typeof raw.motions === "object" ? raw.motions : {}, + }; + } const pack = normalizeCharacterPack(raw, id); return { ...pack, id, imported: true, absoluteSpritePath: path.join(root, raw.sprite), spritePath: pathToFileURL(path.join(root, raw.sprite)).href, @@ -676,6 +720,16 @@ function normalizeTtsSettings(rawTts = {}) { }; } +function normalizeModelMotion(value) { + const valid = value && typeof value.group === "string" && value.group.length <= 80 + && !/[\u0000-\u001f\u007f]/.test(value.group) && Number.isInteger(value.index) && value.index >= 0 && value.index < 256; + return valid ? { group: value.group, index: value.index } : null; +} + +function normalizeModelExpression(value) { + return Number.isInteger(value) && value >= 0 && value < 64 ? value : -1; +} + function normalizePersonaSettings(rawPersona = {}) { const raw = { ...DEFAULT_SETTINGS.persona, ...(rawPersona || {}) }; return { @@ -688,6 +742,16 @@ function normalizePersonaSettings(rawPersona = {}) { speakingStyle: normalizeLongText(raw.speakingStyle, 1200), background: normalizeLongText(raw.background, 1600), extraRules: normalizeLongText(raw.extraRules, 1600), + live2dGaze: raw.live2dGaze !== false, + live2dIdle: raw.live2dIdle !== false, + live2dExpressions: Object.fromEntries(["happy", "shy", "review", "failed"].map((key) => + [key, normalizeModelExpression(raw.live2dExpressions?.[key])])), + live2dMotions: Object.fromEntries(["happy", "shy", "review", "failed"].map((key) => + [key, normalizeModelMotion(raw.live2dMotions?.[key])])), + live2dTouches: Object.fromEntries(["head", "greet"].map((key) => [key, { + expression: normalizeModelExpression(raw.live2dTouches?.[key]?.expression), + motion: normalizeModelMotion(raw.live2dTouches?.[key]?.motion), + }])), }; } @@ -782,7 +846,7 @@ function nearestScale(scale) { function displaySize(scale = settings.scale) { return { width: Math.max(MIN_BUBBLE_WIDTH, Math.round(BASE_SIZE.width * scale)), - height: Math.round(BASE_SIZE.height * scale) + BUBBLE_HEIGHT, + height: Math.round(BASE_SIZE.height * scale) + BUBBLE_HEIGHT + (companionInputOpen ? 88 : 0), }; } @@ -796,6 +860,14 @@ function applyWindowSize(keepCenter = true) { mainWindow.setBounds(fitBounds({ x, y, ...nextSize }, area)); } +function setCompanionInputOpen(event, open) { + if (event.sender !== mainWindow?.webContents) return false; + companionInputOpen = open === true; + applyWindowSize(); + if (companionInputOpen) { mainWindow.show(); mainWindow.focus(); } + return companionInputOpen; +} + function createWindow() { readSettings(); readProfile(); @@ -818,10 +890,11 @@ function createWindow() { preload: path.join(__dirname, "preload.js"), contextIsolation: true, nodeIntegration: false, - sandbox: false, + sandbox: true, }, }); + protectWindow(mainWindow, "index.html"); mainWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); enableInputMenu(mainWindow); mainWindow.loadFile(path.join(__dirname, "index.html")); @@ -834,6 +907,18 @@ function createWindow() { mainWindow.webContents.on("did-start-loading", () => stopVoice()); } +function protectWindow(window, page) { + const localUrl = pathToFileURL(path.join(__dirname, page)).href; + window.webContents.setWindowOpenHandler(() => ({ action: "deny" })); + window.webContents.on("will-navigate", (event, url) => { if (url !== localUrl) event.preventDefault(); }); + window.webContents.on("will-frame-navigate", (event) => { + const allowed = event.isMainFrame ? event.url === localUrl + : page === "index.html" && event.url === `${live2dHost.ORIGIN}/index.html`; + if (!allowed) event.preventDefault(); + }); + window.webContents.on("will-attach-webview", (event) => event.preventDefault()); +} + function enableInputMenu(window) { window.webContents.on("context-menu", (_event, params) => { if (!params.isEditable) { @@ -876,10 +961,11 @@ function createChatWindow() { preload: path.join(__dirname, "preload.js"), contextIsolation: true, nodeIntegration: false, - sandbox: false, + sandbox: true, }, }); + protectWindow(chatWindow, "chat.html"); chatWindow.loadFile(path.join(__dirname, "chat.html")); enableInputMenu(chatWindow); chatWindow.once("ready-to-show", () => chatWindow.show()); @@ -910,10 +996,11 @@ function createQuickChatWindow() { preload: path.join(__dirname, "preload.js"), contextIsolation: true, nodeIntegration: false, - sandbox: false, + sandbox: true, }, }); + protectWindow(quickChatWindow, "quick-chat.html"); quickChatWindow.loadFile(path.join(__dirname, "quick-chat.html")); enableInputMenu(quickChatWindow); quickChatWindow.once("ready-to-show", () => quickChatWindow.show()); @@ -942,10 +1029,11 @@ function createCompanionSettingsWindow() { preload: path.join(__dirname, "preload.js"), contextIsolation: true, nodeIntegration: false, - sandbox: false, + sandbox: true, }, }); + protectWindow(companionSettingsWindow, "settings.html"); companionSettingsWindow.loadFile(path.join(__dirname, "settings.html")); enableInputMenu(companionSettingsWindow); companionSettingsWindow.once("ready-to-show", () => companionSettingsWindow.show()); @@ -1255,6 +1343,9 @@ function chatState() { automaticActionCount: pack.automaticActions.length, clickActionCount: pack.clickActions.length, imported: pack.imported === true, + type: pack.type || "sprite", + expressions: pack.expressions || [], + motions: pack.motions || {}, })); return { language: settings.language, @@ -1298,7 +1389,7 @@ function setChatDraft(event, draft = {}) { else chatDrafts.delete(settings.characterId); chatDraftVersion += 1; // Mirror edits between composers without persisting unsent text. - for (const window of [chatWindow, quickChatWindow]) { + for (const window of [mainWindow, chatWindow, quickChatWindow]) { if (window && !window.isDestroyed()) { window.webContents.send("chat-draft-updated", { ...chatDraftState(), acknowledgedEdit: window.webContents === event?.sender ? draft.edit : undefined }); @@ -1613,6 +1704,7 @@ async function sendChatMessage(_event, rawText, context) { sendPetMessage(result.reply, result.action, { ...presentation, speak: result.ok, + replyMotion: result.ok ? replyMotionFor(result.action) : null, bubbleText: bubblePreview(result.reply), }); if (result.ok) recordChatTimeProgress(); @@ -1627,6 +1719,14 @@ async function sendChatMessage(_event, rawText, context) { } } +function replyMotionFor(action) { + const pack = getCharacterPack(); + const motion = settings.persona?.live2dMotions?.[action]; + if (settings.expressionMode !== "automatic" || pack?.type !== "live2d" || !motion + || !Object.hasOwn(pack.motions, motion.group) || motion.index >= pack.motions[motion.group]) return null; + return { group: motion.group, index: motion.index }; +} + function broadcastChatState() { for (const window of [mainWindow, chatWindow, quickChatWindow]) { if (window && !window.isDestroyed()) window.webContents.send("chat-state-updated", chatState()); @@ -2095,44 +2195,62 @@ else { if (ownsInstance) app.whenReady().then(() => { app.setName(t("app.name")); + protocol.handle("pet-live2d", live2dHost.createModelHandler({ userData: app.getPath("userData"), sourceDir: __dirname, getActiveCharacter: getCharacterPack })); + session.defaultSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false)); + session.defaultSession.setPermissionCheckHandler(() => false); createWindow(); - ipcMain.handle("get-app-state", () => appState()); - ipcMain.handle("get-chat-state", () => chatState()); - ipcMain.handle("save-chat-config", (_event, patch) => applyChatConfigPatch(patch)); - ipcMain.handle("test-assistant-connection", testAssistantConnection); - ipcMain.handle("list-assistant-models", listAssistantModels); - ipcMain.handle("test-tts-connection", testTtsConnection); - ipcMain.handle("send-chat-message", sendChatMessage); - ipcMain.handle("clear-chat-history", clearChatHistory); - ipcMain.handle("stop-chat", stopChat); - ipcMain.on("set-chat-draft", setChatDraft); - ipcMain.handle("confirm-discard", confirmDiscard); - ipcMain.on("confirm-app-quit", confirmAppQuit); - ipcMain.handle("preview-character-import", previewCharacterImport); - ipcMain.handle("confirm-character-import", confirmCharacterImport); - ipcMain.handle("remove-character-import", removeCharacterImport); - ipcMain.handle("begin-speech", beginSpeech); - ipcMain.on("speech-state-changed", speechStateChanged); - ipcMain.handle("stop-voice", stopVoice); - ipcMain.handle("replay-speech", replaySpeech); - ipcMain.handle("show-last-reply", showLastReply); - ipcMain.handle("synthesize-speech", synthesizeSpeech); - ipcMain.on("set-settings", (_event, patch) => updateSettings(patch)); - ipcMain.on("record-interaction", (_event, kind) => updateMoodFromInteraction(kind)); - ipcMain.on("present-notification", (event, notice) => { + // Only our top-level local windows may invoke the preload bridge. + const trusted = (event) => [mainWindow, chatWindow, quickChatWindow, companionSettingsWindow].some((window) => + window && !window.isDestroyed() && event.sender === window.webContents && event.senderFrame === window.webContents.mainFrame + && ["index.html", "chat.html", "quick-chat.html", "settings.html"].some((page) => event.senderFrame.url === pathToFileURL(path.join(__dirname, page)).href)); + const handle = (channel, callback) => ipcMain.handle(channel, (event, ...args) => { + if (!trusted(event)) throw new Error("Unauthorized window"); + return callback(event, ...args); + }); + const on = (channel, callback) => ipcMain.on(channel, (event, ...args) => { if (trusted(event)) callback(event, ...args); }); + handle("get-live2d-runtime", () => ({ ready: live2dHost.runtimeReady(app.getPath("userData")) })); + handle("import-live2d-runtime", importLive2DRuntime); + handle("perform-model-action", performModelAction); + on("open-live2d-download", () => { shell.openExternal(live2dHost.CORE_URL).catch(() => {}); }); + + handle("get-app-state", () => appState()); + handle("get-chat-state", () => chatState()); + handle("set-companion-input-open", setCompanionInputOpen); + handle("save-chat-config", (_event, patch) => applyChatConfigPatch(patch)); + handle("test-assistant-connection", testAssistantConnection); + handle("list-assistant-models", listAssistantModels); + handle("test-tts-connection", testTtsConnection); + handle("send-chat-message", sendChatMessage); + handle("clear-chat-history", clearChatHistory); + handle("stop-chat", stopChat); + on("set-chat-draft", setChatDraft); + on("confirm-app-quit", confirmAppQuit); + handle("confirm-discard", confirmDiscard); + handle("preview-character-import", previewCharacterImport); + handle("confirm-character-import", confirmCharacterImport); + handle("remove-character-import", removeCharacterImport); + handle("begin-speech", beginSpeech); + on("speech-state-changed", speechStateChanged); + handle("stop-voice", stopVoice); + handle("replay-speech", replaySpeech); + handle("show-last-reply", showLastReply); + handle("synthesize-speech", synthesizeSpeech); + on("set-settings", (_event, patch) => updateSettings(patch)); + on("record-interaction", (_event, kind) => updateMoodFromInteraction(kind)); + on("present-notification", (event, notice) => { if (event.sender !== mainWindow?.webContents || !Notification.isSupported()) return; const title = normalizeCompactText(notice?.title, 120); const body = normalizeLongText(notice?.body, 600); if (title || body) new Notification({ title, body, silent: true }).show(); }); - ipcMain.on("open-chat-window", createChatWindow); - ipcMain.on("open-quick-chat-window", createQuickChatWindow); - ipcMain.on("open-companion-settings", createCompanionSettingsWindow); - ipcMain.on("show-context-menu", showContextMenu); - ipcMain.on("drag-start", beginDrag); - ipcMain.handle("drag-move", moveDrag); - ipcMain.on("drag-end", endDrag); + on("open-chat-window", createChatWindow); + on("open-quick-chat-window", createQuickChatWindow); + on("open-companion-settings", createCompanionSettingsWindow); + on("show-context-menu", showContextMenu); + on("drag-start", beginDrag); + handle("drag-move", moveDrag); + on("drag-end", endDrag); if (process.platform === "darwin") { app.dock.hide(); diff --git a/src/preload.js b/src/preload.js index 3d072b4..05646ae 100644 --- a/src/preload.js +++ b/src/preload.js @@ -1,7 +1,17 @@ const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("desktopPet", { + setCompanionInputOpen: (open) => ipcRenderer.invoke("set-companion-input-open", open), getAppState: () => ipcRenderer.invoke("get-app-state"), + getLive2DRuntime: () => ipcRenderer.invoke("get-live2d-runtime"), + importLive2DRuntime: () => ipcRenderer.invoke("import-live2d-runtime"), + openLive2DDownload: () => ipcRenderer.send("open-live2d-download"), + performModelAction: (action) => ipcRenderer.invoke("perform-model-action", action), + onModelAction: (callback) => { + const listener = (_event, action) => callback(action); + ipcRenderer.on("model-action", listener); + return () => ipcRenderer.off("model-action", listener); + }, setSettings: (patch) => ipcRenderer.send("set-settings", patch), getChatState: () => ipcRenderer.invoke("get-chat-state"), saveChatConfig: (patch) => ipcRenderer.invoke("save-chat-config", patch), diff --git a/src/quick-chat.css b/src/quick-chat.css index ca496c2..ee4c552 100644 --- a/src/quick-chat.css +++ b/src/quick-chat.css @@ -5,7 +5,7 @@ body { margin: 0; background: transparent; color: #25282d; - font: 13px/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font: 13px/1.4 var(--pet-font); } body { diff --git a/src/quick-chat.html b/src/quick-chat.html index 6ea5e9a..62ecb5f 100644 --- a/src/quick-chat.html +++ b/src/quick-chat.html @@ -2,8 +2,10 @@
+ Quick Companion Input + diff --git a/src/renderer.js b/src/renderer.js index d14afb1..4808a52 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -8,6 +8,7 @@ const bubblePin = document.querySelector("#bubble-pin"); const bubbleDismiss = document.querySelector("#bubble-dismiss"); const lastReplyButton = document.querySelector("#last-reply"); const talkButton = document.querySelector("#talk"); +const petMenuButton = document.querySelector("#pet-menu"); const ctx = canvas.getContext("2d", { alpha: true }); const i18n = window.DesktopPetI18n; const SINGLE_CLICK_DELAY = 280; @@ -68,6 +69,7 @@ let didDrag = false; let clickTimer; let clickOnlyReadyAt = 0; let ignoreSingleClicksUntil = 0; +let interactionTicket = 0; let hoverReadyAt = 0; let bubbleTimer; let didShowStartupGreeting = false; @@ -81,6 +83,7 @@ let speechActive = false; let speechWatchdog; let conversationActive = false; let conversationAction = "idle"; +let lastReplyGestureId = null; let queuedNotice = null; let bubbleVisible = false; let interactionReadyAt = 0; @@ -104,7 +107,7 @@ function draw() { function applyPetLayout() { const availableScale = Math.min(Number.isFinite(window.innerWidth) ? window.innerWidth / 192 : Infinity, - Number.isFinite(window.innerHeight) ? Math.max(0, window.innerHeight - 160) / 208 : Infinity); + Number.isFinite(window.innerHeight) ? Math.max(0, window.innerHeight - 160 - (window.DesktopPetCompanionInput?.isOpen() ? 88 : 0)) / 208 : Infinity); const scale = Math.min(settings.scale, availableScale); const petWidth = Math.round(192 * scale); const petHeight = Math.round(208 * scale); @@ -114,6 +117,7 @@ function applyPetLayout() { function startAnimation() { window.clearInterval(animationTimer); + if (character.type === "live2d") return; const current = character.states[state] || character.states.idle; animationTimer = window.setInterval(() => { if (settings.expressionMode === "clickOnly" && !dragStart) { @@ -133,13 +137,17 @@ function setState(nextState) { if (!character.states[nextState]) return; if (state === nextState) return; state = nextState; + if (character.type === "live2d") { + if (settings.expressionMode === "automatic") window.DesktopPetModel?.expression(settings.persona?.live2dExpressions?.[nextState] ?? -1); + return; + } frameIndex = 0; startAnimation(); } function scheduleIdleBehavior() { window.clearTimeout(idleTimer); - if (settings.expressionMode !== "automatic" || conversationActive) return; + if (character.type === "live2d" || settings.expressionMode !== "automatic" || conversationActive) return; const delay = 22000 + Math.random() * 15000; idleTimer = window.setTimeout(() => { @@ -230,6 +238,7 @@ function applyAppState(nextAppState = {}) { interactionResponses: nextAppState.settings?.interactionResponses !== false, userName: nextAppState.settings?.persona?.userName || "", characterName: nextAppState.settings?.persona?.name || character.name, + persona: nextAppState.settings?.persona || {}, scale: Number(nextAppState.settings?.scale) || 1, alwaysOnTop: nextAppState.settings?.alwaysOnTop !== false, tts: { @@ -254,11 +263,23 @@ function applyAppState(nextAppState = {}) { if (bubbleVisible) hideBubbleLater(Math.max(3000, bubbleRemaining)); } activeLanguage = settings.resolvedLanguage; - talkButton.textContent = text("pet.talk"); talkButton.title = text("quick.toCharacter", { name: settings.characterName }); + talkButton.setAttribute("aria-label", talkButton.title); updateBubbleControls(); document.documentElement.lang = activeLanguage; applyPetLayout(); + window.DesktopPetModel?.apply(character, settings, conversationActive || speechActive); + + if (character.type === "live2d") { + ++spriteLoadToken; + spriteImage = null; + ctx.clearRect(0, 0, canvas.width, canvas.height); + window.clearInterval(animationTimer); + window.clearTimeout(idleTimer); + if (characterChanged || modeChanged) resetAfterSettingsChange(); + scheduleStartupGreeting(); + return; + } if (characterChanged || !spriteImage) { const token = ++spriteLoadToken; @@ -283,6 +304,7 @@ function applyAppState(nextAppState = {}) { } function resetAfterSettingsChange() { + interactionTicket++; window.clearTimeout(clickTimer); ignoreSingleClicksUntil = 0; clickOnlyReadyAt = 0; @@ -290,6 +312,11 @@ function resetAfterSettingsChange() { temporaryToken += 1; state = "idle"; frameIndex = 0; + if (character.type === "live2d") { + window.DesktopPetModel?.expression(-1); + scheduleStartupGreeting(); + return; + } if (settings.expressionMode === "clickOnly") { window.clearTimeout(idleTimer); const currentIndex = character.staticExpressions.findIndex((expression) => expression.state === "idle" && expression.frame === 0); @@ -305,15 +332,16 @@ function resetAfterSettingsChange() { function respondToInteraction(kind) { if (settings.expressionMode !== "automatic" || !settings.interactionResponses - || conversationActive || speechActive) return; + || conversationActive || speechActive || window.DesktopPetCompanionInput?.isOpen()) return; const choices = kind === "head" ? ["shy", "happy", "review", "idle"] : kind === "drop" ? ["tsundereProud", "happy", "waving", "idle"] : ["waving", "happy", "idle"]; const action = choices.find((name) => character.states[name]); - if (action) playTemporary(action, 1400); + if (character.type === "live2d") window.DesktopPetModel?.touch(kind); + else if (action) playTemporary(action, 1400); // Touches stay local and quiet; they neither replace a visible reply nor queue up. if (bubbleVisible || performance.now() < interactionReadyAt) return; interactionReadyAt = performance.now() + 6000; - const style = character.id === "luna" ? "luna" : "default"; + const style = settings.persona?.relationship === "partner" ? "partner" : character.id === "luna" ? "luna" : "default"; const variant = interactionVariants[kind]++ % 2; const line = text(`pet.interaction.${style}.${kind}.${variant}`); showBubble(settings.userName ? text("pet.interaction.address", { name: settings.userName, line }) : line); @@ -322,42 +350,53 @@ function respondToInteraction(kind) { function handleClick(kind = "greet") { window.desktopPet.recordInteraction("click"); if (settings.expressionMode === "clickOnly") { + if (character.type === "live2d") { window.DesktopPetModel?.cycle(); return; } const [nextState, nextFrame] = nextStaticExpression(); setStaticExpression(nextState, nextFrame); } else { - if (conversationActive || speechActive) return; + if (conversationActive || speechActive || window.DesktopPetCompanionInput?.isOpen()) return; if (settings.interactionResponses) { respondToInteraction(kind); return; } + if (character.type === "live2d") { window.DesktopPetModel?.touch(kind); return; } const nextState = nextClickState(); playTemporary(nextState); } } function handleDoubleClick() { + interactionTicket++; window.clearTimeout(clickTimer); - if (settings.expressionMode === "clickOnly" || conversationActive || speechActive) return; + if (character.type === "live2d" || settings.expressionMode === "clickOnly" || conversationActive || speechActive) return; ignoreSingleClicksUntil = performance.now() + 360; window.desktopPet.recordInteraction("doubleClick"); playTemporary("jumping", 1200); } -function handleLongPress() { +function handleLongPress(kind = "head") { window.clearTimeout(clickTimer); if (settings.expressionMode === "clickOnly" || conversationActive || speechActive) return; window.desktopPet.recordInteraction("longPress"); if (settings.interactionResponses) { - respondToInteraction("head"); + respondToInteraction(kind); + } else if (character.type === "live2d") { + window.DesktopPetModel?.touch(kind); } else { playTemporary("review", 1400); } } -function scheduleSingleClick(kind) { +function scheduleSingleClick(kind, point, longPress = false) { window.clearTimeout(clickTimer); const scheduledAt = performance.now(); - clickTimer = window.setTimeout(() => { + const token = ++interactionTicket; + clickTimer = window.setTimeout(async () => { if (scheduledAt < ignoreSingleClicksUntil) return; - handleClick(kind); - }, SINGLE_CLICK_DELAY); + if (character.type === "live2d" && point) { + kind = await window.DesktopPetModel?.locate(point.x, point.y); + if (!kind || token !== interactionTicket || dragStart || settings.expressionMode !== "automatic") return; + } + if (longPress) handleLongPress(kind); + else handleClick(kind); + }, longPress ? 0 : SINGLE_CLICK_DELAY); } function handleClickOnlyPointerClick() { @@ -369,6 +408,7 @@ function handleClickOnlyPointerClick() { function beginDrag(event) { if (event.button !== 0) return; + interactionTicket++; window.clearTimeout(clickTimer); const bounds = canvas.getBoundingClientRect(); dragStart = { @@ -376,6 +416,7 @@ function beginDrag(event) { y: event.screenY, time: performance.now(), kind: (event.clientY - bounds.top) / bounds.height < 0.46 ? "head" : "greet", + point: { x: (event.clientX - bounds.left) / bounds.width, y: (event.clientY - bounds.top) / bounds.height }, expression: { state, frame: frameIndex }, }; didDrag = false; @@ -393,6 +434,7 @@ function beginDrag(event) { } if (dragStart !== activeDrag) return; if (Math.abs(movement.dx) > 2 || Math.abs(movement.dy) > 2) { + if (!didDrag) window.DesktopPetModel?.dragging(true); didDrag = true; if (Math.abs(movement.dx) > 4) { setState(movement.dx > 0 ? "runningRight" : "runningLeft"); @@ -410,8 +452,9 @@ function endDrag(event) { canvas.classList.remove("dragging"); const heldDuration = performance.now() - dragStart.time; - const { kind, expression } = dragStart; + const { kind, point, expression, clickCount } = dragStart; dragStart = null; + window.DesktopPetModel?.dragging(false); if (didDrag) { didDrag = false; @@ -426,16 +469,19 @@ function endDrag(event) { } if (heldDuration > 450) { - if (settings.expressionMode !== "clickOnly") handleLongPress(); + if (settings.expressionMode !== "clickOnly") { + if (character.type === "live2d") scheduleSingleClick(kind, point, true); + else handleLongPress(); + } return; } if (settings.expressionMode === "clickOnly") { - if (event.detail > 1) return; + if (event.detail > 1 || clickCount > 1) return; handleClickOnlyPointerClick(); return; } if (event.detail > 1) return; - scheduleSingleClick(kind); + scheduleSingleClick(kind, point); } let bubbleDeadline = 0; @@ -454,7 +500,7 @@ function updateBubbleControls() { bubbleSpeaker.title = name; for (const [button, key] of [[bubbleReply, "pet.reply"], [bubbleHistory, "pet.openChat"], [bubblePin, bubblePinned ? "pet.unpinReply" : "pet.pinReply"], [bubbleDismiss, "pet.dismissReply"], - [lastReplyButton, "pet.lastReply"]]) { + [lastReplyButton, "pet.lastReply"], [petMenuButton, "pet.menu"]]) { button.title = text(key); button.setAttribute("aria-label", button.title); } @@ -474,6 +520,7 @@ function dismissBubble() { updateBubbleControls(); conversationActive = false; conversationAction = "idle"; + window.DesktopPetModel?.busy(speechActive); temporaryToken += 1; if (settings.expressionMode === "automatic" && !dragStart) setState("idle"); scheduleIdleBehavior(); @@ -555,10 +602,11 @@ bubblePin.addEventListener("click", () => { updateBubbleControls(); hideBubbleLater(Math.max(3000, bubbleRemaining)); }); -bubbleReply.addEventListener("click", () => window.desktopPet.openQuickChatWindow()); +bubbleReply.addEventListener("click", () => window.DesktopPetCompanionInput?.open()); bubbleHistory.addEventListener("click", () => window.desktopPet.openChatWindow()); lastReplyButton.addEventListener("click", () => window.desktopPet.showLastReply()); -talkButton.addEventListener("click", () => window.desktopPet.openQuickChatWindow()); +talkButton.addEventListener("click", () => window.DesktopPetCompanionInput?.toggle()); +petMenuButton.addEventListener("click", () => window.desktopPet.showContextMenu()); function finishSpeech(token, failed = false) { if (token !== speechToken) return; @@ -584,6 +632,8 @@ function chooseTtsVoice() { function stopSpeech(status = "idle") { speechToken += 1; speechActive = false; + window.DesktopPetModel?.stopMouth(); + window.DesktopPetModel?.busy(conversationActive); if (speechId !== null) window.desktopPet.speechStateChanged({ id: speechId, status }); speechId = null; window.clearTimeout(speechWatchdog); @@ -602,6 +652,7 @@ async function speakText(text) { const token = speechToken; if (!settings.tts?.enabled || settings.tts.provider === "none" || !String(text || "").trim()) return; speechActive = true; + window.DesktopPetModel?.busy(true); window.clearTimeout(bubbleTimer); try { const id = await window.desktopPet.beginSpeech(speechGeneration); @@ -630,6 +681,7 @@ async function speakText(text) { activeAudio.onended = playNext; activeAudio.onerror = () => finishSpeech(token, true); await activeAudio.play(); + if (token === speechToken) window.DesktopPetModel?.attachAudio(activeAudio); if (token === speechToken) window.desktopPet.speechStateChanged({ id, status: "playing" }); } else { if (!("speechSynthesis" in window)) { finishSpeech(token, true); return; } @@ -685,6 +737,7 @@ function handlePetMessage(message = {}) { if (isChat) { if (!conversationActive || (!wasStreaming && bubbleStreaming)) conversationAction = "idle"; conversationActive = true; + window.DesktopPetModel?.busy(true); if (action && character.states[action]) conversationAction = action; window.clearTimeout(idleTimer); temporaryToken += 1; @@ -697,6 +750,11 @@ function handlePetMessage(message = {}) { if (settings.expressionMode === "automatic" && !dragStart) { if (isChat) setState(conversationAction); else if (action && character.states[action]) playTemporary(action, Math.max(temporaryDuration(action), 1200)); + if (isChat && character.type === "live2d" && !message.streaming && message.replyMotion + && Number.isSafeInteger(message.presentationId) && message.presentationId !== lastReplyGestureId) { + lastReplyGestureId = message.presentationId; + window.DesktopPetModel?.replyMotion(message.replyMotion); + } } if (message.notification) window.desktopPet.presentNotification?.(message.notification); } @@ -730,14 +788,26 @@ function loadSprite(spritePath) { } canvas.addEventListener("pointerdown", beginDrag); +// PointerEvent.detail can be zero; mousedown retains the platform's click count. +canvas.addEventListener("mousedown", event => { if (dragStart) dragStart.clickCount = event.detail; }); +canvas.addEventListener("pointermove", (event) => { + if (dragStart || character.type !== "live2d") return; + const bounds = canvas.getBoundingClientRect(); + window.DesktopPetModel?.gaze((event.clientX - bounds.left) / bounds.width * 0.7 - 0.35, + 0.25 - (event.clientY - bounds.top) / bounds.height * 0.5); +}); +canvas.addEventListener("pointerleave", () => window.DesktopPetModel?.gaze(0, 0)); canvas.addEventListener("dblclick", handleDoubleClick); canvas.addEventListener("pointerenter", () => { + if (character.type === "live2d") return; if (settings.expressionMode !== "automatic" || conversationActive || dragStart || performance.now() < hoverReadyAt) return; hoverReadyAt = performance.now() + 10000; if (state === "idle") playTemporary("waving", 900); }); window.addEventListener("pointerup", endDrag); function cancelDrag() { + interactionTicket++; + window.DesktopPetModel?.dragging(false); if (!dragStart) return; const expression = dragStart.expression; dragStart = null; diff --git a/src/settings.css b/src/settings.css index 5179f2c..c2f9db6 100644 --- a/src/settings.css +++ b/src/settings.css @@ -5,7 +5,7 @@ body { margin: 0; background: #f6f7f9; color: #25282d; - font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + font: 14px/1.5 var(--pet-font); } body { @@ -330,3 +330,13 @@ button:focus-visible { outline: 2px solid #316e74; outline-offset: 2px; } #import-preview { border-left: 3px solid #316e74; padding: 12px; } #import-status { font-size: 12px; } .settings-footer div { flex-shrink: 0; } +.live2d-badge { + display: grid; + place-items: center; + width: 56px; + min-height: 90px; + color: #286770; + background: #eff8f8; + font-size: 14px; + border-radius: 4px; +} diff --git a/src/settings.html b/src/settings.html index 1a3a8ad..96239b6 100644 --- a/src/settings.html +++ b/src/settings.html @@ -2,8 +2,10 @@ + Desktop Pet Settings + @@ -46,6 +48,7 @@

角色

+