From ab502f44ef9bc13fe831eacbf56d5a015d8051b7 Mon Sep 17 00:00:00 2001 From: Git Manager GUI Date: Sat, 1 Aug 2026 07:03:08 +0200 Subject: [PATCH] Upload via GUI (19 Dateien) --- README.md | 42 +- package-lock.json | 4185 ++++++++++++++++++++++++++++++++++++++ package.json | 36 + smoke.err.txt | 1 + smoke.out.txt | 1 + src/assets/logo.png | Bin 0 -> 44708 bytes src/assets/logo.svg | 38 + src/auth.js | 333 +++ src/forge.js | 232 +++ src/index.html | 514 +++++ src/launcher.js | 455 +++++ src/loaders.js | 103 + src/main.js | 614 ++++++ src/preload.js | 93 + src/renderer.js | 1488 ++++++++++++++ src/services.js | 263 +++ src/store.js | 308 +++ src/styles.css | 302 +++ src/vendor/skinview3d.js | 1996 ++++++++++++++++++ 19 files changed, 10983 insertions(+), 21 deletions(-) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 smoke.err.txt create mode 100644 smoke.out.txt create mode 100644 src/assets/logo.png create mode 100644 src/assets/logo.svg create mode 100644 src/auth.js create mode 100644 src/forge.js create mode 100644 src/index.html create mode 100644 src/launcher.js create mode 100644 src/loaders.js create mode 100644 src/main.js create mode 100644 src/preload.js create mode 100644 src/renderer.js create mode 100644 src/services.js create mode 100644 src/store.js create mode 100644 src/styles.css create mode 100644 src/vendor/skinview3d.js diff --git a/README.md b/README.md index 04cc35d..879b8e4 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@
-Viper-Network Logo +AeroMC Logo -# Viper-Network Launcher +# AeroMC **Ein instanz-basierter Minecraft-Launcher für Windows – à la MultiMC / Prism.** Verwalte beliebig viele isolierte Minecraft-Instanzen mit eigener Version, eigenen Mods und eigenem Java – lade Mods per Ein-Klick von Modrinth, melde dich mit deinem Microsoft-Konto an und spiele. -![Version](https://img.shields.io/badge/version-0.6.0-2b8bff) -![Platform](https://img.shields.io/badge/platform-Windows%20x64-2b8bff) -![Electron](https://img.shields.io/badge/Electron-28-2b8bff) -![License](https://img.shields.io/badge/license-MIT-e23a3f) +![Version](https://img.shields.io/badge/version-0.19.0-3a7bc8) +![Platform](https://img.shields.io/badge/platform-Windows%20x64-3a7bc8) +![Electron](https://img.shields.io/badge/Electron-28-3a7bc8) +![License](https://img.shields.io/badge/license-MIT-777)
@@ -29,18 +29,21 @@ Verwalte beliebig viele isolierte Minecraft-Instanzen mit eigener Version, eigen | **Mods** | Modrinth-Browser mit **Ein-Klick-Installation** in die Instanz | ✅ | | **Login** | Offizieller Microsoft-Login (Device-Code-Flow) mit **Mehrkonten-Verwaltung** | ✅ | | **Start** | Vanilla-Download (Client, Libraries, Natives, Assets) & Start | ✅ | -| **Loader** | **Fabric** & **Quilt** installieren & starten | ✅ | -| **Loader** | **Forge** & **NeoForge** | ⏳ in Arbeit | +| **Loader** | **Fabric, Quilt, Forge & NeoForge** installieren & starten | ✅ | +| **Mods** | Katalog mit Kategorien/Sortierung + automatische Abhängigkeiten | ✅ | +| **Modpacks** | Import von Modrinth-Modpacks (.mrpack) | ✅ | +| **Instanzen** | Gruppen, Drag & Drop, Import/Export, Screenshots, Welten | ✅ | +| **Launcher** | Dark/Light-Theme, Konsole mit Log-Highlighting, Spielzeit-Statistik | ✅ | --- ## 🎮 Bedienung 1. **+ Neue Instanz** → Name, Minecraft-Version und optional einen Mod-Loader (Fabric/Quilt) wählen. -2. Instanz anklicken → Detailansicht mit **▶ Spielen**, **🧩 Mods**, Bearbeiten, Ordner, Duplizieren, Löschen. -3. **🧩 Mods** → Modrinth durchsuchen und mit einem Klick installieren (passend zu Version + Loader). -4. **👤 Anmelden** (oben rechts) → Microsoft-Konto hinzufügen (mehrere möglich, aktives Konto spielt). -5. **▶ Spielen** → Der Launcher lädt alles Nötige und startet Minecraft mit deinem Konto. +2. Instanz anklicken → rechts erscheinen alle Aktionen (Starten, Bearbeiten, Mods, Welten …). Doppelklick startet direkt. +3. **Mods anzeigen** → Katalog mit beliebten Mods; ein Klick installiert die Mod inklusive aller Abhängigkeiten. +4. **Konten** (oben rechts) → Microsoft-Konto hinzufügen (mehrere möglich, aktives Konto spielt). +5. **Starten** → Der Launcher lädt alles Nötige und startet Minecraft mit deinem Konto. > 💡 **Parallel spielen:** Konto A aktivieren → starten → Konto B aktivieren → starten. Jeder Start ist ein eigener Prozess, so laufen mehrere Clients mit verschiedenen Accounts gleichzeitig. @@ -52,7 +55,7 @@ Der Launcher bringt bereits eine **eingebaute Azure-App-ID** mit – Endnutzer m > ⚠️ **Wichtiger Hinweis zur Freischaltung:** Seit 2024 müssen **neu registrierte** Azure-Apps von Microsoft/Mojang freigeschaltet werden, bevor sie sich bei den Minecraft-Diensten anmelden dürfen. Bis zur Freigabe endet der Login mit `Invalid app registration (403)`. Die Freischaltung wird über das offizielle Formular **[aka.ms/mce-reviewappid](https://aka.ms/mce-reviewappid)** beantragt. Der Launcher-Code ist vollständig – sobald die App-ID freigeschaltet ist, funktioniert der Login ohne weitere Änderungen. -**Eigene Azure-App verwenden (optional):** In den ⚙ Einstellungen lässt sich eine eigene Client-ID hinterlegen. Anforderungen: +**Eigene Azure-App verwenden (optional):** In den Optionen lässt sich eine eigene Client-ID hinterlegen. Anforderungen: - Kontotyp: **Nur persönliche Microsoft-Konten** - Authentifizierung → **„Öffentliche Clientflows zulassen" = Ja** - Freischaltung über [aka.ms/mce-reviewappid](https://aka.ms/mce-reviewappid) @@ -63,7 +66,7 @@ Der Login nutzt ausschließlich den offiziellen Microsoft-OAuth-Flow (echtes Kon ## 🗂️ Datenspeicherorte -Alle Nutzerdaten liegen unter `%APPDATA%\Viper-Network\` (im Dev-Modus `%APPDATA%\viper-network\`): +Alle Nutzerdaten liegen unter `%APPDATA%\AeroMC\` (im Dev-Modus `%APPDATA%\aeromc\`): | Pfad | Inhalt | |---|---| @@ -79,12 +82,9 @@ Alle Nutzerdaten liegen unter `%APPDATA%\Viper-Network\` (im Dev-Modus `%APPDATA ## 🗺️ Roadmap -- [ ] Forge & NeoForge (Installer mit Prozessoren) -- [ ] „Starten als [Konto]" direkt an der Instanz -- [ ] Loader-Versionsauswahl im Dialog -- [ ] Skins/Avatare in der Kontoliste -- [ ] Instanz-Gruppen & Sortierung -- [ ] Import/Export von Instanzen (Modpacks) +- [ ] Shader- und Ressourcenpakete über den Katalog +- [ ] CurseForge-Modpacks (braucht API-Key) +- [ ] Automatische Mod-Updates --- @@ -95,4 +95,4 @@ Dieses Projekt steht in **keiner** Verbindung zu Mojang, Microsoft oder Xbox und ## 📄 Lizenz -MIT © Viper-Network +MIT diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..81b2218 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4185 @@ +{ + "name": "aeromc", + "version": "0.24.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "aeromc", + "version": "0.24.0", + "license": "MIT", + "dependencies": { + "skinview3d": "^3.4.2", + "undici": "^6.28.0" + }, + "devDependencies": { + "electron": "^28.0.0", + "electron-builder": "^24.0.0" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stats.js": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz", + "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==", + "license": "MIT" + }, + "node_modules/@types/three": { + "version": "0.156.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.156.0.tgz", + "integrity": "sha512-733bXDSRdlrxqOmQuOmfC1UBRuJ2pREPk8sWnx9MtIJEVDQMx8U0NQO5MVVaOrjzDPyLI+cFPim2X/ss9v0+LQ==", + "license": "MIT", + "dependencies": { + "@types/stats.js": "*", + "@types/webxr": "*", + "fflate": "~0.6.10", + "meshoptimizer": "~0.18.1" + } + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/webxr": { + "version": "0.5.24", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", + "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==", + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.3.tgz", + "integrity": "sha512-DRdx5neNsG/QXbniLFWi2YmC/68oeOOmKz6zOjVk6ZS1ZLXgLIKqVEc6hWsmkjBbgii0SwaBTcJ5XKj5gzY/4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "28.3.3", + "resolved": "https://registry.npmjs.org/electron/-/electron-28.3.3.tgz", + "integrity": "sha512-ObKMLSPNhomtCOBAxFS8P2DW/4umkh72ouZUlUKzXGtYuPzgr1SYhskhFWgzAsPtUzhL2CzyV2sfbHcEW4CXqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^18.11.18", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fflate": { + "version": "0.6.11", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.11.tgz", + "integrity": "sha512-3JyEFWGjFn7zHmoa9+zG1BmW7X2okcmAB+0Cnu9UFbVs/jCBnl2A8o065ZlXiw145K3eBM3uLuzrYXC0RK7eDg==", + "license": "MIT" + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/isbinaryfile": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/meshoptimizer": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==", + "license": "MIT" + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peer": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.4.tgz", + "integrity": "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/skinview-utils": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/skinview-utils/-/skinview-utils-0.7.1.tgz", + "integrity": "sha512-4eLrMqR526ehlZbsd8SuZ/CHpS9GiH0xUMoV+PYlJVi95ZFz5HJu7Spt5XYa72DRS7wgt5qquvHZf0XZJgmu9Q==", + "license": "MIT" + }, + "node_modules/skinview3d": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/skinview3d/-/skinview3d-3.4.2.tgz", + "integrity": "sha512-nwxTmT+OWCckDu5CsbjFnyOqthNjl9Fahjqzyy55qcl6jXHIjMrmvDj0b1VZFvT39UKYuO1gnzAQicQ1TH4hvg==", + "license": "MIT", + "dependencies": { + "@types/three": "^0.156.0", + "skinview-utils": "^0.7.1", + "three": "^0.156.0" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/three": { + "version": "0.156.1", + "resolved": "https://registry.npmjs.org/three/-/three-0.156.1.tgz", + "integrity": "sha512-kP7H0FK9d/k6t/XvQ9FO6i+QrePoDcNhwl0I02+wmUJRNSLCUIDMcfObnzQvxb37/0Uc9TDT0T1HgsRRrO6SYQ==", + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..50c1486 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "aeromc", + "version": "0.29.0", + "description": "AeroMC – Instanz-basierter Minecraft-Launcher (à la MultiMC/Prism)", + "main": "src/main.js", + "author": "AeroMC", + "license": "MIT", + "scripts": { + "start": "electron .", + "build": "electron-builder --win --x64" + }, + "build": { + "appId": "com.aeromc.launcher", + "productName": "AeroMC", + "files": [ + "src/**/*", + "package.json" + ], + "win": { + "target": "nsis", + "icon": "src/assets/icon.ico" + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true + } + }, + "devDependencies": { + "electron": "^28.0.0", + "electron-builder": "^24.0.0" + }, + "dependencies": { + "skinview3d": "^3.4.2", + "undici": "^6.28.0" + } +} diff --git a/smoke.err.txt b/smoke.err.txt new file mode 100644 index 0000000..7c76b1e --- /dev/null +++ b/smoke.err.txt @@ -0,0 +1 @@ +[23964:0801/065610.401:ERROR:network_service_instance_impl.cc(601)] Network service crashed, restarting service. diff --git a/smoke.out.txt b/smoke.out.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/smoke.out.txt @@ -0,0 +1 @@ + diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f72cd7018fb482d3273f120e94d8b41c9373c8 GIT binary patch literal 44708 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 literal 0 HcmV?d00001 diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..d260d67 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/auth.js b/src/auth.js new file mode 100644 index 0000000..51ecc09 --- /dev/null +++ b/src/auth.js @@ -0,0 +1,333 @@ +'use strict'; + +/* + * auth.js – offizieller Microsoft-Login für Minecraft (Phase 3) + * ------------------------------------------------------------- + * Ablauf (Device-Code-Flow, wie bei Prism/MultiMC): + * 1. Microsoft OAuth Device-Code -> MS access_token + refresh_token + * 2. Xbox-Live-Authentifizierung -> XBL-Token + userhash + * 3. XSTS-Autorisierung -> XSTS-Token + * 4. Minecraft-Login -> MC access_token + * 5. Minecraft-Profil -> UUID + Name (prüft zugleich den Besitz) + * + * Erfordert eine kostenlose Azure-App-ID (öffentlicher Client, Device-Flow). + * Wir bauen KEINEN Offline-/Crack-Login – ohne echtes Konto kein Start. + */ + +const fs = require('fs'); +const path = require('path'); + +// Fest eingebaute Azure-App-ID des Launchers (öffentlicher Client – kein Geheimnis). +// Jeder Nutzer meldet sich damit über SEIN eigenes Microsoft-Konto an. +// Über die Einstellungen lässt sich bei Bedarf eine eigene ID hinterlegen. +const DEFAULT_CLIENT_ID = '0625f4a8-dfff-4eab-8124-a573b00b0319'; + +const SCOPE = 'XboxLive.signin offline_access'; +// Manche Endpunkte (v. a. api.minecraftservices.com hinter Cloudflare) lehnen +// Anfragen ohne User-Agent mit HTTP 403 ab -> überall mitsenden. +const UA = 'AeroMC-Launcher/0.5'; +const DEVICECODE_URL = 'https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode'; +const TOKEN_URL = 'https://login.microsoftonline.com/consumers/oauth2/v2.0/token'; +const XBL_URL = 'https://user.auth.xboxlive.com/user/authenticate'; +const XSTS_URL = 'https://xsts.auth.xboxlive.com/xsts/authorize'; +const MC_LOGIN_URL = 'https://api.minecraftservices.com/authentication/login_with_xbox'; +const MC_PROFILE_URL = 'https://api.minecraftservices.com/minecraft/profile'; + +let USER_DATA = null; +let SECURE = null; // optionaler Verschlüsseler (Electron safeStorage) + +function init(userDataPath, secure) { + USER_DATA = userDataPath; + SECURE = secure && secure.available && secure.available() ? secure : null; + migrateLegacy(); + if (SECURE) { try { writeStore(readStore()); } catch { /* Migration best effort */ } } +} + +// sensible Felder verschlüsselt ablegen (an das Windows-Benutzerkonto gebunden) +const SENSITIVE = ['mcAccessToken', 'msRefreshToken']; +const ENC = 'enc:v1:'; +function protect(acc) { + if (!SECURE) return acc; + const out = Object.assign({}, acc); + for (const k of SENSITIVE) { + const v = out[k]; + if (typeof v === 'string' && v && !v.startsWith(ENC)) { + try { out[k] = ENC + SECURE.encrypt(v); } catch { /* unverschlüsselt lassen */ } + } + } + return out; +} +function unprotect(acc) { + const out = Object.assign({}, acc); + for (const k of SENSITIVE) { + const v = out[k]; + if (typeof v === 'string' && v.startsWith(ENC)) { + try { out[k] = SECURE ? SECURE.decrypt(v.slice(ENC.length)) : null; } catch { out[k] = null; } + } + } + return out; +} +function accountsFile() { return path.join(USER_DATA, 'accounts.json'); } +function legacyFile() { return path.join(USER_DATA, 'account.json'); } + +// Speicherform: { activeId, accounts: [ {profile,mcAccessToken,mcExpiresAt,msRefreshToken,updatedAt}, ... ] } +function readStore() { + try { + const s = JSON.parse(fs.readFileSync(accountsFile(), 'utf8')); + if (s && Array.isArray(s.accounts)) { + return { activeId: s.activeId, accounts: s.accounts.map(unprotect) }; + } + } catch { /* leer */ } + return { activeId: null, accounts: [] }; +} +function writeStore(s) { + const safe = { activeId: s.activeId, accounts: (s.accounts || []).map(protect) }; + fs.writeFileSync(accountsFile(), JSON.stringify(safe, null, 2)); +} + +// altes Einzelkonto (account.json) übernehmen +function migrateLegacy() { + try { + if (fs.existsSync(accountsFile())) return; + const old = JSON.parse(fs.readFileSync(legacyFile(), 'utf8')); + if (old && old.profile) { + writeStore({ activeId: old.profile.id, accounts: [old] }); + try { fs.unlinkSync(legacyFile()); } catch { /* egal */ } + } + } catch { /* nichts zu migrieren */ } +} + +function upsertAccount(acc) { + const s = readStore(); + s.accounts = s.accounts.filter((a) => a.profile.id !== acc.profile.id); + s.accounts.push(acc); + s.activeId = acc.profile.id; // frisch eingeloggtes/erneuertes Konto wird aktiv + writeStore(s); + return acc; +} + +function listAccounts() { + const s = readStore(); + return s.accounts.map((a) => ({ id: a.profile.id, name: a.profile.name, active: a.profile.id === s.activeId })); +} + +function setActive(id) { + const s = readStore(); + if (s.accounts.some((a) => a.profile.id === id)) { s.activeId = id; writeStore(s); } + return listAccounts(); +} + +function removeAccount(id) { + const s = readStore(); + s.accounts = s.accounts.filter((a) => a.profile.id !== id); + if (s.activeId === id) s.activeId = s.accounts[0] ? s.accounts[0].profile.id : null; + writeStore(s); + return listAccounts(); +} + +function getAccountById(id) { + return readStore().accounts.find((a) => a.profile.id === id) || null; +} +function getActiveRaw() { + const s = readStore(); + return s.accounts.find((a) => a.profile.id === s.activeId) || null; +} +function clearAccount() { try { fs.unlinkSync(accountsFile()); } catch { /* egal */ } } + +async function postForm(url, params) { + const res = await fetch(url, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': UA, Accept: 'application/json' }, + body: new URLSearchParams(params).toString(), + }); + const data = await res.json().catch(() => ({})); + return { status: res.status, data }; +} + +async function postJson(url, body, headers = {}) { + const res = await fetch(url, { + method: 'POST', + headers: Object.assign({ 'Content-Type': 'application/json', Accept: 'application/json', 'User-Agent': UA }, headers), + body: JSON.stringify(body), + }); + const data = await res.json().catch(() => ({})); + return { status: res.status, data }; +} + +// --------------------------------------------------------------------------- +// 1. Device-Code anfordern +// --------------------------------------------------------------------------- + +async function requestDeviceCode(clientId) { + if (!clientId) throw new Error('Keine Azure-Client-ID gesetzt (Einstellungen → Microsoft-Login).'); + const { status, data } = await postForm(DEVICECODE_URL, { client_id: clientId, scope: SCOPE }); + if (status !== 200) { + throw new Error('Device-Code fehlgeschlagen: ' + (data.error_description || data.error || status)); + } + return data; // { user_code, device_code, verification_uri, expires_in, interval, message } +} + +// --------------------------------------------------------------------------- +// 2. Auf Autorisierung warten (pollt Token-Endpoint) +// --------------------------------------------------------------------------- + +async function pollForToken(clientId, deviceCode, intervalSec, onTick) { + let interval = Math.max(intervalSec || 5, 3); + const deadline = Date.now() + 15 * 60 * 1000; + while (Date.now() < deadline) { + await sleep(interval * 1000); + const { data } = await postForm(TOKEN_URL, { + grant_type: 'urn:ietf:params:oauth:grant-type:device_code', + client_id: clientId, + device_code: deviceCode, + }); + if (data.access_token) return data; // { access_token, refresh_token, expires_in } + if (data.error === 'authorization_pending') { onTick && onTick(); continue; } + if (data.error === 'slow_down') { interval += 5; continue; } + if (data.error === 'authorization_declined') throw new Error('Anmeldung abgelehnt.'); + if (data.error === 'expired_token') throw new Error('Code abgelaufen – bitte erneut anmelden.'); + throw new Error('Login-Fehler: ' + (data.error_description || data.error)); + } + throw new Error('Zeitüberschreitung – Code nicht rechtzeitig bestätigt.'); +} + +function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); } + +// --------------------------------------------------------------------------- +// 3.–5. Xbox -> XSTS -> Minecraft -> Profil +// --------------------------------------------------------------------------- + +async function xboxLogin(msAccessToken) { + const { status, data } = await postJson(XBL_URL, { + Properties: { AuthMethod: 'RPS', SiteName: 'user.auth.xboxlive.com', RpsTicket: 'd=' + msAccessToken }, + RelyingParty: 'http://auth.xboxlive.com', + TokenType: 'JWT', + }); + if (status !== 200 || !data.Token) { + throw new Error('Xbox-Live-Login fehlgeschlagen (' + status + ')' + (data && data.Message ? ': ' + data.Message : '') + '.'); + } + const uhs = data.DisplayClaims && data.DisplayClaims.xui && data.DisplayClaims.xui[0] && data.DisplayClaims.xui[0].uhs; + return { token: data.Token, uhs }; +} + +async function xstsAuth(xblToken) { + const { status, data } = await postJson(XSTS_URL, { + Properties: { SandboxId: 'RETAIL', UserTokens: [xblToken] }, + RelyingParty: 'rp://api.minecraftservices.com/', + TokenType: 'JWT', + }); + if (status === 401) { + const xerr = data.XErr; + if (xerr === 2148916233) throw new Error('Dieses Microsoft-Konto hat kein Xbox-Profil. Bitte einmal auf xbox.com anmelden.'); + if (xerr === 2148916238) throw new Error('Kinderkonto – muss einer Familie hinzugefügt werden.'); + throw new Error('XSTS-Autorisierung abgelehnt (XErr ' + xerr + ').'); + } + if (status !== 200 || !data.Token) throw new Error('XSTS-Autorisierung fehlgeschlagen (' + status + ').'); + return { token: data.Token }; +} + +async function minecraftLogin(uhs, xstsToken) { + const { status, data } = await postJson(MC_LOGIN_URL, { + identityToken: `XBL3.0 x=${uhs};${xstsToken}`, + }); + if (status !== 200 || !data.access_token) { + const detail = data && (data.errorMessage || data.error || data.path) ? ': ' + (data.errorMessage || data.error || data.path) : ''; + throw new Error('Minecraft-Login fehlgeschlagen (' + status + ')' + detail + '.'); + } + return { accessToken: data.access_token, expiresIn: data.expires_in || 86400 }; +} + +async function minecraftProfile(mcAccessToken) { + const res = await fetch(MC_PROFILE_URL, { + headers: { Authorization: 'Bearer ' + mcAccessToken, 'User-Agent': UA, Accept: 'application/json' }, + }); + if (res.status === 404) throw new Error('Dieses Konto besitzt kein Minecraft (Java Edition).'); + if (!res.ok) throw new Error('Profil laden fehlgeschlagen (' + res.status + ').'); + const data = await res.json(); + return { id: data.id, name: data.name }; // id = UUID ohne Bindestriche +} + +// vollständige Kette ab MS-Token -> gespeichertes Konto +async function completeFromMsToken(msToken) { + const xbl = await xboxLogin(msToken.access_token); + const xsts = await xstsAuth(xbl.token); + const mc = await minecraftLogin(xbl.uhs, xsts.token); + const profile = await minecraftProfile(mc.accessToken); + + return { + profile, // { id, name } + mcAccessToken: mc.accessToken, + mcExpiresAt: Date.now() + (mc.expiresIn - 60) * 1000, + msRefreshToken: msToken.refresh_token || null, + updatedAt: new Date().toISOString(), + }; +} + +// ersetzt ein Konto in der Liste, ohne das aktive Konto zu ändern (für Token-Refresh) +function updateAccount(acc) { + const s = readStore(); + s.accounts = s.accounts.filter((a) => a.profile.id !== acc.profile.id); + s.accounts.push(acc); + writeStore(s); + return acc; +} + +// --------------------------------------------------------------------------- +// Öffentliche Login-Orchestrierung +// --------------------------------------------------------------------------- + +/* + * startLogin: fordert Device-Code an und ruft danach den Callback mit dem Code. + * Läuft dann im Hintergrund bis zur Bestätigung. Gibt am Ende das Konto zurück. + */ +async function login(clientId, onCode, onTick) { + const dc = await requestDeviceCode(clientId); + onCode && onCode({ + userCode: dc.user_code, + verificationUri: dc.verification_uri, + message: dc.message, + expiresIn: dc.expires_in, + }); + const msToken = await pollForToken(clientId, dc.device_code, dc.interval, onTick); + const account = await completeFromMsToken(msToken); + return upsertAccount(account); // neues Konto speichern + aktiv setzen +} + +// ein Konto gültig machen (Token ggf. per Refresh erneuern) +async function refreshAccount(clientId, acc) { + if (acc.mcAccessToken && acc.mcExpiresAt && Date.now() < acc.mcExpiresAt) return acc; + if (acc.msRefreshToken && clientId) { + const { data } = await postForm(TOKEN_URL, { + grant_type: 'refresh_token', + client_id: clientId, + refresh_token: acc.msRefreshToken, + scope: SCOPE, + }); + if (data.access_token) { + try { + const fresh = await completeFromMsToken(data); + if (!fresh.msRefreshToken) fresh.msRefreshToken = acc.msRefreshToken; + return updateAccount(fresh); + } catch { return null; } + } + } + return null; +} + +// aktives Konto gültig holen (null wenn kein Login) +async function getValidAccount(clientId) { + const acc = getActiveRaw(); + return acc ? refreshAccount(clientId, acc) : null; +} +// bestimmtes Konto gültig holen (für „starten als …") +async function getValidAccountById(clientId, id) { + const acc = getAccountById(id); + return acc ? refreshAccount(clientId, acc) : null; +} + +function currentAccount() { return getActiveRaw(); } + +module.exports = { + init, login, getValidAccount, getValidAccountById, currentAccount, clearAccount, + listAccounts, setActive, removeAccount, DEFAULT_CLIENT_ID, +}; diff --git a/src/forge.js b/src/forge.js new file mode 100644 index 0000000..3e44623 --- /dev/null +++ b/src/forge.js @@ -0,0 +1,232 @@ +'use strict'; + +/* + * forge.js – Forge/NeoForge-Installation (Installer + Prozessoren) + * ---------------------------------------------------------------- + * Anders als Fabric/Quilt liefern Forge/NeoForge einen Installer-JAR mit: + * - install_profile.json (processors, data, libraries für die Installation) + * - version.json (Laufzeit-Profil: mainClass, libraries, arguments) + * - data/…, maven/… (gebündelte Dateien/Bibliotheken) + * + * Ablauf: Installer laden → Profile extrahieren → Libraries laden/entpacken → + * data-Tokens auflösen → Prozessoren als Java-Prozesse ausführen (patchen den + * Client) → version.json zurückgeben (wird mit der Vanilla-Version gemerged). + * + * Die Prozessoren sind reine Java-Subprozesse – daher ohne Login testbar. + */ + +const fs = require('fs'); +const path = require('path'); +const zlib = require('zlib'); +const { spawnSync } = require('child_process'); + +const UA = 'AeroMC-Launcher/0.8'; + +function ensureDir(d) { fs.mkdirSync(d, { recursive: true }); } + +// ---------- ZIP-Leser (liest gezielt Einträge aus dem Installer) ---------- + +function readZipIndex(buf) { + let eocd = -1; + for (let i = buf.length - 22; i >= 0 && i > buf.length - 22 - 65536; i--) { + if (buf.readUInt32LE(i) === 0x06054b50) { eocd = i; break; } + } + if (eocd < 0) throw new Error('Installer ist kein gültiges ZIP.'); + const count = buf.readUInt16LE(eocd + 10); + let off = buf.readUInt32LE(eocd + 16); + const entries = {}; + for (let n = 0; n < count; n++) { + if (buf.readUInt32LE(off) !== 0x02014b50) break; + const method = buf.readUInt16LE(off + 10); + const compSize = buf.readUInt32LE(off + 20); + const nameLen = buf.readUInt16LE(off + 28); + const extraLen = buf.readUInt16LE(off + 30); + const commentLen = buf.readUInt16LE(off + 32); + const localOff = buf.readUInt32LE(off + 42); + const name = buf.toString('utf8', off + 46, off + 46 + nameLen).replace(/\\/g, '/'); + entries[name] = { method, compSize, localOff }; + off += 46 + nameLen + extraLen + commentLen; + } + return entries; +} + +function readZipEntry(buf, e) { + const lNameLen = buf.readUInt16LE(e.localOff + 26); + const lExtraLen = buf.readUInt16LE(e.localOff + 28); + const start = e.localOff + 30 + lNameLen + lExtraLen; + const raw = buf.subarray(start, start + e.compSize); + return e.method === 0 ? Buffer.from(raw) : zlib.inflateRawSync(raw); +} + +// ---------- Maven-Koordinaten -> Pfad ---------- + +// "group:artifact:version[:classifier][@ext]" +function mavenPath(coord) { + let ext = 'jar'; + let c = coord; + const at = c.indexOf('@'); + if (at >= 0) { ext = c.slice(at + 1); c = c.slice(0, at); } + const parts = c.split(':'); + const group = parts[0].replace(/\./g, '/'); + const artifact = parts[1]; + const version = parts[2]; + const classifier = parts[3] ? '-' + parts[3] : ''; + return `${group}/${artifact}/${version}/${artifact}-${version}${classifier}.${ext}`; +} + +async function fetchBuffer(url) { + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('Download HTTP ' + res.status + ': ' + url); + return Buffer.from(await res.arrayBuffer()); +} + +function installerUrl(loader, mcVersion, loaderVersion) { + if (loader === 'forge') { + const v = `${mcVersion}-${loaderVersion}`; + return `https://maven.minecraftforge.net/net/minecraftforge/forge/${v}/forge-${v}-installer.jar`; + } + return `https://maven.neoforged.net/releases/net/neoforged/neoforge/${loaderVersion}/neoforge-${loaderVersion}-installer.jar`; +} + +// Main-Class aus dem MANIFEST einer JAR lesen +function jarMainClass(jarPath) { + try { + const buf = fs.readFileSync(jarPath); + const idx = readZipIndex(buf); + const e = idx['META-INF/MANIFEST.MF']; + if (!e) return null; + const mf = readZipEntry(buf, e).toString('utf8').replace(/\r?\n /g, ''); + const m = mf.match(/Main-Class:\s*(\S+)/); + return m ? m[1] : null; + } catch { return null; } +} + +// ---------- Hauptfunktion ---------- + +/* + * opts: { loader, mcVersion, loaderVersion, sharedDir, javaPath, clientJar, onProgress } + * Gibt das Laufzeit-version.json (mit inheritsFrom = Vanilla) zurück. + */ +async function installForge(opts) { + const { loader, mcVersion, loaderVersion, sharedDir, javaPath, clientJar } = opts; + const onProgress = opts.onProgress || (() => {}); + const libDir = path.join(sharedDir, 'libraries'); + const java = javaPath && javaPath.trim() ? javaPath : 'java'; + + onProgress({ phase: 'loader', detail: `${loader} ${loaderVersion} – Installer laden …` }); + const buf = await fetchBuffer(installerUrl(loader, mcVersion, loaderVersion)); + const zip = readZipIndex(buf); + + if (!zip['install_profile.json']) throw new Error('install_profile.json fehlt im Installer.'); + const profile = JSON.parse(readZipEntry(buf, zip['install_profile.json']).toString('utf8')); + const versionEntryName = (profile.json || '/version.json').replace(/^\//, ''); + const vjEntry = zip[versionEntryName] || zip['version.json']; + if (!vjEntry) throw new Error('version.json fehlt im Installer.'); + const versionJson = JSON.parse(readZipEntry(buf, vjEntry).toString('utf8')); + + // version.json ablegen + const vjDir = path.join(sharedDir, 'versions', versionJson.id); + ensureDir(vjDir); + fs.writeFileSync(path.join(vjDir, versionJson.id + '.json'), JSON.stringify(versionJson)); + + // Installer-JAR ablegen (Prozessoren referenzieren ihn evtl. als {INSTALLER}) + const installerPath = path.join(vjDir, 'installer.jar'); + fs.writeFileSync(installerPath, buf); + + // --- Libraries laden: aus install_profile UND version.json --- + const allLibs = [...(profile.libraries || []), ...(versionJson.libraries || [])]; + let li = 0; + for (const lib of allLibs) { + li++; + onProgress({ phase: 'loader', current: li, total: allLibs.length, detail: lib.name }); + const art = lib.downloads && lib.downloads.artifact; + const rel = (art && art.path) || mavenPath(lib.name); + const dest = path.join(libDir, rel.replace(/\//g, path.sep)); + if (fs.existsSync(dest)) continue; + if (art && art.url) { + const data = await fetchBuffer(art.url); + ensureDir(path.dirname(dest)); + fs.writeFileSync(dest, data); + } else { + // im Installer gebündelt: maven/ + const bundled = zip['maven/' + rel]; + if (bundled) { + ensureDir(path.dirname(dest)); + fs.writeFileSync(dest, readZipEntry(buf, bundled)); + } + // sonst: wird von den Prozessoren erzeugt + } + } + + // --- data-Tokens auflösen --- + const extractDir = path.join(vjDir, 'installer-data'); + ensureDir(extractDir); + const data = {}; + for (const [key, val] of Object.entries(profile.data || {})) { + let cv = val.client; + if (cv == null) continue; + if (cv.startsWith('[') && cv.endsWith(']')) { + data[key] = path.join(libDir, mavenPath(cv.slice(1, -1)).replace(/\//g, path.sep)); + } else if (cv.startsWith('/')) { + const entryName = cv.slice(1); + const e = zip[entryName]; + if (e) { + const out = path.join(extractDir, entryName.replace(/\//g, path.sep)); + ensureDir(path.dirname(out)); + fs.writeFileSync(out, readZipEntry(buf, e)); + data[key] = out; + } else { data[key] = cv; } + } else { + data[key] = cv; + } + } + + // Client-Mappings von Mojang bereitstellen (Forge-Prozessoren brauchen sie) + if (data.MAPPINGS && !fs.existsSync(data.MAPPINGS) && opts.clientMappingsUrl) { + ensureDir(path.dirname(data.MAPPINGS)); + fs.writeFileSync(data.MAPPINGS, await fetchBuffer(opts.clientMappingsUrl)); + } + + // --- Token-Auflösung für Prozessor-Argumente --- + const resolveArg = (a) => { + if (a.startsWith('[') && a.endsWith(']')) { + return path.join(libDir, mavenPath(a.slice(1, -1)).replace(/\//g, path.sep)); + } + return a.replace(/\{([^}]+)\}/g, (_, k) => { + if (k === 'SIDE') return 'client'; + if (k === 'MINECRAFT_JAR') return clientJar; + if (k === 'ROOT') return sharedDir; + if (k === 'INSTALLER') return installerPath; + if (k === 'LIBRARY_DIR') return libDir; + if (k in data) return data[k]; + return '{' + k + '}'; + }); + }; + + // --- Prozessoren ausführen --- + const processors = (profile.processors || []).filter( + (p) => !p.sides || p.sides.includes('client'), + ); + let pi = 0; + for (const proc of processors) { + pi++; + onProgress({ phase: 'loader', current: pi, total: processors.length, detail: 'Prozessor ' + pi + '/' + processors.length }); + + const cpCoords = [proc.jar, ...(proc.classpath || [])]; + const cpPaths = cpCoords.map((c) => path.join(libDir, mavenPath(c).replace(/\//g, path.sep))); + const mainJar = cpPaths[0]; + const mainClass = jarMainClass(mainJar); + if (!mainClass) throw new Error('Kein Main-Class im Prozessor-JAR: ' + proc.jar); + + const args = ['-cp', cpPaths.join(path.delimiter), mainClass, ...(proc.args || []).map(resolveArg)]; + const r = spawnSync(java, args, { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 }); + if (r.status !== 0) { + const tail = ((r.stderr || '') + (r.stdout || '')).split('\n').slice(-8).join('\n'); + throw new Error(`Forge-Prozessor ${pi} fehlgeschlagen (Exit ${r.status}).\n${tail}`); + } + } + + return versionJson; +} + +module.exports = { installForge, mavenPath, jarMainClass, readZipIndex, readZipEntry }; diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..ff1b5e9 --- /dev/null +++ b/src/index.html @@ -0,0 +1,514 @@ + + + + + + AeroMC + + + + +
+ + + + + + + + +
+ +
+ + +
+ + +
+
+
+ +
+ + +
+ + +
+
Bereit
+
+ Keine Instanz ausgewählt + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/launcher.js b/src/launcher.js new file mode 100644 index 0000000..1766662 --- /dev/null +++ b/src/launcher.js @@ -0,0 +1,455 @@ +'use strict'; + +/* + * launcher.js – Vanilla-Start-Pipeline (Phase 2) + * ---------------------------------------------- + * Lädt Version-JSON, Client-JAR, Libraries, Natives und Assets herunter, + * wählt eine passende Java-Version und baut das Start-Kommando. + * + * Der eigentliche Prozess-Start ist an ein Konto gebunden (opts.auth): + * Ohne gültigen Microsoft-Login (Phase 3) wird alles vorbereitet, aber + * NICHT gestartet – wir bauen bewusst keinen Offline-/Crack-Bypass. + * + * Gemeinsame Spieldateien (versions/libraries/assets) liegen geteilt unter + * , damit mehrere Instanzen sie sich teilen (spart Platz). + */ + +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); +const { spawn, spawnSync } = require('child_process'); +const services = require('./services'); +const loaders = require('./loaders'); +const forge = require('./forge'); + +const UA = 'AeroMC-Launcher/0.2'; +const RESOURCES = 'https://resources.download.minecraft.net'; + +// --------------------------------------------------------------------------- +// kleine Helfer +// --------------------------------------------------------------------------- + +function ensureDir(d) { fs.mkdirSync(d, { recursive: true }); } + +function sha1File(file) { + try { + const h = crypto.createHash('sha1'); + h.update(fs.readFileSync(file)); + return h.digest('hex'); + } catch { return null; } +} + +async function fetchJson(url) { + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('HTTP ' + res.status + ' bei ' + url); + return res.json(); +} + +// lädt eine Datei, überspringt sie bei passender sha1/Existenz +async function downloadIfNeeded(url, dest, sha1) { + if (fs.existsSync(dest)) { + if (!sha1 || sha1File(dest) === sha1) return { skipped: true, bytes: 0 }; + } + ensureDir(path.dirname(dest)); + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('Download HTTP ' + res.status + ': ' + url); + const buf = Buffer.from(await res.arrayBuffer()); + fs.writeFileSync(dest, buf); + return { skipped: false, bytes: buf.length }; +} + +// begrenzte Parallelität für viele kleine Downloads (Assets) +async function runPool(items, worker, concurrency, onEach) { + let idx = 0, done = 0; + const total = items.length; + async function next() { + while (idx < total) { + const i = idx++; + await worker(items[i]); + done++; + if (onEach) onEach(done, total); + } + } + const runners = []; + for (let c = 0; c < Math.min(concurrency, total); c++) runners.push(next()); + await Promise.all(runners); +} + +// --------------------------------------------------------------------------- +// Regeln (Libraries & Argumente) +// --------------------------------------------------------------------------- + +const OS_NAME = 'windows'; + +function rulesAllow(rules) { + if (!rules || !rules.length) return true; + let action = 'disallow'; + for (const r of rules) { + let matches = true; + if (r.os && r.os.name && r.os.name !== OS_NAME) matches = false; + if (r.features) matches = false; // Demo-/Auflösungs-Features aus + if (matches) action = r.action; + } + return action === 'allow'; +} + +// --------------------------------------------------------------------------- +// Version-JSON +// --------------------------------------------------------------------------- + +async function getVersionJson(versionId, userDataDir, sharedDir) { + const dest = path.join(sharedDir, 'versions', versionId, versionId + '.json'); + if (fs.existsSync(dest)) { + try { return JSON.parse(fs.readFileSync(dest, 'utf8')); } catch { /* neu laden */ } + } + // URL aus dem Manifest suchen (bei Bedarf frisch laden, falls url fehlt) + let manifest = await services.getMcVersions(userDataDir); + let entry = (manifest.versions || []).find((v) => v.id === versionId); + if (!entry || !entry.url) { + manifest = await services.getMcVersions(userDataDir, 0); // erzwinge Refresh + entry = (manifest.versions || []).find((v) => v.id === versionId); + } + if (!entry || !entry.url) throw new Error('Version nicht im Mojang-Manifest gefunden: ' + versionId); + const vj = await fetchJson(entry.url); + ensureDir(path.dirname(dest)); + fs.writeFileSync(dest, JSON.stringify(vj)); + return vj; +} + +// --------------------------------------------------------------------------- +// Libraries + Natives -> Classpath +// --------------------------------------------------------------------------- + +async function prepareLibraries(vj, sharedDir, nativesDir, onProgress) { + const libDir = path.join(sharedDir, 'libraries'); + const classpath = []; + const libs = (vj.libraries || []).filter((l) => rulesAllow(l.rules)); + let i = 0; + for (const lib of libs) { + i++; + onProgress && onProgress({ phase: 'libraries', current: i, total: libs.length, detail: lib.name }); + + const dl = lib.downloads || {}; + // normales Artefakt -> Classpath + if (dl.artifact && dl.artifact.path) { + const dest = path.join(libDir, dl.artifact.path.replace(/\//g, path.sep)); + await downloadIfNeeded(dl.artifact.url, dest, dl.artifact.sha1); + classpath.push(dest); + } + // klassische Natives (vor 1.19) -> in nativesDir extrahieren + if (lib.natives && lib.natives[OS_NAME] && dl.classifiers) { + const key = lib.natives[OS_NAME].replace('${arch}', '64'); + const nat = dl.classifiers[key]; + if (nat) { + const dest = path.join(libDir, nat.path.replace(/\//g, path.sep)); + await downloadIfNeeded(nat.url, dest, nat.sha1); + await extractNatives(dest, nativesDir, lib.extract); + } + } + } + return classpath; +} + +// entpackt eine Natives-JAR (ZIP) nach nativesDir (ohne externe Abhängigkeit) +async function extractNatives(jarPath, nativesDir, extractRule) { + ensureDir(nativesDir); + const exclude = (extractRule && extractRule.exclude) || ['META-INF/']; + const data = fs.readFileSync(jarPath); + // ZIP End-of-Central-Directory finden + let eocd = -1; + for (let i = data.length - 22; i >= 0 && i > data.length - 22 - 65536; i--) { + if (data.readUInt32LE(i) === 0x06054b50) { eocd = i; break; } + } + if (eocd < 0) return; + const count = data.readUInt16LE(eocd + 10); + let off = data.readUInt32LE(eocd + 16); + const zlib = require('zlib'); + for (let n = 0; n < count; n++) { + if (data.readUInt32LE(off) !== 0x02014b50) break; + const method = data.readUInt16LE(off + 10); + const compSize = data.readUInt32LE(off + 20); + const nameLen = data.readUInt16LE(off + 28); + const extraLen = data.readUInt16LE(off + 30); + const commentLen = data.readUInt16LE(off + 32); + const localOff = data.readUInt32LE(off + 42); + const name = data.toString('utf8', off + 46, off + 46 + nameLen); + off += 46 + nameLen + extraLen + commentLen; + + if (name.endsWith('/')) continue; + if (exclude.some((ex) => name.startsWith(ex))) continue; + + // lokalen Header lesen, um Datenoffset zu bestimmen + const lNameLen = data.readUInt16LE(localOff + 26); + const lExtraLen = data.readUInt16LE(localOff + 28); + const dataStart = localOff + 30 + lNameLen + lExtraLen; + const raw = data.subarray(dataStart, dataStart + compSize); + let out; + try { out = method === 0 ? raw : zlib.inflateRawSync(raw); } catch { continue; } + const target = path.join(nativesDir, path.basename(name)); + fs.writeFileSync(target, out); + } +} + +// --------------------------------------------------------------------------- +// Assets +// --------------------------------------------------------------------------- + +async function prepareAssets(vj, sharedDir, onProgress) { + const ai = vj.assetIndex; + if (!ai) return; + const indexFile = path.join(sharedDir, 'assets', 'indexes', ai.id + '.json'); + await downloadIfNeeded(ai.url, indexFile, ai.sha1); + const index = JSON.parse(fs.readFileSync(indexFile, 'utf8')); + const objects = index.objects || {}; + const entries = Object.values(objects); + const objDir = path.join(sharedDir, 'assets', 'objects'); + + await runPool(entries, async (o) => { + const sub = o.hash.slice(0, 2); + const dest = path.join(objDir, sub, o.hash); + if (fs.existsSync(dest)) return; + await downloadIfNeeded(`${RESOURCES}/${sub}/${o.hash}`, dest, o.hash); + }, 16, (done, total) => onProgress && onProgress({ phase: 'assets', current: done, total, detail: 'Assets' })); +} + +// --------------------------------------------------------------------------- +// Java-Auswahl +// --------------------------------------------------------------------------- + +function pickJava(vj, preferredPath) { + if (preferredPath && preferredPath.trim()) { + const info = services.probeJava(preferredPath); + if (info) return { path: preferredPath, major: info.major, forced: true }; + } + const required = (vj.javaVersion && vj.javaVersion.majorVersion) || 8; + const jvms = services.scanJava(); + // exakt passende oder nächsthöhere 64-bit-Version + const x64 = jvms.filter((j) => j.arch === 'x64'); + const exact = x64.find((j) => j.major === required); + if (exact) return { path: exact.path, major: exact.major }; + const higher = x64.filter((j) => j.major >= required).sort((a, b) => a.major - b.major)[0]; + if (higher) return { path: higher.path, major: higher.major }; + const any = jvms[0]; + return any ? { path: any.path, major: any.major, mismatch: required } : null; +} + +// --------------------------------------------------------------------------- +// Argumente +// --------------------------------------------------------------------------- + +function substitute(str, map) { + return str.replace(/\$\{([^}]+)\}/g, (m, k) => (k in map ? map[k] : m)); +} + +function collectArgs(argList, map) { + const out = []; + for (const a of argList || []) { + if (typeof a === 'string') { out.push(substitute(a, map)); continue; } + if (a && a.rules && !rulesAllow(a.rules)) continue; + const val = a && a.value; + if (typeof val === 'string') out.push(substitute(val, map)); + else if (Array.isArray(val)) val.forEach((v) => out.push(substitute(v, map))); + } + return out; +} + +// führt Vanilla-Version + Loader-Profil zusammen (mainClass + Argumente) +function mergeLoader(vj, lp) { + const merged = Object.assign({}, vj, { mainClass: lp.mainClass || vj.mainClass }); + merged.arguments = { + jvm: [...((vj.arguments && vj.arguments.jvm) || []), ...((lp.arguments && lp.arguments.jvm) || [])], + game: [...((vj.arguments && vj.arguments.game) || []), ...((lp.arguments && lp.arguments.game) || [])], + }; + return merged; +} + +function buildArgs(vj, ctx) { + const map = { + auth_player_name: ctx.auth.name, + version_name: vj.id, + library_directory: path.join(ctx.sharedDir, 'libraries'), + classpath_separator: path.delimiter, + game_directory: ctx.gameDir, + assets_root: path.join(ctx.sharedDir, 'assets'), + assets_index_name: vj.assets || (vj.assetIndex && vj.assetIndex.id) || 'legacy', + auth_uuid: ctx.auth.uuid, + auth_access_token: ctx.auth.accessToken, + clientid: ctx.auth.clientId || '', + auth_xuid: ctx.auth.xuid || '', + user_type: ctx.auth.userType || 'msa', + version_type: vj.type || 'release', + natives_directory: ctx.nativesDir, + launcher_name: 'AeroMC', + launcher_version: '0.2', + classpath: ctx.classpath.join(path.delimiter), + game_assets: path.join(ctx.sharedDir, 'assets', 'virtual', 'legacy'), + auth_session: 'token:' + ctx.auth.accessToken, + user_properties: '{}', + }; + + let jvm, game; + if (vj.arguments) { + jvm = collectArgs(vj.arguments.jvm, map); + game = collectArgs(vj.arguments.game, map); + } else { + // altes Format (< 1.13) + jvm = ['-Djava.library.path=' + ctx.nativesDir, '-cp', ctx.classpath.join(path.delimiter)]; + game = (vj.minecraftArguments || '').split(' ').filter(Boolean).map((a) => substitute(a, map)); + } + // RAM + jvm = ['-Xms' + ctx.minMemMb + 'M', '-Xmx' + ctx.maxMemMb + 'M', ...jvm]; + if (ctx.extraArgs) jvm = [...ctx.extraArgs.split(' ').filter(Boolean), ...jvm]; + + return [...jvm, vj.mainClass, ...game]; +} + +// --------------------------------------------------------------------------- +// Hauptfunktion +// --------------------------------------------------------------------------- + +/* + * opts: { versionId, gameDir, sharedDir, userDataDir, javaPath, minMemMb, maxMemMb, extraArgs, auth } + * auth: null (kein Login) ODER { name, uuid, accessToken, userType } + * onProgress: (evt) => void + */ +async function prepareAndLaunch(opts, onProgress) { + const emit = (phase, extra) => onProgress && onProgress(Object.assign({ phase }, extra)); + + emit('version', { detail: 'Version-Daten laden …' }); + const vj = await getVersionJson(opts.versionId, opts.userDataDir, opts.sharedDir); + + const nativesDir = path.join(opts.sharedDir, 'versions', vj.id, 'natives'); + ensureDir(nativesDir); + + // Client-JAR + emit('client', { detail: 'Client herunterladen …' }); + const clientJar = path.join(opts.sharedDir, 'versions', vj.id, vj.id + '.jar'); + if (vj.downloads && vj.downloads.client) { + await downloadIfNeeded(vj.downloads.client.url, clientJar, vj.downloads.client.sha1); + } + + // Libraries + Natives + const classpath = await prepareLibraries(vj, opts.sharedDir, nativesDir, onProgress); + classpath.push(clientJar); + + // Assets + await prepareAssets(vj, opts.sharedDir, onProgress); + + // Java (VOR dem Loader – Forge-Prozessoren brauchen Java) + emit('java', { detail: 'Java wählen …' }); + const java = pickJava(vj, opts.javaPath); + if (!java) return { ok: false, message: 'Keine Java-Installation gefunden. Bitte in den Einstellungen Java festlegen.' }; + + // Mod-Loader + let effectiveVj = vj; + const libDir = path.join(opts.sharedDir, 'libraries'); + + if (opts.loader === 'fabric' || opts.loader === 'quilt') { + emit('loader', { detail: opts.loader + ' vorbereiten …' }); + let lp; + try { lp = (await loaders.resolveLoaderProfile(opts.loader, vj.id, opts.loaderVersion)).profile; } + catch (err) { return { ok: false, message: err.message }; } + const loaderLibs = lp.libraries || []; + let li = 0; + for (const lib of loaderLibs) { + li++; + onProgress && onProgress({ phase: 'loader', current: li, total: loaderLibs.length, detail: lib.name }); + const { relPath, url } = loaders.mavenToUrl(lib.url, lib.name); + const dest = path.join(libDir, relPath.replace(/\//g, path.sep)); + await downloadIfNeeded(url, dest, lib.sha1 || null); + classpath.unshift(dest); + } + effectiveVj = mergeLoader(vj, lp); + + } else if (opts.loader === 'forge' || opts.loader === 'neoforge') { + let lv = opts.loaderVersion; + if (!lv) { + const list = await loaders.listLoaderVersions(opts.loader, vj.id); + if (!list.length) return { ok: false, message: `Keine ${opts.loader}-Version für ${vj.id} gefunden.` }; + lv = list[0].version; + } + let fvj; + try { + fvj = await forge.installForge({ + loader: opts.loader, mcVersion: vj.id, loaderVersion: lv, + sharedDir: opts.sharedDir, javaPath: java.path, clientJar, + clientMappingsUrl: vj.downloads && vj.downloads.client_mappings && vj.downloads.client_mappings.url, + onProgress, + }); + } catch (err) { + return { ok: false, message: (opts.loader === 'forge' ? 'Forge' : 'NeoForge') + '-Installation fehlgeschlagen: ' + err.message }; + } + for (const lib of fvj.libraries || []) { + const art = lib.downloads && lib.downloads.artifact; + const rel = (art && art.path) || forge.mavenPath(lib.name); + classpath.unshift(path.join(libDir, rel.replace(/\//g, path.sep))); + } + effectiveVj = mergeLoader(vj, fvj); + } + + // Ohne Login: alles vorbereitet, aber kein Start (kein Crack-Bypass) + if (!opts.auth) { + return { + ok: false, + needAuth: true, + prepared: true, + java, + requiredJava: (vj.javaVersion && vj.javaVersion.majorVersion) || 8, + message: 'Alles heruntergeladen und startklar ✔ – bitte oben rechts über „👤 Anmelden" mit deinem Microsoft-Konto einloggen, dann startet Minecraft.', + }; + } + + // Start + const args = buildArgs(effectiveVj, { + auth: opts.auth, + gameDir: opts.gameDir, + sharedDir: opts.sharedDir, + nativesDir, + classpath, + minMemMb: opts.minMemMb || 2048, + maxMemMb: opts.maxMemMb || 4096, + extraArgs: opts.extraArgs || '', + }); + + ensureDir(opts.gameDir); + + // Pre-Launch-Befehl (bricht bei Fehler ab) + if (opts.preLaunchCommand && opts.preLaunchCommand.trim()) { + emit('log', { line: '[Pre-Launch] ' + opts.preLaunchCommand + '\n' }); + const pr = spawnSync(opts.preLaunchCommand, { cwd: opts.gameDir, shell: true, encoding: 'utf8' }); + if (pr.stdout) emit('log', { line: pr.stdout }); + if (pr.stderr) emit('log', { line: pr.stderr }); + if (pr.status !== 0) return { ok: false, message: 'Pre-Launch-Befehl fehlgeschlagen (Exit ' + pr.status + ').' }; + } + + emit('launch', { detail: 'Starte Minecraft …' }); + let cmd = java.path; + let spawnArgs = args; + if (opts.wrapperCommand && opts.wrapperCommand.trim()) { + const w = opts.wrapperCommand.trim().split(/\s+/); + cmd = w[0]; + spawnArgs = [...w.slice(1), java.path, ...args]; + } + const child = spawn(cmd, spawnArgs, { cwd: opts.gameDir, detached: false }); + child.stdout.on('data', (d) => emit('log', { line: d.toString() })); + child.stderr.on('data', (d) => emit('log', { line: d.toString() })); + child.on('exit', (code) => { + emit('exit', { code }); + // Post-Exit-Befehl + if (opts.postExitCommand && opts.postExitCommand.trim()) { + emit('log', { line: '[Post-Exit] ' + opts.postExitCommand + '\n' }); + try { + const po = spawnSync(opts.postExitCommand, { cwd: opts.gameDir, shell: true, encoding: 'utf8' }); + if (po.stdout) emit('log', { line: po.stdout }); + if (po.stderr) emit('log', { line: po.stderr }); + } catch { /* egal */ } + } + }); + + return { ok: true, pid: child.pid, java }; +} + +module.exports = { + prepareAndLaunch, getVersionJson, buildArgs, pickJava, rulesAllow, prepareLibraries, prepareAssets, + downloadIfNeeded, extractNatives, +}; diff --git a/src/loaders.js b/src/loaders.js new file mode 100644 index 0000000..ab9550e --- /dev/null +++ b/src/loaders.js @@ -0,0 +1,103 @@ +'use strict'; + +/* + * loaders.js – Mod-Loader-Profile auflösen + * ---------------------------------------- + * Fabric & Quilt liefern über ihre Meta-API ein fertiges Profil-JSON + * (mainClass, zusätzliche Libraries als Maven-Koordinaten, Argumente, + * inheritsFrom = Vanilla-Version). Das mergen wir beim Start mit der Vanilla-Version. + * + * Forge & NeoForge liefern KEIN einfaches Profil, sondern einen Installer, + * der Prozessoren ausführt und den Client patcht -> deutlich aufwändiger, + * daher hier noch als „in Arbeit" gekennzeichnet. + */ + +const UA = 'AeroMC-Launcher/0.5'; + +const META = { + fabric: 'https://meta.fabricmc.net/v2', + quilt: 'https://meta.quiltmc.org/v3', +}; + +async function fetchJson(url) { + const res = await fetch(url, { headers: { 'User-Agent': UA, Accept: 'application/json' } }); + if (!res.ok) throw new Error('HTTP ' + res.status + ' bei ' + url); + return res.json(); +} + +async function fetchText(url) { + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('HTTP ' + res.status + ' bei ' + url); + return res.text(); +} + +const FORGE_META = 'https://maven.minecraftforge.net/net/minecraftforge/forge/maven-metadata.xml'; +const NEOFORGE_META = 'https://maven.neoforged.net/releases/net/neoforged/neoforge/maven-metadata.xml'; + +// NeoForge kodiert die MC-Version im Loader-Namen: 1.21.4 -> 21.4.x +function neoforgePrefix(mcVersion) { + const p = mcVersion.split('.'); + return `${p[1]}.${p[2] || '0'}.`; +} + +// "group:artifact:version[:classifier]" -> { relPath, url } +function mavenToUrl(base, name) { + const parts = name.split(':'); + const group = parts[0].replace(/\./g, '/'); + const artifact = parts[1]; + const version = parts[2]; + const classifier = parts[3] ? '-' + parts[3] : ''; + const file = `${artifact}-${version}${classifier}.jar`; + const relPath = `${group}/${artifact}/${version}/${file}`; + const root = (base || 'https://libraries.minecraft.net/').replace(/\/$/, ''); + return { relPath, url: `${root}/${relPath}` }; +} + +// verfügbare Loader-Versionen (für die Anzeige/Auswahl) +async function listLoaderVersions(loader, mcVersion) { + if (loader === 'fabric' || loader === 'quilt') { + const list = await fetchJson(`${META[loader]}/versions/loader/${mcVersion}`); + return list.map((l) => ({ version: l.loader.version, stable: !!l.loader.stable })); + } + if (loader === 'forge') { + const xml = await fetchText(FORGE_META); + const all = [...xml.matchAll(/([^<]+)<\/version>/g)].map((m) => m[1]); + const prefix = mcVersion + '-'; + const versions = all.filter((v) => v.startsWith(prefix)).map((v) => v.slice(prefix.length)).reverse(); + return versions.map((v, i) => ({ version: v, stable: i === 0 })); + } + if (loader === 'neoforge') { + const xml = await fetchText(NEOFORGE_META); + const all = [...xml.matchAll(/([^<]+)<\/version>/g)].map((m) => m[1]); + const prefix = neoforgePrefix(mcVersion); + const versions = all.filter((v) => v.startsWith(prefix)).reverse(); + return versions.map((v, i) => ({ version: v, stable: i === 0 && !/beta/i.test(v) })); + } + return []; +} + +// löst das Profil (mainClass, libraries, arguments) auf +async function resolveLoaderProfile(loader, mcVersion, loaderVersion) { + if (loader === 'fabric' || loader === 'quilt') { + let lv = loaderVersion; + if (!lv) { + const list = await fetchJson(`${META[loader]}/versions/loader/${mcVersion}`); + if (!list.length) throw new Error(`Kein ${loader}-Loader für Minecraft ${mcVersion} verfügbar.`); + const stable = list.find((l) => l.loader && l.loader.stable) || list[0]; + lv = stable.loader.version; + } + const profile = await fetchJson(`${META[loader]}/versions/loader/${mcVersion}/${lv}/profile/json`); + return { profile, loaderVersion: lv }; + } + if (loader === 'forge' || loader === 'neoforge') { + const e = new Error( + `${loader === 'forge' ? 'Forge' : 'NeoForge'}-Installation ist noch in Arbeit ` + + '(braucht Installer + Prozessoren). Fabric und Quilt funktionieren bereits vollständig.', + ); + e.notImplemented = true; + throw e; + } + throw new Error('Unbekannter Loader: ' + loader); +} + +module.exports = { resolveLoaderProfile, listLoaderVersions, mavenToUrl }; diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..81836ea --- /dev/null +++ b/src/main.js @@ -0,0 +1,614 @@ +'use strict'; + +/* + * main.js – Electron Hauptprozess für ViperCraft + * Phase 1: Fenster, Instanz-Verwaltung, Einstellungen. + * (Vanilla-Start, Microsoft-Login und Mod-Loader folgen in späteren Phasen.) + */ + +const { app, BrowserWindow, ipcMain, dialog, shell, safeStorage } = require('electron'); +const path = require('path'); +const fs = require('fs'); +const { execFile } = require('child_process'); +const store = require('./store'); +const services = require('./services'); +const launcher = require('./launcher'); +const loaders = require('./loaders'); +const forge = require('./forge'); +const auth = require('./auth'); + +// undici als globales fetch verwenden -> ermöglicht Proxy via setGlobalDispatcher +const undici = require('undici'); +globalThis.fetch = undici.fetch; +globalThis.Headers = undici.Headers; +globalThis.Request = undici.Request; +globalThis.Response = undici.Response; + +// --------------------------------------------------------------------------- +// Automatische Überwachung der Anmelde-Dienste +// --------------------------------------------------------------------------- + +const AUTH_ENDPOINTS = [ + { name: 'Microsoft-Login', url: 'https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode' }, + { name: 'Xbox Live', url: 'https://user.auth.xboxlive.com/user/authenticate' }, + { name: 'Minecraft-Dienste', url: 'https://api.minecraftservices.com/minecraft/profile' }, +]; + +let authHealth = { ok: true, checked: null, down: [] }; + +async function checkAuthServices() { + const down = []; + for (const ep of AUTH_ENDPOINTS) { + try { + const ctrl = new AbortController(); + const t = setTimeout(() => ctrl.abort(), 8000); + // Antwort-Status ist egal (401/404 = Dienst lebt); nur Ausfall/5xx zählt als "down" + const res = await fetch(ep.url, { method: 'GET', signal: ctrl.signal, headers: { 'User-Agent': 'AeroMC-Launcher/0.28' } }); + clearTimeout(t); + if (res.status >= 500) down.push(ep.name); + } catch { + down.push(ep.name); + } + } + authHealth = { ok: down.length === 0, checked: new Date().toISOString(), down }; + if (mainWindow && !mainWindow.isDestroyed()) mainWindow.webContents.send('auth:health', authHealth); + return authHealth; +} + +function applyProxy(s) { + try { + if (s.proxyEnabled && s.proxyHost && String(s.proxyPort).trim()) { + const cred = s.proxyUser ? `${encodeURIComponent(s.proxyUser)}:${encodeURIComponent(s.proxyPass || '')}@` : ''; + undici.setGlobalDispatcher(new undici.ProxyAgent(`http://${cred}${s.proxyHost}:${s.proxyPort}`)); + } else { + undici.setGlobalDispatcher(new undici.Agent()); + } + } catch { /* ungültige Proxy-Konfig ignorieren */ } +} + +let mainWindow = null; + +function windowIcon() { + const png = path.join(__dirname, 'assets', 'logo.png'); + const ico = path.join(__dirname, 'assets', 'icon.ico'); + if (fs.existsSync(ico)) return ico; + if (fs.existsSync(png)) return png; + return undefined; // Electron-Standard, solange kein Logo hinterlegt ist +} + +function createWindow() { + mainWindow = new BrowserWindow({ + width: 1100, + height: 720, + minWidth: 880, + minHeight: 560, + backgroundColor: '#1b1e24', + title: 'AeroMC', + icon: windowIcon(), + autoHideMenuBar: true, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + contextIsolation: true, + nodeIntegration: false, + sandbox: false, + }, + }); + + mainWindow.loadFile(path.join(__dirname, 'index.html')); +} + +app.whenReady().then(() => { + store.init(app.getPath('userData')); + // Konten verschlüsselt speichern (Windows-DPAPI, an das Benutzerkonto gebunden) + auth.init(app.getPath('userData'), { + available: () => { try { return safeStorage.isEncryptionAvailable(); } catch { return false; } }, + encrypt: (s) => safeStorage.encryptString(s).toString('base64'), + decrypt: (b) => safeStorage.decryptString(Buffer.from(b, 'base64')), + }); + applyProxy(store.getSettings()); + createWindow(); + + // Anmelde-Dienste automatisch überwachen (sofort + alle 2 Minuten) + setTimeout(() => checkAuthServices(), 2500); + setInterval(() => checkAuthServices(), 120000); + + // Anmeldung im Hintergrund auffrischen -> kein erneuter Login beim Start nötig + const cid = store.getSettings().azureClientId || auth.DEFAULT_CLIENT_ID; + auth.getValidAccount(cid) + .then((acc) => { + if (acc && mainWindow && !mainWindow.isDestroyed()) mainWindow.webContents.send('auth:refreshed'); + }) + .catch(() => { /* offline o. Ä. – Konto bleibt gespeichert */ }); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit(); +}); + +// --------------------------------------------------------------------------- +// Java-Erkennung (für Anzeige in den Einstellungen) +// --------------------------------------------------------------------------- + +function detectJava(javaPath) { + return new Promise((resolve) => { + const cmd = javaPath && javaPath.trim() ? javaPath : 'java'; + execFile(cmd, ['-version'], (err, stdout, stderr) => { + if (err) return resolve({ ok: false, path: cmd, version: null, error: err.message }); + // "java -version" schreibt nach stderr + const out = (stderr || stdout || '').split('\n')[0].trim(); + resolve({ ok: true, path: cmd, version: out }); + }); + }); +} + +// --------------------------------------------------------------------------- +// IPC – Einstellungen +// --------------------------------------------------------------------------- + +ipcMain.handle('settings:get', () => store.getSettings()); + +ipcMain.handle('settings:save', (_e, patch) => { const s = store.saveSettings(patch); applyProxy(s); return s; }); + +ipcMain.handle('settings:instancesDir', () => store.getInstancesDir()); + +ipcMain.handle('java:detect', (_e, javaPath) => detectJava(javaPath)); + +// automatische Java-Suche über das System +ipcMain.handle('java:scan', () => services.scanJava()); + +// --------------------------------------------------------------------------- +// IPC – Minecraft-Versionen (Mojang) +// --------------------------------------------------------------------------- + +ipcMain.handle('mc:versions', () => services.getMcVersions(app.getPath('userData'))); + +// --------------------------------------------------------------------------- +// IPC – Mods (Modrinth) +// --------------------------------------------------------------------------- + +ipcMain.handle('mods:search', (_e, opts) => services.modrinthSearch(opts)); + +ipcMain.handle('mods:list', (_e, id) => store.listMods(id)); + +ipcMain.handle('mods:install', async (_e, id, project) => { + const inst = store.getInstance(id); + if (!inst) return { ok: false, message: 'Instanz nicht gefunden.' }; + const gameVersion = inst.minecraft.version; + const loader = inst.minecraft.loader; + if (!gameVersion) return { ok: false, message: 'Instanz hat keine Minecraft-Version gesetzt.' }; + if (!loader || loader === 'vanilla') return { ok: false, message: 'Mods brauchen einen Mod-Loader (Fabric/Forge/NeoForge/Quilt).' }; + + const modsDir = store.modsDir(id); + const done = new Set(store.listMods(id).map((m) => m.projectId)); + const added = []; + let firstError = null; + + // installiert ein Projekt und rekursiv seine PFLICHT-Abhängigkeiten + async function installOne(proj, isDep) { + if (done.has(proj.projectId)) return; + done.add(proj.projectId); + try { + const res = await services.modrinthInstall({ + projectId: proj.projectId, title: proj.title, gameVersion, loader, modsDir, + }); + if (!res.ok) { + if (!isDep && !firstError) firstError = res.message; + return; + } + store.addMod(id, res.entry); + added.push(res.entry); + for (const dep of res.dependencies || []) { + if (dep.dependency_type === 'required' && dep.project_id && !done.has(dep.project_id)) { + const title = await services.modrinthProjectTitle(dep.project_id); + await installOne({ projectId: dep.project_id, title }, true); + } + } + } catch (err) { + if (!isDep && !firstError) firstError = err.message; + } + } + + await installOne(project, false); + if (!added.length) return { ok: false, message: firstError || 'Installation fehlgeschlagen.' }; + return { ok: true, entry: added[0], added, depCount: added.length - 1 }; +}); + +// verfügbare Loader-Versionen (Fabric/Quilt) für eine MC-Version +ipcMain.handle('loaders:versions', async (_e, loader, mcVersion) => { + try { return await loaders.listLoaderVersions(loader, mcVersion); } + catch { return []; } +}); + +ipcMain.handle('mods:remove', (_e, id, filename) => store.removeMod(id, filename)); + +// --------------------------------------------------------------------------- +// IPC – Microsoft-Login (Phase 3) +// --------------------------------------------------------------------------- + +ipcMain.handle('auth:status', () => auth.currentAccount()); +ipcMain.handle('auth:health', () => authHealth); +ipcMain.handle('auth:recheck', () => checkAuthServices()); +ipcMain.handle('auth:accounts', () => auth.listAccounts()); +ipcMain.handle('auth:setActive', (_e, id) => auth.setActive(id)); +ipcMain.handle('auth:remove', (_e, id) => auth.removeAccount(id)); +ipcMain.handle('auth:logout', () => { auth.clearAccount(); return true; }); + +ipcMain.handle('auth:login', async () => { + const clientId = store.getSettings().azureClientId || auth.DEFAULT_CLIENT_ID; + try { + const account = await auth.login( + clientId, + (code) => { + if (mainWindow && !mainWindow.isDestroyed()) mainWindow.webContents.send('auth:code', code); + }, + () => {}, + ); + return { ok: true, account }; + } catch (err) { + return { ok: false, message: err.message }; + } +}); + +// --------------------------------------------------------------------------- +// IPC – Instanzen +// --------------------------------------------------------------------------- + +ipcMain.handle('instances:list', () => store.listInstances()); + +ipcMain.handle('instances:get', (_e, id) => store.getInstance(id)); + +ipcMain.handle('instances:create', (_e, data) => store.createInstance(data)); + +ipcMain.handle('instances:update', (_e, id, patch) => store.updateInstance(id, patch)); + +ipcMain.handle('instances:delete', (_e, id) => store.deleteInstance(id)); + +ipcMain.handle('instances:duplicate', (_e, id) => store.duplicateInstance(id)); + +ipcMain.handle('instances:openFolder', (_e, id) => { + const p = store.instancePath(id); + if (fs.existsSync(p)) shell.openPath(p); + return true; +}); + +ipcMain.handle('instances:openGameDir', (_e, id) => { + const p = store.gameDir(id); + if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); + shell.openPath(p); + return true; +}); + +// ---- Welten & Ressourcenpakete ---- + +function listDir(dir, dirsOnly) { + if (!fs.existsSync(dir)) return []; + return fs.readdirSync(dir, { withFileTypes: true }) + .filter((e) => (dirsOnly ? e.isDirectory() : true) && !e.name.startsWith('.')) + .map((e) => { + let size = 0; + try { size = fs.statSync(path.join(dir, e.name)).size; } catch { /* egal */ } + return { name: e.name, isDir: e.isDirectory(), size }; + }); +} + +ipcMain.handle('instance:worlds', (_e, id) => listDir(path.join(store.gameDir(id), 'saves'), true)); +ipcMain.handle('instance:resourcepacks', (_e, id) => listDir(path.join(store.gameDir(id), 'resourcepacks'), false)); + +function safeSub(id, sub, name) { + const base = path.join(store.gameDir(id), sub); + const target = path.join(base, name); + // Pfad-Ausbruch verhindern + if (!target.startsWith(base + path.sep)) return null; + return target; +} + +ipcMain.handle('instance:deleteContent', (_e, id, sub, name) => { + const target = safeSub(id, sub, name); + if (target && fs.existsSync(target)) fs.rmSync(target, { recursive: true, force: true }); + return true; +}); + +ipcMain.handle('instance:openSubdir', (_e, id, sub) => { + const p = path.join(store.gameDir(id), sub); + if (!fs.existsSync(p)) fs.mkdirSync(p, { recursive: true }); + shell.openPath(p); + return true; +}); + +// ---- Screenshots ---- + +ipcMain.handle('instance:screenshots', (_e, id) => + listDir(path.join(store.gameDir(id), 'screenshots'), false) + .filter((f) => /\.(png|jpe?g|gif|webp)$/i.test(f.name)) + .sort((a, b) => b.name.localeCompare(a.name))); + +ipcMain.handle('instance:screenshotData', (_e, id, name) => { + const target = safeSub(id, 'screenshots', name); + try { + if (!target || !fs.existsSync(target)) return null; + if (fs.statSync(target).size > 12 * 1024 * 1024) return null; + let ext = path.extname(target).slice(1).toLowerCase(); + if (ext === 'jpg') ext = 'jpeg'; + return `data:image/${ext};base64,` + fs.readFileSync(target).toString('base64'); + } catch { return null; } +}); + +ipcMain.handle('instance:openScreenshot', (_e, id, name) => { + const target = safeSub(id, 'screenshots', name); + if (target && fs.existsSync(target)) shell.openPath(target); + return true; +}); + +// ---- Instanz Import/Export (ZIP über Windows-Bordmittel) ---- + +function runPwsh(command, env) { + return new Promise((resolve, reject) => { + execFile('powershell', ['-NoProfile', '-NonInteractive', '-Command', command], + { env: Object.assign({}, process.env, env), windowsHide: true, maxBuffer: 64 * 1024 * 1024 }, + (err, stdout, stderr) => (err ? reject(new Error(stderr || err.message)) : resolve(stdout))); + }); +} + +ipcMain.handle('instances:export', async (_e, id) => { + const inst = store.getInstance(id); + if (!inst) return { ok: false, message: 'Instanz nicht gefunden.' }; + const safe = (inst.name || 'instanz').replace(/[^\w.-]+/g, '_'); + const res = await dialog.showSaveDialog(mainWindow, { + title: 'Instanz exportieren', + defaultPath: safe + '.zip', + filters: [{ name: 'ZIP-Archiv', extensions: ['zip'] }], + }); + if (res.canceled) return { ok: false, canceled: true }; + try { + if (fs.existsSync(res.filePath)) fs.unlinkSync(res.filePath); + await runPwsh("Compress-Archive -Path (Join-Path $env:VN_SRC '*') -DestinationPath $env:VN_DST -Force", + { VN_SRC: store.instancePath(id), VN_DST: res.filePath }); + return { ok: true, path: res.filePath }; + } catch (err) { + return { ok: false, message: 'Export fehlgeschlagen: ' + err.message }; + } +}); + +// ---- Modpack-Import (Modrinth .mrpack) ---- + +async function importMrpack(buf, zip) { + const raw = forge.readZipEntry(buf, zip['modrinth.index.json']).toString('utf8').replace(/^/, ''); + const index = JSON.parse(raw); + const deps = index.dependencies || {}; + let loader = 'vanilla', loaderVersion = ''; + if (deps['fabric-loader']) { loader = 'fabric'; loaderVersion = deps['fabric-loader']; } + else if (deps['quilt-loader']) { loader = 'quilt'; loaderVersion = deps['quilt-loader']; } + else if (deps.forge) { loader = 'forge'; loaderVersion = deps.forge; } + else if (deps.neoforge) { loader = 'neoforge'; loaderVersion = deps.neoforge; } + + const created = store.createInstance({ + name: index.name || 'Modpack', + minecraft: { version: deps.minecraft || '', loader, loaderVersion }, + }); + const gameDir = store.gameDir(created.id); + const inside = (dest) => dest.startsWith(gameDir + path.sep); + + const files = index.files || []; + let i = 0; + for (const f of files) { + i++; + if (f.env && f.env.client === 'unsupported') continue; + const url = f.downloads && f.downloads[0]; + if (!url || !f.path) continue; + const dest = path.join(gameDir, f.path.replace(/\//g, path.sep)); + if (!inside(dest)) continue; + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('launch:progress', { phase: 'modpack', current: i, total: files.length, detail: 'Modpack-Dateien' }); + } + const res = await fetch(url, { headers: { 'User-Agent': 'AeroMC-Launcher/0.11' } }); + if (!res.ok) continue; + fs.mkdirSync(path.dirname(dest), { recursive: true }); + fs.writeFileSync(dest, Buffer.from(await res.arrayBuffer())); + } + + // overrides einspielen + for (const prefix of ['overrides/', 'client-overrides/']) { + for (const name of Object.keys(zip)) { + if (name.startsWith(prefix) && !name.endsWith('/')) { + const dest = path.join(gameDir, name.slice(prefix.length).replace(/\//g, path.sep)); + if (!inside(dest)) continue; + fs.mkdirSync(path.dirname(dest), { recursive: true }); + fs.writeFileSync(dest, forge.readZipEntry(buf, zip[name])); + } + } + } + return { ok: true, instance: store.getInstance(created.id), fileCount: files.length }; +} + +ipcMain.handle('modpack:import', async () => { + const res = await dialog.showOpenDialog(mainWindow, { + title: 'Modpack importieren', + properties: ['openFile'], + filters: [{ name: 'Modpacks', extensions: ['mrpack', 'zip'] }], + }); + if (res.canceled) return { ok: false, canceled: true }; + try { + const buf = fs.readFileSync(res.filePaths[0]); + const zip = forge.readZipIndex(buf); + if (zip['modrinth.index.json']) return await importMrpack(buf, zip); + if (zip['manifest.json']) { + return { ok: false, message: 'CurseForge-Modpacks brauchen einen CurseForge-API-Key und werden noch nicht unterstützt. Bitte ein Modrinth-.mrpack verwenden.' }; + } + return { ok: false, message: 'Unbekanntes Modpack-Format (keine modrinth.index.json gefunden).' }; + } catch (err) { + return { ok: false, message: 'Modpack-Import fehlgeschlagen: ' + err.message }; + } +}); + +ipcMain.handle('instances:import', async () => { + const res = await dialog.showOpenDialog(mainWindow, { + title: 'Instanz importieren', + properties: ['openFile'], + filters: [{ name: 'ZIP-Archiv', extensions: ['zip'] }], + }); + if (res.canceled) return { ok: false, canceled: true }; + const tmp = path.join(app.getPath('temp'), 'vn-import-' + Date.now()); + try { + fs.mkdirSync(tmp, { recursive: true }); + await runPwsh('Expand-Archive -Path $env:VN_SRC -DestinationPath $env:VN_DST -Force', + { VN_SRC: res.filePaths[0], VN_DST: tmp }); + + // instance.json finden (auch in Unterordner) + let base = tmp; + if (!fs.existsSync(path.join(base, 'instance.json'))) { + const sub = fs.readdirSync(tmp).map((n) => path.join(tmp, n)) + .find((p) => { try { return fs.statSync(p).isDirectory() && fs.existsSync(path.join(p, 'instance.json')); } catch { return false; } }); + if (sub) base = sub; + } + if (!fs.existsSync(path.join(base, 'instance.json'))) { + throw new Error('Keine gültige Instanz im Archiv (instance.json fehlt).'); + } + const imported = JSON.parse(fs.readFileSync(path.join(base, 'instance.json'), 'utf8')); + const created = store.createInstance({ + name: (imported.name || 'Import') + ' (Import)', + icon: imported.icon || 'grass', + notes: imported.notes || '', + minecraft: imported.minecraft || {}, + }); + if (imported.java) store.updateInstance(created.id, { java: imported.java }); + + const mcSrc = path.join(base, 'minecraft'); + if (fs.existsSync(mcSrc)) fs.cpSync(mcSrc, store.gameDir(created.id), { recursive: true }); + const modsSrc = path.join(base, 'mods.json'); + if (fs.existsSync(modsSrc)) fs.copyFileSync(modsSrc, path.join(store.instancePath(created.id), 'mods.json')); + if (imported.customImage && fs.existsSync(path.join(base, imported.customImage))) { + fs.copyFileSync(path.join(base, imported.customImage), path.join(store.instancePath(created.id), imported.customImage)); + store.updateInstance(created.id, { customImage: imported.customImage }); + } + return { ok: true, instance: store.getInstance(created.id) }; + } catch (err) { + return { ok: false, message: 'Import fehlgeschlagen: ' + err.message }; + } finally { + try { fs.rmSync(tmp, { recursive: true, force: true }); } catch { /* egal */ } + } +}); + +// Phase 2: echter Vanilla-Download & -Start (Start selbst ist an Login gebunden). +ipcMain.handle('instances:launch', async (_e, id, accountId) => { + const inst = store.getInstance(id); + if (!inst) return { ok: false, message: 'Instanz nicht gefunden.' }; + if (!inst.minecraft.version) { + return { ok: false, message: 'Bitte zuerst eine Minecraft-Version wählen (Bearbeiten).' }; + } + const settings = store.getSettings(); + const opts = { + versionId: inst.minecraft.version, + loader: inst.minecraft.loader || 'vanilla', + loaderVersion: inst.minecraft.loaderVersion || '', + gameDir: store.gameDir(id), + sharedDir: path.join(app.getPath('userData'), 'shared'), + userDataDir: app.getPath('userData'), + javaPath: inst.java.path || settings.javaPath || '', + minMemMb: inst.java.minMemMb || settings.defaultMinMemMb, + maxMemMb: inst.java.maxMemMb || settings.defaultMaxMemMb, + extraArgs: inst.java.extraArgs || '', + preLaunchCommand: inst.preLaunchCommand || settings.globalPreLaunch || '', + postExitCommand: inst.postExitCommand || settings.globalPostExit || '', + wrapperCommand: settings.wrapperCommand || '', + auth: null, + }; + + // eingeloggtes Microsoft-Konto verwenden (gewähltes oder aktives) -> echter Start + const clientId = settings.azureClientId || auth.DEFAULT_CLIENT_ID; + const account = accountId + ? await auth.getValidAccountById(clientId, accountId) + : await auth.getValidAccount(clientId); + if (account && account.profile) { + opts.auth = { + name: account.profile.name, + uuid: account.profile.id, + accessToken: account.mcAccessToken, + userType: 'msa', + }; + } + + try { + let launchStart = 0; + const res = await launcher.prepareAndLaunch(opts, (evt) => { + if (evt.phase === 'launch') launchStart = Date.now(); + if (evt.phase === 'exit' && launchStart) { + const secs = Math.max(0, Math.round((Date.now() - launchStart) / 1000)); + const cur = store.getInstance(id); + if (cur) store.updateInstance(id, { totalPlaySeconds: (cur.totalPlaySeconds || 0) + secs }); + } + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send('launch:progress', Object.assign({ id }, evt)); + } + }); + if (res.ok) store.updateInstance(id, { lastPlayed: new Date().toISOString() }); + return res; + } catch (err) { + return { ok: false, message: 'Start fehlgeschlagen: ' + err.message }; + } +}); + +// --------------------------------------------------------------------------- +// IPC – Dialoge +// --------------------------------------------------------------------------- + +ipcMain.handle('dialog:pickFolder', async (_e, title) => { + const res = await dialog.showOpenDialog(mainWindow, { + title: title || 'Ordner wählen', + properties: ['openDirectory', 'createDirectory'], + }); + return res.canceled ? null : res.filePaths[0]; +}); + +ipcMain.handle('dialog:pickImage', async () => { + const res = await dialog.showOpenDialog(mainWindow, { + title: 'Instanz-Bild wählen', + properties: ['openFile'], + filters: [{ name: 'Bilder', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp'] }], + }); + return res.canceled ? null : res.filePaths[0]; +}); + +// eigenes Bild einer Instanz zuweisen / entfernen +ipcMain.handle('instances:setImage', (_e, id, sourcePath) => { + store.setCustomImage(id, sourcePath); + return { meta: store.getInstance(id), iconData: store.iconDataUri(id) }; +}); +ipcMain.handle('instances:clearImage', (_e, id) => store.clearCustomImage(id)); +ipcMain.handle('instances:icon', (_e, id) => store.iconDataUri(id)); + +// beliebige Bilddatei als data:-URI (für Vorschau vor dem Speichern) +ipcMain.handle('file:dataUri', (_e, filePath) => { + try { + const stat = fs.statSync(filePath); + if (stat.size > 8 * 1024 * 1024) return null; // >8 MB nicht als Vorschau + let ext = path.extname(filePath).slice(1).toLowerCase(); + if (ext === 'jpg') ext = 'jpeg'; + const buf = fs.readFileSync(filePath); + return `data:image/${ext};base64,` + buf.toString('base64'); + } catch { return null; } +}); + +ipcMain.handle('dialog:pickJava', async () => { + const res = await dialog.showOpenDialog(mainWindow, { + title: 'java.exe wählen', + properties: ['openFile'], + filters: [{ name: 'Java', extensions: ['exe'] }], + }); + return res.canceled ? null : res.filePaths[0]; +}); + +ipcMain.handle('app:openExternal', (_e, url) => { + if (typeof url === 'string' && /^https?:\/\//.test(url)) shell.openExternal(url); + return true; +}); + +ipcMain.handle('app:info', () => ({ + version: app.getVersion(), + electron: process.versions.electron, + node: process.versions.node, + userData: app.getPath('userData'), +})); diff --git a/src/preload.js b/src/preload.js new file mode 100644 index 0000000..d195da4 --- /dev/null +++ b/src/preload.js @@ -0,0 +1,93 @@ +'use strict'; + +/* + * preload.js – stellt dem Renderer eine schmale, sichere API bereit. + * contextIsolation ist aktiv; der Renderer hat KEINEN direkten Node-Zugriff. + */ + +const { contextBridge, ipcRenderer } = require('electron'); + +contextBridge.exposeInMainWorld('api', { + // Einstellungen + getSettings: () => ipcRenderer.invoke('settings:get'), + saveSettings: (patch) => ipcRenderer.invoke('settings:save', patch), + getInstancesDir: () => ipcRenderer.invoke('settings:instancesDir'), + detectJava: (javaPath) => ipcRenderer.invoke('java:detect', javaPath), + scanJava: () => ipcRenderer.invoke('java:scan'), + + // Minecraft-Versionen (Mojang) + mcVersions: () => ipcRenderer.invoke('mc:versions'), + loaderVersions: (loader, mcVersion) => ipcRenderer.invoke('loaders:versions', loader, mcVersion), + + // Mods (Modrinth) + modSearch: (opts) => ipcRenderer.invoke('mods:search', opts), + modList: (id) => ipcRenderer.invoke('mods:list', id), + modInstall: (id, project) => ipcRenderer.invoke('mods:install', id, project), + modRemove: (id, filename) => ipcRenderer.invoke('mods:remove', id, filename), + + // Instanzen + listInstances: () => ipcRenderer.invoke('instances:list'), + getInstance: (id) => ipcRenderer.invoke('instances:get', id), + createInstance: (data) => ipcRenderer.invoke('instances:create', data), + updateInstance: (id, patch) => ipcRenderer.invoke('instances:update', id, patch), + deleteInstance: (id) => ipcRenderer.invoke('instances:delete', id), + duplicateInstance: (id) => ipcRenderer.invoke('instances:duplicate', id), + openInstanceFolder: (id) => ipcRenderer.invoke('instances:openFolder', id), + openGameDir: (id) => ipcRenderer.invoke('instances:openGameDir', id), + + // Welten & Ressourcenpakete + worlds: (id) => ipcRenderer.invoke('instance:worlds', id), + resourcepacks: (id) => ipcRenderer.invoke('instance:resourcepacks', id), + deleteContent: (id, sub, name) => ipcRenderer.invoke('instance:deleteContent', id, sub, name), + openSubdir: (id, sub) => ipcRenderer.invoke('instance:openSubdir', id, sub), + screenshots: (id) => ipcRenderer.invoke('instance:screenshots', id), + screenshotData: (id, name) => ipcRenderer.invoke('instance:screenshotData', id, name), + openScreenshot: (id, name) => ipcRenderer.invoke('instance:openScreenshot', id, name), + launchInstance: (id, accountId) => ipcRenderer.invoke('instances:launch', id, accountId), + exportInstance: (id) => ipcRenderer.invoke('instances:export', id), + importInstance: () => ipcRenderer.invoke('instances:import'), + importModpack: () => ipcRenderer.invoke('modpack:import'), + onLaunchProgress: (cb) => { + const listener = (_e, data) => cb(data); + ipcRenderer.on('launch:progress', listener); + return () => ipcRenderer.removeListener('launch:progress', listener); + }, + + // eigenes Instanz-Bild + pickImage: () => ipcRenderer.invoke('dialog:pickImage'), + setInstanceImage: (id, sourcePath) => ipcRenderer.invoke('instances:setImage', id, sourcePath), + clearInstanceImage: (id) => ipcRenderer.invoke('instances:clearImage', id), + instanceIcon: (id) => ipcRenderer.invoke('instances:icon', id), + fileDataUri: (p) => ipcRenderer.invoke('file:dataUri', p), + + // Microsoft-Login (Phase 3) + Mehrkonten + authStatus: () => ipcRenderer.invoke('auth:status'), + authAccounts: () => ipcRenderer.invoke('auth:accounts'), + authSetActive: (id) => ipcRenderer.invoke('auth:setActive', id), + authRemove: (id) => ipcRenderer.invoke('auth:remove', id), + authLogin: () => ipcRenderer.invoke('auth:login'), + authLogout: () => ipcRenderer.invoke('auth:logout'), + authHealth: () => ipcRenderer.invoke('auth:health'), + authRecheck: () => ipcRenderer.invoke('auth:recheck'), + onAuthHealth: (cb) => { + const listener = (_e, data) => cb(data); + ipcRenderer.on('auth:health', listener); + return () => ipcRenderer.removeListener('auth:health', listener); + }, + onAuthRefreshed: (cb) => { + const listener = () => cb(); + ipcRenderer.on('auth:refreshed', listener); + return () => ipcRenderer.removeListener('auth:refreshed', listener); + }, + onAuthCode: (cb) => { + const listener = (_e, data) => cb(data); + ipcRenderer.on('auth:code', listener); + return () => ipcRenderer.removeListener('auth:code', listener); + }, + + // Dialoge / App + openExternal: (url) => ipcRenderer.invoke('app:openExternal', url), + pickFolder: (title) => ipcRenderer.invoke('dialog:pickFolder', title), + pickJava: () => ipcRenderer.invoke('dialog:pickJava'), + appInfo: () => ipcRenderer.invoke('app:info'), +}); diff --git a/src/renderer.js b/src/renderer.js new file mode 100644 index 0000000..ee4c492 --- /dev/null +++ b/src/renderer.js @@ -0,0 +1,1488 @@ +'use strict'; + +/* renderer.js – UI-Logik für AeroMC */ + +// ---------- Instanz-Icons: eigene Pixel-Grafiken im Minecraft-Stil ---------- +// Jedes Icon ist ein 16x16-Raster; jedes Zeichen verweist auf eine Farbe der Palette. +const PIX = { + grass: { p: { a: '#7cbd56', b: '#63a343', c: '#8b6b4a', d: '#6f5238' }, r: [ + 'aaaaaaaaaaaaaaaa', 'abaabaaabaabaaab', 'aaaaaaaaaaaaaaaa', 'babaabaabaaabaab', + 'cccccccccccccccc', 'cdcccdcccccdccdc', 'ccccccccdcccccdc', 'cccdccccccccdccc', + 'dcccccdcccccdccc', 'ccccdccccdccccdc', 'cdccccccccccccdc', 'ccccccdcccccdccc', + 'ccdcccccccdccccc', 'cccccccdccccccdc', 'cdccccccccccdccc', 'cccccccccccccccc', + ] }, + creeper: { p: { a: '#7cbd56', b: '#5f9c42', k: '#0d0f0d' }, r: [ + 'abbaabbaabbaabba', 'baabbaabbaabbaab', 'abbaabbaabbaabba', 'aakkaaaaaaaakkaa', + 'aakkaaaaaaaakkaa', 'aaaaaakkkkaaaaaa', 'aaaaakkkkkkaaaaa', 'aaaaakkkkkkaaaaa', + 'aaaaakkaakkaaaaa', 'aaaaakkaakkaaaaa', 'abbaabbaabbaabba', 'baabbaabbaabbaab', + 'abbaabbaabbaabba', 'baabbaabbaabbaab', 'abbaabbaabbaabba', 'baabbaabbaabbaab', + ] }, + diamond: { p: { a: '#5ce4e0', b: '#3ec6c9', c: '#2aa3ab', w: '#c9fbff', t: null }, r: [ + 'tttttttttttttttt', 'tttttttttttttttt', 'tttttaaaaaattttt', 'ttttawwwaaaatttt', + 'tttawwbbbaaaattt', 'ttawwbbbbbaaaatt', 'tawwbbbbbbbaaaat', 'abbbbbbbbbbbccca', + 'abbbbbbbbbbbccca', 'tabbbbbbbbbcccat', 'ttabbbbbbbcccatt', 'tttabbbbbcccattt', + 'ttttabbbcccatttt', 'tttttabcccattttt', 'ttttttaccatttttt', 'tttttttaattttttt', + ] }, + tnt: { p: { r: '#c0392b', w: '#f2f2f2', k: '#2b2b2b', d: '#8e2a20' }, r: [ + 'rrrrrrrrrrrrrrrr', 'rdrrrdrrrrdrrrdr', 'wwwwwwwwwwwwwwww', 'wkkwkkwkkwkkwkkw', + 'wkwkwkwkwkwkwkwk', 'wwwwwwwwwwwwwwww', 'rrrrrrrrrrrrrrrr', 'rdrrrrrdrrrrrdrr', + 'rrrrdrrrrrdrrrrr', 'rrdrrrrrdrrrrrdr', 'rrrrrdrrrrrdrrrr', 'rdrrrrrrdrrrrrrr', + 'rrrrdrrrrrrrdrrr', 'rrdrrrrdrrrrrrdr', 'rrrrrrrrrrrrrrrr', 'rrrrrrrrrrrrrrrr', + ] }, + chest: { p: { a: '#a97142', b: '#8a5a33', c: '#6b4423', k: '#3a2716', y: '#e0c060' }, r: [ + 'cccccccccccccccc', 'cabababababababc', 'cbababababababac', 'cabababababababc', + 'ckkkkkkkkkkkkkkc', 'cabababababababc', 'cababyyyyyybabac', 'cababykkkkybabac', + 'cababyyyyyybabac', 'cabababababababc', 'cabababababababc', 'cabababababababc', + 'cabababababababc', 'cabababababababc', 'cabababababababc', 'cccccccccccccccc', + ] }, + sword: { p: { s: '#d8dde6', l: '#f4f7fb', d: '#9aa3b0', h: '#8a5a33', g: '#e0c060', t: null }, r: [ + 'tttttttttttttsst', 'ttttttttttttslls', 'tttttttttttslldt', 'ttttttttttslldtt', + 'tttttttttslldttt', 'ttttttttslldtttt', 'tttttttslldttttt', 'ttttttslldtttttt', + 'tttttslldttttttt', 'ttttslldtttttttt', 'tttgllgdtttttttt', 'tthhghhttttttttt', + 'ttthhhtttttttttt', 'tttthhtttttttttt', 'ttttthtttttttttt', 'tttttttttttttttt', + ] }, + pickaxe: { p: { s: '#c9ced6', l: '#eef2f7', d: '#8e959f', h: '#8a5a33', b: '#6b4423', t: null }, r: [ + 'tttssssttssssttt', 'ttslllsddslllstt', 'tsllddsttsddllst', 'tsldttttttttdlst', + 'ttdttttsstttttdt', 'tttttthhtttttttt', 'ttttttbhtttttttt', 'ttttttthbttttttt', + 'tttttttbhttttttt', 'ttttttttbhtttttt', 'ttttttttthbttttt', 'ttttttttttbhtttt', + 'tttttttttttbhttt', 'ttttttttttttbhtt', 'tttttttttttttbht', 'tttttttttttttttt', + ] }, + potion: { p: { g: '#cfd8e3', l: '#eef3fa', v: '#c0392b', d: '#8e2a20', k: '#5a4632', t: null }, r: [ + 'ttttttkkkktttttt', 'tttttkllkktttttt', 'tttttkllkttttttt', 'tttttkllkttttttt', + 'ttttkglllgkttttt', 'tttkgllllllgkttt', 'ttkglvvvvvvlgktt', 'tkglvvvvvvvvlgkt', + 'tkglvvvvvvvvlgkt', 'tkglvvvvvvvvlgkt', 'tkgdvvvvvvvvdgkt', 'tkgdvvvvvvvvdgkt', + 'ttkgdvvvvvvdgktt', 'tttkgdvvvvdgkttt', 'ttttkkgggggkkttt', 'tttttkkkkkkkkttt', + ] }, + nether: { p: { a: '#e07b39', b: '#c9542a', c: '#8f2f18', y: '#f7c948', t: null }, r: [ + 'tttttttyyttttttt', 'ttttttyaaytttttt', 'tttttyaaaayttttt', 'ttttyaaaaaaytttt', + 'tttyaabbaaaayttt', 'ttyaabbbbaaayttt', 'tyaabbbbbbaaaytt', 'yaabbbcccbbbaayt', + 'yabbbcccccbbbayt', 'yabbcccccccbbayt', 'yabbcccccccbbayt', 'tyabcccccccbaytt', + 'ttyabcccccbayttt', 'tttyabcccbaytttt', 'ttttyaabbayttttt', 'tttttyyyyytttttt', + ] }, + end: { p: { a: '#2f6f66', b: '#3f8f83', c: '#1f4a45', w: '#bff5ea', t: null }, r: [ + 'tttttbbbbbbttttt', 'tttbbaaaaaabbttt', 'ttbaaaawwaaaabtt', 'tbaaawwwwwwaaabt', + 'baaawwbbbbwwaaab', 'baawwbbaabbwwaab', 'baawbbaaaabbwaab', 'bawbbaaaaaabbwab', + 'bawbbaaaaaabbwab', 'baawbbaaaabbwaab', 'baawwbbaabbwwaab', 'baaawwbbbbwwaaab', + 'tbaaawwwwwwaaabt', 'ttbaaaawwaaaabtt', 'tttbbaaaaaabbttt', 'tttttbbbbbbttttt', + ] }, + redstone: { p: { a: '#c0392b', b: '#8e2a20', c: '#5c1a13', g: '#3a3a3a', t: null }, r: [ + 'tttttttggttttttt', 'ttttttgaagtttttt', 'tttttgaaaagttttt', 'ttttgaabbaagtttt', + 'tttgaabbbbaagttt', 'ttgaabbbbbbaagtt', 'tgaabbbccbbbaagt', 'gaabbbcccccbbaag', + 'gaabbbcccccbbaag', 'tgaabbbccbbbaagt', 'ttgaabbbbbbaagtt', 'tttgaabbbbaagttt', + 'ttttgaabbaagtttt', 'tttttgaaaagttttt', 'ttttttgaagtttttt', 'tttttttggttttttt', + ] }, + gold: { p: { a: '#f7d774', b: '#e0b53c', c: '#b8891f', t: null }, r: [ + 'tttttttttttttttt', 'tttttttttttttttt', 'tttaaaaaaaaaattt', 'ttaaaaaaaaaaaatt', + 'taaabbbbbbbbaaat', 'taabbbbbbbbbbaat', 'taabbbbbbbbbbaat', 'tabbbbbbbbbbbbat', + 'tabbbbbbbbbbbbat', 'tabbbcccccbbbbat', 'taccccccccccccat', 'taccccccccccccat', + 'ttcccccccccccctt', 'tttccccccccccttt', 'tttttttttttttttt', 'tttttttttttttttt', + ] }, + book: { p: { a: '#8a5a33', b: '#6b4423', w: '#f0e6d2', y: '#e0c060', t: null }, r: [ + 'tbbbbbbbbbbbbbbt', 'bawwwwwwwwwwwwab', 'bawwwwwwwwwwwwab', 'bawwbbbwwbbbwwab', + 'bawwwwwwwwwwwwab', 'bawwbbbbwbbbbwab', 'bawwwwwwwwwwwwab', 'bawwbbbwwbbbwwab', + 'bawwwwwwwwwwwwab', 'bawwbbbbwbbbbwab', 'bawwwwwwwwwwwwab', 'bawwwwyywwwwwwab', + 'bawwwwyywwwwwwab', 'bawwwwwwwwwwwwab', 'bawwwwwwwwwwwwab', 'tbbbbbbbbbbbbbbt', + ] }, + map: { p: { a: '#e8dcc0', b: '#cdbb95', c: '#8a5a33', g: '#7cbd56', u: '#4a90d9' }, r: [ + 'cccccccccccccccc', 'caaaaaaaaaaaaaac', 'cabbaaaaaaaaaabc', 'caaauuuaaggaaaac', + 'caaauuuaagggaaac', 'caaaauaaaggaaaac', 'caaaaaaaaaaaaaac', 'caagggaaaaauuaac', + 'caaggggaaaauuaac', 'caagggaaaaauuaac', 'caaaaaaaaaaaaaac', 'caaaaaabbaaaaaac', + 'caaaaabbbbaaaaac', 'caaaaaabbaaaaaac', 'caaaaaaaaaaaaaac', 'cccccccccccccccc', + ] }, + star: { p: { a: '#ffffff', b: '#dfe6f2', c: '#9fb0cc', t: null }, r: [ + 'tttttttaattttttt', 'tttttttaattttttt', 'ttttttbaabtttttt', 'ttttttbaabtttttt', + 'tttttbbaabbttttt', 'ttattbbaabbttatt', 'tabaabbaabbaabat', 'taaaaaaaaaaaaaat', + 'taaaaaaaaaaaaaat', 'tabaabbaabbaabat', 'ttcttbbaabbttctt', 'tttttbbaabbttttt', + 'ttttttbaabtttttt', 'ttttttbaabtttttt', 'tttttttaattttttt', 'tttttttaattttttt', + ] }, +}; + +// baut aus dem Raster ein SVG (skaliert scharf, da reine Rechtecke) +function pixelIconSvg(key, size) { + const def = PIX[key] || PIX.grass; + let rects = ''; + def.r.forEach((row, y) => { + for (let x = 0; x < 16 && x < row.length; x++) { + const col = def.p[row[x]]; + if (!col || col === '#00000000') continue; + rects += ``; + } + }); + return `${rects}`; +} + +const ICON_KEYS = Object.keys(PIX); +const ICON_LABELS = { + grass: 'Grasblock', creeper: 'Creeper', diamond: 'Diamant', tnt: 'TNT', chest: 'Truhe', + sword: 'Schwert', pickaxe: 'Spitzhacke', potion: 'Trank', nether: 'Feuer', end: 'Endauge', + redstone: 'Redstone', gold: 'Goldbarren', book: 'Buch', map: 'Karte', star: 'Netherstern', +}; +function iconOf(key, size = 44) { return pixelIconSvg(key, size); } + +const LOADER_LABEL = { + vanilla: 'Vanilla', fabric: 'Fabric', forge: 'Forge', + neoforge: 'NeoForge', quilt: 'Quilt', +}; + +// ---------- Zustand ---------- +let instances = []; +let currentDetailId = null; +let editingId = null; +let confirmAction = null; +let mcVersionData = null; // gecachte Mojang-Versionsliste +let currentModsInstalled = new Set(); // projectIds im offenen Mod-Dialog +let pendingImagePath = null; // im Dialog gewähltes eigenes Bild (noch nicht gespeichert) +let pendingClearImage = false; // eigenes Bild soll entfernt werden +let loginVerificationUri = null; // aktueller Device-Code-Link +const collapsedGroups = new Set(); // eingeklappte Gruppen +let consoleBuffer = ''; // gesammelte Log-Ausgabe (roh, für Kopieren) +let consolePending = ''; // noch nicht abgeschlossene Zeile + +// ---------- DOM-Helfer ---------- +const el = (id) => document.getElementById(id); +function show(id) { el(id).classList.remove('hidden'); } +function hide(id) { el(id).classList.add('hidden'); } + +function toast(msg, isError = false) { + const t = el('toast'); + t.textContent = msg; + t.classList.toggle('err', isError); + t.classList.remove('hidden'); + clearTimeout(toast._t); + toast._t = setTimeout(() => t.classList.add('hidden'), 2800); +} + +function fmtDate(iso) { + if (!iso) return '–'; + try { return new Date(iso).toLocaleString('de-DE'); } catch { return iso; } +} +function status(text) { el('status-left').textContent = text; } + +function fmtDuration(s) { + s = s || 0; + if (s < 60) return s + ' Sek.'; + const h = Math.floor(s / 3600); + const m = Math.floor((s % 3600) / 60); + return h ? `${h} Std. ${m} Min.` : `${m} Min.`; +} + +function escapeHtml(s) { + return String(s).replace(/[&<>"']/g, (c) => ( + { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c] + )); +} +function numOrNull(v) { const n = parseInt(v, 10); return Number.isFinite(n) ? n : null; } + +function applyTheme(theme) { + document.documentElement.setAttribute('data-theme', theme === 'light' ? 'light' : 'dark'); +} + +// ---------- Zustand der Anmelde-Dienste in der Statusleiste ---------- +function showAuthHealth(h) { + const box = el('status-auth'); + if (!h || h.ok) { box.classList.add('hidden'); box.textContent = ''; return; } + const list = (h.down || []).join(', '); + box.textContent = (h.down && h.down.length === AUTH_SERVICE_COUNT) + ? 'Anmelde-Server nicht erreichbar – Login/Start derzeit nicht möglich' + : 'Anmelde-Dienst gestört: ' + list; + box.title = 'Zuletzt geprüft: ' + (h.checked ? new Date(h.checked).toLocaleTimeString('de-DE') : '–') + ' · Klicken zum erneut prüfen'; + box.classList.remove('hidden'); +} +const AUTH_SERVICE_COUNT = 3; + +// ---------- Skin-Hintergrund (wie MultiMCs Katze, nur mit eigenem Skin) ---------- +async function applySkinBackground() { + const s = await window.api.getSettings(); + const root = document.documentElement; + let uuid = ''; + if (s.bgSkin === 'active') { + const acc = await window.api.authStatus(); + uuid = acc && acc.profile ? acc.profile.id : ''; + } else if (s.bgSkin) { + uuid = s.bgSkin; + } + if (!uuid) { root.style.setProperty('--bg-skin', 'none'); return; } + + root.style.setProperty('--bg-skin-opacity', String((s.bgSkinOpacity ?? 55) / 100)); + + // Jede Pose hat auch eine Entsprechung beim 3D-Dienst (Kamerawinkel/Ansicht), + // damit die Auswahl immer sichtbar wirkt – auch wenn der Pose-Dienst offline ist. + // 1) Skin lokal in 3D rendern – unabhängig von Render-Diensten + const local = await renderSkin3D(uuid, s.bgSkinPose || 'walking'); + if (local) { root.style.setProperty('--bg-skin', `url("${local}")`); return; } + + // 2) Rückfall: externe Render-Dienste + for (const url of [ + `https://nmsr.nickac.dev/fullbody/${uuid}?yaw=25&pitch=8`, + `https://visage.surgeplay.com/full/512/${uuid}`, + `https://crafthead.net/armor/body/${uuid}?size=512`, + ]) { + const ok = await new Promise((resolve) => { + const img = new Image(); + img.onload = () => resolve(true); + img.onerror = () => resolve(false); + img.src = url; + }); + if (ok) { root.style.setProperty('--bg-skin', `url("${url}")`); return; } + } + root.style.setProperty('--bg-skin', 'none'); +} + +// Pose-Vorlagen für den lokalen 3D-Renderer (eigene Nachbildungen bekannter Motive) +const SKIN_POSES = { + walking: { label: 'Laufend', fov: 36, zoom: 0.62, apply: (p) => { + p.rotation.set(0.05, -0.62, 0); + p.skin.leftArm.rotation.set(-0.95, 0, 0.06); + p.skin.rightArm.rotation.set(0.85, 0, -0.06); + p.skin.leftLeg.rotation.set(0.8, 0, 0); + p.skin.rightLeg.rotation.set(-0.8, 0, 0); + } }, + standing: { label: 'Stehend', fov: 36, zoom: 0.6, apply: (p) => { + p.rotation.set(0, -0.35, 0); + p.skin.leftArm.rotation.set(0, 0, 0.08); + p.skin.rightArm.rotation.set(0, 0, -0.08); + p.skin.leftLeg.rotation.set(0, 0, 0.02); + p.skin.rightLeg.rotation.set(0, 0, -0.02); + } }, + legends: { label: 'Heldenhaft', fov: 34, zoom: 0.58, apply: (p) => { + p.rotation.set(-0.10, -0.5, 0); + p.skin.leftArm.rotation.set(-0.25, 0, 0.35); + p.skin.rightArm.rotation.set(-0.15, 0, -0.42); + p.skin.leftLeg.rotation.set(0.12, 0, 0.16); + p.skin.rightLeg.rotation.set(-0.12, 0, -0.16); + } }, + bedwars: { label: 'Kampfhaltung', fov: 36, zoom: 0.6, apply: (p) => { + p.rotation.set(0.06, -0.85, 0); + p.skin.rightArm.rotation.set(-1.45, 0, -0.18); // Arm vorgestreckt + p.skin.leftArm.rotation.set(0.45, 0, 0.30); + p.skin.leftLeg.rotation.set(0.45, 0, 0.10); + p.skin.rightLeg.rotation.set(-0.35, 0, -0.10); + } }, + hoverboard: { label: 'Schwebend', fov: 38, zoom: 0.6, apply: (p) => { + p.rotation.set(0.28, -0.7, 0.12); // vorgebeugt, gekippt + p.skin.leftArm.rotation.set(-0.35, 0, 1.05); // Arme zum Ausbalancieren + p.skin.rightArm.rotation.set(-0.35, 0, -1.05); + p.skin.leftLeg.rotation.set(0.5, 0, 0.18); + p.skin.rightLeg.rotation.set(0.15, 0, -0.18); + } }, + sitting: { label: 'Sitzend', fov: 36, zoom: 0.62, apply: (p) => { + p.rotation.set(0.05, -0.55, 0); + p.skin.leftArm.rotation.set(-0.55, 0, 0.18); + p.skin.rightArm.rotation.set(-0.55, 0, -0.18); + p.skin.leftLeg.rotation.set(-1.5, 0, 0.12); // Beine angewinkelt + p.skin.rightLeg.rotation.set(-1.5, 0, -0.12); + } }, + spooky: { label: 'Unheimlich', fov: 32, zoom: 0.6, apply: (p) => { + p.rotation.set(-0.06, -0.45, 0); // gedreht + leichte Untersicht + p.skin.head.rotation.set(0.22, -0.2, 0.28); // Kopf schief gelegt + p.skin.leftArm.rotation.set(-1.35, 0, 0.12); // Arme nach vorn ausgestreckt + p.skin.rightArm.rotation.set(-1.25, 0, -0.16); + p.skin.leftLeg.rotation.set(0.18, 0, 0.06); + p.skin.rightLeg.rotation.set(-0.12, 0, -0.06); + } }, +}; + +// Rendert den Skin lokal mit WebGL in der gewählten Pose +async function renderSkin3D(uuid, poseKey) { + if (typeof skinview3d === 'undefined') return null; + const canvas = el('skin-canvas'); + try { + const viewer = new skinview3d.SkinViewer({ + canvas, width: 420, height: 700, + skin: `https://crafthead.net/skin/${uuid}`, + preserveDrawingBuffer: true, + }); + // Auf das Laden der Skin-Textur warten + await new Promise((resolve, reject) => { + const t = setTimeout(reject, 8000); + const check = () => { + if (viewer.playerObject && viewer.playerObject.skin && viewer.playerObject.skin.map) { clearTimeout(t); resolve(); } + else setTimeout(check, 60); + }; + check(); + }); + + const pose = SKIN_POSES[poseKey] || SKIN_POSES.walking; + viewer.fov = pose.fov; + viewer.zoom = pose.zoom; + viewer.autoRotate = false; + viewer.animation = null; + pose.apply(viewer.playerObject); + + viewer.render(); + const data = canvas.toDataURL('image/png'); + viewer.dispose(); + return data && data.length > 2000 ? data : null; + } catch { + return null; + } +} + +// ---------- Icon-System (SVG statt Emoji) ---------- +const ICONS_SVG = { + plus: '', + import: '', + package: '', + folder: '', + terminal: '', + user: '', + settings: '', + play: '', + blocks: '', + globe: '', + image: '', + edit: '', + copy: '', + export: '', + trash: '', +}; +function svgIcon(name) { + const p = ICONS_SVG[name]; + if (!p) return ''; + const filled = name === 'play'; + const attrs = filled + ? 'fill="currentColor" stroke="none"' + : 'fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"'; + return `${p}`; +} +function applyIcons(root = document) { + root.querySelectorAll('[data-ic]').forEach((b) => { + if (b.querySelector('svg')) return; + b.insertAdjacentHTML('afterbegin', svgIcon(b.dataset.ic)); + }); +} + +// ---------- Instanz-Kacheln ---------- +function buildCard(inst) { + const card = document.createElement('div'); + card.className = 'card' + (inst.id === currentDetailId ? ' sel' : ''); + card.dataset.id = inst.id; + + const iconHtml = inst.iconData + ? `` + : `${iconOf(inst.icon)}`; + // Tooltip: Name, Version/Loader und – falls vorhanden – die Notizen + const loaderTxt = inst.minecraft.loader && inst.minecraft.loader !== 'vanilla' + ? ' · ' + (LOADER_LABEL[inst.minecraft.loader] || inst.minecraft.loader) : ''; + let tip = inst.name + '\n' + (inst.minecraft.version || 'ohne Version') + loaderTxt; + if (inst.notes && inst.notes.trim()) tip += '\n\n' + inst.notes.trim(); + card.title = tip; + + card.innerHTML = ` + ${iconHtml} +
${escapeHtml(inst.name)}
`; + + // einfacher Klick = auswählen (MultiMC), Doppelklick = starten + card.addEventListener('click', () => selectInstance(inst.id)); + card.addEventListener('dblclick', () => launch(inst.id)); + + // Drag & Drop in Gruppen + card.draggable = true; + card.addEventListener('dragstart', (e) => { e.dataTransfer.setData('text/plain', inst.id); card.classList.add('dragging'); }); + card.addEventListener('dragend', () => card.classList.remove('dragging')); + return card; +} + +function render() { + const q = el('search').value.trim().toLowerCase(); + const grid = el('grid'); + grid.innerHTML = ''; + + const filtered = instances.filter((i) => + !q || (i.name + ' ' + i.minecraft.version + ' ' + i.minecraft.loader + ' ' + (i.group || '')).toLowerCase().includes(q)); + + el('empty').classList.toggle('hidden', instances.length !== 0); + grid.classList.toggle('hidden', instances.length === 0); + + // nach Gruppen bündeln + const groups = new Map(); + for (const inst of filtered) { + const g = (inst.group && inst.group.trim()) || ''; + if (!groups.has(g)) groups.set(g, []); + groups.get(g).push(inst); + } + // benannte Gruppen alphabetisch, "ohne Gruppe" zuletzt + const names = [...groups.keys()].sort((a, b) => (a === '' ? 1 : b === '' ? -1 : a.localeCompare(b))); + const showHeaders = names.some((n) => n !== ''); + + for (const g of names) { + const list = groups.get(g); + const section = document.createElement('div'); + section.className = 'group-section' + (collapsedGroups.has(g) ? ' collapsed' : ''); + + if (showHeaders) { + const header = document.createElement('div'); + header.className = 'group-header' + (collapsedGroups.has(g) ? ' collapsed' : ''); + header.innerHTML = `${collapsedGroups.has(g) ? '▸' : '▾'} ${escapeHtml(g || 'Ohne Gruppe')} (${list.length})`; + header.addEventListener('click', () => { + if (collapsedGroups.has(g)) collapsedGroups.delete(g); else collapsedGroups.add(g); + render(); + }); + section.appendChild(header); + } + const gridEl = document.createElement('div'); + gridEl.className = 'group-grid'; + for (const inst of list) gridEl.appendChild(buildCard(inst)); + section.appendChild(gridEl); + + // Drop-Ziel: Instanz per Drag&Drop in diese Gruppe verschieben + section.addEventListener('dragover', (e) => { e.preventDefault(); section.classList.add('drop-hover'); }); + section.addEventListener('dragleave', (e) => { if (!section.contains(e.relatedTarget)) section.classList.remove('drop-hover'); }); + section.addEventListener('drop', async (e) => { + e.preventDefault(); + section.classList.remove('drop-hover'); + const dropId = e.dataTransfer.getData('text/plain'); + const dragged = instances.find((i) => i.id === dropId); + if (dragged && (dragged.group || '') !== g) { + await window.api.updateInstance(dropId, { group: g }); + await reload(); + toast('Verschoben nach: ' + (g || 'Ohne Gruppe')); + } + }); + + grid.appendChild(section); + } + status(`${instances.length} Instanz${instances.length === 1 ? '' : 'en'}`); +} + +function fillGroupDatalist() { + const groups = [...new Set(instances.map((i) => i.group).filter(Boolean))].sort(); + el('group-list').innerHTML = groups.map((g) => ``).join(''); +} + +async function reload() { + instances = await window.api.listInstances(); + render(); +} + +// ---------- Minecraft-Versionen ---------- +async function loadVersions() { + if (mcVersionData) return mcVersionData; + try { + mcVersionData = await window.api.mcVersions(); + } catch (e) { + mcVersionData = { offline: true, versions: [], latest: {} }; + } + return mcVersionData; +} + +function fillVersionSelect(selectedId) { + const type = el('f-version-type').value; + const sel = el('f-version'); + const hint = el('f-version-hint'); + sel.innerHTML = ''; + + const data = mcVersionData || { versions: [], latest: {} }; + let list = data.versions || []; + if (type !== 'all') list = list.filter((v) => v.type === type); + + // gewählte Version muss vorhanden sein (auch wenn Filter sie ausblendet) + if (selectedId && !list.some((v) => v.id === selectedId)) { + const found = (data.versions || []).find((v) => v.id === selectedId); + list = [found || { id: selectedId, type: 'unknown' }, ...list]; + } + + if (!list.length) { + const o = document.createElement('option'); + o.value = selectedId || ''; + o.textContent = selectedId || '(keine Versionsliste – offline?)'; + sel.appendChild(o); + } else { + for (const v of list.slice(0, 1200)) { + const o = document.createElement('option'); + o.value = v.id; + o.textContent = v.id; + if (v.id === selectedId) o.selected = true; + sel.appendChild(o); + } + } + + if (data.offline) hint.textContent = '⚠ Offline – Versionsliste evtl. veraltet.'; + else if (data.latest) hint.textContent = `Neuestes Release: ${data.latest.release || '?'} · Snapshot: ${data.latest.snapshot || '?'}`; +} + +// Loader-Versionen (Fabric/Quilt) passend zur MC-Version laden +async function updateLoaderVersions(preselect) { + const loader = el('f-loader').value; + const mc = el('f-version').value; + const sel = el('f-loader-version'); + const hint = el('f-loader-hint'); + sel.innerHTML = ''; + + if (loader === 'vanilla') { sel.disabled = true; hint.textContent = 'Vanilla hat keinen Loader.'; return; } + sel.disabled = false; + if (!mc) { hint.textContent = 'Erst Minecraft-Version wählen.'; return; } + + hint.textContent = 'Lade Loader-Versionen …'; + try { + const versions = await window.api.loaderVersions(loader, mc); + for (const v of versions.slice(0, 80)) { + const o = document.createElement('option'); + o.value = v.version; + o.textContent = v.version + (v.stable ? '' : ' (beta)'); + if (v.version === preselect) o.selected = true; + sel.appendChild(o); + } + hint.textContent = versions.length ? `${versions.length} Version(en) verfügbar` : 'Keine Loader-Version für diese MC-Version.'; + } catch { + hint.textContent = 'Loader-Versionen konnten nicht geladen werden.'; + } +} + +// ---------- Instanz-Dialog ---------- +function fillIconSelect(selected) { + const sel = el('f-icon'); + sel.innerHTML = ''; + for (const key of ICON_KEYS) { + const o = document.createElement('option'); + o.value = key; + o.textContent = ICON_LABELS[key] || key; + if (key === selected) o.selected = true; + sel.appendChild(o); + } + renderIconChoices(selected); +} + +// klickbare Item-Vorschau unter der Auswahl +function renderIconChoices(selected) { + const box = el('f-icon-grid'); + if (!box) return; + box.innerHTML = ''; + for (const key of ICON_KEYS) { + const b = document.createElement('button'); + b.type = 'button'; + b.className = 'icon-choice' + (key === selected ? ' on' : ''); + b.title = ICON_LABELS[key] || key; + b.innerHTML = pixelIconSvg(key, 26); + b.addEventListener('click', () => { + el('f-icon').value = key; + renderIconChoices(key); + }); + box.appendChild(b); + } +} + +// zeigt/versteckt die Bildvorschau im Dialog +function setIconPreview(dataUri) { + const box = el('f-icon-preview'); + const clr = el('f-clear-image'); + if (dataUri) { + box.innerHTML = ``; + box.classList.remove('hidden'); + clr.classList.remove('hidden'); + } else { + box.innerHTML = ''; + box.classList.add('hidden'); + clr.classList.add('hidden'); + } +} + +function resetIconControls() { + pendingImagePath = null; + pendingClearImage = false; + setIconPreview(null); +} + +async function openCreate() { + editingId = null; + el('instance-modal-title').textContent = 'Neue Instanz'; + el('f-name').value = ''; + el('f-group').value = ''; + fillGroupDatalist(); + el('f-loader').value = 'vanilla'; + el('f-loader-version').value = ''; + el('f-notes').value = ''; + fillIconSelect('grass'); + resetIconControls(); + el('f-advanced').classList.add('hidden'); + show('modal-instance'); + el('f-name').focus(); + + el('f-version-hint').textContent = 'Lade Versionsliste …'; + await loadVersions(); + el('f-version-type').value = 'release'; + fillVersionSelect(mcVersionData.latest && mcVersionData.latest.release); + updateLoaderVersions(); +} + +async function openEdit(inst) { + editingId = inst.id; + el('instance-modal-title').textContent = 'Instanz bearbeiten'; + el('f-name').value = inst.name; + el('f-group').value = inst.group || ''; + fillGroupDatalist(); + el('f-loader').value = inst.minecraft.loader || 'vanilla'; + el('f-loader-version').value = inst.minecraft.loaderVersion || ''; + el('f-notes').value = inst.notes || ''; + fillIconSelect(inst.icon); + resetIconControls(); + if (inst.customImage) { + const data = await window.api.instanceIcon(inst.id); + if (data) setIconPreview(data); + } + el('f-min-mem').value = inst.java.minMemMb || ''; + el('f-max-mem').value = inst.java.maxMemMb || ''; + el('f-extra-args').value = inst.java.extraArgs || ''; + el('f-prelaunch').value = inst.preLaunchCommand || ''; + el('f-postexit').value = inst.postExitCommand || ''; + el('f-advanced').classList.remove('hidden'); + show('modal-instance'); + el('f-name').focus(); + + el('f-version-hint').textContent = 'Lade Versionsliste …'; + await loadVersions(); + el('f-version-type').value = inst.minecraft.version ? 'all' : 'release'; + fillVersionSelect(inst.minecraft.version || (mcVersionData.latest && mcVersionData.latest.release)); + await updateLoaderVersions(inst.minecraft.loaderVersion); +} + +async function saveInstance() { + const name = el('f-name').value.trim(); + if (!name) { toast('Bitte einen Namen angeben.', true); el('f-name').focus(); return; } + + const payload = { + name, + group: el('f-group').value.trim(), + icon: el('f-icon').value, + notes: el('f-notes').value.trim(), + minecraft: { + version: el('f-version').value.trim(), + loader: el('f-loader').value, + loaderVersion: el('f-loader-version').value.trim(), + }, + }; + try { + let targetId = editingId; + if (editingId) { + payload.java = { + minMemMb: numOrNull(el('f-min-mem').value), + maxMemMb: numOrNull(el('f-max-mem').value), + extraArgs: el('f-extra-args').value.trim(), + }; + payload.preLaunchCommand = el('f-prelaunch').value.trim(); + payload.postExitCommand = el('f-postexit').value.trim(); + await window.api.updateInstance(editingId, payload); + } else { + const created = await window.api.createInstance(payload); + targetId = created.id; + } + // eigenes Bild anwenden bzw. entfernen + if (pendingImagePath) await window.api.setInstanceImage(targetId, pendingImagePath); + else if (pendingClearImage && editingId) await window.api.clearInstanceImage(targetId); + + toast(editingId ? 'Instanz gespeichert.' : 'Instanz angelegt.'); + hide('modal-instance'); + await reload(); + await selectInstance(targetId); + } catch (e) { + toast('Fehler: ' + e.message, true); + } +} + +// ---------- Auswahl + rechte Aktionsleiste (MultiMC-Stil) ---------- +async function selectInstance(id) { + currentDetailId = id; + document.querySelectorAll('.card').forEach((c) => c.classList.toggle('sel', c.dataset.id === id)); + // Auswahl merken, damit sie beim nächsten Start wiederhergestellt wird + window.api.saveSettings({ lastSelectedId: id || '' }); + + const inst = id ? await window.api.getInstance(id) : null; + const panelC = el('p-content'); + const panelE = el('p-empty'); + if (!inst) { + panelC.classList.add('hidden'); + panelE.classList.remove('hidden'); + el('status-left').textContent = 'Bereit'; + el('status-play').textContent = 'Keine Instanz ausgewählt'; + el('status-total').textContent = ''; + return; + } + panelE.classList.add('hidden'); + panelC.classList.remove('hidden'); + + const iconData = inst.customImage ? await window.api.instanceIcon(id) : null; + if (iconData) el('p-icon').innerHTML = ``; + else { el('p-icon').innerHTML = iconOf(inst.icon, 56); } + el('p-name').textContent = inst.name; + + const loaderTxt = inst.minecraft.loader && inst.minecraft.loader !== 'vanilla' + ? ' · ' + (LOADER_LABEL[inst.minecraft.loader] || inst.minecraft.loader) : ''; + el('status-left').textContent = inst.name + ' (' + (inst.minecraft.version || 'ohne Version') + loaderTxt + ')'; + el('status-play').textContent = 'Zuletzt gespielt: ' + (inst.lastPlayed ? fmtDate(inst.lastPlayed) : 'nie'); + el('status-total').textContent = 'Spielzeit: ' + fmtDuration(inst.totalPlaySeconds); +} + +let launching = false; + +async function launch(id, accountId) { + if (launching) return; + launching = true; + status('Vorbereiten …'); + el('status-right').textContent = ''; + appendConsole('\n=== Start: ' + new Date().toLocaleTimeString('de-DE') + ' ===\n'); + try { + const res = await window.api.launchInstance(id, accountId); + if (res.ok) { + status('Läuft (PID ' + res.pid + ')'); + toast('Minecraft gestartet.'); + openConsole(); + } else if (res.needAuth) { + status('Bereit'); el('status-right').textContent = ''; + toast(res.message, false); + } else { + status('Bereit'); el('status-right').textContent = ''; + toast(res.message || 'Start fehlgeschlagen.', true); + } + } catch (e) { + status('Bereit'); toast('Fehler: ' + e.message, true); + } finally { + launching = false; + } +} + +// Fortschrittsmeldungen der Download-/Start-Pipeline +function onLaunchEvt(evt) { + const labels = { version: 'Version', client: 'Client', libraries: 'Libraries', assets: 'Assets', loader: 'Loader', java: 'Java', launch: 'Start', modpack: 'Modpack' }; + if (evt.phase === 'log') { appendConsole(evt.line); return; } + if (evt.phase === 'exit') { + status('Minecraft beendet (Code ' + evt.code + ')'); + el('status-right').textContent = ''; + appendConsole('\n[Prozess beendet, Code ' + evt.code + ']\n'); + return; + } + const label = labels[evt.phase] || evt.phase; + if (evt.total) { + status(`${label} … ${evt.current}/${evt.total}`); + el('status-right').textContent = Math.round((evt.current / evt.total) * 100) + '%'; + } else { + status(evt.detail || label + ' …'); + el('status-right').textContent = ''; + appendConsole('[' + label + '] ' + (evt.detail || '') + '\n'); + } +} + +// ---------- Konsole ---------- +function classifyLine(l) { + if (/\/(ERROR|FATAL|SEVERE)\]/.test(l) || /Exception(:| in )|^\s+at\s|Caused by:/.test(l)) return 'log-error'; + if (/\/WARN(ING)?\]/.test(l) || /\bWARN\b/.test(l)) return 'log-warn'; + if (/\[Pre-Launch\]|\[Post-Exit\]|=== Start:|\[Prozess beendet/.test(l)) return 'log-info'; + return ''; +} +function appendLineEl(out, line) { + const div = document.createElement('div'); + div.className = 'log-line ' + classifyLine(line); + div.textContent = line; + out.appendChild(div); +} +function appendConsole(text) { + consoleBuffer += text; + if (consoleBuffer.length > 300000) consoleBuffer = consoleBuffer.slice(-220000); + consolePending += text; + const lines = consolePending.split('\n'); + consolePending = lines.pop(); + const out = el('console-out'); + if (!el('modal-console').classList.contains('hidden')) { + for (const line of lines) appendLineEl(out, line); + out.scrollTop = out.scrollHeight; + } +} +function openConsole() { + const out = el('console-out'); + out.innerHTML = ''; + const lines = (consoleBuffer || '(noch keine Ausgabe)').split('\n'); + for (const line of lines) appendLineEl(out, line); + consolePending = ''; + show('modal-console'); + out.scrollTop = out.scrollHeight; +} + +// ---------- Welten & Ressourcenpakete ---------- +async function openContent() { + const inst = await window.api.getInstance(currentDetailId); + el('content-title').textContent = 'Welten & Ressourcenpakete – ' + inst.name; + await renderContentLists(); + show('modal-content'); +} +async function renderContentLists() { + renderContentList('content-worlds', await window.api.worlds(currentDetailId), 'saves', '🌍'); + renderContentList('content-rp', await window.api.resourcepacks(currentDetailId), 'resourcepacks', '🎨'); +} +// ---------- Screenshots ---------- +async function openScreens() { + const inst = await window.api.getInstance(currentDetailId); + el('screens-title').textContent = 'Screenshots – ' + inst.name; + const grid = el('screens-grid'); + grid.innerHTML = '
Lade …
'; + show('modal-screens'); + + const shots = await window.api.screenshots(currentDetailId); + grid.innerHTML = ''; + if (!shots.length) { grid.innerHTML = '
Keine Screenshots vorhanden.
'; return; } + for (const s of shots) { + const thumb = document.createElement('div'); + thumb.className = 'screen-thumb'; + thumb.innerHTML = + `
${escapeHtml(s.name)}
+ `; + const img = thumb.querySelector('img'); + window.api.screenshotData(currentDetailId, s.name).then((d) => { if (d) img.src = d; }); + img.addEventListener('click', () => window.api.openScreenshot(currentDetailId, s.name)); + thumb.querySelector('.screen-del').addEventListener('click', (e) => { + e.stopPropagation(); + askConfirm('Screenshot löschen', `„${s.name}" löschen?`, '🗑 Löschen', async () => { + await window.api.deleteContent(currentDetailId, 'screenshots', s.name); + openScreens(); + }); + }); + grid.appendChild(thumb); + } +} + +function renderContentList(boxId, items, sub, emoji) { + const box = el(boxId); + box.innerHTML = ''; + if (!items.length) { box.innerHTML = '
Nichts vorhanden.
'; return; } + for (const it of items) { + const item = document.createElement('div'); + item.className = 'mod-item'; + item.innerHTML = + `
${emoji}
+
${escapeHtml(it.name)}
+
`; + const rm = document.createElement('button'); + rm.className = 'btn btn-danger btn-mini'; + rm.textContent = 'Löschen'; + rm.addEventListener('click', () => askConfirm( + 'Löschen', `„${it.name}" wird unwiderruflich gelöscht. Fortfahren?`, '🗑 Löschen', + async () => { await window.api.deleteContent(currentDetailId, sub, it.name); await renderContentLists(); toast('Gelöscht: ' + it.name); }, + )); + item.querySelector('.mod-action').appendChild(rm); + box.appendChild(item); + } +} + +// ---------- Mod-Browser ---------- +async function openMods() { + const inst = await window.api.getInstance(currentDetailId); + if (!inst) return; + el('m-title').textContent = 'Mods – ' + inst.name; + const loaderTxt = LOADER_LABEL[inst.minecraft.loader] || inst.minecraft.loader; + el('m-sub').textContent = (inst.minecraft.version || 'keine Version') + ' · ' + loaderTxt; + + const warn = el('m-warn'); + const blocked = !inst.minecraft.version || inst.minecraft.loader === 'vanilla'; + if (blocked) { + warn.classList.remove('hidden'); + warn.textContent = !inst.minecraft.version + ? '⚠ Diese Instanz hat keine Minecraft-Version. Bitte zuerst im Bearbeiten-Dialog eine Version wählen.' + : '⚠ Vanilla-Instanzen unterstützen keine Mods. Wähle beim Bearbeiten einen Mod-Loader (Fabric/Forge/NeoForge/Quilt).'; + } else { + warn.classList.add('hidden'); + } + ['m-query', 'm-search-btn', 'm-sort', 'm-category'].forEach((id) => { el(id).disabled = blocked; }); + el('m-query').value = ''; + el('m-more').classList.add('hidden'); + switchModTab('catalog'); + + await refreshInstalled(); + show('modal-mods'); + if (blocked) { + const box = el('m-results'); + box.innerHTML = '
Für Mods braucht diese Instanz einen Mod-Loader.
'; + const b = document.createElement('button'); + b.className = 'btn btn-primary'; + b.style.margin = '0 auto'; + b.style.display = 'block'; + b.textContent = 'Mod-Loader hinzufügen'; + b.addEventListener('click', async () => { + hide('modal-mods'); + const i = await window.api.getInstance(currentDetailId); + if (i) openEdit(i); + }); + box.appendChild(b); + } else { + await loadCatalog(false); // beliebte Mods sofort anzeigen + } +} + +function switchModTab(which) { + const cat = which === 'catalog'; + el('m-tab-catalog').classList.toggle('on', cat); + el('m-tab-installed').classList.toggle('on', !cat); + el('m-pane-catalog').classList.toggle('hidden', !cat); + el('m-pane-installed').classList.toggle('hidden', cat); +} + +async function refreshInstalled() { + const list = await window.api.modList(currentDetailId); + currentModsInstalled = new Set(list.map((m) => m.projectId)); + el('m-installed-count').textContent = String(list.length); + const box = el('m-installed'); + box.innerHTML = ''; + if (!list.length) { box.innerHTML = '
Noch keine Mods.
'; return; } + for (const m of list) { + const item = document.createElement('div'); + item.className = 'mod-item'; + item.innerHTML = + `
🧩
+
+
${escapeHtml(m.title)}
+
${escapeHtml(m.versionNumber || '')} · ${escapeHtml(m.filename)}
+
+
`; + const btn = document.createElement('button'); + btn.className = 'btn btn-danger btn-mini'; + btn.textContent = 'Entfernen'; + btn.addEventListener('click', async () => { + await window.api.modRemove(currentDetailId, m.filename); + toast('Entfernt: ' + m.title); + await refreshInstalled(); + }); + item.querySelector('.mod-action').appendChild(btn); + box.appendChild(item); + } +} + +let modOffset = 0; +async function loadCatalog(append) { + const inst = await window.api.getInstance(currentDetailId); + if (!inst || !inst.minecraft.version || inst.minecraft.loader === 'vanilla') return; + const box = el('m-results'); + if (!append) { modOffset = 0; box.innerHTML = '
Lade …
'; el('m-more').classList.add('hidden'); } + try { + const res = await window.api.modSearch({ + query: el('m-query').value.trim(), + gameVersion: inst.minecraft.version, + loader: inst.minecraft.loader, + category: el('m-category').value, + sort: el('m-sort').value, + limit: 30, + offset: modOffset, + }); + if (!append) box.innerHTML = ''; + if (!res.hits.length && !append) { + box.innerHTML = '
Nichts gefunden.
'; + el('m-more').classList.add('hidden'); + return; + } + for (const mod of res.hits) box.appendChild(buildResultItem(mod)); + modOffset += res.hits.length; + el('m-more').classList.toggle('hidden', res.hits.length < 30 || modOffset >= res.total); + } catch (e) { + if (!append) box.innerHTML = `
Fehler: ${escapeHtml(e.message)}
`; + } +} + +function buildResultItem(mod) { + const item = document.createElement('div'); + item.className = 'mod-item'; + + const icon = document.createElement(mod.iconUrl ? 'img' : 'div'); + icon.className = 'mod-icon'; + if (mod.iconUrl) { + icon.src = mod.iconUrl; + icon.addEventListener('error', () => { + const d = document.createElement('div'); + d.className = 'mod-icon'; d.textContent = '🧩'; + icon.replaceWith(d); + }); + } else { icon.textContent = '🧩'; } + + const info = document.createElement('div'); + info.className = 'mod-info'; + info.innerHTML = + `
${escapeHtml(mod.title)}
+
${escapeHtml(mod.description || '')}
+
von ${escapeHtml(mod.author)} · ${Number(mod.downloads).toLocaleString('de-DE')} Downloads
`; + + const action = document.createElement('div'); + action.className = 'mod-action'; + const btn = document.createElement('button'); + btn.className = 'btn btn-primary btn-mini'; + const already = currentModsInstalled.has(mod.projectId); + if (already) { + btn.textContent = '✓ Installiert'; btn.disabled = true; + } else { + btn.textContent = 'Installieren'; + btn.addEventListener('click', (e) => { e.stopPropagation(); installMod(mod, btn, item); }); + // ganze Zeile klickbar: ein Klick installiert Mod + alle Abhängigkeiten + item.classList.add('clickable'); + item.title = 'Klicken zum Installieren (inkl. Abhängigkeiten)'; + item.addEventListener('click', () => { if (!btn.disabled) installMod(mod, btn, item); }); + } + action.appendChild(btn); + + item.appendChild(icon); item.appendChild(info); item.appendChild(action); + return item; +} + +async function installMod(mod, btn, item) { + btn.disabled = true; btn.textContent = 'Lädt …'; + if (item) { item.classList.add('installing'); item.classList.remove('clickable'); } + const res = await window.api.modInstall(currentDetailId, { projectId: mod.projectId, title: mod.title }); + if (item) item.classList.remove('installing'); + if (res.ok) { + const dep = res.depCount ? ` (+${res.depCount} Abhängigkeit${res.depCount > 1 ? 'en' : ''})` : ''; + toast('Installiert: ' + mod.title + dep); + btn.textContent = '✓ Installiert'; + currentModsInstalled.add(mod.projectId); + await refreshInstalled(); + } else { + toast(res.message || 'Installation fehlgeschlagen.', true); + btn.disabled = false; btn.textContent = 'Installieren'; + if (item) item.classList.add('clickable'); + } +} + +// ---------- Einstellungen ---------- +async function openSettings() { + // immer mit der ersten Sektion starten + document.querySelectorAll('.snav').forEach((x, i) => x.classList.toggle('on', i === 0)); + document.querySelectorAll('.spane').forEach((p) => p.classList.toggle('hidden', p.id !== 'pane-launcher')); + + const s = await window.api.getSettings(); + el('s-theme').value = s.theme || 'dark'; + el('s-global-pre').value = s.globalPreLaunch || ''; + el('s-global-post').value = s.globalPostExit || ''; + el('s-wrapper').value = s.wrapperCommand || ''; + + // Skin-Hintergrund: Auswahl aus allen angemeldeten Konten + const accs = await window.api.authAccounts(); + const sel = el('s-bgskin'); + sel.innerHTML = ''; + for (const a of accs) { + const o = document.createElement('option'); + o.value = a.id; o.textContent = a.name; + sel.appendChild(o); + } + sel.value = s.bgSkin || ''; + el('s-bgskin-pose').value = s.bgSkinPose || 'walking'; + el('s-bgskin-opacity').value = s.bgSkinOpacity ?? 55; + el('s-bgskin-val').textContent = String(s.bgSkinOpacity ?? 55); + el('s-proxy-enabled').checked = !!s.proxyEnabled; + el('s-proxy-host').value = s.proxyHost || ''; + el('s-proxy-port').value = s.proxyPort || ''; + el('s-proxy-user').value = s.proxyUser || ''; + el('s-proxy-pass').value = s.proxyPass || ''; + el('s-instances-dir').value = await window.api.getInstancesDir(); + el('s-java').value = s.javaPath || ''; + el('s-min-mem').value = s.defaultMinMemMb; + el('s-max-mem').value = s.defaultMaxMemMb; + el('s-java-detected').innerHTML = ''; + await refreshJavaStatus(s.javaPath); + + const info = await window.api.appInfo(); + el('s-appinfo').innerHTML = + `AeroMC ${info.version} · Electron ${info.electron} · Node ${info.node}
` + + `${escapeHtml(info.userData)}`; + show('modal-settings'); +} + +async function refreshJavaStatus(javaPath) { + el('s-java-status').textContent = 'Prüfe Java …'; + const r = await window.api.detectJava(javaPath); + el('s-java-status').textContent = r.ok ? '✔ ' + r.version : '✖ Java nicht gefunden (' + (r.error || 'unbekannt') + ')'; + el('s-java-status').style.color = r.ok ? 'var(--accent-hover)' : 'var(--danger-hover)'; +} + +async function scanJava() { + const btn = el('s-scan-java'); + btn.disabled = true; btn.textContent = 'Suche …'; + try { + const jvms = await window.api.scanJava(); + const sel = el('s-java-detected'); + sel.innerHTML = ''; + for (const j of jvms) { + const o = document.createElement('option'); + o.value = j.path; + o.textContent = `Java ${j.major} (${j.arch}) – ${j.path}`; + sel.appendChild(o); + } + toast(jvms.length ? `${jvms.length} Java-Installation(en) gefunden.` : 'Keine Java-Installation gefunden.', !jvms.length); + } catch (e) { + toast('Java-Suche fehlgeschlagen: ' + e.message, true); + } finally { + btn.disabled = false; btn.textContent = '🔍 Erkennen'; + } +} + +async function saveSettings() { + const patch = { + theme: el('s-theme').value, + globalPreLaunch: el('s-global-pre').value.trim(), + globalPostExit: el('s-global-post').value.trim(), + bgSkin: el('s-bgskin').value, + bgSkinPose: el('s-bgskin-pose').value, + bgSkinOpacity: numOrNull(el('s-bgskin-opacity').value) || 55, + wrapperCommand: el('s-wrapper').value.trim(), + proxyEnabled: el('s-proxy-enabled').checked, + proxyHost: el('s-proxy-host').value.trim(), + proxyPort: el('s-proxy-port').value.trim(), + proxyUser: el('s-proxy-user').value.trim(), + proxyPass: el('s-proxy-pass').value, + javaPath: el('s-java').value.trim(), + defaultMinMemMb: numOrNull(el('s-min-mem').value) || 2048, + defaultMaxMemMb: numOrNull(el('s-max-mem').value) || 4096, + instancesDir: el('s-instances-dir').value.trim() || null, + }; + await window.api.saveSettings(patch); + applyTheme(patch.theme); + await applySkinBackground(); + hide('modal-settings'); + toast('Einstellungen gespeichert.'); + await reload(); +} + +// ---------- Microsoft-Login / Kontoverwaltung ---------- +async function refreshAccountButton() { + const acc = await window.api.authStatus(); + const av = el('account-av'); + if (acc && acc.profile) { + av.innerHTML = ''; + const img = document.createElement('img'); + img.className = 'acct-head'; + img.src = `https://crafthead.net/bust/${acc.profile.id}?size=64`; + img.addEventListener('error', () => { av.innerHTML = svgIcon('user'); }); + av.appendChild(img); + el('account-name').textContent = acc.profile.name; + } else { + av.innerHTML = svgIcon('user'); + el('account-name').textContent = 'Konten'; + } +} + +async function renderAccounts() { + const accounts = await window.api.authAccounts(); + const box = el('login-accounts'); + box.innerHTML = ''; + if (!accounts.length) { + box.innerHTML = ''; + return; + } + for (const a of accounts) { + const item = document.createElement('div'); + item.className = 'account-item' + (a.active ? ' active' : ''); + + const av = document.createElement('img'); + av.className = 'account-av'; + av.src = `https://crafthead.net/avatar/${a.id}?size=64`; + av.addEventListener('error', () => { + const d = document.createElement('div'); + d.className = 'account-av'; d.textContent = '🎮'; + av.replaceWith(d); + }); + + const main = document.createElement('div'); + main.className = 'account-main'; + main.innerHTML = + ` + `; + + const actions = document.createElement('div'); + actions.className = 'account-actions'; + item.append(av, main, actions); + if (!a.active) { + const use = document.createElement('button'); + use.className = 'btn btn-mini'; + use.textContent = 'Aktivieren'; + use.addEventListener('click', async () => { + await window.api.authSetActive(a.id); + await renderAccounts(); + await refreshAccountButton(); + await applySkinBackground(); + toast('Aktiv: ' + a.name); + }); + actions.appendChild(use); + } + const rm = document.createElement('button'); + rm.className = 'btn btn-danger btn-mini'; + rm.textContent = 'Entfernen'; + rm.addEventListener('click', async () => { + await window.api.authRemove(a.id); + await renderAccounts(); + await refreshAccountButton(); + toast('Entfernt: ' + a.name); + }); + actions.appendChild(rm); + box.appendChild(item); + } +} + +function resetLoginHint() { + const h = el('login-hint'); + h.classList.remove('login-error'); + h.textContent = 'Melde dich mit deinem Microsoft-Konto an (Minecraft Java Edition nötig). Mehrere Konten sind möglich – das aktive wird zum Spielen verwendet.'; +} + +async function openLogin() { + el('login-code').classList.add('hidden'); + resetLoginHint(); + await renderAccounts(); + show('modal-login'); +} + +async function addAccount() { + resetLoginHint(); + el('login-code').classList.remove('hidden'); + el('login-usercode').textContent = '– – – –'; + el('login-url').textContent = 'Lade …'; + el('login-status').textContent = 'Fordere Code an …'; + el('login-add').disabled = true; + try { + const res = await window.api.authLogin(); // läuft bis zur Bestätigung + el('login-code').classList.add('hidden'); + if (res.ok) { + await renderAccounts(); + await refreshAccountButton(); + toast('Angemeldet als ' + res.account.profile.name); + } else { + const msg = res.message || 'Login fehlgeschlagen.'; + el('login-hint').textContent = '✖ ' + msg; + el('login-hint').classList.add('login-error'); + toast(msg, true); + } + } finally { + el('login-add').disabled = false; + } +} + +// Device-Code-Ereignis aus dem Main-Prozess +function onAuthCode(code) { + loginVerificationUri = code.verificationUri; + el('login-code').classList.remove('hidden'); + el('login-url').textContent = code.verificationUri; + el('login-usercode').textContent = code.userCode; + el('login-status').textContent = 'Warte auf Bestätigung im Browser …'; +} + +// ---------- Bestätigung ---------- +function askConfirm(title, text, okLabel, action) { + el('confirm-title').textContent = title; + el('confirm-text').textContent = text; + el('confirm-ok').textContent = okLabel; + confirmAction = action; + show('modal-confirm'); +} + +// ---------- Events ---------- +function wire() { + el('btn-new').addEventListener('click', openCreate); + el('btn-new-2').addEventListener('click', openCreate); + el('btn-settings').addEventListener('click', openSettings); + el('search').addEventListener('input', render); + + el('btn-open-dir').addEventListener('click', () => { + if (currentDetailId) window.api.openInstanceFolder(currentDetailId); + else if (instances[0]) window.api.openInstanceFolder(instances[0].id); + else toast('Noch keine Instanz vorhanden.', false); + }); + + el('btn-import').addEventListener('click', async () => { + const res = await window.api.importInstance(); + if (res.canceled) return; + if (res.ok) { await reload(); toast('Importiert: ' + res.instance.name); } + else toast(res.message || 'Import fehlgeschlagen.', true); + }); + + el('btn-modpack').addEventListener('click', async () => { + status('Importiere Modpack …'); + const res = await window.api.importModpack(); + status('Bereit'); el('status-right').textContent = ''; + if (res.canceled) return; + if (res.ok) { await reload(); toast(`Modpack importiert: ${res.instance.name} (${res.fileCount} Dateien)`); } + else toast(res.message || 'Modpack-Import fehlgeschlagen.', true); + }); + + // Skin-Hintergrund an/aus (wie MultiMCs Katzen-Knopf) + el('btn-skin').addEventListener('click', async () => { + const s = await window.api.getSettings(); + if (s.bgSkin) { + await window.api.saveSettings({ bgSkin: '' }); + toast('Skin-Hintergrund aus.'); + } else { + const acc = await window.api.authStatus(); + if (!acc || !acc.profile) { toast('Erst ein Microsoft-Konto anmelden.', true); return; } + await window.api.saveSettings({ bgSkin: 'active' }); + toast('Skin-Hintergrund an: ' + acc.profile.name); + } + await applySkinBackground(); + }); + + // Warnung anklicken -> sofort erneut prüfen + el('status-auth').addEventListener('click', async () => { + el('status-auth').textContent = 'Prüfe Anmelde-Dienste …'; + const h = await window.api.authRecheck(); + showAuthHealth(h); + if (h.ok) toast('Anmelde-Dienste wieder erreichbar.'); + }); + + // Konsole + el('btn-console').addEventListener('click', openConsole); + el('console-clear').addEventListener('click', () => { consoleBuffer = ''; el('console-out').textContent = ''; }); + el('console-copy').addEventListener('click', async () => { + try { await navigator.clipboard.writeText(consoleBuffer); toast('Log kopiert.'); } + catch { toast('Kopieren nicht möglich.', true); } + }); + + // Instanz-Dialog + el('btn-save-instance').addEventListener('click', saveInstance); + el('f-version-type').addEventListener('change', () => fillVersionSelect(el('f-version').value)); + el('f-loader').addEventListener('change', () => updateLoaderVersions()); + el('f-version').addEventListener('change', () => updateLoaderVersions()); + el('f-pick-image').addEventListener('click', async () => { + const p = await window.api.pickImage(); + if (!p) return; + pendingImagePath = p; + pendingClearImage = false; + const data = await window.api.fileDataUri(p); + setIconPreview(data); + }); + el('f-clear-image').addEventListener('click', () => { + pendingImagePath = null; + pendingClearImage = true; + setIconPreview(null); + }); + + // Rechte Aktionsleiste (Instanz-Aktionen) + el('p-play').addEventListener('click', () => currentDetailId && launch(currentDetailId)); + el('p-offline').addEventListener('click', () => currentDetailId && launch(currentDetailId)); + el('p-shortcut').addEventListener('click', () => toast('Verknüpfung erstellen folgt in einem Update.', false)); + el('p-edit').addEventListener('click', async () => { const inst = await window.api.getInstance(currentDetailId); if (inst) openEdit(inst); }); + el('p-notes').addEventListener('click', async () => { const inst = await window.api.getInstance(currentDetailId); if (inst) openEdit(inst); }); + el('p-groupline').addEventListener('click', async () => { const inst = await window.api.getInstance(currentDetailId); if (inst) openEdit(inst); }); + el('p-mods').addEventListener('click', openMods); + el('p-worlds').addEventListener('click', openContent); + el('p-screens').addEventListener('click', openScreens); + el('p-mcfolder').addEventListener('click', () => currentDetailId && window.api.openGameDir(currentDetailId)); + el('p-configfolder').addEventListener('click', () => currentDetailId && window.api.openSubdir(currentDetailId, 'config')); + el('p-instfolder').addEventListener('click', () => currentDetailId && window.api.openInstanceFolder(currentDetailId)); + el('p-export').addEventListener('click', async () => { + if (!currentDetailId) return; + const res = await window.api.exportInstance(currentDetailId); + if (res.canceled) return; + if (res.ok) toast('Exportiert: ' + res.path); else toast(res.message || 'Export fehlgeschlagen.', true); + }); + el('p-copy').addEventListener('click', async () => { + if (!currentDetailId) return; + const copy = await window.api.duplicateInstance(currentDetailId); + await reload(); await selectInstance(copy.id); toast('Kopiert: ' + copy.name); + }); + el('p-delete').addEventListener('click', async () => { + const inst = await window.api.getInstance(currentDetailId); + if (!inst) return; + askConfirm('Instanz löschen', + `„${inst.name}" wird mit allen Dateien unwiderruflich gelöscht. Fortfahren?`, + 'Endgültig löschen', + async () => { + await window.api.deleteInstance(currentDetailId); + await reload(); + await selectInstance(instances.length ? instances[0].id : null); + toast('Gelöscht.'); + }); + }); + + // Ordner-Buttons in den Inhalte-/Screenshots-Dialogen + el('content-open-worlds').addEventListener('click', () => window.api.openSubdir(currentDetailId, 'saves')); + el('content-open-rp').addEventListener('click', () => window.api.openSubdir(currentDetailId, 'resourcepacks')); + el('screens-open').addEventListener('click', () => window.api.openSubdir(currentDetailId, 'screenshots')); + + // Mod-Dialog + el('m-search-btn').addEventListener('click', () => loadCatalog(false)); + el('m-query').addEventListener('keydown', (e) => { if (e.key === 'Enter') loadCatalog(false); }); + el('m-sort').addEventListener('change', () => loadCatalog(false)); + el('m-category').addEventListener('change', () => loadCatalog(false)); + el('m-more').addEventListener('click', () => loadCatalog(true)); + el('m-tab-catalog').addEventListener('click', () => switchModTab('catalog')); + el('m-tab-installed').addEventListener('click', () => switchModTab('installed')); + el('m-open-folder').addEventListener('click', () => window.api.openGameDir(currentDetailId)); + + // Einstellungen + el('s-pick-dir').addEventListener('click', async () => { + const p = await window.api.pickFolder('Instanz-Verzeichnis wählen'); + if (p) el('s-instances-dir').value = p; + }); + el('s-pick-java').addEventListener('click', async () => { + const p = await window.api.pickJava(); + if (p) { el('s-java').value = p; await refreshJavaStatus(p); } + }); + el('s-theme').addEventListener('change', (e) => applyTheme(e.target.value)); + el('s-bgskin-opacity').addEventListener('input', (e) => { + el('s-bgskin-val').textContent = e.target.value; + document.documentElement.style.setProperty('--bg-skin-opacity', String(e.target.value / 100)); + }); + // Konto-/Pose-Wechsel sofort anwenden (ohne erst zu speichern) + const previewSkin = async () => { + await window.api.saveSettings({ + bgSkin: el('s-bgskin').value, + bgSkinPose: el('s-bgskin-pose').value, + }); + await applySkinBackground(); + }; + el('s-bgskin').addEventListener('change', previewSkin); + el('s-bgskin-pose').addEventListener('change', previewSkin); + el('s-scan-java').addEventListener('click', scanJava); + el('s-java-detected').addEventListener('change', async (e) => { + if (e.target.value) { el('s-java').value = e.target.value; await refreshJavaStatus(e.target.value); } + }); + el('s-java').addEventListener('change', (e) => refreshJavaStatus(e.target.value.trim())); + el('btn-save-settings').addEventListener('click', saveSettings); + document.querySelectorAll('.snav').forEach((b) => b.addEventListener('click', () => { + document.querySelectorAll('.snav').forEach((x) => x.classList.toggle('on', x === b)); + document.querySelectorAll('.spane').forEach((p) => p.classList.toggle('hidden', p.id !== b.dataset.pane)); + })); + el('s-open-accounts').addEventListener('click', () => { hide('modal-settings'); openLogin(); }); + + // Microsoft-Login / Kontoverwaltung + el('btn-account').addEventListener('click', openLogin); + el('login-add').addEventListener('click', addAccount); + el('login-url').addEventListener('click', (e) => { + e.preventDefault(); + if (loginVerificationUri) window.api.openExternal(loginVerificationUri); + }); + el('login-copy').addEventListener('click', async () => { + try { await navigator.clipboard.writeText(el('login-usercode').textContent.trim()); toast('Code kopiert.'); } + catch { toast('Kopieren nicht möglich.', true); } + }); + + // Bestätigung + el('confirm-ok').addEventListener('click', async () => { + hide('modal-confirm'); + if (confirmAction) { const a = confirmAction; confirmAction = null; await a(); } + }); + + // generisches Schließen + document.querySelectorAll('[data-close]').forEach((b) => + b.addEventListener('click', () => b.closest('.modal').classList.add('hidden'))); + document.querySelectorAll('.modal').forEach((m) => + m.addEventListener('mousedown', (e) => { if (e.target === m) m.classList.add('hidden'); })); + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + const open = [...document.querySelectorAll('.modal:not(.hidden)')].pop(); + if (open) open.classList.add('hidden'); + } + }); +} + +window.addEventListener('DOMContentLoaded', async () => { + wire(); + applyIcons(); + try { const s = await window.api.getSettings(); applyTheme(s.theme); } catch { applyTheme('dark'); } + await applySkinBackground(); + window.api.onLaunchProgress(onLaunchEvt); + window.api.onAuthCode(onAuthCode); + window.api.onAuthRefreshed(async () => { await refreshAccountButton(); await applySkinBackground(); }); + window.api.onAuthHealth(showAuthHealth); + try { showAuthHealth(await window.api.authHealth()); } catch { /* noch keine Prüfung */ } + await refreshAccountButton(); + await reload(); + + // zuletzt gewählte Instanz wieder markieren (sonst die zuletzt gespielte) + if (instances.length) { + let start = null; + try { + const s = await window.api.getSettings(); + if (s.lastSelectedId && instances.some((i) => i.id === s.lastSelectedId)) start = s.lastSelectedId; + } catch { /* Einstellungen nicht lesbar */ } + await selectInstance(start || instances[0].id); // instances ist nach lastPlayed sortiert + } +}); diff --git a/src/services.js b/src/services.js new file mode 100644 index 0000000..4f79960 --- /dev/null +++ b/src/services.js @@ -0,0 +1,263 @@ +'use strict'; + +/* + * services.js – externe Dienste & Systemabfragen für AeroMC + * ---------------------------------------------------------------- + * Bewusst frei von Electron-Abhängigkeiten, damit headless (mit `node`) + * testbar. Nutzt globales fetch (Node 18+ / Electron 28). + * + * - scanJava() : findet installierte Java-Runtimes + * - getMcVersions() : Mojang-Versionsliste (mit Datei-Cache) + * - modrinthSearch() : Mod-Suche + * - modrinthInstall() : passende Mod-Version in einen Ordner laden + */ + +const fs = require('fs'); +const path = require('path'); +const os = require('os'); +const { execFileSync, spawnSync } = require('child_process'); + +const UA = 'AeroMC-Launcher/0.2 (Minecraft-Launcher; contact: viper)'; + +// --------------------------------------------------------------------------- +// Java-Erkennung +// --------------------------------------------------------------------------- + +function javaCandidateDirs() { + const pf = process.env['ProgramFiles'] || 'C:\\Program Files'; + const pfx = process.env['ProgramFiles(x86)'] || 'C:\\Program Files (x86)'; + const appdata = process.env['APPDATA'] || ''; + const localappdata = process.env['LOCALAPPDATA'] || ''; + const vendors = ['Java', 'Eclipse Adoptium', 'Eclipse Foundation', 'Zulu', 'Amazon Corretto', + 'BellSoft', 'Microsoft', 'AdoptOpenJDK', 'Semeru', 'JetBrains']; + const roots = []; + for (const base of [pf, pfx]) { + for (const v of vendors) roots.push(path.join(base, v)); + } + // Runtimes der offiziellen Minecraft-Launcher + if (appdata) roots.push(path.join(appdata, '.minecraft', 'runtime')); + if (localappdata) roots.push(path.join(localappdata, 'Packages')); + return roots; +} + +// findet rekursiv (begrenzte Tiefe) alle java.exe unter einem Startordner +function findJavaExes(root, depth, acc) { + if (depth < 0 || !fs.existsSync(root)) return; + let entries; + try { entries = fs.readdirSync(root, { withFileTypes: true }); } catch { return; } + for (const e of entries) { + const full = path.join(root, e.name); + if (e.isFile() && /^javaw?\.exe$/i.test(e.name)) { + // bevorzugt java.exe (Konsole) statt javaw.exe + if (/^java\.exe$/i.test(e.name)) acc.add(full); + } else if (e.isDirectory()) { + // Tiefe begrenzen; typische Struktur ...//bin/java.exe + findJavaExes(full, depth - 1, acc); + } + } +} + +function probeJava(javaPath) { + // `java -version` schreibt nach stderr; spawnSync liefert stdout UND stderr. + try { + const r = spawnSync(javaPath, ['-version'], { encoding: 'utf8', timeout: 5000 }); + const out = (r.stderr || '') + (r.stdout || ''); + if (!out.trim()) return null; + return parseJavaVersion(javaPath, out); + } catch { + return null; + } +} + +function parseJavaVersion(javaPath, out) { + const m = out.match(/version "([^"]+)"/i); + const raw = m ? m[1] : ''; + let major = 0; + if (raw) { + const parts = raw.split('.'); + major = raw.startsWith('1.') ? parseInt(parts[1], 10) : parseInt(parts[0], 10); + } + const arch = /64-bit/i.test(out) ? 'x64' : (/32-bit|Client VM/i.test(out) ? 'x86' : '?'); + const vendorLine = out.split('\n').map((l) => l.trim()).find((l) => /runtime|openjdk|hotspot|jre|jdk/i.test(l)) || ''; + return { path: javaPath, version: raw || 'unbekannt', major: major || 0, arch, info: vendorLine }; +} + +function scanJava() { + const found = new Set(); + + // 1) JAVA_HOME + if (process.env.JAVA_HOME) { + const p = path.join(process.env.JAVA_HOME, 'bin', 'java.exe'); + if (fs.existsSync(p)) found.add(p); + } + // 2) java aus PATH + try { + const where = execFileSync('where', ['java'], { encoding: 'utf8', timeout: 4000 }); + where.split(/\r?\n/).forEach((l) => { l = l.trim(); if (l && /java\.exe$/i.test(l) && fs.existsSync(l)) found.add(l); }); + } catch { /* nix */ } + // 3) bekannte Vendor-Ordner + for (const root of javaCandidateDirs()) findJavaExes(root, 4, found); + + // prüfen & dedupen nach Version+Pfad + const results = []; + for (const p of found) { + const info = probeJava(p); + if (info) results.push(info); + } + // sortieren: 64-bit vor 32-bit, höhere Major-Version zuerst + results.sort((a, b) => { + if ((b.arch === 'x64') - (a.arch === 'x64') !== 0) return (b.arch === 'x64') - (a.arch === 'x64'); + return b.major - a.major; + }); + return results; +} + +// --------------------------------------------------------------------------- +// Mojang-Versionsliste (mit Cache) +// --------------------------------------------------------------------------- + +const MC_MANIFEST_URL = 'https://piston-meta.mojang.com/mc/game/version_manifest_v2.json'; + +async function getMcVersions(cacheDir, maxAgeMs = 6 * 3600 * 1000) { + const cacheFile = path.join(cacheDir, 'mc-versions.json'); + // Cache frisch genug? + try { + const st = fs.statSync(cacheFile); + if (Date.now() - st.mtimeMs < maxAgeMs) { + return Object.assign({ cached: true }, JSON.parse(fs.readFileSync(cacheFile, 'utf8'))); + } + } catch { /* kein Cache */ } + + try { + const res = await fetch(MC_MANIFEST_URL, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('HTTP ' + res.status); + const data = await res.json(); + const slim = { + latest: data.latest, + versions: data.versions.map((v) => ({ id: v.id, type: v.type, releaseTime: v.releaseTime, url: v.url, sha1: v.sha1 })), + fetchedAt: new Date().toISOString(), + }; + try { fs.mkdirSync(cacheDir, { recursive: true }); fs.writeFileSync(cacheFile, JSON.stringify(slim)); } catch { /* egal */ } + return Object.assign({ cached: false }, slim); + } catch (err) { + // offline: alten Cache nehmen, falls vorhanden + try { + const old = JSON.parse(fs.readFileSync(cacheFile, 'utf8')); + return Object.assign({ cached: true, offline: true }, old); + } catch { + return { offline: true, error: err.message, latest: {}, versions: [] }; + } + } +} + +// --------------------------------------------------------------------------- +// Modrinth (Mod-Suche & Installation) +// --------------------------------------------------------------------------- + +const MODRINTH = 'https://api.modrinth.com/v2'; + +const MODRINTH_SORTS = ['relevance', 'downloads', 'follows', 'newest', 'updated']; + +async function modrinthSearch({ query = '', gameVersion = '', loader = '', category = '', sort = 'relevance', limit = 30, offset = 0 } = {}) { + const facets = [['project_type:mod']]; + if (gameVersion) facets.push(['versions:' + gameVersion]); + if (loader && loader !== 'vanilla') facets.push(['categories:' + loader]); + if (category) facets.push(['categories:' + category]); + const url = new URL(MODRINTH + '/search'); + url.searchParams.set('query', query); + url.searchParams.set('limit', String(limit)); + url.searchParams.set('offset', String(offset)); + url.searchParams.set('index', MODRINTH_SORTS.includes(sort) ? sort : 'relevance'); + url.searchParams.set('facets', JSON.stringify(facets)); + + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('Modrinth-Suche fehlgeschlagen: HTTP ' + res.status); + const data = await res.json(); + return { + total: data.total_hits, + hits: (data.hits || []).map((h) => ({ + projectId: h.project_id, + slug: h.slug, + title: h.title, + description: h.description, + author: h.author, + downloads: h.downloads, + iconUrl: h.icon_url || '', + categories: h.categories || [], + })), + }; +} + +// findet die passende Datei-Version für Spielversion + Loader +async function modrinthResolveFile({ projectId, gameVersion, loader }) { + const url = new URL(MODRINTH + '/project/' + projectId + '/version'); + if (gameVersion) url.searchParams.set('game_versions', JSON.stringify([gameVersion])); + if (loader && loader !== 'vanilla') url.searchParams.set('loaders', JSON.stringify([loader])); + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('Versionsabruf fehlgeschlagen: HTTP ' + res.status); + const versions = await res.json(); + if (!versions.length) return null; + const v = versions[0]; // neueste passende + const file = v.files.find((f) => f.primary) || v.files[0]; + if (!file) return null; + return { + versionId: v.id, + versionNumber: v.version_number, + filename: file.filename, + url: file.url, + sha1: file.hashes && file.hashes.sha1, + size: file.size, + dependencies: v.dependencies || [], + }; +} + +async function downloadFile(url, destPath) { + const res = await fetch(url, { headers: { 'User-Agent': UA } }); + if (!res.ok) throw new Error('Download fehlgeschlagen: HTTP ' + res.status); + const buf = Buffer.from(await res.arrayBuffer()); + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + fs.writeFileSync(destPath, buf); + return buf.length; +} + +// lädt eine Mod in ; gibt Metadaten für die Instanz zurück +async function modrinthInstall({ projectId, title, gameVersion, loader, modsDir }) { + const file = await modrinthResolveFile({ projectId, gameVersion, loader }); + if (!file) { + return { ok: false, reason: 'no-match', + message: `Keine passende Version für ${gameVersion} / ${loader} gefunden.` }; + } + const dest = path.join(modsDir, file.filename); + const bytes = await downloadFile(file.url, dest); + return { + ok: true, + dependencies: file.dependencies || [], + entry: { + projectId, + title: title || projectId, + filename: file.filename, + versionId: file.versionId, + versionNumber: file.versionNumber, + gameVersion, + loader, + installedAt: new Date().toISOString(), + bytes, + }, + }; +} + +// Projekttitel nachschlagen (für Abhängigkeiten, die nur eine ID liefern) +async function modrinthProjectTitle(projectId) { + try { + const res = await fetch(`${MODRINTH}/project/${projectId}`, { headers: { 'User-Agent': UA } }); + if (!res.ok) return projectId; + const data = await res.json(); + return data.title || projectId; + } catch { return projectId; } +} + +module.exports = { + scanJava, probeJava, + getMcVersions, + modrinthSearch, modrinthResolveFile, modrinthInstall, modrinthProjectTitle, downloadFile, +}; diff --git a/src/store.js b/src/store.js new file mode 100644 index 0000000..34db161 --- /dev/null +++ b/src/store.js @@ -0,0 +1,308 @@ +'use strict'; + +/* + * store.js – Persistenz für AeroMC + * ------------------------------------ + * Jede Instanz ist ein isolierter Ordner (MultiMC-Prinzip): + * //instance.json – Metadaten + * //minecraft/ – das eigentliche Spielverzeichnis (.minecraft-Ersatz) + * + * Globale Einstellungen liegen in /settings.json. + */ + +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +let USER_DATA = null; // wird von main.js via init() gesetzt + +function init(userDataPath) { + USER_DATA = userDataPath; + ensureDir(USER_DATA); + ensureDir(getInstancesDir()); +} + +// ---------- kleine Helfer ---------- + +function ensureDir(dir) { + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); +} + +function readJson(file, fallback) { + try { + return JSON.parse(fs.readFileSync(file, 'utf8')); + } catch { + return fallback; + } +} + +function writeJson(file, data) { + ensureDir(path.dirname(file)); + fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf8'); +} + +function newId() { + return crypto.randomBytes(8).toString('hex'); +} + +// ---------- Einstellungen ---------- + +const DEFAULT_SETTINGS = { + instancesDir: null, // null => Standard (userData/instances) + javaPath: '', // leer => "java" aus PATH + defaultMinMemMb: 2048, + defaultMaxMemMb: 4096, + azureClientId: '', // Azure-App-ID für den Microsoft-Login (Phase 3) + globalPreLaunch: '', + globalPostExit: '', + lastSelectedId: '', // zuletzt ausgewählte Instanz (beim Start wieder markieren) + bgSkin: '', // '' = aus, 'active' = aktives Konto, sonst Konto-UUID + bgSkinOpacity: 55, // Deckkraft des Hintergrund-Skins in % + bgSkinPose: 'walking', // Pose des 3D-Renders (falls der Pose-Dienst erreichbar ist) + wrapperCommand: '', // Externe Programme: Startprogramm, das Java umschließt + proxyEnabled: false, // HTTP-Proxy für Downloads/Netzwerk + proxyHost: '', + proxyPort: '', + proxyUser: '', + proxyPass: '', + theme: 'dark', +}; + +function settingsFile() { + return path.join(USER_DATA, 'settings.json'); +} + +function getSettings() { + return Object.assign({}, DEFAULT_SETTINGS, readJson(settingsFile(), {})); +} + +function saveSettings(patch) { + const merged = Object.assign({}, getSettings(), patch || {}); + writeJson(settingsFile(), merged); + // Falls sich das Instanzverzeichnis geändert hat: sicherstellen, dass es existiert + ensureDir(getInstancesDir()); + return merged; +} + +// ---------- Instanzen ---------- + +function getInstancesDir() { + const s = getSettings(); + return s.instancesDir && s.instancesDir.trim() + ? s.instancesDir + : path.join(USER_DATA, 'instances'); +} + +function instancePath(id) { + return path.join(getInstancesDir(), id); +} + +function instanceFile(id) { + return path.join(instancePath(id), 'instance.json'); +} + +function gameDir(id) { + return path.join(instancePath(id), 'minecraft'); +} + +function modsDir(id) { + return path.join(gameDir(id), 'mods'); +} + +function modsIndexFile(id) { + return path.join(instancePath(id), 'mods.json'); +} + +// ---------- installierte Mods (Metadaten je Instanz) ---------- + +function listMods(id) { + return readJson(modsIndexFile(id), []); +} + +function addMod(id, entry) { + const list = listMods(id).filter((m) => m.filename !== entry.filename); + list.push(entry); + writeJson(modsIndexFile(id), list); + return list; +} + +function removeMod(id, filename) { + const list = listMods(id).filter((m) => m.filename !== filename); + writeJson(modsIndexFile(id), list); + // zugehörige .jar löschen + const jar = path.join(modsDir(id), filename); + try { if (fs.existsSync(jar)) fs.unlinkSync(jar); } catch { /* egal */ } + return list; +} + +function defaultInstance(name) { + const now = new Date().toISOString(); + return { + id: newId(), + name: name || 'Neue Instanz', + icon: 'grass', // Schlüssel für ein Emoji/Icon im Renderer + customImage: null, // Dateiname eines eigenen Bildes im Instanzordner (überschreibt Emoji) + group: '', // optionale Gruppe (MultiMC-artig) + preLaunchCommand: '', // Befehl vor dem Start + postExitCommand: '', // Befehl nach dem Beenden + created: now, + lastPlayed: null, + totalPlaySeconds: 0, + minecraft: { + version: '', // z. B. "1.21.4" – wird in Phase 2 aus dem Mojang-Manifest befüllt + loader: 'vanilla', // vanilla | fabric | forge | neoforge | quilt + loaderVersion: '', + }, + java: { + path: '', // leer => globale Einstellung + minMemMb: null, // null => globale Einstellung + maxMemMb: null, + extraArgs: '', + }, + notes: '', + }; +} + +// liest ein eigenes Instanz-Bild als data:-URI (für die Anzeige im Renderer) +function iconDataUri(id) { + const meta = readJson(instanceFile(id), null); + if (!meta || !meta.customImage) return null; + try { + const buf = fs.readFileSync(path.join(instancePath(id), meta.customImage)); + let ext = path.extname(meta.customImage).slice(1).toLowerCase(); + if (ext === 'jpg') ext = 'jpeg'; + return `data:image/${ext};base64,` + buf.toString('base64'); + } catch { return null; } +} + +function setCustomImage(id, sourcePath) { + let ext = path.extname(sourcePath).toLowerCase(); + if (!ext) ext = '.png'; + const dest = 'icon' + ext; + fs.copyFileSync(sourcePath, path.join(instancePath(id), dest)); + return updateInstance(id, { customImage: dest }); +} + +function clearCustomImage(id) { + const meta = getInstance(id); + if (meta && meta.customImage) { + try { fs.unlinkSync(path.join(instancePath(id), meta.customImage)); } catch { /* egal */ } + } + return updateInstance(id, { customImage: null }); +} + +function listInstances() { + const dir = getInstancesDir(); + ensureDir(dir); + const result = []; + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const meta = readJson(path.join(dir, entry.name, 'instance.json'), null); + if (meta && meta.id) { + // eigenes Bild direkt für die Anzeige mitliefern (nicht persistiert) + if (meta.customImage) meta.iconData = iconDataUri(meta.id); + result.push(meta); + } + } + // zuletzt gespielt zuerst, dann alphabetisch + result.sort((a, b) => { + if (a.lastPlayed && b.lastPlayed) return b.lastPlayed.localeCompare(a.lastPlayed); + if (a.lastPlayed) return -1; + if (b.lastPlayed) return 1; + return a.name.localeCompare(b.name); + }); + return result; +} + +function getInstance(id) { + return readJson(instanceFile(id), null); +} + +// Ordnername aus dem Instanznamen ableiten (wie MultiMC), ungültige Zeichen raus +function slugForName(name) { + const base = String(name || 'Instanz').trim() + .replace(/[<>:"/\\|?*\u0000-\u001f]/g, '') + .replace(/[.\s]+$/, '') + .trim(); + return (base || 'Instanz').slice(0, 60); +} +// eindeutiger Ordnername (bei Kollision "Name 2", "Name 3", …) +function uniqueFolderId(name) { + const dir = getInstancesDir(); + const base = slugForName(name); + let id = base; + let n = 2; + while (fs.existsSync(path.join(dir, id))) { id = base + ' ' + n; n += 1; } + return id; +} + +function createInstance(data) { + const inst = defaultInstance(data && data.name); + inst.id = uniqueFolderId(inst.name); // Ordner = Instanzname statt Zufalls-ID + if (data) { + if (data.icon) inst.icon = data.icon; + if (data.minecraft) Object.assign(inst.minecraft, data.minecraft); + if (data.notes) inst.notes = data.notes; + if (data.group !== undefined) inst.group = data.group; + } + ensureDir(gameDir(inst.id)); + writeJson(instanceFile(inst.id), inst); + return inst; +} + +function updateInstance(id, patch) { + const inst = getInstance(id); + if (!inst) throw new Error('Instanz nicht gefunden: ' + id); + // flaches Merge mit Sonderbehandlung der verschachtelten Objekte + const next = Object.assign({}, inst, patch); + if (patch.minecraft) next.minecraft = Object.assign({}, inst.minecraft, patch.minecraft); + if (patch.java) next.java = Object.assign({}, inst.java, patch.java); + writeJson(instanceFile(id), next); + return next; +} + +function deleteInstance(id) { + const p = instancePath(id); + if (fs.existsSync(p)) fs.rmSync(p, { recursive: true, force: true }); + return true; +} + +function duplicateInstance(id) { + const src = getInstance(id); + if (!src) throw new Error('Instanz nicht gefunden: ' + id); + const copy = JSON.parse(JSON.stringify(src)); + copy.name = src.name + ' (Kopie)'; + copy.id = uniqueFolderId(copy.name); + copy.created = new Date().toISOString(); + copy.lastPlayed = null; + copy.totalPlaySeconds = 0; + ensureDir(gameDir(copy.id)); + // Spielinhalte mitkopieren (Mods/Configs) – ohne Fehler wenn leer + try { + fs.cpSync(gameDir(id), gameDir(copy.id), { recursive: true }); + } catch { /* Quelle evtl. leer */ } + writeJson(instanceFile(copy.id), copy); + return copy; +} + +module.exports = { + init, + getSettings, + saveSettings, + getInstancesDir, + instancePath, + gameDir, + modsDir, + iconDataUri, + setCustomImage, + clearCustomImage, + listMods, + addMod, + removeMod, + listInstances, + getInstance, + createInstance, + updateInstance, + deleteInstance, + duplicateInstance, +}; diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..c2cbfd0 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,302 @@ +/* AeroMC – heller MultiMC-Native-Look */ +:root{ + --win:#f0f0f0; --area:#e2e2e2; --bar:#e9eaed; + --border:#c4c7cc; --border2:#d6d8dc; + --text:#1c1c1c; --dim:#6b7280; + --sel:#dce8f6; --sel-br:#3a6ea5; --link:#2c5aa0; --accent:#3a6ea5; + --danger:#c0392b; --play:#3a9c3a; + --font:"Segoe UI",Tahoma,system-ui,sans-serif; + --mono:Consolas,"Cascadia Mono",monospace; +} +*{box-sizing:border-box} +html,body{margin:0;height:100%;font-family:var(--font);font-size:12px;color:var(--text);background:var(--win)} +body{display:grid;grid-template-rows:auto 1fr auto;height:100vh;overflow:hidden} +.hidden{display:none!important} +.mono{font-family:var(--mono);font-size:12px} +.spacer{flex:1} +.opt,.hint{color:var(--dim)} +[data-ic] svg,.ic svg{width:16px;height:16px} + +/* ===================== DUNKLER MODUS (native, dunkelgrau) ===================== */ +:root[data-theme="dark"]{ + --win:#2d2d30; --area:#242426; --bar:#333337; + --border:#3f3f46; --border2:#3a3a40; + --text:#e4e4e6; --dim:#9a9aa2; + --sel:#0e639c; --sel-br:#1177bb; --link:#4ea6ff; --accent:#1177bb; + --danger:#e06c6c; --play:#5cb85c; +} +:root[data-theme="dark"] body{background:var(--win)} +:root[data-theme="dark"] .search-wrap input, +:root[data-theme="dark"] .field input, +:root[data-theme="dark"] .field select, +:root[data-theme="dark"] .field textarea, +:root[data-theme="dark"] .mods-search input, +:root[data-theme="dark"] .login-usercode{background:#1e1e1e;color:var(--text);border-color:var(--border)} +:root[data-theme="dark"] .modal-card{background:#2d2d30;border-color:#161618} +:root[data-theme="dark"] .modal-head{background:#333337} +:root[data-theme="dark"] .modal-body{background:#2d2d30} +:root[data-theme="dark"] .modal-foot{background:#2a2a2e} +:root[data-theme="dark"] .advanced{background:#242426} +:root[data-theme="dark"] .mods-list, +:root[data-theme="dark"] .account-item, +:root[data-theme="dark"] .screen-thumb{background:#1e1e1e} +:root[data-theme="dark"] .mod-icon, +:root[data-theme="dark"] .account-av, +:root[data-theme="dark"] .icon-preview{background:#3a3a40} +:root[data-theme="dark"] .mod-item+.mod-item{border-color:#333} +:root[data-theme="dark"] .mod-item:hover{background:#2a2f36} +:root[data-theme="dark"] .btn{background:linear-gradient(#3b3b40,#303034);color:var(--text);border-color:var(--border)} +:root[data-theme="dark"] .btn:hover{background:linear-gradient(#44444b,#35353b);border-color:#5a5a63} +:root[data-theme="dark"] .btn:active{background:#2a2a2e} +:root[data-theme="dark"] .btn-primary{background:linear-gradient(#2a7ac0,#1f66a8);border-color:#1a5a95;color:#fff} +:root[data-theme="dark"] .btn-primary:hover{background:linear-gradient(#3286cc,#2470b4)} +:root[data-theme="dark"] .btn-danger{color:#e88;border-color:#6a3a3a} +:root[data-theme="dark"] .btn-danger:hover{background:#3a2626} +:root[data-theme="dark"] .tbtn:hover, +:root[data-theme="dark"] .sbtn:hover, +:root[data-theme="dark"] .card:hover{background:#37373d;border-color:var(--border)} +:root[data-theme="dark"] .card.sel{background:#0e639c;border-color:#1177bb} +:root[data-theme="dark"] .card.sel .card-name{background:#1177bb;color:#fff} +:root[data-theme="dark"] .st-row2{background:#2a2a2e} +:root[data-theme="dark"] .st-row, +:root[data-theme="dark"] .group-header, +:root[data-theme="dark"] .empty h2, +:root[data-theme="dark"] .mods-col h4, +:root[data-theme="dark"] .field>span{color:var(--text)} +:root[data-theme="dark"] #btn-console svg{color:#c8c8cc} +:root[data-theme="dark"] .acct-av svg{color:#c8c8cc} +:root[data-theme="dark"] .mods-filters select{background:#1e1e1e;color:var(--text);border-color:var(--border)} +:root[data-theme="dark"] .modal-close{color:#aaa} +:root[data-theme="dark"] .modal-close:hover{color:#fff} +:root[data-theme="dark"] ::-webkit-scrollbar-thumb{background:#4a4a52;border-color:var(--area)} + +/* ---------- Toolbar ---------- */ +.toolbar{display:flex;align-items:center;gap:2px;padding:5px 8px;background:var(--win);border-bottom:1px solid var(--border)} +.tbtn{display:inline-flex;align-items:center;gap:7px;padding:6px 10px;border:1px solid transparent;border-radius:3px;background:none;color:var(--text);cursor:pointer;font-family:inherit;font-size:12px} +.tbtn:hover{background:#e2e6ec;border-color:var(--border2)} +.tbtn:active{background:#d7dde5} +.tbtn svg{width:18px;height:18px;color:#4b5563} +/* farbige Toolbar-Icons wie in MultiMC */ +#btn-new svg{color:#3a9c3a} +#btn-import svg{color:#3d7ab5} +#btn-modpack svg{color:#8e5bc7} +#btn-open-dir svg{color:#d8a72f} +#btn-console svg{color:#5a6470} +#btn-account svg{color:#3a9c3a} +#btn-settings svg{color:#3d7ab5} +.tbtn.big{font-size:13px;padding:8px 16px;border:1px solid var(--border);background:linear-gradient(#fdfdfd,#e9e9e9)} +.tbsep{width:1px;height:24px;background:var(--border);margin:0 5px} +.tbgrow{flex:1} +.search-wrap input{padding:5px 9px;border:1px solid var(--border);border-radius:3px;background:#fff;color:var(--text);font-size:12px;width:150px} +.search-wrap input:focus{outline:none;border-color:var(--accent)} + +/* ---------- Arbeitsbereich ---------- */ +.workspace{display:grid;grid-template-columns:1fr 172px;overflow:hidden;background:var(--area)} +.list-area{position:relative;overflow:auto} +/* Skin-Hintergrund (wie MultiMCs Katze) – liegt hinter den Instanzen */ +.list-area::after{ + content:'';position:absolute;right:24px;bottom:8px;width:52%;height:88%; + background-image:var(--bg-skin,none);background-repeat:no-repeat; + background-position:right bottom;background-size:contain; + opacity:var(--bg-skin-opacity,.55);pointer-events:none;z-index:0; +} +.list{position:relative;z-index:1} +.list{padding:4px 8px} +.side{background:var(--win);border-left:1px solid var(--border);overflow:auto;padding:12px 8px} +.side-empty{text-align:center;color:var(--dim);padding:24px 8px} +.side-ico{width:56px;height:56px;margin:2px auto 6px;display:grid;place-items:center;font-size:40px} +.side-ico img{width:56px;height:56px;object-fit:cover;border-radius:3px} +.side-title{text-align:center;font-weight:600;font-size:14px;word-break:break-word} +.side-grp{text-align:center;color:var(--link);font-size:11px;margin-top:2px;cursor:pointer} +.side-grp:hover{text-decoration:underline} +.hr{height:1px;background:var(--border);margin:8px 2px} +.sbtn{display:block;width:100%;text-align:center;padding:6px;border:1px solid transparent;border-radius:3px;background:none;cursor:pointer;font-family:inherit;font-size:12px;color:var(--text)} +.sbtn:hover{background:#e2e6ec;border-color:var(--border2)} +.sbtn.play{font-weight:600} +.sbtn.del:hover{color:var(--danger)} + +/* ---------- Instanzliste / Gruppen / Kacheln ---------- */ +.group-section{margin-bottom:4px} +.group-header{display:flex;align-items:center;gap:7px;padding:7px 4px 5px;color:#333;font-weight:600;font-size:12px;cursor:pointer;user-select:none} +.group-header::after{content:'';flex:1;height:1px;background:var(--border);margin-left:6px} +.group-header .chev{font-size:9px;color:#888;width:10px;text-align:center} +.group-header.collapsed .chev{transform:none} +.group-count{color:var(--dim);font-weight:400} +.group-grid{display:grid;grid-template-columns:repeat(auto-fill,86px);gap:2px;padding:2px 4px 8px;justify-content:start} +.group-section.collapsed .group-grid{display:none} +.card{display:flex;flex-direction:column;align-items:center;gap:4px;padding:8px 4px 5px;border:1px solid transparent;border-radius:2px;cursor:pointer;position:relative} +.card:hover{background:#e3ecf7} +.card.sel{background:var(--sel);border-color:var(--sel-br)} +.card-icon{width:44px;height:44px;display:grid;place-items:center;font-size:30px} +.card-icon svg,.side-ico svg{display:block;image-rendering:pixelated} +.card-icon-img{width:44px;height:44px;object-fit:cover;border-radius:3px} +.card-name{font-size:11px;text-align:center;line-height:1.2;max-width:82px;padding:1px 4px;word-break:break-word} +.card.sel .card-name{background:var(--sel-br);color:#fff;border-radius:2px} +.card-badges{display:none} +.card-play{display:none} +.group-header.drop-hover,.group-section.drop-hover{outline:1px dashed var(--accent);outline-offset:1px} +.card.dragging{opacity:.4} + +/* ---------- Leerer Zustand ---------- */ +.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;color:var(--dim);gap:8px} +.empty h2{color:#333;margin:0} +.empty p{max-width:340px;margin:0 0 8px} + +/* ---------- Statusleiste (zwei Zeilen) ---------- */ +.statusbar{display:flex;flex-direction:column;background:var(--win);border-top:1px solid var(--border)} +.st-row{display:flex;justify-content:space-between;padding:3px 10px;font-size:11px;color:#333} +.st-row2{background:#e4e4e4;border-top:1px solid var(--border2);color:#444} +.auth-warn{ + display:inline-flex;align-items:center;gap:6px; + color:#fff;background:var(--danger); + padding:1px 10px;border-radius:3px;font-weight:600;cursor:pointer; + animation:authpulse 2s ease-in-out infinite; +} +.auth-warn::before{content:'⚠';font-size:12px} +.auth-warn:hover{filter:brightness(1.12)} +@keyframes authpulse{0%,100%{opacity:1}50%{opacity:.72}} + +/* ---------- Modals ---------- */ +.modal{position:fixed;inset:0;background:rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;z-index:50} +.modal-card{width:560px;max-width:calc(100vw - 40px);max-height:calc(100vh - 60px);background:#f6f6f6;border:1px solid #a9a9a9;border-radius:4px;box-shadow:0 10px 30px rgba(0,0,0,.3);display:flex;flex-direction:column;overflow:hidden} +.modal-sm{width:420px}.modal-lg{width:820px} +.modal-head{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:#e8e8e8;border-bottom:1px solid var(--border)} +.modal-head h3{margin:0;font-size:14px;font-weight:600} +.modal-close{background:none;border:none;color:#666;font-size:15px;cursor:pointer;line-height:1} +.modal-close:hover{color:#000} +.modal-body{padding:16px;overflow:auto;background:#f6f6f6} +.modal-foot{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;border-top:1px solid var(--border);background:#efefef} + +/* Formular */ +.field{display:flex;flex-direction:column;gap:5px;margin-bottom:12px} +.field>span{font-size:12px;color:#333} +.field input,.field select,.field textarea{padding:6px 8px;border:1px solid var(--border);border-radius:3px;background:#fff;color:var(--text);font-family:inherit;font-size:13px} +.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--accent)} +.field textarea{resize:vertical} +.field-row{display:flex;gap:12px}.field-row .field{flex:1} +.field-icon{max-width:150px} +.hint{font-size:12px} +.path-row{display:flex;gap:8px}.path-row input{flex:1} +.advanced{border:1px solid var(--border);border-radius:3px;padding:12px 14px 2px;margin-top:4px;background:#fbfbfb} +.advanced legend{color:var(--dim);font-size:12px;padding:0 6px} +.version-row{display:flex;gap:8px}.version-row #f-version-type{max-width:120px}.version-row #f-version{flex:1} +.icon-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:3px;margin-top:6px;max-width:100%} +.icon-choice{display:flex;align-items:center;justify-content:center;padding:3px;border:1px solid transparent;border-radius:3px;background:none;cursor:pointer} +.icon-choice:hover{background:rgba(128,128,128,.18)} +.icon-choice.on{border-color:var(--accent);background:var(--sel)} +.icon-choice svg{display:block} +.icon-custom{display:flex;align-items:center;gap:6px;margin-top:6px;flex-wrap:wrap} +.icon-preview{width:34px;height:34px;border-radius:3px;overflow:hidden;background:#e4e4e4;border:1px solid var(--border)} +.icon-preview img{width:100%;height:100%;object-fit:cover} +.appinfo{margin-top:8px;font-size:12px;color:var(--dim);line-height:1.6} +.about-brand{display:flex;align-items:center;gap:14px;margin-bottom:12px} +.about-logo{width:56px;height:56px;border-radius:12px} +.about-name{font-size:18px;font-weight:600} + +/* Buttons in Dialogen */ +.btn{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid var(--border);border-radius:3px;background:linear-gradient(#fdfdfd,#e9e9e9);color:var(--text);cursor:pointer;font-family:inherit;font-size:12px} +.btn:hover{background:linear-gradient(#ffffff,#e2e2e2);border-color:#9aa0a8} +.btn:active{background:#dcdcdc} +.btn:disabled{opacity:.5;cursor:default} +.btn svg{width:15px;height:15px} +.btn-primary{background:linear-gradient(#5a9be0,#3a7bc8);border-color:#2f6bb0;color:#fff} +.btn-primary:hover{background:linear-gradient(#69a8ea,#3f83d2)} +.btn-danger{color:var(--danger);border-color:#cbb0ac} +.btn-danger:hover{background:#f7e9e7;border-color:#c0392b} +.btn-lg{padding:9px 18px;font-size:13px} +.btn-mini{padding:4px 8px;font-size:11px} + +/* Badges (dezent) */ +.badge{font-size:10px;padding:1px 6px;border-radius:2px;background:#e2e2e2;color:#555;border:1px solid var(--border)} + +/* Detail-Kopf (Mods/Login) */ +.detail-head{display:flex;align-items:center;gap:12px} +.detail-icon{font-size:28px} +.detail-sub{color:var(--dim);font-size:12px;margin-top:2px} + +/* Mods */ +.mods-body{min-height:420px} +.mods-warn{background:#fdecea;border:1px solid #e0b4b0;color:#a5342a;border-radius:3px;padding:10px 12px;margin-bottom:12px} +.mods-search{display:flex;gap:8px;margin-bottom:10px} +.mods-filters{display:flex;gap:8px;margin-bottom:12px} +.mods-filters select{flex:1;padding:6px 8px;border:1px solid var(--border);border-radius:3px;background:var(--input,#fff);color:var(--text);font-family:inherit;font-size:12px} +#m-more{display:block;width:100%;margin-top:8px} +.mods-search input{flex:1;padding:7px 10px;border:1px solid var(--border);border-radius:3px;background:#fff;color:var(--text)} +.mods-search input:focus{outline:none;border-color:var(--accent)} +.mods-columns{display:grid;grid-template-columns:1fr 1fr;gap:14px} +.mods-col h4{margin:0 0 8px;font-size:12px;color:#333;font-weight:600;display:flex;align-items:center;gap:6px} +.mods-tabs{display:flex;gap:2px;margin-bottom:10px;border-bottom:1px solid var(--border)} +.mtab{padding:7px 14px;border:1px solid transparent;border-bottom:none;border-radius:3px 3px 0 0;background:none;color:var(--dim);cursor:pointer;font-family:inherit;font-size:12px;margin-bottom:-1px} +.mtab:hover{color:var(--text)} +.mtab.on{color:var(--text);background:var(--bar);border-color:var(--border);font-weight:600} +.mods-list{height:340px;overflow-y:auto;overflow-x:hidden;border:1px solid var(--border);border-radius:3px;background:#fff;padding:6px} +.mods-empty{color:var(--dim);text-align:center;padding:24px 8px;font-size:12px} +.mod-item{display:flex;gap:10px;align-items:center;padding:8px;border-radius:3px;max-width:100%;overflow:hidden} +.mod-item.clickable{cursor:pointer} +.mod-item.installing{opacity:.6} +.mod-item+.mod-item{border-top:1px solid #eee} +.mod-item:hover{background:#f0f4f8} +.mod-icon{width:38px;height:38px;border-radius:3px;flex:none;background:#e4e4e4;object-fit:cover;display:flex;align-items:center;justify-content:center;font-size:18px} +.mod-info{flex:1;min-width:0} +.mod-name{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.mod-desc{font-size:12px;color:var(--dim);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden} +.mod-meta{font-size:11px;color:var(--dim);margin-top:2px} +.mod-action{flex:none} + +/* Login / Konten */ +.login-code{text-align:center} +.login-link{color:var(--link);font-size:15px;display:inline-block;margin-bottom:12px;cursor:pointer;text-decoration:none} +.login-link:hover{text-decoration:underline} +.login-usercode{font-family:var(--mono);font-size:28px;font-weight:700;letter-spacing:3px;color:#222;background:#fff;border:1px solid var(--border);border-radius:4px;padding:12px;margin:6px 0 12px} +.login-error{color:var(--danger)!important;font-weight:600} +.account-list{display:flex;flex-direction:column;gap:8px;margin-bottom:10px} +.account-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:3px;background:#fff;border:1px solid var(--border)} +.account-item.active{border-color:var(--accent)} +.account-av{width:34px;height:34px;border-radius:3px;flex:none;background:#e4e4e4;display:flex;align-items:center;justify-content:center;font-size:18px} +img.account-av{object-fit:cover;image-rendering:pixelated} +.account-main{flex:1;min-width:0} +.account-name{font-weight:600} +.account-tag{font-size:11px;color:var(--link)} +.account-actions{display:flex;gap:6px} +.account-empty{color:var(--dim);text-align:center;padding:10px} + +/* Screenshots */ +.screens-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px;max-height:460px;overflow:auto} +.screen-thumb{border:1px solid var(--border);border-radius:3px;overflow:hidden;background:#fff;cursor:pointer;position:relative} +.screen-thumb img{width:100%;height:100px;object-fit:cover;display:block} +.screen-thumb .screen-name{font-size:11px;color:var(--dim);padding:4px 6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} +.screen-thumb .screen-del{position:absolute;top:4px;right:4px;opacity:0;background:var(--danger);color:#fff;border:none;border-radius:3px;width:24px;height:24px;cursor:pointer} +.screen-thumb:hover .screen-del{opacity:1} +.screens-empty{color:var(--dim);text-align:center;padding:30px;grid-column:1/-1} + +/* Konsole (dunkel wie ein Log) */ +.console-out{height:440px;overflow:auto;margin:0;background:#1e1e1e;border:1px solid var(--border);border-radius:3px;padding:10px;font-family:var(--mono);font-size:12px;color:#d4d4d4;white-space:pre-wrap;word-break:break-word;line-height:1.5} +.log-line{white-space:pre-wrap} +.log-error{color:#f48771}.log-warn{color:#dcdcaa}.log-info{color:#569cd6} + +/* Einstellungen (MultiMC-Stil: linke Sektions-Navigation) */ +.settings-body{display:flex;padding:0;min-height:360px} +.settings-nav{width:170px;flex:none;background:var(--bar);border-right:1px solid var(--border);padding:8px;display:flex;flex-direction:column;gap:2px} +.snav{text-align:left;padding:8px 11px;border:1px solid transparent;border-radius:3px;background:none;color:var(--text);cursor:pointer;font-family:inherit;font-size:13px} +.snav:hover{background:rgba(128,128,128,.16)} +.snav.on{background:var(--sel);border-color:var(--sel-br);color:var(--text)} +.settings-content{flex:1;padding:16px 18px;overflow:auto} +.spane h4{margin:0 0 14px;font-size:14px;font-weight:600} +.checkbox-field{display:flex;align-items:center;gap:8px;margin-bottom:14px;cursor:pointer;font-size:13px} +.checkbox-field input{width:16px;height:16px} +.field-port{max-width:110px;flex:none} + +/* Konto-Button mit 3D-Skin-Kopf */ +.acct-btn{gap:8px} +.acct-av{display:inline-flex;align-items:center;justify-content:center} +.acct-av svg{width:18px;height:18px;color:#4b5563} +.acct-head{width:24px;height:26px;object-fit:contain;image-rendering:pixelated;margin-top:-2px;margin-bottom:-2px} + +/* Toast */ +.toast{position:fixed;bottom:42px;left:50%;transform:translateX(-50%);background:#333;color:#fff;padding:10px 16px;border-radius:4px;box-shadow:0 6px 20px rgba(0,0,0,.4);z-index:100;font-size:13px} +.toast.err{background:#a5342a} + +/* Scrollbars (hell) */ +::-webkit-scrollbar{width:14px;height:14px} +::-webkit-scrollbar-thumb{background:#c1c1c1;border:3px solid var(--area);border-radius:7px} +::-webkit-scrollbar-thumb:hover{background:#a8a8a8} diff --git a/src/vendor/skinview3d.js b/src/vendor/skinview3d.js new file mode 100644 index 0000000..1dcdfa0 --- /dev/null +++ b/src/vendor/skinview3d.js @@ -0,0 +1,1996 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).skinview3d={})}(this,function(e){"use strict";let t,i;let r={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},a={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},n="srgb",s="srgb-linear",o="display-p3",l="300 es";class h{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});let i=this._listeners;void 0===i[e]&&(i[e]=[]),-1===i[e].indexOf(t)&&i[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;let i=this._listeners;return void 0!==i[e]&&-1!==i[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;let i=this._listeners,r=i[e];if(void 0!==r){let e=r.indexOf(t);-1!==e&&r.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;let t=this._listeners,i=t[e.type];if(void 0!==i){e.target=this;let t=i.slice(0);for(let i=0,r=t.length;i>8&255]+c[e>>16&255]+c[e>>24&255]+"-"+c[255&t]+c[t>>8&255]+"-"+c[t>>16&15|64]+c[t>>24&255]+"-"+c[63&i|128]+c[i>>8&255]+"-"+c[i>>16&255]+c[i>>24&255]+c[255&r]+c[r>>8&255]+c[r>>16&255]+c[r>>24&255];return a.toLowerCase()}function f(e,t,i){return Math.max(t,Math.min(i,e))}function m(e){return(e&e-1)==0&&0!==e}function g(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))}function v(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw Error("Invalid component type.")}}function _(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw Error("Invalid component type.")}}class x{constructor(e=0,t=0){x.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){let t=this.x,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){let i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.x}lengthSq(){return this.x*this.x+this.y*this.y}length(){return Math.sqrt(this.x*this.x+this.y*this.y)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)}normalize(){return this.divideScalar(this.length()||1)}angle(){let e=Math.atan2(-this.y,-this.x)+Math.PI;return e}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;let i=this.dot(e)/t;return Math.acos(f(i,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,i=this.y-e.y;return t*t+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,i){return this.x=e.x+(t.x-e.x)*i,this.y=e.y+(t.y-e.y)*i,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){let i=Math.cos(t),r=Math.sin(t),a=this.x-e.x,n=this.y-e.y;return this.x=a*i-n*r+e.x,this.y=a*r+n*i+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class y{constructor(e,t,i,r,a,n,s,o,l){y.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,i,r,a,n,s,o,l)}set(e,t,i,r,a,n,s,o,l){let h=this.elements;return h[0]=e,h[1]=r,h[2]=s,h[3]=t,h[4]=a,h[5]=o,h[6]=i,h[7]=n,h[8]=l,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){let t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],this}extractBasis(e,t,i){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),i.setFromMatrix3Column(this,2),this}setFromMatrix4(e){let t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){let i=e.elements,r=t.elements,a=this.elements,n=i[0],s=i[3],o=i[6],l=i[1],h=i[4],c=i[7],u=i[2],d=i[5],p=i[8],f=r[0],m=r[3],g=r[6],v=r[1],_=r[4],x=r[7],y=r[2],M=r[5],S=r[8];return a[0]=n*f+s*v+o*y,a[3]=n*m+s*_+o*M,a[6]=n*g+s*x+o*S,a[1]=l*f+h*v+c*y,a[4]=l*m+h*_+c*M,a[7]=l*g+h*x+c*S,a[2]=u*f+d*v+p*y,a[5]=u*m+d*_+p*M,a[8]=u*g+d*x+p*S,this}multiplyScalar(e){let t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){let e=this.elements,t=e[0],i=e[1],r=e[2],a=e[3],n=e[4],s=e[5],o=e[6],l=e[7],h=e[8];return t*n*h-t*s*l-i*a*h+i*s*o+r*a*l-r*n*o}invert(){let e=this.elements,t=e[0],i=e[1],r=e[2],a=e[3],n=e[4],s=e[5],o=e[6],l=e[7],h=e[8],c=h*n-s*l,u=s*o-h*a,d=l*a-n*o,p=t*c+i*u+r*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);let f=1/p;return e[0]=c*f,e[1]=(r*l-h*i)*f,e[2]=(s*i-r*n)*f,e[3]=u*f,e[4]=(h*t-r*o)*f,e[5]=(r*a-s*t)*f,e[6]=d*f,e[7]=(i*o-l*t)*f,e[8]=(n*t-i*a)*f,this}transpose(){let e;let t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){let t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,i,r,a,n,s){let o=Math.cos(a),l=Math.sin(a);return this.set(i*o,i*l,-i*(o*n+l*s)+n+e,-r*l,r*o,-r*(-l*n+o*s)+s+t,0,0,1),this}scale(e,t){return this.premultiply(M.makeScale(e,t)),this}rotate(e){return this.premultiply(M.makeRotation(-e)),this}translate(e,t){return this.premultiply(M.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){let t=Math.cos(e),i=Math.sin(e);return this.set(t,-i,0,i,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){let t=this.elements,i=e.elements;for(let e=0;e<9;e++)if(t[e]!==i[e])return!1;return!0}fromArray(e,t=0){for(let i=0;i<9;i++)this.elements[i]=e[i+t];return this}toArray(e=[],t=0){let i=this.elements;return e[t]=i[0],e[t+1]=i[1],e[t+2]=i[2],e[t+3]=i[3],e[t+4]=i[4],e[t+5]=i[5],e[t+6]=i[6],e[t+7]=i[7],e[t+8]=i[8],e}clone(){return new this.constructor().fromArray(this.elements)}}let M=new y;function S(e){for(let t=e.length-1;t>=0;--t)if(e[t]>=65535)return!0;return!1}function b(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}let w={};function T(e){e in w||(w[e]=!0,console.warn(e))}function E(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function A(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let C=new y().fromArray([.8224621,.0331941,.0170827,.177538,.9668058,.0723974,-.0000001,1e-7,.9105199]),L=new y().fromArray([1.2249401,-.0420569,-.0196376,-.2249404,1.0420571,-.0786361,1e-7,0,1.0982735]),P={[s]:e=>e,[n]:e=>e.convertSRGBToLinear(),[o]:function(e){return e.convertSRGBToLinear().applyMatrix3(L)}},R={[s]:e=>e,[n]:e=>e.convertLinearToSRGB(),[o]:function(e){return e.applyMatrix3(C).convertLinearToSRGB()}},D={enabled:!0,get legacyMode(){return console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),!this.enabled},set legacyMode(legacyMode){console.warn("THREE.ColorManagement: .legacyMode=false renamed to .enabled=true in r150."),this.enabled=!legacyMode},get workingColorSpace(){return s},set workingColorSpace(colorSpace){console.warn("THREE.ColorManagement: .workingColorSpace is readonly.")},convert:function(e,t,i){if(!1===this.enabled||t===i||!t||!i)return e;let r=P[t],a=R[i];if(void 0===r||void 0===a)throw Error(`Unsupported color space conversion, "${t}" to "${i}".`);return a(r(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this.workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this.workingColorSpace)}};class I{static getDataURL(e){let i;if(/^data:/i.test(e.src)||"undefined"==typeof HTMLCanvasElement)return e.src;if(e instanceof HTMLCanvasElement)i=e;else{void 0===t&&(t=b("canvas")),t.width=e.width,t.height=e.height;let r=t.getContext("2d");e instanceof ImageData?r.putImageData(e,0,0):r.drawImage(e,0,0,e.width,e.height),i=t}return i.width>2048||i.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),i.toDataURL("image/jpeg",.6)):i.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){let t=b("canvas");t.width=e.width,t.height=e.height;let i=t.getContext("2d");i.drawImage(e,0,0,e.width,e.height);let r=i.getImageData(0,0,e.width,e.height),a=r.data;for(let e=0;e0&&(i.userData=this.userData),t||(e.textures[this.uuid]=i),i}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(300!==this.mapping)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case 1e3:e.x=e.x-Math.floor(e.x);break;case 1001:e.x=e.x<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case 1e3:e.y=e.y-Math.floor(e.y);break;case 1001:e.y=e.y<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}get encoding(){return T("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace===n?3001:3e3}set encoding(e){T("THREE.Texture: Property .encoding has been replaced by .colorSpace."),this.colorSpace=3001===e?n:""}}F.DEFAULT_IMAGE=null,F.DEFAULT_MAPPING=300,F.DEFAULT_ANISOTROPY=1;class k{constructor(e=0,t=0,i=0,r=1){k.prototype.isVector4=!0,this.x=e,this.y=t,this.z=i,this.w=r}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){let t=this.x,i=this.y,r=this.z,a=this.w,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r+n[12]*a,this.y=n[1]*t+n[5]*i+n[9]*r+n[13]*a,this.z=n[2]*t+n[6]*i+n[10]*r+n[14]*a,this.w=n[3]*t+n[7]*i+n[11]*r+n[15]*a,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);let t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,i,r;let a=e.elements,n=a[0],s=a[4],o=a[8],l=a[1],h=a[5],c=a[9],u=a[2],d=a[6],p=a[10];if(.01>Math.abs(s-l)&&.01>Math.abs(o-u)&&.01>Math.abs(c-d)){if(.1>Math.abs(s+l)&&.1>Math.abs(o+u)&&.1>Math.abs(c+d)&&.1>Math.abs(n+h+p-3))return this.set(1,0,0,0),this;let e=(n+1)/2,a=(h+1)/2,f=(p+1)/2,m=(s+l)/4,g=(o+u)/4,v=(c+d)/4;return e>a&&e>f?e<.01?(t=0,i=.707106781,r=.707106781):(i=m/(t=Math.sqrt(e)),r=g/t):a>f?a<.01?(t=.707106781,i=0,r=.707106781):(t=m/(i=Math.sqrt(a)),r=v/i):f<.01?(t=.707106781,i=.707106781,r=0):(t=g/(r=Math.sqrt(f)),i=v/r),this.set(t,i,r,Math.PI),this}let f=Math.sqrt((d-c)*(d-c)+(o-u)*(o-u)+(l-s)*(l-s));return .001>Math.abs(f)&&(f=1),this.x=(d-c)/f,this.y=(o-u)/f,this.z=(l-s)/f,this.w=Math.acos((n+h+p-1)/2),this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this.w=Math.min(this.w,e.w),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this.w=Math.max(this.w,e.w),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this.w=Math.max(e.w,Math.min(t.w,this.w)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this.w=Math.max(e,Math.min(t,this.w)),this}clampLength(e,t){let i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this.w=Math.trunc(this.w),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.w}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this.w+=(e.w-this.w)*t,this}lerpVectors(e,t,i){return this.x=e.x+(t.x-e.x)*i,this.y=e.y+(t.y-e.y)*i,this.z=e.z+(t.z-e.z)*i,this.w=e.w+(t.w-e.w)*i,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z&&e.w===this.w}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this.w=e[t+3],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e[t+3]=this.w,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this.w=e.getW(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z,yield this.w}}class B extends h{constructor(e=1,t=1,i={}){super(),this.isRenderTarget=!0,this.width=e,this.height=t,this.depth=1,this.scissor=new k(0,0,e,t),this.scissorTest=!1,this.viewport=new k(0,0,e,t),void 0!==i.encoding&&(T("THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace."),i.colorSpace=3001===i.encoding?n:""),this.texture=new F({width:e,height:t,depth:1},i.mapping,i.wrapS,i.wrapT,i.magFilter,i.minFilter,i.format,i.type,i.anisotropy,i.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.flipY=!1,this.texture.generateMipmaps=void 0!==i.generateMipmaps&&i.generateMipmaps,this.texture.internalFormat=void 0!==i.internalFormat?i.internalFormat:null,this.texture.minFilter=void 0!==i.minFilter?i.minFilter:1006,this.depthBuffer=void 0===i.depthBuffer||i.depthBuffer,this.stencilBuffer=void 0!==i.stencilBuffer&&i.stencilBuffer,this.depthTexture=void 0!==i.depthTexture?i.depthTexture:null,this.samples=void 0!==i.samples?i.samples:0}setSize(e,t,i=1){(this.width!==e||this.height!==t||this.depth!==i)&&(this.width=e,this.height=t,this.depth=i,this.texture.image.width=e,this.texture.image.height=t,this.texture.image.depth=i,this.dispose()),this.viewport.set(0,0,e,t),this.scissor.set(0,0,e,t)}clone(){return new this.constructor().copy(this)}copy(e){this.width=e.width,this.height=e.height,this.depth=e.depth,this.scissor.copy(e.scissor),this.scissorTest=e.scissorTest,this.viewport.copy(e.viewport),this.texture=e.texture.clone(),this.texture.isRenderTargetTexture=!0;let t=Object.assign({},e.texture.image);return this.texture.source=new O(t),this.depthBuffer=e.depthBuffer,this.stencilBuffer=e.stencilBuffer,null!==e.depthTexture&&(this.depthTexture=e.depthTexture.clone()),this.samples=e.samples,this}dispose(){this.dispatchEvent({type:"dispose"})}}class H extends B{constructor(e=1,t=1,i={}){super(e,t,i),this.isWebGLRenderTarget=!0}}class V extends F{constructor(e=null,t=1,i=1,r=1){super(null),this.isDataArrayTexture=!0,this.image={data:e,width:t,height:i,depth:r},this.magFilter=1003,this.minFilter=1003,this.wrapR=1001,this.generateMipmaps=!1,this.flipY=!1,this.unpackAlignment=1}}class G{constructor(e=0,t=0,i=0,r=1){this.isQuaternion=!0,this._x=e,this._y=t,this._z=i,this._w=r}static slerpFlat(e,t,i,r,a,n,s){let o=i[r+0],l=i[r+1],h=i[r+2],c=i[r+3],u=a[n+0],d=a[n+1],p=a[n+2],f=a[n+3];if(0===s){e[t+0]=o,e[t+1]=l,e[t+2]=h,e[t+3]=c;return}if(1===s){e[t+0]=u,e[t+1]=d,e[t+2]=p,e[t+3]=f;return}if(c!==f||o!==u||l!==d||h!==p){let e=1-s,t=o*u+l*d+h*p+c*f,i=t>=0?1:-1,r=1-t*t;if(r>Number.EPSILON){let a=Math.sqrt(r),n=Math.atan2(a,t*i);e=Math.sin(e*n)/a,s=Math.sin(s*n)/a}let a=s*i;if(o=o*e+u*a,l=l*e+d*a,h=h*e+p*a,c=c*e+f*a,e===1-s){let e=1/Math.sqrt(o*o+l*l+h*h+c*c);o*=e,l*=e,h*=e,c*=e}}e[t]=o,e[t+1]=l,e[t+2]=h,e[t+3]=c}static multiplyQuaternionsFlat(e,t,i,r,a,n){let s=i[r],o=i[r+1],l=i[r+2],h=i[r+3],c=a[n],u=a[n+1],d=a[n+2],p=a[n+3];return e[t]=s*p+h*c+o*d-l*u,e[t+1]=o*p+h*u+l*c-s*d,e[t+2]=l*p+h*d+s*u-o*c,e[t+3]=h*p-s*c-o*u-l*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t){let i=e._x,r=e._y,a=e._z,n=e._order,s=Math.cos,o=Math.sin,l=s(i/2),h=s(r/2),c=s(a/2),u=o(i/2),d=o(r/2),p=o(a/2);switch(n){case"XYZ":this._x=u*h*c+l*d*p,this._y=l*d*c-u*h*p,this._z=l*h*p+u*d*c,this._w=l*h*c-u*d*p;break;case"YXZ":this._x=u*h*c+l*d*p,this._y=l*d*c-u*h*p,this._z=l*h*p-u*d*c,this._w=l*h*c+u*d*p;break;case"ZXY":this._x=u*h*c-l*d*p,this._y=l*d*c+u*h*p,this._z=l*h*p+u*d*c,this._w=l*h*c-u*d*p;break;case"ZYX":this._x=u*h*c-l*d*p,this._y=l*d*c+u*h*p,this._z=l*h*p-u*d*c,this._w=l*h*c+u*d*p;break;case"YZX":this._x=u*h*c+l*d*p,this._y=l*d*c+u*h*p,this._z=l*h*p-u*d*c,this._w=l*h*c-u*d*p;break;case"XZY":this._x=u*h*c-l*d*p,this._y=l*d*c-u*h*p,this._z=l*h*p+u*d*c,this._w=l*h*c+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+n)}return!1!==t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){let i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this._onChangeCallback(),this}setFromRotationMatrix(e){let t=e.elements,i=t[0],r=t[4],a=t[8],n=t[1],s=t[5],o=t[9],l=t[2],h=t[6],c=t[10],u=i+s+c;if(u>0){let e=.5/Math.sqrt(u+1);this._w=.25/e,this._x=(h-o)*e,this._y=(a-l)*e,this._z=(n-r)*e}else if(i>s&&i>c){let e=2*Math.sqrt(1+i-s-c);this._w=(h-o)/e,this._x=.25*e,this._y=(r+n)/e,this._z=(a+l)/e}else if(s>c){let e=2*Math.sqrt(1+s-i-c);this._w=(a-l)/e,this._x=(r+n)/e,this._y=.25*e,this._z=(o+h)/e}else{let e=2*Math.sqrt(1+c-i-s);this._w=(n-r)/e,this._x=(a+l)/e,this._y=(o+h)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let i=e.dot(t)+1;return iMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=i):(this._x=0,this._y=-e.z,this._z=e.y,this._w=i)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=i),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs(f(this.dot(e),-1,1)))}rotateTowards(e,t){let i=this.angleTo(e);return 0===i||this.slerp(e,Math.min(1,t/i)),this}identity(){return this.set(0,0,0,1)}invert(){return this.conjugate()}conjugate(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this}dot(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w}lengthSq(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w}length(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)}normalize(){let e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){let i=e._x,r=e._y,a=e._z,n=e._w,s=t._x,o=t._y,l=t._z,h=t._w;return this._x=i*h+n*s+r*l-a*o,this._y=r*h+n*o+a*s-i*l,this._z=a*h+n*l+i*o-r*s,this._w=n*h-i*s-r*o-a*l,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);let i=this._x,r=this._y,a=this._z,n=this._w,s=n*e._w+i*e._x+r*e._y+a*e._z;if(s<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,s=-s):this.copy(e),s>=1)return this._w=n,this._x=i,this._y=r,this._z=a,this;let o=1-s*s;if(o<=Number.EPSILON){let e=1-t;return this._w=e*n+t*this._w,this._x=e*i+t*this._x,this._y=e*r+t*this._y,this._z=e*a+t*this._z,this.normalize(),this._onChangeCallback(),this}let l=Math.sqrt(o),h=Math.atan2(l,s),c=Math.sin((1-t)*h)/l,u=Math.sin(t*h)/l;return this._w=n*c+this._w*u,this._x=i*c+this._x*u,this._y=r*c+this._y*u,this._z=a*c+this._z*u,this._onChangeCallback(),this}slerpQuaternions(e,t,i){return this.copy(e).slerp(t,i)}random(){let e=Math.random(),t=Math.sqrt(1-e),i=Math.sqrt(e),r=2*Math.PI*Math.random(),a=2*Math.PI*Math.random();return this.set(t*Math.cos(r),i*Math.sin(a),i*Math.cos(a),t*Math.sin(r))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class W{constructor(e=0,t=0,i=0){W.prototype.isVector3=!0,this.x=e,this.y=t,this.z=i}set(e,t,i){return void 0===i&&(i=this.z),this.x=e,this.y=t,this.z=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(q.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(q.setFromAxisAngle(e,t))}applyMatrix3(e){let t=this.x,i=this.y,r=this.z,a=e.elements;return this.x=a[0]*t+a[3]*i+a[6]*r,this.y=a[1]*t+a[4]*i+a[7]*r,this.z=a[2]*t+a[5]*i+a[8]*r,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){let t=this.x,i=this.y,r=this.z,a=e.elements,n=1/(a[3]*t+a[7]*i+a[11]*r+a[15]);return this.x=(a[0]*t+a[4]*i+a[8]*r+a[12])*n,this.y=(a[1]*t+a[5]*i+a[9]*r+a[13])*n,this.z=(a[2]*t+a[6]*i+a[10]*r+a[14])*n,this}applyQuaternion(e){let t=this.x,i=this.y,r=this.z,a=e.x,n=e.y,s=e.z,o=e.w,l=o*t+n*r-s*i,h=o*i+s*t-a*r,c=o*r+a*i-n*t,u=-a*t-n*i-s*r;return this.x=l*o+-(u*a)+-(h*s)- -(c*n),this.y=h*o+-(u*n)+-(c*a)- -(l*s),this.z=c*o+-(u*s)+-(l*n)- -(h*a),this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){let t=this.x,i=this.y,r=this.z,a=e.elements;return this.x=a[0]*t+a[4]*i+a[8]*r,this.y=a[1]*t+a[5]*i+a[9]*r,this.z=a[2]*t+a[6]*i+a[10]*r,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){let i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))}floor(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this}ceil(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this}round(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this}roundToZero(){return this.x=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.z}lengthSq(){return this.x*this.x+this.y*this.y+this.z*this.z}length(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)}manhattanLength(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)}normalize(){return this.divideScalar(this.length()||1)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,i){return this.x=e.x+(t.x-e.x)*i,this.y=e.y+(t.y-e.y)*i,this.z=e.z+(t.z-e.z)*i,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){let i=e.x,r=e.y,a=e.z,n=t.x,s=t.y,o=t.z;return this.x=r*o-a*s,this.y=a*n-i*o,this.z=i*s-r*n,this}projectOnVector(e){let t=e.lengthSq();if(0===t)return this.set(0,0,0);let i=e.dot(this)/t;return this.copy(e).multiplyScalar(i)}projectOnPlane(e){return j.copy(this).projectOnVector(e),this.sub(j)}reflect(e){return this.sub(j.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){let t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;let i=this.dot(e)/t;return Math.acos(f(i,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){let t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,i){let r=Math.sin(t)*e;return this.x=r*Math.sin(i),this.y=Math.cos(t)*e,this.z=r*Math.cos(i),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,i){return this.x=e*Math.sin(t),this.y=i,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){let t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){let t=this.setFromMatrixColumn(e,0).length(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){let e=(Math.random()-.5)*2,t=Math.random()*Math.PI*2,i=Math.sqrt(1-e**2);return this.x=i*Math.cos(t),this.y=i*Math.sin(t),this.z=e,this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}let j=new W,q=new G;class X{constructor(e=new W(Infinity,Infinity,Infinity),t=new W(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,i=e.length;tthis.max.x)&&!(e.ythis.max.y)&&!(e.zthis.max.z)}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return!(e.max.xthis.max.x)&&!(e.max.ythis.max.y)&&!(e.max.zthis.max.z)}intersectsSphere(e){return this.clampPoint(e.center,Z),Z.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=-e.constant&&i>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(er),ea.subVectors(this.max,er),J.subVectors(e.a,er),Q.subVectors(e.b,er),$.subVectors(e.c,er),ee.subVectors(Q,J),et.subVectors($,Q),ei.subVectors(J,$);let t=[0,-ee.z,ee.y,0,-et.z,et.y,0,-ei.z,ei.y,ee.z,0,-ee.x,et.z,0,-et.x,ei.z,0,-ei.x,-ee.y,ee.x,0,-et.y,et.x,0,-ei.y,ei.x,0];return!!(eo(t,J,Q,$,ea)&&eo(t=[1,0,0,0,1,0,0,0,1],J,Q,$,ea))&&(en.crossVectors(ee,et),eo(t=[en.x,en.y,en.z],J,Q,$,ea))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Z).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Z).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(Y[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Y[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Y[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Y[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Y[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Y[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Y[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Y[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Y)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}let Y=[new W,new W,new W,new W,new W,new W,new W,new W],Z=new W,K=new X,J=new W,Q=new W,$=new W,ee=new W,et=new W,ei=new W,er=new W,ea=new W,en=new W,es=new W;function eo(e,t,i,r,a){for(let n=0,s=e.length-3;n<=s;n+=3){es.fromArray(e,n);let s=a.x*Math.abs(es.x)+a.y*Math.abs(es.y)+a.z*Math.abs(es.z),o=t.dot(es),l=i.dot(es),h=r.dot(es);if(Math.max(-Math.max(o,l,h),Math.min(o,l,h))>s)return!1}return!0}let el=new X,eh=new W,ec=new W;class eu{constructor(e=new W,t=-1){this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){let i=this.center;void 0!==t?i.copy(t):el.setFromPoints(e).getCenter(i);let r=0;for(let t=0,a=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;eh.subVectors(e,this.center);let t=eh.lengthSq();if(t>this.radius*this.radius){let e=Math.sqrt(t),i=(e-this.radius)*.5;this.center.addScaledVector(eh,i/e),this.radius+=i}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(ec.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(eh.copy(e.center).add(ec)),this.expandByPoint(eh.copy(e.center).sub(ec))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return new this.constructor().copy(this)}}let ed=new W,ep=new W,ef=new W,em=new W,eg=new W,ev=new W,e_=new W;class ex{constructor(e=new W,t=new W(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,ed)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);let i=t.dot(this.direction);return i<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,i)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){let t=ed.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(ed.copy(this.origin).addScaledVector(this.direction,t),ed.distanceToSquared(e))}distanceSqToSegment(e,t,i,r){let a,n,s,o;ep.copy(e).add(t).multiplyScalar(.5),ef.copy(t).sub(e).normalize(),em.copy(this.origin).sub(ep);let l=.5*e.distanceTo(t),h=-this.direction.dot(ef),c=em.dot(this.direction),u=-em.dot(ef),d=em.lengthSq(),p=Math.abs(1-h*h);if(p>0){if(a=h*u-c,n=h*c-u,o=l*p,a>=0){if(n>=-o){if(n<=o){let e=1/p;a*=e,n*=e,s=a*(a+h*n+2*c)+n*(h*a+n+2*u)+d}else s=-(a=Math.max(0,-(h*(n=l)+c)))*a+n*(n+2*u)+d}else s=-(a=Math.max(0,-(h*(n=-l)+c)))*a+n*(n+2*u)+d}else n<=-o?(n=(a=Math.max(0,-(-h*l+c)))>0?-l:Math.min(Math.max(-l,-u),l),s=-a*a+n*(n+2*u)+d):n<=o?(a=0,s=(n=Math.min(Math.max(-l,-u),l))*(n+2*u)+d):(n=(a=Math.max(0,-(h*l+c)))>0?l:Math.min(Math.max(-l,-u),l),s=-a*a+n*(n+2*u)+d)}else n=h>0?-l:l,s=-(a=Math.max(0,-(h*n+c)))*a+n*(n+2*u)+d;return i&&i.copy(this.origin).addScaledVector(this.direction,a),r&&r.copy(ep).addScaledVector(ef,n),s}intersectSphere(e,t){ed.subVectors(e.center,this.origin);let i=ed.dot(this.direction),r=ed.dot(ed)-i*i,a=e.radius*e.radius;if(r>a)return null;let n=Math.sqrt(a-r),s=i-n,o=i+n;return o<0?null:s<0?this.at(o,t):this.at(s,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){let t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;let i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null}intersectPlane(e,t){let i=this.distanceToPlane(e);return null===i?null:this.at(i,t)}intersectsPlane(e){let t=e.distanceToPoint(this.origin);if(0===t)return!0;let i=e.normal.dot(this.direction);return i*t<0}intersectBox(e,t){let i,r,a,n,s,o;let l=1/this.direction.x,h=1/this.direction.y,c=1/this.direction.z,u=this.origin;return(l>=0?(i=(e.min.x-u.x)*l,r=(e.max.x-u.x)*l):(i=(e.max.x-u.x)*l,r=(e.min.x-u.x)*l),h>=0?(a=(e.min.y-u.y)*h,n=(e.max.y-u.y)*h):(a=(e.max.y-u.y)*h,n=(e.min.y-u.y)*h),i>n||a>r)?null:((a>i||isNaN(i))&&(i=a),(n=0?(s=(e.min.z-u.z)*c,o=(e.max.z-u.z)*c):(s=(e.max.z-u.z)*c,o=(e.min.z-u.z)*c),i>o||s>r)?null:((s>i||i!=i)&&(i=s),(o=0?i:r,t)}intersectsBox(e){return null!==this.intersectBox(e,ed)}intersectTriangle(e,t,i,r,a){let n;eg.subVectors(t,e),ev.subVectors(i,e),e_.crossVectors(eg,ev);let s=this.direction.dot(e_);if(s>0){if(r)return null;n=1}else{if(!(s<0))return null;n=-1,s=-s}em.subVectors(this.origin,e);let o=n*this.direction.dot(ev.crossVectors(em,ev));if(o<0)return null;let l=n*this.direction.dot(eg.cross(em));if(l<0||o+l>s)return null;let h=-n*em.dot(e_);return h<0?null:this.at(h/s,a)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return new this.constructor().copy(this)}}class ey{constructor(e,t,i,r,a,n,s,o,l,h,c,u,d,p,f,m){ey.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,i,r,a,n,s,o,l,h,c,u,d,p,f,m)}set(e,t,i,r,a,n,s,o,l,h,c,u,d,p,f,m){let g=this.elements;return g[0]=e,g[4]=t,g[8]=i,g[12]=r,g[1]=a,g[5]=n,g[9]=s,g[13]=o,g[2]=l,g[6]=h,g[10]=c,g[14]=u,g[3]=d,g[7]=p,g[11]=f,g[15]=m,this}identity(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this}clone(){return new ey().fromArray(this.elements)}copy(e){let t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this}copyPosition(e){let t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this}setFromMatrix3(e){let t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this}makeBasis(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this}extractRotation(e){let t=this.elements,i=e.elements,r=1/eM.setFromMatrixColumn(e,0).length(),a=1/eM.setFromMatrixColumn(e,1).length(),n=1/eM.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[3]=0,t[4]=i[4]*a,t[5]=i[5]*a,t[6]=i[6]*a,t[7]=0,t[8]=i[8]*n,t[9]=i[9]*n,t[10]=i[10]*n,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){let t=this.elements,i=e.x,r=e.y,a=e.z,n=Math.cos(i),s=Math.sin(i),o=Math.cos(r),l=Math.sin(r),h=Math.cos(a),c=Math.sin(a);if("XYZ"===e.order){let e=n*h,i=n*c,r=s*h,a=s*c;t[0]=o*h,t[4]=-o*c,t[8]=l,t[1]=i+r*l,t[5]=e-a*l,t[9]=-s*o,t[2]=a-e*l,t[6]=r+i*l,t[10]=n*o}else if("YXZ"===e.order){let e=o*h,i=o*c,r=l*h,a=l*c;t[0]=e+a*s,t[4]=r*s-i,t[8]=n*l,t[1]=n*c,t[5]=n*h,t[9]=-s,t[2]=i*s-r,t[6]=a+e*s,t[10]=n*o}else if("ZXY"===e.order){let e=o*h,i=o*c,r=l*h,a=l*c;t[0]=e-a*s,t[4]=-n*c,t[8]=r+i*s,t[1]=i+r*s,t[5]=n*h,t[9]=a-e*s,t[2]=-n*l,t[6]=s,t[10]=n*o}else if("ZYX"===e.order){let e=n*h,i=n*c,r=s*h,a=s*c;t[0]=o*h,t[4]=r*l-i,t[8]=e*l+a,t[1]=o*c,t[5]=a*l+e,t[9]=i*l-r,t[2]=-l,t[6]=s*o,t[10]=n*o}else if("YZX"===e.order){let e=n*o,i=n*l,r=s*o,a=s*l;t[0]=o*h,t[4]=a-e*c,t[8]=r*c+i,t[1]=c,t[5]=n*h,t[9]=-s*h,t[2]=-l*h,t[6]=i*c+r,t[10]=e-a*c}else if("XZY"===e.order){let e=n*o,i=n*l,r=s*o,a=s*l;t[0]=o*h,t[4]=-c,t[8]=l*h,t[1]=e*c+a,t[5]=n*h,t[9]=i*c-r,t[2]=r*c-i,t[6]=s*h,t[10]=a*c+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(eb,e,ew)}lookAt(e,t,i){let r=this.elements;return eA.subVectors(e,t),0===eA.lengthSq()&&(eA.z=1),eA.normalize(),eT.crossVectors(i,eA),0===eT.lengthSq()&&(1===Math.abs(i.z)?eA.x+=1e-4:eA.z+=1e-4,eA.normalize(),eT.crossVectors(i,eA)),eT.normalize(),eE.crossVectors(eA,eT),r[0]=eT.x,r[4]=eE.x,r[8]=eA.x,r[1]=eT.y,r[5]=eE.y,r[9]=eA.y,r[2]=eT.z,r[6]=eE.z,r[10]=eA.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){let i=e.elements,r=t.elements,a=this.elements,n=i[0],s=i[4],o=i[8],l=i[12],h=i[1],c=i[5],u=i[9],d=i[13],p=i[2],f=i[6],m=i[10],g=i[14],v=i[3],_=i[7],x=i[11],y=i[15],M=r[0],S=r[4],b=r[8],w=r[12],T=r[1],E=r[5],A=r[9],C=r[13],L=r[2],P=r[6],R=r[10],D=r[14],I=r[3],U=r[7],O=r[11],N=r[15];return a[0]=n*M+s*T+o*L+l*I,a[4]=n*S+s*E+o*P+l*U,a[8]=n*b+s*A+o*R+l*O,a[12]=n*w+s*C+o*D+l*N,a[1]=h*M+c*T+u*L+d*I,a[5]=h*S+c*E+u*P+d*U,a[9]=h*b+c*A+u*R+d*O,a[13]=h*w+c*C+u*D+d*N,a[2]=p*M+f*T+m*L+g*I,a[6]=p*S+f*E+m*P+g*U,a[10]=p*b+f*A+m*R+g*O,a[14]=p*w+f*C+m*D+g*N,a[3]=v*M+_*T+x*L+y*I,a[7]=v*S+_*E+x*P+y*U,a[11]=v*b+_*A+x*R+y*O,a[15]=v*w+_*C+x*D+y*N,this}multiplyScalar(e){let t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){let e=this.elements,t=e[0],i=e[4],r=e[8],a=e[12],n=e[1],s=e[5],o=e[9],l=e[13],h=e[2],c=e[6],u=e[10],d=e[14],p=e[3],f=e[7],m=e[11],g=e[15];return p*(+a*o*c-r*l*c-a*s*u+i*l*u+r*s*d-i*o*d)+f*(+t*o*d-t*l*u+a*n*u-r*n*d+r*l*h-a*o*h)+m*(+t*l*c-t*s*d-a*n*c+i*n*d+a*s*h-i*l*h)+g*(-r*s*h-t*o*c+t*s*u+r*n*c-i*n*u+i*o*h)}transpose(){let e;let t=this.elements;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this}setPosition(e,t,i){let r=this.elements;return e.isVector3?(r[12]=e.x,r[13]=e.y,r[14]=e.z):(r[12]=e,r[13]=t,r[14]=i),this}invert(){let e=this.elements,t=e[0],i=e[1],r=e[2],a=e[3],n=e[4],s=e[5],o=e[6],l=e[7],h=e[8],c=e[9],u=e[10],d=e[11],p=e[12],f=e[13],m=e[14],g=e[15],v=c*m*l-f*u*l+f*o*d-s*m*d-c*o*g+s*u*g,_=p*u*l-h*m*l-p*o*d+n*m*d+h*o*g-n*u*g,x=h*f*l-p*c*l+p*s*d-n*f*d-h*s*g+n*c*g,y=p*c*o-h*f*o-p*s*u+n*f*u+h*s*m-n*c*m,M=t*v+i*_+r*x+a*y;if(0===M)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);let S=1/M;return e[0]=v*S,e[1]=(f*u*a-c*m*a-f*r*d+i*m*d+c*r*g-i*u*g)*S,e[2]=(s*m*a-f*o*a+f*r*l-i*m*l-s*r*g+i*o*g)*S,e[3]=(c*o*a-s*u*a-c*r*l+i*u*l+s*r*d-i*o*d)*S,e[4]=_*S,e[5]=(h*m*a-p*u*a+p*r*d-t*m*d-h*r*g+t*u*g)*S,e[6]=(p*o*a-n*m*a-p*r*l+t*m*l+n*r*g-t*o*g)*S,e[7]=(n*u*a-h*o*a+h*r*l-t*u*l-n*r*d+t*o*d)*S,e[8]=x*S,e[9]=(p*c*a-h*f*a-p*i*d+t*f*d+h*i*g-t*c*g)*S,e[10]=(n*f*a-p*s*a+p*i*l-t*f*l-n*i*g+t*s*g)*S,e[11]=(h*s*a-n*c*a-h*i*l+t*c*l+n*i*d-t*s*d)*S,e[12]=y*S,e[13]=(h*f*r-p*c*r+p*i*u-t*f*u-h*i*m+t*c*m)*S,e[14]=(p*s*r-n*f*r-p*i*o+t*f*o+n*i*m-t*s*m)*S,e[15]=(n*c*r-h*s*r+h*i*o-t*c*o-n*i*u+t*s*u)*S,this}scale(e){let t=this.elements,i=e.x,r=e.y,a=e.z;return t[0]*=i,t[4]*=r,t[8]*=a,t[1]*=i,t[5]*=r,t[9]*=a,t[2]*=i,t[6]*=r,t[10]*=a,t[3]*=i,t[7]*=r,t[11]*=a,this}getMaxScaleOnAxis(){let e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],i=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],r=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,i,r))}makeTranslation(e,t,i){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,i,0,0,0,1),this}makeRotationX(e){let t=Math.cos(e),i=Math.sin(e);return this.set(1,0,0,0,0,t,-i,0,0,i,t,0,0,0,0,1),this}makeRotationY(e){let t=Math.cos(e),i=Math.sin(e);return this.set(t,0,i,0,0,1,0,0,-i,0,t,0,0,0,0,1),this}makeRotationZ(e){let t=Math.cos(e),i=Math.sin(e);return this.set(t,-i,0,0,i,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){let i=Math.cos(t),r=Math.sin(t),a=1-i,n=e.x,s=e.y,o=e.z,l=a*n,h=a*s;return this.set(l*n+i,l*s-r*o,l*o+r*s,0,l*s+r*o,h*s+i,h*o-r*n,0,l*o-r*s,h*o+r*n,a*o*o+i,0,0,0,0,1),this}makeScale(e,t,i){return this.set(e,0,0,0,0,t,0,0,0,0,i,0,0,0,0,1),this}makeShear(e,t,i,r,a,n){return this.set(1,i,a,0,e,1,n,0,t,r,1,0,0,0,0,1),this}compose(e,t,i){let r=this.elements,a=t._x,n=t._y,s=t._z,o=t._w,l=a+a,h=n+n,c=s+s,u=a*l,d=a*h,p=a*c,f=n*h,m=n*c,g=s*c,v=o*l,_=o*h,x=o*c,y=i.x,M=i.y,S=i.z;return r[0]=(1-(f+g))*y,r[1]=(d+x)*y,r[2]=(p-_)*y,r[3]=0,r[4]=(d-x)*M,r[5]=(1-(u+g))*M,r[6]=(m+v)*M,r[7]=0,r[8]=(p+_)*S,r[9]=(m-v)*S,r[10]=(1-(u+f))*S,r[11]=0,r[12]=e.x,r[13]=e.y,r[14]=e.z,r[15]=1,this}decompose(e,t,i){let r=this.elements,a=eM.set(r[0],r[1],r[2]).length(),n=eM.set(r[4],r[5],r[6]).length(),s=eM.set(r[8],r[9],r[10]).length(),o=this.determinant();o<0&&(a=-a),e.x=r[12],e.y=r[13],e.z=r[14],eS.copy(this);let l=1/a,h=1/n,c=1/s;return eS.elements[0]*=l,eS.elements[1]*=l,eS.elements[2]*=l,eS.elements[4]*=h,eS.elements[5]*=h,eS.elements[6]*=h,eS.elements[8]*=c,eS.elements[9]*=c,eS.elements[10]*=c,t.setFromRotationMatrix(eS),i.x=a,i.y=n,i.z=s,this}makePerspective(e,t,i,r,a,n,s=2e3){let o,l;let h=this.elements;if(2e3===s)o=-(n+a)/(n-a),l=-2*n*a/(n-a);else if(2001===s)o=-n/(n-a),l=-n*a/(n-a);else throw Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+s);return h[0]=2*a/(t-e),h[4]=0,h[8]=(t+e)/(t-e),h[12]=0,h[1]=0,h[5]=2*a/(i-r),h[9]=(i+r)/(i-r),h[13]=0,h[2]=0,h[6]=0,h[10]=o,h[14]=l,h[3]=0,h[7]=0,h[11]=-1,h[15]=0,this}makeOrthographic(e,t,i,r,a,n,s=2e3){let o,l;let h=this.elements,c=1/(t-e),u=1/(i-r),d=1/(n-a);if(2e3===s)o=(n+a)*d,l=-2*d;else if(2001===s)o=a*d,l=-1*d;else throw Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+s);return h[0]=2*c,h[4]=0,h[8]=0,h[12]=-((t+e)*c),h[1]=0,h[5]=2*u,h[9]=0,h[13]=-((i+r)*u),h[2]=0,h[6]=0,h[10]=l,h[14]=-o,h[3]=0,h[7]=0,h[11]=0,h[15]=1,this}equals(e){let t=this.elements,i=e.elements;for(let e=0;e<16;e++)if(t[e]!==i[e])return!1;return!0}fromArray(e,t=0){for(let i=0;i<16;i++)this.elements[i]=e[i+t];return this}toArray(e=[],t=0){let i=this.elements;return e[t]=i[0],e[t+1]=i[1],e[t+2]=i[2],e[t+3]=i[3],e[t+4]=i[4],e[t+5]=i[5],e[t+6]=i[6],e[t+7]=i[7],e[t+8]=i[8],e[t+9]=i[9],e[t+10]=i[10],e[t+11]=i[11],e[t+12]=i[12],e[t+13]=i[13],e[t+14]=i[14],e[t+15]=i[15],e}}let eM=new W,eS=new ey,eb=new W(0,0,0),ew=new W(1,1,1),eT=new W,eE=new W,eA=new W,eC=new ey,eL=new G;class eP{constructor(e=0,t=0,i=0,r=eP.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=i,this._order=r}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,i,r=this._order){return this._x=e,this._y=t,this._z=i,this._order=r,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,i=!0){let r=e.elements,a=r[0],n=r[4],s=r[8],o=r[1],l=r[5],h=r[9],c=r[2],u=r[6],d=r[10];switch(t){case"XYZ":this._y=Math.asin(f(s,-1,1)),.9999999>Math.abs(s)?(this._x=Math.atan2(-h,d),this._z=Math.atan2(-n,a)):(this._x=Math.atan2(u,l),this._z=0);break;case"YXZ":this._x=Math.asin(-f(h,-1,1)),.9999999>Math.abs(h)?(this._y=Math.atan2(s,d),this._z=Math.atan2(o,l)):(this._y=Math.atan2(-c,a),this._z=0);break;case"ZXY":this._x=Math.asin(f(u,-1,1)),.9999999>Math.abs(u)?(this._y=Math.atan2(-c,d),this._z=Math.atan2(-n,l)):(this._y=0,this._z=Math.atan2(o,a));break;case"ZYX":this._y=Math.asin(-f(c,-1,1)),.9999999>Math.abs(c)?(this._x=Math.atan2(u,d),this._z=Math.atan2(o,a)):(this._x=0,this._z=Math.atan2(-n,l));break;case"YZX":this._z=Math.asin(f(o,-1,1)),.9999999>Math.abs(o)?(this._x=Math.atan2(-h,l),this._y=Math.atan2(-c,a)):(this._x=0,this._y=Math.atan2(s,d));break;case"XZY":this._z=Math.asin(-f(n,-1,1)),.9999999>Math.abs(n)?(this._x=Math.atan2(u,l),this._y=Math.atan2(s,a)):(this._x=Math.atan2(-h,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===i&&this._onChangeCallback(),this}setFromQuaternion(e,t,i){return eC.makeRotationFromQuaternion(e),this.setFromRotationMatrix(eC,t,i)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return eL.setFromEuler(this),this.setFromQuaternion(eL,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}eP.DEFAULT_ORDER="XYZ";class eR{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i=i.concat(a))}return i}getWorldPosition(e){return this.updateWorldMatrix(!0,!1),e.setFromMatrixPosition(this.matrixWorld)}getWorldQuaternion(e){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(ez,e,eF),e}getWorldScale(e){return this.updateWorldMatrix(!0,!1),this.matrixWorld.decompose(ez,ek,e),e}getWorldDirection(e){this.updateWorldMatrix(!0,!1);let t=this.matrixWorld.elements;return e.set(t[8],t[9],t[10]).normalize()}raycast(){}traverse(e){e(this);let t=this.children;for(let i=0,r=t.length;i0&&(r.userData=this.userData),r.layers=this.layers.mask,r.matrix=this.matrix.toArray(),r.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(r.matrixAutoUpdate=!1),this.isInstancedMesh&&(r.type="InstancedMesh",r.count=this.count,r.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(r.instanceColor=this.instanceColor.toJSON())),this.isScene)this.background&&(this.background.isColor?r.background=this.background.toJSON():this.background.isTexture&&(r.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(r.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){r.geometry=a(e.geometries,this.geometry);let t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){let i=t.shapes;if(Array.isArray(i))for(let t=0,r=i.length;t0){r.children=[];for(let t=0;t0){r.animations=[];for(let t=0;t0&&(i.geometries=t),r.length>0&&(i.materials=r),a.length>0&&(i.textures=a),s.length>0&&(i.images=s),o.length>0&&(i.shapes=o),l.length>0&&(i.skeletons=l),h.length>0&&(i.animations=h),c.length>0&&(i.nodes=c)}return i.object=r,i;function n(e){let t=[];for(let i in e){let r=e[i];delete r.metadata,t.push(r)}return t}}clone(e){return new this.constructor().copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?r.multiplyScalar(1/Math.sqrt(a)):r.set(0,0,0)}static getBarycoord(e,t,i,r,a){eq.subVectors(r,t),eX.subVectors(i,t),eY.subVectors(e,t);let n=eq.dot(eq),s=eq.dot(eX),o=eq.dot(eY),l=eX.dot(eX),h=eX.dot(eY),c=n*l-s*s;if(0===c)return a.set(-2,-1,-1);let u=1/c,d=(l*o-s*h)*u,p=(n*h-s*o)*u;return a.set(1-d-p,p,d)}static containsPoint(e,t,i,r){return this.getBarycoord(e,t,i,r,eZ),eZ.x>=0&&eZ.y>=0&&eZ.x+eZ.y<=1}static getUV(e,t,i,r,a,n,s,o){return!1===e3&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),e3=!0),this.getInterpolation(e,t,i,r,a,n,s,o)}static getInterpolation(e,t,i,r,a,n,s,o){return this.getBarycoord(e,t,i,r,eZ),o.setScalar(0),o.addScaledVector(a,eZ.x),o.addScaledVector(n,eZ.y),o.addScaledVector(s,eZ.z),o}static isFrontFacing(e,t,i,r){return eq.subVectors(i,t),eX.subVectors(e,t),0>eq.cross(eX).dot(r)}set(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this}setFromPointsAndIndices(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),this}setFromAttributeAndIndices(e,t,i,r){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,i),this.c.fromBufferAttribute(e,r),this}clone(){return new this.constructor().copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return eq.subVectors(this.c,this.b),eX.subVectors(this.a,this.b),.5*eq.cross(eX).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return e2.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return e2.getBarycoord(e,this.a,this.b,this.c,t)}getUV(e,t,i,r,a){return!1===e3&&(console.warn("THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation()."),e3=!0),e2.getInterpolation(e,this.a,this.b,this.c,t,i,r,a)}getInterpolation(e,t,i,r,a){return e2.getInterpolation(e,this.a,this.b,this.c,t,i,r,a)}containsPoint(e){return e2.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return e2.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){let i,r;let a=this.a,n=this.b,s=this.c;eK.subVectors(n,a),eJ.subVectors(s,a),e$.subVectors(e,a);let o=eK.dot(e$),l=eJ.dot(e$);if(o<=0&&l<=0)return t.copy(a);e0.subVectors(e,n);let h=eK.dot(e0),c=eJ.dot(e0);if(h>=0&&c<=h)return t.copy(n);let u=o*c-h*l;if(u<=0&&o>=0&&h<=0)return i=o/(o-h),t.copy(a).addScaledVector(eK,i);e1.subVectors(e,s);let d=eK.dot(e1),p=eJ.dot(e1);if(p>=0&&d<=p)return t.copy(s);let f=d*l-o*p;if(f<=0&&l>=0&&p<=0)return r=l/(l-p),t.copy(a).addScaledVector(eJ,r);let m=h*p-d*c;if(m<=0&&c-h>=0&&d-p>=0)return eQ.subVectors(s,n),r=(c-h)/(c-h+(d-p)),t.copy(n).addScaledVector(eQ,r);let g=1/(m+f+u);return i=f*g,r=u*g,t.copy(a).addScaledVector(eK,i).addScaledVector(eJ,r)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}let e4=0;class e5 extends h{constructor(){super(),this.isMaterial=!0,Object.defineProperty(this,"id",{value:e4++}),this.uuid=p(),this.name="",this.type="Material",this.blending=1,this.side=0,this.vertexColors=!1,this.opacity=1,this.transparent=!1,this.alphaHash=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=100,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.stencilWriteMask=255,this.stencilFunc=519,this.stencilRef=0,this.stencilFuncMask=255,this.stencilFail=7680,this.stencilZFail=7680,this.stencilZPass=7680,this.stencilWrite=!1,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.shadowSide=null,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaToCoverage=!1,this.premultipliedAlpha=!1,this.forceSinglePass=!1,this.visible=!0,this.toneMapped=!0,this.userData={},this.version=0,this._alphaTest=0}get alphaTest(){return this._alphaTest}set alphaTest(e){this._alphaTest>0!=e>0&&this.version++,this._alphaTest=e}onBuild(){}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(let t in e){let i=e[t];if(void 0===i){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}let r=this[t];if(void 0===r){console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`);continue}r&&r.isColor?r.set(i):r&&r.isVector3&&i&&i.isVector3?r.copy(i):this[t]=i}}toJSON(e){let t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});let i={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function r(e){let t=[];for(let i in e){let r=e[i];delete r.metadata,t.push(r)}return t}if(i.uuid=this.uuid,i.type=this.type,""!==this.name&&(i.name=this.name),this.color&&this.color.isColor&&(i.color=this.color.getHex()),void 0!==this.roughness&&(i.roughness=this.roughness),void 0!==this.metalness&&(i.metalness=this.metalness),void 0!==this.sheen&&(i.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(i.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(i.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(i.emissive=this.emissive.getHex()),this.emissiveIntensity&&1!==this.emissiveIntensity&&(i.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(i.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(i.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(i.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(i.shininess=this.shininess),void 0!==this.clearcoat&&(i.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(i.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(i.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(i.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(i.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,i.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.iridescence&&(i.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(i.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(i.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(i.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(i.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(i.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(i.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(i.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(i.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(i.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(i.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(i.lightMap=this.lightMap.toJSON(e).uuid,i.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(i.aoMap=this.aoMap.toJSON(e).uuid,i.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(i.bumpMap=this.bumpMap.toJSON(e).uuid,i.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(i.normalMap=this.normalMap.toJSON(e).uuid,i.normalMapType=this.normalMapType,i.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(i.displacementMap=this.displacementMap.toJSON(e).uuid,i.displacementScale=this.displacementScale,i.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(i.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(i.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(i.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(i.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(i.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(i.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(i.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(i.combine=this.combine)),void 0!==this.envMapIntensity&&(i.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(i.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(i.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(i.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(i.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(i.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(i.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(i.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(i.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(i.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(i.size=this.size),null!==this.shadowSide&&(i.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(i.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(i.blending=this.blending),0!==this.side&&(i.side=this.side),this.vertexColors&&(i.vertexColors=!0),this.opacity<1&&(i.opacity=this.opacity),!0===this.transparent&&(i.transparent=this.transparent),i.depthFunc=this.depthFunc,i.depthTest=this.depthTest,i.depthWrite=this.depthWrite,i.colorWrite=this.colorWrite,i.stencilWrite=this.stencilWrite,i.stencilWriteMask=this.stencilWriteMask,i.stencilFunc=this.stencilFunc,i.stencilRef=this.stencilRef,i.stencilFuncMask=this.stencilFuncMask,i.stencilFail=this.stencilFail,i.stencilZFail=this.stencilZFail,i.stencilZPass=this.stencilZPass,void 0!==this.rotation&&0!==this.rotation&&(i.rotation=this.rotation),!0===this.polygonOffset&&(i.polygonOffset=!0),0!==this.polygonOffsetFactor&&(i.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(i.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(i.linewidth=this.linewidth),void 0!==this.dashSize&&(i.dashSize=this.dashSize),void 0!==this.gapSize&&(i.gapSize=this.gapSize),void 0!==this.scale&&(i.scale=this.scale),!0===this.dithering&&(i.dithering=!0),this.alphaTest>0&&(i.alphaTest=this.alphaTest),!0===this.alphaHash&&(i.alphaHash=this.alphaHash),!0===this.alphaToCoverage&&(i.alphaToCoverage=this.alphaToCoverage),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.forceSinglePass&&(i.forceSinglePass=this.forceSinglePass),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(i.flatShading=this.flatShading),!1===this.visible&&(i.visible=!1),!1===this.toneMapped&&(i.toneMapped=!1),!1===this.fog&&(i.fog=!1),Object.keys(this.userData).length>0&&(i.userData=this.userData),t){let t=r(e.textures),a=r(e.images);t.length>0&&(i.textures=t),a.length>0&&(i.images=a)}return i}clone(){return new this.constructor().copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;let t=e.clippingPlanes,i=null;if(null!==t){let e=t.length;i=Array(e);for(let r=0;r!==e;++r)i[r]=t[r].clone()}return this.clippingPlanes=i,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}}let e6={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},e8={h:0,s:0,l:0},e7={h:0,s:0,l:0};function e9(e,t,i){return(i<0&&(i+=1),i>1&&(i-=1),i<1/6)?e+(t-e)*6*i:i<.5?t:i<2/3?e+(t-e)*6*(2/3-i):e}class te{constructor(e,t,i){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,i)}set(e,t,i){return void 0===t&&void 0===i?e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e):this.setRGB(e,t,i),this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=n){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,D.toWorkingColorSpace(this,t),this}setRGB(e,t,i,r=D.workingColorSpace){return this.r=e,this.g=t,this.b=i,D.toWorkingColorSpace(this,r),this}setHSL(e,t,i,r=D.workingColorSpace){if(e=(e%1+1)%1,t=f(t,0,1),i=f(i,0,1),0===t)this.r=this.g=this.b=i;else{let r=i<=.5?i*(1+t):i+t-i*t,a=2*i-r;this.r=e9(a,r,e+1/3),this.g=e9(a,r,e),this.b=e9(a,r,e-1/3)}return D.toWorkingColorSpace(this,r),this}setStyle(e,t=n){let i;function r(t){void 0!==t&&1>parseFloat(t)&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let a;let n=i[1],s=i[2];switch(n){case"rgb":case"rgba":if(a=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return r(a[4]),this.setRGB(Math.min(255,parseInt(a[1],10))/255,Math.min(255,parseInt(a[2],10))/255,Math.min(255,parseInt(a[3],10))/255,t);if(a=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return r(a[4]),this.setRGB(Math.min(100,parseInt(a[1],10))/100,Math.min(100,parseInt(a[2],10))/100,Math.min(100,parseInt(a[3],10))/100,t);break;case"hsl":case"hsla":if(a=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(s))return r(a[4]),this.setHSL(parseFloat(a[1])/360,parseFloat(a[2])/100,parseFloat(a[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){let r=i[1],a=r.length;if(3===a)return this.setRGB(parseInt(r.charAt(0),16)/15,parseInt(r.charAt(1),16)/15,parseInt(r.charAt(2),16)/15,t);if(6===a)return this.setHex(parseInt(r,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=n){let i=e6[e.toLowerCase()];return void 0!==i?this.setHex(i,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=E(e.r),this.g=E(e.g),this.b=E(e.b),this}copyLinearToSRGB(e){return this.r=A(e.r),this.g=A(e.g),this.b=A(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=n){return D.fromWorkingColorSpace(tt.copy(this),e),65536*Math.round(f(255*tt.r,0,255))+256*Math.round(f(255*tt.g,0,255))+Math.round(f(255*tt.b,0,255))}getHexString(e=n){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=D.workingColorSpace){let i,r;D.fromWorkingColorSpace(tt.copy(this),t);let a=tt.r,n=tt.g,s=tt.b,o=Math.max(a,n,s),l=Math.min(a,n,s),h=(l+o)/2;if(l===o)i=0,r=0;else{let e=o-l;switch(r=h<=.5?e/(o+l):e/(2-o-l),o){case a:i=(n-s)/e+(n0&&(e.userData=this.userData),void 0!==this.parameters){let t=this.parameters;for(let i in t)void 0!==t[i]&&(e[i]=t[i]);return e}e.data={attributes:{}};let t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});let i=this.attributes;for(let t in i){let r=i[t];e.data.attributes[t]=r.toJSON(e.data)}let r={},a=!1;for(let t in this.morphAttributes){let i=this.morphAttributes[t],n=[];for(let t=0,r=i.length;t0&&(r[t]=n,a=!0)}a&&(e.data.morphAttributes=r,e.data.morphTargetsRelative=this.morphTargetsRelative);let n=this.groups;n.length>0&&(e.data.groups=JSON.parse(JSON.stringify(n)));let s=this.boundingSphere;return null!==s&&(e.data.boundingSphere={center:s.center.toArray(),radius:s.radius}),e}clone(){return new this.constructor().copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;let t={};this.name=e.name;let i=e.index;null!==i&&this.setIndex(i.clone(t));let r=e.attributes;for(let e in r){let i=r[e];this.setAttribute(e,i.clone(t))}let a=e.morphAttributes;for(let e in a){let i=[],r=a[e];for(let e=0,a=r.length;e0){let e=t[i[0]];if(void 0!==e){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,i=e.length;t(e.far-e.near)**2)||(tv.copy(a).invert(),t_.copy(e.ray).applyMatrix4(tv),null!==i.boundingBox&&!1===t_.intersectsBox(i.boundingBox)))return;this._computeIntersections(e,t,t_)}}_computeIntersections(e,t,i){let r;let a=this.geometry,n=this.material,s=a.index,o=a.attributes.position,l=a.attributes.uv,h=a.attributes.uv1,c=a.attributes.normal,u=a.groups,d=a.drawRange;if(null!==s){if(Array.isArray(n))for(let a=0,o=u.length;ai.far?null:{distance:l,point:tI.clone(),object:e}}(e,t,i,r,tM,tS,tb,tD);if(c){a&&(tE.fromBufferAttribute(a,o),tA.fromBufferAttribute(a,l),tC.fromBufferAttribute(a,h),c.uv=e2.getInterpolation(tD,tM,tS,tb,tE,tA,tC,new x)),n&&(tE.fromBufferAttribute(n,o),tA.fromBufferAttribute(n,l),tC.fromBufferAttribute(n,h),c.uv1=e2.getInterpolation(tD,tM,tS,tb,tE,tA,tC,new x),c.uv2=c.uv1),s&&(tL.fromBufferAttribute(s,o),tP.fromBufferAttribute(s,l),tR.fromBufferAttribute(s,h),c.normal=e2.getInterpolation(tD,tM,tS,tb,tL,tP,tR,new W),c.normal.dot(r.direction)>0&&c.normal.multiplyScalar(-1));let e={a:o,b:l,c:h,normal:new W,materialIndex:0};e2.getNormal(tM,tS,tb,e.normal),c.face=e}return c}class tN extends tg{constructor(e=1,t=1,i=1,r=1,a=1,n=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:i,widthSegments:r,heightSegments:a,depthSegments:n};let s=this;r=Math.floor(r),a=Math.floor(a),n=Math.floor(n);let o=[],l=[],h=[],c=[],u=0,d=0;function p(e,t,i,r,a,n,p,f,m,g,v){let _=n/m,x=p/g,y=n/2,M=p/2,S=f/2,b=m+1,w=g+1,T=0,E=0,A=new W;for(let n=0;n0?1:-1,h.push(A.x,A.y,A.z),c.push(o/m),c.push(1-n/g),T+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;let i={};for(let e in this.extensions)!0===this.extensions[e]&&(i[e]=!0);return Object.keys(i).length>0&&(t.extensions=i),t}}class tV extends ej{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new ey,this.projectionMatrix=new ey,this.projectionMatrixInverse=new ey,this.coordinateSystem=2e3}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){this.updateWorldMatrix(!0,!1);let t=this.matrixWorld.elements;return e.set(-t[8],-t[9],-t[10]).normalize()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return new this.constructor().copy(this)}}class tG extends tV{constructor(e=50,t=1,i=.1,r=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=i,this.far=r,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){let t=.5*this.getFilmHeight()/e;this.fov=2*d*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){let e=Math.tan(.5*u*this.fov);return .5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*d*Math.atan(Math.tan(.5*u*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}setViewOffset(e,t,i,r,a,n){this.aspect=e/t,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=i,this.view.offsetY=r,this.view.width=a,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){let e=this.near,t=e*Math.tan(.5*u*this.fov)/this.zoom,i=2*t,r=this.aspect*i,a=-.5*r,n=this.view;if(null!==this.view&&this.view.enabled){let e=n.fullWidth,s=n.fullHeight;a+=n.offsetX*r/e,t-=n.offsetY*i/s,r*=n.width/e,i*=n.height/s}let s=this.filmOffset;0!==s&&(a+=e*s/this.getFilmWidth()),this.projectionMatrix.makePerspective(a,a+r,t,t-i,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){let t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}class tW extends ej{constructor(e,t,i){super(),this.type="CubeCamera",this.renderTarget=i,this.coordinateSystem=null;let r=new tG(-90,1,e,t);r.layers=this.layers,this.add(r);let a=new tG(-90,1,e,t);a.layers=this.layers,this.add(a);let n=new tG(-90,1,e,t);n.layers=this.layers,this.add(n);let s=new tG(-90,1,e,t);s.layers=this.layers,this.add(s);let o=new tG(-90,1,e,t);o.layers=this.layers,this.add(o);let l=new tG(-90,1,e,t);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){let e=this.coordinateSystem,t=this.children.concat(),[i,r,a,n,s,o]=t;for(let e of t)this.remove(e);if(2e3===e)i.up.set(0,1,0),i.lookAt(1,0,0),r.up.set(0,1,0),r.lookAt(-1,0,0),a.up.set(0,0,-1),a.lookAt(0,1,0),n.up.set(0,0,1),n.lookAt(0,-1,0),s.up.set(0,1,0),s.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else if(2001===e)i.up.set(0,-1,0),i.lookAt(-1,0,0),r.up.set(0,-1,0),r.lookAt(1,0,0),a.up.set(0,0,1),a.lookAt(0,1,0),n.up.set(0,0,-1),n.lookAt(0,-1,0),s.up.set(0,-1,0),s.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1);else throw Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);for(let e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();let i=this.renderTarget;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());let[r,a,n,s,o,l]=this.children,h=e.getRenderTarget(),c=e.xr.enabled;e.xr.enabled=!1;let u=i.texture.generateMipmaps;i.texture.generateMipmaps=!1,e.setRenderTarget(i,0),e.render(t,r),e.setRenderTarget(i,1),e.render(t,a),e.setRenderTarget(i,2),e.render(t,n),e.setRenderTarget(i,3),e.render(t,s),e.setRenderTarget(i,4),e.render(t,o),i.texture.generateMipmaps=u,e.setRenderTarget(i,5),e.render(t,l),e.setRenderTarget(h),e.xr.enabled=c,i.texture.needsPMREMUpdate=!0}}class tj extends F{constructor(e,t,i,r,a,n,s,o,l,h){super(e=void 0!==e?e:[],t=void 0!==t?t:301,i,r,a,n,s,o,l,h),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class tq extends H{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;let i={width:e,height:e,depth:1};void 0!==t.encoding&&(T("THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace."),t.colorSpace=3001===t.encoding?n:""),this.texture=new tj([i,i,i,i,i,i],t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:1006}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;let i={uniforms:{tEquirect:{value:null}},vertexShader:`varying vec3 vWorldDirection;vec3 transformDirection(in vec3 dir,in mat4 matrix){return normalize((matrix*vec4(dir,0.0)).xyz);}void main(){vWorldDirection=transformDirection(position,modelMatrix); +#include +#include +}`,fragmentShader:`uniform sampler2D tEquirect;varying vec3 vWorldDirection; +#include +void main(){vec3 direction=normalize(vWorldDirection);vec2 sampleUV=equirectUv(direction);gl_FragColor=texture2D(tEquirect,sampleUV);}`},r=new tN(5,5,5),a=new tH({name:"CubemapFromEquirect",uniforms:tz(i.uniforms),vertexShader:i.vertexShader,fragmentShader:i.fragmentShader,side:1,blending:0});a.uniforms.tEquirect.value=t;let n=new tU(r,a),s=t.minFilter;1008===t.minFilter&&(t.minFilter=1006);let o=new tW(1,10,this);return o.update(e,n),t.minFilter=s,n.geometry.dispose(),n.material.dispose(),this}clear(e,t,i,r){let a=e.getRenderTarget();for(let a=0;a<6;a++)e.setRenderTarget(this,a),e.clear(t,i,r);e.setRenderTarget(a)}}let tX=new W,tY=new W,tZ=new y;class tK{constructor(e=new W(1,0,0),t=0){this.isPlane=!0,this.normal=e,this.constant=t}set(e,t){return this.normal.copy(e),this.constant=t,this}setComponents(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this}setFromNormalAndCoplanarPoint(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this}setFromCoplanarPoints(e,t,i){let r=tX.subVectors(i,t).cross(tY.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(r,e),this}copy(e){return this.normal.copy(e.normal),this.constant=e.constant,this}normalize(){let e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this}negate(){return this.constant*=-1,this.normal.negate(),this}distanceToPoint(e){return this.normal.dot(e)+this.constant}distanceToSphere(e){return this.distanceToPoint(e.center)-e.radius}projectPoint(e,t){return t.copy(e).addScaledVector(this.normal,-this.distanceToPoint(e))}intersectLine(e,t){let i=e.delta(tX),r=this.normal.dot(i);if(0===r)return 0===this.distanceToPoint(e.start)?t.copy(e.start):null;let a=-(e.start.dot(this.normal)+this.constant)/r;return a<0||a>1?null:t.copy(e.start).addScaledVector(i,a)}intersectsLine(e){let t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){let i=t||tZ.getNormalMatrix(e),r=this.coplanarPoint(tX).applyMatrix4(e),a=this.normal.applyMatrix3(i).normalize();return this.constant=-r.dot(a),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return new this.constructor().copy(this)}}let tJ=new eu,tQ=new W;class t${constructor(e=new tK,t=new tK,i=new tK,r=new tK,a=new tK,n=new tK){this.planes=[e,t,i,r,a,n]}set(e,t,i,r,a,n){let s=this.planes;return s[0].copy(e),s[1].copy(t),s[2].copy(i),s[3].copy(r),s[4].copy(a),s[5].copy(n),this}copy(e){let t=this.planes;for(let i=0;i<6;i++)t[i].copy(e.planes[i]);return this}setFromProjectionMatrix(e,t=2e3){let i=this.planes,r=e.elements,a=r[0],n=r[1],s=r[2],o=r[3],l=r[4],h=r[5],c=r[6],u=r[7],d=r[8],p=r[9],f=r[10],m=r[11],g=r[12],v=r[13],_=r[14],x=r[15];if(i[0].setComponents(o-a,u-l,m-d,x-g).normalize(),i[1].setComponents(o+a,u+l,m+d,x+g).normalize(),i[2].setComponents(o+n,u+h,m+p,x+v).normalize(),i[3].setComponents(o-n,u-h,m-p,x-v).normalize(),i[4].setComponents(o-s,u-c,m-f,x-_).normalize(),2e3===t)i[5].setComponents(o+s,u+c,m+f,x+_).normalize();else if(2001===t)i[5].setComponents(s,c,f,_).normalize();else throw Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),tJ.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{let t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),tJ.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(tJ)}intersectsSprite(e){return tJ.center.set(0,0,0),tJ.radius=.7071067811865476,tJ.applyMatrix4(e.matrixWorld),this.intersectsSphere(tJ)}intersectsSphere(e){let t=this.planes,i=e.center,r=-e.radius;for(let e=0;e<6;e++){let a=t[e].distanceToPoint(i);if(a0?e.max.x:e.min.x,tQ.y=r.normal.y>0?e.max.y:e.min.y,tQ.z=r.normal.z>0?e.max.z:e.min.z,0>r.distanceToPoint(tQ))return!1}return!0}containsPoint(e){let t=this.planes;for(let i=0;i<6;i++)if(0>t[i].distanceToPoint(e))return!1;return!0}clone(){return new this.constructor().copy(this)}}function t0(){let e=null,t=!1,i=null,r=null;function a(t,n){i(t,n),r=e.requestAnimationFrame(a)}return{start:function(){!0!==t&&null!==i&&(r=e.requestAnimationFrame(a),t=!0)},stop:function(){e.cancelAnimationFrame(r),t=!1},setAnimationLoop:function(e){i=e},setContext:function(t){e=t}}}function t1(e,t){let i=t.isWebGL2,r=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),r.get(e)},remove:function(t){t.isInterleavedBufferAttribute&&(t=t.data);let i=r.get(t);i&&(e.deleteBuffer(i.buffer),r.delete(t))},update:function(t,a){if(t.isGLBufferAttribute){let e=r.get(t);(!e||e.version0 +vec4 plane; +#pragma unroll_loop_start +for(int i=0;iplane.w)discard;} +#pragma unroll_loop_end +#if UNION_CLIPPING_PLANESplane.w)&&clipped;} +#pragma unroll_loop_end +if(clipped)discard; +#endif +#endif`,io=`#if NUM_CLIPPING_PLANES>0 +varying vec3 vClipPosition;uniform vec4 clippingPlanes[NUM_CLIPPING_PLANES]; +#endif`,il=`#if NUM_CLIPPING_PLANES>0 +varying vec3 vClipPosition; +#endif`,ih=`#if NUM_CLIPPING_PLANES>0 +vClipPosition=-mvPosition.xyz; +#endif`,ic=`#if defined(USE_COLOR_ALPHA) +diffuseColor*=vColor; +#elif defined(USE_COLOR) +diffuseColor.rgb*=vColor; +#endif`,iu=`#if defined(USE_COLOR_ALPHA) +varying vec4 vColor; +#elif defined(USE_COLOR) +varying vec3 vColor; +#endif`,id=`#if defined(USE_COLOR_ALPHA) +varying vec4 vColor; +#elif defined(USE_COLOR)||defined(USE_INSTANCING_COLOR) +varying vec3 vColor; +#endif`,ip=`#if defined(USE_COLOR_ALPHA) +vColor=vec4(1.0); +#elif defined(USE_COLOR)||defined(USE_INSTANCING_COLOR) +vColor=vec3(1.0); +#endif +#ifdef USE_COLOR +vColor*=color; +#endif +#ifdef USE_INSTANCING_COLOR +vColor.xyz*=instanceColor.xyz; +#endif`,im=`#define PI 3.141592653589793 +#define PI2 6.283185307179586 +#define PI_HALF 1.5707963267948966 +#define RECIPROCAL_PI 0.3183098861837907 +#define RECIPROCAL_PI2 0.15915494309189535 +#define EPSILON 1e-6 +#ifndef saturate +#define saturate(a)clamp(a,0.0,1.0) +#endif +#define whiteComplement(a)(1.0-saturate(a)) +float pow2(const in float x){return x*x;}vec3 pow2(const in vec3 x){return x*x;}float pow3(const in float x){return x*x*x;}float pow4(const in float x){float x2=x*x;return x2*x2;}float max3(const in vec3 v){return max(max(v.x,v.y),v.z);}float average(const in vec3 v){return dot(v,vec3(0.3333333));}highp float rand(const in vec2 uv){const highp float a=12.9898,b=78.233,c=43758.5453;highp float dt=dot(uv.xy,vec2(a,b)),sn=mod(dt,PI);return fract(sin(sn)*c);} +#ifdef HIGH_PRECISION +float precisionSafeLength(vec3 v){return length(v);} +#else +float precisionSafeLength(vec3 v){float maxComponent=max3(abs(v));return length(v/maxComponent)*maxComponent;} +#endif +struct IncidentLight{vec3 color;vec3 direction;bool visible;};struct ReflectedLight{vec3 directDiffuse;vec3 directSpecular;vec3 indirectDiffuse;vec3 indirectSpecular;};struct GeometricContext{vec3 position;vec3 normal;vec3 viewDir; +#ifdef USE_CLEARCOAT +vec3 clearcoatNormal; +#endif +}; +#ifdef USE_ALPHAHASH +varying vec3 vPosition; +#endif +vec3 transformDirection(in vec3 dir,in mat4 matrix){return normalize((matrix*vec4(dir,0.0)).xyz);}vec3 inverseTransformDirection(in vec3 dir,in mat4 matrix){return normalize((vec4(dir,0.0)*matrix).xyz);}mat3 transposeMat3(const in mat3 m){mat3 tmp;tmp[0]=vec3(m[0].x,m[1].x,m[2].x);tmp[1]=vec3(m[0].y,m[1].y,m[2].y);tmp[2]=vec3(m[0].z,m[1].z,m[2].z);return tmp;}float luminance(const in vec3 rgb){const vec3 weights=vec3(0.2126729,0.7151522,0.0721750);return dot(weights,rgb);}bool isPerspectiveMatrix(mat4 m){return m[2][3]==-1.0;}vec2 equirectUv(in vec3 dir){float u=atan(dir.z,dir.x)*RECIPROCAL_PI2+0.5;float v=asin(clamp(dir.y,-1.0,1.0))*RECIPROCAL_PI+0.5;return vec2(u,v);}vec3 BRDF_Lambert(const in vec3 diffuseColor){return RECIPROCAL_PI*diffuseColor;}vec3 F_Schlick(const in vec3 f0,const in float f90,const in float dotVH){float fresnel=exp2((-5.55473*dotVH-6.98316)*dotVH);return f0*(1.0-fresnel)+(f90*fresnel);}float F_Schlick(const in float f0,const in float f90,const in float dotVH){float fresnel=exp2((-5.55473*dotVH-6.98316)*dotVH);return f0*(1.0-fresnel)+(f90*fresnel);}`,ig=`#ifdef ENVMAP_TYPE_CUBE_UV +#define cubeUV_minMipLevel 4.0 +#define cubeUV_minTileSize 16.0 +float getFace(vec3 direction){vec3 absDirection=abs(direction);float face=-1.0;if(absDirection.x>absDirection.z){if(absDirection.x>absDirection.y)face=direction.x>0.0?0.0:3.0;else face=direction.y>0.0?1.0:4.0;}else{if(absDirection.z>absDirection.y)face=direction.z>0.0?2.0:5.0;else face=direction.y>0.0?1.0:4.0;}return face;}vec2 getUV(vec3 direction,float face){vec2 uv;if(face==0.0){uv=vec2(direction.z,direction.y)/abs(direction.x);}else if(face==1.0){uv=vec2(-direction.x,-direction.z)/abs(direction.y);}else if(face==2.0){uv=vec2(-direction.x,direction.y)/abs(direction.z);}else if(face==3.0){uv=vec2(-direction.z,direction.y)/abs(direction.x);}else if(face==4.0){uv=vec2(-direction.x,direction.z)/abs(direction.y);}else{uv=vec2(direction.x,direction.y)/abs(direction.z);}return 0.5*(uv+1.0);}vec3 bilinearCubeUV(sampler2D envMap,vec3 direction,float mipInt){float face=getFace(direction);float filterInt=max(cubeUV_minMipLevel-mipInt,0.0);mipInt=max(mipInt,cubeUV_minMipLevel);float faceSize=exp2(mipInt);highp vec2 uv=getUV(direction,face)*(faceSize-2.0)+1.0;if(face>2.0){uv.y+=faceSize;face-=3.0;}uv.x+=face*faceSize;uv.x+=filterInt*3.0*cubeUV_minTileSize;uv.y+=4.0*(exp2(CUBEUV_MAX_MIP)-faceSize);uv.x*=CUBEUV_TEXEL_WIDTH;uv.y*=CUBEUV_TEXEL_HEIGHT; +#ifdef texture2DGradEXT +return texture2DGradEXT(envMap,uv,vec2(0.0),vec2(0.0)).rgb; +#else +return texture2D(envMap,uv).rgb; +#endif +} +#define cubeUV_r0 1.0 +#define cubeUV_v0 0.339 +#define cubeUV_m0-2.0 +#define cubeUV_r1 0.8 +#define cubeUV_v1 0.276 +#define cubeUV_m1-1.0 +#define cubeUV_r4 0.4 +#define cubeUV_v4 0.046 +#define cubeUV_m4 2.0 +#define cubeUV_r5 0.305 +#define cubeUV_v5 0.016 +#define cubeUV_m5 3.0 +#define cubeUV_r6 0.21 +#define cubeUV_v6 0.0038 +#define cubeUV_m6 4.0 +float roughnessToMip(float roughness){float mip=0.0;if(roughness>=cubeUV_r1){mip=(cubeUV_r0-roughness)*(cubeUV_m1-cubeUV_m0)/(cubeUV_r0-cubeUV_r1)+cubeUV_m0;}else if(roughness>=cubeUV_r4){mip=(cubeUV_r1-roughness)*(cubeUV_m4-cubeUV_m1)/(cubeUV_r1-cubeUV_r4)+cubeUV_m1;}else if(roughness>=cubeUV_r5){mip=(cubeUV_r4-roughness)*(cubeUV_m5-cubeUV_m4)/(cubeUV_r4-cubeUV_r5)+cubeUV_m4;}else if(roughness>=cubeUV_r6){mip=(cubeUV_r5-roughness)*(cubeUV_m6-cubeUV_m5)/(cubeUV_r5-cubeUV_r6)+cubeUV_m5;}else{mip=-2.0*log2(1.16*roughness);}return mip;}vec4 textureCubeUV(sampler2D envMap,vec3 sampleDir,float roughness){float mip=clamp(roughnessToMip(roughness),cubeUV_m0,CUBEUV_MAX_MIP);float mipF=fract(mip);float mipInt=floor(mip);vec3 color0=bilinearCubeUV(envMap,sampleDir,mipInt);if(mipF==0.0){return vec4(color0,1.0);}else{vec3 color1=bilinearCubeUV(envMap,sampleDir,mipInt+1.0);return vec4(mix(color0,color1,mipF),1.0);}} +#endif`,iv=`vec3 transformedNormal=objectNormal; +#ifdef USE_INSTANCING +mat3 m=mat3(instanceMatrix);transformedNormal/=vec3(dot(m[0],m[0]),dot(m[1],m[1]),dot(m[2],m[2]));transformedNormal=m*transformedNormal; +#endif +transformedNormal=normalMatrix*transformedNormal; +#ifdef FLIP_SIDED +transformedNormal=-transformedNormal; +#endif +#ifdef USE_TANGENT +vec3 transformedTangent=(modelViewMatrix*vec4(objectTangent,0.0)).xyz; +#ifdef FLIP_SIDED +transformedTangent=-transformedTangent; +#endif +#endif`,i_=`#ifdef USE_DISPLACEMENTMAP +uniform sampler2D displacementMap;uniform float displacementScale;uniform float displacementBias; +#endif`,ix=`#ifdef USE_DISPLACEMENTMAP +transformed+=normalize(objectNormal)*(texture2D(displacementMap,vDisplacementMapUv).x*displacementScale+displacementBias); +#endif`,iy=`#ifdef USE_EMISSIVEMAP +vec4 emissiveColor=texture2D(emissiveMap,vEmissiveMapUv);totalEmissiveRadiance*=emissiveColor.rgb; +#endif`,iM=`#ifdef USE_EMISSIVEMAP +uniform sampler2D emissiveMap; +#endif`,iS=`#ifdef USE_ENVMAP +#ifdef ENV_WORLDPOS +vec3 cameraToFrag;if(isOrthographic){cameraToFrag=normalize(vec3(-viewMatrix[0][2],-viewMatrix[1][2],-viewMatrix[2][2]));}else{cameraToFrag=normalize(vWorldPosition-cameraPosition);}vec3 worldNormal=inverseTransformDirection(normal,viewMatrix); +#ifdef ENVMAP_MODE_REFLECTION +vec3 reflectVec=reflect(cameraToFrag,worldNormal); +#else +vec3 reflectVec=refract(cameraToFrag,worldNormal,refractionRatio); +#endif +#else +vec3 reflectVec=vReflect; +#endif +#ifdef ENVMAP_TYPE_CUBE +vec4 envColor=textureCube(envMap,vec3(flipEnvMap*reflectVec.x,reflectVec.yz)); +#else +vec4 envColor=vec4(0.0); +#endif +#ifdef ENVMAP_BLENDING_MULTIPLY +outgoingLight=mix(outgoingLight,outgoingLight*envColor.xyz,specularStrength*reflectivity); +#elif defined(ENVMAP_BLENDING_MIX) +outgoingLight=mix(outgoingLight,envColor.xyz,specularStrength*reflectivity); +#elif defined(ENVMAP_BLENDING_ADD) +outgoingLight+=envColor.xyz*specularStrength*reflectivity; +#endif +#endif`,ib=`#ifdef USE_ENVMAP +uniform float envMapIntensity;uniform float flipEnvMap; +#ifdef ENVMAP_TYPE_CUBE +uniform samplerCube envMap; +#else +uniform sampler2D envMap; +#endif +#endif`,iw=`#ifdef USE_ENVMAP +uniform float reflectivity; +#if defined(USE_BUMPMAP)||defined(USE_NORMALMAP)||defined(PHONG)||defined(LAMBERT) +#define ENV_WORLDPOS +#endif +#ifdef ENV_WORLDPOS +varying vec3 vWorldPosition;uniform float refractionRatio; +#else +varying vec3 vReflect; +#endif +#endif`,iT=`#ifdef USE_ENVMAP +#if defined(USE_BUMPMAP)||defined(USE_NORMALMAP)||defined(PHONG)||defined(LAMBERT) +#define ENV_WORLDPOS +#endif +#ifdef ENV_WORLDPOS +varying vec3 vWorldPosition; +#else +varying vec3 vReflect;uniform float refractionRatio; +#endif +#endif`,iE=`#ifdef USE_ENVMAP +#ifdef ENV_WORLDPOS +vWorldPosition=worldPosition.xyz; +#else +vec3 cameraToVertex;if(isOrthographic){cameraToVertex=normalize(vec3(-viewMatrix[0][2],-viewMatrix[1][2],-viewMatrix[2][2]));}else{cameraToVertex=normalize(worldPosition.xyz-cameraPosition);}vec3 worldNormal=inverseTransformDirection(transformedNormal,viewMatrix); +#ifdef ENVMAP_MODE_REFLECTION +vReflect=reflect(cameraToVertex,worldNormal); +#else +vReflect=refract(cameraToVertex,worldNormal,refractionRatio); +#endif +#endif +#endif`,iA=`#ifdef USE_FOG +vFogDepth=-mvPosition.z; +#endif`,iC=`#ifdef USE_FOG +varying float vFogDepth; +#endif`,iL=`#ifdef USE_FOG +#ifdef FOG_EXP2 +float fogFactor=1.0-exp(-fogDensity*fogDensity*vFogDepth*vFogDepth); +#else +float fogFactor=smoothstep(fogNear,fogFar,vFogDepth); +#endif +gl_FragColor.rgb=mix(gl_FragColor.rgb,fogColor,fogFactor); +#endif`,iP=`#ifdef USE_FOG +uniform vec3 fogColor;varying float vFogDepth; +#ifdef FOG_EXP2 +uniform float fogDensity; +#else +uniform float fogNear;uniform float fogFar; +#endif +#endif`,iR=`#ifdef USE_GRADIENTMAP +uniform sampler2D gradientMap; +#endif +vec3 getGradientIrradiance(vec3 normal,vec3 lightDirection){float dotNL=dot(normal,lightDirection);vec2 coord=vec2(dotNL*0.5+0.5,0.0); +#ifdef USE_GRADIENTMAP +return vec3(texture2D(gradientMap,coord).r); +#else +vec2 fw=fwidth(coord)*0.5;return mix(vec3(0.7),vec3(1.0),smoothstep(0.7-fw.x,0.7+fw.x,coord.x)); +#endif +}`,iD=`#ifdef USE_LIGHTMAP +vec4 lightMapTexel=texture2D(lightMap,vLightMapUv);vec3 lightMapIrradiance=lightMapTexel.rgb*lightMapIntensity;reflectedLight.indirectDiffuse+=lightMapIrradiance; +#endif`,iI=`#ifdef USE_LIGHTMAP +uniform sampler2D lightMap;uniform float lightMapIntensity; +#endif`,iU=`varying vec3 vViewPosition;struct LambertMaterial{vec3 diffuseColor;float specularStrength;};void RE_Direct_Lambert(const in IncidentLight directLight,const in GeometricContext geometry,const in LambertMaterial material,inout ReflectedLight reflectedLight){float dotNL=saturate(dot(geometry.normal,directLight.direction));vec3 irradiance=dotNL*directLight.color;reflectedLight.directDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);}void RE_IndirectDiffuse_Lambert(const in vec3 irradiance,const in GeometricContext geometry,const in LambertMaterial material,inout ReflectedLight reflectedLight){reflectedLight.indirectDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);} +#define RE_Direct RE_Direct_Lambert +#define RE_IndirectDiffuse RE_IndirectDiffuse_Lambert`,iO=`uniform bool receiveShadow;uniform vec3 ambientLightColor;uniform vec3 lightProbe[9];vec3 shGetIrradianceAt(in vec3 normal,in vec3 shCoefficients[9]){float x=normal.x,y=normal.y,z=normal.z;vec3 result=shCoefficients[0]*0.886227;result+=shCoefficients[1]*2.0*0.511664*y;result+=shCoefficients[2]*2.0*0.511664*z;result+=shCoefficients[3]*2.0*0.511664*x;result+=shCoefficients[4]*2.0*0.429043*x*y;result+=shCoefficients[5]*2.0*0.429043*y*z;result+=shCoefficients[6]*(0.743125*z*z-0.247708);result+=shCoefficients[7]*2.0*0.429043*x*z;result+=shCoefficients[8]*0.429043*(x*x-y*y);return result;}vec3 getLightProbeIrradiance(const in vec3 lightProbe[9],const in vec3 normal){vec3 worldNormal=inverseTransformDirection(normal,viewMatrix);vec3 irradiance=shGetIrradianceAt(worldNormal,lightProbe);return irradiance;}vec3 getAmbientLightIrradiance(const in vec3 ambientLightColor){vec3 irradiance=ambientLightColor;return irradiance;}float getDistanceAttenuation(const in float lightDistance,const in float cutoffDistance,const in float decayExponent){ +#if defined(LEGACY_LIGHTS) +if(cutoffDistance>0.0&&decayExponent>0.0){return pow(saturate(-lightDistance/cutoffDistance+1.0),decayExponent);}return 1.0; +#else +float distanceFalloff=1.0/max(pow(lightDistance,decayExponent),0.01);if(cutoffDistance>0.0){distanceFalloff*=pow2(saturate(1.0-pow4(lightDistance/cutoffDistance)));}return distanceFalloff; +#endif +}float getSpotAttenuation(const in float coneCosine,const in float penumbraCosine,const in float angleCosine){return smoothstep(coneCosine,penumbraCosine,angleCosine);} +#if NUM_DIR_LIGHTS>0 +struct DirectionalLight{vec3 direction;vec3 color;};uniform DirectionalLight directionalLights[NUM_DIR_LIGHTS];void getDirectionalLightInfo(const in DirectionalLight directionalLight,const in GeometricContext geometry,out IncidentLight light){light.color=directionalLight.color;light.direction=directionalLight.direction;light.visible=true;} +#endif +#if NUM_POINT_LIGHTS>0 +struct PointLight{vec3 position;vec3 color;float distance;float decay;};uniform PointLight pointLights[NUM_POINT_LIGHTS];void getPointLightInfo(const in PointLight pointLight,const in GeometricContext geometry,out IncidentLight light){vec3 lVector=pointLight.position-geometry.position;light.direction=normalize(lVector);float lightDistance=length(lVector);light.color=pointLight.color;light.color*=getDistanceAttenuation(lightDistance,pointLight.distance,pointLight.decay);light.visible=(light.color!=vec3(0.0));} +#endif +#if NUM_SPOT_LIGHTS>0 +struct SpotLight{vec3 position;vec3 direction;vec3 color;float distance;float decay;float coneCos;float penumbraCos;};uniform SpotLight spotLights[NUM_SPOT_LIGHTS];void getSpotLightInfo(const in SpotLight spotLight,const in GeometricContext geometry,out IncidentLight light){vec3 lVector=spotLight.position-geometry.position;light.direction=normalize(lVector);float angleCos=dot(light.direction,spotLight.direction);float spotAttenuation=getSpotAttenuation(spotLight.coneCos,spotLight.penumbraCos,angleCos);if(spotAttenuation>0.0){float lightDistance=length(lVector);light.color=spotLight.color*spotAttenuation;light.color*=getDistanceAttenuation(lightDistance,spotLight.distance,spotLight.decay);light.visible=(light.color!=vec3(0.0));}else{light.color=vec3(0.0);light.visible=false;}} +#endif +#if NUM_RECT_AREA_LIGHTS>0 +struct RectAreaLight{vec3 color;vec3 position;vec3 halfWidth;vec3 halfHeight;};uniform sampler2D ltc_1;uniform sampler2D ltc_2;uniform RectAreaLight rectAreaLights[NUM_RECT_AREA_LIGHTS]; +#endif +#if NUM_HEMI_LIGHTS>0 +struct HemisphereLight{vec3 direction;vec3 skyColor;vec3 groundColor;};uniform HemisphereLight hemisphereLights[NUM_HEMI_LIGHTS];vec3 getHemisphereLightIrradiance(const in HemisphereLight hemiLight,const in vec3 normal){float dotNL=dot(normal,hemiLight.direction);float hemiDiffuseWeight=0.5*dotNL+0.5;vec3 irradiance=mix(hemiLight.groundColor,hemiLight.skyColor,hemiDiffuseWeight);return irradiance;} +#endif`,iN=`#ifdef USE_ENVMAP +vec3 getIBLIrradiance(const in vec3 normal){ +#ifdef ENVMAP_TYPE_CUBE_UV +vec3 worldNormal=inverseTransformDirection(normal,viewMatrix);vec4 envMapColor=textureCubeUV(envMap,worldNormal,1.0);return PI*envMapColor.rgb*envMapIntensity; +#else +return vec3(0.0); +#endif +}vec3 getIBLRadiance(const in vec3 viewDir,const in vec3 normal,const in float roughness){ +#ifdef ENVMAP_TYPE_CUBE_UV +vec3 reflectVec=reflect(-viewDir,normal);reflectVec=normalize(mix(reflectVec,normal,roughness*roughness));reflectVec=inverseTransformDirection(reflectVec,viewMatrix);vec4 envMapColor=textureCubeUV(envMap,reflectVec,roughness);return envMapColor.rgb*envMapIntensity; +#else +return vec3(0.0); +#endif +} +#ifdef USE_ANISOTROPY +vec3 getIBLAnisotropyRadiance(const in vec3 viewDir,const in vec3 normal,const in float roughness,const in vec3 bitangent,const in float anisotropy){ +#ifdef ENVMAP_TYPE_CUBE_UV +vec3 bentNormal=cross(bitangent,viewDir);bentNormal=normalize(cross(bentNormal,bitangent));bentNormal=normalize(mix(bentNormal,normal,pow2(pow2(1.0-anisotropy*(1.0-roughness)))));return getIBLRadiance(viewDir,bentNormal,roughness); +#else +return vec3(0.0); +#endif +} +#endif +#endif`,iz=`varying vec3 vViewPosition;struct ToonMaterial{vec3 diffuseColor;};void RE_Direct_Toon(const in IncidentLight directLight,const in GeometricContext geometry,const in ToonMaterial material,inout ReflectedLight reflectedLight){vec3 irradiance=getGradientIrradiance(geometry.normal,directLight.direction)*directLight.color;reflectedLight.directDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);}void RE_IndirectDiffuse_Toon(const in vec3 irradiance,const in GeometricContext geometry,const in ToonMaterial material,inout ReflectedLight reflectedLight){reflectedLight.indirectDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);} +#define RE_Direct RE_Direct_Toon +#define RE_IndirectDiffuse RE_IndirectDiffuse_Toon`,iF=`varying vec3 vViewPosition;struct BlinnPhongMaterial{vec3 diffuseColor;vec3 specularColor;float specularShininess;float specularStrength;};void RE_Direct_BlinnPhong(const in IncidentLight directLight,const in GeometricContext geometry,const in BlinnPhongMaterial material,inout ReflectedLight reflectedLight){float dotNL=saturate(dot(geometry.normal,directLight.direction));vec3 irradiance=dotNL*directLight.color;reflectedLight.directDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);reflectedLight.directSpecular+=irradiance*BRDF_BlinnPhong(directLight.direction,geometry.viewDir,geometry.normal,material.specularColor,material.specularShininess)*material.specularStrength;}void RE_IndirectDiffuse_BlinnPhong(const in vec3 irradiance,const in GeometricContext geometry,const in BlinnPhongMaterial material,inout ReflectedLight reflectedLight){reflectedLight.indirectDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);} +#define RE_Direct RE_Direct_BlinnPhong +#define RE_IndirectDiffuse RE_IndirectDiffuse_BlinnPhong`,ik=`PhysicalMaterial material;material.diffuseColor=diffuseColor.rgb*(1.0-metalnessFactor);vec3 dxy=max(abs(dFdx(geometryNormal)),abs(dFdy(geometryNormal)));float geometryRoughness=max(max(dxy.x,dxy.y),dxy.z);material.roughness=max(roughnessFactor,0.0525);material.roughness+=geometryRoughness;material.roughness=min(material.roughness,1.0); +#ifdef IOR +material.ior=ior; +#ifdef USE_SPECULAR +float specularIntensityFactor=specularIntensity;vec3 specularColorFactor=specularColor; +#ifdef USE_SPECULAR_COLORMAP +specularColorFactor*=texture2D(specularColorMap,vSpecularColorMapUv).rgb; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP +specularIntensityFactor*=texture2D(specularIntensityMap,vSpecularIntensityMapUv).a; +#endif +material.specularF90=mix(specularIntensityFactor,1.0,metalnessFactor); +#else +float specularIntensityFactor=1.0;vec3 specularColorFactor=vec3(1.0);material.specularF90=1.0; +#endif +material.specularColor=mix(min(pow2((material.ior-1.0)/(material.ior+1.0))*specularColorFactor,vec3(1.0))*specularIntensityFactor,diffuseColor.rgb,metalnessFactor); +#else +material.specularColor=mix(vec3(0.04),diffuseColor.rgb,metalnessFactor);material.specularF90=1.0; +#endif +#ifdef USE_CLEARCOAT +material.clearcoat=clearcoat;material.clearcoatRoughness=clearcoatRoughness;material.clearcoatF0=vec3(0.04);material.clearcoatF90=1.0; +#ifdef USE_CLEARCOATMAP +material.clearcoat*=texture2D(clearcoatMap,vClearcoatMapUv).x; +#endif +#ifdef USE_CLEARCOAT_ROUGHNESSMAP +material.clearcoatRoughness*=texture2D(clearcoatRoughnessMap,vClearcoatRoughnessMapUv).y; +#endif +material.clearcoat=saturate(material.clearcoat);material.clearcoatRoughness=max(material.clearcoatRoughness,0.0525);material.clearcoatRoughness+=geometryRoughness;material.clearcoatRoughness=min(material.clearcoatRoughness,1.0); +#endif +#ifdef USE_IRIDESCENCE +material.iridescence=iridescence;material.iridescenceIOR=iridescenceIOR; +#ifdef USE_IRIDESCENCEMAP +material.iridescence*=texture2D(iridescenceMap,vIridescenceMapUv).r; +#endif +#ifdef USE_IRIDESCENCE_THICKNESSMAP +material.iridescenceThickness=(iridescenceThicknessMaximum-iridescenceThicknessMinimum)*texture2D(iridescenceThicknessMap,vIridescenceThicknessMapUv).g+iridescenceThicknessMinimum; +#else +material.iridescenceThickness=iridescenceThicknessMaximum; +#endif +#endif +#ifdef USE_SHEEN +material.sheenColor=sheenColor; +#ifdef USE_SHEEN_COLORMAP +material.sheenColor*=texture2D(sheenColorMap,vSheenColorMapUv).rgb; +#endif +material.sheenRoughness=clamp(sheenRoughness,0.07,1.0); +#ifdef USE_SHEEN_ROUGHNESSMAP +material.sheenRoughness*=texture2D(sheenRoughnessMap,vSheenRoughnessMapUv).a; +#endif +#endif +#ifdef USE_ANISOTROPY +#ifdef USE_ANISOTROPYMAP +mat2 anisotropyMat=mat2(anisotropyVector.x,anisotropyVector.y,-anisotropyVector.y,anisotropyVector.x);vec3 anisotropyPolar=texture2D(anisotropyMap,vAnisotropyMapUv).rgb;vec2 anisotropyV=anisotropyMat*normalize(2.0*anisotropyPolar.rg-vec2(1.0))*anisotropyPolar.b; +#else +vec2 anisotropyV=anisotropyVector; +#endif +material.anisotropy=length(anisotropyV);anisotropyV/=material.anisotropy;material.anisotropy=saturate(material.anisotropy);material.alphaT=mix(pow2(material.roughness),1.0,pow2(material.anisotropy));material.anisotropyT=tbn[0]*anisotropyV.x-tbn[1]*anisotropyV.y;material.anisotropyB=tbn[1]*anisotropyV.x+tbn[0]*anisotropyV.y; +#endif`,iB=`struct PhysicalMaterial{vec3 diffuseColor;float roughness;vec3 specularColor;float specularF90; +#ifdef USE_CLEARCOAT +float clearcoat;float clearcoatRoughness;vec3 clearcoatF0;float clearcoatF90; +#endif +#ifdef USE_IRIDESCENCE +float iridescence;float iridescenceIOR;float iridescenceThickness;vec3 iridescenceFresnel;vec3 iridescenceF0; +#endif +#ifdef USE_SHEEN +vec3 sheenColor;float sheenRoughness; +#endif +#ifdef IOR +float ior; +#endif +#ifdef USE_TRANSMISSION +float transmission;float transmissionAlpha;float thickness;float attenuationDistance;vec3 attenuationColor; +#endif +#ifdef USE_ANISOTROPY +float anisotropy;float alphaT;vec3 anisotropyT;vec3 anisotropyB; +#endif +};vec3 clearcoatSpecular=vec3(0.0);vec3 sheenSpecular=vec3(0.0);vec3 Schlick_to_F0(const in vec3 f,const in float f90,const in float dotVH){float x=clamp(1.0-dotVH,0.0,1.0);float x2=x*x;float x5=clamp(x*x2*x2,0.0,0.9999);return(f-vec3(f90)*x5)/(1.0-x5);}float V_GGX_SmithCorrelated(const in float alpha,const in float dotNL,const in float dotNV){float a2=pow2(alpha);float gv=dotNL*sqrt(a2+(1.0-a2)*pow2(dotNV));float gl=dotNV*sqrt(a2+(1.0-a2)*pow2(dotNL));return 0.5/max(gv+gl,EPSILON);}float D_GGX(const in float alpha,const in float dotNH){float a2=pow2(alpha);float denom=pow2(dotNH)*(a2-1.0)+1.0;return RECIPROCAL_PI*a2/pow2(denom);} +#ifdef USE_ANISOTROPY +float V_GGX_SmithCorrelated_Anisotropic(const in float alphaT,const in float alphaB,const in float dotTV,const in float dotBV,const in float dotTL,const in float dotBL,const in float dotNV,const in float dotNL){float gv=dotNL*length(vec3(alphaT*dotTV,alphaB*dotBV,dotNV));float gl=dotNV*length(vec3(alphaT*dotTL,alphaB*dotBL,dotNL));float v=0.5/(gv+gl);return saturate(v);}float D_GGX_Anisotropic(const in float alphaT,const in float alphaB,const in float dotNH,const in float dotTH,const in float dotBH){float a2=alphaT*alphaB;highp vec3 v=vec3(alphaB*dotTH,alphaT*dotBH,a2*dotNH);highp float v2=dot(v,v);float w2=a2/v2;return RECIPROCAL_PI*a2*pow2(w2);} +#endif +#ifdef USE_CLEARCOAT +vec3 BRDF_GGX_Clearcoat(const in vec3 lightDir,const in vec3 viewDir,const in vec3 normal,const in PhysicalMaterial material){vec3 f0=material.clearcoatF0;float f90=material.clearcoatF90;float roughness=material.clearcoatRoughness;float alpha=pow2(roughness);vec3 halfDir=normalize(lightDir+viewDir);float dotNL=saturate(dot(normal,lightDir));float dotNV=saturate(dot(normal,viewDir));float dotNH=saturate(dot(normal,halfDir));float dotVH=saturate(dot(viewDir,halfDir));vec3 F=F_Schlick(f0,f90,dotVH);float V=V_GGX_SmithCorrelated(alpha,dotNL,dotNV);float D=D_GGX(alpha,dotNH);return F*(V*D);} +#endif +vec3 BRDF_GGX(const in vec3 lightDir,const in vec3 viewDir,const in vec3 normal,const in PhysicalMaterial material){vec3 f0=material.specularColor;float f90=material.specularF90;float roughness=material.roughness;float alpha=pow2(roughness);vec3 halfDir=normalize(lightDir+viewDir);float dotNL=saturate(dot(normal,lightDir));float dotNV=saturate(dot(normal,viewDir));float dotNH=saturate(dot(normal,halfDir));float dotVH=saturate(dot(viewDir,halfDir));vec3 F=F_Schlick(f0,f90,dotVH); +#ifdef USE_IRIDESCENCE +F=mix(F,material.iridescenceFresnel,material.iridescence); +#endif +#ifdef USE_ANISOTROPY +float dotTL=dot(material.anisotropyT,lightDir);float dotTV=dot(material.anisotropyT,viewDir);float dotTH=dot(material.anisotropyT,halfDir);float dotBL=dot(material.anisotropyB,lightDir);float dotBV=dot(material.anisotropyB,viewDir);float dotBH=dot(material.anisotropyB,halfDir);float V=V_GGX_SmithCorrelated_Anisotropic(material.alphaT,alpha,dotTV,dotBV,dotTL,dotBL,dotNV,dotNL);float D=D_GGX_Anisotropic(material.alphaT,alpha,dotNH,dotTH,dotBH); +#else +float V=V_GGX_SmithCorrelated(alpha,dotNL,dotNV);float D=D_GGX(alpha,dotNH); +#endif +return F*(V*D);}vec2 LTC_Uv(const in vec3 N,const in vec3 V,const in float roughness){const float LUT_SIZE=64.0;const float LUT_SCALE=(LUT_SIZE-1.0)/LUT_SIZE;const float LUT_BIAS=0.5/LUT_SIZE;float dotNV=saturate(dot(N,V));vec2 uv=vec2(roughness,sqrt(1.0-dotNV));uv=uv*LUT_SCALE+LUT_BIAS;return uv;}float LTC_ClippedSphereFormFactor(const in vec3 f){float l=length(f);return max((l*l+f.z)/(l+1.0),0.0);}vec3 LTC_EdgeVectorFormFactor(const in vec3 v1,const in vec3 v2){float x=dot(v1,v2);float y=abs(x);float a=0.8543985+(0.4965155+0.0145206*y)*y;float b=3.4175940+(4.1616724+y)*y;float v=a/b;float theta_sintheta=(x>0.0)?v:0.5*inversesqrt(max(1.0-x*x,1e-7))-v;return cross(v1,v2)*theta_sintheta;}vec3 LTC_Evaluate(const in vec3 N,const in vec3 V,const in vec3 P,const in mat3 mInv,const in vec3 rectCoords[4]){vec3 v1=rectCoords[1]-rectCoords[0];vec3 v2=rectCoords[3]-rectCoords[0];vec3 lightNormal=cross(v1,v2);if(dot(lightNormal,P-rectCoords[0])<0.0)return vec3(0.0);vec3 T1,T2;T1=normalize(V-N*dot(V,N));T2=-cross(N,T1);mat3 mat=mInv*transposeMat3(mat3(T1,T2,N));vec3 coords[4];coords[0]=mat*(rectCoords[0]-P);coords[1]=mat*(rectCoords[1]-P);coords[2]=mat*(rectCoords[2]-P);coords[3]=mat*(rectCoords[3]-P);coords[0]=normalize(coords[0]);coords[1]=normalize(coords[1]);coords[2]=normalize(coords[2]);coords[3]=normalize(coords[3]);vec3 vectorFormFactor=vec3(0.0);vectorFormFactor+=LTC_EdgeVectorFormFactor(coords[0],coords[1]);vectorFormFactor+=LTC_EdgeVectorFormFactor(coords[1],coords[2]);vectorFormFactor+=LTC_EdgeVectorFormFactor(coords[2],coords[3]);vectorFormFactor+=LTC_EdgeVectorFormFactor(coords[3],coords[0]);float result=LTC_ClippedSphereFormFactor(vectorFormFactor);return vec3(result);} +#if defined(USE_SHEEN) +float D_Charlie(float roughness,float dotNH){float alpha=pow2(roughness);float invAlpha=1.0/alpha;float cos2h=dotNH*dotNH;float sin2h=max(1.0-cos2h,0.0078125);return(2.0+invAlpha)*pow(sin2h,invAlpha*0.5)/(2.0*PI);}float V_Neubelt(float dotNV,float dotNL){return saturate(1.0/(4.0*(dotNL+dotNV-dotNL*dotNV)));}vec3 BRDF_Sheen(const in vec3 lightDir,const in vec3 viewDir,const in vec3 normal,vec3 sheenColor,const in float sheenRoughness){vec3 halfDir=normalize(lightDir+viewDir);float dotNL=saturate(dot(normal,lightDir));float dotNV=saturate(dot(normal,viewDir));float dotNH=saturate(dot(normal,halfDir));float D=D_Charlie(sheenRoughness,dotNH);float V=V_Neubelt(dotNV,dotNL);return sheenColor*(D*V);} +#endif +float IBLSheenBRDF(const in vec3 normal,const in vec3 viewDir,const in float roughness){float dotNV=saturate(dot(normal,viewDir));float r2=roughness*roughness;float a=roughness<0.25?-339.2*r2+161.4*roughness-25.9:-8.48*r2+14.3*roughness-9.95;float b=roughness<0.25?44.0*r2-23.7*roughness+3.26:1.97*r2-3.27*roughness+0.72;float DG=exp(a*dotNV+b)+(roughness<0.25?0.0:0.1*(roughness-0.25));return saturate(DG*RECIPROCAL_PI);}vec2 DFGApprox(const in vec3 normal,const in vec3 viewDir,const in float roughness){float dotNV=saturate(dot(normal,viewDir));const vec4 c0=vec4(-1,-0.0275,-0.572,0.022);const vec4 c1=vec4(1,0.0425,1.04,-0.04);vec4 r=roughness*c0+c1;float a004=min(r.x*r.x,exp2(-9.28*dotNV))*r.x+r.y;vec2 fab=vec2(-1.04,1.04)*a004+r.zw;return fab;}vec3 EnvironmentBRDF(const in vec3 normal,const in vec3 viewDir,const in vec3 specularColor,const in float specularF90,const in float roughness){vec2 fab=DFGApprox(normal,viewDir,roughness);return specularColor*fab.x+specularF90*fab.y;} +#ifdef USE_IRIDESCENCE +void computeMultiscatteringIridescence(const in vec3 normal,const in vec3 viewDir,const in vec3 specularColor,const in float specularF90,const in float iridescence,const in vec3 iridescenceF0,const in float roughness,inout vec3 singleScatter,inout vec3 multiScatter){ +#else +void computeMultiscattering(const in vec3 normal,const in vec3 viewDir,const in vec3 specularColor,const in float specularF90,const in float roughness,inout vec3 singleScatter,inout vec3 multiScatter){ +#endif +vec2 fab=DFGApprox(normal,viewDir,roughness); +#ifdef USE_IRIDESCENCE +vec3 Fr=mix(specularColor,iridescenceF0,iridescence); +#else +vec3 Fr=specularColor; +#endif +vec3 FssEss=Fr*fab.x+specularF90*fab.y;float Ess=fab.x+fab.y;float Ems=1.0-Ess;vec3 Favg=Fr+(1.0-Fr)*0.047619;vec3 Fms=FssEss*Favg/(1.0-Ems*Favg);singleScatter+=FssEss;multiScatter+=Fms*Ems;} +#if NUM_RECT_AREA_LIGHTS>0 +void RE_Direct_RectArea_Physical(const in RectAreaLight rectAreaLight,const in GeometricContext geometry,const in PhysicalMaterial material,inout ReflectedLight reflectedLight){vec3 normal=geometry.normal;vec3 viewDir=geometry.viewDir;vec3 position=geometry.position;vec3 lightPos=rectAreaLight.position;vec3 halfWidth=rectAreaLight.halfWidth;vec3 halfHeight=rectAreaLight.halfHeight;vec3 lightColor=rectAreaLight.color;float roughness=material.roughness;vec3 rectCoords[4];rectCoords[0]=lightPos+halfWidth-halfHeight;rectCoords[1]=lightPos-halfWidth-halfHeight;rectCoords[2]=lightPos-halfWidth+halfHeight;rectCoords[3]=lightPos+halfWidth+halfHeight;vec2 uv=LTC_Uv(normal,viewDir,roughness);vec4 t1=texture2D(ltc_1,uv);vec4 t2=texture2D(ltc_2,uv);mat3 mInv=mat3(vec3(t1.x,0,t1.y),vec3(0,1,0),vec3(t1.z,0,t1.w));vec3 fresnel=(material.specularColor*t2.x+(vec3(1.0)-material.specularColor)*t2.y);reflectedLight.directSpecular+=lightColor*fresnel*LTC_Evaluate(normal,viewDir,position,mInv,rectCoords);reflectedLight.directDiffuse+=lightColor*material.diffuseColor*LTC_Evaluate(normal,viewDir,position,mat3(1.0),rectCoords);} +#endif +void RE_Direct_Physical(const in IncidentLight directLight,const in GeometricContext geometry,const in PhysicalMaterial material,inout ReflectedLight reflectedLight){float dotNL=saturate(dot(geometry.normal,directLight.direction));vec3 irradiance=dotNL*directLight.color; +#ifdef USE_CLEARCOAT +float dotNLcc=saturate(dot(geometry.clearcoatNormal,directLight.direction));vec3 ccIrradiance=dotNLcc*directLight.color;clearcoatSpecular+=ccIrradiance*BRDF_GGX_Clearcoat(directLight.direction,geometry.viewDir,geometry.clearcoatNormal,material); +#endif +#ifdef USE_SHEEN +sheenSpecular+=irradiance*BRDF_Sheen(directLight.direction,geometry.viewDir,geometry.normal,material.sheenColor,material.sheenRoughness); +#endif +reflectedLight.directSpecular+=irradiance*BRDF_GGX(directLight.direction,geometry.viewDir,geometry.normal,material);reflectedLight.directDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);}void RE_IndirectDiffuse_Physical(const in vec3 irradiance,const in GeometricContext geometry,const in PhysicalMaterial material,inout ReflectedLight reflectedLight){reflectedLight.indirectDiffuse+=irradiance*BRDF_Lambert(material.diffuseColor);}void RE_IndirectSpecular_Physical(const in vec3 radiance,const in vec3 irradiance,const in vec3 clearcoatRadiance,const in GeometricContext geometry,const in PhysicalMaterial material,inout ReflectedLight reflectedLight){ +#ifdef USE_CLEARCOAT +clearcoatSpecular+=clearcoatRadiance*EnvironmentBRDF(geometry.clearcoatNormal,geometry.viewDir,material.clearcoatF0,material.clearcoatF90,material.clearcoatRoughness); +#endif +#ifdef USE_SHEEN +sheenSpecular+=irradiance*material.sheenColor*IBLSheenBRDF(geometry.normal,geometry.viewDir,material.sheenRoughness); +#endif +vec3 singleScattering=vec3(0.0);vec3 multiScattering=vec3(0.0);vec3 cosineWeightedIrradiance=irradiance*RECIPROCAL_PI; +#ifdef USE_IRIDESCENCE +computeMultiscatteringIridescence(geometry.normal,geometry.viewDir,material.specularColor,material.specularF90,material.iridescence,material.iridescenceFresnel,material.roughness,singleScattering,multiScattering); +#else +computeMultiscattering(geometry.normal,geometry.viewDir,material.specularColor,material.specularF90,material.roughness,singleScattering,multiScattering); +#endif +vec3 totalScattering=singleScattering+multiScattering;vec3 diffuse=material.diffuseColor*(1.0-max(max(totalScattering.r,totalScattering.g),totalScattering.b));reflectedLight.indirectSpecular+=radiance*singleScattering;reflectedLight.indirectSpecular+=multiScattering*cosineWeightedIrradiance;reflectedLight.indirectDiffuse+=diffuse*cosineWeightedIrradiance;} +#define RE_Direct RE_Direct_Physical +#define RE_Direct_RectArea RE_Direct_RectArea_Physical +#define RE_IndirectDiffuse RE_IndirectDiffuse_Physical +#define RE_IndirectSpecular RE_IndirectSpecular_Physical +float computeSpecularOcclusion(const in float dotNV,const in float ambientOcclusion,const in float roughness){return saturate(pow(dotNV+ambientOcclusion,exp2(-16.0*roughness-1.0))-1.0+ambientOcclusion);}`,iH=`GeometricContext geometry;geometry.position=-vViewPosition;geometry.normal=normal;geometry.viewDir=(isOrthographic)?vec3(0,0,1):normalize(vViewPosition); +#ifdef USE_CLEARCOAT +geometry.clearcoatNormal=clearcoatNormal; +#endif +#ifdef USE_IRIDESCENCE +float dotNVi=saturate(dot(normal,geometry.viewDir));if(material.iridescenceThickness==0.0){material.iridescence=0.0;}else{material.iridescence=saturate(material.iridescence);}if(material.iridescence>0.0){material.iridescenceFresnel=evalIridescence(1.0,material.iridescenceIOR,dotNVi,material.iridescenceThickness,material.specularColor);material.iridescenceF0=Schlick_to_F0(material.iridescenceFresnel,1.0,dotNVi);} +#endif +IncidentLight directLight; +#if (NUM_POINT_LIGHTS>0)&&defined(RE_Direct) +PointLight pointLight; +#if defined(USE_SHADOWMAP)&&NUM_POINT_LIGHT_SHADOWS>0 +PointLightShadow pointLightShadow; +#endif +#pragma unroll_loop_start +for(int i=0;i0)&&defined(RE_Direct) +SpotLight spotLight;vec4 spotColor;vec3 spotLightCoord;bool inSpotLightMap; +#if defined(USE_SHADOWMAP)&&NUM_SPOT_LIGHT_SHADOWS>0 +SpotLightShadow spotLightShadow; +#endif +#pragma unroll_loop_start +for(int i=0;i0)&&defined(RE_Direct) +DirectionalLight directionalLight; +#if defined(USE_SHADOWMAP)&&NUM_DIR_LIGHT_SHADOWS>0 +DirectionalLightShadow directionalLightShadow; +#endif +#pragma unroll_loop_start +for(int i=0;i0)&&defined(RE_Direct_RectArea) +RectAreaLight rectAreaLight; +#pragma unroll_loop_start +for(int i=0;i0) +#pragma unroll_loop_start +for(int i=0;i0 +varying vec4 vSpotLightCoord[NUM_SPOT_LIGHT_COORDS]; +#endif +#if NUM_SPOT_LIGHT_MAPS>0 +uniform sampler2D spotLightMap[NUM_SPOT_LIGHT_MAPS]; +#endif +#ifdef USE_SHADOWMAP +#if NUM_DIR_LIGHT_SHADOWS>0 +uniform sampler2D directionalShadowMap[NUM_DIR_LIGHT_SHADOWS];varying vec4 vDirectionalShadowCoord[NUM_DIR_LIGHT_SHADOWS];struct DirectionalLightShadow{float shadowBias;float shadowNormalBias;float shadowRadius;vec2 shadowMapSize;};uniform DirectionalLightShadow directionalLightShadows[NUM_DIR_LIGHT_SHADOWS]; +#endif +#if NUM_SPOT_LIGHT_SHADOWS>0 +uniform sampler2D spotShadowMap[NUM_SPOT_LIGHT_SHADOWS];struct SpotLightShadow{float shadowBias;float shadowNormalBias;float shadowRadius;vec2 shadowMapSize;};uniform SpotLightShadow spotLightShadows[NUM_SPOT_LIGHT_SHADOWS]; +#endif +#if NUM_POINT_LIGHT_SHADOWS>0 +uniform sampler2D pointShadowMap[NUM_POINT_LIGHT_SHADOWS];varying vec4 vPointShadowCoord[NUM_POINT_LIGHT_SHADOWS];struct PointLightShadow{float shadowBias;float shadowNormalBias;float shadowRadius;vec2 shadowMapSize;float shadowCameraNear;float shadowCameraFar;};uniform PointLightShadow pointLightShadows[NUM_POINT_LIGHT_SHADOWS]; +#endif +float texture2DCompare(sampler2D depths,vec2 uv,float compare){return step(compare,unpackRGBAToDepth(texture2D(depths,uv)));}vec2 texture2DDistribution(sampler2D shadow,vec2 uv){return unpackRGBATo2Half(texture2D(shadow,uv));}float VSMShadow(sampler2D shadow,vec2 uv,float compare){float occlusion=1.0;vec2 distribution=texture2DDistribution(shadow,uv);float hard_shadow=step(compare,distribution.x);if(hard_shadow!=1.0){float distance=compare-distribution.x;float variance=max(0.00000,distribution.y*distribution.y);float softness_probability=variance/(variance+distance*distance);softness_probability=clamp((softness_probability-0.3)/(0.95-0.3),0.0,1.0);occlusion=clamp(max(hard_shadow,softness_probability),0.0,1.0);}return occlusion;}float getShadow(sampler2D shadowMap,vec2 shadowMapSize,float shadowBias,float shadowRadius,vec4 shadowCoord){float shadow=1.0;shadowCoord.xyz/=shadowCoord.w;shadowCoord.z+=shadowBias;bool inFrustum=shadowCoord.x>=0.0&&shadowCoord.x<=1.0&&shadowCoord.y>=0.0&&shadowCoord.y<=1.0;bool frustumTest=inFrustum&&shadowCoord.z<=1.0;if(frustumTest){ +#if defined(SHADOWMAP_TYPE_PCF) +vec2 texelSize=vec2(1.0)/shadowMapSize;float dx0=-texelSize.x*shadowRadius;float dy0=-texelSize.y*shadowRadius;float dx1=+texelSize.x*shadowRadius;float dy1=+texelSize.y*shadowRadius;float dx2=dx0/2.0;float dy2=dy0/2.0;float dx3=dx1/2.0;float dy3=dy1/2.0;shadow=(texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx0,dy0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(0.0,dy0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx1,dy0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx2,dy2),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(0.0,dy2),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx3,dy2),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx0,0.0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx2,0.0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy,shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx3,0.0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx1,0.0),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx2,dy3),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(0.0,dy3),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx3,dy3),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx0,dy1),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(0.0,dy1),shadowCoord.z)+texture2DCompare(shadowMap,shadowCoord.xy+vec2(dx1,dy1),shadowCoord.z))*(1.0/17.0); +#elif defined(SHADOWMAP_TYPE_PCF_SOFT) +vec2 texelSize=vec2(1.0)/shadowMapSize;float dx=texelSize.x;float dy=texelSize.y;vec2 uv=shadowCoord.xy;vec2 f=fract(uv*shadowMapSize+0.5);uv-=f*texelSize;shadow=(texture2DCompare(shadowMap,uv,shadowCoord.z)+texture2DCompare(shadowMap,uv+vec2(dx,0.0),shadowCoord.z)+texture2DCompare(shadowMap,uv+vec2(0.0,dy),shadowCoord.z)+texture2DCompare(shadowMap,uv+texelSize,shadowCoord.z)+mix(texture2DCompare(shadowMap,uv+vec2(-dx,0.0),shadowCoord.z),texture2DCompare(shadowMap,uv+vec2(2.0*dx,0.0),shadowCoord.z),f.x)+mix(texture2DCompare(shadowMap,uv+vec2(-dx,dy),shadowCoord.z),texture2DCompare(shadowMap,uv+vec2(2.0*dx,dy),shadowCoord.z),f.x)+mix(texture2DCompare(shadowMap,uv+vec2(0.0,-dy),shadowCoord.z),texture2DCompare(shadowMap,uv+vec2(0.0,2.0*dy),shadowCoord.z),f.y)+mix(texture2DCompare(shadowMap,uv+vec2(dx,-dy),shadowCoord.z),texture2DCompare(shadowMap,uv+vec2(dx,2.0*dy),shadowCoord.z),f.y)+mix(mix(texture2DCompare(shadowMap,uv+vec2(-dx,-dy),shadowCoord.z),texture2DCompare(shadowMap,uv+vec2(2.0*dx,-dy),shadowCoord.z),f.x),mix(texture2DCompare(shadowMap,uv+vec2(-dx,2.0*dy),shadowCoord.z),texture2DCompare(shadowMap,uv+vec2(2.0*dx,2.0*dy),shadowCoord.z),f.x),f.y))*(1.0/9.0); +#elif defined(SHADOWMAP_TYPE_VSM) +shadow=VSMShadow(shadowMap,shadowCoord.xy,shadowCoord.z); +#else +shadow=texture2DCompare(shadowMap,shadowCoord.xy,shadowCoord.z); +#endif +}return shadow;}vec2 cubeToUV(vec3 v,float texelSizeY){vec3 absV=abs(v);float scaleToCube=1.0/max(absV.x,max(absV.y,absV.z));absV*=scaleToCube;v*=scaleToCube*(1.0-2.0*texelSizeY);vec2 planar=v.xy;float almostATexel=1.5*texelSizeY;float almostOne=1.0-almostATexel;if(absV.z>=almostOne){if(v.z>0.0)planar.x=4.0-v.x;}else if(absV.x>=almostOne){float signX=sign(v.x);planar.x=v.z*signX+2.0*signX;}else if(absV.y>=almostOne){float signY=sign(v.y);planar.x=v.x+2.0*signY+2.0;planar.y=v.z*signY-2.0;}return vec2(0.125,0.25)*planar+vec2(0.375,0.75);}float getPointShadow(sampler2D shadowMap,vec2 shadowMapSize,float shadowBias,float shadowRadius,vec4 shadowCoord,float shadowCameraNear,float shadowCameraFar){vec2 texelSize=vec2(1.0)/(shadowMapSize*vec2(4.0,2.0));vec3 lightToPosition=shadowCoord.xyz;float dp=(length(lightToPosition)-shadowCameraNear)/(shadowCameraFar-shadowCameraNear);dp+=shadowBias;vec3 bd3D=normalize(lightToPosition); +#if defined(SHADOWMAP_TYPE_PCF)||defined(SHADOWMAP_TYPE_PCF_SOFT)||defined(SHADOWMAP_TYPE_VSM) +vec2 offset=vec2(-1,1)*shadowRadius*texelSize.y;return(texture2DCompare(shadowMap,cubeToUV(bd3D+offset.xyy,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.yyy,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.xyx,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.yyx,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.xxy,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.yxy,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.xxx,texelSize.y),dp)+texture2DCompare(shadowMap,cubeToUV(bd3D+offset.yxx,texelSize.y),dp))*(1.0/9.0); +#else +return texture2DCompare(shadowMap,cubeToUV(bd3D,texelSize.y),dp); +#endif +} +#endif`,rd=`#if NUM_SPOT_LIGHT_COORDS>0 +uniform mat4 spotLightMatrix[NUM_SPOT_LIGHT_COORDS];varying vec4 vSpotLightCoord[NUM_SPOT_LIGHT_COORDS]; +#endif +#ifdef USE_SHADOWMAP +#if NUM_DIR_LIGHT_SHADOWS>0 +uniform mat4 directionalShadowMatrix[NUM_DIR_LIGHT_SHADOWS];varying vec4 vDirectionalShadowCoord[NUM_DIR_LIGHT_SHADOWS];struct DirectionalLightShadow{float shadowBias;float shadowNormalBias;float shadowRadius;vec2 shadowMapSize;};uniform DirectionalLightShadow directionalLightShadows[NUM_DIR_LIGHT_SHADOWS]; +#endif +#if NUM_SPOT_LIGHT_SHADOWS>0 +struct SpotLightShadow{float shadowBias;float shadowNormalBias;float shadowRadius;vec2 shadowMapSize;};uniform SpotLightShadow spotLightShadows[NUM_SPOT_LIGHT_SHADOWS]; +#endif +#if NUM_POINT_LIGHT_SHADOWS>0 +uniform mat4 pointShadowMatrix[NUM_POINT_LIGHT_SHADOWS];varying vec4 vPointShadowCoord[NUM_POINT_LIGHT_SHADOWS];struct PointLightShadow{float shadowBias;float shadowNormalBias;float shadowRadius;vec2 shadowMapSize;float shadowCameraNear;float shadowCameraFar;};uniform PointLightShadow pointLightShadows[NUM_POINT_LIGHT_SHADOWS]; +#endif +#endif`,rp=`#if (defined(USE_SHADOWMAP)&&(NUM_DIR_LIGHT_SHADOWS>0||NUM_POINT_LIGHT_SHADOWS>0))||(NUM_SPOT_LIGHT_COORDS>0) +vec3 shadowWorldNormal=inverseTransformDirection(transformedNormal,viewMatrix);vec4 shadowWorldPosition; +#endif +#if defined(USE_SHADOWMAP) +#if NUM_DIR_LIGHT_SHADOWS>0 +#pragma unroll_loop_start +for(int i=0;i0 +#pragma unroll_loop_start +for(int i=0;i0 +#pragma unroll_loop_start +for(int i=0;i0 +DirectionalLightShadow directionalLight; +#pragma unroll_loop_start +for(int i=0;i0 +SpotLightShadow spotLight; +#pragma unroll_loop_start +for(int i=0;i0 +PointLightShadow pointLight; +#pragma unroll_loop_start +for(int i=0;i0 +vec4 worldPosition=vec4(transformed,1.0); +#ifdef USE_INSTANCING +worldPosition=instanceMatrix*worldPosition; +#endif +worldPosition=modelMatrix*worldPosition; +#endif`;let rL=`uniform sampler2D t2D;uniform float backgroundIntensity;varying vec2 vUv;void main(){vec4 texColor=texture2D(t2D,vUv); +#ifdef DECODE_VIDEO_TEXTURE +texColor=vec4(mix(pow(texColor.rgb*0.9478672986+vec3(0.0521327014),vec3(2.4)),texColor.rgb*0.0773993808,vec3(lessThanEqual(texColor.rgb,vec3(0.04045)))),texColor.w); +#endif +texColor.rgb*=backgroundIntensity;gl_FragColor=texColor; +#include +#include +}`,rP=`varying vec3 vWorldDirection; +#include +void main(){vWorldDirection=transformDirection(position,modelMatrix); +#include +#include +gl_Position.z=gl_Position.w;}`,rR=`#ifdef ENVMAP_TYPE_CUBE +uniform samplerCube envMap; +#elif defined(ENVMAP_TYPE_CUBE_UV) +uniform sampler2D envMap; +#endif +uniform float flipEnvMap;uniform float backgroundBlurriness;uniform float backgroundIntensity;varying vec3 vWorldDirection; +#include +void main(){ +#ifdef ENVMAP_TYPE_CUBE +vec4 texColor=textureCube(envMap,vec3(flipEnvMap*vWorldDirection.x,vWorldDirection.yz)); +#elif defined(ENVMAP_TYPE_CUBE_UV) +vec4 texColor=textureCubeUV(envMap,vWorldDirection,backgroundBlurriness); +#else +vec4 texColor=vec4(0.0,0.0,0.0,1.0); +#endif +texColor.rgb*=backgroundIntensity;gl_FragColor=texColor; +#include +#include +}`,rD=`varying vec3 vWorldDirection; +#include +void main(){vWorldDirection=transformDirection(position,modelMatrix); +#include +#include +gl_Position.z=gl_Position.w;}`,rI=`uniform samplerCube tCube;uniform float tFlip;uniform float opacity;varying vec3 vWorldDirection;void main(){vec4 texColor=textureCube(tCube,vec3(tFlip*vWorldDirection.x,vWorldDirection.yz));gl_FragColor=texColor;gl_FragColor.a*=opacity; +#include +#include +}`,rU=`#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW;void main(){ +#include +#include +#ifdef USE_DISPLACEMENTMAP +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +vHighPrecisionZW=gl_Position.zw;}`,rO=`#if DEPTH_PACKING==3200 +uniform float opacity; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +varying vec2 vHighPrecisionZW;void main(){ +#include +vec4 diffuseColor=vec4(1.0); +#if DEPTH_PACKING==3200 +diffuseColor.a=opacity; +#endif +#include +#include +#include +#include +#include +float fragCoordZ=0.5*vHighPrecisionZW[0]/vHighPrecisionZW[1]+0.5; +#if DEPTH_PACKING==3200 +gl_FragColor=vec4(vec3(1.0-fragCoordZ),opacity); +#elif DEPTH_PACKING==3201 +gl_FragColor=packDepthToRGBA(fragCoordZ); +#endif +}`,rN=`#define DISTANCE +varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#ifdef USE_DISPLACEMENTMAP +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +vWorldPosition=worldPosition.xyz;}`,rz=`#define DISTANCE +uniform vec3 referencePosition;uniform float nearDistance;uniform float farDistance;varying vec3 vWorldPosition; +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(1.0); +#include +#include +#include +#include +float dist=length(vWorldPosition-referencePosition);dist=(dist-nearDistance)/(farDistance-nearDistance);dist=saturate(dist);gl_FragColor=packDepthToRGBA(dist);}`,rF=`varying vec3 vWorldDirection; +#include +void main(){vWorldDirection=transformDirection(position,modelMatrix); +#include +#include +}`,rk=`uniform sampler2D tEquirect;varying vec3 vWorldDirection; +#include +void main(){vec3 direction=normalize(vWorldDirection);vec2 sampleUV=equirectUv(direction);gl_FragColor=texture2D(tEquirect,sampleUV); +#include +#include +}`,rB=`uniform float scale;attribute float lineDistance;varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main(){vLineDistance=scale*lineDistance; +#include +#include +#include +#include +#include +#include +#include +#include +#include +}`,rH=`uniform vec3 diffuse;uniform float opacity;uniform float dashSize;uniform float totalSize;varying float vLineDistance; +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +if(mod(vLineDistance,totalSize)>dashSize){discard;}vec3 outgoingLight=vec3(0.0);vec4 diffuseColor=vec4(diffuse,opacity); +#include +#include +#include +outgoingLight=diffuseColor.rgb; +#include +#include +#include +#include +#include +}`,rV=`#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#if defined(USE_ENVMAP)||defined(USE_SKINNING) +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +}`,rG=`uniform vec3 diffuse;uniform float opacity; +#ifndef FLAT_SHADED +varying vec3 vNormal; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(diffuse,opacity); +#include +#include +#include +#include +#include +#include +#include +ReflectedLight reflectedLight=ReflectedLight(vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0)); +#ifdef USE_LIGHTMAP +vec4 lightMapTexel=texture2D(lightMap,vLightMapUv);reflectedLight.indirectDiffuse+=lightMapTexel.rgb*lightMapIntensity*RECIPROCAL_PI; +#else +reflectedLight.indirectDiffuse+=vec3(1.0); +#endif +#include +reflectedLight.indirectDiffuse*=diffuseColor.rgb;vec3 outgoingLight=reflectedLight.indirectDiffuse; +#include +#include +#include +#include +#include +#include +#include +}`,rW=`#define LAMBERT +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vViewPosition=-mvPosition.xyz; +#include +#include +#include +#include +}`,rj=`#define LAMBERT +uniform vec3 diffuse;uniform vec3 emissive;uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(diffuse,opacity);ReflectedLight reflectedLight=ReflectedLight(vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));vec3 totalEmissiveRadiance=emissive; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vec3 outgoingLight=reflectedLight.directDiffuse+reflectedLight.indirectDiffuse+totalEmissiveRadiance; +#include +#include +#include +#include +#include +#include +#include +}`,rq=`#define MATCAP +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vViewPosition=-mvPosition.xyz;}`,rX=`#define MATCAP +uniform vec3 diffuse;uniform float opacity;uniform sampler2D matcap;varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(diffuse,opacity); +#include +#include +#include +#include +#include +#include +#include +#include +vec3 viewDir=normalize(vViewPosition);vec3 x=normalize(vec3(viewDir.z,0.0,-viewDir.x));vec3 y=cross(viewDir,x);vec2 uv=vec2(dot(x,normal),dot(y,normal))*0.495+0.5; +#ifdef USE_MATCAP +vec4 matcapColor=texture2D(matcap,uv); +#else +vec4 matcapColor=vec4(vec3(mix(0.2,0.8,uv.y)),1.0); +#endif +vec3 outgoingLight=diffuseColor.rgb*matcapColor.rgb; +#include +#include +#include +#include +#include +#include +}`,rY=`#define NORMAL +#if defined(FLAT_SHADED)||defined(USE_BUMPMAP)||defined(USE_NORMALMAP_TANGENTSPACE) +varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(FLAT_SHADED)||defined(USE_BUMPMAP)||defined(USE_NORMALMAP_TANGENTSPACE) +vViewPosition=-mvPosition.xyz; +#endif +}`,rZ=`#define NORMAL +uniform float opacity; +#if defined(FLAT_SHADED)||defined(USE_BUMPMAP)||defined(USE_NORMALMAP_TANGENTSPACE) +varying vec3 vViewPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +gl_FragColor=vec4(packNormalToRGB(normal),opacity); +#ifdef OPAQUE +gl_FragColor.a=1.0; +#endif +}`,rK=`#define PHONG +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vViewPosition=-mvPosition.xyz; +#include +#include +#include +#include +}`,rJ=`#define PHONG +uniform vec3 diffuse;uniform vec3 emissive;uniform vec3 specular;uniform float shininess;uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(diffuse,opacity);ReflectedLight reflectedLight=ReflectedLight(vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));vec3 totalEmissiveRadiance=emissive; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vec3 outgoingLight=reflectedLight.directDiffuse+reflectedLight.indirectDiffuse+reflectedLight.directSpecular+reflectedLight.indirectSpecular+totalEmissiveRadiance; +#include +#include +#include +#include +#include +#include +#include +}`,rQ=`#define STANDARD +varying vec3 vViewPosition; +#ifdef USE_TRANSMISSION +varying vec3 vWorldPosition; +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vViewPosition=-mvPosition.xyz; +#include +#include +#include +#ifdef USE_TRANSMISSION +vWorldPosition=worldPosition.xyz; +#endif +}`,r$=`#define STANDARD +#ifdef PHYSICAL +#define IOR +#define USE_SPECULAR +#endif +uniform vec3 diffuse;uniform vec3 emissive;uniform float roughness;uniform float metalness;uniform float opacity; +#ifdef IOR +uniform float ior; +#endif +#ifdef USE_SPECULAR +uniform float specularIntensity;uniform vec3 specularColor; +#ifdef USE_SPECULAR_COLORMAP +uniform sampler2D specularColorMap; +#endif +#ifdef USE_SPECULAR_INTENSITYMAP +uniform sampler2D specularIntensityMap; +#endif +#endif +#ifdef USE_CLEARCOAT +uniform float clearcoat;uniform float clearcoatRoughness; +#endif +#ifdef USE_IRIDESCENCE +uniform float iridescence;uniform float iridescenceIOR;uniform float iridescenceThicknessMinimum;uniform float iridescenceThicknessMaximum; +#endif +#ifdef USE_SHEEN +uniform vec3 sheenColor;uniform float sheenRoughness; +#ifdef USE_SHEEN_COLORMAP +uniform sampler2D sheenColorMap; +#endif +#ifdef USE_SHEEN_ROUGHNESSMAP +uniform sampler2D sheenRoughnessMap; +#endif +#endif +#ifdef USE_ANISOTROPY +uniform vec2 anisotropyVector; +#ifdef USE_ANISOTROPYMAP +uniform sampler2D anisotropyMap; +#endif +#endif +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(diffuse,opacity);ReflectedLight reflectedLight=ReflectedLight(vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));vec3 totalEmissiveRadiance=emissive; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vec3 totalDiffuse=reflectedLight.directDiffuse+reflectedLight.indirectDiffuse;vec3 totalSpecular=reflectedLight.directSpecular+reflectedLight.indirectSpecular; +#include +vec3 outgoingLight=totalDiffuse+totalSpecular+totalEmissiveRadiance; +#ifdef USE_SHEEN +float sheenEnergyComp=1.0-0.157*max3(material.sheenColor);outgoingLight=outgoingLight*sheenEnergyComp+sheenSpecular; +#endif +#ifdef USE_CLEARCOAT +float dotNVcc=saturate(dot(geometry.clearcoatNormal,geometry.viewDir));vec3 Fcc=F_Schlick(material.clearcoatF0,material.clearcoatF90,dotNVcc);outgoingLight=outgoingLight*(1.0-material.clearcoat*Fcc)+clearcoatSpecular*material.clearcoat; +#endif +#include +#include +#include +#include +#include +#include +}`,r0=`#define TOON +varying vec3 vViewPosition; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vViewPosition=-mvPosition.xyz; +#include +#include +#include +}`,r1=`#define TOON +uniform vec3 diffuse;uniform vec3 emissive;uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec4 diffuseColor=vec4(diffuse,opacity);ReflectedLight reflectedLight=ReflectedLight(vec3(0.0),vec3(0.0),vec3(0.0),vec3(0.0));vec3 totalEmissiveRadiance=emissive; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +vec3 outgoingLight=reflectedLight.directDiffuse+reflectedLight.indirectDiffuse+totalEmissiveRadiance; +#include +#include +#include +#include +#include +#include +}`,r3=`uniform float size;uniform float scale; +#include +#include +#include +#include +#include +#include +#ifdef USE_POINTS_UV +varying vec2 vUv;uniform mat3 uvTransform; +#endif +void main(){ +#ifdef USE_POINTS_UV +vUv=(uvTransform*vec3(uv,1)).xy; +#endif +#include +#include +#include +#include +#include +gl_PointSize=size; +#ifdef USE_SIZEATTENUATION +bool isPerspective=isPerspectiveMatrix(projectionMatrix);if(isPerspective)gl_PointSize*=(scale/-mvPosition.z); +#endif +#include +#include +#include +#include +}`,r2=`uniform vec3 diffuse;uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec3 outgoingLight=vec3(0.0);vec4 diffuseColor=vec4(diffuse,opacity); +#include +#include +#include +#include +#include +outgoingLight=diffuseColor.rgb; +#include +#include +#include +#include +#include +}`,r4=`#include +#include +#include +#include +#include +#include +void main(){ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +}`,r5=`uniform vec3 color;uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +gl_FragColor=vec4(color,opacity*(1.0-getShadowMask())); +#include +#include +#include +}`,r6=`uniform float rotation;uniform vec2 center; +#include +#include +#include +#include +#include +void main(){ +#include +vec4 mvPosition=modelViewMatrix*vec4(0.0,0.0,0.0,1.0);vec2 scale;scale.x=length(vec3(modelMatrix[0].x,modelMatrix[0].y,modelMatrix[0].z));scale.y=length(vec3(modelMatrix[1].x,modelMatrix[1].y,modelMatrix[1].z)); +#ifndef USE_SIZEATTENUATION +bool isPerspective=isPerspectiveMatrix(projectionMatrix);if(isPerspective)scale*=-mvPosition.z; +#endif +vec2 alignedPosition=(position.xy-(center-vec2(0.5)))*scale;vec2 rotatedPosition;rotatedPosition.x=cos(rotation)*alignedPosition.x-sin(rotation)*alignedPosition.y;rotatedPosition.y=sin(rotation)*alignedPosition.x+cos(rotation)*alignedPosition.y;mvPosition.xy+=rotatedPosition;gl_Position=projectionMatrix*mvPosition; +#include +#include +#include +}`,r8=`uniform vec3 diffuse;uniform float opacity; +#include +#include +#include +#include +#include +#include +#include +#include +#include +void main(){ +#include +vec3 outgoingLight=vec3(0.0);vec4 diffuseColor=vec4(diffuse,opacity); +#include +#include +#include +#include +#include +outgoingLight=diffuseColor.rgb; +#include +#include +#include +#include +}`,r7={alphahash_fragment:t2,alphahash_pars_fragment:t4,alphamap_fragment:t5,alphamap_pars_fragment:t6,alphatest_fragment:t8,alphatest_pars_fragment:t7,aomap_fragment:t9,aomap_pars_fragment:ie,begin_vertex:it,beginnormal_vertex:ii,bsdfs:"float G_BlinnPhong_Implicit(){return 0.25;}float D_BlinnPhong(const in float shininess,const in float dotNH){return RECIPROCAL_PI*(shininess*0.5+1.0)*pow(dotNH,shininess);}vec3 BRDF_BlinnPhong(const in vec3 lightDir,const in vec3 viewDir,const in vec3 normal,const in vec3 specularColor,const in float shininess){vec3 halfDir=normalize(lightDir+viewDir);float dotNH=saturate(dot(normal,halfDir));float dotVH=saturate(dot(viewDir,halfDir));vec3 F=F_Schlick(specularColor,1.0,dotVH);float G=G_BlinnPhong_Implicit();float D=D_BlinnPhong(shininess,dotNH);return F*(G*D);}",iridescence_fragment:ir,bumpmap_pars_fragment:ia,clipping_planes_fragment:is,clipping_planes_pars_fragment:io,clipping_planes_pars_vertex:il,clipping_planes_vertex:ih,color_fragment:ic,color_pars_fragment:iu,color_pars_vertex:id,color_vertex:ip,common:im,cube_uv_reflection_fragment:ig,defaultnormal_vertex:iv,displacementmap_pars_vertex:i_,displacementmap_vertex:ix,emissivemap_fragment:iy,emissivemap_pars_fragment:iM,colorspace_fragment:"gl_FragColor=linearToOutputTexel(gl_FragColor);",colorspace_pars_fragment:"vec4 LinearToLinear(in vec4 value){return value;}vec4 LinearTosRGB(in vec4 value){return vec4(mix(pow(value.rgb,vec3(0.41666))*1.055-vec3(0.055),value.rgb*12.92,vec3(lessThanEqual(value.rgb,vec3(0.0031308)))),value.a);}",envmap_fragment:iS,envmap_common_pars_fragment:ib,envmap_pars_fragment:iw,envmap_pars_vertex:iT,envmap_physical_pars_fragment:iN,envmap_vertex:iE,fog_vertex:iA,fog_pars_vertex:iC,fog_fragment:iL,fog_pars_fragment:iP,gradientmap_pars_fragment:iR,lightmap_fragment:iD,lightmap_pars_fragment:iI,lights_lambert_fragment:"LambertMaterial material;material.diffuseColor=diffuseColor.rgb;material.specularStrength=specularStrength;",lights_lambert_pars_fragment:iU,lights_pars_begin:iO,lights_toon_fragment:"ToonMaterial material;material.diffuseColor=diffuseColor.rgb;",lights_toon_pars_fragment:iz,lights_phong_fragment:"BlinnPhongMaterial material;material.diffuseColor=diffuseColor.rgb;material.specularColor=specular;material.specularShininess=shininess;material.specularStrength=specularStrength;",lights_phong_pars_fragment:iF,lights_physical_fragment:ik,lights_physical_pars_fragment:iB,lights_fragment_begin:iH,lights_fragment_maps:iV,lights_fragment_end:iG,logdepthbuf_fragment:iW,logdepthbuf_pars_fragment:ij,logdepthbuf_pars_vertex:iq,logdepthbuf_vertex:iX,map_fragment:iY,map_pars_fragment:iZ,map_particle_fragment:iK,map_particle_pars_fragment:iJ,metalnessmap_fragment:iQ,metalnessmap_pars_fragment:i$,morphcolor_vertex:i0,morphnormal_vertex:i1,morphtarget_pars_vertex:i3,morphtarget_vertex:i2,normal_fragment_begin:i4,normal_fragment_maps:i5,normal_pars_fragment:i6,normal_pars_vertex:i8,normal_vertex:i7,normalmap_pars_fragment:i9,clearcoat_normal_fragment_begin:re,clearcoat_normal_fragment_maps:rt,clearcoat_pars_fragment:ri,iridescence_pars_fragment:rr,opaque_fragment:ra,packing:"vec3 packNormalToRGB(const in vec3 normal){return normalize(normal)*0.5+0.5;}vec3 unpackRGBToNormal(const in vec3 rgb){return 2.0*rgb.xyz-1.0;}const float PackUpscale=256./255.;const float UnpackDownscale=255./256.;const vec3 PackFactors=vec3(256.*256.*256.,256.*256.,256.);const vec4 UnpackFactors=UnpackDownscale/vec4(PackFactors,1.);const float ShiftRight8=1./256.;vec4 packDepthToRGBA(const in float v){vec4 r=vec4(fract(v*PackFactors),v);r.yzw-=r.xyz*ShiftRight8;return r*PackUpscale;}float unpackRGBAToDepth(const in vec4 v){return dot(v,UnpackFactors);}vec2 packDepthToRG(in highp float v){return packDepthToRGBA(v).yx;}float unpackRGToDepth(const in highp vec2 v){return unpackRGBAToDepth(vec4(v.xy,0.0,0.0));}vec4 pack2HalfToRGBA(vec2 v){vec4 r=vec4(v.x,fract(v.x*255.0),v.y,fract(v.y*255.0));return vec4(r.x-r.y/255.0,r.y,r.z-r.w/255.0,r.w);}vec2 unpackRGBATo2Half(vec4 v){return vec2(v.x+(v.y/255.0),v.z+(v.w/255.0));}float viewZToOrthographicDepth(const in float viewZ,const in float near,const in float far){return(viewZ+near)/(near-far);}float orthographicDepthToViewZ(const in float depth,const in float near,const in float far){return depth*(near-far)-near;}float viewZToPerspectiveDepth(const in float viewZ,const in float near,const in float far){return((near+viewZ)*far)/((far-near)*viewZ);}float perspectiveDepthToViewZ(const in float depth,const in float near,const in float far){return(near*far)/((far-near)*depth-far);}",premultiplied_alpha_fragment:rn,project_vertex:rs,dithering_fragment:ro,dithering_pars_fragment:rl,roughnessmap_fragment:rh,roughnessmap_pars_fragment:rc,shadowmap_pars_fragment:ru,shadowmap_pars_vertex:rd,shadowmap_vertex:rp,shadowmask_pars_fragment:rf,skinbase_vertex:rm,skinning_pars_vertex:rg,skinning_vertex:rv,skinnormal_vertex:r_,specularmap_fragment:rx,specularmap_pars_fragment:ry,tonemapping_fragment:rM,tonemapping_pars_fragment:rS,transmission_fragment:rb,transmission_pars_fragment:rw,uv_pars_fragment:rT,uv_pars_vertex:rE,uv_vertex:rA,worldpos_vertex:rC,background_vert:"varying vec2 vUv;uniform mat3 uvTransform;void main(){vUv=(uvTransform*vec3(uv,1)).xy;gl_Position=vec4(position.xy,1.0,1.0);}",background_frag:rL,backgroundCube_vert:rP,backgroundCube_frag:rR,cube_vert:rD,cube_frag:rI,depth_vert:rU,depth_frag:rO,distanceRGBA_vert:rN,distanceRGBA_frag:rz,equirect_vert:rF,equirect_frag:rk,linedashed_vert:rB,linedashed_frag:rH,meshbasic_vert:rV,meshbasic_frag:rG,meshlambert_vert:rW,meshlambert_frag:rj,meshmatcap_vert:rq,meshmatcap_frag:rX,meshnormal_vert:rY,meshnormal_frag:rZ,meshphong_vert:rK,meshphong_frag:rJ,meshphysical_vert:rQ,meshphysical_frag:r$,meshtoon_vert:r0,meshtoon_frag:r1,points_vert:r3,points_frag:r2,shadow_vert:r4,shadow_frag:r5,sprite_vert:r6,sprite_frag:r8},r9={common:{diffuse:{value:new te(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new y},alphaMap:{value:null},alphaMapTransform:{value:new y},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new y}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new y}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new y}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new y},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new y},normalScale:{value:new x(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new y},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new y}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new y}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new y}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new te(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}},ltc_1:{value:null},ltc_2:{value:null}},points:{diffuse:{value:new te(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new y},alphaTest:{value:0},uvTransform:{value:new y}},sprite:{diffuse:{value:new te(16777215)},opacity:{value:1},center:{value:new x(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new y},alphaMap:{value:null},alphaMapTransform:{value:new y},alphaTest:{value:0}}},ae={basic:{uniforms:tF([r9.common,r9.specularmap,r9.envmap,r9.aomap,r9.lightmap,r9.fog]),vertexShader:r7.meshbasic_vert,fragmentShader:r7.meshbasic_frag},lambert:{uniforms:tF([r9.common,r9.specularmap,r9.envmap,r9.aomap,r9.lightmap,r9.emissivemap,r9.bumpmap,r9.normalmap,r9.displacementmap,r9.fog,r9.lights,{emissive:{value:new te(0)}}]),vertexShader:r7.meshlambert_vert,fragmentShader:r7.meshlambert_frag},phong:{uniforms:tF([r9.common,r9.specularmap,r9.envmap,r9.aomap,r9.lightmap,r9.emissivemap,r9.bumpmap,r9.normalmap,r9.displacementmap,r9.fog,r9.lights,{emissive:{value:new te(0)},specular:{value:new te(1118481)},shininess:{value:30}}]),vertexShader:r7.meshphong_vert,fragmentShader:r7.meshphong_frag},standard:{uniforms:tF([r9.common,r9.envmap,r9.aomap,r9.lightmap,r9.emissivemap,r9.bumpmap,r9.normalmap,r9.displacementmap,r9.roughnessmap,r9.metalnessmap,r9.fog,r9.lights,{emissive:{value:new te(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:r7.meshphysical_vert,fragmentShader:r7.meshphysical_frag},toon:{uniforms:tF([r9.common,r9.aomap,r9.lightmap,r9.emissivemap,r9.bumpmap,r9.normalmap,r9.displacementmap,r9.gradientmap,r9.fog,r9.lights,{emissive:{value:new te(0)}}]),vertexShader:r7.meshtoon_vert,fragmentShader:r7.meshtoon_frag},matcap:{uniforms:tF([r9.common,r9.bumpmap,r9.normalmap,r9.displacementmap,r9.fog,{matcap:{value:null}}]),vertexShader:r7.meshmatcap_vert,fragmentShader:r7.meshmatcap_frag},points:{uniforms:tF([r9.points,r9.fog]),vertexShader:r7.points_vert,fragmentShader:r7.points_frag},dashed:{uniforms:tF([r9.common,r9.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:r7.linedashed_vert,fragmentShader:r7.linedashed_frag},depth:{uniforms:tF([r9.common,r9.displacementmap]),vertexShader:r7.depth_vert,fragmentShader:r7.depth_frag},normal:{uniforms:tF([r9.common,r9.bumpmap,r9.normalmap,r9.displacementmap,{opacity:{value:1}}]),vertexShader:r7.meshnormal_vert,fragmentShader:r7.meshnormal_frag},sprite:{uniforms:tF([r9.sprite,r9.fog]),vertexShader:r7.sprite_vert,fragmentShader:r7.sprite_frag},background:{uniforms:{uvTransform:{value:new y},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:r7.background_vert,fragmentShader:r7.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1}},vertexShader:r7.backgroundCube_vert,fragmentShader:r7.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:r7.cube_vert,fragmentShader:r7.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:r7.equirect_vert,fragmentShader:r7.equirect_frag},distanceRGBA:{uniforms:tF([r9.common,r9.displacementmap,{referencePosition:{value:new W},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:r7.distanceRGBA_vert,fragmentShader:r7.distanceRGBA_frag},shadow:{uniforms:tF([r9.lights,r9.fog,{color:{value:new te(0)},opacity:{value:1}}]),vertexShader:r7.shadow_vert,fragmentShader:r7.shadow_frag}};ae.physical={uniforms:tF([ae.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new y},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new y},clearcoatNormalScale:{value:new x(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new y},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new y},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new y},sheen:{value:0},sheenColor:{value:new te(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new y},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new y},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new y},transmissionSamplerSize:{value:new x},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new y},attenuationDistance:{value:0},attenuationColor:{value:new te(0)},specularColor:{value:new te(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new y},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new y},anisotropyVector:{value:new x},anisotropyMap:{value:null},anisotropyMapTransform:{value:new y}}]),vertexShader:r7.meshphysical_vert,fragmentShader:r7.meshphysical_frag};let at={r:0,b:0,g:0};function ai(e,t,i,r,a,s,o){let l,h;let c=new te(0),u=!0===s?0:1,d=null,p=0,f=null;function m(t,i){t.getRGB(at,tk(e)),r.buffers.color.setClear(at.r,at.g,at.b,i,o)}return{getClearColor:function(){return c},setClearColor:function(e,t=1){c.set(e),m(c,u=t)},getClearAlpha:function(){return u},setClearAlpha:function(e){m(c,u=e)},render:function(s,g){let v=!1,_=!0===g.isScene?g.background:null;if(_&&_.isTexture){let e=g.backgroundBlurriness>0;_=(e?i:t).get(_)}null===_?m(c,u):_&&_.isColor&&(m(_,1),v=!0);let x=e.xr.getEnvironmentBlendMode();"additive"===x?r.buffers.color.setClear(0,0,0,1,o):"alpha-blend"===x&&r.buffers.color.setClear(0,0,0,0,o),(e.autoClear||v)&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),_&&(_.isCubeTexture||306===_.mapping)?(void 0===h&&((h=new tU(new tN(1,1,1),new tH({name:"BackgroundCubeMaterial",uniforms:tz(ae.backgroundCube.uniforms),vertexShader:ae.backgroundCube.vertexShader,fragmentShader:ae.backgroundCube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.deleteAttribute("normal"),h.geometry.deleteAttribute("uv"),h.onBeforeRender=function(e,t,i){this.matrixWorld.copyPosition(i.matrixWorld)},Object.defineProperty(h.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),a.update(h)),h.material.uniforms.envMap.value=_,h.material.uniforms.flipEnvMap.value=_.isCubeTexture&&!1===_.isRenderTargetTexture?-1:1,h.material.uniforms.backgroundBlurriness.value=g.backgroundBlurriness,h.material.uniforms.backgroundIntensity.value=g.backgroundIntensity,h.material.toneMapped=_.colorSpace!==n,(d!==_||p!==_.version||f!==e.toneMapping)&&(h.material.needsUpdate=!0,d=_,p=_.version,f=e.toneMapping),h.layers.enableAll(),s.unshift(h,h.geometry,h.material,0,0,null)):_&&_.isTexture&&(void 0===l&&((l=new tU(new t3(2,2),new tH({name:"BackgroundMaterial",uniforms:tz(ae.background.uniforms),vertexShader:ae.background.vertexShader,fragmentShader:ae.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),a.update(l)),l.material.uniforms.t2D.value=_,l.material.uniforms.backgroundIntensity.value=g.backgroundIntensity,l.material.toneMapped=_.colorSpace!==n,!0===_.matrixAutoUpdate&&_.updateMatrix(),l.material.uniforms.uvTransform.value.copy(_.matrix),(d!==_||p!==_.version||f!==e.toneMapping)&&(l.material.needsUpdate=!0,d=_,p=_.version,f=e.toneMapping),l.layers.enableAll(),s.unshift(l,l.geometry,l.material,0,0,null))}}}function ar(e,t,i,r){let a=e.getParameter(34921),n=r.isWebGL2?null:t.get("OES_vertex_array_object"),s=r.isWebGL2||null!==n,o={},l=p(null),h=l,c=!1;function u(t){return r.isWebGL2?e.bindVertexArray(t):n.bindVertexArrayOES(t)}function d(t){return r.isWebGL2?e.deleteVertexArray(t):n.deleteVertexArrayOES(t)}function p(e){let t=[],i=[],r=[];for(let e=0;e=0){let i=a[t],r=n[t];if(void 0===r&&("instanceMatrix"===t&&e.instanceMatrix&&(r=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(r=e.instanceColor)),void 0===i||i.attribute!==r||r&&i.data!==r.data)return!0;s++}}return h.attributesNum!==s||h.index!==r}(a,x,d,y))&&function(e,t,i,r){let a={},n=t.attributes,s=0,o=i.getAttributes();for(let t in o){let i=o[t];if(i.location>=0){let i=n[t];void 0===i&&("instanceMatrix"===t&&e.instanceMatrix&&(i=e.instanceMatrix),"instanceColor"===t&&e.instanceColor&&(i=e.instanceColor));let r={};r.attribute=i,i&&i.data&&(r.data=i.data),a[t]=r,s++}}h.attributes=a,h.attributesNum=s,h.index=r}(a,x,d,y)}else{let e=!0===l.wireframe;(h.geometry!==x.id||h.program!==d.id||h.wireframe!==e)&&(h.geometry=x.id,h.program=d.id,h.wireframe=e,M=!0)}null!==y&&i.update(y,34963),(M||c)&&(c=!1,function(a,n,s,o){if(!1===r.isWebGL2&&(a.isInstancedMesh||o.isInstancedBufferGeometry)&&null===t.get("ANGLE_instanced_arrays"))return;f();let l=o.attributes,h=s.getAttributes(),c=n.defaultAttributeValues;for(let t in h){let n=h[t];if(n.location>=0){let s=l[t];if(void 0===s&&("instanceMatrix"===t&&a.instanceMatrix&&(s=a.instanceMatrix),"instanceColor"===t&&a.instanceColor&&(s=a.instanceColor)),void 0!==s){let t=s.normalized,l=s.itemSize,h=i.get(s);if(void 0===h)continue;let c=h.buffer,u=h.type,d=h.bytesPerElement,p=!0===r.isWebGL2&&(5124===u||5125===u||1013===s.gpuType);if(s.isInterleavedBufferAttribute){let i=s.data,r=i.stride,h=s.offset;if(i.isInstancedInterleavedBuffer){for(let e=0;e0&&e.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(35633,36337).precision>0&&e.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}let n="undefined"!=typeof WebGL2RenderingContext&&"WebGL2RenderingContext"===e.constructor.name,s=void 0!==i.precision?i.precision:"highp",o=a(s);o!==s&&(console.warn("THREE.WebGLRenderer:",s,"not supported, using",o,"instead."),s=o);let l=n||t.has("WEBGL_draw_buffers"),h=!0===i.logarithmicDepthBuffer,c=e.getParameter(34930),u=e.getParameter(35660),d=e.getParameter(3379),p=e.getParameter(34076),f=e.getParameter(34921),m=e.getParameter(36347),g=e.getParameter(36348),v=e.getParameter(36349),_=u>0,x=n||t.has("OES_texture_float"),y=n?e.getParameter(36183):0;return{isWebGL2:n,drawBuffers:l,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===t.has("EXT_texture_filter_anisotropic")){let i=t.get("EXT_texture_filter_anisotropic");r=e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:a,precision:s,logarithmicDepthBuffer:h,maxTextures:c,maxVertexTextures:u,maxTextureSize:d,maxCubemapSize:p,maxAttributes:f,maxVertexUniforms:m,maxVaryings:g,maxFragmentUniforms:v,vertexTextures:_,floatFragmentTextures:x,floatVertexTextures:_&&x,maxSamples:y}}function as(e){let t=this,i=null,r=0,a=!1,n=!1,s=new tK,o=new y,l={value:null,needsUpdate:!1};function h(e,i,r,a){let n=null!==e?e.length:0,h=null;if(0!==n){if(h=l.value,!0!==a||null===h){let t=r+4*n,a=i.matrixWorldInverse;o.getNormalMatrix(a),(null===h||h.length0),t.numPlanes=r,t.numIntersection=0)}}function ao(e){let t=new WeakMap;function i(e,t){return 303===t?e.mapping=301:304===t&&(e.mapping=302),e}function r(e){let i=e.target;i.removeEventListener("dispose",r);let a=t.get(i);void 0!==a&&(t.delete(i),a.dispose())}return{get:function(a){if(a&&a.isTexture&&!1===a.isRenderTargetTexture){let n=a.mapping;if(303===n||304===n){if(t.has(a)){let e=t.get(a).texture;return i(e,a.mapping)}{let n=a.image;if(!n||!(n.height>0))return null;{let s=new tq(n.height/2);return s.fromEquirectangularTexture(e,a),t.set(a,s),a.addEventListener("dispose",r),i(s.texture,a.mapping)}}}}return a},dispose:function(){t=new WeakMap}}}class al extends tV{constructor(e=-1,t=1,i=1,r=-1,a=.1,n=2e3){super(),this.isOrthographicCamera=!0,this.type="OrthographicCamera",this.zoom=1,this.view=null,this.left=e,this.right=t,this.top=i,this.bottom=r,this.near=a,this.far=n,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.left=e.left,this.right=e.right,this.top=e.top,this.bottom=e.bottom,this.near=e.near,this.far=e.far,this.zoom=e.zoom,this.view=null===e.view?null:Object.assign({},e.view),this}setViewOffset(e,t,i,r,a,n){null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=i,this.view.offsetY=r,this.view.width=a,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){let e=(this.right-this.left)/(2*this.zoom),t=(this.top-this.bottom)/(2*this.zoom),i=(this.right+this.left)/2,r=(this.top+this.bottom)/2,a=i-e,n=i+e,s=r+t,o=r-t;if(null!==this.view&&this.view.enabled){let e=(this.right-this.left)/this.view.fullWidth/this.zoom,t=(this.top-this.bottom)/this.view.fullHeight/this.zoom;a+=e*this.view.offsetX,n=a+e*this.view.width,s-=t*this.view.offsetY,o=s-t*this.view.height}this.projectionMatrix.makeOrthographic(a,n,s,o,this.near,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){let t=super.toJSON(e);return t.object.zoom=this.zoom,t.object.left=this.left,t.object.right=this.right,t.object.top=this.top,t.object.bottom=this.bottom,t.object.near=this.near,t.object.far=this.far,null!==this.view&&(t.object.view=Object.assign({},this.view)),t}}let ah=[.125,.215,.35,.446,.526,.582],ac=new al,au=new te,ad=null,ap=(1+Math.sqrt(5))/2,af=1/ap,am=[new W(1,1,1),new W(-1,1,1),new W(1,1,-1),new W(-1,1,-1),new W(0,ap,af),new W(0,ap,-af),new W(af,0,ap),new W(-af,0,ap),new W(ap,af,0),new W(-ap,af,0)];class ag{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._compileMaterial(this._blurMaterial)}fromScene(e,t=0,i=.1,r=100){ad=this._renderer.getRenderTarget(),this._setSize(256);let a=this._allocateTargets();return a.depthBuffer=!0,this._sceneToCubeUV(e,i,r,a),t>0&&this._blur(a,0,0,t),this._applyPMREM(a),this._cleanup(a),a}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=ay(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=ax(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose()}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?o=ah[s-e+4-1]:0===s&&(o=0),r.push(o);let l=1/(n-2),h=-l,c=1+l,u=[h,h,c,h,c,c,h,h,c,c,h,c],d=new Float32Array(108),p=new Float32Array(72),f=new Float32Array(36);for(let e=0;e<6;e++){let t=e%3*2/3-1,i=e>2?0:-1,r=[t,i,0,t+2/3,i,0,t+2/3,i+1,0,t,i,0,t+2/3,i+1,0,t,i+1,0];d.set(r,18*e),p.set(u,12*e);let a=[e,e,e,e,e,e];f.set(a,6*e)}let m=new tg;m.setAttribute("position",new tn(d,3)),m.setAttribute("uv",new tn(p,2)),m.setAttribute("faceIndex",new tn(f,1)),t.push(m),a>4&&a--}return{lodPlanes:t,sizeLods:i,sigmas:r}}(r)),this._blurMaterial=function(e,t,i){let r=new Float32Array(20),a=new W(0,1,0),n=new tH({name:"SphericalGaussianBlur",defines:{n:20,CUBEUV_TEXEL_WIDTH:1/t,CUBEUV_TEXEL_HEIGHT:1/i,CUBEUV_MAX_MIP:`${e}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:r},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:a}},vertexShader:aM(),fragmentShader:`precision mediump float;precision mediump int;varying vec3 vOutputDirection;uniform sampler2D envMap;uniform int samples;uniform float weights[n];uniform bool latitudinal;uniform float dTheta;uniform float mipInt;uniform vec3 poleAxis; +#define ENVMAP_TYPE_CUBE_UV +#include +vec3 getSample(float theta,vec3 axis){float cosTheta=cos(theta);vec3 sampleDirection=vOutputDirection*cosTheta+cross(axis,vOutputDirection)*sin(theta)+axis*dot(axis,vOutputDirection)*(1.0-cosTheta);return bilinearCubeUV(envMap,sampleDirection,mipInt);}void main(){vec3 axis=latitudinal?poleAxis:cross(poleAxis,vOutputDirection);if(all(equal(axis,vec3(0.0)))){axis=vec3(vOutputDirection.z,0.0,-vOutputDirection.x);}axis=normalize(axis);gl_FragColor=vec4(0.0,0.0,0.0,1.0);gl_FragColor.rgb+=weights[0]*getSample(0.0,axis);for(int i=1;i=samples){break;}float theta=dTheta*float(i);gl_FragColor.rgb+=weights[i]*getSample(-1.0*theta,axis);gl_FragColor.rgb+=weights[i]*getSample(theta,axis);}}`,blending:0,depthTest:!1,depthWrite:!1});return n}(r,e,t)}return r}_compileMaterial(e){let t=new tU(this._lodPlanes[0],e);this._renderer.compile(t,ac)}_sceneToCubeUV(e,t,i,r){let a=new tG(90,1,t,i),n=[1,-1,1,1,1,1],s=[1,1,1,-1,-1,-1],o=this._renderer,l=o.autoClear,h=o.toneMapping;o.getClearColor(au),o.toneMapping=0,o.autoClear=!1;let c=new ti({name:"PMREM.Background",side:1,depthWrite:!1,depthTest:!1}),u=new tU(new tN,c),d=!1,p=e.background;p?p.isColor&&(c.color.copy(p),e.background=null,d=!0):(c.color.copy(au),d=!0);for(let t=0;t<6;t++){let i=t%3;0===i?(a.up.set(0,n[t],0),a.lookAt(s[t],0,0)):1===i?(a.up.set(0,0,n[t]),a.lookAt(0,s[t],0)):(a.up.set(0,n[t],0),a.lookAt(0,0,s[t]));let l=this._cubeSize;a_(r,i*l,t>2?l:0,l,l),o.setRenderTarget(r),d&&o.render(u,a),o.render(e,a)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=h,o.autoClear=l,e.background=p}_textureToCubeUV(e,t){let i=this._renderer,r=301===e.mapping||302===e.mapping;r?(null===this._cubemapMaterial&&(this._cubemapMaterial=ay()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===e.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=ax());let a=r?this._cubemapMaterial:this._equirectMaterial,n=new tU(this._lodPlanes[0],a),s=a.uniforms;s.envMap.value=e;let o=this._cubeSize;a_(t,0,0,3*o,2*o),i.setRenderTarget(t),i.render(n,ac)}_applyPMREM(e){let t=this._renderer,i=t.autoClear;t.autoClear=!1;for(let t=1;t20&&console.warn(`sigmaRadians, ${a}, is too large and will clip, as it requested ${f} samples when the maximum is set to 20`);let m=[],g=0;for(let e=0;e<20;++e){let t=e/p,i=Math.exp(-t*t/2);m.push(i),0===e?g+=i:ev-4?r-v+4:0),x,3*_,2*_),o.setRenderTarget(t),o.render(h,ac)}}function av(e,t,i){let r=new H(e,t,i);return r.texture.mapping=306,r.texture.name="PMREM.cubeUv",r.scissorTest=!0,r}function a_(e,t,i,r,a){e.viewport.set(t,i,r,a),e.scissor.set(t,i,r,a)}function ax(){return new tH({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:aM(),fragmentShader:`precision mediump float;precision mediump int;varying vec3 vOutputDirection;uniform sampler2D envMap; +#include +void main(){vec3 outputDirection=normalize(vOutputDirection);vec2 uv=equirectUv(outputDirection);gl_FragColor=vec4(texture2D(envMap,uv).rgb,1.0);}`,blending:0,depthTest:!1,depthWrite:!1})}function ay(){return new tH({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:aM(),fragmentShader:"precision mediump float;precision mediump int;uniform float flipEnvMap;varying vec3 vOutputDirection;uniform samplerCube envMap;void main(){gl_FragColor=textureCube(envMap,vec3(flipEnvMap*vOutputDirection.x,vOutputDirection.yz));}",blending:0,depthTest:!1,depthWrite:!1})}function aM(){return"precision mediump float;precision mediump int;attribute float faceIndex;varying vec3 vOutputDirection;vec3 getDirection(vec2 uv,float face){uv=2.0*uv-1.0;vec3 direction=vec3(uv,1.0);if(face==0.0){direction=direction.zyx;}else if(face==1.0){direction=direction.xzy;direction.xz*=-1.0;}else if(face==2.0){direction.x*=-1.0;}else if(face==3.0){direction=direction.zyx;direction.xz*=-1.0;}else if(face==4.0){direction=direction.xzy;direction.xy*=-1.0;}else if(face==5.0){direction.z*=-1.0;}return direction;}void main(){vOutputDirection=getDirection(uv,faceIndex);gl_Position=vec4(position,1.0);}"}function aS(e){let t=new WeakMap,i=null;function r(e){let i=e.target;i.removeEventListener("dispose",r);let a=t.get(i);void 0!==a&&(t.delete(i),a.dispose())}return{get:function(a){if(a&&a.isTexture){let n=a.mapping,s=303===n||304===n,o=301===n||302===n;if(s||o){if(a.isRenderTargetTexture&&!0===a.needsPMREMUpdate){a.needsPMREMUpdate=!1;let r=t.get(a);return null===i&&(i=new ag(e)),r=s?i.fromEquirectangular(a,r):i.fromCubemap(a,r),t.set(a,r),r.texture}if(t.has(a))return t.get(a).texture;{let n=a.image;if(!(s&&n&&n.height>0||o&&n&&function(e){let t=0;for(let i=0;i<6;i++)void 0!==e[i]&&t++;return 6===t}(n)))return null;{null===i&&(i=new ag(e));let n=s?i.fromEquirectangular(a):i.fromCubemap(a);return t.set(a,n),a.addEventListener("dispose",r),n.texture}}}}return a},dispose:function(){t=new WeakMap,null!==i&&(i.dispose(),i=null)}}}function ab(e){let t={};function i(i){let r;if(void 0!==t[i])return t[i];switch(i){case"WEBGL_depth_texture":r=e.getExtension("WEBGL_depth_texture")||e.getExtension("MOZ_WEBGL_depth_texture")||e.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":r=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":r=e.getExtension("WEBGL_compressed_texture_s3tc")||e.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":r=e.getExtension("WEBGL_compressed_texture_pvrtc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;default:r=e.getExtension(i)}return t[i]=r,r}return{has:function(e){return null!==i(e)},init:function(e){e.isWebGL2?i("EXT_color_buffer_float"):(i("WEBGL_depth_texture"),i("OES_texture_float"),i("OES_texture_half_float"),i("OES_texture_half_float_linear"),i("OES_standard_derivatives"),i("OES_element_index_uint"),i("OES_vertex_array_object"),i("ANGLE_instanced_arrays")),i("OES_texture_float_linear"),i("EXT_color_buffer_half_float"),i("WEBGL_multisampled_render_to_texture")},get:function(e){let t=i(e);return null===t&&console.warn("THREE.WebGLRenderer: "+e+" extension not supported."),t}}}function aw(e,t,i,r){let a={},n=new WeakMap;function s(e){let o=e.target;for(let e in null!==o.index&&t.remove(o.index),o.attributes)t.remove(o.attributes[e]);for(let e in o.morphAttributes){let i=o.morphAttributes[e];for(let e=0,r=i.length;et.maxTextureSize&&(f=Math.ceil(p/t.maxTextureSize),p=t.maxTextureSize);let m=new Float32Array(p*f*4*a),g=new V(m,p,f,a);g.type=1015,g.needsUpdate=!0;let v=4*d;for(let t=0;t0)return e;let a=t*i,n=aO[a];if(void 0===n&&(n=new Float32Array(a),aO[a]=n),0!==t){r.toArray(n,0);for(let r=1,a=0;r!==t;++r)a+=i,e[r].toArray(n,a)}return n}function aH(e,t){if(e.length!==t.length)return!1;for(let i=0,r=e.length;i":" "} ${a}: ${i[e]}`)}return r.join("\n")}(e.getShaderSource(t),r)}}function nA(e){return""!==e}function nC(e,t){let i=t.numSpotLightShadows+t.numSpotLightMaps-t.numSpotLightShadowsWithMaps;return e.replace(/NUM_DIR_LIGHTS/g,t.numDirLights).replace(/NUM_SPOT_LIGHTS/g,t.numSpotLights).replace(/NUM_SPOT_LIGHT_MAPS/g,t.numSpotLightMaps).replace(/NUM_SPOT_LIGHT_COORDS/g,i).replace(/NUM_RECT_AREA_LIGHTS/g,t.numRectAreaLights).replace(/NUM_POINT_LIGHTS/g,t.numPointLights).replace(/NUM_HEMI_LIGHTS/g,t.numHemiLights).replace(/NUM_DIR_LIGHT_SHADOWS/g,t.numDirLightShadows).replace(/NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/g,t.numSpotLightShadowsWithMaps).replace(/NUM_SPOT_LIGHT_SHADOWS/g,t.numSpotLightShadows).replace(/NUM_POINT_LIGHT_SHADOWS/g,t.numPointLightShadows)}function nL(e,t){return e.replace(/NUM_CLIPPING_PLANES/g,t.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,t.numClippingPlanes-t.numClipIntersection)}let nP=/^[ \t]*#include +<([\w\d./]+)>/gm;function nR(e){return e.replace(nP,nI)}let nD=new Map([["encodings_fragment","colorspace_fragment"],["encodings_pars_fragment","colorspace_pars_fragment"],["output_fragment","opaque_fragment"]]);function nI(e,t){let i=r7[t];if(void 0===i){let e=nD.get(t);if(void 0!==e)i=r7[e],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',t,e);else throw Error("Can not resolve #include <"+t+">")}return nR(i)}let nU=/#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;function nO(e){return e.replace(nU,nN)}function nN(e,t,i,r){let a="";for(let e=parseInt(t);e0&&(a+="\n"),(o=[S,"#define SHADER_TYPE "+i.shaderType,"#define SHADER_NAME "+i.shaderName,b].filter(nA).join("\n")).length>0&&(o+="\n")):(a=[nz(i),"#define SHADER_TYPE "+i.shaderType,"#define SHADER_NAME "+i.shaderName,b,i.instancing?"#define USE_INSTANCING":"",i.instancingColor?"#define USE_INSTANCING_COLOR":"",i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+x:"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",i.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",i.displacementMap?"#define USE_DISPLACEMENTMAP":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.anisotropyMap?"#define USE_ANISOTROPYMAP":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",i.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.alphaHash?"#define USE_ALPHAHASH":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",i.mapUv?"#define MAP_UV "+i.mapUv:"",i.alphaMapUv?"#define ALPHAMAP_UV "+i.alphaMapUv:"",i.lightMapUv?"#define LIGHTMAP_UV "+i.lightMapUv:"",i.aoMapUv?"#define AOMAP_UV "+i.aoMapUv:"",i.emissiveMapUv?"#define EMISSIVEMAP_UV "+i.emissiveMapUv:"",i.bumpMapUv?"#define BUMPMAP_UV "+i.bumpMapUv:"",i.normalMapUv?"#define NORMALMAP_UV "+i.normalMapUv:"",i.displacementMapUv?"#define DISPLACEMENTMAP_UV "+i.displacementMapUv:"",i.metalnessMapUv?"#define METALNESSMAP_UV "+i.metalnessMapUv:"",i.roughnessMapUv?"#define ROUGHNESSMAP_UV "+i.roughnessMapUv:"",i.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+i.anisotropyMapUv:"",i.clearcoatMapUv?"#define CLEARCOATMAP_UV "+i.clearcoatMapUv:"",i.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+i.clearcoatNormalMapUv:"",i.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+i.clearcoatRoughnessMapUv:"",i.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+i.iridescenceMapUv:"",i.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+i.iridescenceThicknessMapUv:"",i.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+i.sheenColorMapUv:"",i.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+i.sheenRoughnessMapUv:"",i.specularMapUv?"#define SPECULARMAP_UV "+i.specularMapUv:"",i.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+i.specularColorMapUv:"",i.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+i.specularIntensityMapUv:"",i.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+i.transmissionMapUv:"",i.thicknessMapUv?"#define THICKNESSMAP_UV "+i.thicknessMapUv:"",i.vertexTangents&&!1===i.flatShading?"#define USE_TANGENT":"",i.vertexColors?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUv1s?"#define USE_UV1":"",i.vertexUv2s?"#define USE_UV2":"",i.vertexUv3s?"#define USE_UV3":"",i.pointsUvs?"#define USE_POINTS_UV":"",i.flatShading?"#define FLAT_SHADED":"",i.skinning?"#define USE_SKINNING":"",i.morphTargets?"#define USE_MORPHTARGETS":"",i.morphNormals&&!1===i.flatShading?"#define USE_MORPHNORMALS":"",i.morphColors&&i.isWebGL2?"#define USE_MORPHCOLORS":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE":"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_TEXTURE_STRIDE "+i.morphTextureStride:"",i.morphTargetsCount>0&&i.isWebGL2?"#define MORPHTARGETS_COUNT "+i.morphTargetsCount:"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+v:"",i.sizeAttenuation?"#define USE_SIZEATTENUATION":"",i.useLegacyLights?"#define LEGACY_LIGHTS":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","#ifdef USE_INSTANCING_COLOR"," attribute vec3 instanceColor;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1"," attribute vec2 uv1;","#endif","#ifdef USE_UV2"," attribute vec2 uv2;","#endif","#ifdef USE_UV3"," attribute vec2 uv3;","#endif","#ifdef USE_TANGENT"," attribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )"," attribute vec4 color;","#elif defined( USE_COLOR )"," attribute vec3 color;","#endif","#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )"," attribute vec3 morphTarget0;"," attribute vec3 morphTarget1;"," attribute vec3 morphTarget2;"," attribute vec3 morphTarget3;"," #ifdef USE_MORPHNORMALS"," attribute vec3 morphNormal0;"," attribute vec3 morphNormal1;"," attribute vec3 morphNormal2;"," attribute vec3 morphNormal3;"," #else"," attribute vec3 morphTarget4;"," attribute vec3 morphTarget5;"," attribute vec3 morphTarget6;"," attribute vec3 morphTarget7;"," #endif","#endif","#ifdef USE_SKINNING"," attribute vec4 skinIndex;"," attribute vec4 skinWeight;","#endif","\n"].filter(nA).join("\n"),o=[S,nz(i),"#define SHADER_TYPE "+i.shaderType,"#define SHADER_NAME "+i.shaderName,b,i.useFog&&i.fog?"#define USE_FOG":"",i.useFog&&i.fogExp2?"#define FOG_EXP2":"",i.map?"#define USE_MAP":"",i.matcap?"#define USE_MATCAP":"",i.envMap?"#define USE_ENVMAP":"",i.envMap?"#define "+_:"",i.envMap?"#define "+x:"",i.envMap?"#define "+y:"",M?"#define CUBEUV_TEXEL_WIDTH "+M.texelWidth:"",M?"#define CUBEUV_TEXEL_HEIGHT "+M.texelHeight:"",M?"#define CUBEUV_MAX_MIP "+M.maxMip+".0":"",i.lightMap?"#define USE_LIGHTMAP":"",i.aoMap?"#define USE_AOMAP":"",i.bumpMap?"#define USE_BUMPMAP":"",i.normalMap?"#define USE_NORMALMAP":"",i.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",i.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",i.emissiveMap?"#define USE_EMISSIVEMAP":"",i.anisotropy?"#define USE_ANISOTROPY":"",i.anisotropyMap?"#define USE_ANISOTROPYMAP":"",i.clearcoat?"#define USE_CLEARCOAT":"",i.clearcoatMap?"#define USE_CLEARCOATMAP":"",i.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",i.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",i.iridescence?"#define USE_IRIDESCENCE":"",i.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",i.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",i.specularMap?"#define USE_SPECULARMAP":"",i.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",i.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",i.roughnessMap?"#define USE_ROUGHNESSMAP":"",i.metalnessMap?"#define USE_METALNESSMAP":"",i.alphaMap?"#define USE_ALPHAMAP":"",i.alphaTest?"#define USE_ALPHATEST":"",i.alphaHash?"#define USE_ALPHAHASH":"",i.sheen?"#define USE_SHEEN":"",i.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",i.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",i.transmission?"#define USE_TRANSMISSION":"",i.transmissionMap?"#define USE_TRANSMISSIONMAP":"",i.thicknessMap?"#define USE_THICKNESSMAP":"",i.vertexTangents&&!1===i.flatShading?"#define USE_TANGENT":"",i.vertexColors||i.instancingColor?"#define USE_COLOR":"",i.vertexAlphas?"#define USE_COLOR_ALPHA":"",i.vertexUv1s?"#define USE_UV1":"",i.vertexUv2s?"#define USE_UV2":"",i.vertexUv3s?"#define USE_UV3":"",i.pointsUvs?"#define USE_POINTS_UV":"",i.gradientMap?"#define USE_GRADIENTMAP":"",i.flatShading?"#define FLAT_SHADED":"",i.doubleSided?"#define DOUBLE_SIDED":"",i.flipSided?"#define FLIP_SIDED":"",i.shadowMapEnabled?"#define USE_SHADOWMAP":"",i.shadowMapEnabled?"#define "+v:"",i.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",i.useLegacyLights?"#define LEGACY_LIGHTS":"",i.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",i.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",i.logarithmicDepthBuffer&&i.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==i.toneMapping?"#define TONE_MAPPING":"",0!==i.toneMapping?r7.tonemapping_pars_fragment:"",0!==i.toneMapping?function(e,t){let i;switch(t){case 1:i="Linear";break;case 2:i="Reinhard";break;case 3:i="OptimizedCineon";break;case 4:i="ACESFilmic";break;case 5:i="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",t),i="Linear"}return"vec3 "+e+"( vec3 color ) { return "+i+"ToneMapping( color ); }"}("toneMapping",i.toneMapping):"",i.dithering?"#define DITHERING":"",i.opaque?"#define OPAQUE":"",r7.colorspace_pars_fragment,function(e,t){let i=function(e){switch(e){case s:return["Linear","( value )"];case n:return["sRGB","( value )"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",e),["Linear","( value )"]}}(t);return"vec4 "+e+"( vec4 value ) { return LinearTo"+i[0]+i[1]+"; }"}("linearToOutputTexel",i.outputColorSpace),i.useDepthPacking?"#define DEPTH_PACKING "+i.depthPacking:"","\n"].filter(nA).join("\n")),m=nL(m=nC(m=nR(m),i),i),g=nL(g=nC(g=nR(g),i),i),m=nO(m),g=nO(g),i.isWebGL2&&!0!==i.isRawShaderMaterial&&(T="#version 300 es\n",a="precision mediump sampler2DArray;\n#define attribute in\n#define varying out\n#define texture2D texture\n"+a,o=["#define varying in",i.glslVersion===l?"":"layout(location = 0) out highp vec4 pc_fragColor;",i.glslVersion===l?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+o);let E=T+a+m,A=T+o+g,C=nw(p,35633,E),L=nw(p,35632,A);if(p.attachShader(w,C),p.attachShader(w,L),void 0!==i.index0AttributeName?p.bindAttribLocation(w,0,i.index0AttributeName):!0===i.morphTargets&&p.bindAttribLocation(w,0,"position"),p.linkProgram(w),e.debug.checkShaderErrors){let t=p.getProgramInfoLog(w).trim(),i=p.getShaderInfoLog(C).trim(),r=p.getShaderInfoLog(L).trim(),n=!0,s=!0;if(!1===p.getProgramParameter(w,35714)){if(n=!1,"function"==typeof e.debug.onShaderError)e.debug.onShaderError(p,w,C,L);else{let e=nE(p,C,"vertex"),i=nE(p,L,"fragment");console.error("THREE.WebGLProgram: Shader Error "+p.getError()+" - VALIDATE_STATUS "+p.getProgramParameter(w,35715)+"\n\nProgram Info Log: "+t+"\n"+e+"\n"+i)}}else""!==t?console.warn("THREE.WebGLProgram: Program Info Log:",t):(""===i||""===r)&&(s=!1);s&&(this.diagnostics={runnable:n,programLog:t,vertexShader:{log:i,prefix:a},fragmentShader:{log:r,prefix:o}})}return p.deleteShader(C),p.deleteShader(L),this.getUniforms=function(){return void 0===h&&(h=new nb(p,w)),h},this.getAttributes=function(){return void 0===c&&(c=function(e,t){let i={},r=e.getProgramParameter(t,35721);for(let a=0;a0,X=o.clearcoat>0,Y=o.iridescence>0,Z=o.sheen>0,K=o.transmission>0,J=q&&!!o.anisotropyMap,Q=X&&!!o.clearcoatMap,$=X&&!!o.clearcoatNormalMap,ee=X&&!!o.clearcoatRoughnessMap,et=Y&&!!o.iridescenceMap,ei=Y&&!!o.iridescenceThicknessMap,er=Z&&!!o.sheenColorMap,ea=Z&&!!o.sheenRoughnessMap,en=!!o.specularMap,es=!!o.specularColorMap,eo=!!o.specularIntensityMap,el=K&&!!o.transmissionMap,eh=K&&!!o.thicknessMap,ec=!!o.gradientMap,eu=!!o.alphaMap,ed=o.alphaTest>0,ep=!!o.alphaHash,ef=!!o.extensions,em=!!T.attributes.uv1,eg=!!T.attributes.uv2,ev=!!T.attributes.uv3,e_=0;o.toneMapped&&(null===I||!0===I.isXRRenderTarget)&&(e_=e.toneMapping);let ex={isWebGL2:d,shaderID:L,shaderType:o.type,shaderName:o.name,vertexShader:y,fragmentShader:M,defines:o.defines,customVertexShaderID:S,customFragmentShaderID:b,isRawShaderMaterial:!0===o.isRawShaderMaterial,glslVersion:o.glslVersion,precision:m,instancing:U,instancingColor:U&&null!==x.instanceColor,supportsVertexTextures:f,outputColorSpace:null===I?e.outputColorSpace:!0===I.isXRRenderTarget?I.texture.colorSpace:s,map:O,matcap:N,envMap:z,envMapMode:z&&A.mapping,envMapCubeUVHeight:C,aoMap:F,lightMap:k,bumpMap:B,normalMap:H,displacementMap:f&&V,emissiveMap:G,normalMapObjectSpace:H&&1===o.normalMapType,normalMapTangentSpace:H&&0===o.normalMapType,metalnessMap:W,roughnessMap:j,anisotropy:q,anisotropyMap:J,clearcoat:X,clearcoatMap:Q,clearcoatNormalMap:$,clearcoatRoughnessMap:ee,iridescence:Y,iridescenceMap:et,iridescenceThicknessMap:ei,sheen:Z,sheenColorMap:er,sheenRoughnessMap:ea,specularMap:en,specularColorMap:es,specularIntensityMap:eo,transmission:K,transmissionMap:el,thicknessMap:eh,gradientMap:ec,opaque:!1===o.transparent&&1===o.blending,alphaMap:eu,alphaTest:ed,alphaHash:ep,combine:o.combine,mapUv:O&&v(o.map.channel),aoMapUv:F&&v(o.aoMap.channel),lightMapUv:k&&v(o.lightMap.channel),bumpMapUv:B&&v(o.bumpMap.channel),normalMapUv:H&&v(o.normalMap.channel),displacementMapUv:V&&v(o.displacementMap.channel),emissiveMapUv:G&&v(o.emissiveMap.channel),metalnessMapUv:W&&v(o.metalnessMap.channel),roughnessMapUv:j&&v(o.roughnessMap.channel),anisotropyMapUv:J&&v(o.anisotropyMap.channel),clearcoatMapUv:Q&&v(o.clearcoatMap.channel),clearcoatNormalMapUv:$&&v(o.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:ee&&v(o.clearcoatRoughnessMap.channel),iridescenceMapUv:et&&v(o.iridescenceMap.channel),iridescenceThicknessMapUv:ei&&v(o.iridescenceThicknessMap.channel),sheenColorMapUv:er&&v(o.sheenColorMap.channel),sheenRoughnessMapUv:ea&&v(o.sheenRoughnessMap.channel),specularMapUv:en&&v(o.specularMap.channel),specularColorMapUv:es&&v(o.specularColorMap.channel),specularIntensityMapUv:eo&&v(o.specularIntensityMap.channel),transmissionMapUv:el&&v(o.transmissionMap.channel),thicknessMapUv:eh&&v(o.thicknessMap.channel),alphaMapUv:eu&&v(o.alphaMap.channel),vertexTangents:!!T.attributes.tangent&&(H||q),vertexColors:o.vertexColors,vertexAlphas:!0===o.vertexColors&&!!T.attributes.color&&4===T.attributes.color.itemSize,vertexUv1s:em,vertexUv2s:eg,vertexUv3s:ev,pointsUvs:!0===x.isPoints&&!!T.attributes.uv&&(O||eu),fog:!!w,useFog:!0===o.fog,fogExp2:w&&w.isFogExp2,flatShading:!0===o.flatShading,sizeAttenuation:!0===o.sizeAttenuation,logarithmicDepthBuffer:p,skinning:!0===x.isSkinnedMesh,morphTargets:void 0!==T.morphAttributes.position,morphNormals:void 0!==T.morphAttributes.normal,morphColors:void 0!==T.morphAttributes.color,morphTargetsCount:R,morphTextureStride:D,numDirLights:h.directional.length,numPointLights:h.point.length,numSpotLights:h.spot.length,numSpotLightMaps:h.spotLightMap.length,numRectAreaLights:h.rectArea.length,numHemiLights:h.hemi.length,numDirLightShadows:h.directionalShadowMap.length,numPointLightShadows:h.pointShadowMap.length,numSpotLightShadows:h.spotShadowMap.length,numSpotLightShadowsWithMaps:h.numSpotLightShadowsWithMaps,numClippingPlanes:l.numPlanes,numClipIntersection:l.numIntersection,dithering:o.dithering,shadowMapEnabled:e.shadowMap.enabled&&u.length>0,shadowMapType:e.shadowMap.type,toneMapping:e_,useLegacyLights:e._useLegacyLights,decodeVideoTexture:O&&!0===o.map.isVideoTexture&&o.map.colorSpace===n,premultipliedAlpha:o.premultipliedAlpha,doubleSided:2===o.side,flipSided:1===o.side,useDepthPacking:o.depthPacking>=0,depthPacking:o.depthPacking||0,index0AttributeName:o.index0AttributeName,extensionDerivatives:ef&&!0===o.extensions.derivatives,extensionFragDepth:ef&&!0===o.extensions.fragDepth,extensionDrawBuffers:ef&&!0===o.extensions.drawBuffers,extensionShaderTextureLOD:ef&&!0===o.extensions.shaderTextureLOD,rendererExtensionFragDepth:d||r.has("EXT_frag_depth"),rendererExtensionDrawBuffers:d||r.has("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:d||r.has("EXT_shader_texture_lod"),customProgramCacheKey:o.customProgramCacheKey()};return ex},getProgramCacheKey:function(t){let i=[];if(t.shaderID?i.push(t.shaderID):(i.push(t.customVertexShaderID),i.push(t.customFragmentShaderID)),void 0!==t.defines)for(let e in t.defines)i.push(e),i.push(t.defines[e]);return!1===t.isRawShaderMaterial&&(i.push(t.precision),i.push(t.outputColorSpace),i.push(t.envMapMode),i.push(t.envMapCubeUVHeight),i.push(t.mapUv),i.push(t.alphaMapUv),i.push(t.lightMapUv),i.push(t.aoMapUv),i.push(t.bumpMapUv),i.push(t.normalMapUv),i.push(t.displacementMapUv),i.push(t.emissiveMapUv),i.push(t.metalnessMapUv),i.push(t.roughnessMapUv),i.push(t.anisotropyMapUv),i.push(t.clearcoatMapUv),i.push(t.clearcoatNormalMapUv),i.push(t.clearcoatRoughnessMapUv),i.push(t.iridescenceMapUv),i.push(t.iridescenceThicknessMapUv),i.push(t.sheenColorMapUv),i.push(t.sheenRoughnessMapUv),i.push(t.specularMapUv),i.push(t.specularColorMapUv),i.push(t.specularIntensityMapUv),i.push(t.transmissionMapUv),i.push(t.thicknessMapUv),i.push(t.combine),i.push(t.fogExp2),i.push(t.sizeAttenuation),i.push(t.morphTargetsCount),i.push(t.morphAttributeCount),i.push(t.numDirLights),i.push(t.numPointLights),i.push(t.numSpotLights),i.push(t.numSpotLightMaps),i.push(t.numHemiLights),i.push(t.numRectAreaLights),i.push(t.numDirLightShadows),i.push(t.numPointLightShadows),i.push(t.numSpotLightShadows),i.push(t.numSpotLightShadowsWithMaps),i.push(t.shadowMapType),i.push(t.toneMapping),i.push(t.numClippingPlanes),i.push(t.numClipIntersection),i.push(t.depthPacking),h.disableAll(),t.isWebGL2&&h.enable(0),t.supportsVertexTextures&&h.enable(1),t.instancing&&h.enable(2),t.instancingColor&&h.enable(3),t.matcap&&h.enable(4),t.envMap&&h.enable(5),t.normalMapObjectSpace&&h.enable(6),t.normalMapTangentSpace&&h.enable(7),t.clearcoat&&h.enable(8),t.iridescence&&h.enable(9),t.alphaTest&&h.enable(10),t.vertexColors&&h.enable(11),t.vertexAlphas&&h.enable(12),t.vertexUv1s&&h.enable(13),t.vertexUv2s&&h.enable(14),t.vertexUv3s&&h.enable(15),t.vertexTangents&&h.enable(16),t.anisotropy&&h.enable(17),i.push(h.mask),h.disableAll(),t.fog&&h.enable(0),t.useFog&&h.enable(1),t.flatShading&&h.enable(2),t.logarithmicDepthBuffer&&h.enable(3),t.skinning&&h.enable(4),t.morphTargets&&h.enable(5),t.morphNormals&&h.enable(6),t.morphColors&&h.enable(7),t.premultipliedAlpha&&h.enable(8),t.shadowMapEnabled&&h.enable(9),t.useLegacyLights&&h.enable(10),t.doubleSided&&h.enable(11),t.flipSided&&h.enable(12),t.useDepthPacking&&h.enable(13),t.dithering&&h.enable(14),t.transmission&&h.enable(15),t.sheen&&h.enable(16),t.opaque&&h.enable(17),t.pointsUvs&&h.enable(18),t.decodeVideoTexture&&h.enable(19),i.push(h.mask),i.push(e.outputColorSpace)),i.push(t.customProgramCacheKey),i.join()},getUniforms:function(e){let t;let i=g[e.type];if(i){let e=ae[i];t=tB.clone(e.uniforms)}else t=e.uniforms;return t},acquireProgram:function(t,i){let r;for(let e=0,t=u.length;e0?r.push(c):!0===s.transparent?a.push(c):i.push(c)},unshift:function(e,t,s,o,l,h){let c=n(e,t,s,o,l,h);s.transmission>0?r.unshift(c):!0===s.transparent?a.unshift(c):i.unshift(c)},finish:function(){for(let i=t,r=e.length;i1&&i.sort(e||nW),r.length>1&&r.sort(t||nj),a.length>1&&a.sort(t||nj)}}}function nX(){let e=new WeakMap;return{get:function(t,i){let r;let a=e.get(t);return void 0===a?(r=new nq,e.set(t,[r])):i>=a.length?(r=new nq,a.push(r)):r=a[i],r},dispose:function(){e=new WeakMap}}}function nY(){let e={};return{get:function(t){let i;if(void 0!==e[t.id])return e[t.id];switch(t.type){case"DirectionalLight":i={direction:new W,color:new te};break;case"SpotLight":i={position:new W,direction:new W,color:new te,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":i={position:new W,color:new te,distance:0,decay:0};break;case"HemisphereLight":i={direction:new W,skyColor:new te,groundColor:new te};break;case"RectAreaLight":i={color:new te,position:new W,halfWidth:new W,halfHeight:new W}}return e[t.id]=i,i}}}let nZ=0;function nK(e,t){return(t.castShadow?2:0)-(e.castShadow?2:0)+(t.map?1:0)-(e.map?1:0)}function nJ(e,t){let i=new nY,r=function(){let e={};return{get:function(t){let i;if(void 0!==e[t.id])return e[t.id];switch(t.type){case"DirectionalLight":case"SpotLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new x};break;case"PointLight":i={shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new x,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=i,i}}}(),a={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotLightMap:[],spotShadow:[],spotShadowMap:[],spotLightMatrix:[],rectArea:[],rectAreaLTC1:null,rectAreaLTC2:null,point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[],numSpotLightShadowsWithMaps:0};for(let e=0;e<9;e++)a.probe.push(new W);let n=new W,s=new ey,o=new ey;return{setup:function(n,s){let o=0,l=0,h=0;for(let e=0;e<9;e++)a.probe[e].set(0,0,0);let c=0,u=0,d=0,p=0,f=0,m=0,g=0,v=0,_=0,x=0;n.sort(nK);let y=!0===s?Math.PI:1;for(let e=0,t=n.length;e0&&(t.isWebGL2?(a.rectAreaLTC1=r9.LTC_FLOAT_1,a.rectAreaLTC2=r9.LTC_FLOAT_2):!0===e.has("OES_texture_float_linear")?(a.rectAreaLTC1=r9.LTC_FLOAT_1,a.rectAreaLTC2=r9.LTC_FLOAT_2):!0===e.has("OES_texture_half_float_linear")?(a.rectAreaLTC1=r9.LTC_HALF_1,a.rectAreaLTC2=r9.LTC_HALF_2):console.error("THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.")),a.ambient[0]=o,a.ambient[1]=l,a.ambient[2]=h;let M=a.hash;(M.directionalLength!==c||M.pointLength!==u||M.spotLength!==d||M.rectAreaLength!==p||M.hemiLength!==f||M.numDirectionalShadows!==m||M.numPointShadows!==g||M.numSpotShadows!==v||M.numSpotMaps!==_)&&(a.directional.length=c,a.spot.length=d,a.rectArea.length=p,a.point.length=u,a.hemi.length=f,a.directionalShadow.length=m,a.directionalShadowMap.length=m,a.pointShadow.length=g,a.pointShadowMap.length=g,a.spotShadow.length=v,a.spotShadowMap.length=v,a.directionalShadowMatrix.length=m,a.pointShadowMatrix.length=g,a.spotLightMatrix.length=v+_-x,a.spotLightMap.length=_,a.numSpotLightShadowsWithMaps=x,M.directionalLength=c,M.pointLength=u,M.spotLength=d,M.rectAreaLength=p,M.hemiLength=f,M.numDirectionalShadows=m,M.numPointShadows=g,M.numSpotShadows=v,M.numSpotMaps=_,a.version=nZ++)},setupView:function(e,t){let i=0,r=0,l=0,h=0,c=0,u=t.matrixWorldInverse;for(let t=0,d=e.length;t=s.length?(n=new nQ(e,t),s.push(n)):n=s[a],n},dispose:function(){i=new WeakMap}}}class n0 extends e5{constructor(e){super(),this.isMeshDepthMaterial=!0,this.type="MeshDepthMaterial",this.depthPacking=3200,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.setValues(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class n1 extends e5{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}let n3=`uniform sampler2D shadow_pass;uniform vec2 resolution;uniform float radius; +#include +void main(){const float samples=float(VSM_SAMPLES);float mean=0.0;float squared_mean=0.0;float uvStride=samples<=1.0?0.0:2.0/(samples-1.0);float uvStart=samples<=1.0?0.0:-1.0;for(float i=0.0;i0||i.map&&i.alphaTest>0){let e=n.uuid,t=i.uuid,r=h[e];void 0===r&&(r={},h[e]=r);let a=r[t];void 0===a&&(a=n.clone(),r[t]=a),n=a}if(n.visible=i.visible,n.wireframe=i.wireframe,3===a?n.side=null!==i.shadowSide?i.shadowSide:i.side:n.side=null!==i.shadowSide?i.shadowSide:u[i.side],n.alphaMap=i.alphaMap,n.alphaTest=i.alphaTest,n.map=i.map,n.clipShadows=i.clipShadows,n.clippingPlanes=i.clippingPlanes,n.clipIntersection=i.clipIntersection,n.displacementMap=i.displacementMap,n.displacementScale=i.displacementScale,n.displacementBias=i.displacementBias,n.wireframeLinewidth=i.wireframeLinewidth,n.linewidth=i.linewidth,!0===r.isPointLight&&!0===n.isMeshDistanceMaterial){let t=e.properties.get(n);t.light=r}return n}this.render=function(i,o,l){if(!1===g.enabled||!1===g.autoUpdate&&!1===g.needsUpdate||0===i.length)return;let h=e.getRenderTarget(),u=e.getActiveCubeFace(),f=e.getActiveMipmapLevel(),x=e.state;x.setBlending(0),x.buffers.color.setClear(1,1,1,1),x.buffers.depth.setTest(!0),x.setScissorTest(!1);let y=3!==v&&3===this.type,M=3===v&&3!==this.type;for(let h=0,u=i.length;hc||a.y>c)&&(a.x>c&&(n.x=Math.floor(c/g.x),a.x=n.x*g.x,f.mapSize.x=n.x),a.y>c&&(n.y=Math.floor(c/g.y),a.y=n.y*g.y,f.mapSize.y=n.y)),null===f.map||!0===y||!0===M){let e=3!==this.type?{minFilter:1003,magFilter:1003}:{};null!==f.map&&f.map.dispose(),f.map=new H(a.x,a.y,e),f.map.texture.name=u.name+".shadowMap",f.camera.updateProjectionMatrix()}e.setRenderTarget(f.map),e.clear();let v=f.getViewportCount();for(let i=0;i=1:-1!==P.indexOf("OpenGL ES")&&(L=parseFloat(/^OpenGL ES (\d)/.exec(P)[1])>=2);let R=null,D={},I=e.getParameter(3088),U=e.getParameter(2978),O=new k().fromArray(I),N=new k().fromArray(U);function z(t,i,a,n){let s=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,10241,9728),e.texParameteri(t,10240,9728);for(let o=0;or||e.height>r)&&(a=r/Math.max(e.width,e.height)),a<1||!0===t){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){let r=t?g:Math.floor,n=r(a*e.width),s=r(a*e.height);void 0===c&&(c=w(n,s));let o=i?w(n,s):c;o.width=n,o.height=s;let l=o.getContext("2d");return l.drawImage(e,0,0,n,s),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+e.width+"x"+e.height+") to ("+n+"x"+s+")."),o}"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+e.width+"x"+e.height+").")}return e}function E(e){return m(e.width)&&m(e.height)}function A(e,t){return e.generateMipmaps&&t&&1003!==e.minFilter&&1006!==e.minFilter}function C(t){e.generateMipmap(t)}function L(i,r,a,s,o=!1){if(!1===u)return r;if(null!==i){if(void 0!==e[i])return e[i];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+i+"'")}let l=r;return 6403===r&&(5126===a&&(l=33326),5131===a&&(l=33325),5121===a&&(l=33321)),36244===r&&(5121===a&&(l=33330),5123===a&&(l=33332),5125===a&&(l=33334),5120===a&&(l=33329),5122===a&&(l=33331),5124===a&&(l=33333)),33319===r&&(5126===a&&(l=33328),5131===a&&(l=33327),5121===a&&(l=33323)),6408===r&&(5126===a&&(l=34836),5131===a&&(l=34842),5121===a&&(l=s===n&&!1===o?35907:32856),32819===a&&(l=32854),32820===a&&(l=32855)),(33325===l||33326===l||33327===l||33328===l||34842===l||34836===l)&&t.get("EXT_color_buffer_float"),l}function P(e,t,i){return!0===A(e,i)||e.isFramebufferTexture&&1003!==e.minFilter&&1006!==e.minFilter?Math.log2(Math.max(t.width,t.height))+1:void 0!==e.mipmaps&&e.mipmaps.length>0?e.mipmaps.length:e.isCompressedTexture&&Array.isArray(e.image)?t.mipmaps.length:1}function R(e){return 1003===e||1004===e||1005===e?9728:9729}function D(e){let t=e.target;t.removeEventListener("dispose",D),function(e){let t=r.get(e);if(void 0===t.__webglInit)return;let i=e.source,a=M.get(i);if(a){let r=a[t.__cacheKey];r.usedTimes--,0===r.usedTimes&&O(e),0===Object.keys(a).length&&M.delete(i)}r.remove(e)}(t),t.isVideoTexture&&y.delete(t)}function U(t){let i=t.target;i.removeEventListener("dispose",U),function(t){let i=t.texture,a=r.get(t),n=r.get(i);if(void 0!==n.__webglTexture&&(e.deleteTexture(n.__webglTexture),h.memory.textures--),t.depthTexture&&t.depthTexture.dispose(),t.isWebGLCubeRenderTarget)for(let t=0;t<6;t++){if(Array.isArray(a.__webglFramebuffer[t]))for(let i=0;i0&&a.__version!==e.version){let i=e.image;if(null===i)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else if(!1===i.complete)console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete");else{G(a,e,t);return}}i.bindTexture(3553,a.__webglTexture,33984+t)}let F={1e3:10497,1001:33071,1002:33648},k={1003:9728,1004:9984,1005:9986,1006:9729,1007:9985,1008:9987},B={512:512,519:519,513:513,515:515,514:514,518:518,516:516,517:517};function H(i,n,s){if(s?(e.texParameteri(i,10242,F[n.wrapS]),e.texParameteri(i,10243,F[n.wrapT]),(32879===i||35866===i)&&e.texParameteri(i,32882,F[n.wrapR]),e.texParameteri(i,10240,k[n.magFilter]),e.texParameteri(i,10241,k[n.minFilter])):(e.texParameteri(i,10242,33071),e.texParameteri(i,10243,33071),(32879===i||35866===i)&&e.texParameteri(i,32882,33071),(1001!==n.wrapS||1001!==n.wrapT)&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping."),e.texParameteri(i,10240,R(n.magFilter)),e.texParameteri(i,10241,R(n.minFilter)),1003!==n.minFilter&&1006!==n.minFilter&&console.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.")),n.compareFunction&&(e.texParameteri(i,34892,34894),e.texParameteri(i,34893,B[n.compareFunction])),!0===t.has("EXT_texture_filter_anisotropic")){let s=t.get("EXT_texture_filter_anisotropic");1003!==n.magFilter&&(1005===n.minFilter||1008===n.minFilter)&&(1015!==n.type||!1!==t.has("OES_texture_float_linear"))&&(!1!==u||1016!==n.type||!1!==t.has("OES_texture_half_float_linear"))&&(n.anisotropy>1||r.get(n).__currentAnisotropy)&&(e.texParameterf(i,s.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(n.anisotropy,a.getMaxAnisotropy())),r.get(n).__currentAnisotropy=n.anisotropy)}}function V(t,i){let r=!1;void 0===t.__webglInit&&(t.__webglInit=!0,i.addEventListener("dispose",D));let a=i.source,n=M.get(a);void 0===n&&(n={},M.set(a,n));let s=function(e){let t=[];return t.push(e.wrapS),t.push(e.wrapT),t.push(e.wrapR||0),t.push(e.magFilter),t.push(e.minFilter),t.push(e.anisotropy),t.push(e.internalFormat),t.push(e.format),t.push(e.type),t.push(e.generateMipmaps),t.push(e.premultiplyAlpha),t.push(e.flipY),t.push(e.unpackAlignment),t.push(e.colorSpace),t.join()}(i);if(s!==t.__cacheKey){void 0===n[s]&&(n[s]={texture:e.createTexture(),usedTimes:0},h.memory.textures++,r=!0),n[s].usedTimes++;let a=n[t.__cacheKey];void 0!==a&&(n[t.__cacheKey].usedTimes--,0===a.usedTimes&&O(i)),t.__cacheKey=s,t.__webglTexture=n[s].texture}return r}function G(t,a,n){let s=3553;(a.isDataArrayTexture||a.isCompressedArrayTexture)&&(s=35866),a.isData3DTexture&&(s=32879);let o=V(t,a),h=a.source;i.bindTexture(s,t.__webglTexture,33984+n);let c=r.get(h);if(h.version!==c.__version||!0===o){let t;i.activeTexture(33984+n),e.pixelStorei(37440,a.flipY),e.pixelStorei(37441,a.premultiplyAlpha),e.pixelStorei(3317,a.unpackAlignment),e.pixelStorei(37443,0);let r=!u&&(1001!==a.wrapS||1001!==a.wrapT||1003!==a.minFilter&&1006!==a.minFilter)&&!1===E(a.image),d=T(a.image,r,!1,f);d=Z(a,d);let p=E(d)||u,m=l.convert(a.format,a.colorSpace),g=l.convert(a.type),v=L(a.internalFormat,m,g,a.colorSpace,a.isVideoTexture);H(s,a,p);let _=a.mipmaps,x=u&&!0!==a.isVideoTexture,y=void 0===c.__version||!0===o,M=P(a,d,p);if(a.isDepthTexture)v=6402,u?v=1015===a.type?36012:1014===a.type?33190:1020===a.type?35056:33189:1015===a.type&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),1026===a.format&&6402===v&&1012!==a.type&&1014!==a.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),a.type=1014,g=l.convert(a.type)),1027===a.format&&6402===v&&(v=34041,1020!==a.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),a.type=1020,g=l.convert(a.type))),y&&(x?i.texStorage2D(3553,1,v,d.width,d.height):i.texImage2D(3553,0,v,d.width,d.height,0,m,g,null));else if(a.isDataTexture){if(_.length>0&&p){x&&y&&i.texStorage2D(3553,M,v,_[0].width,_[0].height);for(let e=0,r=_.length;e>=1,t>>=1}}}else if(_.length>0&&p){x&&y&&i.texStorage2D(3553,M,v,_[0].width,_[0].height);for(let e=0,r=_.length;e>h),t=Math.max(1,a.height>>h);32879===o||35866===o?i.texImage3D(o,h,d,e,t,a.depth,0,c,u,null):i.texImage2D(o,h,d,e,t,0,c,u,null)}i.bindFramebuffer(36160,t),Y(a)?_.framebufferTexture2DMultisampleEXT(36160,s,o,r.get(n).__webglTexture,0,X(a)):(3553===o||o>=34069&&o<=34074)&&e.framebufferTexture2D(36160,s,o,r.get(n).__webglTexture,h),i.bindFramebuffer(36160,null)}function j(t,i,r){if(e.bindRenderbuffer(36161,t),i.depthBuffer&&!i.stencilBuffer){let a=33189;if(r||Y(i)){let t=i.depthTexture;t&&t.isDepthTexture&&(1015===t.type?a=36012:1014===t.type&&(a=33190));let r=X(i);Y(i)?_.renderbufferStorageMultisampleEXT(36161,r,a,i.width,i.height):e.renderbufferStorageMultisample(36161,r,a,i.width,i.height)}else e.renderbufferStorage(36161,a,i.width,i.height);e.framebufferRenderbuffer(36160,36096,36161,t)}else if(i.depthBuffer&&i.stencilBuffer){let a=X(i);r&&!1===Y(i)?e.renderbufferStorageMultisample(36161,a,35056,i.width,i.height):Y(i)?_.renderbufferStorageMultisampleEXT(36161,a,35056,i.width,i.height):e.renderbufferStorage(36161,34041,i.width,i.height),e.framebufferRenderbuffer(36160,33306,36161,t)}else{let t=!0===i.isWebGLMultipleRenderTargets?i.texture:[i.texture];for(let a=0;a0&&!0===t.has("WEBGL_multisampled_render_to_texture")&&!1!==i.__useRenderToTexture}function Z(e,i){let r=e.colorSpace,a=e.format,l=e.type;return!0===e.isCompressedTexture||!0===e.isVideoTexture||1035===e.format||r!==s&&""!==r&&(r===n||r===o?!1===u?!0===t.has("EXT_sRGB")&&1023===a?(e.format=1035,e.minFilter=1006,e.generateMipmaps=!1):i=I.sRGBToLinear(i):(1023!==a||1009!==l)&&console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",r)),i}this.allocateTextureUnit=function(){let e=N;return e>=d&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+d),N+=1,e},this.resetTextureUnits=function(){N=0},this.setTexture2D=z,this.setTexture2DArray=function(e,t){let a=r.get(e);if(e.version>0&&a.__version!==e.version){G(a,e,t);return}i.bindTexture(35866,a.__webglTexture,33984+t)},this.setTexture3D=function(e,t){let a=r.get(e);if(e.version>0&&a.__version!==e.version){G(a,e,t);return}i.bindTexture(32879,a.__webglTexture,33984+t)},this.setTextureCube=function(t,a){let n=r.get(t);if(t.version>0&&n.__version!==t.version){(function(t,a,n){if(6!==a.image.length)return;let s=V(t,a),o=a.source;i.bindTexture(34067,t.__webglTexture,33984+n);let h=r.get(o);if(o.version!==h.__version||!0===s){let t;i.activeTexture(33984+n),e.pixelStorei(37440,a.flipY),e.pixelStorei(37441,a.premultiplyAlpha),e.pixelStorei(3317,a.unpackAlignment),e.pixelStorei(37443,0);let r=a.isCompressedTexture||a.image[0].isCompressedTexture,c=a.image[0]&&a.image[0].isDataTexture,d=[];for(let e=0;e<6;e++)r||c?d[e]=c?a.image[e].image:a.image[e]:d[e]=T(a.image[e],!1,!0,p),d[e]=Z(a,d[e]);let f=d[0],m=E(f)||u,g=l.convert(a.format,a.colorSpace),v=l.convert(a.type),_=L(a.internalFormat,g,v,a.colorSpace),x=u&&!0!==a.isVideoTexture,y=void 0===h.__version||!0===s,M=P(a,f,m);if(H(34067,a,m),r){x&&y&&i.texStorage2D(34067,M,_,f.width,f.height);for(let e=0;e<6;e++){t=d[e].mipmaps;for(let r=0;r0&&M++,i.texStorage2D(34067,M,_,d[0].width,d[0].height));for(let e=0;e<6;e++)if(c){x?i.texSubImage2D(34069+e,0,0,0,d[e].width,d[e].height,g,v,d[e].data):i.texImage2D(34069+e,0,_,d[e].width,d[e].height,0,g,v,d[e].data);for(let r=0;r0){s.__webglFramebuffer[t]=[];for(let i=0;i0){s.__webglFramebuffer=[];for(let t=0;t0&&!1===Y(t)){let r=d?n:[n];s.__webglMultisampledFramebuffer=e.createFramebuffer(),s.__webglColorRenderbuffer=[],i.bindFramebuffer(36160,s.__webglMultisampledFramebuffer);for(let i=0;i0)for(let i=0;i0)for(let i=0;i0&&!1===Y(t)){let a=t.isWebGLMultipleRenderTargets?t.texture:[t.texture],n=t.width,s=t.height,o=16384,l=[],h=t.stencilBuffer?33306:36096,c=r.get(t),u=!0===t.isWebGLMultipleRenderTargets;if(u)for(let t=0;t.025?(l.inputState.pinching=!1,this.dispatchEvent({type:"pinchend",handedness:e.handedness,target:this})):!l.inputState.pinching&&s<=.015&&(l.inputState.pinching=!0,this.dispatchEvent({type:"pinchstart",handedness:e.handedness,target:this}))}else null!==o&&e.gripSpace&&null!==(a=t.getPose(e.gripSpace,i))&&(o.matrix.fromArray(a.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,a.linearVelocity?(o.hasLinearVelocity=!0,o.linearVelocity.copy(a.linearVelocity)):o.hasLinearVelocity=!1,a.angularVelocity?(o.hasAngularVelocity=!0,o.angularVelocity.copy(a.angularVelocity)):o.hasAngularVelocity=!1);null!==s&&(null===(r=t.getPose(e.targetRaySpace,i))&&null!==a&&(r=a),null!==r&&(s.matrix.fromArray(r.transform.matrix),s.matrix.decompose(s.position,s.rotation,s.scale),s.matrixWorldNeedsUpdate=!0,r.linearVelocity?(s.hasLinearVelocity=!0,s.linearVelocity.copy(r.linearVelocity)):s.hasLinearVelocity=!1,r.angularVelocity?(s.hasAngularVelocity=!0,s.angularVelocity.copy(r.angularVelocity)):s.hasAngularVelocity=!1,this.dispatchEvent(n9)))}return null!==s&&(s.visible=null!==r),null!==o&&(o.visible=null!==a),null!==l&&(l.visible=null!==n),this}_getHandJoint(e,t){if(void 0===e.joints[t.jointName]){let i=new n7;i.matrixAutoUpdate=!1,i.visible=!1,e.joints[t.jointName]=i,e.add(i)}return e.joints[t.jointName]}}class st extends F{constructor(e,t,i,r,a,n,s,o,l,h){if(1026!==(h=void 0!==h?h:1026)&&1027!==h)throw Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===i&&1026===h&&(i=1014),void 0===i&&1027===h&&(i=1020),super(null,r,a,n,s,o,h,i,l),this.isDepthTexture=!0,this.image={width:e,height:t},this.magFilter=void 0!==s?s:1003,this.minFilter=void 0!==o?o:1003,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(e){return super.copy(e),this.compareFunction=e.compareFunction,this}toJSON(e){let t=super.toJSON(e);return null!==this.compareFunction&&(t.compareFunction=this.compareFunction),t}}class si extends h{constructor(e,t){super();let i=this,r=null,a=1,n=null,s="local-floor",o=1,l=null,h=null,c=null,u=null,p=null,f=null,m=t.getContextAttributes(),g=null,v=null,_=[],x=[],y=new tG;y.layers.enable(1),y.viewport=new k;let M=new tG;M.layers.enable(2),M.viewport=new k;let S=[y,M],b=new n8;b.layers.enable(1),b.layers.enable(2);let w=null,T=null;function E(e){let t=x.indexOf(e.inputSource);if(-1===t)return;let i=_[t];void 0!==i&&(i.update(e.inputSource,e.frame,l||n),i.dispatchEvent({type:e.type,data:e.inputSource}))}function A(){r.removeEventListener("select",E),r.removeEventListener("selectstart",E),r.removeEventListener("selectend",E),r.removeEventListener("squeeze",E),r.removeEventListener("squeezestart",E),r.removeEventListener("squeezeend",E),r.removeEventListener("end",A),r.removeEventListener("inputsourceschange",C);for(let e=0;e<_.length;e++){let t=x[e];null!==t&&(x[e]=null,_[e].disconnect(t))}w=null,T=null,e.setRenderTarget(g),p=null,u=null,c=null,r=null,v=null,I.stop(),i.isPresenting=!1,i.dispatchEvent({type:"sessionend"})}function C(e){for(let t=0;t=0&&(x[r]=null,_[r].disconnect(i))}for(let t=0;t=x.length){x.push(i),r=e;break}if(null===x[e]){x[e]=i,r=e;break}}if(-1===r)break}let a=_[r];a&&a.connect(i)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(e){let t=_[e];return void 0===t&&(t=new se,_[e]=t),t.getTargetRaySpace()},this.getControllerGrip=function(e){let t=_[e];return void 0===t&&(t=new se,_[e]=t),t.getGripSpace()},this.getHand=function(e){let t=_[e];return void 0===t&&(t=new se,_[e]=t),t.getHandSpace()},this.setFramebufferScaleFactor=function(e){a=e,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(e){s=e,!0===i.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||n},this.setReferenceSpace=function(e){l=e},this.getBaseLayer=function(){return null!==u?u:p},this.getBinding=function(){return c},this.getFrame=function(){return f},this.getSession=function(){return r},this.setSession=async function(h){if(null!==(r=h)){if(g=e.getRenderTarget(),r.addEventListener("select",E),r.addEventListener("selectstart",E),r.addEventListener("selectend",E),r.addEventListener("squeeze",E),r.addEventListener("squeezestart",E),r.addEventListener("squeezeend",E),r.addEventListener("end",A),r.addEventListener("inputsourceschange",C),!0!==m.xrCompatible&&await t.makeXRCompatible(),void 0===r.renderState.layers||!1===e.capabilities.isWebGL2){let i={antialias:void 0!==r.renderState.layers||m.antialias,alpha:!0,depth:m.depth,stencil:m.stencil,framebufferScaleFactor:a};p=new XRWebGLLayer(r,t,i),r.updateRenderState({baseLayer:p}),v=new H(p.framebufferWidth,p.framebufferHeight,{format:1023,type:1009,colorSpace:e.outputColorSpace,stencilBuffer:m.stencil})}else{let i=null,n=null,s=null;m.depth&&(s=m.stencil?35056:33190,i=m.stencil?1027:1026,n=m.stencil?1020:1014);let o={colorFormat:32856,depthFormat:s,scaleFactor:a};u=(c=new XRWebGLBinding(r,t)).createProjectionLayer(o),r.updateRenderState({layers:[u]}),v=new H(u.textureWidth,u.textureHeight,{format:1023,type:1009,depthTexture:new st(u.textureWidth,u.textureHeight,n,void 0,void 0,void 0,void 0,void 0,void 0,i),stencilBuffer:m.stencil,colorSpace:e.outputColorSpace,samples:m.antialias?4:0});let l=e.properties.get(v);l.__ignoreDepthValues=u.ignoreDepthValues}v.isXRRenderTarget=!0,this.setFoveation(o),l=null,n=await r.requestReferenceSpace(s),I.setContext(r),I.start(),i.isPresenting=!0,i.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==r)return r.environmentBlendMode};let L=new W,P=new W;function R(e,t){null===t?e.matrixWorld.copy(e.matrix):e.matrixWorld.multiplyMatrices(t.matrixWorld,e.matrix),e.matrixWorldInverse.copy(e.matrixWorld).invert()}this.updateCamera=function(e){var t;if(null===r)return;b.near=M.near=y.near=e.near,b.far=M.far=y.far=e.far,(w!==b.near||T!==b.far)&&(r.updateRenderState({depthNear:b.near,depthFar:b.far}),w=b.near,T=b.far);let i=e.parent,a=b.cameras;R(b,i);for(let e=0;e0&&(r.alphaTest.value=a.alphaTest);let n=t.get(a).envMap;if(n&&(r.envMap.value=n,r.flipEnvMap.value=n.isCubeTexture&&!1===n.isRenderTargetTexture?-1:1,r.reflectivity.value=a.reflectivity,r.ior.value=a.ior,r.refractionRatio.value=a.refractionRatio),a.lightMap){r.lightMap.value=a.lightMap;let t=!0===e._useLegacyLights?Math.PI:1;r.lightMapIntensity.value=a.lightMapIntensity*t,i(a.lightMap,r.lightMapTransform)}a.aoMap&&(r.aoMap.value=a.aoMap,r.aoMapIntensity.value=a.aoMapIntensity,i(a.aoMap,r.aoMapTransform))}return{refreshFogUniforms:function(t,i){i.color.getRGB(t.fogColor.value,tk(e)),i.isFog?(t.fogNear.value=i.near,t.fogFar.value=i.far):i.isFogExp2&&(t.fogDensity.value=i.density)},refreshMaterialUniforms:function(e,a,n,s,o){var l,h,c,u,d,p,f,m;a.isMeshBasicMaterial?r(e,a):a.isMeshLambertMaterial?r(e,a):a.isMeshToonMaterial?(r(e,a),l=e,a.gradientMap&&(l.gradientMap.value=a.gradientMap)):a.isMeshPhongMaterial?(r(e,a),(h=e).specular.value.copy(a.specular),h.shininess.value=Math.max(a.shininess,1e-4)):a.isMeshStandardMaterial?(r(e,a),function(e,r){e.metalness.value=r.metalness,r.metalnessMap&&(e.metalnessMap.value=r.metalnessMap,i(r.metalnessMap,e.metalnessMapTransform)),e.roughness.value=r.roughness,r.roughnessMap&&(e.roughnessMap.value=r.roughnessMap,i(r.roughnessMap,e.roughnessMapTransform));let a=t.get(r).envMap;a&&(e.envMapIntensity.value=r.envMapIntensity)}(e,a),a.isMeshPhysicalMaterial&&((c=e).ior.value=a.ior,a.sheen>0&&(c.sheenColor.value.copy(a.sheenColor).multiplyScalar(a.sheen),c.sheenRoughness.value=a.sheenRoughness,a.sheenColorMap&&(c.sheenColorMap.value=a.sheenColorMap,i(a.sheenColorMap,c.sheenColorMapTransform)),a.sheenRoughnessMap&&(c.sheenRoughnessMap.value=a.sheenRoughnessMap,i(a.sheenRoughnessMap,c.sheenRoughnessMapTransform))),a.clearcoat>0&&(c.clearcoat.value=a.clearcoat,c.clearcoatRoughness.value=a.clearcoatRoughness,a.clearcoatMap&&(c.clearcoatMap.value=a.clearcoatMap,i(a.clearcoatMap,c.clearcoatMapTransform)),a.clearcoatRoughnessMap&&(c.clearcoatRoughnessMap.value=a.clearcoatRoughnessMap,i(a.clearcoatRoughnessMap,c.clearcoatRoughnessMapTransform)),a.clearcoatNormalMap&&(c.clearcoatNormalMap.value=a.clearcoatNormalMap,i(a.clearcoatNormalMap,c.clearcoatNormalMapTransform),c.clearcoatNormalScale.value.copy(a.clearcoatNormalScale),1===a.side&&c.clearcoatNormalScale.value.negate())),a.iridescence>0&&(c.iridescence.value=a.iridescence,c.iridescenceIOR.value=a.iridescenceIOR,c.iridescenceThicknessMinimum.value=a.iridescenceThicknessRange[0],c.iridescenceThicknessMaximum.value=a.iridescenceThicknessRange[1],a.iridescenceMap&&(c.iridescenceMap.value=a.iridescenceMap,i(a.iridescenceMap,c.iridescenceMapTransform)),a.iridescenceThicknessMap&&(c.iridescenceThicknessMap.value=a.iridescenceThicknessMap,i(a.iridescenceThicknessMap,c.iridescenceThicknessMapTransform))),a.transmission>0&&(c.transmission.value=a.transmission,c.transmissionSamplerMap.value=o.texture,c.transmissionSamplerSize.value.set(o.width,o.height),a.transmissionMap&&(c.transmissionMap.value=a.transmissionMap,i(a.transmissionMap,c.transmissionMapTransform)),c.thickness.value=a.thickness,a.thicknessMap&&(c.thicknessMap.value=a.thicknessMap,i(a.thicknessMap,c.thicknessMapTransform)),c.attenuationDistance.value=a.attenuationDistance,c.attenuationColor.value.copy(a.attenuationColor)),a.anisotropy>0&&(c.anisotropyVector.value.set(a.anisotropy*Math.cos(a.anisotropyRotation),a.anisotropy*Math.sin(a.anisotropyRotation)),a.anisotropyMap&&(c.anisotropyMap.value=a.anisotropyMap,i(a.anisotropyMap,c.anisotropyMapTransform))),c.specularIntensity.value=a.specularIntensity,c.specularColor.value.copy(a.specularColor),a.specularColorMap&&(c.specularColorMap.value=a.specularColorMap,i(a.specularColorMap,c.specularColorMapTransform)),a.specularIntensityMap&&(c.specularIntensityMap.value=a.specularIntensityMap,i(a.specularIntensityMap,c.specularIntensityMapTransform)))):a.isMeshMatcapMaterial?(r(e,a),u=e,a.matcap&&(u.matcap.value=a.matcap)):a.isMeshDepthMaterial?r(e,a):a.isMeshDistanceMaterial?(r(e,a),function(e,i){let r=t.get(i).light;e.referencePosition.value.setFromMatrixPosition(r.matrixWorld),e.nearDistance.value=r.shadow.camera.near,e.farDistance.value=r.shadow.camera.far}(e,a)):a.isMeshNormalMaterial?r(e,a):a.isLineBasicMaterial?((d=e).diffuse.value.copy(a.color),d.opacity.value=a.opacity,a.map&&(d.map.value=a.map,i(a.map,d.mapTransform)),a.isLineDashedMaterial&&((p=e).dashSize.value=a.dashSize,p.totalSize.value=a.dashSize+a.gapSize,p.scale.value=a.scale)):a.isPointsMaterial?((f=e).diffuse.value.copy(a.color),f.opacity.value=a.opacity,f.size.value=a.size*n,f.scale.value=.5*s,a.map&&(f.map.value=a.map,i(a.map,f.uvTransform)),a.alphaMap&&(f.alphaMap.value=a.alphaMap,i(a.alphaMap,f.alphaMapTransform)),a.alphaTest>0&&(f.alphaTest.value=a.alphaTest)):a.isSpriteMaterial?((m=e).diffuse.value.copy(a.color),m.opacity.value=a.opacity,m.rotation.value=a.rotation,a.map&&(m.map.value=a.map,i(a.map,m.mapTransform)),a.alphaMap&&(m.alphaMap.value=a.alphaMap,i(a.alphaMap,m.alphaMapTransform)),a.alphaTest>0&&(m.alphaTest.value=a.alphaTest)):a.isShadowMaterial?(e.color.value.copy(a.color),e.opacity.value=a.opacity):a.isShaderMaterial&&(a.uniformsNeedUpdate=!1)}}}function sa(e,t,i,r){let a={},n={},s=[],o=i.isWebGL2?e.getParameter(35375):0;function l(e){let t={boundary:0,storage:0};return"number"==typeof e?(t.boundary=4,t.storage=4):e.isVector2?(t.boundary=8,t.storage=8):e.isVector3||e.isColor?(t.boundary=16,t.storage=12):e.isVector4?(t.boundary=16,t.storage=16):e.isMatrix3?(t.boundary=48,t.storage=48):e.isMatrix4?(t.boundary=64,t.storage=64):e.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",e),t}function h(t){let i=t.target;i.removeEventListener("dispose",h);let r=s.indexOf(i.__bindingPointIndex);s.splice(r,1),e.deleteBuffer(a[i.id]),delete a[i.id],delete n[i.id]}return{bind:function(e,t){let i=t.program;r.uniformBlockBinding(e,i)},update:function(i,c){let u=a[i.id];void 0===u&&(function(e){let t=e.uniforms,i=0,r=0;for(let e=0,a=t.length;e0){r=i%16;let e=16-r;0!==r&&e-n.boundary<0&&(i+=16-r,a.__offset=i)}i+=n.storage}(r=i%16)>0&&(i+=16-r),e.__size=i,e.__cache={}}(i),u=function(t){let i=function(){for(let e=0;eo.matrixWorld.determinant(),_=function(e,t,i,n,o){var d,p;!0!==t.isScene&&(t=ew),h.resetTextureUnits();let f=t.fog,m=n.isMeshStandardMaterial?t.environment:null,g=null===ee?K.outputColorSpace:!0===ee.isXRRenderTarget?ee.texture.colorSpace:s,_=(n.isMeshStandardMaterial?u:c).get(n.envMap||m),x=!0===n.vertexColors&&!!i.attributes.color&&4===i.attributes.color.itemSize,y=!!i.attributes.tangent&&(!!n.normalMap||n.anisotropy>0),S=!!i.morphAttributes.position,b=!!i.morphAttributes.normal,w=!!i.morphAttributes.color,E=0;n.toneMapped&&(null===ee||!0===ee.isXRRenderTarget)&&(E=K.toneMapping);let A=i.morphAttributes.position||i.morphAttributes.normal||i.morphAttributes.color,C=void 0!==A?A.length:0,L=l.get(n),R=X.state.lights;if(!0===ev&&(!0===e_||e!==ei)){let t=e===ei&&n.id===et;M.setState(n,e,t)}let D=!1;n.version===L.__version?L.needsLights&&L.lightsStateVersion!==R.state.version?D=!0:L.outputColorSpace!==g?D=!0:o.isInstancedMesh&&!1===L.instancing?D=!0:o.isInstancedMesh||!0!==L.instancing?o.isSkinnedMesh&&!1===L.skinning?D=!0:o.isSkinnedMesh||!0!==L.skinning?o.isInstancedMesh&&!0===L.instancingColor&&null===o.instanceColor?D=!0:o.isInstancedMesh&&!1===L.instancingColor&&null!==o.instanceColor?D=!0:L.envMap!==_?D=!0:!0===n.fog&&L.fog!==f?D=!0:void 0!==L.numClippingPlanes&&(L.numClippingPlanes!==M.numPlanes||L.numIntersection!==M.numIntersection)?D=!0:L.vertexAlphas!==x?D=!0:L.vertexTangents!==y?D=!0:L.morphTargets!==S?D=!0:L.morphNormals!==b?D=!0:L.morphColors!==w?D=!0:L.toneMapping!==E?D=!0:!0===r.isWebGL2&&L.morphTargetsCount!==C&&(D=!0):D=!0:D=!0:(D=!0,L.__version=n.version);let I=L.currentProgram;!0===D&&(I=eH(n,t,o));let U=!1,O=!1,N=!1,z=I.getUniforms(),F=L.uniforms;if(a.useProgram(I.program)&&(U=!0,O=!0,N=!0),n.id!==et&&(et=n.id,O=!0),U||ei!==e){z.setValue(eE,"projectionMatrix",e.projectionMatrix),z.setValue(eE,"viewMatrix",e.matrixWorldInverse);let t=z.map.cameraPosition;void 0!==t&&t.setValue(eE,eb.setFromMatrixPosition(e.matrixWorld)),r.logarithmicDepthBuffer&&z.setValue(eE,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial)&&z.setValue(eE,"isOrthographic",!0===e.isOrthographicCamera),ei!==e&&(ei=e,O=!0,N=!0)}if(o.isSkinnedMesh){z.setOptional(eE,o,"bindMatrix"),z.setOptional(eE,o,"bindMatrixInverse");let e=o.skeleton;e&&(r.floatVertexTextures?(null===e.boneTexture&&e.computeBoneTexture(),z.setValue(eE,"boneTexture",e.boneTexture,h),z.setValue(eE,"boneTextureSize",e.boneTextureSize)):console.warn("THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required."))}let k=i.morphAttributes;if((void 0!==k.position||void 0!==k.normal||void 0!==k.color&&!0===r.isWebGL2)&&T.update(o,i,I),(O||L.receiveShadow!==o.receiveShadow)&&(L.receiveShadow=o.receiveShadow,z.setValue(eE,"receiveShadow",o.receiveShadow)),n.isMeshGouraudMaterial&&null!==n.envMap&&(F.envMap.value=_,F.flipEnvMap.value=_.isCubeTexture&&!1===_.isRenderTargetTexture?-1:1),O&&(z.setValue(eE,"toneMappingExposure",K.toneMappingExposure),L.needsLights&&(d=F,p=N,d.ambientLightColor.needsUpdate=p,d.lightProbe.needsUpdate=p,d.directionalLights.needsUpdate=p,d.directionalLightShadows.needsUpdate=p,d.pointLights.needsUpdate=p,d.pointLightShadows.needsUpdate=p,d.spotLights.needsUpdate=p,d.spotLightShadows.needsUpdate=p,d.rectAreaLights.needsUpdate=p,d.hemisphereLights.needsUpdate=p),f&&!0===n.fog&&v.refreshFogUniforms(F,f),v.refreshMaterialUniforms(F,n,ec,eh,ex),nb.upload(eE,L.uniformsList,F,h)),n.isShaderMaterial&&!0===n.uniformsNeedUpdate&&(nb.upload(eE,L.uniformsList,F,h),n.uniformsNeedUpdate=!1),n.isSpriteMaterial&&z.setValue(eE,"center",o.center),z.setValue(eE,"modelViewMatrix",o.modelViewMatrix),z.setValue(eE,"normalMatrix",o.normalMatrix),z.setValue(eE,"modelMatrix",o.matrixWorld),n.isShaderMaterial||n.isRawShaderMaterial){let e=n.uniformsGroups;for(let t=0,i=e.length;t0&&function(e,t,a,n){let s=r.isWebGL2;null===ex&&(ex=new H(1,1,{generateMipmaps:!0,type:i.has("EXT_color_buffer_half_float")?1016:1009,minFilter:1008,samples:s?4:0})),K.getDrawingBufferSize(eS),s?ex.setSize(eS.x,eS.y):ex.setSize(g(eS.x),g(eS.y));let o=K.getRenderTarget();K.setRenderTarget(ex),K.getClearColor(es),(eo=K.getClearAlpha())<1&&K.setClearColor(16777215,.5),K.clear();let l=K.toneMapping;K.toneMapping=0,ek(e,a,n),h.updateMultisampleRenderTarget(ex),h.updateRenderTargetMipmap(ex);let c=!1;for(let e=0,i=t.length;e0&&ek(o,t,n),l.length>0&&ek(l,t,n),c.length>0&&ek(c,t,n),a.buffers.depth.setTest(!0),a.buffers.depth.setMask(!0),a.buffers.color.setMask(!0),a.setPolygonOffset(!1)}function ek(e,t,i){let r=!0===t.isScene?t.overrideMaterial:null;for(let a=0,n=e.length;a0?Z[Z.length-1]:null,Y.pop(),q=Y.length>0?Y[Y.length-1]:null},this.getActiveCubeFace=function(){return Q},this.getActiveMipmapLevel=function(){return $},this.getRenderTarget=function(){return ee},this.setRenderTargetTextures=function(e,t,r){l.get(e.texture).__webglTexture=t,l.get(e.depthTexture).__webglTexture=r;let a=l.get(e);a.__hasExternalTextures=!0,a.__hasExternalTextures&&(a.__autoAllocateDepthBuffer=void 0===r,a.__autoAllocateDepthBuffer||!0!==i.has("WEBGL_multisampled_render_to_texture")||(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),a.__useRenderToTexture=!1))},this.setRenderTargetFramebuffer=function(e,t){let i=l.get(e);i.__webglFramebuffer=t,i.__useDefaultFramebuffer=void 0===t},this.setRenderTarget=function(e,t=0,i=0){ee=e,Q=t,$=i;let n=!0,s=null,o=!1,c=!1;if(e){let u=l.get(e);void 0!==u.__useDefaultFramebuffer?(a.bindFramebuffer(36160,null),n=!1):void 0===u.__webglFramebuffer?h.setupRenderTarget(e):u.__hasExternalTextures&&h.rebindTextures(e,l.get(e.texture).__webglTexture,l.get(e.depthTexture).__webglTexture);let d=e.texture;(d.isData3DTexture||d.isDataArrayTexture||d.isCompressedArrayTexture)&&(c=!0);let p=l.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(s=Array.isArray(p[t])?p[t][i]:p[t],o=!0):s=r.isWebGL2&&e.samples>0&&!1===h.useMultisampledRTT(e)?l.get(e).__webglMultisampledFramebuffer:Array.isArray(p)?p[i]:p,er.copy(e.viewport),ea.copy(e.scissor),en=e.scissorTest}else er.copy(ep).multiplyScalar(ec).floor(),ea.copy(ef).multiplyScalar(ec).floor(),en=em;let u=a.bindFramebuffer(36160,s);if(u&&r.drawBuffers&&n&&a.drawBuffers(e,s),a.viewport(er),a.scissor(ea),a.setScissorTest(en),o){let r=l.get(e.texture);eE.framebufferTexture2D(36160,36064,34069+t,r.__webglTexture,i)}else if(c){let r=l.get(e.texture);eE.framebufferTextureLayer(36160,36064,r.__webglTexture,i||0,t||0)}et=-1},this.readRenderTargetPixels=function(e,t,n,s,o,h,c){if(!(e&&e.isWebGLRenderTarget)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");return}let u=l.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==c&&(u=u[c]),u){a.bindFramebuffer(36160,u);try{let a=e.texture,l=a.format,c=a.type;if(1023!==l&&C.convert(l)!==eE.getParameter(35739)){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");return}let u=1016===c&&(i.has("EXT_color_buffer_half_float")||r.isWebGL2&&i.has("EXT_color_buffer_float"));if(1009!==c&&C.convert(c)!==eE.getParameter(35738)&&!(1015===c&&(r.isWebGL2||i.has("OES_texture_float")||i.has("WEBGL_color_buffer_float")))&&!u){console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");return}t>=0&&t<=e.width-s&&n>=0&&n<=e.height-o&&eE.readPixels(t,n,s,o,C.convert(l),C.convert(c),h)}finally{let e=null!==ee?l.get(ee).__webglFramebuffer:null;a.bindFramebuffer(36160,e)}}},this.copyFramebufferToTexture=function(e,t,i=0){let r=Math.pow(2,-i),n=Math.floor(t.image.width*r),s=Math.floor(t.image.height*r);h.setTexture2D(t,0),eE.copyTexSubImage2D(3553,i,0,0,e.x,e.y,n,s),a.unbindTexture()},this.copyTextureToTexture=function(e,t,i,r=0){let n=t.image.width,s=t.image.height,o=C.convert(i.format),l=C.convert(i.type);h.setTexture2D(i,0),eE.pixelStorei(37440,i.flipY),eE.pixelStorei(37441,i.premultiplyAlpha),eE.pixelStorei(3317,i.unpackAlignment),t.isDataTexture?eE.texSubImage2D(3553,r,e.x,e.y,n,s,o,l,t.image.data):t.isCompressedTexture?eE.compressedTexSubImage2D(3553,r,e.x,e.y,t.mipmaps[0].width,t.mipmaps[0].height,o,t.mipmaps[0].data):eE.texSubImage2D(3553,r,e.x,e.y,o,l,t.image),0===r&&i.generateMipmaps&&eE.generateMipmap(3553),a.unbindTexture()},this.copyTextureToTexture3D=function(e,t,i,r,n=0){let s;if(K.isWebGL1Renderer){console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.");return}let o=e.max.x-e.min.x+1,l=e.max.y-e.min.y+1,c=e.max.z-e.min.z+1,u=C.convert(r.format),d=C.convert(r.type);if(r.isData3DTexture)h.setTexture3D(r,0),s=32879;else if(r.isDataArrayTexture)h.setTexture2DArray(r,0),s=35866;else{console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");return}eE.pixelStorei(37440,r.flipY),eE.pixelStorei(37441,r.premultiplyAlpha),eE.pixelStorei(3317,r.unpackAlignment);let p=eE.getParameter(3314),f=eE.getParameter(32878),m=eE.getParameter(3316),g=eE.getParameter(3315),v=eE.getParameter(32877),_=i.isCompressedTexture?i.mipmaps[0]:i.image;eE.pixelStorei(3314,_.width),eE.pixelStorei(32878,_.height),eE.pixelStorei(3316,e.min.x),eE.pixelStorei(3315,e.min.y),eE.pixelStorei(32877,e.min.z),i.isDataTexture||i.isData3DTexture?eE.texSubImage3D(s,n,t.x,t.y,t.z,o,l,c,u,d,_.data):i.isCompressedArrayTexture?(console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture."),eE.compressedTexSubImage3D(s,n,t.x,t.y,t.z,o,l,c,u,_.data)):eE.texSubImage3D(s,n,t.x,t.y,t.z,o,l,c,u,d,_),eE.pixelStorei(3314,p),eE.pixelStorei(32878,f),eE.pixelStorei(3316,m),eE.pixelStorei(3315,g),eE.pixelStorei(32877,v),0===n&&r.generateMipmaps&&eE.generateMipmap(s),a.unbindTexture()},this.initTexture=function(e){e.isCubeTexture?h.setTextureCube(e,0):e.isData3DTexture?h.setTexture3D(e,0):e.isDataArrayTexture||e.isCompressedArrayTexture?h.setTexture2DArray(e,0):h.setTexture2D(e,0),a.unbindTexture()},this.resetState=function(){Q=0,$=0,ee=null,a.reset(),L.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return 2e3}get physicallyCorrectLights(){return console.warn("THREE.WebGLRenderer: The property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),!this.useLegacyLights}set physicallyCorrectLights(e){console.warn("THREE.WebGLRenderer: The property .physicallyCorrectLights has been removed. Set renderer.useLegacyLights instead."),this.useLegacyLights=!e}get outputEncoding(){return console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace===n?3001:3e3}set outputEncoding(e){console.warn("THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead."),this.outputColorSpace=3001===e?n:s}get useLegacyLights(){return console.warn("THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733."),this._useLegacyLights}set useLegacyLights(e){console.warn("THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733."),this._useLegacyLights=e}}class ss extends ej{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){let t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t}}class so{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=35044,this.updateRange={offset:0,count:-1},this.version=0,this.uuid=p()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}setUsage(e){return this.usage=e,this}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,i){e*=this.stride,i*=t.stride;for(let r=0,a=this.stride;re.far||t.push({distance:o,point:su.clone(),uv:e2.getInterpolation(su,sv,s_,sx,sy,sM,sS,new x),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function sw(e,t,i,r,a,n){sf.subVectors(e,i).addScalar(.5).multiply(r),void 0!==a?(sm.x=n*sf.x-a*sf.y,sm.y=a*sf.x+n*sf.y):sm.copy(sf),e.copy(t),e.x+=sm.x,e.y+=sm.y,e.applyMatrix4(sg)}class sT extends F{constructor(e,t,i,r,a,n,s,o,l){super(e,t,i,r,a,n,s,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}}class sE extends e5{constructor(e){super(),this.isMeshStandardMaterial=!0,this.defines={STANDARD:""},this.type="MeshStandardMaterial",this.color=new te(16777215),this.roughness=1,this.metalness=0,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new te(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new x(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.roughnessMap=null,this.metalnessMap=null,this.alphaMap=null,this.envMap=null,this.envMapIntensity=1,this.wireframe=!1,this.wireframeLinewidth=1,this.wireframeLinecap="round",this.wireframeLinejoin="round",this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.defines={STANDARD:""},this.color.copy(e.color),this.roughness=e.roughness,this.metalness=e.metalness,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.roughnessMap=e.roughnessMap,this.metalnessMap=e.metalnessMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapIntensity=e.envMapIntensity,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class sA extends ej{constructor(e,t=1){super(),this.isLight=!0,this.type="Light",this.color=new te(e),this.intensity=t}dispose(){}copy(e,t){return super.copy(e,t),this.color.copy(e.color),this.intensity=e.intensity,this}toJSON(e){let t=super.toJSON(e);return t.object.color=this.color.getHex(),t.object.intensity=this.intensity,void 0!==this.groundColor&&(t.object.groundColor=this.groundColor.getHex()),void 0!==this.distance&&(t.object.distance=this.distance),void 0!==this.angle&&(t.object.angle=this.angle),void 0!==this.decay&&(t.object.decay=this.decay),void 0!==this.penumbra&&(t.object.penumbra=this.penumbra),void 0!==this.shadow&&(t.object.shadow=this.shadow.toJSON()),t}}let sC=new ey,sL=new W,sP=new W;class sR{constructor(e){this.camera=e,this.bias=0,this.normalBias=0,this.radius=1,this.blurSamples=8,this.mapSize=new x(512,512),this.map=null,this.mapPass=null,this.matrix=new ey,this.autoUpdate=!0,this.needsUpdate=!1,this._frustum=new t$,this._frameExtents=new x(1,1),this._viewportCount=1,this._viewports=[new k(0,0,1,1)]}getViewportCount(){return this._viewportCount}getFrustum(){return this._frustum}updateMatrices(e){let t=this.camera,i=this.matrix;sL.setFromMatrixPosition(e.matrixWorld),t.position.copy(sL),sP.setFromMatrixPosition(e.target.matrixWorld),t.lookAt(sP),t.updateMatrixWorld(),sC.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),this._frustum.setFromProjectionMatrix(sC),i.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1),i.multiply(sC)}getViewport(e){return this._viewports[e]}getFrameExtents(){return this._frameExtents}dispose(){this.map&&this.map.dispose(),this.mapPass&&this.mapPass.dispose()}copy(e){return this.camera=e.camera.clone(),this.bias=e.bias,this.radius=e.radius,this.mapSize.copy(e.mapSize),this}clone(){return new this.constructor().copy(this)}toJSON(){let e={};return 0!==this.bias&&(e.bias=this.bias),0!==this.normalBias&&(e.normalBias=this.normalBias),1!==this.radius&&(e.radius=this.radius),(512!==this.mapSize.x||512!==this.mapSize.y)&&(e.mapSize=this.mapSize.toArray()),e.camera=this.camera.toJSON(!1).object,delete e.camera.matrix,e}}let sD=new ey,sI=new W,sU=new W;class sO extends sR{constructor(){super(new tG(90,1,.5,500)),this.isPointLightShadow=!0,this._frameExtents=new x(4,2),this._viewportCount=6,this._viewports=[new k(2,1,1,1),new k(0,1,1,1),new k(3,1,1,1),new k(1,1,1,1),new k(3,0,1,1),new k(1,0,1,1)],this._cubeDirections=[new W(1,0,0),new W(-1,0,0),new W(0,0,1),new W(0,0,-1),new W(0,1,0),new W(0,-1,0)],this._cubeUps=[new W(0,1,0),new W(0,1,0),new W(0,1,0),new W(0,1,0),new W(0,0,1),new W(0,0,-1)]}updateMatrices(e,t=0){let i=this.camera,r=this.matrix,a=e.distance||i.far;a!==i.far&&(i.far=a,i.updateProjectionMatrix()),sI.setFromMatrixPosition(e.matrixWorld),i.position.copy(sI),sU.copy(i.position),sU.add(this._cubeDirections[t]),i.up.copy(this._cubeUps[t]),i.lookAt(sU),i.updateMatrixWorld(),r.makeTranslation(-sI.x,-sI.y,-sI.z),sD.multiplyMatrices(i.projectionMatrix,i.matrixWorldInverse),this._frustum.setFromProjectionMatrix(sD)}}class sN extends sA{constructor(e,t,i=0,r=2){super(e,t),this.isPointLight=!0,this.type="PointLight",this.distance=i,this.decay=r,this.shadow=new sO}get power(){return 4*this.intensity*Math.PI}set power(e){this.intensity=e/(4*Math.PI)}dispose(){this.shadow.dispose()}copy(e,t){return super.copy(e,t),this.distance=e.distance,this.decay=e.decay,this.shadow=e.shadow.clone(),this}}class sz extends sA{constructor(e,t){super(e,t),this.isAmbientLight=!0,this.type="AmbientLight"}}class sF{constructor(e=!0){this.autoStart=e,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=sk(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let e=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){let t=sk();e=(t-this.oldTime)/1e3,this.oldTime=t,this.elapsedTime+=e}return e}}function sk(){return("undefined"==typeof performance?Date:performance).now()}class sB{constructor(e=1,t=0,i=0){return this.radius=e,this.phi=t,this.theta=i,this}set(e,t,i){return this.radius=e,this.phi=t,this.theta=i,this}copy(e){return this.radius=e.radius,this.phi=e.phi,this.theta=e.theta,this}makeSafe(){return this.phi=Math.max(1e-6,Math.min(Math.PI-1e-6,this.phi)),this}setFromVector3(e){return this.setFromCartesianCoords(e.x,e.y,e.z)}setFromCartesianCoords(e,t,i){return this.radius=Math.sqrt(e*e+t*t+i*i),0===this.radius?(this.theta=0,this.phi=0):(this.theta=Math.atan2(e,i),this.phi=Math.acos(f(t/this.radius,-1,1))),this}clone(){return new this.constructor().copy(this)}}function sH(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function sV(e,t,i,r,a,n,s,o){let l=(e,t,i,r)=>[new x(e/s,1-r/o),new x(i/s,1-r/o),new x(i/s,1-t/o),new x(e/s,1-t/o)],h=l(t+n,i,t+r+n,i+n),c=l(t+r+n,i,t+2*r+n,i+n),u=l(t,i+n,t+n,i+n+a),d=l(t+n,i+n,t+r+n,i+n+a),p=l(t+r+n,i+n,t+r+2*n,i+a+n),f=l(t+r+2*n,i+n,t+2*r+2*n,i+a+n),m=e.attributes.uv,g=[p[3],p[2],p[0],p[1]],v=[u[3],u[2],u[0],u[1]],_=[h[3],h[2],h[0],h[1]],y=[c[0],c[1],c[3],c[2]],M=[d[3],d[2],d[0],d[1]],S=[f[3],f[2],f[0],f[1]],b=[];for(let e of[g,v,_,y,M,S])for(let t of e)b.push(t.x,t.y);m.set(new Float32Array(b)),m.needsUpdate=!0}function sG(e,t,i,r,a,n){sV(e,t,i,r,a,n,64,64)}function sW(e,t,i,r,a,n){sV(e,t,i,r,a,n,64,32)}class sj extends n7{constructor(e,t){super(),sH(this,"innerLayer",void 0),sH(this,"outerLayer",void 0),this.innerLayer=e,this.outerLayer=t,e.name="inner",t.name="outer"}}class sq extends n7{get map(){return this._map}set map(e){this._map=e,this.layer1Material.map=e,this.layer1Material.needsUpdate=!0,this.layer1MaterialBiased.map=e,this.layer1MaterialBiased.needsUpdate=!0,this.layer2Material.map=e,this.layer2Material.needsUpdate=!0,this.layer2MaterialBiased.map=e,this.layer2MaterialBiased.needsUpdate=!0}get modelType(){return this.slim?"slim":"default"}set modelType(e){this.slim="slim"===e,this.modelListeners.forEach(e=>e())}getBodyParts(){return this.children.filter(e=>e instanceof sj)}setInnerLayerVisible(e){this.getBodyParts().forEach(t=>t.innerLayer.visible=e)}setOuterLayerVisible(e){this.getBodyParts().forEach(t=>t.outerLayer.visible=e)}resetJoints(){this.head.rotation.set(0,0,0),this.leftArm.rotation.set(0,0,0),this.rightArm.rotation.set(0,0,0),this.leftLeg.rotation.set(0,0,0),this.rightLeg.rotation.set(0,0,0),this.body.rotation.set(0,0,0),this.head.position.y=0,this.body.position.y=-6,this.body.position.z=0,this.rightArm.position.x=-5,this.rightArm.position.y=-2,this.rightArm.position.z=0,this.leftArm.position.x=5,this.leftArm.position.y=-2,this.leftArm.position.z=0,this.rightLeg.position.x=-1.9,this.rightLeg.position.y=-12,this.rightLeg.position.z=-.1,this.leftLeg.position.x=1.9,this.leftLeg.position.y=-12,this.leftLeg.position.z=-.1}constructor(){super(),sH(this,"head",void 0),sH(this,"body",void 0),sH(this,"rightArm",void 0),sH(this,"leftArm",void 0),sH(this,"rightLeg",void 0),sH(this,"leftLeg",void 0),sH(this,"modelListeners",[]),sH(this,"slim",!1),sH(this,"_map",null),sH(this,"layer1Material",void 0),sH(this,"layer1MaterialBiased",void 0),sH(this,"layer2Material",void 0),sH(this,"layer2MaterialBiased",void 0),this.layer1Material=new sE({side:0}),this.layer2Material=new sE({side:2,transparent:!0,alphaTest:1e-5}),this.layer1MaterialBiased=this.layer1Material.clone(),this.layer1MaterialBiased.polygonOffset=!0,this.layer1MaterialBiased.polygonOffsetFactor=1,this.layer1MaterialBiased.polygonOffsetUnits=1,this.layer2MaterialBiased=this.layer2Material.clone(),this.layer2MaterialBiased.polygonOffset=!0,this.layer2MaterialBiased.polygonOffsetFactor=1,this.layer2MaterialBiased.polygonOffsetUnits=1;let e=new tN(8,8,8);sG(e,0,0,8,8,8);let t=new tU(e,this.layer1Material),i=new tN(9,9,9);sG(i,32,0,8,8,8);let r=new tU(i,this.layer2Material);this.head=new sj(t,r),this.head.name="head",this.head.add(t,r),t.position.y=4,r.position.y=4,this.add(this.head);let a=new tN(8,12,4);sG(a,16,16,8,12,4);let n=new tU(a,this.layer1Material),s=new tN(8.5,12.5,4.5);sG(s,16,32,8,12,4);let o=new tU(s,this.layer2Material);this.body=new sj(n,o),this.body.name="body",this.body.add(n,o),this.body.position.y=-6,this.add(this.body);let l=new tN,h=new tU(l,this.layer1MaterialBiased);this.modelListeners.push(()=>{h.scale.x=this.slim?3:4,h.scale.y=12,h.scale.z=4,sG(l,40,16,this.slim?3:4,12,4)});let c=new tN,u=new tU(c,this.layer2MaterialBiased);this.modelListeners.push(()=>{u.scale.x=this.slim?3.5:4.5,u.scale.y=12.5,u.scale.z=4.5,sG(c,40,32,this.slim?3:4,12,4)});let d=new n7;d.add(h,u),this.modelListeners.push(()=>{d.position.x=this.slim?-.5:-1}),d.position.y=-4,this.rightArm=new sj(h,u),this.rightArm.name="rightArm",this.rightArm.add(d),this.rightArm.position.x=-5,this.rightArm.position.y=-2,this.add(this.rightArm);let p=new tN,f=new tU(p,this.layer1MaterialBiased);this.modelListeners.push(()=>{f.scale.x=this.slim?3:4,f.scale.y=12,f.scale.z=4,sG(p,32,48,this.slim?3:4,12,4)});let m=new tN,g=new tU(m,this.layer2MaterialBiased);this.modelListeners.push(()=>{g.scale.x=this.slim?3.5:4.5,g.scale.y=12.5,g.scale.z=4.5,sG(m,48,48,this.slim?3:4,12,4)});let v=new n7;v.add(f,g),this.modelListeners.push(()=>{v.position.x=this.slim?.5:1}),v.position.y=-4,this.leftArm=new sj(f,g),this.leftArm.name="leftArm",this.leftArm.add(v),this.leftArm.position.x=5,this.leftArm.position.y=-2,this.add(this.leftArm);let _=new tN(4,12,4);sG(_,0,16,4,12,4);let x=new tU(_,this.layer1MaterialBiased),y=new tN(4.5,12.5,4.5);sG(y,0,32,4,12,4);let M=new tU(y,this.layer2MaterialBiased),S=new n7;S.add(x,M),S.position.y=-6,this.rightLeg=new sj(x,M),this.rightLeg.name="rightLeg",this.rightLeg.add(S),this.rightLeg.position.x=-1.9,this.rightLeg.position.y=-12,this.rightLeg.position.z=-.1,this.add(this.rightLeg);let b=new tN(4,12,4);sG(b,16,48,4,12,4);let w=new tU(b,this.layer1MaterialBiased),T=new tN(4.5,12.5,4.5);sG(T,0,48,4,12,4);let E=new tU(T,this.layer2MaterialBiased),A=new n7;A.add(w,E),A.position.y=-6,this.leftLeg=new sj(w,E),this.leftLeg.name="leftLeg",this.leftLeg.add(A),this.leftLeg.position.x=1.9,this.leftLeg.position.y=-12,this.leftLeg.position.z=-.1,this.add(this.leftLeg),this.modelType="default"}}class sX extends n7{get map(){return this.material.map}set map(e){this.material.map=e,this.material.needsUpdate=!0}constructor(){super(),sH(this,"cape",void 0),sH(this,"material",void 0),this.material=new sE({side:2,transparent:!0,alphaTest:1e-5});let e=new tN(10,16,1);sW(e,0,0,10,16,1),this.cape=new tU(e,this.material),this.cape.position.y=-8,this.cape.position.z=.5,this.add(this.cape)}}class sY extends n7{resetJoints(){this.leftWing.rotation.y=.01,this.leftWing.rotation.z=.2617994,this.updateRightWing()}updateRightWing(){this.rightWing.position.x=-this.leftWing.position.x,this.rightWing.position.y=this.leftWing.position.y,this.rightWing.rotation.x=this.leftWing.rotation.x,this.rightWing.rotation.y=-this.leftWing.rotation.y,this.rightWing.rotation.z=-this.leftWing.rotation.z}get map(){return this.material.map}set map(e){this.material.map=e,this.material.needsUpdate=!0}constructor(){super(),sH(this,"leftWing",void 0),sH(this,"rightWing",void 0),sH(this,"material",void 0),this.material=new sE({side:2,transparent:!0,alphaTest:1e-5});let e=new tN(12,22,4);sW(e,22,0,10,20,2);let t=new tU(e,this.material);t.position.x=-5,t.position.y=-10,t.position.z=-1,this.leftWing=new n7,this.leftWing.add(t),this.add(this.leftWing);let i=new tN(12,22,4);sW(i,22,0,10,20,2);let r=new tU(i,this.material);r.scale.x=-1,r.position.x=5,r.position.y=-10,r.position.z=-1,this.rightWing=new n7,this.rightWing.add(r),this.add(this.rightWing),this.leftWing.position.x=5,this.leftWing.rotation.x=.2617994,this.resetJoints()}}class sZ extends n7{get map(){return this.material.map}set map(e){this.material.map=e,this.material.needsUpdate=!0}constructor(){super(),sH(this,"rightEar",void 0),sH(this,"leftEar",void 0),sH(this,"material",void 0),this.material=new sE({side:0});let e=new tN(8,8,4/3);sV(e,0,0,6,6,1,14,7),this.rightEar=new tU(e,this.material),this.rightEar.name="rightEar",this.rightEar.position.x=-6,this.add(this.rightEar),this.leftEar=new tU(e,this.material),this.leftEar.name="leftEar",this.leftEar.position.x=6,this.add(this.leftEar)}}let sK=10.8*Math.PI/180;class sJ extends n7{get backEquipment(){return this.cape.visible?"cape":this.elytra.visible?"elytra":null}set backEquipment(e){this.cape.visible="cape"===e,this.elytra.visible="elytra"===e}resetJoints(){this.skin.resetJoints(),this.cape.rotation.x=sK,this.cape.position.y=8,this.cape.position.z=-2,this.elytra.position.y=8,this.elytra.position.z=-2,this.elytra.rotation.x=0,this.elytra.resetJoints()}constructor(){super(),sH(this,"skin",void 0),sH(this,"cape",void 0),sH(this,"elytra",void 0),sH(this,"ears",void 0),this.skin=new sq,this.skin.name="skin",this.skin.position.y=8,this.add(this.skin),this.cape=new sX,this.cape.name="cape",this.cape.position.y=8,this.cape.position.z=-2,this.cape.rotation.x=sK,this.cape.rotation.y=Math.PI,this.add(this.cape),this.elytra=new sY,this.elytra.name="elytra",this.elytra.position.y=8,this.elytra.position.z=-2,this.elytra.visible=!1,this.add(this.elytra),this.ears=new sZ,this.ears.name="ears",this.ears.position.y=10,this.ears.position.z=2/3,this.ears.visible=!1,this.skin.head.add(this.ears)}}function sQ(e){return e instanceof HTMLImageElement||e instanceof HTMLVideoElement||e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap||"undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas}function s$(e,t,i,r,a){let n=e.getImageData(t,i,r,a);for(let e=0;ee.clearRect(t*r,i*r,a*r,n*r);a(40,0,8,8),a(48,0,8,8),a(32,8,8,8),a(40,8,8,8),a(48,8,8,8),a(56,8,8,8),i&&(a(4,32,4,4),a(8,32,4,4),a(0,36,4,12),a(4,36,4,12),a(8,36,4,12),a(12,36,4,12),a(20,32,8,4),a(28,32,8,4),a(16,36,4,12),a(20,36,8,12),a(28,36,4,12),a(32,36,8,12),a(44,32,4,4),a(48,32,4,4),a(40,36,4,12),a(44,36,4,12),a(48,36,4,12),a(52,36,12,12),a(4,48,4,4),a(8,48,4,4),a(0,52,4,12),a(4,52,4,12),a(8,52,4,12),a(12,52,4,12),a(52,48,4,4),a(56,48,4,4),a(48,52,4,12),a(52,52,4,12),a(56,52,4,12),a(60,52,4,12))}function s1(e,t){if(t.width!==t.height&&t.width!==2*t.height)throw Error(`Bad skin size: ${t.width}x${t.height}`);let i=t.width/64,r=14*i,a=7*i;e.width=r,e.height=a;let n=e.getContext("2d",{willReadFrequently:!0});n.clearRect(0,0,r,a),n.drawImage(t,24*i,0,r,a,0,0,r,a)}async function s3(e){let t=document.createElement("img");return new Promise((i,r)=>{t.onload=()=>i(t),t.onerror=r,t.crossOrigin="anonymous","string"==typeof e?t.src=e:(void 0!==e.crossOrigin&&(t.crossOrigin=e.crossOrigin),void 0!==e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.src=e.src)})}let s2={type:"change"},s4={type:"start"},s5={type:"end"},s6=new ex,s8=new tK,s7=Math.cos(70*u);class s9 extends h{constructor(e,t){super(),this.object=e,this.domElement=t,this.domElement.style.touchAction="none",this.enabled=!0,this.target=new W,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!0,this.keyPanSpeed=7,this.zoomToCursor=!1,this.autoRotate=!1,this.autoRotateSpeed=2,this.keys={LEFT:"ArrowLeft",UP:"ArrowUp",RIGHT:"ArrowRight",BOTTOM:"ArrowDown"},this.mouseButtons={LEFT:r.ROTATE,MIDDLE:r.DOLLY,RIGHT:r.PAN},this.touches={ONE:a.ROTATE,TWO:a.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this.getPolarAngle=function(){return l.phi},this.getAzimuthalAngle=function(){return l.theta},this.getDistance=function(){return this.object.position.distanceTo(this.target)},this.listenToKeyEvents=function(e){e.addEventListener("keydown",J),this._domElementKeyEvents=e},this.stopListenToKeyEvents=function(){this._domElementKeyEvents.removeEventListener("keydown",J),this._domElementKeyEvents=null},this.saveState=function(){i.target0.copy(i.target),i.position0.copy(i.object.position),i.zoom0=i.object.zoom},this.reset=function(){i.target.copy(i.target0),i.object.position.copy(i.position0),i.object.zoom=i.zoom0,i.object.updateProjectionMatrix(),i.dispatchEvent(s2),i.update(),s=n.NONE},this.update=function(){let t=new W,r=new G().setFromUnitVectors(e.up,new W(0,1,0)),a=r.clone().invert(),d=new W,p=new G,f=new W,m=2*Math.PI;return function(g=null){let v=i.object.position;t.copy(v).sub(i.target),t.applyQuaternion(r),l.setFromVector3(t),i.autoRotate&&s===n.NONE&&C(null!==g?2*Math.PI/60*i.autoRotateSpeed*g:2*Math.PI/60/60*i.autoRotateSpeed),i.enableDamping?(l.theta+=h.theta*i.dampingFactor,l.phi+=h.phi*i.dampingFactor):(l.theta+=h.theta,l.phi+=h.phi);let _=i.minAzimuthAngle,x=i.maxAzimuthAngle;isFinite(_)&&isFinite(x)&&(_<-Math.PI?_+=m:_>Math.PI&&(_-=m),x<-Math.PI?x+=m:x>Math.PI&&(x-=m),_<=x?l.theta=Math.max(_,Math.min(x,l.theta)):l.theta=l.theta>(_+x)/2?Math.max(_,l.theta):Math.min(x,l.theta)),l.phi=Math.max(i.minPolarAngle,Math.min(i.maxPolarAngle,l.phi)),l.makeSafe(),!0===i.enableDamping?i.target.addScaledVector(u,i.dampingFactor):i.target.add(u),i.zoomToCursor&&w||i.object.isOrthographicCamera?l.radius=N(l.radius):l.radius=N(l.radius*c),t.setFromSpherical(l),t.applyQuaternion(a),v.copy(i.target).add(t),i.object.lookAt(i.target),!0===i.enableDamping?(h.theta*=1-i.dampingFactor,h.phi*=1-i.dampingFactor,u.multiplyScalar(1-i.dampingFactor)):(h.set(0,0,0),u.set(0,0,0));let y=!1;if(i.zoomToCursor&&w){let r=null;if(i.object.isPerspectiveCamera){let e=t.length();r=N(e*c);let a=e-r;i.object.position.addScaledVector(S,a),i.object.updateMatrixWorld()}else if(i.object.isOrthographicCamera){let e=new W(b.x,b.y,0);e.unproject(i.object),i.object.zoom=Math.max(i.minZoom,Math.min(i.maxZoom,i.object.zoom/c)),i.object.updateProjectionMatrix(),y=!0;let a=new W(b.x,b.y,0);a.unproject(i.object),i.object.position.sub(a).add(e),i.object.updateMatrixWorld(),r=t.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),i.zoomToCursor=!1;null!==r&&(this.screenSpacePanning?i.target.set(0,0,-1).transformDirection(i.object.matrix).multiplyScalar(r).add(i.object.position):(s6.origin.copy(i.object.position),s6.direction.set(0,0,-1).transformDirection(i.object.matrix),Math.abs(i.object.up.dot(s6.direction))o||8*(1-p.dot(i.object.quaternion))>o||f.distanceToSquared(i.target)>0)&&(i.dispatchEvent(s2),d.copy(i.object.position),p.copy(i.object.quaternion),f.copy(i.target),y=!1,!0)}}(),this.dispose=function(){i.domElement.removeEventListener("contextmenu",Q),i.domElement.removeEventListener("pointerdown",X),i.domElement.removeEventListener("pointercancel",Z),i.domElement.removeEventListener("wheel",K),i.domElement.removeEventListener("pointermove",Y),i.domElement.removeEventListener("pointerup",Z),null!==i._domElementKeyEvents&&(i._domElementKeyEvents.removeEventListener("keydown",J),i._domElementKeyEvents=null)};let i=this,n={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},s=n.NONE,o=1e-6,l=new sB,h=new sB,c=1,u=new W,d=new x,p=new x,f=new x,m=new x,g=new x,v=new x,_=new x,y=new x,M=new x,S=new W,b=new x,w=!1,T=[],E={};function A(){return Math.pow(.95,i.zoomSpeed)}function C(e){h.theta-=e}function L(e){h.phi-=e}let P=function(){let e=new W;return function(t,i){e.setFromMatrixColumn(i,0),e.multiplyScalar(-t),u.add(e)}}(),R=function(){let e=new W;return function(t,r){!0===i.screenSpacePanning?e.setFromMatrixColumn(r,1):(e.setFromMatrixColumn(r,0),e.crossVectors(i.object.up,e)),e.multiplyScalar(t),u.add(e)}}(),D=function(){let e=new W;return function(t,r){let a=i.domElement;if(i.object.isPerspectiveCamera){let n=i.object.position;e.copy(n).sub(i.target);let s=e.length();P(2*t*(s*=Math.tan(i.object.fov/2*Math.PI/180))/a.clientHeight,i.object.matrix),R(2*r*s/a.clientHeight,i.object.matrix)}else i.object.isOrthographicCamera?(P(t*(i.object.right-i.object.left)/i.object.zoom/a.clientWidth,i.object.matrix),R(r*(i.object.top-i.object.bottom)/i.object.zoom/a.clientHeight,i.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),i.enablePan=!1)}}();function I(e){i.object.isPerspectiveCamera||i.object.isOrthographicCamera?c/=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),i.enableZoom=!1)}function U(e){i.object.isPerspectiveCamera||i.object.isOrthographicCamera?c*=e:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),i.enableZoom=!1)}function O(e){if(!i.zoomToCursor)return;w=!0;let t=i.domElement.getBoundingClientRect(),r=e.clientX-t.left,a=e.clientY-t.top,n=t.width,s=t.height;b.x=r/n*2-1,b.y=-(2*(a/s))+1,S.set(b.x,b.y,1).unproject(i.object).sub(i.object.position).normalize()}function N(e){return Math.max(i.minDistance,Math.min(i.maxDistance,e))}function z(e){d.set(e.clientX,e.clientY)}function F(e){m.set(e.clientX,e.clientY)}function k(){if(1===T.length)d.set(T[0].pageX,T[0].pageY);else{let e=.5*(T[0].pageX+T[1].pageX),t=.5*(T[0].pageY+T[1].pageY);d.set(e,t)}}function B(){if(1===T.length)m.set(T[0].pageX,T[0].pageY);else{let e=.5*(T[0].pageX+T[1].pageX),t=.5*(T[0].pageY+T[1].pageY);m.set(e,t)}}function H(){let e=T[0].pageX-T[1].pageX,t=T[0].pageY-T[1].pageY;_.set(0,Math.sqrt(e*e+t*t))}function V(e){if(1==T.length)p.set(e.pageX,e.pageY);else{let t=ee(e),i=.5*(e.pageX+t.x),r=.5*(e.pageY+t.y);p.set(i,r)}f.subVectors(p,d).multiplyScalar(i.rotateSpeed);let t=i.domElement;C(2*Math.PI*f.x/t.clientHeight),L(2*Math.PI*f.y/t.clientHeight),d.copy(p)}function j(e){if(1===T.length)g.set(e.pageX,e.pageY);else{let t=ee(e),i=.5*(e.pageX+t.x),r=.5*(e.pageY+t.y);g.set(i,r)}v.subVectors(g,m).multiplyScalar(i.panSpeed),D(v.x,v.y),m.copy(g)}function q(e){let t=ee(e),r=e.pageX-t.x,a=e.pageY-t.y;y.set(0,Math.sqrt(r*r+a*a)),M.set(0,Math.pow(y.y/_.y,i.zoomSpeed)),I(M.y),_.copy(y)}function X(e){!1!==i.enabled&&(0===T.length&&(i.domElement.setPointerCapture(e.pointerId),i.domElement.addEventListener("pointermove",Y),i.domElement.addEventListener("pointerup",Z)),T.push(e),"touch"===e.pointerType?function(e){switch($(e),T.length){case 1:switch(i.touches.ONE){case a.ROTATE:if(!1===i.enableRotate)return;k(),s=n.TOUCH_ROTATE;break;case a.PAN:if(!1===i.enablePan)return;B(),s=n.TOUCH_PAN;break;default:s=n.NONE}break;case 2:switch(i.touches.TWO){case a.DOLLY_PAN:if(!1===i.enableZoom&&!1===i.enablePan)return;i.enableZoom&&H(),i.enablePan&&B(),s=n.TOUCH_DOLLY_PAN;break;case a.DOLLY_ROTATE:if(!1===i.enableZoom&&!1===i.enableRotate)return;i.enableZoom&&H(),i.enableRotate&&k(),s=n.TOUCH_DOLLY_ROTATE;break;default:s=n.NONE}break;default:s=n.NONE}s!==n.NONE&&i.dispatchEvent(s4)}(e):function(e){let t;switch(e.button){case 0:t=i.mouseButtons.LEFT;break;case 1:t=i.mouseButtons.MIDDLE;break;case 2:t=i.mouseButtons.RIGHT;break;default:t=-1}switch(t){case r.DOLLY:if(!1===i.enableZoom)return;O(e),_.set(e.clientX,e.clientY),s=n.DOLLY;break;case r.ROTATE:if(e.ctrlKey||e.metaKey||e.shiftKey){if(!1===i.enablePan)return;F(e),s=n.PAN}else{if(!1===i.enableRotate)return;z(e),s=n.ROTATE}break;case r.PAN:if(e.ctrlKey||e.metaKey||e.shiftKey){if(!1===i.enableRotate)return;z(e),s=n.ROTATE}else{if(!1===i.enablePan)return;F(e),s=n.PAN}break;default:s=n.NONE}s!==n.NONE&&i.dispatchEvent(s4)}(e))}function Y(e){!1!==i.enabled&&("touch"===e.pointerType?function(e){switch($(e),s){case n.TOUCH_ROTATE:if(!1===i.enableRotate)return;V(e),i.update();break;case n.TOUCH_PAN:if(!1===i.enablePan)return;j(e),i.update();break;case n.TOUCH_DOLLY_PAN:if(!1===i.enableZoom&&!1===i.enablePan)return;i.enableZoom&&q(e),i.enablePan&&j(e),i.update();break;case n.TOUCH_DOLLY_ROTATE:if(!1===i.enableZoom&&!1===i.enableRotate)return;i.enableZoom&&q(e),i.enableRotate&&V(e),i.update();break;default:s=n.NONE}}(e):function(e){switch(s){case n.ROTATE:if(!1===i.enableRotate)return;!function(e){p.set(e.clientX,e.clientY),f.subVectors(p,d).multiplyScalar(i.rotateSpeed);let t=i.domElement;C(2*Math.PI*f.x/t.clientHeight),L(2*Math.PI*f.y/t.clientHeight),d.copy(p),i.update()}(e);break;case n.DOLLY:if(!1===i.enableZoom)return;y.set(e.clientX,e.clientY),M.subVectors(y,_),M.y>0?I(A()):M.y<0&&U(A()),_.copy(y),i.update();break;case n.PAN:if(!1===i.enablePan)return;g.set(e.clientX,e.clientY),v.subVectors(g,m).multiplyScalar(i.panSpeed),D(v.x,v.y),m.copy(g),i.update()}}(e))}function Z(e){(function(e){delete E[e.pointerId];for(let t=0;t0&&I(A()),i.update(),i.dispatchEvent(s5))}function J(e){!1!==i.enabled&&!1!==i.enablePan&&function(e){let t=!1;switch(e.code){case i.keys.UP:e.ctrlKey||e.metaKey||e.shiftKey?L(2*Math.PI*i.rotateSpeed/i.domElement.clientHeight):D(0,i.keyPanSpeed),t=!0;break;case i.keys.BOTTOM:e.ctrlKey||e.metaKey||e.shiftKey?L(-2*Math.PI*i.rotateSpeed/i.domElement.clientHeight):D(0,-i.keyPanSpeed),t=!0;break;case i.keys.LEFT:e.ctrlKey||e.metaKey||e.shiftKey?C(2*Math.PI*i.rotateSpeed/i.domElement.clientHeight):D(i.keyPanSpeed,0),t=!0;break;case i.keys.RIGHT:e.ctrlKey||e.metaKey||e.shiftKey?C(-2*Math.PI*i.rotateSpeed/i.domElement.clientHeight):D(-i.keyPanSpeed,0),t=!0}t&&(e.preventDefault(),i.update())}(e)}function Q(e){!1!==i.enabled&&e.preventDefault()}function $(e){let t=E[e.pointerId];void 0===t&&(t=new x,E[e.pointerId]=t),t.set(e.pageX,e.pageY)}function ee(e){let t=e.pointerId===T[0].pointerId?T[1]:T[0];return E[t.pointerId]}i.domElement.addEventListener("contextmenu",Q),i.domElement.addEventListener("pointerdown",X),i.domElement.addEventListener("pointercancel",Z),i.domElement.addEventListener("wheel",K,{passive:!1}),this.update()}}let oe={name:"CopyShader",uniforms:{tDiffuse:{value:null},opacity:{value:1}},vertexShader:"varying vec2 vUv;void main(){vUv=uv;gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);}",fragmentShader:"uniform float opacity;uniform sampler2D tDiffuse;varying vec2 vUv;void main(){vec4 texel=texture2D(tDiffuse,vUv);gl_FragColor=opacity*texel;}"};class ot{constructor(){this.isPass=!0,this.enabled=!0,this.needsSwap=!0,this.clear=!1,this.renderToScreen=!1}setSize(){}render(){console.error("THREE.Pass: .render() must be implemented in derived pass.")}dispose(){}}let oi=new al(-1,1,1,-1,0,1),or=new tg;or.setAttribute("position",new tl([-1,3,0,-1,-1,0,3,-1,0],3)),or.setAttribute("uv",new tl([0,2,0,0,2,0],2));class oa{constructor(e){this._mesh=new tU(or,e)}dispose(){this._mesh.geometry.dispose()}render(e){e.render(this._mesh,oi)}get material(){return this._mesh.material}set material(e){this._mesh.material=e}}class on extends ot{constructor(e,t){super(),this.textureID=void 0!==t?t:"tDiffuse",e instanceof tH?(this.uniforms=e.uniforms,this.material=e):e&&(this.uniforms=tB.clone(e.uniforms),this.material=new tH({name:void 0!==e.name?e.name:"unspecified",defines:Object.assign({},e.defines),uniforms:this.uniforms,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader})),this.fsQuad=new oa(this.material)}render(e,t,i){this.uniforms[this.textureID]&&(this.uniforms[this.textureID].value=i.texture),this.fsQuad.material=this.material,this.renderToScreen?(e.setRenderTarget(null),this.fsQuad.render(e)):(e.setRenderTarget(t),this.clear&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),this.fsQuad.render(e))}dispose(){this.material.dispose(),this.fsQuad.dispose()}}class os extends ot{constructor(e,t){super(),this.scene=e,this.camera=t,this.clear=!0,this.needsSwap=!1,this.inverse=!1}render(e,t,i){let r,a;let n=e.getContext(),s=e.state;s.buffers.color.setMask(!1),s.buffers.depth.setMask(!1),s.buffers.color.setLocked(!0),s.buffers.depth.setLocked(!0),this.inverse?(r=0,a=1):(r=1,a=0),s.buffers.stencil.setTest(!0),s.buffers.stencil.setOp(n.REPLACE,n.REPLACE,n.REPLACE),s.buffers.stencil.setFunc(n.ALWAYS,r,4294967295),s.buffers.stencil.setClear(a),s.buffers.stencil.setLocked(!0),e.setRenderTarget(i),this.clear&&e.clear(),e.render(this.scene,this.camera),e.setRenderTarget(t),this.clear&&e.clear(),e.render(this.scene,this.camera),s.buffers.color.setLocked(!1),s.buffers.depth.setLocked(!1),s.buffers.color.setMask(!0),s.buffers.depth.setMask(!0),s.buffers.stencil.setLocked(!1),s.buffers.stencil.setFunc(n.EQUAL,1,4294967295),s.buffers.stencil.setOp(n.KEEP,n.KEEP,n.KEEP),s.buffers.stencil.setLocked(!0)}}class oo extends ot{constructor(){super(),this.needsSwap=!1}render(e){e.state.buffers.stencil.setLocked(!1),e.state.buffers.stencil.setTest(!1)}}class ol{constructor(e,t){if(this.renderer=e,this._pixelRatio=e.getPixelRatio(),void 0===t){let i=e.getSize(new x);this._width=i.width,this._height=i.height,(t=new H(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:1016})).texture.name="EffectComposer.rt1"}else this._width=t.width,this._height=t.height;this.renderTarget1=t,this.renderTarget2=t.clone(),this.renderTarget2.texture.name="EffectComposer.rt2",this.writeBuffer=this.renderTarget1,this.readBuffer=this.renderTarget2,this.renderToScreen=!0,this.passes=[],this.copyPass=new on(oe),this.copyPass.material.blending=0,this.clock=new sF}swapBuffers(){let e=this.readBuffer;this.readBuffer=this.writeBuffer,this.writeBuffer=e}addPass(e){this.passes.push(e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}insertPass(e,t){this.passes.splice(t,0,e),e.setSize(this._width*this._pixelRatio,this._height*this._pixelRatio)}removePass(e){let t=this.passes.indexOf(e);-1!==t&&this.passes.splice(t,1)}isLastEnabledPass(e){for(let t=e+1;t0.;if(abs(relativeVContrast)<.3){vec2 dirToEdge;dirToEdge.x=contrastE>contrastW?1.:-1.;dirToEdge.y=contrastS>contrastN?1.:-1.;vec4 rgbaAlongH=FxaaTexOff(tex,posM,vec2(dirToEdge.x,-dirToEdge.y),fxaaQualityRcpFrame.xy);float matchAlongH=contrast(rgbaM,rgbaAlongH);vec4 rgbaAlongV=FxaaTexOff(tex,posM,vec2(-dirToEdge.x,dirToEdge.y),fxaaQualityRcpFrame.xy);float matchAlongV=contrast(rgbaM,rgbaAlongV);relativeVContrast=matchAlongV-matchAlongH;relativeVContrast*=fxaaQualityinvEdgeThreshold;if(abs(relativeVContrast)<.3){return mix(rgbaM,(rgbaN+rgbaS+rgbaE+rgbaW)*.25,.4);}horzSpan=relativeVContrast>0.;}if(!horzSpan)rgbaN=rgbaW;if(!horzSpan)rgbaS=rgbaE;bool pairN=contrast(rgbaM,rgbaN)>contrast(rgbaM,rgbaS);if(!pairN)rgbaN=rgbaS;vec2 offNP;offNP.x=(!horzSpan)?0.0:fxaaQualityRcpFrame.x;offNP.y=(horzSpan)?0.0:fxaaQualityRcpFrame.y;bool doneN=false;bool doneP=false;float nDist=0.;float pDist=0.;vec2 posN=posM;vec2 posP=posM;int iterationsUsed=0;int iterationsUsedN=0;int iterationsUsedP=0;for(int i=0;icontrast(rgbaEndN,rgbaN);iterationsUsedN=i;}if(!doneP){pDist+=increment;posP=posM-offNP*pDist;vec4 rgbaEndP=FxaaTexTop(tex,posP.xy);doneP=contrast(rgbaEndP,rgbaM)>contrast(rgbaEndP,rgbaN);iterationsUsedP=i;}if(doneN||doneP)break;}if(!doneP&&!doneN)return rgbaM;float dist=min(doneN?float(iterationsUsedN)/float(NUM_SAMPLES-1):1.,doneP?float(iterationsUsedP)/float(NUM_SAMPLES-1):1.);dist=pow(dist,.5);dist=1.-dist;return mix(rgbaM,rgbaN,dist*.5);}void main(){const float edgeDetectionQuality=.2;const float invEdgeDetectionQuality=1./edgeDetectionQuality;gl_FragColor=FxaaPixelShader(vUv,tDiffuse,resolution,edgeDetectionQuality,invEdgeDetectionQuality);}`};function ou(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}class od extends sb{async loadAndPaint(){await document.fonts.load(this.font,this.text),this.paint()}paint(){let e=document.createElement("canvas"),t=e.getContext("2d");t.font=this.font;let i=t.measureText(this.text);e.width=this.margin[3]+i.actualBoundingBoxLeft+i.actualBoundingBoxRight+this.margin[1],e.height=this.margin[0]+i.actualBoundingBoxAscent+i.actualBoundingBoxDescent+this.margin[2],(t=e.getContext("2d")).font=this.font,t.fillStyle=this.backgroundStyle,t.fillRect(0,0,e.width,e.height),t.fillStyle=this.textStyle,t.fillText(this.text,this.margin[3]+i.actualBoundingBoxLeft,this.margin[0]+i.actualBoundingBoxAscent);let r=new sT(e);r.magFilter=1003,r.minFilter=1003,this.textMaterial.map=r,this.textMaterial.needsUpdate=!0,this.scale.x=e.width/e.height*this.height,this.scale.y=this.height}constructor(e="",t={}){let i=new sc({transparent:!0,alphaTest:1e-5});super(i),ou(this,"painted",void 0),ou(this,"text",void 0),ou(this,"font",void 0),ou(this,"margin",void 0),ou(this,"textStyle",void 0),ou(this,"backgroundStyle",void 0),ou(this,"height",void 0),ou(this,"textMaterial",void 0),this.textMaterial=i,this.text=e,this.font=void 0===t.font?"48px Minecraft":t.font,this.margin=void 0===t.margin?[5,10,5,10]:t.margin,this.textStyle=void 0===t.textStyle?"white":t.textStyle,this.backgroundStyle=void 0===t.backgroundStyle?"rgba(0,0,0,.25)":t.backgroundStyle,this.height=void 0===t.height?4:t.height;let r=void 0===t.repaintAfterLoaded||t.repaintAfterLoaded;r&&!document.fonts.check(this.font,this.text)?(this.paint(),this.painted=this.loadAndPaint()):(this.paint(),this.painted=Promise.resolve())}}function op(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function of(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}class om{update(e,t){if(this.paused)return;let i=t*this.speed;this.animate(e,i),this.animationObjects.forEach((t,i)=>{let r=this.progress0.get(i);t(e,this.progress-r,i)}),this.progress+=i}addAnimation(e){let t=this.currentId++;return this.progress0.set(t,this.progress),this.animationObjects.set(t,e),t}removeAnimation(e){void 0!=e&&(this.animationObjects.delete(e),this.progress0.delete(e))}constructor(){of(this,"speed",1),of(this,"paused",!1),of(this,"progress",0),of(this,"currentId",0),of(this,"progress0",new Map),of(this,"animationObjects",new Map)}}e.BodyPart=sj,e.CapeObject=sX,e.CrouchAnimation=class extends om{addHitAnimation(e=this.speed){this.isRunningHitAnimation=!0,this.hitAnimationSpeed=e}animate(e){let t=8*this.progress;if(0===t&&(this.isCrouched=void 0),this.runOnce){var i;t=(i=t)<=-1?-1:i>=1?1:i}this.showProgress||(t=Math.floor(t)),e.skin.body.rotation.x=.4537860552*Math.abs(Math.sin(t*Math.PI/2)),e.skin.body.position.z=1.3256181*Math.abs(Math.sin(t*Math.PI/2))-3.4500310377*Math.abs(Math.sin(t*Math.PI/2)),e.skin.body.position.y=-6-2.103677462*Math.abs(Math.sin(t*Math.PI/2)),e.cape.position.y=8-1.851236166577372*Math.abs(Math.sin(t*Math.PI/2)),e.cape.rotation.x=10.8*Math.PI/180+.294220265771*Math.abs(Math.sin(t*Math.PI/2)),e.cape.position.z=-2+3.786619432*Math.abs(Math.sin(t*Math.PI/2))-3.4500310377*Math.abs(Math.sin(t*Math.PI/2)),e.elytra.position.x=e.cape.position.x,e.elytra.position.y=e.cape.position.y,e.elytra.position.z=e.cape.position.z,e.elytra.rotation.x=e.cape.rotation.x-10.8*Math.PI/180;let r=this.progress/this.speed;if(1===Math.abs(Math.sin(t*Math.PI/2))||this.showProgress&&Math.floor(Math.abs(t))%2==0?(this.erp=this.isCrouched?this.erp:r,this.isCrouched=!0,e.elytra.leftWing.rotation.z=.26179944+.4582006*Math.abs(Math.sin(Math.min(r-this.erp,1)*Math.PI/2)),e.elytra.leftWing.rotation.y=.3*Math.abs(Math.sin(Math.min(r-this.erp,1)*Math.PI/2)),e.elytra.updateRightWing()):void 0!==this.isCrouched&&(this.erp=this.isCrouched?r:this.erp,e.elytra.leftWing.rotation.z=.72-.4582006*Math.abs(Math.sin(Math.min(r-this.erp,1)*Math.PI/2)),e.elytra.leftWing.rotation.y=.3-.3*Math.abs(Math.sin(Math.min(r-this.erp,1)*Math.PI/2)),e.elytra.updateRightWing(),this.isCrouched=!1),e.skin.head.position.y=-3.618325234674*Math.abs(Math.sin(t*Math.PI/2)),e.skin.leftArm.position.z=3.618325234674*Math.abs(Math.sin(t*Math.PI/2))-3.4500310377*Math.abs(Math.sin(t*Math.PI/2)),e.skin.rightArm.position.z=e.skin.leftArm.position.z,e.skin.leftArm.rotation.x=.410367746202*Math.abs(Math.sin(t*Math.PI/2)),e.skin.rightArm.rotation.x=e.skin.leftArm.rotation.x,e.skin.leftArm.rotation.z=.1,e.skin.rightArm.rotation.z=-e.skin.leftArm.rotation.z,e.skin.leftArm.position.y=-2-2.53943318*Math.abs(Math.sin(t*Math.PI/2)),e.skin.rightArm.position.y=e.skin.leftArm.position.y,e.skin.rightLeg.position.z=-3.4500310377*Math.abs(Math.sin(t*Math.PI/2)),e.skin.leftLeg.position.z=e.skin.rightLeg.position.z,this.isRunningHitAnimation){let t=this.progress,i=18*this.progress*this.hitAnimationSpeed/this.speed;0==this.speed&&(i=0);let r=1===Math.abs(Math.sin(t*Math.PI/2));e.skin.rightArm.rotation.x=-.4537860552+2*Math.sin(i+Math.PI)*.3-(r?.4537860552:0),e.skin.rightArm.rotation.z=-(.403*Math.cos(i))+(.01*Math.PI+.06),e.skin.body.rotation.y=-(.06*Math.cos(i)),e.skin.leftArm.rotation.x=.077*Math.sin(i+Math.PI)+(r?.47:0),e.skin.leftArm.rotation.z=-(.015*Math.cos(i))+.13-(r?0:.05),r||(e.skin.leftArm.position.z=.3*Math.cos(i),e.skin.leftArm.position.x=5-.05*Math.cos(i))}}constructor(...e){super(...e),of(this,"showProgress",!1),of(this,"runOnce",!1),of(this,"isRunningHitAnimation",!1),of(this,"hitAnimationSpeed",1),of(this,"erp",0),of(this,"isCrouched",void 0)}},e.EarsObject=sZ,e.ElytraObject=sY,e.FlyingAnimation=class extends om{animate(e){var t;let i=this.progress>0?20*this.progress:0,r=(t=i*i/100)<=0?0:t>=1?1:t;e.rotation.x=r*Math.PI/2,e.skin.head.rotation.x=r>.5?Math.PI/4-e.rotation.x:0;let a=.25*Math.PI*r;e.skin.leftArm.rotation.z=a,e.skin.rightArm.rotation.z=-a;let n=Math.PI/2,s=Math.pow(.9,i);e.elytra.leftWing.rotation.x=.34906584+-.08726644*s,e.elytra.leftWing.rotation.z=n+s*(.2617994-n),e.elytra.updateRightWing()}},e.FunctionAnimation=class extends om{animate(e,t){this.fn(e,this.progress,t)}constructor(e){super(),of(this,"fn",void 0),this.fn=e}},e.HitAnimation=class extends om{animate(e){let t=18*this.progress;e.skin.rightArm.rotation.x=-.9075721104+2*Math.sin(t+Math.PI)*.3,e.skin.rightArm.rotation.z=-(.403*Math.cos(t))+(.01*Math.PI+.06),e.skin.body.rotation.y=-(.06*Math.cos(t)),e.skin.leftArm.rotation.x=.077*Math.sin(t+Math.PI),e.skin.leftArm.rotation.z=-(.015*Math.cos(t))+.13-.05,e.skin.leftArm.position.z=.3*Math.cos(t),e.skin.leftArm.position.x=5-.05*Math.cos(t)}},e.IdleAnimation=class extends om{animate(e){let t=2*this.progress,i=.02*Math.PI;e.skin.leftArm.rotation.z=.03*Math.cos(t)+i,e.skin.rightArm.rotation.z=.03*Math.cos(t+Math.PI)-i,e.cape.rotation.x=.01*Math.sin(t)+.06*Math.PI}},e.NameTagObject=od,e.PlayerAnimation=om,e.PlayerObject=sJ,e.RunningAnimation=class extends om{animate(e){let t=15*this.progress+.5*Math.PI;e.skin.leftLeg.rotation.x=1.3*Math.cos(t+Math.PI),e.skin.rightLeg.rotation.x=1.3*Math.cos(t),e.skin.leftArm.rotation.x=1.5*Math.cos(t),e.skin.rightArm.rotation.x=1.5*Math.cos(t+Math.PI);let i=.1*Math.PI;e.skin.leftArm.rotation.z=.1*Math.cos(t)+i,e.skin.rightArm.rotation.z=.1*Math.cos(t+Math.PI)-i,e.position.y=Math.cos(2*t),e.position.x=.15*Math.cos(t),e.rotation.z=.01*Math.cos(t+Math.PI),e.cape.rotation.x=.1*Math.sin(2*t)+.3*Math.PI}},e.SkinObject=sq,e.SkinViewer=class{updateComposerSize(){this.composer.setSize(this.width,this.height);let e=this.renderer.getPixelRatio();this.composer.setPixelRatio(e),this.fxaaPass.material.uniforms.resolution.value.x=1/(this.width*e),this.fxaaPass.material.uniforms.resolution.value.y=1/(this.height*e)}recreateSkinTexture(){null!==this.skinTexture&&this.skinTexture.dispose(),this.skinTexture=new sT(this.skinCanvas),this.skinTexture.magFilter=1003,this.skinTexture.minFilter=1003,this.playerObject.skin.map=this.skinTexture}recreateCapeTexture(){null!==this.capeTexture&&this.capeTexture.dispose(),this.capeTexture=new sT(this.capeCanvas),this.capeTexture.magFilter=1003,this.capeTexture.minFilter=1003,this.playerObject.cape.map=this.capeTexture,this.playerObject.elytra.map=this.capeTexture}recreateEarsTexture(){null!==this.earsTexture&&this.earsTexture.dispose(),this.earsTexture=new sT(this.earsCanvas),this.earsTexture.magFilter=1003,this.earsTexture.minFilter=1003,this.playerObject.ears.map=this.earsTexture}loadSkin(e,t={}){if(null===e)this.resetSkin();else{if(!sQ(e))return s3(e).then(e=>this.loadSkin(e,t));(function(e,t){let i=!1;if(t.width!==t.height){if(t.width===2*t.height)i=!0;else throw Error(`Bad skin size: ${t.width}x${t.height}`)}let r=e.getContext("2d",{willReadFrequently:!0});if(i){let i=t.width;e.width=i,e.height=i,r.clearRect(0,0,i,i),r.drawImage(t,0,0,i,i/2),function(e,t){e.save(),e.scale(-1,1);let i=t/64,r=(t,r,a,n,s,o)=>e.drawImage(e.canvas,t*i,r*i,a*i,n*i,-s*i,o*i,-a*i,n*i);r(4,16,4,4,20,48),r(8,16,4,4,24,48),r(0,20,4,12,24,52),r(4,20,4,12,20,52),r(8,20,4,12,16,52),r(12,20,4,12,28,52),r(44,16,4,4,36,48),r(48,16,4,4,40,48),r(40,20,4,12,40,52),r(44,20,4,12,36,52),r(48,20,4,12,32,52),r(52,20,4,12,44,52),e.restore()}(r,i),s0(r,e.width,!1)}else e.width=t.width,e.height=t.height,r.clearRect(0,0,t.width,t.height),r.drawImage(t,0,0,e.width,e.height),s0(r,e.width,!0)})(this.skinCanvas,e),this.recreateSkinTexture(),void 0===t.model||"auto-detect"===t.model?this.playerObject.skin.modelType=function(e){let t=e.width/64,i=e.getContext("2d",{willReadFrequently:!0}),r=(e,r,a,n)=>s$(i,e*t,r*t,a*t,n*t),a=(e,r,a,n)=>(function(e,t,i,r,a){let n=e.getImageData(t,i,r,a);for(let e=0;e(function(e,t,i,r,a){let n=e.getImageData(t,i,r,a);for(let e=0;ethis.loadCape(e,t));(function(e,t){let i=function(e){if(e.width===2*e.height)return e.width/64;if(17*e.width==22*e.height)return e.width/22;if(11*e.width==23*e.height)return e.width/46;throw Error(`Bad cape size: ${e.width}x${e.height}`)}(t);e.width=64*i,e.height=32*i;let r=e.getContext("2d",{willReadFrequently:!0});r.clearRect(0,0,e.width,e.height),r.drawImage(t,0,0,t.width,t.height)})(this.capeCanvas,e),this.recreateCapeTexture(),!1!==t.makeVisible&&(this.playerObject.backEquipment=void 0===t.backEquipment?"cape":t.backEquipment)}}resetCape(){this.playerObject.backEquipment=null,this.playerObject.cape.map=null,this.playerObject.elytra.map=null,null!==this.capeTexture&&(this.capeTexture.dispose(),this.capeTexture=null)}loadEars(e,t={}){if(null===e)this.resetEars();else{if(!sQ(e))return s3(e).then(e=>this.loadEars(e,t));"skin"===t.textureType?s1(this.earsCanvas,e):function(e,t){let i=function(e){if(e.width===2*e.height&&e.height%7==0)return e.height/7;throw Error(`Bad ears size: ${e.width}x${e.height}`)}(t);e.width=14*i,e.height=7*i;let r=e.getContext("2d",{willReadFrequently:!0});r.clearRect(0,0,e.width,e.height),r.drawImage(t,0,0,t.width,t.height)}(this.earsCanvas,e),this.recreateEarsTexture(),!1!==t.makeVisible&&(this.playerObject.ears.visible=!0,this._nameTag&&(this.nameTagYOffset=25,this._nameTag.position.y=this.nameTagYOffset))}}resetEars(){this.playerObject.ears.visible=!1,this._nameTag&&(this.nameTagYOffset=20,this._nameTag.position.y=this.nameTagYOffset),this.playerObject.ears.map=null,null!==this.earsTexture&&(this.earsTexture.dispose(),this.earsTexture=null)}loadPanorama(e){return this.loadBackground(e,303)}loadBackground(e,t){if(!sQ(e))return s3(e).then(e=>this.loadBackground(e,t));null!==this.backgroundTexture&&this.backgroundTexture.dispose(),this.backgroundTexture=new F,this.backgroundTexture.image=e,void 0!==t&&(this.backgroundTexture.mapping=t),this.backgroundTexture.needsUpdate=!0,this.scene.background=this.backgroundTexture}draw(){let e=this.clock.getDelta();null!==this._animation&&(this._animation.update(this.playerObject,e),this._nameTag&&(this._nameTag.position.y=this.playerObject.skin.head.getWorldPosition(new W).y+this.nameTagYOffset-8)),this.autoRotate&&!(this.controls.enableRotate&&this.isUserRotating)&&(this.playerWrapper.rotation.y+=e*this.autoRotateSpeed),this.controls.update(),this.render(),this.animationID=window.requestAnimationFrame(()=>this.draw())}render(){this.composer.render()}setSize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t),this.updateComposerSize()}dispose(){this._disposed=!0,this.canvas.removeEventListener("webglcontextlost",this.onContextLost,!1),this.canvas.removeEventListener("webglcontextrestored",this.onContextRestored,!1),null!==this.devicePixelRatioQuery&&(this.devicePixelRatioQuery.removeEventListener("change",this.onDevicePixelRatioChange),this.devicePixelRatioQuery=null),null!==this.animationID&&(window.cancelAnimationFrame(this.animationID),this.animationID=null),this.controls.dispose(),this.renderer.dispose(),this.resetSkin(),this.resetCape(),this.resetEars(),this.background=null,this.fxaaPass.fsQuad.dispose()}get disposed(){return this._disposed}get renderPaused(){return this._renderPaused}set renderPaused(e){this._renderPaused=e,this._renderPaused&&null!==this.animationID?(window.cancelAnimationFrame(this.animationID),this.animationID=null,this.clock.stop(),this.clock.autoStart=!0):this._renderPaused||this._disposed||this.renderer.getContext().isContextLost()||null!=this.animationID||(this.animationID=window.requestAnimationFrame(()=>this.draw()))}get width(){return this.renderer.getSize(new x).width}set width(e){this.setSize(e,this.height)}get height(){return this.renderer.getSize(new x).height}set height(e){this.setSize(this.width,e)}get background(){return this.scene.background}set background(e){null===e||e instanceof te||e instanceof F?this.scene.background=e:this.scene.background=new te(e),null!==this.backgroundTexture&&e!==this.backgroundTexture&&(this.backgroundTexture.dispose(),this.backgroundTexture=null)}adjustCameraDistance(){let e=4.5+16.5/Math.tan(this.fov/180*Math.PI/2)/this.zoom;e<10?e=10:e>256&&(e=256),this.camera.position.multiplyScalar(e/this.camera.position.length()),this.camera.updateProjectionMatrix()}resetCameraPose(){this.camera.position.set(0,0,1),this.camera.rotation.set(0,0,0),this.adjustCameraDistance()}get fov(){return this.camera.fov}set fov(e){this.camera.fov=e,this.adjustCameraDistance()}get zoom(){return this._zoom}set zoom(e){this._zoom=e,this.adjustCameraDistance()}get pixelRatio(){return this._pixelRatio}set pixelRatio(e){"match-device"===e?"match-device"!==this._pixelRatio&&(this._pixelRatio=e,this.onDevicePixelRatioChange()):("match-device"===this._pixelRatio&&null!==this.devicePixelRatioQuery&&(this.devicePixelRatioQuery.removeEventListener("change",this.onDevicePixelRatioChange),this.devicePixelRatioQuery=null),this._pixelRatio=e,this.renderer.setPixelRatio(e),this.updateComposerSize())}get animation(){return this._animation}set animation(e){this._animation!==e&&(this.playerObject.resetJoints(),this.playerObject.position.set(0,0,0),this.playerObject.rotation.set(0,0,0),this._nameTag&&(this._nameTag.position.y=this.nameTagYOffset),this.clock.stop(),this.clock.autoStart=!0),null!==e&&(e.progress=0),this._animation=e}get nameTag(){return this._nameTag}set nameTag(e){null!==this._nameTag&&this.playerWrapper.remove(this._nameTag),null!==e&&(e instanceof ej||(e=new od(e)),this.playerWrapper.add(e),this.nameTagYOffset=this.playerObject.ears.visible?25:20,e.position.y=this.nameTagYOffset),this._nameTag=e}constructor(e={}){let t;op(this,"canvas",void 0),op(this,"scene",void 0),op(this,"camera",void 0),op(this,"renderer",void 0),op(this,"controls",void 0),op(this,"playerObject",void 0),op(this,"playerWrapper",void 0),op(this,"globalLight",new sz(16777215,3)),op(this,"cameraLight",new sN(16777215,.6)),op(this,"composer",void 0),op(this,"renderPass",void 0),op(this,"fxaaPass",void 0),op(this,"skinCanvas",void 0),op(this,"capeCanvas",void 0),op(this,"earsCanvas",void 0),op(this,"skinTexture",null),op(this,"capeTexture",null),op(this,"earsTexture",null),op(this,"backgroundTexture",null),op(this,"_disposed",!1),op(this,"_renderPaused",!1),op(this,"_zoom",void 0),op(this,"isUserRotating",!1),op(this,"autoRotate",!1),op(this,"autoRotateSpeed",1),op(this,"_animation",void 0),op(this,"clock",void 0),op(this,"animationID",void 0),op(this,"onContextLost",void 0),op(this,"onContextRestored",void 0),op(this,"_pixelRatio",void 0),op(this,"devicePixelRatioQuery",void 0),op(this,"onDevicePixelRatioChange",void 0),op(this,"_nameTag",null),op(this,"nameTagYOffset",20),this.canvas=void 0===e.canvas?document.createElement("canvas"):e.canvas,this.skinCanvas=document.createElement("canvas"),this.capeCanvas=document.createElement("canvas"),this.earsCanvas=document.createElement("canvas"),this.scene=new ss,this.camera=new tG,this.camera.add(this.cameraLight),this.scene.add(this.camera),this.scene.add(this.globalLight),D.enabled=!1,this.renderer=new sn({canvas:this.canvas,preserveDrawingBuffer:!0===e.preserveDrawingBuffer}),this.onDevicePixelRatioChange=()=>{this.renderer.setPixelRatio(window.devicePixelRatio),this.updateComposerSize(),"match-device"===this._pixelRatio&&(this.devicePixelRatioQuery=matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),this.devicePixelRatioQuery.addEventListener("change",this.onDevicePixelRatioChange,{once:!0}))},void 0===e.pixelRatio||"match-device"===e.pixelRatio?(this._pixelRatio="match-device",this.devicePixelRatioQuery=matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),this.devicePixelRatioQuery.addEventListener("change",this.onDevicePixelRatioChange,{once:!0}),this.renderer.setPixelRatio(window.devicePixelRatio)):(this._pixelRatio=e.pixelRatio,this.devicePixelRatioQuery=null,this.renderer.setPixelRatio(e.pixelRatio)),this.renderer.setClearColor(0,0),this.renderer.capabilities.isWebGL2&&(t=new H(0,0,{depthTexture:new st(0,0,1015)})),this.composer=new ol(this.renderer,t),this.renderPass=new oh(this.scene,this.camera),this.fxaaPass=new on(oc),this.composer.addPass(this.renderPass),this.composer.addPass(this.fxaaPass),this.playerObject=new sJ,this.playerObject.name="player",this.playerObject.skin.visible=!1,this.playerObject.cape.visible=!1,this.playerWrapper=new n7,this.playerWrapper.add(this.playerObject),this.scene.add(this.playerWrapper),this.controls=new s9(this.camera,this.canvas),this.controls.enablePan=!1,this.controls.minDistance=10,this.controls.maxDistance=256,!1===e.enableControls&&(this.controls.enabled=!1),void 0!==e.skin&&this.loadSkin(e.skin,{model:e.model,ears:"current-skin"===e.ears}),void 0!==e.cape&&this.loadCape(e.cape),void 0!==e.ears&&"current-skin"!==e.ears&&this.loadEars(e.ears.source,{textureType:e.ears.textureType}),void 0!==e.width&&(this.width=e.width),void 0!==e.height&&(this.height=e.height),void 0!==e.background&&(this.background=e.background),void 0!==e.panorama&&this.loadPanorama(e.panorama),void 0!==e.nameTag&&(this.nameTag=e.nameTag),this.camera.position.z=1,this._zoom=void 0===e.zoom?.9:e.zoom,this.fov=void 0===e.fov?50:e.fov,this._animation=void 0===e.animation?null:e.animation,this.clock=new sF,!0===e.renderPaused?(this._renderPaused=!0,this.animationID=null):this.animationID=window.requestAnimationFrame(()=>this.draw()),this.onContextLost=e=>{e.preventDefault(),null!==this.animationID&&(window.cancelAnimationFrame(this.animationID),this.animationID=null)},this.onContextRestored=()=>{this.renderer.setClearColor(0,0),this._renderPaused||this._disposed||null!==this.animationID||(this.animationID=window.requestAnimationFrame(()=>this.draw()))},this.canvas.addEventListener("webglcontextlost",this.onContextLost,!1),this.canvas.addEventListener("webglcontextrestored",this.onContextRestored,!1),this.canvas.addEventListener("mousedown",()=>{this.isUserRotating=!0},!1),this.canvas.addEventListener("mouseup",()=>{this.isUserRotating=!1},!1),this.canvas.addEventListener("touchmove",e=>{1===e.touches.length?this.isUserRotating=!0:this.isUserRotating=!1},!1),this.canvas.addEventListener("touchend",()=>{this.isUserRotating=!1},!1)}},e.SwimAnimation=class extends om{animate(e){0===this.progress&&(this.lock=!1);let t=this.progress%1.3,i=t/1.3,r=[0,.5384615384615384,.8461538461538461,1],a=Math.PI/180;function n(e,t,i){let r=new G().setFromAxisAngle(new W(0,0,1),e),a=new G().setFromAxisAngle(new W(0,1,0),t),n=new G().setFromAxisAngle(new W(1,0,0),i);return n.multiply(a).multiply(r)}let s=[{z:180,y:180,x:0},{z:287.2,y:180,x:0},{z:180,y:180,x:90},{z:180,y:180,x:0}].map(e=>n(e.z*a,e.y*a,e.x*a)),o=[{z:-180,y:180,x:0},{z:-287.2,y:180,x:0},{z:-180,y:180,x:90},{z:-180,y:180,x:0}].map(e=>n(e.z*a,e.y*a,e.x*a)),l=function(e){for(let t=0;t=r[t]&&e<=r[t+1])return{i:t,t0:r[t],t1:r[t+1]};return{i:r.length-2,t0:r[r.length-2],t1:r[r.length-1]}}(i),h=(i-l.t0)/(l.t1-l.t0),c=l.i;this.lock||(0==c&&1.3*h<1?(e.position.y=-5*h*1.3,e.rotation.x=1.3*h*Math.PI/2,e.skin.head.rotation.x=-Math.PI/4*h*1.3,e.cape.rotation.x=Math.PI/4*h*1.3):this.lock=!0);let u=new G().copy(s[c]).slerp(s[c+1],h),d=new G().copy(o[c]).slerp(o[c+1],h);e.skin.leftArm.quaternion.copy(u),e.skin.rightArm.quaternion.copy(d);let p=390*a,f=17.2*a,m=f*Math.cos(this.progress*p+Math.PI),g=f*Math.cos(this.progress*p);e.skin.leftLeg.rotation.x=m,e.skin.leftLeg.rotation.y=-.1*a,e.skin.leftLeg.rotation.z=-.1*a,e.skin.rightLeg.rotation.x=g,e.skin.rightLeg.rotation.y=.1*a,e.skin.rightLeg.rotation.z=.1*a}constructor(...e){super(...e),of(this,"lock",!1)}},e.WalkingAnimation=class extends om{animate(e){let t=8*this.progress;e.skin.leftLeg.rotation.x=.5*Math.sin(t),e.skin.rightLeg.rotation.x=.5*Math.sin(t+Math.PI),e.skin.leftArm.rotation.x=.5*Math.sin(t+Math.PI),e.skin.rightArm.rotation.x=.5*Math.sin(t);let i=.02*Math.PI;e.skin.leftArm.rotation.z=.03*Math.cos(t)+i,e.skin.rightArm.rotation.z=.03*Math.cos(t+Math.PI)-i,this.headBobbing?(e.skin.head.rotation.y=.2*Math.sin(t/4),e.skin.head.rotation.x=.1*Math.sin(t/5)):(e.skin.head.rotation.y=0,e.skin.head.rotation.x=0),e.cape.rotation.x=.06*Math.sin(t/1.5)+.06*Math.PI}constructor(...e){super(...e),of(this,"headBobbing",!0)}},e.WaveAnimation=class extends om{animate(e){let t=2*this.progress*Math.PI*.5,i="left"===this.whichArm?e.skin.leftArm:e.skin.rightArm;i.rotation.x=180,i.rotation.z=.5*Math.sin(t)}constructor(e="left"){super(),of(this,"whichArm",void 0),this.whichArm=e}}});//# sourceMappingURL=skinview3d.bundle.js.map