Skip to content

Commit 925fe97

Browse files
committed
refactor: optimize initial load
1 parent da8d254 commit 925fe97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+370
-228
lines changed

.gitattributes

+6
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ bundled/battlecruiser.glb filter=lfs diff=lfs merge=lfs -text
66
bundled/asteroid.glb filter=lfs diff=lfs merge=lfs -text
77
bundled/FireBall03_8x8.exr filter=lfs diff=lfs merge=lfs -text
88
bundled/remix.ogg filter=lfs diff=lfs merge=lfs -text
9+
bundled/basis/basis_transcoder.js filter=lfs diff=lfs merge=lfs -text
10+
bundled/basis/basis_transcoder.wasm filter=lfs diff=lfs merge=lfs -text
11+
src/renderer/image/formats/mesh-opt-decoder.ts filter=lfs diff=lfs merge=lfs -text
12+
bundled/_ast.glb filter=lfs diff=lfs merge=lfs -text
13+
bundled/_bc.glb filter=lfs diff=lfs merge=lfs -text
14+
bundled/_w.glb filter=lfs diff=lfs merge=lfs -text

bundled/_ast.glb

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:5b6ad15e5051930f9880c2ef3b10552782f952f4950270502ddc9857c370e3d3
3+
size 567260

bundled/_bc.glb

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:7fedc4095c8b20eb959d2b0dde16243b9f611eb4a2c4c5d5a1803b26874c4d3e
3+
size 2117068

bundled/_w.glb

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:2d29410378a4ca2058a9acd9b81bc1ba3a29a1b15f39ddf50eb688b22b8401f5
3+
size 1899352

bundled/asteroid.glb

-3
This file was deleted.

bundled/basis/basis_transcoder.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:48a0ef319a28bf0224ee88ded34f74eaf97c175bba9eb18b47fb9720510ad6c4
3+
size 62337

bundled/basis/basis_transcoder.wasm

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:79ae97d781e10a566659c689b7bb1de91726453f55f9f5e3bcc07a4e3904070f
3+
size 499935

bundled/battlecruiser.glb

-3
This file was deleted.

bundled/wraith.glb

-3
This file was deleted.

src/common/utils/electron-file-loader.ts

+11-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import path from "path";
21
import { FileLoader, ImageLoader } from "three";
32

43
function createElementNS(name: string) {
54

6-
return document.createElementNS('http://www.w3.org/1999/xhtml', name);
5+
return document.createElementNS("http://www.w3.org/1999/xhtml", name);
76

87
}
98

@@ -14,8 +13,9 @@ type LoadingCallbacks = {
1413
};
1514
const loading: Record<string, LoadingCallbacks[]> = {};
1615

17-
export default (openFile: (file: string) => Promise<Buffer>) => {
16+
export default (openFile: (file: string, path: string) => Promise<ArrayBuffer | string>) => {
1817
FileLoader.prototype.load = function (url, onLoad, onProgress, onError) {
18+
1919
if (loading[url] !== undefined) {
2020
loading[url].push({
2121
onLoad: onLoad,
@@ -40,11 +40,11 @@ export default (openFile: (file: string) => Promise<Buffer>) => {
4040

4141
this.manager.itemStart(url);
4242

43-
openFile(url)
44-
.then((buf) => {
43+
openFile(url, this.path)
44+
.then((result) => {
4545
for (let i = 0, il = callbacks.length; i < il; i++) {
4646
const callback = callbacks[i];
47-
if (callback.onLoad) callback.onLoad(buf.buffer);
47+
if (callback.onLoad) callback.onLoad(result);
4848
}
4949

5050
this.manager.itemEnd(url);
@@ -64,19 +64,17 @@ export default (openFile: (file: string) => Promise<Buffer>) => {
6464

6565
ImageLoader.prototype.load = function (url, onLoad) {
6666

67-
const image = createElementNS('img') as HTMLImageElement;
67+
const image = createElementNS("img") as HTMLImageElement;
6868

6969
function onImageLoad() {
70-
image.removeEventListener('load', onImageLoad, false);
70+
image.removeEventListener("load", onImageLoad, false);
7171
onLoad && onLoad(image);
7272
}
7373

74-
image.addEventListener('load', onImageLoad, false);
74+
image.addEventListener("load", onImageLoad, false);
7575

76-
openFile(path.join(this.path, url)).then(buf => `data:image/png;base64,${(
77-
buf
78-
).toString("base64")}`).then(src => {
79-
image.src = src;
76+
openFile(url, this.path).then(result => new Blob([result], { type: "octet/stream" })).then(blob => {
77+
image.src = URL.createObjectURL(blob);
8078
})
8179

8280
return image;

src/main/plugins/runtime.tsx

-8
Original file line numberDiff line numberDiff line change
@@ -414,14 +414,6 @@ export class PlayerInfo {
414414
}
415415
}
416416

417-
function blobToBase64(blob: Blob): Promise<string> {
418-
return new Promise((resolve, _) => {
419-
const reader = new FileReader();
420-
reader.onloadend = () => resolve(reader.result as string);
421-
reader.readAsDataURL(blob);
422-
});
423-
}
424-
425417
const playerInfo = new PlayerInfo();
426418
const getPlayerInfo = (
427419
playerId: number,

src/renderer/audio/music.ts

+21-23
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,54 @@
1-
import { Audio, AudioListener, AudioLoader } from "three";
1+
import { mixer } from "@core/global";
2+
import { Audio, AudioListener } from "three";
23
const rand = (n: number) => Math.floor(Math.random() * n);
34

45
export class Music {
5-
audio: Audio;
6+
#audio: Audio;
67
races = ["terran", "zerg", "protoss"];
78

89
constructor(listener: AudioListener) {
9-
this.audio = new Audio(listener);
10+
this.#audio = new Audio(listener);
1011
}
1112

1213
getAudio() {
13-
return this.audio;
14+
return this.#audio;
1415
}
1516

1617
playGame() {
17-
if (!this.audio) return;
18-
this.audio.onEnded = this.playGame.bind(this);
19-
this._play(
18+
if (!this.#audio) return;
19+
this.#audio.onEnded = this.playGame.bind(this);
20+
this.#play(
2021
`music/${this.races[rand(this.races.length)]}${rand(4) + 1}.ogg`
2122
);
2223
}
2324

2425
playMenu() {
2526
const race = ["t", "z", "p"];
26-
this.audio.onEnded = this.playMenu.bind(this);
27-
this._play(race[rand(2)] + "rdyroom.ogg");
27+
this.#audio.onEnded = this.playMenu.bind(this);
28+
this.#play(race[rand(2)] + "rdyroom.ogg");
2829
}
2930

30-
_play(filepath: string) {
31+
async #play(filepath: string) {
3132

32-
const audioLoader = new AudioLoader();
33-
34-
const { audio } = this;
35-
if (audio.isPlaying) {
36-
audio.stop();
33+
if (this.#audio.isPlaying) {
34+
this.#audio.stop();
3735
}
3836

39-
audioLoader.load(filepath, function (buffer) {
40-
audio.setBuffer(buffer);
41-
audio.play();
42-
});
37+
const buffer = await mixer.loadAudioBuffer(`casc:${filepath}`);
38+
39+
this.#audio.setBuffer(buffer);
40+
this.#audio.play();
4341

4442
}
4543

4644
stop() {
47-
this.audio.stop();
45+
this.#audio.stop();
4846
}
4947

5048
dispose() {
51-
if (this.audio && this.audio.isPlaying) {
52-
this.audio.stop();
49+
if (this.#audio && this.#audio.isPlaying) {
50+
this.#audio.stop();
5351
}
54-
this.audio.disconnect();
52+
this.#audio.disconnect();
5553
}
5654
}

src/renderer/core/global.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,9 @@ export const getJanitorLogLevel = () => {
146146
switch (settingsStore().data.utilities.logLevel) {
147147
case "debug":
148148
return JanitorLogLevel.Debug;
149-
case "info":
150-
return JanitorLogLevel.Info;
151149
case "warn":
152150
case "error":
151+
return JanitorLogLevel.Info;
153152
}
154153

155154
return JanitorLogLevel.None;

src/renderer/image/assets.ts

+34-34
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { settingsStore } from "@stores/settings-store";
2121
import { modelSetFileRefIds } from "@core/model-effects-configuration";
2222
import { renderComposer } from "@render/render-composer";
2323
import { loadDatFilesRemote } from "@ipc/files";
24+
import { parseDDS } from "./formats/parse-dds";
25+
import { b2ba } from "@utils/bin-utils";
2426

2527
if (module.hot) {
2628
module.hot.accept("@core/model-effects-configuration")
@@ -40,31 +42,39 @@ const setHDMipMaps = (hd: AnimAtlas, hd2: AnimAtlas) => {
4042

4143
export type Assets = Awaited<ReturnType<typeof initializeAssets>> & {
4244
envMap?: Texture,
43-
bwDat: BwDAT
44-
} & Awaited<ReturnType<typeof generateAllIcons>>;
45+
bwDat: BwDAT;
46+
wireframeIcons?: Blob[],
47+
} & Partial<Awaited<ReturnType<typeof generateAllIcons>>>;
4548

4649
export type UIStateAssets = Pick<Assets, "bwDat" | "gameIcons" | "cmdIcons" | "raceInsetIcons" | "workerIcons" | "wireframeIcons">;
4750

51+
const _hardfiles = [".glb", ".hdr", ".png", ".exr", ".js", ".wasm"];
52+
4853
export const initializeAssets = async (directories: Settings["directories"]) => {
4954

50-
electronFileLoader((file: string) => {
55+
electronFileLoader((file: string, directory: string) => {
56+
5157
log.debug(file);
5258

53-
if (file.includes(".glb") || file.includes(".hdr") || file.includes(".png") || file.includes(".exr")) {
54-
return fsPromises.readFile(file);
59+
if (file.startsWith("blob:")) {
60+
61+
return fetch(file).then(r => r.arrayBuffer());
62+
}
63+
if (_hardfiles.some((ext) => file.endsWith(ext))) {
64+
65+
const fullPath = path.join(directory ?? "", file);
66+
return file.endsWith(".js") ? fsPromises.readFile(fullPath, { encoding: "utf-8" }) : fsPromises.readFile(fullPath).then(buffer => buffer.buffer);
67+
5568
} else {
69+
5670
return readCascFile(file);
71+
5772
}
73+
5874
});
5975

6076
await openCascStorage(directories.starcraft);
6177

62-
loadDatFilesRemote().then(dat => {
63-
setAsset("bwDat", dat);
64-
// preload some assets that will not be loaded otherwise?
65-
loadImageAtlas(imageTypes.warpInFlash, dat);
66-
})
67-
6878
log.debug("@load-assets/images");
6979
const sdAnimBuf = await readCascFile("SD/mainSD.anim");
7080
const sdAnim = parseAnim(sdAnimBuf);
@@ -83,33 +93,22 @@ export const initializeAssets = async (directories: Settings["directories"]) =>
8393
}
8494

8595
const minimapConsole = {
86-
clock: createDDSTexture(await readCascFile("game/observer/UIObserverSquareRight.DDS")),
87-
square: createDDSTexture(await readCascFile("game/observer/UIObserverSquareFull.DDS")),
96+
clock: createDDSTexture(parseDDS(b2ba(await readCascFile("game/observer/UIObserverSquareRight.DDS")))),
97+
square: createDDSTexture(parseDDS(b2ba(await readCascFile("game/observer/UIObserverSquareFull.DDS")))),
8898
}
8999

90-
log.debug("@load-assets/envmap");
91100
const envEXRAssetFilename = path.join(
92101
directories.assets,
93102
"envmap.exr"
94103
)
95104
const envMapFilename = await fileExists(envEXRAssetFilename) ? envEXRAssetFilename : path.join(__static, "./envmap.hdr")
105+
log.debug(`@load-assets/envmap: ${envMapFilename}`);
96106
loadEnvironmentMap(envMapFilename).then(tex => {
97107
setAsset("envMap", tex);
98-
108+
renderComposer.getWebGLRenderer().initTexture(tex);
99109
});
100110

101-
generateAllIcons(readCascFile).then(icons => {
102-
103-
setAsset("gameIcons", icons.gameIcons);
104-
setAsset("cmdIcons", icons.cmdIcons);
105-
setAsset("raceInsetIcons", icons.raceInsetIcons);
106-
setAsset("workerIcons", icons.workerIcons);
107-
setAsset("wireframeIcons", icons.wireframeIcons);
108-
setAsset("arrowIconsGPU", icons.arrowIconsGPU);
109-
setAsset("hoverIconsGPU", icons.hoverIconsGPU);
110-
setAsset("dragIconsGPU", icons.dragIconsGPU);
111-
112-
});
111+
const someIcons = await generateAllIcons(readCascFile);
113112

114113
const refId = (id: number) => {
115114
if (sdAnim?.[id]?.refId !== undefined) {
@@ -141,10 +140,6 @@ export const initializeAssets = async (directories: Settings["directories"]) =>
141140
const glbRefImageId = modelSetFileRefIds.get(refImageId) ?? refImageId
142141
const settings = settingsStore().data.graphics.useHD2 as "auto" | "ignore" | "force";
143142

144-
if (imageId === imageTypes.warpInFlash) {
145-
console.log(imageId, refImageId);
146-
}
147-
148143
let res = UnitTileScale.HD2;
149144
if (loadingHD.has(refImageId)) {
150145

@@ -218,8 +213,6 @@ export const initializeAssets = async (directories: Settings["directories"]) =>
218213

219214
}
220215

221-
222-
223216
log.debug("@load-assets/skybox");
224217
const loader = new CubeTextureLoader();
225218
const rootPath = path.join(__static, "/skybox/sparse");
@@ -236,8 +229,15 @@ export const initializeAssets = async (directories: Settings["directories"]) =>
236229
"back.png",
237230
], res)) as CubeTexture;
238231

232+
loadDatFilesRemote().then(dat => {
233+
setAsset("bwDat", dat);
234+
// preload some assets that will not be loaded otherwise?
235+
loadImageAtlas(imageTypes.warpInFlash, dat);
236+
})
237+
239238
const r = {
240-
remaining: 10,
239+
remaining: 3,
240+
...someIcons,
241241
atlases,
242242
selectionCircles: selectionCirclesHD,
243243
minimapConsole,

src/renderer/image/atlas/load-anim-atlas.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { AnimDds, AnimAtlas, UnitTileScale } from "common/types";
33
import { parseAnim, createDDSTexture } from "../formats";
44
import { LinearEncoding, TextureEncoding } from "three";
55
import { Janitor } from "three-janitor";
6+
import { parseDDS } from "@image/formats/parse-dds";
67

78
const getBufDds = (buf: Buffer, { ddsOffset, size }: AnimDds) =>
89
buf.slice(ddsOffset, ddsOffset + size);
@@ -22,14 +23,14 @@ export const loadAnimAtlas = async (
2223
}
2324

2425
const ddsBuf = getBufDds(buf, sprite.maps.diffuse);
25-
const diffuse = janitor.mop(await createDDSTexture(ddsBuf), "diffuse");
26+
const diffuse = janitor.mop(createDDSTexture(parseDDS(ddsBuf)), "diffuse");
2627

2728
const optionalLoad = async (layer: AnimDds, encoding?: TextureEncoding) => {
2829
if (layer === undefined) {
2930
return undefined;
3031
}
3132
const ddsBuf = getBufDds(buf, layer);
32-
return janitor.mop(await createDDSTexture(ddsBuf, encoding), "layer");
33+
return janitor.mop(await createDDSTexture(parseDDS(ddsBuf), encoding), "layer");
3334
}
3435

3536
const teammask = await optionalLoad(sprite.maps.teamcolor);

src/renderer/image/atlas/load-anim-sd-atlas.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66

77
import { AnimDds, AnimFrame, ImageDAT, UnitTileScale } from "common/types";
88
import { createDDSTexture, Grp } from "../formats";
9+
import { parseDDS } from "@image/formats/parse-dds";
910

1011
export const loadAnimSdAtlas = async ({
1112
readGrp,
@@ -27,7 +28,7 @@ export const loadAnimSdAtlas = async ({
2728
sprite.buf.slice(map.ddsOffset + offset, map.ddsOffset + map.size);
2829

2930
const ddsBuf = getBuf(sprite.maps.diffuse);
30-
const diffuse = await createDDSTexture(ddsBuf);
31+
const diffuse = await createDDSTexture(parseDDS(ddsBuf));
3132

3233
let teammask;
3334
if (sprite.maps.teamcolor) {

src/renderer/image/atlas/load-glb-atlas.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Mesh, Object3D, Texture } from "three";
22
import { ImageDAT, GltfAtlas, AnimFrame } from "common/types";
3-
import loadGlb from "../formats/load-glb";
3+
import { loadGlb } from "../formats/load-glb";
44

55

66
export const loadGlbAtlas = async (

0 commit comments

Comments
 (0)