@woosh/meep-engine 2.44.7 → 2.45.1

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 (35) hide show
  1. package/core/cache/Cache.js +1 -1
  2. package/core/collection/HashMap.d.ts +1 -1
  3. package/core/collection/HashMap.js +2 -1
  4. package/core/localization/LanguageMetadata.js +48 -0
  5. package/core/localization/LocaleDataset.js +37 -0
  6. package/core/localization/Localization.js +253 -0
  7. package/core/model/node-graph/DataType.js +1 -1
  8. package/core/model/node-graph/node/Port.js +4 -0
  9. package/core/process/task/Task.js +22 -5
  10. package/core/process/task/util/iteratorTask.js +29 -0
  11. package/editor/view/ecs/components/items/ItemContainerController.stories.js +1 -1
  12. package/engine/Engine.js +1 -1
  13. package/engine/asset/AssetManager.js +4 -0
  14. package/engine/ecs/foliage/ViewState.js +7 -1
  15. package/engine/ecs/speaker/VoiceSystem.js +1 -1
  16. package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +17 -11
  17. package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +37 -0
  18. package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +19 -0
  19. package/engine/graphics/ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js +11 -2
  20. package/engine/graphics/render/forward_plus/LightManager.js +33 -123
  21. package/engine/graphics/render/forward_plus/SPECIFICATION.md +155 -0
  22. package/engine/graphics/render/forward_plus/assign_cluster.js +125 -0
  23. package/engine/graphics/render/forward_plus/model/Decal.js +6 -2
  24. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts +5 -0
  25. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +11 -4
  26. package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +3 -3
  27. package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
  28. package/engine/graphics/render/forward_plus/sort_decal_data.js +102 -0
  29. package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +1 -1
  30. package/engine/input/devices/InputDeviceButton.d.ts +7 -0
  31. package/engine/input/devices/InputDeviceButton.js +22 -0
  32. package/engine/input/devices/KeyboardDevice.d.ts +11 -0
  33. package/engine/input/devices/KeyboardDevice.js +17 -7
  34. package/package.json +1 -1
  35. package/core/Localization.js +0 -199
@@ -62,7 +62,7 @@ import { TooltipManager } from "../../../../../view/tooltip/TooltipManager.js";
62
62
  import { GMLEngine } from "../../../../../view/tooltip/gml/GMLEngine.js";
63
63
  import { PointerDevice } from "../../../../input/devices/PointerDevice.js";
64
64
  import { StaticKnowledgeDatabase } from "../../../../knowledge/database/StaticKnowledgeDatabase.js";
65
- import { Localization } from "../../../../../core/Localization.js";
65
+ import { Localization } from "../../../../../core/localization/Localization.js";
66
66
  import '../../../../../../../../css/game.scss'
67
67
  import { randomFromArray } from "../../../../../core/math/random/randomFromArray.js";
68
68
  import { debugAtlas } from "../../../particles/particular/engine/shader/debugAtlas.js";
@@ -1558,8 +1558,8 @@ function draw_camera_view_planes() {
1558
1558
  });
1559
1559
  }
1560
1560
 
1561
- prepare_scene_2();
1562
- // prepare_scene_decal_0();
1561
+ // prepare_scene_2();
1562
+ prepare_scene_decal_0();
1563
1563
  // prepare_scene_decal_1();
1564
1564
  // prepare_scene_decal_2();
1565
1565
  // prepare_scene_9();
@@ -125,9 +125,9 @@ export function query_bvh_frustum_from_texture(
125
125
  const light_descriptor = data_view.getUint32(node_address + 24);
126
126
 
127
127
  const light_type = light_descriptor & 3;
128
- const light_texel_index = light_descriptor >> 2;
129
128
 
130
- const light_address = light_texel_index * 4;
129
+ // mask out type bits
130
+ const light_address = light_descriptor & 0xFFFFFFF8;
131
131
 
132
132
  if (light_type === 0) {
133
133
  // Point light
@@ -0,0 +1,102 @@
1
+ const _scratch_array = [];
2
+
3
+ /**
4
+ *
5
+ * @param {number} a
6
+ * @param {number} b
7
+ * @param {number[]} lookup
8
+ * @param {number[]} data
9
+ * @returns {number}
10
+ */
11
+ function compare_decals(a, b, lookup, data) {
12
+ if (a === b) {
13
+ return 0;
14
+ }
15
+
16
+ const a_encoded = lookup[a];
17
+ const b_encoded = lookup[b];
18
+
19
+ // mask out bottom 2 type bits
20
+ const a_address = a_encoded & 0xFFFFFFF8;
21
+ const b_address = b_encoded & 0xFFFFFFF8;
22
+
23
+ const a_priority = data[a_address + 20];
24
+ const b_priority = data[b_address + 20];
25
+
26
+ let diff = b_priority - a_priority;
27
+
28
+ if (diff !== 0) {
29
+ return diff;
30
+ }
31
+
32
+
33
+ const a_id = data[a_address + 21];
34
+ const b_id = data[b_address + 21];
35
+
36
+ // data order is explicit and stable, we use that as a secondary comparison criteria
37
+ return b_id - a_id;
38
+ }
39
+
40
+ /**
41
+ * Decals need to be drawn in a specific order to achieve correct blending, for this they need to be sorted
42
+ * @param {number[]|Uint8ClampedArray|Uint8Array|Uint32Array} lookup
43
+ * @param {number[]|Float32Array} data
44
+ * @param {number} offset
45
+ * @param {number} count
46
+ */
47
+ export function sort_decal_data(lookup, data, offset, count) {
48
+ const stack = _scratch_array;
49
+
50
+ stack[0] = offset;
51
+ stack[1] = offset + count - 1;
52
+
53
+ let stackPointer = 2;
54
+ let i, j;
55
+
56
+ while (stackPointer > 0) {
57
+ stackPointer -= 2;
58
+
59
+ const right = stack[stackPointer + 1];
60
+ const left = stack[stackPointer];
61
+
62
+ i = left;
63
+ j = right;
64
+
65
+ const pivotIndex = (left + right) >> 1;
66
+
67
+ /* partition */
68
+ while (i <= j) {
69
+
70
+ while (compare_decals(i, pivotIndex, lookup, data) > 0) {
71
+ i++;
72
+ }
73
+
74
+ while (compare_decals(j, pivotIndex, lookup, data) < 0) {
75
+ j--;
76
+ }
77
+
78
+ if (i <= j) {
79
+
80
+ if (i !== j) {
81
+ //do swap
82
+ const swap = lookup[i];
83
+ lookup[i] = lookup[j]
84
+ lookup[j] = swap;
85
+ }
86
+
87
+ i++;
88
+ j--;
89
+ }
90
+ }
91
+
92
+ /* recursion */
93
+ if (left < j) {
94
+ stack[stackPointer++] = left;
95
+ stack[stackPointer++] = j;
96
+ }
97
+ if (i < right) {
98
+ stack[stackPointer++] = i;
99
+ stack[stackPointer++] = right;
100
+ }
101
+ }
102
+ }
@@ -27,7 +27,7 @@ import Task from "../../../../core/process/task/Task.js";
27
27
  import { TaskSignal } from "../../../../core/process/task/TaskSignal.js";
28
28
  import Quaternion from "../../../../core/geom/Quaternion.js";
29
29
  import TaskProgressView from "../../../../view/task/TaskProgressView.js";
30
- import { Localization } from "../../../../core/Localization.js";
30
+ import { Localization } from "../../../../core/localization/Localization.js";
31
31
 
32
32
  import '../../../../../../../css/game.scss';
33
33
  import { MouseEvents } from "../../../input/devices/events/MouseEvents.js";
@@ -0,0 +1,7 @@
1
+ import Signal from "../../../core/events/signal/Signal";
2
+
3
+ export class InputDeviceButton{
4
+ readonly up: Signal
5
+ readonly down: Signal
6
+ readonly is_down: boolean
7
+ }
@@ -0,0 +1,22 @@
1
+ import Signal from "../../../core/events/signal/Signal.js";
2
+
3
+ /**
4
+ * Representation of an input device key
5
+ */
6
+ export class InputDeviceButton {
7
+ /**
8
+ * Button press
9
+ * @type {Signal}
10
+ */
11
+ down = new Signal()
12
+ /**
13
+ * Button release
14
+ * @type {Signal}
15
+ */
16
+ up = new Signal()
17
+ /**
18
+ * is button currently being pressed?
19
+ * @type {boolean}
20
+ */
21
+ is_down = false
22
+ }
@@ -1,3 +1,14 @@
1
+ import {InputDeviceButton} from "./InputDeviceButton";
2
+ import Signal from "../../../core/events/signal/Signal";
3
+
1
4
  export default class KeyboardDevice {
5
+ constructor(domElement:EventTarget|Element)
6
+
7
+ readonly on: {up:Signal,down:Signal}
8
+
9
+ readonly keys:{[key:string]:InputDeviceButton}
10
+
11
+ start():void
2
12
 
13
+ stop():void
3
14
  }
@@ -5,6 +5,7 @@
5
5
  import Signal from "../../../core/events/signal/Signal.js";
6
6
  import { KeyCodes } from './KeyCodes.js';
7
7
  import { KeyboardEvents } from "./events/KeyboardEvents.js";
8
+ import { InputDeviceButton } from "./InputDeviceButton.js";
8
9
 
9
10
  /**
10
11
  *
@@ -66,21 +67,23 @@ class KeyboardDevice {
66
67
  up: new Signal()
67
68
  };
68
69
 
69
- //initialize separate events for each key
70
+
71
+ /**
72
+ *
73
+ * @type {Object<InputDeviceButton>}
74
+ */
70
75
  const keys = this.keys = {};
71
76
 
72
77
  const codeToKeyNameMap = [];
73
78
 
79
+ //initialize separate events for each key
74
80
  for (let keyName in KeyCodes) {
75
81
 
76
82
  const keyCode = KeyCodes[keyName];
77
83
 
78
84
  codeToKeyNameMap[keyCode] = keyName;
79
85
 
80
- keys[keyName] = {
81
- down: new Signal(),
82
- up: new Signal()
83
- };
86
+ keys[keyName] = new InputDeviceButton();
84
87
  }
85
88
 
86
89
  this.__handlerKeyDown = (event) => {
@@ -91,7 +94,11 @@ class KeyboardDevice {
91
94
  const keyName = codeToKeyNameMap[keyCode];
92
95
 
93
96
  if (keyName !== undefined) {
94
- keys[keyName].down.send1(event);
97
+ const button = keys[keyName];
98
+
99
+ button.is_down = true;
100
+ button.down.send1(event);
101
+
95
102
  }
96
103
  }
97
104
 
@@ -104,7 +111,10 @@ class KeyboardDevice {
104
111
  const keyName = codeToKeyNameMap[keyCode];
105
112
 
106
113
  if (keyName !== undefined) {
107
- keys[keyName].up.send1(event);
114
+ const button = keys[keyName];
115
+
116
+ button.is_down = false;
117
+ button.up.send1(event);
108
118
  }
109
119
  }
110
120
  }
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.44.7",
8
+ "version": "2.45.1",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",
@@ -1,199 +0,0 @@
1
- import levenshtein from "fast-levenshtein";
2
- import { GameAssetType } from "../engine/asset/GameAssetType.js";
3
- import { parseTooltipString } from "../view/tooltip/gml/parser/parseTooltipString.js";
4
- import { assert } from "./assert.js";
5
- import ObservedString from "./model/ObservedString.js";
6
- import { seedVariablesIntoTemplateString } from "./parser/seedVariablesIntoTemplateString.js";
7
- import { STRING_TEMPLATE_VARIABLE_REGEX } from "./parser/STRING_TEMPLATE_VARIABLE_REGEX.js";
8
-
9
- /**
10
- * Validation utility method
11
- * @param {string} template
12
- * @return {string}
13
- */
14
- function validationMockSeed(template) {
15
-
16
- const result = template.replace(STRING_TEMPLATE_VARIABLE_REGEX, function (match, varName) {
17
- return "0";
18
- });
19
-
20
- return result;
21
- }
22
-
23
- const FAILURE_MESSAGE_CACHE = {};
24
-
25
- export class Localization {
26
- constructor() {
27
- /**
28
- *
29
- * @type {AssetManager|null}
30
- */
31
- this.assetManager = null;
32
-
33
- this.json = {};
34
-
35
- /**
36
- * Measured in characters per second
37
- * @type {number}
38
- */
39
- this.reading_speed = 10;
40
-
41
- /**
42
- *
43
- * @type {ObservedString}
44
- */
45
- this.locale = new ObservedString('');
46
- }
47
-
48
- /**
49
- *
50
- * @param {string} text
51
- * @returns {number}
52
- */
53
- computeReadingTime(text) {
54
- assert.typeOf(text, 'string', 'text');
55
-
56
- return text.length / this.reading_speed;
57
- }
58
-
59
- /**
60
- *
61
- * @param {AssetManager} am
62
- */
63
- setAssetManager(am) {
64
- this.assetManager = am;
65
- }
66
-
67
- /**
68
- * @returns {boolean}
69
- * @param {function(key:string, error:*, original: string)} errorConsumer
70
- */
71
- validate(errorConsumer) {
72
- let result = true;
73
-
74
- for (let key in this.json) {
75
- const value = this.json[key];
76
-
77
- const seededValue = validationMockSeed(value);
78
-
79
- try {
80
- parseTooltipString(seededValue);
81
- } catch (e) {
82
- result = false;
83
- errorConsumer(key, e, value);
84
- }
85
- }
86
-
87
- return result;
88
- }
89
-
90
- /**
91
- *
92
- * @param {string} locale
93
- * @returns {Promise}
94
- */
95
- loadLocale(locale) {
96
- const am = this.assetManager;
97
-
98
- const pLoadData = am.promise(`data/database/text/${locale}.json`, GameAssetType.JSON)
99
- .then(asset => {
100
- const json = asset.create();
101
-
102
- this.json = json;
103
-
104
- this.locale.set(locale);
105
- });
106
-
107
- const pLoadMetadata = am.promise(`data/database/text/languages.json`, GameAssetType.JSON)
108
- .then(asset => {
109
- const languages_metadata = asset.create();
110
-
111
- const { reading_speed = 10 } = languages_metadata[locale];
112
-
113
- assert.isNumber(reading_speed, 'reading_speed');
114
- assert.greaterThan(reading_speed, 0, 'reading_speed');
115
-
116
- this.reading_speed = reading_speed;
117
- });
118
-
119
- return Promise.all([pLoadData, pLoadMetadata]);
120
- }
121
-
122
- /**
123
- *
124
- * @param {String} id
125
- * @return {boolean}
126
- */
127
- hasString(id) {
128
- return this.json[id] !== undefined;
129
- }
130
-
131
- /**
132
- *
133
- * @param {number} value
134
- */
135
- formatIntegerByThousands(value) {
136
- const formatter = new Intl.NumberFormat(this.locale.getValue(), { useGrouping: true });
137
-
138
- return formatter.format(value);
139
- }
140
-
141
- /**
142
- *
143
- * @param {string} id
144
- * @param {object} [seed]
145
- *
146
- * @returns {string}
147
- */
148
- getString(id, seed = {}) {
149
- assert.typeOf(id, 'string', 'id');
150
-
151
- const value = this.json[id];
152
-
153
- if (value === undefined) {
154
-
155
- if (!ENV_PRODUCTION) {
156
- const locale = this.locale.getValue();
157
-
158
- if (FAILURE_MESSAGE_CACHE[locale] === undefined) {
159
- FAILURE_MESSAGE_CACHE[locale] = {};
160
- }
161
-
162
- if (FAILURE_MESSAGE_CACHE[locale][id] === undefined) {
163
-
164
- //try to find similar keys
165
- const similarities = Object.keys(this.json).map(function (key) {
166
- const distance = levenshtein.get(key, id);
167
- return {
168
- key,
169
- distance
170
- };
171
- });
172
-
173
- similarities.sort(function (a, b) {
174
- return a.distance - b.distance;
175
- });
176
-
177
- const suggestions = similarities.slice(0, 3).map(p => p.key);
178
-
179
- const message = `No localization value for id='${id}', seed=${JSON.stringify(seed)}, approximate matches: ${suggestions.join(', ')}`;
180
-
181
- FAILURE_MESSAGE_CACHE[locale][id] = message;
182
-
183
- }
184
-
185
- console.warn(FAILURE_MESSAGE_CACHE[locale][id]);
186
-
187
- }
188
-
189
- //no value
190
- return `@${id}`;
191
-
192
- }
193
-
194
- //value needs to be seeded
195
- const seededValue = seedVariablesIntoTemplateString(value, seed);
196
-
197
- return seededValue;
198
- }
199
- }