diff --git a/packages/parser/package.json b/packages/parser/package.json index 59e0beb3e..eec9748a5 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "webgal-parser", - "version": "4.4.15", + "version": "4.5.2", "description": "WebGAL script parser", "scripts": { "test": "vitest", diff --git a/packages/parser/src/scriptParser/scriptParser.ts b/packages/parser/src/scriptParser/scriptParser.ts index aa33c6d15..10bbfe197 100644 --- a/packages/parser/src/scriptParser/scriptParser.ts +++ b/packages/parser/src/scriptParser/scriptParser.ts @@ -35,8 +35,9 @@ export const scriptParser = ( // 正式开始解析 - // 去分号,前面已做,这里不再需要 - let newSentenceRaw = sentenceRaw.split(';')[0]; + // 去分号 + let newSentenceRaw = sentenceRaw.split(/(? { } // 不处于 allSettled 状态,清除所有普通演出,强制进入settled。 - logger.warn('提前结束被触发,现在清除普通演出'); + logger.debug('提前结束被触发,现在清除普通演出'); let isGoNext = false; for (let i = 0; i < WebGAL.gameplay.performController.performList.length; i++) { const e = WebGAL.gameplay.performController.performList[i]; diff --git a/packages/webgal/src/Core/controller/gamePlay/strIf.ts b/packages/webgal/src/Core/controller/gamePlay/strIf.ts index 26cb5e622..82f7d87f1 100644 --- a/packages/webgal/src/Core/controller/gamePlay/strIf.ts +++ b/packages/webgal/src/Core/controller/gamePlay/strIf.ts @@ -1,6 +1,10 @@ import { compile } from 'angular-expressions'; export function strIf(s: string) { - const res = compile(s); - return res(); + try { + const res = compile(s); + return res(); + } catch { + return false; + } } diff --git a/packages/webgal/src/Core/controller/stage/pixi/PixiController.ts b/packages/webgal/src/Core/controller/stage/pixi/PixiController.ts index 0aa7168f5..33b310834 100644 --- a/packages/webgal/src/Core/controller/stage/pixi/PixiController.ts +++ b/packages/webgal/src/Core/controller/stage/pixi/PixiController.ts @@ -284,36 +284,11 @@ export default class PixiStage { // Load mouth texture (reuse if already loaded) this.loadAsset(mouthTextureUrls[mouthState], () => { const texture = this.assetLoader.resources[mouthTextureUrls[mouthState]].texture; - if (!texture) { + const sprite = currentFigure?.children?.[0] as PIXI.Sprite; + if (!texture || !sprite) { return; } - const originalWidth = texture.width; - const originalHeight = texture.height; - const scaleX = this.stageWidth / originalWidth; - const scaleY = this.stageHeight / originalHeight; - const targetScale = Math.min(scaleX, scaleY); - const figureSprite = new PIXI.Sprite(texture); - figureSprite.scale.x = targetScale; - figureSprite.scale.y = targetScale; - figureSprite.anchor.set(0.5); - figureSprite.position.y = this.stageHeight / 2; - const targetWidth = originalWidth * targetScale; - const targetHeight = originalHeight * targetScale; - currentFigure.setBaseY(this.stageHeight / 2); - if (targetHeight < this.stageHeight) { - currentFigure.setBaseY(this.stageHeight / 2 + this.stageHeight - targetHeight / 2); - } - if (presetPosition === 'center') { - currentFigure.setBaseX(this.stageWidth / 2); - } - if (presetPosition === 'left') { - currentFigure.setBaseX(targetWidth / 2); - } - if (presetPosition === 'right') { - currentFigure.setBaseX(this.stageWidth - targetWidth / 2); - } - currentFigure.pivot.set(0, this.stageHeight / 2); - currentFigure.addChild(figureSprite); + sprite.texture = texture; }); } @@ -337,38 +312,11 @@ export default class PixiStage { // Load eye texture (reuse if already loaded) this.loadAsset(blinkTextureUrls[blinkState], () => { const texture = this.assetLoader.resources[blinkTextureUrls[blinkState]].texture; - - if (!texture) { + const sprite = currentFigure?.children?.[0] as PIXI.Sprite; + if (!texture || !sprite) { return; } - - const originalWidth = texture.width; - const originalHeight = texture.height; - const scaleX = this.stageWidth / originalWidth; - const scaleY = this.stageHeight / originalHeight; - const targetScale = Math.min(scaleX, scaleY); - const figureSprite = new PIXI.Sprite(texture); - figureSprite.scale.x = targetScale; - figureSprite.scale.y = targetScale; - figureSprite.anchor.set(0.5); - figureSprite.position.y = this.stageHeight / 2; - const targetWidth = originalWidth * targetScale; - const targetHeight = originalHeight * targetScale; - currentFigure.setBaseY(this.stageHeight / 2); - if (targetHeight < this.stageHeight) { - currentFigure.setBaseY(this.stageHeight / 2 + this.stageHeight - targetHeight / 2); - } - if (presetPosition === 'center') { - currentFigure.setBaseX(this.stageWidth / 2); - } - if (presetPosition === 'left') { - currentFigure.setBaseX(targetWidth / 2); - } - if (presetPosition === 'right') { - currentFigure.setBaseX(this.stageWidth - targetWidth / 2); - } - currentFigure.pivot.set(0, this.stageHeight / 2); - currentFigure.addChild(figureSprite); + sprite.texture = texture; }); } @@ -447,6 +395,84 @@ export default class PixiStage { } } + public addSpineBg(key: string, url: string) { + const spineId = `spine-${url}`; + const loader = this.assetLoader; + // 准备用于存放这个背景的 Container + const thisBgContainer = new WebGALPixiContainer(); + + // 是否有相同 key 的背景 + const setBgIndex = this.backgroundObjects.findIndex((e) => e.key === key); + const isBgSet = setBgIndex >= 0; + + // 已经有一个这个 key 的背景存在了 + if (isBgSet) { + // 挤占 + this.removeStageObjectByKey(key); + } + + // 挂载 + this.backgroundContainer.addChild(thisBgContainer); + const bgUuid = uuid(); + this.backgroundObjects.push({ + uuid: bgUuid, + key: key, + pixiContainer: thisBgContainer, + sourceUrl: url, + sourceType: 'live2d', + sourceExt: this.getExtName(url), + }); + + // 完成图片加载后执行的函数 + const setup = () => { + const spineResource: any = this.assetLoader.resources?.[spineId]; + // TODO:找一个更好的解法,现在的解法是无论是否复用原来的资源,都设置一个延时以让动画工作正常! + setTimeout(() => { + if (spineResource && this.getStageObjByUuid(bgUuid)) { + const bgSpine = new Spine(spineResource.spineData); + const transY = spineResource?.spineData?.y ?? 0; + /** + * 重设大小 + */ + const originalWidth = bgSpine.width; // TODO: 视图大小可能小于画布大小,应提供参数指定视图大小 + const originalHeight = bgSpine.height; // TODO: 视图大小可能小于画布大小,应提供参数指定视图大小 + const scaleX = this.stageWidth / originalWidth; + const scaleY = this.stageHeight / originalHeight; + logger.debug('bgSpine state', bgSpine.state); + // TODO: 也许应该使用 setAnimation 播放初始动画 + if (bgSpine.spineData.animations.length > 0) { + // 播放首个动画 + bgSpine.state.setAnimation(0, bgSpine.spineData.animations[0].name, true); + } + const targetScale = Math.max(scaleX, scaleY); + const bgSprite = new PIXI.Sprite(); + bgSprite.addChild(bgSpine); + bgSprite.scale.x = targetScale; + bgSprite.scale.y = targetScale; + bgSprite.anchor.set(0.5); + bgSprite.position.y = this.stageHeight / 2; + thisBgContainer.setBaseX(this.stageWidth / 2); + thisBgContainer.setBaseY(this.stageHeight / 2); + thisBgContainer.pivot.set(0, this.stageHeight / 2); + + // 挂载 + thisBgContainer.addChild(bgSprite); + } + }, 0); + }; + + /** + * 加载器部分 + */ + this.cacheGC(); + if (!loader.resources?.[url]) { + this.loadAsset(url, setup, spineId); + } else { + // 复用 + setup(); + } + } + /** * 添加立绘 * @param key 立绘的标识,一般和立绘位置有关 @@ -566,7 +592,6 @@ export default class PixiStage { // 完成图片加载后执行的函数 const setup = () => { - console.log(this.assetLoader.resources); const spineResource: any = this.assetLoader.resources?.[spineId]; // TODO:找一个更好的解法,现在的解法是无论是否复用原来的资源,都设置一个延时以让动画工作正常! setTimeout(() => { @@ -576,14 +601,12 @@ export default class PixiStage { /** * 重设大小 */ - console.log(figureSpine); const originalWidth = figureSpine.width; const originalHeight = figureSpine.height; const scaleX = this.stageWidth / originalWidth; const scaleY = this.stageHeight / originalHeight; // 我也不知道为什么啊啊啊啊 figureSpine.y = -(scaleY * transY) / 2; - console.log(figureSpine.state); figureSpine.state.setAnimation(0, '07', true); const targetScale = Math.min(scaleX, scaleY); const figureSprite = new PIXI.Sprite(); diff --git a/packages/webgal/src/Core/controller/stage/playBgm.ts b/packages/webgal/src/Core/controller/stage/playBgm.ts index 03f8d34ac..07d72a7d2 100644 --- a/packages/webgal/src/Core/controller/stage/playBgm.ts +++ b/packages/webgal/src/Core/controller/stage/playBgm.ts @@ -26,7 +26,7 @@ let emptyBgmTimeout: ReturnType; * @param volume 背景音乐 音量调整(0 - 100) */ export function playBgm(url: string, enter = 0, volume = 100): void { - logger.info('playing bgm' + url); + logger.debug('playing bgm' + url); if (url === '') { emptyBgmTimeout = setTimeout(() => { // 淡入淡出效果结束后,将 bgm 置空 diff --git a/packages/webgal/src/Core/controller/storage/jumpFromBacklog.ts b/packages/webgal/src/Core/controller/storage/jumpFromBacklog.ts index 5b5f0cc21..e0b9a1a8e 100644 --- a/packages/webgal/src/Core/controller/storage/jumpFromBacklog.ts +++ b/packages/webgal/src/Core/controller/storage/jumpFromBacklog.ts @@ -26,25 +26,27 @@ export const restorePerform = () => { /** * 从 backlog 跳转至一个先前的状态 * @param index + * @param refetchScene */ -export const jumpFromBacklog = (index: number) => { +export const jumpFromBacklog = (index: number, refetchScene = true) => { const dispatch = webgalStore.dispatch; // 获得存档文件 const backlogFile = WebGAL.backlogManager.getBacklog()[index]; logger.debug('读取的backlog数据', backlogFile); // 重新获取并同步场景状态 - sceneFetcher(backlogFile.saveScene.sceneUrl).then((rawScene) => { - WebGAL.sceneManager.sceneData.currentScene = sceneParser( - rawScene, - backlogFile.saveScene.sceneName, - backlogFile.saveScene.sceneUrl, - ); - // 开始场景的预加载 - const subSceneList = WebGAL.sceneManager.sceneData.currentScene.subSceneList; - WebGAL.sceneManager.settledScenes.push(WebGAL.sceneManager.sceneData.currentScene.sceneUrl); // 放入已加载场景列表,避免递归加载相同场景 - const subSceneListUniq = uniqWith(subSceneList); // 去重 - scenePrefetcher(subSceneListUniq); - }); + if (refetchScene) + sceneFetcher(backlogFile.saveScene.sceneUrl).then((rawScene) => { + WebGAL.sceneManager.sceneData.currentScene = sceneParser( + rawScene, + backlogFile.saveScene.sceneName, + backlogFile.saveScene.sceneUrl, + ); + // 开始场景的预加载 + const subSceneList = WebGAL.sceneManager.sceneData.currentScene.subSceneList; + WebGAL.sceneManager.settledScenes.push(WebGAL.sceneManager.sceneData.currentScene.sceneUrl); // 放入已加载场景列表,避免递归加载相同场景 + const subSceneListUniq = uniqWith(subSceneList); // 去重 + scenePrefetcher(subSceneListUniq); + }); WebGAL.sceneManager.sceneData.currentSentenceId = backlogFile.saveScene.currentSentenceId; WebGAL.sceneManager.sceneData.sceneStack = cloneDeep(backlogFile.saveScene.sceneStack); diff --git a/packages/webgal/src/Core/util/logger.ts b/packages/webgal/src/Core/util/logger.ts index 2629d134e..fb6695a84 100644 --- a/packages/webgal/src/Core/util/logger.ts +++ b/packages/webgal/src/Core/util/logger.ts @@ -4,3 +4,6 @@ import Cloudlog from 'cloudlogjs'; * 日志打印工具 */ export const logger = new Cloudlog(); +if (process.env.NODE_ENV === 'production') { + logger.setLevel('INFO'); +} diff --git a/packages/webgal/src/Core/util/prefetcher/assetsPrefetcher.ts b/packages/webgal/src/Core/util/prefetcher/assetsPrefetcher.ts index 7b6e31d2e..f6701dff0 100644 --- a/packages/webgal/src/Core/util/prefetcher/assetsPrefetcher.ts +++ b/packages/webgal/src/Core/util/prefetcher/assetsPrefetcher.ts @@ -12,7 +12,7 @@ export const assetsPrefetcher = (assetList: Array) => { // 判断是否已经存在 const hasPrefetch = WebGAL.sceneManager.settledAssets.includes(asset.url); if (hasPrefetch) { - logger.warn('该资源已在预加载列表中,无需重复加载'); + logger.debug(`该资源${asset.url}已在预加载列表中,无需重复加载`); } else { const newLink = document.createElement('link'); newLink.setAttribute('rel', 'prefetch'); diff --git a/packages/webgal/src/Core/util/syncWithEditor/syncWithOrigine.ts b/packages/webgal/src/Core/util/syncWithEditor/syncWithOrigine.ts index 1debdad3f..9e430c7b3 100644 --- a/packages/webgal/src/Core/util/syncWithEditor/syncWithOrigine.ts +++ b/packages/webgal/src/Core/util/syncWithEditor/syncWithOrigine.ts @@ -8,8 +8,13 @@ import { setVisibility } from '@/store/GUIReducer'; import { nextSentence } from '@/Core/controller/gamePlay/nextSentence'; import { WebGAL } from '@/Core/WebGAL'; +import cloneDeep from 'lodash/cloneDeep'; +import { IScene } from '@/Core/controller/scene/sceneInterface'; +import { jumpFromBacklog } from '@/Core/controller/storage/jumpFromBacklog'; -export const syncWithOrigine = (sceneName: string, sentenceId: number) => { +let syncFastTimeout: ReturnType | undefined; + +export const syncWithOrigine = (sceneName: string, sentenceId: number, expermental = false) => { logger.warn('正在跳转到' + sceneName + ':' + sentenceId); const dispatch = webgalStore.dispatch; dispatch(setVisibility({ component: 'showTitle', visibility: false })); @@ -19,15 +24,28 @@ export const syncWithOrigine = (sceneName: string, sentenceId: number) => { if (title) { title.style.display = 'none'; } - resetStage(true); - // 重新获取初始场景 + const pastScene = cloneDeep(WebGAL.sceneManager.sceneData.currentScene); + // 重新获取场景 const sceneUrl: string = assetSetter(sceneName, fileType.scene); // 场景写入到运行时 sceneFetcher(sceneUrl).then((rawScene) => { + // 等等,先检查一下能不能恢复场景 + const lastSameSentence = findLastSameSentence(pastScene, WebGAL.sceneManager.sceneData.currentScene, sentenceId); + const lastRecoverySentenceId = Math.min(sentenceId, lastSameSentence); + const recId = findLastAvailableBacklog(lastRecoverySentenceId, sceneName); + const isCanRec = recId >= 0 && expermental; + resetStage(!isCanRec); WebGAL.sceneManager.sceneData.currentScene = sceneParser(rawScene, sceneName, sceneUrl); // 开始快进到指定语句 const currentSceneName = WebGAL.sceneManager.sceneData.currentScene.sceneName; WebGAL.gameplay.isFast = true; + if (isCanRec) { + jumpFromBacklog(recId, false); + } + if (syncFastTimeout) { + // 之前发生的跳转要清理掉 + clearTimeout(syncFastTimeout); + } syncFast(sentenceId, currentSceneName); }); }; @@ -38,8 +56,33 @@ export function syncFast(sentenceId: number, currentSceneName: string) { WebGAL.sceneManager.sceneData.currentScene.sceneName === currentSceneName ) { nextSentence(); - setTimeout(() => syncFast(sentenceId, currentSceneName), 2); + syncFastTimeout = setTimeout(() => syncFast(sentenceId, currentSceneName), 2); } else { WebGAL.gameplay.isFast = false; } } + +function findLastSameSentence(oldScene: IScene, newScene: IScene, sentenceId: number): number { + let lastSameSentence = 0; + for (let i = 0; i < sentenceId && i < oldScene.sentenceList.length; i++) { + const oldSentenceStr = JSON.stringify(oldScene.sentenceList[i]); + const newSentenceStr = JSON.stringify(newScene.sentenceList[i]); + if (oldSentenceStr !== newSentenceStr) { + break; + } + lastSameSentence = i; + } + return lastSameSentence; +} + +function findLastAvailableBacklog(targetSentence: number, sceneName: string) { + let lastAvailable = -1; + WebGAL.backlogManager.getBacklog().forEach((e, i) => { + const recSentenceId = e.saveScene.currentSentenceId; + const recSceneName = e.saveScene.sceneName; + if (recSentenceId <= targetSentence && recSceneName === sceneName) { + lastAvailable = i; + } + }); + return lastAvailable; +} diff --git a/packages/webgal/src/Core/util/syncWithEditor/webSocketFunc.ts b/packages/webgal/src/Core/util/syncWithEditor/webSocketFunc.ts index 4b913ada6..73f5342d2 100644 --- a/packages/webgal/src/Core/util/syncWithEditor/webSocketFunc.ts +++ b/packages/webgal/src/Core/util/syncWithEditor/webSocketFunc.ts @@ -55,7 +55,7 @@ export const webSocketFunc = () => { const data: IDebugMessage = JSON.parse(str); const message = data.data; if (message.command === DebugCommand.JUMP) { - syncWithOrigine(message.sceneMsg.scene, message.sceneMsg.sentence); + syncWithOrigine(message.sceneMsg.scene, message.sceneMsg.sentence, message.message === 'exp'); } if (message.command === DebugCommand.EXE_COMMAND) { const command = message.message; diff --git a/packages/webgal/src/Stage/MainStage/useSetBg.ts b/packages/webgal/src/Stage/MainStage/useSetBg.ts index 36e4511df..83f270f70 100644 --- a/packages/webgal/src/Stage/MainStage/useSetBg.ts +++ b/packages/webgal/src/Stage/MainStage/useSetBg.ts @@ -22,7 +22,7 @@ export function useSetBg(stageState: IStageState) { removeBg(currentBg); } } - WebGAL.gameplay.pixiStage?.addBg(thisBgKey, bgName); + addBg(undefined, thisBgKey, bgName); setEbg(bgName); logger.debug('重设背景'); const { duration, animation } = getEnterExitAnimation('bg-main', 'enter', true); @@ -49,3 +49,14 @@ function removeBg(bgObject: IStageObject) { WebGAL.gameplay.pixiStage?.removeStageObjectByKey('bg-main-off'); }, duration); } + +function addBg(type?: 'image' | 'spine', ...args: any[]) { + const url = args[1]; + if (url.endsWith('.skel')) { + // @ts-ignore + return WebGAL.gameplay.pixiStage?.addSpineBg(...args); + } else { + // @ts-ignore + return WebGAL.gameplay.pixiStage?.addBg(...args); + } +} \ No newline at end of file diff --git a/packages/webgal/src/Stage/MainStage/useSetFigure.ts b/packages/webgal/src/Stage/MainStage/useSetFigure.ts index f6393605b..9f9d91c47 100644 --- a/packages/webgal/src/Stage/MainStage/useSetFigure.ts +++ b/packages/webgal/src/Stage/MainStage/useSetFigure.ts @@ -187,7 +187,7 @@ function removeFig(figObj: IStageObject, enterTikerKey: string, effects: IEffect WebGAL.gameplay.pixiStage?.removeAnimationWithSetEffects(enterTikerKey); // 快进,跳过退出动画 if (WebGAL.gameplay.isFast) { - logger.info('快速模式,立刻关闭立绘'); + logger.debug('快速模式,立刻关闭立绘'); WebGAL.gameplay.pixiStage?.removeStageObjectByKey(figObj.key); return; } diff --git a/packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx b/packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx index 6c32c2de8..0c3ec545f 100644 --- a/packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx +++ b/packages/webgal/src/Stage/TextBox/IMSSTextbox.tsx @@ -32,6 +32,7 @@ export default function IMSSTextbox(props: ITextboxProps) { e.className = applyStyle('TextBox_textElement_Settled', styles.TextBox_textElement_Settled); }); } + WebGAL.events.textSettle.on(settleText); return () => { WebGAL.events.textSettle.off(settleText); @@ -97,7 +98,6 @@ export default function IMSSTextbox(props: ITextboxProps) { ); }); - console.log(`${textboxOpacity / 100}`); return ( <> @@ -107,19 +107,27 @@ export default function IMSSTextbox(props: ITextboxProps) { className={ applyStyle('TextBox_main', styles.TextBox_main) + ' ' + - applyStyle('TextBox_Background', styles.TextBox_Background) + applyStyle('TextBox_Background', styles.TextBox_Background) + + ' ' + + (miniAvatar === '' + ? applyStyle('TextBox_main_miniavatarOff', styles.TextBox_main_miniavatarOff) + : undefined) } style={{ opacity: `${textboxOpacity / 100}`, - left: miniAvatar === '' ? 25 : undefined, }} />
diff --git a/packages/webgal/src/Stage/TextBox/textbox.module.scss b/packages/webgal/src/Stage/TextBox/textbox.module.scss index 0cdfa8061..eaf84accc 100644 --- a/packages/webgal/src/Stage/TextBox/textbox.module.scss +++ b/packages/webgal/src/Stage/TextBox/textbox.module.scss @@ -41,6 +41,10 @@ $height: 330px; transition: left 0.33s; } +.TextBox_main_miniavatarOff { + left: 25px; +} + .TextBox_Background { z-index: 2; background: linear-gradient(rgba(245, 247, 250, 1) 0%, rgba(189, 198, 222, 1) 100%); diff --git a/packages/webgal/src/config/info.ts b/packages/webgal/src/config/info.ts index 27b475513..6219fb6b8 100644 --- a/packages/webgal/src/config/info.ts +++ b/packages/webgal/src/config/info.ts @@ -1,5 +1,5 @@ export const __INFO = { - version: 'WebGAL 4.5.1', + version: 'WebGAL 4.5.2', contributors: [ { username: 'Mahiru', link: 'https://github.com/MakinoharaShoko' }, { username: 'Hoshinokinya', link: 'https://github.com/hshqwq' }, diff --git a/packages/webgal/src/translations/jp.ts b/packages/webgal/src/translations/jp.ts index ae2778648..f720af7b3 100644 --- a/packages/webgal/src/translations/jp.ts +++ b/packages/webgal/src/translations/jp.ts @@ -24,37 +24,37 @@ const jp = { title: '言語', }, resetData: { - title: 'データの削除またに復元', + title: 'データの復元と削除', options: { - clearGameSave: 'すべてのアーカイブを削除', - resetSettings: 'デフォルト設置を復元', + clearGameSave: 'すべてのセーブデータを削除', + resetSettings: '設定を元に戻す', clearAll: 'すべてのデータを削除', }, dialogs: { - clearGameSave: 'アーカイブをクリアしてもよろしいですか?', - resetSettings: 'デフォルト設定を復元してもよろしいですか?', - clearAll: 'すべてのデータを削除してもよろしいですか?', + clearGameSave: 'すべてのセーブデータを削除しますか?', + resetSettings: '設定を元に戻しますか?', + clearAll: 'すべてのデータを削除しますか?', }, }, gameSave: { - title: 'アーカイブとオプションのインポートまたはエクスポート', + title: 'セーブデータと設定のインポートとエクスポート', options: { - export: 'アーカイブとオプションのエクスポート', - import: 'アーカイブとオプションのインポート', + export: 'セーブデータと設定のエクスポート', + import: 'セーブデータと設定のインポート', }, dialogs: { import: { - title: 'アーカイブとオプションをインポートしますか?', - tip: 'インポートアーカイブ', - error: 'アーカイブの解析に失败しました', + title: 'セーブデータと設定をインポートしますか?', + tip: 'セーブデータのインポート', + error: 'セーブデータの読み込みに失敗しました', }, }, }, about: { - title: 'WebGALについて', - subTitle: 'WebGAL:開源のウェブ基盤視覚小説エンジン', - version: '版数', - source: '源コード保管所', + title: 'WebGAL について', + subTitle: 'WebGAL: オープンソースのウェブベースビジュアルノベルエンジン', + version: 'バージョン', + source: 'ソースコードリポジトリ', contributors: '貢献者', website: 'ウェブサイト', }, @@ -63,6 +63,13 @@ const jp = { display: { title: 'ウィンドウ', options: { + fullScreen: { + title: 'フルスクリーン', + options: { + on: 'オン', + off: 'オフ', + }, + }, textSpeed: { title: 'テキスト表示速度', options: { @@ -82,29 +89,31 @@ const jp = { textFont: { title: 'フォント', options: { - siYuanSimSun: '源ノ明朝', - SimHei: '黒体', - lxgw: '霞鴎文隷', + siYuanSimSun: '源ノ明朝(中国語)', + SimHei: 'OPPO Sans', + lxgw: 'LXGW WenKai', }, }, textboxOpacity: { - title: 'Textbox Opacity', + title: 'テキストボックスの不透明度', }, textPreview: { title: 'テキスト表示プレビュー', - // todo - text: 'プレビューはテキストボックスのテキストサイズとテキスト表示速度です。上記のオプションでフォントも変更できます。', + text: 'これはテキストボックスのフォントとサイズ、表示速度のプレビューです。上にある設定で変更できます。', }, }, }, sound: { title: 'サウンド', options: { - volumeMain: { title: 'MAIN 音量' }, - vocalVolume: { title: 'VOICE 音量' }, + volumeMain: { title: 'メイン音量' }, + vocalVolume: { title: 'ボイス音量' }, bgmVolume: { title: 'BGM 音量' }, - seVolume: { title: 'SE 音量' }, + seVolume: { title: '効果音音量' }, uiSeVolume: { title: 'UI 効果音音量' }, + voiceOption: { title: 'ボイスの中断' }, + voiceStop: { title: '中断する' }, + voiceContinue: { title: '中断しない' }, }, }, // language: { @@ -116,7 +125,7 @@ const jp = { }, saving: { title: 'SAVE', - isOverwrite: '上書きしますか?', + isOverwrite: 'セーブデータを上書きしますか?', }, loadSaving: { title: 'LOAD', @@ -129,7 +138,6 @@ const jp = { }, }, - // todo title: { start: { title: '初めから', @@ -168,7 +176,7 @@ const jp = { load: 'LOAD', options: 'CONFIG', title: 'HOME', - titleTips: 'タイトル画面に戻ることを確認しますか', + titleTips: 'タイトル画面に戻りますか?', }, }, diff --git a/packages/webgal/vite.config.ts b/packages/webgal/vite.config.ts index 400a37ada..725a227b0 100644 --- a/packages/webgal/vite.config.ts +++ b/packages/webgal/vite.config.ts @@ -57,4 +57,7 @@ export default defineConfig({ '@': resolve('src'), }, }, + build: { + sourcemap: true, + }, }); diff --git a/releasenote.md b/releasenote.md index 9d896e034..eec73f24e 100644 --- a/releasenote.md +++ b/releasenote.md @@ -8,15 +8,21 @@ #### 新功能 -Pixi Container 使用 AlphaFilter 代替 alpha 属性,更好地兼容 Live2D +解析器增加前后空值剪切和;的转义 + +在生产环境去除调试输出,提高性能 + +添加试验性快速预览 + +支持使用 Spine 做背景 #### 修复 -WebGAL 与编辑器同步的部分问题 +UI 自定义可以支持小头像不存在的情况 -提高资源预加载效率 +提高唇形同步性能 -修复 moc3 Live2D 加载问题 +提高日语翻译质量 ## Release Notes @@ -29,55 +35,57 @@ WebGAL 与编辑器同步的部分问题 #### New Features -Pixi Container uses AlphaFilter instead of alpha property for better Live2D compatibility +Parser adds trimming of leading and trailing whitespace and escaping of ; + +Remove debug prints in production builds, improving performance + +Add experimental fast preview + +Support using Spine for backgrounds #### Fixes -Some issues with WebGAL syncing with the editor +UI customization can handle the case where small portraits are missing -Improved resource preloading efficiency +Improved performance of lip syncing -Fixed moc3 Live2D loading issues +Improved Japanese translation quality -## リリースノート - -**このリポジトリではソースコードのみを公開しています** +#### 新機能 -**ユーザーフレンドリーなグラフィックエディタを使用してWebGALゲームの作成、制作、リアルタイムプレビューを体験したい場合は、[WebGALグラフィックエディタをダウンロードしてください](https://github.com/MakinoharaShoko/WebGAL_Terre/releases)** +パーサーに前後空白トリムと;のエスケープを追加 -### このバージョンでは +本番環境でデバッグ出力を削除し、パフォーマンスを向上 -#### 新機能 +試験的な高速プレビューを追加 -Pixi Containerがalpha属性の代わりにAlphaFilterを使用するようになり、Live2Dとの互換性が向上しました。 +Spine を背景として使用することをサポート #### 修正 -WebGALとエディターの同期に関するいくつかの問題を修正しました。 +UI カスタマイズでアバターが存在しない場合をサポート -リソースのプリロード効率を向上させました。 +リップシンクのパフォーマンスを向上 -moc3 Live2Dのロードに関する問題を修正しました。 +日本語翻訳の品質を向上 -## Notes de version - -**Seul le code source est publié dans ce dépôt** +#### Nouvelles fonctionnalités -**Si vous souhaitez expérimenter la création, la fabrication et la prévisualisation en temps réel des jeux WebGAL à l'aide d'un éditeur graphique convivial, veuillez [télécharger l'éditeur graphique WebGAL](https://github.com/MakinoharaShoko/WebGAL_Terre/releases)** +L'analyseur ajoute le rognage des espaces vides avant et après et l'échappement des ; -### Dans cette version +Suppression de la sortie de débogage en environnement de production, amélioration des performances -#### Nouvelles fonctionnalités +Ajout d'un aperçu rapide expérimental -Pixi Container utilise AlphaFilter à la place de la propriété alpha, pour une meilleure compatibilité avec Live2D +Prise en charge de Spine pour les arrière-plans -#### Correctifs +#### Corrections -Certains problèmes de synchronisation entre WebGAL et l'éditeur +La personnalisation de l'interface utilisateur peut prendre en charge les cas où il n'y a pas de petite icône -Amélioration de l'efficacité du préchargement des ressources +Amélioration des performances de synchronisation labiale -Correction du problème de chargement de Live2D moc3 +Amélioration de la qualité de la traduction japonaise diff --git a/yarn.lock b/yarn.lock index 95edeb2db..59ecb8b07 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5611,16 +5611,6 @@ void-elements@3.1.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== -webgal-parser@latest: - version "4.4.15" - resolved "https://registry.yarnpkg.com/webgal-parser/-/webgal-parser-4.4.15.tgz#daa99fa523413fe70b76f18160f2ea8ef32b6f2a" - integrity sha512-nVSkdJWzTKmKUlgsRwkjDj+s08LnJpp1jqr9+VyTPO7n3ZxoSJm3NyIWSEz7GcplohYovoPS15EOEZm637HqdA== - dependencies: - chevrotain "^10.5.0" - cloudlogjs "^1.0.11" - lodash "^4.17.21" - tsx "^3.12.7" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"