forked from GDQuest/learn-gdscript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootstrap.js
151 lines (131 loc) · 4.02 KB
/
bootstrap.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//@ts-check
/// <reference path="./bootstrap.d.ts"/>
"use strict";
window.GDQUEST = ((/** @type {GDQuestLib} */ GDQUEST) => {
loadingControl: {
let is_done = false;
// these class names get added to document.body
// css controls what is visible through that mechanism
const StatusMode = {
DONE: "mode-done",
PROGRESS: "mode-progress",
INDETERMINATE: "mode-indeterminate",
NOTICE: "mode-notice",
};
const allModes = Object.values(StatusMode);
let currentStatusMode;
/**
* Sets a status mode (class name) on the body element.
* if `is_done` is `true`, the function no-ops
* @param {string} mode one of the `StatusMode`s
* @returns
*/
const setStatusMode = (mode = StatusMode.INDETERMINATE) => {
if (currentStatusMode === mode || is_done) {
return;
}
document.body.classList.remove(...allModes);
if (allModes.includes(mode)) {
document.body.classList.add(mode);
currentStatusMode = mode;
} else {
throw new Error(`Invalid status mode : ${mode}`);
}
};
/**
* Shows an error to the user
* @param {Error|string} err
*/
const displayFailureNotice = (err) => {
var msg = err instanceof Error ? err.message : err;
console.error(msg);
setStatusMode(StatusMode.NOTICE);
const statusNotice = document.getElementById("notices");
msg.split("\n").forEach((line) => {
statusNotice.appendChild(document.createTextNode(line));
statusNotice.appendChild(document.createElement("br"));
});
is_done = true;
};
/**
* Grows the visual loading bar
* @param {number} percentage
* @returns
*/
const displayPercentage = (percentage = 0) =>
document
.getElementById("loader")
.style.setProperty("--progress", percentage * 100 + "%");
/**
* Callback used during the loading of the engine and packages
* @param {number} current the current amount of bytes loaded
* @param {number} total the total amount of bytes loaded
*/
const onProgress = (current, total) => {
if (total > 0) {
console.info("loading...", total);
setStatusMode(StatusMode.PROGRESS);
displayPercentage(current / total);
if (current === total) {
onPackageLoaded();
}
} else {
setStatusMode(StatusMode.INDETERMINATE);
}
};
/**
* Called once Godot loaded everything.
* All of the operations no-op if `onPackageLoaded` has already been called,
* so it's safe to call several times.
*/
const onPackageLoaded = () => {
displayPercentage(1);
setTimeout(() => {
setStatusMode(StatusMode.DONE);
is_done = true;
}, 200);
};
/**
* Instanciates the engine, starts the package
*/
const load = () => {
setStatusMode(StatusMode.INDETERMINATE);
GODOT_CONFIG.canvasResizePolicy = 0;
const engine = new Engine(GODOT_CONFIG);
engine
.startGame({ onProgress })
.then(onPackageLoaded)
.catch(displayFailureNotice);
};
/**
* Entry point, this is run once the page loads
*/
const startLoading = () => {
setStatusMode(StatusMode.INDETERMINATE);
if (!Engine.isWebGLAvailable()) {
displayFailureNotice("WebGL not available");
} else {
load();
}
};
GDQUEST.startLoading = startLoading;
GDQUEST.displayFailureNotice = displayFailureNotice;
}
mobileHandling: {
const KEY = "force-mobile";
const forceAppOnMobile = () => {
document.body.classList.add(KEY);
localStorage.setItem(KEY, "true");
};
document
.getElementById("mobile-warning-dismiss-button")
.addEventListener("click", forceAppOnMobile);
const currentValue = JSON.parse(localStorage.getItem(KEY) || "false");
if (currentValue === true) {
forceAppOnMobile();
}
}
return GDQUEST;
// @ts-ignore
})(window.GDQUEST || {});
window.GDQUEST.startLoading();