Skip to content

Commit

Permalink
Improve skeletons
Browse files Browse the repository at this point in the history
* Animation skeleton is now changeable
* Skeleton id in SKLB is now changeable
* Parent/fallback skeletons can now be edited in SKLB
  • Loading branch information
AsgardXIV committed Aug 2, 2022
1 parent c1d61c1 commit ab9e52b
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 30 deletions.
121 changes: 91 additions & 30 deletions XAT/XAT/Game/Formats/Sklb/SklbFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,37 @@ public class SklbFormat
{
private const string MAGIC = "blks";

public byte[] PreHavokData { get; set; }
public short Header1 { get; set; }
public short Header2 { get; set; }

[DependsOn(nameof(Header1), nameof(Header2))]
public bool OldHeader
{
get
{
switch (Header2)
{
case 0x3132:
return true;

case 0x3133:
return false;

default:
Log.Warning($"Unknown sklb headers: Part 1: 0x{Header1.ToString("X")}, Part 2: 0x{Header2.ToString("X")} - Assume it's new for now");
return false;
}
}
}

public int Unk1 { get; set; }

public int Skeleton { get; set; }
public int[] ParentSkeletons { get; set; }

public byte[] Unk2 { get; set; }
public byte[] Unk3 { get; set; }

public byte[] HavokData { get; set; }

public SklbFormat(BinaryReader reader)
Expand All @@ -23,51 +53,82 @@ public SklbFormat(BinaryReader reader)
throw new Exception("Invalid sklb file - magic incorrect");

// Read header
int header1 = reader.ReadInt16();
int header2 = reader.ReadInt16();
bool oldHeader;
Header1 = reader.ReadInt16();
Header2 = reader.ReadInt16();
Log.Debug($"Sklb headers were: Part 1: 0x{Header1.ToString("X")}, Part 2: 0x{Header2.ToString("X")}");

Log.Debug($"Sklb headers were: Part 1: 0x{header1.ToString("X")}, Part 2: 0x{header2.ToString("X")}");

switch (header2)
{
case 0x3132:
oldHeader = true;
break;

case 0x3133:
oldHeader = false;
break;

default:
Log.Warning($"Unknown sklb headers: Part 1: 0x{header1.ToString("X")}, Part 2: 0x{header2.ToString("X")} - Assume it's new for now");
oldHeader = false;
break;
}

// Havok offset
// Offsets
int havokOffset;
if (oldHeader)
int unknownOffset;
if (OldHeader)
{
reader.BaseStream.Seek(10, SeekOrigin.Begin);
unknownOffset = reader.ReadInt16();
havokOffset = reader.ReadInt16();
}
else
{
reader.BaseStream.Seek(12, SeekOrigin.Begin);
unknownOffset = reader.ReadInt32();
havokOffset = reader.ReadInt32();
Unk1 = reader.ReadInt32();
}

// Havok data
reader.BaseStream.Seek(0, SeekOrigin.Begin);
this.PreHavokData = reader.ReadBytes(havokOffset);
Skeleton = reader.ReadInt32();

ParentSkeletons = new int[4];
for (int i = 0; i < ParentSkeletons.Length; ++i)
{
ParentSkeletons[i] = reader.ReadInt32();
}

this.Unk2 = reader.ReadBytes((int)(unknownOffset - reader.BaseStream.Position));

this.Unk3 = reader.ReadBytes((int)(havokOffset - reader.BaseStream.Position));

this.HavokData = reader.ReadBytes((int)reader.BaseStream.Length - havokOffset);
}

public void Serialize(BinaryWriter writer)
{
writer.Write(this.PreHavokData);
writer.WriteEncodedString(MAGIC);
writer.Write(Header1);
writer.Write(Header2);

if(OldHeader)
{
writer.Write((short)0);
writer.Write((short)0);
}
else
{
writer.Write((int)0);
writer.Write((int)0);
writer.Write(Unk1);
}

writer.Write(Skeleton);
for (int i = 0; i < ParentSkeletons.Length; ++i)
{
writer.Write(ParentSkeletons[i]);
}

writer.Write(Unk2);
int firstOffset = (int) writer.BaseStream.Position;
writer.Write(Unk3);

int havokOffset = (int)writer.BaseStream.Position;
writer.Write(this.HavokData);

writer.BaseStream.Seek(8, SeekOrigin.Begin);
if (OldHeader)
{
writer.Write((short)firstOffset);
writer.Write((short)havokOffset);
}
else
{
writer.Write((int)firstOffset);
writer.Write((int)havokOffset);
}
}

public byte[] ToBytes()
Expand Down
3 changes: 3 additions & 0 deletions XAT/XAT/UI/Animation/AnimationEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@

<TabItem Header="Advanced">
<StackPanel>
<TextBox Text="{Binding Animation.Container.Skeleton}" materialDesign:HintAssist.Hint="Skeleton Id" materialDesign:HintAssist.HelperText="The skeleton this PAP is bound to." />

<Separator Opacity="0" Height="20"/>
<TextBox Text="{Binding Animation.Data.Name}" materialDesign:HintAssist.Hint="Animation Name" materialDesign:HintAssist.HelperText="The name of this animation." />

<Separator Opacity="0" Height="20"/>
Expand Down
30 changes: 30 additions & 0 deletions XAT/XAT/UI/Skeleton/SkeletonTab.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,36 @@
</GroupBox>

<StackPanel Grid.Column="2">
<GroupBox Header="Properties">
<StackPanel>
<TextBox Text="{Binding Skeleton.Skeleton}" materialDesign:HintAssist.Hint="Skeleton Id" materialDesign:HintAssist.HelperText="The root skeleton." />

<Separator Opacity="0" Height="20"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="10" />
<ColumnDefinition />
<ColumnDefinition Width="10" />
<ColumnDefinition />
<ColumnDefinition Width="10" />
<ColumnDefinition />
</Grid.ColumnDefinitions>

<TextBox Grid.Column="0" Text="{Binding Skeleton.ParentSkeletons[0]}" materialDesign:HintAssist.Hint="Parent 1" materialDesign:HintAssist.HelperText="Parent skeleton 1." />

<TextBox Grid.Column="2" Text="{Binding Skeleton.ParentSkeletons[1]}" materialDesign:HintAssist.Hint="Parent 2" materialDesign:HintAssist.HelperText="Parent skeleton 2." />

<TextBox Grid.Column="4" Text="{Binding Skeleton.ParentSkeletons[2]}" materialDesign:HintAssist.Hint="Parent 3" materialDesign:HintAssist.HelperText="Parent skeleton 3." />

<TextBox Grid.Column="6" Text="{Binding Skeleton.ParentSkeletons[3]}" materialDesign:HintAssist.Hint="Parent 4" materialDesign:HintAssist.HelperText="Parent skeleton 4." />
</Grid>
<Separator Opacity="0" Height="20"/>
</StackPanel>
</GroupBox>

<Separator Opacity="0" Height="10" />

<GroupBox Header="Import">
<local:SkeletonImportView Skeleton="{Binding Skeleton}" />
</GroupBox>
Expand Down

0 comments on commit ab9e52b

Please sign in to comment.