From de21fd0c1c35deb2e133ffa4e1ec3ccc78394a32 Mon Sep 17 00:00:00 2001 From: Akirami <66513481+A-kirami@users.noreply.github.com> Date: Thu, 25 Jun 2026 09:33:08 +0800 Subject: [PATCH 1/2] fix: normalize transform frame parsing Treat empty setTransform content as an empty transform frame so -writeDefault follows the same base default path as setTransform:{}. Accept only object-shaped transform JSON for setTransform, changeFigure, and changeBg. Non-object values from malformed or empty transform input fall back to the default transform path instead of entering animation frames. --- .../src/Core/gameScripts/changeBg/index.ts | 31 +++++++----------- .../src/Core/gameScripts/changeFigure.ts | 32 +++++++------------ .../src/Core/gameScripts/setTransform.ts | 9 +++--- 3 files changed, 28 insertions(+), 44 deletions(-) diff --git a/packages/webgal/src/Core/gameScripts/changeBg/index.ts b/packages/webgal/src/Core/gameScripts/changeBg/index.ts index f65d6d350..ded9f103c 100644 --- a/packages/webgal/src/Core/gameScripts/changeBg/index.ts +++ b/packages/webgal/src/Core/gameScripts/changeBg/index.ts @@ -15,6 +15,7 @@ import { WebGAL } from '@/Core/WebGAL'; import { DEFAULT_BG_OUT_DURATION } from '@/Core/constants'; import localforage from 'localforage'; import { stageStateManager } from '@/Core/Modules/stage/stageStateManager'; +import { parseTransformFrame } from '../parseTransformFrame'; /** * 进行背景图片的切换 @@ -56,29 +57,15 @@ export const changeBg = (sentence: ISentence): IPerform => { // 处理 transform 和 默认 transform let animationObj: AnimationFrame[]; - if (transformString) { - try { - const frame = JSON.parse(transformString.toString()) as AnimationFrame; - animationObj = generateTransformAnimationObj('bg-main', frame, enterDuration, ease, !ignoreDefault); - // 因为是切换,必须把一开始的 alpha 改为 0 - animationObj[0].alpha = 0; - const animationName = (Math.random() * 10).toString(16); - const newAnimation: IUserAnimation = { name: animationName, effects: animationObj }; - WebGAL.animationManager.addAnimation(newAnimation); - duration = getAnimateDuration(animationName); - stageStateManager.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationName', value: animationName }); - } catch (e) { - // 解析都错误了,歇逼吧 - applyDefaultTransform(); - } + const frame = transformString ? parseTransformFrame(transformString) : null; + if (frame) { + applyTransform(frame); } else { applyDefaultTransform(); } - function applyDefaultTransform() { - // 应用默认的 - const frame = {}; - animationObj = generateTransformAnimationObj('bg-main', frame as AnimationFrame, duration, ease, !ignoreDefault); + function applyTransform(frame: AnimationFrame) { + animationObj = generateTransformAnimationObj('bg-main', frame, enterDuration, ease, !ignoreDefault); // 因为是切换,必须把一开始的 alpha 改为 0 animationObj[0].alpha = 0; const animationName = (Math.random() * 10).toString(16); @@ -87,6 +74,12 @@ export const changeBg = (sentence: ISentence): IPerform => { duration = getAnimateDuration(animationName); stageStateManager.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationName', value: animationName }); } + + function applyDefaultTransform() { + // 应用默认的 + const frame = {}; + applyTransform(frame as AnimationFrame); + } stageStateManager.updateAnimationSettings({ target: 'bg-main', key: 'enterAnimationIgnoreDefault', diff --git a/packages/webgal/src/Core/gameScripts/changeFigure.ts b/packages/webgal/src/Core/gameScripts/changeFigure.ts index b6b64e6e4..54c07859d 100644 --- a/packages/webgal/src/Core/gameScripts/changeFigure.ts +++ b/packages/webgal/src/Core/gameScripts/changeFigure.ts @@ -12,6 +12,7 @@ import { WebGAL } from '@/Core/WebGAL'; import { baseBlinkParam, baseFocusParam, BlinkParam, FocusParam } from '@/Core/live2DCore'; import { DEFAULT_FIG_IN_DURATION, DEFAULT_FIG_OUT_DURATION, WEBGAL_NONE } from '../constants'; import { stageStateManager } from '@/Core/Modules/stage/stageStateManager'; +import { parseTransformFrame } from './parseTransformFrame'; /** * 更改立绘 * @param sentence 语句 @@ -161,30 +162,15 @@ export function changeFigure(sentence: ISentence): IPerform { } // 处理 transform 和 默认 transform let animationObj: AnimationFrame[]; - if (transformString) { - console.log(transformString); - try { - const frame = JSON.parse(transformString) as AnimationFrame; - animationObj = generateTransformAnimationObj(key, frame, duration, ease, !ignoreDefault); - // 因为是切换,必须把一开始的 alpha 改为 0 - animationObj[0].alpha = 0; - const animationName = (Math.random() * 10).toString(16); - const newAnimation: IUserAnimation = { name: animationName, effects: animationObj }; - WebGAL.animationManager.addAnimation(newAnimation); - duration = getAnimateDuration(animationName); - stageStateManager.updateAnimationSettings({ target: key, key: 'enterAnimationName', value: animationName }); - } catch (e) { - // 解析都错误了,歇逼吧 - applyDefaultTransform(); - } + const frame = transformString ? parseTransformFrame(transformString) : null; + if (frame) { + applyTransform(frame); } else { applyDefaultTransform(); } - function applyDefaultTransform() { - // 应用默认的 - const frame = {}; - animationObj = generateTransformAnimationObj(key, frame as AnimationFrame, duration, ease, !ignoreDefault); + function applyTransform(frame: AnimationFrame) { + animationObj = generateTransformAnimationObj(key, frame, duration, ease, !ignoreDefault); // 因为是切换,必须把一开始的 alpha 改为 0 animationObj[0].alpha = 0; const animationName = (Math.random() * 10).toString(16); @@ -193,6 +179,12 @@ export function changeFigure(sentence: ISentence): IPerform { duration = getAnimateDuration(animationName); stageStateManager.updateAnimationSettings({ target: key, key: 'enterAnimationName', value: animationName }); } + + function applyDefaultTransform() { + // 应用默认的 + const frame = {}; + applyTransform(frame as AnimationFrame); + } stageStateManager.updateAnimationSettings({ target: key, key: 'enterAnimationIgnoreDefault', diff --git a/packages/webgal/src/Core/gameScripts/setTransform.ts b/packages/webgal/src/Core/gameScripts/setTransform.ts index f306c34ea..ff72934fd 100644 --- a/packages/webgal/src/Core/gameScripts/setTransform.ts +++ b/packages/webgal/src/Core/gameScripts/setTransform.ts @@ -9,6 +9,7 @@ import { WebGAL } from '@/Core/WebGAL'; import { applyAnimationEndState, getAnimateDuration } from '../Modules/animationFunctions'; import { v4 as uuid } from 'uuid'; import { generateTimelineObj } from '@/Core/controller/stage/pixi/animations/timeline'; +import { parseSetTransformFrame } from './parseTransformFrame'; /** * 设置变换 * @param sentence @@ -31,12 +32,10 @@ export const setTransform = (sentence: ISentence): IPerform => { if (!parallel) WebGAL.gameplay.performController.unmountPerform(performInitName, true); - try { - const frame = JSON.parse(animationString) as AnimationFrame; + const frame = parseSetTransformFrame(animationString); + if (frame) { animationObj = generateTransformAnimationObj(target, frame, duration, ease, writeFullEffect); - console.log('animationObj:', animationObj); - } catch (e) { - // 解析都错误了,歇逼吧 + } else { animationObj = []; } From a28217e0745f8c6ae235b1bac4603e78764b4594 Mon Sep 17 00:00:00 2001 From: Akirami <66513481+A-kirami@users.noreply.github.com> Date: Thu, 25 Jun 2026 09:38:12 +0800 Subject: [PATCH 2/2] fix: add missing files --- .../Core/gameScripts/parseTransformFrame.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 packages/webgal/src/Core/gameScripts/parseTransformFrame.ts diff --git a/packages/webgal/src/Core/gameScripts/parseTransformFrame.ts b/packages/webgal/src/Core/gameScripts/parseTransformFrame.ts new file mode 100644 index 000000000..0dbcdda52 --- /dev/null +++ b/packages/webgal/src/Core/gameScripts/parseTransformFrame.ts @@ -0,0 +1,21 @@ +import { AnimationFrame } from '@/Core/Modules/animations'; + +export function parseTransformFrame(raw: string): AnimationFrame | null { + const source = raw.trim(); + if (source === '') return null; + + try { + const parsed: unknown = JSON.parse(source); + return isTransformFrame(parsed) ? parsed : null; + } catch { + return null; + } +} + +export function parseSetTransformFrame(raw: string): AnimationFrame | null { + return parseTransformFrame(raw.trim() === '' ? '{}' : raw); +} + +function isTransformFrame(value: unknown): value is AnimationFrame { + return typeof value === 'object' && value !== null && !Array.isArray(value); +}