bg2e-js 2.1.1 → 2.2.0

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 +616 -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
@@ -0,0 +1,276 @@
1
+ import {
2
+ textureTypeLoader,
3
+ colorTypeLoader,
4
+ vectorTypeLoader,
5
+ primitiveTypeLoader
6
+ } from "../base/Material";
7
+ import Material from "../base/Material";
8
+ import Texture from "../base/Texture";
9
+ import Vec from "../math/Vec";
10
+ import Color from "../base/Color";
11
+
12
+ const checkImageData = (texture: Texture | Color | number | null): Promise<void> => {
13
+ return texture instanceof Texture ? texture.loadImageData() : Promise.resolve();
14
+ }
15
+
16
+ interface MaterialModifierData {
17
+ class?: string;
18
+ alphaCutoff?: number;
19
+ castShadows?: boolean;
20
+ diffuse?: any;
21
+ diffuseScale?: any;
22
+ fresnel?: any;
23
+ isTransparent?: boolean;
24
+ lightEmission?: any;
25
+ lightEmissionChannel?: number;
26
+ lightEmissionScale?: any;
27
+ metallic?: any;
28
+ metallicChannel?: number;
29
+ metallicScale?: any;
30
+ normal?: any;
31
+ normalScale?: any;
32
+ roughness?: any;
33
+ roughnessChannel?: number;
34
+ roughnessScale?: any;
35
+ unlit?: boolean;
36
+ }
37
+
38
+ // TODO: Update all material properties (difuse -> albedo, etc)
39
+ export default class MaterialModifier {
40
+ private _alphaCutoff?: number;
41
+ private _castShadows?: boolean;
42
+ private _diffuse?: any;
43
+ private _diffuseScale?: any;
44
+ private _fresnel?: any;
45
+ private _isTransparent?: boolean;
46
+ private _lightEmission?: any;
47
+ private _lightEmissionChannel?: number;
48
+ private _lightEmissionScale?: any;
49
+ private _metallic?: any;
50
+ private _metallicChannel?: number;
51
+ private _metallicScale?: any;
52
+ private _normal?: any;
53
+ private _normalScale?: any;
54
+ private _roughness?: any;
55
+ private _roughnessChannel?: number;
56
+ private _roughnessScale?: any;
57
+ private _unlit?: boolean;
58
+
59
+ constructor(jsonData: MaterialModifierData | null = null) {
60
+ if (jsonData) {
61
+ if (jsonData['class'] && jsonData['class'] !== "PBRMaterial") {
62
+ console.warn(`Could not apply material modifier because of class "${jsonData['class']}". Check the valid material types in bg2 engine v2`);
63
+ return;
64
+ }
65
+ if (jsonData.alphaCutoff !== undefined) {
66
+ this.alphaCutoff = jsonData.alphaCutoff;
67
+ }
68
+
69
+ if (jsonData.castShadows !== undefined) {
70
+ this.castShadows = jsonData.castShadows;
71
+ }
72
+
73
+ if (jsonData.diffuse !== undefined) {
74
+ this.diffuse = jsonData.diffuse;
75
+ }
76
+
77
+ if (jsonData.diffuseScale !== undefined) {
78
+ this.diffuseScale = jsonData.diffuseScale;
79
+ }
80
+
81
+ if (jsonData.fresnel !== undefined) {
82
+ this.fresnel = jsonData.fresnel;
83
+ }
84
+
85
+ if (jsonData.isTransparent !== undefined) {
86
+ this.isTransparent = jsonData.isTransparent;
87
+ }
88
+
89
+ if (jsonData.lightEmission !== undefined) {
90
+ this.lightEmission = jsonData.lightEmission;
91
+ }
92
+
93
+ if (jsonData.lightEmissionChannel !== undefined) {
94
+ this.lightEmissionChannel = jsonData.lightEmissionChannel;
95
+ }
96
+
97
+ if (jsonData.lightEmissionScale !== undefined) {
98
+ this.lightEmissionScale = jsonData.lightEmissionScale;
99
+ }
100
+
101
+ if (jsonData.metallic !== undefined) {
102
+ this.metallic = jsonData.metallic;
103
+ }
104
+
105
+ if (jsonData.metallicChannel !== undefined) {
106
+ this.metallicChannel = jsonData.metallicChannel;
107
+ }
108
+
109
+ if (jsonData.metallicScale !== undefined) {
110
+ this.metallicScale = jsonData.metallicScale;
111
+ }
112
+
113
+ if (jsonData.normal !== undefined) {
114
+ this.normal = jsonData.normal;
115
+ }
116
+
117
+ if (jsonData.normalScale !== undefined) {
118
+ this.normalScale = jsonData.normalScale;
119
+ }
120
+
121
+ if (jsonData.roughness !== undefined) {
122
+ this.roughness = jsonData.roughness;
123
+ }
124
+
125
+ if (jsonData.roughnessChannel !== undefined) {
126
+ this.roughnessChannel = jsonData.roughnessChannel;
127
+ }
128
+
129
+ if (jsonData.roughnessScale !== undefined) {
130
+ this.roughnessScale = jsonData.roughnessScale;
131
+ }
132
+
133
+ if (jsonData.unlit !== undefined) {
134
+ this.unlit = jsonData.unlit;
135
+ }
136
+
137
+ }
138
+ }
139
+
140
+ get alphaCutoff(): number | undefined { return this._alphaCutoff; }
141
+ set alphaCutoff(v: number | undefined) { this._alphaCutoff = v; }
142
+
143
+ get castShadows(): boolean | undefined { return this._castShadows; }
144
+ set castShadows(v: boolean | undefined) { this._castShadows = v; }
145
+
146
+ get diffuse(): any { return this._diffuse; }
147
+ set diffuse(v: any) { this._diffuse = v; }
148
+
149
+ get diffuseScale(): any { return this._diffuseScale; }
150
+ set diffuseScale(v: any) { this._diffuseScale = v; }
151
+
152
+ get fresnel(): any { return this._fresnel; }
153
+ set fresnel(v: any) { this._fresnel = v; }
154
+
155
+ get isTransparent(): boolean | undefined { return this._isTransparent; }
156
+ set isTransparent(v: boolean | undefined) { this._isTransparent = v; }
157
+
158
+ get lightEmission(): any { return this._lightEmission; }
159
+ set lightEmission(v: any) { this._lightEmission = v; }
160
+
161
+ get lightEmissionChannel(): number | undefined { return this._lightEmissionChannel; }
162
+ set lightEmissionChannel(v: number | undefined) { this._lightEmissionChannel = v; }
163
+
164
+ get lightEmissionScale(): any { return this._lightEmissionScale; }
165
+ set lightEmissionScale(v: any) { this._lightEmissionScale = v; }
166
+
167
+ get metallic(): any { return this._metallic; }
168
+ set metallic(v: any) { this._metallic = v; }
169
+
170
+ get metallicChannel(): number | undefined { return this._metallicChannel; }
171
+ set metallicChannel(v: number | undefined) { this._metallicChannel = v; }
172
+
173
+ get metallicScale(): any { return this._metallicScale; }
174
+ set metallicScale(v: any) { this._metallicScale = v; }
175
+
176
+ get normal(): any { return this._normal; }
177
+ set normal(v: any) { this._normal = v; }
178
+
179
+ get normalScale(): any { return this._normalScale; }
180
+ set normalScale(v: any) { this._normalScale = v; }
181
+
182
+ get roughness(): any { return this._roughness; }
183
+ set roughness(v: any) { this._roughness = v; }
184
+
185
+ get roughnessChannel(): number | undefined { return this._roughnessChannel; }
186
+ set roughnessChannel(v: number | undefined) { this._roughnessChannel = v; }
187
+
188
+ get roughnessScale(): any { return this._roughnessScale; }
189
+ set roughnessScale(v: any) { this._roughnessScale = v; }
190
+
191
+ get unlit(): boolean | undefined { return this._unlit; }
192
+ set unlit(v: boolean | undefined) { this._unlit = v; }
193
+
194
+ async applyModifier(material: Material, relativePath: string = ""): Promise<void> {
195
+ const promises: Promise<void>[] = [];
196
+ if (this.alphaCutoff !== undefined) {
197
+ material.alphaCutoff = this.alphaCutoff;
198
+ }
199
+
200
+ if (this.castShadows !== undefined) {
201
+ material.castShadows = this.castShadows;
202
+ }
203
+
204
+ // TODO: diffuse -> albedo or albedoTexture
205
+ if (this.diffuse !== undefined) {
206
+ //(material as any).diffuse = deserializeColorTexture(this.diffuse, relativePath);
207
+ //promises.push(checkImageData((material as any).diffuse));
208
+ }
209
+
210
+ // TODO: diffuseScale -> albedoScale
211
+ if (this.diffuseScale !== undefined) {
212
+ //(material as any).diffuseScale = deserializeVector(this.diffuseScale);
213
+ }
214
+
215
+ if (this.fresnel !== undefined) {
216
+ //(material as any).fresnel = deserializeVector(this.fresnel);
217
+ }
218
+
219
+ if (this.isTransparent !== undefined) {
220
+ material.isTransparent = this.isTransparent;
221
+ }
222
+
223
+ if (this.lightEmission !== undefined) {
224
+
225
+ }
226
+
227
+ if (this.lightEmissionChannel !== undefined) {
228
+
229
+ }
230
+
231
+ if (this.lightEmissionScale !== undefined) {
232
+
233
+ }
234
+
235
+ if (this.metallic !== undefined) {
236
+ //(material as any).metallic = deserializeValueTexture(this.metallic, relativePath);
237
+ //promises.push(checkImageData((material as any).metallic));
238
+ }
239
+
240
+ if (this.metallicChannel !== undefined) {
241
+ (material as any).metallicChannel = this.metallicChannel;
242
+ }
243
+
244
+ if (this.metallicScale !== undefined) {
245
+ //(material as any).metallicScale = deserializeVector(this.metallicScale);
246
+ }
247
+
248
+ if (this.normal !== undefined) {
249
+ //(material as any).normal = deserializeColorTexture(this.normal, relativePath);
250
+ //promises.push(checkImageData((material as any).normal));
251
+ }
252
+
253
+ if (this.normalScale !== undefined) {
254
+ //material.normalScale = deserializeVector(this.normalScale);
255
+ }
256
+
257
+ if (this.roughness !== undefined) {
258
+ //(material as any).roughness = deserializeValueTexture(this.roughness, relativePath);
259
+ //promises.push(checkImageData((material as any).roughness));
260
+ }
261
+
262
+ if (this.roughnessChannel !== undefined) {
263
+ material.roughnessChannel = this.roughnessChannel;
264
+ }
265
+
266
+ if (this.roughnessScale !== undefined) {
267
+ //material.roughnessScale = deserializeVector(this.roughnessScale);
268
+ }
269
+
270
+ if (this.unlit !== undefined) {
271
+ material.unlit = this.unlit;
272
+ }
273
+ await Promise.allSettled(promises);
274
+ }
275
+
276
+ }
@@ -0,0 +1,203 @@
1
+
2
+ import ImageResourceProvider from "./ImageResourceProvider.js";
3
+ import VideoResourceProvider from "./VideoResourceProvider.js";
4
+ import BinaryResourceProvider from "./BinaryResourceProvider.js";
5
+ import TextResourceProvider from "./TextResourceProvider.js";
6
+ import ResourceProvider from "./ResourceProvider.js";
7
+
8
+ interface WriteStrategy {
9
+ writeBytes(url: string, data: Uint8Array): Promise<void>;
10
+ writeImage(url: string, data: HTMLImageElement): Promise<void>;
11
+ writeText(url: string, data: string): Promise<void>;
12
+ writeJson(url: string, data: any): Promise<void>;
13
+ }
14
+
15
+ interface ResourceConstructorOptions {
16
+ imageProvider?: ImageResourceProvider | null;
17
+ videoProvider?: VideoResourceProvider | null;
18
+ binaryProvider?: BinaryResourceProvider | null;
19
+ textProvider?: TextResourceProvider | null;
20
+ writeStrategy?: WriteStrategy | null;
21
+ }
22
+
23
+ export enum ResourceType {
24
+ PolyList = 'PolyList', // Array of meshes
25
+ Drawable = 'Drawable',
26
+ Node = 'Node',
27
+ Texture = 'Texture',
28
+ Material = 'Material'
29
+ }
30
+
31
+ export const getExtension = (url: string): string => {
32
+ const reResult = /\.([a-z0-9]+)$/i.exec(url);
33
+ if (reResult) {
34
+ return reResult[1];
35
+ }
36
+ else {
37
+ return "";
38
+ }
39
+ }
40
+
41
+ export const getFileName = (url: string): string => {
42
+ const reResult = /(.+)\/(.+)$/.exec(url);
43
+ if (reResult) {
44
+ return reResult[2];
45
+ }
46
+ else {
47
+ return url;
48
+ }
49
+ }
50
+
51
+ export const removeExtension = (url: string): string => {
52
+ const reResult = /(.+)\.(.+)$/.exec(url);
53
+ if (reResult) {
54
+ return reResult[1];
55
+ }
56
+ else {
57
+ return url;
58
+ }
59
+ }
60
+
61
+ export const removeFileName = (url: string): string => {
62
+ const i = url.lastIndexOf('/');
63
+ if (i != -1) {
64
+ return url.substring(0,i + 1);
65
+ }
66
+ return url;
67
+ }
68
+
69
+ export const isAbsolute = (url: string): boolean => {
70
+ return /^http|^\//i.test(url);
71
+ }
72
+
73
+ export const jointUrl = (base: string, append: string): string => {
74
+ if (base[base.length - 1] !== '/' && append[0] !== '/') {
75
+ return `${base}/${append}`;
76
+ }
77
+ else if ((base[base.length - 1] === '/' && append[0] !== '/') ||
78
+ (base[base.length - 1] !== '/' && append[0] === '/')) {
79
+ return `${base}${append}`;
80
+ }
81
+ else {
82
+ return `${base}${append.slice(1)}`;
83
+ }
84
+ }
85
+
86
+ export const isFormat = (url: string, formats: string[]): boolean => formats.some(fmt => (new RegExp(`\.${fmt}`,'i')).test(url));
87
+
88
+ export const addFormats = (fmts: string | string[], dst: string[]): void => {
89
+ if (!Array.isArray(fmts)) {
90
+ fmts = [fmts]
91
+ }
92
+ fmts.forEach(fmt => {
93
+ if (dst.indexOf(fmt) === -1) {
94
+ dst.push(fmt);
95
+ }
96
+ });
97
+ }
98
+
99
+
100
+ const g_validImageFormats = [
101
+ "jpg",
102
+ "jpeg",
103
+ "gif",
104
+ "png"
105
+ ];
106
+
107
+ export const isValidImage = (url: string): boolean => isFormat(url,g_validImageFormats);
108
+
109
+ export const addImageFormats = (fmts: string | string[]): void => {
110
+ addFormats(fmts, g_validImageFormats);
111
+ }
112
+
113
+ export const getValidImageFormats = (): string[] => g_validImageFormats;
114
+
115
+ const g_validVideoFormats = [
116
+ "mp4",
117
+ "m4v"
118
+ ];
119
+
120
+ export const isValidVideo = (url: string): boolean => isFormat(url,g_validVideoFormats);
121
+
122
+ export const addVideoFormats = (fmts: string | string[]): void => {
123
+ addFormats(fmts, g_validVideoFormats);
124
+ }
125
+
126
+ export const getValidVideoFormats = (): string[] => g_validVideoFormats;
127
+
128
+ const g_validBinaryFormats = [
129
+ "vwglb",
130
+ "bg2"
131
+ ];
132
+
133
+ export const isValidBinary = (url: string): boolean => isFormat(url, g_validBinaryFormats);
134
+
135
+ export const addBinaryFormats = (fmts: string | string[]): void => {
136
+ addFormats(fmts, g_validBinaryFormats);
137
+ }
138
+
139
+ export const getValidBinaryFormats = (): string[] => g_validBinaryFormats;
140
+
141
+ export default class Resource {
142
+ private _imageProvider: ImageResourceProvider;
143
+ private _videoProvider: VideoResourceProvider;
144
+ private _binaryProvider: BinaryResourceProvider;
145
+ private _textProvider: TextResourceProvider;
146
+ private _writeStrategy?: WriteStrategy;
147
+
148
+ constructor({
149
+ imageProvider = null,
150
+ videoProvider = null,
151
+ binaryProvider = null,
152
+ textProvider = null,
153
+ writeStrategy = undefined
154
+ }: ResourceConstructorOptions = {}) {
155
+ this._imageProvider = imageProvider || new ImageResourceProvider();
156
+ this._videoProvider = videoProvider || new VideoResourceProvider();
157
+ this._binaryProvider = binaryProvider || new BinaryResourceProvider();
158
+ this._textProvider = textProvider || new TextResourceProvider();
159
+
160
+ if (writeStrategy) {
161
+ this.writeStrategy = writeStrategy;
162
+ }
163
+ }
164
+
165
+ set writeStrategy(ws: WriteStrategy | undefined) {
166
+ this._writeStrategy = ws;
167
+
168
+ if (ws) {
169
+ this._imageProvider.writeStrategy = ws;
170
+ this._videoProvider.writeStrategy = ws;
171
+ this._binaryProvider.writeStrategy = ws;
172
+ this._textProvider.writeStrategy = ws;
173
+ }
174
+ }
175
+
176
+ get writeStrategy(): WriteStrategy | undefined {
177
+ return this._writeStrategy;
178
+ }
179
+
180
+ getProvider(url: string): ResourceProvider {
181
+ switch (true) {
182
+ case isValidImage(url):
183
+ return this._imageProvider;
184
+ case isValidVideo(url):
185
+ return this._videoProvider;
186
+ case isValidBinary(url):
187
+ return this._binaryProvider;
188
+ default:
189
+ return this._textProvider;
190
+ }
191
+ }
192
+
193
+ async load(url: string): Promise<any> {
194
+ const provider = this.getProvider(url);
195
+ const data = await provider.load(url);
196
+ return data;
197
+ }
198
+
199
+ async write(url: string, data: any): Promise<void> {
200
+ const provider = this.getProvider(url);
201
+ return await provider.write(url,data);
202
+ }
203
+ }
@@ -0,0 +1,69 @@
1
+ import { isBrowser } from './processType';
2
+ import { base64ToArrayBuffer } from './base64';
3
+
4
+ export enum DataFormat {
5
+ BYTES = 0, // Uint8Array
6
+ IMAGE = 1, // DOM img
7
+ BASE64 = 2, // Base64 string. It can include or not the Base64 image prefix
8
+ TEXT = 3, // Text string
9
+ JSON_STRING = 4, // JSON text
10
+ JSON_OBJECT = 5, // JSON serializable object
11
+ FILE_PATH = 6 // File path (used to implement file copy)
12
+ }
13
+
14
+ interface WriteStrategy {
15
+ writeBytes(url: string, data: Uint8Array): Promise<void>;
16
+ writeImage(url: string, data: HTMLImageElement): Promise<void>;
17
+ writeText(url: string, data: string): Promise<void>;
18
+ writeJson(url: string, data: any): Promise<void>;
19
+ }
20
+
21
+ export default class ResourceProvider {
22
+ private _writeStrategy?: WriteStrategy;
23
+
24
+ set writeStrategy(ws: WriteStrategy) {
25
+ this._writeStrategy = ws;
26
+ }
27
+
28
+ get writeStrategy(): WriteStrategy {
29
+ if (!this._writeStrategy) {
30
+ throw new Error("ResourceProvider.write(): no write strategy configured.");
31
+ }
32
+ return this._writeStrategy;
33
+ }
34
+
35
+ async load(url: string): Promise<any> {
36
+
37
+ }
38
+
39
+ async write(url: string, data: any, format: DataFormat = DataFormat.TEXT): Promise<void> {
40
+ switch (format) {
41
+ case DataFormat.BYTES:
42
+ return this.writeStrategy.writeBytes(url,data);
43
+ case DataFormat.IMAGE:
44
+ if (isBrowser()) {
45
+ return this.writeStrategy.writeImage(url, data);
46
+ }
47
+ else {
48
+ throw new Error("ResourceProvider.write() unsupported data format: Image data format is supported only on browsers or electron renderer process.");
49
+ }
50
+ case DataFormat.BASE64:
51
+ const bytes = await base64ToArrayBuffer(data);
52
+ return this.writeStrategy.writeBytes(url, bytes);
53
+ case DataFormat.TEXT:
54
+ return this.writeStrategy.writeText(url, data);
55
+ case DataFormat.JSON_STRING:
56
+ return this.writeStrategy.writeText(url, data);
57
+ case DataFormat.JSON_OBJECT:
58
+ return this.writeStrategy.writeJson(url, data);
59
+ case DataFormat.FILE_PATH:
60
+ return this.copyFile(url, data);
61
+ default:
62
+ throw new Error("ResourceProvider.write() invalid format");
63
+ }
64
+ }
65
+
66
+ async copyFile(destinationUrl: string, sourceFilePath: string): Promise<void> {
67
+ throw new Error("ResourceProvider.copyFile(): not implemented");
68
+ }
69
+ }
@@ -0,0 +1,24 @@
1
+ import ResourceProvider from './ResourceProvider';
2
+
3
+ export default class TextResourceProvider extends ResourceProvider {
4
+ async load(url: string): Promise<any> {
5
+ const response = await fetch(url);
6
+ if (response.ok) {
7
+ const textData = await response.text();
8
+ try {
9
+ const objectData = JSON.parse(textData);
10
+ return objectData;
11
+ }
12
+ catch (e) {
13
+ return textData;
14
+ }
15
+ }
16
+ else {
17
+ throw new Error(`Resource not found at '${ url }'`);
18
+ }
19
+ }
20
+
21
+ async write(url: string, data: any): Promise<void> {
22
+ throw new Error('TextResourceProvider.write not implemented.');
23
+ }
24
+ }
@@ -0,0 +1,52 @@
1
+
2
+ import Canvas from '../app/Canvas';
3
+ import Texture from '../base/Texture';
4
+
5
+ const g_canvasCache: { [key: string]: TextureCache } = {};
6
+
7
+ export default class TextureCache {
8
+ static Get(canvas: Canvas | null = null): TextureCache {
9
+ canvas = canvas || Canvas.FirstCanvas();
10
+ if (!canvas && !g_canvasCache["__no_canvas__"]) {
11
+ console.warn("TextureCache.Get() No canvas available. If your application uses a canvas, ensure that it has been created before using TexturCache. If your application does not use a canvas, you may disregard this message.");
12
+ }
13
+
14
+ if (canvas && !g_canvasCache[canvas.id]) {
15
+ g_canvasCache[canvas.id] = new TextureCache(canvas);
16
+ }
17
+ else if (!canvas && !g_canvasCache["__no_canvas__"]) {
18
+ g_canvasCache["__no_canvas__"] = new TextureCache(null);
19
+ }
20
+
21
+ return g_canvasCache[canvas ? canvas.id : "__no_canvas__"];
22
+ }
23
+
24
+ private _canvas: Canvas | null;
25
+ private _cache: { [key: string]: Texture };
26
+
27
+ constructor(canvas: Canvas | null) {
28
+ this._canvas = canvas;
29
+ this._cache = {};
30
+ }
31
+
32
+ get canvas(): Canvas | null { return this._canvas; }
33
+
34
+ registerTexture(texture: Texture): void {
35
+ if (!texture.fileName) {
36
+ throw new Error("TextureCache.registerTexture() texture path is empty");
37
+ }
38
+ this._cache[texture.fileName] = texture;
39
+ }
40
+
41
+ getTexture(texturePath: string): Texture | undefined {
42
+ return this._cache[texturePath];
43
+ }
44
+
45
+ findTexture(texturePath: string): boolean {
46
+ return this._cache[texturePath] != null;
47
+ }
48
+
49
+ clear(): void {
50
+ this._cache = {};
51
+ }
52
+ }