feat(stage-ui): achieve Warudo (https://warudo.app) style rendering for VRM models

This commit is contained in:
Neko Ayaka
2025-08-11 04:53:18 +08:00
parent c3b804a23d
commit ba26cb0537
12 changed files with 2755 additions and 149 deletions
+4 -1
View File
@@ -1,4 +1,4 @@
version: '0.2'
version: "0.2"
ignorePaths: []
dictionaryDefinitions: []
dictionaries: []
@@ -82,6 +82,7 @@ words:
- DuckDBWASMQuery
- eastasia
- elevenlabs
- Equirectangular
- esaxx
- Factorio
- feaxios
@@ -95,6 +96,7 @@ words:
- gugi
- guii
- guiiai
- Hdri
- hfspaceup
- hfsup
- hfup
@@ -198,6 +200,7 @@ words:
- reka
- Replayable
- resampler
- RGBE
- rlib
- rmcp
- rolldown
+2
View File
@@ -71,6 +71,7 @@
"@ricky0123/vad-web": "^0.0.24",
"@tresjs/cientos": "^4.3.1",
"@tresjs/core": "^4.3.6",
"@tresjs/post-processing": "^2.4.0",
"@vueuse/core": "^13.6.0",
"@vueuse/motion": "^3.0.3",
"@vueuse/shared": "^13.6.0",
@@ -97,6 +98,7 @@
"pinia": "^3.0.3",
"pixi-filters": "4",
"pixi-live2d-display": "^0.4.0",
"postprocessing": "^6.37.7",
"rehype-stringify": "^10.0.1",
"reka-ui": "^2.4.1",
"remark-parse": "^11.0.0",
@@ -242,7 +242,7 @@ function handleUrlLoad() {
<Callout :label="t('settings.vrm.scale-and-position.model-info-title')">
<div>
<div class="text-sm text-neutral-600 space-y-1">
<div class="text-sm text-neutral-600 space-y-1 dark:text-neutral-400">
<div class="flex justify-between">
<span>{{ t('settings.vrm.scale-and-position.model-info-x') }}</span>
<span>{{ modelSize.x.toFixed(4) }}</span>
@@ -262,7 +262,7 @@ function handleUrlLoad() {
theme="lime"
label="Tips!"
>
<div class="text-sm text-neutral-600 space-y-1">
<div class="text-sm text-neutral-600 space-y-1 dark:text-neutral-400">
{{ t('settings.vrm.scale-and-position.tips') }}
</div>
</Callout>
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { useTresContext } from '@tresjs/core'
import { until } from '@vueuse/core'
import { onMounted, toRef } from 'vue'
import { onMounted, shallowRef, toRef } from 'vue'
import * as THREE from 'three'
@@ -11,11 +11,29 @@ const props = defineProps<{
const { scene } = useTresContext()
const directionalLightRef = toRef(() => props.directionalLight)
const lightHelper = shallowRef<THREE.DirectionalLightHelper>()
onMounted(async () => {
await until(directionalLightRef).toBeTruthy()
scene.value.add(new THREE.DirectionalLightHelper(props.directionalLight!, 1))
lightHelper.value = new THREE.DirectionalLightHelper(directionalLightRef.value!, 1)
scene.value.add(lightHelper.value)
})
if (import.meta.hot) {
// Ensure cleanup on HMR
import.meta.hot.dispose(() => {
try {
if (lightHelper.value) {
lightHelper.value.dispose()
scene.value.remove(lightHelper.value)
lightHelper.value = undefined
}
}
catch (error) {
console.error('Error during DirectionalLightHelper cleanup:', error)
}
})
}
</script>
<template>
@@ -0,0 +1,41 @@
<script setup lang="ts">
import { useTresContext } from '@tresjs/core'
import { until } from '@vueuse/core'
import { onMounted, shallowRef, toRef } from 'vue'
import * as THREE from 'three'
const props = defineProps<{
hemisphereLight?: THREE.HemisphereLight | null
}>()
const { scene } = useTresContext()
const hemisphereLightRef = toRef(() => props.hemisphereLight)
const lightHelper = shallowRef<THREE.HemisphereLightHelper>()
onMounted(async () => {
await until(hemisphereLightRef).toBeTruthy()
lightHelper.value = new THREE.HemisphereLightHelper(hemisphereLightRef.value!, 1)
scene.value.add(lightHelper.value)
})
if (import.meta.hot) {
// Ensure cleanup on HMR
import.meta.hot.dispose(() => {
try {
if (lightHelper.value) {
lightHelper.value.dispose()
scene.value.remove(lightHelper.value)
lightHelper.value = undefined
}
}
catch (error) {
console.error('Error during HemisphereLightHelper cleanup:', error)
}
})
}
</script>
<template>
<slot />
</template>
File diff suppressed because one or more lines are too long
+45 -24
View File
@@ -1,13 +1,13 @@
<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { EffectComposerPmndrs, HueSaturationPmndrs } from '@tresjs/post-processing'
import { useElementBounding, useMouse } from '@vueuse/core'
import { formatHex } from 'culori'
import { storeToRefs } from 'pinia'
import { BlendFunction } from 'postprocessing'
import { ACESFilmicToneMapping, PerspectiveCamera, Plane, Raycaster, Vector2, Vector3 } from 'three'
import { onUnmounted, ref, shallowRef, watch } from 'vue'
import * as THREE from 'three'
import DirectionalLightHelper from './Tres/DirectionalLightHelper.vue'
import { useVRM } from '../../stores'
import { OrbitControls, VRMModel } from '../Scenes'
@@ -37,26 +37,35 @@ const {
directionalLightPosition,
directionalLightRotation,
directionalLightIntensity,
directionalLightColor,
ambientLightIntensity,
ambientLightColor,
hemisphereLightPosition,
hemisphereLightIntensity,
hemisphereSkyColor,
hemisphereGroundColor,
} = storeToRefs(useVRM())
const modelRef = ref<InstanceType<typeof VRMModel>>()
const camera = shallowRef(new THREE.PerspectiveCamera())
const camera = shallowRef(new PerspectiveCamera())
const controlsRef = shallowRef<InstanceType<typeof OrbitControls>>()
const directionalLightRef = shallowRef<InstanceType<typeof THREE.DirectionalLight>>()
const effectProps = {
saturation: 0.3,
hue: 0,
blendFunction: BlendFunction.SRC,
}
let isUpdatingCamera = true
// manage the sequence of the camera and controls initialization
const controlsReady = ref(false)
const modelReady = ref(false)
const sceneReady = ref(false)
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
const raycaster = new Raycaster()
const mouse = new Vector2()
watch(cameraFOV, (newFov) => {
if (camera.value) {
@@ -113,7 +122,7 @@ function handleLoadModelProgress() {
modelReady.value = true
}
// Then start to set the camera postion and target
// Then start to set the camera position and target
watch(
[controlsReady, modelReady],
([ctrlOk, modelOk]) => {
@@ -146,9 +155,9 @@ watch(
watch(cameraDistance, (newDistance) => {
if (!isUpdatingCamera && camera.value && controlsRef.value && controlsRef.value.controls) {
isUpdatingCamera = true
const newPosition = new THREE.Vector3()
const newPosition = new Vector3()
const target = controlsRef.value.controls.target
const direction = new THREE.Vector3().subVectors(camera.value.position, target).normalize()
const direction = new Vector3().subVectors(camera.value.position, target).normalize()
newPosition.copy(target).addScaledVector(direction, newDistance)
camera.value.position.set(
newPosition.x,
@@ -179,16 +188,16 @@ function lookAtMouse(mouseX: number, mouseY: number) {
raycaster.setFromCamera(mouse, camera.value)
// Create a plane in front of the camera
const cameraDirection = new THREE.Vector3()
const cameraDirection = new Vector3()
camera.value.getWorldDirection(cameraDirection) // Get camera's forward direction
const plane = new THREE.Plane()
const plane = new Plane()
plane.setFromNormalAndCoplanarPoint(
cameraDirection,
camera.value.position.clone().add(cameraDirection.multiplyScalar(1)), // 1 unit in front of the camera
)
const intersection = new THREE.Vector3()
const intersection = new Vector3()
raycaster.ray.intersectPlane(plane, intersection)
lookAtTarget.value = { x: intersection.x, y: intersection.y, z: intersection.z }
@@ -239,28 +248,40 @@ defineExpose({
<template>
<div ref="vrmContainerRef" w="100%" h="100%">
<TresCanvas v-if="camera" v-show="sceneReady" :camera="camera" :antialias="true" :width="width" :height="height">
<TresCanvas
v-if="camera" v-show="sceneReady"
:camera="camera"
:antialias="true"
:width="width"
:height="height"
:tone-mapping="ACESFilmicToneMapping"
:tone-mapping-exposure="1"
>
<OrbitControls ref="controlsRef" />
<TresAmbientLight
:color="formatHex(ambientLightColor)"
:intensity="ambientLightIntensity"
cast-shadow
/>
<TresHemisphereLight
:color="0xFFFFFF"
:color="formatHex(hemisphereSkyColor)"
:ground-color="formatHex(hemisphereGroundColor)"
:position="[hemisphereLightPosition.x, hemisphereLightPosition.y, hemisphereLightPosition.z]"
:intensity="hemisphereLightIntensity"
cast-shadow
/>
<TresDirectionalLight
ref="directionalLightRef"
:color="0xFFFFFF"
:color="formatHex(directionalLightColor)"
:position="[directionalLightPosition.x, directionalLightPosition.y, directionalLightPosition.z]"
:rotation="[directionalLightRotation.x, directionalLightRotation.y, directionalLightRotation.z]"
:intensity="directionalLightIntensity"
cast-shadow
/>
<DirectionalLightHelper :directional-light="directionalLightRef" />
<TresAmbientLight
:color="0xFFFFFF"
:intensity="ambientLightIntensity"
cast-shadow
/>
<Suspense>
<EffectComposerPmndrs>
<HueSaturationPmndrs v-bind="effectProps" />
</EffectComposerPmndrs>
</Suspense>
<VRMModel
ref="modelRef"
:model-src="props.modelSrc"
@@ -0,0 +1,51 @@
<script setup lang="ts">
import type { CanvasTexture, DataTexture } from 'three'
import { useTresContext } from '@tresjs/core'
import { EquirectangularReflectionMapping } from 'three'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import { onMounted, ref } from 'vue'
import defaultSkyBoxHdri from '../Tres/assets/sky_linekotsi_23_HDRI.hdr?url'
// Add these reactive variables to your setup
const environment = ref<DataTexture | CanvasTexture>()
const backgroundBlur = ref(0) // Controls background blur
const backgroundIntensity = ref(1) // Controls background visibility
const { scene } = useTresContext()
// Add this function to load HDRI environment
async function loadEnvironment() {
try {
const loader = new RGBELoader()
// Resources
// - polyhaven.com
// - hdrihaven.com
const texture = await loader.loadAsync(defaultSkyBoxHdri)
texture.mapping = EquirectangularReflectionMapping
environment.value = texture
// Apply to scene if renderer is available
if (scene.value) {
scene.value.environment = texture
scene.value.background = texture
scene.value.backgroundBlurriness = backgroundBlur.value
scene.value.backgroundIntensity = backgroundIntensity.value
}
}
catch (error) {
console.warn('Failed to load HDRI environment:', error)
}
}
// Usage in your component
onMounted(async () => {
await loadEnvironment()
})
</script>
<template>
<slot />
</template>
@@ -6,7 +6,7 @@ import { VRMUtils } from '@pixiv/three-vrm'
import { useLoop, useTresContext } from '@tresjs/core'
import { until, useObjectUrl } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { AnimationMixer, MathUtils, Quaternion, Vector3, VectorKeyframeTrack } from 'three'
import { AnimationMixer, MathUtils, Mesh, MeshPhysicalMaterial, MeshStandardMaterial, Quaternion, Vector3, VectorKeyframeTrack } from 'three'
import { computed, onMounted, onUnmounted, ref, toRef, watch } from 'vue'
import { clipFromVRMAnimation, loadVRMAnimation, useBlink, useIdleEyeSaccades } from '../../../composables/vrm/animation'
@@ -32,6 +32,7 @@ const emit = defineEmits<{
let disposeBeforeRenderLoop: (() => void | undefined)
const modelCreating = ref(false)
const modelLoaded = ref(false)
const modelSrcRef = toRef(() => props.modelSrc)
const modelFileRef = toRef(() => props.modelFile)
const modelFileSrc = useObjectUrl(modelFileRef)
@@ -69,6 +70,7 @@ const idleEyeSaccades = useIdleEyeSaccades()
async function loadModel() {
await until(modelCreating).not.toBeTruthy()
modelCreating.value = true
modelLoaded.value = false
try {
if (!scene.value) {
@@ -83,7 +85,6 @@ async function loadModel() {
const _vrmInfo = await loadVrm(modelSrcNormalized.value, {
scene: scene.value,
lookAt: true,
positionOffset: [modelOffset.value.x, modelOffset.value.y, modelOffset.value.z],
onProgress: progress => emit('loadModelProgress', Number((100 * progress.loaded / progress.total).toFixed(2))),
})
if (!_vrmInfo || !_vrmInfo._vrm) {
@@ -99,6 +100,7 @@ async function loadModel() {
} = _vrmInfo
vrmGroup.value = _vrmGroup
// Set initial camera position
cameraPosition.value = {
x: vrmModelCenter.x + vrmInitialCameraOffset.x,
@@ -119,6 +121,12 @@ async function loadModel() {
z: vrmModelSize.z,
}
vrmGroup.value.position.set(
modelOffset.value.x,
modelOffset.value.y,
modelOffset.value.z,
)
// Set model facing direction
const targetDirection = new Vector3(0, 0, -1) // Default facing direction
const lookAt = _vrm.lookAt
@@ -189,9 +197,28 @@ async function loadModel() {
vrmEmote.value = useVRMEmote(_vrm)
// TODO: perhaps we should allow user to choose whether to enable
// this kind of behavior or not?
// WORKAROUND: set to use envMapIntensity for all matched materials
// REVIEW: MeshToonMaterial, and MeshBasicMaterial will not be affected
// since they do not have envMapIntensity property
_vrm.scene.traverse((child) => {
if (child instanceof Mesh && child.material) {
const material = Array.isArray(child.material) ? child.material : [child.material]
material.forEach((mat) => {
if (mat instanceof MeshStandardMaterial || mat instanceof MeshPhysicalMaterial) {
// Should read envMap intensity from outside props
mat.envMapIntensity = 1.0
mat.needsUpdate = true
}
})
}
})
vrm.value = _vrm
emit('modelReady')
modelLoaded.value = true
function getEyePosition(): number | null {
const eye = vrm.value?.humanoid?.getNormalizedBoneNode('head')
@@ -286,5 +313,5 @@ defineExpose({
</script>
<template>
<slot />
<slot v-if="modelLoaded" />
</template>
@@ -12,7 +12,6 @@ interface GLTFUserdata extends Record<string, any> {
}
export async function loadVrm(model: string, options?: {
positionOffset?: [number, number, number]
scene?: Scene
lookAt?: boolean
onProgress?: (progress: ProgressEvent<EventTarget>) => void | Promise<void>
@@ -57,8 +56,6 @@ export async function loadVrm(model: string, options?: {
box.getCenter(modelCenter)
modelCenter.y += modelSize.y / 5 // Adjust pivot to align chest with the origin
// Set position
// Compute the initial camera position (once per loaded model)
// In order to see the up-2/3 part fo the model, z = (y/3) / tan(fov/2)
const fov = 40 // default fov = 40 degrees
+26 -6
View File
@@ -43,19 +43,39 @@ export const useVRM = defineStore('vrm', () => {
const cameraPosition = useLocalStorage('settings/vrm/camera-position', { x: 0, y: 0, z: -1 })
const cameraDistance = useLocalStorage('settings/vrm/cameraDistance', 0)
const directionalLightPosition = useLocalStorage('settings/vrm/scenes/scene/directional-light/position', { x: 1, y: 1, z: -10 })
const directionalLightPosition = useLocalStorage('settings/vrm/scenes/scene/directional-light/position', { x: 0, y: 0, z: -10 })
const directionalLightTarget = useLocalStorage('settings/vrm/scenes/scene/directional-light/target', { x: 0, y: 0, z: 0 })
const directionalLightRotation = useLocalStorage('settings/vrm/scenes/scene/directional-light/rotation', { x: 0, y: 0, z: 0 })
const directionalLightIntensity = useLocalStorage('settings/vrm/scenes/scene/directional-light/intensity', 0.6)
const directionalLightColor = useLocalStorage('settings/vrm/scenes/scene/directional-light/color', '#FFFFFF')
// TODO: Manual directional light intensity will not work for other
// scenes with different lighting setups. But since the model
// is possible to have MeshToonMaterial, and MeshBasicMaterial
// without envMap to be able to inherit lighting from HDRI map,
// we will have to figure out a way to make this work to apply
// different directional light and other lighting setups
// for different environments.
// WORKAROUND: To achieve the rendering style of Warudo for anime style
// Genshin Impact, or so called Cartoon style rendering with
// harsh shadows and bright highlights.
// REVIEW: This is a temporary solution, and will be replaced with
// a more flexible lighting system in the future.
const directionalLightIntensity = useLocalStorage('settings/vrm/scenes/scene/directional-light/intensity', 2.02)
// TODO: color are the same
const directionalLightColor = useLocalStorage('settings/vrm/scenes/scene/directional-light/color', '#fffbf5')
const hemisphereLightPosition = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/position', { x: 0, y: 1, z: 0 })
const hemisphereLightPosition = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/position', { x: 0, y: 0, z: 0 })
// TODO: color are the same
const hemisphereSkyColor = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/sky-color', '#FFFFFF')
// TODO: color are the same
const hemisphereGroundColor = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/ground-color', '#000000')
const hemisphereLightIntensity = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/intensity', 2.0)
// TODO: The same as directional light, this is a temporary solution
// and will be replaced with a more flexible lighting system in the future.
const hemisphereLightIntensity = useLocalStorage('settings/vrm/scenes/scene/hemisphere-light/intensity', 0.4)
const ambientLightIntensity = useLocalStorage('settings/vrm/scenes/scene/ambient-light/intensity', 0.0)
// TODO: color are the same
const ambientLightColor = useLocalStorage('settings/vrm/scenes/scene/ambient-light/color', '#FFFFFF')
// TODO: The same as directional light, this is a temporary solution
// and will be replaced with a more flexible lighting system in the future.
const ambientLightIntensity = useLocalStorage('settings/vrm/scenes/scene/ambient-light/intensity', 0.6)
const lookAtTarget = useLocalStorage('settings/vrm/lookAtTarget', { x: 0, y: 0, z: 0 })
const isTracking = useLocalStorage('settings/vrm/isTracking', false)
+39 -108
View File
@@ -1122,7 +1122,7 @@ importers:
version: 0.1.3
unplugin-yaml:
specifier: ^3.0.2
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
vitepress:
specifier: ^2.0.0-alpha.9
version: 2.0.0-alpha.9(@types/node@24.1.0)(change-case@5.4.4)(fuse.js@7.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(nprogress@0.2.0)(postcss@8.5.6)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
@@ -1165,7 +1165,7 @@ importers:
devDependencies:
unplugin-yaml:
specifier: ^3.0.2
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
packages/memory-pgvector:
dependencies:
@@ -1320,6 +1320,9 @@ importers:
'@tresjs/core':
specifier: ^4.3.6
version: 4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
'@tresjs/post-processing':
specifier: ^2.4.0
version: 2.4.0(@tresjs/core@4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)))(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
'@vueuse/core':
specifier: ^13.6.0
version: 13.6.0(vue@3.5.18(typescript@5.9.2))
@@ -1398,6 +1401,9 @@ importers:
pixi-live2d-display:
specifier: ^0.4.0
version: 0.4.0(0736f5bd67d2e4de7e9fff36ad63fa2e)
postprocessing:
specifier: ^6.37.7
version: 6.37.7(three@0.179.0)
rehype-stringify:
specifier: ^10.0.1
version: 10.0.1
@@ -1542,7 +1548,7 @@ importers:
version: 1.2.4(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(esbuild@0.25.8)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
unplugin-yaml:
specifier: ^3.0.2
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
version: 3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
vite:
specifier: ^6.3.5
version: 6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
@@ -5282,6 +5288,13 @@ packages:
three: '>=0.133'
vue: '>=3.4'
'@tresjs/post-processing@2.4.0':
resolution: {integrity: sha512-4l18DTLkn0Y/abyn+FD/gSJ6/SC01oXn+/qPgUxMgxZ8zGaw4PZbOi4yorhbSbOTp0gO4D1X7lNOvNUokqJwFw==}
peerDependencies:
'@tresjs/core': '>=4.0'
three: '>=0.169'
vue: '>=3.4'
'@tweenjs/tween.js@23.1.3':
resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==}
@@ -10423,6 +10436,11 @@ packages:
resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
engines: {node: '>=12'}
postprocessing@6.37.7:
resolution: {integrity: sha512-3mXzCyhHQvw6cMQKzvHUzQVsy21yC3PZMIeH7KUjx+EVqLWRFPnARh4DEnnFJ+tE08mmIHrrN7UtxVR1Gxbokw==}
peerDependencies:
three: '>= 0.157.0 < 0.180.0'
potpack@1.0.2:
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==}
@@ -16391,6 +16409,16 @@ snapshots:
transitivePeerDependencies:
- typescript
'@tresjs/post-processing@2.4.0(@tresjs/core@4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2)))(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))':
dependencies:
'@tresjs/core': 4.3.6(three@0.179.0)(typescript@5.9.2)(vue@3.5.18(typescript@5.9.2))
'@vueuse/core': 12.8.2(typescript@5.9.2)
postprocessing: 6.37.7(three@0.179.0)
three: 0.179.0
vue: 3.5.18(typescript@5.9.2)
transitivePeerDependencies:
- typescript
'@tweenjs/tween.js@23.1.3': {}
'@tybys/wasm-util@0.10.0':
@@ -18335,107 +18363,6 @@ snapshots:
- yaml
optional: true
astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0):
dependencies:
'@astrojs/compiler': 2.12.2
'@astrojs/internal-helpers': 0.6.1
'@astrojs/markdown-remark': 6.3.2
'@astrojs/telemetry': 3.3.0
'@capsizecss/unpack': 2.4.0(encoding@0.1.13)
'@oslojs/encoding': 1.1.0
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
acorn: 8.15.0
aria-query: 5.3.2
axobject-query: 4.1.0
boxen: 8.0.1
ci-info: 4.3.0
clsx: 2.1.1
common-ancestor-path: 1.0.1
cookie: 1.0.2
cssesc: 3.0.0
debug: 4.4.1
deterministic-object-hash: 2.0.2
devalue: 5.1.1
diff: 5.2.0
dlv: 1.1.3
dset: 3.1.4
es-module-lexer: 1.7.0
esbuild: 0.25.8
estree-walker: 3.0.3
flattie: 1.1.1
fontace: 0.3.0
github-slugger: 2.0.0
html-escaper: 3.0.3
http-cache-semantics: 4.2.0
import-meta-resolve: 4.1.0
js-yaml: 4.1.0
kleur: 4.1.5
magic-string: 0.30.17
magicast: 0.3.5
mrmime: 2.0.1
neotraverse: 0.6.18
p-limit: 6.2.0
p-queue: 8.1.0
package-manager-detector: 1.3.0
picomatch: 4.0.3
prompts: 2.4.2
rehype: 13.0.2
semver: 7.7.2
shiki: 3.9.1
tinyexec: 0.3.2
tinyglobby: 0.2.14
tsconfck: 3.1.6(typescript@5.9.2)
ultrahtml: 1.6.0
unifont: 0.5.2
unist-util-visit: 5.0.0
unstorage: 1.16.0
vfile: 6.0.3
vite: 6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
vitefu: 1.0.7(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
xxhash-wasm: 1.1.0
yargs-parser: 21.1.1
yocto-spinner: 0.2.3
zod: 3.25.76
zod-to-json-schema: 3.24.6(zod@3.25.76)
zod-to-ts: 1.2.0(typescript@5.9.2)(zod@3.25.76)
optionalDependencies:
sharp: 0.33.5
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
- '@azure/data-tables'
- '@azure/identity'
- '@azure/keyvault-secrets'
- '@azure/storage-blob'
- '@capacitor/preferences'
- '@deno/kv'
- '@netlify/blobs'
- '@planetscale/database'
- '@types/node'
- '@upstash/redis'
- '@vercel/blob'
- '@vercel/kv'
- aws4fetch
- db0
- encoding
- idb-keyval
- ioredis
- jiti
- less
- lightningcss
- rollup
- sass
- sass-embedded
- stylus
- sugarss
- supports-color
- terser
- tsx
- typescript
- uploadthing
- yaml
optional: true
async-mutex@0.3.2:
dependencies:
tslib: 2.8.1
@@ -23105,6 +23032,10 @@ snapshots:
postgres@3.4.7: {}
postprocessing@6.37.7(three@0.179.0):
dependencies:
three: 0.179.0
potpack@1.0.2: {}
prelude-ls@1.2.1: {}
@@ -25280,7 +25211,7 @@ snapshots:
rollup: 4.46.2
vite: rolldown-vite@7.0.12(@types/node@24.1.0)(esbuild@0.25.8)(jiti@2.5.1)(less@4.4.0)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
dependencies:
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
unplugin: 2.3.5
@@ -25288,13 +25219,13 @@ snapshots:
optionalDependencies:
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
astro: 5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
astro: 5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
esbuild: 0.25.8
rolldown: 1.0.0-beta.30
rollup: 4.46.2
vite: 6.3.5(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
unplugin-yaml@3.0.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(@nuxt/schema@3.14.1592(magicast@0.3.5)(rollup@4.46.2))(astro@5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0))(esbuild@0.25.8)(rolldown@1.0.0-beta.30)(rollup@4.46.2)(vite@7.0.6(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)):
dependencies:
'@rollup/pluginutils': 5.2.0(rollup@4.46.2)
unplugin: 2.3.5
@@ -25302,7 +25233,7 @@ snapshots:
optionalDependencies:
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
'@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.46.2)
astro: 5.10.1(@types/node@24.1.0)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
astro: 5.10.1(@types/node@24.1.0)(encoding@0.1.13)(jiti@2.5.1)(less@4.4.0)(lightningcss@1.30.1)(rollup@4.46.2)(terser@5.43.1)(tsx@4.20.3)(typescript@5.9.2)(yaml@2.8.0)
esbuild: 0.25.8
rolldown: 1.0.0-beta.30
rollup: 4.46.2