123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- /**
- * 魔力宝贝图档解析脚本 - CGTool
- *
- * @Author HonorLee (dev@honorlee.me)
- * @Version 1.0 (2023-04-15)
- * @License GPL-3.0
- *
- * Graphic.cs 图档解析类
- */
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using UnityEngine;
- namespace CGTool
- {
- public class GraphicData
- {
- //版本号
- public int Version;
- //索引
- public uint Index;
- //地图编号
- public uint MapSerial;
- //图档宽度
- public uint Width;
- //图档高度
- public uint Height;
- //图档偏移X
- public int OffsetX;
- //图档偏移Y
- public int OffsetY;
- //Palet调色板Index
- public int PaletIndex;
- //图档Sprite
- public Sprite Sprite;
- //图档主色调,用于小地图绘制
- public Color32 PrimaryColor;
- }
- public class Graphic
- {
- //缓存Addr Version -> Addr -> PaletIndex -> GraphicData
- private static Dictionary<int, Dictionary<uint, Dictionary<int, GraphicData>>> _cache =
- new Dictionary<int, Dictionary<uint, Dictionary<int, GraphicData>>>();
- //
- // //缓存Index映射 Version -> Index -> PaletIndex -> GraphicData
- // private static Dictionary<int, Dictionary<uint, Dictionary<int, GraphicData>>> _indexCache =
- // new Dictionary<int, Dictionary<uint, Dictionary<int, GraphicData>>>();
- //
- // //缓存MapSerial映射 Version -> MapSerial -> PaletIndex -> GraphicData
- // private static Dictionary<int, Dictionary<uint, Dictionary<int, GraphicData>>> _serialCache =
- // new Dictionary<int, Dictionary<uint, Dictionary<int, GraphicData>>>();
-
- private static List<string> _graphicPaths = new List<string>()
- {
- //龙之沙漏 之前版本前图档数据
- "Graphic_66.bin",
- //龙之沙漏 版本图档数据
- "GraphicEx_5.bin"
- };
-
- //根据地址获取GraphicData
- public static GraphicData GetGraphicData(GraphicInfoData graphicInfoData,int PaletIndex=0)
- {
- GraphicData graphicData = null;
- //缓存数据
- if (_cache.ContainsKey(graphicInfoData.Version))
- {
- if (_cache[graphicInfoData.Version].ContainsKey(graphicInfoData.Addr))
- {
- if (_cache[graphicInfoData.Version][graphicInfoData.Addr].ContainsKey(PaletIndex))
- {
- graphicData = _cache[graphicInfoData.Version][graphicInfoData.Addr][PaletIndex];
- }
- }
- }
- //无缓存则加载数据
- if (graphicData == null) graphicData = _loadGraphicData(graphicInfoData, PaletIndex);
-
- return graphicData;
- }
- //初始化加载GraphicInfo
- private static GraphicData _loadGraphicData(GraphicInfoData graphicInfoData, int PaletIndex = 0)
- {
- //查找图档文件
- string fileName = _graphicPaths[graphicInfoData.Version];
- FileInfo file = new FileInfo(CGTool.BaseFolder + "/" + fileName);
- if (!file.Exists) return null;
- //创建流读取器
- FileStream fileStream = file.OpenRead();
- BinaryReader fileReader = new BinaryReader(fileStream);
- //获取调色板
- List<Color32> palet = Palet.GetPalet(PaletIndex);
- GraphicData graphicData = new GraphicData();
- List<Color32> pixels = new List<Color32>();
- //调整流指针
- fileStream.Position = graphicInfoData.Addr;
- //读入目标字节集
- byte[] Content = fileReader.ReadBytes((int) graphicInfoData.Length);
- //关闭文件链接
- fileReader.Dispose();
- fileReader.Close();
- fileStream.Close();
- //读取缓存字节集
- BinaryReader contentReader = new BinaryReader(new MemoryStream(Content));
- //16字节头信息
- byte[] HEAD = contentReader.ReadBytes(2);
- int Version = contentReader.ReadByte();
- int Unknow = contentReader.ReadByte();
- uint Width = contentReader.ReadUInt32();
- uint Height = contentReader.ReadUInt32();
- uint Length = contentReader.ReadUInt32();
- //主色调色值
- int r = 0;
- int g = 0;
- int b = 0;
- //数据长度
- uint contentLen = Length - 16;
- //非压缩型数据
- if (Version == 0)
- {
- while (true)
- {
- Color32 color32;
- try
- {
- color32 = palet[contentReader.ReadByte()];
- }
- catch (Exception e)
- {
- break;
- }
- pixels.Add(color32);
- r += color32.r;
- g += color32.g;
- b += color32.b;
- }
- }
- else
- //压缩型数据解压
- {
- int count = 0;
- while (true)
- {
- count++;
- int head;
- try
- {
- head = contentReader.ReadByte();
- }
- catch (Exception e)
- {
- break;
- }
-
- int repeat = 0;
- Color32 color32;
- if (head < 0x10)
- {
- repeat = head;
- for (var i = 0; i < repeat; i++)
- {
- color32 = palet[contentReader.ReadByte()];
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0x20)
- {
- repeat = head % 0x10 * 0x100 + contentReader.ReadByte();
- for (var i = 0; i < repeat; i++)
- {
- color32 = palet[contentReader.ReadByte()];
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0x80)
- {
- repeat = head % 0x20 * 0x10000 + contentReader.ReadByte() * 0x100 + contentReader.ReadByte();
- for (var i = 0; i < repeat; i++)
- {
- color32 = palet[contentReader.ReadByte()];
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0x90)
- {
- repeat = head % 0x80;
- color32 = palet[contentReader.ReadByte()];
- for (var i = 0; i < repeat; i++)
- {
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0xa0)
- {
- color32 = palet[contentReader.ReadByte()];
- repeat = head % 0x90 * 0x100 + contentReader.ReadByte();
- for (var i = 0; i < repeat; i++)
- {
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0xc0)
- {
- color32 = palet[contentReader.ReadByte()];
- repeat = head % 0xa0 * 0x10000 + contentReader.ReadByte() * 0x100 + contentReader.ReadByte();
- for (var i = 0; i < repeat; i++)
- {
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0xd0)
- {
- color32 = Color.clear;
- repeat = head % 0xc0;
- for (var i = 0; i < repeat; i++)
- {
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else if (head < 0xe0)
- {
- color32 = Color.clear;
- repeat = head % 0xd0 * 0x100 + contentReader.ReadByte();
- for (var i = 0; i < repeat; i++)
- {
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- else
- {
- color32 = Color.clear;
- repeat = head % 0xe0 * 0x10000 + contentReader.ReadByte() * 0x100 + contentReader.ReadByte();
- for (var i = 0; i < repeat; i++)
- {
- r += color32.r;
- g += color32.g;
- b += color32.b;
- pixels.Add(color32);
- }
- }
- }
- }
- //主色调计算及提亮
- r = r / pixels.Count * 2;
- g = g / pixels.Count * 2;
- b = b / pixels.Count * 2;
- if (r > 255) r = 255;
- if (g > 255) g = 255;
- if (b > 255) b = 255;
- //主色调
- Color32 primaryColor32 = new Color32((byte) r, (byte) g, (byte) b, 255);
- //释放连接
- contentReader.Dispose();
- contentReader.Close();
- //创建Sprite对象
- Texture2D texture2D = new Texture2D((int) graphicInfoData.Width, (int) graphicInfoData.Height,
- TextureFormat.RGBA32, false);
-
- int len = (int) (graphicInfoData.Width * graphicInfoData.Height);
- if (pixels.Count != len)
- {
- if (pixels.Count > len)
- {
- pixels = pixels.GetRange(0, len);
- }
- else
- {
- Color32[] temc = new Color32[len - pixels.Count];
- ArrayList.Repeat(Color.clear, len - pixels.Count).CopyTo(temc);
- pixels.AddRange(temc);
- }
- }
- texture2D.SetPixels32(pixels.ToArray());
- texture2D.filterMode = FilterMode.Point;
- // texture2D.Compress(true);
- texture2D.Apply();
-
- //直接通过Texture2D做偏移,并转为Sprite的偏移量
- Vector2 offset = new Vector2(0f, 1f);
- offset.x += -(graphicInfoData.OffsetX * 1f) / graphicInfoData.Width;
- offset.y -= (-graphicInfoData.OffsetY * 1f) / graphicInfoData.Height;
- Sprite sprite = Sprite.Create(texture2D, new Rect(0, 0, texture2D.width, texture2D.height), offset, 1,1,SpriteMeshType.FullRect);
- //写入数据
- graphicData.Version = graphicInfoData.Version;
- graphicData.Index = graphicInfoData.Index;
- graphicData.MapSerial = graphicInfoData.MapSerial;
- graphicData.Width = graphicInfoData.Width;
- graphicData.Height = graphicInfoData.Height;
- graphicData.OffsetX = graphicInfoData.OffsetX;
- graphicData.OffsetY = graphicInfoData.OffsetY;
- graphicData.PaletIndex = PaletIndex;
- graphicData.Sprite = sprite;
- graphicData.PrimaryColor = primaryColor32;
-
- //缓存
- if (!_cache.ContainsKey(graphicInfoData.Version))
- _cache.Add(graphicInfoData.Version, new Dictionary<uint, Dictionary<int, GraphicData>>());
- if(!_cache[graphicInfoData.Version].ContainsKey(graphicInfoData.Addr)) _cache[graphicInfoData.Version].Add(graphicInfoData.Addr,new Dictionary<int, GraphicData>());
- if (!_cache[graphicInfoData.Version][graphicInfoData.Addr].ContainsKey(PaletIndex))
- _cache[graphicInfoData.Version][graphicInfoData.Addr].Add(PaletIndex, graphicData);
-
- return graphicData;
- }
-
- }
- }
|