@woosh/meep-engine 2.39.18 → 2.39.19
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/core/color/Color.js +63 -4
- package/core/color/ColorUtils.js +29 -13
- package/core/function/Functions.js +9 -0
- package/core/geom/Vector3.js +7 -0
- package/editor/tools/paint/prototypeTerrainEditor.js +72 -3
- package/editor/tools/v2/BlenderCameraOrientationGizmo.d.ts +17 -0
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +420 -0
- package/editor/tools/v2/TransformControls.d.ts +6 -1
- package/editor/view/EditorView.js +2 -2
- package/engine/graphics/ecs/camera/Camera.js +11 -1
- package/engine/graphics/ecs/camera/CameraSystem.js +4 -22
- package/engine/graphics/ecs/camera/InvertQuaternionOrientation.js +26 -0
- package/engine/input/devices/PointerDevice.js +1 -1
- package/package.json +1 -1
- package/view/SVG.js +2 -1
- package/view/View.d.ts +8 -0
- package/view/elements/EmptyView.js +18 -12
- package/view/elements/progress/SmoothProgressBar.js +9 -0
- package/view/elements/windrose/WindRoseDiagram.js +358 -2
- package/view/elements/windrose/prototype.js +37 -0
- package/view/tooltip/DomTooltipManager.js +1 -1
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import { CanvasView } from "../../../view/elements/CanvasView.js";
|
|
2
|
+
import Vector3 from "../../../core/geom/Vector3.js";
|
|
3
|
+
import { compose_matrix4_array } from "../../../core/geom/3d/compose_matrix4_array.js";
|
|
4
|
+
import { mat4 } from "gl-matrix";
|
|
5
|
+
import { readPositionFromMouseEvent } from "../../../engine/input/devices/PointerDevice.js";
|
|
6
|
+
import Vector2, { v2_distance } from "../../../core/geom/Vector2.js";
|
|
7
|
+
import { Color } from "../../../core/color/Color.js";
|
|
8
|
+
import { inverseLerp } from "../../../core/math/inverseLerp.js";
|
|
9
|
+
import { clamp01 } from "../../../core/math/clamp01.js";
|
|
10
|
+
import { lerp } from "../../../core/math/lerp.js";
|
|
11
|
+
import Signal from "../../../core/events/signal/Signal.js";
|
|
12
|
+
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
13
|
+
import { invertQuaternionOrientation } from "../../../engine/graphics/ecs/camera/InvertQuaternionOrientation.js";
|
|
14
|
+
|
|
15
|
+
const scratch_color = new Color();
|
|
16
|
+
const scratch_quat = new Quaternion();
|
|
17
|
+
const scratch_m4 = new Float32Array(16);
|
|
18
|
+
|
|
19
|
+
class DirectionStyle {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.near = {
|
|
22
|
+
fill: new Color(1, 0, 0),
|
|
23
|
+
stroke_width: 0,
|
|
24
|
+
stroke_color: new Color(0, 0, 0)
|
|
25
|
+
};
|
|
26
|
+
this.far = {
|
|
27
|
+
fill: new Color(1, 0, 0),
|
|
28
|
+
stroke_width: 0,
|
|
29
|
+
stroke_color: new Color(0, 0, 0)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
fromJSON({
|
|
34
|
+
near_fill = '#FF0000',
|
|
35
|
+
near_stroke_width = 0,
|
|
36
|
+
near_stroke_color = '#000000',
|
|
37
|
+
far_fill = '#FF0000',
|
|
38
|
+
far_stroke_width = 0,
|
|
39
|
+
far_stroke_color = '#000000'
|
|
40
|
+
}) {
|
|
41
|
+
|
|
42
|
+
this.near.fill.parse(near_fill);
|
|
43
|
+
this.near.stroke_width = near_stroke_width;
|
|
44
|
+
this.near.stroke_color.parse(near_stroke_color);
|
|
45
|
+
|
|
46
|
+
this.far.fill.parse(far_fill);
|
|
47
|
+
this.far.stroke_width = far_stroke_width;
|
|
48
|
+
this.far.stroke_color.parse(far_stroke_color);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static fromJSON(j) {
|
|
52
|
+
const r = new DirectionStyle();
|
|
53
|
+
|
|
54
|
+
r.fromJSON(j);
|
|
55
|
+
|
|
56
|
+
return r;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Modelled on https://github.com/jrj2211/three-orientation-gizmo/blob/master/src/OrientationGizmo.js
|
|
63
|
+
*/
|
|
64
|
+
export class BlenderCameraOrientationGizmo extends CanvasView {
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param {Quaternion} quaternion
|
|
68
|
+
*/
|
|
69
|
+
constructor(quaternion = null) {
|
|
70
|
+
super();
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
*
|
|
74
|
+
* @type {Quaternion}
|
|
75
|
+
*/
|
|
76
|
+
this.orientation = quaternion;
|
|
77
|
+
|
|
78
|
+
this.options = {
|
|
79
|
+
size: 100,
|
|
80
|
+
padding: 8,
|
|
81
|
+
bubbleSizePrimary: 10,
|
|
82
|
+
bubbleSizeSecondary: 8,
|
|
83
|
+
showSecondary: true,
|
|
84
|
+
lineWidth: 2,
|
|
85
|
+
fontSize: "11px",
|
|
86
|
+
fontFamily: "arial",
|
|
87
|
+
fontWeight: "bold",
|
|
88
|
+
fontColor: "rgba(0,0,0,0.8)",
|
|
89
|
+
fontYAdjust: 1,
|
|
90
|
+
selectionFontColor: "#FFFFFF",
|
|
91
|
+
invertOrientation: true,
|
|
92
|
+
axisStyles: {
|
|
93
|
+
px: DirectionStyle.fromJSON({
|
|
94
|
+
near_fill: "#FF3653",
|
|
95
|
+
far_fill: "#9D3B4A"
|
|
96
|
+
}),
|
|
97
|
+
py: DirectionStyle.fromJSON({
|
|
98
|
+
near_fill: "#8ADB00",
|
|
99
|
+
far_fill: "#648C23"
|
|
100
|
+
}),
|
|
101
|
+
pz: DirectionStyle.fromJSON({
|
|
102
|
+
near_fill: "#2C8FFF",
|
|
103
|
+
far_fill: "#36679D"
|
|
104
|
+
}),
|
|
105
|
+
nx: DirectionStyle.fromJSON({
|
|
106
|
+
near_stroke_color: "#FF3653",
|
|
107
|
+
near_stroke_width: 1,
|
|
108
|
+
near_fill: "#6E3D44",
|
|
109
|
+
far_stroke_color: "#9D3B4A",
|
|
110
|
+
far_stroke_width: 1,
|
|
111
|
+
far_fill: 'rgba(0,0,0,0)'
|
|
112
|
+
}),
|
|
113
|
+
ny: DirectionStyle.fromJSON({
|
|
114
|
+
near_stroke_color: "#8ADB00",
|
|
115
|
+
near_stroke_width: 1,
|
|
116
|
+
near_fill: "#526532",
|
|
117
|
+
far_stroke_color: "#648C23",
|
|
118
|
+
far_stroke_width: 1,
|
|
119
|
+
far_fill: 'rgba(0,0,0,0)'
|
|
120
|
+
}),
|
|
121
|
+
nz: DirectionStyle.fromJSON({
|
|
122
|
+
near_stroke_color: "#2C8FFF",
|
|
123
|
+
near_stroke_width: 1,
|
|
124
|
+
near_fill: "#3B536E",
|
|
125
|
+
far_stroke_color: "#36679D",
|
|
126
|
+
far_stroke_width: 1,
|
|
127
|
+
far_fill: 'rgba(0,0,0,0)'
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Generate list of axes
|
|
133
|
+
this.bubbles = [
|
|
134
|
+
{
|
|
135
|
+
axis: "x",
|
|
136
|
+
direction: new Vector3(1, 0, 0),
|
|
137
|
+
size: this.options.bubbleSizePrimary,
|
|
138
|
+
style: this.options.axisStyles.px,
|
|
139
|
+
line: this.options.lineWidth,
|
|
140
|
+
label: "X",
|
|
141
|
+
primary: true
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
axis: "y",
|
|
145
|
+
direction: new Vector3(0, 1, 0),
|
|
146
|
+
size: this.options.bubbleSizePrimary,
|
|
147
|
+
style: this.options.axisStyles.py,
|
|
148
|
+
line: this.options.lineWidth,
|
|
149
|
+
label: "Y",
|
|
150
|
+
primary: true
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
axis: "z",
|
|
154
|
+
direction: new Vector3(0, 0, 1),
|
|
155
|
+
size: this.options.bubbleSizePrimary,
|
|
156
|
+
style: this.options.axisStyles.pz,
|
|
157
|
+
line: this.options.lineWidth,
|
|
158
|
+
label: "Z",
|
|
159
|
+
primary: true
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
axis: "-x",
|
|
163
|
+
direction: new Vector3(-1, 0, 0),
|
|
164
|
+
size: this.options.bubbleSizeSecondary,
|
|
165
|
+
style: this.options.axisStyles.nx,
|
|
166
|
+
label: "-X",
|
|
167
|
+
labelHideUnselected: true,
|
|
168
|
+
primary: false
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
axis: "-y",
|
|
172
|
+
direction: new Vector3(0, -1, 0),
|
|
173
|
+
size: this.options.bubbleSizeSecondary,
|
|
174
|
+
style: this.options.axisStyles.ny,
|
|
175
|
+
label: "-Y",
|
|
176
|
+
labelHideUnselected: true,
|
|
177
|
+
primary: false
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
axis: "-z",
|
|
181
|
+
direction: new Vector3(0, 0, -1),
|
|
182
|
+
size: this.options.bubbleSizeSecondary,
|
|
183
|
+
style: this.options.axisStyles.nz,
|
|
184
|
+
label: "-Y",
|
|
185
|
+
labelHideUnselected: true,
|
|
186
|
+
primary: false
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
*
|
|
192
|
+
* @type {Vector3|null}
|
|
193
|
+
*/
|
|
194
|
+
this.mouse = null;
|
|
195
|
+
|
|
196
|
+
this.center = new Vector3(this.options.size / 2, this.options.size / 2, 0);
|
|
197
|
+
this.selectedAxis = null;
|
|
198
|
+
|
|
199
|
+
this.size.setScalar(this.options.size);
|
|
200
|
+
|
|
201
|
+
this.onMouseMove = this.onMouseMove.bind(this);
|
|
202
|
+
this.onMouseOut = this.onMouseOut.bind(this);
|
|
203
|
+
this.onMouseClick = this.onMouseClick.bind(this);
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
*
|
|
207
|
+
* Invoked when axis is clicked
|
|
208
|
+
* @type {Signal<string,Vector3>}
|
|
209
|
+
*/
|
|
210
|
+
this.on.axisSelected = new Signal();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
link() {
|
|
214
|
+
super.link();
|
|
215
|
+
|
|
216
|
+
const el = this.el;
|
|
217
|
+
el.addEventListener('mousemove', this.onMouseMove, false);
|
|
218
|
+
el.addEventListener('mouseout', this.onMouseOut, false);
|
|
219
|
+
el.addEventListener('click', this.onMouseClick, false);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
unlink() {
|
|
223
|
+
const el = this.el;
|
|
224
|
+
el.removeEventListener('mousemove', this.onMouseMove, false);
|
|
225
|
+
el.removeEventListener('mouseout', this.onMouseOut, false);
|
|
226
|
+
el.removeEventListener('click', this.onMouseClick, false);
|
|
227
|
+
|
|
228
|
+
super.unlink();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
*
|
|
233
|
+
* @param {MouseEvent} evt
|
|
234
|
+
*/
|
|
235
|
+
onMouseMove(evt) {
|
|
236
|
+
const v2 = new Vector2();
|
|
237
|
+
readPositionFromMouseEvent(v2, evt);
|
|
238
|
+
|
|
239
|
+
this.mouse = new Vector3(v2.x, v2.y, 0);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
*
|
|
244
|
+
* @param {MouseEvent} evt
|
|
245
|
+
*/
|
|
246
|
+
onMouseOut(evt) {
|
|
247
|
+
this.mouse = null;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
*
|
|
252
|
+
* @param {MouseEvent} evt
|
|
253
|
+
*/
|
|
254
|
+
onMouseClick(evt) {
|
|
255
|
+
if (this.selectedAxis !== null) {
|
|
256
|
+
this.on.axisSelected.send2(
|
|
257
|
+
this.selectedAxis.axis,
|
|
258
|
+
this.selectedAxis.direction.clone()
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
drawCircle(p, radius = 10, fill_color = "#FF0000", stroke_width = 0, stroke_color = "#FFFFFF") {
|
|
264
|
+
const ctx = this.context2d;
|
|
265
|
+
|
|
266
|
+
ctx.beginPath();
|
|
267
|
+
ctx.arc(p.x, p.y, radius, 0, 2 * Math.PI, false);
|
|
268
|
+
ctx.fillStyle = fill_color;
|
|
269
|
+
ctx.fill();
|
|
270
|
+
|
|
271
|
+
if (stroke_width > 0) {
|
|
272
|
+
ctx.lineWidth = stroke_width;
|
|
273
|
+
ctx.strokeStyle = stroke_color;
|
|
274
|
+
ctx.stroke();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
ctx.closePath();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
drawLine(p1, p2, width = 1, color = "#FF0000") {
|
|
281
|
+
const ctx = this.context2d;
|
|
282
|
+
|
|
283
|
+
ctx.beginPath();
|
|
284
|
+
ctx.moveTo(p1.x, p1.y);
|
|
285
|
+
ctx.lineTo(p2.x, p2.y);
|
|
286
|
+
ctx.lineWidth = width;
|
|
287
|
+
ctx.strokeStyle = color;
|
|
288
|
+
ctx.stroke();
|
|
289
|
+
ctx.closePath();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
update() {
|
|
293
|
+
this.clear();
|
|
294
|
+
|
|
295
|
+
// Calculate the rotation matrix from the camera
|
|
296
|
+
const rotation_matrix = scratch_m4;
|
|
297
|
+
let rotation = this.orientation;
|
|
298
|
+
|
|
299
|
+
if (rotation === null) {
|
|
300
|
+
// not connected
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (this.options.invertOrientation) {
|
|
305
|
+
const q = scratch_quat;
|
|
306
|
+
|
|
307
|
+
invertQuaternionOrientation(q, rotation);
|
|
308
|
+
|
|
309
|
+
rotation = q;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
compose_matrix4_array(rotation_matrix, Vector3.zero, rotation, Vector3.one);
|
|
313
|
+
mat4.invert(rotation_matrix, rotation_matrix);
|
|
314
|
+
|
|
315
|
+
for (let bubble of this.bubbles) {
|
|
316
|
+
const direction = bubble.direction.clone();
|
|
317
|
+
direction.applyMatrix4(rotation_matrix);
|
|
318
|
+
|
|
319
|
+
bubble.position = this.getBubblePosition(direction);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Generate a list of layers to draw
|
|
323
|
+
const layers = [];
|
|
324
|
+
for (let axis in this.bubbles) {
|
|
325
|
+
// Check if the name starts with a negative and dont add it to the layer list if secondary axis is turned off
|
|
326
|
+
if (this.options.showSecondary === true || axis[0] !== "-") {
|
|
327
|
+
layers.push(this.bubbles[axis]);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Sort the layers where the +Z position is last so its drawn on top of anything below it
|
|
332
|
+
layers.sort((a, b) => (a.position.z > b.position.z) ? 1 : -1);
|
|
333
|
+
|
|
334
|
+
// If the mouse is over the gizmo, find the closest axis and highlight it
|
|
335
|
+
this.selectedAxis = null;
|
|
336
|
+
|
|
337
|
+
if (this.mouse) {
|
|
338
|
+
let closestDist = Infinity;
|
|
339
|
+
let closestZ = -Infinity;
|
|
340
|
+
|
|
341
|
+
// Loop through each layer
|
|
342
|
+
for (let bubble of layers) {
|
|
343
|
+
const distance = v2_distance(this.mouse.x, this.mouse.y, bubble.position.x, bubble.position.y);
|
|
344
|
+
|
|
345
|
+
// Only select the axis if its closer to the mouse than the previous or if its within its bubble circle
|
|
346
|
+
if (
|
|
347
|
+
distance < closestDist
|
|
348
|
+
&& closestZ < bubble.position.z
|
|
349
|
+
&& distance <= bubble.size
|
|
350
|
+
) {
|
|
351
|
+
|
|
352
|
+
closestDist = distance;
|
|
353
|
+
closestZ = bubble.position.z;
|
|
354
|
+
this.selectedAxis = bubble;
|
|
355
|
+
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Draw the layers
|
|
361
|
+
this.drawLayers(layers);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
*
|
|
366
|
+
* @param {{style:DirectionStyle, position:Vector3, size:number,line:boolean, label?:string,labelHideUnselected?:boolean}[]} layers
|
|
367
|
+
*/
|
|
368
|
+
drawLayers(layers) {
|
|
369
|
+
// For each layer, draw the bubble
|
|
370
|
+
for (let bubble of layers) {
|
|
371
|
+
|
|
372
|
+
// Find the color
|
|
373
|
+
const is_selected = this.selectedAxis === bubble;
|
|
374
|
+
|
|
375
|
+
const closeness = clamp01(inverseLerp(-1, 0.8, bubble.position.z));
|
|
376
|
+
|
|
377
|
+
const style = bubble.style;
|
|
378
|
+
|
|
379
|
+
scratch_color.lerpColors(style.far.fill, style.near.fill, closeness);
|
|
380
|
+
const fill_color = scratch_color.toCssRGBAString();
|
|
381
|
+
|
|
382
|
+
scratch_color.lerpColors(style.far.stroke_color, style.near.stroke_color, closeness);
|
|
383
|
+
const stroke_color = scratch_color.toCssRGBAString();
|
|
384
|
+
|
|
385
|
+
const stroke_width = lerp(style.far.stroke_width, style.near.stroke_width, closeness);
|
|
386
|
+
|
|
387
|
+
// Draw the circle for the bubbble
|
|
388
|
+
this.drawCircle(bubble.position, bubble.size, fill_color, stroke_width, stroke_color);
|
|
389
|
+
|
|
390
|
+
// Draw the line that connects it to the center if enabled
|
|
391
|
+
if (bubble.line) {
|
|
392
|
+
this.drawLine(this.center, bubble.position, bubble.line, fill_color);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Write the axis label (X,Y,Z) if provided
|
|
396
|
+
if (bubble.label && (is_selected || (bubble.labelHideUnselected !== true))) {
|
|
397
|
+
const ctx = this.context2d;
|
|
398
|
+
|
|
399
|
+
ctx.font = [this.options.fontWeight, this.options.fontSize, this.options.fontFamily].join(" ");
|
|
400
|
+
ctx.fillStyle = is_selected ? this.options.selectionFontColor : this.options.fontColor;
|
|
401
|
+
ctx.textBaseline = 'middle';
|
|
402
|
+
ctx.textAlign = 'center';
|
|
403
|
+
ctx.fillText(bubble.label, bubble.position.x, bubble.position.y + this.options.fontYAdjust);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
*
|
|
410
|
+
* @param {Vector3} position
|
|
411
|
+
* @returns {Vector3}
|
|
412
|
+
*/
|
|
413
|
+
getBubblePosition(position) {
|
|
414
|
+
return new Vector3(
|
|
415
|
+
(position.x * (this.center.x - (this.options.bubbleSizePrimary / 2) - this.options.padding)) + this.center.x,
|
|
416
|
+
this.center.y - (position.y * (this.center.y - (this.options.bubbleSizePrimary / 2) - this.options.padding)),
|
|
417
|
+
position.z
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
@@ -3,7 +3,7 @@ import {EntityComponentDataset} from "../../../engine/ecs/EntityComponentDataset
|
|
|
3
3
|
import {EntityNode} from "../../../engine/ecs/parent/EntityNode";
|
|
4
4
|
|
|
5
5
|
export class TransformControls extends EntityNode {
|
|
6
|
-
constructor(camera: PerspectiveCamera | OrthographicCamera, domElement: HTMLElement)
|
|
6
|
+
constructor(camera: PerspectiveCamera | OrthographicCamera, domElement: HTMLElement, autoUpdate?: boolean)
|
|
7
7
|
|
|
8
8
|
build(ecd: EntityComponentDataset): void
|
|
9
9
|
|
|
@@ -12,4 +12,9 @@ export class TransformControls extends EntityNode {
|
|
|
12
12
|
attach(entity: number): void
|
|
13
13
|
|
|
14
14
|
detach(): void
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Can be triggered manually if `autoUpdate` was not set in the constructor
|
|
18
|
+
*/
|
|
19
|
+
update(): void
|
|
15
20
|
}
|
|
@@ -428,8 +428,8 @@ class EditorView extends View {
|
|
|
428
428
|
this.toolBar.size.set(this.gameView.size.x, 36);
|
|
429
429
|
this.toolBar.position.set(this.gameView.position.x + 5, this.gameView.position.y + this.gameView.size.y - (this.toolBar.size.y + 5));
|
|
430
430
|
|
|
431
|
-
this.processBar.size.set(this.gameView.size.x, 36);
|
|
432
|
-
this.processBar.position.set(this.toolBar.position.x, 5);
|
|
431
|
+
// this.processBar.size.set(this.gameView.size.x, 36);
|
|
432
|
+
// this.processBar.position.set(this.toolBar.position.x, 5);
|
|
433
433
|
|
|
434
434
|
this.meshLibraryView.position.set(this.gameView.position.x + this.gameView.size.x - (this.meshLibraryView.size.x + 5), 5);
|
|
435
435
|
}
|
|
@@ -12,6 +12,7 @@ import { computePointDistanceToPlane } from "../../../../core/geom/Plane.js";
|
|
|
12
12
|
import { unprojectPoint } from "./unprojectPoint.js";
|
|
13
13
|
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
14
14
|
import { frustum_from_camera } from "./frustum_from_camera.js";
|
|
15
|
+
import { invertQuaternionOrientation } from "./InvertQuaternionOrientation.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
*
|
|
@@ -75,6 +76,15 @@ export class Camera {
|
|
|
75
76
|
this.__clip_near = 0.1;
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
/**
|
|
80
|
+
*
|
|
81
|
+
* @param {Quaternion} output
|
|
82
|
+
* @param {Quaternion} input
|
|
83
|
+
*/
|
|
84
|
+
getReciprocalRotation(output, input) {
|
|
85
|
+
invertQuaternionOrientation(output, input);
|
|
86
|
+
}
|
|
87
|
+
|
|
78
88
|
get clip_far() {
|
|
79
89
|
return this.__clip_far;
|
|
80
90
|
}
|
|
@@ -200,7 +210,7 @@ export class Camera {
|
|
|
200
210
|
source.copy(scratch_v3_1);
|
|
201
211
|
direction.copy(scratch_v3_0);
|
|
202
212
|
|
|
203
|
-
}
|
|
213
|
+
} else {
|
|
204
214
|
throw new Error('Unsupported camera type');
|
|
205
215
|
}
|
|
206
216
|
}
|
|
@@ -6,20 +6,15 @@
|
|
|
6
6
|
import { System } from '../../../ecs/System.js';
|
|
7
7
|
import { Camera } from './Camera.js';
|
|
8
8
|
import { Transform } from '../../../ecs/transform/Transform.js';
|
|
9
|
-
import { Frustum as ThreeFrustum,
|
|
9
|
+
import { Frustum as ThreeFrustum, } from 'three';
|
|
10
10
|
import { assert } from "../../../../core/assert.js";
|
|
11
11
|
import { SignalBinding } from "../../../../core/events/signal/SignalBinding.js";
|
|
12
|
-
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
13
12
|
import { set_camera_aspect_ratio } from "./set_camera_aspect_ratio.js";
|
|
14
13
|
import { build_three_camera_object } from "./build_three_camera_object.js";
|
|
15
14
|
import { update_camera_transform } from "./update_camera_transform.js";
|
|
16
15
|
import { auto_set_camera_clipping_planes } from "./auto_set_camera_clipping_planes.js";
|
|
17
16
|
import { frustum_from_camera } from "./frustum_from_camera.js";
|
|
18
|
-
|
|
19
|
-
const m4_scratch = new Matrix4();
|
|
20
|
-
|
|
21
|
-
const v3_scratch_0 = new Vector3();
|
|
22
|
-
const v3_scratch_1 = new Vector3();
|
|
17
|
+
import { invertQuaternionOrientation } from "./InvertQuaternionOrientation.js";
|
|
23
18
|
|
|
24
19
|
export class CameraSystem extends System {
|
|
25
20
|
/**
|
|
@@ -114,22 +109,9 @@ export class CameraSystem extends System {
|
|
|
114
109
|
See: https://github.com/mrdoob/three.js/blob/412b99a7f26e117ea97f40eb53d010ab81aa3279/src/core/Object3D.js#L282
|
|
115
110
|
*/
|
|
116
111
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const forward = v3_scratch_0;
|
|
121
|
-
const up = v3_scratch_1;
|
|
122
|
-
|
|
123
|
-
forward.copy(Vector3.forward);
|
|
124
|
-
up.copy(Vector3.up);
|
|
125
|
-
|
|
126
|
-
forward.applyQuaternion(rotation);
|
|
127
|
-
up.applyQuaternion(rotation);
|
|
128
|
-
|
|
129
|
-
m4_scratch.lookAt(Vector3.zero, forward, up);
|
|
112
|
+
invertQuaternionOrientation(camera.object.quaternion, rotation);
|
|
130
113
|
|
|
131
|
-
camera.object.rotation.
|
|
132
|
-
camera.object.quaternion.setFromRotationMatrix(m4_scratch);
|
|
114
|
+
camera.object.rotation.setFromQuaternion(camera.object.quaternion);
|
|
133
115
|
|
|
134
116
|
// rotation.__setThreeEuler(camera.object.rotation); // seems unnecessary, based on Object3D.lookAt implementation
|
|
135
117
|
// camera.object.quaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import Vector3 from "../../../../core/geom/Vector3.js";
|
|
2
|
+
import { Matrix4 } from "three";
|
|
3
|
+
|
|
4
|
+
const m4_scratch = new Matrix4();
|
|
5
|
+
const v3_scratch_0 = new Vector3();
|
|
6
|
+
const v3_scratch_1 = new Vector3();
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @param {Quaternion} output
|
|
11
|
+
* @param {Quaternion} input
|
|
12
|
+
*/
|
|
13
|
+
export function invertQuaternionOrientation(output, input) {
|
|
14
|
+
const forward = v3_scratch_0;
|
|
15
|
+
const up = v3_scratch_1;
|
|
16
|
+
|
|
17
|
+
forward.copy(Vector3.forward);
|
|
18
|
+
up.copy(Vector3.up);
|
|
19
|
+
|
|
20
|
+
forward.applyQuaternion(input);
|
|
21
|
+
up.applyQuaternion(input);
|
|
22
|
+
|
|
23
|
+
m4_scratch.lookAt(Vector3.zero, forward, up);
|
|
24
|
+
|
|
25
|
+
output.setFromRotationMatrix(m4_scratch);
|
|
26
|
+
}
|
|
@@ -306,7 +306,7 @@ function observeDrag(up, down, move, dragStart, dragEnd, drag) {
|
|
|
306
306
|
* @param {MouseEvent} event
|
|
307
307
|
* @param {Element} source
|
|
308
308
|
*/
|
|
309
|
-
function readPositionFromMouseEvent(result, event, source = event.target) {
|
|
309
|
+
export function readPositionFromMouseEvent(result, event, source = event.target) {
|
|
310
310
|
let x = event.clientX;
|
|
311
311
|
let y = event.clientY;
|
|
312
312
|
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.39.
|
|
8
|
+
"version": "2.39.19",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|
package/view/SVG.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Created by Alex on 13/12/2016.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
export const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
*
|
|
@@ -111,7 +112,7 @@ function svgArc2(r0, r1, a0, b0, a1, b1) {
|
|
|
111
112
|
* @returns {Element}
|
|
112
113
|
*/
|
|
113
114
|
function createSVGElement(tag) {
|
|
114
|
-
return document.createElementNS(
|
|
115
|
+
return document.createElementNS(SVG_NAMESPACE, tag);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
export default {
|
package/view/View.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import Vector2 from "../core/geom/Vector2";
|
|
2
|
+
import Signal from "../core/events/signal/Signal";
|
|
3
|
+
|
|
4
|
+
export interface IViewSignals {
|
|
5
|
+
readonly linked: Signal
|
|
6
|
+
readonly unlinked: Signal
|
|
7
|
+
}
|
|
2
8
|
|
|
3
9
|
export default class View<T extends Element = HTMLElement> {
|
|
4
10
|
size: Vector2
|
|
@@ -6,6 +12,8 @@ export default class View<T extends Element = HTMLElement> {
|
|
|
6
12
|
|
|
7
13
|
el: T
|
|
8
14
|
|
|
15
|
+
readonly on: IViewSignals
|
|
16
|
+
|
|
9
17
|
public link(): void
|
|
10
18
|
|
|
11
19
|
public unlink(): void
|
|
@@ -3,32 +3,38 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import View from "../View.js";
|
|
6
|
-
import dom from "../DOM.js";
|
|
7
6
|
|
|
8
7
|
class EmptyView extends View {
|
|
9
8
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @param
|
|
9
|
+
* @param {string[]} [classList]
|
|
10
|
+
* @param {Element} [el]
|
|
11
|
+
* @param {string} [tag]
|
|
12
|
+
* @param {string} [tagNamespace]
|
|
13
|
+
* @param {Object<string>} [css]
|
|
14
|
+
* @param {Object<string>} [attr]
|
|
12
15
|
* @extends {View}
|
|
13
16
|
* @constructor
|
|
14
17
|
*/
|
|
15
|
-
constructor({ classList = [], tag = 'div', css } = {}) {
|
|
18
|
+
constructor({ classList = [], el, tag = 'div', tagNamespace = undefined, css, attr } = {}) {
|
|
16
19
|
super();
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
elClassList.add(className);
|
|
21
|
+
if (el !== undefined) {
|
|
22
|
+
this.el = el;
|
|
23
|
+
} else if (tagNamespace !== undefined) {
|
|
24
|
+
this.el = document.createElementNS(tagNamespace, tag);
|
|
25
|
+
} else {
|
|
26
|
+
this.el = document.createElement(tag);
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
this.
|
|
29
|
+
this.addClasses(classList);
|
|
28
30
|
|
|
29
31
|
if (css !== undefined) {
|
|
30
32
|
this.css(css);
|
|
31
33
|
}
|
|
34
|
+
|
|
35
|
+
if (attr !== undefined) {
|
|
36
|
+
this.attr(attr);
|
|
37
|
+
}
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
/**
|
|
@@ -17,6 +17,15 @@ function makeTextAbsolute(value, max, process) {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
class ProgressBarView extends View {
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param {number[]|BoundedValue} model
|
|
23
|
+
* @param classList
|
|
24
|
+
* @param displayLabel
|
|
25
|
+
* @param displayLabelType
|
|
26
|
+
* @param displayTipMarker
|
|
27
|
+
* @param process
|
|
28
|
+
*/
|
|
20
29
|
constructor(model, {
|
|
21
30
|
classList = [],
|
|
22
31
|
displayLabel = false,
|