rw-parser-ng 2.1.0 → 2.3.0
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/README.md +252 -52
- package/lib/codecs/bitmap.d.ts +6 -0
- package/lib/codecs/bitmap.js +77 -0
- package/lib/codecs/color.d.ts +6 -0
- package/lib/codecs/color.js +43 -0
- package/lib/codecs/dxt.d.ts +3 -0
- package/lib/codecs/dxt.js +212 -0
- package/lib/codecs/formats.d.ts +25 -0
- package/lib/codecs/formats.js +32 -0
- package/lib/codecs/index.d.ts +5 -0
- package/lib/codecs/index.js +21 -0
- package/lib/codecs/palette.d.ts +6 -0
- package/lib/codecs/palette.js +86 -0
- package/lib/common/types.d.ts +50 -0
- package/lib/common/types.js +2 -0
- package/lib/core/byte-stream.d.ts +20 -0
- package/lib/core/byte-stream.js +71 -0
- package/lib/core/errors.d.ts +5 -0
- package/lib/core/errors.js +34 -0
- package/lib/core/index.d.ts +5 -0
- package/lib/core/index.js +21 -0
- package/lib/core/rw-file.d.ts +9 -0
- package/lib/core/rw-file.js +36 -0
- package/lib/core/rw-sections.d.ts +24 -0
- package/lib/core/rw-sections.js +28 -0
- package/lib/core/rw-version.d.ts +3 -0
- package/lib/core/rw-version.js +27 -0
- package/lib/dff/dff-model-type.d.ts +5 -0
- package/lib/dff/dff-model-type.js +9 -0
- package/lib/dff/index.d.ts +4 -0
- package/lib/dff/index.js +20 -0
- package/lib/dff/parser.d.ts +5 -0
- package/lib/dff/parser.js +154 -0
- package/lib/dff/readers/2d-effect.d.ts +3 -0
- package/lib/dff/readers/2d-effect.js +211 -0
- package/lib/dff/readers/geometry.d.ts +4 -0
- package/lib/dff/readers/geometry.js +229 -0
- package/lib/dff/readers/index.d.ts +5 -0
- package/lib/dff/readers/index.js +21 -0
- package/lib/dff/readers/material.d.ts +5 -0
- package/lib/dff/readers/material.js +72 -0
- package/lib/dff/readers/mesh.d.ts +5 -0
- package/lib/dff/readers/mesh.js +84 -0
- package/lib/dff/readers/structure.d.ts +6 -0
- package/lib/dff/readers/structure.js +67 -0
- package/lib/dff/types.d.ts +237 -0
- package/lib/dff/types.js +44 -0
- package/lib/fxp/index.d.ts +2 -0
- package/lib/fxp/index.js +18 -0
- package/lib/fxp/info-parser.d.ts +2 -0
- package/lib/fxp/info-parser.js +169 -0
- package/lib/fxp/parser.d.ts +3 -0
- package/lib/fxp/parser.js +285 -0
- package/lib/fxp/types/common.d.ts +36 -0
- package/lib/fxp/types/common.js +2 -0
- package/lib/fxp/types/index.d.ts +3 -0
- package/lib/fxp/types/index.js +19 -0
- package/lib/fxp/types/info.d.ts +186 -0
- package/lib/fxp/types/info.js +2 -0
- package/lib/fxp/types/system.d.ts +27 -0
- package/lib/fxp/types/system.js +2 -0
- package/lib/ifp/index.d.ts +4 -0
- package/lib/ifp/index.js +20 -0
- package/lib/ifp/parser.d.ts +5 -0
- package/lib/ifp/parser.js +38 -0
- package/lib/ifp/readers/anp3.d.ts +3 -0
- package/lib/ifp/readers/anp3.js +56 -0
- package/lib/ifp/readers/anpk.d.ts +3 -0
- package/lib/ifp/readers/anpk.js +86 -0
- package/lib/ifp/types.d.ts +28 -0
- package/lib/ifp/types.js +9 -0
- package/lib/index.d.ts +6 -9
- package/lib/index.js +6 -13
- package/lib/renderware/fxp/FxpData.d.ts +246 -0
- package/lib/renderware/fxp/FxpData.js +2 -0
- package/lib/renderware/fxp/FxpParser.d.ts +3 -0
- package/lib/renderware/fxp/FxpParser.js +512 -0
- package/lib/renderware/fxp/index.d.ts +2 -0
- package/lib/renderware/fxp/index.js +18 -0
- package/lib/renderware/txd/TxdParser.js +3 -2
- package/lib/txd/bitmap-decoder.d.ts +3 -0
- package/lib/txd/bitmap-decoder.js +57 -0
- package/lib/txd/index.d.ts +3 -0
- package/lib/txd/index.js +19 -0
- package/lib/txd/parser.d.ts +8 -0
- package/lib/txd/parser.js +122 -0
- package/lib/txd/types.d.ts +27 -0
- package/lib/txd/types.js +2 -0
- package/package.json +16 -9
- package/src/codecs/bitmap.ts +75 -0
- package/src/codecs/color.ts +40 -0
- package/src/codecs/dxt.ts +243 -0
- package/src/codecs/formats.ts +28 -0
- package/src/codecs/index.ts +5 -0
- package/src/codecs/palette.ts +106 -0
- package/src/common/types.ts +59 -0
- package/src/core/byte-stream.ts +87 -0
- package/src/core/errors.ts +7 -0
- package/src/core/index.ts +5 -0
- package/src/core/rw-file.ts +23 -0
- package/src/core/rw-sections.ts +24 -0
- package/src/core/rw-version.ts +24 -0
- package/src/dff/dff-model-type.ts +5 -0
- package/src/dff/index.ts +4 -0
- package/src/dff/parser.ts +142 -0
- package/src/dff/readers/2d-effect.ts +265 -0
- package/src/dff/readers/geometry.ts +264 -0
- package/src/dff/readers/index.ts +5 -0
- package/src/dff/readers/material.ts +89 -0
- package/src/dff/readers/mesh.ts +93 -0
- package/src/dff/readers/structure.ts +79 -0
- package/src/dff/types.ts +278 -0
- package/src/fxp/index.ts +2 -0
- package/src/fxp/info-parser.ts +166 -0
- package/src/fxp/parser.ts +323 -0
- package/src/fxp/types/common.ts +23 -0
- package/src/fxp/types/index.ts +3 -0
- package/src/fxp/types/info.ts +251 -0
- package/src/fxp/types/system.ts +30 -0
- package/src/ifp/index.ts +4 -0
- package/src/ifp/parser.ts +16 -0
- package/src/ifp/readers/anp3.ts +75 -0
- package/src/ifp/readers/anpk.ts +110 -0
- package/src/ifp/types.ts +33 -0
- package/src/index.ts +6 -12
- package/src/txd/bitmap-decoder.ts +73 -0
- package/src/txd/index.ts +3 -0
- package/src/txd/parser.ts +148 -0
- package/src/txd/types.ts +29 -0
- package/src/renderware/RwFile.ts +0 -26
- package/src/renderware/RwSections.ts +0 -27
- package/src/renderware/common/types.ts +0 -59
- package/src/renderware/dff/DffModelType.ts +0 -5
- package/src/renderware/dff/DffParser.ts +0 -611
- package/src/renderware/errors/RwParseError.ts +0 -11
- package/src/renderware/ifp/IfpData.ts +0 -33
- package/src/renderware/ifp/IfpParser.ts +0 -203
- package/src/renderware/txd/TxdParser.ts +0 -234
- package/src/renderware/utils/ImageDecoder.ts +0 -571
- package/src/renderware/utils/ImageFormatEnums.ts +0 -28
- package/src/renderware/utils/RwVersion.ts +0 -28
- package/src/utils/ByteStream.ts +0 -80
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { parseInfo } from "./info-parser";
|
|
2
|
+
import type {
|
|
3
|
+
FxBoundingSphere,
|
|
4
|
+
FxEmitterBP,
|
|
5
|
+
FxInfo,
|
|
6
|
+
FxInterpData,
|
|
7
|
+
FxKeyframe,
|
|
8
|
+
FxMatrix,
|
|
9
|
+
FxProject,
|
|
10
|
+
FxSystemBP,
|
|
11
|
+
} from "./types";
|
|
12
|
+
|
|
13
|
+
const INFO_TYPE_MAP: Record<string, string> = {
|
|
14
|
+
"FX_INFO_EMRATE_DATA:": "emrate",
|
|
15
|
+
"FX_INFO_EMSIZE_DATA:": "emsize",
|
|
16
|
+
"FX_INFO_EMSPEED_DATA:": "emspeed",
|
|
17
|
+
"FX_INFO_EMDIR_DATA:": "emdir",
|
|
18
|
+
"FX_INFO_EMANGLE_DATA:": "emangle",
|
|
19
|
+
"FX_INFO_EMLIFE_DATA:": "emlife",
|
|
20
|
+
"FX_INFO_EMPOS_DATA:": "empos",
|
|
21
|
+
"FX_INFO_EMWEATHER_DATA:": "emweather",
|
|
22
|
+
"FX_INFO_EMROTATION_DATA:": "emrotation",
|
|
23
|
+
"FX_INFO_NOISE_DATA:": "noise",
|
|
24
|
+
"FX_INFO_FORCE_DATA:": "force",
|
|
25
|
+
"FX_INFO_FRICTION_DATA:": "friction",
|
|
26
|
+
"FX_INFO_ATTRACTPT_DATA:": "attractpt",
|
|
27
|
+
"FX_INFO_ATTRACTLINE_DATA:": "attractline",
|
|
28
|
+
"FX_INFO_GROUNDCOLLIDE_DATA:": "groundcollide",
|
|
29
|
+
"FX_INFO_WIND_DATA:": "wind",
|
|
30
|
+
"FX_INFO_JITTER_DATA:": "jitter",
|
|
31
|
+
"FX_INFO_ROTSPEED_DATA:": "rotspeed",
|
|
32
|
+
"FX_INFO_FLOAT_DATA:": "float",
|
|
33
|
+
"FX_INFO_UNDERWATER_DATA:": "underwater",
|
|
34
|
+
"FX_INFO_COLOUR_DATA:": "colour",
|
|
35
|
+
"FX_INFO_SIZE_DATA:": "size",
|
|
36
|
+
"FX_INFO_SPRITERECT_DATA:": "spriterect",
|
|
37
|
+
"FX_INFO_HEATHAZE_DATA:": "heathaze",
|
|
38
|
+
"FX_INFO_TRAIL_DATA:": "trail",
|
|
39
|
+
"FX_INFO_FLAT_DATA:": "flat",
|
|
40
|
+
"FX_INFO_DIR_DATA:": "dir",
|
|
41
|
+
"FX_INFO_ANIMTEX_DATA:": "animtex",
|
|
42
|
+
"FX_INFO_COLOURRANGE_DATA:": "colourrange",
|
|
43
|
+
"FX_INFO_SELFLIT_DATA:": "selflit",
|
|
44
|
+
"FX_INFO_COLOURBRIGHT_DATA:": "colourbright",
|
|
45
|
+
"FX_INFO_SMOKE_DATA:": "smoke",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
class FxpParserImpl {
|
|
49
|
+
private _lines: string[] = [];
|
|
50
|
+
private _pos = 0;
|
|
51
|
+
|
|
52
|
+
parse(content: string): FxProject {
|
|
53
|
+
this._lines = content.split("\n").map((l) => l.trim());
|
|
54
|
+
this._pos = 0;
|
|
55
|
+
|
|
56
|
+
const systems = new Map<string, FxSystemBP>();
|
|
57
|
+
this._expectLine("FX_PROJECT_DATA:");
|
|
58
|
+
|
|
59
|
+
while (this._pos < this._lines.length) {
|
|
60
|
+
const line = this._currentLine();
|
|
61
|
+
if (!line) {
|
|
62
|
+
this._pos++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (line === "FX_SYSTEM_DATA:") {
|
|
67
|
+
this._pos++;
|
|
68
|
+
this._skipEmpty();
|
|
69
|
+
const version = parseInt(this._currentLine(), 10);
|
|
70
|
+
this._pos++;
|
|
71
|
+
const system = this._parseSystem(version);
|
|
72
|
+
systems.set(system.name, system);
|
|
73
|
+
} else {
|
|
74
|
+
this._pos++;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return { systems };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private _parseSystem(version: number): FxSystemBP {
|
|
82
|
+
this._skipEmpty();
|
|
83
|
+
|
|
84
|
+
const filename = version > 100 ? this._readField("FILENAME:") : "";
|
|
85
|
+
const name = this._readField("NAME:");
|
|
86
|
+
const length = parseFloat(this._readField("LENGTH:"));
|
|
87
|
+
|
|
88
|
+
let loopIntervalMin = 0,
|
|
89
|
+
loopLength = 0;
|
|
90
|
+
if (version >= 106) {
|
|
91
|
+
loopIntervalMin = parseFloat(this._currentLine());
|
|
92
|
+
this._pos++;
|
|
93
|
+
loopLength = parseFloat(this._currentLine());
|
|
94
|
+
this._pos++;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const playMode = parseInt(this._readField("PLAYMODE:"), 10);
|
|
98
|
+
const cullDist = parseFloat(this._readField("CULLDIST:"));
|
|
99
|
+
|
|
100
|
+
let boundingSphere: FxBoundingSphere | null = null;
|
|
101
|
+
if (version > 103) {
|
|
102
|
+
const parts = this._readField("BOUNDINGSPHERE:").split(/\s+/).map(parseFloat);
|
|
103
|
+
boundingSphere = {
|
|
104
|
+
x: parts[0],
|
|
105
|
+
y: parts[1],
|
|
106
|
+
z: parts[2],
|
|
107
|
+
radius: parts[3],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const numPrims = parseInt(this._readField("NUM_PRIMS:"), 10);
|
|
112
|
+
const prims: FxEmitterBP[] = [];
|
|
113
|
+
|
|
114
|
+
for (let i = 0; i < numPrims; i++) {
|
|
115
|
+
this._skipEmpty();
|
|
116
|
+
if (this._currentLine() === "FX_PRIM_EMITTER_DATA:") {
|
|
117
|
+
this._pos++;
|
|
118
|
+
prims.push(this._parsePrimEmitter(version));
|
|
119
|
+
} else {
|
|
120
|
+
this._pos++;
|
|
121
|
+
i--;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (version >= 108) {
|
|
126
|
+
this._skipEmpty();
|
|
127
|
+
if (this._currentLine()?.startsWith("OMITTEXTURES:")) this._pos++;
|
|
128
|
+
}
|
|
129
|
+
if (version >= 109) {
|
|
130
|
+
this._skipEmpty();
|
|
131
|
+
if (this._currentLine()?.startsWith("TXDNAME:")) this._pos++;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
filename,
|
|
136
|
+
name,
|
|
137
|
+
length,
|
|
138
|
+
loopIntervalMin,
|
|
139
|
+
loopLength,
|
|
140
|
+
playMode,
|
|
141
|
+
cullDist,
|
|
142
|
+
boundingSphere,
|
|
143
|
+
prims,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private _parsePrimEmitter(version: number): FxEmitterBP {
|
|
148
|
+
this._skipEmpty();
|
|
149
|
+
this._expectLine("FX_PRIM_BASE_DATA:");
|
|
150
|
+
|
|
151
|
+
const name = this._readField("NAME:");
|
|
152
|
+
const matrix = this._parseMatrix();
|
|
153
|
+
|
|
154
|
+
const textures: (string | null)[] = [this._readNullableTexture("TEXTURE:")];
|
|
155
|
+
if (version > 101) {
|
|
156
|
+
textures.push(this._readNullableTexture("TEXTURE2:"));
|
|
157
|
+
textures.push(this._readNullableTexture("TEXTURE3:"));
|
|
158
|
+
textures.push(this._readNullableTexture("TEXTURE4:"));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const alphaOn = this._readField("ALPHAON:") === "1";
|
|
162
|
+
const srcBlendId = parseInt(this._readField("SRCBLENDID:"), 10);
|
|
163
|
+
const dstBlendId = parseInt(this._readField("DSTBLENDID:"), 10);
|
|
164
|
+
|
|
165
|
+
const numInfos = parseInt(this._readField("NUM_INFOS:"), 10);
|
|
166
|
+
const infos: FxInfo[] = [];
|
|
167
|
+
|
|
168
|
+
for (let i = 0; i < numInfos; i++) {
|
|
169
|
+
this._skipEmpty();
|
|
170
|
+
const infoType = this._currentLine();
|
|
171
|
+
this._pos++;
|
|
172
|
+
|
|
173
|
+
const typeKey = INFO_TYPE_MAP[infoType];
|
|
174
|
+
if (!typeKey) {
|
|
175
|
+
this._skipUnknownInfo();
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this._skipEmpty();
|
|
180
|
+
if (this._currentLine()?.startsWith("TIMEMODEPRT:")) this._pos++;
|
|
181
|
+
|
|
182
|
+
const interps =
|
|
183
|
+
typeKey === "underwater" || typeKey === "selflit" ? {} : this._parseAllInterps();
|
|
184
|
+
const info = parseInfo(typeKey, interps);
|
|
185
|
+
if (info) infos.push(info);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let lodStart = 0,
|
|
189
|
+
lodEnd = 0;
|
|
190
|
+
this._skipEmpty();
|
|
191
|
+
if (this._currentLine()?.startsWith("LODSTART:"))
|
|
192
|
+
lodStart = parseFloat(this._readField("LODSTART:"));
|
|
193
|
+
this._skipEmpty();
|
|
194
|
+
if (this._currentLine()?.startsWith("LODEND:")) lodEnd = parseFloat(this._readField("LODEND:"));
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
name,
|
|
198
|
+
matrix,
|
|
199
|
+
textures,
|
|
200
|
+
alphaOn,
|
|
201
|
+
srcBlendId,
|
|
202
|
+
dstBlendId,
|
|
203
|
+
lodStart,
|
|
204
|
+
lodEnd,
|
|
205
|
+
infos,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private _parseAllInterps(): Record<string, FxInterpData> {
|
|
210
|
+
const result: Record<string, FxInterpData> = {};
|
|
211
|
+
|
|
212
|
+
while (this._pos < this._lines.length) {
|
|
213
|
+
this._skipEmpty();
|
|
214
|
+
const line = this._currentLine();
|
|
215
|
+
if (this._isBlockEnd(line)) break;
|
|
216
|
+
|
|
217
|
+
if (line.endsWith(":") && !line.startsWith("FX_")) {
|
|
218
|
+
const fieldName = line.slice(0, -1).toUpperCase();
|
|
219
|
+
this._pos++;
|
|
220
|
+
this._skipEmpty();
|
|
221
|
+
if (this._currentLine() === "FX_INTERP_DATA:") {
|
|
222
|
+
result[fieldName] = this._parseInterpolation();
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
this._pos++;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private _isBlockEnd(line: string): boolean {
|
|
233
|
+
return (
|
|
234
|
+
!line ||
|
|
235
|
+
line.startsWith("FX_INFO_") ||
|
|
236
|
+
line.startsWith("LODSTART:") ||
|
|
237
|
+
line.startsWith("LODEND:") ||
|
|
238
|
+
line.startsWith("FX_PRIM_") ||
|
|
239
|
+
line.startsWith("FX_SYSTEM_DATA:") ||
|
|
240
|
+
line.startsWith("OMITTEXTURES:") ||
|
|
241
|
+
line.startsWith("TXDNAME:")
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private _parseInterpolation(): FxInterpData {
|
|
246
|
+
this._expectLine("FX_INTERP_DATA:");
|
|
247
|
+
const looped = this._readField("LOOPED:") === "1";
|
|
248
|
+
const numKeys = parseInt(this._readField("NUM_KEYS:"), 10);
|
|
249
|
+
|
|
250
|
+
const keys: FxKeyframe[] = [];
|
|
251
|
+
for (let i = 0; i < numKeys; i++) {
|
|
252
|
+
this._expectLine("FX_KEYFLOAT_DATA:");
|
|
253
|
+
keys.push({
|
|
254
|
+
time: parseFloat(this._readField("TIME:")),
|
|
255
|
+
value: parseFloat(this._readField("VAL:")),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return { looped, keys };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private _parseMatrix(): FxMatrix {
|
|
263
|
+
this._skipEmpty();
|
|
264
|
+
const line = this._currentLine();
|
|
265
|
+
if (!line?.startsWith("MATRIX:")) {
|
|
266
|
+
return {
|
|
267
|
+
right: { x: 1, y: 0, z: 0 },
|
|
268
|
+
up: { x: 0, y: 1, z: 0 },
|
|
269
|
+
at: { x: 0, y: 0, z: 1 },
|
|
270
|
+
pos: { x: 0, y: 0, z: 0 },
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const p = line.slice(7).trim().split(/\s+/).map(parseFloat);
|
|
275
|
+
this._pos++;
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
right: { x: p[0], y: p[1], z: p[2] },
|
|
279
|
+
up: { x: p[3], y: p[4], z: p[5] },
|
|
280
|
+
at: { x: p[6], y: p[7], z: p[8] },
|
|
281
|
+
pos: { x: p[9], y: p[10], z: p[11] },
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private _skipUnknownInfo(): void {
|
|
286
|
+
while (this._pos < this._lines.length && !this._isBlockEnd(this._currentLine())) this._pos++;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
private _readField(prefix: string): string {
|
|
290
|
+
this._skipEmpty();
|
|
291
|
+
const line = this._currentLine();
|
|
292
|
+
if (!line?.startsWith(prefix)) return "";
|
|
293
|
+
this._pos++;
|
|
294
|
+
return line.slice(prefix.length).trim();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private _readNullableTexture(prefix: string): string | null {
|
|
298
|
+
const val = this._readField(prefix);
|
|
299
|
+
return val === "NULL" || val === "" ? null : val;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private _expectLine(expected: string): void {
|
|
303
|
+
this._skipEmpty();
|
|
304
|
+
if (this._currentLine() === expected) this._pos++;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
private _skipEmpty(): void {
|
|
308
|
+
while (this._pos < this._lines.length && this._lines[this._pos].trim() === "") this._pos++;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private _currentLine(): string {
|
|
312
|
+
return this._lines[this._pos] ?? "";
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export function parseFxpContent(content: string): FxProject {
|
|
317
|
+
return new FxpParserImpl().parse(content);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function parseFxpFile(filePath: string): FxProject {
|
|
321
|
+
const fs = require("node:fs");
|
|
322
|
+
return parseFxpContent(fs.readFileSync(filePath, "utf-8"));
|
|
323
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface FxKeyframe {
|
|
2
|
+
time: number;
|
|
3
|
+
value: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface FxInterpData {
|
|
7
|
+
looped: boolean;
|
|
8
|
+
keys: FxKeyframe[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface FxMatrix {
|
|
12
|
+
right: { x: number; y: number; z: number };
|
|
13
|
+
up: { x: number; y: number; z: number };
|
|
14
|
+
at: { x: number; y: number; z: number };
|
|
15
|
+
pos: { x: number; y: number; z: number };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface FxBoundingSphere {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
z: number;
|
|
22
|
+
radius: number;
|
|
23
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import type { FxInterpData } from "./common";
|
|
2
|
+
|
|
3
|
+
export interface FxInfoEmRate {
|
|
4
|
+
type: "emrate";
|
|
5
|
+
rate: FxInterpData;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface FxInfoEmSize {
|
|
9
|
+
type: "emsize";
|
|
10
|
+
radius: FxInterpData;
|
|
11
|
+
sizeMinX: FxInterpData;
|
|
12
|
+
sizeMaxX: FxInterpData;
|
|
13
|
+
sizeMinY: FxInterpData;
|
|
14
|
+
sizeMaxY: FxInterpData;
|
|
15
|
+
sizeMinZ: FxInterpData;
|
|
16
|
+
sizeMaxZ: FxInterpData;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface FxInfoEmSpeed {
|
|
20
|
+
type: "emspeed";
|
|
21
|
+
speed: FxInterpData;
|
|
22
|
+
bias: FxInterpData;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface FxInfoEmDir {
|
|
26
|
+
type: "emdir";
|
|
27
|
+
dirX: FxInterpData;
|
|
28
|
+
dirY: FxInterpData;
|
|
29
|
+
dirZ: FxInterpData;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface FxInfoEmAngle {
|
|
33
|
+
type: "emangle";
|
|
34
|
+
min: FxInterpData;
|
|
35
|
+
max: FxInterpData;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface FxInfoEmLife {
|
|
39
|
+
type: "emlife";
|
|
40
|
+
life: FxInterpData;
|
|
41
|
+
bias: FxInterpData;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface FxInfoEmPos {
|
|
45
|
+
type: "empos";
|
|
46
|
+
x: FxInterpData;
|
|
47
|
+
y: FxInterpData;
|
|
48
|
+
z: FxInterpData;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface FxInfoEmWeather {
|
|
52
|
+
type: "emweather";
|
|
53
|
+
interp: FxInterpData;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface FxInfoEmRotation {
|
|
57
|
+
type: "emrotation";
|
|
58
|
+
min: FxInterpData;
|
|
59
|
+
max: FxInterpData;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface FxInfoNoise {
|
|
63
|
+
type: "noise";
|
|
64
|
+
x: FxInterpData;
|
|
65
|
+
y: FxInterpData;
|
|
66
|
+
z: FxInterpData;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface FxInfoForce {
|
|
70
|
+
type: "force";
|
|
71
|
+
forceX: FxInterpData;
|
|
72
|
+
forceY: FxInterpData;
|
|
73
|
+
forceZ: FxInterpData;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface FxInfoFriction {
|
|
77
|
+
type: "friction";
|
|
78
|
+
friction: FxInterpData;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface FxInfoAttractPt {
|
|
82
|
+
type: "attractpt";
|
|
83
|
+
x: FxInterpData;
|
|
84
|
+
y: FxInterpData;
|
|
85
|
+
z: FxInterpData;
|
|
86
|
+
power: FxInterpData;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface FxInfoAttractLine {
|
|
90
|
+
type: "attractline";
|
|
91
|
+
x1: FxInterpData;
|
|
92
|
+
y1: FxInterpData;
|
|
93
|
+
z1: FxInterpData;
|
|
94
|
+
x2: FxInterpData;
|
|
95
|
+
y2: FxInterpData;
|
|
96
|
+
z2: FxInterpData;
|
|
97
|
+
power: FxInterpData;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface FxInfoGroundCollide {
|
|
101
|
+
type: "groundcollide";
|
|
102
|
+
damping: FxInterpData;
|
|
103
|
+
bounce: FxInterpData;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface FxInfoWind {
|
|
107
|
+
type: "wind";
|
|
108
|
+
interp: FxInterpData;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface FxInfoJitter {
|
|
112
|
+
type: "jitter";
|
|
113
|
+
x: FxInterpData;
|
|
114
|
+
y: FxInterpData;
|
|
115
|
+
z: FxInterpData;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface FxInfoRotSpeed {
|
|
119
|
+
type: "rotspeed";
|
|
120
|
+
speed: FxInterpData;
|
|
121
|
+
speedBias: FxInterpData;
|
|
122
|
+
accel: FxInterpData;
|
|
123
|
+
accelBias: FxInterpData;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface FxInfoFloat {
|
|
127
|
+
type: "float";
|
|
128
|
+
interp: FxInterpData;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface FxInfoUnderwater {
|
|
132
|
+
type: "underwater";
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface FxInfoColour {
|
|
136
|
+
type: "colour";
|
|
137
|
+
red: FxInterpData;
|
|
138
|
+
green: FxInterpData;
|
|
139
|
+
blue: FxInterpData;
|
|
140
|
+
alpha: FxInterpData;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface FxInfoSize {
|
|
144
|
+
type: "size";
|
|
145
|
+
sizeX: FxInterpData;
|
|
146
|
+
sizeY: FxInterpData;
|
|
147
|
+
sizeXBias: FxInterpData;
|
|
148
|
+
sizeYBias: FxInterpData;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface FxInfoSpriteRect {
|
|
152
|
+
type: "spriterect";
|
|
153
|
+
interps: FxInterpData[];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface FxInfoHeatHaze {
|
|
157
|
+
type: "heathaze";
|
|
158
|
+
interps: FxInterpData[];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export interface FxInfoTrail {
|
|
162
|
+
type: "trail";
|
|
163
|
+
interps: FxInterpData[];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface FxInfoFlat {
|
|
167
|
+
type: "flat";
|
|
168
|
+
rightX: FxInterpData;
|
|
169
|
+
rightY: FxInterpData;
|
|
170
|
+
rightZ: FxInterpData;
|
|
171
|
+
upX: FxInterpData;
|
|
172
|
+
upY: FxInterpData;
|
|
173
|
+
upZ: FxInterpData;
|
|
174
|
+
atX: FxInterpData;
|
|
175
|
+
atY: FxInterpData;
|
|
176
|
+
atZ: FxInterpData;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface FxInfoDir {
|
|
180
|
+
type: "dir";
|
|
181
|
+
interps: FxInterpData[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface FxInfoAnimTexture {
|
|
185
|
+
type: "animtex";
|
|
186
|
+
interps: FxInterpData[];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface FxInfoColourRange {
|
|
190
|
+
type: "colourrange";
|
|
191
|
+
redMin: FxInterpData;
|
|
192
|
+
redMax: FxInterpData;
|
|
193
|
+
greenMin: FxInterpData;
|
|
194
|
+
greenMax: FxInterpData;
|
|
195
|
+
blueMin: FxInterpData;
|
|
196
|
+
blueMax: FxInterpData;
|
|
197
|
+
alphaMin: FxInterpData;
|
|
198
|
+
alphaMax: FxInterpData;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface FxInfoSelfLit {
|
|
202
|
+
type: "selflit";
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface FxInfoColourBright {
|
|
206
|
+
type: "colourbright";
|
|
207
|
+
red: FxInterpData;
|
|
208
|
+
green: FxInterpData;
|
|
209
|
+
blue: FxInterpData;
|
|
210
|
+
alpha: FxInterpData;
|
|
211
|
+
brightness: FxInterpData;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export interface FxInfoSmoke {
|
|
215
|
+
type: "smoke";
|
|
216
|
+
interps: FxInterpData[];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export type FxInfo =
|
|
220
|
+
| FxInfoEmRate
|
|
221
|
+
| FxInfoEmSize
|
|
222
|
+
| FxInfoEmSpeed
|
|
223
|
+
| FxInfoEmDir
|
|
224
|
+
| FxInfoEmAngle
|
|
225
|
+
| FxInfoEmLife
|
|
226
|
+
| FxInfoEmPos
|
|
227
|
+
| FxInfoEmWeather
|
|
228
|
+
| FxInfoEmRotation
|
|
229
|
+
| FxInfoNoise
|
|
230
|
+
| FxInfoForce
|
|
231
|
+
| FxInfoFriction
|
|
232
|
+
| FxInfoAttractPt
|
|
233
|
+
| FxInfoAttractLine
|
|
234
|
+
| FxInfoGroundCollide
|
|
235
|
+
| FxInfoWind
|
|
236
|
+
| FxInfoJitter
|
|
237
|
+
| FxInfoRotSpeed
|
|
238
|
+
| FxInfoFloat
|
|
239
|
+
| FxInfoUnderwater
|
|
240
|
+
| FxInfoColour
|
|
241
|
+
| FxInfoSize
|
|
242
|
+
| FxInfoSpriteRect
|
|
243
|
+
| FxInfoHeatHaze
|
|
244
|
+
| FxInfoTrail
|
|
245
|
+
| FxInfoFlat
|
|
246
|
+
| FxInfoDir
|
|
247
|
+
| FxInfoAnimTexture
|
|
248
|
+
| FxInfoColourRange
|
|
249
|
+
| FxInfoSelfLit
|
|
250
|
+
| FxInfoColourBright
|
|
251
|
+
| FxInfoSmoke;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { FxBoundingSphere, FxMatrix } from "./common";
|
|
2
|
+
import type { FxInfo } from "./info";
|
|
3
|
+
|
|
4
|
+
export interface FxEmitterBP {
|
|
5
|
+
name: string;
|
|
6
|
+
matrix: FxMatrix;
|
|
7
|
+
textures: (string | null)[];
|
|
8
|
+
alphaOn: boolean;
|
|
9
|
+
srcBlendId: number;
|
|
10
|
+
dstBlendId: number;
|
|
11
|
+
lodStart: number;
|
|
12
|
+
lodEnd: number;
|
|
13
|
+
infos: FxInfo[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface FxSystemBP {
|
|
17
|
+
filename: string;
|
|
18
|
+
name: string;
|
|
19
|
+
length: number;
|
|
20
|
+
loopIntervalMin: number;
|
|
21
|
+
loopLength: number;
|
|
22
|
+
playMode: number;
|
|
23
|
+
cullDist: number;
|
|
24
|
+
boundingSphere: FxBoundingSphere | null;
|
|
25
|
+
prims: FxEmitterBP[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface FxProject {
|
|
29
|
+
systems: Map<string, FxSystemBP>;
|
|
30
|
+
}
|
package/src/ifp/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { RwFile } from "../core/rw-file";
|
|
2
|
+
import { readAnp3 } from "./readers/anp3";
|
|
3
|
+
import { readAnpk } from "./readers/anpk";
|
|
4
|
+
import type { RwIfp } from "./types";
|
|
5
|
+
|
|
6
|
+
export class IfpParser extends RwFile {
|
|
7
|
+
public parse(): RwIfp {
|
|
8
|
+
const signature = this.readString(4);
|
|
9
|
+
this.setPosition(0);
|
|
10
|
+
|
|
11
|
+
if (signature === "ANP3") return readAnp3(this);
|
|
12
|
+
if (signature === "ANPK") return readAnpk(this);
|
|
13
|
+
|
|
14
|
+
throw new Error("Unsupported IFP version");
|
|
15
|
+
}
|
|
16
|
+
}
|