Files
HX_MapEditor/Assets/Scripts/Character/AnimParserComponent.cs

257 lines
9.2 KiB
C#
Raw Normal View History

2025-07-18 22:28:40 +08:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
namespace Game.HotFix
{
public enum AnimEnum
{
Anim_cloth,
Anim_weapon,
}
// ֡<><D6A1><EFBFBD>ݽṹ
public struct FrameData
{
public int frameID;
public int startX;
public int startY;
public int width;
public int height;
public int offsetX;
public int offsetY;
public int sourceWidth;
public int sourceHeight;
public override string ToString()
{
return $"Frame {frameID}: ({startX},{startY}) {width}x{height} offset:({offsetX},{offsetY})";
}
}
public class AnimParserComponent : MonoBehaviour
{
public static AnimParserComponent instance;
// <20><EFBFBD><E6B4A2><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: [<5B><><EFBFBD><EFBFBD>ID][<5B><><EFBFBD><EFBFBD>][֡]
private Dictionary<string, Dictionary<int, List<FrameData>>> clothAnimData =
new Dictionary<string, Dictionary<int, List<FrameData>>>();
private Dictionary<string, Dictionary<int, List<FrameData>>> weaponAnimData =
new Dictionary<string, Dictionary<int, List<FrameData>>>();
private void Awake()
{
instance = this;
System.Diagnostics.Stopwatch stopwatch = System.Diagnostics.Stopwatch.StartNew();
LoadAndParseCSV("cloth.biz.csv", clothAnimData);
stopwatch.Stop();
Debug.Log($"<22><><EFBFBD><EFBFBD>װ<EFBFBD><D7B0>CSV {clothAnimData.Count} <20><>ʱ {stopwatch.Elapsed.Milliseconds} ms");
stopwatch.Start();
LoadAndParseCSV("weapon.biz.csv", weaponAnimData);
stopwatch.Stop();
Debug.Log($"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>CSV {weaponAnimData.Count} <20><>ʱ {stopwatch.Elapsed.Milliseconds} ms");
}
// <20><><EFBFBD>ز<EFBFBD><D8B2><EFBFBD><EFBFBD><EFBFBD>CSV<53>ļ<EFBFBD>
public void LoadAndParseCSV(string file, Dictionary<string, Dictionary<int, List<FrameData>>> AnimData)
{
string filePath = Path.Combine(Application.dataPath, "GameAssets/CSV", file);
if (!File.Exists(filePath))
{
Debug.LogError($"CSV file not found: {filePath}");
return;
}
string csvContent = File.ReadAllText(filePath);
ParseCSVContent(csvContent, AnimData);
}
// <20><><EFBFBD><EFBFBD>CSV<53>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>
public void ParseCSVContent(string csvContent, Dictionary<string, Dictionary<int, List<FrameData>>> AnimData)
{
// <20><><EFBFBD>зָ<D0B7>
var lines = csvContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
int lineCount = 0;
foreach (var line in lines)
{
lineCount++;
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(","))
continue;
try
{
// <20>ָ<EFBFBD><D6B8><EFBFBD>
var parts = line.Trim().Split(',');
if (parts.Length < 7)
{
Debug.LogWarning($"Skipping line {lineCount}: insufficient parts ({parts.Length})");
continue;
}
string partID = parts[0];
int texWidth = ParseInt(parts[1]);
int texHeight = ParseInt(parts[2]);
int frameCount = ParseInt(parts[3]); //<2F>ܹ<EFBFBD>֡<EFBFBD><D6A1>
int totalDirections = ParseInt(parts[4]); //<2F>ܹ<EFBFBD><DCB9><EFBFBD><EFBFBD><EFBFBD>
int framesPerDirection = ParseInt(parts[5]); //ÿ<><C3BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD>б<EFBFBD>
// <20><><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
for (int i = 6; i < 6 + frameCount; i++)
{
// <20><><EFBFBD>㵱ǰ<E3B5B1><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD><D1B4>ڵķ<DAB5><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int directionIndex = (i - 6) / framesPerDirection;
if (i >= parts.Length)
{
Debug.LogWarning($"Part {partID} direction {directionIndex}: expected {frameCount} frames, got {i - 6}");
break;
}
if (string.IsNullOrWhiteSpace(parts[i]))
continue;
var frameData = parts[i].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (frameData.Length < 10)
{
Debug.LogWarning($"Skipping frame data: insufficient values ({frameData.Length})");
continue;
}
FrameData frame = new FrameData
{
frameID = ParseInt(frameData[0]),
startX = ParseInt(frameData[1]),
startY = ParseInt(frameData[2]),
width = ParseInt(frameData[3]),
height = ParseInt(frameData[4]),
offsetX = ParseInt(frameData[5]),
offsetY = ParseInt(frameData[6]),
sourceWidth = ParseInt(frameData[7]),
sourceHeight = ParseInt(frameData[8])
};
if (!AnimData.ContainsKey(partID))
{
AnimData[partID] = new Dictionary<int, List<FrameData>>();
}
if (!AnimData[partID].ContainsKey(directionIndex))
{
AnimData[partID][frame.frameID / 10000] = new List<FrameData>();
}
AnimData[partID][frame.frameID / 10000].Add(frame);
}
}
catch (Exception e)
{
//Debug.LogError($"Error parsing line {lineCount}: {line}\n{e}");
}
}
}
// <20><>ȡָ<C8A1><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD>
public List<FrameData> GetFramesForPartAndDirection(Dictionary<string, Dictionary<int, List<FrameData>>> AnimData, string partID, int direction)
{
if (AnimData.TryGetValue(partID, out var directions) &&
directions.TryGetValue(direction, out var frames))
{
return frames;
}
Debug.LogWarning($"No frames found for part {partID}, direction {direction}");
return null;
}
public List<FrameData> GetFramesForPartAndDirection(AnimEnum animEnum,string partId,int direction)
{
switch (animEnum)
{
case AnimEnum.Anim_cloth:
return GetFramesForPartAndDirection(clothAnimData,partId,direction);
case AnimEnum.Anim_weapon:
return GetFramesForPartAndDirection(weaponAnimData, partId, direction);
}
return null;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õķ<C3B5><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public int GetDirectionCountForPart(string partID)
{
if (clothAnimData.TryGetValue(partID, out var directions))
{
return directions.Count;
}
return 0;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD>в<EFBFBD><D0B2><EFBFBD>ID
public List<string> GetAllPartIDs()
{
return clothAnimData.Keys.ToList();
}
// <20><>ȡ<EFBFBD>ض<EFBFBD><D8B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>з<EFBFBD><D0B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public Dictionary<int, List<FrameData>> GetPartData(string partID)
{
if (clothAnimData.TryGetValue(partID, out var directions))
{
return directions;
}
return null;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public void ClearAllData()
{
clothAnimData.Clear();
Debug.Log("Cleared all animation data");
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private int ParseInt(string value)
{
if (int.TryParse(value, out int result))
{
return result;
}
Debug.LogWarning($"Failed to parse integer: {value}");
return 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private int GetDirectionIndex(string partID)
{
if (clothAnimData.TryGetValue(partID, out var directions))
{
return directions.Count;
}
return 0;
}
// <20><><EFBFBD>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡ<EFBFBD><D3A1><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
[ContextMenu("Print Animation Data")]
public void PrintAnimationData()
{
Debug.Log("==== Animation Data Summary ====");
Debug.Log($"Total parts: {clothAnimData.Count}");
foreach (var part in clothAnimData)
{
Debug.Log($"Part: {part.Key}");
foreach (var direction in part.Value)
{
Debug.Log($" Direction {direction.Key}: {direction.Value.Count} frames");
// <20><>ӡǰ3֡<33><D6A1><EFBFBD><EFBFBD>
for (int i = 0; i < Mathf.Min(3, direction.Value.Count); i++)
{
Debug.Log($" {direction.Value[i]}");
}
if (direction.Value.Count > 3)
{
Debug.Log($" ... and {direction.Value.Count - 3} more");
}
}
}
Debug.Log("================================");
}
}
}