@gg-web-engine/core 0.0.38 → 0.0.40
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/components/physics/i-rigid-body-2d.component.d.ts +3 -0
- package/dist/2d/components/physics/i-trigger-2d.component.d.ts +3 -0
- package/dist/2d/components/rendering/i-visual-scene-2d.component.d.ts +1 -1
- package/dist/2d/entities/i-renderable-2d.entity.d.ts +3 -1
- package/dist/2d/entities/i-renderable-2d.entity.js +7 -0
- package/dist/2d/gg-2d-world.d.ts +1 -0
- package/dist/2d/models/body-options.d.ts +5 -1
- package/dist/3d/components/physics/i-physics-world-3d.component.d.ts +7 -0
- package/dist/3d/components/physics/i-rigid-body-3d.component.d.ts +3 -0
- package/dist/3d/components/physics/i-trigger-3d.component.d.ts +3 -0
- package/dist/3d/components/rendering/i-visual-scene-3d.component.d.ts +1 -1
- package/dist/3d/entities/controllers/input/car-keyboard-handling.controller.js +2 -2
- package/dist/3d/entities/controllers/input/gg-car-keyboard-handling.controller.js +3 -3
- package/dist/3d/entities/i-renderable-3d.entity.d.ts +3 -1
- package/dist/3d/entities/i-renderable-3d.entity.js +7 -0
- package/dist/3d/entities/map-graph-3d.entity.d.ts +2 -3
- package/dist/3d/entities/map-graph-3d.entity.js +10 -7
- package/dist/3d/entities/raycast-vehicle-3d.entity.d.ts +2 -0
- package/dist/3d/entities/raycast-vehicle-3d.entity.js +15 -1
- package/dist/3d/factories.d.ts +3 -3
- package/dist/3d/gg-3d-world.d.ts +1 -0
- package/dist/3d/models/body-options.d.ts +5 -1
- package/dist/3d/models/shapes.d.ts +41 -1
- package/dist/base/clock/pausable-clock.d.ts +62 -1
- package/dist/base/clock/pausable-clock.js +102 -8
- package/dist/base/components/physics/i-body.component.d.ts +3 -1
- package/dist/base/components/physics/i-physics-world.component.d.ts +8 -6
- package/dist/base/components/rendering/i-renderer.component.d.ts +6 -2
- package/dist/base/components/rendering/i-visual-scene.component.d.ts +0 -4
- package/dist/base/entities/controllers/inline-controller.d.ts +1 -1
- package/dist/base/entities/controllers/inline-controller.js +4 -1
- package/dist/base/entities/i-entity.d.ts +1 -1
- package/dist/base/entities/i-entity.js +3 -3
- package/dist/base/entities/i-renderer.entity.d.ts +4 -0
- package/dist/base/entities/i-renderer.entity.js +8 -0
- package/dist/base/gg-world.d.ts +8 -5
- package/dist/base/gg-world.js +81 -39
- package/dist/base/index.d.ts +0 -1
- package/dist/base/index.js +0 -1
- package/dist/base/inputs/mouse.input.js +9 -4
- package/dist/base/models/body-options.d.ts +9 -0
- package/dist/dev/gg-console.ui.js +16 -8
- package/dist/dev/gg-debugger.ui.d.ts +9 -0
- package/dist/dev/gg-debugger.ui.js +206 -34
- package/dist/dev/gg-static.d.ts +0 -1
- package/dist/dev/gg-static.js +15 -8
- package/dist/dev/index.d.ts +1 -0
- package/dist/dev/index.js +1 -0
- package/dist/dev/performance-meter.entity.d.ts +21 -0
- package/dist/dev/performance-meter.entity.js +120 -0
- package/package.json +1 -1
- package/dist/base/interfaces/i-debug-physics-drawer.d.ts +0 -8
- package/dist/base/interfaces/i-debug-physics-drawer.js +0 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { IRigidBodyComponent, Point2 } from '../../../base';
|
|
2
2
|
import { PhysicsTypeDocRepo2D } from '../../gg-2d-world';
|
|
3
|
+
import { DebugBody2DSettings } from '../../models/body-options';
|
|
3
4
|
export interface IRigidBody2dComponent<TypeDoc extends PhysicsTypeDocRepo2D = PhysicsTypeDocRepo2D> extends IRigidBodyComponent<Point2, number, TypeDoc> {
|
|
4
5
|
angularVelocity: number;
|
|
6
|
+
/** body info for physics debugger view */
|
|
7
|
+
readonly debugBodySettings: DebugBody2DSettings;
|
|
5
8
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { ITriggerComponent, Point2 } from '../../../base';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { PhysicsTypeDocRepo2D } from '../../gg-2d-world';
|
|
4
|
+
import { DebugBody2DSettings } from '../../models/body-options';
|
|
4
5
|
export interface ITrigger2dComponent<TypeDoc extends PhysicsTypeDocRepo2D = PhysicsTypeDocRepo2D> extends ITriggerComponent<Point2, number, TypeDoc> {
|
|
6
|
+
/** body info for physics debugger view */
|
|
7
|
+
readonly debugBodySettings: DebugBody2DSettings;
|
|
5
8
|
get onEntityEntered(): Observable<TypeDoc['rigidBody']>;
|
|
6
9
|
get onEntityLeft(): Observable<TypeDoc['rigidBody'] | null>;
|
|
7
10
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IVisualSceneComponent, Point2, RendererOptions } from '../../../base';
|
|
2
2
|
import { VisualTypeDocRepo2D } from '../../gg-2d-world';
|
|
3
3
|
export interface IVisualScene2dComponent<TypeDoc extends VisualTypeDocRepo2D = VisualTypeDocRepo2D> extends IVisualSceneComponent<Point2, number, TypeDoc> {
|
|
4
|
-
createRenderer(canvas?: HTMLCanvasElement, rendererOptions?: Partial<RendererOptions>): TypeDoc['renderer'];
|
|
4
|
+
createRenderer(canvas?: HTMLCanvasElement, rendererOptions?: Partial<RendererOptions & TypeDoc['rendererExtraOpts']>): TypeDoc['renderer'];
|
|
5
5
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { IRenderableEntity, Point2 } from '../../base';
|
|
2
|
-
import { PhysicsTypeDocRepo2D, VisualTypeDocRepo2D } from '../gg-2d-world';
|
|
2
|
+
import { Gg2dWorld, PhysicsTypeDocRepo2D, VisualTypeDocRepo2D } from '../gg-2d-world';
|
|
3
3
|
export declare abstract class IRenderable2dEntity<TypeDoc extends VisualTypeDocRepo2D = VisualTypeDocRepo2D, PTypeDoc extends PhysicsTypeDocRepo2D = PhysicsTypeDocRepo2D> extends IRenderableEntity<Point2, number, TypeDoc, PTypeDoc> {
|
|
4
|
+
protected _world: Gg2dWorld<TypeDoc, PTypeDoc> | null;
|
|
5
|
+
get world(): Gg2dWorld<TypeDoc, PTypeDoc> | null;
|
|
4
6
|
}
|
package/dist/2d/gg-2d-world.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare type VisualTypeDocRepo2D = {
|
|
|
13
13
|
factory: IDisplayObject2dComponentFactory;
|
|
14
14
|
displayObject: IDisplayObject2dComponent;
|
|
15
15
|
renderer: IRenderer2dComponent;
|
|
16
|
+
rendererExtraOpts: {};
|
|
16
17
|
texture: unknown;
|
|
17
18
|
};
|
|
18
19
|
export declare type PhysicsTypeDocRepo2D = {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import { BodyOptions } from '../../base';
|
|
1
|
+
import { BodyOptions, DebugBodySettings } from '../../base';
|
|
2
|
+
import { Shape2DDescriptor } from './shapes';
|
|
2
3
|
export interface Body2DOptions extends BodyOptions {
|
|
3
4
|
}
|
|
5
|
+
export declare type DebugBody2DSettings = DebugBodySettings & {
|
|
6
|
+
shape: Shape2DDescriptor;
|
|
7
|
+
};
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { IPhysicsWorldComponent, Point3, Point4 } from '../../../base';
|
|
2
2
|
import { PhysicsTypeDocRepo3D } from '../../gg-3d-world';
|
|
3
|
+
import { Subject } from 'rxjs';
|
|
3
4
|
export interface IPhysicsWorld3dComponent<TypeDoc extends PhysicsTypeDocRepo3D = PhysicsTypeDocRepo3D> extends IPhysicsWorldComponent<Point3, Point4, TypeDoc> {
|
|
4
5
|
readonly loader: TypeDoc['loader'];
|
|
6
|
+
/** event emitter, emits newly added physics components */
|
|
7
|
+
readonly added$: Subject<TypeDoc['trigger'] | TypeDoc['rigidBody'] | TypeDoc['raycastVehicle'] | any>;
|
|
8
|
+
/** event emitter, emits just removed physics components */
|
|
9
|
+
readonly removed$: Subject<TypeDoc['trigger'] | TypeDoc['rigidBody'] | TypeDoc['raycastVehicle'] | any>;
|
|
10
|
+
/** list of currently added to world physics components */
|
|
11
|
+
readonly children: (TypeDoc['trigger'] | TypeDoc['rigidBody'] | TypeDoc['raycastVehicle'] | any)[];
|
|
5
12
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { IRigidBodyComponent, Point3, Point4 } from '../../../base';
|
|
2
2
|
import { PhysicsTypeDocRepo3D } from '../../gg-3d-world';
|
|
3
|
+
import { DebugBody3DSettings } from '../../models/body-options';
|
|
3
4
|
export interface IRigidBody3dComponent<TypeDoc extends PhysicsTypeDocRepo3D = PhysicsTypeDocRepo3D> extends IRigidBodyComponent<Point3, Point4, TypeDoc> {
|
|
4
5
|
angularVelocity: Point3;
|
|
6
|
+
/** body info for physics debugger view */
|
|
7
|
+
readonly debugBodySettings: DebugBody3DSettings;
|
|
5
8
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { ITriggerComponent, Point3, Point4 } from '../../../base';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { PhysicsTypeDocRepo3D } from '../../gg-3d-world';
|
|
4
|
+
import { DebugBody3DSettings } from '../../models/body-options';
|
|
4
5
|
export interface ITrigger3dComponent<TypeDoc extends PhysicsTypeDocRepo3D = PhysicsTypeDocRepo3D> extends ITriggerComponent<Point3, Point4, TypeDoc> {
|
|
6
|
+
/** body info for physics debugger view */
|
|
7
|
+
readonly debugBodySettings: DebugBody3DSettings;
|
|
5
8
|
get onEntityEntered(): Observable<TypeDoc['rigidBody']>;
|
|
6
9
|
get onEntityLeft(): Observable<TypeDoc['rigidBody'] | null>;
|
|
7
10
|
}
|
|
@@ -2,5 +2,5 @@ import { IVisualSceneComponent, Point3, Point4, RendererOptions } from '../../..
|
|
|
2
2
|
import { VisualTypeDocRepo3D } from '../../gg-3d-world';
|
|
3
3
|
export interface IVisualScene3dComponent<TypeDoc extends VisualTypeDocRepo3D = VisualTypeDocRepo3D> extends IVisualSceneComponent<Point3, Point4, TypeDoc> {
|
|
4
4
|
readonly loader: TypeDoc['loader'];
|
|
5
|
-
createRenderer(camera: TypeDoc['camera'], canvas?: HTMLCanvasElement, rendererOptions?: Partial<RendererOptions>): TypeDoc['renderer'];
|
|
5
|
+
createRenderer(camera: TypeDoc['camera'], canvas?: HTMLCanvasElement, rendererOptions?: Partial<RendererOptions & TypeDoc['rendererExtraOpts']>): TypeDoc['renderer'];
|
|
6
6
|
}
|
|
@@ -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 { combineLatest, Subject, takeUntil } from 'rxjs';
|
|
10
|
+
import { combineLatest, filter, Subject, takeUntil } from 'rxjs';
|
|
11
11
|
import { DirectionKeyboardInput, IEntity, TickOrder, } from '../../../../base';
|
|
12
12
|
export class CarKeyboardHandlingController extends IEntity {
|
|
13
13
|
constructor(keyboard, options = {
|
|
@@ -32,7 +32,7 @@ export class CarKeyboardHandlingController extends IEntity {
|
|
|
32
32
|
_super.onSpawned.call(this, world);
|
|
33
33
|
let input = { upDown: 0, leftRight: 0 };
|
|
34
34
|
combineLatest([this.directionsInput.output$, this.tick$])
|
|
35
|
-
.pipe(takeUntil(this._onRemoved$))
|
|
35
|
+
.pipe(filter(() => this.active), takeUntil(this._onRemoved$))
|
|
36
36
|
.subscribe(([d, [_, dt]]) => {
|
|
37
37
|
const direction = { upDown: 0, leftRight: 0 };
|
|
38
38
|
if (d.leftRight !== undefined)
|
|
@@ -64,7 +64,7 @@ export class GgCarKeyboardHandlingController extends IEntity {
|
|
|
64
64
|
});
|
|
65
65
|
this.keyboard
|
|
66
66
|
.bind(this.options.gearUpDownKeys[0])
|
|
67
|
-
.pipe(takeUntil(this._onRemoved$), filter(x => this.switchingGearsEnabled && !!x))
|
|
67
|
+
.pipe(takeUntil(this._onRemoved$), filter(x => this.active && this.switchingGearsEnabled && !!x))
|
|
68
68
|
.subscribe(() => {
|
|
69
69
|
if (this.car && (!this.car.carProperties.transmission.isAuto || this.car.gear <= 0)) {
|
|
70
70
|
this.car.gear++;
|
|
@@ -72,7 +72,7 @@ export class GgCarKeyboardHandlingController extends IEntity {
|
|
|
72
72
|
});
|
|
73
73
|
this.keyboard
|
|
74
74
|
.bind(this.options.gearUpDownKeys[1])
|
|
75
|
-
.pipe(takeUntil(this._onRemoved$), filter(x => this.switchingGearsEnabled && !!x))
|
|
75
|
+
.pipe(takeUntil(this._onRemoved$), filter(x => this.active && this.switchingGearsEnabled && !!x))
|
|
76
76
|
.subscribe(() => {
|
|
77
77
|
if (this.car) {
|
|
78
78
|
if (this.car.carProperties.transmission.isAuto && this.car.gear > 1) {
|
|
@@ -85,7 +85,7 @@ export class GgCarKeyboardHandlingController extends IEntity {
|
|
|
85
85
|
});
|
|
86
86
|
this.keyboard
|
|
87
87
|
.bind(this.options.handbrakeKey)
|
|
88
|
-
.pipe(takeUntil(this._onRemoved$))
|
|
88
|
+
.pipe(takeUntil(this._onRemoved$), filter(() => this.active))
|
|
89
89
|
.subscribe(isKeyDown => {
|
|
90
90
|
if (this.car) {
|
|
91
91
|
this.car.handBrake = isKeyDown;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { IRenderableEntity, Point3, Point4 } from '../../base';
|
|
2
|
-
import { PhysicsTypeDocRepo3D, VisualTypeDocRepo3D } from '../gg-3d-world';
|
|
2
|
+
import { Gg3dWorld, PhysicsTypeDocRepo3D, VisualTypeDocRepo3D } from '../gg-3d-world';
|
|
3
3
|
export declare abstract class IRenderable3dEntity<TypeDoc extends VisualTypeDocRepo3D = VisualTypeDocRepo3D, PTypeDoc extends PhysicsTypeDocRepo3D = PhysicsTypeDocRepo3D> extends IRenderableEntity<Point3, Point4, TypeDoc, PTypeDoc> {
|
|
4
|
+
protected _world: Gg3dWorld<TypeDoc, PTypeDoc> | null;
|
|
5
|
+
get world(): Gg3dWorld<TypeDoc, PTypeDoc> | null;
|
|
4
6
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BehaviorSubject, Observable, Subject } from 'rxjs';
|
|
2
|
-
import { Graph, IEntity, Point3, Point4, TickOrder } from '../../base';
|
|
2
|
+
import { Graph, IEntity, PausableClock, Point3, Point4, TickOrder } from '../../base';
|
|
3
3
|
import { Gg3dWorld, PhysicsTypeDocRepo3D, VisualTypeDocRepo3D } from '../gg-3d-world';
|
|
4
4
|
import { Entity3d } from './entity-3d';
|
|
5
5
|
import { LoadOptions, LoadResultWithProps } from '../loader';
|
|
@@ -60,10 +60,9 @@ export declare class MapGraph3dEntity<VTypeDoc extends VisualTypeDocRepo3D = Vis
|
|
|
60
60
|
rotation: Point4;
|
|
61
61
|
}
|
|
62
62
|
]>;
|
|
63
|
-
get world(): Gg3dWorld<VTypeDoc, PTypeDoc> | null;
|
|
64
|
-
protected _world: Gg3dWorld<VTypeDoc, PTypeDoc> | null;
|
|
65
63
|
protected readonly mapGraphNodes: MapGraph[];
|
|
66
64
|
protected readonly options: Gg3dMapGraphEntityOptions;
|
|
65
|
+
protected loadClock: PausableClock | null;
|
|
67
66
|
constructor(mapGraph: MapGraph, options?: Partial<Gg3dMapGraphEntityOptions>);
|
|
68
67
|
onSpawned(world: Gg3dWorld<VTypeDoc, PTypeDoc>): void;
|
|
69
68
|
onRemoved(): void;
|
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { BehaviorSubject, NEVER, startWith, Subject, switchMap, takeUntil } from 'rxjs';
|
|
11
|
-
import { distinctUntilChanged, map, tap
|
|
11
|
+
import { distinctUntilChanged, map, tap } from 'rxjs/operators';
|
|
12
12
|
import { Graph, Qtrn, TickOrder } from '../../base';
|
|
13
13
|
import { IRenderable3dEntity } from './i-renderable-3d.entity';
|
|
14
14
|
export class MapGraph extends Graph {
|
|
@@ -90,7 +90,7 @@ export class MapGraph3dEntity extends IRenderable3dEntity {
|
|
|
90
90
|
this._initialLoadComplete$ = new BehaviorSubject(false);
|
|
91
91
|
this._nearestDummy$ = new BehaviorSubject(null);
|
|
92
92
|
this._chunkLoaded$ = new Subject();
|
|
93
|
-
this.
|
|
93
|
+
this.loadClock = null;
|
|
94
94
|
this.options = Object.assign(Object.assign({}, defaultOptions), options);
|
|
95
95
|
this.mapGraphNodes = mapGraph.nodes();
|
|
96
96
|
}
|
|
@@ -103,15 +103,14 @@ export class MapGraph3dEntity extends IRenderable3dEntity {
|
|
|
103
103
|
get chunkLoaded$() {
|
|
104
104
|
return this._chunkLoaded$.asObservable();
|
|
105
105
|
}
|
|
106
|
-
get world() {
|
|
107
|
-
return this._world;
|
|
108
|
-
}
|
|
109
106
|
onSpawned(world) {
|
|
110
107
|
super.onSpawned(world);
|
|
108
|
+
this.loadClock = world.createClock(true);
|
|
109
|
+
this.loadClock.tickRateLimit = 1;
|
|
111
110
|
this.loaderCursorEntity$
|
|
112
111
|
.pipe(takeUntil(this._onRemoved$), switchMap(entity => entity
|
|
113
|
-
? this.tick$.pipe(startWith(null), // map will perform initial loading even if world not started yet. Handy to preload map
|
|
114
|
-
takeUntil(entity.onRemoved$),
|
|
112
|
+
? this.loadClock.tick$.pipe(startWith(null), // map will perform initial loading even if world not started yet. Handy to preload map
|
|
113
|
+
takeUntil(entity.onRemoved$), map(() => entity.position))
|
|
115
114
|
: NEVER), map(pos => this.mapGraph.getNearestDummy(this.mapGraphNodes, pos)), tap(node => this._nearestDummy$.next(node)), distinctUntilChanged())
|
|
116
115
|
.subscribe(currentChunk => {
|
|
117
116
|
let haveToBeLoaded = new Set();
|
|
@@ -143,6 +142,10 @@ export class MapGraph3dEntity extends IRenderable3dEntity {
|
|
|
143
142
|
}
|
|
144
143
|
onRemoved() {
|
|
145
144
|
super.onRemoved();
|
|
145
|
+
if (this.loadClock) {
|
|
146
|
+
this.loadClock.stop();
|
|
147
|
+
this.loadClock = null;
|
|
148
|
+
}
|
|
146
149
|
this.loaderCursorEntity$.next(null);
|
|
147
150
|
}
|
|
148
151
|
loadChunk(node) {
|
|
@@ -51,6 +51,8 @@ export declare class RaycastVehicle3dEntity<VTypeDoc extends VisualTypeDocRepo3D
|
|
|
51
51
|
protected readonly wheelLocalRotation: (Point4 | null)[];
|
|
52
52
|
protected readonly frontWheelsIndices: number[];
|
|
53
53
|
protected readonly rearWheelsIndices: number[];
|
|
54
|
+
get name(): string;
|
|
55
|
+
set name(value: string);
|
|
54
56
|
getSpeed(): number;
|
|
55
57
|
readonly tractionWheelRadius: number;
|
|
56
58
|
private _steeringAngle;
|
|
@@ -93,11 +93,25 @@ export class RaycastVehicle3dEntity extends Entity3d {
|
|
|
93
93
|
localRotation = { x: 0, y: 0.707107 * (flip ? 1 : -1), z: 0, w: 0.707107 };
|
|
94
94
|
}
|
|
95
95
|
this.wheelLocalRotation.push(localRotation);
|
|
96
|
-
|
|
96
|
+
const wheelEntity = new Entity3d(entity);
|
|
97
|
+
wheelEntity.name = this.name + '__wheel_' + (options.isFront ? 'f' : 'r') + (options.isLeft ? 'l' : 'r');
|
|
98
|
+
this.wheels.push(wheelEntity);
|
|
97
99
|
}
|
|
98
100
|
this.addChildren(...this.wheels.filter(x => !!x));
|
|
99
101
|
this.vehicleComponent.entity = this;
|
|
100
102
|
}
|
|
103
|
+
get name() {
|
|
104
|
+
return super.name;
|
|
105
|
+
}
|
|
106
|
+
set name(value) {
|
|
107
|
+
const oldName = super.name;
|
|
108
|
+
super.name = value;
|
|
109
|
+
for (const w of this.wheels || []) {
|
|
110
|
+
if (w) {
|
|
111
|
+
w.name = w.name.replace(oldName, value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
101
115
|
// m/s
|
|
102
116
|
getSpeed() {
|
|
103
117
|
return this.vehicleComponent.wheelSpeed;
|
package/dist/3d/factories.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { BodyShape3DDescriptor, Shape3DDescriptor } from './models/shapes';
|
|
1
|
+
import { BodyShape3DDescriptor, Shape3DDescriptor, Shape3DMeshDescriptor } from './models/shapes';
|
|
2
2
|
import { Point3, Point4 } from '../base';
|
|
3
3
|
import { PhysicsTypeDocRepo3D, VisualTypeDocRepo3D } from './gg-3d-world';
|
|
4
4
|
export declare type DisplayObject3dOpts<Tex> = {
|
|
5
5
|
color?: number;
|
|
6
|
-
shading?: 'unlit' | 'standart' | 'phong';
|
|
6
|
+
shading?: 'unlit' | 'standart' | 'phong' | 'wireframe';
|
|
7
7
|
diffuse?: Tex;
|
|
8
8
|
castShadow?: boolean;
|
|
9
9
|
receiveShadow?: boolean;
|
|
10
10
|
};
|
|
11
11
|
export declare abstract class IDisplayObject3dComponentFactory<TypeDoc extends VisualTypeDocRepo3D = VisualTypeDocRepo3D> {
|
|
12
|
-
abstract createPrimitive(descriptor:
|
|
12
|
+
abstract createPrimitive(descriptor: Shape3DMeshDescriptor, material?: DisplayObject3dOpts<TypeDoc['texture']>): TypeDoc['displayObject'];
|
|
13
13
|
abstract createPerspectiveCamera(settings: {
|
|
14
14
|
fov?: number;
|
|
15
15
|
aspectRatio?: number;
|
package/dist/3d/gg-3d-world.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import { BodyOptions } from '../../base';
|
|
1
|
+
import { BodyOptions, DebugBodySettings } from '../../base';
|
|
2
|
+
import { Shape3DDescriptor } from './shapes';
|
|
2
3
|
export interface Body3DOptions extends BodyOptions {
|
|
3
4
|
}
|
|
5
|
+
export declare type DebugBody3DSettings = DebugBodySettings & {
|
|
6
|
+
shape: Shape3DDescriptor;
|
|
7
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Point3, Point4 } from '../../base';
|
|
1
|
+
import { Point2, Point3, Point4 } from '../../base';
|
|
2
2
|
import { Body3DOptions } from './body-options';
|
|
3
3
|
export declare type Shape3DDescriptor = {
|
|
4
4
|
shape: 'PLANE';
|
|
@@ -31,6 +31,46 @@ export declare type Shape3DDescriptor = {
|
|
|
31
31
|
vertices: Point3[];
|
|
32
32
|
faces: [number, number, number][];
|
|
33
33
|
};
|
|
34
|
+
export declare type Shape3DMeshDescriptor = {
|
|
35
|
+
shape: 'PLANE';
|
|
36
|
+
dimensions?: Point2;
|
|
37
|
+
segments?: Point2;
|
|
38
|
+
} | {
|
|
39
|
+
shape: 'BOX';
|
|
40
|
+
dimensions: Point3;
|
|
41
|
+
segments?: Point3;
|
|
42
|
+
} | {
|
|
43
|
+
shape: 'CONE' | 'CYLINDER';
|
|
44
|
+
radius: number;
|
|
45
|
+
height: number;
|
|
46
|
+
radialSegments?: number;
|
|
47
|
+
heightSegments?: number;
|
|
48
|
+
} | {
|
|
49
|
+
shape: 'CAPSULE';
|
|
50
|
+
radius: number;
|
|
51
|
+
centersDistance: number;
|
|
52
|
+
capSegments?: number;
|
|
53
|
+
radialSegments?: number;
|
|
54
|
+
} | {
|
|
55
|
+
shape: 'SPHERE';
|
|
56
|
+
radius: number;
|
|
57
|
+
widthSegments?: number;
|
|
58
|
+
heightSegments?: number;
|
|
59
|
+
} | {
|
|
60
|
+
shape: 'COMPOUND';
|
|
61
|
+
children: {
|
|
62
|
+
position?: Point3;
|
|
63
|
+
rotation?: Point4;
|
|
64
|
+
shape: Shape3DMeshDescriptor;
|
|
65
|
+
}[];
|
|
66
|
+
} | {
|
|
67
|
+
shape: 'CONVEX_HULL';
|
|
68
|
+
vertices: Point3[];
|
|
69
|
+
} | {
|
|
70
|
+
shape: 'MESH';
|
|
71
|
+
vertices: Point3[];
|
|
72
|
+
faces: [number, number, number][];
|
|
73
|
+
};
|
|
34
74
|
export declare type BodyShape3DDescriptor = {
|
|
35
75
|
shape: Shape3DDescriptor;
|
|
36
76
|
body: Partial<Body3DOptions>;
|
|
@@ -1,25 +1,86 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { IClock } from './i-clock';
|
|
3
3
|
/**
|
|
4
|
-
* A class
|
|
4
|
+
* A class providing the ability to track time, fire ticks, provide time elapsed, and tick delta with the ability to suspend/resume it.
|
|
5
5
|
*/
|
|
6
6
|
export declare class PausableClock implements IClock {
|
|
7
7
|
protected readonly parentClock: IClock;
|
|
8
8
|
private tickSub;
|
|
9
|
+
private readonly _internalTick$;
|
|
9
10
|
private readonly _tick$;
|
|
11
|
+
/**
|
|
12
|
+
* Observable stream of ticks, emitting an array containing the current time and the tick delta.
|
|
13
|
+
*/
|
|
10
14
|
get tick$(): Observable<[number, number]>;
|
|
15
|
+
/**
|
|
16
|
+
* Checks if the clock is currently running.
|
|
17
|
+
*/
|
|
11
18
|
get isRunning(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if the clock is currently paused.
|
|
21
|
+
*/
|
|
12
22
|
get isPaused(): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Checks if the clock is stopped.
|
|
25
|
+
*/
|
|
26
|
+
get isStopped(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Gets the time scale of the clock.
|
|
29
|
+
*/
|
|
30
|
+
get timeScale(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Sets the time scale of the clock.
|
|
33
|
+
*/
|
|
34
|
+
set timeScale(value: number);
|
|
35
|
+
/**
|
|
36
|
+
* Gets the elapsed time since the clock started.
|
|
37
|
+
*/
|
|
13
38
|
get elapsedTime(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Tick rate limiter. If set to 0 - tick rate is unlimited, 15 means "allow at most 15 ticks per second"
|
|
41
|
+
*/
|
|
42
|
+
tickRateLimit: number;
|
|
14
43
|
private startedAt;
|
|
15
44
|
private oldRelativeTime;
|
|
16
45
|
private pausedAt;
|
|
46
|
+
private lastStopElapsed;
|
|
47
|
+
private _timeScale;
|
|
48
|
+
private pausedByTimescale;
|
|
49
|
+
private lastFiredTickElapsed;
|
|
50
|
+
/**
|
|
51
|
+
* Constructs a new PausableClock instance.
|
|
52
|
+
* @param autoStart Indicates whether the clock should start automatically upon creation.
|
|
53
|
+
* @param parentClock The parent clock to synchronize with. Defaults to GgGlobalClock instance.
|
|
54
|
+
*/
|
|
17
55
|
constructor(autoStart?: boolean, parentClock?: IClock);
|
|
56
|
+
/**
|
|
57
|
+
* Creates a child clock.
|
|
58
|
+
* @param autoStart Indicates whether the child clock should start automatically.
|
|
59
|
+
* @returns A new instance of PausableClock.
|
|
60
|
+
*/
|
|
18
61
|
createChildClock(autoStart: boolean): PausableClock;
|
|
62
|
+
/**
|
|
63
|
+
* Starts the clock.
|
|
64
|
+
*/
|
|
19
65
|
start(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Stops the clock.
|
|
68
|
+
*/
|
|
20
69
|
stop(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Pauses the clock.
|
|
72
|
+
*/
|
|
21
73
|
pause(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Resumes the clock.
|
|
76
|
+
*/
|
|
22
77
|
resume(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Starts listening for ticks from the parent clock.
|
|
80
|
+
*/
|
|
23
81
|
protected startListeningTicks(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Stops listening for ticks from the parent clock.
|
|
84
|
+
*/
|
|
24
85
|
protected stopListeningTicks(): void;
|
|
25
86
|
}
|
|
@@ -1,40 +1,117 @@
|
|
|
1
|
-
import { Subject } from 'rxjs';
|
|
1
|
+
import { filter, Subject } from 'rxjs';
|
|
2
2
|
import { map, tap } from 'rxjs/operators';
|
|
3
3
|
import { GgGlobalClock } from './global-clock';
|
|
4
4
|
/**
|
|
5
|
-
* A class
|
|
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;
|
|
16
|
+
this._internalTick$ = new Subject();
|
|
11
17
|
this._tick$ = new Subject();
|
|
12
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Tick rate limiter. If set to 0 - tick rate is unlimited, 15 means "allow at most 15 ticks per second"
|
|
20
|
+
*/
|
|
21
|
+
this.tickRateLimit = 0;
|
|
22
|
+
// State variables
|
|
13
23
|
this.startedAt = -1;
|
|
14
24
|
this.oldRelativeTime = 0; // "elapsed", emitted on last tick
|
|
15
25
|
this.pausedAt = -1;
|
|
26
|
+
this.lastStopElapsed = 0;
|
|
27
|
+
this._timeScale = 1;
|
|
28
|
+
this.pausedByTimescale = false;
|
|
29
|
+
this.lastFiredTickElapsed = 0;
|
|
16
30
|
if (autoStart) {
|
|
17
31
|
this.start();
|
|
18
32
|
}
|
|
33
|
+
this._internalTick$
|
|
34
|
+
.pipe(map(([_, newTime]) => [newTime, newTime - this.lastFiredTickElapsed]), filter(([elapsed]) => !this.tickRateLimit ||
|
|
35
|
+
Math.floor((this.lastFiredTickElapsed * this.tickRateLimit) / 1000) <
|
|
36
|
+
Math.floor((elapsed * this.tickRateLimit) / 1000)), tap(([elapsed]) => (this.lastFiredTickElapsed = elapsed)))
|
|
37
|
+
.subscribe(this._tick$);
|
|
19
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Observable stream of ticks, emitting an array containing the current time and the tick delta.
|
|
41
|
+
*/
|
|
20
42
|
get tick$() {
|
|
21
|
-
return this._tick$.
|
|
43
|
+
return this._tick$.asObservable();
|
|
22
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Checks if the clock is currently running.
|
|
47
|
+
*/
|
|
23
48
|
get isRunning() {
|
|
24
49
|
return !!this.tickSub;
|
|
25
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks if the clock is currently paused.
|
|
53
|
+
*/
|
|
26
54
|
get isPaused() {
|
|
27
55
|
return this.pausedAt !== -1;
|
|
28
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Checks if the clock is stopped.
|
|
59
|
+
*/
|
|
60
|
+
get isStopped() {
|
|
61
|
+
return this.startedAt === -1;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets the time scale of the clock.
|
|
65
|
+
*/
|
|
66
|
+
get timeScale() {
|
|
67
|
+
return this._timeScale;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sets the time scale of the clock.
|
|
71
|
+
*/
|
|
72
|
+
set timeScale(value) {
|
|
73
|
+
if (value === this._timeScale && !(this.pausedByTimescale && value !== 0))
|
|
74
|
+
return;
|
|
75
|
+
if (value === 0) {
|
|
76
|
+
if (!this.isPaused) {
|
|
77
|
+
this.pause();
|
|
78
|
+
this.pausedByTimescale = true;
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (this.isPaused && this.pausedByTimescale) {
|
|
83
|
+
this.resume();
|
|
84
|
+
this.pausedByTimescale = false;
|
|
85
|
+
}
|
|
86
|
+
if (!this.isStopped) {
|
|
87
|
+
const cur = this.isPaused ? this.pausedAt : this.parentClock.elapsedTime;
|
|
88
|
+
this.startedAt = cur - ((cur - this.startedAt) * this.timeScale) / value;
|
|
89
|
+
}
|
|
90
|
+
this._timeScale = value;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Gets the elapsed time since the clock started.
|
|
94
|
+
*/
|
|
29
95
|
get elapsedTime() {
|
|
96
|
+
if (this.isStopped) {
|
|
97
|
+
return this.lastStopElapsed;
|
|
98
|
+
}
|
|
30
99
|
if (this.isPaused) {
|
|
31
|
-
return this.pausedAt - this.startedAt;
|
|
100
|
+
return this._timeScale * (this.pausedAt - this.startedAt);
|
|
32
101
|
}
|
|
33
|
-
return this.parentClock.elapsedTime - this.startedAt;
|
|
102
|
+
return this._timeScale * (this.parentClock.elapsedTime - this.startedAt);
|
|
34
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Creates a child clock.
|
|
106
|
+
* @param autoStart Indicates whether the child clock should start automatically.
|
|
107
|
+
* @returns A new instance of PausableClock.
|
|
108
|
+
*/
|
|
35
109
|
createChildClock(autoStart) {
|
|
36
110
|
return new PausableClock(autoStart, this);
|
|
37
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Starts the clock.
|
|
114
|
+
*/
|
|
38
115
|
start() {
|
|
39
116
|
if (this.isRunning) {
|
|
40
117
|
return;
|
|
@@ -43,14 +120,25 @@ export class PausableClock {
|
|
|
43
120
|
this.startedAt = this.parentClock.elapsedTime;
|
|
44
121
|
this.startListeningTicks();
|
|
45
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Stops the clock.
|
|
125
|
+
*/
|
|
46
126
|
stop() {
|
|
47
127
|
this.stopListeningTicks();
|
|
128
|
+
this.lastStopElapsed = this.elapsedTime;
|
|
48
129
|
this.startedAt = this.pausedAt = -1;
|
|
49
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Pauses the clock.
|
|
133
|
+
*/
|
|
50
134
|
pause() {
|
|
51
135
|
this.stopListeningTicks();
|
|
52
136
|
this.pausedAt = this.parentClock.elapsedTime;
|
|
137
|
+
this.pausedByTimescale = false;
|
|
53
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Resumes the clock.
|
|
141
|
+
*/
|
|
54
142
|
resume() {
|
|
55
143
|
if (this.isRunning || this.pausedAt == -1) {
|
|
56
144
|
return;
|
|
@@ -59,14 +147,20 @@ export class PausableClock {
|
|
|
59
147
|
this.pausedAt = -1;
|
|
60
148
|
this.startListeningTicks();
|
|
61
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Starts listening for ticks from the parent clock.
|
|
152
|
+
*/
|
|
62
153
|
startListeningTicks() {
|
|
63
154
|
if (this.tickSub) {
|
|
64
155
|
throw new Error('Clock is already ticking!');
|
|
65
156
|
}
|
|
66
157
|
this.tickSub = this.parentClock.tick$
|
|
67
|
-
.pipe(map(([
|
|
68
|
-
.subscribe(this.
|
|
158
|
+
.pipe(map(([_, d]) => [this.oldRelativeTime, this.oldRelativeTime + d * this.timeScale]), tap(([_, cur]) => (this.oldRelativeTime = cur)))
|
|
159
|
+
.subscribe(this._internalTick$);
|
|
69
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Stops listening for ticks from the parent clock.
|
|
163
|
+
*/
|
|
70
164
|
stopListeningTicks() {
|
|
71
165
|
var _a;
|
|
72
166
|
(_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;
|