diff --git a/packages/webgal/src/Core/Modules/animationFunctions.ts b/packages/webgal/src/Core/Modules/animationFunctions.ts index bf9d167ae..662a2b7e9 100644 --- a/packages/webgal/src/Core/Modules/animationFunctions.ts +++ b/packages/webgal/src/Core/Modules/animationFunctions.ts @@ -110,3 +110,35 @@ export function getEnterExitAnimation( return { duration, animation }; } } + +// eslint-disable-next-line max-params +export function registerTimelineAnimation( + animationName: string, + animationKey: string, + target: string, + animationDuration: number, + writeDefault: boolean, +) { + WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget(target); + const animationObj: IAnimationObject | null = getAnimationObject( + animationName, + target, + animationDuration, + writeDefault, + ); + if (animationObj) { + logger.debug(`动画${animationName}作用在${target}`, animationDuration); + WebGAL.gameplay.pixiStage?.registerAnimation(animationObj, animationKey, target); + } +} + +export function removeTimelineAnimation(animationKey: string, keep: boolean): boolean { + if (keep) { + WebGAL.gameplay.pixiStage?.removeAnimationWithoutSetEndState(animationKey); + return true; + } + setTimeout(() => { + WebGAL.gameplay.pixiStage?.removeAnimationWithSetEffects(animationKey); + }, 0); + return false; +} diff --git a/packages/webgal/src/Core/gameScripts/changeBg/index.ts b/packages/webgal/src/Core/gameScripts/changeBg/index.ts index c40c98e3b..7514f75f0 100644 --- a/packages/webgal/src/Core/gameScripts/changeBg/index.ts +++ b/packages/webgal/src/Core/gameScripts/changeBg/index.ts @@ -4,14 +4,18 @@ import { IPerform } from '@/Core/Modules/perform/performInterface'; import styles from '@/Stage/stage.module.scss'; import { webgalStore } from '@/store/store'; import { setStage, stageActions } from '@/store/stageReducer'; -import { getNumberArgByKey, getStringArgByKey } from '@/Core/util/getSentenceArg'; +import { getBooleanArgByKey, getNumberArgByKey, getStringArgByKey } from '@/Core/util/getSentenceArg'; import { unlockCgInUserData } from '@/store/userDataReducer'; import { logger } from '@/Core/util/logger'; import { ITransform } from '@/store/stageInterface'; import { generateTransformAnimationObj } from '@/Core/controller/stage/pixi/animations/generateTransformAnimationObj'; import { AnimationFrame, IUserAnimation } from '@/Core/Modules/animations'; import cloneDeep from 'lodash/cloneDeep'; -import { getAnimateDuration } from '@/Core/Modules/animationFunctions'; +import { + getAnimateDuration, + registerTimelineAnimation, + removeTimelineAnimation, +} from '@/Core/Modules/animationFunctions'; import { WebGAL } from '@/Core/WebGAL'; import { DEFAULT_BG_OUT_DURATION } from '@/Core/constants'; import localforage from 'localforage'; @@ -27,6 +31,7 @@ export const changeBg = (sentence: ISentence): IPerform => { const series = getStringArgByKey(sentence, 'series') ?? 'default'; const transformString = getStringArgByKey(sentence, 'transform'); let duration = getNumberArgByKey(sentence, 'duration') ?? DEFAULT_BG_OUT_DURATION; + const writeDefault = getBooleanArgByKey(sentence, 'writeDefault') ?? false; const enterDuration = getNumberArgByKey(sentence, 'enterDuration') ?? duration; duration = enterDuration; const exitDuration = getNumberArgByKey(sentence, 'exitDuration') ?? DEFAULT_BG_OUT_DURATION; @@ -52,21 +57,29 @@ export const changeBg = (sentence: ISentence): IPerform => { dispatch(stageActions.removeAnimationSettingsByTarget(`bg-main`)); } + const animationName = (Math.random() * 10).toString(16); + const animationKey = `bg-main-${animationName}`; + // 处理 transform 和 默认 transform let animationObj: AnimationFrame[]; if (transformString) { try { const frame = JSON.parse(transformString.toString()) as AnimationFrame; animationObj = generateTransformAnimationObj('bg-main', frame, enterDuration, ease); - // 因为是切换,必须把一开始的 alpha 改为 0 - animationObj[0].alpha = 0; - const animationName = (Math.random() * 10).toString(16); const newAnimation: IUserAnimation = { name: animationName, effects: animationObj }; WebGAL.animationManager.addAnimation(newAnimation); duration = getAnimateDuration(animationName); - webgalStore.dispatch( - stageActions.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationName', value: animationName }), - ); + if (isUrlChanged) { + webgalStore.dispatch( + stageActions.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationName', value: animationName }), + ); + } else { + const animationPerformInitName = `animation-bg-main`; + WebGAL.gameplay.performController.unmountPerform(animationPerformInitName, true); + setTimeout(() => { + registerTimelineAnimation(animationName, animationKey, 'bg-main', duration, writeDefault); + }, 0); + } } catch (e) { // 解析都错误了,歇逼吧 applyDefaultTransform(); @@ -79,15 +92,20 @@ export const changeBg = (sentence: ISentence): IPerform => { // 应用默认的 const frame = {}; animationObj = generateTransformAnimationObj('bg-main', frame as AnimationFrame, duration, ease); - // 因为是切换,必须把一开始的 alpha 改为 0 - animationObj[0].alpha = 0; - const animationName = (Math.random() * 10).toString(16); const newAnimation: IUserAnimation = { name: animationName, effects: animationObj }; WebGAL.animationManager.addAnimation(newAnimation); duration = getAnimateDuration(animationName); - webgalStore.dispatch( - stageActions.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationName', value: animationName }), - ); + if (isUrlChanged) { + webgalStore.dispatch( + stageActions.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationName', value: animationName }), + ); + } else if (transformString) { + const animationPerformInitName = `animation-bg-main`; + WebGAL.gameplay.performController.unmountPerform(animationPerformInitName, true); + setTimeout(() => { + registerTimelineAnimation(animationName, animationKey, 'bg-main', duration, writeDefault); + }, 0); + } } // 应用动画的优先级更高一点 @@ -134,7 +152,11 @@ export const changeBg = (sentence: ISentence): IPerform => { duration, isHoldOn: false, stopFunction: () => { - WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget('bg-main'); + if (isUrlChanged) { + WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget('bg-main'); + } else { + removeTimelineAnimation(animationKey, false); + } }, blockingNext: () => false, blockingAuto: () => true, diff --git a/packages/webgal/src/Core/gameScripts/changeFigure.ts b/packages/webgal/src/Core/gameScripts/changeFigure.ts index 702fce3a5..9132de1fe 100644 --- a/packages/webgal/src/Core/gameScripts/changeFigure.ts +++ b/packages/webgal/src/Core/gameScripts/changeFigure.ts @@ -9,7 +9,11 @@ import { AnimationFrame, IUserAnimation } from '@/Core/Modules/animations'; import { generateTransformAnimationObj } from '@/Core/controller/stage/pixi/animations/generateTransformAnimationObj'; import { assetSetter, fileType } from '@/Core/util/gameAssetsAccess/assetSetter'; import { logger } from '@/Core/util/logger'; -import { getAnimateDuration } from '@/Core/Modules/animationFunctions'; +import { + getAnimateDuration, + registerTimelineAnimation, + removeTimelineAnimation, +} from '@/Core/Modules/animationFunctions'; import { WebGAL } from '@/Core/WebGAL'; import { baseBlinkParam, baseFocusParam, BlinkParam, FocusParam } from '@/Core/live2DCore'; import { DEFAULT_FIG_IN_DURATION, DEFAULT_FIG_OUT_DURATION, WEBGAL_NONE } from '../constants'; @@ -88,6 +92,7 @@ export function changeFigure(sentence: ISentence): IPerform { const transformString = getStringArgByKey(sentence, 'transform'); const ease = getStringArgByKey(sentence, 'ease') ?? ''; let duration = getNumberArgByKey(sentence, 'duration') ?? DEFAULT_FIG_IN_DURATION; + const writeDefault = getBooleanArgByKey(sentence, 'writeDefault') ?? false; const enterAnimation = getStringArgByKey(sentence, 'enter'); const exitAnimation = getStringArgByKey(sentence, 'exit'); let zIndex = getNumberArgByKey(sentence, 'zIndex') ?? -1; @@ -155,6 +160,10 @@ export function changeFigure(sentence: ISentence): IPerform { oldStageObject.isExiting = true; } } + + const animationName = (Math.random() * 10).toString(16); + const animationKey = `${id}-${animationName}`; + const setAnimationNames = (key: string, sentence: ISentence) => { // 如果立绘被关闭了,那么就不用设置了 if (content === '') { @@ -167,15 +176,20 @@ export function changeFigure(sentence: ISentence): IPerform { try { const frame = JSON.parse(transformString) as AnimationFrame; animationObj = generateTransformAnimationObj(key, frame, duration, ease); - // 因为是切换,必须把一开始的 alpha 改为 0 - animationObj[0].alpha = 0; - const animationName = (Math.random() * 10).toString(16); const newAnimation: IUserAnimation = { name: animationName, effects: animationObj }; WebGAL.animationManager.addAnimation(newAnimation); duration = getAnimateDuration(animationName); - webgalStore.dispatch( - stageActions.updateAnimationSettings({ target: key, key: 'enterAnimationName', value: animationName }), - ); + if (isUrlChanged) { + webgalStore.dispatch( + stageActions.updateAnimationSettings({ target: key, key: 'enterAnimationName', value: animationName }), + ); + } else { + const animationPerformInitName = `animation-${id}`; + WebGAL.gameplay.performController.unmountPerform(animationPerformInitName, true); + setTimeout(() => { + registerTimelineAnimation(animationName, animationKey, id, duration, writeDefault); + }, 0); + } } catch (e) { // 解析都错误了,歇逼吧 applyDefaultTransform(); @@ -188,15 +202,20 @@ export function changeFigure(sentence: ISentence): IPerform { // 应用默认的 const frame = {}; animationObj = generateTransformAnimationObj(key, frame as AnimationFrame, duration, ease); - // 因为是切换,必须把一开始的 alpha 改为 0 - animationObj[0].alpha = 0; - const animationName = (Math.random() * 10).toString(16); const newAnimation: IUserAnimation = { name: animationName, effects: animationObj }; WebGAL.animationManager.addAnimation(newAnimation); duration = getAnimateDuration(animationName); - webgalStore.dispatch( - stageActions.updateAnimationSettings({ target: key, key: 'enterAnimationName', value: animationName }), - ); + if (isUrlChanged) { + webgalStore.dispatch( + stageActions.updateAnimationSettings({ target: key, key: 'enterAnimationName', value: animationName }), + ); + } else if (transformString) { + const animationPerformInitName = `animation-${id}`; + WebGAL.gameplay.performController.unmountPerform(animationPerformInitName, true); + setTimeout(() => { + registerTimelineAnimation(animationName, animationKey, id, duration, writeDefault); + }, 0); + } } if (enterAnimation) { @@ -298,7 +317,11 @@ export function changeFigure(sentence: ISentence): IPerform { duration, isHoldOn: false, stopFunction: () => { - WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget(key); + if (isUrlChanged) { + WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget(key); + } else { + removeTimelineAnimation(animationKey, false); + } }, blockingNext: () => false, blockingAuto: () => true, diff --git a/packages/webgal/src/Core/gameScripts/setAnimation.ts b/packages/webgal/src/Core/gameScripts/setAnimation.ts index 748b4498a..6876a2263 100644 --- a/packages/webgal/src/Core/gameScripts/setAnimation.ts +++ b/packages/webgal/src/Core/gameScripts/setAnimation.ts @@ -1,11 +1,14 @@ import { ISentence } from '@/Core/controller/scene/sceneInterface'; import { IPerform } from '@/Core/Modules/perform/performInterface'; import { getBooleanArgByKey, getStringArgByKey } from '@/Core/util/getSentenceArg'; -import { IAnimationObject } from '@/Core/controller/stage/pixi/PixiController'; import { logger } from '@/Core/util/logger'; import { webgalStore } from '@/store/store'; -import { getAnimateDuration, getAnimationObject } from '@/Core/Modules/animationFunctions'; +import { + getAnimateDuration, + registerTimelineAnimation, + removeTimelineAnimation, +} from '@/Core/Modules/animationFunctions'; import { WebGAL } from '@/Core/WebGAL'; /** @@ -13,7 +16,6 @@ import { WebGAL } from '@/Core/WebGAL'; * @param sentence */ export const setAnimation = (sentence: ISentence): IPerform => { - const startDialogKey = webgalStore.getState().stage.currentDialogKey; const animationName = sentence.content; const animationDuration = getAnimateDuration(animationName); let target = getStringArgByKey(sentence, 'target') ?? ''; @@ -21,31 +23,21 @@ export const setAnimation = (sentence: ISentence): IPerform => { const writeDefault = getBooleanArgByKey(sentence, 'writeDefault') ?? false; const keep = getBooleanArgByKey(sentence, 'keep') ?? false; - const key = `${target}-${animationName}-${animationDuration}`; const performInitName = `animation-${target}`; - WebGAL.gameplay.performController.unmountPerform(performInitName, true); - let stopFunction; + const animationKey = `${target}-${animationName}-${animationDuration}`; + let keepAnimationStopped = false; + setTimeout(() => { - WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget(target); - const animationObj: IAnimationObject | null = getAnimationObject( - animationName, - target, - animationDuration, - writeDefault, - ); - if (animationObj) { - logger.debug(`动画${animationName}作用在${target}`, animationDuration); - WebGAL.gameplay.pixiStage?.registerAnimation(animationObj, key, target); + if (keep && keepAnimationStopped) { + return; } + registerTimelineAnimation(animationName, animationKey, target, animationDuration, writeDefault); }, 0); - stopFunction = () => { - setTimeout(() => { - const endDialogKey = webgalStore.getState().stage.currentDialogKey; - const isHasNext = startDialogKey !== endDialogKey; - WebGAL.gameplay.pixiStage?.removeAnimationWithSetEffects(key); - }, 0); + + const stopFunction = () => { + keepAnimationStopped = removeTimelineAnimation(animationKey, keep); }; return { diff --git a/packages/webgal/src/Core/gameScripts/setTempAnimation.ts b/packages/webgal/src/Core/gameScripts/setTempAnimation.ts index 8da9635f7..d99ce19d5 100644 --- a/packages/webgal/src/Core/gameScripts/setTempAnimation.ts +++ b/packages/webgal/src/Core/gameScripts/setTempAnimation.ts @@ -1,14 +1,17 @@ import { ISentence } from '@/Core/controller/scene/sceneInterface'; import { IPerform } from '@/Core/Modules/perform/performInterface'; import { getBooleanArgByKey, getStringArgByKey } from '@/Core/util/getSentenceArg'; -import { IAnimationObject } from '@/Core/controller/stage/pixi/PixiController'; import { logger } from '@/Core/util/logger'; import { webgalStore } from '@/store/store'; import { generateTimelineObj } from '@/Core/controller/stage/pixi/animations/timeline'; import cloneDeep from 'lodash/cloneDeep'; import { baseTransform } from '@/store/stageInterface'; import { IUserAnimation } from '../Modules/animations'; -import { getAnimateDuration, getAnimationObject } from '@/Core/Modules/animationFunctions'; +import { + getAnimateDuration, + registerTimelineAnimation, + removeTimelineAnimation, +} from '@/Core/Modules/animationFunctions'; import { WebGAL } from '@/Core/WebGAL'; /** @@ -16,7 +19,6 @@ import { WebGAL } from '@/Core/WebGAL'; * @param sentence */ export const setTempAnimation = (sentence: ISentence): IPerform => { - const startDialogKey = webgalStore.getState().stage.currentDialogKey; const animationName = (Math.random() * 10).toString(16); const animationString = sentence.content; let animationObj; @@ -32,31 +34,21 @@ export const setTempAnimation = (sentence: ISentence): IPerform => { const writeDefault = getBooleanArgByKey(sentence, 'writeDefault') ?? false; const keep = getBooleanArgByKey(sentence, 'keep') ?? false; - const key = `${target}-${animationName}-${animationDuration}`; const performInitName = `animation-${target}`; - WebGAL.gameplay.performController.unmountPerform(performInitName, true); - let stopFunction = () => {}; + const animationKey = `${target}-${animationName}-${animationDuration}`; + let keepAnimationStopped = false; + setTimeout(() => { - WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget(target); - const animationObj: IAnimationObject | null = getAnimationObject( - animationName, - target, - animationDuration, - writeDefault, - ); - if (animationObj) { - logger.debug(`动画${animationName}作用在${target}`, animationDuration); - WebGAL.gameplay.pixiStage?.registerAnimation(animationObj, key, target); + if (keep && keepAnimationStopped) { + return; } + registerTimelineAnimation(animationName, animationKey, target, animationDuration, writeDefault); }, 0); - stopFunction = () => { - setTimeout(() => { - const endDialogKey = webgalStore.getState().stage.currentDialogKey; - const isHasNext = startDialogKey !== endDialogKey; - WebGAL.gameplay.pixiStage?.removeAnimationWithSetEffects(key); - }, 0); + + const stopFunction = () => { + keepAnimationStopped = removeTimelineAnimation(animationKey, keep); }; return { diff --git a/packages/webgal/src/Core/gameScripts/setTransform.ts b/packages/webgal/src/Core/gameScripts/setTransform.ts index 149287293..722f7a8b5 100644 --- a/packages/webgal/src/Core/gameScripts/setTransform.ts +++ b/packages/webgal/src/Core/gameScripts/setTransform.ts @@ -10,14 +10,13 @@ import { baseTransform, ITransform } from '@/store/stageInterface'; import { AnimationFrame, IUserAnimation } from '../Modules/animations'; import { generateTransformAnimationObj } from '@/Core/controller/stage/pixi/animations/generateTransformAnimationObj'; import { WebGAL } from '@/Core/WebGAL'; -import { getAnimateDuration, getAnimationObject } from '../Modules/animationFunctions'; +import { getAnimateDuration, registerTimelineAnimation, removeTimelineAnimation } from '../Modules/animationFunctions'; /** * 设置变换 * @param sentence */ export const setTransform = (sentence: ISentence): IPerform => { - const startDialogKey = webgalStore.getState().stage.currentDialogKey; const animationName = (Math.random() * 10).toString(16); const animationString = sentence.content; let animationObj: AnimationFrame[]; @@ -29,7 +28,6 @@ export const setTransform = (sentence: ISentence): IPerform => { const keep = getBooleanArgByKey(sentence, 'keep') ?? false; const performInitName = `animation-${target}`; - WebGAL.gameplay.performController.unmountPerform(performInitName, true); try { @@ -45,33 +43,18 @@ export const setTransform = (sentence: ISentence): IPerform => { WebGAL.animationManager.addAnimation(newAnimation); const animationDuration = getAnimateDuration(animationName); - const key = `${target}-${animationName}-${animationDuration}`; + const animationKey = `${target}-${animationName}-${animationDuration}`; let keepAnimationStopped = false; + setTimeout(() => { if (keep && keepAnimationStopped) { return; } - WebGAL.gameplay.pixiStage?.stopPresetAnimationOnTarget(target); - const animationObj: IAnimationObject | null = getAnimationObject( - animationName, - target, - animationDuration, - writeDefault, - ); - if (animationObj) { - logger.debug(`动画${animationName}作用在${target}`, animationDuration); - WebGAL.gameplay.pixiStage?.registerAnimation(animationObj, key, target); - } + registerTimelineAnimation(animationName, animationKey, target, animationDuration, writeDefault); }, 0); + const stopFunction = () => { - if (keep) { - WebGAL.gameplay.pixiStage?.removeAnimationWithoutSetEndState(key); - keepAnimationStopped = true; - return; - } - setTimeout(() => { - WebGAL.gameplay.pixiStage?.removeAnimationWithSetEffects(key); - }, 0); + keepAnimationStopped = removeTimelineAnimation(animationKey, keep); }; return {