fix(stage-ui): auto eye blink wasn't functioning (#352)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { Application } from '@pixi/app'
|
||||
import type { Cubism4InternalModel, InternalModel } from 'pixi-live2d-display/cubism4'
|
||||
|
||||
import localforage from 'localforage'
|
||||
|
||||
@@ -16,6 +17,13 @@ import { computed, onMounted, onUnmounted, ref, shallowRef, toRef, watch } from
|
||||
import { useLive2DIdleEyeFocus } from '../../../composables/live2d'
|
||||
import { useLive2d, useSettings } from '../../../stores'
|
||||
|
||||
type CubismModel = Cubism4InternalModel['coreModel']
|
||||
type CubismEyeBlink = Cubism4InternalModel['eyeBlink']
|
||||
type PixiLive2DInternalModel = InternalModel & {
|
||||
eyeBlink?: CubismEyeBlink
|
||||
coreModel: CubismModel
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
app?: Application
|
||||
mouthOpenSize?: number
|
||||
@@ -61,10 +69,11 @@ const offset = computed(() => parsePropsOffset())
|
||||
const pixiApp = toRef(() => props.app)
|
||||
const paused = toRef(() => props.paused)
|
||||
const focusAt = toRef(() => props.focusAt)
|
||||
const model = ref<Live2DModel>()
|
||||
const model = ref<Live2DModel<PixiLive2DInternalModel>>()
|
||||
const initialModelWidth = ref<number>(0)
|
||||
const initialModelHeight = ref<number>(0)
|
||||
const mouthOpenSize = computed(() => Math.max(0, Math.min(100, props.mouthOpenSize)))
|
||||
const lastUpdateTime = ref(0)
|
||||
|
||||
const dark = useDark()
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind)
|
||||
@@ -126,7 +135,7 @@ async function loadModel() {
|
||||
model.value = undefined
|
||||
}
|
||||
|
||||
const modelInstance = new Live2DModel()
|
||||
const modelInstance = new Live2DModel<PixiLive2DInternalModel>()
|
||||
|
||||
if (loadSource.value === 'file') {
|
||||
await Live2DFactory.setupLive2DModel(modelInstance, [modelFile.value], { autoInteract: false })
|
||||
@@ -149,7 +158,7 @@ async function loadModel() {
|
||||
})
|
||||
|
||||
const internalModel = model.value.internalModel
|
||||
const coreModel = internalModel.coreModel as any
|
||||
const coreModel = internalModel.coreModel
|
||||
const motionManager = internalModel.motionManager
|
||||
coreModel.setParameterValueById('ParamMouthOpenY', mouthOpenSize.value)
|
||||
|
||||
@@ -179,15 +188,51 @@ async function loadModel() {
|
||||
}
|
||||
|
||||
// This is hacky too
|
||||
const hookedUpdate = motionManager.update
|
||||
motionManager.update = function (model, now) {
|
||||
hookedUpdate?.call(this, model, now)
|
||||
// Only update eye focus when the model is idle
|
||||
if (motionManager.state.currentGroup === motionManager.groups.idle) {
|
||||
idleEyeFocus.update(internalModel, now)
|
||||
const hookedUpdate = motionManager.update as (model: CubismModel, now: number) => boolean
|
||||
motionManager.update = function (model: CubismModel, now: number) {
|
||||
// Let's initialize the last update time first
|
||||
if (lastUpdateTime.value === 0) {
|
||||
lastUpdateTime.value = now
|
||||
}
|
||||
|
||||
return true
|
||||
hookedUpdate?.call(this, model, now)
|
||||
// Possibility 1: Only update eye focus when the model is idle
|
||||
// Possibility 2: For models having no motion groups, currentGroup will be undefined while groups can be { idle: ... }
|
||||
if (!motionManager.state.currentGroup || motionManager.state.currentGroup === motionManager.groups.idle) {
|
||||
idleEyeFocus.update(internalModel, now)
|
||||
|
||||
// If the model has eye blink parameters
|
||||
if (internalModel.eyeBlink != null) {
|
||||
// For the part of the auto eye blink implementation in pixi-live2d-display
|
||||
//
|
||||
// this.emit("beforeMotionUpdate");
|
||||
// const motionUpdated = this.motionManager.update(this.coreModel, now);
|
||||
// this.emit("afterMotionUpdate");
|
||||
// model.saveParameters();
|
||||
// this.motionManager.expressionManager?.update(model, now);
|
||||
// if (!motionUpdated) {
|
||||
// this.eyeBlink?.updateParameters(model, dt);
|
||||
// }
|
||||
//
|
||||
// https://github.com/guansss/pixi-live2d-display/blob/31317b37d5e22955a44d5b11f37f421e94a11269/src/cubism4/Cubism4InternalModel.ts#L202-L214
|
||||
//
|
||||
// If the this.motionManager.update returns true, as motion updated flag on,
|
||||
// the eye blink parameters will not be updated, in another hand, the auto eye blink is disabled
|
||||
//
|
||||
// Since we are hooking the motionManager.update method currently,
|
||||
// and previously a always `true` was returned, eye blink parameters were never updated.
|
||||
//
|
||||
// Thous we are here to manually update the eye blink parameters within this hooked method
|
||||
internalModel.eyeBlink.updateParameters(model, (now - lastUpdateTime.value) / 1000)
|
||||
}
|
||||
|
||||
// still, mark the motion as updated
|
||||
return true
|
||||
}
|
||||
|
||||
lastUpdateTime.value = now
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
motionManager.on('motionStart', (group, index) => {
|
||||
|
||||
Reference in New Issue
Block a user