Skip to content
Draft
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
32 changes: 22 additions & 10 deletions packages/webgal/src/Core/controller/stage/pixi/PixiController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export interface IStageObject {
uuid: string;
// 一般与作用目标有关
key: string;
pixiContainer: WebGALPixiContainer;
pixiContainer: WebGALPixiContainer | null;
// 相关的源 url
sourceUrl: string;
sourceExt: string;
Expand Down Expand Up @@ -235,7 +235,7 @@ export default class PixiStage {
const targetPixiContainer = this.getStageObjByKey(target);
if (targetPixiContainer) {
const container = targetPixiContainer.pixiContainer;
PixiStage.assignTransform(container, effect.transform);
if (container) PixiStage.assignTransform(container, effect.transform);
}
return;
}
Expand Down Expand Up @@ -776,6 +776,7 @@ export default class PixiStage {
const figureRecordTarget = this.live2dFigureRecorder.find((e) => e.target === key);
if (target && figureRecordTarget?.motion !== motion) {
const container = target.pixiContainer;
if (!container) return;
const children = container.children;
for (const model of children) {
let category_name = motion;
Expand All @@ -799,6 +800,7 @@ export default class PixiStage {
if (target?.sourceType !== 'spine') return;

const container = target.pixiContainer;
if (!container) return;
// Spine figure 结构: Container -> Sprite -> Spine
const sprite = container.children[0] as PIXI.Container;
if (sprite?.children?.[0]) {
Expand All @@ -825,6 +827,7 @@ export default class PixiStage {
const figureRecordTarget = this.live2dFigureRecorder.find((e) => e.target === key);
if (target && figureRecordTarget?.expression !== expression) {
const container = target.pixiContainer;
if (!container) return;
const children = container.children;
for (const model of children) {
// @ts-ignore
Expand All @@ -840,6 +843,7 @@ export default class PixiStage {
const figureRecordTarget = this.live2dFigureRecorder.find((e) => e.target === key);
if (target && !isEqual(figureRecordTarget?.blink, blinkParam)) {
const container = target.pixiContainer;
if (!container) return;
const children = container.children;
let newBlinkParam: BlinkParam = { ...baseBlinkParam, ...blinkParam };
// 继承现有 BlinkParam
Expand All @@ -860,6 +864,7 @@ export default class PixiStage {
const figureRecordTarget = this.live2dFigureRecorder.find((e) => e.target === key);
if (target && !isEqual(figureRecordTarget?.focus, focusParam)) {
const container = target.pixiContainer;
if (!container) return;
const children = container.children;
let newFocusParam: FocusParam = { ...baseFocusParam, ...focusParam };
// 继承现有 FocusParam
Expand All @@ -883,6 +888,7 @@ export default class PixiStage {
const target = this.figureObjects.find((e) => e.key === key);
if (target && target.sourceType === 'live2d') {
const container = target.pixiContainer;
if (!container) return;
const children = container.children;
for (const model of children) {
// @ts-ignore
Expand Down Expand Up @@ -925,20 +931,26 @@ export default class PixiStage {
const indexBg = this.backgroundObjects.findIndex((e) => e.key === key);
if (indexFig >= 0) {
const bgSprite = this.figureObjects[indexFig];
for (const element of bgSprite.pixiContainer.children) {
element.destroy();
if (bgSprite.pixiContainer) {
for (const element of bgSprite.pixiContainer.children) {
element.destroy();
}
bgSprite.pixiContainer.destroy();
this.figureContainer.removeChild(bgSprite.pixiContainer);
}
bgSprite.pixiContainer.destroy();
this.figureContainer.removeChild(bgSprite.pixiContainer);
bgSprite.pixiContainer = null;
this.figureObjects.splice(indexFig, 1);
}
if (indexBg >= 0) {
const bgSprite = this.backgroundObjects[indexBg];
for (const element of bgSprite.pixiContainer.children) {
element.destroy();
if (bgSprite.pixiContainer) {
for (const element of bgSprite.pixiContainer.children) {
element.destroy();
}
bgSprite.pixiContainer.destroy();
this.backgroundContainer.removeChild(bgSprite.pixiContainer);
}
bgSprite.pixiContainer.destroy();
this.backgroundContainer.removeChild(bgSprite.pixiContainer);
bgSprite.pixiContainer = null;
this.backgroundObjects.splice(indexBg, 1);
}
// /**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function generateTestblurAnimationObj(targetKey: string, duration: number
* 在此书写为动画设置初态的操作
*/
function setStartState() {
if (target) {
if (target?.pixiContainer) {
target.pixiContainer.alpha = 0;
// @ts-ignore
target.pixiContainer.blur = 0;
Expand All @@ -22,7 +22,7 @@ export function generateTestblurAnimationObj(targetKey: string, duration: number
* 在此书写为动画设置终态的操作
*/
function setEndState() {
if (target) {
if (target?.pixiContainer) {
target.pixiContainer.alpha = 1;
// @ts-ignore
target.pixiContainer.blur = 5;
Expand All @@ -40,9 +40,10 @@ export function generateTestblurAnimationObj(targetKey: string, duration: number
const currentAddOplityDelta = (duration / baseDuration) * delta;
const increasement = 1 / currentAddOplityDelta;
const decreasement = 5 / currentAddOplityDelta;
if (container.alpha < 1) {
container.alpha += increasement;
}
if (container)
if (container.alpha < 1) {
container.alpha += increasement;
}
// @ts-ignore
if (container.blur < 5) {
// @ts-ignore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export function generateTimelineObj(
times.push(currentDelay / duration);
} else times.push(0);
}
const container = target?.pixiContainer;
let animateInstance: ReturnType<typeof popmotion.animate> | null = null;
// 只有有 duration 的时候才有动画
if (duration > 0) {
Expand All @@ -52,13 +51,13 @@ export function generateTimelineObj(
duration,
ease: easeArray,
onUpdate: (updateValue) => {
if (container) {
if (target?.pixiContainer) {
const { scaleX, scaleY, ...val } = updateValue;
// @ts-ignore
PixiStage.assignTransform(container, omitBy(val, isUndefined));
PixiStage.assignTransform(target.pixiContainer, omitBy(val, isUndefined));
// 因为 popmotion 不能用嵌套,scale 要手动设置
if (!isUndefined(scaleX)) container.scale.x = scaleX;
if (!isUndefined(scaleY)) container.scale.y = scaleY;
if (!isUndefined(scaleX)) target.pixiContainer.scale.x = scaleX;
if (!isUndefined(scaleY)) target.pixiContainer.scale.y = scaleY;
}
},
});
Expand All @@ -77,13 +76,11 @@ export function generateTimelineObj(
const assignValue = omitBy({ x: position.x, y: position.y, ...state }, isUndefined);
// @ts-ignore
PixiStage.assignTransform(target?.pixiContainer, assignValue);
if (target?.pixiContainer) {
if (!isUndefined(scale.x)) {
target.pixiContainer.scale.x = scale.x;
}
if (!isUndefined(scale?.y)) {
target.pixiContainer.scale.y = scale.y;
}
if (!isUndefined(scale.x)) {
target.pixiContainer.scale.x = scale.x;
}
if (!isUndefined(scale?.y)) {
target.pixiContainer.scale.y = scale.y;
}
}
}
Expand All @@ -101,13 +98,11 @@ export function generateTimelineObj(
const assignValue = omitBy({ x: position.x, y: position.y, ...state }, isUndefined);
// @ts-ignore
PixiStage.assignTransform(target?.pixiContainer, assignValue);
if (target?.pixiContainer) {
if (!isUndefined(scale.x)) {
target.pixiContainer.scale.x = scale.x;
}
if (!isUndefined(scale?.y)) {
target.pixiContainer.scale.y = scale.y;
}
if (!isUndefined(scale.x)) {
target.pixiContainer.scale.x = scale.x;
}
if (!isUndefined(scale?.y)) {
target.pixiContainer.scale.y = scale.y;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function generateUniversalSoftInAnimationObj(targetKey: string, duration:
*/
function setStartState() {
elapsedTime = 0; // Reset timer when animation starts
if (target) {
if (target?.pixiContainer) {
// 修正:不再强制设为 0,而是记录当前的透明度
startAlpha = target.pixiContainer.alpha;
}
Expand All @@ -22,7 +22,7 @@ export function generateUniversalSoftInAnimationObj(targetKey: string, duration:
* 在此书写为动画设置终态的操作
*/
function setEndState() {
if (target) {
if (target?.pixiContainer) {
// 终态是完全不透明,这保持不变
target.pixiContainer.alpha = 1;
}
Expand All @@ -49,7 +49,7 @@ export function generateUniversalSoftInAnimationObj(targetKey: string, duration:
// 公式:最终值 = 初始值 + (目标值 - 初始值) * 进度
// 在这里,目标值是 1,所以公式为:
// alpha = startAlpha + (1 - startAlpha) * easedProgress
sprite.alpha = startAlpha + (1 - startAlpha) * easedProgress;
if (sprite) sprite.alpha = startAlpha + (1 - startAlpha) * easedProgress;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function generateUniversalSoftOffAnimationObj(targetKey: string, duration
*/
function setStartState() {
elapsedTime = 0; // 重置计时器
if (target) {
if (target?.pixiContainer) {
// 修正:不再强制设为1,而是记录当前的透明度
startAlpha = target.pixiContainer.alpha;
}
Expand All @@ -22,7 +22,7 @@ export function generateUniversalSoftOffAnimationObj(targetKey: string, duration
* 在此书写为动画设置终态的操作
*/
function setEndState() {
if (target) {
if (target?.pixiContainer) {
// 终态是完全透明,这保持不变
target.pixiContainer.alpha = 0;
}
Expand Down Expand Up @@ -50,7 +50,7 @@ export function generateUniversalSoftOffAnimationObj(targetKey: string, duration
// 在这里,目标值是 0,所以公式简化为:
// alpha = startAlpha + (0 - startAlpha) * easedProgress
// alpha = startAlpha * (1 - easedProgress)
targetContainer.alpha = startAlpha * (1 - easedProgress);
if (targetContainer) targetContainer.alpha = startAlpha * (1 - easedProgress);
}
}

Expand Down
15 changes: 11 additions & 4 deletions packages/webgal/src/Core/gameScripts/changeBg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,18 @@ export const changeBg = (sentence: ISentence): IPerform => {
dispatch(unlockCgInUserData({ name: unlockName, url, series }));
}

/**
* 删掉相关 Effects,因为已经移除了
*/
if (webgalStore.getState().stage.bgName !== sentence.content) {
// 检测 url 是否变化
let isUrlChanged = webgalStore.getState().stage.bgName !== sentence.content;
if (isUrlChanged) {
// 清除动画
WebGAL.gameplay.pixiStage?.removeAnimation('bg-main');
// 移除旧的 effect
dispatch(stageActions.removeEffectByTargetId(`bg-main`));
// 标记旧的背景为退出中,防止旧背景继承新参数
const oldStageObject = WebGAL.gameplay.pixiStage?.getStageObjByKey('bg-main');
if (oldStageObject) {
oldStageObject.isExiting = true;
}
}

// 处理 transform 和 默认 transform
Expand Down
55 changes: 32 additions & 23 deletions packages/webgal/src/Core/gameScripts/changeFigure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { logger } from '@/Core/util/logger';
import { getAnimateDuration } from '@/Core/Modules/animationFunctions';
import { WebGAL } from '@/Core/WebGAL';
import { baseBlinkParam, baseFocusParam, BlinkParam, FocusParam } from '@/Core/live2DCore';
import { WEBGAL_NONE } from '../constants';
import { STAGE_KEYS, WEBGAL_NONE } from '../constants';
/**
* 更改立绘
* @param sentence 语句
Expand Down Expand Up @@ -46,9 +46,24 @@ export function changeFigure(sentence: ISentence): IPerform {
}

// id 与 自由立绘
let key = getStringArgByKey(sentence, 'id') ?? '';
const isFreeFigure = key ? true : false;
const id = key ? key : `fig-${pos}`;
let idFromArgs = getStringArgByKey(sentence, 'id') ?? '';
const isFreeFigure = idFromArgs ? true : false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这个布尔值的赋值可以写得更简洁一些。

Suggested change
const isFreeFigure = idFromArgs ? true : false;
const isFreeFigure = !!idFromArgs;

let key = '';
if (isFreeFigure) {
key = idFromArgs;
} else {
switch (pos) {
case 'center':
key = STAGE_KEYS.FIG_C;
break;
case 'left':
key = STAGE_KEYS.FIG_L;
break;
case 'right':
key = STAGE_KEYS.FIG_R;
break;
}
}

// live2d 或 spine 相关
let motion = getStringArgByKey(sentence, 'motion') ?? '';
Expand Down Expand Up @@ -95,9 +110,9 @@ export function changeFigure(sentence: ISentence): IPerform {
const dispatch = webgalStore.dispatch;

const currentFigureAssociatedAnimation = webgalStore.getState().stage.figureAssociatedAnimation;
const filteredFigureAssociatedAnimation = currentFigureAssociatedAnimation.filter((item) => item.targetId !== id);
const filteredFigureAssociatedAnimation = currentFigureAssociatedAnimation.filter((item) => item.targetId !== key);
const newFigureAssociatedAnimationItem = {
targetId: id,
targetId: key,
animationFlag: animationFlag,
mouthAnimation: {
open: mouthOpen,
Expand All @@ -112,9 +127,7 @@ export function changeFigure(sentence: ISentence): IPerform {
filteredFigureAssociatedAnimation.push(newFigureAssociatedAnimationItem);
dispatch(setStage({ key: 'figureAssociatedAnimation', value: filteredFigureAssociatedAnimation }));

/**
* 如果 url 没变,不移除
*/
// 检测 url 是否变化
let isUrlChanged = true;
if (key !== '') {
const figWithKey = webgalStore.getState().stage.freeFigure.find((e) => e.key === key);
Expand All @@ -140,12 +153,14 @@ export function changeFigure(sentence: ISentence): IPerform {
}
}
}
/**
* 处理 Effects
*/

if (isUrlChanged) {
webgalStore.dispatch(stageActions.removeEffectByTargetId(id));
const oldStageObject = WebGAL.gameplay.pixiStage?.getStageObjByKey(id);
// 清除动画
WebGAL.gameplay.pixiStage?.removeAnimation(key);
// 移除旧的 effect
webgalStore.dispatch(stageActions.removeEffectByTargetId(key));
// 标记旧的立绘为退出中,防止旧立绘继承新参数
const oldStageObject = WebGAL.gameplay.pixiStage?.getStageObjByKey(key);
if (oldStageObject) {
oldStageObject.isExiting = true;
}
Expand Down Expand Up @@ -196,7 +211,7 @@ export function changeFigure(sentence: ISentence): IPerform {
}
};

function setFigureData() {
function postFigureStateSet() {
if (isUrlChanged) {
// 当 url 发生变化时,即发生新立绘替换
// 应当赋予一些参数以默认值,防止从旧立绘的状态获取数据
Expand Down Expand Up @@ -236,26 +251,20 @@ export function changeFigure(sentence: ISentence): IPerform {
*/
const freeFigureItem: IFreeFigure = { key, name: content, basePosition: pos };
setAnimationNames(key, sentence);
setFigureData();
postFigureStateSet();
dispatch(stageActions.setFreeFigureByKey(freeFigureItem));
} else {
/**
* 下面的代码是设置与位置关联的立绘的
*/
const positionMap = {
center: 'fig-center',
left: 'fig-left',
right: 'fig-right',
};
const dispatchMap: Record<string, keyof IStageState> = {
center: 'figName',
left: 'figNameLeft',
right: 'figNameRight',
};

key = positionMap[pos];
setAnimationNames(key, sentence);
setFigureData();
postFigureStateSet();
dispatch(setStage({ key: dispatchMap[pos], value: content }));
}

Expand Down
Loading