@@ -3,14 +3,13 @@ import { v4 as uuid } from 'uuid';
3
3
import { webgalStore } from '@/store/store' ;
4
4
import { setStage , stageActions } from '@/store/stageReducer' ;
5
5
import cloneDeep from 'lodash/cloneDeep' ;
6
- import { IEffect , IFigureAssociatedAnimation , IFigureMetadata } from '@/store/stageInterface' ;
6
+ import { IEffect , IFigureAssociatedAnimation , IFigureMetadata , ITransform } from '@/store/stageInterface' ;
7
7
import { logger } from '@/Core/util/logger' ;
8
8
import { isIOS } from '@/Core/initializeScript' ;
9
9
import { WebGALPixiContainer } from '@/Core/controller/stage/pixi/WebGALPixiContainer' ;
10
10
import { WebGAL } from '@/Core/WebGAL' ;
11
- import 'pixi-spine' ; // Do this once at the very start of your code. This registers the loader!
12
- import { Spine } from 'pixi-spine' ;
13
11
import { SCREEN_CONSTANTS } from '@/Core/util/constants' ;
12
+ import { addSpineBgImpl , addSpineFigureImpl } from '@/Core/controller/stage/pixi/spine' ;
14
13
// import { figureCash } from '@/Core/gameScripts/vocal/conentsCash'; // 如果要使用 Live2D,取消这里的注释
15
14
// import { Live2DModel, SoundManager } from 'pixi-live2d-display-webgal'; // 如果要使用 Live2D,取消这里的注释
16
15
@@ -60,28 +59,46 @@ export interface ILive2DRecord {
60
59
window . PIXI = PIXI ;
61
60
62
61
export default class PixiStage {
62
+ public static assignTransform < T extends ITransform > ( target : T , source ?: ITransform ) {
63
+ if ( ! source ) return ;
64
+ const targetScale = target . scale ;
65
+ const targetPosition = target . position ;
66
+ if ( target . scale ) Object . assign ( targetScale , source . scale ) ;
67
+ if ( target . position ) Object . assign ( targetPosition , source . position ) ;
68
+ Object . assign ( target , source ) ;
69
+ target . scale = targetScale ;
70
+ target . position = targetPosition ;
71
+ }
72
+
63
73
/**
64
74
* 当前的 PIXI App
65
75
*/
66
76
public currentApp : PIXI . Application | null = null ;
67
77
public readonly effectsContainer : PIXI . Container ;
68
78
public frameDuration = 16.67 ;
69
79
public notUpdateBacklogEffects = false ;
70
- private readonly figureContainer : PIXI . Container ;
71
- private figureObjects : Array < IStageObject > = [ ] ;
72
- private readonly backgroundContainer : PIXI . Container ;
73
- private backgroundObjects : Array < IStageObject > = [ ] ;
74
-
80
+ public readonly figureContainer : PIXI . Container ;
81
+ public figureObjects : Array < IStageObject > = [ ] ;
82
+ public stageWidth = SCREEN_CONSTANTS . width ;
83
+ public stageHeight = SCREEN_CONSTANTS . height ;
84
+ public assetLoader = new PIXI . Loader ( ) ;
85
+ public readonly backgroundContainer : PIXI . Container ;
86
+ public backgroundObjects : Array < IStageObject > = [ ] ;
87
+ /**
88
+ * 添加 Spine 立绘
89
+ * @param key 立绘的标识,一般和立绘位置有关
90
+ * @param url 立绘图片url
91
+ * @param presetPosition
92
+ */
93
+ public addSpineFigure = addSpineFigureImpl . bind ( this ) ;
94
+ public addSpineBg = addSpineBgImpl . bind ( this ) ;
75
95
// 注册到 Ticker 上的函数
76
96
private stageAnimations : Array < IStageAnimationObject > = [ ] ;
77
- private assetLoader = new PIXI . Loader ( ) ;
78
97
private loadQueue : { url : string ; callback : ( ) => void ; name ?: string } [ ] = [ ] ;
79
98
private live2dFigureRecorder : Array < ILive2DRecord > = [ ] ;
80
-
81
99
// 锁定变换对象(对象可能正在执行动画,不能应用变换)
82
100
private lockTransformTarget : Array < string > = [ ] ;
83
- private stageWidth = SCREEN_CONSTANTS . width ;
84
- private stageHeight = SCREEN_CONSTANTS . height ;
101
+
85
102
/**
86
103
* 暂时没用上,以后可能用
87
104
* @private
@@ -188,7 +205,7 @@ export default class PixiStage {
188
205
const targetPixiContainer = this . getStageObjByKey ( target ) ;
189
206
if ( targetPixiContainer ) {
190
207
const container = targetPixiContainer . pixiContainer ;
191
- Object . assign ( container , effect . transform ) ;
208
+ PixiStage . assignTransform ( container , effect . transform ) ;
192
209
}
193
210
return ;
194
211
}
@@ -396,84 +413,6 @@ export default class PixiStage {
396
413
}
397
414
}
398
415
399
- public addSpineBg ( key : string , url : string ) {
400
- const spineId = `spine-${ url } ` ;
401
- const loader = this . assetLoader ;
402
- // 准备用于存放这个背景的 Container
403
- const thisBgContainer = new WebGALPixiContainer ( ) ;
404
-
405
- // 是否有相同 key 的背景
406
- const setBgIndex = this . backgroundObjects . findIndex ( ( e ) => e . key === key ) ;
407
- const isBgSet = setBgIndex >= 0 ;
408
-
409
- // 已经有一个这个 key 的背景存在了
410
- if ( isBgSet ) {
411
- // 挤占
412
- this . removeStageObjectByKey ( key ) ;
413
- }
414
-
415
- // 挂载
416
- this . backgroundContainer . addChild ( thisBgContainer ) ;
417
- const bgUuid = uuid ( ) ;
418
- this . backgroundObjects . push ( {
419
- uuid : bgUuid ,
420
- key : key ,
421
- pixiContainer : thisBgContainer ,
422
- sourceUrl : url ,
423
- sourceType : 'live2d' ,
424
- sourceExt : this . getExtName ( url ) ,
425
- } ) ;
426
-
427
- // 完成图片加载后执行的函数
428
- const setup = ( ) => {
429
- const spineResource : any = this . assetLoader . resources ?. [ spineId ] ;
430
- // TODO:找一个更好的解法,现在的解法是无论是否复用原来的资源,都设置一个延时以让动画工作正常!
431
- setTimeout ( ( ) => {
432
- if ( spineResource && this . getStageObjByUuid ( bgUuid ) ) {
433
- const bgSpine = new Spine ( spineResource . spineData ) ;
434
- const transY = spineResource ?. spineData ?. y ?? 0 ;
435
- /**
436
- * 重设大小
437
- */
438
- const originalWidth = bgSpine . width ; // TODO: 视图大小可能小于画布大小,应提供参数指定视图大小
439
- const originalHeight = bgSpine . height ; // TODO: 视图大小可能小于画布大小,应提供参数指定视图大小
440
- const scaleX = this . stageWidth / originalWidth ;
441
- const scaleY = this . stageHeight / originalHeight ;
442
- logger . debug ( 'bgSpine state' , bgSpine . state ) ;
443
- // TODO: 也许应该使用 setAnimation 播放初始动画
444
- if ( bgSpine . spineData . animations . length > 0 ) {
445
- // 播放首个动画
446
- bgSpine . state . setAnimation ( 0 , bgSpine . spineData . animations [ 0 ] . name , true ) ;
447
- }
448
- const targetScale = Math . max ( scaleX , scaleY ) ;
449
- const bgSprite = new PIXI . Sprite ( ) ;
450
- bgSprite . addChild ( bgSpine ) ;
451
- bgSprite . scale . x = targetScale ;
452
- bgSprite . scale . y = targetScale ;
453
- bgSprite . anchor . set ( 0.5 ) ;
454
- bgSprite . position . y = this . stageHeight / 2 ;
455
- thisBgContainer . setBaseX ( this . stageWidth / 2 ) ;
456
- thisBgContainer . setBaseY ( this . stageHeight / 2 ) ;
457
- thisBgContainer . pivot . set ( 0 , this . stageHeight / 2 ) ;
458
-
459
- // 挂载
460
- thisBgContainer . addChild ( bgSprite ) ;
461
- }
462
- } , 0 ) ;
463
- } ;
464
-
465
- /**
466
- * 加载器部分
467
- */
468
- this . cacheGC ( ) ;
469
- if ( ! loader . resources ?. [ url ] ) {
470
- this . loadAsset ( url , setup , spineId ) ;
471
- } else {
472
- // 复用
473
- setup ( ) ;
474
- }
475
- }
476
-
477
416
/**
478
417
* 添加立绘
479
418
* @param key 立绘的标识,一般和立绘位置有关
@@ -564,103 +503,6 @@ export default class PixiStage {
564
503
}
565
504
}
566
505
567
- /**
568
- * 添加 Spine 立绘
569
- * @param key 立绘的标识,一般和立绘位置有关
570
- * @param url 立绘图片url
571
- * @param presetPosition
572
- */
573
- public addSpineFigure ( key : string , url : string , presetPosition : 'left' | 'center' | 'right' = 'center' ) {
574
- const spineId = `spine-${ url } ` ;
575
- const loader = this . assetLoader ;
576
- // 准备用于存放这个立绘的 Container
577
- const thisFigureContainer = new WebGALPixiContainer ( ) ;
578
-
579
- // 是否有相同 key 的立绘
580
- const setFigIndex = this . figureObjects . findIndex ( ( e ) => e . key === key ) ;
581
- const isFigSet = setFigIndex >= 0 ;
582
-
583
- // 已经有一个这个 key 的立绘存在了
584
- if ( isFigSet ) {
585
- this . removeStageObjectByKey ( key ) ;
586
- }
587
-
588
- const metadata = this . getFigureMetadataByKey ( key ) ;
589
- if ( metadata ) {
590
- if ( metadata . zIndex ) {
591
- thisFigureContainer . zIndex = metadata . zIndex ;
592
- }
593
- }
594
- // 挂载
595
- this . figureContainer . addChild ( thisFigureContainer ) ;
596
- const figureUuid = uuid ( ) ;
597
- this . figureObjects . push ( {
598
- uuid : figureUuid ,
599
- key : key ,
600
- pixiContainer : thisFigureContainer ,
601
- sourceUrl : url ,
602
- sourceType : 'live2d' ,
603
- sourceExt : this . getExtName ( url ) ,
604
- } ) ;
605
-
606
- // 完成图片加载后执行的函数
607
- const setup = ( ) => {
608
- const spineResource : any = this . assetLoader . resources ?. [ spineId ] ;
609
- // TODO:找一个更好的解法,现在的解法是无论是否复用原来的资源,都设置一个延时以让动画工作正常!
610
- setTimeout ( ( ) => {
611
- if ( spineResource && this . getStageObjByUuid ( figureUuid ) ) {
612
- const figureSpine = new Spine ( spineResource . spineData ) ;
613
- const transY = spineResource ?. spineData ?. y ?? 0 ;
614
- /**
615
- * 重设大小
616
- */
617
- const originalWidth = figureSpine . width ;
618
- const originalHeight = figureSpine . height ;
619
- const scaleX = this . stageWidth / originalWidth ;
620
- const scaleY = this . stageHeight / originalHeight ;
621
- // 我也不知道为什么啊啊啊啊
622
- figureSpine . y = - ( scaleY * transY ) / 2 ;
623
- figureSpine . state . setAnimation ( 0 , '07' , true ) ;
624
- const targetScale = Math . min ( scaleX , scaleY ) ;
625
- const figureSprite = new PIXI . Sprite ( ) ;
626
- figureSprite . addChild ( figureSpine ) ;
627
- figureSprite . scale . x = targetScale ;
628
- figureSprite . scale . y = targetScale ;
629
- figureSprite . anchor . set ( 0.5 ) ;
630
- figureSprite . position . y = this . stageHeight / 2 ;
631
- const targetWidth = originalWidth * targetScale ;
632
- const targetHeight = originalHeight * targetScale ;
633
- thisFigureContainer . setBaseY ( this . stageHeight / 2 ) ;
634
- if ( targetHeight < this . stageHeight ) {
635
- thisFigureContainer . setBaseY ( this . stageHeight / 2 + this . stageHeight - targetHeight / 2 ) ;
636
- }
637
- if ( presetPosition === 'center' ) {
638
- thisFigureContainer . setBaseX ( this . stageWidth / 2 ) ;
639
- }
640
- if ( presetPosition === 'left' ) {
641
- thisFigureContainer . setBaseX ( targetWidth / 2 ) ;
642
- }
643
- if ( presetPosition === 'right' ) {
644
- thisFigureContainer . setBaseX ( this . stageWidth - targetWidth / 2 ) ;
645
- }
646
- thisFigureContainer . pivot . set ( 0 , this . stageHeight / 2 ) ;
647
- thisFigureContainer . addChild ( figureSprite ) ;
648
- }
649
- } , 0 ) ;
650
- } ;
651
-
652
- /**
653
- * 加载器部分
654
- */
655
- this . cacheGC ( ) ;
656
- if ( ! loader . resources ?. [ url ] ) {
657
- this . loadAsset ( url , setup , spineId ) ;
658
- } else {
659
- // 复用
660
- setup ( ) ;
661
- }
662
- }
663
-
664
506
/**
665
507
* Live2d立绘,如果要使用 Live2D,取消这里的注释
666
508
* @param jsonPath
@@ -918,6 +760,26 @@ export default class PixiStage {
918
760
PIXI . utils . clearTextureCache ( ) ;
919
761
}
920
762
763
+ public getExtName ( url : string ) {
764
+ return url . split ( '.' ) . pop ( ) ?? 'png' ;
765
+ }
766
+
767
+ public getFigureMetadataByKey ( key : string ) : IFigureMetadata | undefined {
768
+ console . log ( key , webgalStore . getState ( ) . stage . figureMetaData ) ;
769
+ return webgalStore . getState ( ) . stage . figureMetaData [ key ] ;
770
+ }
771
+
772
+ public loadAsset ( url : string , callback : ( ) => void , name ?: string ) {
773
+ /**
774
+ * Loader 复用疑似有问题,转而采用先前的单独方式
775
+ */
776
+ this . loadQueue . unshift ( { url, callback, name } ) ;
777
+ /**
778
+ * 尝试启动加载
779
+ */
780
+ this . callLoader ( ) ;
781
+ }
782
+
921
783
private updateL2dMotionByKey ( target : string , motion : string ) {
922
784
const figureTargetIndex = this . live2dFigureRecorder . findIndex ( ( e ) => e . target === target ) ;
923
785
if ( figureTargetIndex >= 0 ) {
@@ -936,17 +798,6 @@ export default class PixiStage {
936
798
}
937
799
}
938
800
939
- private loadAsset ( url : string , callback : ( ) => void , name ?: string ) {
940
- /**
941
- * Loader 复用疑似有问题,转而采用先前的单独方式
942
- */
943
- this . loadQueue . unshift ( { url, callback, name } ) ;
944
- /**
945
- * 尝试启动加载
946
- */
947
- this . callLoader ( ) ;
948
- }
949
-
950
801
private callLoader ( ) {
951
802
if ( ! this . assetLoader . loading ) {
952
803
const front = this . loadQueue . shift ( ) ;
@@ -993,15 +844,6 @@ export default class PixiStage {
993
844
const index = this . lockTransformTarget . findIndex ( ( name ) => name === targetName ) ;
994
845
if ( index >= 0 ) this . lockTransformTarget . splice ( index , 1 ) ;
995
846
}
996
-
997
- private getExtName ( url : string ) {
998
- return url . split ( '.' ) . pop ( ) ?? 'png' ;
999
- }
1000
-
1001
- private getFigureMetadataByKey ( key : string ) : IFigureMetadata | undefined {
1002
- console . log ( key , webgalStore . getState ( ) . stage . figureMetaData ) ;
1003
- return webgalStore . getState ( ) . stage . figureMetaData [ key ] ;
1004
- }
1005
847
}
1006
848
1007
849
function updateCurrentBacklogEffects ( newEffects : IEffect [ ] ) {
0 commit comments