pigl-js 1.0.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 +135 -0
- package/dist/pigl.mjs +3212 -0
- package/dist/pigl.umd.js +1085 -0
- package/package.json +34 -0
package/dist/pigl.mjs
ADDED
|
@@ -0,0 +1,3212 @@
|
|
|
1
|
+
class V {
|
|
2
|
+
constructor(e = 0, t = 0, i = 0) {
|
|
3
|
+
this.data = new Float32Array([e, t, i]);
|
|
4
|
+
}
|
|
5
|
+
get x() {
|
|
6
|
+
return this.data[0];
|
|
7
|
+
}
|
|
8
|
+
set x(e) {
|
|
9
|
+
this.data[0] = e;
|
|
10
|
+
}
|
|
11
|
+
get y() {
|
|
12
|
+
return this.data[1];
|
|
13
|
+
}
|
|
14
|
+
set y(e) {
|
|
15
|
+
this.data[1] = e;
|
|
16
|
+
}
|
|
17
|
+
get z() {
|
|
18
|
+
return this.data[2];
|
|
19
|
+
}
|
|
20
|
+
set z(e) {
|
|
21
|
+
this.data[2] = e;
|
|
22
|
+
}
|
|
23
|
+
set(e, t, i) {
|
|
24
|
+
return this.data[0] = e, this.data[1] = t, this.data[2] = i, this;
|
|
25
|
+
}
|
|
26
|
+
copy(e) {
|
|
27
|
+
return this.data[0] = e.x, this.data[1] = e.y, this.data[2] = e.z, this;
|
|
28
|
+
}
|
|
29
|
+
toArray() {
|
|
30
|
+
return [this.data[0], this.data[1], this.data[2]];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const R = {
|
|
34
|
+
identity(s) {
|
|
35
|
+
return s.fill(0), s[0] = 1, s[5] = 1, s[10] = 1, s[15] = 1, s;
|
|
36
|
+
},
|
|
37
|
+
multiply(s, e, t) {
|
|
38
|
+
let i = e[0], r = e[1], n = e[2], o = e[3], a = e[4], l = e[5], c = e[6], h = e[7], d = e[8], u = e[9], f = e[10], x = e[11], v = e[12], C = e[13], m = e[14], p = e[15], g = t[0], w = t[1], b = t[2], E = t[3];
|
|
39
|
+
return s[0] = g * i + w * a + b * d + E * v, s[1] = g * r + w * l + b * u + E * C, s[2] = g * n + w * c + b * f + E * m, s[3] = g * o + w * h + b * x + E * p, g = t[4], w = t[5], b = t[6], E = t[7], s[4] = g * i + w * a + b * d + E * v, s[5] = g * r + w * l + b * u + E * C, s[6] = g * n + w * c + b * f + E * m, s[7] = g * o + w * h + b * x + E * p, g = t[8], w = t[9], b = t[10], E = t[11], s[8] = g * i + w * a + b * d + E * v, s[9] = g * r + w * l + b * u + E * C, s[10] = g * n + w * c + b * f + E * m, s[11] = g * o + w * h + b * x + E * p, g = t[12], w = t[13], b = t[14], E = t[15], s[12] = g * i + w * a + b * d + E * v, s[13] = g * r + w * l + b * u + E * C, s[14] = g * n + w * c + b * f + E * m, s[15] = g * o + w * h + b * x + E * p, s;
|
|
40
|
+
},
|
|
41
|
+
translate(s, e, t) {
|
|
42
|
+
let i = t.x !== void 0 ? t.x : t[0], r = t.y !== void 0 ? t.y : t[1], n = t.z !== void 0 ? t.z : t[2];
|
|
43
|
+
if (e === s)
|
|
44
|
+
s[12] = e[0] * i + e[4] * r + e[8] * n + e[12], s[13] = e[1] * i + e[5] * r + e[9] * n + e[13], s[14] = e[2] * i + e[6] * r + e[10] * n + e[14], s[15] = e[3] * i + e[7] * r + e[11] * n + e[15];
|
|
45
|
+
else {
|
|
46
|
+
let o = e[0], a = e[1], l = e[2], c = e[3], h = e[4], d = e[5], u = e[6], f = e[7], x = e[8], v = e[9], C = e[10], m = e[11];
|
|
47
|
+
s[0] = o, s[1] = a, s[2] = l, s[3] = c, s[4] = h, s[5] = d, s[6] = u, s[7] = f, s[8] = x, s[9] = v, s[10] = C, s[11] = m, s[12] = o * i + h * r + x * n + e[12], s[13] = a * i + d * r + v * n + e[13], s[14] = l * i + u * r + C * n + e[14], s[15] = c * i + f * r + m * n + e[15];
|
|
48
|
+
}
|
|
49
|
+
return s;
|
|
50
|
+
},
|
|
51
|
+
scale(s, e, t) {
|
|
52
|
+
let i = t.x !== void 0 ? t.x : t[0], r = t.y !== void 0 ? t.y : t[1], n = t.z !== void 0 ? t.z : t[2];
|
|
53
|
+
return s[0] = e[0] * i, s[1] = e[1] * i, s[2] = e[2] * i, s[3] = e[3] * i, s[4] = e[4] * r, s[5] = e[5] * r, s[6] = e[6] * r, s[7] = e[7] * r, s[8] = e[8] * n, s[9] = e[9] * n, s[10] = e[10] * n, s[11] = e[11] * n, s[12] = e[12], s[13] = e[13], s[14] = e[14], s[15] = e[15], s;
|
|
54
|
+
},
|
|
55
|
+
rotateX(s, e, t) {
|
|
56
|
+
let i = Math.sin(t), r = Math.cos(t), n = e[4], o = e[5], a = e[6], l = e[7], c = e[8], h = e[9], d = e[10], u = e[11];
|
|
57
|
+
return e !== s && (s[0] = e[0], s[1] = e[1], s[2] = e[2], s[3] = e[3], s[12] = e[12], s[13] = e[13], s[14] = e[14], s[15] = e[15]), s[4] = n * r + c * i, s[5] = o * r + h * i, s[6] = a * r + d * i, s[7] = l * r + u * i, s[8] = c * r - n * i, s[9] = h * r - o * i, s[10] = d * r - a * i, s[11] = u * r - l * i, s;
|
|
58
|
+
},
|
|
59
|
+
rotateY(s, e, t) {
|
|
60
|
+
let i = Math.sin(t), r = Math.cos(t), n = e[0], o = e[1], a = e[2], l = e[3], c = e[8], h = e[9], d = e[10], u = e[11];
|
|
61
|
+
return e !== s && (s[4] = e[4], s[5] = e[5], s[6] = e[6], s[7] = e[7], s[12] = e[12], s[13] = e[13], s[14] = e[14], s[15] = e[15]), s[0] = n * r - c * i, s[1] = o * r - h * i, s[2] = a * r - d * i, s[3] = l * r - u * i, s[8] = n * i + c * r, s[9] = o * i + h * r, s[10] = a * i + d * r, s[11] = l * i + u * r, s;
|
|
62
|
+
},
|
|
63
|
+
rotateZ(s, e, t) {
|
|
64
|
+
let i = Math.sin(t), r = Math.cos(t), n = e[0], o = e[1], a = e[2], l = e[3], c = e[4], h = e[5], d = e[6], u = e[7];
|
|
65
|
+
return e !== s && (s[8] = e[8], s[9] = e[9], s[10] = e[10], s[11] = e[11], s[12] = e[12], s[13] = e[13], s[14] = e[14], s[15] = e[15]), s[0] = n * r + c * i, s[1] = o * r + h * i, s[2] = a * r + d * i, s[3] = l * r + u * i, s[4] = c * r - n * i, s[5] = h * r - o * i, s[6] = d * r - a * i, s[7] = u * r - l * i, s;
|
|
66
|
+
},
|
|
67
|
+
invert(s, e) {
|
|
68
|
+
let t = e[0], i = e[1], r = e[2], n = e[3], o = e[4], a = e[5], l = e[6], c = e[7], h = e[8], d = e[9], u = e[10], f = e[11], x = e[12], v = e[13], C = e[14], m = e[15], p = t * a - i * o, g = t * l - r * o, w = t * c - n * o, b = i * l - r * a, E = i * c - n * a, _ = r * c - n * l, F = h * v - d * x, D = h * C - u * x, A = h * m - f * x, S = d * C - u * v, M = d * m - f * v, P = u * m - f * C, T = p * P - g * M + w * S + b * A - E * D + _ * F;
|
|
69
|
+
return T ? (T = 1 / T, s[0] = (a * P - l * M + c * S) * T, s[1] = (r * M - i * P - n * S) * T, s[2] = (v * _ - C * E + m * b) * T, s[3] = (u * E - d * _ - f * b) * T, s[4] = (l * A - o * P - c * D) * T, s[5] = (t * P - r * A + n * D) * T, s[6] = (C * w - x * _ - m * g) * T, s[7] = (h * _ - u * w + f * g) * T, s[8] = (o * M - a * A + c * F) * T, s[9] = (i * A - t * M - n * F) * T, s[10] = (x * E - v * w + m * p) * T, s[11] = (d * w - h * E - f * p) * T, s[12] = (a * D - o * S - l * F) * T, s[13] = (t * S - i * D + r * F) * T, s[14] = (v * g - x * b - C * p) * T, s[15] = (h * b - d * g + u * p) * T, s) : null;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
class H {
|
|
73
|
+
constructor() {
|
|
74
|
+
this.position = new V(0, 0, 0), this.rotation = new V(0, 0, 0), this.scale = new V(1, 1, 1), this.localMatrix = new Float32Array(16), this.worldMatrix = new Float32Array(16), R.identity(this.localMatrix), R.identity(this.worldMatrix), this.parent = null, this.children = [];
|
|
75
|
+
}
|
|
76
|
+
add(e) {
|
|
77
|
+
e.parent && e.parent.remove(e), e.parent = this, this.children.push(e);
|
|
78
|
+
}
|
|
79
|
+
remove(e) {
|
|
80
|
+
const t = this.children.indexOf(e);
|
|
81
|
+
t !== -1 && (e.parent = null, this.children.splice(t, 1));
|
|
82
|
+
}
|
|
83
|
+
updateLocalMatrix() {
|
|
84
|
+
R.identity(this.localMatrix), R.translate(this.localMatrix, this.localMatrix, this.position), R.rotateY(this.localMatrix, this.localMatrix, this.rotation.y), R.rotateX(this.localMatrix, this.localMatrix, this.rotation.x), R.rotateZ(this.localMatrix, this.localMatrix, this.rotation.z), R.scale(this.localMatrix, this.localMatrix, this.scale);
|
|
85
|
+
}
|
|
86
|
+
updateWorldMatrix() {
|
|
87
|
+
if (this.updateLocalMatrix(), this.parent)
|
|
88
|
+
R.multiply(this.worldMatrix, this.parent.worldMatrix, this.localMatrix);
|
|
89
|
+
else
|
|
90
|
+
for (let e = 0; e < 16; e++)
|
|
91
|
+
this.worldMatrix[e] = this.localMatrix[e];
|
|
92
|
+
for (let e = 0; e < this.children.length; e++)
|
|
93
|
+
this.children[e].updateWorldMatrix();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
class X {
|
|
97
|
+
constructor(e, t, i = null, r = "GameObject") {
|
|
98
|
+
this.name = r, this.transform = new H(), this.renderer = e, this.material = t, this.mesh = i;
|
|
99
|
+
}
|
|
100
|
+
render(e, t = void 0, i = null) {
|
|
101
|
+
this.transform.updateWorldMatrix();
|
|
102
|
+
const r = i || this.material;
|
|
103
|
+
this.renderer && r && this.renderer.draw(this, e, t, r);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
class W {
|
|
107
|
+
constructor() {
|
|
108
|
+
this.time = 0, this.deltaTime = 0, this.unscaledTime = 0, this.unscaledDeltaTime = 0, this.timeScale = 1, this._lastTime = 0, this._initialized = !1;
|
|
109
|
+
}
|
|
110
|
+
update(e) {
|
|
111
|
+
const t = e * 1e-3;
|
|
112
|
+
this._initialized || (this._lastTime = t, this._initialized = !0), this.unscaledDeltaTime = t - this._lastTime, this.unscaledTime += this.unscaledDeltaTime, this.deltaTime = this.unscaledDeltaTime * this.timeScale, this.time += this.deltaTime, this._lastTime = t;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const Pe = new W();
|
|
116
|
+
class Re {
|
|
117
|
+
constructor(e, t) {
|
|
118
|
+
this.camera = e, this.domElement = t, this.moveSpeed = 10, this.mouseSensitivity = 2e-3, this.keys = {
|
|
119
|
+
w: !1,
|
|
120
|
+
a: !1,
|
|
121
|
+
s: !1,
|
|
122
|
+
d: !1,
|
|
123
|
+
q: !1,
|
|
124
|
+
e: !1
|
|
125
|
+
}, this.mouse = {
|
|
126
|
+
x: 0,
|
|
127
|
+
y: 0,
|
|
128
|
+
lastX: 0,
|
|
129
|
+
lastY: 0,
|
|
130
|
+
isDown: !1
|
|
131
|
+
}, this.rotation = {
|
|
132
|
+
x: e.transform.rotation.x,
|
|
133
|
+
y: e.transform.rotation.y
|
|
134
|
+
}, this._initEvents();
|
|
135
|
+
}
|
|
136
|
+
_initEvents() {
|
|
137
|
+
window.addEventListener("keydown", (e) => this._onKey(e, !0)), window.addEventListener("keyup", (e) => this._onKey(e, !1)), this.domElement.addEventListener("mousedown", (e) => {
|
|
138
|
+
e.button === 2 && (this.mouse.isDown = !0, this.mouse.lastX = e.clientX, this.mouse.lastY = e.clientY);
|
|
139
|
+
}), window.addEventListener("mouseup", (e) => {
|
|
140
|
+
e.button === 2 && (this.mouse.isDown = !1);
|
|
141
|
+
}), window.addEventListener("mousemove", (e) => {
|
|
142
|
+
if (!this.mouse.isDown) return;
|
|
143
|
+
const t = e.clientX - this.mouse.lastX, i = e.clientY - this.mouse.lastY;
|
|
144
|
+
this.mouse.lastX = e.clientX, this.mouse.lastY = e.clientY, this.rotation.y -= t * this.mouseSensitivity, this.rotation.x -= i * this.mouseSensitivity;
|
|
145
|
+
const r = Math.PI / 2 - 0.01;
|
|
146
|
+
this.rotation.x = Math.max(-r, Math.min(r, this.rotation.x)), this.camera.transform.rotation.x = this.rotation.x, this.camera.transform.rotation.y = this.rotation.y;
|
|
147
|
+
}), this.domElement.addEventListener("contextmenu", (e) => e.preventDefault());
|
|
148
|
+
}
|
|
149
|
+
_onKey(e, t) {
|
|
150
|
+
const i = e.key.toLowerCase();
|
|
151
|
+
this.keys.hasOwnProperty(i) && (this.keys[i] = t);
|
|
152
|
+
}
|
|
153
|
+
update(e) {
|
|
154
|
+
const t = this.moveSpeed * e, i = this.camera.transform, r = Math.sin(i.rotation.y), n = Math.cos(i.rotation.y), o = -r, a = -n, l = n, c = -r;
|
|
155
|
+
let h = 0, d = 0, u = 0;
|
|
156
|
+
if (this.keys.w && (d += 1), this.keys.s && (d -= 1), this.keys.a && (h -= 1), this.keys.d && (h += 1), this.keys.q && (u += 1), this.keys.e && (u -= 1), h !== 0 || d !== 0) {
|
|
157
|
+
const f = Math.sqrt(h * h + d * d);
|
|
158
|
+
h /= f, d /= f;
|
|
159
|
+
}
|
|
160
|
+
i.position.x += (o * d + l * h) * t, i.position.z += (a * d + c * h) * t, i.position.y += u * t;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
class N {
|
|
164
|
+
constructor(e, t, i, r, n = null) {
|
|
165
|
+
this.gl = e, this.vertices = t, this.uvs = i, this.normals = r, this.indices = n, this.count = n ? n.length : t.length / 3, this.vertexBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.vertexBuffer), e.bufferData(e.ARRAY_BUFFER, this.vertices, e.STATIC_DRAW), this.uvs && this.uvs.length > 0 && (this.uvBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.uvBuffer), e.bufferData(e.ARRAY_BUFFER, this.uvs, e.STATIC_DRAW)), this.normals && this.normals.length > 0 && (this.normalBuffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.normalBuffer), e.bufferData(e.ARRAY_BUFFER, this.normals, e.STATIC_DRAW)), this.indices && this.indices.length > 0 && (this.indexBuffer = e.createBuffer(), e.bindBuffer(e.ELEMENT_ARRAY_BUFFER, this.indexBuffer), e.bufferData(e.ELEMENT_ARRAY_BUFFER, this.indices, e.STATIC_DRAW));
|
|
166
|
+
}
|
|
167
|
+
bind(e) {
|
|
168
|
+
const t = this.gl;
|
|
169
|
+
t.bindBuffer(t.ARRAY_BUFFER, this.vertexBuffer);
|
|
170
|
+
const i = e.getAttribLocation("aVertexPosition");
|
|
171
|
+
if (i !== -1 && (t.enableVertexAttribArray(i), t.vertexAttribPointer(i, 3, t.FLOAT, !1, 0, 0)), this.uvBuffer) {
|
|
172
|
+
t.bindBuffer(t.ARRAY_BUFFER, this.uvBuffer);
|
|
173
|
+
const r = e.getAttribLocation("aTexCoord");
|
|
174
|
+
r !== -1 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(r, 2, t.FLOAT, !1, 0, 0));
|
|
175
|
+
}
|
|
176
|
+
if (this.normalBuffer) {
|
|
177
|
+
t.bindBuffer(t.ARRAY_BUFFER, this.normalBuffer);
|
|
178
|
+
const r = e.getAttribLocation("aNormal");
|
|
179
|
+
r !== -1 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(r, 3, t.FLOAT, !1, 0, 0));
|
|
180
|
+
}
|
|
181
|
+
this.indexBuffer && t.bindBuffer(t.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
|
182
|
+
}
|
|
183
|
+
draw() {
|
|
184
|
+
const e = this.gl;
|
|
185
|
+
this.indices && this.indices.length > 0 ? e.drawElements(e.TRIANGLES, this.count, e.UNSIGNED_SHORT, 0) : e.drawArrays(e.TRIANGLES, 0, this.count);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
class Le {
|
|
189
|
+
static async load(e, t) {
|
|
190
|
+
const r = await (await fetch(t)).text(), n = this.parse(e, r);
|
|
191
|
+
return new N(e, n.positions, n.uvs, n.normals);
|
|
192
|
+
}
|
|
193
|
+
static parse(e, t) {
|
|
194
|
+
const i = [], r = [], n = [], o = [], a = [], l = [], c = t.split(`
|
|
195
|
+
`);
|
|
196
|
+
for (let h of c) {
|
|
197
|
+
if (h = h.trim(), h.startsWith("#") || h === "") continue;
|
|
198
|
+
const d = h.split(/\s+/), u = d[0];
|
|
199
|
+
if (u === "v")
|
|
200
|
+
i.push([
|
|
201
|
+
parseFloat(d[1]),
|
|
202
|
+
parseFloat(d[2]),
|
|
203
|
+
parseFloat(d[3])
|
|
204
|
+
]);
|
|
205
|
+
else if (u === "vt")
|
|
206
|
+
r.push([
|
|
207
|
+
parseFloat(d[1]),
|
|
208
|
+
parseFloat(d[2])
|
|
209
|
+
]);
|
|
210
|
+
else if (u === "vn")
|
|
211
|
+
n.push([
|
|
212
|
+
parseFloat(d[1]),
|
|
213
|
+
parseFloat(d[2]),
|
|
214
|
+
parseFloat(d[3])
|
|
215
|
+
]);
|
|
216
|
+
else if (u === "f") {
|
|
217
|
+
const f = d.slice(1);
|
|
218
|
+
for (let x = 1; x < f.length - 1; x++) {
|
|
219
|
+
const v = f[0], C = f[x], m = f[x + 1];
|
|
220
|
+
this.processVertex(v, i, r, n, o, a, l), this.processVertex(C, i, r, n, o, a, l), this.processVertex(m, i, r, n, o, a, l);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
positions: new Float32Array(o),
|
|
226
|
+
uvs: new Float32Array(a),
|
|
227
|
+
normals: new Float32Array(l),
|
|
228
|
+
vertexCount: o.length / 3
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
static processVertex(e, t, i, r, n, o, a) {
|
|
232
|
+
const l = e.split("/"), c = parseInt(l[0]) - 1, h = l[1] ? parseInt(l[1]) - 1 : -1, d = l[2] ? parseInt(l[2]) - 1 : -1, u = t[c];
|
|
233
|
+
if (n.push(u[0], u[1], u[2]), h >= 0) {
|
|
234
|
+
const f = i[h];
|
|
235
|
+
o.push(f[0], f[1]);
|
|
236
|
+
} else
|
|
237
|
+
o.push(0, 0);
|
|
238
|
+
if (d >= 0) {
|
|
239
|
+
const f = r[d];
|
|
240
|
+
a.push(f[0], f[1], f[2]);
|
|
241
|
+
} else
|
|
242
|
+
a.push(0, 1, 0);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
class Y {
|
|
246
|
+
constructor() {
|
|
247
|
+
this.enabled = !1, this.metrics = {
|
|
248
|
+
startTime: 0,
|
|
249
|
+
endTime: 0,
|
|
250
|
+
frameTime: 0,
|
|
251
|
+
cpuTime: 0,
|
|
252
|
+
passes: []
|
|
253
|
+
}, this.lastFrameStart = 0, this.fps = 0, this.history = [], this.maxHistory = 60, this.currentPass = null;
|
|
254
|
+
}
|
|
255
|
+
enable() {
|
|
256
|
+
this.enabled = !0;
|
|
257
|
+
}
|
|
258
|
+
disable() {
|
|
259
|
+
this.enabled = !1, this.metrics.passes = [];
|
|
260
|
+
}
|
|
261
|
+
beginFrame() {
|
|
262
|
+
if (!this.enabled) return;
|
|
263
|
+
const e = performance.now();
|
|
264
|
+
if (this.lastFrameStart > 0) {
|
|
265
|
+
const t = e - this.lastFrameStart;
|
|
266
|
+
this.fps = 1e3 / t;
|
|
267
|
+
}
|
|
268
|
+
this.lastFrameStart = e, this.metrics.startTime = e, this.metrics.passes = [];
|
|
269
|
+
}
|
|
270
|
+
endFrame() {
|
|
271
|
+
this.enabled && (this.metrics.endTime = performance.now(), this.metrics.cpuTime = this.metrics.endTime - this.metrics.startTime, this.addToHistory(this.metrics.cpuTime));
|
|
272
|
+
}
|
|
273
|
+
beginPass(e) {
|
|
274
|
+
if (!this.enabled) return;
|
|
275
|
+
const t = {
|
|
276
|
+
id: this.metrics.passes.length,
|
|
277
|
+
name: e,
|
|
278
|
+
startTime: performance.now(),
|
|
279
|
+
endTime: 0,
|
|
280
|
+
duration: 0,
|
|
281
|
+
drawCalls: []
|
|
282
|
+
};
|
|
283
|
+
this.metrics.passes.push(t), this.currentPass = t;
|
|
284
|
+
}
|
|
285
|
+
endPass() {
|
|
286
|
+
!this.enabled || !this.currentPass || (this.currentPass.endTime = performance.now(), this.currentPass.duration = this.currentPass.endTime - this.currentPass.startTime, this.currentPass = null);
|
|
287
|
+
}
|
|
288
|
+
recordDrawCall(e, t, i, r, n) {
|
|
289
|
+
!this.enabled || !this.currentPass || this.currentPass.drawCalls.push({
|
|
290
|
+
object: e,
|
|
291
|
+
material: t,
|
|
292
|
+
shader: i,
|
|
293
|
+
duration: n - r
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
addToHistory(e) {
|
|
297
|
+
this.history.push(e), this.history.length > this.maxHistory && this.history.shift();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
class Ue {
|
|
301
|
+
static attach(e, t) {
|
|
302
|
+
const i = new Y(), r = e.execute.bind(e);
|
|
303
|
+
e.execute = function(o, a, l) {
|
|
304
|
+
i.enabled && i.beginFrame();
|
|
305
|
+
const c = e.passes || [];
|
|
306
|
+
for (let h = 0; h < c.length; h++) {
|
|
307
|
+
const d = c[h];
|
|
308
|
+
if (!d.__profilerInstrumented) {
|
|
309
|
+
const u = d.execute.bind(d), f = d.constructor.name;
|
|
310
|
+
d.execute = function(x, v, C) {
|
|
311
|
+
i.enabled && i.beginPass(f), u(x, v, C), i.enabled && i.endPass();
|
|
312
|
+
}, d.__profilerInstrumented = !0;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
r(o, a, l), i.enabled && i.endFrame();
|
|
316
|
+
};
|
|
317
|
+
const n = t.draw.bind(t);
|
|
318
|
+
return t.draw = function(o, a, l, c) {
|
|
319
|
+
const h = performance.now();
|
|
320
|
+
n(o, a, l, c);
|
|
321
|
+
const d = performance.now();
|
|
322
|
+
if (i.enabled) {
|
|
323
|
+
const u = o ? o.name : "Unknown", f = c ? c.name : "Unknown";
|
|
324
|
+
i.recordDrawCall(u, f, 0, h, d);
|
|
325
|
+
}
|
|
326
|
+
}, i.disable(), i;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
class G extends X {
|
|
330
|
+
constructor() {
|
|
331
|
+
super(null), this.projectionMatrix = new Float32Array(16), this.viewMatrix = new Float32Array(16), this.fov = 45 * Math.PI / 180, this.aspect = 1, this.near = 0.1, this.far = 100, this.orthographic = !1, this.orthoSize = 30, R.identity(this.projectionMatrix), R.identity(this.viewMatrix), this.transform.position.set(0, 0, 5), this.name = "Camera";
|
|
332
|
+
}
|
|
333
|
+
setPerspective(e, t, i, r) {
|
|
334
|
+
this.fov = e, this.aspect = t, this.near = i, this.far = r, this.orthographic = !1;
|
|
335
|
+
const n = 1 / Math.tan(e / 2), o = this.projectionMatrix;
|
|
336
|
+
o.fill(0), o[0] = n / t, o[5] = n, o[10] = (r + i) / (i - r), o[11] = -1, o[14] = 2 * r * i / (i - r);
|
|
337
|
+
}
|
|
338
|
+
setOrthographic(e, t, i, r, n, o) {
|
|
339
|
+
this.near = n, this.far = o, this.orthographic = !0, this.orthoSize = (r - i) / 2;
|
|
340
|
+
const a = this.projectionMatrix, l = 1 / (e - t), c = 1 / (i - r), h = 1 / (n - o);
|
|
341
|
+
a.fill(0), a[0] = -2 * l, a[5] = -2 * c, a[10] = 2 * h, a[12] = (e + t) * l, a[13] = (r + i) * c, a[14] = (o + n) * h, a[15] = 1;
|
|
342
|
+
}
|
|
343
|
+
updateProjection() {
|
|
344
|
+
if (this.orthographic) {
|
|
345
|
+
const e = this.orthoSize;
|
|
346
|
+
this.setOrthographic(-e * this.aspect, e * this.aspect, -e, e, this.near, this.far);
|
|
347
|
+
} else
|
|
348
|
+
this.setPerspective(this.fov, this.aspect, this.near, this.far);
|
|
349
|
+
}
|
|
350
|
+
updateView() {
|
|
351
|
+
this.transform.updateWorldMatrix(), R.invert(this.viewMatrix, this.transform.worldMatrix);
|
|
352
|
+
}
|
|
353
|
+
getScreenPosition(e) {
|
|
354
|
+
const t = this.viewMatrix, i = this.projectionMatrix;
|
|
355
|
+
e.transform.updateWorldMatrix();
|
|
356
|
+
const r = e.transform.worldMatrix, n = r[12], o = r[13], a = r[14], l = 1, c = t[0] * n + t[4] * o + t[8] * a + t[12] * l, h = t[1] * n + t[5] * o + t[9] * a + t[13] * l, d = t[2] * n + t[6] * o + t[10] * a + t[14] * l, u = t[3] * n + t[7] * o + t[11] * a + t[15] * l, f = i[0] * c + i[4] * h + i[8] * d + i[12] * u, x = i[1] * c + i[5] * h + i[9] * d + i[13] * u;
|
|
357
|
+
i[2] * c + i[6] * h + i[10] * d + i[14] * u;
|
|
358
|
+
const v = i[3] * c + i[7] * h + i[11] * d + i[15] * u;
|
|
359
|
+
if (v === 0) return [0.5, 0.5];
|
|
360
|
+
const C = f / v, m = x / v;
|
|
361
|
+
return [(C + 1) * 0.5, (m + 1) * 0.5];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
class j {
|
|
365
|
+
constructor(e) {
|
|
366
|
+
this.gl = e;
|
|
367
|
+
const t = new Float32Array([
|
|
368
|
+
-1,
|
|
369
|
+
1,
|
|
370
|
+
0,
|
|
371
|
+
1,
|
|
372
|
+
// Top-Left
|
|
373
|
+
-1,
|
|
374
|
+
-1,
|
|
375
|
+
0,
|
|
376
|
+
0,
|
|
377
|
+
// Bottom-Left
|
|
378
|
+
1,
|
|
379
|
+
1,
|
|
380
|
+
1,
|
|
381
|
+
1,
|
|
382
|
+
// Top-Right
|
|
383
|
+
1,
|
|
384
|
+
-1,
|
|
385
|
+
1,
|
|
386
|
+
0
|
|
387
|
+
// Bottom-Right
|
|
388
|
+
]);
|
|
389
|
+
this.buffer = e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, this.buffer), e.bufferData(e.ARRAY_BUFFER, t, e.STATIC_DRAW);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Executes a shader pass.
|
|
393
|
+
* @param {Shader|Material} shaderOrMaterial - The shader to use or a Material object.
|
|
394
|
+
* @param {Object} uniforms - Key-value pairs of uniforms (if passing raw Shader). Ignored if Material is used.
|
|
395
|
+
* @param {RenderTarget|null} target - The output target. If null, renders to screen.
|
|
396
|
+
*/
|
|
397
|
+
draw(e, t = {}, i = null) {
|
|
398
|
+
const r = this.gl;
|
|
399
|
+
let n, o = t;
|
|
400
|
+
if (e.uniforms && e.shader) {
|
|
401
|
+
n = e.shader, o = {};
|
|
402
|
+
for (const h in e.uniforms)
|
|
403
|
+
o[h] = e.uniforms[h].value;
|
|
404
|
+
t && (t.bind || t === null) && (i = t);
|
|
405
|
+
} else
|
|
406
|
+
n = e;
|
|
407
|
+
i ? i.bind() : (r.bindFramebuffer(r.FRAMEBUFFER, null), r.viewport(0, 0, r.canvas.width, r.canvas.height)), n.use(), r.bindBuffer(r.ARRAY_BUFFER, this.buffer);
|
|
408
|
+
const a = n.getAttribLocation("aVertexPosition");
|
|
409
|
+
a !== -1 && (r.enableVertexAttribArray(a), r.vertexAttribPointer(a, 2, r.FLOAT, !1, 16, 0));
|
|
410
|
+
const l = n.getAttribLocation("aTexCoord");
|
|
411
|
+
l !== -1 && (r.enableVertexAttribArray(l), r.vertexAttribPointer(l, 2, r.FLOAT, !1, 16, 8));
|
|
412
|
+
let c = 0;
|
|
413
|
+
for (const h in o) {
|
|
414
|
+
const d = o[h];
|
|
415
|
+
d instanceof WebGLTexture ? (r.activeTexture(r.TEXTURE0 + c), r.bindTexture(r.TEXTURE_2D, d), n.setUniform(h, c, "1i"), c++) : n.setUniform(h, d);
|
|
416
|
+
}
|
|
417
|
+
r.drawArrays(r.TRIANGLE_STRIP, 0, 4);
|
|
418
|
+
for (let h = 0; h < c; h++)
|
|
419
|
+
r.activeTexture(r.TEXTURE0 + h), r.bindTexture(r.TEXTURE_2D, null);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
class $e {
|
|
423
|
+
constructor(e, t = "Material") {
|
|
424
|
+
this.shader = e, this.uniforms = {}, this.name = t;
|
|
425
|
+
}
|
|
426
|
+
setUniforms(e) {
|
|
427
|
+
for (const t in e) {
|
|
428
|
+
let i = e[t];
|
|
429
|
+
Array.isArray(i) || i instanceof Float32Array ? i.length === 2 ? this.setVec2(t, i[0], i[1]) : i.length === 3 ? this.setVec3(t, i[0], i[1], i[2]) : i.length === 4 ? this.setVec4(t, i[0], i[1], i[2], i[3]) : i.length === 16 && this.setMat4(t, i) : typeof i == "number" ? this.setFloat(t, i) : i instanceof WebGLTexture && (this.uniforms[t] = { value: i, type: "Texture" });
|
|
430
|
+
}
|
|
431
|
+
return this;
|
|
432
|
+
}
|
|
433
|
+
setFloat(e, t) {
|
|
434
|
+
this.uniforms[e] && this.uniforms[e].type === "1f" ? this.uniforms[e].value = t : this.uniforms[e] = { type: "1f", value: t };
|
|
435
|
+
}
|
|
436
|
+
setVec2(e, t, i) {
|
|
437
|
+
if (this.uniforms[e] && this.uniforms[e].type === "2fv") {
|
|
438
|
+
const r = this.uniforms[e].value;
|
|
439
|
+
r[0] = t, r[1] = i;
|
|
440
|
+
} else
|
|
441
|
+
this.uniforms[e] = { type: "2fv", value: new Float32Array([t, i]) };
|
|
442
|
+
}
|
|
443
|
+
setVec3(e, t, i, r) {
|
|
444
|
+
if (this.uniforms[e] && this.uniforms[e].type === "3fv") {
|
|
445
|
+
const n = this.uniforms[e].value;
|
|
446
|
+
n[0] = t, n[1] = i, n[2] = r;
|
|
447
|
+
} else
|
|
448
|
+
this.uniforms[e] = { type: "3fv", value: new Float32Array([t, i, r]) };
|
|
449
|
+
}
|
|
450
|
+
setVec4(e, t, i, r, n) {
|
|
451
|
+
if (this.uniforms[e] && this.uniforms[e].type === "4fv") {
|
|
452
|
+
const o = this.uniforms[e].value;
|
|
453
|
+
o[0] = t, o[1] = i, o[2] = r, o[3] = n;
|
|
454
|
+
} else
|
|
455
|
+
this.uniforms[e] = { type: "4fv", value: new Float32Array([t, i, r, n]) };
|
|
456
|
+
}
|
|
457
|
+
setMat4(e, t) {
|
|
458
|
+
this.uniforms[e] = { type: "Matrix4fv", value: t };
|
|
459
|
+
}
|
|
460
|
+
// Helper for direct array setting if user prefers
|
|
461
|
+
setUniform(e, t, i) {
|
|
462
|
+
this.uniforms[e] = { type: i, value: t };
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
class ke {
|
|
466
|
+
constructor(e) {
|
|
467
|
+
this.gl = e, this.drawCalls = 0, this.currentPassDrawCalls = [], this.drawCallDetails = [];
|
|
468
|
+
const t = new Float32Array([
|
|
469
|
+
-0.5,
|
|
470
|
+
0.5,
|
|
471
|
+
0,
|
|
472
|
+
-0.5,
|
|
473
|
+
-0.5,
|
|
474
|
+
0,
|
|
475
|
+
0.5,
|
|
476
|
+
0.5,
|
|
477
|
+
0,
|
|
478
|
+
0.5,
|
|
479
|
+
0.5,
|
|
480
|
+
0,
|
|
481
|
+
-0.5,
|
|
482
|
+
-0.5,
|
|
483
|
+
0,
|
|
484
|
+
0.5,
|
|
485
|
+
-0.5,
|
|
486
|
+
0
|
|
487
|
+
]), i = new Float32Array([
|
|
488
|
+
0,
|
|
489
|
+
1,
|
|
490
|
+
0,
|
|
491
|
+
0,
|
|
492
|
+
1,
|
|
493
|
+
1,
|
|
494
|
+
1,
|
|
495
|
+
1,
|
|
496
|
+
0,
|
|
497
|
+
0,
|
|
498
|
+
1,
|
|
499
|
+
0
|
|
500
|
+
]), r = new Float32Array([
|
|
501
|
+
0,
|
|
502
|
+
0,
|
|
503
|
+
1,
|
|
504
|
+
0,
|
|
505
|
+
0,
|
|
506
|
+
1,
|
|
507
|
+
0,
|
|
508
|
+
0,
|
|
509
|
+
1,
|
|
510
|
+
0,
|
|
511
|
+
0,
|
|
512
|
+
1,
|
|
513
|
+
0,
|
|
514
|
+
0,
|
|
515
|
+
1,
|
|
516
|
+
0,
|
|
517
|
+
0,
|
|
518
|
+
1
|
|
519
|
+
]);
|
|
520
|
+
this.defaultMesh = new N(e, t, i, r);
|
|
521
|
+
}
|
|
522
|
+
draw(e, t, i = void 0, r = null) {
|
|
523
|
+
const n = r || e.material;
|
|
524
|
+
if (!n || !n.shader) return;
|
|
525
|
+
const o = this.gl, a = e.mesh || this.defaultMesh;
|
|
526
|
+
i !== void 0 && (i ? i.bind() : (o.bindFramebuffer(o.FRAMEBUFFER, null), o.viewport(0, 0, o.canvas.width, o.canvas.height)));
|
|
527
|
+
const l = n.shader;
|
|
528
|
+
l.use(), a.bind(l), l.setUniform("uProjectionMatrix", t.projectionMatrix), l.setUniform("uViewMatrix", t.viewMatrix), l.setUniform("uModelMatrix", e.transform.worldMatrix);
|
|
529
|
+
let c = 0;
|
|
530
|
+
for (const h in n.uniforms) {
|
|
531
|
+
const d = n.uniforms[h];
|
|
532
|
+
let u = d.value, f = d.type;
|
|
533
|
+
(u instanceof WebGLTexture || f === "1i" && u && typeof u == "object") && (o.activeTexture(o.TEXTURE0 + c), o.bindTexture(o.TEXTURE_2D, u), (o.isTexture(u) || u instanceof WebGLTexture) && (u = c, f = "1i", c++)), l.setUniform(h, u, f);
|
|
534
|
+
}
|
|
535
|
+
a.draw(), this.drawCalls++, this.drawCallDetails.push({
|
|
536
|
+
object: e ? e.name : "Unknown",
|
|
537
|
+
material: n ? n.name : "Unknown",
|
|
538
|
+
shader: l ? l.name || "Shader" : "Unknown",
|
|
539
|
+
target: i ? "RenderTarget" : "Screen"
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
resetDrawCalls() {
|
|
543
|
+
const e = this.drawCalls, t = [...this.drawCallDetails];
|
|
544
|
+
return this.drawCalls = 0, this.drawCallDetails = [], { count: e, details: t };
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
class Ve {
|
|
548
|
+
constructor(e, t, i, r = {}) {
|
|
549
|
+
this.gl = e, this.width = t, this.height = i, this.framebuffer = e.createFramebuffer(), e.bindFramebuffer(e.FRAMEBUFFER, this.framebuffer), this.texture = e.createTexture(), e.bindTexture(e.TEXTURE_2D, this.texture), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, t, i, 0, e.RGBA, e.UNSIGNED_BYTE, null);
|
|
550
|
+
const n = r.minFilter !== void 0 ? r.minFilter : e.LINEAR, o = r.magFilter !== void 0 ? r.magFilter : e.LINEAR, a = r.wrapS !== void 0 ? r.wrapS : e.CLAMP_TO_EDGE, l = r.wrapT !== void 0 ? r.wrapT : e.CLAMP_TO_EDGE;
|
|
551
|
+
e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, n), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, o), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, a), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, l), e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, this.texture, 0), this.depthBuffer = e.createRenderbuffer(), e.bindRenderbuffer(e.RENDERBUFFER, this.depthBuffer), e.renderbufferStorage(e.RENDERBUFFER, e.DEPTH_COMPONENT16, t, i), e.framebufferRenderbuffer(e.FRAMEBUFFER, e.DEPTH_ATTACHMENT, e.RENDERBUFFER, this.depthBuffer);
|
|
552
|
+
const c = e.checkFramebufferStatus(e.FRAMEBUFFER);
|
|
553
|
+
c !== e.FRAMEBUFFER_COMPLETE && console.error("Framebuffer is not complete: " + c), e.bindTexture(e.TEXTURE_2D, null), e.bindRenderbuffer(e.RENDERBUFFER, null), e.bindFramebuffer(e.FRAMEBUFFER, null);
|
|
554
|
+
}
|
|
555
|
+
bind() {
|
|
556
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.framebuffer), this.gl.viewport(0, 0, this.width, this.height);
|
|
557
|
+
}
|
|
558
|
+
unbind() {
|
|
559
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
560
|
+
}
|
|
561
|
+
resize(e, t) {
|
|
562
|
+
if (this.width === e && this.height === t) return;
|
|
563
|
+
this.width = e, this.height = t;
|
|
564
|
+
const i = this.gl;
|
|
565
|
+
i.bindTexture(i.TEXTURE_2D, this.texture), i.texImage2D(i.TEXTURE_2D, 0, i.RGBA, e, t, 0, i.RGBA, i.UNSIGNED_BYTE, null), i.bindRenderbuffer(i.RENDERBUFFER, this.depthBuffer), i.renderbufferStorage(i.RENDERBUFFER, i.DEPTH_COMPONENT16, e, t), i.bindTexture(i.TEXTURE_2D, null), i.bindRenderbuffer(i.RENDERBUFFER, null);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
class Oe {
|
|
569
|
+
constructor(e, t, i) {
|
|
570
|
+
this.gl = e;
|
|
571
|
+
const r = this.loadShader(e.VERTEX_SHADER, t), n = this.loadShader(e.FRAGMENT_SHADER, i);
|
|
572
|
+
this.program = e.createProgram(), e.attachShader(this.program, r), e.attachShader(this.program, n), e.linkProgram(this.program), e.getProgramParameter(this.program, e.LINK_STATUS) || console.error("Shader init error:", e.getProgramInfoLog(this.program)), this.uniforms = {}, this.attributes = {};
|
|
573
|
+
}
|
|
574
|
+
getUniformLocation(e) {
|
|
575
|
+
return this.uniforms[e] === void 0 && (this.uniforms[e] = this.gl.getUniformLocation(this.program, e)), this.uniforms[e];
|
|
576
|
+
}
|
|
577
|
+
setUniform(e, t, i) {
|
|
578
|
+
const r = this.gl, n = this.getUniformLocation(e);
|
|
579
|
+
if (n) {
|
|
580
|
+
if (i) {
|
|
581
|
+
i === "1i" ? r.uniform1i(n, t) : i === "1f" ? r.uniform1f(n, t) : i === "2fv" ? r.uniform2fv(n, t) : i === "3fv" ? r.uniform3fv(n, t) : i === "4fv" ? r.uniform4fv(n, t) : i === "Matrix4fv" && r.uniformMatrix4fv(n, !1, t);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
if (typeof t == "number")
|
|
585
|
+
r.uniform1f(n, t);
|
|
586
|
+
else if (Array.isArray(t) || t instanceof Float32Array)
|
|
587
|
+
switch (t.length) {
|
|
588
|
+
case 2:
|
|
589
|
+
r.uniform2fv(n, t);
|
|
590
|
+
break;
|
|
591
|
+
case 3:
|
|
592
|
+
r.uniform3fv(n, t);
|
|
593
|
+
break;
|
|
594
|
+
case 4:
|
|
595
|
+
r.uniform4fv(n, t);
|
|
596
|
+
break;
|
|
597
|
+
case 16:
|
|
598
|
+
r.uniformMatrix4fv(n, !1, t);
|
|
599
|
+
break;
|
|
600
|
+
default:
|
|
601
|
+
console.warn(`Unsupported uniform array length: ${t.length} for ${e}`);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
getAttribLocation(e) {
|
|
606
|
+
return this.attributes[e] === void 0 && (this.attributes[e] = this.gl.getAttribLocation(this.program, e)), this.attributes[e];
|
|
607
|
+
}
|
|
608
|
+
use() {
|
|
609
|
+
this.gl.useProgram(this.program);
|
|
610
|
+
}
|
|
611
|
+
loadShader(e, t) {
|
|
612
|
+
const i = this.gl.createShader(e);
|
|
613
|
+
return this.gl.shaderSource(i, t), this.gl.compileShader(i), this.gl.getShaderParameter(i, this.gl.COMPILE_STATUS) ? i : (console.error("Shader compile error:", this.gl.getShaderInfoLog(i)), this.gl.deleteShader(i), null);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
class Be {
|
|
617
|
+
constructor(e, t) {
|
|
618
|
+
this.gl = e, this.texture = e.createTexture(), this.image = new Image(), this.loaded = !1, e.bindTexture(e.TEXTURE_2D, this.texture), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, 1, 1, 0, e.RGBA, e.UNSIGNED_BYTE, new Uint8Array([255, 0, 255, 255])), this.image.onload = () => {
|
|
619
|
+
e.bindTexture(e.TEXTURE_2D, this.texture), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, this.image), this.isPowerOf2(this.image.width) && this.isPowerOf2(this.image.height) ? e.generateMipmap(e.TEXTURE_2D) : (e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR)), this.loaded = !0;
|
|
620
|
+
}, this.image.src = t;
|
|
621
|
+
}
|
|
622
|
+
isPowerOf2(e) {
|
|
623
|
+
return (e & e - 1) === 0;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
class ze {
|
|
627
|
+
constructor() {
|
|
628
|
+
this.passes = [];
|
|
629
|
+
}
|
|
630
|
+
addPass(e) {
|
|
631
|
+
this.passes.push(e);
|
|
632
|
+
}
|
|
633
|
+
removePass(e) {
|
|
634
|
+
const t = this.passes.indexOf(e);
|
|
635
|
+
t > -1 && this.passes.splice(t, 1);
|
|
636
|
+
}
|
|
637
|
+
execute(e, t, i) {
|
|
638
|
+
for (const r of this.passes)
|
|
639
|
+
r.enabled && r.execute(e, t, i);
|
|
640
|
+
}
|
|
641
|
+
resize(e, t) {
|
|
642
|
+
for (const i of this.passes)
|
|
643
|
+
i.resize(e, t);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
class z {
|
|
647
|
+
constructor(e, t, i, r = "RenderPass") {
|
|
648
|
+
this.gl = e, this.width = t, this.height = i, this.name = r, this.enabled = !0, this.autoResize = !0, this.drawCount = 0, this.executionTime = 0;
|
|
649
|
+
}
|
|
650
|
+
resize(e, t) {
|
|
651
|
+
this.autoResize && (this.width = e, this.height = t);
|
|
652
|
+
}
|
|
653
|
+
execute(e, t, i) {
|
|
654
|
+
console.warn("RenderPass.execute() not implemented");
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
class k extends z {
|
|
658
|
+
constructor(e, t, i, r, n = null, o = "ScreenPass") {
|
|
659
|
+
super(e, t, i, o), this.material = r, this.renderTarget = n, this.fullScreenQuad = new j(e), this.inputs = {}, this.clearColor = null;
|
|
660
|
+
}
|
|
661
|
+
setTexture(e, t) {
|
|
662
|
+
this.inputs[e] = t;
|
|
663
|
+
}
|
|
664
|
+
resize(e, t) {
|
|
665
|
+
super.resize(e, t), this.renderTarget && this.renderTarget.resize(e, t);
|
|
666
|
+
}
|
|
667
|
+
execute(e, t, i) {
|
|
668
|
+
const r = performance.now();
|
|
669
|
+
e.resetDrawCalls(), this.renderTarget ? this.renderTarget.bind() : (this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null), this.gl.viewport(0, 0, this.width, this.height)), this.clearColor && (this.gl.clearColor(this.clearColor[0], this.clearColor[1], this.clearColor[2], this.clearColor[3]), this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT));
|
|
670
|
+
for (const [o, a] of Object.entries(this.inputs))
|
|
671
|
+
this.material.setUniform(o, a);
|
|
672
|
+
this.material.setUniform("uResolution", [this.width, this.height]), this.fullScreenQuad.draw(this.material, this.renderTarget), this.renderTarget && this.renderTarget.unbind();
|
|
673
|
+
const n = e.resetDrawCalls();
|
|
674
|
+
this.drawCount = n.count, this.drawDetails = n.details, this.executionTime = performance.now() - r;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
class Ie extends z {
|
|
678
|
+
constructor(e, t, i, r = null, n = null, o = "ObjectPass") {
|
|
679
|
+
super(e, t, i, o), this.renderTarget = r, this.materialOverride = n, this.clearColor = [0, 0, 0, 1], this.clearDepth = !0, this.camera = null;
|
|
680
|
+
}
|
|
681
|
+
resize(e, t) {
|
|
682
|
+
this.autoResize && (super.resize(e, t), this.renderTarget && this.renderTarget.resize(e, t));
|
|
683
|
+
}
|
|
684
|
+
execute(e, t, i) {
|
|
685
|
+
const r = this.camera || i;
|
|
686
|
+
this.camera && r.updateView();
|
|
687
|
+
const n = performance.now();
|
|
688
|
+
if (e.resetDrawCalls(), this.renderTarget ? this.renderTarget.bind() : (this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null), this.gl.viewport(0, 0, this.width, this.height)), this.clearColor) {
|
|
689
|
+
this.gl.clearColor(this.clearColor[0], this.clearColor[1], this.clearColor[2], this.clearColor[3]);
|
|
690
|
+
let a = this.gl.COLOR_BUFFER_BIT;
|
|
691
|
+
this.clearDepth && (a |= this.gl.DEPTH_BUFFER_BIT), this.gl.clear(a);
|
|
692
|
+
}
|
|
693
|
+
if (t && Array.isArray(t))
|
|
694
|
+
for (const a of t)
|
|
695
|
+
if (this.materialOverride) {
|
|
696
|
+
let l = this.materialOverride;
|
|
697
|
+
this.name === "Depth Pass" && a.depthMaterial ? l = a.depthMaterial : this.name === "Normal Pass" && a.normalMaterial ? l = a.normalMaterial : this.name === "Shadow Pass" && a.shadowMaterial && (l = a.shadowMaterial), a.render(r, this.renderTarget, l);
|
|
698
|
+
} else
|
|
699
|
+
a.render(r, this.renderTarget);
|
|
700
|
+
else t && t.render && t.render(r, this.renderTarget, this.materialOverride);
|
|
701
|
+
this.renderTarget && this.renderTarget.unbind();
|
|
702
|
+
const o = e.resetDrawCalls();
|
|
703
|
+
this.drawCount = o.count, this.drawDetails = o.details, this.executionTime = performance.now() - n;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
class Ne extends z {
|
|
707
|
+
constructor(e, t, i, r) {
|
|
708
|
+
super(e, t, i, "ViewportComposition"), this.material = r, this.fullScreenQuad = new j(e), this.buffers = {}, this.viewports = [], this.overlay = null;
|
|
709
|
+
}
|
|
710
|
+
setBuffer(e, t) {
|
|
711
|
+
this.buffers[e] = t;
|
|
712
|
+
}
|
|
713
|
+
setOverlay(e) {
|
|
714
|
+
this.overlay = e;
|
|
715
|
+
}
|
|
716
|
+
setViewports(e) {
|
|
717
|
+
this.viewports = e;
|
|
718
|
+
}
|
|
719
|
+
execute(e, t, i) {
|
|
720
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null), this.gl.viewport(0, 0, this.width, this.height), this.gl.clearColor(0.1, 0.1, 0.1, 1), this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
|
|
721
|
+
for (const r of this.viewports) {
|
|
722
|
+
const n = Math.floor(r.x * this.width), o = Math.floor(r.y * this.height), a = Math.floor(r.w * this.width), l = Math.floor(r.h * this.height);
|
|
723
|
+
this.gl.viewport(n, o, a, l);
|
|
724
|
+
let c = this.buffers.Final;
|
|
725
|
+
const h = r.pass;
|
|
726
|
+
this.buffers[h] && (c = this.buffers[h]), this.material.setUniform("uTexture", c), this.overlay ? (this.material.setUniform("uOverlay", this.overlay), this.material.setUniform("uUseOverlay", 1)) : this.material.setUniform("uUseOverlay", 0), this.fullScreenQuad.draw(this.material);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
class je extends k {
|
|
731
|
+
constructor(e, t, i, r, n = null, o = "Lighting Pass") {
|
|
732
|
+
super(e, t, i, r, n, o), this.lightCamera = null;
|
|
733
|
+
}
|
|
734
|
+
// Set buffers from previous passes
|
|
735
|
+
setInputBuffers(e, t, i, r) {
|
|
736
|
+
this.setTexture("uSceneTexture", e), this.setTexture("uNormalTexture", t), this.setTexture("uDepthTexture", i), this.setTexture("uShadowMap", r);
|
|
737
|
+
}
|
|
738
|
+
execute(e, t, i) {
|
|
739
|
+
this.lightCamera && this.setMatricesFromCameras(i, this.lightCamera), super.execute(e, t, i);
|
|
740
|
+
}
|
|
741
|
+
setMatricesFromCameras(e, t) {
|
|
742
|
+
const i = new Float32Array(16);
|
|
743
|
+
R.multiply(i, t.projectionMatrix, t.viewMatrix);
|
|
744
|
+
const r = new Float32Array(16);
|
|
745
|
+
R.multiply(r, e.projectionMatrix, e.viewMatrix);
|
|
746
|
+
const n = new Float32Array(16);
|
|
747
|
+
this.invertMatrix(r, n);
|
|
748
|
+
const o = e.transform.position;
|
|
749
|
+
this.material.setUniforms({
|
|
750
|
+
uLightSpaceMatrix: i,
|
|
751
|
+
uInverseViewProjection: n,
|
|
752
|
+
uCameraPos: [o.x, o.y, o.z]
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
setMatrices(e, t) {
|
|
756
|
+
this.material.setUniforms({
|
|
757
|
+
uInverseViewProjection: e,
|
|
758
|
+
uLightSpaceMatrix: t
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
setLight(e, t, i) {
|
|
762
|
+
this.material.setUniforms({
|
|
763
|
+
uLightDir: e,
|
|
764
|
+
uLightColor: t,
|
|
765
|
+
uAmbient: i
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
invertMatrix(e, t) {
|
|
769
|
+
let i = e[0], r = e[1], n = e[2], o = e[3], a = e[4], l = e[5], c = e[6], h = e[7], d = e[8], u = e[9], f = e[10], x = e[11], v = e[12], C = e[13], m = e[14], p = e[15], g = i * l - r * a, w = i * c - n * a, b = i * h - o * a, E = r * c - n * l, _ = r * h - o * l, F = n * h - o * c, D = d * C - u * v, A = d * m - f * v, S = d * p - x * v, M = u * m - f * C, P = u * p - x * C, T = f * p - x * m, y = g * T - w * P + b * M + E * S - _ * A + F * D;
|
|
770
|
+
return y ? (y = 1 / y, t[0] = (l * T - c * P + h * M) * y, t[1] = (n * P - r * T - o * M) * y, t[2] = (C * F - m * _ + p * E) * y, t[3] = (f * _ - u * F - x * E) * y, t[4] = (c * S - a * T - h * A) * y, t[5] = (i * T - n * S + o * A) * y, t[6] = (m * b - v * F - p * w) * y, t[7] = (d * F - f * b + x * w) * y, t[8] = (a * P - l * S + h * D) * y, t[9] = (r * S - i * P - o * D) * y, t[10] = (v * _ - C * b + p * g) * y, t[11] = (u * b - d * _ - x * g) * y, t[12] = (l * A - a * M - c * D) * y, t[13] = (i * M - r * A + n * D) * y, t[14] = (C * w - v * E - m * g) * y, t[15] = (d * E - u * w + f * g) * y, !0) : !1;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
class He extends k {
|
|
774
|
+
constructor(e, t, i, r, n = null, o = "Skybox Pass") {
|
|
775
|
+
super(e, t, i, r, n, o), this.clearColor = null, this.clearDepth = !1;
|
|
776
|
+
}
|
|
777
|
+
setCamera(e) {
|
|
778
|
+
const t = new Float32Array(16);
|
|
779
|
+
R.multiply(t, e.projectionMatrix, e.viewMatrix);
|
|
780
|
+
const i = new Float32Array(16);
|
|
781
|
+
this.invertMatrix(t, i), this.material.setUniforms({
|
|
782
|
+
uInverseViewProjection: i,
|
|
783
|
+
uCameraPos: [e.transform.position.x, e.transform.position.y, e.transform.position.z]
|
|
784
|
+
// We pass pos as array or vec3
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
setLight(e, t, i, r) {
|
|
788
|
+
this.material.setUniforms({
|
|
789
|
+
uLightDir: e,
|
|
790
|
+
uSunColor: t,
|
|
791
|
+
uTopColor: i,
|
|
792
|
+
uBottomColor: r
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
setInputTexture(e) {
|
|
796
|
+
this.setTexture("uDepthTexture", e);
|
|
797
|
+
}
|
|
798
|
+
execute(e, t, i) {
|
|
799
|
+
this.setCamera(i), super.execute(e, t, i);
|
|
800
|
+
}
|
|
801
|
+
invertMatrix(e, t) {
|
|
802
|
+
let i = e[0], r = e[1], n = e[2], o = e[3], a = e[4], l = e[5], c = e[6], h = e[7], d = e[8], u = e[9], f = e[10], x = e[11], v = e[12], C = e[13], m = e[14], p = e[15], g = i * l - r * a, w = i * c - n * a, b = i * h - o * a, E = r * c - n * l, _ = r * h - o * l, F = n * h - o * c, D = d * C - u * v, A = d * m - f * v, S = d * p - x * v, M = u * m - f * C, P = u * p - x * C, T = f * p - x * m, y = g * T - w * P + b * M + E * S - _ * A + F * D;
|
|
803
|
+
return y ? (y = 1 / y, t[0] = (l * T - c * P + h * M) * y, t[1] = (n * P - r * T - o * M) * y, t[2] = (C * F - m * _ + p * E) * y, t[3] = (f * _ - u * F - x * E) * y, t[4] = (c * S - a * T - h * A) * y, t[5] = (i * T - n * S + o * A) * y, t[6] = (m * b - v * F - p * w) * y, t[7] = (d * F - f * b + x * w) * y, t[8] = (a * P - l * S + h * D) * y, t[9] = (r * S - i * P - o * D) * y, t[10] = (v * _ - C * b + p * g) * y, t[11] = (u * b - d * _ - x * g) * y, t[12] = (l * A - a * M - c * D) * y, t[13] = (i * M - r * A + n * D) * y, t[14] = (C * w - v * E - m * g) * y, t[15] = (d * E - u * w + f * g) * y, !0) : !1;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
class Xe extends k {
|
|
807
|
+
constructor(e, t, i, r, n = null, o = "Outline Pass") {
|
|
808
|
+
super(e, t, i, r, n, o), this.clearColor = [0, 0, 0, 0];
|
|
809
|
+
}
|
|
810
|
+
setInputBuffers(e, t) {
|
|
811
|
+
this.setTexture("uDepthTexture", e), this.setTexture("uNormalTexture", t), this.setTexture("uSceneTexture", e);
|
|
812
|
+
}
|
|
813
|
+
resize(e, t) {
|
|
814
|
+
super.resize(e, t), this.material.setUniform("uResolution", [e, t]);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
class We extends k {
|
|
818
|
+
constructor(e, t, i, r, n, o = "PixelArt Pass") {
|
|
819
|
+
super(e, t, i, r, n, o);
|
|
820
|
+
}
|
|
821
|
+
setInputBuffers(e, t, i) {
|
|
822
|
+
this.setTexture("uSceneTexture", e), this.setTexture("uDepthTexture", t), this.setTexture("uNormalTexture", i);
|
|
823
|
+
}
|
|
824
|
+
resize(e, t) {
|
|
825
|
+
super.resize(e, t), this.material.setUniform("uResolution", [e, t]);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
class q {
|
|
829
|
+
constructor() {
|
|
830
|
+
this.container = document.createElement("div"), this.container.id = "editor-ui-root", Object.assign(this.container.style, {
|
|
831
|
+
position: "absolute",
|
|
832
|
+
top: "0",
|
|
833
|
+
left: "0",
|
|
834
|
+
width: "100%",
|
|
835
|
+
height: "100%",
|
|
836
|
+
pointerEvents: "none",
|
|
837
|
+
zIndex: "9999",
|
|
838
|
+
fontFamily: "sans-serif"
|
|
839
|
+
}), document.body.appendChild(this.container), this.initNavBar();
|
|
840
|
+
}
|
|
841
|
+
initNavBar() {
|
|
842
|
+
this.navBar = document.createElement("div"), this.navBar.id = "editor-navbar", Object.assign(this.navBar.style, {
|
|
843
|
+
position: "absolute",
|
|
844
|
+
top: "10px",
|
|
845
|
+
left: "50%",
|
|
846
|
+
transform: "translateX(-50%)",
|
|
847
|
+
display: "flex",
|
|
848
|
+
gap: "5px",
|
|
849
|
+
background: "rgba(26, 26, 26, 0.9)",
|
|
850
|
+
padding: "5px 10px",
|
|
851
|
+
borderRadius: "20px",
|
|
852
|
+
border: "1px solid #333",
|
|
853
|
+
pointerEvents: "auto",
|
|
854
|
+
boxShadow: "0 4px 10px rgba(0,0,0,0.5)",
|
|
855
|
+
zIndex: "10001"
|
|
856
|
+
}), this.container.appendChild(this.navBar), this.addDragLogic(this.navBar, this.navBar);
|
|
857
|
+
}
|
|
858
|
+
addNavItem(e, t) {
|
|
859
|
+
const i = document.createElement("button");
|
|
860
|
+
i.innerText = e, Object.assign(i.style, {
|
|
861
|
+
background: "#252525",
|
|
862
|
+
color: "#ccc",
|
|
863
|
+
border: "1px solid #444",
|
|
864
|
+
padding: "4px 12px",
|
|
865
|
+
borderRadius: "15px",
|
|
866
|
+
fontSize: "10px",
|
|
867
|
+
fontWeight: "bold",
|
|
868
|
+
cursor: "pointer",
|
|
869
|
+
transition: "background 0.2s",
|
|
870
|
+
outline: "none"
|
|
871
|
+
}), i.onclick = () => {
|
|
872
|
+
const r = t.style.display === "none";
|
|
873
|
+
t.style.display = r ? "flex" : "none", i.style.background = r ? "#444" : "#252525";
|
|
874
|
+
}, i.onmouseover = () => {
|
|
875
|
+
t.style.display === "none" && (i.style.background = "#333");
|
|
876
|
+
}, i.onmouseout = () => {
|
|
877
|
+
t.style.display === "none" && (i.style.background = "#252525");
|
|
878
|
+
}, i.style.background = t.style.display === "none" ? "#252525" : "#444", this.navBar.appendChild(i);
|
|
879
|
+
}
|
|
880
|
+
addNavSelect(e, t) {
|
|
881
|
+
const i = document.createElement("select");
|
|
882
|
+
Object.assign(i.style, {
|
|
883
|
+
background: "#252525",
|
|
884
|
+
color: "#ccc",
|
|
885
|
+
border: "1px solid #444",
|
|
886
|
+
padding: "4px 8px",
|
|
887
|
+
borderRadius: "15px",
|
|
888
|
+
fontSize: "10px",
|
|
889
|
+
fontWeight: "bold",
|
|
890
|
+
cursor: "pointer",
|
|
891
|
+
outline: "none",
|
|
892
|
+
marginLeft: "10px"
|
|
893
|
+
}), e.forEach((r) => {
|
|
894
|
+
const n = document.createElement("option");
|
|
895
|
+
n.value = r, n.text = r, i.appendChild(n);
|
|
896
|
+
}), i.onchange = (r) => t(r.target.value), this.navBar.appendChild(i);
|
|
897
|
+
}
|
|
898
|
+
toggleVisibility() {
|
|
899
|
+
const e = this.container.style.display === "none";
|
|
900
|
+
this.container.style.display = e ? "block" : "none";
|
|
901
|
+
}
|
|
902
|
+
createWindow(e, t, i, r, n) {
|
|
903
|
+
const o = document.createElement("div");
|
|
904
|
+
Object.assign(o.style, {
|
|
905
|
+
position: "absolute",
|
|
906
|
+
left: `${t}px`,
|
|
907
|
+
top: `${i}px`,
|
|
908
|
+
width: `${r}px`,
|
|
909
|
+
height: `${n}px`,
|
|
910
|
+
backgroundColor: "#1a1a1a",
|
|
911
|
+
border: "1px solid #333",
|
|
912
|
+
display: "flex",
|
|
913
|
+
flexDirection: "column",
|
|
914
|
+
pointerEvents: "auto",
|
|
915
|
+
overflow: "hidden",
|
|
916
|
+
boxShadow: "0 4px 15px rgba(0,0,0,0.5)"
|
|
917
|
+
});
|
|
918
|
+
const a = document.createElement("div");
|
|
919
|
+
a.innerText = e, Object.assign(a.style, {
|
|
920
|
+
padding: "6px 10px",
|
|
921
|
+
background: "#252525",
|
|
922
|
+
color: "#ccc",
|
|
923
|
+
fontSize: "11px",
|
|
924
|
+
fontWeight: "bold",
|
|
925
|
+
cursor: "move",
|
|
926
|
+
userSelect: "none",
|
|
927
|
+
borderBottom: "1px solid #333",
|
|
928
|
+
textTransform: "uppercase",
|
|
929
|
+
display: "flex",
|
|
930
|
+
justifyContent: "space-between",
|
|
931
|
+
alignItems: "center"
|
|
932
|
+
});
|
|
933
|
+
const l = document.createElement("span");
|
|
934
|
+
l.innerHTML = "×", Object.assign(l.style, {
|
|
935
|
+
cursor: "pointer",
|
|
936
|
+
fontSize: "16px",
|
|
937
|
+
lineHeight: "1",
|
|
938
|
+
padding: "0 4px",
|
|
939
|
+
color: "#888"
|
|
940
|
+
}), l.onclick = () => {
|
|
941
|
+
o.style.display = "none";
|
|
942
|
+
}, l.onmouseover = () => {
|
|
943
|
+
l.style.color = "#fff";
|
|
944
|
+
}, l.onmouseout = () => {
|
|
945
|
+
l.style.color = "#888";
|
|
946
|
+
}, a.appendChild(l);
|
|
947
|
+
const c = document.createElement("div");
|
|
948
|
+
c.classList.add("window-content"), Object.assign(c.style, {
|
|
949
|
+
flex: "1",
|
|
950
|
+
overflow: "auto",
|
|
951
|
+
background: "#111",
|
|
952
|
+
position: "relative",
|
|
953
|
+
width: "100%",
|
|
954
|
+
height: "100%"
|
|
955
|
+
});
|
|
956
|
+
const h = document.createElement("div");
|
|
957
|
+
return Object.assign(h.style, {
|
|
958
|
+
width: "10px",
|
|
959
|
+
height: "10px",
|
|
960
|
+
background: "#444",
|
|
961
|
+
position: "absolute",
|
|
962
|
+
right: "0",
|
|
963
|
+
bottom: "0",
|
|
964
|
+
cursor: "nwse-resize",
|
|
965
|
+
zIndex: "10"
|
|
966
|
+
}), o.appendChild(a), o.appendChild(c), o.appendChild(h), this.container.appendChild(o), this.addDragLogic(o, a), this.addResizeLogic(o, h), { content: c, window: o };
|
|
967
|
+
}
|
|
968
|
+
addResizeLogic(e, t) {
|
|
969
|
+
let i = !1, r, n, o, a;
|
|
970
|
+
t.addEventListener("mousedown", (h) => {
|
|
971
|
+
h.preventDefault(), h.stopPropagation(), i = !0, o = h.clientX, a = h.clientY, r = e.offsetWidth, n = e.offsetHeight, document.addEventListener("mousemove", l), document.addEventListener("mouseup", c);
|
|
972
|
+
});
|
|
973
|
+
const l = (h) => {
|
|
974
|
+
if (!i) return;
|
|
975
|
+
const d = r + (h.clientX - o), u = n + (h.clientY - a);
|
|
976
|
+
d > 100 && (e.style.width = d + "px"), u > 100 && (e.style.height = u + "px");
|
|
977
|
+
}, c = () => {
|
|
978
|
+
i = !1, document.removeEventListener("mousemove", l), document.removeEventListener("mouseup", c);
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
addDragLogic(e, t) {
|
|
982
|
+
let i = !1, r, n, o, a;
|
|
983
|
+
t.addEventListener("mousedown", (h) => {
|
|
984
|
+
h.target.tagName !== "BUTTON" && (i = !0, r = h.clientX, n = h.clientY, o = e.offsetLeft, a = e.offsetTop, document.addEventListener("mousemove", l), document.addEventListener("mouseup", c), e.style.zIndex = "10000", e === this.navBar && (e.style.zIndex = "10001"), e !== this.navBar && (this.container.querySelectorAll(".window").forEach((d) => d.style.zIndex = "9999"), e.style.zIndex = "10000"));
|
|
985
|
+
});
|
|
986
|
+
const l = (h) => {
|
|
987
|
+
if (!i) return;
|
|
988
|
+
let d = o + (h.clientX - r), u = a + (h.clientY - n);
|
|
989
|
+
const f = 20;
|
|
990
|
+
d < f && (d = 0), u < f && (u = 0), Math.abs(window.innerWidth - (d + e.offsetWidth)) < f && (d = window.innerWidth - e.offsetWidth), Math.abs(window.innerHeight - (u + e.offsetHeight)) < f && (u = window.innerHeight - e.offsetHeight), e.style.left = d + "px", e.style.top = u + "px";
|
|
991
|
+
}, c = () => {
|
|
992
|
+
i = !1, document.removeEventListener("mousemove", l), document.removeEventListener("mouseup", c);
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* lil-gui
|
|
998
|
+
* https://lil-gui.georgealways.com
|
|
999
|
+
* @version 0.21.0
|
|
1000
|
+
* @author George Michael Brower
|
|
1001
|
+
* @license MIT
|
|
1002
|
+
*/
|
|
1003
|
+
class L {
|
|
1004
|
+
constructor(e, t, i, r, n = "div") {
|
|
1005
|
+
this.parent = e, this.object = t, this.property = i, this._disabled = !1, this._hidden = !1, this.initialValue = this.getValue(), this.domElement = document.createElement(n), this.domElement.classList.add("lil-controller"), this.domElement.classList.add(r), this.$name = document.createElement("div"), this.$name.classList.add("lil-name"), L.nextNameID = L.nextNameID || 0, this.$name.id = `lil-gui-name-${++L.nextNameID}`, this.$widget = document.createElement("div"), this.$widget.classList.add("lil-widget"), this.$disable = this.$widget, this.domElement.appendChild(this.$name), this.domElement.appendChild(this.$widget), this.domElement.addEventListener("keydown", (o) => o.stopPropagation()), this.domElement.addEventListener("keyup", (o) => o.stopPropagation()), this.parent.children.push(this), this.parent.controllers.push(this), this.parent.$children.appendChild(this.domElement), this._listenCallback = this._listenCallback.bind(this), this.name(i);
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Sets the name of the controller and its label in the GUI.
|
|
1009
|
+
* @param {string} name
|
|
1010
|
+
* @returns {this}
|
|
1011
|
+
*/
|
|
1012
|
+
name(e) {
|
|
1013
|
+
return this._name = e, this.$name.textContent = e, this;
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Pass a function to be called whenever the value is modified by this controller.
|
|
1017
|
+
* The function receives the new value as its first parameter. The value of `this` will be the
|
|
1018
|
+
* controller.
|
|
1019
|
+
*
|
|
1020
|
+
* For function controllers, the `onChange` callback will be fired on click, after the function
|
|
1021
|
+
* executes.
|
|
1022
|
+
* @param {Function} callback
|
|
1023
|
+
* @returns {this}
|
|
1024
|
+
* @example
|
|
1025
|
+
* const controller = gui.add( object, 'property' );
|
|
1026
|
+
*
|
|
1027
|
+
* controller.onChange( function( v ) {
|
|
1028
|
+
* console.log( 'The value is now ' + v );
|
|
1029
|
+
* console.assert( this === controller );
|
|
1030
|
+
* } );
|
|
1031
|
+
*/
|
|
1032
|
+
onChange(e) {
|
|
1033
|
+
return this._onChange = e, this;
|
|
1034
|
+
}
|
|
1035
|
+
/**
|
|
1036
|
+
* Calls the onChange methods of this controller and its parent GUI.
|
|
1037
|
+
* @protected
|
|
1038
|
+
*/
|
|
1039
|
+
_callOnChange() {
|
|
1040
|
+
this.parent._callOnChange(this), this._onChange !== void 0 && this._onChange.call(this, this.getValue()), this._changed = !0;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Pass a function to be called after this controller has been modified and loses focus.
|
|
1044
|
+
* @param {Function} callback
|
|
1045
|
+
* @returns {this}
|
|
1046
|
+
* @example
|
|
1047
|
+
* const controller = gui.add( object, 'property' );
|
|
1048
|
+
*
|
|
1049
|
+
* controller.onFinishChange( function( v ) {
|
|
1050
|
+
* console.log( 'Changes complete: ' + v );
|
|
1051
|
+
* console.assert( this === controller );
|
|
1052
|
+
* } );
|
|
1053
|
+
*/
|
|
1054
|
+
onFinishChange(e) {
|
|
1055
|
+
return this._onFinishChange = e, this;
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Should be called by Controller when its widgets lose focus.
|
|
1059
|
+
* @protected
|
|
1060
|
+
*/
|
|
1061
|
+
_callOnFinishChange() {
|
|
1062
|
+
this._changed && (this.parent._callOnFinishChange(this), this._onFinishChange !== void 0 && this._onFinishChange.call(this, this.getValue())), this._changed = !1;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Sets the controller back to its initial value.
|
|
1066
|
+
* @returns {this}
|
|
1067
|
+
*/
|
|
1068
|
+
reset() {
|
|
1069
|
+
return this.setValue(this.initialValue), this._callOnFinishChange(), this;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Enables this controller.
|
|
1073
|
+
* @param {boolean} enabled
|
|
1074
|
+
* @returns {this}
|
|
1075
|
+
* @example
|
|
1076
|
+
* controller.enable();
|
|
1077
|
+
* controller.enable( false ); // disable
|
|
1078
|
+
* controller.enable( controller._disabled ); // toggle
|
|
1079
|
+
*/
|
|
1080
|
+
enable(e = !0) {
|
|
1081
|
+
return this.disable(!e);
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Disables this controller.
|
|
1085
|
+
* @param {boolean} disabled
|
|
1086
|
+
* @returns {this}
|
|
1087
|
+
* @example
|
|
1088
|
+
* controller.disable();
|
|
1089
|
+
* controller.disable( false ); // enable
|
|
1090
|
+
* controller.disable( !controller._disabled ); // toggle
|
|
1091
|
+
*/
|
|
1092
|
+
disable(e = !0) {
|
|
1093
|
+
return e === this._disabled ? this : (this._disabled = e, this.domElement.classList.toggle("lil-disabled", e), this.$disable.toggleAttribute("disabled", e), this);
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Shows the Controller after it's been hidden.
|
|
1097
|
+
* @param {boolean} show
|
|
1098
|
+
* @returns {this}
|
|
1099
|
+
* @example
|
|
1100
|
+
* controller.show();
|
|
1101
|
+
* controller.show( false ); // hide
|
|
1102
|
+
* controller.show( controller._hidden ); // toggle
|
|
1103
|
+
*/
|
|
1104
|
+
show(e = !0) {
|
|
1105
|
+
return this._hidden = !e, this.domElement.style.display = this._hidden ? "none" : "", this;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Hides the Controller.
|
|
1109
|
+
* @returns {this}
|
|
1110
|
+
*/
|
|
1111
|
+
hide() {
|
|
1112
|
+
return this.show(!1);
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Changes this controller into a dropdown of options.
|
|
1116
|
+
*
|
|
1117
|
+
* Calling this method on an option controller will simply update the options. However, if this
|
|
1118
|
+
* controller was not already an option controller, old references to this controller are
|
|
1119
|
+
* destroyed, and a new controller is added to the end of the GUI.
|
|
1120
|
+
* @example
|
|
1121
|
+
* // safe usage
|
|
1122
|
+
*
|
|
1123
|
+
* gui.add( obj, 'prop1' ).options( [ 'a', 'b', 'c' ] );
|
|
1124
|
+
* gui.add( obj, 'prop2' ).options( { Big: 10, Small: 1 } );
|
|
1125
|
+
* gui.add( obj, 'prop3' );
|
|
1126
|
+
*
|
|
1127
|
+
* // danger
|
|
1128
|
+
*
|
|
1129
|
+
* const ctrl1 = gui.add( obj, 'prop1' );
|
|
1130
|
+
* gui.add( obj, 'prop2' );
|
|
1131
|
+
*
|
|
1132
|
+
* // calling options out of order adds a new controller to the end...
|
|
1133
|
+
* const ctrl2 = ctrl1.options( [ 'a', 'b', 'c' ] );
|
|
1134
|
+
*
|
|
1135
|
+
* // ...and ctrl1 now references a controller that doesn't exist
|
|
1136
|
+
* assert( ctrl2 !== ctrl1 )
|
|
1137
|
+
* @param {object|Array} options
|
|
1138
|
+
* @returns {Controller}
|
|
1139
|
+
*/
|
|
1140
|
+
options(e) {
|
|
1141
|
+
const t = this.parent.add(this.object, this.property, e);
|
|
1142
|
+
return t.name(this._name), this.destroy(), t;
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Sets the minimum value. Only works on number controllers.
|
|
1146
|
+
* @param {number} min
|
|
1147
|
+
* @returns {this}
|
|
1148
|
+
*/
|
|
1149
|
+
min(e) {
|
|
1150
|
+
return this;
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Sets the maximum value. Only works on number controllers.
|
|
1154
|
+
* @param {number} max
|
|
1155
|
+
* @returns {this}
|
|
1156
|
+
*/
|
|
1157
|
+
max(e) {
|
|
1158
|
+
return this;
|
|
1159
|
+
}
|
|
1160
|
+
/**
|
|
1161
|
+
* Values set by this controller will be rounded to multiples of `step`. Only works on number
|
|
1162
|
+
* controllers.
|
|
1163
|
+
* @param {number} step
|
|
1164
|
+
* @returns {this}
|
|
1165
|
+
*/
|
|
1166
|
+
step(e) {
|
|
1167
|
+
return this;
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Rounds the displayed value to a fixed number of decimals, without affecting the actual value
|
|
1171
|
+
* like `step()`. Only works on number controllers.
|
|
1172
|
+
* @example
|
|
1173
|
+
* gui.add( object, 'property' ).listen().decimals( 4 );
|
|
1174
|
+
* @param {number} decimals
|
|
1175
|
+
* @returns {this}
|
|
1176
|
+
*/
|
|
1177
|
+
decimals(e) {
|
|
1178
|
+
return this;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Calls `updateDisplay()` every animation frame. Pass `false` to stop listening.
|
|
1182
|
+
* @param {boolean} listen
|
|
1183
|
+
* @returns {this}
|
|
1184
|
+
*/
|
|
1185
|
+
listen(e = !0) {
|
|
1186
|
+
return this._listening = e, this._listenCallbackID !== void 0 && (cancelAnimationFrame(this._listenCallbackID), this._listenCallbackID = void 0), this._listening && this._listenCallback(), this;
|
|
1187
|
+
}
|
|
1188
|
+
_listenCallback() {
|
|
1189
|
+
this._listenCallbackID = requestAnimationFrame(this._listenCallback);
|
|
1190
|
+
const e = this.save();
|
|
1191
|
+
e !== this._listenPrevValue && this.updateDisplay(), this._listenPrevValue = e;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Returns `object[ property ]`.
|
|
1195
|
+
* @returns {any}
|
|
1196
|
+
*/
|
|
1197
|
+
getValue() {
|
|
1198
|
+
return this.object[this.property];
|
|
1199
|
+
}
|
|
1200
|
+
/**
|
|
1201
|
+
* Sets the value of `object[ property ]`, invokes any `onChange` handlers and updates the display.
|
|
1202
|
+
* @param {any} value
|
|
1203
|
+
* @returns {this}
|
|
1204
|
+
*/
|
|
1205
|
+
setValue(e) {
|
|
1206
|
+
return this.getValue() !== e && (this.object[this.property] = e, this._callOnChange(), this.updateDisplay()), this;
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Updates the display to keep it in sync with the current value. Useful for updating your
|
|
1210
|
+
* controllers when their values have been modified outside of the GUI.
|
|
1211
|
+
* @returns {this}
|
|
1212
|
+
*/
|
|
1213
|
+
updateDisplay() {
|
|
1214
|
+
return this;
|
|
1215
|
+
}
|
|
1216
|
+
load(e) {
|
|
1217
|
+
return this.setValue(e), this._callOnFinishChange(), this;
|
|
1218
|
+
}
|
|
1219
|
+
save() {
|
|
1220
|
+
return this.getValue();
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Destroys this controller and removes it from the parent GUI.
|
|
1224
|
+
*/
|
|
1225
|
+
destroy() {
|
|
1226
|
+
this.listen(!1), this.parent.children.splice(this.parent.children.indexOf(this), 1), this.parent.controllers.splice(this.parent.controllers.indexOf(this), 1), this.parent.$children.removeChild(this.domElement);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
class Z extends L {
|
|
1230
|
+
constructor(e, t, i) {
|
|
1231
|
+
super(e, t, i, "lil-boolean", "label"), this.$input = document.createElement("input"), this.$input.setAttribute("type", "checkbox"), this.$input.setAttribute("aria-labelledby", this.$name.id), this.$widget.appendChild(this.$input), this.$input.addEventListener("change", () => {
|
|
1232
|
+
this.setValue(this.$input.checked), this._callOnFinishChange();
|
|
1233
|
+
}), this.$disable = this.$input, this.updateDisplay();
|
|
1234
|
+
}
|
|
1235
|
+
updateDisplay() {
|
|
1236
|
+
return this.$input.checked = this.getValue(), this;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
function B(s) {
|
|
1240
|
+
let e, t;
|
|
1241
|
+
return (e = s.match(/(#|0x)?([a-f0-9]{6})/i)) ? t = e[2] : (e = s.match(/rgb\(\s*(\d*)\s*,\s*(\d*)\s*,\s*(\d*)\s*\)/)) ? t = parseInt(e[1]).toString(16).padStart(2, 0) + parseInt(e[2]).toString(16).padStart(2, 0) + parseInt(e[3]).toString(16).padStart(2, 0) : (e = s.match(/^#?([a-f0-9])([a-f0-9])([a-f0-9])$/i)) && (t = e[1] + e[1] + e[2] + e[2] + e[3] + e[3]), t ? "#" + t : !1;
|
|
1242
|
+
}
|
|
1243
|
+
const Q = {
|
|
1244
|
+
isPrimitive: !0,
|
|
1245
|
+
match: (s) => typeof s == "string",
|
|
1246
|
+
fromHexString: B,
|
|
1247
|
+
toHexString: B
|
|
1248
|
+
}, $ = {
|
|
1249
|
+
isPrimitive: !0,
|
|
1250
|
+
match: (s) => typeof s == "number",
|
|
1251
|
+
fromHexString: (s) => parseInt(s.substring(1), 16),
|
|
1252
|
+
toHexString: (s) => "#" + s.toString(16).padStart(6, 0)
|
|
1253
|
+
}, K = {
|
|
1254
|
+
isPrimitive: !1,
|
|
1255
|
+
match: (s) => Array.isArray(s) || ArrayBuffer.isView(s),
|
|
1256
|
+
fromHexString(s, e, t = 1) {
|
|
1257
|
+
const i = $.fromHexString(s);
|
|
1258
|
+
e[0] = (i >> 16 & 255) / 255 * t, e[1] = (i >> 8 & 255) / 255 * t, e[2] = (i & 255) / 255 * t;
|
|
1259
|
+
},
|
|
1260
|
+
toHexString([s, e, t], i = 1) {
|
|
1261
|
+
i = 255 / i;
|
|
1262
|
+
const r = s * i << 16 ^ e * i << 8 ^ t * i << 0;
|
|
1263
|
+
return $.toHexString(r);
|
|
1264
|
+
}
|
|
1265
|
+
}, J = {
|
|
1266
|
+
isPrimitive: !1,
|
|
1267
|
+
match: (s) => Object(s) === s,
|
|
1268
|
+
fromHexString(s, e, t = 1) {
|
|
1269
|
+
const i = $.fromHexString(s);
|
|
1270
|
+
e.r = (i >> 16 & 255) / 255 * t, e.g = (i >> 8 & 255) / 255 * t, e.b = (i & 255) / 255 * t;
|
|
1271
|
+
},
|
|
1272
|
+
toHexString({ r: s, g: e, b: t }, i = 1) {
|
|
1273
|
+
i = 255 / i;
|
|
1274
|
+
const r = s * i << 16 ^ e * i << 8 ^ t * i << 0;
|
|
1275
|
+
return $.toHexString(r);
|
|
1276
|
+
}
|
|
1277
|
+
}, ee = [Q, $, K, J];
|
|
1278
|
+
function te(s) {
|
|
1279
|
+
return ee.find((e) => e.match(s));
|
|
1280
|
+
}
|
|
1281
|
+
class ie extends L {
|
|
1282
|
+
constructor(e, t, i, r) {
|
|
1283
|
+
super(e, t, i, "lil-color"), this.$input = document.createElement("input"), this.$input.setAttribute("type", "color"), this.$input.setAttribute("tabindex", -1), this.$input.setAttribute("aria-labelledby", this.$name.id), this.$text = document.createElement("input"), this.$text.setAttribute("type", "text"), this.$text.setAttribute("spellcheck", "false"), this.$text.setAttribute("aria-labelledby", this.$name.id), this.$display = document.createElement("div"), this.$display.classList.add("lil-display"), this.$display.appendChild(this.$input), this.$widget.appendChild(this.$display), this.$widget.appendChild(this.$text), this._format = te(this.initialValue), this._rgbScale = r, this._initialValueHexString = this.save(), this._textFocused = !1, this.$input.addEventListener("input", () => {
|
|
1284
|
+
this._setValueFromHexString(this.$input.value);
|
|
1285
|
+
}), this.$input.addEventListener("blur", () => {
|
|
1286
|
+
this._callOnFinishChange();
|
|
1287
|
+
}), this.$text.addEventListener("input", () => {
|
|
1288
|
+
const n = B(this.$text.value);
|
|
1289
|
+
n && this._setValueFromHexString(n);
|
|
1290
|
+
}), this.$text.addEventListener("focus", () => {
|
|
1291
|
+
this._textFocused = !0, this.$text.select();
|
|
1292
|
+
}), this.$text.addEventListener("blur", () => {
|
|
1293
|
+
this._textFocused = !1, this.updateDisplay(), this._callOnFinishChange();
|
|
1294
|
+
}), this.$disable = this.$text, this.updateDisplay();
|
|
1295
|
+
}
|
|
1296
|
+
reset() {
|
|
1297
|
+
return this._setValueFromHexString(this._initialValueHexString), this;
|
|
1298
|
+
}
|
|
1299
|
+
_setValueFromHexString(e) {
|
|
1300
|
+
if (this._format.isPrimitive) {
|
|
1301
|
+
const t = this._format.fromHexString(e);
|
|
1302
|
+
this.setValue(t);
|
|
1303
|
+
} else
|
|
1304
|
+
this._format.fromHexString(e, this.getValue(), this._rgbScale), this._callOnChange(), this.updateDisplay();
|
|
1305
|
+
}
|
|
1306
|
+
save() {
|
|
1307
|
+
return this._format.toHexString(this.getValue(), this._rgbScale);
|
|
1308
|
+
}
|
|
1309
|
+
load(e) {
|
|
1310
|
+
return this._setValueFromHexString(e), this._callOnFinishChange(), this;
|
|
1311
|
+
}
|
|
1312
|
+
updateDisplay() {
|
|
1313
|
+
return this.$input.value = this._format.toHexString(this.getValue(), this._rgbScale), this._textFocused || (this.$text.value = this.$input.value.substring(1)), this.$display.style.backgroundColor = this.$input.value, this;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
class O extends L {
|
|
1317
|
+
constructor(e, t, i) {
|
|
1318
|
+
super(e, t, i, "lil-function"), this.$button = document.createElement("button"), this.$button.appendChild(this.$name), this.$widget.appendChild(this.$button), this.$button.addEventListener("click", (r) => {
|
|
1319
|
+
r.preventDefault(), this.getValue().call(this.object), this._callOnChange();
|
|
1320
|
+
}), this.$button.addEventListener("touchstart", () => {
|
|
1321
|
+
}, { passive: !0 }), this.$disable = this.$button;
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
class re extends L {
|
|
1325
|
+
constructor(e, t, i, r, n, o) {
|
|
1326
|
+
super(e, t, i, "lil-number"), this._initInput(), this.min(r), this.max(n);
|
|
1327
|
+
const a = o !== void 0;
|
|
1328
|
+
this.step(a ? o : this._getImplicitStep(), a), this.updateDisplay();
|
|
1329
|
+
}
|
|
1330
|
+
decimals(e) {
|
|
1331
|
+
return this._decimals = e, this.updateDisplay(), this;
|
|
1332
|
+
}
|
|
1333
|
+
min(e) {
|
|
1334
|
+
return this._min = e, this._onUpdateMinMax(), this;
|
|
1335
|
+
}
|
|
1336
|
+
max(e) {
|
|
1337
|
+
return this._max = e, this._onUpdateMinMax(), this;
|
|
1338
|
+
}
|
|
1339
|
+
step(e, t = !0) {
|
|
1340
|
+
return this._step = e, this._stepExplicit = t, this;
|
|
1341
|
+
}
|
|
1342
|
+
updateDisplay() {
|
|
1343
|
+
const e = this.getValue();
|
|
1344
|
+
if (this._hasSlider) {
|
|
1345
|
+
let t = (e - this._min) / (this._max - this._min);
|
|
1346
|
+
t = Math.max(0, Math.min(t, 1)), this.$fill.style.width = t * 100 + "%";
|
|
1347
|
+
}
|
|
1348
|
+
return this._inputFocused || (this.$input.value = this._decimals === void 0 ? e : e.toFixed(this._decimals)), this;
|
|
1349
|
+
}
|
|
1350
|
+
_initInput() {
|
|
1351
|
+
this.$input = document.createElement("input"), this.$input.setAttribute("type", "text"), this.$input.setAttribute("aria-labelledby", this.$name.id), window.matchMedia("(pointer: coarse)").matches && (this.$input.setAttribute("type", "number"), this.$input.setAttribute("step", "any")), this.$widget.appendChild(this.$input), this.$disable = this.$input;
|
|
1352
|
+
const t = () => {
|
|
1353
|
+
let p = parseFloat(this.$input.value);
|
|
1354
|
+
isNaN(p) || (this._stepExplicit && (p = this._snap(p)), this.setValue(this._clamp(p)));
|
|
1355
|
+
}, i = (p) => {
|
|
1356
|
+
const g = parseFloat(this.$input.value);
|
|
1357
|
+
isNaN(g) || (this._snapClampSetValue(g + p), this.$input.value = this.getValue());
|
|
1358
|
+
}, r = (p) => {
|
|
1359
|
+
p.key === "Enter" && this.$input.blur(), p.code === "ArrowUp" && (p.preventDefault(), i(this._step * this._arrowKeyMultiplier(p))), p.code === "ArrowDown" && (p.preventDefault(), i(this._step * this._arrowKeyMultiplier(p) * -1));
|
|
1360
|
+
}, n = (p) => {
|
|
1361
|
+
this._inputFocused && (p.preventDefault(), i(this._step * this._normalizeMouseWheel(p)));
|
|
1362
|
+
};
|
|
1363
|
+
let o = !1, a, l, c, h, d;
|
|
1364
|
+
const u = 5, f = (p) => {
|
|
1365
|
+
a = p.clientX, l = c = p.clientY, o = !0, h = this.getValue(), d = 0, window.addEventListener("mousemove", x), window.addEventListener("mouseup", v);
|
|
1366
|
+
}, x = (p) => {
|
|
1367
|
+
if (o) {
|
|
1368
|
+
const g = p.clientX - a, w = p.clientY - l;
|
|
1369
|
+
Math.abs(w) > u ? (p.preventDefault(), this.$input.blur(), o = !1, this._setDraggingStyle(!0, "vertical")) : Math.abs(g) > u && v();
|
|
1370
|
+
}
|
|
1371
|
+
if (!o) {
|
|
1372
|
+
const g = p.clientY - c;
|
|
1373
|
+
d -= g * this._step * this._arrowKeyMultiplier(p), h + d > this._max ? d = this._max - h : h + d < this._min && (d = this._min - h), this._snapClampSetValue(h + d);
|
|
1374
|
+
}
|
|
1375
|
+
c = p.clientY;
|
|
1376
|
+
}, v = () => {
|
|
1377
|
+
this._setDraggingStyle(!1, "vertical"), this._callOnFinishChange(), window.removeEventListener("mousemove", x), window.removeEventListener("mouseup", v);
|
|
1378
|
+
}, C = () => {
|
|
1379
|
+
this._inputFocused = !0;
|
|
1380
|
+
}, m = () => {
|
|
1381
|
+
this._inputFocused = !1, this.updateDisplay(), this._callOnFinishChange();
|
|
1382
|
+
};
|
|
1383
|
+
this.$input.addEventListener("input", t), this.$input.addEventListener("keydown", r), this.$input.addEventListener("wheel", n, { passive: !1 }), this.$input.addEventListener("mousedown", f), this.$input.addEventListener("focus", C), this.$input.addEventListener("blur", m);
|
|
1384
|
+
}
|
|
1385
|
+
_initSlider() {
|
|
1386
|
+
this._hasSlider = !0, this.$slider = document.createElement("div"), this.$slider.classList.add("lil-slider"), this.$fill = document.createElement("div"), this.$fill.classList.add("lil-fill"), this.$slider.appendChild(this.$fill), this.$widget.insertBefore(this.$slider, this.$input), this.domElement.classList.add("lil-has-slider");
|
|
1387
|
+
const e = (m, p, g, w, b) => (m - p) / (g - p) * (b - w) + w, t = (m) => {
|
|
1388
|
+
const p = this.$slider.getBoundingClientRect();
|
|
1389
|
+
let g = e(m, p.left, p.right, this._min, this._max);
|
|
1390
|
+
this._snapClampSetValue(g);
|
|
1391
|
+
}, i = (m) => {
|
|
1392
|
+
this._setDraggingStyle(!0), t(m.clientX), window.addEventListener("mousemove", r), window.addEventListener("mouseup", n);
|
|
1393
|
+
}, r = (m) => {
|
|
1394
|
+
t(m.clientX);
|
|
1395
|
+
}, n = () => {
|
|
1396
|
+
this._callOnFinishChange(), this._setDraggingStyle(!1), window.removeEventListener("mousemove", r), window.removeEventListener("mouseup", n);
|
|
1397
|
+
};
|
|
1398
|
+
let o = !1, a, l;
|
|
1399
|
+
const c = (m) => {
|
|
1400
|
+
m.preventDefault(), this._setDraggingStyle(!0), t(m.touches[0].clientX), o = !1;
|
|
1401
|
+
}, h = (m) => {
|
|
1402
|
+
m.touches.length > 1 || (this._hasScrollBar ? (a = m.touches[0].clientX, l = m.touches[0].clientY, o = !0) : c(m), window.addEventListener("touchmove", d, { passive: !1 }), window.addEventListener("touchend", u));
|
|
1403
|
+
}, d = (m) => {
|
|
1404
|
+
if (o) {
|
|
1405
|
+
const p = m.touches[0].clientX - a, g = m.touches[0].clientY - l;
|
|
1406
|
+
Math.abs(p) > Math.abs(g) ? c(m) : (window.removeEventListener("touchmove", d), window.removeEventListener("touchend", u));
|
|
1407
|
+
} else
|
|
1408
|
+
m.preventDefault(), t(m.touches[0].clientX);
|
|
1409
|
+
}, u = () => {
|
|
1410
|
+
this._callOnFinishChange(), this._setDraggingStyle(!1), window.removeEventListener("touchmove", d), window.removeEventListener("touchend", u);
|
|
1411
|
+
}, f = this._callOnFinishChange.bind(this), x = 400;
|
|
1412
|
+
let v;
|
|
1413
|
+
const C = (m) => {
|
|
1414
|
+
if (Math.abs(m.deltaX) < Math.abs(m.deltaY) && this._hasScrollBar) return;
|
|
1415
|
+
m.preventDefault();
|
|
1416
|
+
const g = this._normalizeMouseWheel(m) * this._step;
|
|
1417
|
+
this._snapClampSetValue(this.getValue() + g), this.$input.value = this.getValue(), clearTimeout(v), v = setTimeout(f, x);
|
|
1418
|
+
};
|
|
1419
|
+
this.$slider.addEventListener("mousedown", i), this.$slider.addEventListener("touchstart", h, { passive: !1 }), this.$slider.addEventListener("wheel", C, { passive: !1 });
|
|
1420
|
+
}
|
|
1421
|
+
_setDraggingStyle(e, t = "horizontal") {
|
|
1422
|
+
this.$slider && this.$slider.classList.toggle("lil-active", e), document.body.classList.toggle("lil-dragging", e), document.body.classList.toggle(`lil-${t}`, e);
|
|
1423
|
+
}
|
|
1424
|
+
_getImplicitStep() {
|
|
1425
|
+
return this._hasMin && this._hasMax ? (this._max - this._min) / 1e3 : 0.1;
|
|
1426
|
+
}
|
|
1427
|
+
_onUpdateMinMax() {
|
|
1428
|
+
!this._hasSlider && this._hasMin && this._hasMax && (this._stepExplicit || this.step(this._getImplicitStep(), !1), this._initSlider(), this.updateDisplay());
|
|
1429
|
+
}
|
|
1430
|
+
_normalizeMouseWheel(e) {
|
|
1431
|
+
let { deltaX: t, deltaY: i } = e;
|
|
1432
|
+
return Math.floor(e.deltaY) !== e.deltaY && e.wheelDelta && (t = 0, i = -e.wheelDelta / 120, i *= this._stepExplicit ? 1 : 10), t + -i;
|
|
1433
|
+
}
|
|
1434
|
+
_arrowKeyMultiplier(e) {
|
|
1435
|
+
let t = this._stepExplicit ? 1 : 10;
|
|
1436
|
+
return e.shiftKey ? t *= 10 : e.altKey && (t /= 10), t;
|
|
1437
|
+
}
|
|
1438
|
+
_snap(e) {
|
|
1439
|
+
let t = 0;
|
|
1440
|
+
return this._hasMin ? t = this._min : this._hasMax && (t = this._max), e -= t, e = Math.round(e / this._step) * this._step, e += t, e = parseFloat(e.toPrecision(15)), e;
|
|
1441
|
+
}
|
|
1442
|
+
_clamp(e) {
|
|
1443
|
+
return e < this._min && (e = this._min), e > this._max && (e = this._max), e;
|
|
1444
|
+
}
|
|
1445
|
+
_snapClampSetValue(e) {
|
|
1446
|
+
this.setValue(this._clamp(this._snap(e)));
|
|
1447
|
+
}
|
|
1448
|
+
get _hasScrollBar() {
|
|
1449
|
+
const e = this.parent.root.$children;
|
|
1450
|
+
return e.scrollHeight > e.clientHeight;
|
|
1451
|
+
}
|
|
1452
|
+
get _hasMin() {
|
|
1453
|
+
return this._min !== void 0;
|
|
1454
|
+
}
|
|
1455
|
+
get _hasMax() {
|
|
1456
|
+
return this._max !== void 0;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
class ne extends L {
|
|
1460
|
+
constructor(e, t, i, r) {
|
|
1461
|
+
super(e, t, i, "lil-option"), this.$select = document.createElement("select"), this.$select.setAttribute("aria-labelledby", this.$name.id), this.$display = document.createElement("div"), this.$display.classList.add("lil-display"), this.$select.addEventListener("change", () => {
|
|
1462
|
+
this.setValue(this._values[this.$select.selectedIndex]), this._callOnFinishChange();
|
|
1463
|
+
}), this.$select.addEventListener("focus", () => {
|
|
1464
|
+
this.$display.classList.add("lil-focus");
|
|
1465
|
+
}), this.$select.addEventListener("blur", () => {
|
|
1466
|
+
this.$display.classList.remove("lil-focus");
|
|
1467
|
+
}), this.$widget.appendChild(this.$select), this.$widget.appendChild(this.$display), this.$disable = this.$select, this.options(r);
|
|
1468
|
+
}
|
|
1469
|
+
options(e) {
|
|
1470
|
+
return this._values = Array.isArray(e) ? e : Object.values(e), this._names = Array.isArray(e) ? e : Object.keys(e), this.$select.replaceChildren(), this._names.forEach((t) => {
|
|
1471
|
+
const i = document.createElement("option");
|
|
1472
|
+
i.textContent = t, this.$select.appendChild(i);
|
|
1473
|
+
}), this.updateDisplay(), this;
|
|
1474
|
+
}
|
|
1475
|
+
updateDisplay() {
|
|
1476
|
+
const e = this.getValue(), t = this._values.indexOf(e);
|
|
1477
|
+
return this.$select.selectedIndex = t, this.$display.textContent = t === -1 ? e : this._names[t], this;
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
class se extends L {
|
|
1481
|
+
constructor(e, t, i) {
|
|
1482
|
+
super(e, t, i, "lil-string"), this.$input = document.createElement("input"), this.$input.setAttribute("type", "text"), this.$input.setAttribute("spellcheck", "false"), this.$input.setAttribute("aria-labelledby", this.$name.id), this.$input.addEventListener("input", () => {
|
|
1483
|
+
this.setValue(this.$input.value);
|
|
1484
|
+
}), this.$input.addEventListener("keydown", (r) => {
|
|
1485
|
+
r.code === "Enter" && this.$input.blur();
|
|
1486
|
+
}), this.$input.addEventListener("blur", () => {
|
|
1487
|
+
this._callOnFinishChange();
|
|
1488
|
+
}), this.$widget.appendChild(this.$input), this.$disable = this.$input, this.updateDisplay();
|
|
1489
|
+
}
|
|
1490
|
+
updateDisplay() {
|
|
1491
|
+
return this.$input.value = this.getValue(), this;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
var oe = `.lil-gui {
|
|
1495
|
+
font-family: var(--font-family);
|
|
1496
|
+
font-size: var(--font-size);
|
|
1497
|
+
line-height: 1;
|
|
1498
|
+
font-weight: normal;
|
|
1499
|
+
font-style: normal;
|
|
1500
|
+
text-align: left;
|
|
1501
|
+
color: var(--text-color);
|
|
1502
|
+
user-select: none;
|
|
1503
|
+
-webkit-user-select: none;
|
|
1504
|
+
touch-action: manipulation;
|
|
1505
|
+
--background-color: #1f1f1f;
|
|
1506
|
+
--text-color: #ebebeb;
|
|
1507
|
+
--title-background-color: #111111;
|
|
1508
|
+
--title-text-color: #ebebeb;
|
|
1509
|
+
--widget-color: #424242;
|
|
1510
|
+
--hover-color: #4f4f4f;
|
|
1511
|
+
--focus-color: #595959;
|
|
1512
|
+
--number-color: #2cc9ff;
|
|
1513
|
+
--string-color: #a2db3c;
|
|
1514
|
+
--font-size: 11px;
|
|
1515
|
+
--input-font-size: 11px;
|
|
1516
|
+
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
|
|
1517
|
+
--font-family-mono: Menlo, Monaco, Consolas, "Droid Sans Mono", monospace;
|
|
1518
|
+
--padding: 4px;
|
|
1519
|
+
--spacing: 4px;
|
|
1520
|
+
--widget-height: 20px;
|
|
1521
|
+
--title-height: calc(var(--widget-height) + var(--spacing) * 1.25);
|
|
1522
|
+
--name-width: 45%;
|
|
1523
|
+
--slider-knob-width: 2px;
|
|
1524
|
+
--slider-input-width: 27%;
|
|
1525
|
+
--color-input-width: 27%;
|
|
1526
|
+
--slider-input-min-width: 45px;
|
|
1527
|
+
--color-input-min-width: 45px;
|
|
1528
|
+
--folder-indent: 7px;
|
|
1529
|
+
--widget-padding: 0 0 0 3px;
|
|
1530
|
+
--widget-border-radius: 2px;
|
|
1531
|
+
--checkbox-size: calc(0.75 * var(--widget-height));
|
|
1532
|
+
--scrollbar-width: 5px;
|
|
1533
|
+
}
|
|
1534
|
+
.lil-gui, .lil-gui * {
|
|
1535
|
+
box-sizing: border-box;
|
|
1536
|
+
margin: 0;
|
|
1537
|
+
padding: 0;
|
|
1538
|
+
}
|
|
1539
|
+
.lil-gui.lil-root {
|
|
1540
|
+
width: var(--width, 245px);
|
|
1541
|
+
display: flex;
|
|
1542
|
+
flex-direction: column;
|
|
1543
|
+
background: var(--background-color);
|
|
1544
|
+
}
|
|
1545
|
+
.lil-gui.lil-root > .lil-title {
|
|
1546
|
+
background: var(--title-background-color);
|
|
1547
|
+
color: var(--title-text-color);
|
|
1548
|
+
}
|
|
1549
|
+
.lil-gui.lil-root > .lil-children {
|
|
1550
|
+
overflow-x: hidden;
|
|
1551
|
+
overflow-y: auto;
|
|
1552
|
+
}
|
|
1553
|
+
.lil-gui.lil-root > .lil-children::-webkit-scrollbar {
|
|
1554
|
+
width: var(--scrollbar-width);
|
|
1555
|
+
height: var(--scrollbar-width);
|
|
1556
|
+
background: var(--background-color);
|
|
1557
|
+
}
|
|
1558
|
+
.lil-gui.lil-root > .lil-children::-webkit-scrollbar-thumb {
|
|
1559
|
+
border-radius: var(--scrollbar-width);
|
|
1560
|
+
background: var(--focus-color);
|
|
1561
|
+
}
|
|
1562
|
+
@media (pointer: coarse) {
|
|
1563
|
+
.lil-gui.lil-allow-touch-styles, .lil-gui.lil-allow-touch-styles .lil-gui {
|
|
1564
|
+
--widget-height: 28px;
|
|
1565
|
+
--padding: 6px;
|
|
1566
|
+
--spacing: 6px;
|
|
1567
|
+
--font-size: 13px;
|
|
1568
|
+
--input-font-size: 16px;
|
|
1569
|
+
--folder-indent: 10px;
|
|
1570
|
+
--scrollbar-width: 7px;
|
|
1571
|
+
--slider-input-min-width: 50px;
|
|
1572
|
+
--color-input-min-width: 65px;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
.lil-gui.lil-force-touch-styles, .lil-gui.lil-force-touch-styles .lil-gui {
|
|
1576
|
+
--widget-height: 28px;
|
|
1577
|
+
--padding: 6px;
|
|
1578
|
+
--spacing: 6px;
|
|
1579
|
+
--font-size: 13px;
|
|
1580
|
+
--input-font-size: 16px;
|
|
1581
|
+
--folder-indent: 10px;
|
|
1582
|
+
--scrollbar-width: 7px;
|
|
1583
|
+
--slider-input-min-width: 50px;
|
|
1584
|
+
--color-input-min-width: 65px;
|
|
1585
|
+
}
|
|
1586
|
+
.lil-gui.lil-auto-place, .lil-gui.autoPlace {
|
|
1587
|
+
max-height: 100%;
|
|
1588
|
+
position: fixed;
|
|
1589
|
+
top: 0;
|
|
1590
|
+
right: 15px;
|
|
1591
|
+
z-index: 1001;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
.lil-controller {
|
|
1595
|
+
display: flex;
|
|
1596
|
+
align-items: center;
|
|
1597
|
+
padding: 0 var(--padding);
|
|
1598
|
+
margin: var(--spacing) 0;
|
|
1599
|
+
}
|
|
1600
|
+
.lil-controller.lil-disabled {
|
|
1601
|
+
opacity: 0.5;
|
|
1602
|
+
}
|
|
1603
|
+
.lil-controller.lil-disabled, .lil-controller.lil-disabled * {
|
|
1604
|
+
pointer-events: none !important;
|
|
1605
|
+
}
|
|
1606
|
+
.lil-controller > .lil-name {
|
|
1607
|
+
min-width: var(--name-width);
|
|
1608
|
+
flex-shrink: 0;
|
|
1609
|
+
white-space: pre;
|
|
1610
|
+
padding-right: var(--spacing);
|
|
1611
|
+
line-height: var(--widget-height);
|
|
1612
|
+
}
|
|
1613
|
+
.lil-controller .lil-widget {
|
|
1614
|
+
position: relative;
|
|
1615
|
+
display: flex;
|
|
1616
|
+
align-items: center;
|
|
1617
|
+
width: 100%;
|
|
1618
|
+
min-height: var(--widget-height);
|
|
1619
|
+
}
|
|
1620
|
+
.lil-controller.lil-string input {
|
|
1621
|
+
color: var(--string-color);
|
|
1622
|
+
}
|
|
1623
|
+
.lil-controller.lil-boolean {
|
|
1624
|
+
cursor: pointer;
|
|
1625
|
+
}
|
|
1626
|
+
.lil-controller.lil-color .lil-display {
|
|
1627
|
+
width: 100%;
|
|
1628
|
+
height: var(--widget-height);
|
|
1629
|
+
border-radius: var(--widget-border-radius);
|
|
1630
|
+
position: relative;
|
|
1631
|
+
}
|
|
1632
|
+
@media (hover: hover) {
|
|
1633
|
+
.lil-controller.lil-color .lil-display:hover:before {
|
|
1634
|
+
content: " ";
|
|
1635
|
+
display: block;
|
|
1636
|
+
position: absolute;
|
|
1637
|
+
border-radius: var(--widget-border-radius);
|
|
1638
|
+
border: 1px solid #fff9;
|
|
1639
|
+
top: 0;
|
|
1640
|
+
right: 0;
|
|
1641
|
+
bottom: 0;
|
|
1642
|
+
left: 0;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
.lil-controller.lil-color input[type=color] {
|
|
1646
|
+
opacity: 0;
|
|
1647
|
+
width: 100%;
|
|
1648
|
+
height: 100%;
|
|
1649
|
+
cursor: pointer;
|
|
1650
|
+
}
|
|
1651
|
+
.lil-controller.lil-color input[type=text] {
|
|
1652
|
+
margin-left: var(--spacing);
|
|
1653
|
+
font-family: var(--font-family-mono);
|
|
1654
|
+
min-width: var(--color-input-min-width);
|
|
1655
|
+
width: var(--color-input-width);
|
|
1656
|
+
flex-shrink: 0;
|
|
1657
|
+
}
|
|
1658
|
+
.lil-controller.lil-option select {
|
|
1659
|
+
opacity: 0;
|
|
1660
|
+
position: absolute;
|
|
1661
|
+
width: 100%;
|
|
1662
|
+
max-width: 100%;
|
|
1663
|
+
}
|
|
1664
|
+
.lil-controller.lil-option .lil-display {
|
|
1665
|
+
position: relative;
|
|
1666
|
+
pointer-events: none;
|
|
1667
|
+
border-radius: var(--widget-border-radius);
|
|
1668
|
+
height: var(--widget-height);
|
|
1669
|
+
line-height: var(--widget-height);
|
|
1670
|
+
max-width: 100%;
|
|
1671
|
+
overflow: hidden;
|
|
1672
|
+
word-break: break-all;
|
|
1673
|
+
padding-left: 0.55em;
|
|
1674
|
+
padding-right: 1.75em;
|
|
1675
|
+
background: var(--widget-color);
|
|
1676
|
+
}
|
|
1677
|
+
@media (hover: hover) {
|
|
1678
|
+
.lil-controller.lil-option .lil-display.lil-focus {
|
|
1679
|
+
background: var(--focus-color);
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
.lil-controller.lil-option .lil-display.lil-active {
|
|
1683
|
+
background: var(--focus-color);
|
|
1684
|
+
}
|
|
1685
|
+
.lil-controller.lil-option .lil-display:after {
|
|
1686
|
+
font-family: "lil-gui";
|
|
1687
|
+
content: "↕";
|
|
1688
|
+
position: absolute;
|
|
1689
|
+
top: 0;
|
|
1690
|
+
right: 0;
|
|
1691
|
+
bottom: 0;
|
|
1692
|
+
padding-right: 0.375em;
|
|
1693
|
+
}
|
|
1694
|
+
.lil-controller.lil-option .lil-widget,
|
|
1695
|
+
.lil-controller.lil-option select {
|
|
1696
|
+
cursor: pointer;
|
|
1697
|
+
}
|
|
1698
|
+
@media (hover: hover) {
|
|
1699
|
+
.lil-controller.lil-option .lil-widget:hover .lil-display {
|
|
1700
|
+
background: var(--hover-color);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
.lil-controller.lil-number input {
|
|
1704
|
+
color: var(--number-color);
|
|
1705
|
+
}
|
|
1706
|
+
.lil-controller.lil-number.lil-has-slider input {
|
|
1707
|
+
margin-left: var(--spacing);
|
|
1708
|
+
width: var(--slider-input-width);
|
|
1709
|
+
min-width: var(--slider-input-min-width);
|
|
1710
|
+
flex-shrink: 0;
|
|
1711
|
+
}
|
|
1712
|
+
.lil-controller.lil-number .lil-slider {
|
|
1713
|
+
width: 100%;
|
|
1714
|
+
height: var(--widget-height);
|
|
1715
|
+
background: var(--widget-color);
|
|
1716
|
+
border-radius: var(--widget-border-radius);
|
|
1717
|
+
padding-right: var(--slider-knob-width);
|
|
1718
|
+
overflow: hidden;
|
|
1719
|
+
cursor: ew-resize;
|
|
1720
|
+
touch-action: pan-y;
|
|
1721
|
+
}
|
|
1722
|
+
@media (hover: hover) {
|
|
1723
|
+
.lil-controller.lil-number .lil-slider:hover {
|
|
1724
|
+
background: var(--hover-color);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
.lil-controller.lil-number .lil-slider.lil-active {
|
|
1728
|
+
background: var(--focus-color);
|
|
1729
|
+
}
|
|
1730
|
+
.lil-controller.lil-number .lil-slider.lil-active .lil-fill {
|
|
1731
|
+
opacity: 0.95;
|
|
1732
|
+
}
|
|
1733
|
+
.lil-controller.lil-number .lil-fill {
|
|
1734
|
+
height: 100%;
|
|
1735
|
+
border-right: var(--slider-knob-width) solid var(--number-color);
|
|
1736
|
+
box-sizing: content-box;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
.lil-dragging .lil-gui {
|
|
1740
|
+
--hover-color: var(--widget-color);
|
|
1741
|
+
}
|
|
1742
|
+
.lil-dragging * {
|
|
1743
|
+
cursor: ew-resize !important;
|
|
1744
|
+
}
|
|
1745
|
+
.lil-dragging.lil-vertical * {
|
|
1746
|
+
cursor: ns-resize !important;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
.lil-gui .lil-title {
|
|
1750
|
+
height: var(--title-height);
|
|
1751
|
+
font-weight: 600;
|
|
1752
|
+
padding: 0 var(--padding);
|
|
1753
|
+
width: 100%;
|
|
1754
|
+
text-align: left;
|
|
1755
|
+
background: none;
|
|
1756
|
+
text-decoration-skip: objects;
|
|
1757
|
+
}
|
|
1758
|
+
.lil-gui .lil-title:before {
|
|
1759
|
+
font-family: "lil-gui";
|
|
1760
|
+
content: "▾";
|
|
1761
|
+
padding-right: 2px;
|
|
1762
|
+
display: inline-block;
|
|
1763
|
+
}
|
|
1764
|
+
.lil-gui .lil-title:active {
|
|
1765
|
+
background: var(--title-background-color);
|
|
1766
|
+
opacity: 0.75;
|
|
1767
|
+
}
|
|
1768
|
+
@media (hover: hover) {
|
|
1769
|
+
body:not(.lil-dragging) .lil-gui .lil-title:hover {
|
|
1770
|
+
background: var(--title-background-color);
|
|
1771
|
+
opacity: 0.85;
|
|
1772
|
+
}
|
|
1773
|
+
.lil-gui .lil-title:focus {
|
|
1774
|
+
text-decoration: underline var(--focus-color);
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
.lil-gui.lil-root > .lil-title:focus {
|
|
1778
|
+
text-decoration: none !important;
|
|
1779
|
+
}
|
|
1780
|
+
.lil-gui.lil-closed > .lil-title:before {
|
|
1781
|
+
content: "▸";
|
|
1782
|
+
}
|
|
1783
|
+
.lil-gui.lil-closed > .lil-children {
|
|
1784
|
+
transform: translateY(-7px);
|
|
1785
|
+
opacity: 0;
|
|
1786
|
+
}
|
|
1787
|
+
.lil-gui.lil-closed:not(.lil-transition) > .lil-children {
|
|
1788
|
+
display: none;
|
|
1789
|
+
}
|
|
1790
|
+
.lil-gui.lil-transition > .lil-children {
|
|
1791
|
+
transition-duration: 300ms;
|
|
1792
|
+
transition-property: height, opacity, transform;
|
|
1793
|
+
transition-timing-function: cubic-bezier(0.2, 0.6, 0.35, 1);
|
|
1794
|
+
overflow: hidden;
|
|
1795
|
+
pointer-events: none;
|
|
1796
|
+
}
|
|
1797
|
+
.lil-gui .lil-children:empty:before {
|
|
1798
|
+
content: "Empty";
|
|
1799
|
+
padding: 0 var(--padding);
|
|
1800
|
+
margin: var(--spacing) 0;
|
|
1801
|
+
display: block;
|
|
1802
|
+
height: var(--widget-height);
|
|
1803
|
+
font-style: italic;
|
|
1804
|
+
line-height: var(--widget-height);
|
|
1805
|
+
opacity: 0.5;
|
|
1806
|
+
}
|
|
1807
|
+
.lil-gui.lil-root > .lil-children > .lil-gui > .lil-title {
|
|
1808
|
+
border: 0 solid var(--widget-color);
|
|
1809
|
+
border-width: 1px 0;
|
|
1810
|
+
transition: border-color 300ms;
|
|
1811
|
+
}
|
|
1812
|
+
.lil-gui.lil-root > .lil-children > .lil-gui.lil-closed > .lil-title {
|
|
1813
|
+
border-bottom-color: transparent;
|
|
1814
|
+
}
|
|
1815
|
+
.lil-gui + .lil-controller {
|
|
1816
|
+
border-top: 1px solid var(--widget-color);
|
|
1817
|
+
margin-top: 0;
|
|
1818
|
+
padding-top: var(--spacing);
|
|
1819
|
+
}
|
|
1820
|
+
.lil-gui .lil-gui .lil-gui > .lil-title {
|
|
1821
|
+
border: none;
|
|
1822
|
+
}
|
|
1823
|
+
.lil-gui .lil-gui .lil-gui > .lil-children {
|
|
1824
|
+
border: none;
|
|
1825
|
+
margin-left: var(--folder-indent);
|
|
1826
|
+
border-left: 2px solid var(--widget-color);
|
|
1827
|
+
}
|
|
1828
|
+
.lil-gui .lil-gui .lil-controller {
|
|
1829
|
+
border: none;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
.lil-gui label, .lil-gui input, .lil-gui button {
|
|
1833
|
+
-webkit-tap-highlight-color: transparent;
|
|
1834
|
+
}
|
|
1835
|
+
.lil-gui input {
|
|
1836
|
+
border: 0;
|
|
1837
|
+
outline: none;
|
|
1838
|
+
font-family: var(--font-family);
|
|
1839
|
+
font-size: var(--input-font-size);
|
|
1840
|
+
border-radius: var(--widget-border-radius);
|
|
1841
|
+
height: var(--widget-height);
|
|
1842
|
+
background: var(--widget-color);
|
|
1843
|
+
color: var(--text-color);
|
|
1844
|
+
width: 100%;
|
|
1845
|
+
}
|
|
1846
|
+
@media (hover: hover) {
|
|
1847
|
+
.lil-gui input:hover {
|
|
1848
|
+
background: var(--hover-color);
|
|
1849
|
+
}
|
|
1850
|
+
.lil-gui input:active {
|
|
1851
|
+
background: var(--focus-color);
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
.lil-gui input:disabled {
|
|
1855
|
+
opacity: 1;
|
|
1856
|
+
}
|
|
1857
|
+
.lil-gui input[type=text],
|
|
1858
|
+
.lil-gui input[type=number] {
|
|
1859
|
+
padding: var(--widget-padding);
|
|
1860
|
+
-moz-appearance: textfield;
|
|
1861
|
+
}
|
|
1862
|
+
.lil-gui input[type=text]:focus,
|
|
1863
|
+
.lil-gui input[type=number]:focus {
|
|
1864
|
+
background: var(--focus-color);
|
|
1865
|
+
}
|
|
1866
|
+
.lil-gui input[type=checkbox] {
|
|
1867
|
+
appearance: none;
|
|
1868
|
+
width: var(--checkbox-size);
|
|
1869
|
+
height: var(--checkbox-size);
|
|
1870
|
+
border-radius: var(--widget-border-radius);
|
|
1871
|
+
text-align: center;
|
|
1872
|
+
cursor: pointer;
|
|
1873
|
+
}
|
|
1874
|
+
.lil-gui input[type=checkbox]:checked:before {
|
|
1875
|
+
font-family: "lil-gui";
|
|
1876
|
+
content: "✓";
|
|
1877
|
+
font-size: var(--checkbox-size);
|
|
1878
|
+
line-height: var(--checkbox-size);
|
|
1879
|
+
}
|
|
1880
|
+
@media (hover: hover) {
|
|
1881
|
+
.lil-gui input[type=checkbox]:focus {
|
|
1882
|
+
box-shadow: inset 0 0 0 1px var(--focus-color);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
.lil-gui button {
|
|
1886
|
+
outline: none;
|
|
1887
|
+
cursor: pointer;
|
|
1888
|
+
font-family: var(--font-family);
|
|
1889
|
+
font-size: var(--font-size);
|
|
1890
|
+
color: var(--text-color);
|
|
1891
|
+
width: 100%;
|
|
1892
|
+
border: none;
|
|
1893
|
+
}
|
|
1894
|
+
.lil-gui .lil-controller button {
|
|
1895
|
+
height: var(--widget-height);
|
|
1896
|
+
text-transform: none;
|
|
1897
|
+
background: var(--widget-color);
|
|
1898
|
+
border-radius: var(--widget-border-radius);
|
|
1899
|
+
}
|
|
1900
|
+
@media (hover: hover) {
|
|
1901
|
+
.lil-gui .lil-controller button:hover {
|
|
1902
|
+
background: var(--hover-color);
|
|
1903
|
+
}
|
|
1904
|
+
.lil-gui .lil-controller button:focus {
|
|
1905
|
+
box-shadow: inset 0 0 0 1px var(--focus-color);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
.lil-gui .lil-controller button:active {
|
|
1909
|
+
background: var(--focus-color);
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
@font-face {
|
|
1913
|
+
font-family: "lil-gui";
|
|
1914
|
+
src: url("data:application/font-woff2;charset=utf-8;base64,d09GMgABAAAAAALkAAsAAAAABtQAAAKVAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACDMgqBBIEbATYCJAMUCwwABCAFhAoHgQQbHAbIDiUFEYVARAAAYQTVWNmz9MxhEgodq49wYRUFKE8GWNiUBxI2LBRaVnc51U83Gmhs0Q7JXWMiz5eteLwrKwuxHO8VFxUX9UpZBs6pa5ABRwHA+t3UxUnH20EvVknRerzQgX6xC/GH6ZUvTcAjAv122dF28OTqCXrPuyaDER30YBA1xnkVutDDo4oCi71Ca7rrV9xS8dZHbPHefsuwIyCpmT7j+MnjAH5X3984UZoFFuJ0yiZ4XEJFxjagEBeqs+e1iyK8Xf/nOuwF+vVK0ur765+vf7txotUi0m3N0m/84RGSrBCNrh8Ee5GjODjF4gnWP+dJrH/Lk9k4oT6d+gr6g/wssA2j64JJGP6cmx554vUZnpZfn6ZfX2bMwPPrlANsB86/DiHjhl0OP+c87+gaJo/gY084s3HoYL/ZkWHTRfBXvvoHnnkHvngKun4KBE/ede7tvq3/vQOxDXB1/fdNz6XbPdcr0Vhpojj9dG+owuSKFsslCi1tgEjirjXdwMiov2EioadxmqTHUCIwo8NgQaeIasAi0fTYSPTbSmwbMOFduyh9wvBrESGY0MtgRjtgQR8Q1bRPohn2UoCRZf9wyYANMXFeJTysqAe0I4mrherOekFdKMrYvJjLvOIUM9SuwYB5DVZUwwVjJJOaUnZCmcEkIZZrKqNvRGRMvmFZsmhP4VMKCSXBhSqUBxgMS7h0cZvEd71AWkEhGWaeMFcNnpqyJkyXgYL7PQ1MoSq0wDAkRtJIijkZSmqYTiSImfLiSWXIZwhRh3Rug2X0kk1Dgj+Iu43u5p98ghopcpSo0Uyc8SnjlYX59WUeaMoDqmVD2TOWD9a4pCRAzf2ECgwGcrHjPOWY9bNxq/OL3I/QjwEAAAA=") format("woff2");
|
|
1915
|
+
}`;
|
|
1916
|
+
function ae(s) {
|
|
1917
|
+
const e = document.createElement("style");
|
|
1918
|
+
e.innerHTML = s;
|
|
1919
|
+
const t = document.querySelector("head link[rel=stylesheet], head style");
|
|
1920
|
+
t ? document.head.insertBefore(e, t) : document.head.appendChild(e);
|
|
1921
|
+
}
|
|
1922
|
+
let I = !1;
|
|
1923
|
+
class U {
|
|
1924
|
+
/**
|
|
1925
|
+
* Creates a panel that holds controllers.
|
|
1926
|
+
* @example
|
|
1927
|
+
* new GUI();
|
|
1928
|
+
* new GUI( { container: document.getElementById( 'custom' ) } );
|
|
1929
|
+
*
|
|
1930
|
+
* @param {object} [options]
|
|
1931
|
+
* @param {boolean} [options.autoPlace=true]
|
|
1932
|
+
* Adds the GUI to `document.body` and fixes it to the top right of the page.
|
|
1933
|
+
*
|
|
1934
|
+
* @param {Node} [options.container]
|
|
1935
|
+
* Adds the GUI to this DOM element. Overrides `autoPlace`.
|
|
1936
|
+
*
|
|
1937
|
+
* @param {number} [options.width=245]
|
|
1938
|
+
* Width of the GUI in pixels, usually set when name labels become too long. Note that you can make
|
|
1939
|
+
* name labels wider in CSS with `.lil‑gui { ‑‑name‑width: 55% }`.
|
|
1940
|
+
*
|
|
1941
|
+
* @param {string} [options.title=Controls]
|
|
1942
|
+
* Name to display in the title bar.
|
|
1943
|
+
*
|
|
1944
|
+
* @param {boolean} [options.closeFolders=false]
|
|
1945
|
+
* Pass `true` to close all folders in this GUI by default.
|
|
1946
|
+
*
|
|
1947
|
+
* @param {boolean} [options.injectStyles=true]
|
|
1948
|
+
* Injects the default stylesheet into the page if this is the first GUI.
|
|
1949
|
+
* Pass `false` to use your own stylesheet.
|
|
1950
|
+
*
|
|
1951
|
+
* @param {number} [options.touchStyles=true]
|
|
1952
|
+
* Makes controllers larger on touch devices. Pass `false` to disable touch styles.
|
|
1953
|
+
*
|
|
1954
|
+
* @param {GUI} [options.parent]
|
|
1955
|
+
* Adds this GUI as a child in another GUI. Usually this is done for you by `addFolder()`.
|
|
1956
|
+
*/
|
|
1957
|
+
constructor({
|
|
1958
|
+
parent: e,
|
|
1959
|
+
autoPlace: t = e === void 0,
|
|
1960
|
+
container: i,
|
|
1961
|
+
width: r,
|
|
1962
|
+
title: n = "Controls",
|
|
1963
|
+
closeFolders: o = !1,
|
|
1964
|
+
injectStyles: a = !0,
|
|
1965
|
+
touchStyles: l = !0
|
|
1966
|
+
} = {}) {
|
|
1967
|
+
if (this.parent = e, this.root = e ? e.root : this, this.children = [], this.controllers = [], this.folders = [], this._closed = !1, this._hidden = !1, this.domElement = document.createElement("div"), this.domElement.classList.add("lil-gui"), this.$title = document.createElement("button"), this.$title.classList.add("lil-title"), this.$title.setAttribute("aria-expanded", !0), this.$title.addEventListener("click", () => this.openAnimated(this._closed)), this.$title.addEventListener("touchstart", () => {
|
|
1968
|
+
}, { passive: !0 }), this.$children = document.createElement("div"), this.$children.classList.add("lil-children"), this.domElement.appendChild(this.$title), this.domElement.appendChild(this.$children), this.title(n), this.parent) {
|
|
1969
|
+
this.parent.children.push(this), this.parent.folders.push(this), this.parent.$children.appendChild(this.domElement);
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1972
|
+
this.domElement.classList.add("lil-root"), l && this.domElement.classList.add("lil-allow-touch-styles"), !I && a && (ae(oe), I = !0), i ? i.appendChild(this.domElement) : t && (this.domElement.classList.add("lil-auto-place", "autoPlace"), document.body.appendChild(this.domElement)), r && this.domElement.style.setProperty("--width", r + "px"), this._closeFolders = o;
|
|
1973
|
+
}
|
|
1974
|
+
/**
|
|
1975
|
+
* Adds a controller to the GUI, inferring controller type using the `typeof` operator.
|
|
1976
|
+
* @example
|
|
1977
|
+
* gui.add( object, 'property' );
|
|
1978
|
+
* gui.add( object, 'number', 0, 100, 1 );
|
|
1979
|
+
* gui.add( object, 'options', [ 1, 2, 3 ] );
|
|
1980
|
+
*
|
|
1981
|
+
* @param {object} object The object the controller will modify.
|
|
1982
|
+
* @param {string} property Name of the property to control.
|
|
1983
|
+
* @param {number|object|Array} [$1] Minimum value for number controllers, or the set of
|
|
1984
|
+
* selectable values for a dropdown.
|
|
1985
|
+
* @param {number} [max] Maximum value for number controllers.
|
|
1986
|
+
* @param {number} [step] Step value for number controllers.
|
|
1987
|
+
* @returns {Controller}
|
|
1988
|
+
*/
|
|
1989
|
+
add(e, t, i, r, n) {
|
|
1990
|
+
if (Object(i) === i)
|
|
1991
|
+
return new ne(this, e, t, i);
|
|
1992
|
+
const o = e[t];
|
|
1993
|
+
switch (typeof o) {
|
|
1994
|
+
case "number":
|
|
1995
|
+
return new re(this, e, t, i, r, n);
|
|
1996
|
+
case "boolean":
|
|
1997
|
+
return new Z(this, e, t);
|
|
1998
|
+
case "string":
|
|
1999
|
+
return new se(this, e, t);
|
|
2000
|
+
case "function":
|
|
2001
|
+
return new O(this, e, t);
|
|
2002
|
+
}
|
|
2003
|
+
console.error(`gui.add failed
|
|
2004
|
+
property:`, t, `
|
|
2005
|
+
object:`, e, `
|
|
2006
|
+
value:`, o);
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Adds a color controller to the GUI.
|
|
2010
|
+
* @example
|
|
2011
|
+
* params = {
|
|
2012
|
+
* cssColor: '#ff00ff',
|
|
2013
|
+
* rgbColor: { r: 0, g: 0.2, b: 0.4 },
|
|
2014
|
+
* customRange: [ 0, 127, 255 ],
|
|
2015
|
+
* };
|
|
2016
|
+
*
|
|
2017
|
+
* gui.addColor( params, 'cssColor' );
|
|
2018
|
+
* gui.addColor( params, 'rgbColor' );
|
|
2019
|
+
* gui.addColor( params, 'customRange', 255 );
|
|
2020
|
+
*
|
|
2021
|
+
* @param {object} object The object the controller will modify.
|
|
2022
|
+
* @param {string} property Name of the property to control.
|
|
2023
|
+
* @param {number} rgbScale Maximum value for a color channel when using an RGB color. You may
|
|
2024
|
+
* need to set this to 255 if your colors are too bright.
|
|
2025
|
+
* @returns {Controller}
|
|
2026
|
+
*/
|
|
2027
|
+
addColor(e, t, i = 1) {
|
|
2028
|
+
return new ie(this, e, t, i);
|
|
2029
|
+
}
|
|
2030
|
+
/**
|
|
2031
|
+
* Adds a folder to the GUI, which is just another GUI. This method returns
|
|
2032
|
+
* the nested GUI so you can add controllers to it.
|
|
2033
|
+
* @example
|
|
2034
|
+
* const folder = gui.addFolder( 'Position' );
|
|
2035
|
+
* folder.add( position, 'x' );
|
|
2036
|
+
* folder.add( position, 'y' );
|
|
2037
|
+
* folder.add( position, 'z' );
|
|
2038
|
+
*
|
|
2039
|
+
* @param {string} title Name to display in the folder's title bar.
|
|
2040
|
+
* @returns {GUI}
|
|
2041
|
+
*/
|
|
2042
|
+
addFolder(e) {
|
|
2043
|
+
const t = new U({ parent: this, title: e });
|
|
2044
|
+
return this.root._closeFolders && t.close(), t;
|
|
2045
|
+
}
|
|
2046
|
+
/**
|
|
2047
|
+
* Recalls values that were saved with `gui.save()`.
|
|
2048
|
+
* @param {object} obj
|
|
2049
|
+
* @param {boolean} recursive Pass false to exclude folders descending from this GUI.
|
|
2050
|
+
* @returns {this}
|
|
2051
|
+
*/
|
|
2052
|
+
load(e, t = !0) {
|
|
2053
|
+
return e.controllers && this.controllers.forEach((i) => {
|
|
2054
|
+
i instanceof O || i._name in e.controllers && i.load(e.controllers[i._name]);
|
|
2055
|
+
}), t && e.folders && this.folders.forEach((i) => {
|
|
2056
|
+
i._title in e.folders && i.load(e.folders[i._title]);
|
|
2057
|
+
}), this;
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Returns an object mapping controller names to values. The object can be passed to `gui.load()` to
|
|
2061
|
+
* recall these values.
|
|
2062
|
+
* @example
|
|
2063
|
+
* {
|
|
2064
|
+
* controllers: {
|
|
2065
|
+
* prop1: 1,
|
|
2066
|
+
* prop2: 'value',
|
|
2067
|
+
* ...
|
|
2068
|
+
* },
|
|
2069
|
+
* folders: {
|
|
2070
|
+
* folderName1: { controllers, folders },
|
|
2071
|
+
* folderName2: { controllers, folders }
|
|
2072
|
+
* ...
|
|
2073
|
+
* }
|
|
2074
|
+
* }
|
|
2075
|
+
*
|
|
2076
|
+
* @param {boolean} recursive Pass false to exclude folders descending from this GUI.
|
|
2077
|
+
* @returns {object}
|
|
2078
|
+
*/
|
|
2079
|
+
save(e = !0) {
|
|
2080
|
+
const t = {
|
|
2081
|
+
controllers: {},
|
|
2082
|
+
folders: {}
|
|
2083
|
+
};
|
|
2084
|
+
return this.controllers.forEach((i) => {
|
|
2085
|
+
if (!(i instanceof O)) {
|
|
2086
|
+
if (i._name in t.controllers)
|
|
2087
|
+
throw new Error(`Cannot save GUI with duplicate property "${i._name}"`);
|
|
2088
|
+
t.controllers[i._name] = i.save();
|
|
2089
|
+
}
|
|
2090
|
+
}), e && this.folders.forEach((i) => {
|
|
2091
|
+
if (i._title in t.folders)
|
|
2092
|
+
throw new Error(`Cannot save GUI with duplicate folder "${i._title}"`);
|
|
2093
|
+
t.folders[i._title] = i.save();
|
|
2094
|
+
}), t;
|
|
2095
|
+
}
|
|
2096
|
+
/**
|
|
2097
|
+
* Opens a GUI or folder. GUI and folders are open by default.
|
|
2098
|
+
* @param {boolean} open Pass false to close.
|
|
2099
|
+
* @returns {this}
|
|
2100
|
+
* @example
|
|
2101
|
+
* gui.open(); // open
|
|
2102
|
+
* gui.open( false ); // close
|
|
2103
|
+
* gui.open( gui._closed ); // toggle
|
|
2104
|
+
*/
|
|
2105
|
+
open(e = !0) {
|
|
2106
|
+
return this._setClosed(!e), this.$title.setAttribute("aria-expanded", !this._closed), this.domElement.classList.toggle("lil-closed", this._closed), this;
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* Closes the GUI.
|
|
2110
|
+
* @returns {this}
|
|
2111
|
+
*/
|
|
2112
|
+
close() {
|
|
2113
|
+
return this.open(!1);
|
|
2114
|
+
}
|
|
2115
|
+
_setClosed(e) {
|
|
2116
|
+
this._closed !== e && (this._closed = e, this._callOnOpenClose(this));
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Shows the GUI after it's been hidden.
|
|
2120
|
+
* @param {boolean} show
|
|
2121
|
+
* @returns {this}
|
|
2122
|
+
* @example
|
|
2123
|
+
* gui.show();
|
|
2124
|
+
* gui.show( false ); // hide
|
|
2125
|
+
* gui.show( gui._hidden ); // toggle
|
|
2126
|
+
*/
|
|
2127
|
+
show(e = !0) {
|
|
2128
|
+
return this._hidden = !e, this.domElement.style.display = this._hidden ? "none" : "", this;
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Hides the GUI.
|
|
2132
|
+
* @returns {this}
|
|
2133
|
+
*/
|
|
2134
|
+
hide() {
|
|
2135
|
+
return this.show(!1);
|
|
2136
|
+
}
|
|
2137
|
+
openAnimated(e = !0) {
|
|
2138
|
+
return this._setClosed(!e), this.$title.setAttribute("aria-expanded", !this._closed), requestAnimationFrame(() => {
|
|
2139
|
+
const t = this.$children.clientHeight;
|
|
2140
|
+
this.$children.style.height = t + "px", this.domElement.classList.add("lil-transition");
|
|
2141
|
+
const i = (n) => {
|
|
2142
|
+
n.target === this.$children && (this.$children.style.height = "", this.domElement.classList.remove("lil-transition"), this.$children.removeEventListener("transitionend", i));
|
|
2143
|
+
};
|
|
2144
|
+
this.$children.addEventListener("transitionend", i);
|
|
2145
|
+
const r = e ? this.$children.scrollHeight : 0;
|
|
2146
|
+
this.domElement.classList.toggle("lil-closed", !e), requestAnimationFrame(() => {
|
|
2147
|
+
this.$children.style.height = r + "px";
|
|
2148
|
+
});
|
|
2149
|
+
}), this;
|
|
2150
|
+
}
|
|
2151
|
+
/**
|
|
2152
|
+
* Change the title of this GUI.
|
|
2153
|
+
* @param {string} title
|
|
2154
|
+
* @returns {this}
|
|
2155
|
+
*/
|
|
2156
|
+
title(e) {
|
|
2157
|
+
return this._title = e, this.$title.textContent = e, this;
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* Resets all controllers to their initial values.
|
|
2161
|
+
* @param {boolean} recursive Pass false to exclude folders descending from this GUI.
|
|
2162
|
+
* @returns {this}
|
|
2163
|
+
*/
|
|
2164
|
+
reset(e = !0) {
|
|
2165
|
+
return (e ? this.controllersRecursive() : this.controllers).forEach((i) => i.reset()), this;
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Pass a function to be called whenever a controller in this GUI changes.
|
|
2169
|
+
* @param {function({object:object, property:string, value:any, controller:Controller})} callback
|
|
2170
|
+
* @returns {this}
|
|
2171
|
+
* @example
|
|
2172
|
+
* gui.onChange( event => {
|
|
2173
|
+
* event.object // object that was modified
|
|
2174
|
+
* event.property // string, name of property
|
|
2175
|
+
* event.value // new value of controller
|
|
2176
|
+
* event.controller // controller that was modified
|
|
2177
|
+
* } );
|
|
2178
|
+
*/
|
|
2179
|
+
onChange(e) {
|
|
2180
|
+
return this._onChange = e, this;
|
|
2181
|
+
}
|
|
2182
|
+
_callOnChange(e) {
|
|
2183
|
+
this.parent && this.parent._callOnChange(e), this._onChange !== void 0 && this._onChange.call(this, {
|
|
2184
|
+
object: e.object,
|
|
2185
|
+
property: e.property,
|
|
2186
|
+
value: e.getValue(),
|
|
2187
|
+
controller: e
|
|
2188
|
+
});
|
|
2189
|
+
}
|
|
2190
|
+
/**
|
|
2191
|
+
* Pass a function to be called whenever a controller in this GUI has finished changing.
|
|
2192
|
+
* @param {function({object:object, property:string, value:any, controller:Controller})} callback
|
|
2193
|
+
* @returns {this}
|
|
2194
|
+
* @example
|
|
2195
|
+
* gui.onFinishChange( event => {
|
|
2196
|
+
* event.object // object that was modified
|
|
2197
|
+
* event.property // string, name of property
|
|
2198
|
+
* event.value // new value of controller
|
|
2199
|
+
* event.controller // controller that was modified
|
|
2200
|
+
* } );
|
|
2201
|
+
*/
|
|
2202
|
+
onFinishChange(e) {
|
|
2203
|
+
return this._onFinishChange = e, this;
|
|
2204
|
+
}
|
|
2205
|
+
_callOnFinishChange(e) {
|
|
2206
|
+
this.parent && this.parent._callOnFinishChange(e), this._onFinishChange !== void 0 && this._onFinishChange.call(this, {
|
|
2207
|
+
object: e.object,
|
|
2208
|
+
property: e.property,
|
|
2209
|
+
value: e.getValue(),
|
|
2210
|
+
controller: e
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
/**
|
|
2214
|
+
* Pass a function to be called when this GUI or its descendants are opened or closed.
|
|
2215
|
+
* @param {function(GUI)} callback
|
|
2216
|
+
* @returns {this}
|
|
2217
|
+
* @example
|
|
2218
|
+
* gui.onOpenClose( changedGUI => {
|
|
2219
|
+
* console.log( changedGUI._closed );
|
|
2220
|
+
* } );
|
|
2221
|
+
*/
|
|
2222
|
+
onOpenClose(e) {
|
|
2223
|
+
return this._onOpenClose = e, this;
|
|
2224
|
+
}
|
|
2225
|
+
_callOnOpenClose(e) {
|
|
2226
|
+
this.parent && this.parent._callOnOpenClose(e), this._onOpenClose !== void 0 && this._onOpenClose.call(this, e);
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Destroys all DOM elements and event listeners associated with this GUI.
|
|
2230
|
+
*/
|
|
2231
|
+
destroy() {
|
|
2232
|
+
this.parent && (this.parent.children.splice(this.parent.children.indexOf(this), 1), this.parent.folders.splice(this.parent.folders.indexOf(this), 1)), this.domElement.parentElement && this.domElement.parentElement.removeChild(this.domElement), Array.from(this.children).forEach((e) => e.destroy());
|
|
2233
|
+
}
|
|
2234
|
+
/**
|
|
2235
|
+
* Returns an array of controllers contained by this GUI and its descendents.
|
|
2236
|
+
* @returns {Controller[]}
|
|
2237
|
+
*/
|
|
2238
|
+
controllersRecursive() {
|
|
2239
|
+
let e = Array.from(this.controllers);
|
|
2240
|
+
return this.folders.forEach((t) => {
|
|
2241
|
+
e = e.concat(t.controllersRecursive());
|
|
2242
|
+
}), e;
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Returns an array of folders contained by this GUI and its descendents.
|
|
2246
|
+
* @returns {GUI[]}
|
|
2247
|
+
*/
|
|
2248
|
+
foldersRecursive() {
|
|
2249
|
+
let e = Array.from(this.folders);
|
|
2250
|
+
return this.folders.forEach((t) => {
|
|
2251
|
+
e = e.concat(t.foldersRecursive());
|
|
2252
|
+
}), e;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
class le {
|
|
2256
|
+
constructor(e, t) {
|
|
2257
|
+
this.editor = e, this.gui = new U({
|
|
2258
|
+
container: t,
|
|
2259
|
+
title: "Hierarchy",
|
|
2260
|
+
touchEventTarget: t,
|
|
2261
|
+
autoPlace: !1
|
|
2262
|
+
}), this.gui.domElement.style.width = "100%", this.gui.domElement.style.height = "auto", this.init(), setInterval(() => this.refresh(), 1e3);
|
|
2263
|
+
}
|
|
2264
|
+
refresh() {
|
|
2265
|
+
const e = this.editor.game.scene || [];
|
|
2266
|
+
this.lastCount !== e.length && (this.lastCount = e.length, this.init());
|
|
2267
|
+
}
|
|
2268
|
+
init() {
|
|
2269
|
+
[...this.gui.children].forEach((n) => n.destroy());
|
|
2270
|
+
const t = this.editor.game.camera;
|
|
2271
|
+
t && this.gui.add({ select: () => this.editor.selectObject(t) }, "select").name("Main Camera");
|
|
2272
|
+
const i = this.editor.game.lightCamera;
|
|
2273
|
+
i && this.gui.add({ select: () => this.editor.selectObject(i) }, "select").name("Light Camera"), (this.editor.game.scene || []).forEach((n, o) => {
|
|
2274
|
+
const a = n.name || `Object ${o}`;
|
|
2275
|
+
this.gui.add({ select: () => this.editor.selectObject(n) }, "select").name(a);
|
|
2276
|
+
});
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
class he {
|
|
2280
|
+
constructor(e, t) {
|
|
2281
|
+
this.editor = e, this.container = t, this.gui = new U({
|
|
2282
|
+
container: t,
|
|
2283
|
+
title: "Inspector",
|
|
2284
|
+
touchEventTarget: t,
|
|
2285
|
+
autoPlace: !1
|
|
2286
|
+
}), this.gui.domElement.style.width = "100%", this.gui.domElement.style.height = "auto", this.selectedObject = null, this.refresh();
|
|
2287
|
+
}
|
|
2288
|
+
inspect(e) {
|
|
2289
|
+
this.selectedObject = e, this.refresh();
|
|
2290
|
+
}
|
|
2291
|
+
refresh() {
|
|
2292
|
+
if ([...this.gui.children].forEach((r) => r.destroy()), !this.selectedObject) {
|
|
2293
|
+
this.gui.add({ status: "No selection" }, "status").name("Object").disable();
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
const t = this.selectedObject, i = t.name || "GameObject";
|
|
2297
|
+
if (t.transform) {
|
|
2298
|
+
const r = t.transform, n = this.gui.addFolder(`Transform: ${i}`), o = n.addFolder("Position");
|
|
2299
|
+
o.add(r.position, "x").step(0.1).listen().name("X"), o.add(r.position, "y").step(0.1).listen().name("Y"), o.add(r.position, "z").step(0.1).listen().name("Z");
|
|
2300
|
+
const a = n.addFolder("Rotation");
|
|
2301
|
+
a.add(r.rotation, "x").step(0.1).listen().name("X"), a.add(r.rotation, "y").step(0.1).listen().name("Y"), a.add(r.rotation, "z").step(0.1).listen().name("Z");
|
|
2302
|
+
const l = n.addFolder("Scale");
|
|
2303
|
+
l.add(r.scale, "x").step(0.1).listen().name("X"), l.add(r.scale, "y").step(0.1).listen().name("Y"), l.add(r.scale, "z").step(0.1).listen().name("Z");
|
|
2304
|
+
}
|
|
2305
|
+
if (t instanceof G) {
|
|
2306
|
+
const r = this.gui.addFolder("Camera Settings");
|
|
2307
|
+
r.add(t, "orthographic").name("Orthographic").onChange(() => t.updateProjection());
|
|
2308
|
+
const n = r.addFolder("Perspective");
|
|
2309
|
+
n.add(t, "fov", 0.1, 3.14).step(0.01).name("FOV").onChange(() => t.updateProjection()), r.addFolder("Orthographic").add(t, "orthoSize", 0.1, 100).step(1).name("Size (Half Height)").onChange(() => t.updateProjection()), r.add(t, "near", 0.01, 10).step(0.01).name("Near Plane").onChange(() => t.updateProjection()), r.add(t, "far", 10.1, 1e3).step(1).name("Far Plane").onChange(() => t.updateProjection()), n.open();
|
|
2310
|
+
}
|
|
2311
|
+
if (t.material) {
|
|
2312
|
+
const r = this.gui.addFolder("Material");
|
|
2313
|
+
r.add(t.material, "name").name("Material Name").disable().listen(), r.add({ select: () => {
|
|
2314
|
+
this.editor.windows.material && (this.editor.windows.material.inspect(t.material), this.editor.windows.material.container.parentElement.style.display = "flex");
|
|
2315
|
+
} }, "select").name("Open in Material Editor");
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
class de {
|
|
2320
|
+
constructor(e, t) {
|
|
2321
|
+
this.editor = e, this.container = t, this.gui = new U({
|
|
2322
|
+
container: t,
|
|
2323
|
+
title: "Material Editor",
|
|
2324
|
+
touchEventTarget: t,
|
|
2325
|
+
autoPlace: !1
|
|
2326
|
+
}), this.gui.domElement.style.width = "100%", this.gui.domElement.style.height = "auto", this.selectedMaterial = null, this.init();
|
|
2327
|
+
}
|
|
2328
|
+
init() {
|
|
2329
|
+
this.refreshList();
|
|
2330
|
+
}
|
|
2331
|
+
refreshList() {
|
|
2332
|
+
[...this.gui.children].forEach((r) => r.destroy()), this.propertyFolder = null;
|
|
2333
|
+
const t = this.editor.game.materials || {}, i = this.gui.addFolder("Project Materials");
|
|
2334
|
+
for (const r in t) {
|
|
2335
|
+
const n = t[r];
|
|
2336
|
+
i.add({ select: () => this.inspect(n) }, "select").name(r);
|
|
2337
|
+
}
|
|
2338
|
+
this.selectedMaterial ? this.drawMaterialProperties(this.selectedMaterial) : this.gui.add({ info: "Select a material" }, "info").name("Status").disable();
|
|
2339
|
+
}
|
|
2340
|
+
inspect(e) {
|
|
2341
|
+
this.selectedMaterial = e, this.refreshList();
|
|
2342
|
+
}
|
|
2343
|
+
drawMaterialProperties(e) {
|
|
2344
|
+
let t;
|
|
2345
|
+
if (this.propertyFolder ? (t = this.propertyFolder, [...t.children].forEach((r) => r.destroy()), t.title(`Properties: ${e.name || "Unnamed"}`)) : (t = this.gui.addFolder(`Properties: ${e.name || "Unnamed"}`), this.propertyFolder = t), !!e.uniforms)
|
|
2346
|
+
for (const i in e.uniforms) {
|
|
2347
|
+
const r = e.uniforms[i], n = r.value;
|
|
2348
|
+
if (r.type, Array.isArray(n) || n instanceof Float32Array)
|
|
2349
|
+
if (i.toLowerCase().includes("color") && (n.length === 3 || n.length === 4))
|
|
2350
|
+
t.addColor(r, "value").name(i).listen();
|
|
2351
|
+
else {
|
|
2352
|
+
const a = t.addFolder(i), l = ["x", "y", "z", "w"];
|
|
2353
|
+
for (let c = 0; c < n.length; c++) {
|
|
2354
|
+
const h = {
|
|
2355
|
+
get val() {
|
|
2356
|
+
return n[c];
|
|
2357
|
+
},
|
|
2358
|
+
set val(d) {
|
|
2359
|
+
n[c] = d;
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
a.add(h, "val").step(0.01).name(l[c] || `[${c}]`).listen();
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
else if (typeof n == "number") {
|
|
2366
|
+
const o = {
|
|
2367
|
+
get val() {
|
|
2368
|
+
return r.value;
|
|
2369
|
+
},
|
|
2370
|
+
// Access from source object
|
|
2371
|
+
set val(l) {
|
|
2372
|
+
r.value = l;
|
|
2373
|
+
}
|
|
2374
|
+
};
|
|
2375
|
+
let a = t.add(o, "val").name(i);
|
|
2376
|
+
i.toLowerCase().includes("threshold") || i.toLowerCase().includes("factor") ? a = a.min(0).max(1).step(0.01) : a = a.step(0.01), a.listen();
|
|
2377
|
+
} else n instanceof WebGLTexture && t.add({ info: "Texture" }, "info").name(i).disable();
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
class ce {
|
|
2382
|
+
constructor(e, t) {
|
|
2383
|
+
this.editor = e, this.container = t, this.gui = new U({
|
|
2384
|
+
container: t,
|
|
2385
|
+
title: "Render Passes",
|
|
2386
|
+
touchEventTarget: t,
|
|
2387
|
+
autoPlace: !1
|
|
2388
|
+
}), this.gui.domElement.style.width = "100%", this.gui.domElement.style.height = "auto", this.init();
|
|
2389
|
+
}
|
|
2390
|
+
init() {
|
|
2391
|
+
this.refresh(), setInterval(() => this.updateStats(), 1e3);
|
|
2392
|
+
}
|
|
2393
|
+
refresh() {
|
|
2394
|
+
[...this.gui.children].forEach((i) => i.destroy());
|
|
2395
|
+
const t = this.editor.game.renderQueue;
|
|
2396
|
+
!t || !t.passes || t.passes.forEach((i, r) => {
|
|
2397
|
+
const n = this.gui.addFolder(`${r}: ${i.name || "Pass"}`);
|
|
2398
|
+
if (n.add(i, "enabled").name("Active"), n.add(i, "drawCount").name("Draw Calls").disable().listen(), n.add(i, "executionTime").name("Time (ms)").disable().listen(), i.clearColor) {
|
|
2399
|
+
const l = {
|
|
2400
|
+
get color() {
|
|
2401
|
+
return [i.clearColor[0], i.clearColor[1], i.clearColor[2]];
|
|
2402
|
+
},
|
|
2403
|
+
set color(c) {
|
|
2404
|
+
i.clearColor[0] = c[0], i.clearColor[1] = c[1], i.clearColor[2] = c[2];
|
|
2405
|
+
}
|
|
2406
|
+
};
|
|
2407
|
+
n.addColor(l, "color").name("Clear Color");
|
|
2408
|
+
}
|
|
2409
|
+
i.renderTarget ? n.add({ info: `${i.renderTarget.width}x${i.renderTarget.height}` }, "info").name("Resolution").disable() : n.add({ info: "Screen" }, "info").name("Target").disable(), i.material && n.add({ select: () => {
|
|
2410
|
+
this.editor.windows.material && this.editor.windows.material.inspect(i.material);
|
|
2411
|
+
} }, "select").name("Inspect Material");
|
|
2412
|
+
const o = { show: !1 }, a = n.addFolder("Performance Details");
|
|
2413
|
+
a.add(o, "show").name("List Draw Calls").onChange((l) => {
|
|
2414
|
+
l ? this.showDetails(a, i) : this.clearDetails(a);
|
|
2415
|
+
});
|
|
2416
|
+
});
|
|
2417
|
+
}
|
|
2418
|
+
showDetails(e, t) {
|
|
2419
|
+
if (this.clearDetails(e), !t.drawDetails || t.drawDetails.length === 0) {
|
|
2420
|
+
e.add({ info: "No draw calls" }, "info").name("Status").disable();
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2423
|
+
t.drawDetails.forEach((i, r) => {
|
|
2424
|
+
const n = e.addFolder(`Draw ${r}: ${i.object}`);
|
|
2425
|
+
n.add(i, "material").name("Material").disable(), n.add(i, "shader").name("Shader").disable(), n.add(i, "target").name("Target").disable();
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
clearDetails(e) {
|
|
2429
|
+
[...e.children].forEach((i) => {
|
|
2430
|
+
i.property !== "show" && i.destroy();
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
updateStats() {
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
class ue {
|
|
2437
|
+
constructor(e, t) {
|
|
2438
|
+
this.editor = e, this.container = t, this.gui = new U({
|
|
2439
|
+
container: t,
|
|
2440
|
+
title: "Engine Profiler",
|
|
2441
|
+
touchEventTarget: t,
|
|
2442
|
+
autoPlace: !1
|
|
2443
|
+
}), this.gui.domElement.style.width = "100%", this.gui.domElement.style.height = "auto", this.stats = {
|
|
2444
|
+
fps: 0,
|
|
2445
|
+
ms: 0,
|
|
2446
|
+
totalDrawCalls: 0,
|
|
2447
|
+
totalPasses: 0
|
|
2448
|
+
}, this.init();
|
|
2449
|
+
}
|
|
2450
|
+
init() {
|
|
2451
|
+
this.gui.add(this.stats, "fps").name("FPS").disable().listen(), this.gui.add(this.stats, "ms").name("Frame Time (ms)").disable().listen(), this.gui.add(this.stats, "totalDrawCalls").name("Total Draw Calls").disable().listen(), this.gui.add(this.stats, "totalPasses").name("Total Passes").disable().listen(), this.passesFolder = this.gui.addFolder("Pass Performance"), this.showPassDetails = !1, this.passesFolder.add(this, "showPassDetails").name("Show Details").onChange(() => this.rebuildPassFolders()), setInterval(() => this.update(), 500);
|
|
2452
|
+
}
|
|
2453
|
+
rebuildPassFolders() {
|
|
2454
|
+
if ([...this.passesFolder.children].forEach((i) => {
|
|
2455
|
+
i.property !== "showPassDetails" && i.destroy();
|
|
2456
|
+
}), !this.showPassDetails) return;
|
|
2457
|
+
const t = this.editor.game;
|
|
2458
|
+
t.renderQueue && t.renderQueue.passes && t.renderQueue.passes.forEach((i) => {
|
|
2459
|
+
const r = this.passesFolder.addFolder(i.name || "Pass");
|
|
2460
|
+
r.add(i, "drawCount").name("Draw Calls").disable().listen(), r.add(i, "executionTime").name("Perf (ms)").disable().listen(), r.add(i, "enabled").name("Active").disable().listen();
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2463
|
+
update() {
|
|
2464
|
+
const e = this.editor.game;
|
|
2465
|
+
if (!e) return;
|
|
2466
|
+
this.stats.fps = Math.round(1 / (this.editor.game.deltaTime || 0.016)), this.stats.ms = ((this.editor.game.deltaTime || 0.016) * 1e3).toFixed(2);
|
|
2467
|
+
let t = 0;
|
|
2468
|
+
e.renderQueue && e.renderQueue.passes && (this.stats.totalPasses = e.renderQueue.passes.length, e.renderQueue.passes.forEach((i) => {
|
|
2469
|
+
t += i.drawCount || 0;
|
|
2470
|
+
})), this.stats.totalDrawCalls = t, e.renderQueue.passes.forEach((i) => {
|
|
2471
|
+
`${i.name}${i.drawCount}`;
|
|
2472
|
+
});
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
class Ye {
|
|
2476
|
+
constructor(e) {
|
|
2477
|
+
this.game = e, this.wm = new q(), this.windows = {}, this.initWindows();
|
|
2478
|
+
}
|
|
2479
|
+
initWindows() {
|
|
2480
|
+
const e = this.wm.createWindow("Hierarchy", 20, 20, 250, 400);
|
|
2481
|
+
this.windows.hierarchy = new le(this, e.content), this.wm.addNavItem("HIERARCHY", e.window), e.window.style.display = "none";
|
|
2482
|
+
const t = this.wm.createWindow("Inspector", 290, 20, 320, 500);
|
|
2483
|
+
this.windows.inspector = new he(this, t.content), this.wm.addNavItem("INSPECTOR", t.window), t.window.style.display = "none";
|
|
2484
|
+
const i = this.wm.createWindow("Materials", 630, 20, 320, 500);
|
|
2485
|
+
this.windows.material = new de(this, i.content), this.wm.addNavItem("MATERIALS", i.window), i.window.style.display = "none";
|
|
2486
|
+
const r = this.wm.createWindow("Render Passes", 970, 20, 320, 500);
|
|
2487
|
+
this.windows.renderPass = new ce(this, r.content), this.wm.addNavItem("PASSES", r.window), r.window.style.display = "none";
|
|
2488
|
+
const n = this.wm.createWindow("Profiler", 20, 440, 250, 250);
|
|
2489
|
+
this.windows.profiler = new ue(this, n.content), this.wm.addNavItem("PROFILER", n.window), n.window.style.display = "none";
|
|
2490
|
+
let o = ["Final"];
|
|
2491
|
+
this.game.viewportPass && this.game.viewportPass.buffers && (o = Object.keys(this.game.viewportPass.buffers)), this.wm.addNavSelect(o, (a) => {
|
|
2492
|
+
this.game.setViewports(a);
|
|
2493
|
+
}), this.setupShortcuts();
|
|
2494
|
+
}
|
|
2495
|
+
setupShortcuts() {
|
|
2496
|
+
window.addEventListener("keydown", (e) => {
|
|
2497
|
+
e.key.toLowerCase() === "h" && this.wm.toggleVisibility();
|
|
2498
|
+
});
|
|
2499
|
+
}
|
|
2500
|
+
selectObject(e) {
|
|
2501
|
+
e && (this.windows.inspector.inspect(e), this.windows.inspector.gui.parentElement.style.display === "none" && (this.windows.inspector.gui.parentElement.style.display = "block"));
|
|
2502
|
+
}
|
|
2503
|
+
update() {
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
const fe = `attribute vec4 aVertexPosition;\r
|
|
2507
|
+
attribute vec2 aTexCoord;\r
|
|
2508
|
+
\r
|
|
2509
|
+
uniform mat4 uViewMatrix;\r
|
|
2510
|
+
uniform mat4 uProjectionMatrix;\r
|
|
2511
|
+
uniform mat4 uModelMatrix;\r
|
|
2512
|
+
\r
|
|
2513
|
+
varying highp vec2 vTexCoord;\r
|
|
2514
|
+
\r
|
|
2515
|
+
void main() {\r
|
|
2516
|
+
gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aVertexPosition;\r
|
|
2517
|
+
vTexCoord = aTexCoord;\r
|
|
2518
|
+
}\r
|
|
2519
|
+
`, me = `precision highp float;\r
|
|
2520
|
+
varying highp vec2 vTexCoord;\r
|
|
2521
|
+
uniform highp vec4 uColor;\r
|
|
2522
|
+
\r
|
|
2523
|
+
void main() {\r
|
|
2524
|
+
gl_FragColor = uColor;\r
|
|
2525
|
+
}\r
|
|
2526
|
+
`, pe = `precision highp float;\r
|
|
2527
|
+
\r
|
|
2528
|
+
attribute vec2 aVertexPosition;\r
|
|
2529
|
+
attribute vec2 aTexCoord;\r
|
|
2530
|
+
\r
|
|
2531
|
+
varying vec2 vTexCoord;\r
|
|
2532
|
+
\r
|
|
2533
|
+
void main() {\r
|
|
2534
|
+
// Just forward texture coordinates, no transforms needed for screen-space quad\r
|
|
2535
|
+
gl_Position = vec4(aVertexPosition.x, aVertexPosition.y, 0.0, 1.0);\r
|
|
2536
|
+
vTexCoord = aTexCoord;\r
|
|
2537
|
+
}\r
|
|
2538
|
+
`, ge = `precision highp float;\r
|
|
2539
|
+
\r
|
|
2540
|
+
varying vec2 vTexCoord;\r
|
|
2541
|
+
uniform sampler2D uTexture;\r
|
|
2542
|
+
uniform sampler2D uOverlay; // Optional outline texture\r
|
|
2543
|
+
uniform float uUseOverlay; // Toggle overlay blending (float 0.0 or 1.0)\r
|
|
2544
|
+
\r
|
|
2545
|
+
void main() {\r
|
|
2546
|
+
vec4 baseColor = texture2D(uTexture, vTexCoord);\r
|
|
2547
|
+
\r
|
|
2548
|
+
if (uUseOverlay > 0.5) {\r
|
|
2549
|
+
vec4 overlayColor = texture2D(uOverlay, vTexCoord);\r
|
|
2550
|
+
// Simple alpha blend: overlay over base\r
|
|
2551
|
+
gl_FragColor = vec4(mix(baseColor.rgb, overlayColor.rgb, overlayColor.a), baseColor.a);\r
|
|
2552
|
+
} else {\r
|
|
2553
|
+
gl_FragColor = baseColor;\r
|
|
2554
|
+
}\r
|
|
2555
|
+
}\r
|
|
2556
|
+
`, ve = `precision highp float;\r
|
|
2557
|
+
\r
|
|
2558
|
+
attribute vec4 aVertexPosition;\r
|
|
2559
|
+
\r
|
|
2560
|
+
uniform mat4 uModelMatrix;\r
|
|
2561
|
+
uniform mat4 uViewMatrix;\r
|
|
2562
|
+
uniform mat4 uProjectionMatrix;\r
|
|
2563
|
+
\r
|
|
2564
|
+
void main() {\r
|
|
2565
|
+
gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aVertexPosition;\r
|
|
2566
|
+
}\r
|
|
2567
|
+
`, xe = `precision highp float;\r
|
|
2568
|
+
\r
|
|
2569
|
+
void main() {\r
|
|
2570
|
+
float near = 0.1; \r
|
|
2571
|
+
float far = 100.0; \r
|
|
2572
|
+
\r
|
|
2573
|
+
float z = gl_FragCoord.z * 2.0 - 1.0; // Back to NDC \r
|
|
2574
|
+
float linearDepth = (2.0 * near * far) / (far + near - z * (far - near)); // Linearize\r
|
|
2575
|
+
\r
|
|
2576
|
+
linearDepth /= far; // Normalize to [0, 1] range\r
|
|
2577
|
+
\r
|
|
2578
|
+
gl_FragColor = vec4(vec3(linearDepth), 1.0);\r
|
|
2579
|
+
}\r
|
|
2580
|
+
`, we = `precision highp float;\r
|
|
2581
|
+
\r
|
|
2582
|
+
attribute vec4 aVertexPosition;\r
|
|
2583
|
+
attribute vec3 aVertexNormal;\r
|
|
2584
|
+
\r
|
|
2585
|
+
uniform mat4 uModelMatrix;\r
|
|
2586
|
+
uniform mat4 uViewMatrix;\r
|
|
2587
|
+
uniform mat4 uProjectionMatrix;\r
|
|
2588
|
+
\r
|
|
2589
|
+
varying vec3 vWorldPos;\r
|
|
2590
|
+
\r
|
|
2591
|
+
void main() {\r
|
|
2592
|
+
vec4 worldPos = uModelMatrix * aVertexPosition;\r
|
|
2593
|
+
vWorldPos = worldPos.xyz;\r
|
|
2594
|
+
gl_Position = uProjectionMatrix * uViewMatrix * worldPos;\r
|
|
2595
|
+
}\r
|
|
2596
|
+
`, be = `#extension GL_OES_standard_derivatives : enable\r
|
|
2597
|
+
precision highp float;\r
|
|
2598
|
+
\r
|
|
2599
|
+
varying vec3 vWorldPos;\r
|
|
2600
|
+
\r
|
|
2601
|
+
void main() {\r
|
|
2602
|
+
// Calculate face normal using derivatives of world position\r
|
|
2603
|
+
vec3 dx = dFdx(vWorldPos);\r
|
|
2604
|
+
vec3 dy = dFdy(vWorldPos);\r
|
|
2605
|
+
vec3 normal = normalize(cross(dx, dy));\r
|
|
2606
|
+
\r
|
|
2607
|
+
// Remap to 0-1 range for visualization\r
|
|
2608
|
+
gl_FragColor = vec4(normal * 0.5 + 0.5, 1.0);\r
|
|
2609
|
+
}\r
|
|
2610
|
+
`, ye = `precision highp float;\r
|
|
2611
|
+
\r
|
|
2612
|
+
varying vec2 vTexCoord;\r
|
|
2613
|
+
\r
|
|
2614
|
+
uniform sampler2D uDepthTexture;\r
|
|
2615
|
+
uniform sampler2D uNormalTexture;\r
|
|
2616
|
+
uniform sampler2D uSceneTexture;\r
|
|
2617
|
+
\r
|
|
2618
|
+
uniform vec2 uResolution;\r
|
|
2619
|
+
\r
|
|
2620
|
+
// Tunable Uniforms\r
|
|
2621
|
+
uniform float uDepthThreshold;\r
|
|
2622
|
+
uniform float uNormalThreshold;\r
|
|
2623
|
+
uniform float uThickness;\r
|
|
2624
|
+
uniform vec4 uOutlineColor;\r
|
|
2625
|
+
\r
|
|
2626
|
+
void main() {\r
|
|
2627
|
+
// Determine thickness scale\r
|
|
2628
|
+
float thickness = uThickness > 0.0 ? uThickness : 1.0;\r
|
|
2629
|
+
vec2 texelSize = (1.0 / uResolution) * thickness;\r
|
|
2630
|
+
\r
|
|
2631
|
+
// Default fallbacks if uniform is 0 (optional, but good for safety)\r
|
|
2632
|
+
float dThresh = uDepthThreshold > 0.0 ? uDepthThreshold : 0.5; \r
|
|
2633
|
+
float nThresh = uNormalThreshold > 0.0 ? uNormalThreshold : 0.4;\r
|
|
2634
|
+
\r
|
|
2635
|
+
// 1. Sample Center\r
|
|
2636
|
+
float depthCenter = texture2D(uDepthTexture, vTexCoord).r;\r
|
|
2637
|
+
vec3 normalCenter = texture2D(uNormalTexture, vTexCoord).rgb;\r
|
|
2638
|
+
\r
|
|
2639
|
+
// 2. Sample Neighbors (Top, Right) for finite difference\r
|
|
2640
|
+
vec2 uvTop = vTexCoord + vec2(0.0, texelSize.y);\r
|
|
2641
|
+
vec2 uvRight = vTexCoord + vec2(texelSize.x, 0.0);\r
|
|
2642
|
+
\r
|
|
2643
|
+
float depthTop = texture2D(uDepthTexture, uvTop).r;\r
|
|
2644
|
+
float depthRight = texture2D(uDepthTexture, uvRight).r;\r
|
|
2645
|
+
\r
|
|
2646
|
+
vec3 normalTop = texture2D(uNormalTexture, uvTop).rgb;\r
|
|
2647
|
+
vec3 normalRight = texture2D(uNormalTexture, uvRight).rgb;\r
|
|
2648
|
+
\r
|
|
2649
|
+
// 3. Compute Differences\r
|
|
2650
|
+
// Depth: simple derivative magnitude\r
|
|
2651
|
+
float depthDiff0 = depthCenter - depthTop;\r
|
|
2652
|
+
float depthDiff1 = depthCenter - depthRight;\r
|
|
2653
|
+
// Scale by 100 to make depth differences more significant relative to threshold\r
|
|
2654
|
+
float edgeDepth = sqrt(pow(depthDiff0, 2.0) + pow(depthDiff1, 2.0)) * 100.0;\r
|
|
2655
|
+
\r
|
|
2656
|
+
// Normal: distance between normal vectors\r
|
|
2657
|
+
vec3 normalDiff0 = normalCenter - normalTop;\r
|
|
2658
|
+
vec3 normalDiff1 = normalCenter - normalRight;\r
|
|
2659
|
+
float edgeNormal = sqrt(dot(normalDiff0, normalDiff0) + dot(normalDiff1, normalDiff1));\r
|
|
2660
|
+
\r
|
|
2661
|
+
// 4. Thresholding\r
|
|
2662
|
+
float edge = 0.0;\r
|
|
2663
|
+
if (edgeDepth > dThresh) { edge = 1.0; }\r
|
|
2664
|
+
if (edgeNormal > nThresh) { edge = 1.0; }\r
|
|
2665
|
+
\r
|
|
2666
|
+
// 5. Output Outline Only\r
|
|
2667
|
+
// Transparent where no edge\r
|
|
2668
|
+
gl_FragColor = vec4(uOutlineColor.rgb, uOutlineColor.a * edge);\r
|
|
2669
|
+
}\r
|
|
2670
|
+
`, Ce = `precision highp float;\r
|
|
2671
|
+
\r
|
|
2672
|
+
varying highp vec2 vTexCoord;\r
|
|
2673
|
+
\r
|
|
2674
|
+
uniform highp float uTime; \r
|
|
2675
|
+
uniform highp float uSpeed; \r
|
|
2676
|
+
uniform vec2 uWind; \r
|
|
2677
|
+
uniform float uScale;\r
|
|
2678
|
+
\r
|
|
2679
|
+
uniform vec3 uColor1; \r
|
|
2680
|
+
uniform vec3 uColor2; \r
|
|
2681
|
+
uniform vec3 uColor3; \r
|
|
2682
|
+
\r
|
|
2683
|
+
vec2 hash(vec2 p) {\r
|
|
2684
|
+
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));\r
|
|
2685
|
+
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);\r
|
|
2686
|
+
}\r
|
|
2687
|
+
\r
|
|
2688
|
+
float gradientNoise(vec2 p) {\r
|
|
2689
|
+
vec2 i = floor(p);\r
|
|
2690
|
+
vec2 f = fract(p);\r
|
|
2691
|
+
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);\r
|
|
2692
|
+
float a = dot(hash(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0));\r
|
|
2693
|
+
float b = dot(hash(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0));\r
|
|
2694
|
+
float c = dot(hash(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0));\r
|
|
2695
|
+
float d = dot(hash(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0));\r
|
|
2696
|
+
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);\r
|
|
2697
|
+
}\r
|
|
2698
|
+
\r
|
|
2699
|
+
void main() {\r
|
|
2700
|
+
float time = uTime * uSpeed;\r
|
|
2701
|
+
vec2 movement = uWind * time;\r
|
|
2702
|
+
\r
|
|
2703
|
+
// Layer 1: The Macro "Gust" (Very large, slow-moving shadows)\r
|
|
2704
|
+
float n1 = gradientNoise((vTexCoord * uScale * 0.25) + (movement * 0.3));\r
|
|
2705
|
+
\r
|
|
2706
|
+
// Layer 2: The "Tuft" (Medium scale, standard waving)\r
|
|
2707
|
+
float n2 = gradientNoise((vTexCoord * uScale * 1.5) + movement);\r
|
|
2708
|
+
\r
|
|
2709
|
+
// Layer 3: The "Jitter" (High frequency, moves slightly faster)\r
|
|
2710
|
+
// We rotate the wind vector slightly for this layer to create "cross-winds"\r
|
|
2711
|
+
vec2 jitterMovement = vec2(movement.y, -movement.x) * 1.5; \r
|
|
2712
|
+
float n3 = gradientNoise((vTexCoord * uScale * 4.0) + jitterMovement);\r
|
|
2713
|
+
\r
|
|
2714
|
+
// Combine them with weighted averages\r
|
|
2715
|
+
// 20% big gust, 50% main tuft, 30% jitter detail\r
|
|
2716
|
+
float n = (n1 * 0.2) + (n2 * 0.5) + (n3 * 0.3);\r
|
|
2717
|
+
\r
|
|
2718
|
+
// Smoothstep creates that "hand-painted" clumped look\r
|
|
2719
|
+
// Using a tighter range (e.g. -0.3 to 0.4) makes the grass "edges" sharper\r
|
|
2720
|
+
n = smoothstep(-0.4, 0.4, n);\r
|
|
2721
|
+
\r
|
|
2722
|
+
vec3 finalColor;\r
|
|
2723
|
+
if (n < 0.5) {\r
|
|
2724
|
+
finalColor = mix(uColor1, uColor2, n * 2.0);\r
|
|
2725
|
+
} else {\r
|
|
2726
|
+
finalColor = mix(uColor2, uColor3, (n - 0.5) * 2.0);\r
|
|
2727
|
+
}\r
|
|
2728
|
+
\r
|
|
2729
|
+
gl_FragColor = vec4(finalColor, 1.0);\r
|
|
2730
|
+
} `, Ee = `precision highp float;\r
|
|
2731
|
+
\r
|
|
2732
|
+
attribute vec2 aVertexPosition;\r
|
|
2733
|
+
attribute vec2 aTexCoord;\r
|
|
2734
|
+
\r
|
|
2735
|
+
varying vec2 vUv;\r
|
|
2736
|
+
\r
|
|
2737
|
+
void main() {\r
|
|
2738
|
+
vUv = aTexCoord;\r
|
|
2739
|
+
gl_Position = vec4(aVertexPosition, 0.0, 1.0);\r
|
|
2740
|
+
}\r
|
|
2741
|
+
`, Te = `precision highp float;\r
|
|
2742
|
+
\r
|
|
2743
|
+
varying vec2 vUv;\r
|
|
2744
|
+
\r
|
|
2745
|
+
uniform sampler2D uSceneTexture;\r
|
|
2746
|
+
uniform sampler2D uNormalTexture;\r
|
|
2747
|
+
uniform sampler2D uDepthTexture;\r
|
|
2748
|
+
\r
|
|
2749
|
+
// Shadows & Transform\r
|
|
2750
|
+
uniform sampler2D uShadowMap;\r
|
|
2751
|
+
uniform mat4 uInverseViewProjection;\r
|
|
2752
|
+
uniform mat4 uLightSpaceMatrix;\r
|
|
2753
|
+
uniform vec3 uCameraPos; \r
|
|
2754
|
+
uniform float uTime; // Optional for noise\r
|
|
2755
|
+
\r
|
|
2756
|
+
uniform vec3 uLightDir;\r
|
|
2757
|
+
uniform vec3 uLightColor;\r
|
|
2758
|
+
uniform float uAmbient;\r
|
|
2759
|
+
\r
|
|
2760
|
+
// --- SPECULAR UNIFORMS ---\r
|
|
2761
|
+
uniform float uSpecularStrength;\r
|
|
2762
|
+
uniform float uShininess;\r
|
|
2763
|
+
\r
|
|
2764
|
+
// --- VOLUMETRIC UNIFORMS ---\r
|
|
2765
|
+
uniform float uVolumetricSteps;\r
|
|
2766
|
+
uniform float uVolumetricIntensity; \r
|
|
2767
|
+
uniform float uVolumetricScattering; \r
|
|
2768
|
+
\r
|
|
2769
|
+
const int MAX_VOLUMETRIC_STEPS = 50; // Hard limit for loop\r
|
|
2770
|
+
\r
|
|
2771
|
+
// Helper for shadow check without bias issues inside volume\r
|
|
2772
|
+
float isLit(vec3 pos) {\r
|
|
2773
|
+
vec4 posLightSpace = uLightSpaceMatrix * vec4(pos, 1.0);\r
|
|
2774
|
+
vec3 projCoords = posLightSpace.xyz / posLightSpace.w;\r
|
|
2775
|
+
projCoords = projCoords * 0.5 + 0.5;\r
|
|
2776
|
+
\r
|
|
2777
|
+
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0) \r
|
|
2778
|
+
return 0.0; // Outside light cone\r
|
|
2779
|
+
\r
|
|
2780
|
+
float closestDepth = texture2D(uShadowMap, projCoords.xy).r; \r
|
|
2781
|
+
float currentDepth = projCoords.z;\r
|
|
2782
|
+
\r
|
|
2783
|
+
// Slightly larger bias for volume sampling to avoid self-shadowing acne in air\r
|
|
2784
|
+
float bias = 0.01; \r
|
|
2785
|
+
\r
|
|
2786
|
+
return currentDepth - bias > closestDepth ? 0.0 : 1.0; // 1.0 = Lit, 0.0 = Shadow\r
|
|
2787
|
+
}\r
|
|
2788
|
+
\r
|
|
2789
|
+
vec3 calculateVolumetricLight(vec3 startPos, vec3 endPos) {\r
|
|
2790
|
+
vec3 rayVector = endPos - startPos;\r
|
|
2791
|
+
float rayLength = length(rayVector);\r
|
|
2792
|
+
vec3 rayDir = rayVector / rayLength;\r
|
|
2793
|
+
\r
|
|
2794
|
+
// Max distance for volumetric fog\r
|
|
2795
|
+
float maxDist = 50.0;\r
|
|
2796
|
+
if(rayLength > maxDist) {\r
|
|
2797
|
+
rayLength = maxDist;\r
|
|
2798
|
+
}\r
|
|
2799
|
+
\r
|
|
2800
|
+
float stepSize = rayLength / uVolumetricSteps;\r
|
|
2801
|
+
vec3 currentPos = startPos;\r
|
|
2802
|
+
\r
|
|
2803
|
+
// Simple dither to break banding (using UV)\r
|
|
2804
|
+
float dither = fract(sin(dot(vUv, vec2(12.9898, 78.233))) * 43758.5453);\r
|
|
2805
|
+
currentPos += rayDir * stepSize * dither;\r
|
|
2806
|
+
\r
|
|
2807
|
+
float accumulation = 0.0;\r
|
|
2808
|
+
\r
|
|
2809
|
+
for(int i = 0; i < MAX_VOLUMETRIC_STEPS; i++) {\r
|
|
2810
|
+
if(float(i) >= uVolumetricSteps) break;\r
|
|
2811
|
+
accumulation += isLit(currentPos);\r
|
|
2812
|
+
currentPos += rayDir * stepSize;\r
|
|
2813
|
+
}\r
|
|
2814
|
+
\r
|
|
2815
|
+
accumulation /= uVolumetricSteps;\r
|
|
2816
|
+
\r
|
|
2817
|
+
// Scattering phase function (simple isotropic for now)\r
|
|
2818
|
+
// float phase = 1.0 / (4.0 * 3.14159); \r
|
|
2819
|
+
\r
|
|
2820
|
+
return uLightColor * accumulation * uVolumetricIntensity; // * phase;\r
|
|
2821
|
+
}\r
|
|
2822
|
+
\r
|
|
2823
|
+
vec3 getWorldPosition(vec2 uv, float depth) {\r
|
|
2824
|
+
float near = 0.1;\r
|
|
2825
|
+
float far = 100.0;\r
|
|
2826
|
+
float linearDepth = depth * far;\r
|
|
2827
|
+
\r
|
|
2828
|
+
float z_ndc = 1.0; \r
|
|
2829
|
+
if (linearDepth > 0.0001) {\r
|
|
2830
|
+
z_ndc = (far + near - (2.0 * near * far) / linearDepth) / (far - near);\r
|
|
2831
|
+
}\r
|
|
2832
|
+
\r
|
|
2833
|
+
vec4 clipSpacePosition = vec4(uv * 2.0 - 1.0, z_ndc, 1.0);\r
|
|
2834
|
+
vec4 worldPosition = uInverseViewProjection * clipSpacePosition;\r
|
|
2835
|
+
\r
|
|
2836
|
+
return worldPosition.xyz / worldPosition.w;\r
|
|
2837
|
+
}\r
|
|
2838
|
+
\r
|
|
2839
|
+
float calculateShadow(vec3 worldPos) {\r
|
|
2840
|
+
vec4 posLightSpace = uLightSpaceMatrix * vec4(worldPos, 1.0);\r
|
|
2841
|
+
vec3 projCoords = posLightSpace.xyz / posLightSpace.w;\r
|
|
2842
|
+
projCoords = projCoords * 0.5 + 0.5;\r
|
|
2843
|
+
\r
|
|
2844
|
+
if (projCoords.z > 1.0 || projCoords.x < 0.0 || projCoords.x > 1.0 || projCoords.y < 0.0 || projCoords.y > 1.0) \r
|
|
2845
|
+
return 0.0;\r
|
|
2846
|
+
\r
|
|
2847
|
+
float closestDepth = texture2D(uShadowMap, projCoords.xy).r; \r
|
|
2848
|
+
float currentDepth = projCoords.z;\r
|
|
2849
|
+
float bias = 0.005; \r
|
|
2850
|
+
\r
|
|
2851
|
+
return currentDepth - bias > closestDepth ? 1.0 : 0.0;\r
|
|
2852
|
+
}\r
|
|
2853
|
+
\r
|
|
2854
|
+
void main() {\r
|
|
2855
|
+
vec4 sceneColor = texture2D(uSceneTexture, vUv);\r
|
|
2856
|
+
vec3 normalOrig = texture2D(uNormalTexture, vUv).rgb;\r
|
|
2857
|
+
float depthVal = texture2D(uDepthTexture, vUv).r;\r
|
|
2858
|
+
\r
|
|
2859
|
+
// 1. Reconstruct World Position\r
|
|
2860
|
+
vec3 worldPos = getWorldPosition(vUv, depthVal);\r
|
|
2861
|
+
\r
|
|
2862
|
+
// 2. Vectors\r
|
|
2863
|
+
vec3 N = normalize(normalOrig * 2.0 - 1.0);\r
|
|
2864
|
+
vec3 L = normalize(uLightDir);\r
|
|
2865
|
+
vec3 V = normalize(uCameraPos - worldPos); // View Direction\r
|
|
2866
|
+
vec3 H = normalize(L + V); // Halfway Vector (Blinn-Phong)\r
|
|
2867
|
+
\r
|
|
2868
|
+
// 3. Diffuse Component\r
|
|
2869
|
+
float diff = max(dot(N, L), 0.0);\r
|
|
2870
|
+
\r
|
|
2871
|
+
// 4. Specular Component\r
|
|
2872
|
+
// Only calculate specular if the surface is facing the light (diff > 0)\r
|
|
2873
|
+
float spec = pow(max(dot(N, H), 0.0), uShininess);\r
|
|
2874
|
+
vec3 specular = uSpecularStrength * spec * uLightColor;\r
|
|
2875
|
+
\r
|
|
2876
|
+
// 5. Shadow Calculation\r
|
|
2877
|
+
float shadow = calculateShadow(worldPos);\r
|
|
2878
|
+
\r
|
|
2879
|
+
// 6. Volumetric Lighting\r
|
|
2880
|
+
vec3 volumeLight = calculateVolumetricLight(uCameraPos, worldPos);\r
|
|
2881
|
+
\r
|
|
2882
|
+
// 7. Final Radiance Calculation\r
|
|
2883
|
+
vec3 ambient = uAmbient * uLightColor;\r
|
|
2884
|
+
vec3 diffuse = diff * uLightColor;\r
|
|
2885
|
+
\r
|
|
2886
|
+
// Shadow affects both Diffuse and Specular, but not Ambient\r
|
|
2887
|
+
vec3 lightContribution = (1.0 - shadow) * (diffuse + specular);\r
|
|
2888
|
+
\r
|
|
2889
|
+
// Add volumetric light (additive blending)\r
|
|
2890
|
+
vec3 radiance = (ambient + lightContribution) * sceneColor.rgb + volumeLight;\r
|
|
2891
|
+
\r
|
|
2892
|
+
gl_FragColor = vec4(radiance, sceneColor.a);\r
|
|
2893
|
+
}`, _e = `precision highp float;\r
|
|
2894
|
+
\r
|
|
2895
|
+
attribute vec4 aVertexPosition;\r
|
|
2896
|
+
\r
|
|
2897
|
+
uniform mat4 uModelMatrix;\r
|
|
2898
|
+
uniform mat4 uViewMatrix;\r
|
|
2899
|
+
uniform mat4 uProjectionMatrix;\r
|
|
2900
|
+
\r
|
|
2901
|
+
void main() {\r
|
|
2902
|
+
gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * aVertexPosition;\r
|
|
2903
|
+
}\r
|
|
2904
|
+
`, Fe = `precision highp float;\r
|
|
2905
|
+
\r
|
|
2906
|
+
void main() {\r
|
|
2907
|
+
gl_FragColor = vec4(gl_FragCoord.z, gl_FragCoord.z, gl_FragCoord.z, 1.0);\r
|
|
2908
|
+
}\r
|
|
2909
|
+
`, De = `precision highp float;\r
|
|
2910
|
+
\r
|
|
2911
|
+
varying vec2 vTexCoord;\r
|
|
2912
|
+
\r
|
|
2913
|
+
uniform sampler2D uDepthTexture;\r
|
|
2914
|
+
uniform mat4 uInverseViewProjection;\r
|
|
2915
|
+
uniform vec3 uCameraPos;\r
|
|
2916
|
+
uniform vec3 uLightDir;\r
|
|
2917
|
+
uniform float uTime;\r
|
|
2918
|
+
\r
|
|
2919
|
+
uniform vec3 uTopColor;\r
|
|
2920
|
+
uniform vec3 uBottomColor;\r
|
|
2921
|
+
uniform vec3 uSunColor;\r
|
|
2922
|
+
\r
|
|
2923
|
+
// --- STYLIZED UNIFORMS ---\r
|
|
2924
|
+
uniform float uCloudScale;\r
|
|
2925
|
+
uniform float uCloudThreshold; \r
|
|
2926
|
+
uniform float uCloudDensity; // Global Opacity (0.0 to 1.0)\r
|
|
2927
|
+
uniform float uCloudCoverage; // Higher = more clusters appear\r
|
|
2928
|
+
uniform float uCloudSpeed;\r
|
|
2929
|
+
uniform vec3 uCloudMainColor;\r
|
|
2930
|
+
uniform vec3 uCloudShadeColor; \r
|
|
2931
|
+
\r
|
|
2932
|
+
vec2 hash22(vec2 p) {\r
|
|
2933
|
+
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));\r
|
|
2934
|
+
return fract(sin(p) * 43758.5453123);\r
|
|
2935
|
+
}\r
|
|
2936
|
+
\r
|
|
2937
|
+
float worley(vec2 p) {\r
|
|
2938
|
+
vec2 n = floor(p);\r
|
|
2939
|
+
vec2 f = fract(p);\r
|
|
2940
|
+
float minDist = 1.0;\r
|
|
2941
|
+
for (int y = -1; y <= 1; y++) {\r
|
|
2942
|
+
for (int x = -1; x <= 1; x++) {\r
|
|
2943
|
+
vec2 g = vec2(float(x), float(y));\r
|
|
2944
|
+
vec2 o = hash22(n + g);\r
|
|
2945
|
+
o = 0.5 + 0.5 * sin(uTime * uCloudSpeed + 6.2831 * o);\r
|
|
2946
|
+
vec2 r = g + o - f;\r
|
|
2947
|
+
float d = dot(r, r);\r
|
|
2948
|
+
minDist = min(minDist, d);\r
|
|
2949
|
+
}\r
|
|
2950
|
+
}\r
|
|
2951
|
+
return 1.0 - sqrt(minDist);\r
|
|
2952
|
+
}\r
|
|
2953
|
+
\r
|
|
2954
|
+
void main() {\r
|
|
2955
|
+
float depth = texture2D(uDepthTexture, vTexCoord).r;\r
|
|
2956
|
+
if (depth < 0.99) discard;\r
|
|
2957
|
+
\r
|
|
2958
|
+
vec4 clipPos = vec4(vTexCoord * 2.0 - 1.0, 1.0, 1.0);\r
|
|
2959
|
+
vec4 worldPosH = uInverseViewProjection * clipPos;\r
|
|
2960
|
+
vec3 worldPos = worldPosH.xyz / worldPosH.w;\r
|
|
2961
|
+
vec3 dir = normalize(worldPos - uCameraPos);\r
|
|
2962
|
+
\r
|
|
2963
|
+
// 1. Sky Gradient\r
|
|
2964
|
+
vec3 skyColor = mix(uBottomColor, uTopColor, smoothstep(-0.1, 0.8, dir.y));\r
|
|
2965
|
+
\r
|
|
2966
|
+
// 2. Spherical Cloud Logic\r
|
|
2967
|
+
vec2 cloudUV = dir.xz / (max(dir.y, 0.01) + 0.2); \r
|
|
2968
|
+
vec2 wind = vec2(uTime * uCloudSpeed);\r
|
|
2969
|
+
\r
|
|
2970
|
+
float n = worley((cloudUV + wind) * uCloudScale);\r
|
|
2971
|
+
\r
|
|
2972
|
+
// --- DENSITY CONTROL ---\r
|
|
2973
|
+
// Subtracting coverage from the noise value determines "how many" spheres survive\r
|
|
2974
|
+
float baseMask = n - (1.0 - uCloudCoverage);\r
|
|
2975
|
+
float cloudMask = smoothstep(uCloudThreshold, uCloudThreshold + 0.02, baseMask);\r
|
|
2976
|
+
\r
|
|
2977
|
+
// Fade out at horizon and apply global density/opacity\r
|
|
2978
|
+
cloudMask *= smoothstep(0.0, 0.15, dir.y);\r
|
|
2979
|
+
float finalOpacity = cloudMask * uCloudDensity;\r
|
|
2980
|
+
\r
|
|
2981
|
+
// 3. Cel-Shaded Volume\r
|
|
2982
|
+
float shadowMask = smoothstep(uCloudThreshold + 0.1, uCloudThreshold + 0.12, baseMask);\r
|
|
2983
|
+
\r
|
|
2984
|
+
// 4. Directional Rim Light\r
|
|
2985
|
+
float lightN = worley((cloudUV + wind + normalize(uLightDir.xz) * 0.1) * uCloudScale) - (1.0 - uCloudCoverage);\r
|
|
2986
|
+
float rimLight = smoothstep(uCloudThreshold, uCloudThreshold + 0.05, lightN);\r
|
|
2987
|
+
\r
|
|
2988
|
+
vec3 cloudCol = mix(uCloudShadeColor, uCloudMainColor, shadowMask);\r
|
|
2989
|
+
\r
|
|
2990
|
+
float sunDot = max(dot(dir, normalize(uLightDir)), 0.0);\r
|
|
2991
|
+
cloudCol += uSunColor * pow(sunDot, 15.0) * rimLight * 0.5;\r
|
|
2992
|
+
\r
|
|
2993
|
+
\r
|
|
2994
|
+
// 5. Final Composition using the Opacity factor\r
|
|
2995
|
+
vec3 color = mix(skyColor, cloudCol, finalOpacity);\r
|
|
2996
|
+
\r
|
|
2997
|
+
// Stylized Sun\r
|
|
2998
|
+
float sunDisk = smoothstep(0.998, 0.999, sunDot); \r
|
|
2999
|
+
color += uSunColor * sunDisk * 1.5;\r
|
|
3000
|
+
\r
|
|
3001
|
+
gl_FragColor = vec4(color, 1.0);\r
|
|
3002
|
+
}`, Ae = `precision highp float;\r
|
|
3003
|
+
\r
|
|
3004
|
+
varying vec2 vTexCoord;\r
|
|
3005
|
+
\r
|
|
3006
|
+
uniform sampler2D uSceneTexture;\r
|
|
3007
|
+
uniform sampler2D uNormalTexture;\r
|
|
3008
|
+
uniform sampler2D uDepthTexture;\r
|
|
3009
|
+
\r
|
|
3010
|
+
uniform float uPixelSize;\r
|
|
3011
|
+
uniform float uColorLevels;\r
|
|
3012
|
+
uniform vec2 uResolution;\r
|
|
3013
|
+
\r
|
|
3014
|
+
// Fine-tuned thresholds\r
|
|
3015
|
+
uniform float uDepthThreshold;\r
|
|
3016
|
+
uniform float uNormalThreshold;\r
|
|
3017
|
+
\r
|
|
3018
|
+
// Color modifiers for edges\r
|
|
3019
|
+
uniform float uSilhouetteDarkening; // Very dark for outer edges\r
|
|
3020
|
+
uniform float uCreaseDarkening; // Subtler darkening for inner corners\r
|
|
3021
|
+
\r
|
|
3022
|
+
void main() {\r
|
|
3023
|
+
// 1. PIXELATION\r
|
|
3024
|
+
vec2 size = uResolution / uPixelSize;\r
|
|
3025
|
+
vec2 uv = floor(vTexCoord * size) / size;\r
|
|
3026
|
+
vec2 texelSize = 1.0 / size;\r
|
|
3027
|
+
\r
|
|
3028
|
+
// 2. SAMPLING\r
|
|
3029
|
+
float depthCenter = texture2D(uDepthTexture, uv).r;\r
|
|
3030
|
+
vec3 normalCenter = texture2D(uNormalTexture, uv).rgb * 2.0 - 1.0;\r
|
|
3031
|
+
vec4 sceneColor = texture2D(uSceneTexture, uv);\r
|
|
3032
|
+
\r
|
|
3033
|
+
// Quantize scene color early so edge colors are based on the "flat" art style\r
|
|
3034
|
+
vec3 quantizedColor = floor(sceneColor.rgb * uColorLevels) / uColorLevels;\r
|
|
3035
|
+
\r
|
|
3036
|
+
float depthEdge = 0.0;\r
|
|
3037
|
+
float normalEdge = 0.0;\r
|
|
3038
|
+
\r
|
|
3039
|
+
// 3. EDGE DETECTION LOOP\r
|
|
3040
|
+
vec2 offsets[4];\r
|
|
3041
|
+
offsets[0] = vec2(1.0, 0.0);\r
|
|
3042
|
+
offsets[1] = vec2(-1.0, 0.0);\r
|
|
3043
|
+
offsets[2] = vec2(0.0, 1.0);\r
|
|
3044
|
+
offsets[3] = vec2(0.0, -1.0);\r
|
|
3045
|
+
\r
|
|
3046
|
+
for(int i = 0; i < 4; i++) {\r
|
|
3047
|
+
vec2 neighborUV = uv + offsets[i] * texelSize;\r
|
|
3048
|
+
\r
|
|
3049
|
+
// Depth logic\r
|
|
3050
|
+
float depthNeighbor = texture2D(uDepthTexture, neighborUV).r;\r
|
|
3051
|
+
depthEdge = max(depthEdge, abs(depthCenter - depthNeighbor));\r
|
|
3052
|
+
\r
|
|
3053
|
+
// Normal logic\r
|
|
3054
|
+
vec3 normalNeighbor = texture2D(uNormalTexture, neighborUV).rgb * 2.0 - 1.0;\r
|
|
3055
|
+
normalEdge = max(normalEdge, (1.0 - dot(normalCenter, normalNeighbor)));\r
|
|
3056
|
+
}\r
|
|
3057
|
+
\r
|
|
3058
|
+
// 4. ADAPTIVE COLOR LOGIC\r
|
|
3059
|
+
vec3 finalColor = quantizedColor;\r
|
|
3060
|
+
\r
|
|
3061
|
+
// Is it an internal crease? (Normal-based)\r
|
|
3062
|
+
if (normalEdge > uNormalThreshold) {\r
|
|
3063
|
+
// Darken the surface color rather than making it black\r
|
|
3064
|
+
finalColor = quantizedColor * uCreaseDarkening;\r
|
|
3065
|
+
}\r
|
|
3066
|
+
\r
|
|
3067
|
+
// Is it a silhouette? (Depth-based)\r
|
|
3068
|
+
// We do this second so silhouette (outer) edges override crease (inner) edges\r
|
|
3069
|
+
if (depthEdge > uDepthThreshold) {\r
|
|
3070
|
+
// Use a much heavier darkening for the outer silhouette\r
|
|
3071
|
+
finalColor = quantizedColor * uSilhouetteDarkening;\r
|
|
3072
|
+
}\r
|
|
3073
|
+
\r
|
|
3074
|
+
gl_FragColor = vec4(finalColor, 1.0);\r
|
|
3075
|
+
}`, Se = `attribute vec4 aVertexPosition;\r
|
|
3076
|
+
attribute vec2 aTexCoord;\r
|
|
3077
|
+
\r
|
|
3078
|
+
uniform mat4 uViewMatrix;\r
|
|
3079
|
+
uniform mat4 uProjectionMatrix;\r
|
|
3080
|
+
uniform mat4 uModelMatrix;\r
|
|
3081
|
+
\r
|
|
3082
|
+
uniform lowp float uTime; \r
|
|
3083
|
+
uniform lowp float uSpeed; \r
|
|
3084
|
+
uniform vec2 uWind; \r
|
|
3085
|
+
uniform float uScale;\r
|
|
3086
|
+
uniform float udisplacement;\r
|
|
3087
|
+
\r
|
|
3088
|
+
\r
|
|
3089
|
+
varying lowp vec2 vTexCoord;\r
|
|
3090
|
+
varying lowp float vNoise;\r
|
|
3091
|
+
varying vec3 vWorldPos;\r
|
|
3092
|
+
\r
|
|
3093
|
+
// Noise functions must be in both or shared via an include\r
|
|
3094
|
+
vec2 hash(vec2 p) {\r
|
|
3095
|
+
p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3)));\r
|
|
3096
|
+
return -1.0 + 2.0 * fract(sin(p) * 43758.5453123);\r
|
|
3097
|
+
}\r
|
|
3098
|
+
\r
|
|
3099
|
+
\r
|
|
3100
|
+
float gradientNoise(vec2 p) {\r
|
|
3101
|
+
vec2 i = floor(p);\r
|
|
3102
|
+
vec2 f = fract(p);\r
|
|
3103
|
+
vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);\r
|
|
3104
|
+
float a = dot(hash(i + vec2(0.0, 0.0)), f - vec2(0.0, 0.0));\r
|
|
3105
|
+
float b = dot(hash(i + vec2(1.0, 0.0)), f - vec2(1.0, 0.0));\r
|
|
3106
|
+
float c = dot(hash(i + vec2(0.0, 1.0)), f - vec2(0.0, 1.0));\r
|
|
3107
|
+
float d = dot(hash(i + vec2(1.0, 1.0)), f - vec2(1.0, 1.0));\r
|
|
3108
|
+
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);\r
|
|
3109
|
+
}\r
|
|
3110
|
+
\r
|
|
3111
|
+
void main() {\r
|
|
3112
|
+
vec4 worldPos = uModelMatrix * aVertexPosition;\r
|
|
3113
|
+
\r
|
|
3114
|
+
float time = uTime * uSpeed;\r
|
|
3115
|
+
vec2 movement = uWind * time;\r
|
|
3116
|
+
\r
|
|
3117
|
+
// Use World Position XZ for noise so displacement is seamless across objects\r
|
|
3118
|
+
vec2 noiseCoord = worldPos.xz * uScale;\r
|
|
3119
|
+
\r
|
|
3120
|
+
float n1 = gradientNoise((noiseCoord * 0.25) + (movement * 0.3));\r
|
|
3121
|
+
float n2 = gradientNoise((noiseCoord * 1.5) + movement);\r
|
|
3122
|
+
vec2 jitterMovement = vec2(movement.y, -movement.x) * 1.5; \r
|
|
3123
|
+
float n3 = gradientNoise((noiseCoord * 4.0) + jitterMovement);\r
|
|
3124
|
+
\r
|
|
3125
|
+
float n = (n1 * 0.2) + (n2 * 0.5) + (n3 * 0.3);\r
|
|
3126
|
+
vNoise = smoothstep(-0.4, 0.4, n);\r
|
|
3127
|
+
\r
|
|
3128
|
+
// Displace the Y position based on noise\r
|
|
3129
|
+
worldPos.y += vNoise * udisplacement; // Adjust '2.0' for displacement strength\r
|
|
3130
|
+
\r
|
|
3131
|
+
gl_Position = uProjectionMatrix * uViewMatrix * worldPos;\r
|
|
3132
|
+
\r
|
|
3133
|
+
vTexCoord = aTexCoord;\r
|
|
3134
|
+
vWorldPos = worldPos.xyz;\r
|
|
3135
|
+
}`, Me = `precision lowp float;\r
|
|
3136
|
+
\r
|
|
3137
|
+
varying lowp vec2 vTexCoord;\r
|
|
3138
|
+
varying lowp float vNoise;\r
|
|
3139
|
+
varying vec3 vWorldPos;\r
|
|
3140
|
+
\r
|
|
3141
|
+
uniform vec3 uColor1; \r
|
|
3142
|
+
uniform vec3 uColor2; \r
|
|
3143
|
+
uniform vec3 uColor3; \r
|
|
3144
|
+
\r
|
|
3145
|
+
void main() {\r
|
|
3146
|
+
float n = clamp(vNoise, 0.0, 1.0);\r
|
|
3147
|
+
\r
|
|
3148
|
+
// 1. Create a smooth transition for the first blend (Deep to Shallow)\r
|
|
3149
|
+
// This blend happens between 0.0 and 0.6\r
|
|
3150
|
+
float blend1 = smoothstep(0.0, 0.6, n);\r
|
|
3151
|
+
vec3 waterBase = mix(uColor1, uColor2, blend1);\r
|
|
3152
|
+
\r
|
|
3153
|
+
// 2. Create a smooth transition for the second blend (Shallow to Foam)\r
|
|
3154
|
+
// This blend starts late (at 0.7) and ends at the peak (1.0)\r
|
|
3155
|
+
float blend2 = smoothstep(0.7, 1.0, n);\r
|
|
3156
|
+
vec3 finalColor = mix(waterBase, uColor3, blend2);\r
|
|
3157
|
+
\r
|
|
3158
|
+
gl_FragColor = vec4(finalColor, 1.0);\r
|
|
3159
|
+
}`, Ge = {
|
|
3160
|
+
quadVert: fe,
|
|
3161
|
+
quadFrag: me,
|
|
3162
|
+
quadScreenVert: pe,
|
|
3163
|
+
quadScreenFrag: ge,
|
|
3164
|
+
depthVert: ve,
|
|
3165
|
+
depthFrag: xe,
|
|
3166
|
+
normalVert: we,
|
|
3167
|
+
normalFrag: be,
|
|
3168
|
+
outlineFrag: ye,
|
|
3169
|
+
noiseFrag: Ce,
|
|
3170
|
+
lightingVert: Ee,
|
|
3171
|
+
lightingFrag: Te,
|
|
3172
|
+
shadowVert: _e,
|
|
3173
|
+
shadowFrag: Fe,
|
|
3174
|
+
skyboxFrag: De,
|
|
3175
|
+
pixelArtFrag: Ae,
|
|
3176
|
+
waterVert: Se,
|
|
3177
|
+
waterFrag: Me
|
|
3178
|
+
};
|
|
3179
|
+
export {
|
|
3180
|
+
G as Camera,
|
|
3181
|
+
Re as CameraController,
|
|
3182
|
+
Ye as Editor,
|
|
3183
|
+
j as FullScreenQuad,
|
|
3184
|
+
X as GameObject,
|
|
3185
|
+
le as HierarchyWindow,
|
|
3186
|
+
he as InspectorWindow,
|
|
3187
|
+
je as LightingPass,
|
|
3188
|
+
$e as Material,
|
|
3189
|
+
de as MaterialWindow,
|
|
3190
|
+
N as Mesh,
|
|
3191
|
+
Le as ObjLoader,
|
|
3192
|
+
Ie as ObjectRenderPass,
|
|
3193
|
+
Xe as OutlinePass,
|
|
3194
|
+
We as PixelArtPass,
|
|
3195
|
+
Ue as ProfilerInstrumenter,
|
|
3196
|
+
ue as ProfilerWindow,
|
|
3197
|
+
z as RenderPass,
|
|
3198
|
+
ce as RenderPassWindow,
|
|
3199
|
+
ze as RenderQueue,
|
|
3200
|
+
Ve as RenderTarget,
|
|
3201
|
+
ke as Renderer,
|
|
3202
|
+
k as ScreenRenderPass,
|
|
3203
|
+
Oe as Shader,
|
|
3204
|
+
Ge as Shaders,
|
|
3205
|
+
He as SkyboxPass,
|
|
3206
|
+
Be as Texture,
|
|
3207
|
+
Pe as Time,
|
|
3208
|
+
H as Transform,
|
|
3209
|
+
V as Vector3,
|
|
3210
|
+
Ne as ViewportPass,
|
|
3211
|
+
q as WindowManager
|
|
3212
|
+
};
|