Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 33 additions & 70 deletions packages/webgal/src/Core/Modules/animationFunctions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { generateUniversalSoftInAnimationObj } from '@/Core/controller/stage/pixi/animations/universalSoftIn';
import { logger } from '@/Core/util/logger';
import { generateUniversalSoftOffAnimationObj } from '@/Core/controller/stage/pixi/animations/universalSoftOff';
import cloneDeep from 'lodash/cloneDeep';
Expand All @@ -8,12 +7,7 @@ import { WebGAL } from '@/Core/WebGAL';
import PixiStage, { IAnimationObject } from '@/Core/controller/stage/pixi/PixiController';
import { IUserAnimation } from './animations';
import { pickBy } from 'lodash';
import {
DEFAULT_BG_IN_DURATION,
DEFAULT_BG_OUT_DURATION,
DEFAULT_FIG_IN_DURATION,
DEFAULT_FIG_OUT_DURATION,
} from '../constants';
import { DEFAULT_BG_OUT_DURATION, DEFAULT_FIG_OUT_DURATION } from '../constants';
import { stageStateManager } from '@/Core/Modules/stage/stageStateManager';
import { AnimationFrame } from '@/Core/Modules/animations';

Expand All @@ -24,11 +18,10 @@ export function getAnimationObject(
duration: number,
writeDefault: boolean,
writeFullEffect = true,
syncEndStateToStageState = true,
) {
const mappedEffects = getAnimationTimeline(animationName, target, writeDefault, writeFullEffect);
if (mappedEffects) {
return generateTimelineObj(mappedEffects, target, duration, syncEndStateToStageState);
return generateTimelineObj(mappedEffects, target, duration);
}
return null;
}
Expand Down Expand Up @@ -104,73 +97,43 @@ export function getAnimateDuration(animationName: string) {
return 0;
}

// eslint-disable-next-line max-params
export function getEnterExitAnimation(
/**
* 取退出动画。
*
* 入场动画不在这里产出:它由 changeFigure/changeBg 作为普通演出返回,
* 终态在演算期写入 effects,因此不需要视图层反推该播哪个动画。
*/
export function getExitAnimation(
target: string,
type: 'enter' | 'exit',
isBg = false,
realTarget?: string, // 用于立绘和背景移除时,以当前时间打上特殊标记
): {
duration: number;
animation: IAnimationObject | null;
} {
if (type === 'enter') {
let duration = DEFAULT_FIG_IN_DURATION;
if (isBg) {
duration = DEFAULT_BG_IN_DURATION;
}
const animationSettings = stageStateManager
.getCalculationStageState()
.animationSettings.find((setting) => setting.target === target);
duration = animationSettings?.enterDuration ?? duration;
// 走默认动画
let animation: IAnimationObject | null = generateUniversalSoftInAnimationObj(realTarget ?? target, duration);

const transformState = stageStateManager.getCalculationStageState().effects;
const targetEffect = transformState.find((effect) => effect.target === target);

const animationName = animationSettings?.enterAnimationName;
if (animationName && !targetEffect) {
logger.debug('取代默认进入动画', target);
animation = getAnimationObject(
animationName,
realTarget ?? target,
getAnimateDuration(animationName),
false,
!(animationSettings?.enterAnimationIgnoreDefault ?? false),
);
duration = getAnimateDuration(animationName);
}
return { duration, animation };
} else {
// exit
let duration = DEFAULT_FIG_OUT_DURATION;
if (isBg) {
duration = DEFAULT_BG_OUT_DURATION;
}
const animationSettings = stageStateManager
.getCalculationStageState()
.animationSettings.find((setting) => setting.target === target);
duration = animationSettings?.exitDuration ?? duration;
// 走默认动画
let animation: IAnimationObject | null = generateUniversalSoftOffAnimationObj(realTarget ?? target, duration);
const animationName = animationSettings?.exitAnimationName;
if (animationName) {
logger.debug('取代默认退出动画', target);
animation = getAnimationObject(
animationName,
realTarget ?? target,
getAnimateDuration(animationName),
false,
!(animationSettings?.exitAnimationIgnoreDefault ?? false),
);
duration = getAnimateDuration(animationName);
}
if (animationSettings) {
// 退出动画拿完后,删了这个设定
stageStateManager.removeAnimationSettingsByTargetOff(target);
logger.debug('删除退出动画设定', target);
}
return { duration, animation };
let duration = isBg ? DEFAULT_BG_OUT_DURATION : DEFAULT_FIG_OUT_DURATION;
const animationSettings = stageStateManager
.getCalculationStageState()
.animationSettings.find((setting) => setting.target === target);
duration = animationSettings?.exitDuration ?? duration;
// 走默认动画
let animation: IAnimationObject | null = generateUniversalSoftOffAnimationObj(realTarget ?? target, duration);
const animationName = animationSettings?.exitAnimationName;
if (animationName) {
logger.debug('取代默认退出动画', target);
animation = getAnimationObject(
animationName,
realTarget ?? target,
getAnimateDuration(animationName),
false,
!(animationSettings?.exitAnimationIgnoreDefault ?? false),
);
duration = getAnimateDuration(animationName);
}
if (animationSettings) {
// 退出动画拿完后,删了这个设定
stageStateManager.removeAnimationSettingsByTargetOff(target);
logger.debug('删除退出动画设定', target);
}
return { duration, animation };
}
6 changes: 1 addition & 5 deletions packages/webgal/src/Core/Modules/backlog.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* 当前的backlog
*/
import { IEffect, IStageState } from '@/Core/Modules/stage/stageInterface';
import { IStageState } from '@/Core/Modules/stage/stageInterface';
import { ISaveScene } from '@/store/userDataInterface';
import cloneDeep from 'lodash/cloneDeep';

Expand All @@ -28,10 +28,6 @@ export class BacklogManager {
return this.backlog;
}

public editLastBacklogItemEffect(effects: IEffect[]) {
this.backlog[this.backlog.length - 1].currentStageState.effects = effects;
}

public makeBacklogEmpty() {
this.backlog.splice(0, this.backlog.length); // 清空backlog
}
Expand Down
12 changes: 2 additions & 10 deletions packages/webgal/src/Core/Modules/perform/performController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,8 @@ export class PerformController {
});
}

public discardUncommittedNonHoldPerforms(settleDiscardedState = false) {
this.pendingPerformList = this.pendingPerformList.filter(({ perform }) => {
if (perform.isHoldOn) {
return true;
}
if (settleDiscardedState) {
perform.settleStateOnDiscard?.();
}
return false;
});
public discardUncommittedNonHoldPerforms() {
this.pendingPerformList = this.pendingPerformList.filter(({ perform }) => perform.isHoldOn);
}

public hasPendingBlockingStateCalculationPerform() {
Expand Down
2 changes: 0 additions & 2 deletions packages/webgal/src/Core/Modules/perform/performInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ export interface IPerform {
blockingAuto: () => boolean;
// 是否阻塞同一轮 -next 继续演算;只有需要外部输入才能确定后续状态的演出需要覆盖。
blockingStateCalculation?: () => boolean;
// 未 commit 的演出被丢弃时,将它的终态同步到演算状态
settleStateOnDiscard?: () => void;
// 演出自然结束或被卸载后触发内部继续推进;推进前仍会等待 blockingNext 解除。
goNextWhenOver?: boolean;
// 跳过由 nextSentence/continueSentence 引发的非 hold 演出回收。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const forward = (options: ForwardOptions = {}) => {
return false;
}

WebGAL.gameplay.performController.discardUncommittedNonHoldPerforms(WebGAL.gameplay.isFastPreview);
WebGAL.gameplay.performController.discardUncommittedNonHoldPerforms();
WebGAL.gameplay.performController.clearNonHoldPerformsFromStageState();
WebGAL.gameplay.performController.beginCollectingPerforms();
try {
Expand Down
82 changes: 2 additions & 80 deletions packages/webgal/src/Core/controller/stage/pixi/PixiController.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {
getFigureBaseX,
IEffect,
IFigureAssociatedAnimation,
IFigureMetadata,
IFigurePosition,
ITransform,
} from '@/Core/Modules/stage/stageInterface';
import { Live2D, WebGAL } from '@/Core/WebGAL';
import { Live2D } from '@/Core/WebGAL';
import { baseBlinkParam, baseFocusParam, BlinkParam, FocusParam } from '@/Core/live2DCore';
import { isIOS } from '@/Core/initializeScript';
import { WebGALPixiContainer } from '@/Core/controller/stage/pixi/WebGALPixiContainer';
Expand All @@ -31,12 +30,9 @@ export interface IAnimationObject {
}

interface IStageAnimationObject {
// 唯一标识
uuid: string;
// 一般与作用目标有关
key: string;
targetKey?: string;
type: 'common' | 'preset';
animationObject: IAnimationObject;
}

Expand Down Expand Up @@ -86,7 +82,6 @@ export default class PixiStage {
public readonly mainStageContainer: WebGALPixiContainer;
public readonly foregroundEffectsContainer: PIXI.Container;
public readonly backgroundEffectsContainer: PIXI.Container;
public notUpdateBacklogEffects = false;
public readonly figureContainer: PIXI.Container;
public figureObjects = this.createReactiveList<IStageObject>([]);
public stageWidth = SCREEN_CONSTANTS.width;
Expand Down Expand Up @@ -226,52 +221,13 @@ export default class PixiStage {
*/
public registerAnimation(animationObject: IAnimationObject | null, key: string, target = 'default') {
if (!animationObject) return;
this.stageAnimations.push({ uuid: uuid(), animationObject, key: key, targetKey: target, type: 'common' });
this.stageAnimations.push({ animationObject, key: key, targetKey: target });
// 上锁
this.lockStageObject(target);
animationObject.setStartState();
this.currentApp?.ticker.add(animationObject.tickerFunc);
}

/**
* 注册预设动画
* @param animationObject
* @param key
* @param target
* @param currentEffects
*/
// eslint-disable-next-line max-params
public registerPresetAnimation(
animationObject: IAnimationObject | null,
key: string,
target = 'default',
currentEffects: IEffect[],
) {
if (!animationObject) return;
const effect = currentEffects.find((effect) => effect.target === target);
if (effect) {
const targetPixiContainer = this.getStageObjByKey(target);
if (targetPixiContainer) {
const container = targetPixiContainer.pixiContainer;
if (container) PixiStage.assignTransform(container, effect.transform);
}
this.requestRender();
return;
}
this.stageAnimations.push({ uuid: uuid(), animationObject, key: key, targetKey: target, type: 'preset' });
// 上锁
this.lockStageObject(target);
animationObject.setStartState();
this.currentApp?.ticker.add(animationObject.tickerFunc);
}

public stopPresetAnimationOnTarget(target: string) {
const targetPresetAnimations = this.stageAnimations.find((e) => e.targetKey === target && e.type === 'preset');
if (targetPresetAnimations) {
this.removeAnimation(targetPresetAnimations.key);
}
}

/**
* 移除动画
* @param key
Expand Down Expand Up @@ -318,29 +274,6 @@ export default class PixiStage {
}
}

public removeAnimationWithSetEffects(key: string) {
const index = this.stageAnimations.findIndex((e) => e.key === key);
if (index >= 0) {
const thisTickerFunc = this.stageAnimations[index];
this.currentApp?.ticker.remove(thisTickerFunc.animationObject.tickerFunc);
thisTickerFunc.animationObject.setEndState();
const endStateEffect = thisTickerFunc.animationObject.getEndStateEffect?.() ?? {};
this.unlockStageObject(thisTickerFunc.targetKey ?? 'default');
if (thisTickerFunc.targetKey) {
const target = this.getStageObjByKey(thisTickerFunc.targetKey);
if (target) {
let effect: IEffect = {
target: thisTickerFunc.targetKey,
transform: endStateEffect,
};
stageStateManager.updateEffect(effect);
// if (!this.notUpdateBacklogEffects) updateCurrentBacklogEffects(stageStateManager.getViewStageState().effects);
}
}
this.stageAnimations.splice(index, 1);
}
}

// eslint-disable-next-line max-params
public performMouthSyncAnimation(
key: string,
Expand Down Expand Up @@ -1272,14 +1205,3 @@ export default class PixiStage {
});
}
}

function updateCurrentBacklogEffects(newEffects: IEffect[]) {
/**
* 更新当前 backlog 条目的 effects 记录
*/
setTimeout(() => {
WebGAL.backlogManager.editLastBacklogItemEffect(cloneDeep(newEffects));
}, 50);

stageStateManager.setStageAndCommit('effects', newEffects);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import omitBy from 'lodash/omitBy';
import isUndefined from 'lodash/isUndefined';
import PixiStage, { IAnimationObject } from '@/Core/controller/stage/pixi/PixiController';
import { AnimationFrame } from '@/Core/Modules/animations';
import { stageStateManager } from '@/Core/Modules/stage/stageStateManager';

/**
* 动画创建模板
Expand All @@ -17,7 +16,6 @@ export function generateTimelineObj(
timeline: Array<AnimationFrame>,
targetKey: string,
duration: number,
syncEndStateToStageState = true,
): IAnimationObject {
const target = WebGAL.gameplay.pixiStage!.getStageObjByKey(targetKey);
let currentDelay = 0;
Expand Down Expand Up @@ -63,11 +61,6 @@ export function generateTimelineObj(
});
}

if (syncEndStateToStageState) {
const { duration: sliceDuration, ease, ...endState } = getEndStateEffect();
stageStateManager.updateEffect({ target: targetKey, transform: endState });
}

/**
* 在此书写为动画设置初态的操作
*/
Expand Down
Loading
Loading