1
0
mirror of synced 2024-12-12 15:51:16 +01:00
Switch-Toolbox/File_Format_Library/FileFormats/Layout/Common.cs

2859 lines
85 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Syroot.Maths;
using Toolbox.Library.IO;
using Toolbox.Library.Animations;
using Toolbox.Library;
using WeifenLuo.WinFormsUI.Docking;
using System.ComponentModel;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using SharpYaml.Serialization;
namespace LayoutBXLYT
{
public class BasePane : SectionCommon, ICloneable
{
[Browsable(false)]
[YamlIgnore]
internal BxlytHeader LayoutFile;
[Browsable(false)]
[YamlIgnore]
internal PaneAnimController animController = new PaneAnimController();
[Browsable(false)]
[YamlIgnore]
internal TreeNodeCustom NodeWrapper;
[Browsable(false)]
[YamlIgnore]
internal bool IsRoot
{
get { return Parent == null; }
}
[Browsable(false)]
[YamlIgnore]
internal bool ParentIsRoot
{
get { return Parent != null && Parent.IsRoot; }
}
[YamlIgnore]
internal RenderablePane renderablePane;
[Browsable(false)]
[YamlIgnore]
internal virtual bool DisplayInEditor { get; set; } = true;
private string name;
[DisplayName("Name"), CategoryAttribute("Pane")]
public string Name
{
get { return name; }
set
{
//Adjust necessary parameters if the user changes the name
if (name != null && LayoutFile != null)
{
//Adjust name table entry
if (LayoutFile != null && LayoutFile.PaneLookup.ContainsKey(name))
LayoutFile.PaneLookup.Remove(name);
//Adjust material reference
if (this is IPicturePane)
((IPicturePane)this).Material.SetName(name, value);
else if (this is ITextPane)
((ITextPane)this).Material.SetName(name, value);
else if (this is IWindowPane)
{
var wnd = this as IWindowPane;
wnd.Content?.Material?.SetName(name, value);
if (wnd.WindowFrames != null)
{
foreach (var frame in wnd.WindowFrames)
{
if (frame.Material == null) continue;
frame.Material.SetName(name, value);
}
}
}
}
name = value;
if (LayoutFile != null && !LayoutFile.PaneLookup.ContainsKey(name))
LayoutFile.PaneLookup.Add(name, this);
}
}
[DisplayName("Is Visible"), CategoryAttribute("Flags")]
public virtual bool Visible { get; set; }
public BxlytMaterial TryGetActiveMaterial()
{
if (this is IPicturePane)
return ((IPicturePane)this).Material;
return null;
}
[DisplayName("Translate"), CategoryAttribute("Pane")]
public Vector3F Translate { get; set; }
[DisplayName("Rotate"), CategoryAttribute("Pane")]
public Vector3F Rotate { get; set; }
[DisplayName("Scale"), CategoryAttribute("Pane")]
public Vector2F Scale { get; set; }
[DisplayName("Width"), CategoryAttribute("Pane")]
public float Width { get; set; }
[DisplayName("Height"), CategoryAttribute("Pane")]
public float Height { get; set; }
[DisplayName("Origin X"), CategoryAttribute("Origin")]
public virtual OriginX originX { get; set; }
[DisplayName("Origin X"), CategoryAttribute("Origin")]
public virtual OriginY originY { get; set; }
[DisplayName("Parent Origin X"), CategoryAttribute("Origin")]
public virtual OriginX ParentOriginX { get; set; }
[DisplayName("Parent Origin Y"), CategoryAttribute("Origin")]
public virtual OriginY ParentOriginY { get; set; }
[DisplayName("Alpha"), CategoryAttribute("Alpha")]
public byte Alpha { get; set; }
[DisplayName("Influence Alpha"), CategoryAttribute("Alpha")]
public virtual bool InfluenceAlpha { get; set; }
[Browsable(false)]
[YamlIgnore]
public BasePane Parent { get; set; }
[Browsable(false)]
public List<BasePane> Childern { get; set; } = new List<BasePane>();
[Browsable(false)]
[YamlIgnore]
internal bool HasChildern
{
get { return Childern.Count > 0; }
}
public OpenTK.Matrix4 GetRotationMatrix()
{
var paneRotate = GetRotation();
OpenTK.Matrix4 rotationX = OpenTK.Matrix4.CreateRotationX(OpenTK.MathHelper.DegreesToRadians(paneRotate.X));
OpenTK.Matrix4 rotationY = OpenTK.Matrix4.CreateRotationY(OpenTK.MathHelper.DegreesToRadians(paneRotate.Y));
OpenTK.Matrix4 rotationZ = OpenTK.Matrix4.CreateRotationZ(OpenTK.MathHelper.DegreesToRadians(paneRotate.Z));
var rotationMatrix = rotationX * rotationY * rotationZ;
if (Parent != null)
rotationMatrix = Parent.GetRotationMatrix() * rotationMatrix;
return rotationMatrix;
}
public Vector3F GetTranslation()
{
var posX = Translate.X;
var posY = Translate.Y;
var posZ = Translate.Z;
if (animController.PaneSRT.ContainsKey(LPATarget.TranslateX))
posX = animController.PaneSRT[LPATarget.TranslateX];
if (animController.PaneSRT.ContainsKey(LPATarget.TranslateY))
posY = animController.PaneSRT[LPATarget.TranslateY];
if (animController.PaneSRT.ContainsKey(LPATarget.TranslateZ))
posZ = animController.PaneSRT[LPATarget.TranslateZ];
return new Vector3F(posX, posY, posZ);
}
public Vector3F GetRotation()
{
var rotX = Rotate.X;
var rotY = Rotate.Y;
var rotZ = Rotate.Z;
if (animController.PaneSRT.ContainsKey(LPATarget.RotateX))
rotX = animController.PaneSRT[LPATarget.RotateX];
if (animController.PaneSRT.ContainsKey(LPATarget.RotateY))
rotY = animController.PaneSRT[LPATarget.RotateY];
if (animController.PaneSRT.ContainsKey(LPATarget.RotateZ))
rotZ = animController.PaneSRT[LPATarget.RotateZ];
return new Vector3F(rotX, rotY, rotZ);
}
public Vector2F GetScale()
{
var scaX = Scale.X;
var scaY = Scale.Y;
if (animController.PaneSRT.ContainsKey(LPATarget.ScaleX))
scaX = animController.PaneSRT[LPATarget.ScaleX];
if (animController.PaneSRT.ContainsKey(LPATarget.ScaleY))
scaY = animController.PaneSRT[LPATarget.ScaleY];
return new Vector2F(scaX, scaY);
}
public Vector2F GetSize()
{
var scaX = Width;
var scaY = Height;
if (animController.PaneSRT.ContainsKey(LPATarget.SizeX))
scaX = animController.PaneSRT[LPATarget.SizeX];
if (animController.PaneSRT.ContainsKey(LPATarget.SizeY))
scaY = animController.PaneSRT[LPATarget.SizeY];
return new Vector2F(scaX, scaY);
}
public BasePane()
{
originX = OriginX.Center;
originY = OriginY.Center;
ParentOriginX = OriginX.Center;
ParentOriginY = OriginY.Center;
}
public virtual void LoadDefaults()
{
Alpha = 255;
Name = "";
Translate = new Vector3F(0, 0, 0);
Rotate = new Vector3F(0, 0, 0);
Scale = new Vector2F(1, 1);
Width = 30;
Height = 40;
originX = OriginX.Center;
originY = OriginY.Center;
ParentOriginX = OriginX.Center;
ParentOriginY = OriginY.Center;
InfluenceAlpha = false;
Visible = true;
}
public virtual BasePane Copy()
{
return new BasePane();
}
public object Clone()
{
BasePane copiedPane = (BasePane)this.MemberwiseClone();
if (copiedPane is IPicturePane)
((IPicturePane)copiedPane).CopyMaterial();
if (copiedPane is ITextPane)
((ITextPane)copiedPane).CopyMaterial();
if (copiedPane is IWindowPane)
((IWindowPane)copiedPane).CopyWindows();
return copiedPane;
}
public virtual UserData CreateUserData()
{
return new UserData();
}
public bool IsNullPane
{
get
{
if (this is IPicturePane)
return false;
else if (this is IWindowPane)
return false;
else if (this is ITextPane)
return false;
else if (this is IBoundryPane)
return false;
else if (this is IPartPane)
return false;
return true;
}
}
public void ResetParentTransform(BasePane newParent)
{
//We need to get the difference in the parent transform and remove it to the current transform of this pane
var transform = GetParentTransform(Parent);
var newParentTransform = GetParentTransform(newParent);
Translate += transform;
Translate -= newParentTransform;
Console.WriteLine($"newParentTransform {newParentTransform.X} {newParentTransform.Y} {newParentTransform.Z}");
Console.WriteLine($"transform {transform.X} {transform.Y} {transform.Z}");
}
private Vector3F GetParentTransform(BasePane parent) {
return GetParentTransform(parent.Translate);
}
private Vector3F GetParentTransform(Vector3F translate)
{
if (Parent != null)
translate = Parent.Translate + Parent.GetParentTransform(translate);
return translate;
}
public void KeepChildrenTransform(float newTransX, float newTransY)
{
Vector2F distance = new Vector2F(newTransX - Translate.X, newTransY - Translate.Y);
KeepChildrenTransform(distance, newTransX, newTransY);
}
private void KeepChildrenTransform(Vector2F distance, float newTransX, float newTransY)
{
if (HasChildern)
{
foreach (var child in Childern)
{
child.Translate -= new Vector3F(distance.X, distance.Y, 0);
child.KeepChildrenTransform(child.Translate.X, child.Translate.Y);
}
}
}
public CustomRectangle TransformParent(CustomRectangle rect)
{
return rect.GetTransformedRectangle(Parent, GetTranslation(),GetRotation(), GetScale());
}
private CustomRectangle rectangle;
[Browsable(false)]
[YamlIgnore]
public virtual CustomRectangle Rectangle
{
get
{
UpdateRectangle();
return rectangle;
}
}
private void UpdateRectangle()
{
rectangle = CreateRectangle();
}
public CustomRectangle CreateRectangle(uint width, uint height)
{
//Do origin transforms
var transformed = TransformOrientation((int)width, (int)height, originX, originY);
var parentTransform = ParentOriginTransform(transformed);
return new CustomRectangle(
parentTransform.X,
parentTransform.Y,
parentTransform.Z,
parentTransform.W);
}
public void TransformRectangle(LayoutViewer.PickAction pickAction, CustomRectangle selectionBox, float pickMouseX, float pickMouseY)
{
CustomRectangle currentRectangle = this.CreateRectangle();
currentRectangle = currentRectangle.GetTransformedRectangle(Parent, GetTranslation(), GetRotation(), GetScale());
//The selection box can have mutlile panes selected in one box
//Scaling the edges will have different distances
float distanceLeft = selectionBox.LeftPoint - currentRectangle.LeftPoint;
float distanceRight = selectionBox.RightPoint - currentRectangle.RightPoint;
float distanceTop = selectionBox.TopPoint - currentRectangle.TopPoint;
float distanceBottom = selectionBox.BottomPoint - currentRectangle.BottomPoint;
Console.WriteLine("distanceLeft " + distanceLeft);
Console.WriteLine("distanceRight " + distanceRight);
Console.WriteLine("distanceTop " + distanceTop);
Console.WriteLine("distanceBottom " + distanceBottom);
float posX = Translate.X;
float posY = Translate.Y;
float posZ = Translate.Z;
float pickWidth = pickMouseX;
float pickHeight = pickMouseY;
switch (pickAction)
{
case LayoutViewer.PickAction.DragLeft:
Width += pickMouseX;
if (originX == OriginX.Left)
posX = Translate.X - pickMouseX;
else if (originX == OriginX.Right)
posX = Translate.X + pickMouseX;
else
posX = Translate.X - (pickMouseX / 2);
break;
case LayoutViewer.PickAction.DragRight:
if (originX == OriginX.Right)
{
Width -= pickMouseX;
posX = Translate.X + pickMouseX;
}
else if (originX == OriginX.Left)
{
Width -= pickMouseX;
posX = Translate.X + pickMouseX;
}
else
{
Width -= pickMouseX;
posX = Translate.X - (pickMouseX / 2);
}
break;
case LayoutViewer.PickAction.DragTop:
if (originY == OriginY.Top)
{
Height -= pickMouseY;
posY = Translate.Y - pickMouseY;
}
else if (originY == OriginY.Bottom)
{
Height -= pickMouseY;
posY = Translate.Y - pickMouseY;
}
else
{
Height -= pickMouseY;
posY = Translate.Y - (pickMouseY / 2);
}
break;
case LayoutViewer.PickAction.DragBottom:
Height += pickMouseY;
posY = Translate.Y - (pickMouseY / 2);
break;
case LayoutViewer.PickAction.DragTopLeft:
Width += pickMouseX;
Height -= pickMouseY;
posX = Translate.X - (pickMouseX / 2);
posY = Translate.Y - (pickMouseY / 2);
break;
case LayoutViewer.PickAction.DragBottomLeft:
Width += pickMouseX;
Height += pickMouseY;
posX = Translate.X - (pickMouseX / 2);
posY = Translate.Y - (pickMouseY / 2);
break;
case LayoutViewer.PickAction.DragBottomRight:
Width -= pickMouseX;
Height += pickMouseY;
posX = Translate.X - (pickMouseX / 2);
posY = Translate.Y - (pickMouseY / 2);
break;
case LayoutViewer.PickAction.DragTopRight:
Width -= pickMouseX;
Height -= pickMouseY;
posX = Translate.X - (pickMouseX / 2);
posY = Translate.Y - (pickMouseY / 2);
break;
}
if (!Runtime.LayoutEditor.TransformChidlren)
KeepChildrenTransform(posX, posY);
Translate = new Vector3F(posX, posY, posZ);
}
private Vector2F SetOrientation(float pickWidth, float pickHeight)
{
float posX = 0;
float posY = 0;
switch (originX)
{
case OriginX.Left:
Width += pickWidth;
posX = pickWidth;
break;
default:
Width += pickWidth;
posX = pickWidth / 2;
break;
}
switch (originY)
{
case OriginY.Top:
Height += pickHeight;
posY = pickHeight;
break;
default:
Height += pickHeight;
posY = pickHeight / 2;
break;
}
return new Vector2F(posX, posY);
}
public CustomRectangle CreateRectangle()
{
//Do origin transforms
var transformed = new Vector4();
int paneWidth = (int)Width;
int paneHeight = (int)Height;
if (animController.PaneSRT.ContainsKey(LPATarget.SizeX))
paneWidth = (int)animController.PaneSRT[LPATarget.SizeX];
if (animController.PaneSRT.ContainsKey(LPATarget.SizeY))
paneHeight = (int)animController.PaneSRT[LPATarget.SizeY];
transformed = TransformOrientation(paneWidth, paneHeight, originX, originY);
var parentTransform = ParentOriginTransform(transformed);
return new CustomRectangle(
parentTransform.X,
parentTransform.Y,
parentTransform.Z,
parentTransform.W);
}
public static float MixColors(params float[] c)
{
float a = c[0];
for (int i = 1; i < c.Length; i++)
{
a *= c[i];
}
for (int i = 1; i < c.Length; i++)
{
a /= 255f;
}
return a / 255f;
}
//Get the previous transform from the parent origin
private Vector4 ParentOriginTransform(Vector4 points)
{
//Dont shift the root or the first child of the root
//The parent setting shouldn't be set, but it doesn't hurt to do this
if (IsRoot || ParentIsRoot || Parent == null)
return points;
var transformedPosition = TransformOrientationPosition((int)Parent.Width, (int)Parent.Height, ParentOriginX, ParentOriginY);
var transformed = ShiftRectangle(transformedPosition, points);
if (Parent != null)
return Parent.ParentOriginTransform(transformed);
return transformed;
}
private static Vector4 ShiftRectangle(Vector2 position, Vector4 points)
{
int left = points[0] + position.X;
int right = points[1] + position.X;
int top = points[2] + position.Y;
int bottom = points[3] + position.Y;
return new Vector4(left, right, top, bottom);
}
private static Vector2 TransformOrientationPosition(int Width, int Height, OriginX originX, OriginY originY)
{
int x = 0;
int y = 0;
if (originX == OriginX.Left)
x = -(Width / 2);
else if (originX == OriginX.Right)
x = (Width / 2);
if (originY == OriginY.Top)
y = Height / 2;
else if (originY == OriginY.Bottom)
y = -(Height / 2);
return new Vector2(x, y);
}
private static Vector4 TransformOrientation(int Width, int Height, OriginX originX, OriginY originY)
{
int left = 0;
int right = 0;
int top = 0;
int bottom = 0;
if (originX == OriginX.Left)
right = Width;
else if (originX == OriginX.Right)
left = -Width;
else //To center
{
left = -Width / 2;
right = Width / 2;
}
if (originY == OriginY.Top)
bottom = -Height;
else if (originY == OriginY.Bottom)
top = Height;
else //To center
{
top = Height / 2;
bottom = -Height / 2;
}
return new Vector4(left, right, top, bottom);
}
public bool IsHit(CustomRectangle selectionBox)
{
var rect = CreateRectangle();
var transformed = rect.GetTransformedRectangle(Parent, GetTranslation(), GetRotation(), GetScale());
if ((selectionBox.LeftPoint < transformed.RightPoint) &&
(selectionBox.RightPoint > transformed.LeftPoint) &&
(selectionBox.TopPoint > transformed.BottomPoint) &&
(selectionBox.BottomPoint < transformed.TopPoint))
return true;
else
return false;
}
public bool IsHit(int X, int Y)
{
var rect = CreateRectangle();
var transformed = rect.GetTransformedRectangle(Parent, GetTranslation(), GetRotation(), GetScale());
bool isInBetweenX = (X > transformed.LeftPoint) && (X < transformed.RightPoint) ||
(X < transformed.LeftPoint) && (X > transformed.RightPoint);
bool isInBetweenY = (Y > transformed.BottomPoint) && (Y < transformed.TopPoint) ||
(Y < transformed.BottomPoint) && (Y > transformed.TopPoint);
if (isInBetweenX && isInBetweenY)
return true;
else
return false;
}
public BasePane SearchPane(string name)
{
if (Name == name)
return this;
foreach (var child in Childern)
{
var matchPane = child.SearchPane(name);
if (matchPane != null) return matchPane;
}
return null;
}
}
public class VertexColorHelper
{
public static System.Drawing.Color Mix(System.Drawing.Color colorA, System.Drawing.Color colorB, float value)
{
byte R = (byte)InterpolationHelper.Lerp(colorA.R, colorB.R, value);
byte G = (byte)InterpolationHelper.Lerp(colorA.G, colorB.G, value);
byte B = (byte)InterpolationHelper.Lerp(colorA.B, colorB.B, value);
byte A = (byte)InterpolationHelper.Lerp(colorA.A, colorB.A, value);
return System.Drawing.Color.FromArgb(A, R, G, B);
}
}
public class PaneAnimController
{
public Dictionary<LPATarget, float> PaneSRT = new Dictionary<LPATarget, float>();
public Dictionary<LVCTarget, float> PaneVertexColors = new Dictionary<LVCTarget, float>();
public bool Visibile = true;
public void ResetAnim()
{
Visibile = true;
PaneSRT.Clear();
PaneVertexColors.Clear();
}
}
public enum FilterMode
{
Near = 0,
Linear = 1
}
public enum WrapMode
{
Clamp = 0,
Repeat = 1,
Mirror = 2
}
public enum OriginX : byte
{
Center = 0,
Left = 1,
Right = 2
};
public enum OriginY : byte
{
Center = 0,
Top = 1,
Bottom = 2
};
public interface IUserDataContainer
{
UserData UserData { get; set; }
}
public class BxlytTextureRef
{
public short ID { get; set; }
public string Name { get; set; }
public virtual WrapMode WrapModeU { get; set; }
public virtual WrapMode WrapModeV { get; set; }
public virtual FilterMode MinFilterMode { get; set; }
public virtual FilterMode MaxFilterMode { get; set; }
}
public class BxlytAlphaCompare
{
public GfxAlphaFunction CompareMode { get; set; }
public float Value { get; set; }
public BxlytAlphaCompare()
{
CompareMode = GfxAlphaFunction.Always;
Value = 0;
}
public BxlytAlphaCompare(FileReader reader, BxlytHeader header)
{
CompareMode = reader.ReadEnum<GfxAlphaFunction>(false);
reader.ReadBytes(0x3);
Value = reader.ReadSingle();
}
public virtual void Write(FileWriter writer)
{
writer.Write(CompareMode, false);
writer.Seek(3);
writer.Write(Value);
}
}
public class BxlytBlendMode
{
public GX2BlendOp BlendOp { get; set; }
public GX2BlendFactor SourceFactor { get; set; }
public GX2BlendFactor DestFactor { get; set; }
public GX2LogicOp LogicOp { get; set; }
public BxlytBlendMode()
{
BlendOp = GX2BlendOp.Add;
SourceFactor = GX2BlendFactor.SourceAlpha;
DestFactor = GX2BlendFactor.SourceInvAlpha;
LogicOp = GX2LogicOp.Set;
}
public bool HasDefaults()
{
return BlendOp == GX2BlendOp.Add &&
SourceFactor == GX2BlendFactor.SourceAlpha &&
DestFactor == GX2BlendFactor.SourceInvAlpha &&
LogicOp == GX2LogicOp.Set;
}
public BxlytBlendMode(FileReader reader, BxlytHeader header)
{
BlendOp = (GX2BlendOp)reader.ReadByte();
SourceFactor = (GX2BlendFactor)reader.ReadByte();
DestFactor = (GX2BlendFactor)reader.ReadByte();
LogicOp = (GX2LogicOp)reader.ReadByte();
}
public void Write(FileWriter writer)
{
writer.Write(BlendOp, false);
writer.Write(SourceFactor, false);
writer.Write(DestFactor, false);
writer.Write(LogicOp, false);
}
public enum GX2BlendFactor : byte
{
Factor0 = 0,
Factor1 = 1,
DestColor = 2,
DestInvColor = 3,
SourceAlpha = 4,
SourceInvAlpha = 5,
DestAlpha = 6,
DestInvAlpha = 7,
SourceColor = 8,
SourceInvColor = 9
}
public enum GX2BlendOp : byte
{
Disable = 0,
Add = 1,
Subtract = 2,
ReverseSubtract = 3,
SelectMin = 4,
SelectMax = 5
}
public enum GX2LogicOp : byte
{
Disable = 0,
NoOp = 1,
Clear = 2,
Set = 3,
Copy = 4,
InvCopy = 5,
Inv = 6,
And = 7,
Nand = 8,
Or = 9,
Nor = 10,
Xor = 11,
Equiv = 12,
RevAnd = 13,
InvAd = 14,
RevOr = 15,
InvOr = 16
}
}
public class UserData : SectionCommon
{
public List<UserDataEntry> Entries { get; set; }
public UserData()
{
Entries = new List<UserDataEntry>();
}
public override void Write(FileWriter writer, LayoutHeader header)
{
}
}
public class UserDataEntry
{
public string Name { get; set; }
public UserDataType Type { get; set; }
public byte Unknown { get; set; }
public object data;
public string GetString()
{
return (string)data;
}
public float[] GetFloats()
{
return (float[])data;
}
public int[] GetInts()
{
return (int[])data;
}
public byte[] GetBytes()
{
return (byte[])data;
}
public void SetValue(string value)
{
data = value;
Type = UserDataType.String;
}
public void SetValue(float[] value)
{
data = value;
Type = UserDataType.Float;
}
public void SetValue(int[] value)
{
data = value;
Type = UserDataType.Int;
}
public void SetValue(List<UserDataStruct> value)
{
data = value;
Type = UserDataType.StructData;
}
public List<UserDataStruct> GetStructs()
{
return (List<UserDataStruct>)data;
}
internal long _pos;
}
public class UserDataStruct
{
public ushort Unknown { get; set; } // 0
public List<UserDataStructEntry> Entries = new List<UserDataStructEntry>();
public UserDataStruct(FileReader reader, BxlytHeader header)
{
long pos = reader.Position;
ushort unknown = reader.ReadUInt16();
ushort numEntries = reader.ReadUInt16();
uint[] offsets = reader.ReadUInt32s(numEntries);
for (int i = 0; i < numEntries; i++)
{
reader.SeekBegin(pos + offsets[i]);
Entries.Add(new UserDataStructEntry(reader, header));
}
}
public void Write(FileWriter writer, LayoutHeader header)
{
long pos = writer.Position;
writer.Write(Unknown);
writer.Write((ushort)Entries.Count);
long _ofsPos = writer.Position;
//Fill empty spaces for offsets later
writer.Write(new uint[Entries.Count]);
for (int i = 0; i < Entries.Count; i++)
{
writer.WriteUint32Offset(_ofsPos + (i * 4), pos);
Entries[i].Write(writer, header);
}
}
}
public class UserDataStructEntry
{
public uint DataType { get; set; }
public List<object> Data { get; set; }
public UserDataStructEntry(FileReader reader, BxlytHeader header)
{
long pos = reader.Position;
DataType = reader.ReadUInt32();
Console.WriteLine($"USD1 Struct DataType " + DataType);
if (DataType == 0)
{
uint numEntries = reader.ReadUInt32();
uint[] offsets = reader.ReadUInt32s((int)numEntries);
Data = new List<object>();
for (int i = 0; i < numEntries; i++)
{
reader.SeekBegin(pos + offsets[i]);
switch (DataType)
{
case 0:
string str = reader.ReadZeroTerminatedString();
Console.WriteLine($"USD1 str " + str);
Data.Add(str);
break;
}
}
}
}
public void Write(FileWriter writer, LayoutHeader header)
{
long pos = writer.Position;
writer.Write(DataType);
switch (DataType)
{
case 0:
writer.Write(Data.Count);
long _ofsPos = writer.Position;
//Fill empty spaces for offsets later
writer.Write(new uint[Data.Count]);
for (int i = 0; i < Data.Count; i++)
{
writer.WriteUint32Offset(_ofsPos + (i * 4), pos);
writer.WriteString((string)Data[i]);
if (i == Data.Count - 1)
writer.Align(64);
}
break;
}
}
}
public enum UserDataType : byte
{
String,
Int,
Float,
StructData,
}
public enum AnimationTarget : byte
{
Pane = 0,
Material = 1
}
public enum LPATarget : byte
{
TranslateX = 0x00,
TranslateY = 0x01,
TranslateZ = 0x02,
RotateX = 0x03,
RotateY = 0x04,
RotateZ = 0x05,
ScaleX = 0x06,
ScaleY = 0x07,
SizeX = 0x08,
SizeY = 0x09,
}
public enum LTSTarget : byte
{
TranslateS = 0x00,
TranslateT = 0x01,
Rotate = 0x02,
ScaleS = 0x03,
ScaleT = 0x04,
}
public enum LVITarget : byte
{
Visibility = 0x00,
}
public enum LVCTarget : byte
{
LeftTopRed = 0x00,
LeftTopGreen = 0x01,
LeftTopBlue = 0x02,
LeftTopAlpha = 0x03,
RightTopRed = 0x04,
RightTopGreen = 0x05,
RightTopBlue = 0x06,
RightTopAlpha = 0x07,
LeftBottomRed = 0x08,
LeftBottomGreen = 0x09,
LeftBottomBlue = 0x0A,
LeftBottomAlpha = 0x0B,
RightBottomRed = 0x0C,
RightBottomGreen = 0x0D,
RightBottomBlue = 0x0E,
RightBottomAlpha = 0x0F,
PaneAlpha = 0x10,
}
public enum LTPTarget : byte
{
Image1 = 0x00,
Image2 = 0x01, //Unsure if mutliple are used but just in case
Image3 = 0x02,
}
public enum RevLMCTarget : byte
{
MatColorRed,
MatColorGreen,
MatColorBlue,
MatColorAlpha,
BlackColorRed,
BlackColorGreen,
BlackColorBlue,
BlackColorAlpha,
WhiteColorRed,
WhiteColorGreen,
WhiteColorBlue,
WhiteColorAlpha,
ColorReg3Red,
ColorReg3Green,
ColorReg3Blue,
ColorReg3Alpha,
TevColor1Red,
TevColor1Green,
TevColor1Blue,
TevColor1Alpha,
TevColor2Red,
TevColor2Green,
TevColor2Blue,
TevColor2Alpha,
TevColor3Red,
TevColor3Green,
TevColor3Blue,
TevColor3Alpha,
TevColor4Red,
TevColor4Green,
TevColor4Blue,
TevColor4Alpha,
}
public enum LMCTarget : byte
{
BlackColorRed,
BlackColorGreen,
BlackColorBlue,
BlackColorAlpha,
WhiteColorRed,
WhiteColorGreen,
WhiteColorBlue,
WhiteColorAlpha,
TextureColorBlendRatio,
TexColor0Red,
TexColor0Green,
TexColor0Blue,
TexColor0Alpha,
TexColor1Red,
TexColor1Green,
TexColor1Blue,
TexColor1Alpha,
TexColor2Red,
TexColor2Green,
TexColor2Blue,
TexColor2Alpha,
TevKonstantColor0Red,
TevKonstantColor0Green,
TevKonstantColor0Blue,
TevKonstantColor0Alpha,
TevKonstantColor1Red,
TevKonstantColor1Green,
TevKonstantColor1Blue,
TevKonstantColor1Alpha,
TevKonstantColor2Red,
TevKonstantColor2Green,
TevKonstantColor2Blue,
TevKonstantColor2Alpha,
}
public enum LIMTarget : byte
{
Rotation,
ScaleU,
ScaleV,
}
public enum LFSTarget : byte
{
FontShadowBlackColorRed,
FontShadowBlackColorGreen,
FontShadowBlackColorBlue,
FontShadowBlackColorAlpha,
FontShadowWhiteColorRed,
FontShadowWhiteColorGreen,
FontShadowWhiteColorBlue,
FontShadowWhiteColorAlpha,
}
public enum LCTTarget : byte
{
FontShadowBlackColorRed,
FontShadowBlackColorGreen,
FontShadowBlackColorBlue,
FontShadowBlackColorAlpha,
FontShadowWhiteColorRed,
FontShadowWhiteColorGreen,
FontShadowWhiteColorBlue,
FontShadowWhiteColorAlpha,
}
public enum WindowKind
{
Around = 0,
Horizontal = 1,
HorizontalNoContent = 2
}
public enum WindowFrameTexFlip : byte
{
None = 0,
FlipH = 1,
FlipV = 2,
Rotate90 = 3,
Rotate180 = 4,
Rotate270 = 5
}
public enum GfxAlphaFunction : byte
{
Never = 0,
Less = 1,
LessOrEqual = 2,
Equal = 3,
NotEqual = 4,
GreaterOrEqual = 5,
Greater = 6,
Always = 7,
}
public enum GfxAlphaOp : byte
{
And = 0,
Or = 1,
Xor = 2,
Nor = 3,
}
public enum TevMode : byte
{
Replace,
Modulate,
Add,
AddSigned,
Interpolate,
Subtract,
AddMultiplicate,
MultiplcateAdd,
Overlay,
Indirect,
BlendIndirect,
EachIndirect,
}
public enum TevScale
{
Scale1,
Scale2,
Scale4
}
public enum TevSource
{
Tex0 = 0,
Tex1 = 1,
Tex2 = 2,
Tex3 = 3,
Constant = 4,
Primary = 5,
Previous = 6,
Register = 7
}
public enum TevColorOp
{
RGB = 0,
InvRGB = 1,
Alpha = 2,
InvAlpha = 3,
RRR = 4,
InvRRR = 5,
GGG = 6,
InvGGG = 7,
BBB = 8,
InvBBB = 9
}
public enum TevAlphaOp
{
Alpha = 0,
InvAlpha = 1,
R = 2,
InvR = 3,
G = 4,
InvG = 5,
B = 6,
InvB = 7
}
public interface IPicturePane
{
ushort MaterialIndex { get; set; }
BxlytMaterial Material { get; set; }
TexCoord[] TexCoords { get; set; }
STColor8 ColorTopLeft { get; set; }
STColor8 ColorTopRight { get; set; }
STColor8 ColorBottomLeft { get; set; }
STColor8 ColorBottomRight { get; set; }
void CopyMaterial();
}
public interface IBoundryPane
{
}
public interface ITextPane
{
ushort MaterialIndex { get; set; }
string Text { get; set; }
OriginX HorizontalAlignment { get; set; }
OriginY VerticalAlignment { get; set; }
List<string> GetFonts { get; }
ushort TextLength { get; set; }
ushort MaxTextLength { get; set; }
ushort RestrictedLength { get; }
BxlytMaterial Material { get; set; }
Toolbox.Library.Rendering.RenderableTex RenderableFont { get; set; }
byte TextAlignment { get; set; }
LineAlign LineAlignment { get; set; }
float ItalicTilt { get; set; }
STColor8 FontTopColor { get; set; }
STColor8 FontBottomColor { get; set; }
Vector2F FontSize { get; set; }
float CharacterSpace { get; set; }
float LineSpace { get; set; }
Vector2F ShadowXY { get; set; }
Vector2F ShadowXYSize { get; set; }
STColor8 ShadowForeColor { get; set; }
STColor8 ShadowBackColor { get; set; }
float ShadowItalic { get; set; }
string TextBoxName { get; set; }
bool RestrictedTextLengthEnabled { get; set; }
bool ShadowEnabled { get; set; }
string FontName { get; set; }
ushort FontIndex { get; set; }
void CopyMaterial();
}
public interface IPartPane
{
string LayoutFileName { get; set; }
}
public interface IWindowPane
{
System.Drawing.Color[] GetVertexColors();
void ReloadFrames();
bool UseOneMaterialForAll { get; set; }
bool UseVertexColorForAll { get; set; }
WindowKind WindowKind { get; set; }
bool NotDrawnContent { get; set; }
ushort StretchLeft { get; set; }
ushort StretchRight { get; set; }
ushort StretchTop { get; set; }
ushort StretchBottm { get; set; }
ushort FrameElementLeft { get; set; }
ushort FrameElementRight { get; set; }
ushort FrameElementTop { get; set; }
ushort FrameElementBottm { get; set; }
byte FrameCount { get; set; }
BxlytWindowContent Content { get; set; }
[Browsable(false)]
List<BxlytWindowFrame> WindowFrames { get; set; }
void CopyWindows();
}
public class BXLAN
{
public BxlanHeader BxlanHeader;
}
public class BxlytWindowContent : ICloneable
{
public STColor8 ColorTopLeft { get; set; }
public STColor8 ColorTopRight { get; set; }
public STColor8 ColorBottomLeft { get; set; }
public STColor8 ColorBottomRight { get; set; }
public ushort MaterialIndex { get; set; }
[TypeConverter(typeof(ExpandableObjectConverter))]
public virtual BxlytMaterial Material { get; set; }
public List<TexCoord> TexCoords = new List<TexCoord>();
[YamlIgnore]
private BxlytHeader LayoutFile;
public object Clone()
{
return this.MemberwiseClone();
}
public BxlytWindowContent(BxlytHeader header) {
LayoutFile = header;
ColorTopLeft = STColor8.White;
ColorTopRight = STColor8.White;
ColorBottomLeft = STColor8.White;
ColorBottomRight = STColor8.White;
TexCoords.Add(new TexCoord());
}
public BxlytWindowContent(BxlytHeader header, string name)
{
LayoutFile = header;
ColorTopLeft = STColor8.White;
ColorTopRight = STColor8.White;
ColorBottomLeft = STColor8.White;
ColorBottomRight = STColor8.White;
TexCoords.Add(new TexCoord());
//Add new material
Material = header.CreateNewMaterial($"{name}_C");
MaterialIndex = (ushort)header.AddMaterial(Material);
}
public BxlytWindowContent(FileReader reader, BxlytHeader header)
{
LayoutFile = header;
ColorTopLeft = reader.ReadColor8RGBA();
ColorTopRight = reader.ReadColor8RGBA();
ColorBottomLeft = reader.ReadColor8RGBA();
ColorBottomRight = reader.ReadColor8RGBA();
MaterialIndex = reader.ReadUInt16();
byte UVCount = reader.ReadByte();
reader.ReadByte(); //padding
for (int i = 0; i < UVCount; i++)
TexCoords.Add(new TexCoord()
{
TopLeft = reader.ReadVec2SY(),
TopRight = reader.ReadVec2SY(),
BottomLeft = reader.ReadVec2SY(),
BottomRight = reader.ReadVec2SY(),
});
Material = LayoutFile.Materials[MaterialIndex];
}
public void Write(FileWriter writer)
{
writer.Write(ColorTopLeft);
writer.Write(ColorTopRight);
writer.Write(ColorBottomLeft);
writer.Write(ColorBottomRight);
writer.Write(MaterialIndex);
writer.Write((byte)TexCoords.Count);
writer.Write((byte)0);
foreach (var texCoord in TexCoords)
{
writer.Write(texCoord.TopLeft);
writer.Write(texCoord.TopRight);
writer.Write(texCoord.BottomLeft);
writer.Write(texCoord.BottomRight);
}
}
}
public class BxlytWindowFrame : ICloneable
{
[TypeConverter(typeof(ExpandableObjectConverter))]
public BxlytMaterial Material { get; set; }
public ushort MaterialIndex;
public WindowFrameTexFlip TextureFlip { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
public BxlytWindowFrame()
{
}
public BxlytWindowFrame(BxlytHeader header, string materialName)
{
TextureFlip = WindowFrameTexFlip.None;
var mat = header.CreateNewMaterial(materialName);
MaterialIndex = (ushort)header.AddMaterial(mat);
Console.WriteLine($"NEW MAT {mat.Name} {MaterialIndex}");
Material = mat;
}
public BxlytWindowFrame(FileReader reader, BxlytHeader header)
{
MaterialIndex = reader.ReadUInt16();
TextureFlip = (WindowFrameTexFlip)reader.ReadByte();
reader.ReadByte(); //padding
Material = header.Materials[MaterialIndex];
}
public void Write(FileWriter writer)
{
writer.Write(MaterialIndex);
writer.Write(TextureFlip, false);
writer.Write((byte)0);
}
}
public class TexCoord
{
public Vector2F TopLeft { get; set; }
public Vector2F TopRight { get; set; }
public Vector2F BottomLeft { get; set; }
public Vector2F BottomRight { get; set; }
public TexCoord()
{
TopLeft = new Vector2F(0, 0);
TopRight = new Vector2F(1, 0);
BottomLeft = new Vector2F(0, 1);
BottomRight = new Vector2F(1, 1);
}
}
public class LayoutHeader : IDisposable
{
[Browsable(false)]
public TextureManager TextureManager = new TextureManager();
public PartsManager PartsManager = new PartsManager();
[Browsable(false)]
public string FileName
{
get { return FileInfo.FileName; }
}
[DisplayName("Use Big Endian"), CategoryAttribute("File Settings")]
public bool IsBigEndian { get; set; }
[Browsable(false)]
internal IFileFormat FileInfo;
[Browsable(false)]
internal uint Version;
[DisplayName("Version"), CategoryAttribute("File Settings")]
public string VersionFull
{
get
{
return $"{VersionMajor},{VersionMinor},{VersionMicro},{VersionMicro2}";
}
}
[RefreshProperties(RefreshProperties.All)]
public uint VersionMajor { get; set; }
[RefreshProperties(RefreshProperties.All)]
public uint VersionMinor { get; set; }
[RefreshProperties(RefreshProperties.All)]
public uint VersionMicro { get; set; }
[RefreshProperties(RefreshProperties.All)]
public uint VersionMicro2 { get; set; }
internal void SetVersionInfo()
{
VersionMajor = Version >> 24;
VersionMinor = Version >> 16 & 0xFF;
VersionMicro = Version >> 8 & 0xFF;
VersionMicro2 = Version & 0xFF;
}
internal uint SaveVersion()
{
return VersionMajor << 24 | VersionMinor << 16 | VersionMicro << 8 | VersionMicro2;
}
public static void WriteSection(FileWriter writer, string magic, SectionCommon section, Action WriteMethod = null)
{
long startPos = writer.Position;
writer.WriteSignature(magic);
writer.Write(uint.MaxValue);
WriteMethod?.Invoke();
writer.Align(4);
long endPos = writer.Position;
using (writer.TemporarySeek(startPos + 4, System.IO.SeekOrigin.Begin))
{
writer.Write((uint)(endPos - startPos));
}
}
public virtual BasePane CreateNewNullPane(string name)
{
return null;
}
public virtual BasePane CreateNewTextPane(string name)
{
return null;
}
public virtual BasePane CreateNewPicturePane(string name)
{
return null;
}
public virtual BasePane CreateNewWindowPane(string name)
{
return null;
}
public virtual BasePane CreateNewBoundryPane(string name)
{
return null;
}
public virtual BasePane CreateNewPartPane(string name)
{
return null;
}
public void Dispose()
{
PartsManager?.Dispose();
TextureManager?.Dispose();
FileInfo.Unload();
}
}
public class BxlanHeader : LayoutHeader
{
public BxlanPAT1 AnimationTag;
public BxlanPAI1 AnimationInfo;
public static bool ContainsEntry(byte[] bxlanFile, string[] EntryNames)
{
using (var reader = new FileReader(new System.IO.MemoryStream(bxlanFile)))
{
reader.SetByteOrder(true);
reader.ReadUInt32(); //magic
ushort byteOrderMark = reader.ReadUInt16();
reader.CheckByteOrderMark(byteOrderMark);
ushort HeaderSize = reader.ReadUInt16();
uint Version = reader.ReadUInt32();
uint FileSize = reader.ReadUInt32();
ushort sectionCount = reader.ReadUInt16();
reader.ReadUInt16(); //Padding
reader.SeekBegin(HeaderSize);
for (int i = 0; i < sectionCount; i++)
{
long pos = reader.Position;
string Signature = reader.ReadString(4, Encoding.ASCII);
uint SectionSize = reader.ReadUInt32();
if (Signature == "pai1")
{
reader.ReadUInt16(); //FrameSize
reader.ReadBoolean(); //Loop
reader.ReadByte(); //padding
var numTextures = reader.ReadUInt16();
var numEntries = reader.ReadUInt16();
var entryOffsetTbl = reader.ReadUInt32();
reader.SeekBegin(pos + entryOffsetTbl);
var entryOffsets = reader.ReadUInt32s(numEntries);
for (int e = 0; e < numEntries; e++)
{
reader.SeekBegin(pos + entryOffsets[e]);
string name = reader.ReadString(28, true);
if (EntryNames.Contains(name))
return true;
}
}
reader.SeekBegin(pos + SectionSize);
}
}
return false;
}
public BxlanPaiEntry TryGetTag(string name)
{
for (int i = 0; i < AnimationInfo.Entries?.Count; i++)
{
if (AnimationInfo.Entries[i].Name == name)
return AnimationInfo.Entries[i];
}
return null;
}
public bool ContainsEntry(string name)
{
for (int i = 0; i < AnimationInfo.Entries?.Count; i++) {
if (AnimationInfo.Entries[i].Name == name)
return true;
}
return false;
}
public virtual void Read(FileReader reader, BXLAN header)
{
}
public virtual void Write(FileWriter writer)
{
}
public LytAnimation GetGenericAnimation()
{
return animation;
}
private LytAnimation animation;
public LytAnimation ToGenericAnimation(BxlytHeader parentLayout)
{
if (animation == null)
animation = new LytAnimation(this, parentLayout);
animation.UpdateLayout(parentLayout);
return animation;
}
}
public class BxlanPAT1 : SectionCommon
{
[DisplayName("Name"), CategoryAttribute("Animation")]
public string Name { get; set; }
[DisplayName("Groups"), CategoryAttribute("Animation")]
public List<string> Groups { get; set; }
[DisplayName("Start"), CategoryAttribute("Frames")]
public short StartFrame { get; set; }
[DisplayName("End"), CategoryAttribute("Frames")]
public short EndFrame { get; set; }
[DisplayName("Animation Order"), CategoryAttribute("Parameters")]
public ushort AnimationOrder { get; set; }
[DisplayName("Child Binding"), CategoryAttribute("Parameters")]
public bool ChildBinding { get; set; }
}
public class BxlanPAI1 : SectionCommon
{
public ushort FrameSize;
public bool Loop;
public bool ContainsEntry(string name)
{
return Entries.Any(x => x.Name == name);
}
public virtual BxlanPaiEntry AddEntry(string name, byte target)
{
return new BxlanPaiEntry();
}
public List<string> Textures { get; set; } = new List<string>();
public List<BxlanPaiEntry> Entries = new List<BxlanPaiEntry>();
}
public class BxlanPaiEntry
{
public virtual BxlanPaiTag AddEntry(string tag)
{
return new BxlanPaiTag();
}
[DisplayName("Name"), CategoryAttribute("Animation")]
public string Name { get; set; }
[DisplayName("Target"), CategoryAttribute("Animation")]
public AnimationTarget Target { get; set; }
public List<BxlanPaiTag> Tags = new List<BxlanPaiTag>();
}
public class BxlanPaiTag
{
public BxlanPaiTag()
{
}
public BxlanPaiTag(string tag)
{
Tag = tag;
}
public BxlanPaiTagEntry CreateTarget(object TargetType, byte interpolationType)
{
byte target = (byte)TargetType;
string tagType = Tag.Remove(0, 1);
switch (tagType)
{
case "LPA":
return new LPATagEntry(target, interpolationType);
case "LTS":
return new LTSTagEntry(target, interpolationType);
case "LVI":
return new LVITagEntry(target, interpolationType);
case "LVC":
return new LVCTagEntry(target, interpolationType);
case "LMC":
return new LMCTagEntry(target, interpolationType);
case "LTP":
return new LTPTagEntry(target, interpolationType);
default:
return new BxlanPaiTagEntry(target, interpolationType);
}
}
public List<BxlanPaiTagEntry> Entries = new List<BxlanPaiTagEntry>();
public string Tag;
public string Type
{
get { return TypeDefine.ContainsKey(Tag) ? TypeDefine[Tag] : Tag; }
}
public static Dictionary<string, string> CafeTypeDefine = new Dictionary<string, string>()
{
{"FLPA","PaneSRT" },
{"FLVI","Visibility" },
{"FLTS","TextureSRT" },
{"FLVC","VertexColor" },
{"FLMC","MaterialColor" },
{"FLTP","TexturePattern" },
{"FLIM","IndTextureSRT" },
{"FLAC","AlphaTest" },
{"FLCT","FontShadow" },
{"FLCC","PerCharacterTransformCurve" },
};
public static Dictionary<string, string> RevTypeDefine = new Dictionary<string, string>()
{
{"RLPA","PaneSRT" },
{"RLVI","Visibility" },
{"RLTS","TextureSRT" },
{"RLVC","VertexColor" },
{"RLMC","MaterialColor" },
{"RLTP","TexturePattern" },
{"RLIM","IndTextureSRT" },
{"RLAC","AlphaTest" },
{"RLCT","FontShadow" },
{"RLCC","PerCharacterTransformCurve" },
};
public static Dictionary<string, string> CtrTypeDefine = new Dictionary<string, string>()
{
{"CLPA","PaneSRT" },
{"CLVI","Visibility" },
{"CLTS","TextureSRT" },
{"CLVC","VertexColor" },
{"CLMC","MaterialColor" },
{"CLTP","TexturePattern" },
{"CLIM","IndTextureSRT" },
{"CLAC","AlphaTest" },
{"CLCT","FontShadow" },
{"CLCC","PerCharacterTransformCurve" },
};
public static Dictionary<string, string> TypeDefine = new Dictionary<string, string>()
{
{"FLPA","PaneSRT" },
{"FLVI","Visibility" },
{"FLTS","TextureSRT" },
{"FLVC","VertexColor" },
{"FLMC","MaterialColor" },
{"FLTP","TexturePattern" },
{"FLIM","IndTextureSRT" },
{"FLAC","AlphaTest" },
{"FLCT","FontShadow" },
{"FLCC","PerCharacterTransformCurve" },
{"RLPA","PaneSRT" },
{"RLVI","Visibility" },
{"RLTS","TextureSRT" },
{"RLVC","VertexColor" },
{"RLMC","MaterialColor" },
{"RLTP","TexturePattern" },
{"RLIM","IndTextureSRT" },
{"RLAC","AlphaTest" },
{"RLCT","FontShadow" },
{"RLCC","PerCharacterTransformCurve" },
{"CLPA","PaneSRT" },
{"CLVI","Visibility" },
{"CLTS","TextureSRT" },
{"CLVC","VertexColor" },
{"CLMC","MaterialColor" },
{"CLTP","TexturePattern" },
{"CLIM","IndTextureSRT" },
{"CLAC","AlphaTest" },
{"CLCT","FontShadow" },
{"CLCC","PerCharacterTransformCurve" },
};
}
public class LPATagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public LPATarget Target
{
get { return (LPATarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public LPATagEntry(byte target, byte curveType) : base(target, curveType) { }
public LPATagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class LTSTagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public LTSTarget Target
{
get { return (LTSTarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public LTSTagEntry(byte target, byte curveType) : base(target, curveType) { }
public LTSTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class LVITagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public LVITarget Target
{
get { return (LVITarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public LVITagEntry(byte target, byte curveType) : base(target, curveType) { }
public LVITagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class LVCTagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public LVCTarget Target
{
get { return (LVCTarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public LVCTagEntry(byte target, byte curveType) : base(target, curveType) { }
public LVCTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class LMCTagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public LMCTarget Target
{
get { return (LMCTarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public LMCTagEntry(byte target, byte curveType) : base(target, curveType) { }
public LMCTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class RevLMCTagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public RevLMCTarget Target
{
get { return (RevLMCTarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public RevLMCTagEntry(byte target, byte curveType) : base(target, curveType) { }
public RevLMCTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class LTPTagEntry : BxlanPaiTagEntry
{
public override string TargetName => Target.ToString();
[DisplayName("Target"), CategoryAttribute("Tag")]
public LTPTarget Target
{
get { return (LTPTarget)AnimationTarget; }
set { AnimationTarget = (byte)value; }
}
public LTPTagEntry(byte target, byte curveType) : base(target, curveType) { }
public LTPTagEntry(FileReader reader, BxlanHeader header) : base(reader, header) { }
}
public class BxlanPaiTagEntry
{
[Browsable(false)]
public virtual string TargetName
{
get { return AnimationTarget.ToString(); }
}
public byte AnimationTarget;
[DisplayName("Index"), CategoryAttribute("Tag")]
public byte Index { get; set; }
[DisplayName("Curve Type"), CategoryAttribute("Tag")]
public CurveType CurveType { get; set; }
public List<KeyFrame> KeyFrames = new List<KeyFrame>();
public BxlanPaiTagEntry(byte target, byte curveType)
{
AnimationTarget = target;
CurveType = (CurveType)curveType;
}
public BxlanPaiTagEntry(FileReader reader, BxlanHeader header)
{
long startPos = reader.Position;
Index = reader.ReadByte();
AnimationTarget = reader.ReadByte();
CurveType = reader.ReadEnum<CurveType>(true);
reader.ReadByte(); //padding
var KeyFrameCount = reader.ReadUInt16();
reader.ReadUInt16(); //Padding
uint keyFrameOffset = reader.ReadUInt32();
reader.SeekBegin(startPos + keyFrameOffset);
for (int i = 0; i < KeyFrameCount; i++)
KeyFrames.Add(new KeyFrame(reader, CurveType));
}
public void Write(FileWriter writer, LayoutHeader header)
{
long startPos = writer.Position;
writer.Write(Index);
writer.Write(AnimationTarget);
writer.Write(CurveType, true);
writer.Write((byte)0); //padding
writer.Write((ushort)KeyFrames.Count);
writer.Write((ushort)0); //padding
writer.Write(0); //key offset
if (KeyFrames.Count > 0)
{
writer.WriteUint32Offset(startPos + 8, startPos);
for (int i = 0; i < KeyFrames.Count; i++)
KeyFrames[i].Write(writer, CurveType);
}
}
}
public enum BorderType : byte
{
Standard = 0,
DeleteBorder = 1,
RenderTwoCycles = 2,
};
public enum LineAlign : byte
{
Unspecified = 0,
Left = 1,
Center = 2,
Right = 3,
};
public enum CurveType : byte
{
Constant,
Step,
Hermite,
}
public class KeyFrame
{
[DisplayName("Slope"), CategoryAttribute("Key Frame")]
public float Slope { get; set; }
[DisplayName("Frame"), CategoryAttribute("Key Frame")]
public float Frame { get; set; }
[DisplayName("Value"), CategoryAttribute("Key Frame")]
public float Value { get; set; }
public KeyFrame(float frame)
{
Frame = frame;
Value = 0;
Slope = 0;
}
public KeyFrame(FileReader reader, CurveType curveType)
{
switch (curveType)
{
case CurveType.Hermite:
Frame = reader.ReadSingle();
Value = reader.ReadSingle();
Slope = reader.ReadSingle();
break;
default:
Frame = reader.ReadSingle();
Value = reader.ReadInt16();
reader.ReadInt16(); //padding
break;
}
}
public void Write(FileWriter writer, CurveType curveType)
{
switch (curveType)
{
case CurveType.Hermite:
writer.Write(Frame);
writer.Write(Value);
writer.Write(Slope);
break;
default:
writer.Write(Frame);
writer.Write((ushort)Value);
writer.Write((ushort)0);
break;
}
}
}
public class BxlytHeader : LayoutHeader
{
[Browsable(false)]
public System.Windows.Forms.TreeNode MaterialFolder;
[Browsable(false)]
public System.Windows.Forms.TreeNode TextureFolder;
[Browsable(false)]
public System.Windows.Forms.TreeNode FontFolder;
[Browsable(false)]
public Dictionary<string, BasePane> PaneLookup = new Dictionary<string, BasePane>();
[Browsable(false)]
public BasePane RootPane { get; set; }
[Browsable(false)]
public BasePane RootGroup { get; set; }
[Browsable(false)]
public virtual Dictionary<string, STGenericTexture> GetTextures { get; }
[Browsable(false)]
public virtual List<string> Textures { get; }
[Browsable(false)]
public virtual List<string> Fonts { get; }
[Browsable(false)]
public virtual List<BxlytMaterial> Materials { get;}
public virtual short AddMaterial(BxlytMaterial material, ushort index) { return -1; }
public virtual short AddMaterial(BxlytMaterial material) { return -1; }
public virtual List<int> AddMaterial(List<BxlytMaterial> materials) { return new List<int>(); }
public virtual void TryRemoveMaterial(BxlytMaterial material) { }
public virtual void TryRemoveMaterial(List<BxlytMaterial> materials) { }
public virtual BxlytMaterial CreateNewMaterial(string name)
{
return new BxlytMaterial();
}
public virtual BxlytMaterial GetMaterial(ushort index)
{
return new BxlytMaterial();
}
public void RemoveTextureReferences(string texture)
{
foreach (var mat in Materials)
mat.TryRemoveTexture(texture);
}
public BxlytMaterial SearchMaterial(string name)
{
for (int i = 0; i < Materials.Count; i++)
{
if (Materials[i].Name == name)
return Materials[i];
}
return null;
}
public virtual int AddFont(string name)
{
return -1;
}
public virtual void RemoveTexture(string name)
{
}
public virtual int AddTexture(string name)
{
return -1;
}
public void AddPaneToTable(BasePane pane)
{
if (!PaneLookup.ContainsKey(pane.Name))
PaneLookup.Add(pane.Name, pane);
}
public void AddPane(BasePane pane, string parent)
{
if (PaneLookup.ContainsKey(parent))
AddPane(pane, PaneLookup[parent]);
else
throw new Exception($"Failed to find parent pane! [{parent}]");
}
public void AddPane(BasePane pane, BasePane parent)
{
if (!PaneLookup.ContainsKey(pane.Name))
PaneLookup.Add(pane.Name, pane);
pane.Parent = parent;
parent.Childern.Add(pane);
parent.NodeWrapper.Nodes.Add(pane.NodeWrapper);
}
public void RemovePanes(List<BasePane> panes, BasePane rootPane)
{
Console.WriteLine("RemovePanes num " + panes.Count);
for (int i = 0; i < panes.Count; i++)
{
Console.WriteLine($"RemovePanes {panes[i].Name} {panes[i]}");
//We need to remove any materials that the material referenced
if (panes[i] is IPicturePane)
TryRemoveMaterial(((IPicturePane)panes[i]).Material);
if (panes[i] is ITextPane)
TryRemoveMaterial(((ITextPane)panes[i]).Material);
if (panes[i] is IWindowPane)
{
var wnd = panes[i] as IWindowPane;
List<BxlytMaterial> materials = new List<BxlytMaterial>();
var matC = wnd.Content.Material;
materials.Add(matC);
foreach (var windowFrame in wnd.WindowFrames)
materials.Add(windowFrame.Material);
TryRemoveMaterial(materials);
materials.Clear();
}
}
List<BasePane> topMostPanes = new List<BasePane>();
GetTopMostPanes(panes, topMostPanes, rootPane);
foreach (var pane in topMostPanes)
{
pane.Parent.NodeWrapper.Nodes.Remove(pane.NodeWrapper);
pane.Parent.Childern.Remove(pane);
}
for (int i = 0; i < panes.Count; i++)
{
if (PaneLookup.ContainsKey(panes[i].Name))
PaneLookup.Remove(panes[i].Name);
}
}
//Loop through each pane in the heiarchy until it finds the first set of panes
//The topmost panes are only going to be removed for adding with redo to be easier
private void GetTopMostPanes(List<BasePane> panes, List<BasePane> topMost, BasePane root)
{
foreach (var child in root.Childern)
{
if (panes.Contains(child))
topMost.Add(child);
}
if (topMost.Count == 0)
{
foreach (var child in root.Childern)
GetTopMostPanes(panes, topMost, child);
}
}
}
public class BxlytMaterial
{
//Setup some enable booleans
//These determine wether to switch to default values or not
//While i could null out the instances of each, it's best to keep those intact
//incase the settings get renabled, which keeps the previous data
[Browsable(false)]
[YamlIgnore]
public bool EnableAlphaCompare { get; set; }
[Browsable(false)]
[YamlIgnore]
public bool EnableBlend { get; set; }
[Browsable(false)]
[YamlIgnore]
public bool EnableBlendLogic { get; set; }
[Browsable(false)]
[YamlIgnore]
public bool EnableIndParams { get; set; }
[Browsable(false)]
[YamlIgnore]
public bool EnableFontShadowParams { get; set; }
[Browsable(false)]
[YamlIgnore]
public TreeNodeCustom NodeWrapper;
public bool TryRemoveTexture(string name)
{
int removeIndex = -1;
for (int i = 0; i < TextureMaps?.Length; i++)
{
if (TextureMaps[i].Name == name)
removeIndex = i;
}
if (removeIndex != -1)
{
TextureMaps = TextureMaps.RemoveAt(removeIndex);
return true;
}
return false;
}
public virtual BxlytMaterial Clone()
{
return (BxlytMaterial)this.MemberwiseClone();
}
public void RemoveNodeWrapper()
{
if (NodeWrapper != null && NodeWrapper.Parent != null)
{
var parent = NodeWrapper.Parent;
parent.Nodes.Remove(NodeWrapper);
}
}
public virtual void AddTexture(string texture)
{
int index = ParentLayout.AddTexture(texture);
BxlytTextureRef textureRef = new BxlytTextureRef();
textureRef.ID = (short)index;
textureRef.Name = texture;
TextureMaps = TextureMaps.AddToArray(textureRef);
TextureTransforms = TextureTransforms.AddToArray(new BxlytTextureTransform());
}
[DisplayName("Texture Transforms"), CategoryAttribute("Texture")]
public BxlytTextureTransform[] TextureTransforms { get; set; }
[Browsable(false)]
[YamlIgnore]
public MaterialAnimController animController = new MaterialAnimController();
[DisplayName("Name"), CategoryAttribute("General")]
public virtual string Name { get; set; }
[Browsable(false)]
[YamlIgnore]
public BxlytHeader ParentLayout;
public void SetName(string oldName, string newName)
{
if (Name == null) return;
Name = Name.Replace(oldName, newName);
}
[DisplayName("Black Color"), CategoryAttribute("Color")]
public virtual STColor8 WhiteColor { get; set; } = STColor8.White;
[DisplayName("White Color"), CategoryAttribute("Color")]
public virtual STColor8 BlackColor { get; set; } = STColor8.Black;
[DisplayName("Blend Mode"), CategoryAttribute("Blend")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public BxlytBlendMode BlendMode { get; set; }
[DisplayName("Blend Mode Logic"), CategoryAttribute("Blend")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public BxlytBlendMode BlendModeLogic { get; set; }
[DisplayName("Alpha Compare"), CategoryAttribute("Alpha")]
[TypeConverter(typeof(ExpandableObjectConverter))]
public BxlytAlphaCompare AlphaCompare { get; set; }
[DisplayName("Alpha Interpolation"), CategoryAttribute("Alpha")]
public virtual bool AlphaInterpolation { get; set; }
[DisplayName("Texture Maps"), CategoryAttribute("Texture")]
public BxlytTextureRef[] TextureMaps { get; set; }
[DisplayName("Tev Stages"), CategoryAttribute("Tev")]
public BxlytTevStage[] TevStages { get; set; }
}
public class BxlytTevStage
{
public TevMode ColorMode { get; set; }
public TevMode AlphaMode { get; set; }
}
public class MaterialAnimController
{
public Dictionary<LMCTarget, float> MaterialColors = new Dictionary<LMCTarget, float>();
public Dictionary<LTPTarget, string> TexturePatterns = new Dictionary<LTPTarget, string>();
public Dictionary<LTSTarget, float> TextureSRTS = new Dictionary<LTSTarget, float>();
public Dictionary<LIMTarget, float> IndTextureSRTS = new Dictionary<LIMTarget, float>();
public void ResetAnim()
{
MaterialColors.Clear();
TexturePatterns.Clear();
TextureSRTS.Clear();
IndTextureSRTS.Clear();
}
}
public class BxlytTextureTransform
{
public Vector2F Translate { get; set; }
public float Rotate { get; set; }
public Vector2F Scale { get; set; }
public BxlytTextureTransform()
{
Translate = new Vector2F(0,0);
Scale = new Vector2F(1, 1);
Rotate = 0;
}
public BxlytTextureTransform(FileReader reader)
{
Translate = reader.ReadVec2SY();
Rotate = reader.ReadSingle();
Scale = reader.ReadVec2SY();
}
public void Write(FileWriter writer)
{
writer.Write(Translate);
writer.Write(Rotate);
writer.Write(Scale);
}
}
public class BxlytIndTextureTransform
{
public float Rotation { get; set; }
public float ScaleX { get; set; }
public float ScaleY { get; set; }
}
public class SectionCommon
{
[Browsable(false)]
public virtual string Signature { get; }
internal uint SectionSize { get; set; }
internal long StartPosition { get; set; }
internal byte[] Data { get; set; }
public SectionCommon()
{
}
public SectionCommon(string signature)
{
Signature = signature;
}
public virtual void Write(FileWriter writer, LayoutHeader header)
{
if (Data != null)
writer.Write(Data);
}
}
public class PerCharacterTransform
{
public float CurveTimeOffset { get; set; }
public float CurveWidth { get; set; }
public byte LoopType { get; set; }
public byte VerticalOrigin { get; set; }
public byte HasAnimInfo { get; set; }
public byte padding { get; set; }
public virtual void Read(FileReader reader, LayoutHeader header)
{
CurveTimeOffset = reader.ReadSingle();
CurveWidth = reader.ReadSingle();
LoopType = reader.ReadByte();
VerticalOrigin = reader.ReadByte();
HasAnimInfo = reader.ReadByte();
padding = reader.ReadByte();
}
public virtual void Write(FileWriter writer, LayoutHeader header)
{
writer.Write(CurveTimeOffset);
writer.Write(CurveWidth);
writer.Write(LoopType);
writer.Write(VerticalOrigin);
writer.Write(HasAnimInfo);
writer.Write(padding);
}
}
public class CustomRectangle
{
public int LeftPoint;
public int RightPoint;
public int TopPoint;
public int BottomPoint;
public OpenTK.Vector2 TopLeftPoint;
public OpenTK.Vector2 TopRightPoint;
public OpenTK.Vector2 BottomLeftPoint;
public OpenTK.Vector2 BottomRightPoint;
public CustomRectangle() { }
public CustomRectangle(OpenTK.Vector2 topLeft, OpenTK.Vector2 topRight,
OpenTK.Vector2 bottomLeft, OpenTK.Vector2 bottomRight)
{
TopLeftPoint = topLeft;
TopRightPoint = topRight;
BottomLeftPoint = bottomLeft;
BottomRightPoint = bottomRight;
LeftPoint = (int)topLeft.X;
RightPoint = (int)topRight.X;
TopPoint = (int)topLeft.Y;
BottomPoint = (int)bottomRight.Y;
}
public CustomRectangle(int left, int right, int top, int bottom)
{
LeftPoint = left;
RightPoint = right;
TopPoint = top;
BottomPoint = bottom;
TopLeftPoint = new OpenTK.Vector2(left,top);
TopRightPoint = new OpenTK.Vector2(right, top);
BottomLeftPoint = new OpenTK.Vector2(left, bottom);
BottomRightPoint = new OpenTK.Vector2(right, bottom);
}
public CustomRectangle RotateZ(float rotate)
{
var topLeft = RotateZPoint(TopLeftPoint.X, TopLeftPoint.Y, rotate).Xy;
var topRight = RotateZPoint(TopRightPoint.X, TopRightPoint.Y, rotate).Xy;
var bottomLeft = RotateZPoint(BottomLeftPoint.X, BottomLeftPoint.Y, rotate).Xy;
var bottomRight = RotateZPoint(BottomRightPoint.X, BottomRightPoint.Y, rotate).Xy;
return new CustomRectangle(
topLeft,
topRight,
bottomLeft,
bottomRight);
}
private OpenTK.Vector3 RotateZPoint(float p1, float p2, float rotate)
{
var rotatioZ = OpenTK.Matrix4.CreateRotationZ(OpenTK.MathHelper.DegreesToRadians(rotate));
return OpenTK.Vector3.TransformPosition(new OpenTK.Vector3(p1, p2, 0), rotatioZ);
}
public CustomRectangle GetTransformedRectangle(BasePane parent, Vector3F Transform, Vector3F Rotate, Vector2F scale)
{
var sca = new OpenTK.Vector2(scale.X, scale.Y);
var pos = new OpenTK.Vector2(Transform.X, Transform.Y);
var rect = this.RotateZ(Rotate.Z);
rect = new CustomRectangle(
(rect.TopLeftPoint * sca) + pos,
(rect.TopRightPoint * sca) + pos,
(rect.BottomLeftPoint * sca) + pos,
(rect.BottomRightPoint * sca) + pos);
if (parent != null)
return parent.TransformParent(rect);
else
return rect;
}
public int Width
{
get { return LeftPoint - RightPoint; }
}
public int Height
{
get { return TopPoint - BottomPoint; }
}
}
public class CNT1 : SectionCommon
{
public string Name { get; set; }
public CNT1(FileReader reader, Cafe.Header header)
{
uint paneNamesOffset = 0;
uint paneCount = 0;
uint animCount = 0;
uint controlUserNameOffset = 0;
uint paneParamNamesOffset = 0;
uint animParamNamesOffset = 0;
if (header.VersionMajor < 3)
{
paneNamesOffset = reader.ReadUInt32();
paneCount = reader.ReadUInt32();
animCount = reader.ReadUInt32();
}
else
{
controlUserNameOffset = reader.ReadUInt32();
paneNamesOffset = reader.ReadUInt32();
paneCount = reader.ReadUInt16();
animCount = reader.ReadUInt16();
paneParamNamesOffset = reader.ReadUInt32();
animParamNamesOffset = reader.ReadUInt32();
}
Name = reader.ReadZeroTerminatedString();
}
public override void Write(FileWriter writer, LayoutHeader header)
{
}
}
public class GroupPane : BasePane
{
public override string Signature { get; } = "grp1";
public List<string> Panes { get; set; } = new List<string>();
private bool displayInEditor = true;
internal override bool DisplayInEditor
{
get { return displayInEditor; }
set
{
displayInEditor = value;
for (int i = 0; i < Panes.Count; i++)
{
var pane = SearchPane(Panes[i]);
if (pane != null)
pane.DisplayInEditor = value;
}
}
}
public GroupPane() : base()
{
}
}
public class FNL1 : SectionCommon
{
public List<string> Fonts { get; set; }
public FNL1()
{
Fonts = new List<string>();
}
public FNL1(FileReader reader, BxlytHeader header) : base() {
Fonts = StringList.Read(reader, header);
}
public override void Write(FileWriter writer, LayoutHeader header) {
StringList.Write(Fonts, writer, header);
}
}
public class TXL1 : SectionCommon
{
public List<string> Textures { get; set; }
public TXL1()
{
Textures = new List<string>();
}
public TXL1(FileReader reader, BxlytHeader header) : base() {
Textures = StringList.Read(reader, header);
}
public override void Write(FileWriter writer, LayoutHeader header) {
StringList.Write(Textures, writer, header);
}
}
public class StringList
{
public static List<string> Read(FileReader reader, LayoutHeader header)
{
List<string> values = new List<string>();
ushort count = reader.ReadUInt16();
reader.Seek(2); //padding
long pos = reader.Position;
if (header is BRLYT.Header)
{
for (int i = 0; i < count; i++)
{
uint offset = reader.ReadUInt32();
reader.ReadUInt32(); //padding
using (reader.TemporarySeek(offset + pos, SeekOrigin.Begin)) {
values.Add(reader.ReadZeroTerminatedString());
}
}
}
else
{
uint[] offsets = reader.ReadUInt32s(count);
for (int i = 0; i < offsets.Length; i++)
{
reader.SeekBegin(offsets[i] + pos);
values.Add(reader.ReadZeroTerminatedString());
}
}
return values;
}
public static void Write(List<string> values,
FileWriter writer, LayoutHeader header)
{
writer.Write((ushort)values.Count);
writer.Write((ushort)0);
//Fill empty spaces for offsets later
long pos = writer.Position;
if (header is BRLYT.Header)
{
writer.Write(new uint[values.Count * 2]);
//Save offsets and strings
for (int i = 0; i < values.Count; i++)
{
writer.WriteUint32Offset(pos + (i * 8), pos);
writer.WriteString(values[i]);
}
}
else
{
writer.Write(new uint[values.Count]);
//Save offsets and strings
for (int i = 0; i < values.Count; i++)
{
writer.WriteUint32Offset(pos + (i * 4), pos);
writer.WriteString(values[i]);
}
}
}
}
public class LayoutInfo : SectionCommon
{
public bool DrawFromCenter { get; set; }
[DisplayName("Canvas Width"), CategoryAttribute("Layout")]
public float Width { get; set; }
[DisplayName("Canvas Height"), CategoryAttribute("Layout")]
public float Height { get; set; }
[DisplayName("Layout Name"), CategoryAttribute("Layout")]
public string Name { get; set; }
public LayoutInfo()
{
DrawFromCenter = false;
Width = 0;
Height = 0;
Name = "";
}
}
public class LayoutControlDocked : Toolbox.Library.Forms.STUserControl
{
public DockContent DockContent;
public DockPane Pane => DockContent?.Pane;
}
public class LayoutDocked : DockContent
{
}
}