Skip to content
This repository has been archived by the owner on Feb 14, 2025. It is now read-only.

Commit

Permalink
Animation2 rewrite based on Pepa Kopinec's template
Browse files Browse the repository at this point in the history
  • Loading branch information
Kamzik123 committed Aug 2, 2024
1 parent 9b80325 commit 585b7f6
Show file tree
Hide file tree
Showing 7 changed files with 382 additions and 66 deletions.
30 changes: 30 additions & 0 deletions Mafia2Libs/Core/IO/FileAnimation2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using ResourceTypes.Animation2;
using System;
using System.IO;

namespace Core.IO
{
public class FileAnimation2 : FileBase
{
public FileAnimation2(FileInfo info) : base(info)
{

}

public override bool Open()
{
Animation2 anim = new(file.FullName);
return true;
}

public override void Save()
{
throw new NotImplementedException();
}

public override string GetExtensionUpper()
{
return "AN2";
}
}
}
2 changes: 2 additions & 0 deletions Mafia2Libs/Core/IO/FileFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public static FileBase ConstructFromFileInfo(FileInfo info)
return new FileRoadmapClassic(info);
case "IFL":
return new FileIFL(info);
case "AN2":
return new FileAnimation2(info);
default:
return new FileBase(info);
}
Expand Down
135 changes: 135 additions & 0 deletions Mafia2Libs/ResourceTypes/FileTypes/Animations/AnimTrack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using Gibbed.Illusion.FileFormats.Hashing;
using System;
using System.IO;
using static ResourceTypes.FrameNameTable.FrameNameTable;

namespace ResourceTypes.Animation2
{
public class AnimTrack
{
public ulong BoneID { get; set; }
public byte Flags { get; set; }
public bool IsDataPresent { get; set; }
public byte DataFlags { get; set; }
public short NumKeyFrames { get; set; }
public byte ComponentSize { get; set; }
public byte TimeSize { get; set; }
public uint PackedReferenceQuat { get; set; }
public float Scale { get; set; }
public float Duration { get; set; }
public byte[] KeyFrameData { get; set; }
public float Unk00 { get; set; }
public UnkDataBlock[] UnkData { get; set; } = new UnkDataBlock[0];
public AnimTrack()
{

}

public AnimTrack(Stream s)
{
Read(s);
}

public AnimTrack(BinaryReader br)
{
Read(br);
}

public void Read(Stream s)
{
using (BinaryReader br = new(s))
{
Read(br);
}
}

public void Read(BinaryReader br)
{
BoneID = br.ReadUInt64();
Flags = br.ReadByte();
IsDataPresent = br.ReadBoolean();
DataFlags = br.ReadByte();
NumKeyFrames = br.ReadInt16();
ComponentSize = br.ReadByte();
TimeSize = br.ReadByte();
PackedReferenceQuat = br.ReadUInt32();
Scale = br.ReadSingle();
Duration = br.ReadSingle();
KeyFrameData = br.ReadBytes(GetKeyframeDataSize(NumKeyFrames, ComponentSize, TimeSize));

if ((Flags & 0x01) == 1)
{
short Count = br.ReadInt16();
Unk00 = br.ReadSingle();
UnkData = new UnkDataBlock[Count];

for (int i = 0; i < UnkData.Length; i++)
{
UnkData[i] = new(br);
}
}

//DumpTrackData();
}

public int GetKeyframeSize(int ComponentSize, int TimeSize)
{
// Perform the calculation and apply the bitwise AND operation
return (3 * ComponentSize + TimeSize + 2) & 0x7F;
}

public int GetKeyframeDataSize(int NumRotationFrames, int ComponentSize, int TimeSize)
{
// Perform the calculation and apply the bitwise AND operation
return 4 + 4 * (NumRotationFrames * GetKeyframeSize(ComponentSize, TimeSize) / 32);
}

private void DumpTrackData()
{
string folderPath = "%userprofile%\\Desktop\\AnimTracks";
string path = Environment.ExpandEnvironmentVariables(folderPath);

if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}

File.WriteAllBytes(Path.Combine(path, $"AnimTrack_{BoneID}_{FNV32.Hash(KeyFrameData, 0, KeyFrameData.Length)}.bin"), KeyFrameData);
}
}

public class UnkDataBlock
{
public short BoneIndex { get; set; }
public byte[] Data { get; set; } = new byte[10];

public UnkDataBlock()
{

}

public UnkDataBlock(Stream s)
{
Read(s);
}

public UnkDataBlock(BinaryReader br)
{
Read(br);
}

public void Read(Stream s)
{
using (BinaryReader br = new(s))
{
Read(br);
}
}

public void Read(BinaryReader br)
{
BoneIndex = br.ReadInt16();
Data = br.ReadBytes(10);
}
}
}
142 changes: 87 additions & 55 deletions Mafia2Libs/ResourceTypes/FileTypes/Animations/Animation2.cs
Original file line number Diff line number Diff line change
@@ -1,65 +1,97 @@
using System.IO;
using System.Numerics;
using Utils.Logging;

namespace ResourceTypes.Animation2
{
public class Animation2Loader
public class Animation2
{
private int animSetID; //usually in the name. Different types. If not using skeleton, it's 0xFFFF
private byte version; //Potentially Version 2, Because why not, it is Animation2. :)
private int magic; //IDA says 0xFA5612BC
private short unk0;
private short unk1;
private Vector4 unk2;
private Vector3 unk3;
private Vector3 unk4;
private ulong hash;
private byte unk5;
private float unk6;
private short unk7;
private byte unk8;
private ulong boneID;
private byte unk9;


//private TransformMatrix matrix; //matrix of the root?
//private ulong hash; //hash of the animation?
//private byte unk0; //usually 0? right after hash.
//private Half[] bonePos = new Half[3]; //potential bone positionings.
//private byte unk1; //usually 3? right after the position.
//private long traceBone; //Detected trace (1000), or 0
//private byte unk2; //usually 1? after the traceBone, and before counts?
//private short unkS1; //usually 0xFF?
//private short unkS2; //count1? timeline count? (Number of frames?)
//private short unkS3; //count2? Bone count.
//private TransformMatrix boneMatrix; //matrix of the bone?

public void ReadFromFile(BinaryReader reader)
public Header Header { get; set; } = new();
public bool IsDataPresent { get; set; } //Not confirmed?
public Event[] Events { get; set; } = new Event[0];
public ushort Unk00 { get; set; }
public ushort Unk01 { get; set; }
public AnimTrack[] Tracks { get; set; } = new AnimTrack[0];
public short[] UnkShorts00 { get; set; } = new short[0];
public short[] UnkShorts01 { get; set; } = new short[0];

public Animation2()
{

}

public Animation2(string fileName)
{
Read(fileName);
}

public Animation2(Stream s)
{
animSetID = reader.ReadInt32();
version = reader.ReadByte();
magic = reader.ReadInt32();
//matrix = new TransformMatrix(reader);
//hash = reader.ReadUInt64();
//unk0 = reader.ReadByte();
//bonePos[0] = Half.ToHalf(reader.ReadBytes(2), 0);
//bonePos[1] = Half.ToHalf(reader.ReadBytes(2), 0);
//bonePos[2] = Half.ToHalf(reader.ReadBytes(2), 0);
//unk1 = reader.ReadByte(); //usually 3
//traceBone = reader.ReadInt64();

////if (traceBone != 0 || traceBone != 1000)
//// throw new FormatException("Error, traceBone isn't 0 or 1000");

//unkS1 = reader.ReadInt16();
//reader.ReadBytes(3); //usually 1 0 0;
////if unkS2 and unkS3 is 0, then thats EOF.
//unkS2 = reader.ReadInt16(); //must be counts
//unkS3 = reader.ReadInt16(); //must be counts
////boneMatrix = new TransformMatrix(reader);

//long boneID = reader.ReadInt64();
Read(s);
}

public Animation2(BinaryReader br)
{
Read(br);
}

public void Read(string fileName)
{
using (MemoryStream ms = new(File.ReadAllBytes(fileName)))
{
Read(ms);
}
}

public void Read(Stream s)
{
using (BinaryReader br = new(s))
{
Read(br);
}
}

public void Read(BinaryReader br)
{
Header = new(br);

IsDataPresent = br.ReadBoolean();

Events = new Event[Header.NumEvents];

for (int i = 0; i < Events.Length; i++)
{
Events[i] = new(br);
}

Unk00 = br.ReadUInt16();
Unk01 = br.ReadUInt16();
short Count2 = br.ReadInt16();

ToolkitAssert.Ensure(Header.Count == Count2, "Animation2: Count 1 != Count 2");

Count2 = IsDataPresent ? Count2++ : Count2;

Tracks = new AnimTrack[Count2];

for (int i = 0;i < Tracks.Length; i++)
{
Tracks[i] = new(br);
}

UnkShorts00 = new short[Unk01];
UnkShorts01 = new short[Count2];

for (int i = 0; i < UnkShorts00.Length; i++)
{
UnkShorts00[i] = br.ReadInt16();
}

for (int i = 0; i < UnkShorts01.Length; i++)
{
UnkShorts01[i] = br.ReadInt16();
}

ToolkitAssert.Ensure(br.BaseStream.Position == br.BaseStream.Length, "Animation2: Failed to reach EOF.");
}
}
}
38 changes: 38 additions & 0 deletions Mafia2Libs/ResourceTypes/FileTypes/Animations/Event.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.IO;

namespace ResourceTypes.Animation2
{
public class Event
{
public uint EventID { get; set; }
public float Time { get; set; }
public Event()
{

}

public Event(Stream s)
{
Read(s);
}

public Event(BinaryReader br)
{
Read(br);
}

public void Read(Stream s)
{
using (BinaryReader br = new(s))
{
Read(br);
}
}

public void Read(BinaryReader br)
{
EventID = br.ReadUInt32();
Time = br.ReadSingle();
}
}
}
Loading

0 comments on commit 585b7f6

Please sign in to comment.