DCFronted/dist/assets/TerrainGenerate-w3a7BwWs.js
2025-07-06 20:54:40 +08:00

2 lines
8.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import{J as f}from"./jszip.min-CRsa9W6H.js";import{_ as w,b as c,d as s,i as v,n as m,t as g,e as F,q as b,F as _,B as y,z as d}from"./index-DGJ6dnLh.js";const k={name:"TerrainTool",data(){return{colorFiles:[],normalFiles:[],roughnessFiles:[],generatedFiles:[],isProcessing:!1}},computed:{canProcess(){return this.colorFiles.length>0&&this.normalFiles.length>0&&this.roughnessFiles.length>0&&this.getMatchCount()>0}},methods:{onFilesSelected(o,e){const n=Array.from(e.target.files);this[o+"Files"]=n},getMatchCount(){const o=n=>n.map(i=>i.name.split(".")[0]);return o(this.colorFiles).filter(n=>o(this.normalFiles).includes(n)&&o(this.roughnessFiles).includes(n)).length},async generateTGA(){if(!(!this.canProcess||this.isProcessing)){this.isProcessing=!0,this.generatedFiles=[];try{const o=l=>Object.fromEntries(l.map(a=>[a.name.split(".")[0],a])),e=o(this.colorFiles),n=o(this.normalFiles),i=o(this.roughnessFiles),t=Object.keys(e).filter(l=>n[l]&&i[l]);for(const l of t){const a=await this.loadImage(e[l]),r=await this.loadImage(n[l]),p=await this.loadImage(i[l]),[h,u]=this.processImages(a,r,p);this.generatedFiles.push({name:`${l}_ResultColor.tga`,blob:h}),this.generatedFiles.push({name:`${l}_ResultNRM.tga`,blob:u})}}catch(o){console.error("生成过程中出错:",o),alert("处理过程中发生错误,请检查文件格式后再试。")}finally{this.isProcessing=!1}}},loadImage(o){return new Promise((e,n)=>{const i=new Image;i.onload=()=>e(i),i.onerror=n,i.src=URL.createObjectURL(o)})},processImages(o,e,n){const i=document.createElement("canvas");i.width=256,i.height=256;const t=i.getContext("2d");t.drawImage(o,0,0,256,256);const l=t.getImageData(0,0,256,256);t.clearRect(0,0,256,256),t.drawImage(n,0,0,256,256);const a=t.getImageData(0,0,256,256),r=t.createImageData(256,256);for(let u=0;u<r.data.length;u+=4)r.data[u]=l.data[u],r.data[u+1]=l.data[u+1],r.data[u+2]=l.data[u+2],r.data[u+3]=255-a.data[u];t.putImageData(r,0,0);const p=this.toTGA(t,256,256);t.clearRect(0,0,256,256),t.drawImage(e,0,0,256,256);const h=this.toTGA(t,256,256);return[p,h]},toTGA(o,e,n){const i=o.getImageData(0,0,e,n).data,t=new Uint8Array(18);t[2]=2,t[12]=e&255,t[13]=e>>8&255,t[14]=n&255,t[15]=n>>8&255,t[16]=32,t[17]=0;const l=new Uint8Array(e*n*4);let a=0;for(let r=n-1;r>=0;r--)for(let p=0;p<e;p++){const h=(r*e+p)*4;l[a++]=i[h+2],l[a++]=i[h+1],l[a++]=i[h],l[a++]=i[h+3]}return new Blob([t,l],{type:"application/octet-stream"})},async downloadZip(){if(this.generatedFiles.length!==0)try{const o=new f;for(const i of this.generatedFiles)o.file(i.name,i.blob);const e=await o.generateAsync({type:"blob"}),n=document.createElement("a");n.href=URL.createObjectURL(e),n.download="TerrainTextures.zip",n.click()}catch(o){console.error("打包下载出错:",o),alert("创建ZIP文件时出错请重试。")}},formatFileSize(o){if(o===0)return"0 Bytes";const e=1024,n=["Bytes","KB","MB","GB"],i=Math.floor(Math.log(o)/Math.log(e));return parseFloat((o/Math.pow(e,i)).toFixed(2))+" "+n[i]}}},x={class:"terrain-tool-container"},I={class:"upload-section"},C={class:"upload-label"},M={class:"upload-content"},B={key:0},P={key:1},T={class:"upload-label"},G={class:"upload-content"},A={key:0},z={key:1},R={class:"upload-label"},D={class:"upload-content"},S={key:0},j={key:1},N={class:"status-section"},Z={class:"status-card"},L={class:"status-item"},U={class:"status-value"},O={class:"status-item"},V={class:"status-value"},E={class:"status-item"},J={class:"status-value"},K={class:"status-item highlight"},q={class:"status-value"},H={class:"action-buttons"},Q=["disabled"],W={key:0},X={key:1,class:"processing"},Y=["disabled"],$={key:0,class:"results-section"},ee={class:"results-grid"},se={class:"file-name"},te={class:"file-size"},le={key:1,class:"instructions"};function oe(o,e,n,i,t,l){return d(),c("div",x,[e[18]||(e[18]=s("div",{class:"header"},[s("h1",null,"地形纹理合成工具"),s("p",{class:"subtitle"},"将颜色、法线和粗糙度贴图合成为地形使用的TGA格式")],-1)),s("div",I,[s("div",{class:m(["upload-card",{active:t.colorFiles.length>0}])},[s("label",C,[s("input",{type:"file",multiple:"",accept:"image/*",onChange:e[0]||(e[0]=a=>l.onFilesSelected("color",a))},null,32),s("div",M,[e[5]||(e[5]=s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[s("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2",ry:"2"}),s("circle",{cx:"8.5",cy:"8.5",r:"1.5"}),s("polyline",{points:"21 15 16 10 5 21"})],-1)),e[6]||(e[6]=s("h3",null,"颜色贴图",-1)),t.colorFiles.length===0?(d(),c("p",B,"点击或拖放文件到这里")):(d(),c("p",P,g(t.colorFiles.length)+" 个文件已选择",1))])])],2),s("div",{class:m(["upload-card",{active:t.normalFiles.length>0}])},[s("label",T,[s("input",{type:"file",multiple:"",accept:"image/*",onChange:e[1]||(e[1]=a=>l.onFilesSelected("normal",a))},null,32),s("div",G,[e[7]||(e[7]=s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[s("path",{d:"M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"})],-1)),e[8]||(e[8]=s("h3",null,"法线贴图(OpenGL格式)",-1)),t.normalFiles.length===0?(d(),c("p",A,"点击或拖放文件到这里")):(d(),c("p",z,g(t.normalFiles.length)+" 个文件已选择",1))])])],2),s("div",{class:m(["upload-card",{active:t.roughnessFiles.length>0}])},[s("label",R,[s("input",{type:"file",multiple:"",accept:"image/*",onChange:e[2]||(e[2]=a=>l.onFilesSelected("roughness",a))},null,32),s("div",D,[e[9]||(e[9]=F('<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" data-v-860e1977><circle cx="12" cy="12" r="10" data-v-860e1977></circle><path d="M8 14s1.5 2 4 2 4-2 4-2" data-v-860e1977></path><line x1="9" y1="9" x2="9.01" y2="9" data-v-860e1977></line><line x1="15" y1="9" x2="15.01" y2="9" data-v-860e1977></line></svg><h3 data-v-860e1977>粗糙度贴图</h3>',2)),t.roughnessFiles.length===0?(d(),c("p",S,"点击或拖放文件到这里")):(d(),c("p",j,g(t.roughnessFiles.length)+" 个文件已选择",1))])])],2)]),s("div",N,[s("div",Z,[s("div",L,[e[10]||(e[10]=s("span",{class:"status-label"},"颜色贴图:",-1)),s("span",U,g(t.colorFiles.length),1)]),s("div",O,[e[11]||(e[11]=s("span",{class:"status-label"},"法线贴图:",-1)),s("span",V,g(t.normalFiles.length),1)]),s("div",E,[e[12]||(e[12]=s("span",{class:"status-label"},"粗糙度贴图:",-1)),s("span",J,g(t.roughnessFiles.length),1)]),s("div",K,[e[13]||(e[13]=s("span",{class:"status-label"},"可匹配文件组:",-1)),s("span",q,g(l.getMatchCount()),1)])])]),s("div",H,[s("button",{class:m(["btn generate-btn",{disabled:!l.canProcess}]),onClick:e[3]||(e[3]=(...a)=>l.generateTGA&&l.generateTGA(...a)),disabled:!l.canProcess},[t.isProcessing?(d(),c("span",X,e[14]||(e[14]=[s("svg",{class:"spinner",viewBox:"0 0 50 50"},[s("circle",{class:"path",cx:"25",cy:"25",r:"20",fill:"none","stroke-width":"5"})],-1),b(" 处理中... ")]))):(d(),c("span",W,"生成地形TGA文件"))],10,Q),s("button",{class:m(["btn download-btn",{disabled:t.generatedFiles.length===0}]),onClick:e[4]||(e[4]=(...a)=>l.downloadZip&&l.downloadZip(...a)),disabled:t.generatedFiles.length===0}," 打包下载ZIP ",10,Y)]),t.generatedFiles.length>0?(d(),c("div",$,[e[16]||(e[16]=s("h2",null,"生成结果",-1)),s("div",ee,[(d(!0),c(_,null,y(t.generatedFiles,(a,r)=>(d(),c("div",{key:r,class:"result-item"},[e[15]||(e[15]=s("div",{class:"file-icon"},[s("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},[s("path",{d:"M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"}),s("polyline",{points:"13 2 13 9 20 9"})])],-1)),s("div",se,g(a.name),1),s("div",te,g(l.formatFileSize(a.blob.size)),1)]))),128))])])):v("",!0),t.generatedFiles.length===0&&!l.canProcess?(d(),c("div",le,e[17]||(e[17]=[s("h3",null,"使用说明",-1),s("ol",null,[s("li",null,"上传颜色、法线和粗糙度贴图PNG/JPG格式"),s("li",null,"确保每组贴图有相同的文件名(仅扩展名不同)"),s("li",null,'点击"生成地形TGA文件"按钮'),s("li",null,"处理完成后下载ZIP包")],-1),s("p",{class:"note"},"注意:系统会自动匹配文件名相同的贴图进行合成处理。",-1)]))):v("",!0)])}const ae=w(k,[["render",oe],["__scopeId","data-v-860e1977"]]);export{ae as default};