@gg-web-engine/core 0.0.49 → 0.0.56

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 (35) hide show
  1. package/dist/2d/entities/entity-2d.d.ts +6 -3
  2. package/dist/2d/entities/entity-2d.js +20 -17
  3. package/dist/2d/gg-2d-world.d.ts +3 -0
  4. package/dist/2d/gg-2d-world.js +21 -13
  5. package/dist/3d/entities/controllers/input/free-camera.controller.d.ts +9 -1
  6. package/dist/3d/entities/controllers/input/free-camera.controller.js +45 -12
  7. package/dist/3d/entities/controllers/input/orbit-camera.controller.d.ts +9 -8
  8. package/dist/3d/entities/controllers/input/orbit-camera.controller.js +46 -32
  9. package/dist/3d/entities/entity-3d.d.ts +6 -3
  10. package/dist/3d/entities/entity-3d.js +20 -17
  11. package/dist/3d/entities/raycast-vehicle-3d.entity.js +5 -5
  12. package/dist/3d/gg-3d-world.d.ts +3 -0
  13. package/dist/3d/gg-3d-world.js +21 -13
  14. package/dist/3d/loader.js +1 -1
  15. package/dist/base/clock/global-clock.d.ts +2 -6
  16. package/dist/base/clock/global-clock.js +16 -16
  17. package/dist/base/clock/i-clock.d.ts +14 -5
  18. package/dist/base/clock/i-clock.js +43 -1
  19. package/dist/base/clock/pausable-clock.d.ts +3 -13
  20. package/dist/base/clock/pausable-clock.js +8 -16
  21. package/dist/base/gg-world.d.ts +6 -0
  22. package/dist/base/gg-world.js +102 -65
  23. package/dist/base/inputs/keyboard.input.d.ts +1 -1
  24. package/dist/base/inputs/keyboard.input.js +10 -10
  25. package/dist/base/inputs/mouse.input.js +3 -2
  26. package/dist/dev/gg-console.ui.js +14 -4
  27. package/dist/dev/gg-debugger.ui.d.ts +2 -2
  28. package/dist/dev/gg-debugger.ui.js +13 -10
  29. package/dist/dev/gg-static.d.ts +6 -1
  30. package/dist/dev/gg-static.js +104 -25
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +3 -0
  33. package/dist/version.d.ts +1 -0
  34. package/dist/version.js +1 -0
  35. package/package.json +4 -3
@@ -69,7 +69,7 @@ export class GgDebuggerUI {
69
69
  }
70
70
  }
71
71
  this.currentWorld = selectedWorld;
72
- if (value) {
72
+ if (selectedWorld && value) {
73
73
  const stats = new Stats();
74
74
  this.ui.stats = stats;
75
75
  stats.dom.style.left = 'unset';
@@ -139,9 +139,10 @@ export class GgDebuggerUI {
139
139
  }
140
140
  }
141
141
  makeSnapshot() {
142
+ var _a, _b;
142
143
  const renderers = [];
143
144
  let performanceMeter = null;
144
- for (const e of this.currentWorld.children) {
145
+ for (const e of ((_a = this.currentWorld) === null || _a === void 0 ? void 0 : _a.children) || []) {
145
146
  if (e instanceof IRendererEntity) {
146
147
  renderers.push(e);
147
148
  }
@@ -150,7 +151,7 @@ export class GgDebuggerUI {
150
151
  }
151
152
  }
152
153
  return {
153
- timeScale: this.currentWorld.worldClock.timeScale,
154
+ timeScale: ((_b = this.currentWorld) === null || _b === void 0 ? void 0 : _b.worldClock.timeScale) || NaN,
154
155
  renderers: renderers.map(r => ({
155
156
  name: r.name,
156
157
  entity: r,
@@ -160,9 +161,10 @@ export class GgDebuggerUI {
160
161
  };
161
162
  }
162
163
  makePerformanceStatsSnapshot() {
164
+ var _a;
163
165
  if (!this.snapshot.performanceStatsEnabled)
164
166
  return null;
165
- let performanceMeter = this.currentWorld.children.find(e => e instanceof PerformanceMeterEntity);
167
+ let performanceMeter = (((_a = this.currentWorld) === null || _a === void 0 ? void 0 : _a.children) || []).find(e => e instanceof PerformanceMeterEntity);
166
168
  if (performanceMeter) {
167
169
  if (this.perfStatsMode === 'AVG') {
168
170
  return performanceMeter.avgReport;
@@ -178,19 +180,19 @@ export class GgDebuggerUI {
178
180
  for (const { entity, physicsDebugViewActive } of this.snapshot.renderers) {
179
181
  html += `
180
182
  <div ${this.css}>
181
- <input type='checkbox' name='checkbox' id='physics_debugger_checkbox_id_${entity.name}' value='1'${physicsDebugViewActive ? ' checked' : ''}>
183
+ <input type='checkbox' name='checkbox' id='physics_debugger_checkbox_id_${entity.name}' onkeydown='event.preventDefault()' value='1'${physicsDebugViewActive ? ' checked' : ''}>
182
184
  <label for='physics_debugger_checkbox_id_${entity.name}' style='user-select: none;'>Physics debugger${this.snapshot.renderers.length > 1 ? ' (' + entity.name + ')' : ''}</label>
183
185
  </div>`;
184
186
  }
185
187
  html += `
186
188
  <div ${this.css}>
187
- <input id='time_scale_slider' type='range' min='0' max='5' step='0.01' style='flex-grow:1' value='${this.snapshot.timeScale}'/>
189
+ <input id='time_scale_slider' type='range' min='0' max='5' step='0.01' onkeydown='event.preventDefault()' style='flex-grow:1' value='${this.snapshot.timeScale}'/>
188
190
  <label for='time_scale_slider' style='user-select: none;'>Time scale</label>
189
191
  </div>`;
190
192
  html +=
191
193
  `
192
194
  <div ${this.css}>
193
- <input type='checkbox' name='checkbox' id='perf_stats_checkbox_id' value='1'${this.snapshot.performanceStatsEnabled ? ' checked' : ''}>
195
+ <input type='checkbox' name='checkbox' id='perf_stats_checkbox_id' onkeydown='event.preventDefault()' value='1'${this.snapshot.performanceStatsEnabled ? ' checked' : ''}>
194
196
  <label for='perf_stats_checkbox_id' style='user-select: none;'>Entities performance distribution</label>
195
197
  </div>
196
198
  ` +
@@ -233,12 +235,13 @@ export class GgDebuggerUI {
233
235
  fromEvent(document.getElementById('perf_stats_checkbox_id'), 'change')
234
236
  .pipe(takeUntil(this.debugControlsRemoved$), takeUntil(this.viewUpdated$))
235
237
  .subscribe(e => {
236
- const entity = this.currentWorld.children.find(x => x instanceof PerformanceMeterEntity);
238
+ var _a;
239
+ const entity = (((_a = this.currentWorld) === null || _a === void 0 ? void 0 : _a.children) || []).find(x => x instanceof PerformanceMeterEntity);
237
240
  if (e.target.checked == !entity) {
238
241
  if (entity) {
239
242
  this.currentWorld.removeEntity(entity);
240
243
  }
241
- else {
244
+ else if (this.currentWorld) {
242
245
  this.currentWorld.addEntity(new PerformanceMeterEntity());
243
246
  }
244
247
  }
@@ -265,7 +268,7 @@ export class GgDebuggerUI {
265
268
  html += `
266
269
  <div ${pCss}>
267
270
  <label for='stat_progress' ${labelCss}>${total.toFixed(2)}ms</label>
268
- <progress id="stat_progress" ${progressCss} max="16" value="${total}"></progress>
271
+ <progress id='stat_progress' ${progressCss} max='16' value='${total}'></progress>
269
272
  <span ${spanCss}>Total frame time</span>
270
273
  </div>`;
271
274
  for (const [i, [name, value]] of this.performanceStatsSnapshot.entries.entries()) {
@@ -7,12 +7,17 @@ export declare class GgStatic {
7
7
  get devConsoleEnabled(): boolean;
8
8
  consoleKeyPressEventListener: (event: KeyboardEvent) => void;
9
9
  set devConsoleEnabled(value: boolean);
10
+ toggleDevConsole(value: boolean): void;
11
+ private showStats$;
10
12
  get showStats(): boolean;
11
13
  set showStats(value: boolean);
14
+ private showDebugControls$;
12
15
  get showDebugControls(): boolean;
13
16
  set showDebugControls(value: boolean);
14
- private _selectedWorld;
17
+ private _selectedWorld$;
15
18
  get selectedWorld(): GgWorld<any, any> | null;
19
+ private set selectedWorld(value);
20
+ private autoAssignSelectedWorld;
16
21
  get availableCommands(): [string, {
17
22
  handler: (...args: string[]) => Promise<string>;
18
23
  doc?: string;
@@ -7,13 +7,14 @@ 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 { GgWorld } from '../base';
10
+ import { GgWorld, KeyboardInput } from '../base';
11
11
  import { GgConsoleUI } from './gg-console.ui';
12
12
  import { GgDebuggerUI } from './gg-debugger.ui';
13
+ import { BehaviorSubject, combineLatest, filter, fromEvent, NEVER, Subject, switchMap, take, takeUntil, takeWhile, } from 'rxjs';
13
14
  export class GgStatic {
14
15
  static get instance() {
15
16
  if (!window.ggstatic) {
16
- window.ggstatic = new GgStatic();
17
+ return new GgStatic();
17
18
  }
18
19
  return window.ggstatic;
19
20
  }
@@ -35,25 +36,52 @@ export class GgStatic {
35
36
  }
36
37
  }
37
38
  }
39
+ toggleDevConsole(value) {
40
+ if (value === this.consoleUI.isUIShown)
41
+ return;
42
+ if (this.consoleUI.isUIShown) {
43
+ this.consoleUI.destroyUI();
44
+ }
45
+ else {
46
+ this.consoleUI.createUI();
47
+ }
48
+ }
38
49
  get showStats() {
39
- return this.debuggerUI.showStats;
50
+ return this.showStats$.getValue();
40
51
  }
41
52
  set showStats(value) {
42
- this.debuggerUI.setShowStats(this.selectedWorld, value);
53
+ if (value === this.showStats)
54
+ return;
55
+ this.showStats$.next(value);
43
56
  }
44
57
  get showDebugControls() {
45
- return this.debuggerUI.showDebugControls;
58
+ return this.showDebugControls$.getValue();
46
59
  }
47
60
  set showDebugControls(value) {
48
- this.debuggerUI.setShowDebugControls(this.selectedWorld, value);
61
+ if (value === this.showDebugControls)
62
+ return;
63
+ this.showDebugControls$.next(value);
49
64
  }
50
65
  get selectedWorld() {
51
- return this._selectedWorld || GgWorld.documentWorlds[0] || null;
66
+ return this._selectedWorld$.getValue();
67
+ }
68
+ set selectedWorld(w) {
69
+ this._selectedWorld$.next(w);
70
+ }
71
+ autoAssignSelectedWorld() {
72
+ if (GgWorld.documentWorlds.length > 0) {
73
+ this.selectedWorld = GgWorld.documentWorlds[0];
74
+ }
75
+ else {
76
+ GgWorld.worldCreated$
77
+ .pipe(takeWhile(() => !this.selectedWorld), take(1))
78
+ .subscribe(w => (this.selectedWorld = w));
79
+ }
52
80
  }
53
81
  get availableCommands() {
54
82
  let commands = this.consoleCommands.get(null) || {};
55
83
  if (this.selectedWorld) {
56
- commands = Object.assign(Object.assign({}, (this.consoleCommands.get(this.selectedWorld) || {})), commands);
84
+ commands = Object.assign(Object.assign({}, commands), (this.consoleCommands.get(this.selectedWorld) || {}));
57
85
  }
58
86
  return Object.entries(commands);
59
87
  }
@@ -72,37 +100,88 @@ export class GgStatic {
72
100
  }
73
101
  }
74
102
  };
75
- this._selectedWorld = null;
103
+ this.showStats$ = new BehaviorSubject(false);
104
+ this.showDebugControls$ = new BehaviorSubject(false);
105
+ this._selectedWorld$ = new BehaviorSubject(null);
76
106
  this.consoleCommands = new Map();
77
- this.registerConsoleCommand(null, 'ls_commands', () => __awaiter(this, void 0, void 0, function* () {
107
+ this.registerConsoleCommand(null, 'commands', () => __awaiter(this, void 0, void 0, function* () {
78
108
  return this.availableCommands
79
109
  .map(([key, value]) => `<span style='color:yellow'>${key}</span>${value.doc ? '\t<span style="color:#aaa">// ' + value.doc + '</span>' : ''}`)
80
- .sort()
81
110
  .join('\n\n');
82
- }), 'no args; print all available commands');
83
- this.registerConsoleCommand(null, 'ls_worlds', () => __awaiter(this, void 0, void 0, function* () {
111
+ }), 'no args; Print all available commands. List includes global commands and commands, ' +
112
+ 'specific to currently selected world. Run "world" to check which world is currently ' +
113
+ 'selected and "world {world_name}" to select desired world');
114
+ this.registerConsoleCommand(null, 'help', (keyword) => __awaiter(this, void 0, void 0, function* () {
115
+ var _a;
116
+ const command = (_a = this.availableCommands.find(([key]) => key === keyword)) === null || _a === void 0 ? void 0 : _a[1];
117
+ if (!command) {
118
+ throw new Error(`Unrecognized command: ${keyword}`);
119
+ }
120
+ return `<span style='color:#aaa'>${command.doc || 'No doc string given'}</span>`;
121
+ }), 'args: [ string ]; Print doc string of provided command');
122
+ this.registerConsoleCommand(null, 'worlds', () => __awaiter(this, void 0, void 0, function* () {
84
123
  return GgWorld.documentWorlds
85
124
  .map(w => (w === this.selectedWorld ? `<span style='color:lightgreen;'>* ${w.name}</span>` : ` ${w.name}`))
86
125
  .join('\n');
87
- }), 'no args; print all available worlds');
88
- this.registerConsoleCommand(null, 'select_world', (...args) => __awaiter(this, void 0, void 0, function* () {
126
+ }), 'no args; Print all currently available worlds');
127
+ this.registerConsoleCommand(null, 'world', (...args) => __awaiter(this, void 0, void 0, function* () {
89
128
  var _a;
90
129
  for (const w of GgWorld.documentWorlds) {
91
130
  if (w.name === args[0]) {
92
- this._selectedWorld = w;
131
+ this.selectedWorld = w;
93
132
  break;
94
133
  }
95
134
  }
96
135
  return ((_a = this.selectedWorld) === null || _a === void 0 ? void 0 : _a.name) || 'null';
97
- }), 'args: [string]; select world by name');
98
- this.registerConsoleCommand(null, 'show_debugger', (...args) => __awaiter(this, void 0, void 0, function* () {
99
- this.showDebugControls = ['1', 'true', '+'].includes(args[0]);
100
- return '' + this.showDebugControls;
101
- }), 'args: [0 or 1]; turn on/off debug panel. Default value is 0');
102
- this.registerConsoleCommand(null, 'show_stats', (...args) => __awaiter(this, void 0, void 0, function* () {
103
- this.showStats = ['1', 'true', '+'].includes(args[0]);
104
- return '' + this.showStats;
105
- }), 'args: [0 or 1]; turn on/off stats. Default value is 0');
136
+ }), 'args: [ string? ]; Get name of selected world or select world by name. Use ' +
137
+ '"worlds" to get list of currently available worlds');
138
+ this.registerConsoleCommand(null, 'stats_panel', (...args) => __awaiter(this, void 0, void 0, function* () {
139
+ this.showStats = args[0] === undefined ? !this.showStats : args[0] === '1';
140
+ return this.showStats ? '1' : '0';
141
+ }), 'args: [ 0|1? ]; Turn on/off stats panel, skip argument to toggle value');
142
+ this.registerConsoleCommand(null, 'debug_panel', (...args) => __awaiter(this, void 0, void 0, function* () {
143
+ this.showDebugControls = args[0] === undefined ? !this.showDebugControls : args[0] === '1';
144
+ return this.showDebugControls ? '1' : '0';
145
+ }), 'args: [ 0|1? ]; Turn on/off debug panel, skip argument to toggle value');
146
+ let unbindKey$ = new Subject();
147
+ this.registerConsoleCommand(null, 'bind_key', (keyCode, command, ...args) => __awaiter(this, void 0, void 0, function* () {
148
+ fromEvent(window, 'keydown')
149
+ .pipe(takeUntil(unbindKey$.pipe(filter(x => x === keyCode))), filter(e => {
150
+ if (e.code !== keyCode) {
151
+ return false;
152
+ }
153
+ if (document.activeElement) {
154
+ for (const k of KeyboardInput.externalFocusBlacklist) {
155
+ if (document.activeElement instanceof k) {
156
+ return false;
157
+ }
158
+ }
159
+ }
160
+ return true;
161
+ }))
162
+ .subscribe(() => {
163
+ this.runConsoleCommand(command, args);
164
+ });
165
+ return 'Ok';
166
+ }), 'args: [ string, ...string ]; Bind a keyboard key by code to console command. Check key codes' +
167
+ ' <a target="_blank" rel="noopener noreferrer" href="https://www.toptal.com/developers/keycode">here</a>. Use "unbind_key" command to unbind it');
168
+ this.registerConsoleCommand(null, 'unbind_key', (...args) => __awaiter(this, void 0, void 0, function* () {
169
+ unbindKey$.next(args[0]);
170
+ return 'Ok';
171
+ }), 'args: [ string ]; Unbind a keyboard key from console command');
172
+ window.ggstatic = this;
173
+ this.autoAssignSelectedWorld();
174
+ this._selectedWorld$.pipe(switchMap(w => (w ? w.disposed$ : NEVER))).subscribe(() => {
175
+ this.selectedWorld = null;
176
+ this.autoAssignSelectedWorld();
177
+ });
178
+ window.dispatchEvent(new Event('ggstatic_added'));
179
+ combineLatest([this._selectedWorld$, this.showDebugControls$]).subscribe(([world, showControls]) => {
180
+ this.debuggerUI.setShowDebugControls(world, !!world && showControls);
181
+ });
182
+ combineLatest([this._selectedWorld$, this.showStats$]).subscribe(([world, showStats]) => {
183
+ this.debuggerUI.setShowStats(world, !!world && showStats);
184
+ });
106
185
  }
107
186
  registerConsoleCommand(world, command, handler, doc) {
108
187
  let commands = {};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import { VERSION } from './version';
1
2
  export * from './base';
2
3
  export * from './2d';
3
4
  export * from './3d';
4
5
  export * from './dev';
6
+ export { VERSION };
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
+ import { VERSION } from './version';
2
+ window.gg_version = VERSION;
1
3
  export * from './base';
2
4
  export * from './2d';
3
5
  export * from './3d';
4
6
  export * from './dev';
7
+ export { VERSION };
@@ -0,0 +1 @@
1
+ export declare const VERSION = "0.0.56";
@@ -0,0 +1 @@
1
+ export const VERSION = '0.0.56';
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@gg-web-engine/core",
3
- "version": "0.0.49",
3
+ "version": "0.0.56",
4
4
  "description": "An attempt to create open source game engine for browser",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "test": "jest",
9
9
  "prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write",
10
- "prepublish": "rm -rf ./dist/ && tsc",
11
- "build": "tsc"
10
+ "prepublish": "rm -rf ./dist/ && npm run build",
11
+ "update-version": "VERSION=$(grep '\"version\":' package.json | sed -E 's/.*\"version\": *\"([^\"]+)\".*/\\1/') && echo \"export const VERSION = '$VERSION';\" > src/version.ts",
12
+ "build": "npm run update-version && tsc"
12
13
  },
13
14
  "repository": {
14
15
  "type": "git",