@gg-web-engine/core 0.0.1 → 0.0.2

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 (60) hide show
  1. package/package.json +1 -1
  2. package/src/2d/entities/gg-2d-entity.ts +0 -86
  3. package/src/2d/entities/gg-2d-trigger.entity.ts +0 -17
  4. package/src/2d/entities/gg-positionable-2d-entity.ts +0 -16
  5. package/src/2d/factories.ts +0 -20
  6. package/src/2d/gg-2d-world.ts +0 -32
  7. package/src/2d/interfaces.ts +0 -31
  8. package/src/2d/models/body-options.ts +0 -3
  9. package/src/2d/models/shapes.ts +0 -7
  10. package/src/3d/controllers/car-keyboard.controller.ts +0 -128
  11. package/src/3d/controllers/free-camera.controller.ts +0 -86
  12. package/src/3d/entities/controllers/entity-motion.controller.ts +0 -122
  13. package/src/3d/entities/gg-3d-camera.entity.ts +0 -8
  14. package/src/3d/entities/gg-3d-entity.ts +0 -116
  15. package/src/3d/entities/gg-3d-map-graph.entity.ts +0 -204
  16. package/src/3d/entities/gg-3d-raycast-vehicle.entity.ts +0 -468
  17. package/src/3d/entities/gg-3d-trigger.entity.ts +0 -22
  18. package/src/3d/entities/gg-positionable-3d-entity.ts +0 -31
  19. package/src/3d/factories.ts +0 -29
  20. package/src/3d/gg-3d-world.ts +0 -36
  21. package/src/3d/interfaces.ts +0 -96
  22. package/src/3d/loader.ts +0 -165
  23. package/src/3d/models/body-options.ts +0 -3
  24. package/src/3d/models/gg-meta.ts +0 -12
  25. package/src/3d/models/shapes.ts +0 -13
  26. package/src/base/clock.ts +0 -97
  27. package/src/base/controllers/common.ts +0 -37
  28. package/src/base/controllers/i-controller.ts +0 -5
  29. package/src/base/controllers/keyboard.controller.ts +0 -109
  30. package/src/base/controllers/mouse.controller.ts +0 -73
  31. package/src/base/data-structures/graph.ts +0 -125
  32. package/src/base/entities/base-gg-renderer.ts +0 -77
  33. package/src/base/entities/gg-entity.ts +0 -61
  34. package/src/base/entities/gg-positionable-entity.ts +0 -64
  35. package/src/base/entities/inline-controller.ts +0 -31
  36. package/src/base/entities/interfaces/i-tick-listener.ts +0 -15
  37. package/src/base/gg-static.ts +0 -30
  38. package/src/base/gg-viewport-manager.ts +0 -122
  39. package/src/base/gg-viewport.ts +0 -159
  40. package/src/base/gg-world.ts +0 -198
  41. package/src/base/interfaces/gg-body.ts +0 -23
  42. package/src/base/interfaces/gg-debug-physics-drawer.ts +0 -10
  43. package/src/base/interfaces/gg-object.ts +0 -26
  44. package/src/base/interfaces/gg-physics-world.ts +0 -24
  45. package/src/base/interfaces/gg-trigger.ts +0 -10
  46. package/src/base/interfaces/gg-visual-scene.ts +0 -11
  47. package/src/base/math/box.ts +0 -19
  48. package/src/base/math/matrix4.ts +0 -29
  49. package/src/base/math/numbers.ts +0 -10
  50. package/src/base/math/point2.ts +0 -43
  51. package/src/base/math/point3.ts +0 -119
  52. package/src/base/math/quaternion.ts +0 -172
  53. package/src/base/models/axis-directions.ts +0 -3
  54. package/src/base/models/body-options.ts +0 -6
  55. package/src/base/models/geometry-nodes.ts +0 -5
  56. package/src/base/models/points.ts +0 -3
  57. package/src/base/ui/gg-console.ui.ts +0 -165
  58. package/src/base/ui/gg-debugger.ui.ts +0 -69
  59. package/src/index.ts +0 -53
  60. package/test/base/data-structures/graph.spec.ts +0 -76
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gg-web-engine/core",
3
- "version": "0.0.01",
3
+ "version": "0.0.02",
4
4
  "description": "An attempt to create open source game engine for browser",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,86 +0,0 @@
1
- import { Subject, Subscription } from 'rxjs';
2
- import { GgPositionable2dEntity } from './gg-positionable-2d-entity';
3
- import { ITickListener } from '../../base/entities/interfaces/i-tick-listener';
4
- import { Point2 } from '../../base/models/points';
5
- import { IGg2dBody, IGg2dObject } from '../interfaces';
6
- import { Gg2dWorld } from '../gg-2d-world';
7
-
8
- export class Gg2dEntity extends GgPositionable2dEntity implements ITickListener {
9
- public readonly tick$: Subject<[number, number]> = new Subject<[number, number]>();
10
- public readonly tickOrder = 750;
11
- private tickSub: Subscription | null = null;
12
-
13
- set position(value: Point2) {
14
- if (this.object2D) {
15
- this.object2D.position = value;
16
- }
17
- if (this.objectBody) {
18
- this.objectBody.position = value;
19
- }
20
- super.position = value;
21
- }
22
-
23
- set rotation(value: number) {
24
- if (this.object2D) {
25
- this.object2D.rotation = value;
26
- }
27
- if (this.objectBody) {
28
- this.objectBody.rotation = value;
29
- }
30
- super.rotation = value;
31
- }
32
-
33
- set scale(value: Point2) {
34
- if (this.object2D) {
35
- this.object2D.scale = value;
36
- }
37
- if (this.objectBody) {
38
- this.objectBody.scale = value;
39
- }
40
- super.scale = value;
41
- }
42
-
43
- constructor(public readonly object2D: IGg2dObject | null, public readonly objectBody: IGg2dBody | null) {
44
- super();
45
- if (objectBody && object2D) {
46
- this.tickSub = this.tick$.subscribe(() => {
47
- // bind physics body transform to object transform
48
- const pos = objectBody.position;
49
- const rot = objectBody.rotation;
50
- object2D.position = pos;
51
- object2D.rotation = rot;
52
- this._position$.next(pos);
53
- this._rotation$.next(rot);
54
- });
55
- } else if (!objectBody && !object2D) {
56
- throw new Error('Cannot create entity without a sprite and a body');
57
- }
58
- if (objectBody) {
59
- objectBody.entity = this;
60
- }
61
- }
62
-
63
- onSpawned(world: Gg2dWorld) {
64
- super.onSpawned(world);
65
- this.object2D?.addToWorld(world.visualScene);
66
- this.objectBody?.addToWorld(world.physicsWorld);
67
- }
68
-
69
- onRemoved() {
70
- this.object2D?.removeFromWorld(this.world!.visualScene);
71
- this.objectBody?.removeFromWorld(this.world!.physicsWorld);
72
- super.onRemoved();
73
- }
74
-
75
- dispose(): void {
76
- super.dispose();
77
- this.tickSub?.unsubscribe();
78
- this.tickSub = null;
79
- if (this.object2D) {
80
- this.object2D.dispose();
81
- }
82
- if (this.objectBody) {
83
- this.objectBody.dispose();
84
- }
85
- }
86
- }
@@ -1,17 +0,0 @@
1
- import { IGg2dTrigger } from '../interfaces';
2
- import { Gg2dEntity } from './gg-2d-entity';
3
- import { Observable } from 'rxjs';
4
- import { GgPositionable2dEntity } from './gg-positionable-2d-entity';
5
-
6
- export class Gg2dTriggerEntity extends Gg2dEntity {
7
- get onEntityEntered(): Observable<GgPositionable2dEntity> {
8
- return this.objectBody.onEntityEntered;
9
- }
10
- get onEntityLeft(): Observable<GgPositionable2dEntity | null> {
11
- return this.objectBody.onEntityLeft;
12
- }
13
-
14
- constructor(public readonly objectBody: IGg2dTrigger) {
15
- super(null, objectBody);
16
- }
17
- }
@@ -1,16 +0,0 @@
1
- import { Point2 } from '../../base/models/points';
2
- import { GgPositionableEntity } from '../../base/entities/gg-positionable-entity';
3
-
4
- export abstract class GgPositionable2dEntity extends GgPositionableEntity<Point2, number> {
5
- getDefaultPosition(): Point2 {
6
- return { x: 0, y: 0 };
7
- }
8
-
9
- getDefaultRotation(): number {
10
- return 0;
11
- }
12
-
13
- getDefaultScale(): Point2 {
14
- return { x: 1, y: 1 };
15
- }
16
- }
@@ -1,20 +0,0 @@
1
- import { BodyShape2DDescriptor, Shape2DDescriptor } from './models/shapes';
2
- import { Point2 } from '../base/models/points';
3
- import { IGg2dBody, IGg2dObject, IGg2dTrigger } from './interfaces';
4
-
5
- export abstract class IGg2dObjectFactory<T extends IGg2dObject = IGg2dObject> {
6
- abstract createPrimitive(descriptor: Shape2DDescriptor): T;
7
-
8
- // shortcuts
9
- createSquare(dimensions: Point2): T {
10
- return this.createPrimitive({ shape: 'SQUARE', dimensions });
11
- }
12
- createCircle(radius: number): T {
13
- return this.createPrimitive({ shape: 'CIRCLE', radius });
14
- }
15
- }
16
-
17
- export interface IGg2dBodyFactory<T extends IGg2dBody = IGg2dBody, K extends IGg2dTrigger = IGg2dTrigger> {
18
- createRigidBody(descriptor: BodyShape2DDescriptor, transform?: { position?: Point2; rotation?: number }): T;
19
- createTrigger(descriptor: Shape2DDescriptor, transform?: { position?: Point2; rotation?: number }): K;
20
- }
@@ -1,32 +0,0 @@
1
- import { GgWorld } from '../base/gg-world';
2
- import { Point2 } from '../base/models/points';
3
- import { IGg2dPhysicsWorld, IGg2dVisualScene } from './interfaces';
4
-
5
- export class Gg2dWorld<
6
- V extends IGg2dVisualScene = IGg2dVisualScene,
7
- P extends IGg2dPhysicsWorld = IGg2dPhysicsWorld,
8
- > extends GgWorld<Point2, number, V, P> {
9
- constructor(
10
- public readonly visualScene: V,
11
- public readonly physicsWorld: P,
12
- protected readonly consoleEnabled: boolean = false,
13
- ) {
14
- super(visualScene, physicsWorld, consoleEnabled);
15
- if (consoleEnabled) {
16
- this.registerConsoleCommand(
17
- 'ph_gravity',
18
- async (...args: string[]) => {
19
- if (args.length == 1) {
20
- args = ['0', args[0]]; // mean Y axis
21
- }
22
- if (args.length > 0) {
23
- this.physicsWorld.gravity = { x: +args[0], y: +args[1] };
24
- }
25
- return JSON.stringify(this.physicsWorld.gravity);
26
- },
27
- 'args: [float] or [float float]; change 2D world gravity vector. 1 argument means ' +
28
- '{x: 0, y: value}, 2 arguments set the whole vector. Default value is "9.82" or "0 9.82"',
29
- );
30
- }
31
- }
32
- }
@@ -1,31 +0,0 @@
1
- import { GgBody } from '../base/interfaces/gg-body';
2
- import { Point2 } from '../base/models/points';
3
- import { GgObject } from '../base/interfaces/gg-object';
4
- import { GgPhysicsWorld } from '../base/interfaces/gg-physics-world';
5
- import { GgVisualScene } from '../base/interfaces/gg-visual-scene';
6
- import { BaseGgRenderer } from '../base/entities/base-gg-renderer';
7
- import { GgTrigger } from '../base/interfaces/gg-trigger';
8
- import { Observable } from 'rxjs';
9
- import { GgPositionable2dEntity } from './entities/gg-positionable-2d-entity';
10
- import { IGg2dBodyFactory, IGg2dObjectFactory } from './factories';
11
-
12
- // These interfaces have to be implemented for a particular 2D physics engine
13
- export interface IGg2dPhysicsWorld extends GgPhysicsWorld<Point2, number> {
14
- readonly factory: IGg2dBodyFactory;
15
- }
16
-
17
- export abstract class Gg2dRenderer extends BaseGgRenderer {}
18
-
19
- export interface IGg2dBody extends GgBody<Point2, number> {}
20
-
21
- export interface IGg2dTrigger extends GgTrigger<Point2, number> {
22
- get onEntityEntered(): Observable<GgPositionable2dEntity>;
23
- get onEntityLeft(): Observable<GgPositionable2dEntity | null>;
24
- }
25
-
26
- // These interfaces have to be implemented for a particular 2D rendering engine
27
- export interface IGg2dVisualScene extends GgVisualScene<Point2, number> {
28
- readonly factory: IGg2dObjectFactory;
29
- }
30
-
31
- export interface IGg2dObject extends GgObject<Point2, number> {}
@@ -1,3 +0,0 @@
1
- import { BodyOptions } from '../../base/models/body-options';
2
-
3
- export interface Body2DOptions extends BodyOptions {}
@@ -1,7 +0,0 @@
1
- import { Point2 } from '../../base/models/points';
2
- import { Body2DOptions } from './body-options';
3
-
4
- export type Shape2DDescriptor = { shape: 'SQUARE'; dimensions: Point2 } | { shape: 'CIRCLE'; radius: number };
5
- // TODO add more shapes
6
-
7
- export type BodyShape2DDescriptor = { shape: Shape2DDescriptor; body: Partial<Body2DOptions> };
@@ -1,128 +0,0 @@
1
- import { BehaviorSubject, combineLatest, interval, pipe, Subject, takeUntil, filter } from 'rxjs';
2
- import { distinctUntilChanged, map, pairwise, startWith, switchMap, take, tap } from 'rxjs/operators';
3
- import { IController } from '../../base/controllers/i-controller';
4
- import { KeyboardController } from '../../base/controllers/keyboard.controller';
5
- import { Gg3dRaycastVehicleEntity } from '../entities/gg-3d-raycast-vehicle.entity';
6
- import { bindDirectionKeys, DirectionKeymap, DirectionOutput } from '../../base/controllers/common';
7
-
8
- // TODO pass as settings
9
- // TODO smooth y?
10
- const TICKER_INTERVAL = 16;
11
- const TICKER_MAX_STEPS = 10;
12
-
13
- type CarKeyboardControllerOptions = {
14
- keymap: DirectionKeymap;
15
- gearUpDownKeys: [string, string];
16
- };
17
-
18
- export class CarKeyboardController implements IController {
19
- // emits values -1 - 1; -1 = full turn left; 1 = full turn right
20
- private readonly x$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
21
- // emits values -1 - 1; -1 = full brake; 1 = full acceleration
22
- private readonly y$: BehaviorSubject<number> = new BehaviorSubject<number>(0);
23
-
24
- private lastX: number = 0;
25
- private readonly stop$: Subject<void> = new Subject<void>();
26
-
27
- protected readonly car$: BehaviorSubject<Gg3dRaycastVehicleEntity> = new BehaviorSubject<Gg3dRaycastVehicleEntity>(
28
- null!,
29
- );
30
-
31
- pairTickerPipe = pipe(
32
- startWith(0),
33
- pairwise<number>(),
34
- map(([beforeValue, afterValue]) => [this.lastX, afterValue] as [number, number]),
35
- switchMap(([beforeValue, afterValue]: [number, number]) =>
36
- interval(TICKER_INTERVAL).pipe(
37
- take(TICKER_MAX_STEPS),
38
- map(count => ++count),
39
- map(
40
- count =>
41
- beforeValue * ((TICKER_MAX_STEPS - count) / TICKER_MAX_STEPS) + afterValue * (count / TICKER_MAX_STEPS),
42
- ),
43
- tap(x => {
44
- this.lastX = x;
45
- }),
46
- ),
47
- ),
48
- );
49
-
50
- public set car(value: Gg3dRaycastVehicleEntity) {
51
- this.car$.next(value);
52
- }
53
-
54
- public get car(): Gg3dRaycastVehicleEntity {
55
- return this.car$.getValue();
56
- }
57
-
58
- constructor(
59
- private readonly keyboardController: KeyboardController,
60
- car: Gg3dRaycastVehicleEntity,
61
- private readonly options: CarKeyboardControllerOptions = { keymap: 'arrows', gearUpDownKeys: ['KeyA', 'KeyZ'] },
62
- ) {
63
- this.car$.next(car);
64
- }
65
-
66
- async start(): Promise<void> {
67
- let moveDirection: DirectionOutput = {};
68
- bindDirectionKeys(this.keyboardController, this.options.keymap)
69
- .pipe(takeUntil(this.stop$))
70
- .subscribe(d => {
71
- moveDirection = d;
72
- });
73
- this.car$
74
- .pipe(
75
- takeUntil(this.stop$),
76
- switchMap(c => c.tick$),
77
- takeUntil(this.stop$),
78
- map(() => {
79
- const direction = [0, 0];
80
- if (moveDirection.leftRight !== undefined) direction[0] = moveDirection.leftRight ? -1 : 1;
81
- if (moveDirection.upDown !== undefined) direction[1] = moveDirection.upDown ? 1 : -1;
82
- return direction;
83
- }),
84
- )
85
- .subscribe(([x, y]) => {
86
- this.x$.next(x);
87
- this.y$.next(y);
88
- });
89
- combineLatest([
90
- this.x$.pipe(takeUntil(this.stop$), distinctUntilChanged(), this.pairTickerPipe),
91
- this.y$.pipe(takeUntil(this.stop$), distinctUntilChanged()),
92
- ]).subscribe(([x, y]) => {
93
- this.car$.getValue().setXAxisControlValue(x);
94
- this.car$.getValue().setYAxisControlValue(y);
95
- });
96
- this.keyboardController
97
- .bind(this.options.gearUpDownKeys[0])
98
- .pipe(
99
- takeUntil(this.stop$),
100
- filter(x => !!x),
101
- )
102
- .subscribe(() => {
103
- if (
104
- this.car$.getValue() &&
105
- (!this.car$.getValue().carProperties.transmission.isAuto || this.car$.getValue().gear <= 0)
106
- ) {
107
- this.car$.getValue().gear++;
108
- }
109
- });
110
- this.keyboardController
111
- .bind(this.options.gearUpDownKeys[1])
112
- .pipe(
113
- takeUntil(this.stop$),
114
- filter(x => !!x),
115
- )
116
- .subscribe(() => {
117
- if (this.car$.getValue().carProperties.transmission.isAuto && this.car.gear > 1) {
118
- this.car$.getValue().gear = 0;
119
- } else {
120
- this.car$.getValue().gear--;
121
- }
122
- });
123
- }
124
-
125
- async stop(): Promise<void> {
126
- this.stop$.next();
127
- }
128
- }
@@ -1,86 +0,0 @@
1
- import { IController } from '../../base/controllers/i-controller';
2
- import { combineLatest, Subject, takeUntil } from 'rxjs';
3
- import { MouseController, MouseControllerOptions } from '../../base/controllers/mouse.controller';
4
- import { Pnt3 } from '../../base/math/point3';
5
- import { Gg3dCameraEntity } from '../entities/gg-3d-camera.entity';
6
- import { KeyboardController } from '../../base/controllers/keyboard.controller';
7
- import { Pnt2 } from '../../base/math/point2';
8
- import { Point2 } from '../../base/models/points';
9
- import { Qtrn } from '../../base/math/quaternion';
10
- import { bindDirectionKeys, DirectionKeymap, DirectionOutput } from '../../base/controllers/common';
11
-
12
- type FreeCameraControllerOptions = {
13
- keymap: DirectionKeymap;
14
- movementOptions: {
15
- speed: number;
16
- };
17
- mouseOptions: MouseControllerOptions;
18
- };
19
-
20
- export class FreeCameraController implements IController {
21
- private readonly mController: MouseController;
22
- private readonly stop$: Subject<void> = new Subject<void>();
23
-
24
- constructor(
25
- private readonly keyboardController: KeyboardController,
26
- private readonly camera: Gg3dCameraEntity,
27
- private readonly options: FreeCameraControllerOptions = {
28
- keymap: 'wasd',
29
- movementOptions: { speed: 0.5 },
30
- mouseOptions: {},
31
- },
32
- ) {
33
- this.mController = new MouseController(options.mouseOptions);
34
- }
35
-
36
- async start(): Promise<void> {
37
- let controls: { direction: DirectionOutput; rest: boolean[] } = { direction: {}, rest: [] };
38
- const keys = ['KeyE', 'KeyQ'];
39
- if (this.camera.object3D.supportsFov) {
40
- keys.push('KeyZ', 'KeyC');
41
- }
42
- bindDirectionKeys(this.keyboardController, this.options.keymap)
43
- .pipe(takeUntil(this.stop$))
44
- .subscribe(d => {
45
- controls.direction = d;
46
- });
47
- combineLatest(keys.map(c => this.keyboardController.bind(c)))
48
- .pipe(takeUntil(this.stop$))
49
- .subscribe((d: boolean[]) => {
50
- controls.rest = d;
51
- });
52
-
53
- let rotationDelta: Point2 = { x: 0, y: 0 };
54
- this.mController.delta$.pipe(takeUntil(this.stop$)).subscribe(delta => {
55
- rotationDelta = Pnt2.add(rotationDelta, delta);
56
- });
57
-
58
- this.camera.tick$.pipe(takeUntil(this.stop$)).subscribe(() => {
59
- let translateVector = { x: 0, y: 0, z: 0 };
60
- const [u, d, zo, zi] = controls.rest;
61
- if (controls.direction.upDown !== undefined) translateVector.z = controls.direction.upDown ? -1 : 1;
62
- if (controls.direction.leftRight !== undefined) translateVector.x = controls.direction.leftRight ? -1 : 1;
63
- if (u != d) translateVector.y = d ? -1 : 1;
64
- if (zo != zi) this.camera.object3D.fov += zo ? 1 : -1;
65
- this.camera.position = Pnt3.add(
66
- this.camera.position,
67
- Pnt3.rot(Pnt3.scalarMult(Pnt3.norm(translateVector), this.options.movementOptions.speed), this.camera.rotation),
68
- );
69
- if (rotationDelta.x != 0 || rotationDelta.y != 0) {
70
- this.camera.rotation = Qtrn.combineRotations(
71
- Qtrn.fromAngle({ x: 0, y: 0, z: 1 }, -rotationDelta.x / 300),
72
- this.camera.rotation,
73
- Qtrn.fromAngle({ x: 1, y: 0, z: 0 }, -rotationDelta.y / 300),
74
- );
75
- rotationDelta = { x: 0, y: 0 };
76
- }
77
- });
78
-
79
- await this.mController.start();
80
- }
81
-
82
- async stop(unlockPointer: boolean = true): Promise<void> {
83
- this.stop$.next();
84
- await this.mController.stop(unlockPointer);
85
- }
86
- }
@@ -1,122 +0,0 @@
1
- import { GgEntity } from '../../../base/entities/gg-entity';
2
- import { ITickListener } from '../../../base/entities/interfaces/i-tick-listener';
3
- import { Subject, Subscription, takeUntil } from 'rxjs';
4
- import { Gg3dWorld } from '../../gg-3d-world';
5
- import { GgPositionable3dEntity } from '../gg-positionable-3d-entity';
6
- import { Point3, Point4 } from '../../../base/models/points';
7
- import { Pnt3 } from '../../../base/math/point3';
8
- import { Qtrn } from '../../../base/math/quaternion';
9
-
10
- export type MotionControlFuncReturn = { position: Point3; rotation: Point4; customParameters: { [key: string]: any } };
11
- export type MotionControlFunction = (delta: number) => MotionControlFuncReturn;
12
-
13
- export class EntityMotionController extends GgEntity implements ITickListener {
14
- get motionControlFunction(): MotionControlFunction {
15
- return this._motionControlFunction;
16
- }
17
-
18
- set motionControlFunction(value: MotionControlFunction) {
19
- if (this.currentTransition) {
20
- this.currentTransition.unsubscribe();
21
- this.currentTransition = null;
22
- }
23
- this._motionControlFunction = value;
24
- }
25
- public readonly tick$: Subject<[number, number]> = new Subject<[number, number]>();
26
-
27
- protected readonly removed$: Subject<void> = new Subject<void>();
28
- public readonly tickOrder: number = 750;
29
-
30
- constructor(
31
- public target: GgPositionable3dEntity,
32
- protected _motionControlFunction: MotionControlFunction,
33
- public customParametersHandleFunc: (target: GgPositionable3dEntity, params: any) => void = () => {},
34
- ) {
35
- super();
36
- }
37
-
38
- protected lastValue: MotionControlFuncReturn | undefined;
39
- private currentTransition: Subscription | null = null;
40
-
41
- // smoothly set controller function, animate from some determined state
42
- transitFromStaticState(
43
- state: MotionControlFuncReturn,
44
- newFunc: MotionControlFunction,
45
- transitionDuration: number,
46
- easing: (t: number) => number = x => x,
47
- customParametersLerpFunc: (a: any, b: any, t: number) => any = (a, b, t) => b,
48
- ) {
49
- this.lastValue = state;
50
- this._motionControlFunction = () => state;
51
- return this.transitControlFunction(newFunc, transitionDuration, easing, customParametersLerpFunc);
52
- }
53
-
54
- // smoothly change controller function
55
- transitControlFunction(
56
- newFunc: MotionControlFunction,
57
- transitionDuration: number,
58
- easing: (t: number) => number = x => x,
59
- customParametersLerpFunc: (a: any, b: any, t: number) => any = (a, b, t) => b,
60
- ) {
61
- let oldControlFunc: MotionControlFunction;
62
- if (this.currentTransition) {
63
- this.currentTransition.unsubscribe();
64
- this.currentTransition = null;
65
- if (this.lastValue) {
66
- oldControlFunc = () => this.lastValue!;
67
- } else {
68
- this._motionControlFunction = newFunc;
69
- return;
70
- }
71
- } else {
72
- oldControlFunc = this._motionControlFunction;
73
- }
74
- let k = 0;
75
- this._motionControlFunction = delta => {
76
- const oldRes = oldControlFunc(delta);
77
- const newRes = newFunc(delta);
78
- return {
79
- customParameters: customParametersLerpFunc(oldRes.customParameters, newRes.customParameters, k),
80
- position: Pnt3.lerp(oldRes.position, newRes.position, k),
81
- rotation: Qtrn.slerp(oldRes.rotation, newRes.rotation, k),
82
- };
83
- };
84
- let startTime: number | undefined;
85
- this.currentTransition = this.tick$.pipe(takeUntil(this.removed$)).subscribe(([elapsed, _]) => {
86
- if (startTime === undefined) {
87
- startTime = elapsed;
88
- } else {
89
- k = (elapsed - startTime) / transitionDuration;
90
- if (k >= 1) {
91
- k = 1;
92
- this.currentTransition!.unsubscribe();
93
- this.currentTransition = null;
94
- this._motionControlFunction = newFunc;
95
- } else {
96
- k = easing(k);
97
- }
98
- }
99
- });
100
- }
101
-
102
- onSpawned(world: Gg3dWorld) {
103
- super.onSpawned(world);
104
- this.tick$.pipe(takeUntil(this.removed$)).subscribe(([_, delta]) => {
105
- this.lastValue = this._motionControlFunction(delta);
106
- this.target.position = this.lastValue.position;
107
- this.target.rotation = this.lastValue.rotation;
108
- this.customParametersHandleFunc(this.target, this.lastValue.customParameters);
109
- });
110
- }
111
-
112
- onRemoved() {
113
- super.onRemoved();
114
- this.removed$.next();
115
- }
116
-
117
- dispose(): void {
118
- super.dispose();
119
- this.tick$.unsubscribe();
120
- this.tick$.complete();
121
- }
122
- }
@@ -1,8 +0,0 @@
1
- import { IGg3dBody, IGg3dCamera } from '../interfaces';
2
- import { Gg3dEntity } from './gg-3d-entity';
3
-
4
- export class Gg3dCameraEntity<T extends IGg3dCamera = IGg3dCamera> extends Gg3dEntity {
5
- constructor(public readonly object3D: T, public readonly objectBody: IGg3dBody | null = null) {
6
- super(object3D, objectBody);
7
- }
8
- }