@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.
- package/core/cache/Cache.js +1 -1
- package/core/collection/HashMap.d.ts +1 -1
- package/core/collection/HashMap.js +2 -1
- package/core/localization/LanguageMetadata.js +48 -0
- package/core/localization/LocaleDataset.js +37 -0
- package/core/localization/Localization.js +253 -0
- package/core/model/node-graph/DataType.js +1 -1
- package/core/model/node-graph/node/Port.js +4 -0
- package/core/process/task/Task.js +22 -5
- package/core/process/task/util/iteratorTask.js +29 -0
- package/editor/view/ecs/components/items/ItemContainerController.stories.js +1 -1
- package/engine/Engine.js +1 -1
- package/engine/asset/AssetManager.js +4 -0
- package/engine/ecs/foliage/ViewState.js +7 -1
- package/engine/ecs/speaker/VoiceSystem.js +1 -1
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +17 -11
- package/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +37 -0
- package/engine/graphics/ecs/mesh-v2/render/ShadedGeometryRendererContext.js +19 -0
- package/engine/graphics/ecs/mesh-v2/render/adapters/AbstractRenderAdapter.js +11 -2
- package/engine/graphics/render/forward_plus/LightManager.js +33 -123
- package/engine/graphics/render/forward_plus/SPECIFICATION.md +155 -0
- package/engine/graphics/render/forward_plus/assign_cluster.js +125 -0
- package/engine/graphics/render/forward_plus/model/Decal.js +6 -2
- package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.d.ts +5 -0
- package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +11 -4
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +3 -3
- package/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
- package/engine/graphics/render/forward_plus/sort_decal_data.js +102 -0
- package/engine/graphics/sh3/path_tracer/prototypePathTracer.js +1 -1
- package/engine/input/devices/InputDeviceButton.d.ts +7 -0
- package/engine/input/devices/InputDeviceButton.js +22 -0
- package/engine/input/devices/KeyboardDevice.d.ts +11 -0
- package/engine/input/devices/KeyboardDevice.js +17 -7
- package/package.json +1 -1
- 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
|
-
|
|
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
|
-
|
|
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,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
|
-
|
|
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]
|
|
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]
|
|
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.
|
|
8
|
+
"version": "2.45.1",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|
package/core/Localization.js
DELETED
|
@@ -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
|
-
}
|