diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c39d7bc..0a2c848 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ on: env: REGISTRY: ghcr.io - IMAGE_NAME: kolyma + IMAGE_NAME: gate IMAGE_AUTHOR: orzklv jobs: diff --git a/Dockerfile b/Dockerfile index 5343fbf..a4a87d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,2 +1,4 @@ FROM nginx + COPY . /usr/share/nginx/html +COPY ./assets/favicon/favicon.ico /usr/share/nginx/html diff --git a/mmd/audios/readme.txt b/assets/audios/readme.txt similarity index 100% rename from mmd/audios/readme.txt rename to assets/audios/readme.txt diff --git a/mmd/audios/wavefile_short.mp3 b/assets/audios/wavefile_short.mp3 similarity index 100% rename from mmd/audios/wavefile_short.mp3 rename to assets/audios/wavefile_short.mp3 diff --git a/favicon.ico b/assets/favicon/favicon.ico similarity index 100% rename from favicon.ico rename to assets/favicon/favicon.ico diff --git a/mmd/miku/eyeM2.bmp b/assets/miku/eyeM2.bmp similarity index 100% rename from mmd/miku/eyeM2.bmp rename to assets/miku/eyeM2.bmp diff --git a/mmd/miku/miku_v2.pmd b/assets/miku/miku_v2.pmd similarity index 100% rename from mmd/miku/miku_v2.pmd rename to assets/miku/miku_v2.pmd diff --git a/mmd/miku/readme.txt b/assets/miku/readme.txt similarity index 100% rename from mmd/miku/readme.txt rename to assets/miku/readme.txt diff --git a/mmd/miku/readme_miku_v2.txt b/assets/miku/readme_miku_v2.txt similarity index 100% rename from mmd/miku/readme_miku_v2.txt rename to assets/miku/readme_miku_v2.txt diff --git a/mmd/vmds/readme.txt b/assets/vmds/readme.txt similarity index 100% rename from mmd/vmds/readme.txt rename to assets/vmds/readme.txt diff --git a/mmd/vmds/readme_wavefile.txt b/assets/vmds/readme_wavefile.txt similarity index 100% rename from mmd/vmds/readme_wavefile.txt rename to assets/vmds/readme_wavefile.txt diff --git a/mmd/vmds/readme_wavefile_camera.txt b/assets/vmds/readme_wavefile_camera.txt similarity index 100% rename from mmd/vmds/readme_wavefile_camera.txt rename to assets/vmds/readme_wavefile_camera.txt diff --git a/mmd/vmds/wavefile_camera.vmd b/assets/vmds/wavefile_camera.vmd similarity index 100% rename from mmd/vmds/wavefile_camera.vmd rename to assets/vmds/wavefile_camera.vmd diff --git a/mmd/vmds/wavefile_v2.vmd b/assets/vmds/wavefile_v2.vmd similarity index 100% rename from mmd/vmds/wavefile_v2.vmd rename to assets/vmds/wavefile_v2.vmd diff --git a/mmd/vpds/01.vpd b/assets/vpds/01.vpd similarity index 100% rename from mmd/vpds/01.vpd rename to assets/vpds/01.vpd diff --git a/mmd/vpds/02.vpd b/assets/vpds/02.vpd similarity index 100% rename from mmd/vpds/02.vpd rename to assets/vpds/02.vpd diff --git a/mmd/vpds/03.vpd b/assets/vpds/03.vpd similarity index 100% rename from mmd/vpds/03.vpd rename to assets/vpds/03.vpd diff --git a/mmd/vpds/04.vpd b/assets/vpds/04.vpd similarity index 100% rename from mmd/vpds/04.vpd rename to assets/vpds/04.vpd diff --git a/mmd/vpds/05.vpd b/assets/vpds/05.vpd similarity index 100% rename from mmd/vpds/05.vpd rename to assets/vpds/05.vpd diff --git a/mmd/vpds/06.vpd b/assets/vpds/06.vpd similarity index 100% rename from mmd/vpds/06.vpd rename to assets/vpds/06.vpd diff --git a/mmd/vpds/07.vpd b/assets/vpds/07.vpd similarity index 100% rename from mmd/vpds/07.vpd rename to assets/vpds/07.vpd diff --git a/mmd/vpds/08.vpd b/assets/vpds/08.vpd similarity index 100% rename from mmd/vpds/08.vpd rename to assets/vpds/08.vpd diff --git a/mmd/vpds/09.vpd b/assets/vpds/09.vpd similarity index 100% rename from mmd/vpds/09.vpd rename to assets/vpds/09.vpd diff --git a/mmd/vpds/10.vpd b/assets/vpds/10.vpd similarity index 100% rename from mmd/vpds/10.vpd rename to assets/vpds/10.vpd diff --git a/mmd/vpds/11.vpd b/assets/vpds/11.vpd similarity index 100% rename from mmd/vpds/11.vpd rename to assets/vpds/11.vpd diff --git a/mmd/vpds/readme.txt b/assets/vpds/readme.txt similarity index 100% rename from mmd/vpds/readme.txt rename to assets/vpds/readme.txt diff --git a/index.html b/index.html index 1b3a04c..d0876d4 100644 --- a/index.html +++ b/index.html @@ -7,16 +7,8 @@ name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" /> - - + + @@ -36,224 +28,17 @@ However, you may enjoy Hatsune Miku dance while being here. - - - - - - + + + - - + diff --git a/jsm/animation/CCDIKSolver.js b/libs/animation/CCDIKSolver.js similarity index 100% rename from jsm/animation/CCDIKSolver.js rename to libs/animation/CCDIKSolver.js diff --git a/jsm/animation/MMDAnimationHelper.js b/libs/animation/MMDAnimationHelper.js similarity index 100% rename from jsm/animation/MMDAnimationHelper.js rename to libs/animation/MMDAnimationHelper.js diff --git a/jsm/animation/MMDPhysics.js b/libs/animation/MMDPhysics.js similarity index 100% rename from jsm/animation/MMDPhysics.js rename to libs/animation/MMDPhysics.js diff --git a/jsm/effects/OutlineEffect.js b/libs/effects/OutlineEffect.js similarity index 100% rename from jsm/effects/OutlineEffect.js rename to libs/effects/OutlineEffect.js diff --git a/jsm/libs/ammo.wasm.js b/libs/libs/ammo.wasm.js similarity index 100% rename from jsm/libs/ammo.wasm.js rename to libs/libs/ammo.wasm.js diff --git a/jsm/libs/ammo.wasm.wasm b/libs/libs/ammo.wasm.wasm similarity index 100% rename from jsm/libs/ammo.wasm.wasm rename to libs/libs/ammo.wasm.wasm diff --git a/jsm/libs/mmdparser.module.js b/libs/libs/mmdparser.module.js similarity index 100% rename from jsm/libs/mmdparser.module.js rename to libs/libs/mmdparser.module.js diff --git a/jsm/loaders/MMDLoader.js b/libs/loaders/MMDLoader.js similarity index 100% rename from jsm/loaders/MMDLoader.js rename to libs/loaders/MMDLoader.js diff --git a/jsm/loaders/TGALoader.js b/libs/loaders/TGALoader.js similarity index 100% rename from jsm/loaders/TGALoader.js rename to libs/loaders/TGALoader.js diff --git a/libs/personal/animation.js b/libs/personal/animation.js new file mode 100644 index 0000000..8558bc6 --- /dev/null +++ b/libs/personal/animation.js @@ -0,0 +1,153 @@ +import * as THREE from "three"; +import { OutlineEffect } from "three/addons/effects/OutlineEffect.js"; +import { MMDLoader } from "three/addons/loaders/MMDLoader.js"; +import { MMDAnimationHelper } from "three/addons/animation/MMDAnimationHelper.js"; + +let mesh, camera, scene, renderer, effect; +let helper; + +let ready = false; + +const clock = new THREE.Clock(); + +const startButton = document.getElementById("startButton"); +startButton.addEventListener("click", function () { +Ammo().then(function () { + init(); + animate(); +}); +}); + +function init() { +const overlay = document.getElementById("overlay"); +// overlay.remove(); + +const container = document.createElement("div"); +document.body.appendChild(container); + +camera = new THREE.PerspectiveCamera( + 45, + window.innerWidth / window.innerHeight, + 1, + 2000, +); + +// scene + +scene = new THREE.Scene(); +scene.background = new THREE.Color(0x000000); + +scene.add(new THREE.PolarGridHelper(30, 0)); + +const listener = new THREE.AudioListener(); +camera.add(listener); +scene.add(camera); + +const ambient = new THREE.AmbientLight(0xaaaaaa, 1); +scene.add(ambient); + +const directionalLight = new THREE.DirectionalLight(0xffffff, 1); +directionalLight.position.set(-1, 1, 1).normalize(); +scene.add(directionalLight); + +// + +renderer = new THREE.WebGLRenderer({ antialias: true }); +renderer.setPixelRatio(window.devicePixelRatio); +renderer.setSize(window.innerWidth, window.innerHeight); +container.appendChild(renderer.domElement); + +effect = new OutlineEffect(renderer); + +// model + +function onProgress(xhr) { + if (xhr.lengthComputable) { + const percentComplete = (xhr.loaded / xhr.total) * 100; + const rounded = Math.round(percentComplete, 2); + console.log("👨🏻‍🚀 " + rounded + "% horny"); + + if (rounded == 100) { + console.log("✨ Max level horniness reached!"); + } + } +} + +const modelFile = "assets/miku/miku_v2.pmd"; +const vmdFiles = ["assets/vmds/wavefile_v2.vmd"]; +const cameraFiles = ["assets/vmds/wavefile_camera.vmd"]; +const audioFile = "assets/audios/wavefile_short.mp3"; +const audioParams = { delayTime: (160 * 1) / 30 }; + +helper = new MMDAnimationHelper(); + +const loader = new MMDLoader(); + +loader.loadWithAnimation( + modelFile, + vmdFiles, + function (mmd) { + mesh = mmd.mesh; + + helper.add(mesh, { + animation: mmd.animation, + physics: true, + }); + + loader.loadAnimation( + cameraFiles, + camera, + function (cameraAnimation) { + helper.add(camera, { + animation: cameraAnimation, + }); + + new THREE.AudioLoader().load( + audioFile, + function (buffer) { + const audio = new THREE.Audio(listener).setBuffer(buffer); + + helper.add(audio, audioParams); + scene.add(mesh); + + ready = true; + }, + onProgress, + null, + ); + }, + onProgress, + null, + ); + }, + onProgress, + null, +); + +// Remove the overlay +overlay.remove(); + +window.addEventListener("resize", onWindowResize); +} + +function onWindowResize() { +camera.aspect = window.innerWidth / window.innerHeight; +camera.updateProjectionMatrix(); + +effect.setSize(window.innerWidth, window.innerHeight); +} + +// + +function animate() { +requestAnimationFrame(animate); +render(); +} + +function render() { +if (ready) { + helper.update(clock.getDelta()); +} + +effect.render(scene, camera); +} \ No newline at end of file diff --git a/libs/personal/ascii.js b/libs/personal/ascii.js new file mode 100644 index 0000000..5ae6224 --- /dev/null +++ b/libs/personal/ascii.js @@ -0,0 +1,44 @@ +const art = [ + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠤⠤⠠⡖⠲⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⡠⠶⣴⣶⣄⠀⠀⠀⢀⣴⣞⣼⣴⣖⣶⣾⡷⣶⣿⣿⣷⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⢸⠀⠀⠀⠙⢟⠛⠴⣶⣿⣿⠟⠙⣍⠑⢌⠙⢵⣝⢿⣽⡮⣎⢿⡦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⢱⡶⣋⠿⣽⣸⡀⠘⣎⢢⡰⣷⢿⣣⠹⣿⢸⣿⢿⠿⡦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⢧⡿⣇⡅⣿⣇⠗⢤⣸⣿⢳⣹⡀⠳⣷⣻⣼⢿⣯⡷⣿⣁⠒⠠⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⣼⣿⣧⡏⣿⣿⢾⣯⡠⣾⣸⣿⡿⣦⣙⣿⢹⡇⣿⣷⣝⠿⣅⣂⡀⠀⠡⢂⠄⣀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠇⠀⠀⠀⠀⣿⡟⣿⡇⡏⣿⣽⣿⣧⢻⡗⡇⣇⣤⣿⣿⣿⣧⣿⣿⡲⣭⣀⡭⠛⠁⠀⠀⠈⠀⠉⢂⢄⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠸⠀⠀⠀⠀⢻⣿⣇⣥⣏⣘⣿⣏⠛⠻⣷⠿⡻⡛⠷⡽⡿⣿⣿⣿⣷⠟⠓⠉⠢⢄⡀⠀⠀⠀⠀⠀⠁⠫⢢⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⢇⠀⠀⠀⢸⣾⣿⣽⣿⣏⣻⠻⠁⢠⠁⠀⠀⠀⠘⣰⣿⣿⢟⢹⢻⠀⠀⠀⠀⠀⠈⠒⢄⡀⠀⠀⠀⠀⠀⠀⠑⢄", + "⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⢸⣯⣿⣿⣿⢷⡀⠀⠀⠀⠀⠀⠀⠀⠛⣩⣿⣿⢿⣾⣸⠀⠀⠀⠀⠀⠀⢀⡠⠚⠉⠉⠁⠀⠀⠀⢀⠌", + "⠀⠀⠀⠀⠀⠀⠀⢡⠀⠀⠀⢟⣿⣯⡟⠿⡟⢇⡀⠀⠀⠐⠁⢀⢴⠋⡼⢣⣿⣻⡏⠀⠀⠀⣀⠄⠂⠁⠀⠀⠀⠀⠀⠀⢀⡤⠂⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠇⠀⠀⠈⠊⢻⣿⣜⡹⡀⠈⠱⠂⠤⠔⠡⢶⣽⡷⢟⡿⠕⠒⠀⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⡠⠐⠁⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⢿⠿⠿⢿⠾⣽⡀⠀⠀⠀⠈⠻⣥⣃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠤⠒⠁⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⡀⡀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣖⠂⠠⠐⠋⠀⠙⠳⣤⣠⠀⠀⠀⣀⠤⠒⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠵⡐⠄⠀⠀⠀⠀⠀⠀⠀⠈⢷⣄⡀⠀⠠⡀⠀⠈⠙⠶⣖⡉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡥⠈⠂⠀⠀⠀⠀⠀⠀⠀⣼⠉⠙⠲⣄⠈⠣⡀⠀⠀⠈⢻⡦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠈⣷⡄⠈⠄⠀⠀⠀⢧⠀⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⡀⠀⢠⣿⣤⣤⣶⣶⣾⣿⣿⡄⢸⠀⠀⠀⢸⣄⣤⣼⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠇⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⢸⠀⠀⠀⣼⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣀⣀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⢀⣼⣿⣿⣿⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠉⠁⠀⠈⠉⠙⠛⠿⠿⠽⠿⠟⠛⡉⠛⠲⣿⣿⠿⡿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡇⠀⠀⢠⡏⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠋⠀⠀⣠⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢔⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠄⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⢀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠊⠀⠀⠀⠀⠀⣃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⡠⣻⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⢫⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⣰⡿⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⣼⠏⣸⣿⣷⢷⠙⣻⢶⣤⣄⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⠾⠉⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠰⣏⠀⣿⣿⡘⣼⡇⠀⠁⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⠁⠀⠀⣽⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⢙⠓⠛⠘⣧⠾⢷⣄⠀⠀⠀⠈⠻⣿⣿⣿⣿⣿⣿⣿⠿⠋⠀⠀⠀⠀⠀⠀⣿⢟⢇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠸⠀⠀⠀⢸⣧⠀⠹⣆⠀⠀⠀⠀⠈⢻⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⣿⢂⠙⢿⡷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⢃⠀⠀⠈⠙⠀⠀⠻⡄⠀⠀⠀⠀⠸⡀⠹⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡾⠐⠠⠀⠻⠬⠄⡒⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠈⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠘⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠐⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠑⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + " ", + "Sometimes, we feel little Yanderedev ourselves - a wise horny man..." +]; + +console.log(art.join("\n")); \ No newline at end of file diff --git a/jsm/shaders/MMDToonShader.js b/libs/shaders/MMDToonShader.js similarity index 100% rename from jsm/shaders/MMDToonShader.js rename to libs/shaders/MMDToonShader.js diff --git a/libs/shims/modules.js b/libs/shims/modules.js new file mode 100644 index 0000000..aa306b6 --- /dev/null +++ b/libs/shims/modules.js @@ -0,0 +1,1063 @@ +/* ES Module Shims 1.10.0 */ +(function () { + + const hasDocument = typeof document !== 'undefined'; + + const noop = () => {}; + + const optionsScript = hasDocument ? document.querySelector('script[type=esms-options]') : undefined; + + const esmsInitOptions = optionsScript ? JSON.parse(optionsScript.innerHTML) : {}; + Object.assign(esmsInitOptions, self.esmsInitOptions || {}); + + let shimMode = hasDocument ? !!esmsInitOptions.shimMode : true; + + const importHook = globalHook(shimMode && esmsInitOptions.onimport); + const resolveHook = globalHook(shimMode && esmsInitOptions.resolve); + let fetchHook = esmsInitOptions.fetch ? globalHook(esmsInitOptions.fetch) : fetch; + const metaHook = esmsInitOptions.meta ? globalHook(shimMode && esmsInitOptions.meta) : noop; + + const mapOverrides = esmsInitOptions.mapOverrides; + + let nonce = esmsInitOptions.nonce; + if (!nonce && hasDocument) { + const nonceElement = document.querySelector('script[nonce]'); + if (nonceElement) + nonce = nonceElement.nonce || nonceElement.getAttribute('nonce'); + } + + const onerror = globalHook(esmsInitOptions.onerror || noop); + + const { revokeBlobURLs, noLoadEventRetriggers, globalLoadEventRetrigger, enforceIntegrity } = esmsInitOptions; + + function globalHook (name) { + return typeof name === 'string' ? self[name] : name; + } + + const enable = Array.isArray(esmsInitOptions.polyfillEnable) ? esmsInitOptions.polyfillEnable : []; + const cssModulesEnabled = enable.includes('css-modules'); + const jsonModulesEnabled = enable.includes('json-modules'); + const wasmModulesEnabled = enable.includes('wasm-modules'); + const sourcePhaseEnabled = enable.includes('source-phase'); + + const onpolyfill = esmsInitOptions.onpolyfill ? globalHook(esmsInitOptions.onpolyfill) : () => { + console.log(`%c^^ Module error above is polyfilled and can be ignored ^^`, 'font-weight:900;color:#391'); + }; + + const edge = !navigator.userAgentData && !!navigator.userAgent.match(/Edge\/\d+\.\d+/); + + const baseUrl = hasDocument + ? document.baseURI + : `${location.protocol}//${location.host}${location.pathname.includes('/') + ? location.pathname.slice(0, location.pathname.lastIndexOf('/') + 1) + : location.pathname}`; + + const createBlob = (source, type = 'text/javascript') => URL.createObjectURL(new Blob([source], { type })); + let { skip } = esmsInitOptions; + if (Array.isArray(skip)) { + const l = skip.map(s => new URL(s, baseUrl).href); + skip = s => l.some(i => i[i.length - 1] === '/' && s.startsWith(i) || s === i); + } + else if (typeof skip === 'string') { + const r = new RegExp(skip); + skip = s => r.test(s); + } else if (skip instanceof RegExp) { + skip = s => skip.test(s); + } + + const dispatchError = error => self.dispatchEvent(Object.assign(new Event('error'), { error })); + + const throwError = err => { (self.reportError || dispatchError)(err), void onerror(err); }; + + function fromParent (parent) { + return parent ? ` imported from ${parent}` : ''; + } + + let importMapSrcOrLazy = false; + + function setImportMapSrcOrLazy () { + importMapSrcOrLazy = true; + } + + // shim mode is determined on initialization, no late shim mode + if (!shimMode) { + if (document.querySelectorAll('script[type=module-shim],script[type=importmap-shim],link[rel=modulepreload-shim]').length) { + shimMode = true; + } + else { + let seenScript = false; + for (const script of document.querySelectorAll('script[type=module],script[type=importmap]')) { + if (!seenScript) { + if (script.type === 'module' && !script.ep) + seenScript = true; + } + else if (script.type === 'importmap' && seenScript) { + importMapSrcOrLazy = true; + break; + } + } + } + } + + const backslashRegEx = /\\/g; + + function asURL (url) { + try { + if (url.indexOf(':') !== -1) + return new URL(url).href; + } + catch (_) {} + } + + function resolveUrl (relUrl, parentUrl) { + return resolveIfNotPlainOrUrl(relUrl, parentUrl) || (asURL(relUrl) || resolveIfNotPlainOrUrl('./' + relUrl, parentUrl)); + } + + function resolveIfNotPlainOrUrl (relUrl, parentUrl) { + const hIdx = parentUrl.indexOf('#'), qIdx = parentUrl.indexOf('?'); + if (hIdx + qIdx > -2) + parentUrl = parentUrl.slice(0, hIdx === -1 ? qIdx : qIdx === -1 || qIdx > hIdx ? hIdx : qIdx); + if (relUrl.indexOf('\\') !== -1) + relUrl = relUrl.replace(backslashRegEx, '/'); + // protocol-relative + if (relUrl[0] === '/' && relUrl[1] === '/') { + return parentUrl.slice(0, parentUrl.indexOf(':') + 1) + relUrl; + } + // relative-url + else if (relUrl[0] === '.' && (relUrl[1] === '/' || relUrl[1] === '.' && (relUrl[2] === '/' || relUrl.length === 2 && (relUrl += '/')) || + relUrl.length === 1 && (relUrl += '/')) || + relUrl[0] === '/') { + const parentProtocol = parentUrl.slice(0, parentUrl.indexOf(':') + 1); + if (parentProtocol === 'blob:') { + throw new TypeError(`Failed to resolve module specifier "${relUrl}". Invalid relative url or base scheme isn't hierarchical.`); + } + // Disabled, but these cases will give inconsistent results for deep backtracking + //if (parentUrl[parentProtocol.length] !== '/') + // throw new Error('Cannot resolve'); + // read pathname from parent URL + // pathname taken to be part after leading "/" + let pathname; + if (parentUrl[parentProtocol.length + 1] === '/') { + // resolving to a :// so we need to read out the auth and host + if (parentProtocol !== 'file:') { + pathname = parentUrl.slice(parentProtocol.length + 2); + pathname = pathname.slice(pathname.indexOf('/') + 1); + } + else { + pathname = parentUrl.slice(8); + } + } + else { + // resolving to :/ so pathname is the /... part + pathname = parentUrl.slice(parentProtocol.length + (parentUrl[parentProtocol.length] === '/')); + } + + if (relUrl[0] === '/') + return parentUrl.slice(0, parentUrl.length - pathname.length - 1) + relUrl; + + // join together and split for removal of .. and . segments + // looping the string instead of anything fancy for perf reasons + // '../../../../../z' resolved to 'x/y' is just 'z' + const segmented = pathname.slice(0, pathname.lastIndexOf('/') + 1) + relUrl; + + const output = []; + let segmentIndex = -1; + for (let i = 0; i < segmented.length; i++) { + // busy reading a segment - only terminate on '/' + if (segmentIndex !== -1) { + if (segmented[i] === '/') { + output.push(segmented.slice(segmentIndex, i + 1)); + segmentIndex = -1; + } + continue; + } + // new segment - check if it is relative + else if (segmented[i] === '.') { + // ../ segment + if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i + 2 === segmented.length)) { + output.pop(); + i += 2; + continue; + } + // ./ segment + else if (segmented[i + 1] === '/' || i + 1 === segmented.length) { + i += 1; + continue; + } + } + // it is the start of a new segment + while (segmented[i] === '/') i++; + segmentIndex = i; + } + // finish reading out the last segment + if (segmentIndex !== -1) + output.push(segmented.slice(segmentIndex)); + return parentUrl.slice(0, parentUrl.length - pathname.length) + output.join(''); + } + } + + function resolveAndComposeImportMap (json, baseUrl, parentMap) { + const outMap = { imports: Object.assign({}, parentMap.imports), scopes: Object.assign({}, parentMap.scopes), integrity: Object.assign({}, parentMap.integrity) }; + + if (json.imports) + resolveAndComposePackages(json.imports, outMap.imports, baseUrl, parentMap); + + if (json.scopes) + for (let s in json.scopes) { + const resolvedScope = resolveUrl(s, baseUrl); + resolveAndComposePackages(json.scopes[s], outMap.scopes[resolvedScope] || (outMap.scopes[resolvedScope] = {}), baseUrl, parentMap); + } + + if (json.integrity) + resolveAndComposeIntegrity(json.integrity, outMap.integrity, baseUrl); + + return outMap; + } + + function getMatch (path, matchObj) { + if (matchObj[path]) + return path; + let sepIndex = path.length; + do { + const segment = path.slice(0, sepIndex + 1); + if (segment in matchObj) + return segment; + } while ((sepIndex = path.lastIndexOf('/', sepIndex - 1)) !== -1) + } + + function applyPackages (id, packages) { + const pkgName = getMatch(id, packages); + if (pkgName) { + const pkg = packages[pkgName]; + if (pkg === null) return; + return pkg + id.slice(pkgName.length); + } + } + + + function resolveImportMap (importMap, resolvedOrPlain, parentUrl) { + let scopeUrl = parentUrl && getMatch(parentUrl, importMap.scopes); + while (scopeUrl) { + const packageResolution = applyPackages(resolvedOrPlain, importMap.scopes[scopeUrl]); + if (packageResolution) + return packageResolution; + scopeUrl = getMatch(scopeUrl.slice(0, scopeUrl.lastIndexOf('/')), importMap.scopes); + } + return applyPackages(resolvedOrPlain, importMap.imports) || resolvedOrPlain.indexOf(':') !== -1 && resolvedOrPlain; + } + + function resolveAndComposePackages (packages, outPackages, baseUrl, parentMap) { + for (let p in packages) { + const resolvedLhs = resolveIfNotPlainOrUrl(p, baseUrl) || p; + if ((!shimMode || !mapOverrides) && outPackages[resolvedLhs] && (outPackages[resolvedLhs] !== packages[resolvedLhs])) { + throw Error(`Rejected map override "${resolvedLhs}" from ${outPackages[resolvedLhs]} to ${packages[resolvedLhs]}.`); + } + let target = packages[p]; + if (typeof target !== 'string') + continue; + const mapped = resolveImportMap(parentMap, resolveIfNotPlainOrUrl(target, baseUrl) || target, baseUrl); + if (mapped) { + outPackages[resolvedLhs] = mapped; + continue; + } + console.warn(`Mapping "${p}" -> "${packages[p]}" does not resolve`); + } + } + + function resolveAndComposeIntegrity (integrity, outIntegrity, baseUrl) { + for (let p in integrity) { + const resolvedLhs = resolveIfNotPlainOrUrl(p, baseUrl) || p; + if ((!shimMode || !mapOverrides) && outIntegrity[resolvedLhs] && (outIntegrity[resolvedLhs] !== integrity[resolvedLhs])) { + throw Error(`Rejected map integrity override "${resolvedLhs}" from ${outIntegrity[resolvedLhs]} to ${integrity[resolvedLhs]}.`); + } + outIntegrity[resolvedLhs] = integrity[p]; + } + } + + let dynamicImport = !hasDocument && (0, eval)('u=>import(u)'); + + let supportsDynamicImport; + + const dynamicImportCheck = hasDocument && new Promise(resolve => { + const s = Object.assign(document.createElement('script'), { + src: createBlob('self._d=u=>import(u)'), + ep: true + }); + s.setAttribute('nonce', nonce); + s.addEventListener('load', () => { + if (!(supportsDynamicImport = !!(dynamicImport = self._d))) { + let err; + window.addEventListener('error', _err => err = _err); + dynamicImport = (url, opts) => new Promise((resolve, reject) => { + const s = Object.assign(document.createElement('script'), { + type: 'module', + src: createBlob(`import*as m from'${url}';self._esmsi=m`) + }); + err = undefined; + s.ep = true; + if (nonce) + s.setAttribute('nonce', nonce); + // Safari is unique in supporting module script error events + s.addEventListener('error', cb); + s.addEventListener('load', cb); + function cb (_err) { + document.head.removeChild(s); + if (self._esmsi) { + resolve(self._esmsi, baseUrl); + self._esmsi = undefined; + } + else { + reject(!(_err instanceof Event) && _err || err && err.error || new Error(`Error loading ${opts && opts.errUrl || url} (${s.src}).`)); + err = undefined; + } + } + document.head.appendChild(s); + }); + } + document.head.removeChild(s); + delete self._d; + resolve(); + }); + document.head.appendChild(s); + }); + + // support browsers without dynamic import support (eg Firefox 6x) + let supportsJsonAssertions = false; + let supportsCssAssertions = false; + + const supports = hasDocument && HTMLScriptElement.supports; + + let supportsImportMaps = supports && supports.name === 'supports' && supports('importmap'); + let supportsImportMeta = supportsDynamicImport; + let supportsWasmModules = false; + let supportsSourcePhase = false; + + const wasmBytes = [0,97,115,109,1,0,0,0]; + + let featureDetectionPromise = Promise.resolve(dynamicImportCheck).then(() => { + if (!supportsDynamicImport) + return; + if (!hasDocument) + return Promise.all([ + supportsImportMaps || dynamicImport(createBlob('import.meta')).then(() => supportsImportMeta = true, noop), + cssModulesEnabled && dynamicImport(createBlob(`import"${createBlob('', 'text/css')}"with{type:"css"}`)).then(() => supportsCssAssertions = true, noop), + jsonModulesEnabled && dynamicImport(createBlob(`import"${createBlob('{}', 'text/json')}"with{type:"json"}`)).then(() => supportsJsonAssertions = true, noop), + wasmModulesEnabled && dynamicImport(createBlob(`import"${createBlob(new Uint8Array(wasmBytes), 'application/wasm')}"`)).then(() => supportsWasmModules = true, noop), + wasmModulesEnabled && sourcePhaseEnabled && dynamicImport(createBlob(`import source x from"${createBlob(new Uint8Array(wasmBytes), 'application/wasm')}"`)).then(() => supportsSourcePhase = true, noop), + ]); + + return new Promise(resolve => { + const iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.setAttribute('nonce', nonce); + function cb ({ data }) { + const isFeatureDetectionMessage = Array.isArray(data) && data[0] === 'esms'; + if (!isFeatureDetectionMessage) + return; + [, supportsImportMaps, supportsImportMeta, supportsCssAssertions, supportsJsonAssertions, supportsWasmModules, supportsSourcePhase] = data; + resolve(); + document.head.removeChild(iframe); + window.removeEventListener('message', cb, false); + } + window.addEventListener('message', cb, false); + + const importMapTest = `