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
|
|
}
|
|
}
|
|
|
|
|