webgal-parser 4.6.3 → 4.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/build/cjs/index.cjs +34 -11
- package/build/cjs/index.d.ts +5 -1
- package/build/cjs/interface/sceneInterface.d.ts +2 -1
- package/build/cjs/sceneParser.d.ts +1 -1
- package/build/cjs/scriptParser/scriptParser.d.ts +3 -1
- package/build/es/index.d.ts +5 -1
- package/build/es/index.js +34 -11
- package/build/es/interface/sceneInterface.d.ts +2 -1
- package/build/es/sceneParser.d.ts +1 -1
- package/build/es/scriptParser/scriptParser.d.ts +3 -1
- package/build/types/index.d.ts +5 -1
- package/build/types/interface/sceneInterface.d.ts +2 -1
- package/build/types/sceneParser.d.ts +1 -1
- package/build/types/scriptParser/scriptParser.d.ts +3 -1
- package/build/umd/index.global.js +34 -11
- package/package.json +1 -1
- package/src/config/scriptConfig.ts +1 -0
- package/src/index.ts +5 -1
- package/src/interface/sceneInterface.ts +5 -4
- package/src/sceneParser.ts +23 -7
- package/src/scriptParser/assetsScanner.ts +1 -1
- package/src/scriptParser/contentParser.ts +1 -0
- package/src/scriptParser/scriptParser.ts +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# WebGAL Parser Changelog
|
|
2
2
|
|
|
3
|
+
## [4.6.5] - 2026-09-24
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- 新增 `changeFigureDiff` 命令(切换立绘差分),语句内容按立绘路径解析,并参与资源扫描
|
|
7
|
+
- `SceneParser` 的 `assetsPrefetcher` 改为可选:省略时跳过资源收集,`sentenceAssets`、`subScene`、`assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(如编辑器语法解析)
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- 资源与子场景列表改为就地累积,消除资源密集的长场景解析时 Θ(资源数²) 的开销
|
|
11
|
+
|
|
3
12
|
## [4.6.3] - 2026-08-01
|
|
4
13
|
|
|
5
14
|
正式发布 4.6.3-beta.1 / beta.2 的多行语句支持,另含以下改动。
|
package/build/cjs/index.cjs
CHANGED
|
@@ -40,12 +40,14 @@ var commandType;
|
|
|
40
40
|
commandType[commandType["wait"] = 33] = "wait";
|
|
41
41
|
commandType[commandType["callSteam"] = 34] = "callSteam";
|
|
42
42
|
commandType[commandType["return"] = 35] = "return";
|
|
43
|
+
commandType[commandType["changeFigureDiff"] = 36] = "changeFigureDiff";
|
|
43
44
|
})(commandType || (commandType = {}));
|
|
44
45
|
|
|
45
46
|
const SCRIPT_CONFIG = [
|
|
46
47
|
{ scriptString: 'say', scriptType: commandType.say },
|
|
47
48
|
{ scriptString: 'changeBg', scriptType: commandType.changeBg },
|
|
48
49
|
{ scriptString: 'changeFigure', scriptType: commandType.changeFigure },
|
|
50
|
+
{ scriptString: 'changeFigureDiff', scriptType: commandType.changeFigureDiff },
|
|
49
51
|
{ scriptString: 'bgm', scriptType: commandType.bgm },
|
|
50
52
|
{ scriptString: 'playVideo', scriptType: commandType.video },
|
|
51
53
|
{ scriptString: 'pixiPerform', scriptType: commandType.pixi },
|
|
@@ -297,6 +299,7 @@ const contentParser = (contentRaw, type, assetSetter) => {
|
|
|
297
299
|
case commandType.changeBg:
|
|
298
300
|
return assetSetter(contentRaw, fileType.background);
|
|
299
301
|
case commandType.changeFigure:
|
|
302
|
+
case commandType.changeFigureDiff:
|
|
300
303
|
return assetSetter(contentRaw, fileType.figure);
|
|
301
304
|
case commandType.bgm:
|
|
302
305
|
return assetSetter(contentRaw, fileType.bgm);
|
|
@@ -377,7 +380,7 @@ const assetsScanner = (command, content, args, lineNumber) => {
|
|
|
377
380
|
type: fileType.background,
|
|
378
381
|
});
|
|
379
382
|
}
|
|
380
|
-
if (command === commandType.changeFigure) {
|
|
383
|
+
if (command === commandType.changeFigure || command === commandType.changeFigureDiff) {
|
|
381
384
|
returnAssetsList.push({
|
|
382
385
|
name: content,
|
|
383
386
|
url: content,
|
|
@@ -441,8 +444,10 @@ const subSceneScanner = (command, content) => {
|
|
|
441
444
|
* @param assetSetter
|
|
442
445
|
* @param ADD_NEXT_ARG_LIST
|
|
443
446
|
* @param SCRIPT_CONFIG_MAP
|
|
447
|
+
* @param lineNumber 语句所在行号
|
|
448
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
444
449
|
*/
|
|
445
|
-
const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, lineNumber = 0) => {
|
|
450
|
+
const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, lineNumber = 0, collectAssets = true) => {
|
|
446
451
|
let command; // 默认为对话
|
|
447
452
|
let content; // 语句内容
|
|
448
453
|
let subScene; // 语句携带的子场景(可能没有)
|
|
@@ -510,8 +515,8 @@ const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG
|
|
|
510
515
|
}
|
|
511
516
|
}
|
|
512
517
|
content = contentParser(newSentenceRaw.trim(), command, assetSetter); // 将语句内容里的文件名转为相对或绝对路径
|
|
513
|
-
sentenceAssets = assetsScanner(command, content, args, lineNumber); // 扫描语句携带资源
|
|
514
|
-
subScene = subSceneScanner(command, content); // 扫描语句携带子场景
|
|
518
|
+
sentenceAssets = collectAssets ? assetsScanner(command, content, args, lineNumber) : []; // 扫描语句携带资源
|
|
519
|
+
subScene = collectAssets ? subSceneScanner(command, content) : []; // 扫描语句携带子场景
|
|
515
520
|
return {
|
|
516
521
|
command: command,
|
|
517
522
|
commandRaw: commandRaw.trim(),
|
|
@@ -688,6 +693,8 @@ function placeholderLine(content = "") {
|
|
|
688
693
|
* @return {IScene} 解析后的场景
|
|
689
694
|
*/
|
|
690
695
|
const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
|
|
696
|
+
// 没有预取回调时不需要场景级资源列表,连同每条语句的资源扫描一起跳过
|
|
697
|
+
const collectAssets = assetsPrefetcher !== undefined;
|
|
691
698
|
// 预处理把多行语句折叠进它的首行,并用占位行补齐被折叠掉的行,
|
|
692
699
|
// 因此这里的行数与原始场景严格一致,「语句 index == 文件行号」始终成立。
|
|
693
700
|
const rawSentenceList = sceneTextPreProcess(rawScene).split('\n'); // 原始句子列表
|
|
@@ -698,16 +705,28 @@ const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSette
|
|
|
698
705
|
let assetsList = []; // 场景资源列表
|
|
699
706
|
let subSceneList = []; // 子场景列表
|
|
700
707
|
const sentenceList = rawSentenceListWithoutEmpty.map((sentence, index) => {
|
|
701
|
-
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index);
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
708
|
+
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index, collectAssets);
|
|
709
|
+
if (!collectAssets) {
|
|
710
|
+
return returnSentence;
|
|
711
|
+
}
|
|
712
|
+
// 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList。
|
|
713
|
+
// 必须就地追加:如果写成 [...assetsList, ...sentenceAssets],每条语句都要复制
|
|
714
|
+
// 一次已累积的列表,整体退化成 Θ(资源数²)——资源密集的场景脚本(几乎每条语句
|
|
715
|
+
// 都带 bg / figure / vocal)在数千条语句规模下会明显变慢。
|
|
716
|
+
for (const asset of returnSentence.sentenceAssets) {
|
|
717
|
+
assetsList.push(asset);
|
|
718
|
+
}
|
|
719
|
+
for (const subScene of returnSentence.subScene) {
|
|
720
|
+
subSceneList.push(subScene);
|
|
721
|
+
}
|
|
705
722
|
return returnSentence;
|
|
706
723
|
});
|
|
707
724
|
markMultilineRanges(sentenceList, rawSentenceList);
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
725
|
+
if (collectAssets) {
|
|
726
|
+
// 开始资源的预加载
|
|
727
|
+
assetsList = deduplicateAssets(assetsList);
|
|
728
|
+
assetsPrefetcher(assetsList);
|
|
729
|
+
}
|
|
711
730
|
return {
|
|
712
731
|
sceneName: sceneName,
|
|
713
732
|
sceneUrl: sceneUrl,
|
|
@@ -789,6 +808,10 @@ class SceneParser {
|
|
|
789
808
|
assetSetter;
|
|
790
809
|
ADD_NEXT_ARG_LIST;
|
|
791
810
|
SCRIPT_CONFIG_MAP;
|
|
811
|
+
/**
|
|
812
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
813
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
814
|
+
*/
|
|
792
815
|
constructor(assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_INPUT) {
|
|
793
816
|
this.assetsPrefetcher = assetsPrefetcher;
|
|
794
817
|
this.assetSetter = assetSetter;
|
package/build/cjs/index.d.ts
CHANGED
|
@@ -9,7 +9,11 @@ export default class SceneParser {
|
|
|
9
9
|
private readonly assetSetter;
|
|
10
10
|
private readonly ADD_NEXT_ARG_LIST;
|
|
11
11
|
private readonly SCRIPT_CONFIG_MAP;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
14
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
15
|
+
*/
|
|
16
|
+
constructor(assetsPrefetcher: ((assetList: IAsset[]) => void) | undefined, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: number[], SCRIPT_CONFIG_INPUT: ConfigItem[] | ConfigMap);
|
|
13
17
|
/**
|
|
14
18
|
* 解析场景
|
|
15
19
|
* @param rawScene 原始场景
|
|
@@ -12,4 +12,4 @@ import { ConfigMap } from './config/scriptConfig';
|
|
|
12
12
|
* @param SCRIPT_CONFIG_MAP
|
|
13
13
|
* @return {IScene} 解析后的场景
|
|
14
14
|
*/
|
|
15
|
-
export declare const sceneParser: (rawScene: string, sceneName: string, sceneUrl: string, assetsPrefetcher: (assetList: Array<IAsset>) => void, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap) => IScene;
|
|
15
|
+
export declare const sceneParser: (rawScene: string, sceneName: string, sceneUrl: string, assetsPrefetcher: ((assetList: Array<IAsset>) => void) | undefined, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap) => IScene;
|
|
@@ -6,5 +6,7 @@ import { ConfigMap } from '../config/scriptConfig';
|
|
|
6
6
|
* @param assetSetter
|
|
7
7
|
* @param ADD_NEXT_ARG_LIST
|
|
8
8
|
* @param SCRIPT_CONFIG_MAP
|
|
9
|
+
* @param lineNumber 语句所在行号
|
|
10
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
9
11
|
*/
|
|
10
|
-
export declare const scriptParser: (sentenceRaw: string, assetSetter: any, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap, lineNumber?: number) => ISentence;
|
|
12
|
+
export declare const scriptParser: (sentenceRaw: string, assetSetter: any, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap, lineNumber?: number, collectAssets?: boolean) => ISentence;
|
package/build/es/index.d.ts
CHANGED
|
@@ -9,7 +9,11 @@ export default class SceneParser {
|
|
|
9
9
|
private readonly assetSetter;
|
|
10
10
|
private readonly ADD_NEXT_ARG_LIST;
|
|
11
11
|
private readonly SCRIPT_CONFIG_MAP;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
14
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
15
|
+
*/
|
|
16
|
+
constructor(assetsPrefetcher: ((assetList: IAsset[]) => void) | undefined, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: number[], SCRIPT_CONFIG_INPUT: ConfigItem[] | ConfigMap);
|
|
13
17
|
/**
|
|
14
18
|
* 解析场景
|
|
15
19
|
* @param rawScene 原始场景
|
package/build/es/index.js
CHANGED
|
@@ -36,12 +36,14 @@ var commandType;
|
|
|
36
36
|
commandType[commandType["wait"] = 33] = "wait";
|
|
37
37
|
commandType[commandType["callSteam"] = 34] = "callSteam";
|
|
38
38
|
commandType[commandType["return"] = 35] = "return";
|
|
39
|
+
commandType[commandType["changeFigureDiff"] = 36] = "changeFigureDiff";
|
|
39
40
|
})(commandType || (commandType = {}));
|
|
40
41
|
|
|
41
42
|
const SCRIPT_CONFIG = [
|
|
42
43
|
{ scriptString: 'say', scriptType: commandType.say },
|
|
43
44
|
{ scriptString: 'changeBg', scriptType: commandType.changeBg },
|
|
44
45
|
{ scriptString: 'changeFigure', scriptType: commandType.changeFigure },
|
|
46
|
+
{ scriptString: 'changeFigureDiff', scriptType: commandType.changeFigureDiff },
|
|
45
47
|
{ scriptString: 'bgm', scriptType: commandType.bgm },
|
|
46
48
|
{ scriptString: 'playVideo', scriptType: commandType.video },
|
|
47
49
|
{ scriptString: 'pixiPerform', scriptType: commandType.pixi },
|
|
@@ -293,6 +295,7 @@ const contentParser = (contentRaw, type, assetSetter) => {
|
|
|
293
295
|
case commandType.changeBg:
|
|
294
296
|
return assetSetter(contentRaw, fileType.background);
|
|
295
297
|
case commandType.changeFigure:
|
|
298
|
+
case commandType.changeFigureDiff:
|
|
296
299
|
return assetSetter(contentRaw, fileType.figure);
|
|
297
300
|
case commandType.bgm:
|
|
298
301
|
return assetSetter(contentRaw, fileType.bgm);
|
|
@@ -373,7 +376,7 @@ const assetsScanner = (command, content, args, lineNumber) => {
|
|
|
373
376
|
type: fileType.background,
|
|
374
377
|
});
|
|
375
378
|
}
|
|
376
|
-
if (command === commandType.changeFigure) {
|
|
379
|
+
if (command === commandType.changeFigure || command === commandType.changeFigureDiff) {
|
|
377
380
|
returnAssetsList.push({
|
|
378
381
|
name: content,
|
|
379
382
|
url: content,
|
|
@@ -437,8 +440,10 @@ const subSceneScanner = (command, content) => {
|
|
|
437
440
|
* @param assetSetter
|
|
438
441
|
* @param ADD_NEXT_ARG_LIST
|
|
439
442
|
* @param SCRIPT_CONFIG_MAP
|
|
443
|
+
* @param lineNumber 语句所在行号
|
|
444
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
440
445
|
*/
|
|
441
|
-
const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, lineNumber = 0) => {
|
|
446
|
+
const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, lineNumber = 0, collectAssets = true) => {
|
|
442
447
|
let command; // 默认为对话
|
|
443
448
|
let content; // 语句内容
|
|
444
449
|
let subScene; // 语句携带的子场景(可能没有)
|
|
@@ -506,8 +511,8 @@ const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG
|
|
|
506
511
|
}
|
|
507
512
|
}
|
|
508
513
|
content = contentParser(newSentenceRaw.trim(), command, assetSetter); // 将语句内容里的文件名转为相对或绝对路径
|
|
509
|
-
sentenceAssets = assetsScanner(command, content, args, lineNumber); // 扫描语句携带资源
|
|
510
|
-
subScene = subSceneScanner(command, content); // 扫描语句携带子场景
|
|
514
|
+
sentenceAssets = collectAssets ? assetsScanner(command, content, args, lineNumber) : []; // 扫描语句携带资源
|
|
515
|
+
subScene = collectAssets ? subSceneScanner(command, content) : []; // 扫描语句携带子场景
|
|
511
516
|
return {
|
|
512
517
|
command: command,
|
|
513
518
|
commandRaw: commandRaw.trim(),
|
|
@@ -684,6 +689,8 @@ function placeholderLine(content = "") {
|
|
|
684
689
|
* @return {IScene} 解析后的场景
|
|
685
690
|
*/
|
|
686
691
|
const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
|
|
692
|
+
// 没有预取回调时不需要场景级资源列表,连同每条语句的资源扫描一起跳过
|
|
693
|
+
const collectAssets = assetsPrefetcher !== undefined;
|
|
687
694
|
// 预处理把多行语句折叠进它的首行,并用占位行补齐被折叠掉的行,
|
|
688
695
|
// 因此这里的行数与原始场景严格一致,「语句 index == 文件行号」始终成立。
|
|
689
696
|
const rawSentenceList = sceneTextPreProcess(rawScene).split('\n'); // 原始句子列表
|
|
@@ -694,16 +701,28 @@ const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSette
|
|
|
694
701
|
let assetsList = []; // 场景资源列表
|
|
695
702
|
let subSceneList = []; // 子场景列表
|
|
696
703
|
const sentenceList = rawSentenceListWithoutEmpty.map((sentence, index) => {
|
|
697
|
-
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
704
|
+
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index, collectAssets);
|
|
705
|
+
if (!collectAssets) {
|
|
706
|
+
return returnSentence;
|
|
707
|
+
}
|
|
708
|
+
// 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList。
|
|
709
|
+
// 必须就地追加:如果写成 [...assetsList, ...sentenceAssets],每条语句都要复制
|
|
710
|
+
// 一次已累积的列表,整体退化成 Θ(资源数²)——资源密集的场景脚本(几乎每条语句
|
|
711
|
+
// 都带 bg / figure / vocal)在数千条语句规模下会明显变慢。
|
|
712
|
+
for (const asset of returnSentence.sentenceAssets) {
|
|
713
|
+
assetsList.push(asset);
|
|
714
|
+
}
|
|
715
|
+
for (const subScene of returnSentence.subScene) {
|
|
716
|
+
subSceneList.push(subScene);
|
|
717
|
+
}
|
|
701
718
|
return returnSentence;
|
|
702
719
|
});
|
|
703
720
|
markMultilineRanges(sentenceList, rawSentenceList);
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
721
|
+
if (collectAssets) {
|
|
722
|
+
// 开始资源的预加载
|
|
723
|
+
assetsList = deduplicateAssets(assetsList);
|
|
724
|
+
assetsPrefetcher(assetsList);
|
|
725
|
+
}
|
|
707
726
|
return {
|
|
708
727
|
sceneName: sceneName,
|
|
709
728
|
sceneUrl: sceneUrl,
|
|
@@ -785,6 +804,10 @@ class SceneParser {
|
|
|
785
804
|
assetSetter;
|
|
786
805
|
ADD_NEXT_ARG_LIST;
|
|
787
806
|
SCRIPT_CONFIG_MAP;
|
|
807
|
+
/**
|
|
808
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
809
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
810
|
+
*/
|
|
788
811
|
constructor(assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_INPUT) {
|
|
789
812
|
this.assetsPrefetcher = assetsPrefetcher;
|
|
790
813
|
this.assetSetter = assetSetter;
|
|
@@ -12,4 +12,4 @@ import { ConfigMap } from './config/scriptConfig';
|
|
|
12
12
|
* @param SCRIPT_CONFIG_MAP
|
|
13
13
|
* @return {IScene} 解析后的场景
|
|
14
14
|
*/
|
|
15
|
-
export declare const sceneParser: (rawScene: string, sceneName: string, sceneUrl: string, assetsPrefetcher: (assetList: Array<IAsset>) => void, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap) => IScene;
|
|
15
|
+
export declare const sceneParser: (rawScene: string, sceneName: string, sceneUrl: string, assetsPrefetcher: ((assetList: Array<IAsset>) => void) | undefined, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap) => IScene;
|
|
@@ -6,5 +6,7 @@ import { ConfigMap } from '../config/scriptConfig';
|
|
|
6
6
|
* @param assetSetter
|
|
7
7
|
* @param ADD_NEXT_ARG_LIST
|
|
8
8
|
* @param SCRIPT_CONFIG_MAP
|
|
9
|
+
* @param lineNumber 语句所在行号
|
|
10
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
9
11
|
*/
|
|
10
|
-
export declare const scriptParser: (sentenceRaw: string, assetSetter: any, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap, lineNumber?: number) => ISentence;
|
|
12
|
+
export declare const scriptParser: (sentenceRaw: string, assetSetter: any, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap, lineNumber?: number, collectAssets?: boolean) => ISentence;
|
package/build/types/index.d.ts
CHANGED
|
@@ -9,7 +9,11 @@ export default class SceneParser {
|
|
|
9
9
|
private readonly assetSetter;
|
|
10
10
|
private readonly ADD_NEXT_ARG_LIST;
|
|
11
11
|
private readonly SCRIPT_CONFIG_MAP;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
14
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
15
|
+
*/
|
|
16
|
+
constructor(assetsPrefetcher: ((assetList: IAsset[]) => void) | undefined, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: number[], SCRIPT_CONFIG_INPUT: ConfigItem[] | ConfigMap);
|
|
13
17
|
/**
|
|
14
18
|
* 解析场景
|
|
15
19
|
* @param rawScene 原始场景
|
|
@@ -12,4 +12,4 @@ import { ConfigMap } from './config/scriptConfig';
|
|
|
12
12
|
* @param SCRIPT_CONFIG_MAP
|
|
13
13
|
* @return {IScene} 解析后的场景
|
|
14
14
|
*/
|
|
15
|
-
export declare const sceneParser: (rawScene: string, sceneName: string, sceneUrl: string, assetsPrefetcher: (assetList: Array<IAsset>) => void, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap) => IScene;
|
|
15
|
+
export declare const sceneParser: (rawScene: string, sceneName: string, sceneUrl: string, assetsPrefetcher: ((assetList: Array<IAsset>) => void) | undefined, assetSetter: (fileName: string, assetType: fileType) => string, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap) => IScene;
|
|
@@ -6,5 +6,7 @@ import { ConfigMap } from '../config/scriptConfig';
|
|
|
6
6
|
* @param assetSetter
|
|
7
7
|
* @param ADD_NEXT_ARG_LIST
|
|
8
8
|
* @param SCRIPT_CONFIG_MAP
|
|
9
|
+
* @param lineNumber 语句所在行号
|
|
10
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
9
11
|
*/
|
|
10
|
-
export declare const scriptParser: (sentenceRaw: string, assetSetter: any, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap, lineNumber?: number) => ISentence;
|
|
12
|
+
export declare const scriptParser: (sentenceRaw: string, assetSetter: any, ADD_NEXT_ARG_LIST: commandType[], SCRIPT_CONFIG_MAP: ConfigMap, lineNumber?: number, collectAssets?: boolean) => ISentence;
|
|
@@ -39,12 +39,14 @@ var webgalParser = (function (exports) {
|
|
|
39
39
|
commandType[commandType["wait"] = 33] = "wait";
|
|
40
40
|
commandType[commandType["callSteam"] = 34] = "callSteam";
|
|
41
41
|
commandType[commandType["return"] = 35] = "return";
|
|
42
|
+
commandType[commandType["changeFigureDiff"] = 36] = "changeFigureDiff";
|
|
42
43
|
})(commandType || (commandType = {}));
|
|
43
44
|
|
|
44
45
|
const SCRIPT_CONFIG = [
|
|
45
46
|
{ scriptString: 'say', scriptType: commandType.say },
|
|
46
47
|
{ scriptString: 'changeBg', scriptType: commandType.changeBg },
|
|
47
48
|
{ scriptString: 'changeFigure', scriptType: commandType.changeFigure },
|
|
49
|
+
{ scriptString: 'changeFigureDiff', scriptType: commandType.changeFigureDiff },
|
|
48
50
|
{ scriptString: 'bgm', scriptType: commandType.bgm },
|
|
49
51
|
{ scriptString: 'playVideo', scriptType: commandType.video },
|
|
50
52
|
{ scriptString: 'pixiPerform', scriptType: commandType.pixi },
|
|
@@ -296,6 +298,7 @@ var webgalParser = (function (exports) {
|
|
|
296
298
|
case commandType.changeBg:
|
|
297
299
|
return assetSetter(contentRaw, fileType.background);
|
|
298
300
|
case commandType.changeFigure:
|
|
301
|
+
case commandType.changeFigureDiff:
|
|
299
302
|
return assetSetter(contentRaw, fileType.figure);
|
|
300
303
|
case commandType.bgm:
|
|
301
304
|
return assetSetter(contentRaw, fileType.bgm);
|
|
@@ -376,7 +379,7 @@ var webgalParser = (function (exports) {
|
|
|
376
379
|
type: fileType.background,
|
|
377
380
|
});
|
|
378
381
|
}
|
|
379
|
-
if (command === commandType.changeFigure) {
|
|
382
|
+
if (command === commandType.changeFigure || command === commandType.changeFigureDiff) {
|
|
380
383
|
returnAssetsList.push({
|
|
381
384
|
name: content,
|
|
382
385
|
url: content,
|
|
@@ -440,8 +443,10 @@ var webgalParser = (function (exports) {
|
|
|
440
443
|
* @param assetSetter
|
|
441
444
|
* @param ADD_NEXT_ARG_LIST
|
|
442
445
|
* @param SCRIPT_CONFIG_MAP
|
|
446
|
+
* @param lineNumber 语句所在行号
|
|
447
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
443
448
|
*/
|
|
444
|
-
const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, lineNumber = 0) => {
|
|
449
|
+
const scriptParser = (sentenceRaw, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, lineNumber = 0, collectAssets = true) => {
|
|
445
450
|
let command; // 默认为对话
|
|
446
451
|
let content; // 语句内容
|
|
447
452
|
let subScene; // 语句携带的子场景(可能没有)
|
|
@@ -509,8 +514,8 @@ var webgalParser = (function (exports) {
|
|
|
509
514
|
}
|
|
510
515
|
}
|
|
511
516
|
content = contentParser(newSentenceRaw.trim(), command, assetSetter); // 将语句内容里的文件名转为相对或绝对路径
|
|
512
|
-
sentenceAssets = assetsScanner(command, content, args, lineNumber); // 扫描语句携带资源
|
|
513
|
-
subScene = subSceneScanner(command, content); // 扫描语句携带子场景
|
|
517
|
+
sentenceAssets = collectAssets ? assetsScanner(command, content, args, lineNumber) : []; // 扫描语句携带资源
|
|
518
|
+
subScene = collectAssets ? subSceneScanner(command, content) : []; // 扫描语句携带子场景
|
|
514
519
|
return {
|
|
515
520
|
command: command,
|
|
516
521
|
commandRaw: commandRaw.trim(),
|
|
@@ -687,6 +692,8 @@ var webgalParser = (function (exports) {
|
|
|
687
692
|
* @return {IScene} 解析后的场景
|
|
688
693
|
*/
|
|
689
694
|
const sceneParser = (rawScene, sceneName, sceneUrl, assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP) => {
|
|
695
|
+
// 没有预取回调时不需要场景级资源列表,连同每条语句的资源扫描一起跳过
|
|
696
|
+
const collectAssets = assetsPrefetcher !== undefined;
|
|
690
697
|
// 预处理把多行语句折叠进它的首行,并用占位行补齐被折叠掉的行,
|
|
691
698
|
// 因此这里的行数与原始场景严格一致,「语句 index == 文件行号」始终成立。
|
|
692
699
|
const rawSentenceList = sceneTextPreProcess(rawScene).split('\n'); // 原始句子列表
|
|
@@ -697,16 +704,28 @@ var webgalParser = (function (exports) {
|
|
|
697
704
|
let assetsList = []; // 场景资源列表
|
|
698
705
|
let subSceneList = []; // 子场景列表
|
|
699
706
|
const sentenceList = rawSentenceListWithoutEmpty.map((sentence, index) => {
|
|
700
|
-
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index);
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
707
|
+
const returnSentence = scriptParser(sentence, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_MAP, index, collectAssets);
|
|
708
|
+
if (!collectAssets) {
|
|
709
|
+
return returnSentence;
|
|
710
|
+
}
|
|
711
|
+
// 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList。
|
|
712
|
+
// 必须就地追加:如果写成 [...assetsList, ...sentenceAssets],每条语句都要复制
|
|
713
|
+
// 一次已累积的列表,整体退化成 Θ(资源数²)——资源密集的场景脚本(几乎每条语句
|
|
714
|
+
// 都带 bg / figure / vocal)在数千条语句规模下会明显变慢。
|
|
715
|
+
for (const asset of returnSentence.sentenceAssets) {
|
|
716
|
+
assetsList.push(asset);
|
|
717
|
+
}
|
|
718
|
+
for (const subScene of returnSentence.subScene) {
|
|
719
|
+
subSceneList.push(subScene);
|
|
720
|
+
}
|
|
704
721
|
return returnSentence;
|
|
705
722
|
});
|
|
706
723
|
markMultilineRanges(sentenceList, rawSentenceList);
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
724
|
+
if (collectAssets) {
|
|
725
|
+
// 开始资源的预加载
|
|
726
|
+
assetsList = deduplicateAssets(assetsList);
|
|
727
|
+
assetsPrefetcher(assetsList);
|
|
728
|
+
}
|
|
710
729
|
return {
|
|
711
730
|
sceneName: sceneName,
|
|
712
731
|
sceneUrl: sceneUrl,
|
|
@@ -788,6 +807,10 @@ var webgalParser = (function (exports) {
|
|
|
788
807
|
assetSetter;
|
|
789
808
|
ADD_NEXT_ARG_LIST;
|
|
790
809
|
SCRIPT_CONFIG_MAP;
|
|
810
|
+
/**
|
|
811
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
812
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
813
|
+
*/
|
|
791
814
|
constructor(assetsPrefetcher, assetSetter, ADD_NEXT_ARG_LIST, SCRIPT_CONFIG_INPUT) {
|
|
792
815
|
this.assetsPrefetcher = assetsPrefetcher;
|
|
793
816
|
this.assetSetter = assetSetter;
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ export const SCRIPT_CONFIG = [
|
|
|
4
4
|
{ scriptString: 'say', scriptType: commandType.say },
|
|
5
5
|
{ scriptString: 'changeBg', scriptType: commandType.changeBg },
|
|
6
6
|
{ scriptString: 'changeFigure', scriptType: commandType.changeFigure },
|
|
7
|
+
{ scriptString: 'changeFigureDiff', scriptType: commandType.changeFigureDiff },
|
|
7
8
|
{ scriptString: 'bgm', scriptType: commandType.bgm },
|
|
8
9
|
{ scriptString: 'playVideo', scriptType: commandType.video },
|
|
9
10
|
{ scriptString: 'pixiPerform', scriptType: commandType.pixi },
|
package/src/index.ts
CHANGED
|
@@ -17,8 +17,12 @@ import {
|
|
|
17
17
|
|
|
18
18
|
export default class SceneParser {
|
|
19
19
|
private readonly SCRIPT_CONFIG_MAP: ConfigMap;
|
|
20
|
+
/**
|
|
21
|
+
* @param assetsPrefetcher 资源预取回调。省略时不收集资源:`sentenceAssets`、`subScene`、
|
|
22
|
+
* `assetsList`、`subSceneList` 均为空数组,适用于只需要语句结构的调用方(编辑器语法解析等)。
|
|
23
|
+
*/
|
|
20
24
|
constructor(
|
|
21
|
-
private readonly assetsPrefetcher: (assetList: IAsset[]) => void,
|
|
25
|
+
private readonly assetsPrefetcher: ((assetList: IAsset[]) => void) | undefined,
|
|
22
26
|
private readonly assetSetter: (
|
|
23
27
|
fileName: string,
|
|
24
28
|
assetType: fileType,
|
|
@@ -41,6 +41,7 @@ export enum commandType {
|
|
|
41
41
|
wait,
|
|
42
42
|
callSteam, // 调用Steam功能
|
|
43
43
|
return, // 从被调用的场景返回
|
|
44
|
+
changeFigureDiff, // 切换等尺寸静态立绘差分;追加以保持旧指令编号
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/**
|
|
@@ -72,8 +73,8 @@ export interface ISentence {
|
|
|
72
73
|
commandRaw: string; // 命令的原始内容,方便调试
|
|
73
74
|
content: string; // 语句内容
|
|
74
75
|
args: Array<arg>; // 参数列表
|
|
75
|
-
sentenceAssets: Array<IAsset>; //
|
|
76
|
-
subScene: Array<string>; //
|
|
76
|
+
sentenceAssets: Array<IAsset>; // 语句携带的资源列表;SceneParser 未提供 assetsPrefetcher 时为空
|
|
77
|
+
subScene: Array<string>; // 语句包含子场景列表;未提供 assetsPrefetcher 时为空
|
|
77
78
|
inlineComment: string; // 行内注释
|
|
78
79
|
/**
|
|
79
80
|
* 本语句在原始场景文件中占据的行范围(0-based,含首尾)。
|
|
@@ -94,8 +95,8 @@ export interface IScene {
|
|
|
94
95
|
sceneName: string; // 场景名称
|
|
95
96
|
sceneUrl: string; // 场景url
|
|
96
97
|
sentenceList: Array<ISentence>; // 语句列表
|
|
97
|
-
assetsList: Array<IAsset>; //
|
|
98
|
-
subSceneList: Array<string>; // 子场景的url
|
|
98
|
+
assetsList: Array<IAsset>; // 资源列表;未提供 assetsPrefetcher 时为空
|
|
99
|
+
subSceneList: Array<string>; // 子场景的url列表;未提供 assetsPrefetcher 时为空
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
/**
|
package/src/sceneParser.ts
CHANGED
|
@@ -27,11 +27,14 @@ export const sceneParser = (
|
|
|
27
27
|
rawScene: string,
|
|
28
28
|
sceneName: string,
|
|
29
29
|
sceneUrl: string,
|
|
30
|
-
assetsPrefetcher: (assetList: Array<IAsset>) => void,
|
|
30
|
+
assetsPrefetcher: ((assetList: Array<IAsset>) => void) | undefined,
|
|
31
31
|
assetSetter: (fileName: string, assetType: fileType) => string,
|
|
32
32
|
ADD_NEXT_ARG_LIST: commandType[],
|
|
33
33
|
SCRIPT_CONFIG_MAP: ConfigMap,
|
|
34
34
|
): IScene => {
|
|
35
|
+
// 没有预取回调时不需要场景级资源列表,连同每条语句的资源扫描一起跳过
|
|
36
|
+
const collectAssets = assetsPrefetcher !== undefined;
|
|
37
|
+
|
|
35
38
|
// 预处理把多行语句折叠进它的首行,并用占位行补齐被折叠掉的行,
|
|
36
39
|
// 因此这里的行数与原始场景严格一致,「语句 index == 文件行号」始终成立。
|
|
37
40
|
const rawSentenceList = sceneTextPreProcess(rawScene).split('\n'); // 原始句子列表
|
|
@@ -50,19 +53,32 @@ export const sceneParser = (
|
|
|
50
53
|
ADD_NEXT_ARG_LIST,
|
|
51
54
|
SCRIPT_CONFIG_MAP,
|
|
52
55
|
index,
|
|
56
|
+
collectAssets,
|
|
53
57
|
);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
if (!collectAssets) {
|
|
59
|
+
return returnSentence;
|
|
60
|
+
}
|
|
61
|
+
// 在这里解析出语句可能携带的资源和场景,合并到 assetsList 和 subSceneList。
|
|
62
|
+
// 必须就地追加:如果写成 [...assetsList, ...sentenceAssets],每条语句都要复制
|
|
63
|
+
// 一次已累积的列表,整体退化成 Θ(资源数²)——资源密集的场景脚本(几乎每条语句
|
|
64
|
+
// 都带 bg / figure / vocal)在数千条语句规模下会明显变慢。
|
|
65
|
+
for (const asset of returnSentence.sentenceAssets) {
|
|
66
|
+
assetsList.push(asset);
|
|
67
|
+
}
|
|
68
|
+
for (const subScene of returnSentence.subScene) {
|
|
69
|
+
subSceneList.push(subScene);
|
|
70
|
+
}
|
|
57
71
|
return returnSentence;
|
|
58
72
|
},
|
|
59
73
|
);
|
|
60
74
|
|
|
61
75
|
markMultilineRanges(sentenceList, rawSentenceList);
|
|
62
76
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
if (collectAssets) {
|
|
78
|
+
// 开始资源的预加载
|
|
79
|
+
assetsList = deduplicateAssets(assetsList);
|
|
80
|
+
assetsPrefetcher(assetsList);
|
|
81
|
+
}
|
|
66
82
|
|
|
67
83
|
return {
|
|
68
84
|
sceneName: sceneName, // 场景名称
|
|
@@ -41,7 +41,7 @@ export const assetsScanner = (
|
|
|
41
41
|
type: fileType.background,
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
|
-
if (command === commandType.changeFigure) {
|
|
44
|
+
if (command === commandType.changeFigure || command === commandType.changeFigureDiff) {
|
|
45
45
|
returnAssetsList.push({
|
|
46
46
|
name: content,
|
|
47
47
|
url: content,
|
|
@@ -22,6 +22,7 @@ export const contentParser = (
|
|
|
22
22
|
case commandType.changeBg:
|
|
23
23
|
return assetSetter(contentRaw, fileType.background);
|
|
24
24
|
case commandType.changeFigure:
|
|
25
|
+
case commandType.changeFigureDiff:
|
|
25
26
|
return assetSetter(contentRaw, fileType.figure);
|
|
26
27
|
case commandType.bgm:
|
|
27
28
|
return assetSetter(contentRaw, fileType.bgm);
|
|
@@ -18,6 +18,8 @@ import { ConfigMap } from '../config/scriptConfig';
|
|
|
18
18
|
* @param assetSetter
|
|
19
19
|
* @param ADD_NEXT_ARG_LIST
|
|
20
20
|
* @param SCRIPT_CONFIG_MAP
|
|
21
|
+
* @param lineNumber 语句所在行号
|
|
22
|
+
* @param collectAssets 是否扫描语句携带的资源与子场景;为 false 时两者都返回空数组
|
|
21
23
|
*/
|
|
22
24
|
export const scriptParser = (
|
|
23
25
|
sentenceRaw: string,
|
|
@@ -25,6 +27,7 @@ export const scriptParser = (
|
|
|
25
27
|
ADD_NEXT_ARG_LIST: commandType[],
|
|
26
28
|
SCRIPT_CONFIG_MAP: ConfigMap,
|
|
27
29
|
lineNumber = 0,
|
|
30
|
+
collectAssets = true,
|
|
28
31
|
): ISentence => {
|
|
29
32
|
let command: commandType; // 默认为对话
|
|
30
33
|
let content: string; // 语句内容
|
|
@@ -109,8 +112,8 @@ export const scriptParser = (
|
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
content = contentParser(newSentenceRaw.trim(), command, assetSetter); // 将语句内容里的文件名转为相对或绝对路径
|
|
112
|
-
sentenceAssets = assetsScanner(command, content, args, lineNumber); // 扫描语句携带资源
|
|
113
|
-
subScene = subSceneScanner(command, content); // 扫描语句携带子场景
|
|
115
|
+
sentenceAssets = collectAssets ? assetsScanner(command, content, args, lineNumber) : []; // 扫描语句携带资源
|
|
116
|
+
subScene = collectAssets ? subSceneScanner(command, content) : []; // 扫描语句携带子场景
|
|
114
117
|
return {
|
|
115
118
|
command: command, // 语句类型
|
|
116
119
|
commandRaw: commandRaw.trim(), // 命令原始内容,方便调试
|