"use strict";(()=>{var _=THREE,ie=Vue,le=window.JSZip;var F="1.2.0",K="1.0.0",B="_NONE_",h={albedo:{id:"albedo",label:"Albedo",description:"The color of the material",map:"map",icon:"tonality",default:new _.Color(16777215),regex:new RegExp("(s|_)*(basecolor|color|albedo)","i")},metalness:{id:"metalness",label:"Metalness",description:"The material's metalness map",map:"metalnessMap",icon:"brightness_6",default:new _.Color(0),regex:new RegExp("[ _]*metal(lic|ness)?","i")},emissive:{id:"emissive",label:"Emissive",description:"The material's emissive map",map:"emissiveMap",icon:"wb_twilight",default:new _.Color(0),regex:new RegExp("[ _]*(emissive|emission)","i")},roughness:{id:"roughness",label:"Roughness",description:"The material's roughness map",map:"roughnessMap",icon:"grain",default:new _.Color(16777215),regex:new RegExp("[ _]*rough(ness)?","i")},height:{id:"height",label:"Height",description:"The material's height map",map:"bumpMap",icon:"landscape",default:new _.Color(16777215),regex:new RegExp("[ _]*(height|bump)","i")},normal:{id:"normal",label:"Normal",description:"The material's normal map",map:"normalMap",icon:"looks",default:new _.Color("rgb(128, 128, 255)"),regex:new RegExp("[ _]*normal","i")},ao:{id:"ao",label:"Ambient Occlusion",description:"The material's ambient occlusion map",map:"aoMap",icon:"motion_mode",default:new _.Color(16777215),regex:new RegExp("[ _]*(ao|ambientocclusion|ambient occlusion)","i")}},o={},y=[],C=[];var ce=[...Object.keys(h).map(e=>h[e].id),B];y.push(()=>{o.channelProp=new Property(TextureLayer,"enum","channel",{default:B,values:ce,label:"PBR Channel",exposed:!1}),o.textureChannelProp=new Property(Texture,"enum","channel",{default:B,values:ce,label:"PBR Channel",exposed:!1}),o.materialTextureProp=new Property(Texture,"boolean","material",{default:!1,label:"Material Texture"}),o.pbrMaterialsProp=new Property(ModelProject,"object","pbr_materials",{default:{},exposed:!1,label:"PBR Materials"}),o.projectMaterialsProp=new Property(ModelProject,"object","bb_materials",{default:{},exposed:!1,label:"Project Materials"}),o.projectPbrModeProp=new Property(ModelProject,"boolean","pbr_active",{default:!1,exposed:!1,values:[],label:"PBR Mode"})});function E(){return Texture.selected?Texture.selected:TextureLayer.selected?TextureLayer.selected.texture:Project?Project.selected_texture?Project.selected_texture:Project.textures.find(e=>e.selected)??null:Texture.all.find(e=>e.selected)??Texture.getDefault()}function R(){return TextureLayer.selected?TextureLayer.selected:Texture.selected?.selected_layer?Texture.selected.selected_layer:Project.selected_texture!==null&&Project.selected_texture?.layers_enabled===!0?Project.selected_texture.layers.find(e=>e.selected)??Project.selected_texture.layers[0]:E()?.getActiveLayer()??null}function G(){return Project?Project.model_identifier.length>0?Project.model_identifier:Project.getDisplayName():pathToName(E()?.name??"texture")}function ue(e,a){let t;return function(...r){let n=()=>{t=void 0,e.apply(this,r)};clearTimeout(t),t=setTimeout(n,a)}}function z(e){let a=MediaPreview.renderer??new _.WebGLRenderer({alpha:!0,antialias:!0}),t=new _.Scene,r=new _.PerspectiveCamera(75,96/96,.1,1e3),n=new _.AmbientLight(16777215,.75);t.add(n);let i=new _.PointLight(16777215,1,100);i.position.set(5,5,5),t.add(i);let s=new _.SphereGeometry(1,32,32),l=e instanceof _.MeshStandardMaterial&&e.isMeshStandardMaterial?e:new _.MeshStandardMaterial({color:e.albedo,metalness:e.metalness??0,roughness:e.roughness??1,emissive:e.emissive,bumpScale:e.height??0,envMap:PreviewScene.active?.cubemap??null,envMapIntensity:.5}),u=new _.Mesh(s,l);t.add(u),r.position.x=0,r.position.y=0,r.position.z=2,a.setSize(96,96),a.render(t,r);let m=a.domElement.toDataURL();return l.dispose(),MediaPreview.renderer||(a.clear(),a.dispose()),m}function Y(e,a){let t=a??document.createElement("canvas"),r=t.getContext("2d");if(!r)return t.remove(),null;let n=Math.max(Project?Project.texture_width:16,16),i=Math.max(Project?Project.texture_height:16,16);t.width=n,t.height=i,r.fillStyle=`rgb(${e.r*255}, ${e.g*255}, ${e.b*255})`,r.fillRect(0,0,n,i);let s=t.toDataURL();return a||t.remove(),s}var Qe=(e=!0)=>{let a=Project?Project.textures??Texture.all:Texture.all;return e?a.filter(t=>t.layers_enabled&&t.layers.length>0).flatMap(t=>t.layers):a},k=class e{constructor(a,t){this._scope=a??Qe(),this._materialUuid=t}merToCanvas(){let a=this.getTexture(h.emissive),t=this.getTexture(h.roughness),r=this.getTexture(h.metalness);if(!a&&!t&&!r){let{metalness:n,emissive:i,roughness:s}=this.decodeMer();n&&(r=e.makePixelatedCanvas(n)),i&&(a=e.makePixelatedCanvas(i)),s&&(t=e.makePixelatedCanvas(s))}return{emissiveMap:a,roughnessMap:t,metalnessMap:r}}getMaterial(a={}){let{emissiveMap:t,roughnessMap:r,metalnessMap:n}=Format.id.startsWith("bedrock")?this.merToCanvas():{emissiveMap:this.getTexture(h.emissive),roughnessMap:this.getTexture(h.roughness),metalnessMap:this.getTexture(h.metalness)},i=this.getTexture(h.normal);return new _.MeshStandardMaterial({map:this.getTexture(h.albedo)??e.makePixelatedCanvas(TextureLayer.selected?.canvas??Texture.all.find(s=>s.selected)?.canvas??Texture.getDefault().canvas),aoMap:this.getTexture(h.ao),bumpMap:this.getTexture(h.height),normalMap:i,normalScale:new _.Vector2(-1,1),metalnessMap:n,metalness:n?1:0,roughnessMap:r,roughness:1,emissiveMap:t,emissiveIntensity:t?1:0,emissive:t?16777215:0,envMap:PreviewScene.active?.cubemap??null,envMapIntensity:.95,alphaTest:.1,transparent:!0,...a})}renderMaterialPreview(){return z(this.getMaterial())}saveTexture(a,t){Project&&(Project.pbr_materials||(Project.pbr_materials={}),Project.pbr_materials[this._materialUuid]||(Project.pbr_materials[this._materialUuid]={}),Project.pbr_materials[this._materialUuid][a.id]=t.uuid,t.extend({channel:a.id}))}findTexture(a,t=!0){if(!Project)return null;let r=this._scope.find(u=>u.channel&&(u.channel===a||u.channel===a.id));if(r)return r;let[n,i]=typeof a=="string"?[a,new RegExp(`_*${a}(.[^.]+)?$`,"i")]:[a.id,a.regex??new RegExp(`_*${a.id}(.[^.]+)?$`,"i")];Project.pbr_materials=Project.pbr_materials??{};let s=Project.pbr_materials[this._materialUuid];if(t&&!s?.length&&n!==B)return this._scope.find(u=>i.test(u.name))??null;let l=s?.[n];return l?this._scope.find(u=>u.uuid===l)??null:null}static makePixelatedCanvas(a){let t=new _.CanvasTexture(a,void 0,void 0,void 0,_.NearestFilter,_.NearestFilter);return t.needsUpdate=!0,t}getTexture(a){let t=this.findTexture(a);return t?e.makePixelatedCanvas(t.canvas):null}static extractChannel(a,t){let r=a.canvas,{width:n,height:i}=r,s=r.getContext("2d");if(!s||!n||!i)return null;let l=document.createElement("canvas");l.width=n,l.height=i;let u=l.getContext("2d");if(!u)return null;let m={r:0,g:1,b:2,a:3}[t],{data:d}=s.getImageData(0,0,n,i),c=new Uint8ClampedArray(n*i*4);for(let g=0;ga){x[f]=v.data[f],x[f+1]=v.data[f+1],x[f+2]=v.data[f+2],x[f+3]=255;continue}x[f]=0,x[f+1]=0,x[f+2]=0,x[f+3]=255}return m.putImageData(new ImageData(x,l.width,l.height),0,0),{metalness:r,emissive:l,emissiveLevel:n,roughness:i,sss:s}}createMer(a=!1){let t=this.findTexture(h.metalness,a),r=this.findTexture(h.emissive,a),n=this.findTexture(h.roughness,a),i=this.findTexture("sss",!1),s=Math.max(t?.img.width??0,r?.img.width??0,n?.img.width??0,Project?Project.texture_width:0,16),l=Math.max(t?.img.height??0,r?.img.height??0,n?.img.height??0,Project?Project.texture_height:0,16),u=document.createElement("canvas");u.width=s,u.height=l;let m=u.getContext("2d");if(!m)return null;let d=t?.img?e.extractChannel(t,"r"):null,c=r?.img?e.extractChannel(r,"g"):null,v=n?.img?e.extractChannel(n,"b"):null,g=i&&i?.img?e.extractChannel(i,"a"):null,x=d?.getContext("2d")?.getImageData(0,0,s,l)??new ImageData(s,l),f=c?.getContext("2d")?.getImageData(0,0,s,l)??new ImageData(s,l),p=v?.getContext("2d")?.getImageData(0,0,s,l)??new ImageData(s,l),b=g?.getContext("2d")?.getImageData(0,0,s,l)??new ImageData(new Uint8ClampedArray(s*l*4).fill(255),s,l),M=new Uint8ClampedArray(s*l*4);for(let w=0;w{n&&new Texture({name:`${a.name}_${r}`,saved:!1,particle:!1,keep_size:!1}).fromDataURL(n.toDataURL()).add()}),t}createTexturesFromNormal(a){let t=this.decodeLabPbrNormal(a);return Object.entries(t).forEach(([r,n])=>{n&&new Texture({name:`${a.name}_${r}`,saved:!1,particle:!1,keep_size:!1}).fromDataURL(n.toDataURL()).add()}),t}};var V=class{constructor({lightHeight:a=.66,ambientLight:t=[.1,.1,.1],minLightIntensity:r=0,lightDiffuse:n=[1,1,1]}={}){this.lightHeight=a,this.ambientLight=t,this.minLightIntensity=r,this.lightDiffuse=n}bake(a,t,r){let n=t instanceof HTMLCanvasElement?t:this.createCanvas(t.width,t.height),i=r instanceof HTMLCanvasElement?r:this.createCanvas(r.width,r.height),s=n.getContext("2d"),l=i.getContext("2d");s.drawImage(t,0,0),l.drawImage(r,0,0);let u=s.getImageData(0,0,t.width,t.height),m=l.getImageData(0,0,r.width,r.height),d=[],c=[];for(let g=0;g{let x=this.createCanvas(t.width,t.height),f=x.getContext("2d"),p=f.getImageData(0,0,x.width,x.height),b=[Math.cos(g),Math.sin(g),this.lightHeight];for(let M=0;M{if(!Project)return;let r=Project.selected_texture??Texture.getDefault(),n=new k(r.layers_enabled?r.layers:Project.textures,r.uuid),i=n.findTexture(h.albedo);if(!i){Blockbench.showStatusMessage("Can not bake without a base color assigned.",3e3);return}let s=n.findTexture(h.normal);if(!s){Blockbench.showStatusMessage("Can not bake without a normal map assigned.",3e3);return}let u=new V(e).bake(a,i.canvas,s.canvas),m=new Texture({name:`${i.name}_baked`,saved:!1,particle:!1,keep_size:!1,layers_enabled:!0}).fromDataURL(u[0].toDataURL()),d=t?c=>{let v=n.findTexture(h.emissive);if(!v)return c;let g=v.canvas;if(!g.getContext("2d"))return c;let f=Math.max(c.width,g.width,Project?Project.texture_width:16),p=Math.max(c.height,g.height,Project?Project.texture_height:16),b=document.createElement("canvas");b.width=f,b.height=p;let M=b.getContext("2d");return M?(M.drawImage(c,0,0),M.globalCompositeOperation="screen",M.drawImage(g,0,0),b):c}:c=>c;u.forEach((c,v)=>{new TextureLayer({name:`baked_${v+1}`,data_url:d(c).toDataURL()},m).addForEditing()}),m.add().select(),Blockbench.showQuickMessage("Textures baked \u{1F950}",2e3)};y.push(()=>{o.bakeTexturesDialog=new Dialog("bake_textures",{id:"bake_textures",title:"Bake Textures",buttons:["Bake","Cancel"],form:{ambientLight:{type:"color",label:"Ambient Light",value:"#1f1f1f"},lightDiffuse:{type:"color",label:"Light Diffuse",value:"#ffffff"},lightHeight:{type:"range",label:"Light Height",min:0,max:1,step:.01,value:.66},minLightIntensity:{type:"range",label:"Minimum Light Intensity",min:0,max:1,step:.01,value:0},directions:{type:"number",label:"Directions",value:8,min:1,max:360,step:1},blendEmissive:{type:"checkbox",label:"Blend Emissive",value:!1}},onConfirm(e){let a=new _.Color(e.ambientLight.toString()),t=new _.Color(e.lightDiffuse.toString());me({ambientLight:[a.r,a.g,a.b],lightDiffuse:[t.r,t.g,t.b],lightHeight:Number(e.lightHeight),minLightIntensity:Number(e.minLightIntensity)},e.directions??8,e.blendEmissive??!1)}}),o.bakeTexturesAction=new Action("bake_textures",{icon:"cake",name:"Bake Textures",description:"Bakes textures for the selected PBR material",click(){o.bakeTexturesDialog?.show()}}),MenuBar.addAction(o.bakeTexturesAction,"tools")});C.push(()=>{MenuBar.removeAction("tools.bake_textures")});function de(e,a){let t=e.getTexture();if(!t||!Project)return null;let r=Project.materials[t.uuid];r.isShaderMaterial&&!Project.bb_materials[t.uuid]?Project.bb_materials[t.uuid]=r:r.isMeshStandardMaterial&&r.dispose();let n=new k(t.layers_enabled?t.layers.filter(i=>i.visible)??null:Project.textures,t.uuid).getMaterial({side:Canvas.getRenderSide(t),...a});return Project.materials[t.uuid]=_.ShaderMaterial.prototype.copy.call(n,r),t}function he(e){return Object.values(e).filter(a=>a?(Canvas.updateAllFaces(a),!0):!1).length>0}function Je(e,a){let t={};return e.forAllFaces(r=>{let n=de(r,a);n&&(t[n.uuid]=n)}),he(t)}function Xe(e,a){let t={};return Object.keys(e.faces).forEach(r=>{let n=e.faces[r],i=de(n,a);i&&(t[i.uuid]=i)}),he(t)}var N=(e={})=>{Project&&(Project.pbr_active=Texture.all.length>0&&Project.elements.map(a=>a instanceof Mesh&&Je(a,e)||a instanceof Cube&&Xe(a,e)).filter(Boolean).length>0)},A=(e=100)=>ue(N,e);var te={},ee=()=>Condition({modes:["edit","paint"],selected:{texture:!0},project:!0,method(){let e=E();return e&&!e.material?!0:e?.material===!0&&R()!==null&&Modes.paint}}),pe=()=>Condition({modes:["paint","edit"],selected:{texture:!0},method(){let e=E();if(e?.material&&Modes.edit)return!1;let a=R()??e;return a?.channel&&a.channel!==B}});y.push(()=>{Object.entries(h).forEach(([e,a])=>{te[e]=new Action(`assign_channel_${e}`,{icon:a.icon??"tv_options_edit_channels",name:`Assign to ${a.label.toLocaleLowerCase()} channel`,description:`Assign the selected layer to the ${a.label} channel`,category:"textures",condition:ee,click(){let t=TextureLayer.selected??(Project?Project.selected_texture:null);if(!t)return;Undo.initEdit({layers:[t]}),t.extend({channel:a.id});let r=t instanceof TextureLayer?t.texture:t;r.updateChangesAfterEdit(),Project.pbr_materials[r.uuid]||(Project.pbr_materials[r.uuid]={}),Object.entries(Project.pbr_materials[r.uuid]).forEach(([n,i])=>{i===t.uuid&&(delete Project.pbr_materials[r.uuid][n],t.channel=B)}),r.uuid===t.uuid&&(Project.pbr_materials[r.uuid]={}),Project.pbr_materials[r.uuid][e]=t.uuid,Undo.finishEdit("Change channel assignment"),Blockbench.showQuickMessage(`Assigned "${t.name}" to ${a.label} channel`,2e3),N()}})})});C.push(()=>{Object.values(te).forEach(e=>{e.delete()})});y.push(()=>{o.unassignChannel=new Action("unassign_channel",{icon:"cancel",name:"Unassign Channel",description:"Unassign the selected layer from the channel",category:"textures",condition:pe,click(){let e=TextureLayer.selected??(Project?Project.selected_texture:null);if(!e)return;Undo.initEdit({layers:[e]});let a=e instanceof TextureLayer?e.texture:e,t=e.channel;Project.pbr_materials[a.uuid]={},e.channel=B,a.updateChangesAfterEdit(),Undo.finishEdit("Unassign channel"),Blockbench.showQuickMessage(`Unassigned "${e.name}" from ${t} channel`,2e3),A()}}),o.channelMenu=new Menu("channel_menu",[...Object.keys(h).map(e=>`assign_channel_${e}`),"unassign_channel"],{onOpen(){A()}}),o.openChannelMenu=new Action("pbr_channel_menu",{name:"Assign to PBR Channel",icon:"texture",condition:()=>ee()||pe(),click(e){o.channelMenu?.open(e)},children:[...Object.values(te),o.unassignChannel]}),o.showChannelMenu=new Action("show_channel_menu",{icon:"texture",name:"Assign to PBR Channel",description:"Assign the selected layer to a channel",category:"textures",condition:ee,click(e){o.channelMenu?.open(e)}}),o.openChannelMenu&&(MenuBar.addAction(o.openChannelMenu,"image.0"),Texture.prototype.menu.addAction(o.openChannelMenu,"0"),TextureLayer.prototype.menu.addAction(o.openChannelMenu,"0")),Toolbars.layers.add(o.showChannelMenu,1)});C.push(()=>{MenuBar.removeAction("image.pbr_channel_menu"),Texture.prototype.menu.removeAction("pbr_channel_menu"),TextureLayer.prototype.menu.removeAction("pbr_channel_menu"),Toolbars.layers.remove(o.showChannelMenu)});function $(e,a="DirectX",t=!1){let r=e.canvas.getContext("2d");if(!r)return null;let n=Math.max(e.img.width??e.canvas.width,Project?Project.texture_width:0,16),i=Math.max(e.img.height??e.canvas.height,Project?Project.texture_height:0,16),{data:s}=r.getImageData(0,0,n,i),l=document.createElement("canvas"),u=l.getContext("2d");if(!u)return null;let m=(p,b)=>{let M=(p+b*n)*4;return s[M]/255};l.width=n,l.height=i,u.drawImage(e.img,0,0,n,i);let d=u.getImageData(0,0,n,i),c=d.data,v=p=>{let b=Math.sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);return[p[0]/b,p[1]/b,p[2]/b]};for(let p=0;p{let f=(g+x*t)*4;return n[f]/255};i.width=t,i.height=r,s.drawImage(e.img,0,0,t,r);let u=s.getImageData(0,0,t,r),m=u.data;for(let g=0;g{let t=R()??E()??Texture.getDefault();if(!t)return;let r=$(t,a,!1);if(!r){Blockbench.showQuickMessage("Failed to generate normal map",2e3);return}r.select(e),new k(t instanceof Texture&&t.layers_enabled?t.layers:null,t.uuid).saveTexture(h.normal,r),Blockbench.showQuickMessage("Normal map generated",2e3)};y.push(()=>{o.generateDirectXNormal=new Action("generate_dx_normal",{icon:h.normal.icon??"altitude",name:"Generate DirectX Normal Map",description:"Generates a DirectX normal map from the height map",condition:()=>(R()??E())!==null,click:e=>fe(e)}),o.generateOpenGlNormal=new Action("generate_opengl_normal",{icon:h.normal.icon??"altitude",name:"Generate OpenGL Normal Map",description:"Generates an OpenGL normal map from the height map",condition:()=>(R()??E())!==null,click:e=>fe(e,"OpenGL")}),o.generateAo=new Action("generate_ao",{icon:h.ao.icon??"motion_mode",name:"Generate Ambient Occlusion Map",description:"Generates an ambient occlusion map from the height map",condition:{selected:{texture:!0},project:!0},click(){let e=R()??E()??Texture.getDefault();if(!e)return;let a=new k(e instanceof Texture&&e.layers_enabled?e.layers:null,e.uuid),t=a.findTexture(h.normal)??$(e);if(!t){Blockbench.showQuickMessage("Unable to generate ambient occlusion map without a normal map",2e3);return}let r=ge(t);if(r){a.saveTexture(h.ao,r),r.select(),Blockbench.showQuickMessage("Ambient occlusion map generated",2e3);return}Blockbench.showQuickMessage("Failed to generate ambient occlusion map",2e3)}}),o.generateNormal=new Action("generate_normal",{children:[o.generateDirectXNormal,o.generateOpenGlNormal],name:"Generate Normal Map",description:"Generates a normal map from the height map",condition:()=>(R()??E())!==null,click(){},icon:h.normal.icon??"altitude"}),MenuBar.addAction(o.generateNormal,"tools"),MenuBar.addAction(o.generateAo,"tools")});C.push(()=>{MenuBar.removeAction("tools.generate_normal"),MenuBar.removeAction("tools.generate_ao")});var Ze=(e,a="texture")=>{e.toBlob(async t=>{t&&Blockbench.export({content:await t.arrayBuffer(),type:"PNG",name:`${a}_n`,extensions:["png"],resource_id:"normal_map",savetype:"image"})})},We=(e,a="texture")=>{e.toBlob(async t=>{t&&Blockbench.export({content:await t.arrayBuffer(),type:"PNG",name:`${a}_s`,extensions:["png"],resource_id:"specular_map",savetype:"image"})})};y.push(()=>{o.generateLabPbr=new Action("generate_lab_pbr",{icon:"experiment",name:"Generate labPBR textures",description:"Generate a specular and normal map in labPBR format for Java shaders",condition:{formats:["java_block"],project:!0},async click(){let e=E();if(!e)return;let t=new k(e.layers_enabled?e.layers:[e],e.uuid).createLabPbrOutput();if(t===null)return;let r=e.name??(Project?Project.getDisplayName():"texture");await Promise.all([Ze(t.normalMap,pathToName(r)),We(t.specular,pathToName(r))]),Blockbench.showQuickMessage("Exported labPBR textures")}}),o.decodeLabPbr=new Action("decode_lab_pbr",{icon:"frame_source",name:"Decode labPBR textures",description:"Decodes the selected texture into a specular or normal map in labPBR format",condition:{formats:["java"],project:!0,selected:{texture:!0}},click(){let e=TextureLayer.selected?.texture??Texture.all.find(t=>t.selected)??Texture.getDefault(),a=new k(e.layers_enabled?e.layers:[e],e.uuid);if(pathToName(e.name).endsWith("_n")){a.createTexturesFromNormal(e);return}if(pathToName(e.name).endsWith("_s")){a.createTexturesFromSpecular(e);return}Blockbench.showQuickMessage("Failed to decode labPBR texture")}}),MenuBar.addAction(o.generateLabPbr,"file.export"),MenuBar.addAction(o.decodeLabPbr,"tools")});C.push(()=>{MenuBar.removeAction("file.export.generate_lab_pbr")});y.push(()=>{o.createMaterialTexture=new Action("create_material_texture",{icon:"deployed_code",name:"Create Material Texture",description:"Creates a new texture for a PBR material",condition:{modes:["edit","paint"],project:!0},click(){if(!Project)return;let e={...h},a=new Texture({name:"New Material",saved:!1,particle:!1});a.extend({material:!0});let t=Texture.all.filter(s=>(s.selected||s.multi_selected)&&!s.material)??Texture.all,r=E(),n=r?new k(t,r.uuid):null;try{let s=n?.findTexture(h.albedo,!0)?.canvas.toDataURL()??r?.canvas.toDataURL()??Y(new _.Color(8421504),a.canvas);if(!s)return;a.fromDataURL(s);let l=new TextureLayer({name:e.albedo.label,visible:!0,data_url:s,keep_size:!0},a);l.extend({channel:e.albedo.id}),l.addForEditing(),l.texture.updateChangesAfterEdit(),n?.saveTexture(e.albedo,l),delete e.albedo}catch(s){console.warn("Failed to create base color texture",s),Blockbench.showStatusMessage("Failed to create base color texture in new material",3e3)}let i=Object.keys(e).reverse().map(s=>{let l=h[s],u=n?.findTexture(l,!0),m=u?u.canvas.toDataURL():Y(l.default??new _.Color(0));if(!m)return;let d=new TextureLayer({name:l.label,visible:!0,data_url:m,keep_size:!0},a);return d.extend({channel:l.id}),n?.saveTexture(l,d),d}).filter(Boolean);Undo.initEdit({textures:Texture.all,layers:i}),a.add().select(),a.activateLayers(),i.map(s=>{s.addForEditing(),a.width=Math.max(a.width,s.img.width),a.height=Math.max(a.height,s.img.height)}),a.updateChangesAfterEdit(),Undo.finishEdit("Create Material Texture")}}),MenuBar.addAction(o.createMaterialTexture,"tools"),Toolbars.texturelist.add(o.createMaterialTexture,3)});C.push(()=>{MenuBar.removeAction("tools.create_material_texture"),Toolbars.texturelist.remove("create_material_texture")});var Q=(e,a)=>{let t=E()??Texture.getDefault(),r=new k(t.layers_enabled?t.layers:Project?Project.textures:null,t.uuid).createMer(!0);if(!r)throw new Error("Failed to generate MER map from selected texture.");r.toBlob(async n=>{if(!n)throw new Error("Failed to save MER map.");let[i,s]=Project?[e?`${e}_mer`:`${t.name??Project.getDisplayName()}_mer`,Project.export_path]:["mer"];Blockbench.export({content:await n.arrayBuffer(),type:"PNG",name:i,extensions:["png"],resource_id:"mer",savetype:"image",startpath:s},a)})};y.push(()=>{o.generateMer=new Action("create_mer",{icon:"lightbulb_circle",name:"Export MER",description:"Exports a texture map from the metalness, emissive, and roughness channels. (For use in Bedrock resource packs.)",condition:{formats:["bedrock","bedrock_block"],project:!0},click(){try{Q()}catch(e){console.error("Failed to export MER map:",e),Blockbench.showStatusMessage("Failed to export MER map",3e3)}}}),o.decodeMer=new Action("decode_mer",{name:"Decode MER",icon:"arrow_split",condition:{formats:["bedrock","bedrock_block"],project:!0,selected:{texture:!0}},children:[{icon:"move_item",name:"Decode MER to Textures",description:"Decodes a MER texture map into metalness, emissive, and roughness channels into separate textures",click(){let e=E()??Texture.getDefault(),a=new k([e],e.uuid),t=a.decodeMer(),r=[h.metalness,h.emissive,h.roughness];Undo.initEdit({textures:[e]}),r.forEach(n=>{let i=n.id,s=t[i];if(!s){Blockbench.showStatusMessage(`Failed to decode ${n.label} channel`,3e3);return}let l=new Texture({name:`${e?.name}_${i}`,keep_size:!1}).fromDataURL(s.toDataURL());l.add(!0),a.saveTexture(n,l)}),Undo.finishEdit("Decode MER to textures")}},{icon:"move_group",name:"Decode MER to Layers",description:"Decodes a MER texture map into metalness, emissive, and roughness channels into material layers",condition:()=>E()?.layers_enabled===!0,click(){let e=E()??Texture.getDefault(),a=new k(e.layers_enabled?e.layers:[e],e.uuid),t=a.decodeMer(),r=[h.metalness,h.emissive,h.roughness];Undo.initEdit({textures:[e]}),r.forEach(n=>{let i=n.id,s=t[i];if(!s){Blockbench.showStatusMessage(`Failed to decode ${n.label} channel`,3e3);return}let l=new TextureLayer({name:`${e?.name}_${i}`,data_url:s.toDataURL()},e);a.saveTexture(n,l),l.addForEditing()}),Undo.finishEdit("Decode MER to layers")}}],click(){}}),MenuBar.addAction(o.decodeMer,"tools"),MenuBar.addAction(o.generateMer,"file.export")});C.push(()=>{MenuBar.removeAction("file.export.create_mer"),MenuBar.removeAction("tools.decode_mer")});var qe=()=>{Project&&Project.textures.forEach(e=>{let a=new k(null,e.uuid),t=a.findTexture(h.normal,!1),r=a.findTexture(h.height,!1),n=a.findTexture(h.albedo,!1),i=a.findTexture(h.metalness,!1)?.name,s=a.findTexture(h.emissive,!1)?.name,l=a.findTexture(h.roughness,!1)?.name,u={};return n||(u.baseColor={type:"color",label:"Base Color",value:"#ff00ff"}),!i&&!s&&!l&&(u.metalness={label:"Metalness",type:"range",min:0,max:255,step:1,value:0},u.emissive={label:"Emissive",type:"range",min:0,max:255,step:1,value:0},u.roughness={label:"Roughness",type:"range",min:0,max:255,step:1,value:0}),t&&(u.depthMap={type:"checkbox",label:"Normal Map",value:"normal"}),r&&(u.depthMap={type:"checkbox",label:"Height Map",value:"heightmap"}),t&&r&&(u.depthMap={type:"radio",label:"Depth Map",options:{normal:"Normal Map",heightmap:"Height"},value:"normal"}),o.textureSetDialog=new Dialog("texture_set",{id:"texture_set",title:"Create Texture Set JSON",buttons:["Create","Cancel"],form:u,cancelIndex:1,onConfirm(m){let d=G(),c=i||s||l,v={format_version:"1.16.100","minecraft:texture_set":{color:(n?d:m.baseColor?.toHexString())??d,metalness_emissive_roughness:[m.metalness??0,m.emissive??0,m.roughness??255]}};m.depthMap==="normal"&&t||!r&&t?v["minecraft:texture_set"].normal=`${d}_normal`:(!t||m.depthMap==="heightmap")&&r&&(v["minecraft:texture_set"].heightmap=`${d}_heightmap`);let g=p=>{if(!m.depthMap)return p();let b=m.depthMap==="normal"||m.depthMap&&!r,M=b?t:r;if(!M)return p();Blockbench.export({content:M.canvas.toDataURL()??"",type:"PNG",name:`${d}_${b?"normal":"heightmap"}`,extensions:["png"],resource_id:m.depthMap,startpath:Project.export_path,savetype:"image"},w=>{v["minecraft:texture_set"][b?"normal":"heightmap"]=pathToName(w,!1),p()})},x=p=>{if(!n)return p();Blockbench.export({content:n.canvas.toDataURL(),extensions:["png"],type:"PNG",name:d,startpath:Project.export_path,savetype:"image"},b=>{v["minecraft:texture_set"].color=pathToName(b,!1),p()})},f=()=>g(()=>{x(()=>{Blockbench.export({content:JSON.stringify(v,null,2),type:"JSON",name:`${d}.texture_set`,extensions:["json"],resource_id:"texture_set",startpath:Project.export_path,savetype:"text"},()=>{Blockbench.showQuickMessage("Texture set created",2e3),o.textureSetDialog?.hide()})})});if(c){try{Q(d,p=>{v["minecraft:texture_set"].metalness_emissive_roughness=pathToName(p,!1),f()})}catch(p){console.warn("Failed to export MER map:",p),Blockbench.showStatusMessage("Failed to export MER map",3e3)}return}f()}}),o.textureSetDialog.show()})};y.push(()=>{o.createTextureSet=new Action("create_texture_set",{name:"Create Texture Set",icon:"layers",description:"Creates a texture set JSON file. Generates a MER when metalness, emissive, or roughness channels are set.",click(){qe()},condition:{formats:["bedrock","bedrock_block"],project:!0}}),MenuBar.addAction(o.createTextureSet,"file.export")});C.push(()=>{MenuBar.removeAction("file.export.create_texture_set")});y.push(()=>{o.toggleCorrectLights=new Toggle("correct_lights",{category:"preview",name:"Correct Lights",description:"Corrects the lighting in the preview",icon:"fluorescent",default:!1,onChange(e){Preview.all.forEach(a=>{a.renderer.physicallyCorrectLights=e}),Preview.selected.renderer.physicallyCorrectLights=e,Blockbench.showQuickMessage(`Physically corrected lighting is now ${e?"enabled":"disabled"}`,2e3),e&&o.togglePbr?.set(!0),N()},click(){}}),MenuBar.addAction(o.toggleCorrectLights,"preview")});C.push(()=>{MenuBar.removeAction("preview.correct_lights")});var J=()=>{!Project||!Project.bb_materials||(Project.elements.forEach(e=>{e instanceof Cube&&Object.keys(e.faces).forEach(a=>{let r=e.faces[a].getTexture();if(!r)return;let n=Project.bb_materials[r.uuid];n&&(Project.materials[r.uuid]=n)})}),Project.pbr_active=!1,Canvas.updateAll())};var xe=["undo","redo","add_texture","finish_edit","finished_edit","load_project","select_preview_scene","change_texture_path","select_project","load_undo_save","add_cube"],be=()=>Project&&Project.pbr_active&&N(),Ke=()=>{Blockbench.on(xe.join(" "),be)},ve=()=>{xe.forEach(e=>{Blockbench.removeListener(e,be)})};y.push(()=>{o.togglePbr=new Toggle("toggle_pbr",{name:"PBR Preview",description:"Toggle PBR Preview",icon:"panorama_photosphere",category:"view",default:!1,click(){},onChange(e){if(e){N(),Ke(),Blockbench.showQuickMessage("PBR Preview is now enabled");return}J(),ve(),Blockbench.showQuickMessage("PBR Preview is now disabled")}}),MenuBar.addAction(o.togglePbr,"view")});C.push(()=>{ve(),MenuBar.removeAction("view.toggle_pbr")});var _e=e=>{let a=Math.max(-2,Math.min(2,e));Preview.all.forEach(t=>{t.renderer.toneMappingExposure=a}),Preview.selected.renderer.toneMappingExposure=a};y.push(()=>{o.exposureSlider=new NumSlider("display_settings_exposure",{category:"preview",name:"Exposure",description:"Adjusts the exposure of the scene",type:"number",value:1,icon:"exposure",settings:{min:-2,max:2,step:.01,default:1},onBefore(){Number(o.tonemappingSelect?.get())===_.NoToneMapping&&o.tonemappingSelect.change(_.LinearToneMapping.toString()),o.togglePbr?.set(!0)},onChange(e){_e(Number(e))},onAfter(){A()}}),o.resetExposureButton=new Action("display_settings_reset_exposure",{category:"preview",name:"Reset Exposure",description:"Resets the exposure of the scene",icon:"exposure_plus_1",condition:()=>o.exposureSlider!==void 0&&Number(o.exposureSlider?.get())!==1,click(){_e(1),o.exposureSlider?.setValue(1,!0),A()}}),o.tonemappingSelect=new BarSelect("display_settings_tone_mapping",{category:"preview",name:"Tone Mapping",description:"Changes the tone mapping of the preview",type:"select",default_value:_.NoToneMapping,value:Preview.selected.renderer.toneMapping??_.NoToneMapping,icon:"monochrome_photos",options:{[_.NoToneMapping]:"No Tone Mapping",[_.LinearToneMapping]:"Linear",[_.ReinhardToneMapping]:"Reinhard",[_.CineonToneMapping]:"Cineon",[_.NeutralToneMapping]:"Neutral",[_.ACESFilmicToneMapping]:"ACES"},onChange({value:e}){Preview.selected.renderer.toneMapping=Number(e);let a=1;Preview.selected.renderer.toneMapping===_.NoToneMapping?o.exposureSlider?.setValue(a,!0):a=Number(o.exposureSlider?.get()??1),Preview.all.forEach(t=>{t.renderer.toneMapping=Number(e),t.renderer.toneMappingExposure=a}),Preview.selected.renderer.toneMappingExposure=a,Blockbench.showQuickMessage(`Tone mapping set to ${this.getNameFor(e)}`,2e3),o.togglePbr&&!o.togglePbr.value&&o.togglePbr.set(!0),N()}})});var ae=class{async parse(a){let t=new le,r="model.usda";t.file(r,"");let n=Te(),i={},s={};a.traverseVisible(m=>{if(!m.isMesh)return;let d=m;if(!d.material.isMeshStandardMaterial){console.warn("THREE.USDZExporter: Unsupported material type (USDZ only supports MeshStandardMaterial)",m);return}let c=d.geometry,v=d.material,g="geometries/Geometry_"+c.id+".usd";if(!t.file(g)){let x=rt(c);t.file(g,et(x))}v.uuid in i||(i[v.uuid]=v),n+=tt(d,c,v)}),n+=lt(i,s),t.file(r,n),n=null;for(let m in s){let d=s[m],c=m.split("_")[1],v=d.format===_.RGBAFormat,g=Ye(d.image,c),f=await(await new Promise(p=>g.toBlob(b=>b&&p(b),v?"image/png":"image/jpeg",1))).arrayBuffer();t.file(`textures/Texture_${m}.${v?"png":"jpg"}`,f)}let l=0;t.forEach(async m=>{let d=34+m.length;l+=d;let c=l&63,v=await t.file(m).async("uint8array");if(c!==4){let g=64-c,x=new Uint8Array(g),f=new Uint8Array(v.length+g);f.set(v,0),f.set(x,v.length),t.file(m,f)}l+=v.length});let u=await t.generateAsync({type:"blob",compression:"STORE"});return new Uint8Array(await u.arrayBuffer())}};function Ye(e,a){if(typeof HTMLImageElement<"u"&&e instanceof HTMLImageElement||typeof HTMLCanvasElement<"u"&&e instanceof HTMLCanvasElement||typeof OffscreenCanvas<"u"&&e instanceof OffscreenCanvas||typeof ImageBitmap<"u"&&e instanceof ImageBitmap){let t=1024/Math.max(e.width,e.height),r=document.createElement("canvas");r.width=e.width*Math.min(1,t),r.height=e.height*Math.min(1,t);let n=r.getContext("2d");if(n.imageSmoothingEnabled=!1,n.drawImage(e,0,0,r.width,r.height),a!==void 0){let i=parseInt(a,16),s=(i>>16&255)/255,l=(i>>8&255)/255,u=(i&255)/255,m=n.getImageData(0,0,r.width,r.height),d=m.data;for(let c=0;c ) { matrix4d xformOp:transform = ${n} uniform token[] xformOpOrder = ["xformOp:transform"] rel material:binding = } `}function at(e){let a=e.elements;return`( ${X(a,0)}, ${X(a,4)}, ${X(a,8)}, ${X(a,12)} )`}function X(e,a){return`(${e[a+0]}, ${e[a+1]}, ${e[a+2]}, ${e[a+3]})`}function rt(e){return` def "Geometry" { ${nt(e)} } `}function nt(e){let a="Geometry",t=e.attributes,r=t.position.count;return` def Mesh "${a}" { int[] faceVertexCounts = [${st(e)}] int[] faceVertexIndices = [${ot(e)}] normal3f[] normals = [${Me(t.normal,r)}] ( interpolation = "vertex" ) point3f[] points = [${Me(t.position,r)}] float2[] primvars:st = [${it(t.uv,r)}] ( interpolation = "vertex" ) uniform token subdivisionScheme = "none" } `}function st(e){let a=e.index!==null?e.index.count:e.attributes.position.count;return Array(a/3).fill(3).join(", ")}function ot(e){let a=e.index,t=[];if(a!==null)for(let r=0;r float2 inputs:scale = ${we(l.repeat)} float2 inputs:translation = ${we(l.offset)} float2 outputs:result } def Shader "Texture_${l.id}_${u}" { uniform token info:id = "UsdUVTexture" asset inputs:file = @textures/Texture_${d}.${c?"png":"jpg"}@ float2 inputs:st.connect = token inputs:wrapS = "repeat" token inputs:wrapT = "repeat" float outputs:r float outputs:g float outputs:b float3 outputs:rgb }`}let s=e;if(s.map!==null?(r.push(`${t}color3f inputs:diffuseColor.connect = `),n.push(i(s.map,"diffuse",s.color))):r.push(`${t}color3f inputs:diffuseColor = ${ye(s.color)}`),s.emissiveMap!==null?(r.push(`${t}color3f inputs:emissiveColor.connect = `),n.push(i(s.emissiveMap,"emissive"))):s.emissive.getHex()>0&&r.push(`${t}color3f inputs:emissiveColor = ${ye(s.emissive)}`),s.normalMap!==null&&(r.push(`${t}normal3f inputs:normal.connect = `),n.push(i(s.normalMap,"normal"))),s.aoMap!==null&&(r.push(`${t}float inputs:occlusion.connect = `),n.push(i(s.aoMap,"occlusion"))),s.roughnessMap!==null&&s.roughness===1?(r.push(`${t}float inputs:roughness.connect = `),n.push(i(s.roughnessMap,"roughness"))):r.push(`${t}float inputs:roughness = ${s.roughness}`),s.metalnessMap!==null&&s.metalness===1?(r.push(`${t}float inputs:metallic.connect = `),n.push(i(s.metalnessMap,"metallic"))):r.push(`${t}float inputs:metallic = ${s.metalness}`),s.alphaMap!==null?(r.push(`${t}float inputs:opacity.connect = `),r.push(`${t}float inputs:opacityThreshold = 0.0001`),n.push(i(s.alphaMap,"opacity"))):r.push(`${t}float inputs:opacity = ${s.opacity}`),s.isMeshPhysicalMaterial){let l=s;r.push(`${t}float inputs:clearcoat = ${l.clearcoat}`),r.push(`${t}float inputs:clearcoatRoughness = ${l.clearcoatRoughness}`),r.push(`${t}float inputs:ior = ${l.ior}`)}return` def Material "Material_${s.id}" { def Shader "PreviewSurface" { uniform token info:id = "UsdPreviewSurface" ${r.join(` `)} int inputs:useSpecularWorkflow = 0 token outputs:surface } token outputs:surface.connect = token inputs:frame:stPrimvarName = "st" def Shader "uvReader_st" { uniform token info:id = "UsdPrimvarReader_float2" token inputs:varname.connect = float2 inputs:fallback = (0.0, 0.0) float2 outputs:result } ${n.join(` `)} } `}function ye(e){return`(${e.r}, ${e.g}, ${e.b})`}function we(e){return`(${e.x}, ${e.y})`}var Ce=ae;y.push(()=>{let e=new Codec("usdz",{extension:"usdz",name:"USDZ",remember:!0,export_options:{normal_type:{type:"select",label:"Normal Map Type",default:"opengl",options:{opengl:"OpenGL",directx:"DirectX"}}},fileName(){return G()+".usdz"},async compile(a={}){if(!Project)throw new Error("No project loaded");let t=Object.assign(this.getExportOptions(),a);Project.textures.forEach(s=>{if(!s.material)return;let l=new k(s.layers,s.uuid),u=l.findTexture("normal",!0);if(!u)return;let m=$(u,t.normal_type);m&&l.saveTexture(h.normal,m)}),N();let r=new Ce,n=new _.Scene;n.name="blockbench_export",n.add(Project.model_3d);let i=await r.parse(n);return this.dispatchEvent("compile",{model:i,options:t}),Canvas.scene.add(Project.model_3d),i},async export(a={}){let t=await this.compile(a);Blockbench.export({content:t,name:this.fileName(),startpath:this.startPath(),resource_id:"usdz",type:this.name,extensions:["usdz"],savetype:"buffer"},r=>this.afterDownload(r))}});o.exportUsdz=new Action("export_usdz",{category:"file",name:"Export USDZ",description:"Exports the current model as a USDZ file",icon:"stacks",async click(){if(!e)return;let a=await e.promptExportOptions();await e.export(a)}}),o.usdz=e,MenuBar.addAction(o.exportUsdz,"file.export")});C.push(()=>{MenuBar.removeAction("file.export_usdz")});y.push(()=>{o.bbmat=new Codec("material",{name:"Blockbench Material",extension:"bbmat",remember:!1,load_filter:{extensions:["bbmat"],type:"json"},compile(){if(!Texture.selected?.material||!Texture.selected?.layers_enabled)return;let e=Texture.selected.layers.map(a=>{let t=a.channel,r=a.canvas.toDataURL();return[t,r]});return JSON.stringify({version:K,channels:Object.fromEntries(e)})},parse(e,a){return e=typeof e=="string"?JSON.parse(e):e,e.version!==K?(Blockbench.showMessageBox({title:"Invalid Blockbench Material Version",message:`The material file "${a}" is not compatible with version ${F} of the PBR plugin.`,buttons:["OK"],confirm:0,width:400,cancel:0,checkboxes:{}},()=>null),{}):e.channels},load(e,a,t){if(!Project)return;let r=this.parse(e,a.path),n=Object.keys(r);if(!n.length)throw new Error("No valid channels found in the material");let i=r[h.albedo.id]??r[n[0]];n.includes("preview")&&(i=r.preview);let s=new Texture({name:pathToName(a.name),saved:!0,particle:!1,source:i,layers_enabled:!0});s.extend({material:!0});let l=n.map(u=>{if(!(u in h))return null;let m=r[u],d=new TextureLayer({name:u,data_url:m,visible:!0},s);return d.extend({channel:u}),d}).filter(Boolean);if(!l.length)throw new Error("No valid channel layers found in the material");i||s.fromDataURL(l[0].canvas.toDataURL()),s.add().select(),l.forEach(u=>{u.addForEditing(),s.width=Math.max(s.width,u.img.width),s.height=Math.max(s.height,u.img.height)}),s.updateChangesAfterEdit()},export(){Blockbench.export({resource_id:"material",type:this.name,extensions:[this.extension],name:`${Texture.selected?.name??this.fileName??"material"}.bbmat`,startpath:this.startPath(),content:this.compile()},e=>this.afterDownload(e))}}),o.bbMatExport=new Action("export_bbmat",{icon:"stacks",name:"Save as .bbmat",category:"file",condition:{project:!0,selected:{texture:!0},method(){return Texture.selected?.material}},click(){o.bbmat?.export?.()}}),o.bbMatImport=new Action("import_bbmat",{icon:"stacks",name:"Import .bbmat",category:"file",condition:{project:!0},click(){Blockbench.import({extensions:["bbmat"],type:"json",title:"Import .bbmat",multiple:!0},e=>{o.bbmat?.load&&e.forEach(a=>{o.bbmat.load(a.content,a,!0)})})}}),o.bbmat.export_action=o.bbMatExport,Texture.prototype.menu.addAction(o.bbMatExport),MenuBar.addAction(o.bbMatImport,"file.import")});C.push(()=>{Texture.prototype.menu.removeAction("export_bbmat"),MenuBar.removeAction("file.import.import_bbmat")});var Z=class e{constructor({colors:a}){this._colors={...Object.fromEntries(Object.keys(h).map(t=>[t,h[t].default??new _.Color(4294967040)])),...a}}get colors(){return this._colors}set colors(a){this._colors={...this._colors,...a}}toString(){let a=Object.entries(this._colors).map(([t,r])=>[t,r.getHexString()]);return JSON.stringify(a)}getChannel(a){return this._colors[a]}static makeLinearColor(a){let t=Math.min(1,Math.max(0,a));return new _.Color(t,t,t).convertSRGBToLinear()}static fromSettings(){let a="#000000",t=Number(o.brushMetalnessSlider?.get()),r=Number(o.brushRoughnessSlider?.get()??1),n=(o.brushEmissiveColor?.get()??a).toString(),i=Number(o.brushHeightSlider?.get()),s=ColorPanel.get(),l={[h.albedo.id]:new _.Color(s),[h.metalness.id]:e.makeLinearColor(t),[h.roughness.id]:e.makeLinearColor(r),[h.emissive.id]:new _.Color(n??a),[h.height.id]:e.makeLinearColor(i)};return new e({colors:l})}};var Ee="materialBrushPresets",re=()=>JSON.parse(localStorage.getItem(Ee)||"{}"),ut=(e,a)=>{let t=re(),r=a??guid(),n=o.userMaterialBrushPresets?.getFormResult()??{},i={};return n.albedo&&(i.albedo=n.albedo.toString()),n.metalness&&(i.metalness=Number(n.metalness)),n.roughness&&(i.roughness=Number(n.roughness)),n.emissive&&(i.emissive=n.emissive.toString()),n.height&&(i.height=Number(n.height)),t[r]=[i,e??"New Preset",z(i)],localStorage.setItem(Ee,JSON.stringify(t)),r},Pe=({metalness:e,roughness:a,emissive:t,height:r,albedo:n})=>{e!==void 0&&o.brushMetalnessSlider?.setValue(e||0,!0),a!==void 0&&o.brushRoughnessSlider?.setValue(a??1,!0),t!==void 0&&o.brushEmissiveColor?.set(t??"#000000"),r!==void 0&&o.brushHeightSlider?.setValue(Math.max(0,Math.min(1,r??.5)),!0),n!==void 0&&ColorPanel.set(n)},W=({id:e})=>Condition({project:!0,tools:["material_brush"],method(){let a=E();return(a?.layers_enabled&&a.layers.find(({channel:t})=>t&&t===e)!==void 0)===!0}}),mt=ie.extend({name:"UserPresetsDialog",data(){return{userPresets:{},channels:h}},methods:{applyPreset(e){try{let[a,t]=this.userPresets[e],{metalness:r,roughness:n,emissive:i,height:s,albedo:l}=a;Pe({metalness:Number(r),roughness:Number(n),emissive:i.toString(),height:Number(s),albedo:l.toString()}),o.userMaterialBrushPresets?.hide(),Blockbench.showQuickMessage(`Preset "${t}" applied`,2e3)}catch{Blockbench.showQuickMessage("Failed to apply preset",2e3)}},deletePreset(e){Blockbench.showMessageBox({title:"Delete Preset",message:"Are you sure you want to delete this preset?",confirm:1,cancel:0,buttons:["Cancel","Delete"],checkboxes:{},width:400},a=>{if(a){let t=re(),r=this.userPresets[e][1]??e;delete t[e],localStorage.setItem("materialBrushPresets",JSON.stringify(t)),this.userPresets=t,Blockbench.showQuickMessage(`Preset "${r}" deleted`,2e3)}})},editPreset(e){o.userMaterialBrushPresets?.setFormValues({name:this.userPresets[e][1]??e,...this.userPresets[e][0]})},getSummary(e){return Object.entries(e).filter(([a])=>a in this.channels).map(([a,t])=>a==="albedo"||a==="emissive"?`${this.channels[a]?.label??a}: ${t}`:`${this.channels[a]?.label??a}: ${Number(t).toFixed(1)}`).join(` `)}},computed:{presets(){return Object.entries(this.userPresets)}},mounted(){this.userPresets=re()},template:`
  • {{ name }}
    {{ name }}
`});y.push(()=>{o.materialBrushStyles=Blockbench.addCSS(` .preset_list { display: grid; grid-template-columns: repeat(auto-fill, 96px); grid-gap: 8px; justify-content: start; align-items: start; margin: 0 auto; padding: 8px; } .user_preset { display: flex; justify-content: start; align-items: center; width: 100%; padding: 8px; position: relative; } .preset_title { font-size: 1em; color: var(--color-text); } .user_preset:hover .preset_title { color: var(--color-accent); } .preset_preview { display: flex; flex-direction: column; flex-wrap: nowrap; justify-content: center; align-items: center; text-align: center; } .preset_buttons { display: flex; flex-direction: row; align-items: center; font-size: 0.8em; padding: 0 4px; } .preset_channel { display: flex; flex-direction: row; align-items: center; margin: 0 8px; font-size: 0.8em; } .delete_preset { margin-left: 8px; padding: 4px; height: 24px; width: 24px; min-width: 24px; background-color: transparent; color: var(--color-text); border: none; border-radius: 100%; position: absolute; right: -8px; top: 0; filter: drop-shadow(0 0 2px var(--color-shadow)); } .delete_preset:hover { background: transparent; color: var(--color-accent); } .delete_preset .material-icons { font-size: 0.825em; } .delete_preset:hover .material-icons { color: var(--color-accent); }`),o.brushMetalnessSlider=new NumSlider("slider_brush_metalness",{category:"paint",name:"Metalness",description:"Adjust the metalness of the brush",tool_setting:"brush_metalness",settings:{min:0,max:1,step:.01,default:0},condition:()=>W(h.metalness)}),o.brushRoughnessSlider=new NumSlider("slider_brush_roughness",{category:"paint",name:"Roughness",description:"Adjust the roughness of the brush",tool_setting:"brush_roughness",settings:{min:0,max:1,step:.01,default:1},condition:()=>W(h.roughness)}),o.brushEmissiveColor=new ColorPicker("brush_emissive_color",{category:"paint",name:"Emissive",description:"Adjust the emissive color of the brush",value:"#000000",tool_setting:"brush_emissive",condition:()=>W(h.emissive)}),o.brushHeightSlider=new NumSlider("slider_brush_height",{category:"paint",name:"Height",description:"Adjust the height of the brush",tool_setting:"brush_height",settings:{min:0,max:1,step:.01,default:.5},condition:()=>W(h.height)}),o.materialBrushTool=new Tool("material_brush",{name:"Material Brush",description:"Paints across multiple texture layers",icon:"view_in_ar",paintTool:!0,cursor:"cell",category:"tools",toolbar:"brush",condition:{project:!0,selected:{texture:!0},modes:["paint"],method(){return E()?.layers_enabled??!1}},allowed_view_modes:"textured",tool_settings:{brush_metalness:0,brush_roughness:1,brush_emissive:"#000000",brush_height:.5},brush:{blend_modes:!1,shapes:!0,size:!0,softness:!0,opacity:!0,offset_even_radius:!0,floor_coordinates:!0,changePixel(e,a,t,r,{size:n,softness:i,texture:s,x:l,y:u}){let m=Z.fromSettings(),d=Object.keys(m.colors),c=Math.floor(n-i*n/100),v=t;return s.layers.forEach(g=>{if(!g.visible||!d.includes(g.channel))return;let x=m.getChannel(g.channel);if(!x)return;let f=Math.sqrt((l-e)**2+(u-a)**2),p=Math.min(1,f/c);if(l%c<=p&&u%c<=p){let b=g.ctx.getImageData(e,a,1,1).data,M=new _.Color(`rgb(${b[0]}, ${b[1]}, ${b[2]})`);x.lerp(M,1)}g.ctx.fillStyle=x.getStyle(),g.ctx.fillRect(e,a,1,1),g.selected&&(v={r:x.r*255,g:x.g*255,b:x.b*255,a:r*255})}),v}},onCanvasClick(e){Painter.startPaintToolCanvas(e,e.event)},onSelect(){Painter.updateNslideValues(),N()},click(){A()}}),o.loadBrushPreset=new Action("load_brush_preset",{icon:"stroke_full",name:"Material Brush Presets",description:"Load or save a brush preset",category:"paint",condition:{project:!0},click(){o.userMaterialBrushPresets=new Dialog("user_brush_presets",{id:"user_brush_presets",title:"Edit Material Brush",component:mt,part_order:["lines","component","form"],form:{albedo:{type:"color",label:"Albedo",value:ColorPanel.get(),toggle_enabled:!0},metalness:{type:"number",label:"Metalness",min:0,max:1,step:.01,full_width:!1,toggle_enabled:!0},roughness:{type:"number",label:"Roughness",min:0,max:1,step:.01,toggle_enabled:!0,full_width:!1},emissive:{type:"color",label:"Emissive",value:"#000000",toggle_enabled:!0},height:{type:"number",label:"Height",min:0,max:1,step:.01,toggle_enabled:!0}},onConfirm(e){Pe({metalness:Number(e.metalness??o.brushMetalnessSlider?.get()),roughness:Number(e.roughness??o.brushRoughnessSlider?.get()),emissive:(e.emissive??o.brushEmissiveColor?.get()).toString(),height:Number(e.height??o.brushHeightSlider?.get()),albedo:(e.albedo??ColorPanel.get()).toString()})},buttons:["Close","Save","Apply"],cancelIndex:0,confirmIndex:2,onButton(e,a){o.materialBrushTool?.select(),e===1&&Blockbench.textPrompt("Save Preset","New Preset",t=>{t&&(ut(t),Blockbench.showQuickMessage(`Preset "${t}" saved`,2e3))})}}).show()}}),MenuBar.addAction(o.materialBrushTool,"tools.0")});C.push(()=>{MenuBar.removeAction("tools.material_brush")});y.push(()=>{o.materialBrushPanel=new Panel("material_brush_panel",{name:"Material Brush",id:"material_brush_panel",icon:"view_in_ar",toolbars:[new Toolbar("material_brush_toolbar",{id:"material_brush_toolbar",children:["material_brush","load_brush_preset","slider_brush_metalness","slider_brush_roughness","brush_emissive_color","slider_brush_height"],name:"Material Settings"})],condition:{modes:["paint"],project:!0},component:{},expand_button:!0,growable:!1,onFold(){},onResize(){},default_side:"right",default_position:{slot:"right_bar",float_position:[0,0],float_size:[400,300],height:300,folded:!1},insert_after:"color",insert_before:"outliner"})});y.push(()=>{o.displaySettingsPanel=new Panel("display_settings",{name:"PBR Controls",id:"display_settings_panel",icon:"display_settings",toolbars:[new Toolbar("controls_toolbar",{id:"controls_toolbar",children:["toggle_pbr","correct_lights","display_settings_tone_mapping","display_settings_exposure","display_settings_reset_exposure","show_channel_select_menu"],name:"Display Settings"})],display_condition:{modes:["edit","paint","animate"],project:!0},component:{},expand_button:!0,growable:!1,onFold(){},onResize(){},default_side:"left",default_position:{slot:"left_bar",float_position:[0,0],float_size:[400,300],height:300,folded:!1},insert_after:"textures",insert_before:"color"})});var q=e=>e.visible&&e.channel&&e.channel!==B,dt=()=>{let e=R();if(e)return e.texture.layers.filter(q);let a=E();return a?a.layers_enabled?a.layers.filter(q):Texture.all.map(t=>t.layers_enabled?[...t.layers.filter(q)]:[q(t)?t:null]).flat().filter(Boolean):[]},Le=["select_texture","update_texture_selection","finish_edit","add_texture"],De=()=>{Panels.channels_panel.inside_vue.textures=dt()};y.push(()=>{o.channelsPanelStyle=Blockbench.addCSS(` .texture_channel { color: var(--color-text); flex: 1; font-size: 1em; margin: 0 0 0 auto; padding: 0 8px; text-align: right; } .texture_channel + .texture_particle_icon { padding-right: 8px; } .texture_channel_description { background-color: var(--color-back); display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; } .texture_channel_wrapper { align-items: center; background-color: var(--color-ui); border-left: 1px solid var(--color-border); display: flex; flex: 1; flex-direction: row; align-items: center; flex-wrap: nowrap; padding: 0 8px; } .texture_channel_wrapper:hover { background-color: var(--color-button); } .texture_channel_description .texture_name { flex-direction: column; flex-wrap: nowrap; color: var(--color-subtle_text); display: flex; flex: 1; justify-content: center; align-items: start; } .texture_parent { color: var(--color-subtle_text); font-size: 0.8em; } .texture_channel_description:hover .texture_channel { color: var(--color-accent); } #pbr_channel_list { display: flex; flex-direction: column; } #pbr_channel_list .texture { border-top: 1px solid var(--color-border); padding-right: 0; } `),o.channelsPanel=new Panel("channels_panel",{name:"PBR Channels",id:"channels_panel",icon:"gallery_thumbnail",condition:{project:!0,selected:{texture:!0},modes:["paint","edit"]},toolbars:[],component:{name:"ChannelsPanel",data(){return{channels:h,textures:[]}},methods:{openMenu(e){o.channelMenu?.open(e)},selectTexture(e){Modes.options.paint.select(),e.select(),e.scrollTo()},channelEnabled(e){return e.channel&&e.channel!==B&&e.channel in this.channels},getImgSrc(e){return e.img?.src??`data:image/png;base64,${e.canvas.toDataURL()}`}},template:`
  • {{ texture.name }}
    {{ texture.texture.name }}
    {{ channels[texture.channel].label }}
    {{ channels[texture.channel].icon }}
`},expand_button:!0,growable:!0,onFold(){},onResize(){},default_side:"left",default_position:{slot:"left_bar",float_position:[0,0],float_size:[400,300],height:350,folded:!0},insert_after:"layers",insert_before:"color"}),Blockbench.on(Le.join(" "),De)});C.push(()=>{Le.forEach(e=>{Blockbench.removeListener(e,De)})});(()=>{let e=()=>{y.forEach(t=>t())},a=()=>{J(),C.forEach(t=>t()),Object.entries(o).forEach(([t,r])=>{try{r?.delete()}catch(n){console.warn(`Failed to delete ${t} action:`,n)}})};BBPlugin.register("pbr_preview",{version:F,title:"PBR Tools",author:"Jason J. Gardner",description:"Create and view PBR materials in Blockbench. Export USDZ scenes and textures for Java or RenderDragon shaders.",tags:["Minecraft: Java Edition","Minecraft: Bedrock Edition","PBR"],icon:"icon.png",variant:"both",await_loading:!0,repository:"https://github.com/jasonjgardner/blockbench-plugins",has_changelog:!0,min_version:"4.10.3",onload:e,onunload:a})})();})();