@woosh/meep-engine 2.37.19 → 2.37.20

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.
Files changed (110) hide show
  1. package/core/binary/float2uint8.js +8 -0
  2. package/core/binary/uint82float.js +8 -0
  3. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +6 -4
  4. package/core/collection/list/List.d.ts +1 -1
  5. package/core/color/Color.js +69 -1
  6. package/core/color/YCbCr_to_rgb_uint24.js +3 -4
  7. package/core/color/hsv2rgb.js +4 -3
  8. package/core/color/linear_to_sRGB.js +4 -5
  9. package/core/color/rgb2uint24.js +6 -4
  10. package/core/color/rgb_to_YCbCr_uint24.js +11 -13
  11. package/core/events/signal/Signal.d.ts +11 -9
  12. package/core/geom/2d/quad-tree/qt_collect_by_circle.js +67 -0
  13. package/core/geom/Quaternion.d.ts +16 -1
  14. package/core/geom/Quaternion.js +129 -65
  15. package/core/geom/Quaternion.spec.js +24 -0
  16. package/core/geom/Vector2.js +3 -3
  17. package/core/geom/Vector3.d.ts +2 -0
  18. package/core/geom/Vector3.js +31 -7
  19. package/core/geom/Vector4.js +16 -0
  20. package/core/math/bell_membership_function.js +19 -0
  21. package/core/math/exp2.js +8 -0
  22. package/core/math/interval/NumericInterval.js +17 -0
  23. package/core/math/physics/brdf/brdf_burley.js +25 -0
  24. package/core/math/physics/bsdf/bsdf_schlick.js +22 -0
  25. package/core/math/physics/irradiance/interpolate_irradiance_linear.js +18 -0
  26. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundLogarithmic.js → core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js} +2 -2
  27. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundSmith.js → core/math/physics/irradiance/interpolate_irradiance_smith.js} +1 -1
  28. package/editor/actions/concrete/ModifyPatchSampler2DAction.js +118 -0
  29. package/editor/actions/concrete/ModifyPatchSampler2DAction.spec.js +30 -0
  30. package/editor/actions/concrete/PatchTerrainHeightAction.js +12 -104
  31. package/editor/ecs/component/createObjectEditor.js +53 -29
  32. package/editor/ecs/component/editors/Sampler2DEditor.js +71 -24
  33. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +47 -0
  34. package/editor/ecs/component/editors/primitive/FunctionEditor.js +6 -2
  35. package/editor/tools/SelectionTool.js +1 -1
  36. package/editor/tools/paint/TerrainHeightPaintTool.js +88 -68
  37. package/editor/tools/paint/TerrainPaintTool.js +2 -1
  38. package/editor/tools/paint/TerrainTexturePaintTool.js +8 -73
  39. package/engine/asset/AssetManager.d.ts +1 -1
  40. package/engine/asset/AssetManager.js +390 -388
  41. package/engine/asset/loaders/gltf/extensions/MSFT_texture_dds.js +14 -2
  42. package/engine/ecs/fow/FogOfWarEditor.js +13 -0
  43. package/engine/ecs/terrain/ecs/OffsetScaleTransform2D.d.ts +6 -0
  44. package/engine/ecs/terrain/ecs/Terrain.js +21 -1
  45. package/engine/ecs/terrain/ecs/splat/SplatMapping.js +26 -28
  46. package/engine/ecs/terrain/overlay/TerrainOverlay.js +71 -66
  47. package/engine/ecs/terrain/tiles/TerrainTileManager.js +23 -0
  48. package/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +13 -7
  49. package/engine/ecs/transform/Transform.d.ts +2 -0
  50. package/engine/ecs/transform/Transform.js +3 -0
  51. package/engine/graphics/ecs/light/Light.js +0 -47
  52. package/engine/graphics/ecs/light/LightSerializationAdapter.js +50 -0
  53. package/engine/graphics/ecs/mesh-v2/DrawMode.js +2 -1
  54. package/engine/graphics/ecs/mesh-v2/build_three_object.js +3 -1
  55. package/engine/graphics/ecs/sprite/Sprite.js +11 -0
  56. package/engine/graphics/ecs/sprite/SpriteSystemPE.js +133 -0
  57. package/engine/graphics/ecs/sprite/prototypeSpriteSystem.js +1566 -0
  58. package/engine/graphics/micron/prototypeVirtualGeometry.js +2 -2
  59. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +17 -9
  60. package/engine/graphics/particles/particular/engine/renderers/ParticleRenderer.js +12 -10
  61. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +7 -2
  62. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticlePool.js +27 -0
  63. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticleRenderer.js +80 -0
  64. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +16 -4
  65. package/engine/graphics/shaders/TerrainShader.js +8 -8
  66. package/engine/graphics/texture/atlas/TextureAtlasDebugger.js +2 -1
  67. package/engine/graphics/texture/sampler/Sampler2D.js +190 -201
  68. package/engine/graphics/texture/sampler/Sampler2D.spec.js +34 -35
  69. package/engine/graphics/texture/sampler/bicubic.js +59 -0
  70. package/engine/graphics/texture/sampler/downsampleSample2D.spec.js +2 -2
  71. package/engine/graphics/texture/sampler/genericResampleSampler2D.js +0 -2
  72. package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +146 -0
  73. package/engine/graphics/texture/sampler/{downsampleSampler2D.js → sampler2D_scale_down_linear.js} +8 -4
  74. package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +140 -0
  75. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -3
  76. package/engine/graphics/texture/sampler/writeSampler2DDataToDataTexture.js +1 -1
  77. package/engine/input/ecs/util/TerrainCameraTargetSampler.js +2 -2
  78. package/engine/navigation/ecs/components/computeNonuniformCatmullRomSplineSample.js +117 -0
  79. package/engine/platform/GetURLHash.js +27 -0
  80. package/engine/platform/WebEnginePlatform.js +1 -22
  81. package/engine/sound/ecs/emitter/SoundEmitter.js +10 -6
  82. package/generation/GridGenerator.js +7 -6
  83. package/generation/example/SampleGenerator0.js +6 -6
  84. package/generation/example/filters/SampleGroundMoistureFilter.js +58 -17
  85. package/generation/example/themes/SampleTheme0.js +11 -7
  86. package/generation/filtering/numeric/CellFilterLiteralFloat.js +5 -0
  87. package/generation/filtering/numeric/complex/CellFilterDilate.js +36 -0
  88. package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +15 -5
  89. package/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +53 -1
  90. package/generation/filtering/numeric/math/CellFilterMax2.js +3 -0
  91. package/generation/filtering/numeric/math/CellFilterMembershipGeneralizedBell.js +55 -0
  92. package/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +42 -0
  93. package/generation/filtering/numeric/sampling/CellFilterSampleLayerCubic.js +36 -0
  94. package/generation/filtering/numeric/sampling/CellFilterSampleLayerLinear.js +41 -0
  95. package/generation/grid/GridData.d.ts +5 -1
  96. package/generation/grid/GridData.js +35 -36
  97. package/generation/grid/MarkerMatchCounter.js +5 -3
  98. package/generation/markers/GridActionRuleSet.js +15 -32
  99. package/generation/markers/GridCellActionPlaceMarker.js +8 -10
  100. package/generation/markers/debug/visualizeMarkers.js +56 -36
  101. package/generation/markers/emitter/MarkerNodeEmitterFromAction.js +8 -8
  102. package/generation/markers/prototypeGridCellActionPlaceMarker.js +209 -0
  103. package/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +1 -5
  104. package/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.spec.js +2 -2
  105. package/generation/placement/GridCellPlacementRule.js +10 -3
  106. package/package.json +1 -1
  107. package/samples/terrain/from_image.js +7 -3
  108. package/engine/graphics/particles/particular/engine/renderers/SoftBillboardParticleRenderer.js +0 -7
  109. package/engine/sound/ecs/emitter/attenuate/attenuateSoundLinear.js +0 -11
  110. package/generation/filtering/numeric/CellFilterReadGridLayer.js +0 -73
@@ -0,0 +1,118 @@
1
+ import { Action } from "../../../core/process/undo/Action.js";
2
+ import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
3
+
4
+ export class ModifyPatchSampler2DAction extends Action {
5
+ /**
6
+ *
7
+ * @param {Sampler2D} sampler
8
+ * @param {number[]} bounds
9
+ */
10
+ constructor(sampler, bounds) {
11
+ super();
12
+
13
+ /**
14
+ *
15
+ * @type {Sampler2D}
16
+ * @private
17
+ */
18
+ this.__sampler = sampler;
19
+
20
+ /**
21
+ *
22
+ * @type {number[]}
23
+ * @private
24
+ */
25
+ this.__bounds = bounds;
26
+
27
+ const width = this.__bounds[2] - this.__bounds[0];
28
+ const height = this.__bounds[3] - this.__bounds[1];
29
+
30
+ /**
31
+ *
32
+ * @type {Sampler2D}
33
+ */
34
+ this.__patch_new = Sampler2D.float32(sampler.itemSize, width, height);
35
+
36
+ /**
37
+ *
38
+ * @type {Sampler2D}
39
+ * @private
40
+ */
41
+ this.__patch_old = Sampler2D.float32(sampler.itemSize, width, height);
42
+ }
43
+
44
+ get patch() {
45
+ return this.__patch_new;
46
+ }
47
+
48
+ get x() {
49
+ return this.__bounds[0];
50
+ }
51
+
52
+ get y() {
53
+ return this.__bounds[1];
54
+ }
55
+
56
+ /**
57
+ *
58
+ * @param {number} x coordinate in global space
59
+ * @param {number} y coordinate in global space
60
+ * @param {number} [channel]
61
+ * @returns {number} delta between original value and the new one after the change
62
+ */
63
+ computeDelta(x, y, channel = 0) {
64
+ const _x = x - this.x;
65
+
66
+ if (_x < 0 || _x > this.__patch_new.width - 1) {
67
+ return 0;
68
+ }
69
+
70
+ const _y = y - this.y;
71
+
72
+ if (_y < 0 || _y > this.__patch_new.height - 1) {
73
+ return 0;
74
+ }
75
+
76
+ const value_old = this.__patch_old.sampleChannelBilinear(_x, _y, channel);
77
+ const value_new = this.__patch_new.sampleChannelBilinear(_x, _y, channel);
78
+
79
+ return value_new - value_old;
80
+ }
81
+
82
+ computeByteSize() {
83
+ return this.__patch_new.computeByteSize() + this.__patch_old.computeByteSize() + 280;
84
+ }
85
+
86
+
87
+ async apply(context) {
88
+
89
+ /**
90
+ *
91
+ * @type {Sampler2D}
92
+ */
93
+ const source = this.__sampler;
94
+
95
+ //store old data from the patch
96
+ const patch_old = this.__patch_old;
97
+
98
+ patch_old.copy_sameItemSize(source, this.x, this.y, 0, 0, patch_old.width, patch_old.height);
99
+
100
+ const patch_new = this.__patch_new;
101
+
102
+ //apply the patch
103
+ source.copy_sameItemSize(patch_new, 0, 0, this.x, this.y, patch_new.width, patch_new.height);
104
+ }
105
+
106
+ async revert(context) {
107
+ /**
108
+ *
109
+ * @type {Sampler2D}
110
+ */
111
+ const source = this.__sampler;
112
+
113
+ const patch_old = this.__patch_old;
114
+
115
+ //apply the patch
116
+ source.copy_sameItemSize(patch_old, 0, 0, this.x, this.y, patch_old.width, patch_old.height);
117
+ }
118
+ }
@@ -0,0 +1,30 @@
1
+ import { ModifyPatchSampler2DAction } from "./ModifyPatchSampler2DAction.js";
2
+ import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
3
+
4
+ test("apply patch size 0", async () => {
5
+ const sampler = Sampler2D.uint8(1, 1, 1);
6
+ sampler.data[0] = 123;
7
+
8
+ const action = new ModifyPatchSampler2DAction(sampler, [0, 0, 0, 0]);
9
+
10
+ await action.apply();
11
+
12
+ expect([...sampler.data]).toEqual([123]);
13
+ });
14
+
15
+ test("apply patch size 1, fill entire", async () => {
16
+ const sampler = Sampler2D.uint8(1, 1, 1);
17
+ sampler.data[0] = 123;
18
+
19
+ const action = new ModifyPatchSampler2DAction(sampler, [0, 0, 1, 1]);
20
+
21
+ action.patch.data[0] = 42;
22
+
23
+ await action.apply();
24
+
25
+ expect([...sampler.data]).toEqual([42]);
26
+
27
+ await action.revert();
28
+
29
+ expect([...sampler.data]).toEqual([123]);
30
+ });
@@ -1,7 +1,6 @@
1
- import { Action } from "../../../core/process/undo/Action.js";
2
- import { Sampler2D } from "../../../engine/graphics/texture/sampler/Sampler2D.js";
1
+ import { ModifyPatchSampler2DAction } from "./ModifyPatchSampler2DAction.js";
3
2
 
4
- export class PatchTerrainHeightAction extends Action {
3
+ export class PatchTerrainHeightAction extends ModifyPatchSampler2DAction {
5
4
  /**
6
5
  *
7
6
  * @param {Terrain} terrain
@@ -11,64 +10,25 @@ export class PatchTerrainHeightAction extends Action {
11
10
  * @param {number} height
12
11
  */
13
12
  constructor(terrain, x, y, width, height) {
14
- super();
13
+ super(terrain.samplerHeight, [x, y, x + width, y + height]);
15
14
 
16
15
  /**
17
16
  *
18
17
  * @type {Terrain}
19
18
  */
20
19
  this.terrain = terrain;
21
-
22
- /**
23
- *
24
- * @type {Sampler2D}
25
- */
26
- this.patch = Sampler2D.float32(1, width, height);
27
-
28
- this.x = x;
29
- this.y = y;
30
-
31
- this.__oldPatch = Sampler2D.float32(1, width, height);
32
20
  }
33
21
 
34
- /**
35
- *
36
- * @param {number} x
37
- * @param {number} y
38
- * @returns {number}
39
- */
40
- computeDelta(x, y) {
41
-
42
- const _x = x - this.x;
43
-
44
- if (_x < 0 || _x > this.patch.width - 1) {
45
- return 0;
46
- }
47
-
48
- const _y = y - this.y;
49
-
50
- if (_y < 0 || _y > this.patch.height - 1) {
51
- return 0;
52
- }
53
-
54
- const sourceValue = this.__oldPatch.sampleChannelBilinear(_x, _y, 0);
55
- const targetValue = this.patch.sampleChannelBilinear(_x, _y, 0);
56
-
57
-
58
- return targetValue - sourceValue;
59
- }
60
-
61
- computeByteSize() {
62
- return this.patch.computeByteSize() + this.__oldPatch.computeByteSize() + 280;
63
- }
64
-
65
- updateTerrain() {
22
+ async updateTerrain() {
66
23
  /**
67
24
  *
68
25
  * @type {Terrain}
69
26
  */
70
27
  const terrain = this.terrain;
71
28
 
29
+ terrain.updateHeightTexture();
30
+ terrain.updateWorkerHeights();
31
+
72
32
  /**
73
33
  *
74
34
  * @type {Sampler2D}
@@ -81,10 +41,6 @@ export class PatchTerrainHeightAction extends Action {
81
41
  */
82
42
  const tiles = terrain.__tiles;
83
43
 
84
- tiles.buildWorker.setHeightSampler(heightMap.data, heightMap.itemSize, heightMap.width, heightMap.height);
85
-
86
- const terrainSize = terrain.size;
87
-
88
44
  const x = this.x;
89
45
  const y = this.y;
90
46
 
@@ -94,66 +50,18 @@ export class PatchTerrainHeightAction extends Action {
94
50
  const v0 = y / heightMap.height;
95
51
  const v1 = (y + this.patch.height) / heightMap.height;
96
52
 
97
- const tx0 = u0 * terrainSize.x;
98
- const tx1 = u1 * terrainSize.x;
99
-
100
- const ty0 = v0 * terrainSize.y;
101
- const ty1 = v1 * terrainSize.y;
102
-
103
- const dirtyTiles = tiles.getRawTilesOverlappingRectangle(tx0 - 1, ty0 - 1, tx1 + 1, ty1 + 1);
104
-
105
- dirtyTiles.forEach(tile => {
106
- tile.isBuilt = false;
107
- });
108
-
109
- terrain.heightTexture.needsUpdate = true;
53
+ tiles.rebuildTilesByUV(u0, v0, u1, v1);
110
54
  }
111
55
 
112
56
  async apply(context) {
57
+ await super.apply(context);
113
58
 
114
- /**
115
- *
116
- * @type {Terrain}
117
- */
118
- const terrain = this.terrain;
119
-
120
- /**
121
- *
122
- * @type {Sampler2D}
123
- */
124
- const heightMap = terrain.heightMap;
125
-
126
- //store old data from the patch
127
- const oldPatch = this.__oldPatch;
128
-
129
- oldPatch.copy_sameItemSize(heightMap, this.x, this.y, 0, 0, oldPatch.width, oldPatch.height);
130
-
131
- const patch = this.patch;
132
- //apply the patch
133
- heightMap.copy_sameItemSize(patch, 0, 0, this.x, this.y, patch.width, patch.height);
134
-
135
- this.updateTerrain();
59
+ await this.updateTerrain();
136
60
  }
137
61
 
138
62
  async revert(context) {
63
+ await super.revert(context);
139
64
 
140
- /**
141
- *
142
- * @type {Terrain}
143
- */
144
- const terrain = this.terrain;
145
-
146
- /**
147
- *
148
- * @type {Sampler2D}
149
- */
150
- const heightMap = terrain.heightMap;
151
-
152
- const patch = this.__oldPatch;
153
-
154
- //apply the patch
155
- heightMap.copy_sameItemSize(patch, 0, 0, this.x, this.y, patch.width, patch.height);
156
-
157
- this.updateTerrain();
65
+ await this.updateTerrain();
158
66
  }
159
67
  }
@@ -67,6 +67,19 @@ function isReservedField(object, field_name) {
67
67
  return false;
68
68
  }
69
69
 
70
+ /**
71
+ *
72
+ * @type {string[]}
73
+ */
74
+ const reserved_prototype_names = [
75
+ "constructor"
76
+ ];
77
+
78
+ const reserved_prototypes = [
79
+ Object,
80
+ Object.prototype
81
+ ];
82
+
70
83
  /**
71
84
  *
72
85
  * @param {Object} object
@@ -101,48 +114,58 @@ function extract_object_fields_reflection(object, result, object_proto) {
101
114
  result.push(descriptor);
102
115
  }
103
116
 
104
- const descriptors = Object.getOwnPropertyDescriptors(object_proto);
117
+ if (!reserved_prototypes.includes(object_proto)) {
105
118
 
106
- for (let d_name in descriptors) {
107
- const d = descriptors[d_name];
119
+ const descriptors = Object.getOwnPropertyDescriptors(object_proto);
108
120
 
109
- const adapter = new FieldValueAdapter();
121
+ for (let d_name in descriptors) {
110
122
 
111
- if (d.get === undefined) {
112
- adapter.readable = false;
113
- }
123
+ if (reserved_prototype_names.includes(d_name)) {
124
+ // reserved name, skip
125
+ continue;
126
+ }
114
127
 
115
- if (d.set === undefined) {
116
- adapter.writable = false;
117
- }
128
+ const d = descriptors[d_name];
118
129
 
119
- if (!adapter.readable) {
120
- continue;
121
- }
130
+ const adapter = new FieldValueAdapter();
122
131
 
132
+ if (d.get === undefined && d.value === undefined) {
133
+ adapter.readable = false;
134
+ }
123
135
 
124
- let field_value;
136
+ if (d.get !== undefined && d.set === undefined) {
137
+ adapter.writable = false;
138
+ }
125
139
 
126
- try {
127
- field_value = adapter.read(object, d_name);
128
- } catch (e) {
129
- console.warn(e);
130
- continue;
131
- }
140
+ if (!adapter.readable) {
141
+ continue;
142
+ }
132
143
 
133
- const field_type = objectToClass(field_value);
134
144
 
135
- if (field_type === undefined) {
136
- continue;
137
- }
145
+ let field_value;
138
146
 
139
- const descriptor = new FieldDescriptor();
147
+ try {
148
+ field_value = adapter.read(object, d_name);
149
+ } catch (e) {
150
+ console.warn(e);
151
+ continue;
152
+ }
140
153
 
141
- descriptor.name = d_name;
142
- descriptor.type = field_type;
143
- descriptor.adapter = adapter;
154
+ const field_type = objectToClass(field_value);
155
+
156
+ if (field_type === undefined) {
157
+ continue;
158
+ }
159
+
160
+ const descriptor = new FieldDescriptor();
161
+
162
+ descriptor.name = d_name;
163
+ descriptor.type = field_type;
164
+ descriptor.adapter = adapter;
165
+
166
+ result.push(descriptor);
167
+ }
144
168
 
145
- result.push(descriptor);
146
169
  }
147
170
  }
148
171
 
@@ -153,6 +176,7 @@ function extract_object_fields_reflection(object, result, object_proto) {
153
176
  * @returns {FieldDescriptor[]}
154
177
  */
155
178
  function extractObjectFields(object, registry) {
179
+
156
180
  const result = [];
157
181
 
158
182
  const object_proto = Object.getPrototypeOf(object);
@@ -11,49 +11,96 @@ import { DataType } from "../../../../core/collection/table/DataType.js";
11
11
  import { min2 } from "../../../../core/math/min2.js";
12
12
  import { max2 } from "../../../../core/math/max2.js";
13
13
  import { isTypedArray } from "../../../../core/collection/array/typed/isTypedArray.js";
14
+ import { FrameRunner } from "../../../../engine/graphics/FrameRunner.js";
15
+
16
+ const UPDATE_DELAY = 200;
14
17
 
15
18
  export class Sampler2DEditor extends TypeEditor {
16
19
  build(parent, field, context) {
20
+
17
21
  /**
18
22
  * @type {Sampler2D}
19
23
  */
20
24
  const sampler = field.adapter.read(parent, field.name);
21
25
 
22
- let dataType;
26
+ let last_version = -1;
27
+ let last_update_time = 0;
28
+ let last_update_duration = 0;
23
29
 
24
- if (isTypedArray(sampler.data)) {
25
- dataType = typedArrayToDataType(sampler.data);
26
- } else {
27
- dataType = DataType.Float32;
28
- }
30
+ const view = new CanvasView();
31
+ view.css({
32
+ background: 'black'
33
+ });
29
34
 
30
- const TypedArrayConstructor = typedArrayConstructorByInstance(sampler.data);
35
+ function draw() {
36
+ const draw_start_time = performance.now();
31
37
 
32
- const res = 32;
33
- const result_sampler = new Sampler2D(new TypedArrayConstructor(sampler.itemSize * res * res), sampler.itemSize, res, res);
38
+ let dataType;
34
39
 
35
- scaleSampler2D(sampler, result_sampler);
40
+ if (isTypedArray(sampler.data)) {
41
+ dataType = typedArrayToDataType(sampler.data);
42
+ } else {
43
+ dataType = DataType.Float32;
44
+ }
36
45
 
37
- const view = new CanvasView();
46
+ let TypedArrayConstructor = typedArrayConstructorByInstance(sampler.data);
47
+
48
+ if (TypedArrayConstructor === Uint8Array) {
49
+ // use clamped array to avoid filtering artifacts
50
+ TypedArrayConstructor = Uint8ClampedArray;
51
+ }
52
+
53
+ const res = 32;
54
+ const result_sampler = new Sampler2D(new TypedArrayConstructor(sampler.itemSize * res * res), sampler.itemSize, res, res);
55
+
56
+ scaleSampler2D(sampler, result_sampler);
57
+
58
+
59
+ let min = 0, max = 0;
60
+ if (dataType === DataType.Float32) {
61
+ min = Infinity;
62
+ max = -Infinity;
63
+ for (let i = 0; i < result_sampler.itemSize; i++) {
64
+
65
+ min = min2(min, result_sampler.computeMin(i).value)
66
+ max = max2(min, result_sampler.computeMax(i).value)
67
+ }
68
+ } else if (dataType === DataType.Uint8) {
69
+ min = 0;
70
+ max = 255;
71
+ }
72
+
73
+ const scale = 255 / (max - min);
74
+ const offset = min;
75
+
76
+ sampler2D2Canvas(result_sampler, scale, offset, view.el);
77
+
78
+ last_version = sampler.version;
79
+
80
+ const draw_end_time = performance.now();
81
+ last_update_duration = draw_end_time - draw_start_time;
82
+
83
+ last_update_time = draw_end_time;
84
+ }
85
+
86
+
87
+ view.on.linked.add(try_update);
88
+
89
+ function try_update() {
90
+ if (sampler.version !== last_version) {
38
91
 
39
- let min = 0, max = 0;
40
- if (dataType === DataType.Float32) {
41
- min = Infinity;
42
- max = -Infinity;
43
- for (let i = 0; i < result_sampler.itemSize; i++) {
92
+ const time_now = performance.now();
44
93
 
45
- min = min2(min, result_sampler.computeMin(i).value)
46
- max = max2(min, result_sampler.computeMax(i).value)
94
+ if ((time_now - last_update_time) >= UPDATE_DELAY) {
95
+ draw();
96
+ }
47
97
  }
48
- } else if (dataType === DataType.Uint8) {
49
- min = 0;
50
- max = 255;
51
98
  }
52
99
 
53
- const scale = 255 / (max - min);
54
- const offset = min;
100
+ const frameRunner = new FrameRunner(try_update);
55
101
 
56
- sampler2D2Canvas(result_sampler, scale, offset, view.el);
102
+ view.on.linked.add(frameRunner.startup, frameRunner);
103
+ view.on.unlinked.add(frameRunner.shutdown, frameRunner);
57
104
 
58
105
  return view;
59
106
  }
@@ -4,8 +4,49 @@ import { TerrainFlags } from "../../../../../../engine/ecs/terrain/ecs/TerrainFl
4
4
  import { ImagePathEditor } from "../../ImagePathEditor.js";
5
5
  import { EnumEditor } from "../../common/EnumEditor.js";
6
6
  import { GridTransformKind } from "../../../../../../engine/ecs/terrain/ecs/GridTransformKind.js";
7
+ import { Texture } from "three";
7
8
 
8
9
  export class TerrainEditor extends ObjectEditor {
10
+ build(parent, field, registry) {
11
+ const view = super.build(parent, field, registry);
12
+
13
+ if (view) {
14
+
15
+ /**
16
+ * @type {Terrain}
17
+ */
18
+ const terrain = field.adapter.read(parent, field.name);
19
+
20
+ function updateLayers() {
21
+
22
+ terrain.layers.buildTexture();
23
+ terrain.layers.writeAllLayersDataIntoTexture();
24
+
25
+ terrain.updateMaterial();
26
+ }
27
+
28
+ // splats
29
+ view.bindSignal(terrain.layers.layers.on.added, () => {
30
+ terrain.splat.addWeightLayer();
31
+ updateLayers();
32
+ });
33
+ view.bindSignal(terrain.layers.layers.on.removed, (a, index) => {
34
+ terrain.splat.removeWeightLayer(index);
35
+
36
+ updateLayers();
37
+ });
38
+
39
+ // mapping sizes
40
+ view.bindSignal(terrain.splat.size.onChanged, (x, y) => {
41
+ terrain.splat.resize(x, y, terrain.splat.depth);
42
+
43
+ terrain.updateMaterial();
44
+ });
45
+ }
46
+
47
+ return view;
48
+ }
49
+
9
50
  get schema() {
10
51
  return {
11
52
  properties: {
@@ -35,6 +76,12 @@ export class TerrainEditor extends ObjectEditor {
35
76
  },
36
77
  heightTexture: {
37
78
  transient: true
79
+ },
80
+ buildLightMap: {
81
+ type: Function
82
+ },
83
+ aoMap: {
84
+ type: Texture
38
85
  }
39
86
  }
40
87
  };
@@ -3,6 +3,12 @@ import ButtonView from "../../../../../view/elements/button/ButtonView.js";
3
3
 
4
4
  export class FunctionEditor extends TypeEditor {
5
5
  build(parent, field, registry) {
6
+
7
+ if (field.schema === undefined) {
8
+ // no schema, function editors are only available for explicit schema
9
+ return undefined;
10
+ }
11
+
6
12
  /**
7
13
  * @type {Function}
8
14
  */
@@ -13,8 +19,6 @@ export class FunctionEditor extends TypeEditor {
13
19
  return undefined;
14
20
  }
15
21
 
16
- // TODO check that function takes no parameters maybe?
17
-
18
22
  return new ButtonView({
19
23
  action: () => {
20
24
  v.call(parent);
@@ -270,7 +270,7 @@ export function pickingEntitySelection(point, engine, camera) {
270
270
  */
271
271
  const sgm = em.getSystem(ShadedGeometrySystem);
272
272
 
273
- if (sgm !== undefined) {
273
+ if (sgm !== undefined && sgm !== null) {
274
274
  const hits = sgm.raycast(
275
275
  source.x, source.y, source.y,
276
276
  rayDirection.x, rayDirection.y, rayDirection.z