diff --git a/packages/stage-ui-three/package.json b/packages/stage-ui-three/package.json index 47a2bb4ca..fe65c3df9 100644 --- a/packages/stage-ui-three/package.json +++ b/packages/stage-ui-three/package.json @@ -27,6 +27,7 @@ "@pixiv/three-vrm-animation": "^3.4.4", "@pixiv/three-vrm-core": "^3.4.4", "@proj-airi/stage-shared": "workspace:*", + "@proj-airi/ui": "workspace:*", "@tresjs/cientos": "^5.2.1", "@tresjs/core": "^5.2.1", "@tresjs/post-processing": "^3.2.0", diff --git a/packages/stage-ui-three/src/components/ThreeScene.vue b/packages/stage-ui-three/src/components/ThreeScene.vue index 831e2532c..3608b1266 100644 --- a/packages/stage-ui-three/src/components/ThreeScene.vue +++ b/packages/stage-ui-three/src/components/ThreeScene.vue @@ -13,6 +13,7 @@ import type { DirectionalLight, SphericalHarmonics3, Texture, WebGLRenderTarget import type { Vec3 } from '../stores/model-store' +import { Screen } from '@proj-airi/ui' import { TresCanvas } from '@tresjs/core' import { EffectComposerPmndrs, HueSaturationPmndrs } from '@tresjs/post-processing' import { useElementBounding } from '@vueuse/core' @@ -53,6 +54,8 @@ const emit = defineEmits<{ (e: 'error', value: unknown): void }>() +const componentState = defineModel<'pending' | 'loading' | 'mounted'>('state', { default: 'pending' }) + const sceneContainerRef = ref() const { width, height } = useElementBounding(sceneContainerRef) const modelStore = useModelStore() @@ -206,38 +209,42 @@ function applyVrmFrameHook() { watch(modelRef, () => applyVrmFrameHook(), { immediate: true }) // === Directional Light === -// TODO: wrap to integrate all the below code +// Directional light setup moved inline, no ready event needed const sceneReady = ref(false) -const dirLightReady = ref(false) - -function onDirLightReady() { - dirLightReady.value = true -} -// Then start to set the camera position and target +// Setup directional light when controls are ready and we have the light ref watch( - [controlsReady, dirLightReady], - ([ctrlOk, modelOk]) => { - if (ctrlOk && modelOk && camera.value && controlsRef.value && controlsRef.value.controls && dirLightRef.value) { - // isUpdatingCamera = true - try { - // setup initial target of directional light - dirLightRef.value.parent?.add(dirLightRef.value.target) - dirLightRef.value.target.position.set( - directionalLightTarget.value.x, - directionalLightTarget.value.y, - directionalLightTarget.value.z, - ) - // console.debug("direction light target set: ", dirLightRef.value.target.position) - dirLightRef.value.target.updateMatrixWorld() - } - finally { - // isUpdatingCamera = false - sceneReady.value = true - } + [controlsReady, modelLoaded, dirLightRef], + ([ctrlOk, loaded, dirLight]) => { + if (!ctrlOk || !loaded || !dirLight || !camera.value || !controlsRef.value?.controls) + return + + try { + // setup initial target of directional light + dirLight.parent?.add(dirLight.target) + dirLight.target.position.set( + directionalLightTarget.value.x, + directionalLightTarget.value.y, + directionalLightTarget.value.z, + ) + dirLight.target.updateMatrixWorld() + sceneReady.value = true + } + catch (error) { + console.error('[ThreeScene] Failed to setup directional light:', error) } }, ) +// Update component state based on scene readiness +watch([sceneReady, modelLoaded], ([ready, loaded]) => { + if (ready && loaded) { + componentState.value = 'mounted' + } + else if (loaded) { + componentState.value = 'loading' + } +}, { immediate: true }) + function updateDirLightTarget(newRotation: { x: number, y: number, z: number }) { const light = dirLightRef.value if (!light) @@ -288,94 +295,95 @@ defineExpose({ diff --git a/packages/stage-ui/src/components/scenes/Stage.vue b/packages/stage-ui/src/components/scenes/Stage.vue index 3e80ef78c..731f0581a 100644 --- a/packages/stage-ui/src/components/scenes/Stage.vue +++ b/packages/stage-ui/src/components/scenes/Stage.vue @@ -382,6 +382,7 @@ onPlaybackStarted(({ text }) => {