@gmvjs/xray-v1 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +71 -2
- package/dist/db.d.ts +12 -0
- package/dist/db.js +134 -0
- package/dist/db.js.map +1 -0
- package/dist/details.d.ts +42 -0
- package/dist/details.js +210 -0
- package/dist/details.js.map +1 -0
- package/dist/export.d.ts +38 -0
- package/dist/export.js +241 -0
- package/dist/export.js.map +1 -0
- package/dist/games/cop.d.ts +7 -0
- package/dist/games/cop.js +11 -0
- package/dist/games/cop.js.map +1 -0
- package/dist/games/cs.d.ts +7 -0
- package/dist/games/cs.js +11 -0
- package/dist/games/cs.js.map +1 -0
- package/dist/games/sdk.d.ts +7 -0
- package/dist/games/sdk.js +10 -0
- package/dist/games/sdk.js.map +1 -0
- package/dist/games/soc.d.ts +9 -0
- package/dist/games/soc.js +13 -0
- package/dist/games/soc.js.map +1 -0
- package/dist/i18n.d.ts +2 -0
- package/dist/i18n.js +48 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/level.d.ts +39 -0
- package/dist/level.js +234 -0
- package/dist/level.js.map +1 -0
- package/dist/load.d.ts +5 -0
- package/dist/load.js +126 -0
- package/dist/load.js.map +1 -0
- package/dist/lzhuf.d.ts +2 -0
- package/dist/lzhuf.js +136 -0
- package/dist/lzhuf.js.map +1 -0
- package/dist/motion.d.ts +28 -0
- package/dist/motion.js +20 -0
- package/dist/motion.js.map +1 -0
- package/dist/object.d.ts +138 -0
- package/dist/object.js +361 -0
- package/dist/object.js.map +1 -0
- package/dist/ogf.d.ts +93 -0
- package/dist/ogf.js +418 -0
- package/dist/ogf.js.map +1 -0
- package/dist/scene.d.ts +28 -0
- package/dist/scene.js +141 -0
- package/dist/scene.js.map +1 -0
- package/dist/skeleton.d.ts +34 -0
- package/dist/skeleton.js +252 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/smotion.d.ts +44 -0
- package/dist/smotion.js +283 -0
- package/dist/smotion.js.map +1 -0
- package/dist/soc-key.d.ts +18 -0
- package/dist/soc-key.js +125 -0
- package/dist/soc-key.js.map +1 -0
- package/dist/thm.d.ts +26 -0
- package/dist/thm.js +69 -0
- package/dist/thm.js.map +1 -0
- package/dist/write-object.d.ts +31 -0
- package/dist/write-object.js +228 -0
- package/dist/write-object.js.map +1 -0
- package/dist/write-omf.d.ts +47 -0
- package/dist/write-scene.d.ts +26 -0
- package/dist/write-scene.js +114 -0
- package/dist/write-scene.js.map +1 -0
- package/package.json +70 -4
package/dist/export.js
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { hasAlpha, encodeDdsRgba } from "@gmvjs/core/writers/dds";
|
|
2
|
+
import { visibleIndices } from "@gmvjs/core/scene";
|
|
3
|
+
import { writeThm } from "./thm.js";
|
|
4
|
+
import { writeObject } from "./write-object.js";
|
|
5
|
+
import { writeScene } from "./write-scene.js";
|
|
6
|
+
const clean = (s) => s.toLowerCase().replace(/\.[a-z0-9]+$/, "").replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "tex";
|
|
7
|
+
function toXray(model, mi, scale) {
|
|
8
|
+
const m = model.meshes[mi], n = m.vertexCount, sk = model.skeleton, pos = new Float32Array(n * 3), nor = new Float32Array(n * 3);
|
|
9
|
+
if (sk) sk.pose(null, 0, false);
|
|
10
|
+
for (let v = 0; v < n; v++) {
|
|
11
|
+
let x = m.pos[v * 3], y = m.pos[v * 3 + 1], z = m.pos[v * 3 + 2], a = m.nor[v * 3], b = m.nor[v * 3 + 1], c = m.nor[v * 3 + 2];
|
|
12
|
+
if (sk && m.skinned) {
|
|
13
|
+
let px = 0, py = 0, pz = 0, na = 0, nb = 0, nc = 0, ws = 0;
|
|
14
|
+
for (let k = 0; k < 4; k++) {
|
|
15
|
+
const w = m.weight[v * 4 + k];
|
|
16
|
+
if (!w) continue;
|
|
17
|
+
const M = sk.skinV[m.bone[v * 4 + k]];
|
|
18
|
+
ws += w;
|
|
19
|
+
px += w * (x * M[0] + y * M[4] + z * M[8] + M[12]);
|
|
20
|
+
py += w * (x * M[1] + y * M[5] + z * M[9] + M[13]);
|
|
21
|
+
pz += w * (x * M[2] + y * M[6] + z * M[10] + M[14]);
|
|
22
|
+
na += w * (a * M[0] + b * M[4] + c * M[8]);
|
|
23
|
+
nb += w * (a * M[1] + b * M[5] + c * M[9]);
|
|
24
|
+
nc += w * (a * M[2] + b * M[6] + c * M[10]);
|
|
25
|
+
}
|
|
26
|
+
if (ws) {
|
|
27
|
+
x = px;
|
|
28
|
+
y = py;
|
|
29
|
+
z = pz;
|
|
30
|
+
a = na;
|
|
31
|
+
b = nb;
|
|
32
|
+
c = nc;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (model.defaultZUp) {
|
|
36
|
+
[y, z] = [z, -y];
|
|
37
|
+
[b, c] = [c, -b];
|
|
38
|
+
}
|
|
39
|
+
if (!model.flipZ) {
|
|
40
|
+
z = -z;
|
|
41
|
+
c = -c;
|
|
42
|
+
}
|
|
43
|
+
const l = Math.hypot(a, b, c) || 1;
|
|
44
|
+
pos[v * 3] = x * scale;
|
|
45
|
+
pos[v * 3 + 1] = y * scale;
|
|
46
|
+
pos[v * 3 + 2] = z * scale;
|
|
47
|
+
nor[v * 3] = a / l;
|
|
48
|
+
nor[v * 3 + 1] = b / l;
|
|
49
|
+
nor[v * 3 + 2] = c / l;
|
|
50
|
+
}
|
|
51
|
+
const indices = visibleIndices(model, mi);
|
|
52
|
+
if (!model.flipZ) for (let t = 0; t + 2 < indices.length; t += 3) {
|
|
53
|
+
const q = indices[t + 1];
|
|
54
|
+
indices[t + 1] = indices[t + 2];
|
|
55
|
+
indices[t + 2] = q;
|
|
56
|
+
}
|
|
57
|
+
return { pos, nor, indices };
|
|
58
|
+
}
|
|
59
|
+
async function exportXraySdk(model, o) {
|
|
60
|
+
const name = clean(o.name), prefix = (o.prefix ?? `gmv\\${name}`).replace(/\//g, "\\").replace(/\\+$/, ""), scale = o.scale ?? 1;
|
|
61
|
+
const files = /* @__PURE__ */ new Map(), report = [];
|
|
62
|
+
const inst = o.instances !== false && model.instances && model.flipZ && !model.defaultZUp ? model.instances : null;
|
|
63
|
+
const instMeshes = new Set(inst?.meshes ?? []);
|
|
64
|
+
const meshIdx = model.meshes.map((_, i) => i).filter((i) => !o.hidden?.has(i) && model.meshes[i].indices.length >= 3);
|
|
65
|
+
const geo = new Map(meshIdx.filter((i) => !instMeshes.has(i)).map((i) => [i, toXray(model, i, scale)]));
|
|
66
|
+
const lo = [Infinity, Infinity, Infinity], hi = [-Infinity, -Infinity, -Infinity];
|
|
67
|
+
for (const g of geo.values()) for (let i = 0; i < g.pos.length; i++) {
|
|
68
|
+
lo[i % 3] = Math.min(lo[i % 3], g.pos[i]);
|
|
69
|
+
hi[i % 3] = Math.max(hi[i % 3], g.pos[i]);
|
|
70
|
+
}
|
|
71
|
+
const extent = Math.max(hi[0] - lo[0], hi[2] - lo[2]);
|
|
72
|
+
const triCount = [...geo.values()].reduce((a, g) => a + g.indices.length / 3, 0);
|
|
73
|
+
const cell = o.cell ?? (extent > 400 ? 64 : extent > 100 || triCount > 6e4 ? 32 : 0);
|
|
74
|
+
const surfaces = [], surfOfMesh = /* @__PURE__ */ new Map(), texOut = /* @__PURE__ */ new Map();
|
|
75
|
+
let copied = 0, encoded = 0, missingTex = 0;
|
|
76
|
+
for (const i of meshIdx) {
|
|
77
|
+
const m = model.meshes[i], key = m.texture || `mesh_${i}`;
|
|
78
|
+
if (o.xraySource) {
|
|
79
|
+
const sk = `${m.texture}|${m.shader ?? ""}|${m.material ?? ""}`;
|
|
80
|
+
let si = surfaces.findIndex((x) => `${x.texture}|${x.eshader}|${x.gamemtl}` === sk);
|
|
81
|
+
if (si < 0) si = surfaces.push({ name: `${clean(m.texture.split("\\").pop() ?? "s")}_${surfaces.length}`, texture: m.texture, eshader: m.shader || "default", gamemtl: m.material || "default" }) - 1;
|
|
82
|
+
surfOfMesh.set(i, si);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
let xname = texOut.get(key);
|
|
86
|
+
if (!xname) {
|
|
87
|
+
const base = clean(key.split(/[\\/]/).pop() ?? key);
|
|
88
|
+
let cand = base, k = 1;
|
|
89
|
+
while ([...texOut.values()].includes(`${prefix}\\${cand}`)) cand = `${base}_${k++}`;
|
|
90
|
+
xname = `${prefix}\\${cand}`;
|
|
91
|
+
texOut.set(key, xname);
|
|
92
|
+
const t = o.texture ? await o.texture(i).catch(() => null) : null;
|
|
93
|
+
const path = `gamedata/textures/${xname.replace(/\\/g, "/")}`;
|
|
94
|
+
if (t?.dds && t.dds.length > 128) {
|
|
95
|
+
files.set(`${path}.dds`, t.dds);
|
|
96
|
+
const dv = new DataView(t.dds.buffer, t.dds.byteOffset), fourcc = String.fromCharCode(t.dds[84], t.dds[85], t.dds[86], t.dds[87]);
|
|
97
|
+
files.set(`${path}.thm`, writeThm({ width: dv.getUint32(16, true), height: dv.getUint32(12, true), alpha: fourcc !== "DXT1" }));
|
|
98
|
+
copied++;
|
|
99
|
+
} else if (t?.image?.rgba) {
|
|
100
|
+
const a = hasAlpha(t.image);
|
|
101
|
+
files.set(`${path}.dds`, encodeDdsRgba({ width: t.image.width, height: t.image.height, rgba: t.image.rgba }));
|
|
102
|
+
files.set(`${path}.thm`, writeThm({ width: t.image.width, height: t.image.height, alpha: a }));
|
|
103
|
+
encoded++;
|
|
104
|
+
} else missingTex++;
|
|
105
|
+
surfaces.push({ name: cand, texture: xname });
|
|
106
|
+
}
|
|
107
|
+
surfOfMesh.set(i, surfaces.findIndex((s) => s.texture === xname));
|
|
108
|
+
}
|
|
109
|
+
const cells = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const [i, g] of geo) {
|
|
111
|
+
for (let t = 0; t + 2 < g.indices.length; t += 3) {
|
|
112
|
+
let key = "all";
|
|
113
|
+
if (cell > 0) {
|
|
114
|
+
const a = g.indices[t] * 3, b = g.indices[t + 1] * 3, c = g.indices[t + 2] * 3;
|
|
115
|
+
const cx = (g.pos[a] + g.pos[b] + g.pos[c]) / 3, cz = (g.pos[a + 2] + g.pos[b + 2] + g.pos[c + 2]) / 3;
|
|
116
|
+
key = `${Math.floor((cx - lo[0]) / cell)}_${Math.floor((cz - lo[2]) / cell)}`;
|
|
117
|
+
}
|
|
118
|
+
const byMesh = cells.get(key) ?? cells.set(key, /* @__PURE__ */ new Map()).get(key);
|
|
119
|
+
(byMesh.get(i) ?? byMesh.set(i, []).get(i)).push(t);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const objects = [];
|
|
123
|
+
let tris = 0;
|
|
124
|
+
for (const [key, byMesh] of cells) {
|
|
125
|
+
const meshes = [];
|
|
126
|
+
for (const [i, list] of byMesh) {
|
|
127
|
+
const g = geo.get(i), src = model.meshes[i], remap = /* @__PURE__ */ new Map(), pos = [], nor = [], uv = [], idx = [];
|
|
128
|
+
for (const t of list) for (let k = 0; k < 3; k++) {
|
|
129
|
+
const v = g.indices[t + k];
|
|
130
|
+
let r = remap.get(v);
|
|
131
|
+
if (r === void 0) {
|
|
132
|
+
r = pos.length / 3;
|
|
133
|
+
remap.set(v, r);
|
|
134
|
+
pos.push(g.pos[v * 3], g.pos[v * 3 + 1], g.pos[v * 3 + 2]);
|
|
135
|
+
nor.push(g.nor[v * 3], g.nor[v * 3 + 1], g.nor[v * 3 + 2]);
|
|
136
|
+
uv.push(src.uv[v * 2], src.uv[v * 2 + 1]);
|
|
137
|
+
}
|
|
138
|
+
idx.push(r);
|
|
139
|
+
}
|
|
140
|
+
tris += list.length;
|
|
141
|
+
meshes.push({ name: clean(src.name || `mesh_${i}`), pos, nor, uv, indices: idx, surface: surfOfMesh.get(i) });
|
|
142
|
+
}
|
|
143
|
+
const oname = cell > 0 ? `${name}_${key}` : name, reference = `${prefix}\\${oname}`;
|
|
144
|
+
const used = [...new Set(meshes.map((m) => m.surface))], local = new Map(used.map((s, k) => [s, k]));
|
|
145
|
+
for (const m of meshes) m.surface = local.get(m.surface);
|
|
146
|
+
files.set(`rawdata/objects/${reference.replace(/\\/g, "/")}.object`, writeObject({ meshes, surfaces: used.map((s) => surfaces[s]) }));
|
|
147
|
+
objects.push({ name: oname, reference });
|
|
148
|
+
}
|
|
149
|
+
const scene = objects.map((x) => ({ ...x, position: [0, 0, 0] }));
|
|
150
|
+
let instTris = 0, protoCount = 0, mirrored = 0;
|
|
151
|
+
if (inst) {
|
|
152
|
+
const protoRef = /* @__PURE__ */ new Map(), used = new Set(inst.placements.map((p) => p.proto)), mirrorMeshes = [];
|
|
153
|
+
const names = /* @__PURE__ */ new Set();
|
|
154
|
+
const meshesOf = (pi, M) => inst.protos[pi].parts.filter((pt) => !o.hidden?.has(pt.mesh) && surfOfMesh.has(pt.mesh) && pt.indices.length >= 3).map((pt, k) => {
|
|
155
|
+
const n = pt.pos.length / 3, pos = [], nor = [];
|
|
156
|
+
for (let v = 0; v < n; v++) {
|
|
157
|
+
let x = pt.pos[v * 3], y = pt.pos[v * 3 + 1], z = pt.pos[v * 3 + 2], a = pt.nor[v * 3], b = pt.nor[v * 3 + 1], c = pt.nor[v * 3 + 2];
|
|
158
|
+
if (M) {
|
|
159
|
+
[x, y, z] = [x * M[0] + y * M[4] + z * M[8] + M[12], x * M[1] + y * M[5] + z * M[9] + M[13], x * M[2] + y * M[6] + z * M[10] + M[14]];
|
|
160
|
+
[a, b, c] = [a * M[0] + b * M[4] + c * M[8], a * M[1] + b * M[5] + c * M[9], a * M[2] + b * M[6] + c * M[10]];
|
|
161
|
+
const l = Math.hypot(a, b, c) || 1;
|
|
162
|
+
a /= l;
|
|
163
|
+
b /= l;
|
|
164
|
+
c /= l;
|
|
165
|
+
}
|
|
166
|
+
pos.push(x * scale, y * scale, z * scale);
|
|
167
|
+
nor.push(a, b, c);
|
|
168
|
+
}
|
|
169
|
+
const indices = Array.from(pt.indices);
|
|
170
|
+
if (M) for (let t = 0; t + 2 < indices.length; t += 3) {
|
|
171
|
+
const q = indices[t + 1];
|
|
172
|
+
indices[t + 1] = indices[t + 2];
|
|
173
|
+
indices[t + 2] = q;
|
|
174
|
+
}
|
|
175
|
+
return { name: `part_${k}`, pos, nor, uv: pt.uv, indices, surface: surfOfMesh.get(pt.mesh) };
|
|
176
|
+
});
|
|
177
|
+
const writeWith = (reference, meshes) => {
|
|
178
|
+
const usedS = [...new Set(meshes.map((m) => m.surface))], local = new Map(usedS.map((x, k) => [x, k]));
|
|
179
|
+
for (const m of meshes) m.surface = local.get(m.surface);
|
|
180
|
+
files.set(`rawdata/objects/${reference.replace(/\\/g, "/")}.object`, writeObject({ meshes, surfaces: usedS.map((x) => surfaces[x]) }));
|
|
181
|
+
};
|
|
182
|
+
for (const pl of inst.placements) {
|
|
183
|
+
if (!used.has(pl.proto) || pl.hidden) continue;
|
|
184
|
+
const M = pl.pose, R = [M[0], M[1], M[2], M[4], M[5], M[6], M[8], M[9], M[10]];
|
|
185
|
+
const sc = [Math.hypot(R[0], R[1], R[2]), Math.hypot(R[3], R[4], R[5]), Math.hypot(R[6], R[7], R[8])];
|
|
186
|
+
const det = R[0] * (R[4] * R[8] - R[5] * R[7]) - R[1] * (R[3] * R[8] - R[5] * R[6]) + R[2] * (R[3] * R[7] - R[4] * R[6]);
|
|
187
|
+
if (det < 0) {
|
|
188
|
+
const ms = meshesOf(pl.proto, M);
|
|
189
|
+
mirrorMeshes.push(...ms);
|
|
190
|
+
mirrored++;
|
|
191
|
+
for (const m of ms) instTris += m.indices.length / 3;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
let ref = protoRef.get(pl.proto);
|
|
195
|
+
if (ref === void 0) {
|
|
196
|
+
const ms = meshesOf(pl.proto, null);
|
|
197
|
+
if (!ms.length) {
|
|
198
|
+
protoRef.set(pl.proto, "");
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
let base = clean(inst.protos[pl.proto].name.split(/[\\/]/).pop() ?? "obj"), cand = base, k = 1;
|
|
202
|
+
while (names.has(cand)) cand = `${base}_${k++}`;
|
|
203
|
+
names.add(cand);
|
|
204
|
+
ref = `${prefix}\\props\\${cand}`;
|
|
205
|
+
writeWith(ref, ms);
|
|
206
|
+
protoRef.set(pl.proto, ref);
|
|
207
|
+
protoCount++;
|
|
208
|
+
}
|
|
209
|
+
if (!ref) continue;
|
|
210
|
+
for (const pt of inst.protos[pl.proto].parts) instTris += pt.indices.length / 3;
|
|
211
|
+
let nm = clean(pl.name), j = 1;
|
|
212
|
+
while (names.has(nm)) nm = `${clean(pl.name)}_${j++}`;
|
|
213
|
+
names.add(nm);
|
|
214
|
+
scene.push({ name: nm, reference: ref, position: [M[12] * scale, M[13] * scale, M[14] * scale], matrix: R.map((v, i) => v / sc[Math.floor(i / 3)]), scale: sc });
|
|
215
|
+
}
|
|
216
|
+
if (mirrorMeshes.length) {
|
|
217
|
+
const ref = `${prefix}\\${name}_mirrored`;
|
|
218
|
+
writeWith(ref, mirrorMeshes);
|
|
219
|
+
scene.push({ name: `${name}_mirrored`, reference: ref, position: [0, 0, 0] });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const [path, data] of writeScene({ name, objects: scene })) files.set(`rawdata/levels/${path}`, data);
|
|
223
|
+
report.push(
|
|
224
|
+
`Объектов .object: ${objects.length}${cell > 0 ? ` (ячейки ${cell} м)` : ""}, треугольников: ${tris}, размер сцены: ${(hi[0] - lo[0]).toFixed(1)} × ${(hi[1] - lo[1]).toFixed(1)} × ${(hi[2] - lo[2]).toFixed(1)} м`,
|
|
225
|
+
...inst ? [`Объекты уровня: ${inst.placements.length} экземпляров, ${protoCount} моделей в ${prefix}\\props (треугольников ${instTris})${mirrored ? `; зеркальных ${mirrored} — влиты в ${name}_mirrored` : ""}`] : [],
|
|
226
|
+
o.xraySource ? `Текстуры, шейдеры и материалы — игровые (${surfaces.length} поверхностей), файлы текстур не копируются` : `Текстуры: ${copied} DDS скопировано, ${encoded} перекодировано в DDS без сжатия${missingTex ? `, ${missingTex} не найдено (объект ссылается на имя, файл положите сами)` : ""}`,
|
|
227
|
+
`Сцена: rawdata/levels/${name}.level — откройте в LevelEditor, добавьте свет, секторы/порталы и спавн, затем соберите xrLC.`
|
|
228
|
+
);
|
|
229
|
+
if (!o.xraySource) {
|
|
230
|
+
report.push("Шейдеры поверхностей — «default», материал — «default»: настройте в редакторе (стекло, листва, двусторонние грани).");
|
|
231
|
+
const mats = [...new Set(meshIdx.map((i) => model.meshes[i].material).filter((x) => !!x))];
|
|
232
|
+
if (mats.length) report.push(`Материалы исходника (для настройки game material): ${mats.slice(0, 30).join(", ")}${mats.length > 30 ? "…" : ""}`);
|
|
233
|
+
}
|
|
234
|
+
if (model.skeleton) report.push("Скелетная модель выгружена в bind-позе как статика (кости и анимации в .object пока не пишутся).");
|
|
235
|
+
if (!model.flipZ) report.push("Координаты переведены в левостороннюю систему X-Ray (Z отражён, обход граней развёрнут).");
|
|
236
|
+
return { files, report };
|
|
237
|
+
}
|
|
238
|
+
export {
|
|
239
|
+
exportXraySdk
|
|
240
|
+
};
|
|
241
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sources":["../src/export.ts"],"sourcesContent":["// Выгрузка любой загруженной модели или уровня в исходники X-Ray SDK (ЗП, SDK 0.7):\n// rawdata/objects/<префикс>/<имя>_<ячейка>.object — геометрия, разбитая на ячейки сетки (для больших карт);\n// rawdata/levels/<имя>.level + <имя>/scene_object.part — сцена с этими объектами;\n// gamedata/textures/<префикс>/<текстура>.dds + .thm — текстуры (DDS копируется как есть, остальное — без сжатия).\n// Дальше: LevelEditor → свет, секторы/порталы, спавн → сборка xrLC/xrAI/xrDO.\nimport { encodeDdsRgba, hasAlpha } from '@gmvjs/core/writers/dds';\nimport type { DecodedImage, Model } from '@gmvjs/core/types';\nimport { visibleIndices } from '@gmvjs/core/scene';\nimport { writeThm } from './thm';\nimport { writeObject, type ObjectMeshIn, type ObjectSurfaceIn } from './write-object';\nimport { writeScene, type SceneObjectOut } from './write-scene';\n\nexport interface TextureForExport {\n /** Имя исходной текстуры (для имени файла). */\n name: string;\n /** Исходный DDS — копируется без перекодирования. */\n dds?: Uint8Array;\n /** Иначе — декодированная картинка. */\n image?: DecodedImage | null;\n}\n\nexport interface XrayExportOptions {\n /** Имя уровня/объекта: латиница, цифры, «_». */\n name: string;\n /** Папка внутри rawdata/objects и gamedata/textures. По умолчанию «gmv\\\\<имя>». */\n prefix?: string;\n /** Множитель единиц в метры (X-Ray: 1 = 1 м). */\n scale?: number;\n /** Размер ячейки разбиения, м; 0 — один объект. По умолчанию: 0 для моделей, 32 м для сцен больше 100 м или 60 тыс. треугольников, 64 м — больше 400 м. */\n cell?: number;\n /** Текстура меша по номеру (из сессии просмотра). */\n texture?: (meshIndex: number) => Promise<TextureForExport | null>;\n /** Скрытые меши не выгружаются. */\n hidden?: ReadonlySet<number>;\n /**\n * Объекты уровня (model.instances): true (по умолчанию) — каждая модель одним .object в «<префикс>\\\\props», в сцене — ссылки с позами;\n * false — объекты вливаются в геометрию ячеек.\n */\n instances?: boolean;\n /**\n * Источник — сам X-Ray (скомпилированный уровень, OGF, .object): имена текстур, шейдеры и материалы остаются игровыми,\n * текстуры не копируются (они уже есть в gamedata).\n */\n xraySource?: boolean;\n}\n\nexport interface XrayExportResult { files: Map<string, Uint8Array>; report: string[] }\n\nconst clean = (s: string) => s.toLowerCase().replace(/\\.[a-z0-9]+$/, '').replace(/[^a-z0-9_]+/g, '_').replace(/^_+|_+$/g, '') || 'tex';\n\n/** Вершины меша в координатах X-Ray: поза bind, Z-вверх -> Y-вверх, правые -> левые (с разворотом обхода), масштаб. */\nfunction toXray(model: Model, mi: number, scale: number): { pos: Float32Array; nor: Float32Array; indices: Uint32Array } {\n const m = model.meshes[mi]!, n = m.vertexCount, sk = model.skeleton, pos = new Float32Array(n * 3), nor = new Float32Array(n * 3);\n if (sk) sk.pose(null, 0, false);\n for (let v = 0; v < n; v++) {\n let x = m.pos[v * 3]!, y = m.pos[v * 3 + 1]!, z = m.pos[v * 3 + 2]!, a = m.nor[v * 3]!, b = m.nor[v * 3 + 1]!, c = m.nor[v * 3 + 2]!;\n if (sk && m.skinned) {\n let px = 0, py = 0, pz = 0, na = 0, nb = 0, nc = 0, ws = 0;\n for (let k = 0; k < 4; k++) {\n const w = m.weight[v * 4 + k]!;\n if (!w) continue;\n const M = sk.skinV[m.bone[v * 4 + k]!]!;\n ws += w;\n px += w * (x * M[0]! + y * M[4]! + z * M[8]! + M[12]!); py += w * (x * M[1]! + y * M[5]! + z * M[9]! + M[13]!); pz += w * (x * M[2]! + y * M[6]! + z * M[10]! + M[14]!);\n na += w * (a * M[0]! + b * M[4]! + c * M[8]!); nb += w * (a * M[1]! + b * M[5]! + c * M[9]!); nc += w * (a * M[2]! + b * M[6]! + c * M[10]!);\n }\n if (ws) { x = px; y = py; z = pz; a = na; b = nb; c = nc; }\n }\n if (model.defaultZUp) { [y, z] = [z, -y]; [b, c] = [c, -b]; }\n if (!model.flipZ) { z = -z; c = -c; }\n const l = Math.hypot(a, b, c) || 1;\n pos[v * 3] = x * scale; pos[v * 3 + 1] = y * scale; pos[v * 3 + 2] = z * scale;\n nor[v * 3] = a / l; nor[v * 3 + 1] = b / l; nor[v * 3 + 2] = c / l;\n }\n const indices = visibleIndices(model, mi);\n // отражение меняет обход: внешняя нормаль X-Ray = (b − a) × (c − a)\n if (!model.flipZ) for (let t = 0; t + 2 < indices.length; t += 3) { const q = indices[t + 1]!; indices[t + 1] = indices[t + 2]!; indices[t + 2] = q; }\n return { pos, nor, indices };\n}\n\nexport async function exportXraySdk(model: Model, o: XrayExportOptions): Promise<XrayExportResult> {\n const name = clean(o.name), prefix = (o.prefix ?? `gmv\\\\${name}`).replace(/\\//g, '\\\\').replace(/\\\\+$/, ''), scale = o.scale ?? 1;\n const files = new Map<string, Uint8Array>(), report: string[] = [];\n const inst = o.instances !== false && model.instances && model.flipZ && !model.defaultZUp ? model.instances : null;\n const instMeshes = new Set(inst?.meshes ?? []);\n const meshIdx = model.meshes.map((_, i) => i).filter((i) => !o.hidden?.has(i) && model.meshes[i]!.indices.length >= 3);\n const geo = new Map(meshIdx.filter((i) => !instMeshes.has(i)).map((i) => [i, toXray(model, i, scale)]));\n // размер сцены -> ячейка\n const lo = [Infinity, Infinity, Infinity], hi = [-Infinity, -Infinity, -Infinity];\n for (const g of geo.values()) for (let i = 0; i < g.pos.length; i++) { lo[i % 3] = Math.min(lo[i % 3]!, g.pos[i]!); hi[i % 3] = Math.max(hi[i % 3]!, g.pos[i]!); }\n const extent = Math.max(hi[0]! - lo[0]!, hi[2]! - lo[2]!);\n // авто: большие сцены режутся на ячейки, чтобы объекты в LevelEditor оставались удобными\n const triCount = [...geo.values()].reduce((a, g) => a + g.indices.length / 3, 0);\n const cell = o.cell ?? (extent > 400 ? 64 : extent > 100 || triCount > 60000 ? 32 : 0);\n\n // текстуры и поверхности: одна поверхность на текстуру (+ двусторонность по названию шейдера не угадываем)\n const surfaces: ObjectSurfaceIn[] = [], surfOfMesh = new Map<number, number>(), texOut = new Map<string, string>();\n let copied = 0, encoded = 0, missingTex = 0;\n for (const i of meshIdx) {\n const m = model.meshes[i]!, key = m.texture || `mesh_${i}`;\n if (o.xraySource) {\n // игровые имена: поверхность на сочетание текстуры, шейдера и материала\n const sk = `${m.texture}|${m.shader ?? ''}|${m.material ?? ''}`;\n let si = surfaces.findIndex((x) => `${x.texture}|${x.eshader}|${x.gamemtl}` === sk);\n if (si < 0) si = surfaces.push({ name: `${clean(m.texture.split('\\\\').pop() ?? 's')}_${surfaces.length}`, texture: m.texture, eshader: m.shader || 'default', gamemtl: m.material || 'default' }) - 1;\n surfOfMesh.set(i, si);\n continue;\n }\n let xname = texOut.get(key);\n if (!xname) {\n const base = clean(key.split(/[\\\\/]/).pop() ?? key);\n let cand = base, k = 1;\n while ([...texOut.values()].includes(`${prefix}\\\\${cand}`)) cand = `${base}_${k++}`;\n xname = `${prefix}\\\\${cand}`;\n texOut.set(key, xname);\n const t = o.texture ? await o.texture(i).catch(() => null) : null;\n const path = `gamedata/textures/${xname.replace(/\\\\/g, '/')}`;\n if (t?.dds && t.dds.length > 128) {\n files.set(`${path}.dds`, t.dds);\n const dv = new DataView(t.dds.buffer, t.dds.byteOffset), fourcc = String.fromCharCode(t.dds[84]!, t.dds[85]!, t.dds[86]!, t.dds[87]!);\n files.set(`${path}.thm`, writeThm({ width: dv.getUint32(16, true), height: dv.getUint32(12, true), alpha: fourcc !== 'DXT1' }));\n copied++;\n } else if (t?.image?.rgba) {\n const a = hasAlpha(t.image);\n files.set(`${path}.dds`, encodeDdsRgba({ width: t.image.width, height: t.image.height, rgba: t.image.rgba }));\n files.set(`${path}.thm`, writeThm({ width: t.image.width, height: t.image.height, alpha: a }));\n encoded++;\n } else missingTex++;\n surfaces.push({ name: cand, texture: xname });\n }\n surfOfMesh.set(i, surfaces.findIndex((s) => s.texture === xname));\n }\n\n // ячейки: треугольник относится к ячейке своего центра\n const cells = new Map<string, Map<number, number[]>>();\n for (const [i, g] of geo) {\n for (let t = 0; t + 2 < g.indices.length; t += 3) {\n let key = 'all';\n if (cell > 0) {\n const a = g.indices[t]! * 3, b = g.indices[t + 1]! * 3, c = g.indices[t + 2]! * 3;\n const cx = (g.pos[a]! + g.pos[b]! + g.pos[c]!) / 3, cz = (g.pos[a + 2]! + g.pos[b + 2]! + g.pos[c + 2]!) / 3;\n key = `${Math.floor((cx - lo[0]!) / cell)}_${Math.floor((cz - lo[2]!) / cell)}`;\n }\n const byMesh = cells.get(key) ?? cells.set(key, new Map()).get(key)!;\n (byMesh.get(i) ?? byMesh.set(i, []).get(i)!).push(t);\n }\n }\n const objects: Array<{ name: string; reference: string }> = [];\n let tris = 0;\n for (const [key, byMesh] of cells) {\n const meshes: ObjectMeshIn[] = [];\n for (const [i, list] of byMesh) {\n const g = geo.get(i)!, src = model.meshes[i]!, remap = new Map<number, number>(), pos: number[] = [], nor: number[] = [], uv: number[] = [], idx: number[] = [];\n for (const t of list) for (let k = 0; k < 3; k++) {\n const v = g.indices[t + k]!;\n let r = remap.get(v);\n if (r === undefined) {\n r = pos.length / 3; remap.set(v, r);\n pos.push(g.pos[v * 3]!, g.pos[v * 3 + 1]!, g.pos[v * 3 + 2]!); nor.push(g.nor[v * 3]!, g.nor[v * 3 + 1]!, g.nor[v * 3 + 2]!); uv.push(src.uv[v * 2]!, src.uv[v * 2 + 1]!);\n }\n idx.push(r);\n }\n tris += list.length;\n meshes.push({ name: clean(src.name || `mesh_${i}`), pos, nor, uv, indices: idx, surface: surfOfMesh.get(i)! });\n }\n const oname = cell > 0 ? `${name}_${key}` : name, reference = `${prefix}\\\\${oname}`;\n // поверхности объекта — только используемые им, с перенумерацией\n const used = [...new Set(meshes.map((m) => m.surface as number))], local = new Map(used.map((s, k) => [s, k]));\n for (const m of meshes) m.surface = local.get(m.surface as number)!;\n files.set(`rawdata/objects/${reference.replace(/\\\\/g, '/')}.object`, writeObject({ meshes, surfaces: used.map((s) => surfaces[s]!) }));\n objects.push({ name: oname, reference });\n }\n const scene: SceneObjectOut[] = objects.map((x) => ({ ...x, position: [0, 0, 0] }));\n let instTris = 0, protoCount = 0, mirrored = 0;\n if (inst) {\n // прототипы: один .object на модель; зеркальные позы (det < 0) поворотом не выразить — их геометрия вливается в отдельный объект\n const protoRef = new Map<number, string>(), used = new Set(inst.placements.map((p) => p.proto)), mirrorMeshes: ObjectMeshIn[] = [];\n const names = new Set<string>();\n const meshesOf = (pi: number, M: number[] | null): ObjectMeshIn[] => inst.protos[pi]!.parts.filter((pt) => !o.hidden?.has(pt.mesh) && surfOfMesh.has(pt.mesh) && pt.indices.length >= 3).map((pt, k) => {\n const n = pt.pos.length / 3, pos: number[] = [], nor: number[] = [];\n for (let v = 0; v < n; v++) {\n let x = pt.pos[v * 3]!, y = pt.pos[v * 3 + 1]!, z = pt.pos[v * 3 + 2]!, a = pt.nor[v * 3]!, b = pt.nor[v * 3 + 1]!, c = pt.nor[v * 3 + 2]!;\n if (M) {\n [x, y, z] = [x * M[0]! + y * M[4]! + z * M[8]! + M[12]!, x * M[1]! + y * M[5]! + z * M[9]! + M[13]!, x * M[2]! + y * M[6]! + z * M[10]! + M[14]!];\n [a, b, c] = [a * M[0]! + b * M[4]! + c * M[8]!, a * M[1]! + b * M[5]! + c * M[9]!, a * M[2]! + b * M[6]! + c * M[10]!];\n const l = Math.hypot(a, b, c) || 1; a /= l; b /= l; c /= l;\n }\n pos.push(x * scale, y * scale, z * scale); nor.push(a, b, c);\n }\n const indices = Array.from(pt.indices);\n if (M) for (let t = 0; t + 2 < indices.length; t += 3) { const q = indices[t + 1]!; indices[t + 1] = indices[t + 2]!; indices[t + 2] = q; }\n return { name: `part_${k}`, pos, nor, uv: pt.uv, indices, surface: surfOfMesh.get(pt.mesh)! };\n });\n const writeWith = (reference: string, meshes: ObjectMeshIn[]) => {\n const usedS = [...new Set(meshes.map((m) => m.surface as number))], local = new Map(usedS.map((x, k) => [x, k]));\n for (const m of meshes) m.surface = local.get(m.surface as number)!;\n files.set(`rawdata/objects/${reference.replace(/\\\\/g, '/')}.object`, writeObject({ meshes, surfaces: usedS.map((x) => surfaces[x]!) }));\n };\n for (const pl of inst.placements) {\n if (!used.has(pl.proto) || pl.hidden) continue;\n const M = pl.pose, R = [M[0]!, M[1]!, M[2]!, M[4]!, M[5]!, M[6]!, M[8]!, M[9]!, M[10]!];\n const sc = [Math.hypot(R[0]!, R[1]!, R[2]!), Math.hypot(R[3]!, R[4]!, R[5]!), Math.hypot(R[6]!, R[7]!, R[8]!)];\n const det = R[0]! * (R[4]! * R[8]! - R[5]! * R[7]!) - R[1]! * (R[3]! * R[8]! - R[5]! * R[6]!) + R[2]! * (R[3]! * R[7]! - R[4]! * R[6]!);\n if (det < 0) { const ms = meshesOf(pl.proto, M); mirrorMeshes.push(...ms); mirrored++; for (const m of ms) instTris += m.indices.length / 3; continue; }\n let ref = protoRef.get(pl.proto);\n if (ref === undefined) {\n const ms = meshesOf(pl.proto, null);\n if (!ms.length) { protoRef.set(pl.proto, ''); continue; }\n let base = clean(inst.protos[pl.proto]!.name.split(/[\\\\/]/).pop() ?? 'obj'), cand = base, k = 1;\n while (names.has(cand)) cand = `${base}_${k++}`;\n names.add(cand);\n ref = `${prefix}\\\\props\\\\${cand}`;\n writeWith(ref, ms);\n protoRef.set(pl.proto, ref);\n protoCount++;\n }\n if (!ref) continue;\n for (const pt of inst.protos[pl.proto]!.parts) instTris += pt.indices.length / 3;\n let nm = clean(pl.name), j = 1;\n while (names.has(nm)) nm = `${clean(pl.name)}_${j++}`;\n names.add(nm);\n scene.push({ name: nm, reference: ref, position: [M[12]! * scale, M[13]! * scale, M[14]! * scale], matrix: R.map((v, i) => v / sc[Math.floor(i / 3)]!), scale: sc });\n }\n if (mirrorMeshes.length) {\n const ref = `${prefix}\\\\${name}_mirrored`;\n writeWith(ref, mirrorMeshes);\n scene.push({ name: `${name}_mirrored`, reference: ref, position: [0, 0, 0] });\n }\n }\n for (const [path, data] of writeScene({ name, objects: scene })) files.set(`rawdata/levels/${path}`, data);\n\n report.push(\n `Объектов .object: ${objects.length}${cell > 0 ? ` (ячейки ${cell} м)` : ''}, треугольников: ${tris}, размер сцены: ${(hi[0]! - lo[0]!).toFixed(1)} × ${(hi[1]! - lo[1]!).toFixed(1)} × ${(hi[2]! - lo[2]!).toFixed(1)} м`,\n ...(inst ? [`Объекты уровня: ${inst.placements.length} экземпляров, ${protoCount} моделей в ${prefix}\\\\props (треугольников ${instTris})${mirrored ? `; зеркальных ${mirrored} — влиты в ${name}_mirrored` : ''}`] : []),\n o.xraySource ? `Текстуры, шейдеры и материалы — игровые (${surfaces.length} поверхностей), файлы текстур не копируются` : `Текстуры: ${copied} DDS скопировано, ${encoded} перекодировано в DDS без сжатия${missingTex ? `, ${missingTex} не найдено (объект ссылается на имя, файл положите сами)` : ''}`,\n `Сцена: rawdata/levels/${name}.level — откройте в LevelEditor, добавьте свет, секторы/порталы и спавн, затем соберите xrLC.`,\n );\n if (!o.xraySource) {\n report.push('Шейдеры поверхностей — «default», материал — «default»: настройте в редакторе (стекло, листва, двусторонние грани).');\n const mats = [...new Set(meshIdx.map((i) => model.meshes[i]!.material).filter((x): x is string => !!x))];\n if (mats.length) report.push(`Материалы исходника (для настройки game material): ${mats.slice(0, 30).join(', ')}${mats.length > 30 ? '…' : ''}`);\n }\n if (model.skeleton) report.push('Скелетная модель выгружена в bind-позе как статика (кости и анимации в .object пока не пишутся).');\n if (!model.flipZ) report.push('Координаты переведены в левостороннюю систему X-Ray (Z отражён, обход граней развёрнут).');\n return { files, report };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
2
|
+
export declare const preset: import("@gmvjs/core/plugin").GamePreset;
|
|
3
|
+
declare const _default: {
|
|
4
|
+
engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
5
|
+
preset: import("@gmvjs/core/plugin").GamePreset;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pickGames } from "@gmvjs/core/plugin";
|
|
2
|
+
import { xrayV1Engine } from "../index.js";
|
|
3
|
+
const engine = pickGames(xrayV1Engine, "stalker-cop");
|
|
4
|
+
const preset = engine.games[0];
|
|
5
|
+
const cop = { engine, preset };
|
|
6
|
+
export {
|
|
7
|
+
cop as default,
|
|
8
|
+
engine,
|
|
9
|
+
preset
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=cop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cop.js","sources":["../../src/games/cop.ts"],"sourcesContent":["// S.T.A.L.K.E.R.: Зов Припяти — подпуть `@gmvjs/xray-v1/cop`: пресет игры и движок только с ней.\nimport { pickGames } from '@gmvjs/core/plugin';\nimport { xrayV1Engine } from '../index';\n\nexport const engine = pickGames(xrayV1Engine, 'stalker-cop');\nexport const preset = engine.games![0]!;\nexport default { engine, preset };\n"],"names":[],"mappings":";;AAIO,MAAM,SAAS,UAAU,cAAc,aAAa;AACpD,MAAM,SAAS,OAAO,MAAO,CAAC;AACrC,MAAA,MAAe,EAAE,QAAQ,OAAA;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
2
|
+
export declare const preset: import("@gmvjs/core/plugin").GamePreset;
|
|
3
|
+
declare const _default: {
|
|
4
|
+
engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
5
|
+
preset: import("@gmvjs/core/plugin").GamePreset;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
package/dist/games/cs.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { pickGames } from "@gmvjs/core/plugin";
|
|
2
|
+
import { xrayV1Engine } from "../index.js";
|
|
3
|
+
const engine = pickGames(xrayV1Engine, "stalker-cs");
|
|
4
|
+
const preset = engine.games[0];
|
|
5
|
+
const cs = { engine, preset };
|
|
6
|
+
export {
|
|
7
|
+
cs as default,
|
|
8
|
+
engine,
|
|
9
|
+
preset
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=cs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cs.js","sources":["../../src/games/cs.ts"],"sourcesContent":["// S.T.A.L.K.E.R.: Чистое небо — подпуть `@gmvjs/xray-v1/cs`: пресет игры и движок только с ней.\nimport { pickGames } from '@gmvjs/core/plugin';\nimport { xrayV1Engine } from '../index';\n\nexport const engine = pickGames(xrayV1Engine, 'stalker-cs');\nexport const preset = engine.games![0]!;\nexport default { engine, preset };\n"],"names":[],"mappings":";;AAIO,MAAM,SAAS,UAAU,cAAc,YAAY;AACnD,MAAM,SAAS,OAAO,MAAO,CAAC;AACrC,MAAA,KAAe,EAAE,QAAQ,OAAA;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { exportXraySdk, type XrayExportOptions, type XrayExportResult, type TextureForExport } from '../index';
|
|
2
|
+
/** Вариант выгрузки «исходники X-Ray SDK 0.7» (ExporterPlugin). */
|
|
3
|
+
export declare const exporter: import("@gmvjs/core/plugin").ExporterPlugin;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
exporter: import("@gmvjs/core/plugin").ExporterPlugin;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { xrayV1Engine } from "../index.js";
|
|
2
|
+
import { exportXraySdk } from "../index.js";
|
|
3
|
+
const exporter = xrayV1Engine.exporters.find((x) => x.id === "xray-sdk");
|
|
4
|
+
const sdk = { exporter };
|
|
5
|
+
export {
|
|
6
|
+
sdk as default,
|
|
7
|
+
exportXraySdk,
|
|
8
|
+
exporter
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sources":["../../src/games/sdk.ts"],"sourcesContent":["// Выгрузка в X-Ray SDK 0.7 — подпуть `@gmvjs/xray-v1/sdk`.\nimport { xrayV1Engine } from '../index';\n\nexport { exportXraySdk, type XrayExportOptions, type XrayExportResult, type TextureForExport } from '../index';\n/** Вариант выгрузки «исходники X-Ray SDK 0.7» (ExporterPlugin). */\nexport const exporter = xrayV1Engine.exporters!.find((x) => x.id === 'xray-sdk')!;\nexport default { exporter };\n"],"names":[],"mappings":";;AAKO,MAAM,WAAW,aAAa,UAAW,KAAK,CAAC,MAAM,EAAE,OAAO,UAAU;AAC/E,MAAA,MAAe,EAAE,SAAA;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
2
|
+
export declare const preset: import("@gmvjs/core/plugin").GamePreset;
|
|
3
|
+
declare const _default: {
|
|
4
|
+
engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
5
|
+
preset: import("@gmvjs/core/plugin").GamePreset;
|
|
6
|
+
};
|
|
7
|
+
export default _default;
|
|
8
|
+
/** Шифрование таблицы файлов gamedata.db* (для тестов и сборки архивов). */
|
|
9
|
+
export { socEncode } from '../soc-key';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { pickGames } from "@gmvjs/core/plugin";
|
|
2
|
+
import { xrayV1Engine } from "../index.js";
|
|
3
|
+
import { socEncode } from "../soc-key.js";
|
|
4
|
+
const engine = pickGames(xrayV1Engine, "stalker-soc");
|
|
5
|
+
const preset = engine.games[0];
|
|
6
|
+
const soc = { engine, preset };
|
|
7
|
+
export {
|
|
8
|
+
soc as default,
|
|
9
|
+
engine,
|
|
10
|
+
preset,
|
|
11
|
+
socEncode
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=soc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"soc.js","sources":["../../src/games/soc.ts"],"sourcesContent":["// S.T.A.L.K.E.R.: Тень Чернобыля — подпуть `@gmvjs/xray-v1/soc`: пресет игры и движок только с ней.\nimport { pickGames } from '@gmvjs/core/plugin';\nimport { xrayV1Engine } from '../index';\n\nexport const engine = pickGames(xrayV1Engine, 'stalker-soc');\nexport const preset = engine.games![0]!;\nexport default { engine, preset };\n/** Шифрование таблицы файлов gamedata.db* (для тестов и сборки архивов). */\nexport { socEncode } from '../soc-key';\n"],"names":[],"mappings":";;;AAIO,MAAM,SAAS,UAAU,cAAc,aAAa;AACpD,MAAM,SAAS,OAAO,MAAO,CAAC;AACrC,MAAA,MAAe,EAAE,QAAQ,OAAA;"}
|
package/dist/i18n.d.ts
ADDED
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const EN = {
|
|
2
|
+
"presets": {
|
|
3
|
+
"stalker-soc": {
|
|
4
|
+
"title": "S.T.A.L.K.E.R.: Shadow of Chernobyl",
|
|
5
|
+
"hint": "OGF v4. Animations are inside the model or in an external .omf. gamedata.db* archives open through “Game folder” (the file-table key is taken from your game’s bin/XR_3DA.exe) or with “Open .db…” together with XR_3DA.exe; mod .xdb archives and an unpacked gamedata folder open too. External .omf files referenced by a model are attached automatically when the gamedata folder or archives are open; torso animations play together with legs (choose in “Other body parts”). Levels include grass from level.details; SDK sources: .object with skeleton and animations, .skl/.skls.",
|
|
6
|
+
"archiveLabel": "Open .db…"
|
|
7
|
+
},
|
|
8
|
+
"stalker-cs": {
|
|
9
|
+
"title": "S.T.A.L.K.E.R.: Clear Sky",
|
|
10
|
+
"hint": "OGF v4. Open resources.db0–db2 (models and textures) and patches/xpatch_*.db, or a gamedata folder. External .omf files referenced by a model are attached automatically when the gamedata folder or archives are open; torso animations play together with legs (choose in “Other body parts”). Levels include grass from level.details; SDK sources: .object with skeleton and animations, .skl/.skls.",
|
|
11
|
+
"archiveLabel": "Open .db…"
|
|
12
|
+
},
|
|
13
|
+
"stalker-cop": {
|
|
14
|
+
"title": "S.T.A.L.K.E.R.: Call of Pripyat",
|
|
15
|
+
"hint": "OGF v4, including 3- and 4-weight vertices. .db archives as in Clear Sky. External .omf files referenced by a model are attached automatically when the gamedata folder or archives are open; torso animations play together with legs (choose in “Other body parts”). Levels include grass from level.details; SDK sources: .object with skeleton and animations, .skl/.skls.",
|
|
16
|
+
"archiveLabel": "Open .db…"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"exporters": {
|
|
20
|
+
"xray-sdk": {
|
|
21
|
+
"title": "S.T.A.L.K.E.R.: X-Ray SDK 0.7 sources",
|
|
22
|
+
"description": "For LevelEditor and ActorEditor (Call of Pripyat, SDK 0.7): .object geometry (large maps are split into cells), a .level + scene_object.part scene, DDS + .thm textures — one ZIP. Lights, sectors, the AI grid and the xrLC build are done in the SDK.",
|
|
23
|
+
"fields": {
|
|
24
|
+
"name": {
|
|
25
|
+
"label": "Level name",
|
|
26
|
+
"hint": 'Latin letters, digits, "_": rawdata/objects/gmv/<name>, rawdata/levels/<name>.level'
|
|
27
|
+
},
|
|
28
|
+
"cell": {
|
|
29
|
+
"label": "Cell, m",
|
|
30
|
+
"placeholder": "auto",
|
|
31
|
+
"hint": "Split the geometry into objects (0 — a single object; 32–64 suits maps)"
|
|
32
|
+
},
|
|
33
|
+
"scale": {
|
|
34
|
+
"label": "Scale",
|
|
35
|
+
"hint": "Metres per model unit (X-Ray: 1 unit = 1 m)"
|
|
36
|
+
},
|
|
37
|
+
"instances": {
|
|
38
|
+
"label": "Level objects as references",
|
|
39
|
+
"hint": "Each object model becomes one .object in props, the scene holds references with poses. Uncheck to merge objects into the cell geometry"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export {
|
|
46
|
+
EN
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=i18n.js.map
|
package/dist/i18n.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sources":["../src/i18n.ts"],"sourcesContent":["// Английские тексты движка xray-v1 (русские — в самих плагинах).\nimport type { EngineTexts } from '@gmvjs/core/plugin';\n\nexport const EN: EngineTexts = {\n \"presets\": {\n \"stalker-soc\": {\n \"title\": \"S.T.A.L.K.E.R.: Shadow of Chernobyl\",\n \"hint\": \"OGF v4. Animations are inside the model or in an external .omf. gamedata.db* archives open through “Game folder” (the file-table key is taken from your game’s bin/XR_3DA.exe) or with “Open .db…” together with XR_3DA.exe; mod .xdb archives and an unpacked gamedata folder open too. External .omf files referenced by a model are attached automatically when the gamedata folder or archives are open; torso animations play together with legs (choose in “Other body parts”). Levels include grass from level.details; SDK sources: .object with skeleton and animations, .skl/.skls.\",\n \"archiveLabel\": \"Open .db…\"\n },\n \"stalker-cs\": {\n \"title\": \"S.T.A.L.K.E.R.: Clear Sky\",\n \"hint\": \"OGF v4. Open resources.db0–db2 (models and textures) and patches/xpatch_*.db, or a gamedata folder. External .omf files referenced by a model are attached automatically when the gamedata folder or archives are open; torso animations play together with legs (choose in “Other body parts”). Levels include grass from level.details; SDK sources: .object with skeleton and animations, .skl/.skls.\",\n \"archiveLabel\": \"Open .db…\"\n },\n \"stalker-cop\": {\n \"title\": \"S.T.A.L.K.E.R.: Call of Pripyat\",\n \"hint\": \"OGF v4, including 3- and 4-weight vertices. .db archives as in Clear Sky. External .omf files referenced by a model are attached automatically when the gamedata folder or archives are open; torso animations play together with legs (choose in “Other body parts”). Levels include grass from level.details; SDK sources: .object with skeleton and animations, .skl/.skls.\",\n \"archiveLabel\": \"Open .db…\"\n }\n },\n \"exporters\": {\n \"xray-sdk\": {\n \"title\": \"S.T.A.L.K.E.R.: X-Ray SDK 0.7 sources\",\n \"description\": \"For LevelEditor and ActorEditor (Call of Pripyat, SDK 0.7): .object geometry (large maps are split into cells), a .level + scene_object.part scene, DDS + .thm textures — one ZIP. Lights, sectors, the AI grid and the xrLC build are done in the SDK.\",\n \"fields\": {\n \"name\": {\n \"label\": \"Level name\",\n \"hint\": \"Latin letters, digits, \\\"_\\\": rawdata/objects/gmv/<name>, rawdata/levels/<name>.level\"\n },\n \"cell\": {\n \"label\": \"Cell, m\",\n \"placeholder\": \"auto\",\n \"hint\": \"Split the geometry into objects (0 — a single object; 32–64 suits maps)\"\n },\n \"scale\": {\n \"label\": \"Scale\",\n \"hint\": \"Metres per model unit (X-Ray: 1 unit = 1 m)\"\n },\n \"instances\": {\n \"label\": \"Level objects as references\",\n \"hint\": \"Each object model becomes one .object in props, the scene holds references with poses. Uncheck to merge objects into the cell geometry\"\n }\n }\n }\n }\n};\n"],"names":[],"mappings":"AAGO,MAAM,KAAkB;AAAA,EAC7B,WAAW;AAAA,IACT,eAAe;AAAA,MACb,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAAA;AAAA,IAElB,cAAc;AAAA,MACZ,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAAA;AAAA,IAElB,eAAe;AAAA,MACb,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,gBAAgB;AAAA,IAAA;AAAA,EAClB;AAAA,EAEF,aAAa;AAAA,IACX,YAAY;AAAA,MACV,SAAS;AAAA,MACT,eAAe;AAAA,MACf,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,QAAA;AAAA,QAEV,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,eAAe;AAAA,UACf,QAAQ;AAAA,QAAA;AAAA,QAEV,SAAS;AAAA,UACP,SAAS;AAAA,UACT,QAAQ;AAAA,QAAA;AAAA,QAEV,aAAa;AAAA,UACX,SAAS;AAAA,UACT,QAAQ;AAAA,QAAA;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEJ;"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const xrayV1Engine: import("@gmvjs/core/plugin").EnginePlugin;
|
|
2
|
+
/** Выгрузка модели/уровня в исходники X-Ray SDK (.object, .level, текстуры); модуль подгружается по требованию. */
|
|
3
|
+
export declare function exportXraySdk(...args: Parameters<typeof import('./export').exportXraySdk>): ReturnType<typeof import('./export').exportXraySdk>;
|
|
4
|
+
export type { XrayExportOptions, XrayExportResult, TextureForExport } from './export';
|
|
5
|
+
export { autoLayers, XRAY_FX_PART, type XrayMotion, type XrayTrack } from './motion';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { u32le, ascii } from "@gmvjs/core/binary";
|
|
2
|
+
import { defineEngine } from "@gmvjs/core/plugin";
|
|
3
|
+
import { EN } from "./i18n.js";
|
|
4
|
+
import { XRAY_FX_PART, autoLayers } from "./motion.js";
|
|
5
|
+
const DB_EXTS = ["db", "xdb", ..."0123456789".split("").flatMap((d) => ["db" + d, "xdb" + d]), "dba", "dbb", "dbc", "dbd"];
|
|
6
|
+
const ui = { motionLabel: "+ .omf", invertQuat: true, archives: true, archiveExts: [...DB_EXTS, "exe"], archiveLabel: "Открыть .db…" };
|
|
7
|
+
const game = (id, title, hint) => ({ id, group: "Игры", title, engine: "xray-v1", formats: ["xray-ogf", "xray-object", "xray-level", "xray-dm", "xray-scene"], hint, ui, status: "beta", markers: ["gamedata", "fsgame.ltx"] });
|
|
8
|
+
const xrayV1Engine = defineEngine({
|
|
9
|
+
id: "xray-v1",
|
|
10
|
+
title: "X-Ray Engine 1.x",
|
|
11
|
+
i18n: { en: EN },
|
|
12
|
+
formats: [
|
|
13
|
+
{
|
|
14
|
+
id: "xray-ogf",
|
|
15
|
+
title: "X-Ray OGF",
|
|
16
|
+
engine: "xray-v1",
|
|
17
|
+
extensions: ["ogf"],
|
|
18
|
+
motionExtensions: ["omf", "skl", "skls"],
|
|
19
|
+
status: "beta",
|
|
20
|
+
// первый чанк — OGF_HEADER (id 1), затем байт версии; иначе не уверены, но и не исключаем
|
|
21
|
+
sniff: (h) => u32le(h, 0) === 1 ? h[8] === 4 ? 1 : 0.6 : 0.2,
|
|
22
|
+
load: async (main, ctx) => (await import("./load.js")).loadOgf(main, ctx)
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "xray-object",
|
|
26
|
+
title: "X-Ray SDK .object",
|
|
27
|
+
engine: "xray-v1",
|
|
28
|
+
extensions: ["object"],
|
|
29
|
+
motionExtensions: ["omf", "skl", "skls"],
|
|
30
|
+
status: "beta",
|
|
31
|
+
sniff: (h) => u32le(h, 0) === 30583 ? 1 : 0,
|
|
32
|
+
load: async (main, ctx) => (await import("./load.js")).loadObject(main, ctx)
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: "xray-level",
|
|
36
|
+
title: "X-Ray: скомпилированный уровень (level + level.geom)",
|
|
37
|
+
engine: "xray-v1",
|
|
38
|
+
extensions: [],
|
|
39
|
+
pathPattern: /(^|\/)levels\/[^/]+\/level$/,
|
|
40
|
+
status: "beta",
|
|
41
|
+
// первый чанк — заголовок уровня (id 1, 4 байта: версия и качество)
|
|
42
|
+
sniff: (h) => u32le(h, 0) === 1 && u32le(h, 4) === 4 && u32le(h, 8) !== 16 ? 0.9 : 0,
|
|
43
|
+
// 16 — версия уровня Metro 2033 (4A)
|
|
44
|
+
load: async (main, ctx) => (await import("./level.js")).loadLevel(main, ctx)
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "xray-dm",
|
|
48
|
+
title: "X-Ray: деталь (.dm — трава, кусты)",
|
|
49
|
+
engine: "xray-v1",
|
|
50
|
+
extensions: ["dm"],
|
|
51
|
+
status: "beta",
|
|
52
|
+
// начинается с имени шейдера (латиница, «\\», «_»)
|
|
53
|
+
sniff: (h) => /^[\w\\.-]{2,}\0/.test(ascii(h, 0, Math.min(h.length, 64))) ? 0.8 : 0,
|
|
54
|
+
load: async (main) => {
|
|
55
|
+
const { parseDM, dmMesh } = await import("./details.js");
|
|
56
|
+
const { boundsOf } = await import("@gmvjs/core/geometry");
|
|
57
|
+
const m = parseDM(new Uint8Array(await main.arrayBuffer())), mesh = dmMesh(m, m.texture);
|
|
58
|
+
return { meshes: [mesh], skeleton: null, motions: [], bounds: boundsOf([mesh]), flipZ: true, info: [`Деталь X-Ray: ${m.shader} · ${m.texture}`, `Вершин ${mesh.vertexCount}, треугольников ${m.indices.length / 3}, масштаб ${m.minScale}…${m.maxScale}`] };
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: "xray-scene",
|
|
63
|
+
title: "X-Ray SDK: уровень (.level + scene_object.part)",
|
|
64
|
+
engine: "xray-v1",
|
|
65
|
+
extensions: ["level"],
|
|
66
|
+
status: "beta",
|
|
67
|
+
// SDK 0.7 (ЗП) сохраняет сцену как ini; бинарные .level старых SDK пока не читаются
|
|
68
|
+
sniff: (h) => /^\s*\[(build_params|camera|guid|level_options|level_tag|version)\]/.test(ascii(h, 0, Math.min(h.length, 64))) ? 1 : 0,
|
|
69
|
+
load: async (main, ctx) => (await import("./scene.js")).loadSceneLevel(main, ctx)
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
archives: [
|
|
73
|
+
{
|
|
74
|
+
id: "xray-db",
|
|
75
|
+
title: "X-Ray .db / .xdb (Чистое небо, Зов Припяти)",
|
|
76
|
+
engine: "xray-v1",
|
|
77
|
+
extensions: DB_EXTS,
|
|
78
|
+
// ТЧ: исполняемый файл игры — спутник архивов (из него берётся ключ таблиц файлов)
|
|
79
|
+
companionExtensions: ["exe"],
|
|
80
|
+
// в «Папке игры» архивы открываются сами (читается только таблица файлов): ЧН/ЗП — с заголовком, ТЧ — gamedata.db*
|
|
81
|
+
openFromFolder: (h, name) => u32le(h, 0) === 666 || u32le(h, 0) === 0 && /^gamedata\.db[0-9a-z]$/i.test(name),
|
|
82
|
+
// ЧН/ЗП начинаются с текстового чанка [header] (id 0x29A), ТЧ и моды — с чанка данных (id 0)
|
|
83
|
+
sniff: (h) => u32le(h, 0) === 666 ? 1 : u32le(h, 0) === 0 ? 0.5 : 0,
|
|
84
|
+
open: async (file, siblings) => (await import("./db.js")).openXrayDb(file, siblings)
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
exporters: [
|
|
88
|
+
{
|
|
89
|
+
id: "xray-sdk",
|
|
90
|
+
title: "S.T.A.L.K.E.R.: исходники X-Ray SDK 0.7",
|
|
91
|
+
target: "xray",
|
|
92
|
+
description: "Для LevelEditor и ActorEditor (Зов Припяти, SDK 0.7): геометрия .object (большие карты режутся на ячейки), сцена .level + scene_object.part, текстуры DDS + .thm — одним ZIP. Свет, секторы, AI-сетку и сборку xrLC делаете в SDK.",
|
|
93
|
+
from: ["4a", "xray-v1"],
|
|
94
|
+
fields: [
|
|
95
|
+
{ id: "name", label: "Имя уровня", type: "text", hint: "Латиница, цифры, «_»: rawdata/objects/gmv/<имя>, rawdata/levels/<имя>.level", default: (_m, base) => base.toLowerCase().replace(/[^a-z0-9_]+/g, "_").replace(/^_+|_+$/g, "") || "level" },
|
|
96
|
+
{ id: "cell", label: "Ячейка, м", type: "number", min: 0, step: 8, placeholder: "авто", hint: "Разбиение геометрии на объекты (0 — одним объектом; для карт удобно 32–64)" },
|
|
97
|
+
{ id: "scale", label: "Масштаб", type: "number", min: 0, step: 0.01, default: 1, hint: "Сколько метров в одной единице модели (X-Ray: 1 единица = 1 м)" },
|
|
98
|
+
{ id: "instances", label: "Объекты уровня — ссылками", type: "checkbox", default: true, hint: "Каждая модель объекта одним .object в props, в сцене — ссылки с позами. Снимите, чтобы влить объекты в геометрию ячеек", when: (m) => !!m.instances }
|
|
99
|
+
],
|
|
100
|
+
run: async (model, v, ctx) => {
|
|
101
|
+
const { exportXraySdk: exportXraySdk2 } = await import("./export.js");
|
|
102
|
+
const name = String(v.name || ctx.baseName);
|
|
103
|
+
const r = await exportXraySdk2(model, {
|
|
104
|
+
name,
|
|
105
|
+
cell: v.cell === "" || v.cell === void 0 ? void 0 : +v.cell,
|
|
106
|
+
scale: +v.scale || 1,
|
|
107
|
+
hidden: ctx.hidden,
|
|
108
|
+
texture: (i) => ctx.texture(i),
|
|
109
|
+
xraySource: ctx.sourceEngine === "xray-v1",
|
|
110
|
+
instances: v.instances !== false
|
|
111
|
+
});
|
|
112
|
+
return { ...r, name: `${name}_xray_sdk` };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
games: [
|
|
117
|
+
game("stalker-soc", "S.T.A.L.K.E.R.: Тень Чернобыля", "OGF v4. Анимации — внутри модели или во внешнем .omf. Архивы gamedata.db* открываются через «Папку игры» (ключ таблиц файлов берётся из bin/XR_3DA.exe вашей игры) или кнопкой «Открыть .db…» вместе с XR_3DA.exe; .xdb модов и распакованная gamedata тоже открываются. Внешние .omf из ссылок модели подключаются сами, если открыта папка gamedata или архивы; анимации торса играют вместе с ногами (выбор — «Другие части тела»). Уровни — с травой из level.details; исходники SDK: .object со скелетом и анимациями, .skl/.skls."),
|
|
118
|
+
game("stalker-cs", "S.T.A.L.K.E.R.: Чистое небо", "OGF v4. Откройте resources.db0–db2 (модели и текстуры) и patches/xpatch_*.db или папку gamedata. Внешние .omf из ссылок модели подключаются сами, если открыта папка gamedata или архивы; анимации торса играют вместе с ногами (выбор — «Другие части тела»). Уровни — с травой из level.details; исходники SDK: .object со скелетом и анимациями, .skl/.skls."),
|
|
119
|
+
game("stalker-cop", "S.T.A.L.K.E.R.: Зов Припяти", "OGF v4, в том числе 3/4-весовые вершины. Архивы .db — как у Чистого неба. Внешние .omf из ссылок модели подключаются сами, если открыта папка gamedata или архивы; анимации торса играют вместе с ногами (выбор — «Другие части тела»). Уровни — с травой из level.details; исходники SDK: .object со скелетом и анимациями, .skl/.skls.")
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
async function exportXraySdk(...args) {
|
|
123
|
+
return (await import("./export.js")).exportXraySdk(...args);
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
XRAY_FX_PART,
|
|
127
|
+
autoLayers,
|
|
128
|
+
exportXraySdk,
|
|
129
|
+
xrayV1Engine
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=index.js.map
|