@threepipe/plugin-blend-importer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,783 @@
1
+ /* eslint-disable camelcase, no-unused-vars, no-empty, no-constant-condition */
2
+ const DNA1 = 826363460;
3
+ const ENDB = 1111772741;
4
+
5
+ /* Note: Blender coordinates treat the Z axis as the vertical an Y as depth. */
6
+
7
+ // web worker not functional in this version
8
+ let USE_WEBWORKER = false;
9
+
10
+ let worker = null;
11
+
12
+ // FR = new FileReader(),
13
+
14
+ const return_object = {
15
+ loadBlendFromArrayBuffer: function (array_buffer) {
16
+ return_object.ready = false;
17
+ if (USE_WEBWORKER) {
18
+ worker.postMessage(array_buffer, array_buffer);
19
+ } else {
20
+ worker.onmessage({
21
+ data: array_buffer,
22
+ });
23
+ }
24
+ },
25
+ // loadBlendFromBlob: function (blob) {
26
+ // FR.onload = function () {
27
+ // return_object.loadBlendFromArrayBuffer(this.result);
28
+ // };
29
+ // FR.readAsArrayBuffer(blob);
30
+ // },
31
+ ready: true,
32
+ onParseReady: function () {},
33
+ };
34
+
35
+ function worker_code () {
36
+ 'use strict';
37
+
38
+ let data = null,
39
+ _data = null,
40
+ BIG_ENDIAN = false,
41
+ pointer_size = 0,
42
+ struct_names = [],
43
+ offset = 0,
44
+ working_blend_file = null,
45
+ current_SDNA_template = null,
46
+ templates = {},
47
+ finished_objects = [],
48
+ FILE = null,
49
+ ERROR = null,
50
+ AB = null;
51
+
52
+ const self = this;
53
+
54
+ function parseFile (msg) {
55
+
56
+ if (typeof msg.data == 'object') {
57
+ // reset global variables
58
+ AB = null;
59
+ data = null;
60
+ BIG_ENDIAN = false;
61
+ pointer_size = 0;
62
+ struct_names = [];
63
+ offset = 0;
64
+ working_blend_file = null;
65
+ finished_objects = [];
66
+ current_SDNA_template = null;
67
+
68
+
69
+ // set data
70
+ _data = msg.data;
71
+
72
+ AB = _data.slice();
73
+
74
+ data = new DataView(_data);
75
+
76
+
77
+ FILE = new BLENDER_FILE(AB);
78
+
79
+ // start parsing
80
+ readFile();
81
+
82
+ // export parsed data
83
+ self.postMessage(FILE, ERROR);
84
+ }
85
+ }
86
+
87
+ /*
88
+ Export object for a parsed __blender_file__.
89
+ */
90
+
91
+ var BLENDER_FILE = function (AB) {
92
+ this.AB = AB;
93
+ // this.double = new Float64Array(AB);
94
+ this.byte = new Uint8Array(AB);
95
+
96
+ this.dv = new DataView(AB);
97
+
98
+ this.objects = {};
99
+ this.memory_lookup = {},
100
+ this.object_array = [];
101
+
102
+ this.template = null;
103
+ };
104
+
105
+ BLENDER_FILE.prototype = {
106
+ addObject: function (obj) {
107
+ this.object_array.push(obj);
108
+ if (!this.objects[obj.blender_name]) this.objects[obj.blender_name] = [];
109
+ this.objects[obj.blender_name].push(obj);
110
+ },
111
+
112
+ getPointer: function (offset) {
113
+ const pointerLow = this.dv.getUint32(offset, this.template.endianess);
114
+ if (this.template.pointer_size > 4) {
115
+ const pointerHigh = this.dv.getUint32(offset + 4, this.template.endianess);
116
+ if (this.template.endianess) {
117
+ return (pointerLow) + 'l|h' + pointerHigh;
118
+ } else {
119
+ return (pointerHigh) + 'h|l' + pointerLow;
120
+ }
121
+ } else {
122
+ return pointerLow;
123
+ }
124
+ },
125
+ };
126
+
127
+ self.onmessage = parseFile;
128
+ // this.onmessage = parseFile;
129
+
130
+ /*
131
+ These functions map offsets in the blender __blender_file__ to basic types (byte,short,int,float) through TypedArrays;
132
+ This allows the underlying binary data to be changed.
133
+ */
134
+
135
+ function float64Prop (offset, Blender_Array_Length, length) {
136
+ return {
137
+ get: function () {
138
+ return (Blender_Array_Length > 1) ?
139
+ new Float64Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
140
+ this.__blender_file__.dv.getFloat64(this.__data_address__ + offset, this.__blender_file__.template.endianess);
141
+ },
142
+ set: function (float) {
143
+ if (Blender_Array_Length > 1) {} else {
144
+ this.__blender_file__.dv.setFloat64(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
145
+ }
146
+ },
147
+ };
148
+ }
149
+
150
+ function floatProp (offset, Blender_Array_Length, length) {
151
+ return {
152
+ get: function () {
153
+ return (Blender_Array_Length > 1) ?
154
+ new Float32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
155
+ this.__blender_file__.dv.getFloat32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
156
+ },
157
+ set: function (float) {
158
+ if (Blender_Array_Length > 1) {} else {
159
+ this.__blender_file__.dv.setFloat32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
160
+ }
161
+ },
162
+ };
163
+ }
164
+
165
+ function intProp (offset, Blender_Array_Length, length) {
166
+ return {
167
+ get: function () {
168
+ return (Blender_Array_Length > 1) ?
169
+ new Int32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
170
+ this.__blender_file__.dv.getInt32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
171
+ },
172
+ set: function (float) {
173
+ if (Blender_Array_Length > 1) {} else {
174
+ this.__blender_file__.dv.setInt32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
175
+ }
176
+ },
177
+ };
178
+ }
179
+
180
+ function uIntProp (offset, Blender_Array_Length, length) {
181
+ return {
182
+ get: function () {
183
+ return (Blender_Array_Length > 1) ?
184
+ new Uint32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
185
+ this.__blender_file__.dv.getUint32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
186
+ },
187
+ set: function (float) {
188
+ if (Blender_Array_Length > 1) {} else {
189
+ this.__blender_file__.dv.setUint32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
190
+ }
191
+ },
192
+ };
193
+ }
194
+
195
+ function shortProp (offset, Blender_Array_Length, length) {
196
+ return {
197
+ get: function () {
198
+ return (Blender_Array_Length > 1) ?
199
+ new Int16Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
200
+ this.__blender_file__.dv.getInt16(this.__data_address__ + offset, this.__blender_file__.template.endianess);
201
+ },
202
+ set: function (float) {
203
+ if (Blender_Array_Length > 1) {} else {
204
+ this.__blender_file__.dv.setInt16(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
205
+ }
206
+ },
207
+ };
208
+ }
209
+
210
+ const uShortProp = (offset, Blender_Array_Length, length) => {
211
+ return {
212
+ get: function () {
213
+ return (Blender_Array_Length > 1) ?
214
+ new Uint16Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
215
+ this.__blender_file__.dv.getUint16(this.__data_address__ + offset, this.__blender_file__.template.endianess);
216
+ },
217
+ set: function (float) {
218
+ if (Blender_Array_Length > 1) {
219
+ } else {
220
+ this.__blender_file__.dv.setUint16(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
221
+ }
222
+ },
223
+ };
224
+ };
225
+
226
+ function charProp (offset, Blender_Array_Length, length) {
227
+ return {
228
+ get: function () {
229
+ if (Blender_Array_Length > 1) {
230
+ let start = this.__data_address__ + offset;
231
+ let end = start;
232
+ let buffer_guard = 0;
233
+
234
+ while (this.__blender_file__.byte[end] != 0 && buffer_guard++ < length) end++;
235
+
236
+ return toString(this.__blender_file__.AB, start, end);
237
+ }
238
+ return this.__blender_file__.byte[(this.__data_address__ + offset)];
239
+ },
240
+ set: function (byte) {
241
+ if (Blender_Array_Length > 1) {
242
+ const string = byte + '';
243
+ let i = 0;
244
+ const l = string.length;
245
+ while (i < length) {
246
+ if (i < l) {
247
+ this.__blender_file__.byte[(this.__data_address__ + offset + i)] = string.charCodeAt(i) | 0;
248
+ } else {
249
+ this.__blender_file__.byte[(this.__data_address__ + offset + i)] = 0;
250
+ }
251
+ i++;
252
+ }
253
+ } else {
254
+ this.__blender_file__.byte[(this.__data_address__ + offset)] = byte | 0;
255
+ }
256
+ },
257
+ };
258
+ }
259
+
260
+ function pointerProp2 (offset) {
261
+ return {
262
+ get: function () {
263
+ let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset, this.__blender_file__);
264
+ const link = this.__blender_file__.memory_lookup[pointer];
265
+
266
+ const results = [];
267
+
268
+ if (link) {
269
+ const address = link.__data_address__;
270
+ let j = 0;
271
+ while (true) {
272
+ pointer = this.__blender_file__.getPointer(address + j * 8, this.__blender_file__);
273
+ let obj = this.__blender_file__.memory_lookup[pointer];
274
+ if (!obj) break;
275
+ results.push(obj);
276
+ j++;
277
+ }
278
+
279
+ }
280
+
281
+ return results;
282
+ },
283
+ set: function () {},
284
+ };
285
+ }
286
+
287
+ function pointerProp (offset, Blender_Array_Length, length) {
288
+ return {
289
+ get: function () {
290
+ if (Blender_Array_Length > 1) {
291
+ let array = [];
292
+ let j = 0;
293
+ let off = offset;
294
+ while (j < Blender_Array_Length) {
295
+ let pointer = this.__blender_file__.getPointer(this.__data_address__ + off, this.__blender_file__);
296
+
297
+ array.push(this.__blender_file__.memory_lookup[pointer]);
298
+ off += length;
299
+ j++;
300
+ }
301
+
302
+ return array;
303
+ } else {
304
+ let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset, this.__blender_file__);
305
+ return this.__blender_file__.memory_lookup[pointer];
306
+ }
307
+ },
308
+ set: function () {},
309
+ };
310
+ }
311
+
312
+ function compileProp (obj, name, type, offset, array_size, IS_POINTER, pointer_size, length) {
313
+
314
+ if (!IS_POINTER) {
315
+ switch (type) {
316
+ case 'double':
317
+ Object.defineProperty(obj, name, float64Prop(offset, array_size, length >> 3));
318
+ break;
319
+ case 'float':
320
+ Object.defineProperty(obj, name, floatProp(offset, array_size, length >> 2));
321
+ break;
322
+ case 'int':
323
+ Object.defineProperty(obj, name, intProp(offset, array_size, length >> 2));
324
+ break;
325
+ case 'short':
326
+ case 'ushort':
327
+ Object.defineProperty(obj, name, shortProp(offset, array_size, length >> 1));
328
+ break;
329
+ case 'char':
330
+ case 'uchar':
331
+ Object.defineProperty(obj, name, charProp(offset, array_size, length));
332
+ break;
333
+ default:
334
+ // compile list to
335
+ obj[name] = {};
336
+ obj.__list__.push(name, type, length, offset, array_size, IS_POINTER);
337
+ }
338
+ obj._length += length;
339
+ offset += length;
340
+ } else {
341
+ Object.defineProperty(obj, name, pointerProp(offset, array_size, pointer_size));
342
+ offset += pointer_size * array_size;
343
+ }
344
+
345
+ return offset;
346
+ }
347
+
348
+ // Store final DNA structs
349
+ const MASTER_SDNA_SCHEMA = function (version) {
350
+ this.version = version;
351
+ this.SDNA_SET = false;
352
+ this.byte_size = 0;
353
+ this.struct_index = 0;
354
+ this.structs = {};
355
+ this.SDNA = {};
356
+ this.endianess = false;
357
+ };
358
+
359
+ MASTER_SDNA_SCHEMA.prototype = {
360
+ getSDNAStructureConstructor: function (name, struct) {
361
+ if (struct) {
362
+ const blen_struct = Function('function ' + name + '(){}; return ' + name)();
363
+
364
+ blen_struct.prototype = new BLENDER_STRUCTURE();
365
+ blen_struct.prototype.blender_name = name;
366
+ blen_struct.prototype.__pointers = [];
367
+ blen_struct.prototype.__list__ = [];
368
+
369
+ let offset = 0;
370
+ // Create properties of struct
371
+ for (let i = 0; i < struct.length; i += 3) {
372
+ let _name = struct[i];
373
+ const n = _name,
374
+ type = struct[i + 1];
375
+ let length = struct[i + 2],
376
+ array_length = 0,
377
+ match = null,
378
+ Blender_Array_Length = 1,
379
+ Suparray_match = 1,
380
+ PointerToArray = false,
381
+ Pointer_Match = 0;
382
+ const DNA = this.SDNA[name] = {
383
+ constructor: blen_struct,
384
+ };
385
+
386
+
387
+ let original_name = _name;
388
+
389
+ // mini type parser
390
+ if ((match = _name.match(/(\*?)(\*?)(\w+)(\[(\w*)\])?(\[(\w*)\])?/))) {
391
+
392
+ // base name
393
+ _name = match[3];
394
+
395
+ // pointer type
396
+ if (match[1]) {
397
+ Pointer_Match = 10;
398
+ blen_struct.prototype.__pointers.push(_name);
399
+ }
400
+
401
+ if (match[2]) {
402
+ PointerToArray = true;
403
+ }
404
+
405
+ // arrays
406
+ if (match[4]) {
407
+ if (match[6]) {
408
+ Suparray_match = parseInt(match[5]);
409
+ Blender_Array_Length = parseInt(match[7]);
410
+ } else {
411
+ Blender_Array_Length = parseInt(match[5]);
412
+ }
413
+ }
414
+ array_length = Blender_Array_Length * length;
415
+ length = array_length * Suparray_match;
416
+ }
417
+
418
+ DNA[n] = {
419
+ type: type,
420
+ length: length,
421
+ isArray: (Blender_Array_Length > 0),
422
+ };
423
+
424
+ if (PointerToArray) {
425
+ Object.defineProperty(blen_struct.prototype, _name, pointerProp2(offset));
426
+ offset += pointer_size;
427
+ } else if (Suparray_match > 1) {
428
+ const array_names = new Array(Suparray_match);
429
+
430
+ // construct sub_array object that will return the correct structs
431
+ for (let j = 0; j < Suparray_match; j++) {
432
+ let array_name_ = `__${_name}[${j}]__`;
433
+ array_names[j] = array_name_;
434
+
435
+ offset = compileProp(blen_struct.prototype, array_name_, type, offset, Blender_Array_Length, Pointer_Match, pointer_size, array_length);
436
+ }
437
+
438
+ Object.defineProperty(blen_struct.prototype, _name, {
439
+ get: (function (array_names) {
440
+ return function () {
441
+ const array = [];
442
+ for (let i = 0; i < array_names.length; i++) {
443
+ array.push(this[array_names[i]]);
444
+ }
445
+ return array;
446
+ };
447
+ })(array_names),
448
+ });
449
+ } else {
450
+ offset = compileProp(blen_struct.prototype, _name, type, offset, Blender_Array_Length, Pointer_Match, pointer_size, length);
451
+ }
452
+ }
453
+
454
+ return this.SDNA[name].constructor;
455
+
456
+ } else {
457
+ if (!this.SDNA[name]) {
458
+ return null;
459
+ }
460
+ return this.SDNA[name].constructor;
461
+ }
462
+ },
463
+ };
464
+
465
+ var BLENDER_STRUCTURE = function () {
466
+ this.__blender_file__ = null;
467
+ this.__list__ = null;
468
+ this.__super_array_list__ = null;
469
+ this.blender_name = '';
470
+ this.__pointers = null;
471
+ this.address = null;
472
+ this.length = 0;
473
+ this.__data_address__ = 0;
474
+ this.blender_name = '';
475
+ this._length = 0;
476
+ };
477
+
478
+
479
+ /*
480
+ Returns a pre-constructed BLENDER_STRUCTURE or creates a new BLENDER_STRUCTURE to match the DNA struct type
481
+ */
482
+ const pointer_function = (pointer) => () => {
483
+ return FILE.memory_lookup[pointer];
484
+ };
485
+
486
+ function getPointer (offset) {
487
+ const pointerLow = data.getUint32(offset, BIG_ENDIAN);
488
+ if (pointer_size > 4) {
489
+ const pointerHigh = data.getUint32(offset + 4, BIG_ENDIAN);
490
+
491
+ if (BIG_ENDIAN) {
492
+ return (pointerLow) + '' + pointerHigh;
493
+ } else {
494
+ return (pointerHigh) + '' + pointerLow;
495
+ }
496
+ } else {
497
+ return pointerLow;
498
+ }
499
+ }
500
+
501
+ BLENDER_STRUCTURE.prototype = {
502
+ setData: function (pointer, _data_offset, data_block_length, BLENDER_FILE) {
503
+ if (this.__list__ === null) return this;
504
+ BLENDER_FILE.addObject(this);
505
+
506
+ this.__blender_file__ = BLENDER_FILE;
507
+
508
+ const struct = this.__list__;
509
+ let j = 0,
510
+ i = 0,
511
+ obj, name = '',
512
+ type, length, Blender_Array_Length, Pointer_Match, offset, constructor;
513
+
514
+ this.__data_address__ = _data_offset;
515
+
516
+ if (struct === null) return this;
517
+
518
+ for (i = 0; i < struct.length; i += 6) {
519
+ obj = null;
520
+ name = struct[i];
521
+ type = struct[i + 1];
522
+ Blender_Array_Length = struct[i + 4];
523
+ Pointer_Match = struct[i + 5];
524
+ offset = this.__data_address__ + struct[i + 3];
525
+
526
+ if (Blender_Array_Length > 1) {
527
+ this[name] = [];
528
+ j = 0;
529
+ while (j < Blender_Array_Length) {
530
+ if (current_SDNA_template.getSDNAStructureConstructor(type)) {
531
+ constructor = current_SDNA_template.getSDNAStructureConstructor(type);
532
+ this[name].push((new constructor()).setData(0, offset, offset + length / Blender_Array_Length, BLENDER_FILE));
533
+ } else this[name].push(null);
534
+ offset += length / Blender_Array_Length;
535
+ j++;
536
+ }
537
+ } else {
538
+ if (current_SDNA_template.getSDNAStructureConstructor(type)) {
539
+ constructor = current_SDNA_template.getSDNAStructureConstructor(type);
540
+ this[name] = (new constructor()).setData(0, offset, length + offset, BLENDER_FILE);
541
+ } else this[name] = null;
542
+ }
543
+ }
544
+ // break connection to configuration list
545
+ this.__list__ = null;
546
+ return this;
547
+ },
548
+
549
+ get aname () {
550
+ if (this.id) return this.id.name.slice(2);
551
+ else return undefined;
552
+ },
553
+ };
554
+
555
+ function toString (buffer, _in, _out) {
556
+ return String.fromCharCode.apply(String, new Uint8Array(buffer, _in, _out - _in));
557
+ }
558
+
559
+ // Begin parsing blender __blender_file__
560
+
561
+ function readFile () {
562
+ let count = 0;
563
+ let offset2 = 0;
564
+ const root = 0;
565
+ const i = 0;
566
+ let data_offset = 0;
567
+ let sdna_index = 0;
568
+ let code = '';
569
+ let block_length = 0;
570
+ let curr_count = 0;
571
+ let curr_count2 = 0;
572
+
573
+ FILE.memory_lookup = {};
574
+ struct_names = [];
575
+ offset = 0;
576
+
577
+ // Make sure we have a .blend __blender_file__. All blend files have the first 12bytes
578
+ // set with BLENDER-v### in Utf-8
579
+ if (toString(_data, offset, 7) !== 'BLENDER') return ERROR = 'File supplied is not a .blend compatible Blender file.';
580
+
581
+ // otherwise get templete from save version.
582
+
583
+ offset += 7;
584
+ pointer_size = ((toString(_data, offset++, offset)) == '_') ? 4 : 8;
585
+ BIG_ENDIAN = toString(_data, offset++, offset) !== 'V';
586
+ const version = toString(_data, offset, offset + 3);
587
+
588
+
589
+ // create new master template if none exist for current blender version;
590
+ if (!templates[version]) {
591
+ templates[version] = new MASTER_SDNA_SCHEMA(version);
592
+ }
593
+
594
+ current_SDNA_template = templates[version];
595
+
596
+ FILE.template = current_SDNA_template;
597
+
598
+ offset += 3;
599
+
600
+ // Set SDNA structs if template hasn't been set.
601
+ // Todo: Move the following block into the MASTER_SDNA_SCHEMA object.
602
+ //* Like so:*/ current_SDNA_template.set(AB);
603
+
604
+ if (!current_SDNA_template.SDNA_SET) {
605
+ current_SDNA_template.endianess = BIG_ENDIAN;
606
+ current_SDNA_template.pointer_size = pointer_size;
607
+ // find DNA1 data block
608
+ offset2 = offset;
609
+
610
+ while (true) {
611
+ sdna_index = data.getInt32(offset2 + pointer_size + 8, BIG_ENDIAN);
612
+ // eslint-disable-next-line no-control-regex
613
+ code = toString(_data, offset2, offset2 + 4).replace(/\u0000/g, '');
614
+ block_length = data.getInt32(offset2 + 4, true);
615
+ offset2 += 16 + (pointer_size);
616
+ if (code === 'DNA1') {
617
+ // DNA found; This is the core of the __blender_file__ and contains all the structure for the various data types used in Blender.
618
+ count = 0;
619
+ let types = [],
620
+ fields = [],
621
+ names = [],
622
+ lengths = [],
623
+ name = '',
624
+ curr_name = '';
625
+
626
+ // skip SDNA and NAME identifiers
627
+ offset2 += 8;
628
+
629
+ // Number of structs.
630
+ count = data.getInt32(offset2, true);
631
+ offset2 += 4;
632
+
633
+ curr_count = 0;
634
+
635
+ // Build up list of names for structs
636
+ while (curr_count < count) {
637
+ curr_name = '';
638
+ while (data.getInt8(offset2) !== 0) {
639
+ curr_name += toString(_data, offset2, offset2 + 1);
640
+ offset2++;
641
+ }
642
+ names.push(curr_name);
643
+ offset2++;
644
+ curr_count++;
645
+ }
646
+
647
+
648
+ // Adjust for 4byte alignment
649
+ if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
650
+ offset2 += 4;
651
+
652
+ // Number of struct types
653
+ count = data.getInt32(offset2, true);
654
+ offset2 += 4;
655
+ curr_count = 0;
656
+
657
+ // Build up list of types
658
+ while (curr_count < count) {
659
+ curr_name = '';
660
+ while (data.getInt8(offset2) !== 0) {
661
+ curr_name += toString(_data, offset2, offset2 + 1);
662
+ offset2++;
663
+ }
664
+ types.push(curr_name);
665
+ offset2++;
666
+ curr_count++;
667
+ }
668
+
669
+ // Adjust for 4byte alignment
670
+ if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
671
+ offset2 += 4;
672
+ curr_count = 0;
673
+
674
+ // Build up list of byte lengths for types
675
+ while (curr_count < count) {
676
+ lengths.push(data.getInt16(offset2, BIG_ENDIAN));
677
+ offset2 += 2;
678
+ curr_count++;
679
+ }
680
+
681
+ // Adjust for 4byte alignment
682
+ if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
683
+ offset2 += 4;
684
+
685
+ // Number of structures
686
+ const structure_count = data.getInt32(offset2, BIG_ENDIAN);
687
+ offset2 += 4;
688
+ curr_count = 0;
689
+
690
+ // Create constructor objects from list of SDNA structs
691
+ while (curr_count < structure_count) {
692
+ const struct_name = types[data.getInt16(offset2, BIG_ENDIAN)];
693
+ offset2 += 2;
694
+ const obj = [];
695
+ count = data.getInt16(offset2, BIG_ENDIAN);
696
+ offset2 += 2;
697
+ curr_count2 = 0;
698
+ struct_names.push(struct_name);
699
+
700
+ // Fill an array with name, type, and length for each SDNA struct property
701
+ while (curr_count2 < count) {
702
+ obj.push(names[data.getInt16(offset2 + 2, BIG_ENDIAN)], types[data.getInt16(offset2, BIG_ENDIAN)], lengths[data.getInt16(offset2, BIG_ENDIAN)]);
703
+ offset2 += 4;
704
+ curr_count2++;
705
+ }
706
+
707
+ // Create a SDNA constructor by passing [type,name,lenth] array as second argument
708
+ current_SDNA_template.getSDNAStructureConstructor(struct_name, obj);
709
+ curr_count++;
710
+ }
711
+ current_SDNA_template.SDNA_SET = true;
712
+ current_SDNA_template.SDNA_NAMES = struct_names;
713
+ break;
714
+ }
715
+ offset2 += block_length;
716
+ }
717
+ }
718
+
719
+ // parse the rest of the data, starting back at the top.
720
+
721
+ // TODO: turn into "on-demand" parsing.
722
+
723
+ while (true) {
724
+ if ((offset % 4) > 0) {
725
+ offset = (4 - (offset % 4)) + offset;
726
+ }
727
+
728
+ data_offset = offset;
729
+ sdna_index = data.getInt32(offset + pointer_size + 8, BIG_ENDIAN);
730
+ let code_uint = data.getUint32(offset, BIG_ENDIAN);
731
+ offset2 = offset + 16 + (pointer_size);
732
+ offset += data.getInt32(offset + 4, true) + 16 + (pointer_size);
733
+
734
+ if (code_uint === DNA1); // skip - already processed at this point
735
+ else if (code_uint === ENDB) break; // end of __blender_file__ found
736
+ else {
737
+ // Create a Blender object using a constructor template from current_SDNA_template
738
+ const data_start = data_offset + pointer_size + 16;
739
+
740
+ // Get a SDNA constructor by name;
741
+ const constructor = current_SDNA_template.getSDNAStructureConstructor(current_SDNA_template.SDNA_NAMES[sdna_index]);
742
+
743
+ const size = data.getInt32(data_offset + 4, BIG_ENDIAN);
744
+
745
+ count = data.getInt32(data_offset + 12 + pointer_size, BIG_ENDIAN);
746
+
747
+ if (count > 0) {
748
+ let obj = new constructor();
749
+
750
+ const length = constructor.prototype._length;
751
+
752
+
753
+ const address = FILE.getPointer(data_offset + 8);
754
+
755
+ obj.address = address + '';
756
+
757
+ obj.setData(address, data_start, data_start + size, FILE);
758
+
759
+ if (count > 1) {
760
+ let array = [];
761
+ array.push(obj);
762
+ for (let u = 1; u < count; u++) {
763
+ obj = new constructor();
764
+ obj.setData(address, data_start + length * u, data_start + (length * u) + length, FILE);
765
+ array.push(obj);
766
+ }
767
+ FILE.memory_lookup[address] = array;
768
+ } else {
769
+ FILE.memory_lookup[address] = obj;
770
+ }
771
+ }
772
+ }
773
+ }
774
+ }
775
+ }
776
+
777
+ worker = new worker_code();
778
+
779
+ worker.postMessage = function (message) {
780
+ return_object.onParseReady(message);
781
+ };
782
+
783
+ export default return_object;