@woosh/meep-engine 2.33.60 → 2.33.61
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/geom/3d/SurfacePoint3.js +44 -5
- package/core/geom/Vector2.d.ts +2 -0
- package/core/geom/packing/MaxRectangles.js +13 -4
- package/core/math/hash/murmur3_32.js +3 -3
- package/engine/asset/loaders/material/computeTextureHash.js +7 -13
- package/engine/ecs/attachment/AttachmentSystem.js +18 -17
- package/engine/ecs/grid/HeightMap2NormalMap.js +1 -1
- package/engine/ecs/grid/NormalMap2AOMap.js +1 -1
- package/engine/ecs/gui/position/ViewportPositionSystem.js +5 -5
- package/engine/ecs/parent/EntityNode.d.ts +20 -0
- package/engine/ecs/parent/EntityNode.js +284 -0
- package/engine/ecs/parent/FaceEditor.js +137 -0
- package/engine/ecs/parent/testCompositionEntityNode.js +153 -0
- package/engine/ecs/parent/testHuDPerf.js +123 -0
- package/engine/ecs/terrain/ecs/Terrain.js +14 -5
- package/engine/graphics/GraphicsEngine.js +1 -2
- package/engine/graphics/camera/testClippingPlaneComputation.js +0 -4
- package/engine/graphics/ecs/light/LightSystem.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +29 -0
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +158 -1
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
- package/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +55 -11
- package/engine/graphics/micron/render/v1/MaterialContext.js +1 -0
- package/engine/graphics/particles/particular/engine/simulator/SimulationStepFixedPhysics.js +19 -3
- package/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +0 -2
- package/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
- package/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
- package/engine/graphics/render/frame_graph/FrameGraphBuilder.js +36 -0
- package/engine/graphics/render/frame_graph/IRenderContext.js +8 -0
- package/engine/graphics/render/frame_graph/RenderPass.js +32 -0
- package/engine/graphics/render/frame_graph/RenderPassFlags.js +6 -0
- package/engine/graphics/render/frame_graph/RenderPassResources.js +15 -0
- package/engine/graphics/render/frame_graph/Resource.js +21 -0
- package/engine/graphics/render/frame_graph/ResourceReference.js +14 -0
- package/engine/graphics/render/frame_graph/TextureDescriptor.js +30 -0
- package/engine/graphics/render/frame_graph/UsageModeType.js +5 -0
- package/engine/graphics/render/frame_graph/sample/deferred/GBufferDrawPass.js +27 -0
- package/engine/graphics/render/frame_graph/sample/deferred/PresentPass.js +17 -0
- package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
- package/engine/graphics/render/webgpu/sample/_main.ts +650 -0
- package/engine/graphics/render/webgpu/sample/fragmentDeferredRendering.wgsl +67 -0
- package/engine/graphics/render/webgpu/sample/fragmentGBuffersDebugView.wgsl +38 -0
- package/engine/graphics/render/webgpu/sample/fragmentWriteGBuffers.wgsl +21 -0
- package/engine/graphics/render/webgpu/sample/lightUpdate.wgsl +34 -0
- package/engine/graphics/render/webgpu/sample/main.js +566 -0
- package/engine/graphics/render/webgpu/sample/vertexTextureQuad.wgsl +9 -0
- package/engine/graphics/render/webgpu/sample/vertexWriteGBuffers.wgsl +28 -0
- package/engine/graphics/shadows/testShadowMapRendering.js +0 -2
- package/engine/{ecs/grid → graphics/texture/sampler}/sampler2DToFloat32Texture.js +1 -1
- package/package.json +1 -1
- package/samples/terrain/main.js +117 -0
- package/engine/ecs/sockets/AttachmentSocketsSystem.js +0 -10
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Quaternion from "../Quaternion.js";
|
|
2
2
|
import Vector3 from "../Vector3.js";
|
|
3
|
+
import { v3_length } from "../v3_length.js";
|
|
3
4
|
|
|
4
5
|
const q = new Quaternion();
|
|
5
6
|
|
|
@@ -14,14 +15,52 @@ export class SurfacePoint3 {
|
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
*
|
|
17
|
-
* @param {
|
|
18
|
+
* @param {number[]|mat4|Float32Array} m4
|
|
18
19
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
applyMatrix4(m4) {
|
|
21
|
+
// transform position
|
|
22
|
+
const p = this.position;
|
|
23
|
+
|
|
24
|
+
const p_x = p.x;
|
|
25
|
+
const p_y = p.y;
|
|
26
|
+
const p_z = p.z;
|
|
27
|
+
|
|
28
|
+
const result_p_x = m4[0] * p_x + m4[4] * p_y + m4[8] * p_z + m4[12];
|
|
29
|
+
const result_p_y = m4[1] * p_x + m4[5] * p_y + m4[9] * p_z + m4[13];
|
|
30
|
+
const result_p_z = m4[2] * p_x + m4[6] * p_y + m4[10] * p_z + m4[14];
|
|
31
|
+
|
|
32
|
+
this.position.set(
|
|
33
|
+
result_p_x,
|
|
34
|
+
result_p_y,
|
|
35
|
+
result_p_z
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// transform normal
|
|
39
|
+
const n = this.normal;
|
|
40
|
+
|
|
41
|
+
const n_x = n.x;
|
|
42
|
+
const n_y = n.y;
|
|
43
|
+
const n_z = n.z;
|
|
44
|
+
|
|
45
|
+
const result_n_x = m4[0] * n_x + m4[4] * n_y + m4[8] * n_z;
|
|
46
|
+
const result_n_y = m4[1] * n_x + m4[5] * n_y + m4[9] * n_z;
|
|
47
|
+
const result_n_z = m4[2] * n_x + m4[6] * n_y + m4[10] * n_z;
|
|
21
48
|
|
|
22
|
-
|
|
49
|
+
const normal_multiplier = 1 / v3_length(result_n_x, result_n_y, result_n_z);
|
|
23
50
|
|
|
24
|
-
this.normal.
|
|
51
|
+
this.normal.set(
|
|
52
|
+
result_n_x * normal_multiplier,
|
|
53
|
+
result_n_y * normal_multiplier,
|
|
54
|
+
result_n_z * normal_multiplier,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
*
|
|
60
|
+
* @param {THREE.Matrix4} matrix4
|
|
61
|
+
*/
|
|
62
|
+
applyMatrix4_three(matrix4) {
|
|
63
|
+
this.applyMatrix4(matrix4.elements);
|
|
25
64
|
}
|
|
26
65
|
|
|
27
66
|
/**
|
package/core/geom/Vector2.d.ts
CHANGED
|
@@ -12,9 +12,10 @@ import Vector2 from "../Vector2.js";
|
|
|
12
12
|
* @param {AABB2[]} boxes
|
|
13
13
|
*/
|
|
14
14
|
function removeRedundantBoxesArray(boxes) {
|
|
15
|
+
let i, j;
|
|
15
16
|
let numBoxes = boxes.length;
|
|
16
17
|
|
|
17
|
-
loop_a: for (
|
|
18
|
+
loop_a: for (i = 0; i < numBoxes; i++) {
|
|
18
19
|
const a = boxes[i];
|
|
19
20
|
|
|
20
21
|
const ax0 = a.x0;
|
|
@@ -22,7 +23,7 @@ function removeRedundantBoxesArray(boxes) {
|
|
|
22
23
|
const ax1 = a.x1;
|
|
23
24
|
const ay1 = a.y1;
|
|
24
25
|
|
|
25
|
-
for (
|
|
26
|
+
for (j = i + 1; j < numBoxes; j++) {
|
|
26
27
|
const b = boxes[j];
|
|
27
28
|
|
|
28
29
|
const bx0 = b.x0;
|
|
@@ -157,7 +158,7 @@ function findBestContainer(width, height, boxes, costFunction) {
|
|
|
157
158
|
let best = null;
|
|
158
159
|
let bestScore = Number.POSITIVE_INFINITY;
|
|
159
160
|
|
|
160
|
-
|
|
161
|
+
const visitor = (node) => {
|
|
161
162
|
|
|
162
163
|
if (node.getWidth() < width) {
|
|
163
164
|
//too small, don't traverse deeper
|
|
@@ -195,7 +196,11 @@ function findBestContainer(width, height, boxes, costFunction) {
|
|
|
195
196
|
best = box;
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
|
-
|
|
199
|
+
|
|
200
|
+
return true;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
boxes.traversePreOrder(visitor);
|
|
199
204
|
|
|
200
205
|
return best;
|
|
201
206
|
}
|
|
@@ -337,6 +342,10 @@ export class MaxRectanglesPacker {
|
|
|
337
342
|
this.free = new QuadTreeNode(0, 0, width, height);
|
|
338
343
|
this.free.add(null, 0, 0, width, height);
|
|
339
344
|
|
|
345
|
+
/**
|
|
346
|
+
*
|
|
347
|
+
* @type {AABB2[]}
|
|
348
|
+
*/
|
|
340
349
|
this.boxes = [];
|
|
341
350
|
}
|
|
342
351
|
|
|
@@ -9,9 +9,9 @@ export function murmur3_32(key, seed) {
|
|
|
9
9
|
let k1;
|
|
10
10
|
let i = 0;
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const key_length = key.length;
|
|
13
13
|
|
|
14
|
-
while (i <
|
|
14
|
+
while (i < key_length) {
|
|
15
15
|
k1 = key[i];
|
|
16
16
|
++i;
|
|
17
17
|
|
|
@@ -26,7 +26,7 @@ export function murmur3_32(key, seed) {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// mix in array length
|
|
29
|
-
h1 ^=
|
|
29
|
+
h1 ^= key_length;
|
|
30
30
|
|
|
31
31
|
h1 ^= h1 >>> 16;
|
|
32
32
|
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { max2 } from "../../../../core/math/max2.js";
|
|
2
1
|
import { computeImageBitmapHash } from "./computeImageBitmapHash.js";
|
|
3
2
|
import { computeHashIntegerArray } from "../../../../core/collection/array/computeHashIntegerArray.js";
|
|
4
3
|
import { computeHashFloat } from "../../../../core/math/hash/computeHashFloat.js";
|
|
4
|
+
import { murmur3_32 } from "../../../../core/math/hash/murmur3_32.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
*
|
|
@@ -59,6 +59,7 @@ export function computeImageDataHash(image) {
|
|
|
59
59
|
*/
|
|
60
60
|
function computeSpecificHash(texture) {
|
|
61
61
|
let dataHash = 0;
|
|
62
|
+
let i;
|
|
62
63
|
|
|
63
64
|
if (texture.image !== null && texture.image !== undefined) {
|
|
64
65
|
|
|
@@ -73,25 +74,18 @@ function computeSpecificHash(texture) {
|
|
|
73
74
|
if (Array.isArray(mipmaps)) {
|
|
74
75
|
const nMipmaps = mipmaps.length;
|
|
75
76
|
|
|
76
|
-
for (
|
|
77
|
+
for (i = 0; i < nMipmaps; i++) {
|
|
77
78
|
const mipmap = mipmaps[i];
|
|
78
79
|
|
|
79
|
-
if (mipmap.width > 16) {
|
|
80
|
-
continue;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
80
|
const data = mipmap.data;
|
|
84
|
-
|
|
85
81
|
const dataSize = data.length;
|
|
86
82
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
for (let i = 0; i < dataSize; i += dataStride) {
|
|
90
|
-
const datum = data[i];
|
|
91
|
-
|
|
92
|
-
dataHash = ((dataHash << 5) - dataHash) + datum;
|
|
83
|
+
if (dataSize > 1024) {
|
|
84
|
+
continue;
|
|
93
85
|
}
|
|
94
86
|
|
|
87
|
+
dataHash = ((dataHash << 5) - dataHash) + murmur3_32(data, 1337);
|
|
88
|
+
|
|
95
89
|
break;
|
|
96
90
|
}
|
|
97
91
|
|
|
@@ -6,7 +6,6 @@ import { assert } from "../../../core/assert.js";
|
|
|
6
6
|
import Mesh from "../../graphics/ecs/mesh/Mesh.js";
|
|
7
7
|
import { BoneAttachmentBinding } from "./BoneAttachmentBinding.js";
|
|
8
8
|
import { TransformAttachmentBinding } from "./TransformAttachmentBinding.js";
|
|
9
|
-
import { MeshSystem } from "../../graphics/ecs/mesh/MeshSystem.js";
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* @readonly
|
|
@@ -318,10 +317,10 @@ export class AttachmentSystem extends System {
|
|
|
318
317
|
|
|
319
318
|
/**
|
|
320
319
|
*
|
|
321
|
-
* @param {Mesh} mesh
|
|
322
320
|
* @param {number} entity
|
|
321
|
+
* @private
|
|
323
322
|
*/
|
|
324
|
-
|
|
323
|
+
__update_entity(entity) {
|
|
325
324
|
const bindings = this.parentBindingIndex.get(entity);
|
|
326
325
|
|
|
327
326
|
if (bindings !== undefined) {
|
|
@@ -335,25 +334,27 @@ export class AttachmentSystem extends System {
|
|
|
335
334
|
}
|
|
336
335
|
}
|
|
337
336
|
|
|
337
|
+
/**
|
|
338
|
+
*
|
|
339
|
+
* @param {Mesh} mesh
|
|
340
|
+
* @param {number} entity
|
|
341
|
+
*/
|
|
342
|
+
visitComponent(mesh, entity) {
|
|
343
|
+
this.__update_entity(entity);
|
|
344
|
+
}
|
|
345
|
+
|
|
338
346
|
update(timeDelta) {
|
|
339
347
|
//process wait queue
|
|
340
348
|
this.processWaiting();
|
|
341
349
|
|
|
342
|
-
|
|
343
|
-
*
|
|
344
|
-
* @type {MeshSystem}
|
|
345
|
-
*/
|
|
346
|
-
const meshSystem = this.entityManager.getSystem(MeshSystem);
|
|
350
|
+
const em = this.entityManager;
|
|
347
351
|
|
|
348
|
-
|
|
352
|
+
const ecd = em.dataset;
|
|
349
353
|
|
|
350
|
-
|
|
351
|
-
|
|
354
|
+
if (ecd === null) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
352
357
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
* @param {AttachmentBinding} binding
|
|
356
|
-
*/
|
|
357
|
-
function updateBinding(binding) {
|
|
358
|
-
binding.update();
|
|
358
|
+
ecd.traverseComponents(Attachment, this.visitComponent, this);
|
|
359
|
+
}
|
|
359
360
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { Sampler2D } from '../../graphics/texture/sampler/Sampler2D.js';
|
|
6
6
|
import NormalMapShader from '../../graphics/shaders/NormalMapShader2.js';
|
|
7
7
|
import ImageFilter from '../../graphics/filter/ImageFilter.js';
|
|
8
|
-
import { sampler2DtoFloat32Texture } from "
|
|
8
|
+
import { sampler2DtoFloat32Texture } from "../../graphics/texture/sampler/sampler2DToFloat32Texture.js";
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
function convertChannel(v) {
|
|
@@ -9,7 +9,7 @@ import sampler2D2Texture from '../../graphics/texture/sampler/Sampler2D2Texture.
|
|
|
9
9
|
import AmbientOcclusionShader from '../../graphics/shaders/AmbientOcclusionShader.js';
|
|
10
10
|
import GaussianBlurShader from '../../graphics/shaders/GaussianBlurShader.js';
|
|
11
11
|
import ImageFilter from '../../graphics/filter/ImageFilter.js';
|
|
12
|
-
import { sampler2DtoFloat32Texture } from "
|
|
12
|
+
import { sampler2DtoFloat32Texture } from "../../graphics/texture/sampler/sampler2DToFloat32Texture.js";
|
|
13
13
|
|
|
14
14
|
function filterResult2Texture(data, width, height) {
|
|
15
15
|
const result = new DataTexture();
|
|
@@ -5,7 +5,6 @@ import { System } from '../../System.js';
|
|
|
5
5
|
import ViewportPosition from './ViewportPosition.js';
|
|
6
6
|
import GUIElement from "../GUIElement.js";
|
|
7
7
|
import { assert } from "../../../../core/assert.js";
|
|
8
|
-
import Vector2 from "../../../../core/geom/Vector2.js";
|
|
9
8
|
import { SignalBinding } from "../../../../core/events/signal/SignalBinding.js";
|
|
10
9
|
import { EPSILON } from "../../../../core/math/MathUtils.js";
|
|
11
10
|
import AABB2 from "../../../../core/geom/AABB2.js";
|
|
@@ -202,8 +201,9 @@ function setElementPosition(view, bounds, viewportSize, vp) {
|
|
|
202
201
|
if (vp.stickToScreenEdge) {
|
|
203
202
|
|
|
204
203
|
|
|
205
|
-
const
|
|
206
|
-
const
|
|
204
|
+
const screenEdgeWidth = vp.screenEdgeWidth;
|
|
205
|
+
const clipEdgeX = screenEdgeWidth / viewportSize.x;
|
|
206
|
+
const clipEdgeY = screenEdgeWidth / viewportSize.y;
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
stickyBounds.set(clipEdgeX, clipEdgeY, 1 - clipEdgeX, 1 - clipEdgeY);
|
|
@@ -241,8 +241,8 @@ function setElementPosition(view, bounds, viewportSize, vp) {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
|
|
244
|
-
const targetX =
|
|
245
|
-
const targetY =
|
|
244
|
+
const targetX = x * (viewportSize.x);
|
|
245
|
+
const targetY = y * (viewportSize.y);
|
|
246
246
|
|
|
247
247
|
const viewPosition = view.position;
|
|
248
248
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import EntityBuilder from "../EntityBuilder";
|
|
2
|
+
import {EntityComponentDataset} from "../EntityComponentDataset";
|
|
3
|
+
import {Transform} from "../transform/Transform";
|
|
4
|
+
|
|
5
|
+
export class EntityNode {
|
|
6
|
+
constructor(entity?: EntityBuilder)
|
|
7
|
+
|
|
8
|
+
parent: EntityNode | null
|
|
9
|
+
entity: EntityBuilder
|
|
10
|
+
|
|
11
|
+
transform: Transform
|
|
12
|
+
|
|
13
|
+
addChild(node: EntityNode): boolean
|
|
14
|
+
|
|
15
|
+
removeChild(node: EntityNode): boolean
|
|
16
|
+
|
|
17
|
+
build(ecd: EntityComponentDataset): void
|
|
18
|
+
|
|
19
|
+
destroy(): void
|
|
20
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { ParentEntity } from "./ParentEntity.js";
|
|
2
|
+
import EntityBuilder from "../EntityBuilder.js";
|
|
3
|
+
import { array_remove_first } from "../../../core/collection/array/array_remove_first.js";
|
|
4
|
+
import { assert } from "../../../core/assert.js";
|
|
5
|
+
import { array_push_if_unique } from "../../../core/collection/array/array_push_if_unique.js";
|
|
6
|
+
import { Attachment } from "../attachment/Attachment.js";
|
|
7
|
+
import { AttachmentSockets } from "../sockets/AttachmentSockets.js";
|
|
8
|
+
import { AttachmentSocket } from "../sockets/AttachmentSocket.js";
|
|
9
|
+
import { Transform } from "../transform/Transform.js";
|
|
10
|
+
|
|
11
|
+
export class EntityNode {
|
|
12
|
+
/**
|
|
13
|
+
*
|
|
14
|
+
* @param {EntityBuilder} [entity] optional entity to be wrapped
|
|
15
|
+
*/
|
|
16
|
+
constructor(entity = new EntityBuilder()) {
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @type {EntityNode|null}
|
|
20
|
+
* @private
|
|
21
|
+
*/
|
|
22
|
+
this.__parent = null;
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @type {EntityBuilder}
|
|
26
|
+
* @private
|
|
27
|
+
*/
|
|
28
|
+
this.__entity = entity;
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @type {EntityNode[]}
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
this.__children = [];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @type {Transform}
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
41
|
+
this.__transform = new Transform();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @private
|
|
47
|
+
*/
|
|
48
|
+
__transform_sync_down() {
|
|
49
|
+
|
|
50
|
+
if (this.__parent === null) {
|
|
51
|
+
const t = this.__entity.getComponent(Transform);
|
|
52
|
+
if (t !== null) {
|
|
53
|
+
t.copy(this.__transform);
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
this.__safe_get_attachment().transform.copy(this.__transform);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
*
|
|
63
|
+
* @param {*} components
|
|
64
|
+
* @return {EntityNode}
|
|
65
|
+
*/
|
|
66
|
+
static fromComponents(...components) {
|
|
67
|
+
const node = new EntityNode();
|
|
68
|
+
|
|
69
|
+
for (let i = 0; i < components.length; i++) {
|
|
70
|
+
const component = components[i];
|
|
71
|
+
|
|
72
|
+
node.entity.add(component);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return node;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
* @return {Attachment}
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
__safe_get_attachment() {
|
|
84
|
+
let attachment = this.__entity.getComponent(Attachment);
|
|
85
|
+
|
|
86
|
+
if (attachment === null) {
|
|
87
|
+
attachment = new Attachment();
|
|
88
|
+
attachment.socket = "root";
|
|
89
|
+
attachment.immediate = true;
|
|
90
|
+
|
|
91
|
+
this.__entity.add(attachment);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return attachment;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @returns {Transform}
|
|
99
|
+
*/
|
|
100
|
+
get transform() {
|
|
101
|
+
return this.__transform;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
*
|
|
106
|
+
* @return {EntityNode|null}
|
|
107
|
+
*/
|
|
108
|
+
get parent() {
|
|
109
|
+
return this.__parent;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* @param {EntityNode|null} node
|
|
115
|
+
*/
|
|
116
|
+
set parent(node) {
|
|
117
|
+
// check if entity is built
|
|
118
|
+
if (this.__entity.isBuilt) {
|
|
119
|
+
// live re-wiring
|
|
120
|
+
let parent_entity = this.__entity.removeComponent(ParentEntity);
|
|
121
|
+
let attachment = this.__entity.removeComponent(Attachment);
|
|
122
|
+
|
|
123
|
+
if (node !== null) {
|
|
124
|
+
|
|
125
|
+
// handle component ParentEntity
|
|
126
|
+
|
|
127
|
+
if (parent_entity === null) {
|
|
128
|
+
parent_entity = new ParentEntity();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const parent_entity_builder = node.entity;
|
|
132
|
+
|
|
133
|
+
if (!parent_entity_builder.isBuilt) {
|
|
134
|
+
throw new Error('Parent entity is not built');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const parent_entity_id = parent_entity_builder.entity;
|
|
138
|
+
parent_entity.entity = parent_entity_id;
|
|
139
|
+
|
|
140
|
+
// add component back
|
|
141
|
+
this.__entity.add(parent_entity);
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
// handle component Attachment
|
|
145
|
+
if (attachment === null) {
|
|
146
|
+
attachment = this.__safe_get_attachment();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
attachment.parent = parent_entity_id;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.__parent = node;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get entity() {
|
|
157
|
+
return this.__entity;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
*
|
|
162
|
+
* @param {EntityNode} node
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
addChild(node) {
|
|
166
|
+
const added = array_push_if_unique(this.__children, node);
|
|
167
|
+
|
|
168
|
+
if (added) {
|
|
169
|
+
if (node.parent !== null) {
|
|
170
|
+
// has a parent already, detach
|
|
171
|
+
node.parent.removeChild(node);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
node.parent = this;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return added;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
*
|
|
182
|
+
* @param {EntityNode} node
|
|
183
|
+
* @returns {boolean}
|
|
184
|
+
*/
|
|
185
|
+
removeChild(node) {
|
|
186
|
+
const removed = array_remove_first(this.__children, node);
|
|
187
|
+
|
|
188
|
+
if (removed) {
|
|
189
|
+
assert.equal(node.parent, this, 'node is a child, but parent property points to something else instead of this node');
|
|
190
|
+
|
|
191
|
+
node.parent = null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return removed;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
*
|
|
199
|
+
* @param {EntityComponentDataset} ecd
|
|
200
|
+
*/
|
|
201
|
+
build(ecd) {
|
|
202
|
+
|
|
203
|
+
// assume that parent is built
|
|
204
|
+
const parent = this.__parent;
|
|
205
|
+
|
|
206
|
+
if (parent !== null) {
|
|
207
|
+
/**
|
|
208
|
+
*
|
|
209
|
+
* @type {ParentEntity}
|
|
210
|
+
*/
|
|
211
|
+
let parent_entity = this.__entity.getComponent(ParentEntity);
|
|
212
|
+
if (parent_entity === null) {
|
|
213
|
+
parent_entity = new ParentEntity();
|
|
214
|
+
this.__entity.add(parent_entity);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const parent_entity_builder = parent.__entity;
|
|
218
|
+
|
|
219
|
+
if (!parent_entity_builder.isBuilt) {
|
|
220
|
+
throw new Error('Parent entity is not built');
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const parent_entity_id = parent_entity_builder.entity;
|
|
224
|
+
parent_entity.entity = parent_entity_id;
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
const attachment = this.__safe_get_attachment();
|
|
228
|
+
|
|
229
|
+
attachment.parent = parent_entity_id;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ensure "root" socket exists for transform parenting
|
|
233
|
+
/**
|
|
234
|
+
*
|
|
235
|
+
* @type {AttachmentSockets}
|
|
236
|
+
*/
|
|
237
|
+
let sockets = this.__entity.getComponent(AttachmentSockets);
|
|
238
|
+
if (sockets === null) {
|
|
239
|
+
sockets = new AttachmentSockets();
|
|
240
|
+
this.__entity.add(sockets);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (sockets.get("root") === undefined) {
|
|
244
|
+
const socket = new AttachmentSocket();
|
|
245
|
+
socket.id = "root";
|
|
246
|
+
|
|
247
|
+
sockets.add(socket);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
this.__transform_sync_down();
|
|
251
|
+
this.__transform.position.onChanged.add(this.__transform_sync_down, this);
|
|
252
|
+
this.__transform.scale.onChanged.add(this.__transform_sync_down, this);
|
|
253
|
+
this.__transform.rotation.onChanged.add(this.__transform_sync_down, this);
|
|
254
|
+
|
|
255
|
+
this.__entity.build(ecd);
|
|
256
|
+
|
|
257
|
+
// build children
|
|
258
|
+
const children = this.__children;
|
|
259
|
+
const child_count = children.length;
|
|
260
|
+
for (let i = 0; i < child_count; i++) {
|
|
261
|
+
const child = children[i];
|
|
262
|
+
|
|
263
|
+
child.build(ecd);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
destroy() {
|
|
268
|
+
this.__transform.position.onChanged.remove(this.__transform_sync_down, this);
|
|
269
|
+
this.__transform.scale.onChanged.remove(this.__transform_sync_down, this);
|
|
270
|
+
this.__transform.rotation.onChanged.remove(this.__transform_sync_down, this);
|
|
271
|
+
|
|
272
|
+
// destroy children first
|
|
273
|
+
const children = this.__children;
|
|
274
|
+
const child_count = children.length;
|
|
275
|
+
for (let i = 0; i < child_count; i++) {
|
|
276
|
+
const child = children[i];
|
|
277
|
+
|
|
278
|
+
child.destroy();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// then main entity
|
|
282
|
+
this.__entity.destroy();
|
|
283
|
+
}
|
|
284
|
+
}
|