@woosh/meep-engine 2.44.8 → 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/collection/HashMap.d.ts +1 -1
- package/core/collection/HashMap.js +2 -1
- package/core/localization/LanguageMetadata.js +22 -2
- package/core/localization/LocaleDataset.js +37 -0
- package/core/localization/Localization.js +28 -19
- package/core/process/task/Task.js +22 -5
- package/core/process/task/util/iteratorTask.js +29 -0
- package/engine/ecs/foliage/ViewState.js +7 -1
- 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 +13 -1
- 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/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
|
@@ -29,7 +29,7 @@ export class HashMap<K, V> implements Iterable<[V, K]> {
|
|
|
29
29
|
|
|
30
30
|
forEach(callback: (value: V, key: K, map: this) => any, thisArg?: any): void
|
|
31
31
|
|
|
32
|
-
[Symbol.iterator](): IterableIterator<[
|
|
32
|
+
[Symbol.iterator](): IterableIterator<[K, V]>
|
|
33
33
|
|
|
34
34
|
values(): IterableIterator<V>
|
|
35
35
|
|
|
@@ -40,6 +40,7 @@ const DEFAULT_LOAD_FACTOR = 0.75;
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Implements part of {@link Map} interface
|
|
43
|
+
* @copyright Alex Goldring (c) 2023
|
|
43
44
|
* @template K,V
|
|
44
45
|
* @extends Map<K,V>
|
|
45
46
|
*/
|
|
@@ -519,7 +520,7 @@ export class HashMap {
|
|
|
519
520
|
*/
|
|
520
521
|
const entry = bucket[i];
|
|
521
522
|
|
|
522
|
-
yield [entry.
|
|
523
|
+
yield [entry.key, entry.value];
|
|
523
524
|
}
|
|
524
525
|
}
|
|
525
526
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assert } from "../assert.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Represents information about a language
|
|
5
5
|
*/
|
|
6
6
|
export class LanguageMetadata {
|
|
7
7
|
/**
|
|
@@ -10,12 +10,32 @@ export class LanguageMetadata {
|
|
|
10
10
|
*/
|
|
11
11
|
reading_speed = 10
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Ordered list of fallback languages, if no value is found for a key in this language, other languages will be attempted in order
|
|
15
|
+
* Identified by localization key
|
|
16
|
+
* @see {@link #locale}
|
|
17
|
+
* @type {string[]}
|
|
18
|
+
*/
|
|
19
|
+
fallback_languages = []
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Localization key,
|
|
23
|
+
* @see ISO 639
|
|
24
|
+
* @type {string}
|
|
25
|
+
*/
|
|
26
|
+
locale = "";
|
|
27
|
+
|
|
28
|
+
fromJSON({
|
|
29
|
+
reading_speed = 10,
|
|
30
|
+
fallback_languages = []
|
|
31
|
+
}) {
|
|
14
32
|
|
|
15
33
|
assert.isNumber(reading_speed, 'reading_speed');
|
|
16
34
|
assert.greaterThan(reading_speed, 0, 'reading_speed');
|
|
17
35
|
|
|
18
36
|
this.reading_speed = reading_speed;
|
|
37
|
+
|
|
38
|
+
this.fallback_languages = fallback_languages;
|
|
19
39
|
}
|
|
20
40
|
|
|
21
41
|
static fromJSON(j) {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
|
|
3
|
+
import { assert } from "../assert.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents data for a single localization
|
|
7
|
+
*/
|
|
8
|
+
export class LocaleDataset {
|
|
9
|
+
/**
|
|
10
|
+
* Localized strings, identified by localization key
|
|
11
|
+
* @type {Object<string>}
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
__strings = {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* Does a given key exist?
|
|
19
|
+
* @param {string} key
|
|
20
|
+
* @return {boolean}
|
|
21
|
+
*/
|
|
22
|
+
hasString(key) {
|
|
23
|
+
assert.isString(key, 'key');
|
|
24
|
+
|
|
25
|
+
return this.__strings[key] !== undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
*
|
|
30
|
+
* @param {string} key
|
|
31
|
+
* @returns {string|undefined}
|
|
32
|
+
*/
|
|
33
|
+
getString(key) {
|
|
34
|
+
return this.__strings[key];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
@@ -25,7 +25,7 @@ function validationMockSeed(template) {
|
|
|
25
25
|
|
|
26
26
|
const EMPTY_SEED = Object.freeze({});
|
|
27
27
|
|
|
28
|
-
const DEFAULT_LANGUAGE_METADATA = new LanguageMetadata();
|
|
28
|
+
const DEFAULT_LANGUAGE_METADATA = Object.freeze(new LanguageMetadata());
|
|
29
29
|
|
|
30
30
|
export class Localization {
|
|
31
31
|
constructor() {
|
|
@@ -117,7 +117,8 @@ export class Localization {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
|
-
*
|
|
120
|
+
* Request locale switch
|
|
121
|
+
* Assumes a specific folder structure, each different locale is stored with its locale code as name, and there's also "languages.json" file expected to be in the folder
|
|
121
122
|
* @param {string} locale
|
|
122
123
|
* @param {string} path where to look for localization data
|
|
123
124
|
* @returns {Promise}
|
|
@@ -132,7 +133,14 @@ export class Localization {
|
|
|
132
133
|
throw new Error('AssetManager is not set');
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
let _path = path.trim();
|
|
137
|
+
|
|
138
|
+
while (_path.endsWith('/') || _path.endsWith('\\')) {
|
|
139
|
+
// remove trailing slash if present
|
|
140
|
+
_path.slice(0, _path.length - 1);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const pLoadData = am.promise(`${_path}/${locale}.json`, "json")
|
|
136
144
|
.then(asset => {
|
|
137
145
|
const json = asset.create();
|
|
138
146
|
|
|
@@ -148,7 +156,7 @@ export class Localization {
|
|
|
148
156
|
|
|
149
157
|
});
|
|
150
158
|
|
|
151
|
-
const pLoadMetadata = am.promise(`${
|
|
159
|
+
const pLoadMetadata = am.promise(`${_path}/languages.json`, "json")
|
|
152
160
|
.then(asset => {
|
|
153
161
|
const languages_metadata = asset.create();
|
|
154
162
|
|
|
@@ -162,14 +170,6 @@ export class Localization {
|
|
|
162
170
|
return Promise.all([pLoadData, pLoadMetadata]);
|
|
163
171
|
}
|
|
164
172
|
|
|
165
|
-
/**
|
|
166
|
-
*
|
|
167
|
-
* @param {String} id
|
|
168
|
-
* @return {boolean}
|
|
169
|
-
*/
|
|
170
|
-
hasString(id) {
|
|
171
|
-
return this.json[id] !== undefined;
|
|
172
|
-
}
|
|
173
173
|
|
|
174
174
|
/**
|
|
175
175
|
*
|
|
@@ -216,29 +216,38 @@ export class Localization {
|
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
|
-
*
|
|
220
|
-
* @param {string}
|
|
219
|
+
* Get a localized string by a key
|
|
220
|
+
* @param {string} key
|
|
221
221
|
* @param {object} [seed]
|
|
222
222
|
*
|
|
223
223
|
* @returns {string}
|
|
224
224
|
*/
|
|
225
|
-
getString(
|
|
226
|
-
assert.isString(
|
|
225
|
+
getString(key, seed = EMPTY_SEED) {
|
|
226
|
+
assert.isString(key, 'id');
|
|
227
227
|
|
|
228
|
-
const value = this.json[
|
|
228
|
+
const value = this.json[key];
|
|
229
229
|
|
|
230
230
|
if (value === undefined) {
|
|
231
231
|
|
|
232
232
|
if (this.debug) {
|
|
233
|
-
this.__debugMissingKey(
|
|
233
|
+
this.__debugMissingKey(key, seed)
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
//no value, provide substitute
|
|
237
|
-
return `@${
|
|
237
|
+
return `@${key}`;
|
|
238
238
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
//value needs to be seeded
|
|
242
242
|
return seedVariablesIntoTemplateString(value, seed);
|
|
243
243
|
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Does a given key exist?
|
|
247
|
+
* @param {string} key
|
|
248
|
+
* @return {boolean}
|
|
249
|
+
*/
|
|
250
|
+
hasString(key) {
|
|
251
|
+
return this.json[key] !== undefined;
|
|
252
|
+
}
|
|
244
253
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { assert } from "../../assert.js";
|
|
7
7
|
import Signal from "../../events/signal/Signal.js";
|
|
8
|
-
import { noop
|
|
8
|
+
import { noop } from "../../function/Functions.js";
|
|
9
9
|
import ObservedInteger from "../../model/ObservedInteger.js";
|
|
10
10
|
import { TaskSignal } from "./TaskSignal.js";
|
|
11
11
|
import TaskState from "./TaskState.js";
|
|
@@ -27,14 +27,14 @@ class Task {
|
|
|
27
27
|
name,
|
|
28
28
|
initializer = noop,
|
|
29
29
|
cycleFunction,
|
|
30
|
-
computeProgress
|
|
30
|
+
computeProgress,
|
|
31
31
|
dependencies = [],
|
|
32
32
|
estimatedDuration = 1
|
|
33
33
|
}
|
|
34
34
|
) {
|
|
35
35
|
|
|
36
|
-
assert.
|
|
37
|
-
assert.
|
|
36
|
+
assert.isFunction(cycleFunction, 'cycleFunction');
|
|
37
|
+
assert.isNumber(estimatedDuration, 'estimatedDuration');
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
this.dependencies = dependencies;
|
|
@@ -59,7 +59,12 @@ class Task {
|
|
|
59
59
|
*/
|
|
60
60
|
this.initialize = initializer;
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
if (computeProgress !== undefined) {
|
|
63
|
+
|
|
64
|
+
// override progress function
|
|
65
|
+
this.computeProgress = computeProgress;
|
|
66
|
+
|
|
67
|
+
}
|
|
63
68
|
|
|
64
69
|
this.on = {
|
|
65
70
|
started: new Signal(),
|
|
@@ -87,6 +92,18 @@ class Task {
|
|
|
87
92
|
this.__executedCycleCount = 0;
|
|
88
93
|
}
|
|
89
94
|
|
|
95
|
+
computeProgress() {
|
|
96
|
+
|
|
97
|
+
const cycles = this.__executedCycleCount;
|
|
98
|
+
|
|
99
|
+
if (cycles === 0) {
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// inverse logarithmic progression, never reaches 1
|
|
104
|
+
return 1 - (1 / cycles);
|
|
105
|
+
}
|
|
106
|
+
|
|
90
107
|
/**
|
|
91
108
|
* Time in milliseconds that the task has been executing for, suspended time does not count
|
|
92
109
|
* @returns {number}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Task from "../Task.js";
|
|
2
|
+
import { TaskSignal } from "../TaskSignal.js";
|
|
3
|
+
import { assert } from "../../../assert.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {string} name
|
|
8
|
+
* @param {Iterator} iterator
|
|
9
|
+
* @param {TaskSignal.Continue|TaskSignal.Yield} [cycle_signal] what to signal at the end of each iteration, Continue will provide better throughput, whereas Yield will produce very low load on the CPU
|
|
10
|
+
* @returns {Task}
|
|
11
|
+
*/
|
|
12
|
+
export function iteratorTask(name, iterator, cycle_signal = TaskSignal.Continue) {
|
|
13
|
+
assert.defined(iterator, 'iterator');
|
|
14
|
+
assert.notNull(iterator, 'iterator');
|
|
15
|
+
assert.isFunction(iterator.next, 'iterator.next');
|
|
16
|
+
|
|
17
|
+
return new Task({
|
|
18
|
+
name,
|
|
19
|
+
cycleFunction() {
|
|
20
|
+
const next = iterator.next();
|
|
21
|
+
|
|
22
|
+
if (next.done) {
|
|
23
|
+
return TaskSignal.EndSuccess
|
|
24
|
+
} else {
|
|
25
|
+
return cycle_signal;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { BitSet } from "../../../core/binary/BitSet.js";
|
|
2
2
|
import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
queryBinaryNode_FrustumIntersections_Data
|
|
5
|
+
} from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
|
|
4
6
|
import Quaternion from "../../../core/geom/Quaternion.js";
|
|
5
7
|
import Vector3 from "../../../core/geom/Vector3.js";
|
|
6
8
|
import { compose_matrix4_array } from "../../../core/geom/3d/compose_matrix4_array.js";
|
|
@@ -30,6 +32,10 @@ export class ViewState {
|
|
|
30
32
|
* @type {InstancedMeshGroup}
|
|
31
33
|
*/
|
|
32
34
|
this.instances = new InstancedMeshGroup();
|
|
35
|
+
|
|
36
|
+
// make shrinking unlikely to prevent thrashing
|
|
37
|
+
this.instances.shrinkFactor = 0.4;
|
|
38
|
+
this.instances.shrinkConstant = 1024;
|
|
33
39
|
|
|
34
40
|
/**
|
|
35
41
|
*
|
|
@@ -20,6 +20,7 @@ import TaskState from "../../../../core/process/task/TaskState.js";
|
|
|
20
20
|
import {
|
|
21
21
|
bvh_query_user_data_overlaps_frustum
|
|
22
22
|
} from "../../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_frustum.js";
|
|
23
|
+
import { iteratorTask } from "../../../../core/process/task/util/iteratorTask.js";
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
/**
|
|
@@ -34,6 +35,31 @@ const scratch_point = new SurfacePoint3();
|
|
|
34
35
|
*/
|
|
35
36
|
const scratch_ray_0 = new Float32Array(6);
|
|
36
37
|
|
|
38
|
+
/**
|
|
39
|
+
*
|
|
40
|
+
* @param {ShadedGeometrySystem} system
|
|
41
|
+
* @return {Generator}
|
|
42
|
+
*/
|
|
43
|
+
function* maintenance_generator(system) {
|
|
44
|
+
while (true) { //infinite loop
|
|
45
|
+
|
|
46
|
+
const contexts = system.__view_contexts;
|
|
47
|
+
|
|
48
|
+
for (const [key, value] of contexts) {
|
|
49
|
+
|
|
50
|
+
if (value === undefined) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
yield* value.maintain();
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// a small break between re-runs
|
|
59
|
+
yield;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
37
63
|
export class ShadedGeometrySystem extends System {
|
|
38
64
|
/**
|
|
39
65
|
*
|
|
@@ -100,8 +126,15 @@ export class ShadedGeometrySystem extends System {
|
|
|
100
126
|
}
|
|
101
127
|
}
|
|
102
128
|
});
|
|
129
|
+
|
|
130
|
+
this.__maintenance_task = iteratorTask(
|
|
131
|
+
'Maintenance',
|
|
132
|
+
maintenance_generator(this),
|
|
133
|
+
TaskSignal.Yield
|
|
134
|
+
);
|
|
103
135
|
}
|
|
104
136
|
|
|
137
|
+
|
|
105
138
|
/**
|
|
106
139
|
*
|
|
107
140
|
* @returns {ExplicitBinaryBoundingVolumeHierarchy}
|
|
@@ -222,6 +255,9 @@ export class ShadedGeometrySystem extends System {
|
|
|
222
255
|
this.__optimization_task.state.set(TaskState.INITIAL);
|
|
223
256
|
engine.executor.run(this.__optimization_task);
|
|
224
257
|
|
|
258
|
+
this.__maintenance_task.state.set(TaskState.INITIAL);
|
|
259
|
+
engine.executor.run(this.__maintenance_task);
|
|
260
|
+
|
|
225
261
|
readyCallback();
|
|
226
262
|
}
|
|
227
263
|
|
|
@@ -233,6 +269,7 @@ export class ShadedGeometrySystem extends System {
|
|
|
233
269
|
const view_list = graphics.views.elements;
|
|
234
270
|
|
|
235
271
|
engine.executor.removeTask(this.__optimization_task);
|
|
272
|
+
engine.executor.removeTask(this.__maintenance_task);
|
|
236
273
|
|
|
237
274
|
view_list.forEach(this.__handle_view_removed, this);
|
|
238
275
|
view_list.on.added.remove(this.__handle_view_added, this);
|
|
@@ -30,6 +30,25 @@ export class ShadedGeometryRendererContext {
|
|
|
30
30
|
];
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Performs maintenance on the context, mainly to check the hash tables for changes
|
|
35
|
+
* @return {Generator}
|
|
36
|
+
*/
|
|
37
|
+
* maintain() {
|
|
38
|
+
const adapters = this.adapters;
|
|
39
|
+
for (let i = 0; i < adapters.length; i++) {
|
|
40
|
+
const adapter = adapters[i];
|
|
41
|
+
|
|
42
|
+
if (adapter === undefined) {
|
|
43
|
+
// adapter may disappear between invocations, since this is a continuation-type function
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// delegate to adapter's maintenance
|
|
48
|
+
yield* adapter.maintain();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
33
52
|
/**
|
|
34
53
|
*
|
|
35
54
|
* @param {number} index
|
|
@@ -2,8 +2,8 @@ import { array_quick_sort_by_comparator } from "../../../../../../core/collectio
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
*
|
|
5
|
-
* @param {THREE.Object3D} a
|
|
6
|
-
* @param {THREE.Object3D} b
|
|
5
|
+
* @param {THREE.Object3D|{material?:Material}} a
|
|
6
|
+
* @param {THREE.Object3D|{material?:Material}} b
|
|
7
7
|
* @returns {number}
|
|
8
8
|
*/
|
|
9
9
|
function compare_by_material(a, b) {
|
|
@@ -96,6 +96,15 @@ export class AbstractRenderAdapter {
|
|
|
96
96
|
this.__object_count = 0;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Used to perform infrequent housekeeping on the adapter's internal data structures
|
|
101
|
+
* Returns a maintenance sequence
|
|
102
|
+
* @return {Generator}
|
|
103
|
+
*/
|
|
104
|
+
* maintain() {
|
|
105
|
+
// override as necessary
|
|
106
|
+
}
|
|
107
|
+
|
|
99
108
|
/**
|
|
100
109
|
* @returns {THREE.Object3D[]}
|
|
101
110
|
*/
|
|
@@ -1076,12 +1076,24 @@ export class LightManager {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
|
|
1078
1078
|
/**
|
|
1079
|
-
*
|
|
1079
|
+
* Set resolution of the cluster texture, higher resolution will result in less load on the GPU, but will take up more RAM to represent and more time to build the clusters each frame
|
|
1080
1080
|
* @param {number} x
|
|
1081
1081
|
* @param {number} y
|
|
1082
1082
|
* @param {number} z
|
|
1083
1083
|
*/
|
|
1084
1084
|
setTileMapResolution(x, y, z) {
|
|
1085
|
+
assert.isNumber(x,'x');
|
|
1086
|
+
assert.isNonNegativeInteger(x,'x');
|
|
1087
|
+
assert.isFiniteNumber(x,'x');
|
|
1088
|
+
|
|
1089
|
+
assert.isNumber(y,'y');
|
|
1090
|
+
assert.isNonNegativeInteger(y,'y');
|
|
1091
|
+
assert.isFiniteNumber(y,'y');
|
|
1092
|
+
|
|
1093
|
+
assert.isNumber(z,'z');
|
|
1094
|
+
assert.isNonNegativeInteger(z,'z');
|
|
1095
|
+
assert.isFiniteNumber(z,'z');
|
|
1096
|
+
|
|
1085
1097
|
const r = this.__tiles_resolution;
|
|
1086
1098
|
|
|
1087
1099
|
if (x === r.x && y === r.y && z === r.z) {
|
|
@@ -9,6 +9,7 @@ export class ForwardPlusRenderingPlugin extends EnginePlugin {
|
|
|
9
9
|
super();
|
|
10
10
|
|
|
11
11
|
this.__light_manager = new LightManager();
|
|
12
|
+
lm.setTileMapResolution(16, 8, 8);
|
|
12
13
|
|
|
13
14
|
this.__resolution = new ThreeVector2();
|
|
14
15
|
|
|
@@ -19,6 +20,16 @@ export class ForwardPlusRenderingPlugin extends EnginePlugin {
|
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Set resolution of the cluster texture, higher resolution will result in less load on the GPU, but will take up more RAM to represent and more time to build the clusters each frame
|
|
25
|
+
* @param {number} x
|
|
26
|
+
* @param {number} y
|
|
27
|
+
* @param {number} z
|
|
28
|
+
*/
|
|
29
|
+
setClusterResolution(x, y, z) {
|
|
30
|
+
this.__light_manager.setTileMapResolution(x, y, z);
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
/**
|
|
23
34
|
*
|
|
24
35
|
* @param {CameraView} view
|
|
@@ -37,10 +48,6 @@ export class ForwardPlusRenderingPlugin extends EnginePlugin {
|
|
|
37
48
|
}
|
|
38
49
|
|
|
39
50
|
async startup() {
|
|
40
|
-
const lm = this.__light_manager;
|
|
41
|
-
|
|
42
|
-
lm.setTileMapResolution(16, 8, 8);
|
|
43
|
-
|
|
44
51
|
const graphics = this.engine.graphics;
|
|
45
52
|
|
|
46
53
|
graphics.getMaterialManager().addCompileStep(this.__material_transformer);
|
|
@@ -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",
|