@gg-web-engine/core 0.0.37 → 0.0.39

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 (45) hide show
  1. package/dist/2d/components/physics/i-rigid-body-2d.component.d.ts +3 -0
  2. package/dist/2d/components/physics/i-trigger-2d.component.d.ts +3 -0
  3. package/dist/2d/models/body-options.d.ts +5 -1
  4. package/dist/3d/components/physics/i-physics-world-3d.component.d.ts +7 -0
  5. package/dist/3d/components/physics/i-rigid-body-3d.component.d.ts +3 -0
  6. package/dist/3d/components/physics/i-trigger-3d.component.d.ts +3 -0
  7. package/dist/3d/entities/controllers/input/car-keyboard-handling.controller.js +2 -2
  8. package/dist/3d/entities/controllers/input/gg-car-keyboard-handling.controller.js +3 -3
  9. package/dist/3d/entities/gg-car/gg-car.entity.js +4 -2
  10. package/dist/3d/entities/map-graph-3d.entity.d.ts +1 -1
  11. package/dist/3d/entities/map-graph-3d.entity.js +3 -4
  12. package/dist/3d/entities/raycast-vehicle-3d.entity.d.ts +8 -5
  13. package/dist/3d/entities/raycast-vehicle-3d.entity.js +41 -25
  14. package/dist/3d/factories.d.ts +3 -3
  15. package/dist/3d/models/body-options.d.ts +5 -1
  16. package/dist/3d/models/shapes.d.ts +41 -1
  17. package/dist/base/clock/pausable-clock.d.ts +56 -1
  18. package/dist/base/clock/pausable-clock.js +88 -5
  19. package/dist/base/components/physics/i-body.component.d.ts +3 -1
  20. package/dist/base/components/physics/i-physics-world.component.d.ts +8 -6
  21. package/dist/base/components/rendering/i-renderer.component.d.ts +4 -0
  22. package/dist/base/components/rendering/i-visual-scene.component.d.ts +0 -4
  23. package/dist/base/entities/i-entity.d.ts +4 -2
  24. package/dist/base/entities/i-entity.js +9 -3
  25. package/dist/base/entities/i-renderer.entity.d.ts +4 -0
  26. package/dist/base/entities/i-renderer.entity.js +8 -0
  27. package/dist/base/gg-world.d.ts +0 -2
  28. package/dist/base/gg-world.js +26 -25
  29. package/dist/base/index.d.ts +0 -1
  30. package/dist/base/index.js +0 -1
  31. package/dist/base/math/point2.d.ts +12 -0
  32. package/dist/base/math/point2.js +35 -0
  33. package/dist/base/math/point3.d.ts +8 -0
  34. package/dist/base/math/point3.js +16 -0
  35. package/dist/base/math/quaternion.d.ts +2 -0
  36. package/dist/base/math/quaternion.js +4 -0
  37. package/dist/base/models/body-options.d.ts +9 -0
  38. package/dist/dev/gg-console.ui.js +16 -8
  39. package/dist/dev/gg-debugger.ui.d.ts +4 -0
  40. package/dist/dev/gg-debugger.ui.js +83 -32
  41. package/dist/dev/gg-static.d.ts +0 -1
  42. package/dist/dev/gg-static.js +3 -4
  43. package/package.json +3 -3
  44. package/dist/base/interfaces/i-debug-physics-drawer.d.ts +0 -8
  45. package/dist/base/interfaces/i-debug-physics-drawer.js +0 -1
@@ -2,39 +2,105 @@ import { Subject } from 'rxjs';
2
2
  import { map, tap } from 'rxjs/operators';
3
3
  import { GgGlobalClock } from './global-clock';
4
4
  /**
5
- * A class, providing ability to track time, fire ticks, provide time elapsed + tick delta with ability to suspend/resume it.
5
+ * A class providing the ability to track time, fire ticks, provide time elapsed, and tick delta with the ability to suspend/resume it.
6
6
  */
7
7
  export class PausableClock {
8
+ /**
9
+ * Constructs a new PausableClock instance.
10
+ * @param autoStart Indicates whether the clock should start automatically upon creation.
11
+ * @param parentClock The parent clock to synchronize with. Defaults to GgGlobalClock instance.
12
+ */
8
13
  constructor(autoStart = false, parentClock = GgGlobalClock.instance) {
9
14
  this.parentClock = parentClock;
10
15
  this.tickSub = null;
11
16
  this._tick$ = new Subject();
12
- // state
17
+ // State variables
13
18
  this.startedAt = -1;
14
19
  this.oldRelativeTime = 0; // "elapsed", emitted on last tick
15
20
  this.pausedAt = -1;
21
+ this.lastStopElapsed = 0;
22
+ this._timeScale = 1;
23
+ this.pausedByTimescale = false;
16
24
  if (autoStart) {
17
25
  this.start();
18
26
  }
19
27
  }
28
+ /**
29
+ * Observable stream of ticks, emitting an array containing the current time and the tick delta.
30
+ */
20
31
  get tick$() {
21
32
  return this._tick$.pipe(map(([oldTime, newTime]) => [newTime, newTime - oldTime]));
22
33
  }
34
+ /**
35
+ * Checks if the clock is currently running.
36
+ */
23
37
  get isRunning() {
24
38
  return !!this.tickSub;
25
39
  }
40
+ /**
41
+ * Checks if the clock is currently paused.
42
+ */
26
43
  get isPaused() {
27
44
  return this.pausedAt !== -1;
28
45
  }
46
+ /**
47
+ * Checks if the clock is stopped.
48
+ */
49
+ get isStopped() {
50
+ return this.startedAt === -1;
51
+ }
52
+ /**
53
+ * Gets the time scale of the clock.
54
+ */
55
+ get timeScale() {
56
+ return this._timeScale;
57
+ }
58
+ /**
59
+ * Sets the time scale of the clock.
60
+ */
61
+ set timeScale(value) {
62
+ if (value === this._timeScale && !(this.pausedByTimescale && value !== 0))
63
+ return;
64
+ if (value === 0) {
65
+ if (!this.isPaused) {
66
+ this.pause();
67
+ this.pausedByTimescale = true;
68
+ }
69
+ return;
70
+ }
71
+ if (this.isPaused && this.pausedByTimescale) {
72
+ this.resume();
73
+ this.pausedByTimescale = false;
74
+ }
75
+ if (!this.isStopped) {
76
+ const cur = this.isPaused ? this.pausedAt : this.parentClock.elapsedTime;
77
+ this.startedAt = cur - ((cur - this.startedAt) * this.timeScale) / value;
78
+ }
79
+ this._timeScale = value;
80
+ }
81
+ /**
82
+ * Gets the elapsed time since the clock started.
83
+ */
29
84
  get elapsedTime() {
85
+ if (this.isStopped) {
86
+ return this.lastStopElapsed;
87
+ }
30
88
  if (this.isPaused) {
31
- return this.pausedAt - this.startedAt;
89
+ return this._timeScale * (this.pausedAt - this.startedAt);
32
90
  }
33
- return this.parentClock.elapsedTime - this.startedAt;
91
+ return this._timeScale * (this.parentClock.elapsedTime - this.startedAt);
34
92
  }
93
+ /**
94
+ * Creates a child clock.
95
+ * @param autoStart Indicates whether the child clock should start automatically.
96
+ * @returns A new instance of PausableClock.
97
+ */
35
98
  createChildClock(autoStart) {
36
99
  return new PausableClock(autoStart, this);
37
100
  }
101
+ /**
102
+ * Starts the clock.
103
+ */
38
104
  start() {
39
105
  if (this.isRunning) {
40
106
  return;
@@ -43,14 +109,25 @@ export class PausableClock {
43
109
  this.startedAt = this.parentClock.elapsedTime;
44
110
  this.startListeningTicks();
45
111
  }
112
+ /**
113
+ * Stops the clock.
114
+ */
46
115
  stop() {
47
116
  this.stopListeningTicks();
117
+ this.lastStopElapsed = this.elapsedTime;
48
118
  this.startedAt = this.pausedAt = -1;
49
119
  }
120
+ /**
121
+ * Pauses the clock.
122
+ */
50
123
  pause() {
51
124
  this.stopListeningTicks();
52
125
  this.pausedAt = this.parentClock.elapsedTime;
126
+ this.pausedByTimescale = false;
53
127
  }
128
+ /**
129
+ * Resumes the clock.
130
+ */
54
131
  resume() {
55
132
  if (this.isRunning || this.pausedAt == -1) {
56
133
  return;
@@ -59,14 +136,20 @@ export class PausableClock {
59
136
  this.pausedAt = -1;
60
137
  this.startListeningTicks();
61
138
  }
139
+ /**
140
+ * Starts listening for ticks from the parent clock.
141
+ */
62
142
  startListeningTicks() {
63
143
  if (this.tickSub) {
64
144
  throw new Error('Clock is already ticking!');
65
145
  }
66
146
  this.tickSub = this.parentClock.tick$
67
- .pipe(map(([parentElapsed, _]) => [this.oldRelativeTime, parentElapsed - this.startedAt]), tap(([_, cur]) => (this.oldRelativeTime = cur)))
147
+ .pipe(map(([_, d]) => [this.oldRelativeTime, this.oldRelativeTime + d * this.timeScale]), tap(([_, cur]) => (this.oldRelativeTime = cur)))
68
148
  .subscribe(this._tick$);
69
149
  }
150
+ /**
151
+ * Stops listening for ticks from the parent clock.
152
+ */
70
153
  stopListeningTicks() {
71
154
  var _a;
72
155
  (_a = this.tickSub) === null || _a === void 0 ? void 0 : _a.unsubscribe();
@@ -1,7 +1,7 @@
1
1
  import { IEntity } from '../../entities/i-entity';
2
2
  import { IWorldComponent } from '../i-world-component';
3
3
  import { GgWorld, PhysicsTypeDocRepo, VisualTypeDocRepo } from '../../gg-world';
4
- import { CollisionGroup } from '../../models/body-options';
4
+ import { CollisionGroup, DebugBodySettings } from '../../models/body-options';
5
5
  export interface IBodyComponent<D, R, TypeDoc extends PhysicsTypeDocRepo<D, R> = PhysicsTypeDocRepo<D, R>> extends IWorldComponent<D, R, VisualTypeDocRepo<D, R>, TypeDoc> {
6
6
  entity: IEntity | null;
7
7
  position: D;
@@ -11,6 +11,8 @@ export interface IBodyComponent<D, R, TypeDoc extends PhysicsTypeDocRepo<D, R> =
11
11
  set ownCollisionGroups(value: CollisionGroup[] | 'all');
12
12
  get interactWithCollisionGroups(): CollisionGroup[];
13
13
  set interactWithCollisionGroups(value: CollisionGroup[] | 'all');
14
+ /** body info for physics debugger view */
15
+ readonly debugBodySettings: DebugBodySettings;
14
16
  clone(): IBodyComponent<D, R, TypeDoc>;
15
17
  addToWorld(world: GgWorld<D, R, VisualTypeDocRepo<D, R>, TypeDoc>): void;
16
18
  removeFromWorld(world: GgWorld<D, R, VisualTypeDocRepo<D, R>, TypeDoc>): void;
@@ -1,12 +1,16 @@
1
- import { GgWorld, PhysicsTypeDocRepo } from '../../gg-world';
2
- import { IDebugPhysicsDrawer } from '../../interfaces/i-debug-physics-drawer';
1
+ import { PhysicsTypeDocRepo } from '../../gg-world';
3
2
  import { IComponent } from '../i-component';
4
3
  import { CollisionGroup } from '../../models/body-options';
4
+ import { Subject } from 'rxjs';
5
5
  export interface IPhysicsWorldComponent<D, R, TypeDoc extends PhysicsTypeDocRepo<D, R> = PhysicsTypeDocRepo<D, R>> extends IComponent {
6
6
  readonly factory: TypeDoc['factory'];
7
7
  gravity: D;
8
- timeScale: number;
9
- get physicsDebugViewActive(): boolean;
8
+ /** event emitter, emits newly added physics components */
9
+ readonly added$: Subject<TypeDoc['rigidBody'] | TypeDoc['trigger'] | any>;
10
+ /** event emitter, emits just removed physics components */
11
+ readonly removed$: Subject<TypeDoc['rigidBody'] | TypeDoc['trigger'] | any>;
12
+ /** list of currently added to world physics components */
13
+ readonly children: (TypeDoc['rigidBody'] | TypeDoc['trigger'] | any)[];
10
14
  init(): Promise<void>;
11
15
  /**
12
16
  * Runs simulation of the physics world.
@@ -16,6 +20,4 @@ export interface IPhysicsWorldComponent<D, R, TypeDoc extends PhysicsTypeDocRepo
16
20
  simulate(delta: number): void;
17
21
  registerCollisionGroup(): CollisionGroup;
18
22
  deregisterCollisionGroup(group: CollisionGroup): void;
19
- startDebugger(world: GgWorld<D, R>, drawer: IDebugPhysicsDrawer<D, R>): void;
20
- stopDebugger(world: GgWorld<D, R>): void;
21
23
  }
@@ -26,6 +26,10 @@ export declare abstract class IRendererComponent<D, R, VTypeDoc extends VisualTy
26
26
  entity: IEntity | null;
27
27
  /** Specifies the options for the renderer. */
28
28
  readonly rendererOptions: RendererOptions;
29
+ /** get flag whether renderer shows physics debugger view */
30
+ abstract get physicsDebugViewActive(): boolean;
31
+ /** turns on/off physics debugger view for this renderer */
32
+ abstract set physicsDebugViewActive(value: boolean);
29
33
  protected constructor(scene: IVisualSceneComponent<D, R, VTypeDoc>, canvas?: HTMLCanvasElement | undefined, options?: Partial<RendererOptions>);
30
34
  /**
31
35
  * Renders the scene.
@@ -1,10 +1,6 @@
1
- import { IDebugPhysicsDrawer } from '../../interfaces/i-debug-physics-drawer';
2
1
  import { IComponent } from '../i-component';
3
2
  import { VisualTypeDocRepo } from '../../gg-world';
4
3
  export interface IVisualSceneComponent<D, R, TypeDoc extends VisualTypeDocRepo<D, R> = VisualTypeDocRepo<D, R>> extends IComponent {
5
4
  readonly factory: TypeDoc['factory'];
6
- readonly debugPhysicsDrawerClass?: {
7
- new (): IDebugPhysicsDrawer<D, R, TypeDoc>;
8
- };
9
5
  init(): Promise<void>;
10
6
  }
@@ -1,5 +1,5 @@
1
1
  import { GgWorld, PhysicsTypeDocRepo, VisualTypeDocRepo } from '../gg-world';
2
- import { Subject } from 'rxjs';
2
+ import { Observable, Subject } from 'rxjs';
3
3
  import { IWorldComponent } from '../components/i-world-component';
4
4
  /**
5
5
  * Engine's default tick orders: the less value, the earlier tick will be run.
@@ -34,7 +34,7 @@ export declare abstract class IEntity<D = any, R = any, VTypeDoc extends VisualT
34
34
  /**
35
35
  * The flag whether entity should listen to ticks. If set to false, ticks will not be propagated to this entity
36
36
  * */
37
- protected _active: boolean;
37
+ protected _selfActive: boolean;
38
38
  get active(): boolean;
39
39
  set active(value: boolean);
40
40
  parent: IEntity | null;
@@ -48,6 +48,8 @@ export declare abstract class IEntity<D = any, R = any, VTypeDoc extends VisualT
48
48
  removeComponents(components: IWorldComponent<D, R, VTypeDoc, PTypeDoc>[], dispose?: boolean): void;
49
49
  protected _onSpawned$: Subject<void>;
50
50
  protected _onRemoved$: Subject<void>;
51
+ get onSpawned$(): Observable<void>;
52
+ get onRemoved$(): Observable<void>;
51
53
  onSpawned(world: GgWorld<D, R, VTypeDoc, PTypeDoc>): void;
52
54
  onRemoved(): void;
53
55
  dispose(): void;
@@ -26,7 +26,7 @@ export class IEntity {
26
26
  /**
27
27
  * The flag whether entity should listen to ticks. If set to false, ticks will not be propagated to this entity
28
28
  * */
29
- this._active = true;
29
+ this._selfActive = true;
30
30
  this.parent = null;
31
31
  this._children = [];
32
32
  this._components = [];
@@ -43,10 +43,10 @@ export class IEntity {
43
43
  this._name = value;
44
44
  }
45
45
  get active() {
46
- return this._active;
46
+ return this._selfActive && (!this.parent || this.parent.active);
47
47
  }
48
48
  set active(value) {
49
- this._active = value;
49
+ this._selfActive = value;
50
50
  }
51
51
  get children() {
52
52
  return [...this._children];
@@ -100,6 +100,12 @@ export class IEntity {
100
100
  }
101
101
  }
102
102
  }
103
+ get onSpawned$() {
104
+ return this._onSpawned$.asObservable();
105
+ }
106
+ get onRemoved$() {
107
+ return this._onRemoved$.asObservable();
108
+ }
103
109
  onSpawned(world) {
104
110
  this._world = world;
105
111
  for (const c of this._components) {
@@ -23,6 +23,10 @@ export declare abstract class IRendererEntity<D, R, TypeDoc extends VisualTypeDo
23
23
  */
24
24
  get rendererSize(): Point2 | null;
25
25
  get rendererOptions(): RendererOptions;
26
+ /** get flag whether renderer shows physics debugger view */
27
+ get physicsDebugViewActive(): boolean;
28
+ /** turns on/off physics debugger view for this renderer */
29
+ set physicsDebugViewActive(value: boolean);
26
30
  /**
27
31
  Initializes a new instance of the BaseGgRenderer class.
28
32
  * @param renderer
@@ -38,6 +38,14 @@ export class IRendererEntity extends IEntity {
38
38
  get rendererOptions() {
39
39
  return this.renderer.rendererOptions;
40
40
  }
41
+ /** get flag whether renderer shows physics debugger view */
42
+ get physicsDebugViewActive() {
43
+ return this.renderer.physicsDebugViewActive;
44
+ }
45
+ /** turns on/off physics debugger view for this renderer */
46
+ set physicsDebugViewActive(value) {
47
+ this.renderer.physicsDebugViewActive = value;
48
+ }
41
49
  onSpawned(world) {
42
50
  this._rendererSize$.next(null);
43
51
  if (this.rendererOptions.size == 'fullscreen' || typeof this.rendererOptions.size === 'function') {
@@ -34,6 +34,4 @@ export declare abstract class GgWorld<D, R, VTypeDoc extends VisualTypeDocRepo<D
34
34
  position?: D, rotation?: R, material?: unknown): IPositionable<D, R> & IRenderableEntity<D, R, VTypeDoc>;
35
35
  addEntity(entity: IEntity): void;
36
36
  removeEntity(entity: IEntity, dispose?: boolean): void;
37
- get physicsDebugViewActive(): boolean;
38
- set physicsDebugViewActive(value: boolean);
39
37
  }
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { GgGlobalClock, KeyboardInput, TickOrder, } from '../base';
10
+ import { GgGlobalClock, IRendererEntity, KeyboardInput, TickOrder, } from '../base';
11
11
  export class GgWorld {
12
12
  constructor(visualScene, physicsWorld) {
13
13
  this.visualScene = visualScene;
@@ -30,13 +30,32 @@ export class GgWorld {
30
30
  return '' + window.ggstatic.showStats;
31
31
  }), 'args: [0 or 1]; turn on/off stats. Default value is 0');
32
32
  window.ggstatic.registerConsoleCommand(this, 'ph_timescale', (...args) => __awaiter(this, void 0, void 0, function* () {
33
- this.physicsWorld.timeScale = +args[0];
34
- return JSON.stringify(this.physicsWorld.timeScale);
33
+ this.worldClock.timeScale = +args[0];
34
+ return JSON.stringify(this.worldClock.timeScale);
35
35
  }), 'args: [float]; change time scale of physics engine. Default value is 1.0');
36
+ window.ggstatic.registerConsoleCommand(this, 'ls_renderers', () => __awaiter(this, void 0, void 0, function* () {
37
+ return this.children
38
+ .filter(e => e instanceof IRendererEntity)
39
+ .map(r => r.name)
40
+ .join('\n');
41
+ }), 'no args; print all renderers in selected world');
36
42
  window.ggstatic.registerConsoleCommand(this, 'dr_drawphysics', (...args) => __awaiter(this, void 0, void 0, function* () {
37
- this.physicsDebugViewActive = ['1', 'true', '+'].includes(args[0]);
38
- return '' + this.physicsWorld.physicsDebugViewActive;
39
- }), 'args: [0 or 1]; turn on/off physics debug view. Default value is 0');
43
+ const value = ['1', 'true', '+'].includes(args[0]);
44
+ const rendererName = args[1];
45
+ let renderer;
46
+ if (rendererName) {
47
+ renderer = this.children.find(x => x instanceof IRendererEntity && x.name === rendererName);
48
+ }
49
+ else {
50
+ renderer = this.children.find(x => x instanceof IRendererEntity);
51
+ }
52
+ if (renderer) {
53
+ renderer.physicsDebugViewActive = value;
54
+ return '' + value;
55
+ }
56
+ return 'false';
57
+ }), 'args: [0 or 1] or [0 or 1, string]; turn on/off physics debug view. Second argument expects renderer ' +
58
+ 'name, if not provided first renderer will be picked. Look up for renderer names using command "ls_renderers"');
40
59
  }
41
60
  }
42
61
  static get documentWorlds() {
@@ -56,7 +75,7 @@ export class GgWorld {
56
75
  this.tickListeners[i].tick$.next([elapsed, delta]);
57
76
  }
58
77
  }
59
- // run phycics simulation
78
+ // run physics simulation
60
79
  this.physicsWorld.simulate(delta);
61
80
  // emit tick to all remained entities
62
81
  for (i; i < this.tickListeners.length; i++) {
@@ -126,24 +145,6 @@ export class GgWorld {
126
145
  entity.dispose();
127
146
  }
128
147
  }
129
- get physicsDebugViewActive() {
130
- return this.physicsWorld.physicsDebugViewActive;
131
- }
132
- set physicsDebugViewActive(value) {
133
- if (this.physicsDebugViewActive === value) {
134
- return;
135
- }
136
- if (value) {
137
- const cls = this.visualScene.debugPhysicsDrawerClass;
138
- if (!cls) {
139
- throw new Error('Debug drawer is not available');
140
- }
141
- this.physicsWorld.startDebugger(this, new cls());
142
- }
143
- else {
144
- this.physicsWorld.stopDebugger(this);
145
- }
146
- }
147
148
  }
148
149
  GgWorld.default_name_counter = 0;
149
150
  GgWorld._documentWorlds = [];
@@ -21,7 +21,6 @@ export * from './inputs/direction.keyboard.input';
21
21
  export * from './inputs/i-input';
22
22
  export * from './inputs/keyboard.input';
23
23
  export * from './inputs/mouse.input';
24
- export * from './interfaces/i-debug-physics-drawer';
25
24
  export * from './interfaces/i-positionable';
26
25
  export * from './models/axis-directions';
27
26
  export * from './models/body-options';
@@ -21,7 +21,6 @@ export * from './inputs/direction.keyboard.input';
21
21
  export * from './inputs/i-input';
22
22
  export * from './inputs/keyboard.input';
23
23
  export * from './inputs/mouse.input';
24
- export * from './interfaces/i-debug-physics-drawer';
25
24
  export * from './interfaces/i-positionable';
26
25
  export * from './models/axis-directions';
27
26
  export * from './models/body-options';
@@ -12,12 +12,20 @@ export declare class Pnt2 {
12
12
  static get nY(): Point2;
13
13
  /** clone point */
14
14
  static clone(p: Point2): Point2;
15
+ /** spread point components */
16
+ static spr(p: Point2): [number, number];
17
+ /** get negation of the point */
18
+ static neg(p: Point2): Point2;
15
19
  /** add point b to point a */
16
20
  static add(a: Point2, b: Point2): Point2;
17
21
  /** subtract point b from point a */
18
22
  static sub(a: Point2, b: Point2): Point2;
23
+ /** scale point b by point. The result is the point, where each component is a product of appropriate components of input points */
24
+ static scale(a: Point2, s: Point2): Point2;
19
25
  /** average point between a and b */
20
26
  static avg(a: Point2, b: Point2): Point2;
27
+ /** round point components */
28
+ static round(p: Point2): Point2;
21
29
  /** calculate vector length (squared) */
22
30
  static lenSq(v: Point2): number;
23
31
  /** calculate vector length */
@@ -32,4 +40,8 @@ export declare class Pnt2 {
32
40
  static lerp(a: Point2, b: Point2, t: number): Point2;
33
41
  /** angle between vectors in radians */
34
42
  static angle(a: Point2, b: Point2): number;
43
+ /** rotate point around zero by provided angle */
44
+ static rot(p: Point2, angle: number): Point2;
45
+ /** rotate point around pivot by provided angle */
46
+ static rotAround(p: Point2, pivot: Point2, angle: number): Point2;
35
47
  }
@@ -23,6 +23,14 @@ export class Pnt2 {
23
23
  static clone(p) {
24
24
  return { x: p.x, y: p.y };
25
25
  }
26
+ /** spread point components */
27
+ static spr(p) {
28
+ return [p.x, p.y];
29
+ }
30
+ /** get negation of the point */
31
+ static neg(p) {
32
+ return { x: -p.x, y: -p.y };
33
+ }
26
34
  /** add point b to point a */
27
35
  static add(a, b) {
28
36
  return { x: a.x + b.x, y: a.y + b.y };
@@ -31,10 +39,18 @@ export class Pnt2 {
31
39
  static sub(a, b) {
32
40
  return { x: a.x - b.x, y: a.y - b.y };
33
41
  }
42
+ /** scale point b by point. The result is the point, where each component is a product of appropriate components of input points */
43
+ static scale(a, s) {
44
+ return { x: a.x * s.x, y: a.y * s.y };
45
+ }
34
46
  /** average point between a and b */
35
47
  static avg(a, b) {
36
48
  return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
37
49
  }
50
+ /** round point components */
51
+ static round(p) {
52
+ return { x: Math.round(p.x), y: Math.round(p.y) };
53
+ }
38
54
  /** calculate vector length (squared) */
39
55
  static lenSq(v) {
40
56
  return v.x * v.x + v.y * v.y;
@@ -75,4 +91,23 @@ export class Pnt2 {
75
91
  const magnitudeProduct = Math.sqrt(a.x ** 2 + a.y ** 2) * Math.sqrt(b.x ** 2 + b.y ** 2);
76
92
  return Math.acos(dotProduct / magnitudeProduct);
77
93
  }
94
+ /** rotate point around zero by provided angle */
95
+ static rot(p, angle) {
96
+ const cos = Math.cos(angle);
97
+ const sin = Math.sin(angle);
98
+ return {
99
+ x: p.x * cos - p.y * sin,
100
+ y: p.x * sin + p.y * cos,
101
+ };
102
+ }
103
+ /** rotate point around pivot by provided angle */
104
+ static rotAround(p, pivot, angle) {
105
+ const cos = Math.cos(angle);
106
+ const sin = Math.sin(angle);
107
+ const p0 = { x: p.x - pivot.x, y: p.y - pivot.y };
108
+ return {
109
+ x: p0.x * cos - p0.y * sin + pivot.x,
110
+ y: p0.x * sin + p0.y * cos + pivot.y,
111
+ };
112
+ }
78
113
  }
@@ -16,12 +16,20 @@ export declare class Pnt3 {
16
16
  static get nZ(): Point3;
17
17
  /** clone point */
18
18
  static clone(p: Point3): Point3;
19
+ /** spread point components */
20
+ static spr(p: Point3): [number, number, number];
21
+ /** get negation of the point */
22
+ static neg(p: Point3): Point3;
19
23
  /** add point b to point a */
20
24
  static add(a: Point3, b: Point3): Point3;
21
25
  /** subtract point b from point a */
22
26
  static sub(a: Point3, b: Point3): Point3;
27
+ /** scale point b by point. The result is the point, where each component is a product of appropriate components of input points */
28
+ static scale(a: Point3, s: Point3): Point3;
23
29
  /** average point between a and b */
24
30
  static avg(a: Point3, b: Point3): Point3;
31
+ /** round point components */
32
+ static round(p: Point3): Point3;
25
33
  /** calculate vector length (squared) */
26
34
  static lenSq(v: Point3): number;
27
35
  /** calculate vector length */
@@ -32,6 +32,14 @@ export class Pnt3 {
32
32
  static clone(p) {
33
33
  return { x: p.x, y: p.y, z: p.z };
34
34
  }
35
+ /** spread point components */
36
+ static spr(p) {
37
+ return [p.x, p.y, p.z];
38
+ }
39
+ /** get negation of the point */
40
+ static neg(p) {
41
+ return { x: -p.x, y: -p.y, z: -p.z };
42
+ }
35
43
  /** add point b to point a */
36
44
  static add(a, b) {
37
45
  return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
@@ -40,10 +48,18 @@ export class Pnt3 {
40
48
  static sub(a, b) {
41
49
  return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
42
50
  }
51
+ /** scale point b by point. The result is the point, where each component is a product of appropriate components of input points */
52
+ static scale(a, s) {
53
+ return { x: a.x * s.x, y: a.y * s.y, z: a.z * s.z };
54
+ }
43
55
  /** average point between a and b */
44
56
  static avg(a, b) {
45
57
  return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2, z: (a.z + b.z) / 2 };
46
58
  }
59
+ /** round point components */
60
+ static round(p) {
61
+ return { x: Math.round(p.x), y: Math.round(p.y), z: Math.round(p.z) };
62
+ }
47
63
  /** calculate vector length (squared) */
48
64
  static lenSq(v) {
49
65
  return v.x * v.x + v.y * v.y + v.z * v.z;
@@ -18,6 +18,8 @@ export declare class Qtrn {
18
18
  * @returns A new Point4 instance with the same values as the given Point4 object.
19
19
  */
20
20
  static clone(q: Point4): Point4;
21
+ /** spread quaternion components */
22
+ static spr(p: Point4): [number, number, number, number];
21
23
  /**
22
24
  * Returns the sum of two Point4 objects.
23
25
  * @param a The first Point4 object to add.
@@ -23,6 +23,10 @@ export class Qtrn {
23
23
  static clone(q) {
24
24
  return { x: q.x, y: q.y, z: q.z, w: q.w };
25
25
  }
26
+ /** spread quaternion components */
27
+ static spr(p) {
28
+ return [p.x, p.y, p.z, p.w];
29
+ }
26
30
  /**
27
31
  * Returns the sum of two Point4 objects.
28
32
  * @param a The first Point4 object to add.
@@ -7,3 +7,12 @@ export interface BodyOptions {
7
7
  ownCollisionGroups: CollisionGroup[] | 'all';
8
8
  interactWithCollisionGroups: CollisionGroup[] | 'all';
9
9
  }
10
+ export declare type DebugBodySettings = {
11
+ shape: any;
12
+ ignoreTransform?: boolean;
13
+ } & ({
14
+ type: 'RIGID_STATIC' | 'TRIGGER';
15
+ } | {
16
+ type: 'RIGID_DYNAMIC';
17
+ sleeping: boolean;
18
+ });
@@ -67,31 +67,39 @@ List of available commands: `.replace(/ /g, '&nbsp;') + `<span style="color:yell
67
67
  };
68
68
  document.getElementById('gg-console-close-icon').onmousedown = () => this.destroyUI();
69
69
  this.elements.input.onkeydown = event => {
70
- if ((event === null || event === void 0 ? void 0 : event.keyCode) === 13) {
70
+ var _a;
71
+ if ((event === null || event === void 0 ? void 0 : event.code) === 'Enter') {
71
72
  event.preventDefault();
72
73
  this.onInput().then();
73
74
  }
74
- else if ((event === null || event === void 0 ? void 0 : event.keyCode) === 38) {
75
+ else if ((event === null || event === void 0 ? void 0 : event.code) === 'ArrowUp') {
75
76
  event.preventDefault();
76
77
  this.onUsePreviousCommand();
77
78
  }
78
- else if ((event === null || event === void 0 ? void 0 : event.keyCode) === 40) {
79
+ else if ((event === null || event === void 0 ? void 0 : event.code) === 'ArrowDown') {
79
80
  event.preventDefault();
80
81
  this.onUseNextCommand();
81
82
  }
83
+ else if ((event === null || event === void 0 ? void 0 : event.code) === 'Backspace') {
84
+ let input = (_a = this.elements) === null || _a === void 0 ? void 0 : _a.input;
85
+ if (input) {
86
+ let value = input.value || '';
87
+ // backspace pressed while input had completion selected.
88
+ // Native logic will remove selected text (completion part), we remove one additional character
89
+ if ((input.selectionStart || value.length) < value.length && input.selectionEnd == value.length) {
90
+ this.elements.input.value = value.substring(0, input.selectionStart || value.length - 1);
91
+ }
92
+ }
93
+ }
82
94
  };
83
95
  this.elements.input.oninput = event => {
84
96
  var _a;
85
97
  let value = ((_a = this.elements) === null || _a === void 0 ? void 0 : _a.input.value) || '';
86
- // backspace
87
- if (value.length > 0 && event.data === null) {
88
- value = value.substring(0, value.length - 1);
89
- }
90
98
  if (value.trim() === '') {
91
99
  return;
92
100
  }
93
101
  let autocompletion = window.ggstatic.availableCommands.find((c) => c[0].startsWith(value));
94
- if (autocompletion) {
102
+ if (autocompletion && autocompletion[0].length > value.length) {
95
103
  this.elements.input.value = autocompletion[0];
96
104
  this.elements.input.setSelectionRange(value.length, this.elements.input.value.length);
97
105
  }
@@ -6,6 +6,10 @@ export declare class GgDebuggerUI {
6
6
  private currentWorld;
7
7
  setShowStats(selectedWorld: GgWorld<any, any>, value: boolean): void;
8
8
  private debugControlsRemoved$;
9
+ private viewUpdated$;
9
10
  get showDebugControls(): boolean;
10
11
  setShowDebugControls(selectedWorld: GgWorld<any, any>, value: boolean): void;
12
+ private snapshot;
13
+ private makeSnapshot;
14
+ private renderControls;
11
15
  }