bg2e-js 2.1.2 → 2.2.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.
Files changed (147) hide show
  1. package/dist/bg2e-js.js +7031 -6989
  2. package/dist/bg2e-js.js.map +1 -1
  3. package/package.json +20 -2
  4. package/src/app/AppController.ts +39 -0
  5. package/src/app/Bg2KeyboardEvent.ts +54 -0
  6. package/src/app/Bg2MouseEvent.ts +82 -0
  7. package/src/app/Bg2TouchEvent.ts +18 -0
  8. package/src/app/Canvas.ts +108 -0
  9. package/src/app/EventBase.ts +10 -0
  10. package/src/app/MainLoop.ts +273 -0
  11. package/src/app/index.ts +25 -0
  12. package/src/base/Color.ts +134 -0
  13. package/src/base/Environment.ts +183 -0
  14. package/src/base/Light.ts +192 -0
  15. package/src/base/Material.ts +619 -0
  16. package/src/base/PolyList.ts +365 -0
  17. package/src/base/Texture.ts +620 -0
  18. package/src/base/index.ts +81 -0
  19. package/src/db/Bg2LoaderPlugin.ts +129 -0
  20. package/src/db/DBPluginApi.ts +48 -0
  21. package/src/db/Loader.ts +116 -0
  22. package/src/db/LoaderPlugin.ts +34 -0
  23. package/src/db/MtlParser.ts +7 -0
  24. package/src/db/ObjLoaderPlugin.ts +55 -0
  25. package/src/db/ObjParser.ts +252 -0
  26. package/src/db/ObjWriterPlugin.ts +19 -0
  27. package/src/db/VitscnjLoaderPlugin.ts +100 -0
  28. package/src/db/Writer.ts +52 -0
  29. package/src/db/WriterPlugin.ts +22 -0
  30. package/src/db/index.ts +44 -0
  31. package/src/debug/DebugRenderer.ts +173 -0
  32. package/src/debug/WebGLTextureViewer.ts +75 -0
  33. package/src/debug/index.ts +7 -0
  34. package/src/index.html +11 -0
  35. package/src/index.ts +33 -0
  36. package/src/manipulation/SelectionBuffer.ts +82 -0
  37. package/src/manipulation/SelectionHighlight.ts +85 -0
  38. package/src/manipulation/SelectionIdAssignVisitor.ts +97 -0
  39. package/src/manipulation/SelectionManager.ts +166 -0
  40. package/src/manipulation/SelectionMode.ts +6 -0
  41. package/src/math/Mat3.ts +259 -0
  42. package/src/math/Mat4.ts +706 -0
  43. package/src/math/MatrixStrategy.ts +25 -0
  44. package/src/math/Quat.ts +65 -0
  45. package/src/math/Vec.ts +753 -0
  46. package/src/math/constants.ts +47 -0
  47. package/src/math/functions.ts +103 -0
  48. package/src/math/index.ts +74 -0
  49. package/src/phsics/joint.ts +137 -0
  50. package/src/primitives/arrow.ts +58 -0
  51. package/src/primitives/cone.ts +138 -0
  52. package/src/primitives/cube.ts +60 -0
  53. package/src/primitives/cylinder.ts +216 -0
  54. package/src/primitives/index.ts +13 -0
  55. package/src/primitives/plane.ts +31 -0
  56. package/src/primitives/sphere.ts +809 -0
  57. package/src/render/BRDFIntegrationMap.ts +4 -0
  58. package/src/render/Environment.ts +136 -0
  59. package/src/render/FrameBuffer.ts +35 -0
  60. package/src/render/MaterialRenderer.ts +34 -0
  61. package/src/render/Pipeline.ts +109 -0
  62. package/src/render/PolyListRenderer.ts +47 -0
  63. package/src/render/RenderBuffer.ts +197 -0
  64. package/src/render/RenderQueue.ts +199 -0
  65. package/src/render/RenderState.ts +116 -0
  66. package/src/render/Renderer.ts +248 -0
  67. package/src/render/SceneAppController.ts +238 -0
  68. package/src/render/SceneRenderer.ts +373 -0
  69. package/src/render/Shader.ts +32 -0
  70. package/src/render/ShadowRenderer.ts +176 -0
  71. package/src/render/SkyCube.ts +106 -0
  72. package/src/render/SkySphere.ts +118 -0
  73. package/src/render/TextureMergerRenderer.ts +70 -0
  74. package/src/render/TextureRenderer.ts +34 -0
  75. package/src/render/index.ts +67 -0
  76. package/src/render/webgl/FrameBuffer.ts +10 -0
  77. package/src/render/webgl/MaterialRenderer.ts +113 -0
  78. package/src/render/webgl/Pipeline.ts +89 -0
  79. package/src/render/webgl/PolyListRenderer.ts +260 -0
  80. package/src/render/webgl/RenderBuffer.ts +227 -0
  81. package/src/render/webgl/Renderer.ts +262 -0
  82. package/src/render/webgl/SceneRenderer.ts +68 -0
  83. package/src/render/webgl/ShaderProgram.ts +424 -0
  84. package/src/render/webgl/ShadowRenderer.ts +6 -0
  85. package/src/render/webgl/SkyCube.ts +16 -0
  86. package/src/render/webgl/SkySphere.ts +16 -0
  87. package/src/render/webgl/State.ts +152 -0
  88. package/src/render/webgl/TextureRenderer.ts +167 -0
  89. package/src/render/webgl/VertexBuffer.ts +137 -0
  90. package/src/render/webgl/index.ts +35 -0
  91. package/src/scene/Camera.ts +458 -0
  92. package/src/scene/Chain.ts +44 -0
  93. package/src/scene/ChainJoint.ts +58 -0
  94. package/src/scene/Component.ts +173 -0
  95. package/src/scene/ComponentMap.ts +107 -0
  96. package/src/scene/Drawable.ts +154 -0
  97. package/src/scene/EnvironmentComponent.ts +142 -0
  98. package/src/scene/FindNodeVisitor.ts +60 -0
  99. package/src/scene/LightComponent.ts +155 -0
  100. package/src/scene/MatrixState.ts +46 -0
  101. package/src/scene/Node.ts +314 -0
  102. package/src/scene/NodeVisitor.ts +15 -0
  103. package/src/scene/OrbitCameraController.ts +450 -0
  104. package/src/scene/SmoothOrbitCameraController.ts +99 -0
  105. package/src/scene/Transform.ts +73 -0
  106. package/src/scene/index.ts +57 -0
  107. package/src/shaders/BasicDiffuseColorShader.ts +111 -0
  108. package/src/shaders/BasicPBRLightShader.ts +277 -0
  109. package/src/shaders/DebugRenderShader.ts +98 -0
  110. package/src/shaders/DepthRenderShader.ts +91 -0
  111. package/src/shaders/IrradianceMapCubeShader.ts +116 -0
  112. package/src/shaders/PBRLightIBLShader.ts +487 -0
  113. package/src/shaders/PickSelectionShader.ts +101 -0
  114. package/src/shaders/PresentDebugFramebufferShader.ts +118 -0
  115. package/src/shaders/PresentTextureShader.ts +99 -0
  116. package/src/shaders/SelectionHighlightShader.ts +127 -0
  117. package/src/shaders/ShaderFunction.ts +318 -0
  118. package/src/shaders/SkyCubeShader.ts +94 -0
  119. package/src/shaders/SkySphereShader.ts +102 -0
  120. package/src/shaders/SpecularMapCubeShader.ts +165 -0
  121. package/src/shaders/TextureMergerShader.ts +171 -0
  122. package/src/shaders/index.ts +37 -0
  123. package/src/shaders/webgl/color_correction.glsl +47 -0
  124. package/src/shaders/webgl/constants.glsl +6 -0
  125. package/src/shaders/webgl/index.ts +70 -0
  126. package/src/shaders/webgl/normal_map.glsl +9 -0
  127. package/src/shaders/webgl/pbr.glsl +173 -0
  128. package/src/shaders/webgl/uniforms.glsl +91 -0
  129. package/src/shaders/webgl_shader_lib.ts +213 -0
  130. package/src/tools/BinaryResourceProvider.ts +14 -0
  131. package/src/tools/ImageResourceProvider.ts +66 -0
  132. package/src/tools/MaterialModifier.ts +276 -0
  133. package/src/tools/Resource.ts +203 -0
  134. package/src/tools/ResourceProvider.ts +69 -0
  135. package/src/tools/TextResourceProvider.ts +24 -0
  136. package/src/tools/TextureCache.ts +52 -0
  137. package/src/tools/TextureResourceDatabase.ts +100 -0
  138. package/src/tools/UserAgent.ts +362 -0
  139. package/src/tools/VideoResourceProvider.ts +50 -0
  140. package/src/tools/WriteStrategy.ts +22 -0
  141. package/src/tools/base64.ts +11 -0
  142. package/src/tools/crypto.ts +19 -0
  143. package/src/tools/endiantess.ts +13 -0
  144. package/src/tools/image.ts +18 -0
  145. package/src/tools/index.ts +41 -0
  146. package/src/tools/processType.ts +38 -0
  147. package/src/vite-env.d.ts +12 -0
package/package.json CHANGED
@@ -1,13 +1,30 @@
1
1
  {
2
2
  "name": "bg2e-js",
3
- "version": "2.1.2",
3
+ "version": "2.2.1",
4
4
  "description": "a graphics engine for productivity applications",
5
5
  "main": "./dist/bg2e-js.js",
6
+ "types": "./src/index.ts",
6
7
  "files": [
7
8
  "dist/bg2e-js.js",
8
- "dist/bg2e-js.js.map"
9
+ "dist/bg2e-js.js.map",
10
+ "src"
9
11
  ],
10
12
  "module": "./dist/bg2e-js.js",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./src/index.ts",
16
+ "import": "./dist/bg2e-js.js",
17
+ "default": "./dist/bg2e-js.js"
18
+ },
19
+ "./ts": {
20
+ "types": "./src/index.ts",
21
+ "import": "./src/index.ts"
22
+ },
23
+ "./ts/*": {
24
+ "types": "./src/*",
25
+ "import": "./src/*"
26
+ }
27
+ },
11
28
  "type": "module",
12
29
  "scripts": {
13
30
  "dev": "vite build --watch --emptyOutDir",
@@ -33,6 +50,7 @@
33
50
  "bg2io": "^1.0.7"
34
51
  },
35
52
  "devDependencies": {
53
+ "typescript": "^5.9.3",
36
54
  "vite": "^7.1.5"
37
55
  }
38
56
  }
@@ -0,0 +1,39 @@
1
+ import Bg2MouseEvent from "./Bg2MouseEvent";
2
+ import Bg2KeyboardEvent from "./Bg2KeyboardEvent";
3
+ import Bg2TouchEvent from "./Bg2TouchEvent";
4
+
5
+ export default class AppController {
6
+ _mainLoop: any;
7
+
8
+ constructor() {
9
+ this._mainLoop = null;
10
+ }
11
+
12
+ get mainLoop(): any { return this._mainLoop; }
13
+ set mainLoop(ml: any) { this._mainLoop = ml; }
14
+
15
+ get canvas(): any { return this._mainLoop?.canvas; }
16
+
17
+ get renderer(): any { return this._mainLoop?.canvas?.renderer; }
18
+
19
+ get viewport(): { width: number; height: number; aspectRatio: number } {
20
+ return this.canvas?.viewport || { width: 0, height: 0, aspectRatio: 0 };
21
+ }
22
+
23
+ async init(): Promise<void> {}
24
+ reshape(width: number, height: number): void {}
25
+ async frame(delta: number): Promise<void> {}
26
+ display(): void {}
27
+ destroy(): void {}
28
+ keyDown(evt: Bg2KeyboardEvent): void {}
29
+ keyUp(evt: Bg2KeyboardEvent): void {}
30
+ mouseUp(evt: Bg2MouseEvent): void {}
31
+ mouseDown(evt: Bg2MouseEvent): void {}
32
+ mouseMove(evt: Bg2MouseEvent): void {}
33
+ mouseOut(evt: Bg2MouseEvent): void {}
34
+ mouseDrag(evt: Bg2MouseEvent): void {}
35
+ mouseWheel(evt: Bg2MouseEvent): void {}
36
+ touchStart(evt: Bg2TouchEvent): void {}
37
+ touchMove(evt: Bg2TouchEvent): void {}
38
+ touchEnd(evt: Bg2TouchEvent): void {}
39
+ }
@@ -0,0 +1,54 @@
1
+ import EventBase from "./EventBase";
2
+
3
+ export enum SpecialKey {
4
+ BACKSPACE = "Backspace",
5
+ TAB = "Tab",
6
+ ENTER = "Enter",
7
+ SHIFT = "Shift",
8
+ SHIFT_LEFT = "ShiftLeft",
9
+ SHIFT_RIGHT = "ShiftRight",
10
+ CTRL = "Control",
11
+ CTRL_LEFT = "ControlLeft",
12
+ CTRL_RIGHT = "ControlRight",
13
+ ALT = "Alt",
14
+ ALT_LEFT = "AltLeft",
15
+ ALT_RIGHT = "AltRight",
16
+ PAUSE = "Pause",
17
+ CAPS_LOCK = "CapsLock",
18
+ ESCAPE = "Escape",
19
+ PAGE_UP = "PageUp",
20
+ PAGEDOWN = "PageDown",
21
+ END = "End",
22
+ HOME = "Home",
23
+ LEFT_ARROW = "ArrowLeft",
24
+ UP_ARROW = "ArrowUp",
25
+ RIGHT_ARROW = "ArrowRight",
26
+ DOWN_ARROW = "ArrowDown",
27
+ INSERT = "Insert",
28
+ DELETE = "Delete",
29
+ SPACE = "Space"
30
+ }
31
+
32
+ export const createKeyboardEvent = (evt: any): KeyboardEvent => {
33
+ const code = (SpecialKey as any)[evt.code] != null ? evt.keyCode : evt.code;
34
+ return new KeyboardEvent(code, evt);
35
+ }
36
+
37
+ export default class KeyboardEvent extends EventBase {
38
+ key: string;
39
+ event: any;
40
+
41
+ static IsSpecialKey(event: any): boolean {
42
+ return (SpecialKey as any)[event.code] != null;
43
+ }
44
+
45
+ constructor(key: string, event: any) {
46
+ super();
47
+ this.key = key;
48
+ this.event = event;
49
+ }
50
+
51
+ get isSpecialKey(): boolean {
52
+ return KeyboardEvent.IsSpecialKey(this.event);
53
+ }
54
+ }
@@ -0,0 +1,82 @@
1
+ import { getMouseEventOffset } from "./Canvas";
2
+ import EventBase from "./EventBase";
3
+
4
+ export enum MouseButton {
5
+ LEFT = 0,
6
+ MIDDLE = 1,
7
+ RIGHT = 2,
8
+ NONE = -1
9
+ }
10
+
11
+ export enum MouseButtonEventType {
12
+ NONE = 0,
13
+ UP = 1,
14
+ DOWN = 2
15
+ }
16
+
17
+ export const createMouseEvent = (evt: any, mainLoop: any, buttonType: MouseButtonEventType): MouseEvent => {
18
+ mainLoop.mouseStatus.pos = getMouseEventOffset(evt, mainLoop.canvas);
19
+ if (buttonType !== MouseButtonEventType.NONE) {
20
+ const buttonStatus = buttonType === MouseButtonEventType.DOWN;
21
+ if (evt.button === MouseButton.LEFT) {
22
+ mainLoop.mouseStatus.leftButton = buttonStatus;
23
+ }
24
+ else if (evt.button === MouseButton.MIDDLE) {
25
+ mainLoop.mouseStatus.middleButton = buttonStatus;
26
+ }
27
+ else if (evt.button === MouseButton.RIGHT) {
28
+ mainLoop.mouseStatus.rightButton = buttonStatus;
29
+ }
30
+ }
31
+
32
+ return new MouseEvent(evt.button, mainLoop.mouseStatus.pos.x, mainLoop.mouseStatus.pos.y, 0, evt);
33
+ }
34
+
35
+ const g_mouseButtons: boolean[] = [false, false, false];
36
+ export const leftMouseButton = (): boolean => {
37
+ return g_mouseButtons[0];
38
+ }
39
+
40
+ export const middleMouseButton = (): boolean => {
41
+ return g_mouseButtons[1];
42
+ }
43
+
44
+ export const rightMouseButton = (): boolean => {
45
+ return g_mouseButtons[2];
46
+ }
47
+
48
+ export const clearMouseButtons = (): void => {
49
+ g_mouseButtons[0] = false;
50
+ g_mouseButtons[1] = false;
51
+ g_mouseButtons[2] = false;
52
+ }
53
+
54
+ export const setMouseButton = (event: any, status: boolean): void => {
55
+ switch (event.button) {
56
+ case MouseButton.LEFT:
57
+ g_mouseButtons[0] = status;
58
+ break;
59
+ case MouseButton.MIDDLE:
60
+ g_mouseButtons[1] = status;
61
+ break;
62
+ case MouseButton.RIGHT:
63
+ g_mouseButtons[2] = status;
64
+ break;
65
+ }
66
+ }
67
+ export default class MouseEvent extends EventBase {
68
+ button: MouseButton;
69
+ x: number;
70
+ y: number;
71
+ delta: number;
72
+ event: any;
73
+
74
+ constructor(button: MouseButton = MouseButton.NONE, x: number = -1, y: number = -1, delta: number = 0, event: any = null) {
75
+ super();
76
+ this.button = button;
77
+ this.x = x;
78
+ this.y = y;
79
+ this.delta = delta;
80
+ this.event = event;
81
+ }
82
+ }
@@ -0,0 +1,18 @@
1
+ import { getEventTouches } from "./Canvas";
2
+ import EventBase from "./EventBase";
3
+
4
+ export const createTouchEvent = (evt: any, mainLoop: any): TouchEvent => {
5
+ const touches = getEventTouches(evt,mainLoop.canvas);
6
+ return new TouchEvent(touches, evt);
7
+ }
8
+
9
+ export default class TouchEvent extends EventBase {
10
+ touches: any;
11
+ event: any;
12
+
13
+ constructor(touches: any, event: any) {
14
+ super();
15
+ this.touches = touches;
16
+ this.event = event;
17
+ }
18
+ }
@@ -0,0 +1,108 @@
1
+ import { generateUUID } from "../tools/crypto";
2
+
3
+ export const getMouseEventOffset = (evt: any, canvas: Canvas): { x: number; y: number } => {
4
+ const offset = canvas.domElement.getBoundingClientRect();
5
+ return {
6
+ x: evt.clientX - offset.left,
7
+ y: evt.clientY - offset.top
8
+ };
9
+ }
10
+
11
+ export const getEventTouches = (evt: any, canvas: Canvas): any[] => {
12
+ const offset = canvas.domElement.getBoundingClientRect();
13
+ const touches = Array.from(evt.touches).map((touch: any) => {
14
+ return {
15
+ identifier: touch.identifier,
16
+ x: touch.clientX - offset.left,
17
+ y: touch.clientY - offset.top,
18
+ force: touch.force,
19
+ rotationAngle: touch.rotationAngle,
20
+ radiusX: touch.radiusX,
21
+ radiusY: touch.radiusY
22
+ };
23
+ });
24
+ return touches;
25
+ }
26
+
27
+ let g_firstCanvas: Canvas | null = null;
28
+
29
+ export default class Canvas {
30
+ private _renderer: any;
31
+ private _domElement: HTMLCanvasElement;
32
+ _mainLoop: any;
33
+
34
+ static FirstCanvas(): Canvas {
35
+ if (!g_firstCanvas) {
36
+ throw new Error("No Canvas instance has been created yet.");
37
+ }
38
+ return g_firstCanvas;
39
+ }
40
+
41
+ constructor(domElement: HTMLCanvasElement, renderer: any) {
42
+ this._renderer = renderer;
43
+ this._domElement = domElement;
44
+ (this._domElement as any)._bg2e_id = generateUUID();
45
+
46
+ g_firstCanvas = g_firstCanvas || this;
47
+
48
+ // Initialized in mainLoop constructor
49
+ this._mainLoop = null;
50
+ }
51
+
52
+ get id(): string {
53
+ return (this._domElement as any)._bg2e_id;
54
+ }
55
+
56
+ async init(): Promise<void> {
57
+ await this._renderer.init(this);
58
+ }
59
+
60
+ get mainLoop(): any { return this._mainLoop; }
61
+
62
+ get renderer(): any { return this._renderer; }
63
+
64
+ get domElement(): HTMLCanvasElement { return this._domElement; }
65
+
66
+ get width(): number { return this._domElement.clientWidth; }
67
+
68
+ get height(): number { return this._domElement.clientHeight; }
69
+
70
+ get viewport(): { width: number; height: number; aspectRatio: number } { return { width: this.width, height: this.height, aspectRatio: this.width / this.height }; }
71
+
72
+ updateViewportSize(): void {
73
+ const sizeInPx = { w: this.domElement.clientWidth, h: this.domElement.clientHeight };
74
+ this.domElement.width = sizeInPx.w * window.devicePixelRatio;
75
+ this.domElement.height = sizeInPx.h * window.devicePixelRatio;
76
+ }
77
+
78
+ screenshot(format?: string, width?: number, height?: number): string {
79
+ let canvasStyle = "";
80
+ const prevSize = {
81
+ width: 0,
82
+ height: 0
83
+ };
84
+
85
+ if (width) {
86
+ height = height ? height : width;
87
+ canvasStyle = this.domElement.style.cssText;
88
+ prevSize.width = this.domElement.width;
89
+ prevSize.height = this.domElement.height;
90
+
91
+ this.domElement.style.cssText = `top:auto;left:auto;bottom:auto;right:auto;width:${width}px;height:${height}px;`;
92
+ this.domElement.width = width;
93
+ this.domElement.height = height;
94
+ this.mainLoop.appController.reshape(width, height);
95
+ this.mainLoop.appController.display();
96
+ }
97
+
98
+ const data = this.domElement.toDataURL(format);
99
+ if (width) {
100
+ this.domElement.style.cssText = canvasStyle;
101
+ this.domElement.width = prevSize.width;
102
+ this.domElement.height = prevSize.height;
103
+ this.mainLoop.appController.reshape(prevSize.width, prevSize.height);
104
+ this.mainLoop.appController.display();
105
+ }
106
+ return data;
107
+ }
108
+ }
@@ -0,0 +1,10 @@
1
+
2
+ export default class EventBase {
3
+ private _stopPropagation: boolean = false;
4
+
5
+ stopPropagation() {
6
+ this._stopPropagation = true;
7
+ }
8
+
9
+ get isEventPropagationStopped() { return this._stopPropagation; }
10
+ }
@@ -0,0 +1,273 @@
1
+ import Canvas from "./Canvas";
2
+ import AppController from "./AppController";
3
+
4
+ import {
5
+ MouseButtonEventType,
6
+ createMouseEvent,
7
+ clearMouseButtons,
8
+ setMouseButton
9
+ } from "./Bg2MouseEvent";
10
+ import Bg2MouseEvent from "./Bg2MouseEvent";
11
+ import { createTouchEvent } from "./Bg2TouchEvent";
12
+ import Bg2TouchEvent from "./Bg2TouchEvent";
13
+ import { createKeyboardEvent } from "./Bg2KeyboardEvent";
14
+ import Bg2KeyboardEvent from "./Bg2KeyboardEvent";
15
+
16
+ export enum FrameUpdate {
17
+ AUTO = 0,
18
+ MANUAL = 1
19
+ }
20
+
21
+ interface AnimationLoopState {
22
+ lastTime: number;
23
+ mainLoop: MainLoop[];
24
+ }
25
+
26
+ const g_animationLoop: AnimationLoopState = {
27
+ lastTime: 0,
28
+ mainLoop: []
29
+ };
30
+
31
+ async function animationLoop(totalTime?: number): Promise<void> {
32
+ totalTime = totalTime || 0;
33
+ requestAnimationFrame(animationLoop);
34
+ const elapsed = totalTime - g_animationLoop.lastTime;
35
+ g_animationLoop.lastTime = totalTime;
36
+ for (const ml of g_animationLoop.mainLoop) {
37
+ await onUpdate(ml, elapsed);
38
+ }
39
+ }
40
+
41
+ class MouseStatus {
42
+ pos: { x: number; y: number };
43
+ leftButton: boolean;
44
+ middleButton: boolean;
45
+ rightButton: boolean;
46
+
47
+ constructor() {
48
+ this.pos = { x: 0, y: 0 };
49
+ this.leftButton = false;
50
+ this.middleButton = false;
51
+ this.rightButton = false;
52
+ }
53
+
54
+ get anyButton(): boolean { return this.leftButton || this.middleButton || this.rightButton; }
55
+ }
56
+
57
+ export default class MainLoop {
58
+ private _canvas: Canvas;
59
+ private _appController: AppController;
60
+ private _updateMode: FrameUpdate;
61
+ private _firstFrameRendered: boolean;
62
+ private _redisplayFrames: number;
63
+ private _mouseStatus: MouseStatus;
64
+
65
+ constructor(canvas: Canvas, appController: AppController) {
66
+ this._canvas = canvas;
67
+ (this._canvas as any)._mainLoop = this;
68
+ this._appController = appController;
69
+ (this._appController as any)._mainLoop = this;
70
+ this._updateMode = FrameUpdate.AUTO;
71
+ this._firstFrameRendered = false;
72
+ this._redisplayFrames = 1;
73
+
74
+ this._mouseStatus = new MouseStatus();
75
+ }
76
+
77
+ get canvas(): Canvas { return this._canvas; }
78
+ get appController(): AppController { return this._appController; }
79
+ get renderer(): any { return this._canvas?.renderer; }
80
+
81
+ get updateMode(): FrameUpdate { return this._updateMode; }
82
+ set updateMode(um: FrameUpdate) { this._updateMode = um; }
83
+
84
+ get mouseStatus(): MouseStatus { return this._mouseStatus; }
85
+
86
+ get redisplay(): boolean { return this._redisplayFrames > 0; }
87
+
88
+ async run(): Promise<void> {
89
+ await this.canvas.init();
90
+ await this.appController.init();
91
+ initEvents(this);
92
+ g_animationLoop.mainLoop.push(this);
93
+ animationLoop();
94
+ }
95
+
96
+ exit(): void {
97
+ this.appController.destroy();
98
+ const i = g_animationLoop.mainLoop.indexOf(this);
99
+ if (i !== -1) {
100
+ g_animationLoop.mainLoop.splice(i, 1);
101
+ }
102
+ }
103
+
104
+ postReshape(): void {
105
+ onResize(this);
106
+ }
107
+
108
+ postRedisplay({ frames = 10, timeout = 10 }: { frames?: number; timeout?: number } = {}): void {
109
+ if (timeout <= 0) {
110
+ this._redisplayFrames = frames;
111
+ }
112
+ else {
113
+ setTimeout(() => this._redisplayFrames = frames, timeout);
114
+ }
115
+ }
116
+ }
117
+
118
+
119
+ function initEvents(mainLoop: MainLoop): void {
120
+ onResize(mainLoop);
121
+
122
+ const handlePropagation = (bgEvt: any, evt: Event): boolean => {
123
+ if (bgEvt.isEventPropagationStopped) {
124
+ evt.stopPropagation();
125
+ evt.preventDefault();
126
+ return false;
127
+ }
128
+ return true;
129
+ }
130
+
131
+ const c = mainLoop.canvas.domElement;
132
+ (c as any).__mainLoop = mainLoop;
133
+ c.addEventListener("mousedown", (evt: any) => {
134
+ return handlePropagation(onMouseDown(evt, (evt.target as any).__mainLoop), evt);
135
+ });
136
+ c.addEventListener("mousemove", (evt: any) => {
137
+ return handlePropagation(onMouseMove(evt, (evt.target as any).__mainLoop), evt);
138
+ });
139
+ c.addEventListener("mouseout", (evt: any) => {
140
+ return handlePropagation(onMouseOut(evt, (evt.target as any).__mainLoop), evt);
141
+ });
142
+
143
+ c.addEventListener("mouseover", (evt: any) => {
144
+ return handlePropagation(onMouseOver(evt, (evt.target as any).__mainLoop), evt);
145
+ });
146
+
147
+ c.addEventListener("mouseup", (evt: any) => {
148
+ return handlePropagation(onMouseUp(evt, (evt.target as any).__mainLoop), evt);
149
+ });
150
+
151
+ c.addEventListener("touchstart", (evt: any) => {
152
+ return handlePropagation(onTouchStart(evt, (evt.target as any).__mainLoop), evt);
153
+ });
154
+
155
+ c.addEventListener("touchmove", (evt: any) => {
156
+ return handlePropagation(onTouchMove(evt, (evt.target as any).__mainLoop), evt);
157
+ });
158
+
159
+ c.addEventListener("touchend", (evt: any) => {
160
+ return handlePropagation(onTouchEnd(evt, (evt.target as any).__mainLoop), evt);
161
+ });
162
+
163
+ const mouseWheelEvt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
164
+ c.addEventListener(mouseWheelEvt, (evt: any) => {
165
+ return handlePropagation(onMouseWheel(evt, (evt.target as any).__mainLoop), evt);
166
+ });
167
+
168
+ window.addEventListener("keydown", (evt: any) => {
169
+ g_animationLoop.mainLoop.forEach(ml => onKeyDown(evt, ml));
170
+ });
171
+
172
+ window.addEventListener("keyup", (evt: any) => {
173
+ g_animationLoop.mainLoop.forEach(ml => onKeyUp(evt, ml));
174
+ });
175
+
176
+ window.addEventListener("resize", (evt: Event) => {
177
+ onResize(mainLoop);
178
+ });
179
+
180
+ (c as any).oncontextmenu = (evt: Event) => false;
181
+ }
182
+
183
+ function onResize(mainLoop: MainLoop): void {
184
+ const dpi = window.devicePixelRatio;
185
+ mainLoop.appController.reshape(mainLoop.canvas.width * dpi, mainLoop.canvas.height * dpi);
186
+ }
187
+
188
+ async function onUpdate(mainLoop: MainLoop, elapsed: number): Promise<void> {
189
+ if (mainLoop.redisplay) {
190
+ if (mainLoop.updateMode === FrameUpdate.AUTO) {
191
+ (mainLoop as any)._redisplayFrames = 1;
192
+ }
193
+ else {
194
+ (mainLoop as any)._redisplayFrames--;
195
+ }
196
+ if ((mainLoop as any)._redisplayFrames > 0 || !(mainLoop as any)._firstFrameRendered) {
197
+ await mainLoop.appController.frame(elapsed);
198
+ mainLoop.appController.display();
199
+ (mainLoop as any)._firstFrameRendered = true;
200
+ }
201
+ }
202
+ }
203
+
204
+ function onMouseDown(evt: any, mainLoop: MainLoop): Bg2MouseEvent {
205
+ const bg2Event = createMouseEvent(evt, mainLoop, MouseButtonEventType.DOWN);
206
+ setMouseButton(bg2Event, true);
207
+ mainLoop.appController.mouseDown(bg2Event);
208
+ return bg2Event;
209
+ }
210
+
211
+ function onMouseMove(evt: any, mainLoop: MainLoop): Bg2MouseEvent {
212
+ const bg2Event = createMouseEvent(evt, mainLoop, MouseButtonEventType.NONE);
213
+ mainLoop.appController.mouseMove(bg2Event);
214
+ if (mainLoop.mouseStatus.anyButton) {
215
+ mainLoop.appController.mouseDrag(bg2Event);
216
+ }
217
+ return bg2Event;
218
+ }
219
+
220
+ function onMouseOut(evt: any, mainLoop: MainLoop): Bg2MouseEvent {
221
+ const bg2Event = createMouseEvent(evt, mainLoop, MouseButtonEventType.NONE);
222
+ clearMouseButtons();
223
+ mainLoop.appController.mouseOut(bg2Event);
224
+ return bg2Event;
225
+ }
226
+
227
+ function onMouseOver(evt: any, mainLoop: MainLoop): Bg2MouseEvent {
228
+ return onMouseMove(evt, mainLoop);
229
+ }
230
+
231
+ function onMouseUp(evt: any, mainLoop: MainLoop): Bg2MouseEvent {
232
+ const bg2Event = createMouseEvent(evt, mainLoop, MouseButtonEventType.UP);
233
+ setMouseButton(bg2Event, false);
234
+ mainLoop.appController.mouseUp(bg2Event);
235
+ return bg2Event;
236
+ }
237
+
238
+ function onMouseWheel(evt: any, mainLoop: MainLoop): Bg2MouseEvent {
239
+ const bg2Event = createMouseEvent(evt, mainLoop, MouseButtonEventType.NONE);
240
+ bg2Event.delta = evt.wheelDelta ? evt.wheelDelta * -1 : evt.detail * 10;
241
+ mainLoop.appController.mouseWheel(bg2Event);
242
+ return bg2Event;
243
+ }
244
+
245
+ function onTouchStart(evt: any, mainLoop: MainLoop): Bg2TouchEvent {
246
+ const bgEvent = createTouchEvent(evt, mainLoop);
247
+ mainLoop.appController.touchStart(bgEvent);
248
+ return bgEvent;
249
+ }
250
+
251
+ function onTouchMove(evt: any, mainLoop: MainLoop): Bg2TouchEvent {
252
+ const bgEvent = createTouchEvent(evt, mainLoop);
253
+ mainLoop.appController.touchMove(bgEvent);
254
+ return bgEvent;
255
+ }
256
+
257
+ function onTouchEnd(evt: any, mainLoop: MainLoop): Bg2TouchEvent {
258
+ const bgEvent = createTouchEvent(evt, mainLoop);
259
+ mainLoop.appController.touchEnd(bgEvent);
260
+ return bgEvent;
261
+ }
262
+
263
+ function onKeyDown(evt: any, mainLoop: MainLoop): Bg2KeyboardEvent {
264
+ const bgEvent = createKeyboardEvent(evt);
265
+ mainLoop.appController.keyDown(bgEvent);
266
+ return bgEvent;
267
+ }
268
+
269
+ function onKeyUp(evt: any, mainLoop: MainLoop): Bg2KeyboardEvent {
270
+ const bgEvent = createKeyboardEvent(evt);
271
+ mainLoop.appController.keyUp(bgEvent);
272
+ return bgEvent;
273
+ }
@@ -0,0 +1,25 @@
1
+ import AppController from "./AppController";
2
+ import Canvas, {
3
+ getMouseEventOffset,
4
+ getEventTouches
5
+ } from "./Canvas";
6
+ import EventBase from "./EventBase";
7
+ import MainLoop, {
8
+ FrameUpdate
9
+ } from "./MainLoop";
10
+ import Bg2KeyboardEvent from "./Bg2KeyboardEvent";
11
+ import Bg2MouseEvent from "./Bg2MouseEvent";
12
+ import Bg2TouchEvent from "./Bg2TouchEvent";
13
+
14
+ export default {
15
+ AppController,
16
+ FrameUpdate,
17
+ Canvas,
18
+ getMouseEventOffset,
19
+ getEventTouches,
20
+ EventBase,
21
+ Bg2KeyboardEvent,
22
+ MainLoop,
23
+ Bg2MouseEvent,
24
+ Bg2TouchEvent
25
+ }