Skip to content

Commit 875e8a5

Browse files
Merge branch 'dev' into pr/612
2 parents bd21022 + 24c3e8a commit 875e8a5

File tree

22 files changed

+450
-364
lines changed

22 files changed

+450
-364
lines changed

packages/webgal/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
"modern-css-reset": "^1.4.0",
2323
"pixi-filters": "^4.2.0",
2424
"pixi-live2d-display-webgal": "^0.5.8",
25-
"pixi-spine": "^3.1.2",
2625
"pixi.js": "^6.3.0",
2726
"popmotion": "^11.0.5",
2827
"react": "^17.0.2",
3.44 MB
Binary file not shown.

packages/webgal/src/Core/Modules/animationFunctions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import cloneDeep from 'lodash/cloneDeep';
66
import { baseTransform } from '@/store/stageInterface';
77
import { generateTimelineObj } from '@/Core/controller/stage/pixi/animations/timeline';
88
import { WebGAL } from '@/Core/WebGAL';
9+
import PixiStage from '@/Core/controller/stage/pixi/PixiController';
910

1011
export function getAnimationObject(animationName: string, target: string, duration: number) {
1112
const effect = WebGAL.animationManager.getAnimations().find((ani) => ani.name === animationName);
1213
if (effect) {
1314
const mappedEffects = effect.effects.map((effect) => {
1415
const targetSetEffect = webgalStore.getState().stage.effects.find((e) => e.target === target);
1516
const newEffect = cloneDeep({ ...(targetSetEffect?.transform ?? baseTransform), duration: 0 });
16-
Object.assign(newEffect, effect);
17+
PixiStage.assignTransform(newEffect, effect);
1718
newEffect.duration = effect.duration;
1819
return newEffect;
1920
});

packages/webgal/src/Core/controller/gamePlay/autoPlay.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,9 @@ export const autoNextSentence = () => {
5858
* 自动播放的执行函数
5959
*/
6060
const autoPlay = () => {
61-
const delay = webgalStore.getState().userData.optionData.autoSpeed;
62-
const autoPlayDelay = 750 - 250 * delay;
61+
const data = webgalStore.getState().userData.optionData.autoSpeed;
62+
// 范围为 [250, 1750]
63+
const autoPlayDelay = 250 + (100 - data) * 15;
6364
let isBlockingAuto = false;
6465
WebGAL.gameplay.performController.performList.forEach((e) => {
6566
if (e.blockingAuto())

packages/webgal/src/Core/controller/gamePlay/backToTitle.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { stopFast } from '@/Core/controller/gamePlay/fastSkip';
77
import { setEbg } from '@/Core/gameScripts/changeBg/setEbg';
88

99
export const backToTitle = () => {
10+
if (webgalStore.getState().GUI.showTitle) return;
1011
const dispatch = webgalStore.dispatch;
1112
stopAllPerform();
1213
stopAuto();

packages/webgal/src/Core/controller/stage/pixi/PixiController.ts

Lines changed: 50 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ import { v4 as uuid } from 'uuid';
33
import { webgalStore } from '@/store/store';
44
import { setStage, stageActions } from '@/store/stageReducer';
55
import cloneDeep from 'lodash/cloneDeep';
6-
import { IEffect, IFigureAssociatedAnimation, IFigureMetadata } from '@/store/stageInterface';
6+
import { IEffect, IFigureAssociatedAnimation, IFigureMetadata, ITransform } from '@/store/stageInterface';
77
import { logger } from '@/Core/util/logger';
88
import { isIOS } from '@/Core/initializeScript';
99
import { WebGALPixiContainer } from '@/Core/controller/stage/pixi/WebGALPixiContainer';
1010
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';
1311
import { SCREEN_CONSTANTS } from '@/Core/util/constants';
12+
import { addSpineBgImpl, addSpineFigureImpl } from '@/Core/controller/stage/pixi/spine';
1413
// import { figureCash } from '@/Core/gameScripts/vocal/conentsCash'; // 如果要使用 Live2D,取消这里的注释
1514
// import { Live2DModel, SoundManager } from 'pixi-live2d-display-webgal'; // 如果要使用 Live2D,取消这里的注释
1615

@@ -60,28 +59,46 @@ export interface ILive2DRecord {
6059
window.PIXI = PIXI;
6160

6261
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+
6373
/**
6474
* 当前的 PIXI App
6575
*/
6676
public currentApp: PIXI.Application | null = null;
6777
public readonly effectsContainer: PIXI.Container;
6878
public frameDuration = 16.67;
6979
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);
7595
// 注册到 Ticker 上的函数
7696
private stageAnimations: Array<IStageAnimationObject> = [];
77-
private assetLoader = new PIXI.Loader();
7897
private loadQueue: { url: string; callback: () => void; name?: string }[] = [];
7998
private live2dFigureRecorder: Array<ILive2DRecord> = [];
80-
8199
// 锁定变换对象(对象可能正在执行动画,不能应用变换)
82100
private lockTransformTarget: Array<string> = [];
83-
private stageWidth = SCREEN_CONSTANTS.width;
84-
private stageHeight = SCREEN_CONSTANTS.height;
101+
85102
/**
86103
* 暂时没用上,以后可能用
87104
* @private
@@ -188,7 +205,7 @@ export default class PixiStage {
188205
const targetPixiContainer = this.getStageObjByKey(target);
189206
if (targetPixiContainer) {
190207
const container = targetPixiContainer.pixiContainer;
191-
Object.assign(container, effect.transform);
208+
PixiStage.assignTransform(container, effect.transform);
192209
}
193210
return;
194211
}
@@ -396,84 +413,6 @@ export default class PixiStage {
396413
}
397414
}
398415

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-
477416
/**
478417
* 添加立绘
479418
* @param key 立绘的标识,一般和立绘位置有关
@@ -564,103 +503,6 @@ export default class PixiStage {
564503
}
565504
}
566505

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-
664506
/**
665507
* Live2d立绘,如果要使用 Live2D,取消这里的注释
666508
* @param jsonPath
@@ -918,6 +760,26 @@ export default class PixiStage {
918760
PIXI.utils.clearTextureCache();
919761
}
920762

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+
921783
private updateL2dMotionByKey(target: string, motion: string) {
922784
const figureTargetIndex = this.live2dFigureRecorder.findIndex((e) => e.target === target);
923785
if (figureTargetIndex >= 0) {
@@ -936,17 +798,6 @@ export default class PixiStage {
936798
}
937799
}
938800

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-
950801
private callLoader() {
951802
if (!this.assetLoader.loading) {
952803
const front = this.loadQueue.shift();
@@ -993,15 +844,6 @@ export default class PixiStage {
993844
const index = this.lockTransformTarget.findIndex((name) => name === targetName);
994845
if (index >= 0) this.lockTransformTarget.splice(index, 1);
995846
}
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-
}
1005847
}
1006848

1007849
function updateCurrentBacklogEffects(newEffects: IEffect[]) {

packages/webgal/src/Core/controller/stage/pixi/animations/generateTransformAnimationObj.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ITransform } from '@/store/stageInterface';
22
import { webgalStore } from '@/store/store';
3+
import isNull from 'lodash/isNull';
34

45
type AnimationFrame = ITransform & { duration: number };
56
type AnimationObj = Array<AnimationFrame>;
@@ -14,7 +15,7 @@ export function generateTransformAnimationObj(
1415
const transformState = webgalStore.getState().stage.effects;
1516
const targetEffect = transformState.find((effect) => effect.target === target);
1617
applyFrame.duration = 500;
17-
if (duration && typeof duration === 'number') {
18+
if (!isNull(duration) && typeof duration === 'number') {
1819
applyFrame.duration = duration;
1920
}
2021
animationObj = [applyFrame];

0 commit comments

Comments
 (0)