@@ -3,11 +3,15 @@ import { logger } from '@/Core/util/logger';
33import { generateUniversalSoftOffAnimationObj } from '@/Core/controller/stage/pixi/animations/universalSoftOff' ;
44import { webgalStore } from '@/store/store' ;
55import cloneDeep from 'lodash/cloneDeep' ;
6- import { baseTransform } from '@/store/stageInterface' ;
6+ import { baseTransform , IEffect , ITransform } from '@/store/stageInterface' ;
77import { generateTimelineObj } from '@/Core/controller/stage/pixi/animations/timeline' ;
88import { WebGAL } from '@/Core/WebGAL' ;
9- import PixiStage , { IAnimationObject } from '@/Core/controller/stage/pixi/PixiController' ;
10- import { DEFALUT_FIG_IN_DURATION , DEFALUT_FIG_OUT_DURATION } from '../constants' ;
9+ import PixiStage , { IAnimationObject , IStageObject } from '@/Core/controller/stage/pixi/PixiController' ;
10+ import { DEFAULT_STAGE_OBJECT_ENTER_DURATION , DEFAULT_STAGE_OBJECT_EXIT_DURATION } from '../constants' ;
11+ import { AnimationFrame , IUserAnimation } from './animations' ;
12+ import { generateTransformAnimationObj } from '../controller/stage/pixi/animations/generateTransformAnimationObj' ;
13+ import { getNumberArgByKey , getStringArgByKey } from '../util/getSentenceArg' ;
14+ import { ISentence } from '../controller/scene/sceneInterface' ;
1115
1216// eslint-disable-next-line max-params
1317export function getAnimationObject ( animationName : string , target : string , duration : number , writeDefault : boolean ) {
@@ -46,52 +50,216 @@ export function getAnimateDuration(animationName: string) {
4650 return 0 ;
4751}
4852
53+ /***
54+ * 获取入场或退场动画的对象
55+ * @param target 目标对象
56+ * @param type 动画类型,'enter' 或 'exit'
57+ * @param realTarget 真正的目标对象,用于立绘和背景移除时,打上特殊标记
58+ */
4959// eslint-disable-next-line max-params
5060export function getEnterExitAnimation (
5161 target : string ,
5262 type : 'enter' | 'exit' ,
53- isBg = false ,
54- realTarget ?: string , // 用于立绘和背景移除时,以当前时间打上特殊标记
63+ realTarget ?: string ,
5564) : {
5665 duration : number ;
5766 animation : IAnimationObject | null ;
5867} {
68+ let duration = type === 'enter' ? DEFAULT_STAGE_OBJECT_ENTER_DURATION : DEFAULT_STAGE_OBJECT_EXIT_DURATION ;
69+ // 走默认动画
70+ let animation : IAnimationObject | null = null ;
71+ let animationName : string | undefined ;
5972 if ( type === 'enter' ) {
60- let duration = DEFALUT_FIG_IN_DURATION ;
61- if ( isBg ) {
62- duration = 1500 ;
63- }
64- // 走默认动画
65- let animation : IAnimationObject | null = generateUniversalSoftInAnimationObj ( realTarget ?? target , duration ) ;
66-
67- const transformState = webgalStore . getState ( ) . stage . effects ;
68- const targetEffect = transformState . find ( ( effect ) => effect . target === target ) ;
69-
70- const animarionName = WebGAL . animationManager . nextEnterAnimationName . get ( target ) ;
71- if ( animarionName && ! targetEffect ) {
72- logger . debug ( '取代默认进入动画' , target ) ;
73- animation = getAnimationObject ( animarionName , realTarget ?? target , getAnimateDuration ( animarionName ) , false ) ;
74- duration = getAnimateDuration ( animarionName ) ;
75- // 用后重置
73+ animation = generateUniversalSoftInAnimationObj ( realTarget ?? target , duration ) ;
74+ animationName = WebGAL . animationManager . nextEnterAnimationName . get ( target ) ;
75+ } else {
76+ animation = generateUniversalSoftOffAnimationObj ( realTarget ?? target , duration ) ;
77+ animationName = WebGAL . animationManager . nextExitAnimationName . get ( target ) ;
78+ }
79+
80+ const transformState = webgalStore . getState ( ) . stage . effects ;
81+ const targetEffect = transformState . find ( ( effect ) => effect . target === target ) ;
82+
83+ if ( animationName && ! targetEffect ) {
84+ logger . debug ( `取代默认 ${ type === 'enter' ? '入场' : '退场' } 动画` , target ) ;
85+ animation = getAnimationObject ( animationName , realTarget ?? target , getAnimateDuration ( animationName ) , false ) ;
86+ duration = getAnimateDuration ( animationName ) ;
87+ // 用后重置
88+ if ( type === 'enter' ) {
7689 WebGAL . animationManager . nextEnterAnimationName . delete ( target ) ;
90+ } else {
91+ WebGAL . animationManager . nextExitAnimationName . delete ( target ) ;
7792 }
78- return { duration, animation } ;
93+ }
94+ return { duration, animation } ;
95+ }
96+
97+ /**
98+ * 创建默认的入场或退场动画
99+ * @param type 动画类型,'enter' 或 'exit'
100+ * @param target 目标对象
101+ * @param frame 应用的动画帧
102+ * @param duration 动画持续时间
103+ * @param ease 缓动类型
104+ */
105+ // eslint-disable-next-line max-params
106+ export function createDefaultEnterExitAnimation (
107+ type : 'enter' | 'exit' ,
108+ target : string ,
109+ frame : AnimationFrame ,
110+ duration : number ,
111+ ease : string ,
112+ ) {
113+ const animationObj = generateTransformAnimationObj ( target , frame , duration , ease , type ) ;
114+ const animationName = ( Math . random ( ) * 10 ) . toString ( 16 ) ;
115+ const newAnimation : IUserAnimation = { name : animationName , effects : animationObj } ;
116+ WebGAL . animationManager . addAnimation ( newAnimation ) ;
117+ if ( type === 'enter' ) {
118+ WebGAL . animationManager . nextEnterAnimationName . set ( target , animationName ) ;
79119 } else {
80- // exit
81- let duration = DEFALUT_FIG_OUT_DURATION ;
82- if ( isBg ) {
83- duration = 1500 ;
120+ WebGAL . animationManager . nextExitAnimationName . set ( target , animationName ) ;
121+ }
122+ }
123+
124+ // eslint-disable-next-line max-params
125+ export function createEnterExitAnimation (
126+ sentence : ISentence ,
127+ targetKey : string ,
128+ defaultDuration : number ,
129+ currentTransform : ITransform ,
130+ ) : number {
131+ // 处理 transform 和 默认 transform
132+ const transformString = getStringArgByKey ( sentence , 'transform' ) ;
133+ const ease = getStringArgByKey ( sentence , 'ease' ) ?? '' ;
134+ let duration = getNumberArgByKey ( sentence , 'duration' ) ?? defaultDuration ;
135+
136+ if ( transformString ) {
137+ console . log ( transformString ) ;
138+ try {
139+ const transform = JSON . parse ( transformString . toString ( ) ) as ITransform ;
140+ const enterFrame = { ...transform , duration : 0 , ease : '' } ;
141+ const exitFrame = { ...currentTransform , duration : 0 , ease : '' } ;
142+ createDefaultEnterExitAnimation ( 'enter' , targetKey , enterFrame , duration , ease ) ;
143+ createDefaultEnterExitAnimation ( 'exit' , targetKey , exitFrame , duration , ease ) ;
144+ } catch ( e ) {
145+ // 解析都错误了,歇逼吧
146+ applyDefaultTransform ( ) ;
84147 }
85- // 走默认动画
86- let animation : IAnimationObject | null = generateUniversalSoftOffAnimationObj ( realTarget ?? target , duration ) ;
87- const animarionName = WebGAL . animationManager . nextExitAnimationName . get ( target ) ;
88- if ( animarionName ) {
89- logger . debug ( '取代默认退出动画' , target ) ;
90- animation = getAnimationObject ( animarionName , realTarget ?? target , getAnimateDuration ( animarionName ) , false ) ;
91- duration = getAnimateDuration ( animarionName ) ;
92- // 用后重置
93- WebGAL . animationManager . nextExitAnimationName . delete ( target ) ;
148+ } else {
149+ applyDefaultTransform ( ) ;
150+ }
151+
152+ function applyDefaultTransform ( ) {
153+ const enterFrame = { ...baseTransform , duration : 0 , ease : '' } ;
154+ const exitFrame = { ...currentTransform , duration : 0 , ease : '' } ;
155+ createDefaultEnterExitAnimation ( 'enter' , targetKey , enterFrame , duration , ease ) ;
156+ createDefaultEnterExitAnimation ( 'exit' , targetKey , exitFrame , duration , ease ) ;
157+ }
158+
159+ const enterAnimation = getStringArgByKey ( sentence , 'enter' ) ;
160+ const exitAnimation = getStringArgByKey ( sentence , 'exit' ) ;
161+ if ( enterAnimation ) {
162+ WebGAL . animationManager . nextEnterAnimationName . set ( targetKey , enterAnimation ) ;
163+ duration = getAnimateDuration ( enterAnimation ) ;
164+ }
165+ if ( exitAnimation ) {
166+ WebGAL . animationManager . nextExitAnimationName . set ( targetKey , exitAnimation ) ;
167+ duration = getAnimateDuration ( exitAnimation ) ;
168+ }
169+
170+ return duration ;
171+ }
172+
173+ export function getOldTargetSuffix ( ) : string {
174+ return '-old' ;
175+ }
176+
177+ export function getOldTargetKey ( targetKey : string ) : string {
178+ const dateString = String ( new Date ( ) . getTime ( ) ) ;
179+ return targetKey + dateString + getOldTargetSuffix ( ) ;
180+ }
181+
182+ export function getEnterAnimationKey ( targetKey : string ) : string {
183+ return targetKey + '-enter' ;
184+ }
185+
186+ export function getExitAnimationKey ( targetKey : string ) : string {
187+ return targetKey + '-exit' ;
188+ }
189+
190+ /**
191+ * 移除指定的场景对象及其动画
192+ * @param targetKey 目标对象的 key
193+ * @param currentEffects 当前场景效果列表
194+ */
195+ export function removeStageObjectWithAnimationByKey ( targetKey : string , currentEffects : IEffect [ ] ) {
196+ // 移除入场动画
197+ const enterAnimationKey = getEnterAnimationKey ( targetKey ) ;
198+ WebGAL . gameplay . pixiStage ?. removeAnimation ( enterAnimationKey , false ) ;
199+ // 快进,跳过退出动画
200+ if ( WebGAL . gameplay . isFast ) {
201+ logger . debug ( '快速模式,立刻关闭立绘' ) ;
202+ WebGAL . gameplay . pixiStage ?. removeStageObjectByKey ( targetKey ) ;
203+ return ;
204+ }
205+ const oldTarget = WebGAL . gameplay . pixiStage ?. getStageObjByKey ( targetKey ) ;
206+ if ( oldTarget ) {
207+ // 修改旧目标的 key, 以避免和新目标冲突
208+ const oldTargetKey = getOldTargetKey ( targetKey ) ;
209+ oldTarget . key = oldTargetKey ;
210+ // 注册退场动画
211+ const exitAnimationKey = getExitAnimationKey ( targetKey ) ;
212+ const { duration, animation } = getEnterExitAnimation ( targetKey , 'exit' , oldTargetKey ) ;
213+ WebGAL . gameplay . pixiStage ?. registerPresetAnimation ( animation , exitAnimationKey , oldTargetKey , currentEffects ) ;
214+ // 在动画结束后移除对象及其动画
215+ setTimeout ( ( ) => {
216+ WebGAL . gameplay . pixiStage ?. removeAnimation ( exitAnimationKey , false , false ) ;
217+ WebGAL . gameplay . pixiStage ?. removeStageObjectByKey ( oldTargetKey ) ;
218+ } , duration ) ;
219+ }
220+ }
221+
222+ /***
223+ * 添加或移除场景对象
224+ * @param targetKey 目标对象的 key
225+ * @param newUrl 新的资源地址
226+ * @param currentEffects 当前场景效果列表
227+ * @param addFunction 添加函数
228+ */
229+ // eslint-disable-next-line max-params
230+ export function addOrRemoveStageObject (
231+ targetKey : string ,
232+ newUrl : string ,
233+ currentEffects : IEffect [ ] ,
234+ addFunction : Function ,
235+ ) {
236+ if ( newUrl !== '' ) {
237+ // 如果对象存在且地址不同,移除旧对象, 并添加新对象
238+ const currentStageObject = WebGAL . gameplay . pixiStage ?. getStageObjByKey ( targetKey ) ;
239+ if ( currentStageObject ) {
240+ if ( currentStageObject . sourceUrl !== newUrl ) {
241+ logger . debug ( `移除目标 ${ targetKey } : ${ currentStageObject . sourceUrl } ` ) ;
242+ removeStageObjectWithAnimationByKey ( targetKey , currentEffects ) ;
243+ // 添加新对象
244+ logger . debug ( `新增目标 ${ targetKey } : ${ newUrl } ` ) ;
245+ addFunction ( ) ;
246+ // 注册入场动画
247+ const enterAnimationKey = getEnterAnimationKey ( targetKey ) ;
248+ const { duration, animation } = getEnterExitAnimation ( targetKey , 'enter' ) ;
249+ WebGAL . gameplay . pixiStage ! . registerPresetAnimation ( animation , enterAnimationKey , targetKey , currentEffects ) ;
250+ }
251+ } else {
252+ // 如果对象不存在,添加新对象
253+ logger . debug ( `新增目标 ${ targetKey } : ${ newUrl } ` ) ;
254+ addFunction ( ) ;
255+ // 注册入场动画
256+ const enterAnimationKey = getEnterAnimationKey ( targetKey ) ;
257+ const { duration, animation } = getEnterExitAnimation ( targetKey , 'enter' ) ;
258+ WebGAL . gameplay . pixiStage ! . registerPresetAnimation ( animation , enterAnimationKey , targetKey , currentEffects ) ;
94259 }
95- return { duration, animation } ;
260+ } else {
261+ // 如果新地址为空,移除对象
262+ logger . debug ( `移除目标 ${ targetKey } ` ) ;
263+ removeStageObjectWithAnimationByKey ( targetKey , currentEffects ) ;
96264 }
97265}
0 commit comments