freeform-modeling-mcp 1.0.26

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 (81) hide show
  1. package/README.md +61 -0
  2. package/index.cjs +21 -0
  3. package/package.json +48 -0
  4. package/src/cli.ts +47 -0
  5. package/src/commands/start.ts +88 -0
  6. package/src/commands/status.ts +81 -0
  7. package/src/dev.ts +24 -0
  8. package/src/lib/fileproxy/index.ts +505 -0
  9. package/src/lib/fileproxy/proxy-server.js +347 -0
  10. package/src/lib/gltf2obj/compress.js +33 -0
  11. package/src/lib/gltf2obj/engine/core/core.js +34 -0
  12. package/src/lib/gltf2obj/engine/core/eventnotifier.js +39 -0
  13. package/src/lib/gltf2obj/engine/core/taskrunner.js +88 -0
  14. package/src/lib/gltf2obj/engine/export/exporter.js +38 -0
  15. package/src/lib/gltf2obj/engine/export/exporterbase.js +86 -0
  16. package/src/lib/gltf2obj/engine/export/exportermodel.js +117 -0
  17. package/src/lib/gltf2obj/engine/export/exporterobj.js +147 -0
  18. package/src/lib/gltf2obj/engine/geometry/box3d.js +60 -0
  19. package/src/lib/gltf2obj/engine/geometry/coord2d.js +35 -0
  20. package/src/lib/gltf2obj/engine/geometry/coord3d.js +126 -0
  21. package/src/lib/gltf2obj/engine/geometry/coord4d.js +15 -0
  22. package/src/lib/gltf2obj/engine/geometry/geometry.js +56 -0
  23. package/src/lib/gltf2obj/engine/geometry/matrix.js +440 -0
  24. package/src/lib/gltf2obj/engine/geometry/octree.js +160 -0
  25. package/src/lib/gltf2obj/engine/geometry/quaternion.js +83 -0
  26. package/src/lib/gltf2obj/engine/geometry/transformation.js +63 -0
  27. package/src/lib/gltf2obj/engine/geometry/tween.js +31 -0
  28. package/src/lib/gltf2obj/engine/import/importer.js +270 -0
  29. package/src/lib/gltf2obj/engine/import/importerbase.js +115 -0
  30. package/src/lib/gltf2obj/engine/import/importerfiles.js +139 -0
  31. package/src/lib/gltf2obj/engine/import/importergltf.js +1045 -0
  32. package/src/lib/gltf2obj/engine/import/importerutils.js +102 -0
  33. package/src/lib/gltf2obj/engine/io/binaryreader.js +93 -0
  34. package/src/lib/gltf2obj/engine/io/binarywriter.js +92 -0
  35. package/src/lib/gltf2obj/engine/io/bufferutils.js +85 -0
  36. package/src/lib/gltf2obj/engine/io/externallibs.js +42 -0
  37. package/src/lib/gltf2obj/engine/io/fileutils.js +120 -0
  38. package/src/lib/gltf2obj/engine/io/textwriter.js +41 -0
  39. package/src/lib/gltf2obj/engine/main.js +19 -0
  40. package/src/lib/gltf2obj/engine/model/color.js +130 -0
  41. package/src/lib/gltf2obj/engine/model/generator.js +433 -0
  42. package/src/lib/gltf2obj/engine/model/material.js +243 -0
  43. package/src/lib/gltf2obj/engine/model/mesh.js +173 -0
  44. package/src/lib/gltf2obj/engine/model/meshbuffer.js +233 -0
  45. package/src/lib/gltf2obj/engine/model/meshinstance.js +128 -0
  46. package/src/lib/gltf2obj/engine/model/meshutils.js +64 -0
  47. package/src/lib/gltf2obj/engine/model/model.js +195 -0
  48. package/src/lib/gltf2obj/engine/model/modelfinalization.js +377 -0
  49. package/src/lib/gltf2obj/engine/model/modelutils.js +117 -0
  50. package/src/lib/gltf2obj/engine/model/node.js +178 -0
  51. package/src/lib/gltf2obj/engine/model/object.js +90 -0
  52. package/src/lib/gltf2obj/engine/model/property.js +86 -0
  53. package/src/lib/gltf2obj/engine/model/quantities.js +46 -0
  54. package/src/lib/gltf2obj/engine/model/topology.js +139 -0
  55. package/src/lib/gltf2obj/engine/model/triangle.js +99 -0
  56. package/src/lib/gltf2obj/engine/threejs/threemodelloader.js +85 -0
  57. package/src/lib/gltf2obj/handler.js +63 -0
  58. package/src/lib/gltf2obj/index.js +47 -0
  59. package/src/lib/logger.ts +304 -0
  60. package/src/lib/print.ts +37 -0
  61. package/src/lib/utils.ts +34 -0
  62. package/src/lib/wsbridge/bridge.ts +639 -0
  63. package/src/lib/wsbridge/lock.ts +258 -0
  64. package/src/llmClient.ts +245 -0
  65. package/src/prompt.ts +187 -0
  66. package/src/server.ts +125 -0
  67. package/src/tools/assets-tool.ts +314 -0
  68. package/src/tools/basic-tools.ts +531 -0
  69. package/src/tools/index.ts +2 -0
  70. package/src/tools/material-tools.ts +88 -0
  71. package/src/tools/modeling/auxiliary-curve-tool.ts +44 -0
  72. package/src/tools/modeling/find-face.ts +38 -0
  73. package/src/tools/modeling/sweep-tool.ts +60 -0
  74. package/src/tools/modeling/utils.ts +181 -0
  75. package/src/tools/modeling-tools.ts +135 -0
  76. package/src/tools/screenshot-tools.ts +107 -0
  77. package/src/tools/tools-info.ts +107 -0
  78. package/src/tools/tripo3d-tools.ts +496 -0
  79. package/src/types/index.ts +25 -0
  80. package/src/types/tripo3d.ts +38 -0
  81. package/tsconfig.json +22 -0
@@ -0,0 +1,63 @@
1
+ import { Coord3D } from './coord3d.js';
2
+ import { Coord4D } from './coord4d.js';
3
+ import { Matrix, MatrixIsEqual } from './matrix.js';
4
+
5
+ export class Transformation
6
+ {
7
+ constructor (matrix)
8
+ {
9
+ if (matrix !== undefined && matrix !== null) {
10
+ this.matrix = matrix;
11
+ } else {
12
+ this.matrix = new Matrix ();
13
+ this.matrix.CreateIdentity ();
14
+ }
15
+ }
16
+
17
+ SetMatrix (matrix)
18
+ {
19
+ this.matrix = matrix;
20
+ return this;
21
+ }
22
+
23
+ GetMatrix ()
24
+ {
25
+ return this.matrix;
26
+ }
27
+
28
+ IsIdentity ()
29
+ {
30
+ return this.matrix.IsIdentity ();
31
+ }
32
+
33
+ AppendMatrix (matrix)
34
+ {
35
+ this.matrix = this.matrix.MultiplyMatrix (matrix);
36
+ return this;
37
+ }
38
+
39
+ Append (transformation)
40
+ {
41
+ this.AppendMatrix (transformation.GetMatrix ());
42
+ return this;
43
+ }
44
+
45
+ TransformCoord3D (coord)
46
+ {
47
+ let coord4D = new Coord4D (coord.x, coord.y, coord.z, 1.0);
48
+ let resultCoord4D = this.matrix.MultiplyVector (coord4D);
49
+ let result = new Coord3D (resultCoord4D.x, resultCoord4D.y, resultCoord4D.z);
50
+ return result;
51
+ }
52
+
53
+ Clone ()
54
+ {
55
+ const clonedMatrix = this.matrix.Clone ();
56
+ return new Transformation (clonedMatrix);
57
+ }
58
+ }
59
+
60
+ export function TransformationIsEqual (a, b)
61
+ {
62
+ return MatrixIsEqual (a.GetMatrix (), b.GetMatrix ());
63
+ }
@@ -0,0 +1,31 @@
1
+ import { CoordDistance3D, SubCoord3D } from './coord3d.js';
2
+
3
+ export function BezierTweenFunction (distance, index, count)
4
+ {
5
+ let t = index / count;
6
+ return distance * (t * t * (3.0 - 2.0 * t));
7
+ }
8
+
9
+ export function LinearTweenFunction (distance, index, count)
10
+ {
11
+ return index * distance / count;
12
+ }
13
+
14
+ export function ParabolicTweenFunction (distance, index, count)
15
+ {
16
+ let t = index / count;
17
+ let t2 = t * t;
18
+ return distance * (t2 / (2.0 * (t2 - t) + 1.0));
19
+ }
20
+
21
+ export function TweenCoord3D (a, b, count, tweenFunc)
22
+ {
23
+ let dir = SubCoord3D (b, a).Normalize ();
24
+ let distance = CoordDistance3D (a, b);
25
+ let result = [];
26
+ for (let i = 0; i < count; i++) {
27
+ let step = tweenFunc (distance, i, count - 1);
28
+ result.push (a.Clone ().Offset (dir, step));
29
+ }
30
+ return result;
31
+ }
@@ -0,0 +1,270 @@
1
+ import { RunTaskAsync } from '../core/taskrunner.js';
2
+ import { FileSource, GetFileName } from '../io/fileutils.js';
3
+ import { RGBColor } from '../model/color.js';
4
+ import { ImporterFile, ImporterFileList } from './importerfiles.js';
5
+ import { ImporterGltf } from './importergltf.js';
6
+
7
+ import * as fflate from 'fflate';
8
+
9
+ export class ImportSettings {
10
+ constructor() {
11
+ this.defaultColor = new RGBColor(200, 200, 200);
12
+ }
13
+ }
14
+
15
+ export const ImportErrorCode =
16
+ {
17
+ NoImportableFile: 1,
18
+ FailedToLoadFile: 2,
19
+ ImportFailed: 3,
20
+ UnknownError: 4
21
+ };
22
+
23
+ export class ImportError {
24
+ constructor(code) {
25
+ this.code = code;
26
+ this.mainFile = null;
27
+ this.message = null;
28
+ }
29
+ }
30
+
31
+ export class ImportResult {
32
+ constructor() {
33
+ this.model = null;
34
+ this.mainFile = null;
35
+ this.upVector = null;
36
+ this.usedFiles = null;
37
+ this.missingFiles = null;
38
+ }
39
+ }
40
+
41
+ export class ImporterFileAccessor {
42
+ constructor(getBufferCallback) {
43
+ this.getBufferCallback = getBufferCallback;
44
+ this.fileBuffers = new Map();
45
+ }
46
+
47
+ GetFileBuffer (filePath) {
48
+ let fileName = GetFileName(filePath);
49
+ if (this.fileBuffers.has(fileName)) {
50
+ return this.fileBuffers.get(fileName);
51
+ }
52
+ let buffer = this.getBufferCallback(fileName);
53
+ this.fileBuffers.set(fileName, buffer);
54
+ return buffer;
55
+ }
56
+ }
57
+
58
+ export class Importer {
59
+ constructor() {
60
+ this.importers = [
61
+ new ImporterGltf(),
62
+ ];
63
+ this.fileList = new ImporterFileList();
64
+ this.model = null;
65
+ this.usedFiles = [];
66
+ this.missingFiles = [];
67
+ }
68
+
69
+ AddImporter (importer) {
70
+ this.importers.push(importer);
71
+ }
72
+
73
+ ImportFiles (inputFiles, settings, callbacks) {
74
+ callbacks.onLoadStart();
75
+ this.LoadFiles(inputFiles, {
76
+ onReady: () => {
77
+ callbacks.onImportStart();
78
+ this.DecompressArchives(this.fileList, () => {
79
+ this.ImportLoadedFiles(settings, callbacks);
80
+ });
81
+ // RunTaskAsync(() => {
82
+
83
+ // });
84
+
85
+
86
+
87
+ },
88
+ onFileListProgress: callbacks.onFileListProgress,
89
+ onFileLoadProgress: callbacks.onFileLoadProgress
90
+ });
91
+ }
92
+
93
+ LoadFiles (inputFiles, callbacks) {
94
+ let newFileList = new ImporterFileList();
95
+ newFileList.FillFromInputFiles(inputFiles);
96
+
97
+ let reset = false;
98
+ if (this.HasImportableFile(newFileList)) {
99
+ reset = true;
100
+ } else {
101
+ let foundMissingFile = false;
102
+ for (let i = 0; i < this.missingFiles.length; i++) {
103
+ let missingFile = this.missingFiles[i];
104
+ if (newFileList.ContainsFileByPath(missingFile)) {
105
+ foundMissingFile = true;
106
+ }
107
+ }
108
+ if (!foundMissingFile) {
109
+ reset = true;
110
+ } else {
111
+ this.fileList.ExtendFromFileList(newFileList);
112
+ reset = false;
113
+ }
114
+ }
115
+ if (reset) {
116
+ this.fileList = newFileList;
117
+ }
118
+ this.fileList.GetContent({
119
+ onReady: callbacks.onReady,
120
+ onFileListProgress: callbacks.onFileListProgress,
121
+ onFileLoadProgress: callbacks.onFileLoadProgress
122
+ });
123
+ }
124
+
125
+ ImportLoadedFiles (settings, callbacks) {
126
+ let importableFiles = this.GetImportableFiles(this.fileList);
127
+ if (importableFiles.length === 0) {
128
+ callbacks.onImportError(new ImportError(ImportErrorCode.NoImportableFile));
129
+ return;
130
+ }
131
+
132
+ if (importableFiles.length === 1 || !callbacks.onSelectMainFile) {
133
+ let mainFile = importableFiles[0];
134
+ this.ImportLoadedMainFile(mainFile, settings, callbacks);
135
+ } else {
136
+ let fileNames = importableFiles.map(importableFile => importableFile.file.name);
137
+ callbacks.onSelectMainFile(fileNames, (mainFileIndex) => {
138
+ if (mainFileIndex === null) {
139
+ callbacks.onImportError(new ImportError(ImportErrorCode.NoImportableFile));
140
+ return;
141
+ }
142
+ let mainFile = importableFiles[mainFileIndex];
143
+ this.ImportLoadedMainFile(mainFile, settings, callbacks);
144
+ // RunTaskAsync(() => {
145
+
146
+ // });
147
+ });
148
+ }
149
+ }
150
+
151
+ ImportLoadedMainFile (mainFile, settings, callbacks) {
152
+ if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
153
+ let error = new ImportError(ImportErrorCode.FailedToLoadFile);
154
+ if (mainFile !== null && mainFile.file !== null) {
155
+ error.mainFile = mainFile.file.name;
156
+ }
157
+ callbacks.onImportError(error);
158
+ return;
159
+ }
160
+
161
+ this.model = null;
162
+ this.usedFiles = [];
163
+ this.missingFiles = [];
164
+ this.usedFiles.push(mainFile.file.name);
165
+
166
+ let importer = mainFile.importer;
167
+ let fileAccessor = new ImporterFileAccessor((fileName) => {
168
+ let fileBuffer = null;
169
+ let file = this.fileList.FindFileByPath(fileName);
170
+ if (file === null || file.content === null) {
171
+ this.missingFiles.push(fileName);
172
+ fileBuffer = null;
173
+ } else {
174
+ this.usedFiles.push(fileName);
175
+ fileBuffer = file.content;
176
+ }
177
+ return fileBuffer;
178
+ });
179
+
180
+ importer.Import(mainFile.file.name, mainFile.file.extension, mainFile.file.content, {
181
+ getDefaultMaterialColor: () => {
182
+ return settings.defaultColor;
183
+ },
184
+ getFileBuffer: (filePath) => {
185
+ return fileAccessor.GetFileBuffer(filePath);
186
+ },
187
+ onSuccess: () => {
188
+ this.model = importer.GetModel();
189
+ let result = new ImportResult();
190
+ result.mainFile = mainFile.file.name;
191
+ result.model = this.model;
192
+ result.usedFiles = this.usedFiles;
193
+ result.missingFiles = this.missingFiles;
194
+ result.upVector = importer.GetUpDirection();
195
+ callbacks.onImportSuccess(result);
196
+ },
197
+ onError: () => {
198
+ let error = new ImportError(ImportErrorCode.ImportFailed);
199
+ error.mainFile = mainFile.file.name;
200
+ error.message = importer.GetErrorMessage();
201
+ callbacks.onImportError(error);
202
+ },
203
+ onComplete: () => {
204
+ importer.Clear();
205
+ }
206
+ });
207
+ }
208
+
209
+ DecompressArchives (fileList, onReady) {
210
+ let files = fileList.GetFiles();
211
+ let archives = [];
212
+ for (let file of files) {
213
+ if (file.extension === 'zip') {
214
+ archives.push(file);
215
+ }
216
+ }
217
+ if (archives.length === 0) {
218
+ onReady();
219
+ return;
220
+ }
221
+ for (let i = 0; i < archives.length; i++) {
222
+ const archiveFile = archives[i];
223
+ const archiveBuffer = new Uint8Array(archiveFile.content);
224
+ const decompressed = fflate.unzipSync(archiveBuffer);
225
+ for (const fileName in decompressed) {
226
+ if (Object.prototype.hasOwnProperty.call(decompressed, fileName)) {
227
+ let file = new ImporterFile(fileName, FileSource.Decompressed, null);
228
+ file.SetContent(decompressed[fileName].buffer);
229
+ fileList.AddFile(file);
230
+ }
231
+ }
232
+ }
233
+ onReady();
234
+ }
235
+
236
+ GetFileList () {
237
+ return this.fileList;
238
+ }
239
+
240
+ HasImportableFile (fileList) {
241
+ let importableFiles = this.GetImportableFiles(fileList);
242
+ return importableFiles.length > 0;
243
+ }
244
+
245
+ GetImportableFiles (fileList) {
246
+ function FindImporter (file, importers) {
247
+ for (let importerIndex = 0; importerIndex < importers.length; importerIndex++) {
248
+ let importer = importers[importerIndex];
249
+ if (importer.CanImportExtension(file.extension)) {
250
+ return importer;
251
+ }
252
+ }
253
+ return null;
254
+ }
255
+
256
+ let importableFiles = [];
257
+ let files = fileList.GetFiles();
258
+ for (let fileIndex = 0; fileIndex < files.length; fileIndex++) {
259
+ let file = files[fileIndex];
260
+ let importer = FindImporter(file, this.importers);
261
+ if (importer !== null) {
262
+ importableFiles.push({
263
+ file: file,
264
+ importer: importer
265
+ });
266
+ }
267
+ }
268
+ return importableFiles;
269
+ }
270
+ }
@@ -0,0 +1,115 @@
1
+ import { Direction } from '../geometry/geometry.js';
2
+ import { Model } from '../model/model.js';
3
+ import { FinalizeModel } from '../model/modelfinalization.js';
4
+ import { IsModelEmpty } from '../model/modelutils.js';
5
+
6
+ export class ImporterBase
7
+ {
8
+ constructor ()
9
+ {
10
+ this.name = null;
11
+ this.extension = null;
12
+ this.callbacks = null;
13
+ this.model = null;
14
+ this.error = null;
15
+ this.message = null;
16
+ }
17
+
18
+ Import (name, extension, content, callbacks)
19
+ {
20
+ this.Clear ();
21
+
22
+ this.name = name;
23
+ this.extension = extension;
24
+ this.callbacks = callbacks;
25
+ this.model = new Model ();
26
+ this.error = false;
27
+ this.message = null;
28
+ this.ResetContent ();
29
+ this.ImportContent (content, () => {
30
+ this.CreateResult (callbacks);
31
+ });
32
+ }
33
+
34
+ Clear ()
35
+ {
36
+ this.name = null;
37
+ this.extension = null;
38
+ this.callbacks = null;
39
+ this.model = null;
40
+ this.error = null;
41
+ this.message = null;
42
+ this.ClearContent ();
43
+ }
44
+
45
+ CreateResult (callbacks)
46
+ {
47
+ if (this.error) {
48
+ callbacks.onError ();
49
+ callbacks.onComplete ();
50
+ return;
51
+ }
52
+
53
+ if (IsModelEmpty (this.model)) {
54
+ this.SetError ('The model doesn\'t contain any meshes.');
55
+ callbacks.onError ();
56
+ callbacks.onComplete ();
57
+ return;
58
+ }
59
+
60
+ FinalizeModel (this.model, {
61
+ getDefaultMaterialColor : this.callbacks.getDefaultMaterialColor
62
+ });
63
+
64
+ callbacks.onSuccess ();
65
+ callbacks.onComplete ();
66
+ }
67
+
68
+ CanImportExtension (extension)
69
+ {
70
+ return false;
71
+ }
72
+
73
+ GetUpDirection ()
74
+ {
75
+ return Direction.Z;
76
+ }
77
+
78
+ ClearContent ()
79
+ {
80
+
81
+ }
82
+
83
+ ResetContent ()
84
+ {
85
+
86
+ }
87
+
88
+ ImportContent (fileContent, onFinish)
89
+ {
90
+
91
+ }
92
+
93
+ GetModel ()
94
+ {
95
+ return this.model;
96
+ }
97
+
98
+ SetError (message)
99
+ {
100
+ this.error = true;
101
+ if (message !== undefined && message !== null) {
102
+ this.message = message;
103
+ }
104
+ }
105
+
106
+ WasError ()
107
+ {
108
+ return this.error;
109
+ }
110
+
111
+ GetErrorMessage ()
112
+ {
113
+ return this.message;
114
+ }
115
+ }
@@ -0,0 +1,139 @@
1
+ import { RunTasks } from '../core/taskrunner.js';
2
+ import { FileSource, GetFileExtension, GetFileName, ReadFile, RequestUrl } from '../io/fileutils.js';
3
+
4
+ export class InputFile {
5
+ constructor(name, source, data) {
6
+ this.name = name;
7
+ this.source = source;
8
+ this.data = data;
9
+ }
10
+ }
11
+
12
+ export function InputFilesFromUrls (urls) {
13
+ let inputFiles = [];
14
+ for (let url of urls) {
15
+ let fileName = GetFileName(url);
16
+ inputFiles.push(new InputFile(fileName, FileSource.Url, url));
17
+ }
18
+ return inputFiles;
19
+ }
20
+
21
+ export function InputFilesFromFileObjects (files) {
22
+ let inputFiles = [];
23
+ for (let url of files) {
24
+ let fileName = GetFileName(url);
25
+ inputFiles.push(new InputFile(fileName, FileSource.File, url));
26
+ }
27
+ return inputFiles;
28
+ }
29
+
30
+ export class ImporterFile {
31
+ constructor(name, source, data) {
32
+ this.name = name;// GetFileName(name);
33
+ this.extension = GetFileExtension(name);
34
+ this.source = source;
35
+ this.data = data;
36
+ this.content = null;
37
+ }
38
+
39
+ SetContent (content) {
40
+ this.content = content;
41
+ }
42
+ }
43
+
44
+ export class ImporterFileList {
45
+ constructor() {
46
+ this.files = [];
47
+ }
48
+
49
+ FillFromInputFiles (inputFiles) {
50
+ this.files = [];
51
+ for (let inputFile of inputFiles) {
52
+ let file = new ImporterFile(inputFile.name, inputFile.source, inputFile.data);
53
+ this.files.push(file);
54
+ }
55
+ }
56
+
57
+
58
+
59
+ ExtendFromFileList (fileList) {
60
+ let files = fileList.GetFiles();
61
+ for (let i = 0; i < files.length; i++) {
62
+ let file = files[i];
63
+ if (!this.ContainsFileByPath(file.name)) {
64
+ this.files.push(file);
65
+ }
66
+ }
67
+ }
68
+
69
+ GetFiles () {
70
+ return this.files;
71
+ }
72
+
73
+ GetContent (callbacks) {
74
+ RunTasks(this.files.length, {
75
+ runTask: (index, onTaskComplete) => {
76
+ callbacks.onFileListProgress(index, this.files.length);
77
+ this.GetFileContent(this.files[index], {
78
+ onReady: onTaskComplete,
79
+ onProgress: callbacks.onFileLoadProgress
80
+ });
81
+ },
82
+ onReady: callbacks.onReady
83
+ });
84
+ }
85
+
86
+ ContainsFileByPath (filePath) {
87
+ return this.FindFileByPath(filePath) !== null;
88
+ }
89
+
90
+ FindFileByPath (filePath) {
91
+ let fileName = GetFileName(filePath).toLowerCase();
92
+ for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
93
+ let file = this.files[fileIndex];
94
+ if (file.name.toLowerCase() === fileName) {
95
+ return file;
96
+ }
97
+ }
98
+ return null;
99
+ }
100
+
101
+ IsOnlyUrlSource () {
102
+ if (this.files.length === 0) {
103
+ return false;
104
+ }
105
+ for (let i = 0; i < this.files.length; i++) {
106
+ let file = this.files[i];
107
+ if (file.source !== FileSource.Url && file.source !== FileSource.Decompressed) {
108
+ return false;
109
+ }
110
+ }
111
+ return true;
112
+ }
113
+
114
+ AddFile (file) {
115
+ this.files.push(file);
116
+ }
117
+
118
+ GetFileContent (file, callbacks) {
119
+ if (file.content !== null) {
120
+ callbacks.onReady();
121
+ return;
122
+ }
123
+ let loaderPromise = null;
124
+ if (file.source === FileSource.Url) {
125
+ loaderPromise = RequestUrl(file.data, callbacks.onProgress);
126
+ } else if (file.source === FileSource.File) {
127
+ loaderPromise = ReadFile(file.data, callbacks.onProgress);
128
+ } else {
129
+ callbacks.onReady();
130
+ return;
131
+ }
132
+ loaderPromise.then((content) => {
133
+ file.SetContent(content);
134
+ }).catch(() => {
135
+ }).finally(() => {
136
+ callbacks.onReady();
137
+ });
138
+ }
139
+ }