@gg-web-engine/core 0.0.2 → 0.0.4
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.d.ts +16 -0
- package/dist/2d/entities/controllers/entity-2d-positioning.animator.js +26 -0
- package/dist/2d/entities/gg-2d-entity.d.ts +12 -6
- package/dist/2d/entities/gg-2d-entity.js +52 -20
- package/dist/2d/gg-2d-world.d.ts +3 -0
- package/dist/2d/gg-2d-world.js +11 -0
- package/dist/3d/controllers/car-keyboard.controller.d.ts +10 -10
- package/dist/3d/controllers/car-keyboard.controller.js +21 -20
- package/dist/3d/controllers/free-camera.controller.d.ts +8 -8
- 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/camera-3d.animator.d.ts +17 -0
- package/dist/3d/entities/controllers/camera-3d.animator.js +32 -0
- package/dist/3d/entities/controllers/entity-3d-positioning.animator.d.ts +16 -0
- package/dist/3d/entities/controllers/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-camera.entity.d.ts +2 -0
- package/dist/3d/entities/gg-3d-camera.entity.js +6 -0
- package/dist/3d/entities/gg-3d-entity.d.ts +7 -6
- package/dist/3d/entities/gg-3d-entity.js +21 -13
- package/dist/3d/entities/gg-3d-map-graph.entity.d.ts +10 -10
- package/dist/3d/entities/gg-3d-map-graph.entity.js +2 -3
- package/dist/3d/entities/gg-3d-raycast-vehicle.entity.d.ts +6 -5
- package/dist/3d/gg-3d-world.d.ts +3 -0
- package/dist/3d/gg-3d-world.js +12 -0
- 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/clock.d.ts +25 -0
- package/dist/base/clock/clock.js +79 -0
- package/dist/base/clock/global-clock.d.ts +16 -0
- package/dist/base/clock/global-clock.js +36 -0
- 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/entities/base-gg-renderer.d.ts +3 -15
- package/dist/base/entities/base-gg-renderer.js +2 -30
- package/dist/base/entities/controllers/animation-mixer.d.ts +76 -0
- package/dist/base/entities/controllers/animation-mixer.js +143 -0
- package/dist/base/entities/gg-entity.d.ts +33 -1
- package/dist/base/entities/gg-entity.js +42 -1
- package/dist/base/entities/inline-controller.js +1 -7
- 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 +4 -0
- package/dist/base/gg-world.d.ts +11 -6
- package/dist/base/gg-world.js +50 -31
- 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/matrix4.js +3 -3
- package/dist/base/math/point2.js +1 -1
- package/dist/base/math/point3.js +1 -1
- package/dist/base/math/quaternion.d.ts +83 -9
- package/dist/base/math/quaternion.js +93 -10
- package/dist/base/models/points.d.ts +9 -9
- package/dist/index.d.ts +13 -9
- package/dist/index.js +13 -9
- package/package.json +1 -1
- package/.prettierrc +0 -8
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AnimationMixer = void 0;
|
|
4
|
+
const gg_entity_1 = require("../gg-entity");
|
|
5
|
+
const rxjs_1 = require("rxjs");
|
|
6
|
+
const operators_1 = require("rxjs/operators");
|
|
7
|
+
/**
|
|
8
|
+
* A class that performs property animations for a specific type `T` by using provided animation function.
|
|
9
|
+
* Supports smooth transition between animation function by interpolating between values over time.
|
|
10
|
+
* The current value of the animation can be subscribed to using the `subscribeToValue` property.
|
|
11
|
+
* The animation function can be changed with `transitAnimationFunction` or `transitFromStaticState`.
|
|
12
|
+
*/
|
|
13
|
+
class AnimationMixer extends gg_entity_1.GgEntity {
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new `AnimationMixer` entity.
|
|
16
|
+
* @param _animationFunction The initial motion control function that determines the animation.
|
|
17
|
+
* @param _lerp The linear interpolation between two values of type `T`.
|
|
18
|
+
*/
|
|
19
|
+
constructor(_animationFunction, _lerp = (a, b, t) => b) {
|
|
20
|
+
super();
|
|
21
|
+
this._animationFunction = _animationFunction;
|
|
22
|
+
this._lerp = _lerp;
|
|
23
|
+
this.tickOrder = gg_entity_1.GGTickOrder.ANIMATION_MIXERS;
|
|
24
|
+
/**
|
|
25
|
+
* A subject that emits the current value of the animation on every tick.
|
|
26
|
+
*/
|
|
27
|
+
this._value$ = new rxjs_1.Subject();
|
|
28
|
+
/**
|
|
29
|
+
* The current transition time reference `[elapsed, delta]` that interpolates between the old and new functions.
|
|
30
|
+
*/
|
|
31
|
+
this._currentTransitionK = [0, 0];
|
|
32
|
+
/**
|
|
33
|
+
* The current transition subscription, which is null if no transition is currently active.
|
|
34
|
+
*/
|
|
35
|
+
this._currentTransition = null;
|
|
36
|
+
/**
|
|
37
|
+
* A behavior subject that emits whether the animator is currently in a transition.
|
|
38
|
+
*/
|
|
39
|
+
this._isInTransition$ = new rxjs_1.BehaviorSubject(false);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Gets an observable of the current value of the animation.
|
|
43
|
+
*/
|
|
44
|
+
get value$() {
|
|
45
|
+
return this._value$.asObservable();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Gets the current motion control function that determines the animation.
|
|
49
|
+
*/
|
|
50
|
+
get animationFunction() {
|
|
51
|
+
return this._animationFunction;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Sets the current motion control function that determines the animation.
|
|
55
|
+
* @param value The new motion control function.
|
|
56
|
+
*/
|
|
57
|
+
set animationFunction(value) {
|
|
58
|
+
if (this.currentTransition) {
|
|
59
|
+
this.currentTransition = null;
|
|
60
|
+
}
|
|
61
|
+
this._animationFunction = value;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets a flag whether the animator is currently in a transition.
|
|
65
|
+
*/
|
|
66
|
+
get isInTransition() {
|
|
67
|
+
return this._isInTransition$.getValue();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Gets an observable that emits whether the animator is currently in a transition.
|
|
71
|
+
*/
|
|
72
|
+
get isInTransition$() {
|
|
73
|
+
return this._isInTransition$.pipe((0, rxjs_1.distinctUntilChanged)());
|
|
74
|
+
}
|
|
75
|
+
get currentTransition() {
|
|
76
|
+
return this._currentTransition;
|
|
77
|
+
}
|
|
78
|
+
set currentTransition(value) {
|
|
79
|
+
this._currentTransition = value;
|
|
80
|
+
this._isInTransition$.next(!!value);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Set output to static value and smoothly transit to new control function
|
|
84
|
+
* @param newFunc a new function
|
|
85
|
+
* @param transitionDuration a duration, after which new function will be fully controlling the output
|
|
86
|
+
* @param easing an easing function for transition
|
|
87
|
+
*/
|
|
88
|
+
transitFromStaticState(state, newFunc, transitionDuration, easing = x => x) {
|
|
89
|
+
this.animationFunction = () => state;
|
|
90
|
+
return this.transitAnimationFunction(newFunc, transitionDuration, easing);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Smoothly transit to new control function
|
|
94
|
+
* @param newFunc a new function
|
|
95
|
+
* @param transitionDuration a duration, after which new function will be fully controlling the output
|
|
96
|
+
* @param easing an easing function for transition
|
|
97
|
+
*/
|
|
98
|
+
transitAnimationFunction(newFunc, transitionDuration, easing = x => x) {
|
|
99
|
+
let oldAnimFunc;
|
|
100
|
+
if (this.currentTransition) {
|
|
101
|
+
// interrupt it by freezing K, so it will still work as binding, but do not animate further
|
|
102
|
+
this.currentTransition = null;
|
|
103
|
+
const oldTransitionAnimationFunction = this._animationFunction;
|
|
104
|
+
const oldTransitionLatestK = this._currentTransitionK;
|
|
105
|
+
oldAnimFunc = () => oldTransitionAnimationFunction(...oldTransitionLatestK);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
oldAnimFunc = this._animationFunction;
|
|
109
|
+
}
|
|
110
|
+
let k = 0;
|
|
111
|
+
this._animationFunction = (elapsed, delta) => this._lerp(oldAnimFunc(elapsed, delta), newFunc(elapsed, delta), k);
|
|
112
|
+
let startTime;
|
|
113
|
+
this.currentTransition = ([elapsed, delta]) => {
|
|
114
|
+
this._currentTransitionK = [elapsed, delta];
|
|
115
|
+
if (startTime === undefined) {
|
|
116
|
+
startTime = elapsed;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
k = (elapsed - startTime) / transitionDuration;
|
|
120
|
+
if (k >= 1) {
|
|
121
|
+
k = 1;
|
|
122
|
+
this.currentTransition = null;
|
|
123
|
+
this._animationFunction = newFunc;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
k = easing(k);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
onSpawned(world) {
|
|
132
|
+
super.onSpawned(world);
|
|
133
|
+
this.tick$
|
|
134
|
+
.pipe((0, rxjs_1.takeUntil)(this._onRemoved$), (0, operators_1.tap)(([elapsed, delta]) => this.currentTransition && this.currentTransition([elapsed, delta])), (0, operators_1.map)(([elapsed, delta]) => this._animationFunction(elapsed, delta)))
|
|
135
|
+
.subscribe(value => this._value$.next(value));
|
|
136
|
+
}
|
|
137
|
+
dispose() {
|
|
138
|
+
super.dispose();
|
|
139
|
+
this.tick$.complete();
|
|
140
|
+
this._value$.complete();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
exports.AnimationMixer = AnimationMixer;
|
|
@@ -1,13 +1,45 @@
|
|
|
1
1
|
import { GgWorld } from '../gg-world';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
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
|
+
}
|
|
2
15
|
export declare abstract class GgEntity {
|
|
3
|
-
|
|
16
|
+
/**
|
|
17
|
+
* will receive [elapsed time, delta] of each world clock tick
|
|
18
|
+
*/
|
|
19
|
+
readonly tick$: Subject<[number, number]>;
|
|
20
|
+
/**
|
|
21
|
+
* the priority of ticker: the less value, the earlier tick will be run.
|
|
22
|
+
*/
|
|
23
|
+
abstract readonly tickOrder: GGTickOrder | number;
|
|
24
|
+
/**
|
|
25
|
+
* a world reference, where this entity was added to
|
|
26
|
+
*/
|
|
4
27
|
protected _world: GgWorld<any, any> | null;
|
|
28
|
+
get world(): GgWorld<any, any> | null;
|
|
5
29
|
protected _name: string;
|
|
6
30
|
get name(): string;
|
|
7
31
|
set name(value: string);
|
|
32
|
+
/**
|
|
33
|
+
* The flag whether entity should listen to ticks. If set to false, ticks will not be propagated to this entity
|
|
34
|
+
* */
|
|
35
|
+
protected _active: boolean;
|
|
36
|
+
get active(): boolean;
|
|
37
|
+
set active(value: boolean);
|
|
8
38
|
protected _children: GgEntity[];
|
|
9
39
|
addChildren(...entities: GgEntity[]): void;
|
|
10
40
|
removeChildren(entities: GgEntity[], dispose?: boolean): void;
|
|
41
|
+
protected _onSpawned$: Subject<void>;
|
|
42
|
+
protected _onRemoved$: Subject<void>;
|
|
11
43
|
onSpawned(world: GgWorld<any, any>): void;
|
|
12
44
|
onRemoved(): void;
|
|
13
45
|
dispose(): void;
|
|
@@ -1,11 +1,38 @@
|
|
|
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
|
+
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 = {}));
|
|
4
18
|
class GgEntity {
|
|
5
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
|
+
*/
|
|
6
27
|
this._world = null;
|
|
7
28
|
this._name = '';
|
|
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;
|
|
8
33
|
this._children = [];
|
|
34
|
+
this._onSpawned$ = new rxjs_1.Subject();
|
|
35
|
+
this._onRemoved$ = new rxjs_1.Subject();
|
|
9
36
|
}
|
|
10
37
|
get world() {
|
|
11
38
|
return this._world;
|
|
@@ -16,6 +43,12 @@ class GgEntity {
|
|
|
16
43
|
set name(value) {
|
|
17
44
|
this._name = value;
|
|
18
45
|
}
|
|
46
|
+
get active() {
|
|
47
|
+
return this._active;
|
|
48
|
+
}
|
|
49
|
+
set active(value) {
|
|
50
|
+
this._active = value;
|
|
51
|
+
}
|
|
19
52
|
addChildren(...entities) {
|
|
20
53
|
this._children.push(...entities);
|
|
21
54
|
if (this._world) {
|
|
@@ -37,6 +70,7 @@ class GgEntity {
|
|
|
37
70
|
for (const c of this._children) {
|
|
38
71
|
world.addEntity(c);
|
|
39
72
|
}
|
|
73
|
+
this._onSpawned$.next();
|
|
40
74
|
}
|
|
41
75
|
onRemoved() {
|
|
42
76
|
const world = this._world;
|
|
@@ -44,9 +78,16 @@ class GgEntity {
|
|
|
44
78
|
for (const c of this._children) {
|
|
45
79
|
world.removeEntity(c);
|
|
46
80
|
}
|
|
81
|
+
this._onRemoved$.next();
|
|
47
82
|
}
|
|
48
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
|
|
49
84
|
dispose() {
|
|
85
|
+
if (this.world) {
|
|
86
|
+
this.world.removeEntity(this);
|
|
87
|
+
}
|
|
88
|
+
this._onSpawned$.complete();
|
|
89
|
+
this._onRemoved$.complete();
|
|
90
|
+
this.tick$.complete();
|
|
50
91
|
for (const c of this._children) {
|
|
51
92
|
c.dispose();
|
|
52
93
|
}
|
|
@@ -7,15 +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$.unsubscribe();
|
|
15
|
-
this.tick$.complete();
|
|
16
10
|
}
|
|
17
11
|
}
|
|
18
|
-
function createInlineTickController(world, tickOrder =
|
|
12
|
+
function createInlineTickController(world, tickOrder = gg_entity_1.GGTickOrder.CONTROLLERS) {
|
|
19
13
|
const controller = new InlineTickController(tickOrder);
|
|
20
14
|
world.addEntity(controller);
|
|
21
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;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Subject } from 'rxjs';
|
|
2
2
|
import { BaseGgRenderer } from './entities/base-gg-renderer';
|
|
3
|
+
export declare type CanvasAppDescr = {
|
|
4
|
+
canvas: HTMLCanvasElement;
|
|
5
|
+
renderer?: BaseGgRenderer;
|
|
6
|
+
};
|
|
3
7
|
export declare class GgViewportManager {
|
|
4
8
|
private static _instance;
|
|
5
9
|
static get instance(): GgViewportManager;
|
package/dist/base/gg-world.d.ts
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
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
|
+
import { GgPositionableEntity } from './entities/gg-positionable-entity';
|
|
6
7
|
export declare abstract class GgWorld<D, R, V extends GgVisualScene<D, R> = GgVisualScene<D, R>, P extends GgPhysicsWorld<D, R> = GgPhysicsWorld<D, R>> {
|
|
7
8
|
readonly visualScene: V;
|
|
8
9
|
readonly physicsWorld: P;
|
|
9
10
|
protected readonly consoleEnabled: boolean;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
readonly keyboardController: KeyboardController;
|
|
11
|
+
readonly worldClock: PausableClock;
|
|
12
|
+
readonly keyboardInput: KeyboardInput;
|
|
13
13
|
readonly children: GgEntity[];
|
|
14
|
-
protected readonly tickListeners:
|
|
14
|
+
protected readonly tickListeners: GgEntity[];
|
|
15
15
|
constructor(visualScene: V, physicsWorld: P, consoleEnabled?: boolean);
|
|
16
16
|
init(): Promise<void>;
|
|
17
17
|
start(): void;
|
|
18
18
|
pauseWorld(): void;
|
|
19
19
|
resumeWorld(): void;
|
|
20
|
+
get isRunning(): boolean;
|
|
21
|
+
get isPaused(): boolean;
|
|
22
|
+
get worldTime(): number;
|
|
23
|
+
createClock(autoStart: boolean): PausableClock;
|
|
20
24
|
dispose(): void;
|
|
25
|
+
abstract addPrimitiveRigidBody(descr: any, position?: D, rotation?: R): GgPositionableEntity<D, R>;
|
|
21
26
|
addEntity(entity: GgEntity): void;
|
|
22
27
|
removeEntity(entity: GgEntity, dispose?: boolean): void;
|
|
23
28
|
protected commands: {
|
package/dist/base/gg-world.js
CHANGED
|
@@ -10,32 +10,29 @@ 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
|
|
14
|
-
const i_tick_listener_1 = require("./entities/interfaces/i-tick-listener");
|
|
13
|
+
const gg_entity_1 = require("./entities/gg-entity");
|
|
15
14
|
const gg_static_1 = require("./gg-static");
|
|
16
|
-
const
|
|
15
|
+
const keyboard_input_1 = require("./inputs/keyboard.input");
|
|
17
16
|
const rxjs_1 = require("rxjs");
|
|
18
17
|
const gg_console_ui_1 = require("./ui/gg-console.ui");
|
|
19
18
|
const gg_debugger_ui_1 = require("./ui/gg-debugger.ui");
|
|
19
|
+
const global_clock_1 = require("./clock/global-clock");
|
|
20
20
|
class GgWorld {
|
|
21
21
|
constructor(visualScene, physicsWorld, consoleEnabled = false) {
|
|
22
22
|
this.visualScene = visualScene;
|
|
23
23
|
this.physicsWorld = physicsWorld;
|
|
24
24
|
this.consoleEnabled = consoleEnabled;
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
// world clock, can be paused/resumed. Stops when disposing world
|
|
28
|
-
this.worldClock = new clock_1.Clock(this.animationFrameClock.tick$);
|
|
29
|
-
// TODO consider adding mouse controller
|
|
30
|
-
this.keyboardController = new keyboard_controller_1.KeyboardController();
|
|
25
|
+
this.worldClock = global_clock_1.GgGlobalClock.instance.createChildClock(false);
|
|
26
|
+
this.keyboardInput = new keyboard_input_1.KeyboardInput();
|
|
31
27
|
this.children = [];
|
|
28
|
+
// the same as children, but sorted by tick order
|
|
32
29
|
this.tickListeners = [];
|
|
33
30
|
this.commands = {};
|
|
34
31
|
gg_static_1.GgStatic.instance.worlds.push(this);
|
|
35
32
|
gg_static_1.GgStatic.instance.selectedWorld = this;
|
|
36
|
-
this.
|
|
33
|
+
this.keyboardInput.start().then();
|
|
37
34
|
if (consoleEnabled) {
|
|
38
|
-
this.
|
|
35
|
+
this.keyboardInput
|
|
39
36
|
.bind('Backquote')
|
|
40
37
|
.pipe((0, rxjs_1.filter)(x => x))
|
|
41
38
|
.subscribe(() => {
|
|
@@ -82,16 +79,23 @@ class GgWorld {
|
|
|
82
79
|
return __awaiter(this, void 0, void 0, function* () {
|
|
83
80
|
yield Promise.all([this.physicsWorld.init(), this.visualScene.init()]);
|
|
84
81
|
this.worldClock.tick$.subscribe(([elapsed, delta]) => {
|
|
85
|
-
let
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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]);
|
|
90
90
|
}
|
|
91
|
-
this.tickListeners[i].tick$.next([elapsed, delta]);
|
|
92
91
|
}
|
|
93
|
-
|
|
94
|
-
|
|
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
|
+
}
|
|
95
99
|
}
|
|
96
100
|
});
|
|
97
101
|
});
|
|
@@ -103,11 +107,24 @@ class GgWorld {
|
|
|
103
107
|
this.worldClock.pause();
|
|
104
108
|
}
|
|
105
109
|
resumeWorld() {
|
|
106
|
-
this.worldClock.
|
|
110
|
+
this.worldClock.resume();
|
|
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);
|
|
107
123
|
}
|
|
108
124
|
dispose() {
|
|
109
125
|
this.worldClock.stop();
|
|
110
126
|
for (let i = 0; i < this.children.length; i++) {
|
|
127
|
+
this.children[i].onRemoved();
|
|
111
128
|
this.children[i].dispose();
|
|
112
129
|
}
|
|
113
130
|
this.children.splice(0, this.children.length);
|
|
@@ -117,24 +134,26 @@ class GgWorld {
|
|
|
117
134
|
}
|
|
118
135
|
addEntity(entity) {
|
|
119
136
|
if (!!entity.world) {
|
|
120
|
-
|
|
137
|
+
console.warn('Trying to spawn entity, which is already spawned');
|
|
138
|
+
return;
|
|
121
139
|
}
|
|
122
140
|
this.children.push(entity);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
this.tickListeners.sort((l1, l2) => l1.tickOrder - l2.tickOrder);
|
|
126
|
-
}
|
|
141
|
+
this.tickListeners.push(entity);
|
|
142
|
+
this.tickListeners.sort((l1, l2) => l1.tickOrder - l2.tickOrder);
|
|
127
143
|
entity.onSpawned(this);
|
|
128
144
|
}
|
|
129
145
|
removeEntity(entity, dispose = true) {
|
|
130
|
-
if (entity.world
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
if (entity.world) {
|
|
147
|
+
if (entity.world !== this) {
|
|
148
|
+
throw new Error('Entity is not a part of this world');
|
|
149
|
+
}
|
|
150
|
+
this.children.splice(this.children.findIndex(x => x === entity), 1);
|
|
135
151
|
this.tickListeners.splice(this.tickListeners.findIndex(x => x === entity), 1);
|
|
152
|
+
entity.onRemoved();
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.warn('Trying to remove entity, which is not spawned');
|
|
136
156
|
}
|
|
137
|
-
entity.onRemoved();
|
|
138
157
|
if (dispose) {
|
|
139
158
|
entity.dispose();
|
|
140
159
|
}
|
|
@@ -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;
|