建档
This commit is contained in:
397
source/Asset/AnimationStruct.cpp
Normal file
397
source/Asset/AnimationStruct.cpp
Normal file
@@ -0,0 +1,397 @@
|
||||
#include "Asset/AnimationStruct.h"
|
||||
#include "Asset/ScriptData.h"
|
||||
|
||||
namespace AniScriptParser
|
||||
{
|
||||
|
||||
std::string Get_Ani_Flag(int data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case 0:
|
||||
return "LOOP";
|
||||
case 1:
|
||||
return "SHADOW";
|
||||
case 3:
|
||||
return "COORD";
|
||||
case 7:
|
||||
return "IMAGE_RATE";
|
||||
case 8:
|
||||
return "IMAGE_ROTATE";
|
||||
case 9:
|
||||
return "RGBA";
|
||||
case 10:
|
||||
return "INTERPOLATION";
|
||||
case 11:
|
||||
return "GRAPHIC_EFFECT";
|
||||
case 12:
|
||||
return "DELAY";
|
||||
case 13:
|
||||
return "DAMAGE_TYPE";
|
||||
case 14:
|
||||
return "DAMAGE_BOX";
|
||||
case 15:
|
||||
return "ATTACK_BOX";
|
||||
case 16:
|
||||
return "PLAY_SOUND";
|
||||
case 17:
|
||||
return "PRELOAD";
|
||||
case 18:
|
||||
return "SPECTRUM";
|
||||
case 23:
|
||||
return "SET_FLAG";
|
||||
case 24:
|
||||
return "FLIP_TYPE";
|
||||
case 25:
|
||||
return "LOOP_START";
|
||||
case 26:
|
||||
return "LOOP_END";
|
||||
case 27:
|
||||
return "CLIP";
|
||||
case 28:
|
||||
return "OPERATION";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string Get_Ani_Effect_Type(int data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case 0:
|
||||
return "NONE";
|
||||
case 1:
|
||||
return "DODGE";
|
||||
case 2:
|
||||
return "LINEARDODGE";
|
||||
case 3:
|
||||
return "DARK";
|
||||
case 4:
|
||||
return "XOR";
|
||||
case 5:
|
||||
return "MONOCHROME";
|
||||
case 6:
|
||||
return "SPACEDISTORT";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
std::string Get_Ani_Flip_Type(int data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case 1:
|
||||
return "HORIZON";
|
||||
case 2:
|
||||
return "VERTICAL";
|
||||
case 3:
|
||||
return "ALL";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
std::string Get_Ani_Damage_Type(int data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case 0:
|
||||
return "NORMAL";
|
||||
case 1:
|
||||
return "SUPERARMOR";
|
||||
case 2:
|
||||
return "UNBREAKABLE";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
AlsInfo StructAlsInfo(ScriptData &Data)
|
||||
{
|
||||
AlsInfo Info;
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[use animation]")
|
||||
{
|
||||
std::string AniPath = Data.Get();
|
||||
std::string AniKey = Data.Get();
|
||||
Info.AniList[AniKey].path = Tool_toLowerCase(AniPath);
|
||||
}
|
||||
else if (Segment == "[none effect add]")
|
||||
{
|
||||
std::vector<int> AniLayer = {std::stoi(Data.Get()), std::stoi(Data.Get())};
|
||||
std::string AniKey = Data.Get();
|
||||
Info.AniList[AniKey].layer = AniLayer;
|
||||
}
|
||||
else if (Segment == "[add]")
|
||||
{
|
||||
std::vector<int> AniLayer = {std::stoi(Data.Get()), std::stoi(Data.Get())};
|
||||
std::string AniKey = Data.Get();
|
||||
Info.AniList[AniKey].layer = AniLayer;
|
||||
}
|
||||
}
|
||||
return Info;
|
||||
};
|
||||
|
||||
AniInfo StructAniInfo(ScriptData &Data)
|
||||
{
|
||||
AniInfo Info;
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[image]")
|
||||
{
|
||||
}
|
||||
}
|
||||
return Info;
|
||||
};
|
||||
|
||||
/////////以下是读取逻辑
|
||||
AniInfo StructAniInfo(Blob blob)
|
||||
{
|
||||
AniInfo Info;
|
||||
int Frame_Max = blob.getUShort();
|
||||
int Img_Count = blob.getUShort();
|
||||
|
||||
// Img的路径读取 存入数组
|
||||
for (int i = 0; i < Img_Count; i++)
|
||||
{
|
||||
int Buf = blob.getInt();
|
||||
std::string ImgPath = "sprite/" + blob.getString(Buf);
|
||||
Info.Img_List.push_back(ImgPath);
|
||||
}
|
||||
|
||||
// Ani头部标签数量
|
||||
int Ani_H_Item_Count = blob.getUShort();
|
||||
// 处理标签
|
||||
for (int i = 0; i < Ani_H_Item_Count; i++)
|
||||
{
|
||||
int Type = blob.getUShort();
|
||||
switch (Type)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
std::string Key = AniScriptParser::Get_Ani_Flag(Type);
|
||||
int Value = blob.getByte();
|
||||
Info.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
case 28:
|
||||
{
|
||||
std::string Key = AniScriptParser::Get_Ani_Flag(Type);
|
||||
int Value = blob.getUShort();
|
||||
Info.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
blob.getByte();
|
||||
blob.getInt();
|
||||
blob.getInt();
|
||||
blob.getInt();
|
||||
blob.get256();
|
||||
blob.get256();
|
||||
blob.get256();
|
||||
blob.get256();
|
||||
blob.getUShort();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 读取每一个Img
|
||||
for (int i = 0; i < Frame_Max; i++)
|
||||
{
|
||||
AniFrame FrameObject;
|
||||
|
||||
// 碰撞框项目数量
|
||||
int Ani_Box_Item_Count = blob.getUShort();
|
||||
for (int j = 0; j < Ani_Box_Item_Count; j++)
|
||||
{
|
||||
int Box_Type = blob.getUShort();
|
||||
std::vector<int> D_Box_b;
|
||||
for (int k = 0; k < 6; k++)
|
||||
{
|
||||
D_Box_b.push_back(blob.getInt());
|
||||
}
|
||||
if (Box_Type == 15)
|
||||
FrameObject.AttackBox.push_back(D_Box_b);
|
||||
else
|
||||
FrameObject.DamageBox.push_back(D_Box_b);
|
||||
}
|
||||
|
||||
// 调用的第几个Img
|
||||
int Index_Buf = blob.getShort();
|
||||
if (Index_Buf != -1)
|
||||
{
|
||||
FrameObject.Img_Path = Tool_toLowerCase(Info.Img_List[Index_Buf]);
|
||||
FrameObject.Img_Index = blob.getUShort();
|
||||
}
|
||||
else
|
||||
{
|
||||
FrameObject.Img_Path = "";
|
||||
FrameObject.Img_Index = 0;
|
||||
}
|
||||
|
||||
// 坐标
|
||||
FrameObject.Img_Pos = VecPos{blob.getInt(), blob.getInt()};
|
||||
|
||||
// Img中的项目数量
|
||||
int Img_Flag_Count = blob.getUShort();
|
||||
for (int j = 0; j < Img_Flag_Count; j++)
|
||||
{
|
||||
int Img_Flag_Type = blob.getUShort();
|
||||
std::string Key;
|
||||
int Value;
|
||||
switch (Img_Flag_Type)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 10:
|
||||
{
|
||||
Key = AniScriptParser::Get_Ani_Flag(Img_Flag_Type);
|
||||
Value = blob.getByte();
|
||||
FrameObject.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
Key = "COORD";
|
||||
Value = blob.getUShort();
|
||||
FrameObject.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
Key = "PRELOAD";
|
||||
Value = 1;
|
||||
FrameObject.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
Key = "IMAGE_RATE";
|
||||
VecFPos pos{
|
||||
blob.getFloat(),
|
||||
blob.getFloat()};
|
||||
FrameObject.Flag.emplace(Key, pos);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
Key = "IMAGE_ROTATE";
|
||||
float RateBuffer = blob.getFloat();
|
||||
FrameObject.Flag.emplace(Key, RateBuffer);
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
Key = "RGBA";
|
||||
std::vector<int> RGBA = {
|
||||
(int)blob.get256(),
|
||||
(int)blob.get256(),
|
||||
(int)blob.get256(),
|
||||
(int)blob.get256()};
|
||||
FrameObject.Flag.emplace(Key, RGBA);
|
||||
break;
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
int Effect_Type = blob.getUShort();
|
||||
Key = "GRAPHIC_EFFECT_" + AniScriptParser::Get_Ani_Effect_Type(Effect_Type);
|
||||
std::vector<float> effect;
|
||||
switch (Effect_Type)
|
||||
{
|
||||
case 5:
|
||||
{
|
||||
effect.push_back(blob.get256());
|
||||
effect.push_back(blob.get256());
|
||||
effect.push_back(blob.get256());
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
effect.push_back(blob.get256());
|
||||
effect.push_back(blob.get256());
|
||||
break;
|
||||
}
|
||||
}
|
||||
FrameObject.Flag.emplace(Key, effect);
|
||||
break;
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
Value = blob.getInt();
|
||||
FrameObject.Delay = Value;
|
||||
break;
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
Key = "DAMAGE_TYPE";
|
||||
std::string DTYPE = AniScriptParser::Get_Ani_Damage_Type(blob.getUShort());
|
||||
FrameObject.Flag.emplace(Key, DTYPE);
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
int SoundTempSize = blob.getInt();
|
||||
Key = "PLAY_SOUND";
|
||||
std::string sound = blob.getString(SoundTempSize);
|
||||
FrameObject.Flag.emplace(Key, sound);
|
||||
break;
|
||||
}
|
||||
case 23:
|
||||
{
|
||||
Key = "SET_FLAG";
|
||||
Value = blob.getInt();
|
||||
FrameObject.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 24:
|
||||
{
|
||||
Key = "FLIP_TYPE";
|
||||
std::string FTYPEValue = AniScriptParser::Get_Ani_Flip_Type(blob.getUShort());
|
||||
FrameObject.Flag.emplace(Key, FTYPEValue);
|
||||
break;
|
||||
}
|
||||
case 25:
|
||||
{
|
||||
Key = "LOOP_START";
|
||||
FrameObject.Flag.emplace(Key, 1);
|
||||
break;
|
||||
}
|
||||
case 26:
|
||||
{
|
||||
Key = "LOOP_END";
|
||||
Value = blob.getInt();
|
||||
FrameObject.Flag.emplace(Key, Value);
|
||||
break;
|
||||
}
|
||||
case 27:
|
||||
{
|
||||
Key = "CLIP";
|
||||
std::vector<int> ClipArr{
|
||||
blob.getShort(),
|
||||
blob.getShort(),
|
||||
blob.getShort(),
|
||||
blob.getShort(),
|
||||
};
|
||||
FrameObject.Flag.emplace(Key, ClipArr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Info.Frame.push_back(FrameObject);
|
||||
}
|
||||
return Info;
|
||||
}
|
||||
};
|
||||
58
source/Asset/AnimationStruct.h
Normal file
58
source/Asset/AnimationStruct.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <unordered_map>
|
||||
#include <SDL.h>
|
||||
#include "Tool/Blob.hpp"
|
||||
#include "Tool/Tool_String.h"
|
||||
#include "Tool/Common.h"
|
||||
|
||||
class ScriptData;
|
||||
namespace AniScriptParser
|
||||
{
|
||||
using AniFlag = std::variant<
|
||||
int,
|
||||
float,
|
||||
VecPos,
|
||||
VecFPos,
|
||||
std::string,
|
||||
std::vector<int>,
|
||||
std::vector<float>>;
|
||||
struct AniFrame
|
||||
{
|
||||
std::string Img_Path; // img路径
|
||||
int Img_Index; // img索引
|
||||
VecPos Img_Pos; // img位置
|
||||
std::vector<std::vector<int>> AttackBox; // 攻击框
|
||||
std::vector<std::vector<int>> DamageBox; // 受击框
|
||||
std::unordered_map<std::string, AniFlag> Flag; // Frame特效数据
|
||||
int Delay; // 延迟
|
||||
};
|
||||
struct AniInfo
|
||||
{
|
||||
std::vector<std::string> Img_List; // img列表
|
||||
std::vector<AniFrame> Frame; // ani列表
|
||||
std::unordered_map<std::string, AniFlag> Flag; // ani特效数据
|
||||
};
|
||||
|
||||
struct AlsAniInfo
|
||||
{
|
||||
std::string path;
|
||||
std::vector<int> layer;
|
||||
};
|
||||
struct AlsInfo
|
||||
{
|
||||
std::unordered_map<std::string, AlsAniInfo> AniList; // Ani列表
|
||||
};
|
||||
|
||||
// 工具函数
|
||||
std::string Get_Ani_Flag(int data);
|
||||
std::string Get_Ani_Effect_Type(int data);
|
||||
std::string Get_Ani_Flip_Type(int data);
|
||||
std::string Get_Ani_Damage_Type(int data);
|
||||
|
||||
// Ani脚本的读取逻辑
|
||||
AniInfo StructAniInfo(Blob blob);
|
||||
AlsInfo StructAlsInfo(ScriptData &blob);
|
||||
};
|
||||
48
source/Asset/AssetManager.cpp
Normal file
48
source/Asset/AssetManager.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "AssetManager.h"
|
||||
#include "Asset/Asset_Script.h"
|
||||
|
||||
AssetManager::AssetManager()
|
||||
{
|
||||
}
|
||||
AssetManager::~AssetManager()
|
||||
{
|
||||
}
|
||||
|
||||
AniScriptParser::AniInfo AssetManager::StructAniInfo(std::string path)
|
||||
{
|
||||
std::vector<BYTE> Data = Asset_Script::GetInstance().GetFileContentByte(path);
|
||||
if (Data.size() > 0)
|
||||
{
|
||||
Blob blob(Data);
|
||||
return AniScriptParser::StructAniInfo(blob);
|
||||
}
|
||||
SDL_LogError(0, "Ani加载失败 Error : %s", path.c_str());
|
||||
return AniScriptParser::AniInfo();
|
||||
}
|
||||
|
||||
AniScriptParser::AlsInfo AssetManager::StructAlsInfo(std::string path)
|
||||
{
|
||||
std::vector<BYTE> Data = Asset_Script::GetInstance().GetFileContentByte(path);
|
||||
if (Data.size() > 0)
|
||||
{
|
||||
ScriptData Pvf;
|
||||
Pvf.Init(Data, path);
|
||||
AniScriptParser::AlsInfo Info = AniScriptParser::StructAlsInfo(Pvf);
|
||||
return Info;
|
||||
}
|
||||
SDL_LogError(0, "Als加载失败 Error : %s", path.c_str());
|
||||
return AniScriptParser::AlsInfo();
|
||||
}
|
||||
|
||||
ScriptData AssetManager::GetScriptInfo(std::string path)
|
||||
{
|
||||
std::vector<BYTE> Data = Asset_Script::GetInstance().GetFileContentByte(path);
|
||||
if (Data.size() > 0)
|
||||
{
|
||||
ScriptData Pvf;
|
||||
Pvf.Init(Data, path);
|
||||
return Pvf;
|
||||
}
|
||||
SDL_LogError(0, "Script加载失败 Error : %s", path.c_str());
|
||||
return ScriptData();
|
||||
}
|
||||
29
source/Asset/AssetManager.h
Normal file
29
source/Asset/AssetManager.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
#include "Asset/AnimationStruct.h" //Ani结构
|
||||
#include "Asset/ScriptData.h"
|
||||
class AssetManager
|
||||
{
|
||||
|
||||
public:
|
||||
AssetManager(const AssetManager &) = delete;
|
||||
AssetManager &operator=(const AssetManager &) = delete;
|
||||
AssetManager(AssetManager &&) = delete;
|
||||
AssetManager &operator=(AssetManager &&) = delete;
|
||||
// 全局访问点
|
||||
static AssetManager &GetInstance()
|
||||
{
|
||||
static AssetManager instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
AssetManager(/* args */);
|
||||
~AssetManager();
|
||||
|
||||
public:
|
||||
// 构造Ani结构体
|
||||
AniScriptParser::AniInfo StructAniInfo(std::string path);
|
||||
AniScriptParser::AlsInfo StructAlsInfo(std::string path);
|
||||
// Script读取体
|
||||
ScriptData GetScriptInfo(std::string path);
|
||||
};
|
||||
246
source/Asset/Asset_ImagePack.cpp
Normal file
246
source/Asset/Asset_ImagePack.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "Asset_ImagePack.h"
|
||||
|
||||
Asset_ImagePack::Asset_ImagePack()
|
||||
{
|
||||
}
|
||||
Asset_ImagePack::~Asset_ImagePack()
|
||||
{
|
||||
}
|
||||
|
||||
void Asset_ImagePack::Init()
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
std::string path = "ImagePacks2/";
|
||||
dir = opendir(path.c_str());
|
||||
|
||||
while ((ent = readdir(dir)))
|
||||
{
|
||||
// 跳过.和..目录
|
||||
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
std::string RealPath = path + ent->d_name;
|
||||
Ifstream_NPK Fs;
|
||||
Fs.open(RealPath.c_str(), std::ios::in | std::ios::binary);
|
||||
if (Fs.is_open())
|
||||
{
|
||||
std::string Header = Fs.ReadString();
|
||||
// 如果是NPK
|
||||
if (Header.find("NeoplePack_Bill") != std::string::npos)
|
||||
{
|
||||
// 读取img数量
|
||||
int ImageCount = Fs.ReadInt();
|
||||
// 读取头
|
||||
NpkInfo *ImgList = new NpkInfo[ImageCount];
|
||||
for (int i = 0; i < ImageCount; i++)
|
||||
{
|
||||
ImgList[i].Offset = Fs.ReadInt();
|
||||
ImgList[i].Length = Fs.ReadInt();
|
||||
ImgList[i].Path = Fs.ReadInfo();
|
||||
}
|
||||
for (int i = 0; i < ImageCount; i++)
|
||||
{
|
||||
IMG img;
|
||||
img.imgOffset = ImgList[i].Offset;
|
||||
img.imgSize = ImgList[i].Length;
|
||||
img.img_index = i;
|
||||
img.lpBelongsFile = ent->d_name;
|
||||
img.lpImgName = ImgList[i].Path;
|
||||
img.lp_lplist = NULL;
|
||||
img.png_sum = 0;
|
||||
|
||||
map_npk.insert(make_pair(img.lpImgName, img));
|
||||
}
|
||||
// 销毁
|
||||
delete[] ImgList;
|
||||
}
|
||||
}
|
||||
Fs.close();
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void Asset_ImagePack::ParseColor(BYTE *Tab, int Type, BYTE *SaveByte, int Offset)
|
||||
{
|
||||
BYTE a = 0;
|
||||
BYTE r = 0;
|
||||
BYTE g = 0;
|
||||
BYTE b = 0;
|
||||
switch (Type)
|
||||
{
|
||||
case 0x0e:
|
||||
a = (BYTE)(Tab[1] >> 7);
|
||||
r = (BYTE)((Tab[1] >> 2) & 0x1f);
|
||||
g = (BYTE)((Tab[0] >> 5) | ((Tab[1] & 3) << 3));
|
||||
b = (BYTE)(Tab[0] & 0x1f);
|
||||
a = (BYTE)(a * 0xff);
|
||||
r = (BYTE)((r << 3) | (r >> 2));
|
||||
g = (BYTE)((g << 3) | (g >> 2));
|
||||
b = (BYTE)((b << 3) | (b >> 2));
|
||||
break;
|
||||
case 0x0f:
|
||||
a = (BYTE)(Tab[1] & 0xf0);
|
||||
r = (BYTE)((Tab[1] & 0xf) << 4);
|
||||
g = (BYTE)(Tab[0] & 0xf0);
|
||||
b = (BYTE)((Tab[0] & 0xf) << 4);
|
||||
break;
|
||||
}
|
||||
SaveByte[Offset + 0] = b;
|
||||
SaveByte[Offset + 1] = g;
|
||||
SaveByte[Offset + 2] = r;
|
||||
SaveByte[Offset + 3] = a;
|
||||
}
|
||||
|
||||
void Asset_ImagePack::LoadImgToMem(IMG *p)
|
||||
{
|
||||
std::string Path = "ImagePacks2/" + p->lpBelongsFile;
|
||||
// SDL_Log("LoadImgToMem : %s", Path.c_str());
|
||||
Ifstream_NPK Fs;
|
||||
Fs.open(Path.c_str(), std::ios::in | std::ios::binary);
|
||||
if (Fs.is_open())
|
||||
{
|
||||
Fs.seekg(p->imgOffset);
|
||||
std::string Flag = Fs.ReadString(); // 读取Flag
|
||||
if (Flag.find("Neople Img File") != std::string::npos)
|
||||
{
|
||||
// 索引表大小
|
||||
long TableLength = Fs.ReadLong();
|
||||
// img 版本 4字节
|
||||
Fs.ReadInt(); // 读取版本
|
||||
// img 帧数
|
||||
int IndexCount = Fs.ReadInt();
|
||||
// 图片数量赋值
|
||||
p->png_sum = IndexCount;
|
||||
|
||||
// new出 Png数量的 结构体
|
||||
ImgInfo *PngList = new ImgInfo[IndexCount];
|
||||
|
||||
for (int i = 0; i < IndexCount; i++)
|
||||
{
|
||||
PngList[i].Type = Fs.ReadInt();
|
||||
if (PngList[i].Type == 17)
|
||||
{
|
||||
// 引用贴图
|
||||
int frbuf = Fs.ReadInt();
|
||||
// 压缩类型 用来临时存一下引用编号
|
||||
PngList[i].CmpType = frbuf;
|
||||
////大小
|
||||
PngList[i].Size = 0;
|
||||
PngList[i].Offset = PngList[i - 1].Offset + PngList[i - 1].Size;
|
||||
continue;
|
||||
}
|
||||
// 压缩类型
|
||||
PngList[i].CmpType = Fs.ReadInt();
|
||||
// 宽度
|
||||
PngList[i].Width = Fs.ReadInt();
|
||||
// 高度
|
||||
PngList[i].Height = Fs.ReadInt();
|
||||
// 大小
|
||||
PngList[i].Size = Fs.ReadInt();
|
||||
// Xpos
|
||||
PngList[i].Xpos = Fs.ReadInt();
|
||||
// Ypos
|
||||
PngList[i].Ypos = Fs.ReadInt();
|
||||
// 帧域X
|
||||
PngList[i].FrameXpos = Fs.ReadInt();
|
||||
// 帧域Y
|
||||
PngList[i].FrameYpos = Fs.ReadInt();
|
||||
// 计算偏移
|
||||
if (i == 0)
|
||||
PngList[i].Offset = 0 + p->imgOffset + TableLength + 32;
|
||||
else
|
||||
PngList[i].Offset = PngList[i - 1].Offset + PngList[i - 1].Size;
|
||||
}
|
||||
|
||||
for (int i = 0; i < IndexCount; i++)
|
||||
{
|
||||
// 引用
|
||||
if (PngList[i].Type == 17)
|
||||
{
|
||||
// 引用编号
|
||||
int YYIndex = PngList[i].CmpType;
|
||||
int sizebuf = PngList[YYIndex].Width * PngList[YYIndex].Height * 4;
|
||||
BYTE *bByte = new BYTE[sizebuf];
|
||||
memcpy(bByte, PngList[PngList[i].CmpType].PNGdata, sizebuf);
|
||||
PngList[i].PNGdata = PngList[YYIndex].PNGdata;
|
||||
|
||||
// 压缩类型 用来临时存一下引用编号
|
||||
PngList[i].CmpType = PngList[YYIndex].CmpType;
|
||||
// 宽度
|
||||
PngList[i].Width = PngList[YYIndex].Width;
|
||||
// 高度
|
||||
PngList[i].Height = PngList[YYIndex].Height;
|
||||
// 大小
|
||||
PngList[i].Size = 0;
|
||||
// Xpos
|
||||
PngList[i].Xpos = PngList[YYIndex].Xpos;
|
||||
// Ypos
|
||||
PngList[i].Ypos = PngList[YYIndex].Ypos;
|
||||
// 帧域X
|
||||
PngList[i].FrameXpos = PngList[YYIndex].FrameXpos;
|
||||
// 帧域Y
|
||||
PngList[i].FrameYpos = PngList[YYIndex].FrameYpos;
|
||||
continue;
|
||||
}
|
||||
|
||||
Fs.seekg(PngList[i].Offset);
|
||||
BYTE *PngData = Fs.ReadCustomSize(PngList[i].Size);
|
||||
int DeSize = PngList[i].Width * PngList[i].Height * 4;
|
||||
BYTE *bByte = new BYTE[DeSize];
|
||||
unsigned long RealSize = DeSize;
|
||||
uncompress(bByte, &RealSize, PngData, (unsigned long)PngList[i].Size);
|
||||
delete[] PngData;
|
||||
|
||||
if (PngList[i].Type != 16)
|
||||
{
|
||||
int PngByteSize = DeSize * 2;
|
||||
PngList[i].PNGdata = new BYTE[PngByteSize];
|
||||
|
||||
for (int e = 0; e < PngByteSize; e += 4)
|
||||
{
|
||||
BYTE NeedData[2];
|
||||
memset(NeedData, 0, 2);
|
||||
memcpy(NeedData, bByte + (e / 4) * 2, 2);
|
||||
ParseColor(NeedData, PngList[i].Type, PngList[i].PNGdata, e);
|
||||
}
|
||||
delete[] bByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
PngList[i].PNGdata = bByte;
|
||||
}
|
||||
}
|
||||
|
||||
p->lp_lplist = PngList;
|
||||
}
|
||||
else if (Flag.find("Neople Image File") != std::string::npos)
|
||||
{
|
||||
// LoadImgToMem2(p);
|
||||
}
|
||||
Fs.close();
|
||||
}
|
||||
}
|
||||
|
||||
Asset_ImagePack::IMG *Asset_ImagePack::GetIMG(std::string imgName)
|
||||
{
|
||||
IMG *img = NULL;
|
||||
std::map<std::string, IMG>::iterator itr;
|
||||
itr = map_npk.find(imgName);
|
||||
if (itr == map_npk.end())
|
||||
{
|
||||
std::string mes = "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!调用了不存在的Img : " + imgName;
|
||||
SDL_Log(mes.c_str());
|
||||
img = &map_npk["sprite/interface/base.img"];
|
||||
}
|
||||
else
|
||||
{
|
||||
img = &itr->second;
|
||||
}
|
||||
// 如果图片数组不存在 或者 图片数据不存在都要重读
|
||||
if (!img->lp_lplist)
|
||||
{
|
||||
LoadImgToMem(img);
|
||||
}
|
||||
img->UseTime = SDL_GetTicks();
|
||||
return img;
|
||||
}
|
||||
86
source/Asset/Asset_ImagePack.h
Normal file
86
source/Asset/Asset_ImagePack.h
Normal file
@@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
#ifdef _SWITCH_
|
||||
#include <switch.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <SDL.h>
|
||||
#include <map>
|
||||
|
||||
#include "Tool/Ifstream_NPK.h"
|
||||
#include <zlib.h>
|
||||
|
||||
class Asset_ImagePack
|
||||
{
|
||||
public:
|
||||
struct NpkInfo
|
||||
{
|
||||
int Offset;
|
||||
int Length;
|
||||
std::string Path;
|
||||
};
|
||||
|
||||
// PNG结构体
|
||||
struct ImgInfo
|
||||
{
|
||||
// 图片格式
|
||||
int Type;
|
||||
// 压缩类型
|
||||
int CmpType;
|
||||
// 宽度
|
||||
int Width;
|
||||
// 高度
|
||||
int Height;
|
||||
// 大小
|
||||
int Size;
|
||||
// Xpos
|
||||
int Xpos;
|
||||
// Ypos
|
||||
int Ypos;
|
||||
// 帧域X
|
||||
int FrameXpos;
|
||||
// 帧域Y
|
||||
int FrameYpos;
|
||||
// 偏移
|
||||
int Offset;
|
||||
// Png位图数据
|
||||
BYTE *PNGdata;
|
||||
};
|
||||
|
||||
struct IMG // npk的img的结构体
|
||||
{
|
||||
std::string lpImgName; // img文件的路径
|
||||
int img_index; // img文件在npk文件里的序号
|
||||
unsigned imgOffset;
|
||||
unsigned imgSize;
|
||||
std::string lpBelongsFile; // 这个img属于哪个npk文件
|
||||
int png_sum; // 这个img文件有多少个 图片
|
||||
ImgInfo *lp_lplist; // 图片的数组..
|
||||
Uint32 UseTime = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
Asset_ImagePack(const Asset_ImagePack &) = delete;
|
||||
Asset_ImagePack &operator=(const Asset_ImagePack &) = delete;
|
||||
Asset_ImagePack(Asset_ImagePack &&) = delete;
|
||||
Asset_ImagePack &operator=(Asset_ImagePack &&) = delete;
|
||||
// 全局访问点
|
||||
static Asset_ImagePack &GetInstance()
|
||||
{
|
||||
static Asset_ImagePack instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void ParseColor(BYTE *Tab, int Type, BYTE *SaveByte, int Offset);
|
||||
void LoadImgToMem(IMG *p);
|
||||
IMG *GetIMG(std::string imgName);
|
||||
|
||||
private:
|
||||
Asset_ImagePack(/* args */);
|
||||
~Asset_ImagePack();
|
||||
|
||||
std::map<std::string, IMG> map_npk;
|
||||
};
|
||||
227
source/Asset/Asset_Script.cpp
Normal file
227
source/Asset/Asset_Script.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include "Asset/Asset_Script.h"
|
||||
#include "Asset_Script.h"
|
||||
|
||||
void Asset_Script::Init()
|
||||
{
|
||||
// 读取头建立树
|
||||
InitHeader();
|
||||
// 读取bin文件
|
||||
InitBin();
|
||||
// 读取LoadString
|
||||
InitLoadString();
|
||||
}
|
||||
|
||||
void Asset_Script::Clear()
|
||||
{
|
||||
FileInfo.clear();
|
||||
BinStringM.clear();
|
||||
LoadStringM.clear();
|
||||
_Data.clear();
|
||||
_Data.shrink_to_fit();
|
||||
}
|
||||
|
||||
void Asset_Script::InitHeader()
|
||||
{
|
||||
// 读取UUID的长度
|
||||
int UUID_LENGTH = GetInt();
|
||||
// UUID 读 1 - 36位 构造 UTF8 string
|
||||
std::string UUID = GetString(UUID_LENGTH);
|
||||
// 版本号
|
||||
int Version = GetInt();
|
||||
(void)Version;
|
||||
// 文件路径数据的大小
|
||||
int AlignedIndexHeaderSize = GetInt();
|
||||
// 解密密钥
|
||||
int IndexHeaderCrc = GetInt();
|
||||
// 文件数量
|
||||
int IndexSize = GetInt();
|
||||
// 文件起始位置
|
||||
int FristPos = tellg();
|
||||
CrcDecode(AlignedIndexHeaderSize, IndexHeaderCrc);
|
||||
int CurrPos = 0;
|
||||
StartPos = AlignedIndexHeaderSize + 56;
|
||||
// 建立pvf文件索引表
|
||||
for (int i = 0; i < IndexSize; i++)
|
||||
{
|
||||
seek(FristPos + CurrPos);
|
||||
int FileNumber = GetInt();
|
||||
(void)FileNumber;
|
||||
int FilePathLength = GetInt();
|
||||
std::string FileName = tolower(GetString(FilePathLength));
|
||||
int FileLength = GetInt();
|
||||
int Cre32 = GetInt();
|
||||
int RelativeOffset = GetInt();
|
||||
if (FileLength > 0)
|
||||
{
|
||||
int RealFileLength = (FileLength + 3) & 4294967292;
|
||||
PvfFileInfo Info;
|
||||
Info.ROffset = RelativeOffset;
|
||||
Info.Cr32 = Cre32;
|
||||
Info.Length = RealFileLength;
|
||||
Info.DecodeFlag = false;
|
||||
FileInfo[FileName] = Info;
|
||||
}
|
||||
CurrPos += 20;
|
||||
CurrPos += FilePathLength;
|
||||
}
|
||||
}
|
||||
|
||||
void Asset_Script::InitBin()
|
||||
{
|
||||
if (FileInfo.count("stringtable.bin") == 0)
|
||||
{
|
||||
SDL_LogError(0, "stringtable.bin文件不存在");
|
||||
return;
|
||||
}
|
||||
PvfFileInfo BinInfo = FileInfo["stringtable.bin"];
|
||||
seek(StartPos + BinInfo.ROffset);
|
||||
CrcDecode(BinInfo.Length, BinInfo.Cr32);
|
||||
seek(StartPos + BinInfo.ROffset);
|
||||
int FileHPos = tellg();
|
||||
int Count = GetInt();
|
||||
int CurrentIndex = 0;
|
||||
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
seek(FileHPos + CurrentIndex * 4 + 4);
|
||||
int StartPos = GetInt();
|
||||
int EndPos = GetInt();
|
||||
int Len = EndPos - StartPos;
|
||||
seek(FileHPos + StartPos + 4);
|
||||
std::string Str = GetString(Len);
|
||||
BinStringM[CurrentIndex] = Str;
|
||||
CurrentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void Asset_Script::InitLoadString()
|
||||
{
|
||||
if (FileInfo.count("n_string.lst") == 0)
|
||||
{
|
||||
SDL_LogError(0, "n_string.lst文件不存在");
|
||||
}
|
||||
PvfFileInfo Info = FileInfo["n_string.lst"];
|
||||
seek(StartPos + Info.ROffset);
|
||||
CrcDecode(Info.Length, Info.Cr32);
|
||||
seek(StartPos + Info.ROffset);
|
||||
|
||||
int FileHPos = tellg();
|
||||
int Flag = GetShort();
|
||||
(void)Flag;
|
||||
int i = 2;
|
||||
while (i < Info.Length)
|
||||
{
|
||||
if ((Info.Length - i) >= 10)
|
||||
{
|
||||
seek(FileHPos + i + 6);
|
||||
int FindKey = GetInt();
|
||||
std::string Key = GetBinString(FindKey);
|
||||
std::string Type = tolower(Key.substr(0, Key.find("/")));
|
||||
if (Key.length() > 0)
|
||||
{
|
||||
PvfFileInfo *FileInfo = GetFileInfo(Key);
|
||||
if (FileInfo == nullptr)
|
||||
continue;
|
||||
|
||||
seek(StartPos + FileInfo->ROffset);
|
||||
CrcDecode(FileInfo->Length, FileInfo->Cr32);
|
||||
seek(StartPos + FileInfo->ROffset);
|
||||
|
||||
std::string Str = GetStringNormal(FileInfo->Length);
|
||||
std::vector<std::string> StrArr = split(Str, "\n");
|
||||
for (auto it = StrArr.begin(); it != StrArr.end(); ++it)
|
||||
{
|
||||
std::string strobj = *it;
|
||||
if (strobj.find(">") != std::string::npos)
|
||||
{
|
||||
std::vector<std::string> strobjarr = split(strobj, ">");
|
||||
if (strobjarr.size() > 1)
|
||||
{
|
||||
LoadStringM[Type][strobjarr[0]] = strobjarr[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
i += 10;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Asset_Script::GetBinString(int Key)
|
||||
{
|
||||
if (BinStringM.count(Key))
|
||||
return BinStringM[Key];
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Asset_Script::GetLoadString(std::string Type, std::string Key)
|
||||
{
|
||||
if (LoadStringM.count(Type) && LoadStringM[Type].count(Key))
|
||||
return LoadStringM[Type][Key];
|
||||
return "";
|
||||
}
|
||||
|
||||
Asset_Script::PvfFileInfo *Asset_Script::GetFileInfo(std::string path)
|
||||
{
|
||||
path = tolower(path);
|
||||
if (FileInfo.count(path))
|
||||
return &FileInfo[path];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string Asset_Script::GetFileContent(std::string path)
|
||||
{
|
||||
if (FileInfo.count(path))
|
||||
{
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
if (FileInfo[path].DecodeFlag == false)
|
||||
{
|
||||
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
FileInfo[path].DecodeFlag = true;
|
||||
}
|
||||
char *blobp = new char[FileInfo[path].Length];
|
||||
read((char *)blobp, FileInfo[path].Length);
|
||||
std::string Str(blobp, FileInfo[path].Length);
|
||||
delete[] blobp;
|
||||
return Str;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
char *Asset_Script::GetFileContentChar(std::string path)
|
||||
{
|
||||
if (FileInfo.count(path))
|
||||
{
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
if (FileInfo[path].DecodeFlag == false)
|
||||
{
|
||||
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
FileInfo[path].DecodeFlag = true;
|
||||
}
|
||||
char *blobp = new char[FileInfo[path].Length];
|
||||
read((char *)blobp, FileInfo[path].Length);
|
||||
return blobp;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<BYTE> Asset_Script::GetFileContentByte(std::string path)
|
||||
{
|
||||
if (FileInfo.count(path))
|
||||
{
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
if (FileInfo[path].DecodeFlag == false)
|
||||
{
|
||||
CrcDecode(FileInfo[path].Length, FileInfo[path].Cr32);
|
||||
seek(StartPos + FileInfo[path].ROffset);
|
||||
FileInfo[path].DecodeFlag = true;
|
||||
}
|
||||
std::vector<BYTE> blobp(FileInfo[path].Length);
|
||||
read((char *)blobp.data(), FileInfo[path].Length);
|
||||
return blobp;
|
||||
}
|
||||
return std::vector<BYTE>();
|
||||
}
|
||||
60
source/Asset/Asset_Script.h
Normal file
60
source/Asset/Asset_Script.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#ifdef _SWITCH_
|
||||
#include <switch.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <dirent.h>
|
||||
#include <SDL.h>
|
||||
#include <map>
|
||||
|
||||
#include "Tool/Ifstream_PVF.h"
|
||||
|
||||
class Asset_Script : public Ifstream_PVF
|
||||
{
|
||||
public:
|
||||
struct PvfFileInfo
|
||||
{
|
||||
int ROffset;
|
||||
int Cr32;
|
||||
int Length;
|
||||
bool DecodeFlag = false;
|
||||
};
|
||||
|
||||
private:
|
||||
Asset_Script(const std::string filename = "Script.pvf") : Ifstream_PVF(filename) {};
|
||||
~Asset_Script() = default;
|
||||
|
||||
int StartPos = 0;
|
||||
std::map<std::string, PvfFileInfo> FileInfo;
|
||||
std::map<int, std::string> BinStringM;
|
||||
std::map<std::string, std::map<std::string, std::string>> LoadStringM;
|
||||
|
||||
public:
|
||||
Asset_Script(const Asset_Script &) = delete;
|
||||
Asset_Script &operator=(const Asset_Script &) = delete;
|
||||
Asset_Script(Asset_Script &&) = delete;
|
||||
Asset_Script &operator=(Asset_Script &&) = delete;
|
||||
// 全局访问点
|
||||
static Asset_Script &GetInstance()
|
||||
{
|
||||
static Asset_Script instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void InitHeader();
|
||||
void InitBin();
|
||||
void InitLoadString();
|
||||
void Clear();
|
||||
|
||||
public:
|
||||
std::string GetBinString(int Key);
|
||||
std::string GetLoadString(std::string Type, std::string Key);
|
||||
PvfFileInfo *GetFileInfo(std::string path);
|
||||
|
||||
std::string GetFileContent(std::string path); // 获取文件内容
|
||||
char* GetFileContentChar(std::string path); // 获取文件内容
|
||||
std::vector<BYTE> GetFileContentByte(std::string path); // 获取文件内容
|
||||
};
|
||||
105
source/Asset/ScriptData.cpp
Normal file
105
source/Asset/ScriptData.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "ScriptData.h"
|
||||
#include "Tool/Tool_String.h"
|
||||
#include "Asset/Asset_Script.h"
|
||||
|
||||
ScriptData::ScriptData()
|
||||
{
|
||||
}
|
||||
|
||||
ScriptData::~ScriptData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ScriptData::Init(std::vector<BYTE> Data, std::string FilePath)
|
||||
{
|
||||
std::string ASA = "";
|
||||
for (size_t i = 0; i < Data.size(); i++)
|
||||
{
|
||||
ASA += std::to_string((int)Data[i]);
|
||||
ASA += ",";
|
||||
}
|
||||
|
||||
if (Data.size() < 7)
|
||||
return;
|
||||
IO = std::make_shared<Blob>(Data);
|
||||
filepath = FilePath;
|
||||
filetype = Tool_toLowerCase(FilePath.substr(0, FilePath.find_first_of("/")));
|
||||
filesize = Data.size();
|
||||
}
|
||||
|
||||
std::string ScriptData::Get()
|
||||
{
|
||||
if (!IO)
|
||||
return "";
|
||||
if (_CurI < filesize && filesize - _CurI >= 5)
|
||||
{
|
||||
std::string Ret = UnpackData();
|
||||
_CurI += 5;
|
||||
return Ret;
|
||||
}
|
||||
return "_nop_";
|
||||
}
|
||||
|
||||
void ScriptData::Back()
|
||||
{
|
||||
if (_CurI >= 5)
|
||||
_CurI -= 5;
|
||||
}
|
||||
|
||||
bool ScriptData::IsEnd()
|
||||
{
|
||||
return (_CurI >= filesize || filesize - _CurI < 5);
|
||||
}
|
||||
|
||||
std::string ScriptData::UnpackData()
|
||||
{
|
||||
IO->setOffset(_CurI);
|
||||
int currentByte = (int)(IO->getByte());
|
||||
int after = IO->getInt();
|
||||
switch (currentByte)
|
||||
{
|
||||
case 9:
|
||||
{
|
||||
BYTE NewcurrentByte = IO->getByte(); // 内容指示位
|
||||
(void)NewcurrentByte;
|
||||
int Newafter = IO->getInt();
|
||||
std::string Buf = Asset_Script::GetInstance().GetBinString(Newafter);
|
||||
if (Buf.empty())
|
||||
Buf = "";
|
||||
else
|
||||
Buf = Asset_Script::GetInstance().GetLoadString(filetype, Buf);
|
||||
return Buf;
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
std::string Buf = Asset_Script::GetInstance().GetBinString(after);
|
||||
if (Buf.empty())
|
||||
Buf = "";
|
||||
else
|
||||
Buf = Asset_Script::GetInstance().GetLoadString(filetype, Buf);
|
||||
return Buf;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
IO->setOffset(IO->getOffset() - 4);
|
||||
int ret = IO->getInt();
|
||||
return std::to_string(ret);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
float Bbuf;
|
||||
std::memcpy(&Bbuf, &after, sizeof(float));
|
||||
return std::to_string(Bbuf);
|
||||
}
|
||||
case 6:
|
||||
case 8:
|
||||
case 7:
|
||||
case 5:
|
||||
{
|
||||
return Asset_Script::GetInstance().GetBinString(after);
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
25
source/Asset/ScriptData.h
Normal file
25
source/Asset/ScriptData.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "Tool/Blob.hpp"
|
||||
#include <memory>
|
||||
class ScriptData
|
||||
{
|
||||
using BYTE = unsigned char;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Blob> IO;
|
||||
|
||||
public:
|
||||
ScriptData();
|
||||
~ScriptData();
|
||||
|
||||
std::string filepath;
|
||||
std::string filetype;
|
||||
int filesize;
|
||||
int _CurI = 2;
|
||||
|
||||
void Init(std::vector<BYTE> Data, std::string FilePath);
|
||||
std::string Get();
|
||||
void Back();
|
||||
bool IsEnd();
|
||||
std::string UnpackData();
|
||||
};
|
||||
Reference in New Issue
Block a user