# Crossgate-魔力宝贝
## Unity C# 图档解析库

## 1、开源目的
本脚本旨在学习研究```Crossgate``` ```魔力宝贝``` 图档bin文件的解压与使用,相关资料来源于互联网文章与相关技术大佬指导

再次感谢```阿伍```等在互联网上分享相关解压、算法解析等教学文章的技术大佬所提供的帮助

本脚本遵照GPL共享协议,可随意修改、调整代码学习使用

请务删除或修改文档或源代码中相关版权声明信息,且严禁用于商业项目

因利用本脚本盈利或其他行为导致的任何商业版权纠纷,脚本作者不承担任何责任或损失

本解析库原始发布地址: [https://git.honorlee.me/HonorLee/CGTool](https://git.honorlee.me/HonorLee/CGTool)

同步更新至Github: [https://github.com/HonorLee-cn/CGTool](https://github.com/HonorLee-cn/CGTool)

如有任何问题请至Github提交Issues或联系作者

![预览](Preview/Preview.png)

## 2、功能支持
> 当前版本目前已支持 魔力宝贝3.7-龙之沙漏 及以下版本的图档解析,以及 4.0 版本以上图档、动画数据解析
>
> <font color="red">注意:当前版本 4.0 及以上地图暂不支持</font>
>
> 目前版本支持以下功能:
> 
> * `GraphicInfo` [图档索引解析](#获取图档索引数据)
> * `GraphicData` [图档数据解析](#获取图档实体数据)
> * `Palet` 调色板数据解析
> * `Map` [服务端/客户端 图数据解析](#获取地图数据)
> * `Audio` [音频索引及加载](#播放音频)
> * `AnimeInfo` 动画索引解析
> * `Anime` 动画数据解析
> * `AnimePlayer` [动画播放器挂载组件](#动画播放) 
>   * `AnimePlayer` 动画关键帧(攻击/攻击完成)事件回调
>   * `AnimePlayer` 音频帧事件回调

<div style="display: flex;flex-direction: column;align-items: center;">
<div><img style="" src="Preview/AnimeSupport.gif"><img style="" src="Preview/AnimeHSupport.gif"></div>
<div><img style="" src="Preview/AnimePlayer.png"></div>
<div><img style="" src="Preview/PUK3Graphic.jpg"></div>

</div>



## 3、使用说明

### 基本环境

请确认Unity已安装以下Package包:
```
"dependencies": {
    "com.unity.burst": "1.6.0",
    "com.unity.visualscripting": "1.9.0"
}
```

克隆当前仓库或下载zip包解压,将 CrossgateToolkit 文件夹放置于Unity项目文件夹内引用

可直接下载Release中unitypackage直接导入

### 工具库说明

最新 V2.0 版本已移除对魔力宝贝原版本的强绑定,初始化程序将根据目标路径进行自动分析

规划图档目录结构时,图档根目录下建议以数字版本号方式命名不同版本图档子目录

CGTool在初始化时对所配置图档根目录进行扫描,并按照``根目录优先``、``子目录按字符排序``方式依次加载并初始化图档数据

所涉及的所有Index则为图档序号、Serial为图档或动画的具体编号而非索引档中序号,实际使用时请注意区分



其他相关部分会逐渐更新完善

### 框架初始化
在入口或初始化脚本头部引入CGTool初始化文件
```csharp
using CrossgateToolkit;
```
并在相关初始化位置对CGTool进行初始化
```csharp
// 配置Crossgate相关资源路径,如跳过则默认为 Environment.CurrentDirectory 下相关 目录
CGTool.PATH = new CGTool.CGPath()
{
    // 调色板目录,不可省略
    PAL = Application.persistentDataPath + "/pal",
    // BIN图档目录,包含图档索引、图档文件、动画索引、动画文件等根目录
    // 初始化时会自动便利查询分析所有文件数据,不可省略
    BIN = Application.persistentDataPath + "/bin",
    // 地图文件目录,省略则不对地图数据初始化
    MAP = Application.persistentDataPath + "/map",
    // 音频文件目录,省略则不对音频初始化
    BGM = Application.persistentDataPath + "/bgm",
    AUDIO = Application.persistentDataPath + "/se"
};
// 初始化
CGTool.Init();
```
CGTool初始化时,会自动对相关索引Info文件进行解析,请根据实际所采用版本情况,对脚本代码中解析相关的文件名称进行修改调整


### 获取图档索引数据
(图档基本索引数据属性信息)
```csharp
// 正常通过编号获取图档信息,无需版本号(常规图档)
GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoData(uint Serial);

// 通过索引获取图档信息,带版本号(特殊无编号图档获取,如动画获取每帧图档时)
GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoDataByIndex(string version, uint Serial);
```

### 获取图档实体数据
(图档实际数据,包含图像Sprite资源)
```csharp
// 直接通过编号获取
GraphicDetail graphicDetail = Graphic.GetGraphicDetail(uint serial,int palet = 0);
// 或 通过GraphicInfoData获取
GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(GraphicInfoData graphicInfoData, int palet = 0);
/**
 * 使用说明:
 * 所有通过Graphic获取的图档Sprite均已做偏移处理,可直接使用
 * 需自行判断图档是否存在,并处理图档不存在的情况
 * 1.获取指定编号的图档索引信息
 * 2.根据获取到的索引取得图档数据
 * 3.使用图档数据中的Sprite资源进行绘制
 */

GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoData(Serial);
GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(graphicInfoData ,0);
SpriteRenderer(Image).sprite = graphicDetail.Sprite;
```

### 获取地图数据
```csharp
// 通过编号获取地图数据,地图数据中包含地面及地上物件数据以及寻路用的二维数组
// 可自行阅读源码查询相关属性成员和使用方式
Map.MapInfo mapInfo = Map.GetMap(uint Serial);
```

### 图档合批

为减少渲染时的Drawcall和Batchs动态合批数量提高性能并降低内存消耗,工具库提供了大量图档合批(并)处理方法

图档合并时,会自动根据每个图档图像由小到大进行排序处理,以最大限度将多个图档合并至一个或多个稍大的Texture2D中

```csharp
/**
* 合批图档
* 通过指定图档序列,对图档进行合批处理,并返回合批后的图档数据
* @param graphicInfoDatas 图档索引数据序列
* @param palet 调色板序号
* @param maxTextureSize 单个Texture最大尺寸,地面数据建议2048,物件数据建议4096
* @param padding 图档间隔,可以有效避免图档渲染时出现多余的黑边或像素黏连
* @return Dictionary 合批后的图档数据,Key(unit)为图档数据编号,Value为图档数据
*/
GraphicData.BakeGraphics(
    List<GraphicInfoData> graphicInfoDatas,
    int palet = 0,
    int maxTextureSize = 2048,
    int padding = 0)
```

### 地图地面/物件图档合批数据
针对地图图档部分合批提供了相应的简化方法,可以酌情使用
```csharp
/**
 * * 地面数据将拼合成一个或多个2048*2048尺寸Texture2D
 * * 物件(建筑等)拼合成一个或多个不大于4096*4096尺寸Texture2D
 * 另: 由于4.0后地图模式变动,部分地图图档过大,所以这个方法可能不适用于4.0后的地图
 */

// 地面合批
Dictionary<int, GraphicDetail> MapGroundSerialDic =
    Map.BakeGrounds(    // <= 合并地面图形
        List<GraphicInfoData> graphicInfoDatas,
        int PaletIndex = 0
    );

// 物件合批
Dictionary<int, GraphicDetail> MapObjectSerialDic =
    Graphic.BakeObjects(    // <= 合并物件图形
        List<GraphicInfoData> graphicInfoDatas,
        int PaletIndex = 0
    );
```
![地面合并效果](Preview/MapGroundMix.png)
![物件合并效果](Preview/MapObjectMix.png)
![资源合并后效果](Preview/batches.png)

### 播放音频
```csharp
CGTool.Audio.Play(AudioSource audioSource,Type type, int serial)

//播放背景音乐
CGTool.Audio.Play(AudioSource audioSource,Audio.Type.BGM,int serial);
//获取音效音频
CGTool.Audio.Play(AudioSource audioSource,Audio.Type.EFFECT,int serial);
```

### 动画播放
```csharp
/**
* 动画播放器,用于播放CG动画,支持多动画队列播放
* 1.3更新后已无需手动挂载SpriteRenderer、Image组件,程序会自动处理
* 只需将AnimePlayer挂载到任意GameObject上即可
* 可手动指定渲染方式是否以Image组件渲染
* 可选择是否对序列帧图像进行合批(建议开启)
*
* 动画解析Anime类中包含以下多个枚举预设:
* DirectionType 方向类型,含8个不同方向
* ActionType    动作类型,含20个不同动作
* EffectType    动作效果,含Hit和HitOver两种判定
* PlayType      播放类型,含Loop、Once、OnceAndDestory三种类型
*
* 当动画播放完成后会自动调用onFinishCallback回调函数
* 另外可指定onActionListener和onAudioListener监听动画动作帧和音频帧相关判定
*
* 目前已知的动作帧有:
* 击中 Hit (未结束攻击动作,如小石像、黄蜂、绿螳螂等单次攻击动作中有多次击中效果)
* 伤害结算 HitOver
*/

AnimePlayer player = GetComponent<AnimePlayer>();

/**
* 播放动画,调用此方法将会清空当前播放队列,调用完成可通过链式调用nextPlay方法添加动画到播放队列
* @param Serial     动画序列号
* @param Direction  动画方向
* @param ActionType 动画动作
* @param PlayType   播放类型 Loop / Once / OnceAndDestory
* @param Speed      播放速度倍率,以 1s 为单位基准,根据动画帧率计算实际播放周期时长
* @param onFinishCallback 动画结束回调
* @return AnimePlayer
*/

player.play(
    uint Serial,
    Anime.DirectionType Direction = Anime.DirectionType.North,
    Anime.ActionType actionType = Anime.ActionType.Stand,
    Anime.PlayType playType = Anime.PlayType.Once,
    float Speed = 1f,
    AnimeCallback onFinishCallback = null
);

// 简化播放: 此方法大多数情况下用以播放特效动画,没有方向和动作类型
player.play(
    uint Serial,
    Anime.PlayType playType,
    float speed = 1f,
    AnimeCallback onFinishCallback = null
);

// 播放一次
player.playOnce(
    Anime.DirectionType directionType,
    Anime.ActionType actionType,
    float Speed=1f,
    AnimeCallback onFinishCallback=null
    );

// 循环播放
player.playLoop(
    Anime.DirectionType directionType,
    Anime.ActionType actionType,
    float Speed=1f,
    AnimeCallback onFinishCallback=null
    );

/**
 * 可通过setter方法设置动画
 * 通过setter方法设置的动画将使用以下默认配置
 * DirectionType = DirectionType.North
 * ActionType = ActionType.Stand
 * PlayType = PlayType.Loop
 * Speed = 1f
 */
player.Serial = uint AnimeSerial;

// 设置帧动效反馈监听
player.onEffectListener = effect => {...};

// 设置帧音效反馈监听
player.onAudioListener = audioIndex => {...};

// 链式调用添加动作队列
player.play(...params).nextPlay(...params);

// 动态修改动画所用的调色板索引
player.PaletIndex = int PaletIndex;

// 动态修改动画播放类型
player.PlayType = Anime.PlayType;

// 动态调整当前动画方向
player.DirectionType = Anime.DirectionType;

// 动态调整当前动画动作
player.ActionType = Anime.ActionType;

// 动画帧延时,动态修改当前动画,延长每帧之间的时间间隔(此方法定义有歧义,后续更新调整)
player.DelayPlay(float delayTime)

// 停止动画
player.Stop();

```

### 其他
请根据情况自行探索修改代码适应应用场景



## 4、更新日志
### v 2.2
> `ADD` 增加 <font color="red">4.0 版本(乐园之卵)及后续版本图档、动画解析</font>
>
> `UPD` 调整图档目录版本号分析过程,以更好的适应多种图档目录结构

### v 2.1
> `UPD` 图档合并方法进行统一处理,并增加地图相关简便方法

### v 2.0
> `ADD` 修改初始化方法以支持更复杂的图档文件建构
>
> `UPD` 图档解析支持多层目录结构并能自动识别加载,方便对图档进行扩充升级,建议根据版本号对图档子目录进行命名
>
> `UPD` 图档获取和加载方法优化,减少无用参数
>
> `UPD` 根据新的加载方式调整相关工具库代码以适应新的加载方式

### v 1.7
> `ADD` 加入地图物件合批处理

### v 1.6
> `ADD` 加入<font color="red">客户端</font>地图读取支持,同时附加了客户端地图文件缺失的名字和调色版映射表
>
> `UPD` Anime合批处理图形之间增加间隔,避免出现像素黏连
>
> `UPD` AnimePlayer挂载件预留FrameTexture属性可在Editor中查看合批的图像
>
> `UPD` CGTool入口调整,可指定bin目录位置

### v 1.5
> `UPD` Anime序列帧合批忘了考虑不同调色板的问题,现已增加相关处理

### v 1.4
> `ADD` 加入Anime序列帧合批,挂载AnimePlayer后可手动设置是否开启合批(建议开启)

### v 1.3
> `UPD` 优化AnimePlayer组件的挂载和使用方式
> 
> `UPD` 优化AnimePlayer动画播放器,增加动画相关处理方法
>
> `UPD` 更新README说明文档,增加、调整使用说明
> 

### v 1.2

> `FIX` 修正文件加载时判断为正则,避免因使用不同版本bin导致加载报错问题

### v 1.1
> `ADD` 音频索引及加载AudioTool
> 
> `ADD` 动画播放器添加对Image渲染支持,用以支持GUI动画播放
> 
> `ADD` Graphic增加地面图档动态合批
> 
> `ADD` Anime增加动画帧动态合批方法
> 
> `UPD` 优化Graphic解析,统一改为RGBA4444模式,以减少内存占用
> 
> `UPD` 重新整理初始化代码,优化初始化流程
> 
> `UPD` 优化动画播放器,增加动画相关处理方法
> 
> `UPD` 动画播放器添加对Image渲染支持,用以支持GUI动画播放
> 
> `FIX` 修复动画序列中攻击判定、音频序列解析方式错误的问题

### v 1.0

> `ADD` 脚本初始化
> 
> `ADD` 图档索引GraphicInfo文件解析
> 
> `ADD` 图档Graphic文件数据解析
> 
> `ADD` 调色板Palet文件解析
> 
> `ADD` 动画索引AnimeInfo文件解析
> 
> `ADD` 动画Anime文件数据解析
> 
> `ADD` <font color="red">服务端</font>地图文件解析



## 5、待处理

- 支援 4.0 以上版本图档解析
- 其他未知
- 优化

## LICENSE
This project is licensed under the GPL license. Copyrights are respective of each contributor listed at the beginning of each definition file.