329 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
| 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<number> = [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<string, NewType> = new Map<string, Img>();
 | |
|     //NPK的本地路径 对应的 NPK名字
 | |
|     private Npk_URL_Table: Map<string, string> = new Map<string, string>();
 | |
| 
 | |
| 
 | |
| 
 | |
|     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();
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     NpkHasImg: Map<string, Array<string>> = new Map<string, Array<string>>();
 | |
|     LoadNpk(): void {
 | |
|         this.BundleObject.loadDir("", BufferAsset, (err, contents: Array<BufferAsset>) => {
 | |
|             //记录NPK文件数量
 | |
|             this.NpkCount = contents.length;
 | |
|             console.log(this.NpkCount);
 | |
| 
 | |
|             contents.forEach(content => {
 | |
|                 let ImgArr: Array<string> = [];
 | |
|                 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<NpkInfo>(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++) {
 | |
|                         ImgArr.push(ImgList[i].Path);
 | |
|                         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.NpkHasImg.set(content.name, ImgArr);
 | |
|                 }
 | |
| 
 | |
|                 //完成一个加载
 | |
|                 this.LoadNpkCount = this.LoadNpkCount + 1;
 | |
|                 //把本地路径和NPK名称挂钩一下
 | |
|                 this.Npk_URL_Table.set(content.nativeUrl, content.name);
 | |
|                 //载入完成以后需要释放
 | |
|                 assetManager.releaseAsset(content);
 | |
|                 //加载完成
 | |
|                 if (this.LoadNpkCount == this.NpkCount) {
 | |
|                     this.initSuccess();
 | |
|                 }
 | |
|             });
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     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;
 | |
|     }
 | |
| 
 | |
|     LoadNpkImgCount = 0;
 | |
|     //读取Npk数据
 | |
|     ReadNpkFile(npkname: string, func: Function): number {
 | |
|         let ImgArr = this.NpkHasImg.get(npkname);
 | |
| 
 | |
|         ImgArr.forEach(imgname => {
 | |
|             let ImgObj: Img = this.Map_Img.get(imgname);
 | |
|             if (ImgObj) {
 | |
|                 //没有图片数据 需要加载
 | |
|                 if (ImgObj.Png_List == null) {
 | |
|                     //加载Img进内存
 | |
|                     this.LoadImgToMem(ImgObj, func);
 | |
|                 }
 | |
|                 else {
 | |
|                     func(ImgObj);
 | |
|                 }
 | |
|             }
 | |
|         });
 | |
|         return ImgArr.length;
 | |
|     }
 | |
| 
 | |
|     ReleaseNpkTable(p: Img): void {
 | |
|         // implementation
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 |