@threepipe/plugin-blend-importer 0.0.2 → 0.0.5
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.
- package/dist/BlendLoadPlugin.d.ts +11 -11
- package/dist/BlendLoadPlugin.d.ts.map +1 -1
- package/dist/index.js +1009 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +997 -5
- package/dist/index.mjs.map +1 -1
- package/dist/js-blend/main.d.ts +1 -0
- package/dist/loader/bakeGetters.d.ts +2 -0
- package/dist/loader/bakeGetters.d.ts.map +1 -0
- package/dist/loader/camera.d.ts +3 -0
- package/dist/loader/camera.d.ts.map +1 -0
- package/dist/loader/geometry.d.ts +2 -2
- package/dist/loader/geometry.d.ts.map +1 -1
- package/dist/loader/index.d.ts +2 -2
- package/dist/loader/index.d.ts.map +1 -1
- package/dist/loader/light.d.ts +2 -2
- package/dist/loader/light.d.ts.map +1 -1
- package/dist/loader/material.d.ts +1 -2
- package/dist/loader/material.d.ts.map +1 -1
- package/dist/loader/mesh.d.ts +3 -2
- package/dist/loader/mesh.d.ts.map +1 -1
- package/package.json +19 -11
- package/src/BlendLoadPlugin.ts +37 -3
- package/src/js-blend/main.js +3 -2
- package/src/js-blend/parser/parser.js +152 -24
- package/src/js-blend/threejs/blend_three.js +1 -1
- package/src/js-blend/threejs/light.js +1 -1
- package/src/js-blend/threejs/material.js +1 -1
- package/src/loader/bakeGetters.ts +63 -0
- package/src/loader/camera.ts +46 -0
- package/src/loader/geometry.ts +234 -13
- package/src/loader/index.ts +59 -7
- package/src/loader/light.ts +17 -13
- package/src/loader/material.ts +5 -5
- package/src/loader/mesh.ts +26 -13
package/dist/index.js
CHANGED
|
@@ -1,18 +1,1013 @@
|
|
|
1
|
-
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("threepipe")) : typeof define === "function" && define.amd ? define(["exports", "threepipe"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["@threepipe/plugin-blend-importer"] = {}, global.threepipe));
|
|
3
|
+
})(this, function(exports2, threepipe) {
|
|
4
|
+
"use strict";/**
|
|
2
5
|
* @license
|
|
3
|
-
* @threepipe/plugin-blend-importer v0.0.
|
|
4
|
-
* Copyright 2022-
|
|
6
|
+
* @threepipe/plugin-blend-importer v0.0.5
|
|
7
|
+
* Copyright 2022-2025 repalash <palash@shaders.app>
|
|
5
8
|
* Apache-2.0 License
|
|
6
|
-
* See ./dependencies.txt for bundled third-party dependencies and licenses.
|
|
9
|
+
* See ./dependencies.txt for any bundled third-party dependencies and licenses.
|
|
7
10
|
*/
|
|
8
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("threepipe")):"function"==typeof define&&define.amd?define(["exports","threepipe"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["@threepipe/plugin-blend-importer"]={},e.threepipe)}(this,(function(e,t){"use strict";const n=826363460,r=1111772741;let s=null;const _={loadBlendFromArrayBuffer:function(e){_.ready=!1,s.onmessage({data:e})},ready:!0,onParseReady:function(){}};s=new function(){let e=null,t=null,s=!1,_=0,i=[],o=0,a=null,l={},d=null,u=null,c=null;const h=this;var f=function(e){this.AB=e,this.byte=new Uint8Array(e),this.dv=new DataView(e),this.objects={},this.memory_lookup={},this.object_array=[],this.template=null};function p(e){return{get:function(){let t=this.__blender_file__.getPointer(this.__data_address__+e,this.__blender_file__);const n=this.__blender_file__.memory_lookup[t],r=[];if(n){const e=n.__data_address__;let s=0;for(;;){t=this.__blender_file__.getPointer(e+8*s,this.__blender_file__);let n=this.__blender_file__.memory_lookup[t];if(!n)break;r.push(n),s++}}return r},set:function(){}}}function b(e,t,n,r,s,_,i,o){if(_)Object.defineProperty(e,t,function(e,t,n){return{get:function(){if(t>1){let r=[],s=0,_=e;for(;s<t;){let e=this.__blender_file__.getPointer(this.__data_address__+_,this.__blender_file__);r.push(this.__blender_file__.memory_lookup[e]),_+=n,s++}return r}{let t=this.__blender_file__.getPointer(this.__data_address__+e,this.__blender_file__);return this.__blender_file__.memory_lookup[t]}},set:function(){}}}(r,s,i)),r+=i*s;else{switch(n){case"double":Object.defineProperty(e,t,function(e,t,n){return{get:function(){return t>1?new Float64Array(this.__blender_file__.AB,this.__data_address__+e,n):this.__blender_file__.dv.getFloat64(this.__data_address__+e,this.__blender_file__.template.endianess)},set:function(n){t>1||this.__blender_file__.dv.setFloat64(this.__data_address__+e,n,this.__blender_file__.template.endianess)}}}(r,s,o>>3));break;case"float":Object.defineProperty(e,t,function(e,t,n){return{get:function(){return t>1?new Float32Array(this.__blender_file__.AB,this.__data_address__+e,n):this.__blender_file__.dv.getFloat32(this.__data_address__+e,this.__blender_file__.template.endianess)},set:function(n){t>1||this.__blender_file__.dv.setFloat32(this.__data_address__+e,n,this.__blender_file__.template.endianess)}}}(r,s,o>>2));break;case"int":Object.defineProperty(e,t,function(e,t,n){return{get:function(){return t>1?new Int32Array(this.__blender_file__.AB,this.__data_address__+e,n):this.__blender_file__.dv.getInt32(this.__data_address__+e,this.__blender_file__.template.endianess)},set:function(n){t>1||this.__blender_file__.dv.setInt32(this.__data_address__+e,n,this.__blender_file__.template.endianess)}}}(r,s,o>>2));break;case"short":case"ushort":Object.defineProperty(e,t,function(e,t,n){return{get:function(){return t>1?new Int16Array(this.__blender_file__.AB,this.__data_address__+e,n):this.__blender_file__.dv.getInt16(this.__data_address__+e,this.__blender_file__.template.endianess)},set:function(n){t>1||this.__blender_file__.dv.setInt16(this.__data_address__+e,n,this.__blender_file__.template.endianess)}}}(r,s,o>>1));break;case"char":case"uchar":Object.defineProperty(e,t,function(e,t,n){return{get:function(){if(t>1){let t=this.__data_address__+e,r=t,s=0;for(;0!=this.__blender_file__.byte[r]&&s++<n;)r++;return m(this.__blender_file__.AB,t,r)}return this.__blender_file__.byte[this.__data_address__+e]},set:function(r){if(t>1){const t=r+"";let s=0;const _=t.length;for(;s<n;)this.__blender_file__.byte[this.__data_address__+e+s]=s<_?0|t.charCodeAt(s):0,s++}else this.__blender_file__.byte[this.__data_address__+e]=0|r}}}(r,s,o));break;default:e[t]={},e.__list__.push(t,n,o,r,s,_)}e._length+=o,r+=o}return r}f.prototype={addObject:function(e){this.object_array.push(e),this.objects[e.blender_name]||(this.objects[e.blender_name]=[]),this.objects[e.blender_name].push(e)},getPointer:function(e){const t=this.dv.getUint32(e,this.template.endianess);if(this.template.pointer_size>4){const n=this.dv.getUint32(e+4,this.template.endianess);return this.template.endianess?t+"l|h"+n:n+"h|l"+t}return t}},h.onmessage=function(p){"object"==typeof p.data&&(c=null,e=null,s=!1,_=0,i=[],o=0,a=null,t=p.data,c=t.slice(),e=new DataView(t),d=new f(c),function(){let c=0,h=0,f=0,p=0,b="",g=0,A=0,w=0;if(d.memory_lookup={},i=[],o=0,"BLENDER"!==m(t,o,7))return u="File supplied is not a .blend compatible Blender file.";o+=7,_="_"==m(t,o++,o)?4:8,s="V"!==m(t,o++,o);const S=m(t,o,o+3);l[S]||(l[S]=new y(S));if(a=l[S],d.template=a,o+=3,!a.SDNA_SET)for(a.endianess=s,a.pointer_size=_,h=o;;){if(p=e.getInt32(h+_+8,s),b=m(t,h,h+4).replace(/\u0000/g,""),g=e.getInt32(h+4,!0),h+=16+_,"DNA1"===b){c=0;let n=[],r=[],_=[],o="";for(h+=8,c=e.getInt32(h,!0),h+=4,A=0;A<c;){for(o="";0!==e.getInt8(h);)o+=m(t,h,h+1),h++;r.push(o),h++,A++}for(h%4>0&&(h=4-h%4+h),h+=4,c=e.getInt32(h,!0),h+=4,A=0;A<c;){for(o="";0!==e.getInt8(h);)o+=m(t,h,h+1),h++;n.push(o),h++,A++}for(h%4>0&&(h=4-h%4+h),h+=4,A=0;A<c;)_.push(e.getInt16(h,s)),h+=2,A++;h%4>0&&(h=4-h%4+h),h+=4;const l=e.getInt32(h,s);for(h+=4,A=0;A<l;){const t=n[e.getInt16(h,s)];h+=2;const o=[];for(c=e.getInt16(h,s),h+=2,w=0,i.push(t);w<c;)o.push(r[e.getInt16(h+2,s)],n[e.getInt16(h,s)],_[e.getInt16(h,s)]),h+=4,w++;a.getSDNAStructureConstructor(t,o),A++}a.SDNA_SET=!0,a.SDNA_NAMES=i;break}h+=g}for(;;){o%4>0&&(o=4-o%4+o),f=o,p=e.getInt32(o+_+8,s);let t=e.getUint32(o,s);if(h=o+16+_,o+=e.getInt32(o+4,!0)+16+_,t===n);else{if(t===r)break;{const t=f+_+16,n=a.getSDNAStructureConstructor(a.SDNA_NAMES[p]),r=e.getInt32(f+4,s);if(c=e.getInt32(f+12+_,s),c>0){let e=new n;const s=n.prototype._length,_=d.getPointer(f+8);if(e.address=_+"",e.setData(_,t,t+r,d),c>1){let r=[];r.push(e);for(let i=1;i<c;i++)e=new n,e.setData(_,t+s*i,t+s*i+s,d),r.push(e);d.memory_lookup[_]=r}else d.memory_lookup[_]=e}}}}}(),h.postMessage(d,u))};const y=function(e){this.version=e,this.SDNA_SET=!1,this.byte_size=0,this.struct_index=0,this.structs={},this.SDNA={},this.endianess=!1};y.prototype={getSDNAStructureConstructor:function(e,t){if(t){const n=Function("function "+e+"(){}; return "+e)();n.prototype=new g,n.prototype.blender_name=e,n.prototype.__pointers=[],n.prototype.__list__=[];let r=0;for(let s=0;s<t.length;s+=3){let i=t[s];const o=i,a=t[s+1];let l=t[s+2],d=0,u=null,c=1,h=1,f=!1,y=0;const g=this.SDNA[e]={constructor:n};if((u=i.match(/(\*?)(\*?)(\w+)(\[(\w*)\])?(\[(\w*)\])?/))&&(i=u[3],u[1]&&(y=10,n.prototype.__pointers.push(i)),u[2]&&(f=!0),u[4]&&(u[6]?(h=parseInt(u[5]),c=parseInt(u[7])):c=parseInt(u[5])),d=c*l,l=d*h),g[o]={type:a,length:l,isArray:c>0},f)Object.defineProperty(n.prototype,i,p(r)),r+=_;else if(h>1){const e=new Array(h);for(let t=0;t<h;t++){let s=`__${i}[${t}]__`;e[t]=s,r=b(n.prototype,s,a,r,c,y,_,d)}Object.defineProperty(n.prototype,i,{get:function(e){return function(){const t=[];for(let n=0;n<e.length;n++)t.push(this[e[n]]);return t}}(e)})}else r=b(n.prototype,i,a,r,c,y,_,l)}return this.SDNA[e].constructor}return this.SDNA[e]?this.SDNA[e].constructor:null}};var g=function(){this.__blender_file__=null,this.__list__=null,this.__super_array_list__=null,this.blender_name="",this.__pointers=null,this.address=null,this.length=0,this.__data_address__=0,this.blender_name="",this._length=0};function m(e,t,n){return String.fromCharCode.apply(String,new Uint8Array(e,t,n-t))}g.prototype={setData:function(e,t,n,r){if(null===this.__list__)return this;r.addObject(this),this.__blender_file__=r;const s=this.__list__;let _,i,o,l,d,u=0,c=0,h="";if(this.__data_address__=t,null===s)return this;for(c=0;c<s.length;c+=6)if(h=s[c],_=s[c+1],o=s[c+4],s[c+5],l=this.__data_address__+s[c+3],o>1)for(this[h]=[],u=0;u<o;)a.getSDNAStructureConstructor(_)?(d=a.getSDNAStructureConstructor(_),this[h].push((new d).setData(0,l,l+i/o,r))):this[h].push(null),l+=i/o,u++;else a.getSDNAStructureConstructor(_)?(d=a.getSDNAStructureConstructor(_),this[h]=(new d).setData(0,l,i+l,r)):this[h]=null;return this.__list__=null,this},get aname(){return this.id?this.id.name.slice(2):void 0}}},s.postMessage=function(e){_.onParseReady(e)};const i={point:0,sun:1,spot:0,hemi:0,area:0};function o(e){const n=e.data,r=[e.loc[0],e.loc[2],-e.loc[1]],s=255*n.r<<16|255*n.g<<8|255*n.b<<0,_=n.energy;let o=null;switch(n.type){case i.point:o=new t.PointLight(s,_,0),o.position.fromArray(r,0),o.castShadow=!0;break;case i.sun:o=new t.PointLight(s,_,0),o.position.fromArray(r,0),o.castShadow=!0,o.shadow.mapSize.width=1024,o.shadow.mapSize.height=1024,o.shadow.camera.near=.01,o.shadow.camera.far=500;break;default:console.warn("Unsupported light type",n.type)}return o}function a(e){if(!e.data)return null;const n=function(e,n){const r=Array.isArray(e.mpoly)?e.mpoly:[e.mpoly],s=e.mloop,_=e.mloopuv,i=e.mvert,o=new t.BufferGeometry;if(!r)return o;const a=r.reduce(((e,t)=>e+Math.floor(3*t.totloop/2)),0),l=new Uint32Array(a),d=new Float32Array(2*a),u=new Float32Array(3*a),c=new Float32Array(3*a);let h=0;for(const e of r){const t=e.totloop,r=e.loopstart;let o=1;for(;o<t;){let e=0;for(let a=0;a<3;a++){e=r,o-1+a<t&&(e+=o-1+a);const f=i[s[e].v];l[h]=h,c[3*h+0]=f.co[0]+n[0],c[3*h+1]=f.co[2]+n[2],c[3*h+2]=-f.co[1]-n[1],u[3*h+0]=f.no[0],u[3*h+1]=f.no[2],u[3*h+2]=-f.no[1],_&&(d[2*h+0]=_[e].uv[0],d[2*h+1]=_[e].uv[1]),h++}o+=2}}return o.setAttribute("position",new t.BufferAttribute(c,3)),o.setIndex(new t.BufferAttribute(l,1)),o.setAttribute("normal",new t.BufferAttribute(u,3)),o.setAttribute("uv",new t.BufferAttribute(d,2)),o}(e.data,[0,0,0]),r=e.data.mat[0],s=r?function(e){const n=new t.MeshPhysicalMaterial;return n.color.setRGB(e.r,e.g,e.b),n.roughness=void 0!==e.roughness?e.roughness:.4,n.metalness=void 0!==e.metallic?e.metallic:0,n.opacity=void 0!==e.alpha?e.alpha:0,n.transparent=n.opacity<1,n}(r):void 0,_=new t.Mesh(n,s);return _.castShadow=!0,_.receiveShadow=!0,_.rotateZ(e.rot[2]),_.rotateY(e.rot[1]),_.rotateX(e.rot[0]),_.scale.fromArray(e.size,0),_.position.fromArray([e.loc[0],e.loc[2],-e.loc[1]],0),_}const l=1,d=10;class u extends t.BaseImporterPlugin{constructor(){super(),this._importer=new t.Importer(class extends t.FileLoader{async loadAsync(e,n){this.setResponseType("arraybuffer");const r=await super.loadAsync(e,n),s=
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
|
|
12
|
+
let worker = null;
|
|
13
|
+
const return_object = {
|
|
14
|
+
loadBlendFromArrayBuffer: function(array_buffer) {
|
|
15
|
+
return_object.ready = false;
|
|
16
|
+
{
|
|
17
|
+
worker.onmessage({
|
|
18
|
+
data: array_buffer
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
// loadBlendFromBlob: function (blob) {
|
|
23
|
+
// FR.onload = function () {
|
|
24
|
+
// return_object.loadBlendFromArrayBuffer(this.result);
|
|
25
|
+
// };
|
|
26
|
+
// FR.readAsArrayBuffer(blob);
|
|
27
|
+
// },
|
|
28
|
+
ready: true,
|
|
29
|
+
onParseReady: function() {
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function worker_code() {
|
|
33
|
+
let data = null, _data = null, BIG_ENDIAN = false, pointer_size = 0, struct_names = [], offset = 0, current_SDNA_template = null, templates = {}, FILE = null, ERROR = null, AB = null;
|
|
34
|
+
const self2 = this;
|
|
35
|
+
function parseFile(msg) {
|
|
36
|
+
if (typeof msg.data == "object") {
|
|
37
|
+
AB = null;
|
|
38
|
+
data = null;
|
|
39
|
+
BIG_ENDIAN = false;
|
|
40
|
+
pointer_size = 0;
|
|
41
|
+
struct_names = [];
|
|
42
|
+
offset = 0;
|
|
43
|
+
current_SDNA_template = null;
|
|
44
|
+
_data = msg.data;
|
|
45
|
+
AB = _data.slice();
|
|
46
|
+
data = new DataView(_data);
|
|
47
|
+
FILE = new BLENDER_FILE(AB);
|
|
48
|
+
readFile();
|
|
49
|
+
self2.postMessage(FILE, ERROR);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const BLENDER_FILE = function(AB2) {
|
|
53
|
+
this.AB = AB2;
|
|
54
|
+
this.byte = new Uint8Array(AB2);
|
|
55
|
+
this.dv = new DataView(AB2);
|
|
56
|
+
this.objects = {};
|
|
57
|
+
this.memory_lookup = {}, this.object_array = [];
|
|
58
|
+
this.template = null;
|
|
59
|
+
};
|
|
60
|
+
BLENDER_FILE.prototype = {
|
|
61
|
+
addObject: function(obj) {
|
|
62
|
+
this.object_array.push(obj);
|
|
63
|
+
if (!this.objects[obj.blender_name]) this.objects[obj.blender_name] = [];
|
|
64
|
+
this.objects[obj.blender_name].push(obj);
|
|
65
|
+
},
|
|
66
|
+
getPointer: function(offset2) {
|
|
67
|
+
const pointerLow = this.dv.getUint32(offset2, this.template.endianess);
|
|
68
|
+
if (this.template.pointer_size > 4) {
|
|
69
|
+
const pointerHigh = this.dv.getUint32(offset2 + 4, this.template.endianess);
|
|
70
|
+
if (this.template.endianess) {
|
|
71
|
+
return pointerLow + "l|h" + pointerHigh;
|
|
72
|
+
} else {
|
|
73
|
+
return pointerHigh + "h|l" + pointerLow;
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
return pointerLow;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
self2.onmessage = parseFile;
|
|
81
|
+
function float64Prop(offset2, Blender_Array_Length, length) {
|
|
82
|
+
return {
|
|
83
|
+
get: function() {
|
|
84
|
+
return Blender_Array_Length > 1 ? new Float64Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getFloat64(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
85
|
+
},
|
|
86
|
+
set: function(float) {
|
|
87
|
+
if (Blender_Array_Length > 1) ;
|
|
88
|
+
else {
|
|
89
|
+
this.__blender_file__.dv.setFloat64(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
enumerable: true,
|
|
93
|
+
configurable: true
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function floatProp(offset2, Blender_Array_Length, length) {
|
|
97
|
+
return {
|
|
98
|
+
get: function() {
|
|
99
|
+
return Blender_Array_Length > 1 ? new Float32Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getFloat32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
100
|
+
},
|
|
101
|
+
set: function(float) {
|
|
102
|
+
if (Blender_Array_Length > 1) ;
|
|
103
|
+
else {
|
|
104
|
+
this.__blender_file__.dv.setFloat32(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
enumerable: true,
|
|
108
|
+
configurable: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function intProp(offset2, Blender_Array_Length, length) {
|
|
112
|
+
return {
|
|
113
|
+
get: function() {
|
|
114
|
+
return Blender_Array_Length > 1 ? new Int32Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt32(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
115
|
+
},
|
|
116
|
+
set: function(float) {
|
|
117
|
+
if (Blender_Array_Length > 1) ;
|
|
118
|
+
else {
|
|
119
|
+
this.__blender_file__.dv.setInt32(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
enumerable: true,
|
|
123
|
+
configurable: true
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function shortProp(offset2, Blender_Array_Length, length) {
|
|
127
|
+
return {
|
|
128
|
+
get: function() {
|
|
129
|
+
return Blender_Array_Length > 1 ? new Int16Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getInt16(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
130
|
+
},
|
|
131
|
+
set: function(float) {
|
|
132
|
+
if (Blender_Array_Length > 1) ;
|
|
133
|
+
else {
|
|
134
|
+
this.__blender_file__.dv.setInt16(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
enumerable: true,
|
|
138
|
+
configurable: true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const uShortProp = (offset2, Blender_Array_Length, length) => {
|
|
142
|
+
return {
|
|
143
|
+
get: function() {
|
|
144
|
+
return Blender_Array_Length > 1 ? new Uint16Array(this.__blender_file__.AB, this.__data_address__ + offset2, length) : this.__blender_file__.dv.getUint16(this.__data_address__ + offset2, this.__blender_file__.template.endianess);
|
|
145
|
+
},
|
|
146
|
+
set: function(float) {
|
|
147
|
+
if (Blender_Array_Length > 1) ;
|
|
148
|
+
else {
|
|
149
|
+
this.__blender_file__.dv.setUint16(this.__data_address__ + offset2, float, this.__blender_file__.template.endianess);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
enumerable: true,
|
|
153
|
+
configurable: true
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
function charProp(offset2, Blender_Array_Length, length) {
|
|
157
|
+
return {
|
|
158
|
+
get: function() {
|
|
159
|
+
if (Blender_Array_Length > 1) {
|
|
160
|
+
let start = this.__data_address__ + offset2;
|
|
161
|
+
let end = start;
|
|
162
|
+
let buffer_guard = 0;
|
|
163
|
+
while (this.__blender_file__.byte[end] != 0 && buffer_guard++ < length) end++;
|
|
164
|
+
return toString(this.__blender_file__.AB, start, end);
|
|
165
|
+
}
|
|
166
|
+
return this.__blender_file__.byte[this.__data_address__ + offset2];
|
|
167
|
+
},
|
|
168
|
+
set: function(byte) {
|
|
169
|
+
if (Blender_Array_Length > 1) {
|
|
170
|
+
const string = byte + "";
|
|
171
|
+
let i = 0;
|
|
172
|
+
const l = string.length;
|
|
173
|
+
while (i < length) {
|
|
174
|
+
if (i < l) {
|
|
175
|
+
this.__blender_file__.byte[this.__data_address__ + offset2 + i] = string.charCodeAt(i) | 0;
|
|
176
|
+
} else {
|
|
177
|
+
this.__blender_file__.byte[this.__data_address__ + offset2 + i] = 0;
|
|
178
|
+
}
|
|
179
|
+
i++;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
this.__blender_file__.byte[this.__data_address__ + offset2] = byte | 0;
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
enumerable: true,
|
|
186
|
+
configurable: true
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function pointerProp2(offset2) {
|
|
190
|
+
return {
|
|
191
|
+
get: function() {
|
|
192
|
+
let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset2, this.__blender_file__);
|
|
193
|
+
const link = this.__blender_file__.memory_lookup[pointer];
|
|
194
|
+
const results = [];
|
|
195
|
+
if (link) {
|
|
196
|
+
const address = link.__data_address__;
|
|
197
|
+
let j = 0;
|
|
198
|
+
while (true) {
|
|
199
|
+
pointer = this.__blender_file__.getPointer(address + j * 8, this.__blender_file__);
|
|
200
|
+
let obj = this.__blender_file__.memory_lookup[pointer];
|
|
201
|
+
if (!obj) break;
|
|
202
|
+
results.push(obj);
|
|
203
|
+
j++;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return results;
|
|
207
|
+
},
|
|
208
|
+
set: function() {
|
|
209
|
+
},
|
|
210
|
+
enumerable: true,
|
|
211
|
+
configurable: true
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function pointerProp(offset2, Blender_Array_Length, length) {
|
|
215
|
+
return {
|
|
216
|
+
get: function() {
|
|
217
|
+
if (Blender_Array_Length > 1) {
|
|
218
|
+
let array = [];
|
|
219
|
+
let j = 0;
|
|
220
|
+
let off = offset2;
|
|
221
|
+
while (j < Blender_Array_Length) {
|
|
222
|
+
let pointer = this.__blender_file__.getPointer(this.__data_address__ + off, this.__blender_file__);
|
|
223
|
+
array.push(this.__blender_file__.memory_lookup[pointer]);
|
|
224
|
+
off += length;
|
|
225
|
+
j++;
|
|
226
|
+
}
|
|
227
|
+
return array;
|
|
228
|
+
} else {
|
|
229
|
+
let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset2, this.__blender_file__);
|
|
230
|
+
return this.__blender_file__.memory_lookup[pointer];
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
set: function() {
|
|
234
|
+
},
|
|
235
|
+
enumerable: true,
|
|
236
|
+
configurable: true
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
function compileProp(obj, name, type, offset2, array_size, IS_POINTER, pointer_size2, length) {
|
|
240
|
+
if (!IS_POINTER) {
|
|
241
|
+
switch (type) {
|
|
242
|
+
case "double":
|
|
243
|
+
Object.defineProperty(obj, name, float64Prop(offset2, array_size, length >> 3));
|
|
244
|
+
break;
|
|
245
|
+
case "float":
|
|
246
|
+
Object.defineProperty(obj, name, floatProp(offset2, array_size, length >> 2));
|
|
247
|
+
break;
|
|
248
|
+
case "int":
|
|
249
|
+
Object.defineProperty(obj, name, intProp(offset2, array_size, length >> 2));
|
|
250
|
+
break;
|
|
251
|
+
case "short":
|
|
252
|
+
Object.defineProperty(obj, name, shortProp(offset2, array_size, length >> 1));
|
|
253
|
+
break;
|
|
254
|
+
case "ushort":
|
|
255
|
+
Object.defineProperty(obj, name, uShortProp(offset2, array_size, length >> 1));
|
|
256
|
+
break;
|
|
257
|
+
case "char":
|
|
258
|
+
case "uchar":
|
|
259
|
+
Object.defineProperty(obj, name, charProp(offset2, array_size, length));
|
|
260
|
+
break;
|
|
261
|
+
default:
|
|
262
|
+
obj[name] = {};
|
|
263
|
+
obj.__list__.push(name, type, length, offset2, array_size, IS_POINTER);
|
|
264
|
+
}
|
|
265
|
+
obj._length += length;
|
|
266
|
+
offset2 += length;
|
|
267
|
+
} else {
|
|
268
|
+
Object.defineProperty(obj, name, pointerProp(offset2, array_size, pointer_size2));
|
|
269
|
+
obj._length += pointer_size2 * array_size;
|
|
270
|
+
offset2 += pointer_size2 * array_size;
|
|
271
|
+
}
|
|
272
|
+
return offset2;
|
|
273
|
+
}
|
|
274
|
+
const MASTER_SDNA_SCHEMA = function(version) {
|
|
275
|
+
this.version = version;
|
|
276
|
+
this.SDNA_SET = false;
|
|
277
|
+
this.byte_size = 0;
|
|
278
|
+
this.struct_index = 0;
|
|
279
|
+
this.structs = {};
|
|
280
|
+
this.SDNA = {};
|
|
281
|
+
this.endianess = false;
|
|
282
|
+
};
|
|
283
|
+
MASTER_SDNA_SCHEMA.prototype = {
|
|
284
|
+
getSDNAStructureConstructor: function(name, struct) {
|
|
285
|
+
if (struct) {
|
|
286
|
+
const jsName = name === "void" ? "void_" : name;
|
|
287
|
+
const blen_struct = Function("function " + jsName + "(){}; return " + jsName)();
|
|
288
|
+
blen_struct.prototype = new BLENDER_STRUCTURE();
|
|
289
|
+
blen_struct.prototype.blender_name = name;
|
|
290
|
+
blen_struct.prototype.__pointers = [];
|
|
291
|
+
blen_struct.prototype.__list__ = [];
|
|
292
|
+
const DNA = this.SDNA[name] = {
|
|
293
|
+
constructor: blen_struct
|
|
294
|
+
};
|
|
295
|
+
let offset2 = 0;
|
|
296
|
+
for (let i = 0; i < struct.length; i += 3) {
|
|
297
|
+
let _name = struct[i];
|
|
298
|
+
const n = _name, type = struct[i + 1];
|
|
299
|
+
let length = struct[i + 2], array_length = 0, match = null, Blender_Array_Length = 1, Suparray_match = 1, PointerToArray = false, Pointer_Match = 0;
|
|
300
|
+
if (match = _name.match(/(\*?)(\*?)(\w+)(\[(\w*)\])?(\[(\w*)\])?/)) {
|
|
301
|
+
_name = match[3];
|
|
302
|
+
if (match[1]) {
|
|
303
|
+
Pointer_Match = 10;
|
|
304
|
+
blen_struct.prototype.__pointers.push(_name);
|
|
305
|
+
}
|
|
306
|
+
if (match[2]) {
|
|
307
|
+
PointerToArray = true;
|
|
308
|
+
}
|
|
309
|
+
if (match[4]) {
|
|
310
|
+
if (match[6]) {
|
|
311
|
+
Suparray_match = parseInt(match[5]);
|
|
312
|
+
Blender_Array_Length = parseInt(match[7]);
|
|
313
|
+
} else {
|
|
314
|
+
Blender_Array_Length = parseInt(match[5]);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
array_length = Blender_Array_Length * length;
|
|
318
|
+
length = array_length * Suparray_match;
|
|
319
|
+
}
|
|
320
|
+
DNA[n] = {
|
|
321
|
+
type,
|
|
322
|
+
length,
|
|
323
|
+
isArray: Blender_Array_Length > 0
|
|
324
|
+
};
|
|
325
|
+
if (PointerToArray) {
|
|
326
|
+
Object.defineProperty(blen_struct.prototype, _name, pointerProp2(offset2));
|
|
327
|
+
offset2 += pointer_size;
|
|
328
|
+
} else if (Suparray_match > 1) {
|
|
329
|
+
const array_names = new Array(Suparray_match);
|
|
330
|
+
for (let j = 0; j < Suparray_match; j++) {
|
|
331
|
+
let array_name_ = `__${_name}[${j}]__`;
|
|
332
|
+
array_names[j] = array_name_;
|
|
333
|
+
offset2 = compileProp(blen_struct.prototype, array_name_, type, offset2, Blender_Array_Length, Pointer_Match, pointer_size, array_length);
|
|
334
|
+
}
|
|
335
|
+
Object.defineProperty(blen_struct.prototype, _name, {
|
|
336
|
+
get: /* @__PURE__ */ function(array_names2) {
|
|
337
|
+
return function() {
|
|
338
|
+
const array = [];
|
|
339
|
+
for (let i2 = 0; i2 < array_names2.length; i2++) {
|
|
340
|
+
array.push(this[array_names2[i2]]);
|
|
341
|
+
}
|
|
342
|
+
return array;
|
|
343
|
+
};
|
|
344
|
+
}(array_names),
|
|
345
|
+
enumerable: true,
|
|
346
|
+
configurable: true
|
|
347
|
+
});
|
|
348
|
+
} else {
|
|
349
|
+
offset2 = compileProp(blen_struct.prototype, _name, type, offset2, Blender_Array_Length, Pointer_Match, pointer_size, length);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return this.SDNA[name].constructor;
|
|
353
|
+
} else {
|
|
354
|
+
if (!this.SDNA[name]) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
return this.SDNA[name].constructor;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const BLENDER_STRUCTURE = function() {
|
|
362
|
+
this.__blender_file__ = null;
|
|
363
|
+
this.__list__ = null;
|
|
364
|
+
this.__super_array_list__ = null;
|
|
365
|
+
this.blender_name = "";
|
|
366
|
+
this.__pointers = null;
|
|
367
|
+
this.address = null;
|
|
368
|
+
this.length = 0;
|
|
369
|
+
this.__data_address__ = 0;
|
|
370
|
+
this.blender_name = "";
|
|
371
|
+
this._length = 0;
|
|
372
|
+
};
|
|
373
|
+
BLENDER_STRUCTURE.prototype = {
|
|
374
|
+
setData: function(pointer, _data_offset, data_block_length, BLENDER_FILE2) {
|
|
375
|
+
if (this.__list__ === null) return this;
|
|
376
|
+
BLENDER_FILE2.addObject(this);
|
|
377
|
+
this.__blender_file__ = BLENDER_FILE2;
|
|
378
|
+
const struct = this.__list__;
|
|
379
|
+
let j = 0, i = 0, name = "", type, length, Blender_Array_Length, offset2, constructor;
|
|
380
|
+
this.__data_address__ = _data_offset;
|
|
381
|
+
if (struct === null) return this;
|
|
382
|
+
for (i = 0; i < struct.length; i += 6) {
|
|
383
|
+
name = struct[i];
|
|
384
|
+
type = struct[i + 1];
|
|
385
|
+
Blender_Array_Length = struct[i + 4];
|
|
386
|
+
struct[i + 5];
|
|
387
|
+
offset2 = this.__data_address__ + struct[i + 3];
|
|
388
|
+
if (Blender_Array_Length > 1) {
|
|
389
|
+
this[name] = [];
|
|
390
|
+
j = 0;
|
|
391
|
+
while (j < Blender_Array_Length) {
|
|
392
|
+
if (current_SDNA_template.getSDNAStructureConstructor(type)) {
|
|
393
|
+
constructor = current_SDNA_template.getSDNAStructureConstructor(type);
|
|
394
|
+
this[name].push(new constructor().setData(0, offset2, offset2 + length / Blender_Array_Length, BLENDER_FILE2));
|
|
395
|
+
} else this[name].push(null);
|
|
396
|
+
offset2 += length / Blender_Array_Length;
|
|
397
|
+
j++;
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
if (current_SDNA_template.getSDNAStructureConstructor(type)) {
|
|
401
|
+
constructor = current_SDNA_template.getSDNAStructureConstructor(type);
|
|
402
|
+
this[name] = new constructor().setData(0, offset2, length + offset2, BLENDER_FILE2);
|
|
403
|
+
} else this[name] = null;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
this.__list__ = null;
|
|
407
|
+
return this;
|
|
408
|
+
},
|
|
409
|
+
get aname() {
|
|
410
|
+
if (this.id) return this.id.name.slice(2);
|
|
411
|
+
else return void 0;
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
function toString(buffer, _in, _out) {
|
|
415
|
+
return String.fromCharCode.apply(String, new Uint8Array(buffer, _in, _out - _in));
|
|
416
|
+
}
|
|
417
|
+
function readFile() {
|
|
418
|
+
let count = 0;
|
|
419
|
+
let offset2 = 0;
|
|
420
|
+
let data_offset = 0;
|
|
421
|
+
let sdna_index = 0;
|
|
422
|
+
let code = "";
|
|
423
|
+
let block_length = 0;
|
|
424
|
+
let curr_count = 0;
|
|
425
|
+
let curr_count2 = 0;
|
|
426
|
+
FILE.memory_lookup = {};
|
|
427
|
+
struct_names = [];
|
|
428
|
+
offset = 0;
|
|
429
|
+
const magic = toString(_data, offset, 7);
|
|
430
|
+
if (magic !== "BLENDER") return ERROR = "File supplied is not a .blend compatible Blender file.";
|
|
431
|
+
offset += 7;
|
|
432
|
+
pointer_size = toString(_data, offset++, offset) == "_" ? 4 : 8;
|
|
433
|
+
BIG_ENDIAN = toString(_data, offset++, offset) !== "V";
|
|
434
|
+
const version = toString(_data, offset, offset + 3);
|
|
435
|
+
if (!templates[version]) {
|
|
436
|
+
templates[version] = new MASTER_SDNA_SCHEMA(version);
|
|
437
|
+
}
|
|
438
|
+
current_SDNA_template = templates[version];
|
|
439
|
+
FILE.template = current_SDNA_template;
|
|
440
|
+
offset += 3;
|
|
441
|
+
if (!current_SDNA_template.SDNA_SET) {
|
|
442
|
+
current_SDNA_template.endianess = BIG_ENDIAN;
|
|
443
|
+
current_SDNA_template.pointer_size = pointer_size;
|
|
444
|
+
offset2 = offset;
|
|
445
|
+
while (true) {
|
|
446
|
+
sdna_index = data.getInt32(offset2 + pointer_size + 8, BIG_ENDIAN);
|
|
447
|
+
code = toString(_data, offset2, offset2 + 4).replace(/\u0000/g, "");
|
|
448
|
+
block_length = data.getInt32(offset2 + 4, true);
|
|
449
|
+
offset2 += 16 + pointer_size;
|
|
450
|
+
if (code === "DNA1") {
|
|
451
|
+
count = 0;
|
|
452
|
+
let types = [], names = [], lengths = [], curr_name = "";
|
|
453
|
+
offset2 += 8;
|
|
454
|
+
count = data.getInt32(offset2, true);
|
|
455
|
+
offset2 += 4;
|
|
456
|
+
curr_count = 0;
|
|
457
|
+
while (curr_count < count) {
|
|
458
|
+
curr_name = "";
|
|
459
|
+
while (data.getInt8(offset2) !== 0) {
|
|
460
|
+
curr_name += toString(_data, offset2, offset2 + 1);
|
|
461
|
+
offset2++;
|
|
462
|
+
}
|
|
463
|
+
names.push(curr_name);
|
|
464
|
+
offset2++;
|
|
465
|
+
curr_count++;
|
|
466
|
+
}
|
|
467
|
+
if (toString(_data, offset2, offset2 + 4) !== "TYPE") {
|
|
468
|
+
for (let j = 0; j < 8; j++) {
|
|
469
|
+
if (toString(_data, offset2, offset2 + 4) === "TYPE") break;
|
|
470
|
+
offset2++;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (toString(_data, offset2, offset2 + 4) !== "TYPE") {
|
|
474
|
+
debugger;
|
|
475
|
+
}
|
|
476
|
+
offset2 += 4;
|
|
477
|
+
count = data.getUint32(offset2, true);
|
|
478
|
+
offset2 += 4;
|
|
479
|
+
curr_count = 0;
|
|
480
|
+
while (curr_count < count) {
|
|
481
|
+
curr_name = "";
|
|
482
|
+
while (data.getInt8(offset2) !== 0) {
|
|
483
|
+
curr_name += toString(_data, offset2, offset2 + 1);
|
|
484
|
+
offset2++;
|
|
485
|
+
}
|
|
486
|
+
types.push(curr_name);
|
|
487
|
+
offset2++;
|
|
488
|
+
curr_count++;
|
|
489
|
+
}
|
|
490
|
+
if (toString(_data, offset2, offset2 + 4) !== "TLEN") {
|
|
491
|
+
for (let j = 0; j < 8; j++) {
|
|
492
|
+
if (toString(_data, offset2, offset2 + 4) === "TLEN") break;
|
|
493
|
+
offset2++;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (toString(_data, offset2, offset2 + 4) !== "TLEN") {
|
|
497
|
+
debugger;
|
|
498
|
+
}
|
|
499
|
+
offset2 += 4;
|
|
500
|
+
curr_count = 0;
|
|
501
|
+
while (curr_count < count) {
|
|
502
|
+
lengths.push(data.getInt16(offset2, BIG_ENDIAN));
|
|
503
|
+
offset2 += 2;
|
|
504
|
+
curr_count++;
|
|
505
|
+
}
|
|
506
|
+
if (toString(_data, offset2, offset2 + 4) !== "STRC") {
|
|
507
|
+
for (let j = 0; j < 8; j++) {
|
|
508
|
+
if (toString(_data, offset2, offset2 + 4) === "STRC") break;
|
|
509
|
+
offset2++;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (toString(_data, offset2, offset2 + 4) !== "STRC") {
|
|
513
|
+
debugger;
|
|
514
|
+
}
|
|
515
|
+
offset2 += 4;
|
|
516
|
+
const structure_count = data.getInt32(offset2, BIG_ENDIAN);
|
|
517
|
+
offset2 += 4;
|
|
518
|
+
curr_count = 0;
|
|
519
|
+
while (curr_count < structure_count) {
|
|
520
|
+
const struct_name = types[data.getInt16(offset2, BIG_ENDIAN)];
|
|
521
|
+
offset2 += 2;
|
|
522
|
+
const obj = [];
|
|
523
|
+
count = data.getInt16(offset2, BIG_ENDIAN);
|
|
524
|
+
offset2 += 2;
|
|
525
|
+
curr_count2 = 0;
|
|
526
|
+
struct_names.push(struct_name);
|
|
527
|
+
while (curr_count2 < count) {
|
|
528
|
+
obj.push(names[data.getInt16(offset2 + 2, BIG_ENDIAN)], types[data.getInt16(offset2, BIG_ENDIAN)], lengths[data.getInt16(offset2, BIG_ENDIAN)]);
|
|
529
|
+
offset2 += 4;
|
|
530
|
+
curr_count2++;
|
|
531
|
+
}
|
|
532
|
+
current_SDNA_template.getSDNAStructureConstructor(struct_name, obj);
|
|
533
|
+
curr_count++;
|
|
534
|
+
}
|
|
535
|
+
current_SDNA_template.SDNA_SET = true;
|
|
536
|
+
current_SDNA_template.SDNA_NAMES = struct_names;
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
offset2 += block_length;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
while (true) {
|
|
543
|
+
for (let j = 0; j < 8; j++) {
|
|
544
|
+
if (data.getInt8(offset) === 0) {
|
|
545
|
+
offset++;
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
break;
|
|
549
|
+
}
|
|
550
|
+
if (data.getInt8(offset) === 0) {
|
|
551
|
+
debugger;
|
|
552
|
+
}
|
|
553
|
+
data_offset = offset;
|
|
554
|
+
if (offset + pointer_size + 12 >= data.byteLength) {
|
|
555
|
+
ERROR = "Unexpected end of file while parsing";
|
|
556
|
+
break;
|
|
557
|
+
}
|
|
558
|
+
sdna_index = data.getInt32(offset + pointer_size + 8, BIG_ENDIAN);
|
|
559
|
+
const code_str = toString(_data, offset, offset + 4);
|
|
560
|
+
offset2 = offset + 16 + pointer_size;
|
|
561
|
+
const blockLength = data.getInt32(offset + 4, true);
|
|
562
|
+
if (blockLength < 0 || offset + blockLength + 16 + pointer_size > data.byteLength) {
|
|
563
|
+
ERROR = "Invalid block length detected";
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
offset += blockLength + 16 + pointer_size;
|
|
567
|
+
if (code_str === "DNA1") ;
|
|
568
|
+
else if (code_str === "ENDB") break;
|
|
569
|
+
else if (code_str === "TEST") {
|
|
570
|
+
const data_start = data_offset + pointer_size + 16;
|
|
571
|
+
const width = data.getInt32(data_start, BIG_ENDIAN);
|
|
572
|
+
const height = data.getInt32(data_start + 4, BIG_ENDIAN);
|
|
573
|
+
if (width * height > 0) {
|
|
574
|
+
const data_len = width * height * 4;
|
|
575
|
+
if (blockLength < data_len + 8) {
|
|
576
|
+
ERROR = "Invalid TEST block length detected";
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
const image_data = new Uint32Array(_data, data_start + 8, data_len >> 2);
|
|
580
|
+
const image = {
|
|
581
|
+
width,
|
|
582
|
+
height,
|
|
583
|
+
data: image_data
|
|
584
|
+
};
|
|
585
|
+
FILE.thumbnail = image;
|
|
586
|
+
}
|
|
587
|
+
} else {
|
|
588
|
+
const data_start = data_offset + pointer_size + 16;
|
|
589
|
+
const constructor = current_SDNA_template.getSDNAStructureConstructor(current_SDNA_template.SDNA_NAMES[sdna_index]);
|
|
590
|
+
const size = data.getInt32(data_offset + 4, BIG_ENDIAN);
|
|
591
|
+
count = data.getInt32(data_offset + 12 + pointer_size, BIG_ENDIAN);
|
|
592
|
+
if (count > 0 && constructor) {
|
|
593
|
+
let obj = new constructor();
|
|
594
|
+
const length = constructor.prototype._length;
|
|
595
|
+
const address = FILE.getPointer(data_offset + 8);
|
|
596
|
+
obj.address = address + "";
|
|
597
|
+
obj.setData(address, data_start, data_start + size, FILE);
|
|
598
|
+
if (count > 1) {
|
|
599
|
+
let array = [];
|
|
600
|
+
array.push(obj);
|
|
601
|
+
for (let u = 1; u < count; u++) {
|
|
602
|
+
obj = new constructor();
|
|
603
|
+
obj.setData(address, data_start + length * u, data_start + length * u + length, FILE);
|
|
604
|
+
array.push(obj);
|
|
605
|
+
}
|
|
606
|
+
FILE.memory_lookup[address] = array;
|
|
607
|
+
} else {
|
|
608
|
+
FILE.memory_lookup[address] = obj;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
worker = new worker_code();
|
|
616
|
+
worker.postMessage = function(message, err) {
|
|
617
|
+
return_object.onParseReady(message, err);
|
|
618
|
+
};
|
|
619
|
+
/**
|
|
620
|
+
* JS.Blend
|
|
621
|
+
* Original Repo: https://github.com/acweathersby/js.blend
|
|
622
|
+
* Slightly modified for three.js and js updates, minor refactor.
|
|
623
|
+
* Object-creation part re-written for latest three.js and typescript
|
|
624
|
+
* MIT License
|
|
625
|
+
* Copyright (c) 2020 Anthony C, Weathersby
|
|
626
|
+
* @license
|
|
627
|
+
*/
|
|
628
|
+
async function parseBlend(buffer, name = "") {
|
|
629
|
+
return new Promise((res, rej) => {
|
|
630
|
+
return_object.onParseReady = (file, error) => {
|
|
631
|
+
if (error) console.error(error);
|
|
632
|
+
res(file);
|
|
633
|
+
};
|
|
634
|
+
return_object.loadBlendFromArrayBuffer(buffer, name);
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
function createCamera(object, ctx) {
|
|
638
|
+
const cdata = object.data;
|
|
639
|
+
if (!cdata) return void 0;
|
|
640
|
+
const type = cdata.type;
|
|
641
|
+
let camera;
|
|
642
|
+
if (type === 0) {
|
|
643
|
+
camera = new ctx.PerspectiveCamera(
|
|
644
|
+
cdata.lens || 50,
|
|
645
|
+
// fov or lens
|
|
646
|
+
(cdata.sensor_x || 36) / (cdata.sensor_y || 24),
|
|
647
|
+
// aspect
|
|
648
|
+
cdata.clipsta || 0.1,
|
|
649
|
+
// near
|
|
650
|
+
cdata.clipend || 1e3
|
|
651
|
+
// far
|
|
652
|
+
);
|
|
653
|
+
camera.position.set(0, 0, 0);
|
|
654
|
+
if ("shiftx" in cdata) camera.userData.shiftX = cdata.shiftx;
|
|
655
|
+
if ("shifty" in cdata) camera.userData.shiftY = cdata.shifty;
|
|
656
|
+
} else if (type === 1) {
|
|
657
|
+
const scale = cdata.ortho_scale || 1;
|
|
658
|
+
const aspect = (cdata.sensor_x || 36) / (cdata.sensor_y || 24);
|
|
659
|
+
const left = -scale * aspect / 2;
|
|
660
|
+
const right = scale * aspect / 2;
|
|
661
|
+
const top = scale / 2;
|
|
662
|
+
const bottom = -scale / 2;
|
|
663
|
+
camera = new ctx.OrthographicCamera(
|
|
664
|
+
left,
|
|
665
|
+
right,
|
|
666
|
+
top,
|
|
667
|
+
bottom,
|
|
668
|
+
cdata.clipsta || 0.1,
|
|
669
|
+
cdata.clipend || 1e3
|
|
670
|
+
);
|
|
671
|
+
camera.position.set(0, 0, 0);
|
|
672
|
+
if ("shiftx" in cdata) camera.userData.shiftX = cdata.shiftx;
|
|
673
|
+
if ("shifty" in cdata) camera.userData.shiftY = cdata.shifty;
|
|
674
|
+
} else {
|
|
675
|
+
camera = new ctx.PerspectiveCamera();
|
|
676
|
+
console.warn("Unsupported camera type", type);
|
|
677
|
+
}
|
|
678
|
+
return camera;
|
|
679
|
+
}
|
|
680
|
+
const blenderLightTypes = {
|
|
681
|
+
point: 0,
|
|
682
|
+
sun: 1
|
|
683
|
+
};
|
|
684
|
+
function createLight(lamp, ctx) {
|
|
685
|
+
const ldata = lamp.data;
|
|
686
|
+
const position = [lamp.loc[0], lamp.loc[2], -lamp.loc[1]];
|
|
687
|
+
const color = ldata.r * 255 << 16 | ldata.g * 255 << 8 | ldata.b * 255 << 0;
|
|
688
|
+
const intensity = ldata.energy;
|
|
689
|
+
const distance = 0;
|
|
690
|
+
let light = void 0;
|
|
691
|
+
switch (ldata.type) {
|
|
692
|
+
case blenderLightTypes.point:
|
|
693
|
+
light = new ctx.PointLight(color, intensity, distance);
|
|
694
|
+
light.position.fromArray(position, 0);
|
|
695
|
+
light.castShadow = true;
|
|
696
|
+
break;
|
|
697
|
+
case blenderLightTypes.sun:
|
|
698
|
+
light = new ctx.PointLight(color, intensity, distance);
|
|
699
|
+
light.position.fromArray(position, 0);
|
|
700
|
+
light.castShadow = true;
|
|
701
|
+
if (light.shadow) {
|
|
702
|
+
light.shadow.mapSize.width = 1024;
|
|
703
|
+
light.shadow.mapSize.height = 1024;
|
|
704
|
+
light.shadow.camera.near = 0.01;
|
|
705
|
+
light.shadow.camera.far = 500;
|
|
706
|
+
}
|
|
707
|
+
break;
|
|
708
|
+
default:
|
|
709
|
+
console.warn("Unsupported light type", ldata.type);
|
|
710
|
+
}
|
|
711
|
+
return light;
|
|
712
|
+
}
|
|
713
|
+
function getLayer(layers, i) {
|
|
714
|
+
if (!Array.isArray(layers)) return layers;
|
|
715
|
+
return layers[i];
|
|
716
|
+
}
|
|
717
|
+
function createBufferGeometry(meshData, ctx) {
|
|
718
|
+
var _a;
|
|
719
|
+
if (meshData.mpoly) return createBufferGeometryOld(meshData, ctx);
|
|
720
|
+
const geometry = new ctx.BufferGeometry();
|
|
721
|
+
geometry.name = meshData.aname || "";
|
|
722
|
+
let vertices;
|
|
723
|
+
let indices;
|
|
724
|
+
if (meshData.vdata && meshData.vdata.layers && meshData.vdata.totlayer > 0) {
|
|
725
|
+
for (let i = 0; i < meshData.vdata.totlayer; i++) {
|
|
726
|
+
const layer = getLayer(meshData.vdata.layers, i);
|
|
727
|
+
const data = layer.data || [];
|
|
728
|
+
if (data.length === meshData.totvert) {
|
|
729
|
+
if (vertices && (layer.name !== "position" || vertices.name === "position")) {
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
vertices = layer;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (meshData.ldata && meshData.ldata.layers) {
|
|
737
|
+
for (let i = 0; i < meshData.ldata.totlayer; i++) {
|
|
738
|
+
const layer = getLayer(meshData.ldata.layers, i);
|
|
739
|
+
const data = layer.data || [];
|
|
740
|
+
if (data.length === meshData.totloop) {
|
|
741
|
+
if (indices && (layer.name !== ".corner_vert" || indices.name === ".corner_vert")) {
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
indices = layer;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
let faceIndices = [];
|
|
749
|
+
if (meshData.poly_offset_indices && meshData.totpoly > 0) {
|
|
750
|
+
faceIndices = [...new Int32Array(meshData.poly_offset_indices.__blender_file__.AB, meshData.poly_offset_indices.__data_address__, meshData.totpoly + 1)];
|
|
751
|
+
}
|
|
752
|
+
if ((vertices == null ? void 0 : vertices.data) && vertices.data.length > 0) {
|
|
753
|
+
const positions = new Float32Array(vertices.data.length * 3);
|
|
754
|
+
for (let j = 0; j < vertices.data.length; j++) {
|
|
755
|
+
const vertex = vertices.data[j];
|
|
756
|
+
if (vertex.x !== void 0) {
|
|
757
|
+
positions[j * 3] = vertex.x;
|
|
758
|
+
positions[j * 3 + 1] = vertex.z;
|
|
759
|
+
positions[j * 3 + 2] = -vertex.y;
|
|
760
|
+
} else if (vertex.co !== void 0) {
|
|
761
|
+
positions[j * 3] = vertex.co[0];
|
|
762
|
+
positions[j * 3 + 1] = vertex.co[2];
|
|
763
|
+
positions[j * 3 + 2] = -vertex.co[1];
|
|
764
|
+
} else {
|
|
765
|
+
console.error("BlendLoader - unknown vertex", vertex);
|
|
766
|
+
break;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
geometry.setAttribute("position", new ctx.BufferAttribute(positions, 3));
|
|
770
|
+
}
|
|
771
|
+
if ((indices == null ? void 0 : indices.data) && indices.data.length > 0 && ((_a = vertices == null ? void 0 : vertices.data) == null ? void 0 : _a.length)) {
|
|
772
|
+
const faceSize = meshData.totloop / meshData.totpoly;
|
|
773
|
+
if (faceIndices.length > 0) {
|
|
774
|
+
let totalTriangles = 0;
|
|
775
|
+
for (let i = 0; i < faceIndices.length - 1; i++) {
|
|
776
|
+
const faceVertCount = faceIndices[i + 1] - faceIndices[i];
|
|
777
|
+
totalTriangles += Math.max(0, faceVertCount - 2);
|
|
778
|
+
}
|
|
779
|
+
const indexes = new Uint32Array(totalTriangles * 3);
|
|
780
|
+
let t = 0;
|
|
781
|
+
for (let i = 0; i < faceIndices.length - 1; i++) {
|
|
782
|
+
const faceStart = faceIndices[i];
|
|
783
|
+
const faceEnd = faceIndices[i + 1];
|
|
784
|
+
const faceVertCount = faceEnd - faceStart;
|
|
785
|
+
if (faceVertCount >= 3) {
|
|
786
|
+
const firstVert = indices.data[faceStart].i;
|
|
787
|
+
for (let k = 1; k < faceVertCount - 1; k++) {
|
|
788
|
+
indexes[t++] = firstVert;
|
|
789
|
+
indexes[t++] = indices.data[faceStart + k].i;
|
|
790
|
+
indexes[t++] = indices.data[faceStart + k + 1].i;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
geometry.setIndex(new ctx.BufferAttribute(indexes, 1));
|
|
795
|
+
} else if (faceSize === 3 || faceSize === 4) {
|
|
796
|
+
const isQuad = faceSize === 4;
|
|
797
|
+
const faceCount = indices.length / faceSize;
|
|
798
|
+
const indexes = new Uint32Array(faceCount * 3 * (isQuad ? 2 : 1));
|
|
799
|
+
if (faceSize !== 3 && faceSize !== 4) return geometry;
|
|
800
|
+
for (let j = 0, t = 0; j < indices.length; j += faceSize) {
|
|
801
|
+
const a = indices[j].i;
|
|
802
|
+
const b = indices[j + 1].i;
|
|
803
|
+
const c = indices[j + 2].i;
|
|
804
|
+
indexes[t++] = a;
|
|
805
|
+
indexes[t++] = b;
|
|
806
|
+
indexes[t++] = c;
|
|
807
|
+
if (isQuad) {
|
|
808
|
+
const d = indices[j + 3].i;
|
|
809
|
+
indexes[t++] = a;
|
|
810
|
+
indexes[t++] = c;
|
|
811
|
+
indexes[t++] = d;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
geometry.setIndex(new ctx.BufferAttribute(indexes, 1));
|
|
815
|
+
}
|
|
816
|
+
} else if (faceIndices) {
|
|
817
|
+
console.error("BlendLoader - no indices data found, but face indices are present", faceIndices);
|
|
818
|
+
}
|
|
819
|
+
if (geometry.attributes.position && !geometry.attributes.normal)
|
|
820
|
+
geometry.computeVertexNormals();
|
|
821
|
+
return geometry;
|
|
822
|
+
}
|
|
823
|
+
function createBufferGeometryOld(mesh, ctx) {
|
|
824
|
+
const faces = Array.isArray(mesh.mpoly) ? mesh.mpoly : [mesh.mpoly], loops = mesh.mloop, uv = mesh.mloopuv, vertices = mesh.mvert;
|
|
825
|
+
const geometry = new ctx.BufferGeometry();
|
|
826
|
+
if (!faces) return geometry;
|
|
827
|
+
const size = faces.reduce((acc, face) => acc + Math.floor(face.totloop * 3 / 2), 0);
|
|
828
|
+
const indices = new Uint32Array(size);
|
|
829
|
+
const uvs = new Float32Array(size * 2);
|
|
830
|
+
const normals = new Float32Array(size * 3);
|
|
831
|
+
const positions = new Float32Array(size * 3);
|
|
832
|
+
let currentIndex = 0;
|
|
833
|
+
let computeNormals = false;
|
|
834
|
+
for (const face of faces) {
|
|
835
|
+
const len = face.totloop;
|
|
836
|
+
const start = face.loopstart;
|
|
837
|
+
let indexi = 1;
|
|
838
|
+
while (indexi < len) {
|
|
839
|
+
let index = 0;
|
|
840
|
+
for (let l = 0; l < 3; l++) {
|
|
841
|
+
index = start;
|
|
842
|
+
if (indexi - 1 + l < len)
|
|
843
|
+
index += indexi - 1 + l;
|
|
844
|
+
const loop = loops[index];
|
|
845
|
+
const vert = vertices[loop.v];
|
|
846
|
+
indices[currentIndex] = currentIndex;
|
|
847
|
+
positions[currentIndex * 3 + 0] = vert.co[0];
|
|
848
|
+
positions[currentIndex * 3 + 1] = vert.co[2];
|
|
849
|
+
positions[currentIndex * 3 + 2] = -vert.co[1];
|
|
850
|
+
if (vert.no) {
|
|
851
|
+
normals[currentIndex * 3 + 0] = vert.no[0];
|
|
852
|
+
normals[currentIndex * 3 + 1] = vert.no[2];
|
|
853
|
+
normals[currentIndex * 3 + 2] = -vert.no[1];
|
|
854
|
+
} else {
|
|
855
|
+
computeNormals = true;
|
|
856
|
+
}
|
|
857
|
+
if (uv) {
|
|
858
|
+
uvs[currentIndex * 2 + 0] = uv[index].uv[0];
|
|
859
|
+
uvs[currentIndex * 2 + 1] = uv[index].uv[1];
|
|
860
|
+
}
|
|
861
|
+
currentIndex++;
|
|
862
|
+
}
|
|
863
|
+
indexi += 2;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
geometry.setAttribute("position", new ctx.BufferAttribute(positions, 3));
|
|
867
|
+
geometry.setIndex(new ctx.BufferAttribute(indices, 1));
|
|
868
|
+
geometry.setAttribute("normal", new ctx.BufferAttribute(normals, 3));
|
|
869
|
+
geometry.setAttribute("uv", new ctx.BufferAttribute(uvs, 2));
|
|
870
|
+
if (computeNormals) {
|
|
871
|
+
geometry.computeVertexNormals();
|
|
872
|
+
}
|
|
873
|
+
return geometry;
|
|
874
|
+
}
|
|
875
|
+
function createMaterial(mat, ctx) {
|
|
876
|
+
const material = new ctx.MeshPhysicalMaterial();
|
|
877
|
+
material.color.setRGB(mat.r, mat.g, mat.b);
|
|
878
|
+
material.roughness = mat.roughness !== void 0 ? mat.roughness : 0.4;
|
|
879
|
+
material.metalness = mat.metallic !== void 0 ? mat.metallic : 0;
|
|
880
|
+
material.opacity = 1;
|
|
881
|
+
material.transparent = material.opacity < 1;
|
|
882
|
+
return material;
|
|
883
|
+
}
|
|
884
|
+
function setCreateTransform(object, obj) {
|
|
885
|
+
obj.name = object.aname;
|
|
886
|
+
obj.quaternion.set(object.quat[1], object.quat[3], -object.quat[2], object.quat[0]);
|
|
887
|
+
obj.scale.set(object.size[0], object.size[1], object.size[2]);
|
|
888
|
+
obj.position.set(object.loc[0], object.loc[2], -object.loc[1]);
|
|
889
|
+
obj.updateMatrix();
|
|
890
|
+
}
|
|
891
|
+
function createMesh(object, loaded, ctx) {
|
|
892
|
+
if (!object.data) {
|
|
893
|
+
return void 0;
|
|
894
|
+
}
|
|
895
|
+
const geometry = loaded.get(object.data) ?? createBufferGeometry(object.data, ctx);
|
|
896
|
+
loaded.set(object.data, geometry);
|
|
897
|
+
const mat = object.data.mat[0];
|
|
898
|
+
const material = mat ? loaded.get(mat) ?? createMaterial(mat, ctx) : new ctx.MeshPhysicalMaterial();
|
|
899
|
+
if (mat) loaded.set(mat, material);
|
|
900
|
+
const mesh = new ctx.Mesh(geometry, material);
|
|
901
|
+
mesh.castShadow = true;
|
|
902
|
+
mesh.receiveShadow = true;
|
|
903
|
+
return mesh;
|
|
904
|
+
}
|
|
905
|
+
const blenderObjectTypes = {
|
|
906
|
+
empty: 0,
|
|
907
|
+
mesh: 1,
|
|
908
|
+
lamp: 10,
|
|
909
|
+
camera: 11
|
|
910
|
+
};
|
|
911
|
+
async function createObjects(file, ctx) {
|
|
912
|
+
const objects = [];
|
|
913
|
+
const childMap = /* @__PURE__ */ new Map();
|
|
914
|
+
const objMap = /* @__PURE__ */ new Map();
|
|
915
|
+
const blendObjects = file.objects.Object ?? [];
|
|
916
|
+
const loaded = /* @__PURE__ */ new WeakMap();
|
|
917
|
+
for (const object of blendObjects) {
|
|
918
|
+
if (loaded.has(object)) {
|
|
919
|
+
console.warn("BlendLoader - duplicate object");
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
let obj = void 0;
|
|
923
|
+
switch (object.type) {
|
|
924
|
+
case blenderObjectTypes.empty:
|
|
925
|
+
obj = new ctx.Object3D();
|
|
926
|
+
break;
|
|
927
|
+
case blenderObjectTypes.mesh:
|
|
928
|
+
obj = createMesh(object, loaded, ctx);
|
|
929
|
+
break;
|
|
930
|
+
case blenderObjectTypes.lamp:
|
|
931
|
+
obj = createLight(object, ctx);
|
|
932
|
+
break;
|
|
933
|
+
case blenderObjectTypes.camera:
|
|
934
|
+
obj = createCamera(object, ctx);
|
|
935
|
+
break;
|
|
936
|
+
default:
|
|
937
|
+
obj = new ctx.Object3D();
|
|
938
|
+
console.warn("Unsupported object type", object.type, object, obj);
|
|
939
|
+
}
|
|
940
|
+
if (obj) {
|
|
941
|
+
setCreateTransform(object, obj);
|
|
942
|
+
const exChildren = childMap.get(object);
|
|
943
|
+
if (exChildren) {
|
|
944
|
+
for (const exChild of exChildren) {
|
|
945
|
+
obj.add(exChild);
|
|
946
|
+
}
|
|
947
|
+
childMap.delete(object);
|
|
948
|
+
}
|
|
949
|
+
objMap.set(object, obj);
|
|
950
|
+
if (object.parent === object) {
|
|
951
|
+
console.error("invalid, parent same as object, adding to root", object);
|
|
952
|
+
objects.push(obj);
|
|
953
|
+
} else if (!object.parent) {
|
|
954
|
+
objects.push(obj);
|
|
955
|
+
} else {
|
|
956
|
+
const parent = objMap.get(object.parent);
|
|
957
|
+
if (!parent) {
|
|
958
|
+
const chi = childMap.get(object.parent) ?? [];
|
|
959
|
+
chi.push(obj);
|
|
960
|
+
childMap.set(object, chi);
|
|
961
|
+
} else {
|
|
962
|
+
parent.add(obj);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
loaded.set(object, obj);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
if (childMap.size) {
|
|
969
|
+
const vals = [...childMap.values()].flat();
|
|
970
|
+
console.warn("unknown objects with parents, adding to root", vals, childMap);
|
|
971
|
+
objects.push(...vals);
|
|
972
|
+
}
|
|
973
|
+
return objects.filter((o) => !!o);
|
|
974
|
+
}
|
|
975
|
+
const _BlendLoadPlugin = class _BlendLoadPlugin extends threepipe.BaseImporterPlugin {
|
|
976
|
+
constructor() {
|
|
977
|
+
super();
|
|
978
|
+
this._importer = new threepipe.Importer(class extends threepipe.FileLoader {
|
|
979
|
+
async loadAsync(url, onProgress) {
|
|
980
|
+
this.setResponseType("arraybuffer");
|
|
981
|
+
const res = await super.loadAsync(url, onProgress);
|
|
982
|
+
const blend = await parseBlend(res);
|
|
983
|
+
const ctx = {
|
|
984
|
+
Object3D: threepipe.Object3D2,
|
|
985
|
+
Mesh: threepipe.Mesh2,
|
|
986
|
+
MeshPhysicalMaterial: threepipe.PhysicalMaterial,
|
|
987
|
+
PerspectiveCamera: threepipe.PerspectiveCamera0,
|
|
988
|
+
OrthographicCamera: threepipe.OrthographicCamera0,
|
|
989
|
+
PointLight: threepipe.PointLight2,
|
|
990
|
+
BufferGeometry: threepipe.BufferGeometry2,
|
|
991
|
+
BufferAttribute: threepipe.BufferAttribute
|
|
992
|
+
};
|
|
993
|
+
const objects = await createObjects(blend, ctx);
|
|
994
|
+
const root = new threepipe.Object3D();
|
|
995
|
+
root.add(...objects);
|
|
996
|
+
blend.scene = root;
|
|
997
|
+
return blend;
|
|
998
|
+
}
|
|
999
|
+
transform(res, options) {
|
|
1000
|
+
if (typeof options.onBlendLoad === "function") {
|
|
1001
|
+
options.onBlendLoad(res);
|
|
1002
|
+
}
|
|
1003
|
+
return res.scene;
|
|
1004
|
+
}
|
|
1005
|
+
}, ["blend"], ["application/x-blender"], true);
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
_BlendLoadPlugin.PluginType = "BlendLoadPlugin";
|
|
1009
|
+
let BlendLoadPlugin = _BlendLoadPlugin;
|
|
1010
|
+
exports2.BlendLoadPlugin = BlendLoadPlugin;
|
|
1011
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
1012
|
+
});
|
|
18
1013
|
//# sourceMappingURL=index.js.map
|