import { _decorator, Asset, assetManager, BufferAsset, Component, error, Node, resources, TextAsset, Texture2D } from 'cc'; import { ReadStream } from '../Tool/ReadStream'; import * as pako from 'pako'; import { Img, ImgInfo, NpkInfo } from '../GlobalInterface/GlobalInterface'; const { ccclass, property } = _decorator; type NewType = Img; @ccclass('ImagePack') export class ImagePack extends Component { //全局单例类 private static instance: ImagePack; private constructor() { super(); } public static getInstance(): ImagePack { if (!ImagePack.instance) { ImagePack.instance = new ImagePack(); } return ImagePack.instance; } Key: Array = [112, 117, 99, 104, 105, 107, 111, 110, 64, 110, 101, 111, 112, 108, 101, 32, 100, 117, 110, 103, 101, 111, 110, 32, 97, 110, 100, 32, 102, 105, 103, 104, 116, 101, 114, 32, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 68, 78, 70, 0]; //NPK加载完成后的回调函数 LoadCallBack = undefined; //NPK文件数量 private NpkCount = 0; //已加载NPK文件数量 private LoadNpkCount = 0; //Img的map Key:img路径 Value:Img结构体 private Map_Img: Map = new Map(); //NPK的本地路径 对应的 NPK名字 private Npk_URL_Table: Map = new Map(); start() { } update(deltaTime: number) { } initSuccess(): void { if (this.LoadCallBack) this.LoadCallBack(); } BundleObject; init(Func: Function): void { //储存回调 this.LoadCallBack = Func; assetManager.loadBundle('ImagePacks', (err, bundle) => { this.BundleObject = bundle; this.LoadNpk(); }); } LoadNpk(): void { this.BundleObject.loadDir("", BufferAsset, (err, contents: Array) => { //记录NPK文件数量 this.NpkCount = contents.length; console.log(this.NpkCount); contents.forEach(content => { const Buf = new Uint8Array(content.buffer()); const Ro = new ReadStream(Buf); //文件头 const Header = Ro.GetString(); if (Header == "NeoplePack_Bill") { //读取img数量 const ImageCount = Ro.GetInt(); let ImgList: NpkInfo[] = new Array(ImageCount); for (let i = 0; i < ImageCount; i++) { ImgList[i] = { Offset: Ro.GetInt(), Length: Ro.GetInt(), Path: Ro.ReadInfo(this.Key), } } for (let i = 0; i < ImageCount; i++) { let Buf: Img = { ImgOffset: ImgList[i].Offset, ImgSize: ImgList[i].Length, Img_Index: i, BelongsFile: content.nativeUrl, ImgName: ImgList[i].Path, Png_List: null, Png_Count: 0 } this.Map_Img.set(ImgList[i].Path, Buf); } } //完成一个加载 this.LoadNpkCount = this.LoadNpkCount + 1; //加载完成 if (this.LoadNpkCount == this.NpkCount) { this.initSuccess(); } //把本地路径和NPK名称挂钩一下 this.Npk_URL_Table.set(content.nativeUrl, content.name); //载入完成以后需要释放 assetManager.releaseAsset(content); }); }); } LoadImgToMem(ImgObj: Img, func: Function) { //获取路径 如果不存在直接返回 const Path = this.Npk_URL_Table.get(ImgObj.BelongsFile); if (!Path) return; this.BundleObject.load(Path, BufferAsset, (err, content) => { const Buf = new Uint8Array(content.buffer()); const Ro = new ReadStream(Buf); Ro.Seekg(ImgObj.ImgOffset); //Img头 const Header = Ro.GetString(); //开始读图片 if (Header == "Neople Img File") { //索引表大小 const TableLength = Ro.GetLongInt(); //img 版本 4字节 const ver = Ro.GetInt(); //img 帧数 const IndexCount = Ro.GetInt(); ImgObj.Png_Count = IndexCount; let PngArr: ImgInfo[] = []; for (let index = 0; index < IndexCount; index++) { let ImgBuf: ImgInfo = {}; //图片格式 ImgBuf.Type = Ro.GetInt(); if (ImgBuf.Type == 17) { //引用贴图 const IndexBuf = Ro.GetInt(); ImgBuf.Offset = PngArr[index - 1].Offset; ImgBuf.Type = 17; ImgBuf.QuoteIndex = IndexBuf; ImgBuf.Size = PngArr[index - 1].Size; PngArr.push(ImgBuf); continue; } //压缩类型 ImgBuf.CmpType = Ro.GetInt(); //宽度 ImgBuf.Width = Ro.GetInt(); //高度 ImgBuf.Height = Ro.GetInt(); //大小 ImgBuf.Size = Ro.GetInt(); //Xpos ImgBuf.Xpos = Ro.GetInt(); //Ypos ImgBuf.Ypos = Ro.GetInt(); //帧域X ImgBuf.FrameXpos = Ro.GetInt(); //帧域Y ImgBuf.FrameYpos = Ro.GetInt(); if (index == 0) { ImgBuf.Offset = 0 + ImgObj.ImgOffset + Number(TableLength) + 32; } else { ImgBuf.Offset = PngArr[index - 1].Offset + PngArr[index - 1].Size; } PngArr.push(ImgBuf); } for (let index = 0; index < IndexCount; index++) { let PngObj = PngArr[index]; //引用贴图 if (PngObj.Type == 17) { const QuoteIndexBuf = PngObj.QuoteIndex; PngArr[index] = PngArr[QuoteIndexBuf]; } } for (let index = 0; index < IndexCount; index++) { let PngObj = PngArr[index]; Ro.Seekg(PngObj.Offset); //PNG压缩原始数据 let DataBuf = Ro.GetBufferByLength(PngObj.Size); //图片数据应有大小 let PngBufSize = PngObj.Width * PngObj.Height * 4; // 使用pako 解压 zlib的inflate函数解压缩数据 let Bsf; try { Bsf = pako.inflate(DataBuf); } catch (error) { Bsf = DataBuf; } if (PngObj.Type != 16) { let PngByteSize = Bsf.length * 2; PngObj.PNGdata = new Uint8Array(PngByteSize); for (let e = 0; e < PngByteSize; e += 4) { let BarBuf = new Uint8Array(2); let Pos = (e / 4) * 2; BarBuf[0] = Bsf[Pos]; BarBuf[1] = Bsf[Pos + 1]; this.ReadColor(BarBuf, PngObj, e); } } else { PngObj.PNGdata = new Uint8Array(Bsf.length); for (let index = 0; index < Bsf.length; index += 4) { PngObj.PNGdata[index] = Bsf[index + 2]; PngObj.PNGdata[index + 1] = Bsf[index + 1]; PngObj.PNGdata[index + 2] = Bsf[index]; PngObj.PNGdata[index + 3] = Bsf[index + 3]; } } } ImgObj.Png_List = PngArr; func(ImgObj); } //载入完成以后需要释放 assetManager.releaseAsset(content); }); } ReadColor(Bar: Uint8Array, PngObj: ImgInfo, Offset: number) { let a: number = 0; let r: number = 0; let g: number = 0; let b: number = 0; switch (PngObj.Type) { case 0x0e: a = Bar[1] >> 7; r = (Bar[1] >> 2) & 0x1f; g = (Bar[0] >> 5) | ((Bar[1] & 3) << 3); b = Bar[0] & 0x1f; a = a * 0xff; r = (r << 3) | (r >> 2); g = (g << 3) | (g >> 2); b = (b << 3) | (b >> 2); break; case 0x0f: a = Bar[1] & 0xf0; r = (Bar[1] & 0xf) << 4; g = Bar[0] & 0xf0; b = (Bar[0] & 0xf) << 4; break; default: console.log(PngObj.Type); break; } PngObj.PNGdata[Offset + 0] = r; PngObj.PNGdata[Offset + 1] = g; PngObj.PNGdata[Offset + 2] = b; PngObj.PNGdata[Offset + 3] = a; } //读取Img数据 ReadNpkTable(imgname: string, func: Function): boolean { let ImgObj: Img = this.Map_Img.get(imgname); if (ImgObj) { //没有图片数据 需要加载 if (ImgObj.Png_List == null) { //加载Img进内存 this.LoadImgToMem(ImgObj, func); return true; } else { func(ImgObj); return true; } } return false; } ReleaseNpkTable(p: Img): void { // implementation } }