@gg-web-engine/core 0.0.1
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/.prettierrc +8 -0
- package/README.md +8 -0
- package/blender_exporter/build_blender_scene.py +180 -0
- package/blender_exporter/spherical_to_cube_texture.py +116 -0
- package/dist/2d/entities/gg-2d-entity.d.ts +20 -0
- package/dist/2d/entities/gg-2d-entity.js +84 -0
- package/dist/2d/entities/gg-2d-trigger.entity.d.ts +10 -0
- package/dist/2d/entities/gg-2d-trigger.entity.js +17 -0
- package/dist/2d/entities/gg-positionable-2d-entity.d.ts +7 -0
- package/dist/2d/entities/gg-positionable-2d-entity.js +16 -0
- package/dist/2d/factories.d.ts +18 -0
- package/dist/2d/factories.js +13 -0
- package/dist/2d/gg-2d-world.d.ts +9 -0
- package/dist/2d/gg-2d-world.js +34 -0
- package/dist/2d/interfaces.d.ts +26 -0
- package/dist/2d/interfaces.js +7 -0
- package/dist/2d/models/body-options.d.ts +3 -0
- package/dist/2d/models/body-options.js +2 -0
- package/dist/2d/models/shapes.d.ts +13 -0
- package/dist/2d/models/shapes.js +2 -0
- package/dist/3d/controllers/car-keyboard.controller.d.ts +25 -0
- package/dist/3d/controllers/car-keyboard.controller.js +98 -0
- package/dist/3d/controllers/free-camera.controller.d.ts +23 -0
- package/dist/3d/controllers/free-camera.controller.js +79 -0
- package/dist/3d/entities/controllers/entity-motion.controller.d.ts +32 -0
- package/dist/3d/entities/controllers/entity-motion.controller.js +100 -0
- package/dist/3d/entities/gg-3d-camera.entity.d.ts +7 -0
- package/dist/3d/entities/gg-3d-camera.entity.js +12 -0
- package/dist/3d/entities/gg-3d-entity.d.ts +25 -0
- package/dist/3d/entities/gg-3d-entity.js +108 -0
- package/dist/3d/entities/gg-3d-map-graph.entity.d.ts +51 -0
- package/dist/3d/entities/gg-3d-map-graph.entity.js +164 -0
- package/dist/3d/entities/gg-3d-raycast-vehicle.entity.d.ts +107 -0
- package/dist/3d/entities/gg-3d-raycast-vehicle.entity.js +372 -0
- package/dist/3d/entities/gg-3d-trigger.entity.d.ts +10 -0
- package/dist/3d/entities/gg-3d-trigger.entity.js +21 -0
- package/dist/3d/entities/gg-positionable-3d-entity.d.ts +11 -0
- package/dist/3d/entities/gg-positionable-3d-entity.js +27 -0
- package/dist/3d/factories.d.ts +21 -0
- package/dist/3d/factories.js +22 -0
- package/dist/3d/gg-3d-world.d.ts +11 -0
- package/dist/3d/gg-3d-world.js +36 -0
- package/dist/3d/interfaces.d.ts +65 -0
- package/dist/3d/interfaces.js +40 -0
- package/dist/3d/loader.d.ts +40 -0
- package/dist/3d/loader.js +129 -0
- package/dist/3d/models/body-options.d.ts +3 -0
- package/dist/3d/models/body-options.js +2 -0
- package/dist/3d/models/gg-meta.d.ts +22 -0
- package/dist/3d/models/gg-meta.js +2 -0
- package/dist/3d/models/shapes.d.ts +35 -0
- package/dist/3d/models/shapes.js +2 -0
- package/dist/base/clock.d.ts +26 -0
- package/dist/base/clock.js +82 -0
- package/dist/base/controllers/common.d.ts +8 -0
- package/dist/base/controllers/common.js +32 -0
- package/dist/base/controllers/i-controller.d.ts +4 -0
- package/dist/base/controllers/i-controller.js +2 -0
- package/dist/base/controllers/keyboard.controller.d.ts +16 -0
- package/dist/base/controllers/keyboard.controller.js +109 -0
- package/dist/base/controllers/mouse.controller.d.ts +24 -0
- package/dist/base/controllers/mouse.controller.js +68 -0
- package/dist/base/data-structures/graph.d.ts +20 -0
- package/dist/base/data-structures/graph.js +118 -0
- package/dist/base/entities/base-gg-renderer.d.ts +28 -0
- package/dist/base/entities/base-gg-renderer.js +49 -0
- package/dist/base/entities/gg-entity.d.ts +14 -0
- package/dist/base/entities/gg-entity.js +55 -0
- package/dist/base/entities/gg-positionable-entity.d.ts +23 -0
- package/dist/base/entities/gg-positionable-entity.js +47 -0
- package/dist/base/entities/inline-controller.d.ts +3 -0
- package/dist/base/entities/inline-controller.js +25 -0
- package/dist/base/entities/interfaces/i-tick-listener.d.ts +7 -0
- package/dist/base/entities/interfaces/i-tick-listener.js +6 -0
- package/dist/base/gg-static.d.ts +9 -0
- package/dist/base/gg-static.js +40 -0
- package/dist/base/gg-viewport-manager.d.ts +14 -0
- package/dist/base/gg-viewport-manager.js +125 -0
- package/dist/base/gg-viewport.d.ts +23 -0
- package/dist/base/gg-viewport.js +123 -0
- package/dist/base/gg-world.d.ts +32 -0
- package/dist/base/gg-world.js +172 -0
- package/dist/base/interfaces/gg-body.d.ts +15 -0
- package/dist/base/interfaces/gg-body.js +2 -0
- package/dist/base/interfaces/gg-debug-physics-drawer.d.ts +7 -0
- package/dist/base/interfaces/gg-debug-physics-drawer.js +2 -0
- package/dist/base/interfaces/gg-object.d.ts +16 -0
- package/dist/base/interfaces/gg-object.js +2 -0
- package/dist/base/interfaces/gg-physics-world.d.ts +18 -0
- package/dist/base/interfaces/gg-physics-world.js +2 -0
- package/dist/base/interfaces/gg-trigger.d.ts +8 -0
- package/dist/base/interfaces/gg-trigger.js +2 -0
- package/dist/base/interfaces/gg-visual-scene.d.ts +9 -0
- package/dist/base/interfaces/gg-visual-scene.js +2 -0
- package/dist/base/math/box.d.ts +5 -0
- package/dist/base/math/box.js +21 -0
- package/dist/base/math/matrix4.d.ts +5 -0
- package/dist/base/math/matrix4.js +33 -0
- package/dist/base/math/numbers.d.ts +2 -0
- package/dist/base/math/numbers.js +14 -0
- package/dist/base/math/point2.d.ts +15 -0
- package/dist/base/math/point2.js +40 -0
- package/dist/base/math/point3.d.ts +25 -0
- package/dist/base/math/point3.js +104 -0
- package/dist/base/math/quaternion.d.ts +28 -0
- package/dist/base/math/quaternion.js +145 -0
- package/dist/base/models/axis-directions.d.ts +3 -0
- package/dist/base/models/axis-directions.js +2 -0
- package/dist/base/models/body-options.d.ts +6 -0
- package/dist/base/models/body-options.js +2 -0
- package/dist/base/models/geometry-nodes.d.ts +7 -0
- package/dist/base/models/geometry-nodes.js +2 -0
- package/dist/base/models/points.d.ts +15 -0
- package/dist/base/models/points.js +2 -0
- package/dist/base/ui/gg-console.ui.d.ts +21 -0
- package/dist/base/ui/gg-console.ui.js +162 -0
- package/dist/base/ui/gg-debugger.ui.d.ts +10 -0
- package/dist/base/ui/gg-debugger.ui.js +68 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +67 -0
- package/package.json +64 -0
- package/src/2d/entities/gg-2d-entity.ts +86 -0
- package/src/2d/entities/gg-2d-trigger.entity.ts +17 -0
- package/src/2d/entities/gg-positionable-2d-entity.ts +16 -0
- package/src/2d/factories.ts +20 -0
- package/src/2d/gg-2d-world.ts +32 -0
- package/src/2d/interfaces.ts +31 -0
- package/src/2d/models/body-options.ts +3 -0
- package/src/2d/models/shapes.ts +7 -0
- package/src/3d/controllers/car-keyboard.controller.ts +128 -0
- package/src/3d/controllers/free-camera.controller.ts +86 -0
- package/src/3d/entities/controllers/entity-motion.controller.ts +122 -0
- package/src/3d/entities/gg-3d-camera.entity.ts +8 -0
- package/src/3d/entities/gg-3d-entity.ts +116 -0
- package/src/3d/entities/gg-3d-map-graph.entity.ts +204 -0
- package/src/3d/entities/gg-3d-raycast-vehicle.entity.ts +468 -0
- package/src/3d/entities/gg-3d-trigger.entity.ts +22 -0
- package/src/3d/entities/gg-positionable-3d-entity.ts +31 -0
- package/src/3d/factories.ts +29 -0
- package/src/3d/gg-3d-world.ts +36 -0
- package/src/3d/interfaces.ts +96 -0
- package/src/3d/loader.ts +165 -0
- package/src/3d/models/body-options.ts +3 -0
- package/src/3d/models/gg-meta.ts +12 -0
- package/src/3d/models/shapes.ts +13 -0
- package/src/base/clock.ts +97 -0
- package/src/base/controllers/common.ts +37 -0
- package/src/base/controllers/i-controller.ts +5 -0
- package/src/base/controllers/keyboard.controller.ts +109 -0
- package/src/base/controllers/mouse.controller.ts +73 -0
- package/src/base/data-structures/graph.ts +125 -0
- package/src/base/entities/base-gg-renderer.ts +77 -0
- package/src/base/entities/gg-entity.ts +61 -0
- package/src/base/entities/gg-positionable-entity.ts +64 -0
- package/src/base/entities/inline-controller.ts +31 -0
- package/src/base/entities/interfaces/i-tick-listener.ts +15 -0
- package/src/base/gg-static.ts +30 -0
- package/src/base/gg-viewport-manager.ts +122 -0
- package/src/base/gg-viewport.ts +159 -0
- package/src/base/gg-world.ts +198 -0
- package/src/base/interfaces/gg-body.ts +23 -0
- package/src/base/interfaces/gg-debug-physics-drawer.ts +10 -0
- package/src/base/interfaces/gg-object.ts +26 -0
- package/src/base/interfaces/gg-physics-world.ts +24 -0
- package/src/base/interfaces/gg-trigger.ts +10 -0
- package/src/base/interfaces/gg-visual-scene.ts +11 -0
- package/src/base/math/box.ts +19 -0
- package/src/base/math/matrix4.ts +29 -0
- package/src/base/math/numbers.ts +10 -0
- package/src/base/math/point2.ts +43 -0
- package/src/base/math/point3.ts +119 -0
- package/src/base/math/quaternion.ts +172 -0
- package/src/base/models/axis-directions.ts +3 -0
- package/src/base/models/body-options.ts +6 -0
- package/src/base/models/geometry-nodes.ts +5 -0
- package/src/base/models/points.ts +3 -0
- package/src/base/ui/gg-console.ui.ts +165 -0
- package/src/base/ui/gg-debugger.ui.ts +69 -0
- package/src/index.ts +53 -0
- package/test/base/data-structures/graph.spec.ts +76 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,125 @@
|
|
|
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.GgViewportManager = void 0;
|
|
13
|
+
const rxjs_1 = require("rxjs");
|
|
14
|
+
const gg_viewport_1 = require("./gg-viewport");
|
|
15
|
+
class GgViewportManager {
|
|
16
|
+
constructor() {
|
|
17
|
+
this.canvases = {};
|
|
18
|
+
this.gameStage$ = new rxjs_1.BehaviorSubject(null);
|
|
19
|
+
this.destroyed = new rxjs_1.Subject();
|
|
20
|
+
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
let retries = 120;
|
|
22
|
+
let stage = null;
|
|
23
|
+
while (retries > 0) {
|
|
24
|
+
retries--;
|
|
25
|
+
stage = document.getElementById('gg-stage');
|
|
26
|
+
if (stage) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
yield new Promise(r => setTimeout(r, 250));
|
|
30
|
+
}
|
|
31
|
+
if (!stage) {
|
|
32
|
+
this.gameStage$.error(new Error('Div with id "gg-stage" not found in 30 seconds'));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
gg_viewport_1.GgViewport.instance
|
|
36
|
+
.subscribeOnViewportSize()
|
|
37
|
+
.pipe((0, rxjs_1.takeUntil)(this.destroyed))
|
|
38
|
+
.subscribe(size => {
|
|
39
|
+
for (const zIndex of Object.keys(this.canvases)) {
|
|
40
|
+
const canvasDescr = this.canvases[+zIndex];
|
|
41
|
+
if (canvasDescr.renderer && !canvasDescr.renderer.rendererOptions.forceRendererSize) {
|
|
42
|
+
canvasDescr.renderer.resize(size);
|
|
43
|
+
}
|
|
44
|
+
canvasDescr.canvas.width = size.x;
|
|
45
|
+
canvasDescr.canvas.height = size.y;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
this.gameStage$.next(stage);
|
|
49
|
+
}
|
|
50
|
+
}), 0);
|
|
51
|
+
}
|
|
52
|
+
static get instance() {
|
|
53
|
+
if (!this._instance) {
|
|
54
|
+
this._instance = new GgViewportManager();
|
|
55
|
+
}
|
|
56
|
+
return this._instance;
|
|
57
|
+
}
|
|
58
|
+
getStageAsync() {
|
|
59
|
+
const current = this.gameStage$.getValue();
|
|
60
|
+
if (current) {
|
|
61
|
+
return Promise.resolve(current);
|
|
62
|
+
}
|
|
63
|
+
return Promise.race([
|
|
64
|
+
this.gameStage$
|
|
65
|
+
.pipe((0, rxjs_1.takeUntil)(this.destroyed), (0, rxjs_1.filter)(x => !!x), (0, rxjs_1.first)())
|
|
66
|
+
.toPromise(),
|
|
67
|
+
new Promise((resolve, reject) => {
|
|
68
|
+
setTimeout(() => {
|
|
69
|
+
reject('Cannot find div with id "gg-stage" in 30 seconds');
|
|
70
|
+
}, 30000);
|
|
71
|
+
}),
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
createCanvas(zIndex) {
|
|
75
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
76
|
+
zIndex = Math.round(zIndex);
|
|
77
|
+
if (this.canvases[zIndex]) {
|
|
78
|
+
throw new Error(`Cannot add canvas on zIndex ${zIndex}. Index is locked by another canvas`);
|
|
79
|
+
}
|
|
80
|
+
const stage = yield this.getStageAsync();
|
|
81
|
+
const canvas = document.createElement('canvas');
|
|
82
|
+
yield this.registerCanvas(canvas, zIndex);
|
|
83
|
+
stage.appendChild(canvas);
|
|
84
|
+
return canvas;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
registerCanvas(canvas, zIndex) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
canvas.style.zIndex = '' + zIndex;
|
|
90
|
+
canvas.style.position = 'absolute';
|
|
91
|
+
canvas.style.width = '100%';
|
|
92
|
+
canvas.style.height = '100%';
|
|
93
|
+
canvas.id = 'canvas-' + zIndex;
|
|
94
|
+
this.canvases[zIndex] = { canvas };
|
|
95
|
+
const size = gg_viewport_1.GgViewport.instance.getCurrentViewportSize();
|
|
96
|
+
canvas.width = size.x;
|
|
97
|
+
canvas.height = size.y;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
assignRendererToCanvas(renderer, canvas) {
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
if (!gg_viewport_1.GgViewport.instance.isActive) {
|
|
103
|
+
gg_viewport_1.GgViewport.instance.activate();
|
|
104
|
+
}
|
|
105
|
+
let zIndex = null;
|
|
106
|
+
let maxExistingZIndex = 0;
|
|
107
|
+
for (const index in this.canvases) {
|
|
108
|
+
if (this.canvases[index].canvas === canvas) {
|
|
109
|
+
zIndex = +index;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
maxExistingZIndex = +index;
|
|
113
|
+
}
|
|
114
|
+
if (!zIndex) {
|
|
115
|
+
zIndex = maxExistingZIndex + 1;
|
|
116
|
+
yield this.registerCanvas(canvas, zIndex);
|
|
117
|
+
}
|
|
118
|
+
this.canvases[zIndex].renderer = renderer;
|
|
119
|
+
if (!renderer.rendererOptions.forceRendererSize) {
|
|
120
|
+
renderer.resize(gg_viewport_1.GgViewport.instance.getCurrentViewportSize());
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.GgViewportManager = GgViewportManager;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Observable, Subject } from 'rxjs';
|
|
2
|
+
import { Point2 } from './models/points';
|
|
3
|
+
export declare class GgViewport {
|
|
4
|
+
private static _instance;
|
|
5
|
+
static get instance(): GgViewport;
|
|
6
|
+
private constructor();
|
|
7
|
+
protected destroy$: Subject<void> | null;
|
|
8
|
+
private scenes;
|
|
9
|
+
get isActive(): boolean;
|
|
10
|
+
activate(): void;
|
|
11
|
+
deactivate(): void;
|
|
12
|
+
private viewportSize;
|
|
13
|
+
getCurrentViewportSize(): Point2;
|
|
14
|
+
subscribeOnViewportSize(): Observable<Point2>;
|
|
15
|
+
private mousePosition;
|
|
16
|
+
private mouseClicked;
|
|
17
|
+
private isMouseDown;
|
|
18
|
+
isMouseEnabled(): boolean;
|
|
19
|
+
isTouchDevice(): boolean;
|
|
20
|
+
subscribeOnMouseMove(): Observable<Point2>;
|
|
21
|
+
subscribeOnIsMouseDown(): Observable<boolean>;
|
|
22
|
+
subscribeOnMouseClick(): Observable<Point2>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GgViewport = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const getCurrentWindowSize = () => {
|
|
7
|
+
return {
|
|
8
|
+
x: window.innerWidth,
|
|
9
|
+
y: window.innerHeight,
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
const getMousePositionFromEvent = (event) => {
|
|
13
|
+
if (event instanceof MouseEvent) {
|
|
14
|
+
return { x: event.x, y: event.y };
|
|
15
|
+
}
|
|
16
|
+
else if (event instanceof TouchEvent) {
|
|
17
|
+
if (event.touches.length === 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return { x: event.touches[0].clientX, y: event.touches[0].clientY };
|
|
21
|
+
}
|
|
22
|
+
console.warn('Cannot determine mouse position from event', event);
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
class GgViewport {
|
|
26
|
+
constructor() {
|
|
27
|
+
this.destroy$ = null;
|
|
28
|
+
this.scenes = [];
|
|
29
|
+
// ================================================== VIEWPORT SIZE ==================================================
|
|
30
|
+
this.viewportSize = new rxjs_1.BehaviorSubject(getCurrentWindowSize());
|
|
31
|
+
// ================================================== VIEWPORT SIZE ==================================================
|
|
32
|
+
// ================================================== POINTER LOGIC ==================================================
|
|
33
|
+
this.mousePosition = new rxjs_1.BehaviorSubject({ x: 0, y: 0 });
|
|
34
|
+
this.mouseClicked = new rxjs_1.Subject();
|
|
35
|
+
this.isMouseDown = new rxjs_1.Subject();
|
|
36
|
+
}
|
|
37
|
+
static get instance() {
|
|
38
|
+
if (!this._instance) {
|
|
39
|
+
this._instance = new GgViewport();
|
|
40
|
+
}
|
|
41
|
+
return this._instance;
|
|
42
|
+
}
|
|
43
|
+
get isActive() {
|
|
44
|
+
return !!this.destroy$;
|
|
45
|
+
}
|
|
46
|
+
activate() {
|
|
47
|
+
if (this.destroy$) {
|
|
48
|
+
throw new Error('GgViewport is already active');
|
|
49
|
+
}
|
|
50
|
+
this.destroy$ = new rxjs_1.Subject();
|
|
51
|
+
// cursor position
|
|
52
|
+
(0, rxjs_1.merge)((0, rxjs_1.fromEvent)(window, 'mousemove'), (0, rxjs_1.fromEvent)(window, 'touchstart'), (0, rxjs_1.fromEvent)(window, 'touchmove'))
|
|
53
|
+
.pipe((0, rxjs_1.takeUntil)(this.destroy$), (0, operators_1.map)(event => event))
|
|
54
|
+
.subscribe(event => {
|
|
55
|
+
const point = getMousePositionFromEvent(event);
|
|
56
|
+
if (point) {
|
|
57
|
+
this.mousePosition.next(point);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
// clicks
|
|
61
|
+
(0, rxjs_1.merge)((0, rxjs_1.fromEvent)(window, 'mousedown'), (0, rxjs_1.fromEvent)(window, 'touchstart'))
|
|
62
|
+
.pipe((0, rxjs_1.takeUntil)(this.destroy$), (0, operators_1.map)(event => event))
|
|
63
|
+
.subscribe(event => {
|
|
64
|
+
const point = getMousePositionFromEvent(event);
|
|
65
|
+
if (point) {
|
|
66
|
+
this.mousePosition.next(point);
|
|
67
|
+
}
|
|
68
|
+
this.isMouseDown.next(true);
|
|
69
|
+
});
|
|
70
|
+
(0, rxjs_1.merge)((0, rxjs_1.fromEvent)(window, 'mouseup'), (0, rxjs_1.fromEvent)(window, 'click'), (0, rxjs_1.fromEvent)(window, 'touchend'))
|
|
71
|
+
.pipe((0, rxjs_1.takeUntil)(this.destroy$), (0, operators_1.map)(event => event))
|
|
72
|
+
.subscribe(event => {
|
|
73
|
+
const point = getMousePositionFromEvent(event);
|
|
74
|
+
if (point) {
|
|
75
|
+
this.mousePosition.next(point);
|
|
76
|
+
}
|
|
77
|
+
this.isMouseDown.next(false);
|
|
78
|
+
if (event.target['nodeName'] === 'canvas') {
|
|
79
|
+
this.mouseClicked.next(this.mousePosition.getValue());
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
// viewport size
|
|
83
|
+
(0, rxjs_1.merge)((0, rxjs_1.fromEvent)(window, 'resize'), (0, rxjs_1.fromEvent)(window, 'orientationchange'))
|
|
84
|
+
.pipe((0, rxjs_1.takeUntil)(this.destroy$), (0, operators_1.map)(() => getCurrentWindowSize()))
|
|
85
|
+
.subscribe(this.viewportSize);
|
|
86
|
+
}
|
|
87
|
+
deactivate() {
|
|
88
|
+
if (!this.destroy$) {
|
|
89
|
+
throw new Error('GgViewport is already inactive');
|
|
90
|
+
}
|
|
91
|
+
this.destroy$.next();
|
|
92
|
+
this.destroy$.complete();
|
|
93
|
+
this.destroy$ = null;
|
|
94
|
+
}
|
|
95
|
+
getCurrentViewportSize() {
|
|
96
|
+
return this.viewportSize.getValue();
|
|
97
|
+
}
|
|
98
|
+
subscribeOnViewportSize() {
|
|
99
|
+
return this.viewportSize.asObservable().pipe((0, rxjs_1.distinctUntilChanged)((v1, v2) => {
|
|
100
|
+
return v1.x === v2.x && v1.y === v2.y;
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
103
|
+
isMouseEnabled() {
|
|
104
|
+
return matchMedia('(hover:hover)').matches && matchMedia('(pointer:fine)').matches;
|
|
105
|
+
}
|
|
106
|
+
isTouchDevice() {
|
|
107
|
+
return ('createTouch' in document ||
|
|
108
|
+
!!navigator.userAgent.match(/(iPhone|iPod|iPad)/) ||
|
|
109
|
+
!!navigator.userAgent.match(/Android/));
|
|
110
|
+
}
|
|
111
|
+
subscribeOnMouseMove() {
|
|
112
|
+
return this.mousePosition.asObservable().pipe((0, rxjs_1.distinctUntilChanged)((v1, v2) => {
|
|
113
|
+
return v1.x === v2.x && v1.y === v2.y;
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
subscribeOnIsMouseDown() {
|
|
117
|
+
return this.isMouseDown.asObservable().pipe((0, rxjs_1.distinctUntilChanged)());
|
|
118
|
+
}
|
|
119
|
+
subscribeOnMouseClick() {
|
|
120
|
+
return this.mouseClicked.asObservable();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.GgViewport = GgViewport;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { GgEntity } from './entities/gg-entity';
|
|
2
|
+
import { ITickListener } from './entities/interfaces/i-tick-listener';
|
|
3
|
+
import { GgPhysicsWorld } from './interfaces/gg-physics-world';
|
|
4
|
+
import { GgVisualScene } from './interfaces/gg-visual-scene';
|
|
5
|
+
import { KeyboardController } from './controllers/keyboard.controller';
|
|
6
|
+
export declare abstract class GgWorld<D, R, V extends GgVisualScene<D, R> = GgVisualScene<D, R>, P extends GgPhysicsWorld<D, R> = GgPhysicsWorld<D, R>> {
|
|
7
|
+
readonly visualScene: V;
|
|
8
|
+
readonly physicsWorld: P;
|
|
9
|
+
protected readonly consoleEnabled: boolean;
|
|
10
|
+
private readonly animationFrameClock;
|
|
11
|
+
private readonly worldClock;
|
|
12
|
+
readonly keyboardController: KeyboardController;
|
|
13
|
+
readonly children: GgEntity[];
|
|
14
|
+
protected readonly tickListeners: ITickListener[];
|
|
15
|
+
constructor(visualScene: V, physicsWorld: P, consoleEnabled?: boolean);
|
|
16
|
+
init(): Promise<void>;
|
|
17
|
+
start(): void;
|
|
18
|
+
pauseWorld(): void;
|
|
19
|
+
resumeWorld(): void;
|
|
20
|
+
dispose(): void;
|
|
21
|
+
addEntity(entity: GgEntity): void;
|
|
22
|
+
removeEntity(entity: GgEntity, dispose?: boolean): void;
|
|
23
|
+
protected commands: {
|
|
24
|
+
[key: string]: {
|
|
25
|
+
handler: (...args: string[]) => Promise<string>;
|
|
26
|
+
doc?: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
registerConsoleCommand(command: string, handler: (...args: string[]) => Promise<string>, doc?: string): void;
|
|
30
|
+
runConsoleCommand(command: string, args: string[]): Promise<string>;
|
|
31
|
+
triggerPhysicsDebugView(): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
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.GgWorld = void 0;
|
|
13
|
+
const clock_1 = require("./clock");
|
|
14
|
+
const i_tick_listener_1 = require("./entities/interfaces/i-tick-listener");
|
|
15
|
+
const gg_static_1 = require("./gg-static");
|
|
16
|
+
const keyboard_controller_1 = require("./controllers/keyboard.controller");
|
|
17
|
+
const rxjs_1 = require("rxjs");
|
|
18
|
+
const gg_console_ui_1 = require("./ui/gg-console.ui");
|
|
19
|
+
const gg_debugger_ui_1 = require("./ui/gg-debugger.ui");
|
|
20
|
+
class GgWorld {
|
|
21
|
+
constructor(visualScene, physicsWorld, consoleEnabled = false) {
|
|
22
|
+
this.visualScene = visualScene;
|
|
23
|
+
this.physicsWorld = physicsWorld;
|
|
24
|
+
this.consoleEnabled = consoleEnabled;
|
|
25
|
+
// inner clock, runs constantly
|
|
26
|
+
this.animationFrameClock = clock_1.Clock.animationFrameClock;
|
|
27
|
+
// world clock, can be paused/resumed. Stops when disposing world
|
|
28
|
+
this.worldClock = new clock_1.Clock(this.animationFrameClock.tick$);
|
|
29
|
+
// TODO consider adding mouse controller
|
|
30
|
+
this.keyboardController = new keyboard_controller_1.KeyboardController();
|
|
31
|
+
this.children = [];
|
|
32
|
+
this.tickListeners = [];
|
|
33
|
+
this.commands = {};
|
|
34
|
+
gg_static_1.GgStatic.instance.worlds.push(this);
|
|
35
|
+
gg_static_1.GgStatic.instance.selectedWorld = this;
|
|
36
|
+
this.keyboardController.start().then();
|
|
37
|
+
if (consoleEnabled) {
|
|
38
|
+
this.keyboardController
|
|
39
|
+
.bind('Backquote')
|
|
40
|
+
.pipe((0, rxjs_1.filter)(x => x))
|
|
41
|
+
.subscribe(() => {
|
|
42
|
+
// open console UI
|
|
43
|
+
if (gg_console_ui_1.GgConsoleUI.instance.isUIShown) {
|
|
44
|
+
gg_console_ui_1.GgConsoleUI.instance.destroyUI();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
gg_console_ui_1.GgConsoleUI.instance.createUI();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.registerConsoleCommand('commandslist', () => __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
return Object.entries(this.commands)
|
|
52
|
+
.map(([key, value]) => `${key}${value.doc ? '\t// ' + value.doc : ''}`)
|
|
53
|
+
.sort()
|
|
54
|
+
.join('\n\n');
|
|
55
|
+
}), 'no args; print all available commands');
|
|
56
|
+
this.registerConsoleCommand('debugger', (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
const shouldDraw = ['1', 'true', '+'].includes(args[0]);
|
|
58
|
+
if (shouldDraw != gg_debugger_ui_1.GgDebuggerUI.instance.isUIShown) {
|
|
59
|
+
if (gg_debugger_ui_1.GgDebuggerUI.instance.isUIShown) {
|
|
60
|
+
gg_debugger_ui_1.GgDebuggerUI.instance.destroyUI();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
gg_debugger_ui_1.GgDebuggerUI.instance.createUI();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return '' + gg_debugger_ui_1.GgDebuggerUI.instance.isUIShown;
|
|
67
|
+
}), 'args: [0 or 1]; turn on/off debug panel. Default value is 0');
|
|
68
|
+
this.registerConsoleCommand('ph_timescale', (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
this.physicsWorld.timeScale = +args[0];
|
|
70
|
+
return JSON.stringify(this.physicsWorld.timeScale);
|
|
71
|
+
}), 'args: [float]; change time scale of physics engine. Default value is 1.0');
|
|
72
|
+
this.registerConsoleCommand('dr_drawphysics', (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const shouldDraw = ['1', 'true', '+'].includes(args[0]);
|
|
74
|
+
if (shouldDraw != this.physicsWorld.physicsDebugViewActive) {
|
|
75
|
+
this.triggerPhysicsDebugView();
|
|
76
|
+
}
|
|
77
|
+
return '' + this.physicsWorld.physicsDebugViewActive;
|
|
78
|
+
}), 'args: [0 or 1]; turn on/off physics debug view. Default value is 0');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
init() {
|
|
82
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
+
yield Promise.all([this.physicsWorld.init(), this.visualScene.init()]);
|
|
84
|
+
this.worldClock.tick$.subscribe(([elapsed, delta]) => {
|
|
85
|
+
let physicsTickPerformed = false;
|
|
86
|
+
for (let i = 0; i < this.tickListeners.length; i++) {
|
|
87
|
+
if (!physicsTickPerformed && this.tickListeners[i].tickOrder >= 500) {
|
|
88
|
+
this.physicsWorld.simulate(delta);
|
|
89
|
+
physicsTickPerformed = true;
|
|
90
|
+
}
|
|
91
|
+
this.tickListeners[i].tick$.next([elapsed, delta]);
|
|
92
|
+
}
|
|
93
|
+
if (!physicsTickPerformed) {
|
|
94
|
+
this.physicsWorld.simulate(delta);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
start() {
|
|
100
|
+
this.worldClock.start();
|
|
101
|
+
}
|
|
102
|
+
pauseWorld() {
|
|
103
|
+
this.worldClock.pause();
|
|
104
|
+
}
|
|
105
|
+
resumeWorld() {
|
|
106
|
+
this.worldClock.pause();
|
|
107
|
+
}
|
|
108
|
+
dispose() {
|
|
109
|
+
this.worldClock.stop();
|
|
110
|
+
for (let i = 0; i < this.children.length; i++) {
|
|
111
|
+
this.children[i].dispose();
|
|
112
|
+
}
|
|
113
|
+
this.children.splice(0, this.children.length);
|
|
114
|
+
this.tickListeners.splice(0, this.tickListeners.length);
|
|
115
|
+
this.physicsWorld.dispose();
|
|
116
|
+
this.visualScene.dispose();
|
|
117
|
+
}
|
|
118
|
+
addEntity(entity) {
|
|
119
|
+
if (!!entity.world) {
|
|
120
|
+
throw new Error('Entity already spawned');
|
|
121
|
+
}
|
|
122
|
+
this.children.push(entity);
|
|
123
|
+
if ((0, i_tick_listener_1.isITickListener)(entity)) {
|
|
124
|
+
this.tickListeners.push(entity);
|
|
125
|
+
this.tickListeners.sort((l1, l2) => l1.tickOrder - l2.tickOrder);
|
|
126
|
+
}
|
|
127
|
+
entity.onSpawned(this);
|
|
128
|
+
}
|
|
129
|
+
removeEntity(entity, dispose = true) {
|
|
130
|
+
if (entity.world !== this) {
|
|
131
|
+
throw new Error('Entity is not a part of this world');
|
|
132
|
+
}
|
|
133
|
+
this.children.splice(this.children.findIndex(x => x === entity), 1);
|
|
134
|
+
if ((0, i_tick_listener_1.isITickListener)(entity)) {
|
|
135
|
+
this.tickListeners.splice(this.tickListeners.findIndex(x => x === entity), 1);
|
|
136
|
+
}
|
|
137
|
+
entity.onRemoved();
|
|
138
|
+
if (dispose) {
|
|
139
|
+
entity.dispose();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
registerConsoleCommand(command, handler, doc) {
|
|
143
|
+
if (!this.consoleEnabled) {
|
|
144
|
+
throw new Error('Console not enabled for this world');
|
|
145
|
+
}
|
|
146
|
+
this.commands[command] = { handler, doc };
|
|
147
|
+
}
|
|
148
|
+
runConsoleCommand(command, args) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
if (!this.consoleEnabled) {
|
|
151
|
+
throw new Error('Console not enabled for this world');
|
|
152
|
+
}
|
|
153
|
+
if (!this.commands[command]) {
|
|
154
|
+
return 'Unrecognized command: ' + command;
|
|
155
|
+
}
|
|
156
|
+
return this.commands[command].handler(...args);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
triggerPhysicsDebugView() {
|
|
160
|
+
if (this.physicsWorld.physicsDebugViewActive) {
|
|
161
|
+
this.physicsWorld.stopDebugger(this);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const cls = this.visualScene.debugPhysicsDrawerClass;
|
|
165
|
+
if (!cls) {
|
|
166
|
+
throw new Error('Debug drawer is not available');
|
|
167
|
+
}
|
|
168
|
+
this.physicsWorld.startDebugger(this, new cls());
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
exports.GgWorld = GgWorld;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { GgPhysicsWorld } from './gg-physics-world';
|
|
2
|
+
import { GgEntity } from '../entities/gg-entity';
|
|
3
|
+
export interface GgBody<D, R> {
|
|
4
|
+
position: D;
|
|
5
|
+
rotation: R;
|
|
6
|
+
scale: D;
|
|
7
|
+
name: string;
|
|
8
|
+
entity: GgEntity | null;
|
|
9
|
+
clone(): GgBody<D, R>;
|
|
10
|
+
addToWorld(world: GgPhysicsWorld<D, R>): void;
|
|
11
|
+
removeFromWorld(world: GgPhysicsWorld<D, R>): void;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
/** clear velocities etc. */
|
|
14
|
+
resetMotion(): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Point3 } from '../models/points';
|
|
2
|
+
import { GgObject } from './gg-object';
|
|
3
|
+
export interface GgDebugPhysicsDrawer<D, R> extends GgObject<D, R> {
|
|
4
|
+
drawContactPoint(point: D, normal: D, color?: Point3): void;
|
|
5
|
+
drawLine(from: D, to: D, color?: Point3): void;
|
|
6
|
+
update(): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { GgVisualScene } from './gg-visual-scene';
|
|
2
|
+
import { GgBox } from '../models/geometry-nodes';
|
|
3
|
+
export interface GgObject<D, R> {
|
|
4
|
+
position: D;
|
|
5
|
+
rotation: R;
|
|
6
|
+
scale: D;
|
|
7
|
+
visible: boolean;
|
|
8
|
+
name: string;
|
|
9
|
+
isEmpty(): boolean;
|
|
10
|
+
popChild(name: string): GgObject<D, R> | null;
|
|
11
|
+
getBoundings(): GgBox<D>;
|
|
12
|
+
clone(): GgObject<D, R>;
|
|
13
|
+
addToWorld(world: GgVisualScene<D, R>): void;
|
|
14
|
+
removeFromWorld(world: GgVisualScene<D, R>): void;
|
|
15
|
+
dispose(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GgDebugPhysicsDrawer } from './gg-debug-physics-drawer';
|
|
2
|
+
import { GgWorld } from '../gg-world';
|
|
3
|
+
export interface GgPhysicsWorld<D, R> {
|
|
4
|
+
readonly factory: any;
|
|
5
|
+
gravity: D;
|
|
6
|
+
timeScale: number;
|
|
7
|
+
get physicsDebugViewActive(): boolean;
|
|
8
|
+
init(): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Runs simulation of the physics world.
|
|
11
|
+
*
|
|
12
|
+
* @param delta delta time from last tick in milliseconds.
|
|
13
|
+
*/
|
|
14
|
+
simulate(delta: number): void;
|
|
15
|
+
startDebugger(world: GgWorld<D, R>, drawer: GgDebugPhysicsDrawer<D, R>): void;
|
|
16
|
+
stopDebugger(world: GgWorld<D, R>): void;
|
|
17
|
+
dispose(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GgBody } from './gg-body';
|
|
2
|
+
import { GgPositionableEntity } from '../entities/gg-positionable-entity';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
export interface GgTrigger<D, R> extends GgBody<D, R> {
|
|
5
|
+
get onEntityEntered(): Observable<GgPositionableEntity<D, R>>;
|
|
6
|
+
get onEntityLeft(): Observable<GgPositionableEntity<D, R> | null>;
|
|
7
|
+
checkOverlaps(): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Box = void 0;
|
|
4
|
+
class Box {
|
|
5
|
+
static clone(box) {
|
|
6
|
+
return { min: Object.assign({}, box.min), max: Object.assign({}, box.max) };
|
|
7
|
+
}
|
|
8
|
+
static expandByPoint(box, point) {
|
|
9
|
+
const res = Box.clone(box);
|
|
10
|
+
for (const c in point) {
|
|
11
|
+
if (res.min[c] > point[c]) {
|
|
12
|
+
res.min[c] = point[c];
|
|
13
|
+
}
|
|
14
|
+
if (res.max[c] < point[c]) {
|
|
15
|
+
res.max[c] = point[c];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return res;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Box = Box;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Mtrx4 = void 0;
|
|
4
|
+
const point3_1 = require("./point3");
|
|
5
|
+
class Mtrx4 {
|
|
6
|
+
/** creates a rotation matrix for object, so it will look at some point in space */
|
|
7
|
+
static lookAt(eye, target, up) {
|
|
8
|
+
let z = point3_1.Pnt3.sub(eye, target);
|
|
9
|
+
if (point3_1.Pnt3.lenSq(z) === 0) {
|
|
10
|
+
// same position
|
|
11
|
+
z.z = 1;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
z = point3_1.Pnt3.norm(z);
|
|
15
|
+
}
|
|
16
|
+
let x = point3_1.Pnt3.cross(up, z);
|
|
17
|
+
if (point3_1.Pnt3.lenSq(x) === 0) {
|
|
18
|
+
// up and z are parallel
|
|
19
|
+
if (Math.abs(up.z) === 1) {
|
|
20
|
+
z.x += 0.0001;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
z.z += 0.0001;
|
|
24
|
+
}
|
|
25
|
+
z = point3_1.Pnt3.norm(z);
|
|
26
|
+
x = point3_1.Pnt3.cross(up, z);
|
|
27
|
+
}
|
|
28
|
+
x = point3_1.Pnt3.norm(x);
|
|
29
|
+
let y = point3_1.Pnt3.cross(z, x);
|
|
30
|
+
return [x.x, x.y, x.z, 0, y.x, y.y, y.z, 0, z.x, z.y, z.z, 0];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.Mtrx4 = Mtrx4;
|