@gg-web-engine/core 0.0.3 → 0.0.5
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/dist/2d/entities/controllers/entity-2d-positioning.animator.js +1 -1
- package/dist/2d/entities/gg-2d-entity.d.ts +3 -5
- package/dist/2d/entities/gg-2d-entity.js +2 -4
- package/dist/3d/entities/controllers/animators/camera-3d.animator.d.ts +17 -0
- package/dist/3d/entities/controllers/animators/camera-3d.animator.js +32 -0
- package/dist/3d/entities/controllers/animators/entity-3d-positioning.animator.d.ts +16 -0
- package/dist/3d/entities/controllers/animators/entity-3d-positioning.animator.js +26 -0
- package/dist/3d/entities/controllers/input/car-keyboard-handling.controller.d.ts +25 -0
- package/dist/3d/entities/controllers/input/car-keyboard-handling.controller.js +105 -0
- package/dist/3d/entities/controllers/input/free-camera.controller.d.ts +54 -0
- package/dist/3d/entities/controllers/input/free-camera.controller.js +102 -0
- package/dist/3d/entities/gg-3d-entity.d.ts +3 -5
- package/dist/3d/entities/gg-3d-entity.js +2 -4
- package/dist/3d/entities/gg-3d-map-graph.entity.d.ts +20 -6
- package/dist/3d/entities/gg-3d-map-graph.entity.js +21 -3
- package/dist/3d/inputs/car-keyboard.input.d.ts +25 -0
- package/dist/3d/inputs/car-keyboard.input.js +100 -0
- package/dist/3d/inputs/free-camera.input.d.ts +22 -0
- package/dist/3d/inputs/free-camera.input.js +80 -0
- package/dist/base/clock/global-clock.d.ts +4 -3
- package/dist/base/clock/global-clock.js +2 -2
- package/dist/base/clock/i-clock.d.ts +7 -0
- package/dist/base/clock/i-clock.js +2 -0
- package/dist/base/clock/pausable-clock.d.ts +25 -0
- package/dist/base/clock/pausable-clock.js +79 -0
- package/dist/base/data-structures/graph.d.ts +17 -1
- package/dist/base/data-structures/graph.js +20 -1
- package/dist/base/entities/base-gg-renderer.d.ts +8 -16
- package/dist/base/entities/base-gg-renderer.js +16 -32
- package/dist/base/entities/controllers/animation-mixer.d.ts +1 -8
- package/dist/base/entities/controllers/animation-mixer.js +2 -11
- package/dist/base/entities/gg-entity.d.ts +30 -0
- package/dist/base/entities/gg-entity.js +37 -2
- package/dist/base/entities/inline-controller.js +1 -6
- package/dist/base/entities/interfaces/i-tick-listener.d.ts +25 -1
- package/dist/base/entities/interfaces/i-tick-listener.js +17 -1
- package/dist/base/gg-viewport-manager.d.ts +1 -0
- package/dist/base/gg-viewport-manager.js +10 -0
- package/dist/base/gg-world.d.ts +9 -6
- package/dist/base/gg-world.js +45 -29
- package/dist/base/inputs/direction.keyboard-input.d.ts +41 -0
- package/dist/base/inputs/direction.keyboard-input.js +85 -0
- package/dist/base/inputs/input.d.ts +50 -0
- package/dist/base/inputs/input.js +80 -0
- package/dist/base/inputs/keyboard.input.d.ts +45 -0
- package/dist/base/inputs/keyboard.input.js +130 -0
- package/dist/base/inputs/mouse.input.d.ts +57 -0
- package/dist/base/inputs/mouse.input.js +81 -0
- package/dist/base/math/point2.d.ts +2 -0
- package/dist/base/math/point2.js +6 -0
- package/dist/base/math/point3.d.ts +2 -0
- package/dist/base/math/point3.js +6 -0
- package/dist/index.d.ts +10 -10
- package/dist/index.js +10 -10
- package/package.json +1 -1
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GgEntity = void 0;
|
|
3
|
+
exports.GgEntity = exports.GGTickOrder = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
|
+
/**
|
|
6
|
+
* Engine's default tick orders: the less value, the earlier tick will be run.
|
|
7
|
+
*/
|
|
8
|
+
var GGTickOrder;
|
|
9
|
+
(function (GGTickOrder) {
|
|
10
|
+
GGTickOrder[GGTickOrder["INPUT_CONTROLLERS"] = 0] = "INPUT_CONTROLLERS";
|
|
11
|
+
GGTickOrder[GGTickOrder["PHYSICS_SIMULATION"] = 200] = "PHYSICS_SIMULATION";
|
|
12
|
+
GGTickOrder[GGTickOrder["OBJECTS_BINDING"] = 400] = "OBJECTS_BINDING";
|
|
13
|
+
GGTickOrder[GGTickOrder["ANIMATION_MIXERS"] = 600] = "ANIMATION_MIXERS";
|
|
14
|
+
GGTickOrder[GGTickOrder["CONTROLLERS"] = 800] = "CONTROLLERS";
|
|
15
|
+
GGTickOrder[GGTickOrder["RENDERING"] = 1000] = "RENDERING";
|
|
16
|
+
GGTickOrder[GGTickOrder["POST_RENDERING"] = 1200] = "POST_RENDERING";
|
|
17
|
+
})(GGTickOrder = exports.GGTickOrder || (exports.GGTickOrder = {}));
|
|
5
18
|
class GgEntity {
|
|
6
19
|
constructor() {
|
|
20
|
+
/**
|
|
21
|
+
* will receive [elapsed time, delta] of each world clock tick
|
|
22
|
+
*/
|
|
23
|
+
this.tick$ = new rxjs_1.Subject();
|
|
24
|
+
/**
|
|
25
|
+
* a world reference, where this entity was added to
|
|
26
|
+
*/
|
|
7
27
|
this._world = null;
|
|
8
|
-
this._name = '';
|
|
28
|
+
this._name = '0x' + (GgEntity.default_name_counter++).toString(16);
|
|
29
|
+
/**
|
|
30
|
+
* The flag whether entity should listen to ticks. If set to false, ticks will not be propagated to this entity
|
|
31
|
+
* */
|
|
32
|
+
this._active = true;
|
|
9
33
|
this._children = [];
|
|
10
34
|
this._onSpawned$ = new rxjs_1.Subject();
|
|
11
35
|
this._onRemoved$ = new rxjs_1.Subject();
|
|
@@ -19,6 +43,12 @@ class GgEntity {
|
|
|
19
43
|
set name(value) {
|
|
20
44
|
this._name = value;
|
|
21
45
|
}
|
|
46
|
+
get active() {
|
|
47
|
+
return this._active;
|
|
48
|
+
}
|
|
49
|
+
set active(value) {
|
|
50
|
+
this._active = value;
|
|
51
|
+
}
|
|
22
52
|
addChildren(...entities) {
|
|
23
53
|
this._children.push(...entities);
|
|
24
54
|
if (this._world) {
|
|
@@ -52,11 +82,16 @@ class GgEntity {
|
|
|
52
82
|
}
|
|
53
83
|
// TODO add some flag to entity that it is disposed, and throw a normal error when trying to add such entity to world again
|
|
54
84
|
dispose() {
|
|
85
|
+
if (this.world) {
|
|
86
|
+
this.world.removeEntity(this);
|
|
87
|
+
}
|
|
55
88
|
this._onSpawned$.complete();
|
|
56
89
|
this._onRemoved$.complete();
|
|
90
|
+
this.tick$.complete();
|
|
57
91
|
for (const c of this._children) {
|
|
58
92
|
c.dispose();
|
|
59
93
|
}
|
|
60
94
|
}
|
|
61
95
|
}
|
|
62
96
|
exports.GgEntity = GgEntity;
|
|
97
|
+
GgEntity.default_name_counter = 0;
|
|
@@ -7,14 +7,9 @@ class InlineTickController extends gg_entity_1.GgEntity {
|
|
|
7
7
|
constructor(tickOrder) {
|
|
8
8
|
super();
|
|
9
9
|
this.tickOrder = tickOrder;
|
|
10
|
-
this.tick$ = new rxjs_1.Subject();
|
|
11
|
-
}
|
|
12
|
-
dispose() {
|
|
13
|
-
super.dispose();
|
|
14
|
-
this.tick$.complete();
|
|
15
10
|
}
|
|
16
11
|
}
|
|
17
|
-
function createInlineTickController(world, tickOrder =
|
|
12
|
+
function createInlineTickController(world, tickOrder = gg_entity_1.GGTickOrder.CONTROLLERS) {
|
|
18
13
|
const controller = new InlineTickController(tickOrder);
|
|
19
14
|
world.addEntity(controller);
|
|
20
15
|
return controller.tick$.pipe((0, rxjs_1.finalize)(() => {
|
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
2
|
import { GgEntity } from '../gg-entity';
|
|
3
|
+
/**
|
|
4
|
+
* Engine's default tick orders: the less value, the earlier tick will be run.
|
|
5
|
+
*/
|
|
6
|
+
export declare enum GGTickOrder {
|
|
7
|
+
INPUT_CONTROLLERS = 0,
|
|
8
|
+
PHYSICS_SIMULATION = 200,
|
|
9
|
+
OBJECTS_BINDING = 400,
|
|
10
|
+
ANIMATION_MIXERS = 600,
|
|
11
|
+
CONTROLLERS = 800,
|
|
12
|
+
RENDERING = 1000,
|
|
13
|
+
POST_RENDERING = 1200
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* An interface for world entities, which need to do some routine on each world clock tick
|
|
17
|
+
*/
|
|
3
18
|
export interface ITickListener {
|
|
19
|
+
/**
|
|
20
|
+
* will receive [elapsed time, delta] of each world clock tick
|
|
21
|
+
*/
|
|
4
22
|
tick$: Subject<[number, number]>;
|
|
5
|
-
|
|
23
|
+
/**
|
|
24
|
+
* the priority of ticker: the less value, the earlier tick will be run.
|
|
25
|
+
*/
|
|
26
|
+
readonly tickOrder: GGTickOrder | number;
|
|
6
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* A function which determines whether entity implements ITickListener interface
|
|
30
|
+
*/
|
|
7
31
|
export declare const isITickListener: (entity: GgEntity) => boolean;
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isITickListener = void 0;
|
|
3
|
+
exports.isITickListener = exports.GGTickOrder = void 0;
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
|
+
/**
|
|
6
|
+
* Engine's default tick orders: the less value, the earlier tick will be run.
|
|
7
|
+
*/
|
|
8
|
+
var GGTickOrder;
|
|
9
|
+
(function (GGTickOrder) {
|
|
10
|
+
GGTickOrder[GGTickOrder["INPUT_CONTROLLERS"] = 0] = "INPUT_CONTROLLERS";
|
|
11
|
+
GGTickOrder[GGTickOrder["PHYSICS_SIMULATION"] = 200] = "PHYSICS_SIMULATION";
|
|
12
|
+
GGTickOrder[GGTickOrder["OBJECTS_BINDING"] = 400] = "OBJECTS_BINDING";
|
|
13
|
+
GGTickOrder[GGTickOrder["ANIMATION_MIXERS"] = 600] = "ANIMATION_MIXERS";
|
|
14
|
+
GGTickOrder[GGTickOrder["CONTROLLERS"] = 800] = "CONTROLLERS";
|
|
15
|
+
GGTickOrder[GGTickOrder["RENDERING"] = 1000] = "RENDERING";
|
|
16
|
+
GGTickOrder[GGTickOrder["POST_RENDERING"] = 1200] = "POST_RENDERING";
|
|
17
|
+
})(GGTickOrder = exports.GGTickOrder || (exports.GGTickOrder = {}));
|
|
18
|
+
/**
|
|
19
|
+
* A function which determines whether entity implements ITickListener interface
|
|
20
|
+
*/
|
|
5
21
|
const isITickListener = entity => (entity === null || entity === void 0 ? void 0 : entity.tick$) instanceof rxjs_1.Subject;
|
|
6
22
|
exports.isITickListener = isITickListener;
|
|
@@ -14,5 +14,6 @@ export declare class GgViewportManager {
|
|
|
14
14
|
private getStageAsync;
|
|
15
15
|
createCanvas(zIndex: number): Promise<HTMLCanvasElement>;
|
|
16
16
|
registerCanvas(canvas: HTMLCanvasElement, zIndex: number): Promise<void>;
|
|
17
|
+
deregisterCanvas(canvas: HTMLCanvasElement): Promise<void>;
|
|
17
18
|
assignRendererToCanvas(renderer: BaseGgRenderer, canvas: HTMLCanvasElement): Promise<void>;
|
|
18
19
|
}
|
|
@@ -97,6 +97,16 @@ class GgViewportManager {
|
|
|
97
97
|
canvas.height = size.y;
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
|
+
deregisterCanvas(canvas) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
for (const index in this.canvases) {
|
|
103
|
+
if (this.canvases[index].canvas === canvas) {
|
|
104
|
+
delete this.canvases[index];
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
100
110
|
assignRendererToCanvas(renderer, canvas) {
|
|
101
111
|
return __awaiter(this, void 0, void 0, function* () {
|
|
102
112
|
if (!gg_viewport_1.GgViewport.instance.isActive) {
|
package/dist/base/gg-world.d.ts
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
|
+
import { PausableClock } from './clock/pausable-clock';
|
|
1
2
|
import { GgEntity } from './entities/gg-entity';
|
|
2
|
-
import { ITickListener } from './entities/interfaces/i-tick-listener';
|
|
3
3
|
import { GgPhysicsWorld } from './interfaces/gg-physics-world';
|
|
4
4
|
import { GgVisualScene } from './interfaces/gg-visual-scene';
|
|
5
|
-
import {
|
|
5
|
+
import { KeyboardInput } from './inputs/keyboard.input';
|
|
6
6
|
import { GgPositionableEntity } from './entities/gg-positionable-entity';
|
|
7
7
|
export declare abstract class GgWorld<D, R, V extends GgVisualScene<D, R> = GgVisualScene<D, R>, P extends GgPhysicsWorld<D, R> = GgPhysicsWorld<D, R>> {
|
|
8
8
|
readonly visualScene: V;
|
|
9
9
|
readonly physicsWorld: P;
|
|
10
10
|
protected readonly consoleEnabled: boolean;
|
|
11
|
-
|
|
12
|
-
readonly
|
|
13
|
-
get worldTime(): number;
|
|
11
|
+
readonly worldClock: PausableClock;
|
|
12
|
+
readonly keyboardInput: KeyboardInput;
|
|
14
13
|
readonly children: GgEntity[];
|
|
15
|
-
protected readonly tickListeners:
|
|
14
|
+
protected readonly tickListeners: GgEntity[];
|
|
16
15
|
constructor(visualScene: V, physicsWorld: P, consoleEnabled?: boolean);
|
|
17
16
|
init(): Promise<void>;
|
|
18
17
|
start(): void;
|
|
19
18
|
pauseWorld(): void;
|
|
20
19
|
resumeWorld(): void;
|
|
20
|
+
get isRunning(): boolean;
|
|
21
|
+
get isPaused(): boolean;
|
|
22
|
+
get worldTime(): number;
|
|
23
|
+
createClock(autoStart: boolean): PausableClock;
|
|
21
24
|
dispose(): void;
|
|
22
25
|
abstract addPrimitiveRigidBody(descr: any, position?: D, rotation?: R): GgPositionableEntity<D, R>;
|
|
23
26
|
addEntity(entity: GgEntity): void;
|
package/dist/base/gg-world.js
CHANGED
|
@@ -10,9 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.GgWorld = void 0;
|
|
13
|
-
const
|
|
13
|
+
const gg_entity_1 = require("./entities/gg-entity");
|
|
14
14
|
const gg_static_1 = require("./gg-static");
|
|
15
|
-
const
|
|
15
|
+
const keyboard_input_1 = require("./inputs/keyboard.input");
|
|
16
16
|
const rxjs_1 = require("rxjs");
|
|
17
17
|
const gg_console_ui_1 = require("./ui/gg-console.ui");
|
|
18
18
|
const gg_debugger_ui_1 = require("./ui/gg-debugger.ui");
|
|
@@ -22,18 +22,17 @@ class GgWorld {
|
|
|
22
22
|
this.visualScene = visualScene;
|
|
23
23
|
this.physicsWorld = physicsWorld;
|
|
24
24
|
this.consoleEnabled = consoleEnabled;
|
|
25
|
-
// world clock, can be paused/resumed. Stops when disposing world
|
|
26
25
|
this.worldClock = global_clock_1.GgGlobalClock.instance.createChildClock(false);
|
|
27
|
-
|
|
28
|
-
this.keyboardController = new keyboard_controller_1.KeyboardController();
|
|
26
|
+
this.keyboardInput = new keyboard_input_1.KeyboardInput();
|
|
29
27
|
this.children = [];
|
|
28
|
+
// the same as children, but sorted by tick order
|
|
30
29
|
this.tickListeners = [];
|
|
31
30
|
this.commands = {};
|
|
32
31
|
gg_static_1.GgStatic.instance.worlds.push(this);
|
|
33
32
|
gg_static_1.GgStatic.instance.selectedWorld = this;
|
|
34
|
-
this.
|
|
33
|
+
this.keyboardInput.start().then();
|
|
35
34
|
if (consoleEnabled) {
|
|
36
|
-
this.
|
|
35
|
+
this.keyboardInput
|
|
37
36
|
.bind('Backquote')
|
|
38
37
|
.pipe((0, rxjs_1.filter)(x => x))
|
|
39
38
|
.subscribe(() => {
|
|
@@ -76,23 +75,27 @@ class GgWorld {
|
|
|
76
75
|
}), 'args: [0 or 1]; turn on/off physics debug view. Default value is 0');
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
|
-
get worldTime() {
|
|
80
|
-
return this.worldClock.elapsedTime;
|
|
81
|
-
}
|
|
82
78
|
init() {
|
|
83
79
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
80
|
yield Promise.all([this.physicsWorld.init(), this.visualScene.init()]);
|
|
85
81
|
this.worldClock.tick$.subscribe(([elapsed, delta]) => {
|
|
86
|
-
let
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
let i = 0;
|
|
83
|
+
// emit tick to all entities with tick order < GGTickOrder.PHYSICS_SIMULATION
|
|
84
|
+
for (i; i < this.tickListeners.length; i++) {
|
|
85
|
+
if (this.tickListeners[i].tickOrder >= gg_entity_1.GGTickOrder.PHYSICS_SIMULATION) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (this.tickListeners[i].active) {
|
|
89
|
+
this.tickListeners[i].tick$.next([elapsed, delta]);
|
|
91
90
|
}
|
|
92
|
-
this.tickListeners[i].tick$.next([elapsed, delta]);
|
|
93
91
|
}
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
// run phycics simulation
|
|
93
|
+
this.physicsWorld.simulate(delta);
|
|
94
|
+
// emit tick to all remained entities
|
|
95
|
+
for (i; i < this.tickListeners.length; i++) {
|
|
96
|
+
if (this.tickListeners[i].active) {
|
|
97
|
+
this.tickListeners[i].tick$.next([elapsed, delta]);
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
});
|
|
98
101
|
});
|
|
@@ -106,9 +109,23 @@ class GgWorld {
|
|
|
106
109
|
resumeWorld() {
|
|
107
110
|
this.worldClock.resume();
|
|
108
111
|
}
|
|
112
|
+
get isRunning() {
|
|
113
|
+
return this.worldClock.isRunning;
|
|
114
|
+
}
|
|
115
|
+
get isPaused() {
|
|
116
|
+
return this.worldClock.isPaused;
|
|
117
|
+
}
|
|
118
|
+
get worldTime() {
|
|
119
|
+
return this.worldClock.elapsedTime;
|
|
120
|
+
}
|
|
121
|
+
createClock(autoStart) {
|
|
122
|
+
return this.worldClock.createChildClock(autoStart);
|
|
123
|
+
}
|
|
109
124
|
dispose() {
|
|
110
125
|
this.worldClock.stop();
|
|
126
|
+
this.keyboardInput.stop().then();
|
|
111
127
|
for (let i = 0; i < this.children.length; i++) {
|
|
128
|
+
this.children[i].onRemoved();
|
|
112
129
|
this.children[i].dispose();
|
|
113
130
|
}
|
|
114
131
|
this.children.splice(0, this.children.length);
|
|
@@ -118,24 +135,23 @@ class GgWorld {
|
|
|
118
135
|
}
|
|
119
136
|
addEntity(entity) {
|
|
120
137
|
if (!!entity.world) {
|
|
121
|
-
|
|
138
|
+
console.warn('Trying to spawn entity, which is already spawned');
|
|
139
|
+
return;
|
|
122
140
|
}
|
|
123
141
|
this.children.push(entity);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.tickListeners.sort((l1, l2) => l1.tickOrder - l2.tickOrder);
|
|
127
|
-
}
|
|
142
|
+
this.tickListeners.push(entity);
|
|
143
|
+
this.tickListeners.sort((l1, l2) => l1.tickOrder - l2.tickOrder);
|
|
128
144
|
entity.onSpawned(this);
|
|
129
145
|
}
|
|
130
146
|
removeEntity(entity, dispose = true) {
|
|
131
|
-
if (entity.world
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
147
|
+
if (entity.world) {
|
|
148
|
+
if (entity.world !== this) {
|
|
149
|
+
throw new Error('Entity is not a part of this world');
|
|
150
|
+
}
|
|
151
|
+
this.children.splice(this.children.findIndex(x => x === entity), 1);
|
|
136
152
|
this.tickListeners.splice(this.tickListeners.findIndex(x => x === entity), 1);
|
|
153
|
+
entity.onRemoved();
|
|
137
154
|
}
|
|
138
|
-
entity.onRemoved();
|
|
139
155
|
if (dispose) {
|
|
140
156
|
entity.dispose();
|
|
141
157
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { KeyboardInput } from './keyboard.input';
|
|
3
|
+
import { Input } from './input';
|
|
4
|
+
/**
|
|
5
|
+
* The type representing desired keymap for DirectionKeyboardInput
|
|
6
|
+
*/
|
|
7
|
+
export declare type DirectionKeyboardKeymap = 'arrows' | 'wasd' | 'wasd+arrows';
|
|
8
|
+
/**
|
|
9
|
+
* The type of DirectionKeyboardInput output value
|
|
10
|
+
*/
|
|
11
|
+
export declare type DirectionKeyboardOutput = {
|
|
12
|
+
upDown?: boolean;
|
|
13
|
+
leftRight?: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* An input class, responsible for handling direction keys and providing simple current direction observable.
|
|
17
|
+
* Supports two the most popular keyboard layouts: WASD and arrows.
|
|
18
|
+
*/
|
|
19
|
+
export declare class DirectionKeyboardInput extends Input {
|
|
20
|
+
protected readonly keyboard: KeyboardInput;
|
|
21
|
+
protected readonly keymap: DirectionKeyboardKeymap;
|
|
22
|
+
/**
|
|
23
|
+
* A subject that emits `DirectionKeyboardOutput` objects whenever the input changes.
|
|
24
|
+
*/
|
|
25
|
+
private _output$;
|
|
26
|
+
/**
|
|
27
|
+
* Returns an observable that emits `DirectionKeyboardOutput` objects whenever the input changes.
|
|
28
|
+
*/
|
|
29
|
+
get output$(): Observable<DirectionKeyboardOutput>;
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new instance of the `DirectionKeyboardInput` class.
|
|
32
|
+
*
|
|
33
|
+
* @param keyboard The `KeyboardInput` instance to use for input handling. You should probably use one from the World instance
|
|
34
|
+
* @param keymap The `DirectionKeyboardKeymap` defining which keys to listen for.
|
|
35
|
+
*/
|
|
36
|
+
constructor(keyboard: KeyboardInput, keymap: DirectionKeyboardKeymap);
|
|
37
|
+
/**
|
|
38
|
+
* Called when the input handling should start.
|
|
39
|
+
*/
|
|
40
|
+
protected startInternal(): Promise<void>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DirectionKeyboardInput = void 0;
|
|
13
|
+
const rxjs_1 = require("rxjs");
|
|
14
|
+
const operators_1 = require("rxjs/operators");
|
|
15
|
+
const input_1 = require("./input");
|
|
16
|
+
/**
|
|
17
|
+
* An input class, responsible for handling direction keys and providing simple current direction observable.
|
|
18
|
+
* Supports two the most popular keyboard layouts: WASD and arrows.
|
|
19
|
+
*/
|
|
20
|
+
class DirectionKeyboardInput extends input_1.Input {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new instance of the `DirectionKeyboardInput` class.
|
|
23
|
+
*
|
|
24
|
+
* @param keyboard The `KeyboardInput` instance to use for input handling. You should probably use one from the World instance
|
|
25
|
+
* @param keymap The `DirectionKeyboardKeymap` defining which keys to listen for.
|
|
26
|
+
*/
|
|
27
|
+
constructor(keyboard, keymap) {
|
|
28
|
+
super();
|
|
29
|
+
this.keyboard = keyboard;
|
|
30
|
+
this.keymap = keymap;
|
|
31
|
+
/**
|
|
32
|
+
* A subject that emits `DirectionKeyboardOutput` objects whenever the input changes.
|
|
33
|
+
*/
|
|
34
|
+
this._output$ = new rxjs_1.Subject();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Returns an observable that emits `DirectionKeyboardOutput` objects whenever the input changes.
|
|
38
|
+
*/
|
|
39
|
+
get output$() {
|
|
40
|
+
return this._output$.asObservable();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Called when the input handling should start.
|
|
44
|
+
*/
|
|
45
|
+
startInternal() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
// Initialize an array to hold the keys to listen for
|
|
48
|
+
const keys = [[], [], [], []];
|
|
49
|
+
// Add the "wasd" keys to the array if specified in the keymap
|
|
50
|
+
if (this.keymap.includes('wasd')) {
|
|
51
|
+
keys[0].push('KeyW');
|
|
52
|
+
keys[1].push('KeyA');
|
|
53
|
+
keys[2].push('KeyS');
|
|
54
|
+
keys[3].push('KeyD');
|
|
55
|
+
}
|
|
56
|
+
// Add the arrow keys to the array if specified in the keymap
|
|
57
|
+
if (this.keymap.includes('arrows')) {
|
|
58
|
+
keys[0].push('ArrowUp');
|
|
59
|
+
keys[1].push('ArrowLeft');
|
|
60
|
+
keys[2].push('ArrowDown');
|
|
61
|
+
keys[3].push('ArrowRight');
|
|
62
|
+
}
|
|
63
|
+
// Bind to the keyboard events for the specified keys
|
|
64
|
+
(0, rxjs_1.combineLatest)(keys.map(x => this.keyboard.bindMany(...x)))
|
|
65
|
+
.pipe(
|
|
66
|
+
// Stop listening when the `stop$` signal is received
|
|
67
|
+
(0, rxjs_1.takeUntil)(this.stop$),
|
|
68
|
+
// Map the key states to a `DirectionKeyboardOutput` object
|
|
69
|
+
(0, operators_1.map)(moveDirection => {
|
|
70
|
+
const result = {};
|
|
71
|
+
if (moveDirection.includes(true)) {
|
|
72
|
+
const [f, l, b, r] = moveDirection;
|
|
73
|
+
if (f != b)
|
|
74
|
+
result.upDown = f;
|
|
75
|
+
if (l != r)
|
|
76
|
+
result.leftRight = l;
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}))
|
|
80
|
+
// Emit the resulting `DirectionKeyboardOutput` object through the `_output$` subject
|
|
81
|
+
.subscribe(this._output$);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.DirectionKeyboardInput = DirectionKeyboardInput;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Subject } from 'rxjs';
|
|
2
|
+
/**
|
|
3
|
+
* An abstract class that provides basic implementation for Input class.
|
|
4
|
+
* Input is an entity for handling input from user, such as mouse movements, key presses etc.
|
|
5
|
+
* Inputs are not bound to World-s and working independently by design.
|
|
6
|
+
*
|
|
7
|
+
* TStartParams - A type representing an array of input arguments for the start method. Items are recommended to be named.
|
|
8
|
+
*
|
|
9
|
+
* TStopParams - A type representing an array of input arguments for the stop method. Items are recommended to be named.
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class Input<TStartParams extends any[] = [], TStopParams extends any[] = []> {
|
|
12
|
+
/**
|
|
13
|
+
* A private boolean that represents the running state of the process.
|
|
14
|
+
*/
|
|
15
|
+
private _running;
|
|
16
|
+
/**
|
|
17
|
+
* A protected subject that emits a void value when the process is stopped.
|
|
18
|
+
* Subclasses, when subscribing to something using rxjs, have to add pipe takeUntil(this.stop$),
|
|
19
|
+
* so everything will be unsubscribed when stopping input
|
|
20
|
+
*/
|
|
21
|
+
protected readonly stop$: Subject<void>;
|
|
22
|
+
/**
|
|
23
|
+
* A public getter that returns the running state of the Input.
|
|
24
|
+
*/
|
|
25
|
+
get running(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* An asynchronous method that starts the input. Do not override it
|
|
28
|
+
* @param args - An array of input arguments for the start method.
|
|
29
|
+
* @returns A Promise that resolves when the input is started.
|
|
30
|
+
*/
|
|
31
|
+
start(...args: TStartParams): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* An asynchronous method that stops the input. Do not override it
|
|
34
|
+
* @param args - An array of input arguments for the stop method.
|
|
35
|
+
* @returns A Promise that resolves when the input is stopped.
|
|
36
|
+
*/
|
|
37
|
+
stop(...args: TStopParams): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* An abstract asynchronous method that starts the input.
|
|
40
|
+
* @param args - An array of input arguments for the start method.
|
|
41
|
+
* @returns A Promise that resolves when the process is started.
|
|
42
|
+
*/
|
|
43
|
+
protected abstract startInternal(...args: TStartParams): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* An asynchronous method that stops the input.
|
|
46
|
+
* @param args - An array of input arguments for the stop method.
|
|
47
|
+
* @returns A Promise that resolves when the process is stopped.
|
|
48
|
+
*/
|
|
49
|
+
protected stopInternal(...args: TStopParams): Promise<void>;
|
|
50
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.Input = void 0;
|
|
13
|
+
const rxjs_1 = require("rxjs");
|
|
14
|
+
/**
|
|
15
|
+
* An abstract class that provides basic implementation for Input class.
|
|
16
|
+
* Input is an entity for handling input from user, such as mouse movements, key presses etc.
|
|
17
|
+
* Inputs are not bound to World-s and working independently by design.
|
|
18
|
+
*
|
|
19
|
+
* TStartParams - A type representing an array of input arguments for the start method. Items are recommended to be named.
|
|
20
|
+
*
|
|
21
|
+
* TStopParams - A type representing an array of input arguments for the stop method. Items are recommended to be named.
|
|
22
|
+
*/
|
|
23
|
+
class Input {
|
|
24
|
+
constructor() {
|
|
25
|
+
/**
|
|
26
|
+
* A private boolean that represents the running state of the process.
|
|
27
|
+
*/
|
|
28
|
+
this._running = false;
|
|
29
|
+
/**
|
|
30
|
+
* A protected subject that emits a void value when the process is stopped.
|
|
31
|
+
* Subclasses, when subscribing to something using rxjs, have to add pipe takeUntil(this.stop$),
|
|
32
|
+
* so everything will be unsubscribed when stopping input
|
|
33
|
+
*/
|
|
34
|
+
this.stop$ = new rxjs_1.Subject();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A public getter that returns the running state of the Input.
|
|
38
|
+
*/
|
|
39
|
+
get running() {
|
|
40
|
+
return this._running;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* An asynchronous method that starts the input. Do not override it
|
|
44
|
+
* @param args - An array of input arguments for the start method.
|
|
45
|
+
* @returns A Promise that resolves when the input is started.
|
|
46
|
+
*/
|
|
47
|
+
start(...args) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
if (this.running) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
yield this.startInternal(...args);
|
|
53
|
+
this._running = true;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* An asynchronous method that stops the input. Do not override it
|
|
58
|
+
* @param args - An array of input arguments for the stop method.
|
|
59
|
+
* @returns A Promise that resolves when the input is stopped.
|
|
60
|
+
*/
|
|
61
|
+
stop(...args) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
if (!this.running) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.stop$.next();
|
|
67
|
+
yield this.stopInternal(...args);
|
|
68
|
+
this._running = false;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* An asynchronous method that stops the input.
|
|
73
|
+
* @param args - An array of input arguments for the stop method.
|
|
74
|
+
* @returns A Promise that resolves when the process is stopped.
|
|
75
|
+
*/
|
|
76
|
+
stopInternal(...args) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () { });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.Input = Input;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Input } from './input';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
/**
|
|
4
|
+
* A main keyboard input: it does not have own key bindings, but provides an API to bind keys.
|
|
5
|
+
* It is responsible for listening key up/down events (when running!) and emit the events to subscribers.
|
|
6
|
+
* Every World entity has its own dedicated instance of Keyboard input, which is running only when the world is running
|
|
7
|
+
*/
|
|
8
|
+
export declare class KeyboardInput extends Input {
|
|
9
|
+
private bindings;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new instance of the `KeyboardInput` class.
|
|
12
|
+
*/
|
|
13
|
+
constructor();
|
|
14
|
+
protected startInternal(): Promise<void>;
|
|
15
|
+
protected stopInternal(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Creates an observable that emits a boolean whenever a key with the given code is pressed or released
|
|
18
|
+
* @param code The key code to bind the observable to
|
|
19
|
+
* @returns An observable that emits true when the key is pressed and false when it's released
|
|
20
|
+
*/
|
|
21
|
+
bind(code: string): Observable<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Creates an observable that emits a boolean indicating whether any of the keys with the given codes are pressed or released.
|
|
24
|
+
* Should be used when you have more than one keys, responsible for the same action.
|
|
25
|
+
* @param codes The key codes to bind the observable to
|
|
26
|
+
* @returns An observable that emits true when any of the keys are pressed and false when they're all released
|
|
27
|
+
*/
|
|
28
|
+
bindMany(...codes: string[]): Observable<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Emulates a key down event for the given key code
|
|
31
|
+
* @param code The key code to emulate
|
|
32
|
+
*/
|
|
33
|
+
emulateKeyDown(code: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Emulates a key up event for the given key code
|
|
36
|
+
* @param code The key code to emulate
|
|
37
|
+
*/
|
|
38
|
+
emulateKeyUp(code: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Emulates a key press event (down and up) for the given key code
|
|
41
|
+
* @param code The key code to emulate
|
|
42
|
+
*/
|
|
43
|
+
emulateKeyPress(code: string): void;
|
|
44
|
+
private handleKeys;
|
|
45
|
+
}
|