@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.
Files changed (55) hide show
  1. package/dist/2d/entities/controllers/entity-2d-positioning.animator.js +1 -1
  2. package/dist/2d/entities/gg-2d-entity.d.ts +3 -5
  3. package/dist/2d/entities/gg-2d-entity.js +2 -4
  4. package/dist/3d/entities/controllers/animators/camera-3d.animator.d.ts +17 -0
  5. package/dist/3d/entities/controllers/animators/camera-3d.animator.js +32 -0
  6. package/dist/3d/entities/controllers/animators/entity-3d-positioning.animator.d.ts +16 -0
  7. package/dist/3d/entities/controllers/animators/entity-3d-positioning.animator.js +26 -0
  8. package/dist/3d/entities/controllers/input/car-keyboard-handling.controller.d.ts +25 -0
  9. package/dist/3d/entities/controllers/input/car-keyboard-handling.controller.js +105 -0
  10. package/dist/3d/entities/controllers/input/free-camera.controller.d.ts +54 -0
  11. package/dist/3d/entities/controllers/input/free-camera.controller.js +102 -0
  12. package/dist/3d/entities/gg-3d-entity.d.ts +3 -5
  13. package/dist/3d/entities/gg-3d-entity.js +2 -4
  14. package/dist/3d/entities/gg-3d-map-graph.entity.d.ts +20 -6
  15. package/dist/3d/entities/gg-3d-map-graph.entity.js +21 -3
  16. package/dist/3d/inputs/car-keyboard.input.d.ts +25 -0
  17. package/dist/3d/inputs/car-keyboard.input.js +100 -0
  18. package/dist/3d/inputs/free-camera.input.d.ts +22 -0
  19. package/dist/3d/inputs/free-camera.input.js +80 -0
  20. package/dist/base/clock/global-clock.d.ts +4 -3
  21. package/dist/base/clock/global-clock.js +2 -2
  22. package/dist/base/clock/i-clock.d.ts +7 -0
  23. package/dist/base/clock/i-clock.js +2 -0
  24. package/dist/base/clock/pausable-clock.d.ts +25 -0
  25. package/dist/base/clock/pausable-clock.js +79 -0
  26. package/dist/base/data-structures/graph.d.ts +17 -1
  27. package/dist/base/data-structures/graph.js +20 -1
  28. package/dist/base/entities/base-gg-renderer.d.ts +8 -16
  29. package/dist/base/entities/base-gg-renderer.js +16 -32
  30. package/dist/base/entities/controllers/animation-mixer.d.ts +1 -8
  31. package/dist/base/entities/controllers/animation-mixer.js +2 -11
  32. package/dist/base/entities/gg-entity.d.ts +30 -0
  33. package/dist/base/entities/gg-entity.js +37 -2
  34. package/dist/base/entities/inline-controller.js +1 -6
  35. package/dist/base/entities/interfaces/i-tick-listener.d.ts +25 -1
  36. package/dist/base/entities/interfaces/i-tick-listener.js +17 -1
  37. package/dist/base/gg-viewport-manager.d.ts +1 -0
  38. package/dist/base/gg-viewport-manager.js +10 -0
  39. package/dist/base/gg-world.d.ts +9 -6
  40. package/dist/base/gg-world.js +45 -29
  41. package/dist/base/inputs/direction.keyboard-input.d.ts +41 -0
  42. package/dist/base/inputs/direction.keyboard-input.js +85 -0
  43. package/dist/base/inputs/input.d.ts +50 -0
  44. package/dist/base/inputs/input.js +80 -0
  45. package/dist/base/inputs/keyboard.input.d.ts +45 -0
  46. package/dist/base/inputs/keyboard.input.js +130 -0
  47. package/dist/base/inputs/mouse.input.d.ts +57 -0
  48. package/dist/base/inputs/mouse.input.js +81 -0
  49. package/dist/base/math/point2.d.ts +2 -0
  50. package/dist/base/math/point2.js +6 -0
  51. package/dist/base/math/point3.d.ts +2 -0
  52. package/dist/base/math/point3.js +6 -0
  53. package/dist/index.d.ts +10 -10
  54. package/dist/index.js +10 -10
  55. package/package.json +1 -1
@@ -16,7 +16,7 @@ class Entity2dPositioningAnimator extends animation_mixer_1.AnimationMixer {
16
16
  }
17
17
  onSpawned(world) {
18
18
  super.onSpawned(world);
19
- this.value$.pipe((0, rxjs_1.takeUntil)(this.removed$)).subscribe(value => this.applyPositioning(value));
19
+ this.value$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(value => this.applyPositioning(value));
20
20
  }
21
21
  applyPositioning(value) {
22
22
  this.entity.position = value.position;
@@ -1,14 +1,12 @@
1
- import { Subject } from 'rxjs';
2
1
  import { GgPositionable2dEntity } from './gg-positionable-2d-entity';
3
- import { ITickListener } from '../../base/entities/interfaces/i-tick-listener';
4
2
  import { Point2 } from '../../base/models/points';
5
3
  import { IGg2dBody, IGg2dObject } from '../interfaces';
6
4
  import { Gg2dWorld } from '../gg-2d-world';
7
- export declare class Gg2dEntity extends GgPositionable2dEntity implements ITickListener {
5
+ import { GGTickOrder } from '../../base/entities/gg-entity';
6
+ export declare class Gg2dEntity extends GgPositionable2dEntity {
8
7
  readonly object2D: IGg2dObject | null;
9
8
  readonly objectBody: IGg2dBody | null;
10
- readonly tick$: Subject<[number, number]>;
11
- readonly tickOrder = 750;
9
+ readonly tickOrder = GGTickOrder.OBJECTS_BINDING;
12
10
  get position(): Point2;
13
11
  set position(value: Point2);
14
12
  get rotation(): number;
@@ -1,15 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Gg2dEntity = void 0;
4
- const rxjs_1 = require("rxjs");
5
4
  const gg_positionable_2d_entity_1 = require("./gg-positionable-2d-entity");
5
+ const gg_entity_1 = require("../../base/entities/gg-entity");
6
6
  class Gg2dEntity extends gg_positionable_2d_entity_1.GgPositionable2dEntity {
7
7
  constructor(object2D, objectBody) {
8
8
  super();
9
9
  this.object2D = object2D;
10
10
  this.objectBody = objectBody;
11
- this.tick$ = new rxjs_1.Subject();
12
- this.tickOrder = 750;
11
+ this.tickOrder = gg_entity_1.GGTickOrder.OBJECTS_BINDING;
13
12
  if (objectBody) {
14
13
  objectBody.entity = this;
15
14
  this.tick$.subscribe(() => {
@@ -105,7 +104,6 @@ class Gg2dEntity extends gg_positionable_2d_entity_1.GgPositionable2dEntity {
105
104
  }
106
105
  dispose() {
107
106
  super.dispose();
108
- this.tick$.unsubscribe();
109
107
  if (this.object2D) {
110
108
  this.object2D.dispose();
111
109
  }
@@ -0,0 +1,17 @@
1
+ import { AnimationFunction, AnimationMixer } from '../../../../base/entities/controllers/animation-mixer';
2
+ import { Point3 } from '../../../../base/models/points';
3
+ import { Gg3dWorld } from '../../../gg-3d-world';
4
+ import { Gg3dCameraEntity } from '../../gg-3d-camera.entity';
5
+ export declare type Camera3dAnimationArgs = {
6
+ position: Point3;
7
+ target: Point3;
8
+ up?: Point3;
9
+ fov?: number;
10
+ };
11
+ export declare class Camera3dAnimator extends AnimationMixer<Camera3dAnimationArgs> {
12
+ entity: Gg3dCameraEntity;
13
+ protected _animationFunction: AnimationFunction<Camera3dAnimationArgs>;
14
+ constructor(entity: Gg3dCameraEntity, _animationFunction: AnimationFunction<Camera3dAnimationArgs>);
15
+ onSpawned(world: Gg3dWorld): void;
16
+ protected applyPositioning(value: Camera3dAnimationArgs): void;
17
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Camera3dAnimator = void 0;
4
+ const animation_mixer_1 = require("../../../../base/entities/controllers/animation-mixer");
5
+ const point3_1 = require("../../../../base/math/point3");
6
+ const quaternion_1 = require("../../../../base/math/quaternion");
7
+ const rxjs_1 = require("rxjs");
8
+ const numbers_1 = require("../../../../base/math/numbers");
9
+ const defaultUp = { x: 0, y: 0, z: 1 };
10
+ const defaultFov = 65;
11
+ class Camera3dAnimator extends animation_mixer_1.AnimationMixer {
12
+ constructor(entity, _animationFunction) {
13
+ super(_animationFunction, (a, b, t) => ({
14
+ position: point3_1.Pnt3.lerp(a.position, b.position, t),
15
+ target: point3_1.Pnt3.lerp(a.target, b.target, t),
16
+ up: point3_1.Pnt3.lerp(a.up || defaultUp, b.up || defaultUp, t),
17
+ fov: (0, numbers_1.lerpNumber)(a.fov || defaultFov, b.fov || defaultFov, t),
18
+ }));
19
+ this.entity = entity;
20
+ this._animationFunction = _animationFunction;
21
+ }
22
+ onSpawned(world) {
23
+ super.onSpawned(world);
24
+ this.value$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(value => this.applyPositioning(value));
25
+ }
26
+ applyPositioning(value) {
27
+ this.entity.position = value.position;
28
+ this.entity.rotation = quaternion_1.Qtrn.lookAt(value.position, value.target, value.up || defaultUp);
29
+ this.entity.fov = value.fov || defaultFov;
30
+ }
31
+ }
32
+ exports.Camera3dAnimator = Camera3dAnimator;
@@ -0,0 +1,16 @@
1
+ import { Gg3dEntity } from '../../gg-3d-entity';
2
+ import { AnimationFunction, AnimationMixer } from '../../../../base/entities/controllers/animation-mixer';
3
+ import { Point3, Point4 } from '../../../../base/models/points';
4
+ import { Gg3dWorld } from '../../../gg-3d-world';
5
+ declare type Positioning3d = {
6
+ position: Point3;
7
+ rotation: Point4;
8
+ };
9
+ export declare class Entity3dPositioningAnimator<T extends Gg3dEntity = Gg3dEntity> extends AnimationMixer<Positioning3d> {
10
+ entity: T;
11
+ protected _animationFunction: AnimationFunction<Positioning3d>;
12
+ constructor(entity: T, _animationFunction: AnimationFunction<Positioning3d>);
13
+ onSpawned(world: Gg3dWorld): void;
14
+ protected applyPositioning(value: Positioning3d): void;
15
+ }
16
+ export {};
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Entity3dPositioningAnimator = void 0;
4
+ const animation_mixer_1 = require("../../../../base/entities/controllers/animation-mixer");
5
+ const point3_1 = require("../../../../base/math/point3");
6
+ const quaternion_1 = require("../../../../base/math/quaternion");
7
+ const rxjs_1 = require("rxjs");
8
+ class Entity3dPositioningAnimator extends animation_mixer_1.AnimationMixer {
9
+ constructor(entity, _animationFunction) {
10
+ super(_animationFunction, (a, b, t) => ({
11
+ position: point3_1.Pnt3.lerp(a.position, b.position, t),
12
+ rotation: quaternion_1.Qtrn.slerp(a.rotation, b.rotation, t),
13
+ }));
14
+ this.entity = entity;
15
+ this._animationFunction = _animationFunction;
16
+ }
17
+ onSpawned(world) {
18
+ super.onSpawned(world);
19
+ this.value$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(value => this.applyPositioning(value));
20
+ }
21
+ applyPositioning(value) {
22
+ this.entity.position = value.position;
23
+ this.entity.rotation = value.rotation;
24
+ }
25
+ }
26
+ exports.Entity3dPositioningAnimator = Entity3dPositioningAnimator;
@@ -0,0 +1,25 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { KeyboardInput } from '../../../../base/inputs/keyboard.input';
3
+ import { Gg3dRaycastVehicleEntity } from '../../gg-3d-raycast-vehicle.entity';
4
+ import { DirectionKeyboardInput, DirectionKeyboardKeymap } from '../../../../base/inputs/direction.keyboard-input';
5
+ import { GgEntity, GGTickOrder } from '../../../../base/entities/gg-entity';
6
+ import { GgWorld } from '../../../../base/gg-world';
7
+ export declare type CarKeyboardControllerOptions = {
8
+ keymap: DirectionKeyboardKeymap;
9
+ gearUpDownKeys: [string, string];
10
+ };
11
+ export declare class CarKeyboardHandlingController extends GgEntity {
12
+ protected readonly keyboard: KeyboardInput;
13
+ car: Gg3dRaycastVehicleEntity | null;
14
+ protected readonly options: CarKeyboardControllerOptions;
15
+ readonly tickOrder = GGTickOrder.INPUT_CONTROLLERS;
16
+ protected readonly directionsInput: DirectionKeyboardInput;
17
+ protected readonly x$: BehaviorSubject<number>;
18
+ protected readonly y$: BehaviorSubject<number>;
19
+ protected lastX: number;
20
+ switchingGearsEnabled: boolean;
21
+ pairTickerPipe: import("rxjs").UnaryFunction<import("rxjs").Observable<number>, import("rxjs").Observable<number>>;
22
+ constructor(keyboard: KeyboardInput, car: Gg3dRaycastVehicleEntity | null, options?: CarKeyboardControllerOptions);
23
+ onSpawned(world: GgWorld<any, any>): Promise<void>;
24
+ onRemoved(): Promise<void>;
25
+ }
@@ -0,0 +1,105 @@
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.CarKeyboardHandlingController = void 0;
13
+ const rxjs_1 = require("rxjs");
14
+ const operators_1 = require("rxjs/operators");
15
+ const direction_keyboard_input_1 = require("../../../../base/inputs/direction.keyboard-input");
16
+ const gg_entity_1 = require("../../../../base/entities/gg-entity");
17
+ // TODO pass as settings
18
+ // TODO smooth y?
19
+ const TICKER_INTERVAL = 16;
20
+ const TICKER_MAX_STEPS = 10;
21
+ class CarKeyboardHandlingController extends gg_entity_1.GgEntity {
22
+ constructor(keyboard, car, options = { keymap: 'arrows', gearUpDownKeys: ['KeyA', 'KeyZ'] }) {
23
+ super();
24
+ this.keyboard = keyboard;
25
+ this.car = car;
26
+ this.options = options;
27
+ this.tickOrder = gg_entity_1.GGTickOrder.INPUT_CONTROLLERS;
28
+ // emits values -1 - 1; -1 = full turn left; 1 = full turn right
29
+ this.x$ = new rxjs_1.BehaviorSubject(0);
30
+ // emits values -1 - 1; -1 = full brake; 1 = full acceleration
31
+ this.y$ = new rxjs_1.BehaviorSubject(0);
32
+ this.lastX = 0;
33
+ this.switchingGearsEnabled = true;
34
+ this.pairTickerPipe = (0, rxjs_1.pipe)((0, operators_1.startWith)(0), (0, operators_1.pairwise)(), (0, operators_1.map)(([beforeValue, afterValue]) => [this.lastX, afterValue]), (0, operators_1.switchMap)(([beforeValue, afterValue]) => (0, rxjs_1.interval)(TICKER_INTERVAL).pipe((0, operators_1.take)(TICKER_MAX_STEPS), (0, operators_1.map)(count => ++count), (0, operators_1.map)(count => beforeValue * ((TICKER_MAX_STEPS - count) / TICKER_MAX_STEPS) + afterValue * (count / TICKER_MAX_STEPS)), (0, operators_1.tap)(x => {
35
+ this.lastX = x;
36
+ }))));
37
+ this.directionsInput = new direction_keyboard_input_1.DirectionKeyboardInput(keyboard, options.keymap);
38
+ }
39
+ onSpawned(world) {
40
+ const _super = Object.create(null, {
41
+ onSpawned: { get: () => super.onSpawned }
42
+ });
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ _super.onSpawned.call(this, world);
45
+ let moveDirection = {};
46
+ this.keyboard
47
+ .bind(this.options.gearUpDownKeys[0])
48
+ .pipe((0, rxjs_1.takeUntil)(this._onRemoved$), (0, rxjs_1.filter)(x => this.switchingGearsEnabled && !!x))
49
+ .subscribe(() => {
50
+ if (this.car && (!this.car.carProperties.transmission.isAuto || this.car.gear <= 0)) {
51
+ this.car.gear++;
52
+ }
53
+ });
54
+ this.keyboard
55
+ .bind(this.options.gearUpDownKeys[1])
56
+ .pipe((0, rxjs_1.takeUntil)(this._onRemoved$), (0, rxjs_1.filter)(x => this.switchingGearsEnabled && !!x))
57
+ .subscribe(() => {
58
+ if (this.car) {
59
+ if (this.car.carProperties.transmission.isAuto && this.car.gear > 1) {
60
+ this.car.gear = 0;
61
+ }
62
+ else {
63
+ this.car.gear--;
64
+ }
65
+ }
66
+ });
67
+ this.directionsInput.output$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(d => {
68
+ moveDirection = d;
69
+ });
70
+ this.tick$
71
+ .pipe((0, rxjs_1.takeUntil)(this._onRemoved$), (0, operators_1.map)(() => {
72
+ const direction = [0, 0];
73
+ if (moveDirection.leftRight !== undefined)
74
+ direction[0] = moveDirection.leftRight ? -1 : 1;
75
+ if (moveDirection.upDown !== undefined)
76
+ direction[1] = moveDirection.upDown ? 1 : -1;
77
+ return direction;
78
+ }))
79
+ .subscribe(([x, y]) => {
80
+ this.x$.next(x);
81
+ this.y$.next(y);
82
+ });
83
+ (0, rxjs_1.combineLatest)([
84
+ this.x$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$), (0, operators_1.distinctUntilChanged)(), this.pairTickerPipe),
85
+ this.y$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$), (0, operators_1.distinctUntilChanged)()),
86
+ ]).subscribe(([x, y]) => {
87
+ if (this.car) {
88
+ this.car.setXAxisControlValue(x);
89
+ this.car.setYAxisControlValue(y);
90
+ }
91
+ });
92
+ yield this.directionsInput.start();
93
+ });
94
+ }
95
+ onRemoved() {
96
+ const _super = Object.create(null, {
97
+ onRemoved: { get: () => super.onRemoved }
98
+ });
99
+ return __awaiter(this, void 0, void 0, function* () {
100
+ yield _super.onRemoved.call(this);
101
+ yield this.directionsInput.stop();
102
+ });
103
+ }
104
+ }
105
+ exports.CarKeyboardHandlingController = CarKeyboardHandlingController;
@@ -0,0 +1,54 @@
1
+ import { MouseInput, MouseInputOptions } from '../../../../base/inputs/mouse.input';
2
+ import { Gg3dCameraEntity } from '../../gg-3d-camera.entity';
3
+ import { KeyboardInput } from '../../../../base/inputs/keyboard.input';
4
+ import { DirectionKeyboardInput, DirectionKeyboardKeymap } from '../../../../base/inputs/direction.keyboard-input';
5
+ import { GgEntity, GGTickOrder } from '../../../../base/entities/gg-entity';
6
+ import { GgWorld } from '../../../../base/gg-world';
7
+ /**
8
+ * Options for configuring a FreeCameraInput controller.
9
+ */
10
+ export declare type FreeCameraControllerOptions = {
11
+ /**
12
+ * A keymap for controlling camera movement, where each key corresponds to a movement direction.
13
+ */
14
+ keymap: DirectionKeyboardKeymap;
15
+ /**
16
+ * Options for configuring camera movement.
17
+ */
18
+ movementOptions: {
19
+ /**
20
+ * The speed of camera movement.
21
+ */
22
+ speed: number;
23
+ };
24
+ /**
25
+ * Options for configuring mouse input.
26
+ */
27
+ mouseOptions: MouseInputOptions;
28
+ };
29
+ /**
30
+ * A controller for a free-moving camera.
31
+ */
32
+ export declare class FreeCameraController extends GgEntity {
33
+ protected readonly keyboard: KeyboardInput;
34
+ protected readonly camera: Gg3dCameraEntity;
35
+ protected readonly options: FreeCameraControllerOptions;
36
+ readonly tickOrder = GGTickOrder.INPUT_CONTROLLERS;
37
+ /**
38
+ * The mouse input controller used for camera rotation.
39
+ */
40
+ protected readonly mouseInput: MouseInput;
41
+ /**
42
+ * The keyboard input controller used for camera movement.
43
+ */
44
+ protected readonly directionsInput: DirectionKeyboardInput;
45
+ /**
46
+ * Creates a new FreeCameraInput instance.
47
+ * @param keyboard The keyboard input controller to use for camera movement.
48
+ * @param camera The camera entity to control.
49
+ * @param options Optional configuration options for the controller.
50
+ */
51
+ constructor(keyboard: KeyboardInput, camera: Gg3dCameraEntity, options?: FreeCameraControllerOptions);
52
+ onSpawned(world: GgWorld<any, any>): Promise<void>;
53
+ onRemoved(): Promise<void>;
54
+ }
@@ -0,0 +1,102 @@
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.FreeCameraController = void 0;
13
+ const rxjs_1 = require("rxjs");
14
+ const mouse_input_1 = require("../../../../base/inputs/mouse.input");
15
+ const point3_1 = require("../../../../base/math/point3");
16
+ const point2_1 = require("../../../../base/math/point2");
17
+ const quaternion_1 = require("../../../../base/math/quaternion");
18
+ const direction_keyboard_input_1 = require("../../../../base/inputs/direction.keyboard-input");
19
+ const gg_entity_1 = require("../../../../base/entities/gg-entity");
20
+ /**
21
+ * A controller for a free-moving camera.
22
+ */
23
+ class FreeCameraController extends gg_entity_1.GgEntity {
24
+ /**
25
+ * Creates a new FreeCameraInput instance.
26
+ * @param keyboard The keyboard input controller to use for camera movement.
27
+ * @param camera The camera entity to control.
28
+ * @param options Optional configuration options for the controller.
29
+ */
30
+ constructor(keyboard, camera, options = {
31
+ keymap: 'wasd',
32
+ movementOptions: { speed: 0.5 },
33
+ mouseOptions: {},
34
+ }) {
35
+ super();
36
+ this.keyboard = keyboard;
37
+ this.camera = camera;
38
+ this.options = options;
39
+ this.tickOrder = gg_entity_1.GGTickOrder.INPUT_CONTROLLERS;
40
+ this.mouseInput = new mouse_input_1.MouseInput(options.mouseOptions);
41
+ this.directionsInput = new direction_keyboard_input_1.DirectionKeyboardInput(keyboard, options.keymap);
42
+ }
43
+ onSpawned(world) {
44
+ const _super = Object.create(null, {
45
+ onSpawned: { get: () => super.onSpawned }
46
+ });
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ yield _super.onSpawned.call(this, world);
49
+ // Subscribe to keyboard input for movement controls
50
+ let controls = { direction: {}, rest: [] };
51
+ const keys = ['KeyE', 'KeyQ'];
52
+ if (this.camera.object3D.supportsFov) {
53
+ keys.push('KeyZ', 'KeyC');
54
+ }
55
+ this.directionsInput.output$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(d => {
56
+ controls.direction = d;
57
+ });
58
+ (0, rxjs_1.combineLatest)(keys.map(c => this.keyboard.bind(c)))
59
+ .pipe((0, rxjs_1.takeUntil)(this._onRemoved$))
60
+ .subscribe((d) => {
61
+ controls.rest = d;
62
+ });
63
+ // Subscribe to mouse input for camera rotation
64
+ let rotationDelta = { x: 0, y: 0 };
65
+ this.mouseInput.delta$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(delta => {
66
+ rotationDelta = point2_1.Pnt2.add(rotationDelta, delta);
67
+ });
68
+ // Setup updating camera position and rotation based on input
69
+ this.camera.tick$.pipe((0, rxjs_1.takeUntil)(this._onRemoved$)).subscribe(() => {
70
+ let translateVector = { x: 0, y: 0, z: 0 };
71
+ const [u, d, zo, zi] = controls.rest;
72
+ if (controls.direction.upDown !== undefined)
73
+ translateVector.z = controls.direction.upDown ? -1 : 1;
74
+ if (controls.direction.leftRight !== undefined)
75
+ translateVector.x = controls.direction.leftRight ? -1 : 1;
76
+ if (u != d)
77
+ translateVector.y = d ? -1 : 1;
78
+ if (zo != zi)
79
+ this.camera.object3D.fov += zo ? 1 : -1;
80
+ this.camera.position = point3_1.Pnt3.add(this.camera.position, point3_1.Pnt3.rot(point3_1.Pnt3.scalarMult(point3_1.Pnt3.norm(translateVector), this.options.movementOptions.speed), this.camera.rotation));
81
+ if (rotationDelta.x != 0 || rotationDelta.y != 0) {
82
+ this.camera.rotation = quaternion_1.Qtrn.combineRotations(quaternion_1.Qtrn.fromAngle({ x: 0, y: 0, z: 1 }, -rotationDelta.x / 300), this.camera.rotation, quaternion_1.Qtrn.fromAngle({ x: 1, y: 0, z: 0 }, -rotationDelta.y / 300));
83
+ rotationDelta = { x: 0, y: 0 };
84
+ }
85
+ });
86
+ // start input
87
+ yield this.mouseInput.start();
88
+ yield this.directionsInput.start();
89
+ });
90
+ }
91
+ onRemoved() {
92
+ const _super = Object.create(null, {
93
+ onRemoved: { get: () => super.onRemoved }
94
+ });
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ yield _super.onRemoved.call(this);
97
+ yield this.mouseInput.stop(true);
98
+ yield this.directionsInput.stop();
99
+ });
100
+ }
101
+ }
102
+ exports.FreeCameraController = FreeCameraController;
@@ -1,14 +1,12 @@
1
- import { Subject } from 'rxjs';
2
1
  import { GgPositionable3dEntity } from './gg-positionable-3d-entity';
3
- import { ITickListener } from '../../base/entities/interfaces/i-tick-listener';
4
2
  import { Point3, Point4 } from '../../base/models/points';
5
3
  import { Gg3dWorld } from '../gg-3d-world';
6
4
  import { IGg3dBody, IGg3dObject } from '../interfaces';
7
- export declare class Gg3dEntity extends GgPositionable3dEntity implements ITickListener {
5
+ import { GGTickOrder } from '../../base/entities/gg-entity';
6
+ export declare class Gg3dEntity extends GgPositionable3dEntity {
8
7
  readonly object3D: IGg3dObject | null;
9
8
  readonly objectBody: IGg3dBody | null;
10
- readonly tick$: Subject<[number, number]>;
11
- readonly tickOrder = 750;
9
+ readonly tickOrder = GGTickOrder.OBJECTS_BINDING;
12
10
  get position(): Point3;
13
11
  set position(value: Point3);
14
12
  get rotation(): Point4;
@@ -1,15 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Gg3dEntity = void 0;
4
- const rxjs_1 = require("rxjs");
5
4
  const gg_positionable_3d_entity_1 = require("./gg-positionable-3d-entity");
5
+ const gg_entity_1 = require("../../base/entities/gg-entity");
6
6
  class Gg3dEntity extends gg_positionable_3d_entity_1.GgPositionable3dEntity {
7
7
  constructor(object3D, objectBody = null) {
8
8
  super();
9
9
  this.object3D = object3D;
10
10
  this.objectBody = objectBody;
11
- this.tick$ = new rxjs_1.Subject();
12
- this.tickOrder = 750;
11
+ this.tickOrder = gg_entity_1.GGTickOrder.OBJECTS_BINDING;
13
12
  if (objectBody) {
14
13
  objectBody.entity = this;
15
14
  this.tick$.subscribe(() => {
@@ -105,7 +104,6 @@ class Gg3dEntity extends gg_positionable_3d_entity_1.GgPositionable3dEntity {
105
104
  }
106
105
  dispose() {
107
106
  super.dispose();
108
- this.tick$.unsubscribe();
109
107
  if (this.object3D) {
110
108
  this.object3D.dispose();
111
109
  }
@@ -1,8 +1,7 @@
1
1
  import { BehaviorSubject, Observable, Subject } from 'rxjs';
2
2
  import { Point3, Point4 } from '../../base/models/points';
3
3
  import { Graph } from '../../base/data-structures/graph';
4
- import { GgEntity } from '../../base/entities/gg-entity';
5
- import { ITickListener } from '../../base/entities/interfaces/i-tick-listener';
4
+ import { GgEntity, GGTickOrder } from '../../base/entities/gg-entity';
6
5
  import { GgPositionable3dEntity } from './gg-positionable-3d-entity';
7
6
  import { Gg3dWorld } from '../gg-3d-world';
8
7
  import { Gg3dEntity } from './gg-3d-entity';
@@ -14,7 +13,23 @@ export declare type MapGraphNodeType = {
14
13
  loadOptions: Partial<Omit<LoadOptions, 'position' | 'rotation'>>;
15
14
  };
16
15
  export declare class MapGraph extends Graph<MapGraphNodeType> {
17
- static fromMapArray(array: MapGraphNodeType[]): MapGraph;
16
+ /**
17
+ * Creates a new MapGraph instance from an array of elements, where each element in the array is a node in the graph.
18
+ * The first element of the array is used as the root node of the graph.
19
+ * @param array The array of elements to create the graph from.
20
+ * @param closed An optional boolean indicating whether the graph is closed, meaning that the last node is adjacent to the first node.
21
+ * @returns A new Graph instance created from the array.
22
+ * @typeparam T The type of elements in the array and nodes in the graph.
23
+ */
24
+ static fromMapArray(array: MapGraphNodeType[], closed?: boolean): MapGraph;
25
+ /**
26
+ * Creates a new MapGraph instance from a two-dimensional square grid of elements, where each element in the grid is a node in the graph.
27
+ * The top-left element of the grid is used as the root node of the graph.
28
+ * The nodes in the graph are created in the same order as the elements in the grid, from left to right and then from top to bottom.
29
+ * @param grid The two-dimensional square grid of elements to create the graph from.
30
+ * @returns A new Graph instance created from the square grid.
31
+ * @typeparam T The type of elements in the square grid and nodes in the graph.
32
+ */
18
33
  static fromMapSquareGrid(grid: MapGraphNodeType[][]): MapGraph;
19
34
  getNearestDummy(thisNodes: Graph<MapGraphNodeType>[], cursor: Point3): Graph<MapGraphNodeType>;
20
35
  nodes(): MapGraph[];
@@ -23,10 +38,9 @@ export declare type Gg3dMapGraphEntityOptions = {
23
38
  loadDepth: number;
24
39
  inertia: number;
25
40
  };
26
- export declare class Gg3dMapGraphEntity extends GgEntity implements ITickListener {
41
+ export declare class Gg3dMapGraphEntity extends GgEntity {
27
42
  readonly mapGraph: MapGraph;
28
- readonly tick$: Subject<[number, number]>;
29
- readonly tickOrder = 1500;
43
+ readonly tickOrder = GGTickOrder.POST_RENDERING;
30
44
  readonly loaderCursorEntity$: BehaviorSubject<GgPositionable3dEntity | null>;
31
45
  readonly loaded: Map<MapGraphNodeType, GgPositionable3dEntity[]>;
32
46
  private _initialLoadComplete$;
@@ -15,7 +15,15 @@ const operators_1 = require("rxjs/operators");
15
15
  const graph_1 = require("../../base/data-structures/graph");
16
16
  const gg_entity_1 = require("../../base/entities/gg-entity");
17
17
  class MapGraph extends graph_1.Graph {
18
- static fromMapArray(array) {
18
+ /**
19
+ * Creates a new MapGraph instance from an array of elements, where each element in the array is a node in the graph.
20
+ * The first element of the array is used as the root node of the graph.
21
+ * @param array The array of elements to create the graph from.
22
+ * @param closed An optional boolean indicating whether the graph is closed, meaning that the last node is adjacent to the first node.
23
+ * @returns A new Graph instance created from the array.
24
+ * @typeparam T The type of elements in the array and nodes in the graph.
25
+ */
26
+ static fromMapArray(array, closed = false) {
19
27
  const root = new MapGraph(array[0]);
20
28
  let tail = root;
21
29
  for (let i = 1; i < array.length; i++) {
@@ -23,8 +31,19 @@ class MapGraph extends graph_1.Graph {
23
31
  tail.addAdjacent(newTail);
24
32
  tail = newTail;
25
33
  }
34
+ if (closed) {
35
+ tail.addAdjacent(root);
36
+ }
26
37
  return root;
27
38
  }
39
+ /**
40
+ * Creates a new MapGraph instance from a two-dimensional square grid of elements, where each element in the grid is a node in the graph.
41
+ * The top-left element of the grid is used as the root node of the graph.
42
+ * The nodes in the graph are created in the same order as the elements in the grid, from left to right and then from top to bottom.
43
+ * @param grid The two-dimensional square grid of elements to create the graph from.
44
+ * @returns A new Graph instance created from the square grid.
45
+ * @typeparam T The type of elements in the square grid and nodes in the graph.
46
+ */
28
47
  static fromMapSquareGrid(grid) {
29
48
  const nodes = grid.map(sgrid => sgrid.map(item => new MapGraph(item)));
30
49
  // bind them
@@ -69,8 +88,7 @@ class Gg3dMapGraphEntity extends gg_entity_1.GgEntity {
69
88
  constructor(mapGraph, options = {}) {
70
89
  super();
71
90
  this.mapGraph = mapGraph;
72
- this.tick$ = new rxjs_1.Subject();
73
- this.tickOrder = 1500;
91
+ this.tickOrder = gg_entity_1.GGTickOrder.POST_RENDERING;
74
92
  this.loaderCursorEntity$ = new rxjs_1.BehaviorSubject(null);
75
93
  this.loaded = new Map();
76
94
  this._initialLoadComplete$ = new rxjs_1.BehaviorSubject(false);
@@ -0,0 +1,25 @@
1
+ import { BehaviorSubject } from 'rxjs';
2
+ import { Input } from '../../base/inputs/input';
3
+ import { KeyboardInput } from '../../base/inputs/keyboard.input';
4
+ import { Gg3dRaycastVehicleEntity } from '../entities/gg-3d-raycast-vehicle.entity';
5
+ import { DirectionKeyboardInput, DirectionKeyboardKeymap } from '../../base/inputs/direction.keyboard-input';
6
+ export declare type CarKeyboardControllerOptions = {
7
+ keymap: DirectionKeyboardKeymap;
8
+ gearUpDownKeys: [string, string];
9
+ };
10
+ export declare class CarKeyboardInput extends Input {
11
+ protected readonly keyboard: KeyboardInput;
12
+ protected readonly options: CarKeyboardControllerOptions;
13
+ protected readonly directionsInput: DirectionKeyboardInput;
14
+ protected readonly x$: BehaviorSubject<number>;
15
+ protected readonly y$: BehaviorSubject<number>;
16
+ protected lastX: number;
17
+ protected readonly car$: BehaviorSubject<Gg3dRaycastVehicleEntity>;
18
+ set car(value: Gg3dRaycastVehicleEntity);
19
+ get car(): Gg3dRaycastVehicleEntity;
20
+ switchingGearsEnabled: boolean;
21
+ pairTickerPipe: import("rxjs").UnaryFunction<import("rxjs").Observable<number>, import("rxjs").Observable<number>>;
22
+ constructor(keyboard: KeyboardInput, car: Gg3dRaycastVehicleEntity, options?: CarKeyboardControllerOptions);
23
+ protected startInternal(): Promise<void>;
24
+ protected stopInternal(): Promise<void>;
25
+ }