Anime.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /**
  2. * 魔力宝贝图档解析脚本 - CGTool
  3. *
  4. * @Author HonorLee (dev@honorlee.me)
  5. * @Version 1.0 (2023-04-15)
  6. * @License GPL-3.0
  7. *
  8. * Anime.cs 动画基础类
  9. */
  10. using System;
  11. using System.Collections.Generic;
  12. using System.IO;
  13. using UnityEngine;
  14. namespace CrossgateToolkit
  15. {
  16. //动画信息
  17. public class AnimeInfo
  18. {
  19. // 版本
  20. public string Version;
  21. //4 bytes 动画序号
  22. public uint Serial;
  23. //4 bytes 动画文件地址
  24. public uint Addr;
  25. //2 bytes 动作数量
  26. public int ActionCount;
  27. //2 bytes 未知字节
  28. public byte[] Unknow;
  29. //动画数据 Direction -> ActionType -> AnimeData
  30. public Dictionary<int, Dictionary<int, AnimeDetail>> AnimeDatas = new Dictionary<int, Dictionary<int, AnimeDetail>>();
  31. }
  32. //动画帧数据
  33. public class AnimeFrameInfo
  34. {
  35. //图档编号
  36. public uint GraphicIndex;
  37. //宽度
  38. public int Width;
  39. //高度
  40. public int Height;
  41. //偏移X
  42. public int OffsetX;
  43. //偏移Y
  44. public int OffsetY;
  45. //音效编号
  46. public int AudioIndex;
  47. //动效编号
  48. public Anime.EffectType Effect;
  49. //GraphicInfo;
  50. public GraphicInfoData GraphicInfo;
  51. //动画Sprite
  52. public Dictionary<int,Sprite> AnimeSprites = new Dictionary<int, Sprite>();
  53. }
  54. //动画数据
  55. public class AnimeDetail
  56. {
  57. public uint Serial;
  58. public string Version;
  59. public int Direction;
  60. public int ActionType;
  61. public uint CycleTime;
  62. public uint FrameCount;
  63. public Dictionary<int,Texture2D> AnimeTextures = new Dictionary<int, Texture2D>();
  64. // public Texture2D AnimeTexture;
  65. public AnimeFrameInfo[] AnimeFrameInfos;
  66. // public byte[] unknown;
  67. }
  68. //动画相关Enum类型
  69. public class Anime : MonoBehaviour
  70. {
  71. //方向
  72. public enum DirectionType
  73. {
  74. NULL = -1,
  75. North = 0,
  76. NorthEast = 1,
  77. East = 2,
  78. SouthEast = 3,
  79. South = 4,
  80. SouthWest = 5,
  81. West = 6,
  82. NorthWest = 7
  83. }
  84. //方向九宫映射表
  85. public static DirectionType[,] DirectionTypeMap = new DirectionType[3,3]
  86. {
  87. {DirectionType.North,DirectionType.NorthEast,DirectionType.East},
  88. {DirectionType.NorthWest,DirectionType.NULL,DirectionType.SouthEast},
  89. {DirectionType.West,DirectionType.SouthWest,DirectionType.South}
  90. };
  91. //动作
  92. public enum ActionType
  93. {
  94. NULL = -1,
  95. Stand = 0,
  96. Walk = 1,
  97. BeforeRun = 2,
  98. Run = 3,
  99. AfterRun = 4,
  100. Attack = 5,
  101. Magic = 6,
  102. Throw = 7,
  103. Hurt = 8,
  104. Defence = 9,
  105. Dead = 10,
  106. Sit = 11,
  107. Hi = 12,
  108. Happy = 13,
  109. Angry = 14,
  110. Sad = 15,
  111. Shake = 16,
  112. Rock = 17,
  113. Scissors = 18,
  114. Paper = 19,
  115. Fishing = 20,
  116. }
  117. //动效
  118. public enum EffectType
  119. {
  120. Hit =1,
  121. HitOver =2
  122. }
  123. public enum PlayType
  124. {
  125. Loop,
  126. Once,
  127. OnceAndDestroy
  128. }
  129. //动画列表缓存 Serial -> AnimeInfo
  130. private static Dictionary<uint, AnimeInfo> _animeInfoCache = new Dictionary<uint, AnimeInfo>();
  131. //加载动画数据
  132. public static void Init(string Version,FileInfo animeInfoFile,FileInfo animeFile)
  133. {
  134. //创建流读取器
  135. FileStream infoFileStream = animeInfoFile.OpenRead();
  136. FileStream dataFileStream = animeFile.OpenRead();
  137. BinaryReader infoFileReader = new BinaryReader(infoFileStream);
  138. BinaryReader dataFileReader = new BinaryReader(dataFileStream);
  139. // Dictionary<uint, AnimeInfo> animeInfos = new Dictionary<uint, AnimeInfo>();
  140. long DataLength = infoFileStream.Length / 12;
  141. for (int i = 0; i < DataLength; i++)
  142. {
  143. //初始化对象
  144. AnimeInfo animeInfo = new AnimeInfo();
  145. animeInfo.Version = Version;
  146. animeInfo.Serial = BitConverter.ToUInt32(infoFileReader.ReadBytes(4),0);
  147. // Debug.Log(animeInfo.Serial);
  148. animeInfo.Addr = BitConverter.ToUInt32(infoFileReader.ReadBytes(4),0);
  149. animeInfo.ActionCount = infoFileReader.ReadUInt16();
  150. animeInfo.Unknow = infoFileReader.ReadBytes(2);
  151. dataFileStream.Position = animeInfo.Addr;
  152. for (int j = 0; j < animeInfo.ActionCount; j++)
  153. {
  154. AnimeDetail animeData = new AnimeDetail();
  155. animeData.Version = Version;
  156. animeData.Serial = animeInfo.Serial;
  157. animeData.Direction = dataFileReader.ReadUInt16();
  158. animeData.ActionType = dataFileReader.ReadUInt16();
  159. animeData.CycleTime = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
  160. animeData.FrameCount = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
  161. animeData.AnimeFrameInfos = new AnimeFrameInfo[animeData.FrameCount];
  162. // if (animeInfo.Index == 101201) Debug.Log("----------------------------------");
  163. for (int k = 0; k < animeData.FrameCount; k++)
  164. {
  165. animeData.AnimeFrameInfos[k] = new AnimeFrameInfo();
  166. //GraphicIndex序号
  167. animeData.AnimeFrameInfos[k].GraphicIndex = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
  168. animeData.AnimeFrameInfos[k].OffsetX = BitConverter.ToInt16(dataFileReader.ReadBytes(2),0);
  169. animeData.AnimeFrameInfos[k].OffsetY = BitConverter.ToInt16(dataFileReader.ReadBytes(2),0);
  170. //标识位
  171. int flag = BitConverter.ToInt16(dataFileReader.ReadBytes(2),0);
  172. // if (animeData.Index == 110053) Debug.Log("FLAG---" + " " + k + " " + flag);
  173. if (flag>20000)
  174. {
  175. //击打判定
  176. animeData.AnimeFrameInfos[k].Effect = EffectType.Hit;
  177. animeData.AnimeFrameInfos[k].AudioIndex = flag - 20000;
  178. }
  179. else if(flag>10000)
  180. {
  181. //攻击动作结束判定
  182. animeData.AnimeFrameInfos[k].Effect = EffectType.HitOver;
  183. animeData.AnimeFrameInfos[k].AudioIndex = flag - 10000;
  184. }
  185. else
  186. {
  187. animeData.AnimeFrameInfos[k].AudioIndex = flag;
  188. }
  189. }
  190. if (!animeInfo.AnimeDatas.ContainsKey(animeData.Direction))
  191. animeInfo.AnimeDatas.Add(animeData.Direction, new Dictionary<int, AnimeDetail>());
  192. animeInfo.AnimeDatas[animeData.Direction][animeData.ActionType] = animeData;
  193. _animeInfoCache[animeInfo.Serial] = animeInfo;
  194. }
  195. }
  196. infoFileReader.Dispose();
  197. infoFileReader.Close();
  198. dataFileReader.Dispose();
  199. dataFileReader.Close();
  200. infoFileStream.Close();
  201. dataFileStream.Close();
  202. Debug.Log("[CGTool] 加载AnimeInfo - 文件: " + animeInfoFile.Name + " 动画总量: " + DataLength);
  203. }
  204. //获取动画数据信息
  205. public static AnimeInfo GetAnimeInfo(uint serial)
  206. {
  207. _animeInfoCache.TryGetValue(serial, out var animeInfo);
  208. return animeInfo;
  209. }
  210. //获取动画数据
  211. public static AnimeDetail GetAnimeDetail(uint serial,DirectionType Direction,ActionType Action)
  212. {
  213. AnimeInfo animeInfo = GetAnimeInfo(serial);
  214. if (animeInfo == null) return null;
  215. if (animeInfo.AnimeDatas.ContainsKey((int)Direction))
  216. {
  217. if (animeInfo.AnimeDatas[(int) Direction].ContainsKey((int) Action))
  218. {
  219. AnimeDetail animeDetail = animeInfo.AnimeDatas[(int) Direction][(int) Action];
  220. // if(animeDetail.AnimeTexture == null) prepareAnimeFrames(animeDetail);
  221. return animeDetail;
  222. }
  223. }
  224. return null;
  225. }
  226. //预处理动画图形合批烘焙
  227. public static void BakeAnimeFrames(AnimeDetail animeDetail,int palet = 0)
  228. {
  229. if(animeDetail.AnimeTextures.ContainsKey(palet)) return;
  230. //所有帧的图形数据
  231. GraphicDetail[] graphicDetails = new GraphicDetail[animeDetail.FrameCount];
  232. //合并后的Texture2D尺寸
  233. uint textureWidth = 0;
  234. uint textureHeight = 0;
  235. for (var i = 0; i < animeDetail.FrameCount; i++)
  236. {
  237. //载入图档
  238. GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoDataByIndex(animeDetail.Version,animeDetail.AnimeFrameInfos[i].GraphicIndex);
  239. if (graphicInfoData == null) continue;
  240. GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(graphicInfoData, palet);
  241. if(graphicDetail == null) continue;
  242. graphicDetails[i] = graphicDetail;
  243. if(graphicDetail.Height > textureHeight) textureHeight = graphicDetail.Height;
  244. textureWidth += graphicDetail.Width + 5;
  245. animeDetail.AnimeFrameInfos[i].Width = (int) graphicDetail.Width;
  246. animeDetail.AnimeFrameInfos[i].Height = (int) graphicDetail.Height;
  247. animeDetail.AnimeFrameInfos[i].OffsetX = (int) graphicInfoData.OffsetX;
  248. animeDetail.AnimeFrameInfos[i].OffsetY = (int) graphicInfoData.OffsetY;
  249. animeDetail.AnimeFrameInfos[i].GraphicInfo = graphicInfoData;
  250. }
  251. //合并图档
  252. Texture2D texture2dMix = new Texture2D((int) textureWidth, (int) textureHeight, TextureFormat.RGBA4444, false,false);
  253. texture2dMix.filterMode = FilterMode.Point;
  254. Color32 transparentColor = new Color32(0, 0, 0, 0);
  255. Color32[] transparentColors = new Color32[texture2dMix.width * texture2dMix.height];
  256. for (var i = 0; i < transparentColors.Length; i++)
  257. {
  258. transparentColors[i] = transparentColor;
  259. }
  260. texture2dMix.SetPixels32(transparentColors,0);
  261. int offsetX = 0;
  262. for (var i = 0; i < animeDetail.FrameCount; i++)
  263. {
  264. GraphicDetail graphicDetail = graphicDetails[i];
  265. if(graphicDetail == null) continue;
  266. texture2dMix.SetPixels32((int) offsetX, 0, (int) graphicDetail.Width,
  267. (int) graphicDetail.Height,
  268. graphicDetail.Sprite.texture.GetPixels32());
  269. offsetX += (int) graphicDetail.Width + 5;
  270. }
  271. texture2dMix.Apply();
  272. animeDetail.AnimeTextures.Add(palet,texture2dMix);
  273. //创建动画每帧Sprite
  274. offsetX = 0;
  275. for (var l = 0; l < animeDetail.FrameCount; l++)
  276. {
  277. if(graphicDetails[l] == null) continue;
  278. AnimeFrameInfo animeFrameInfo = animeDetail.AnimeFrameInfos[l];
  279. Vector2 pivot = new Vector2(0f, 1f);
  280. pivot.x += -(animeFrameInfo.OffsetX * 1f) / animeFrameInfo.Width;
  281. pivot.y -= (-animeFrameInfo.OffsetY * 1f) / animeFrameInfo.Height;
  282. Sprite sprite = Sprite.Create(texture2dMix, new Rect(offsetX, 0,
  283. animeDetail.AnimeFrameInfos[l].Width, animeDetail.AnimeFrameInfos[l].Height),
  284. pivot, 1, 1, SpriteMeshType.FullRect);
  285. offsetX += animeDetail.AnimeFrameInfos[l].Width + 5;
  286. animeFrameInfo.AnimeSprites.Add(palet, sprite);
  287. }
  288. }
  289. }
  290. }