threepipe
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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