KopMap/Assets/MindPowerSdk/Map/SceneObjFile.cs

157 lines
4.8 KiB
C#
Raw Normal View History

2025-04-03 02:30:16 +08:00
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using MindPowerSdk;
using UnityEngine;
namespace MindPowerSdk
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct SceneObjInfo
{
public ushort TypeId; // 高2位是type(0: 场景物件, 1: 特效物件), 其余是ID
public int X; // 相对坐标
public int Y;
public short HeightOff;
public short YawAngle;
public short Scale; // 保留未使用
public short GetTypeId()
{
return (short)(TypeId >> 14);
}
public short GetID()
{
return (short)(TypeId & 0x3FFF);
}
public override string ToString()
{
return $"type={GetTypeId()},id={GetID()},x={X},y={Y},height_off={HeightOff},yaw_angle={YawAngle},scale={Scale}";
}
}
public class SceneObjFile
{
/// <summary>
/// 文件头
/// </summary>
public struct Header
{
public string Title; // "HF Object File!" char[16]
public int Version;
public int FileSize;
public int SectionCntX; // 地图的横向区域数
public int SectionCntY; // 地图的纵向区域数
public int SectionWidth; // 区域的宽度单位Tile
public int SectionHeight; // 区域的高度单位Tile
public int SectionObjNum; // 区域允许的最大物件数
}
/// <summary>
/// 用来索引文件中对象的数据
/// </summary>
public struct SSectionIndex
{
public int ObjInfoPos;
public int ObjNum;
}
public Header FileHeader { get; private set; }
SSectionIndex[,] sectionIndex;
public List<SceneObjInfo>[,] objInfos;
public unsafe int Load(string obj_file)
{
FileStream fs = File.OpenRead(obj_file);
BinaryReader r = new BinaryReader(fs);
long size = r.BaseStream.Length;
Header s = new Header();
s.Title = Encoding.ASCII.GetString(r.ReadBytes(16));
s.Version = r.ReadInt32();
s.FileSize = r.ReadInt32(); // 实际是32位
s.SectionCntX = r.ReadInt32();
s.SectionCntY = r.ReadInt32();
s.SectionWidth = r.ReadInt32();
s.SectionHeight = r.ReadInt32();
s.SectionObjNum = r.ReadInt32();
FileHeader = s;
Debug.Log(JsonUtility.ToJson(s));
if (s.FileSize != size)
{
Debug.LogWarning($"{obj_file} 文件szie不匹配: {s.FileSize} != {size}");
return -1;
}
if (s.Version != 600)
{
Debug.LogWarning($"{obj_file} 版本只支持600: 当前是={s.Version}");
return -1;
}
// 读取索引信息
sectionIndex = new SSectionIndex[s.SectionCntX, s.SectionCntY];
for (int y = 0; y < s.SectionCntY; y++)
{
for (int x = 0; x < s.SectionCntX; x++)
{
SSectionIndex data = new SSectionIndex();
data.ObjInfoPos = r.ReadInt32();
data.ObjNum = r.ReadInt32();
sectionIndex[x, y] = data;
if (data.ObjNum != 0)
Debug.Log(JsonUtility.ToJson(data));
}
}
// 读取场景物体
objInfos = new List<SceneObjInfo>[s.SectionCntX, s.SectionCntY];
for (int y = 0; y < s.SectionCntY; y++)
{
for (int x = 0; x < s.SectionCntX; x++)
{
SSectionIndex idx = sectionIndex[x, y];
if (idx.ObjNum == 0)
continue;
var list = objInfos[x, y] ??= new List<SceneObjInfo>();
r.BaseStream.Seek(idx.ObjInfoPos, SeekOrigin.Begin);
for (int i = 0; i < idx.ObjNum; i++)
{
byte[] tmpBytes = r.ReadBytes(sizeof(SceneObjInfo));
SceneObjInfo sceneObjInfo = StructReader.ReadStructFromArray<SceneObjInfo>(tmpBytes);
// 转成绝对坐标
int sectionX = x * s.SectionWidth * 100;
int sectionY = y * s.SectionHeight * 100;
sceneObjInfo.X += sectionX;
sceneObjInfo.Y += sectionY;
list.Add(sceneObjInfo);
Debug.Log(sceneObjInfo.ToString());
}
}
}
return 0;
}
}
}