Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
903 changes: 601 additions & 302 deletions StudioSB/GUI/Attachments/LVDAttachment.cs

Large diffs are not rendered by default.

100 changes: 59 additions & 41 deletions StudioSB/IO/Formats/IO_SSF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,89 +7,107 @@ public class IO_SSF
/// <summary>
///
/// </summary>
/// <param name="lvd"></param>
/// <param name="levelData"></param>
/// <param name="filePath"></param>
public static void Export(LevelData lvd, string filePath)
public static void Export(LevelData levelData, string filePath)
{
SSF ssf = new SSF();

foreach(var v in lvd.Collisions)
foreach (var collision in levelData.Collisions)
{
var g = new SSFGroup();
ssf.Groups.Add(g);
g.Name = v.EntryLabel;
g.Bone = v.BoneName;
foreach(var x in v.Vertices)
g.Vertices.Add(new SSFVertex() { X = x.X, Y = x.Y });
for(int i = 0; i < v.Materials.Count; i++)
g.Name = collision.DynamicName;
g.JointName = collision.JointName;

foreach (var v in collision.Vertices)
{
g.Vertices.Add(new SSFVertex() { X = v.X, Y = v.Y });
}

for (int i = 0; i < collision.Attributes.Count; i++)
{
g.Lines.Add(new SSFLine() {
g.Edges.Add(new SSFEdge() {
Vertex1 = i,
Vertex2 = i + 1,
Material = v.Materials[i].Physics.ToString(),
Flags = (v.Materials[i].LeftLedge ? SSFLineFlag.LeftLedge : 0) |
(v.Materials[i].RightLedge ? SSFLineFlag.RightLedge : 0) |
(v.PassThrough ? SSFLineFlag.DropThrough : 0)
Material = collision.Attributes[i].Type.ToString(),
Flags = (collision.Attributes[i].Unpaintable ? SSFEdgeFlags.Unpaintable : SSFEdgeFlags.None) |
(collision.Attributes[i].RightWallOverride ? SSFEdgeFlags.RightWallOverride : SSFEdgeFlags.None) |
(collision.Attributes[i].LeftWallOverride ? SSFEdgeFlags.LeftWallOverride : SSFEdgeFlags.None) |
(collision.Attributes[i].CeilingOverride ? SSFEdgeFlags.CeilingOverride : SSFEdgeFlags.None) |
(collision.Attributes[i].FloorOverride ? SSFEdgeFlags.FloorOverride : SSFEdgeFlags.None) |
(collision.Attributes[i].NoWallJump ? SSFEdgeFlags.NoWallJump : SSFEdgeFlags.None) |
(collision.Attributes[i].DropThrough ? SSFEdgeFlags.DropThrough : SSFEdgeFlags.None) |
(collision.Attributes[i].LeftLedge ? SSFEdgeFlags.LeftLedge : SSFEdgeFlags.None) |
(collision.Attributes[i].RightLedge ? SSFEdgeFlags.RightLedge : SSFEdgeFlags.None) |
(collision.Attributes[i].IgnoreLinkFromLeft ? SSFEdgeFlags.IgnoreLinkFromLeft : SSFEdgeFlags.None) |
(collision.Attributes[i].Supersoft ? SSFEdgeFlags.Supersoft : SSFEdgeFlags.None) |
(collision.Attributes[i].IgnoreLinkFromRight ? SSFEdgeFlags.IgnoreLinkFromRight : SSFEdgeFlags.None),
});
}
}

foreach (var v in lvd.BlastZoneBounds)
int index = 0;

foreach (var v in levelData.StartPositions)
{
ssf.Points.Add(new SSFPoint()
{
Tag = "BlastStart",
X = v.Left,
Y = v.Top
Tag = "StartPosition" + index++,
X = v.Position.X,
Y = v.Position.Y
});
}

index = 0;

foreach (var v in levelData.RestartPositions)
{
ssf.Points.Add(new SSFPoint()
{
Tag = "BlastEnd",
X = v.Right,
Y = v.Bottom
Tag = "RestartPosition" + index++,
X = v.Position.X,
Y = v.Position.Y
});
}

foreach (var v in lvd.CameraBounds)
index = 0;

foreach (var v in levelData.CameraRegions)
{
ssf.Points.Add(new SSFPoint()
{
Tag = "CameraStart",
X = v.Left,
Y = v.Top
Tag = "CameraRegionStart" + index++,
X = v.Rectangle.Left,
Y = v.Rectangle.Top
});
ssf.Points.Add(new SSFPoint()
{
Tag = "CameraEnd",
X = v.Right,
Y = v.Bottom
Tag = "CameraRegionEnd" + index++,
X = v.Rectangle.Right,
Y = v.Rectangle.Bottom
});
}

int sIndex = 0;
foreach (var v in lvd.Spawns)
index = 0;

foreach (var v in levelData.DeathRegions)
{
ssf.Points.Add(new SSFPoint()
{
Tag = "Spawn" + sIndex++,
X = v.X,
Y = v.Y
Tag = "DeathRegionStart" + index++,
X = v.Rectangle.Left,
Y = v.Rectangle.Top
});
}
sIndex = 0;
foreach (var v in lvd.Respawns)
{
ssf.Points.Add(new SSFPoint()
{
Tag = "Respawn" + sIndex++,
X = v.X,
Y = v.Y
Tag = "DeathRegionEnd" + index++,
X = v.Rectangle.Right,
Y = v.Rectangle.Bottom
});
}

ssf.Save(filePath);
}
}


}
26 changes: 18 additions & 8 deletions StudioSB/IO/Formats/SSF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@
namespace StudioSB.IO.Formats
{
[Flags]
public enum SSFLineFlag
public enum SSFEdgeFlags
{
RightLedge,
LeftLedge,
DropThrough
None = 0x0,
Unpaintable = 0x20,
RightWallOverride = 0x100,
LeftWallOverride = 0x200,
CeilingOverride = 0x400,
FloorOverride = 0x800,
NoWallJump = 0x1000,
DropThrough = 0x2000,
LeftLedge = 0x4000,
RightLedge = 0x8000,
IgnoreLinkFromLeft = 0x10000,
Supersoft = 0x20000,
IgnoreLinkFromRight = 0x40000,
}

[Serializable]
Expand Down Expand Up @@ -48,17 +58,17 @@ public class SSFPoint
public class SSFGroup
{
public string Name;
public string Bone;
public List<SSFLine> Lines = new List<SSFLine>();
public string JointName;
public List<SSFVertex> Vertices = new List<SSFVertex>();
public List<SSFEdge> Edges = new List<SSFEdge>();
}

public class SSFLine
public class SSFEdge
{
public int Vertex1;
public int Vertex2;
public string Material;
public SSFLineFlag Flags;
public SSFEdgeFlags Flags = SSFEdgeFlags.None;
public string Tags;
}

Expand Down
176 changes: 176 additions & 0 deletions StudioSB/Scenes/LVD/LVDBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
using StudioSB.Tools;
using System.ComponentModel;

namespace StudioSB.Scenes.LVD
{
public class LVDBase
{
[ReadOnly(true), Category("Version")]
public byte BaseVersion { get; internal set; } = 4;

[Category("Base"), TypeConverter(typeof(ExpandableObjectConverter))]
public LVDMetaInfo MetaInfo { get; set; } = new LVDMetaInfo();

[Category("Base")]
public string DynamicName { get; set; }

[Category("Base"), TypeConverter(typeof(ExpandableObjectConverter))]
public LVDVector3 DynamicOffset { get; set; } = new LVDVector3(0.0f, 0.0f, 0.0f);

[Category("Base")]
public bool IsDynamic { get; set; }

[Category("Base")]
public uint InstanceID { get; set; }

[Category("Base"), TypeConverter(typeof(ExpandableObjectConverter))]
public LVDVector3 InstanceOffset { get; set; } = new LVDVector3(0.0f, 0.0f, 0.0f);

[Category("Base")]
public int JointIndex { get; set; }

[Category("Base")]
public string JointName { get; set; }

public virtual void Read(BinaryReaderExt reader)
{
BaseVersion = reader.ReadByte();

MetaInfo.Read(reader);

reader.Skip(1);
DynamicName = reader.ReadString();
reader.Skip(0x40 - (uint)DynamicName.Length - 1);

if (BaseVersion < 2)
{
return;
}

DynamicOffset.Read(reader);

if (BaseVersion < 3)
{
return;
}

IsDynamic = reader.ReadBoolean();

reader.Skip(1);
InstanceID = reader.ReadUInt32();

InstanceOffset.Read(reader);

if (BaseVersion < 4)
{
return;
}

JointIndex = reader.ReadInt32();

reader.Skip(1);
JointName = reader.ReadString();
reader.Skip(0x40 - (uint)JointName.Length - 1);
}

public virtual void Write(BinaryWriterExt writer)
{
writer.Write(BaseVersion);

MetaInfo.Write(writer);

writer.Write((byte)1);
writer.Write(DynamicName);
writer.Write(new byte[0x40 - DynamicName.Length - 1]);

if (BaseVersion < 2)
{
return;
}

DynamicOffset.Write(writer);

if (BaseVersion < 3)
{
return;
}

writer.Write(IsDynamic);

writer.Write((byte)1);
writer.Write(InstanceID);

InstanceOffset.Write(writer);

if (BaseVersion < 4)
{
return;
}

writer.Write(JointIndex);

writer.Write((byte)1);
writer.Write(JointName);
writer.Write(new byte[0x40 - JointName.Length - 1]);
}
}

public class LVDMetaInfo
{
[ReadOnly(true)]
public byte Version { get; internal set; } = 1;

[ReadOnly(true), TypeConverter(typeof(ExpandableObjectConverter))]
public LVDVersionInfo VersionInfo { get; internal set; } = new LVDVersionInfo();

public string Name { get; set; }

public void Read(BinaryReaderExt reader)
{
Version = reader.ReadByte();

VersionInfo.Read(reader);

reader.Skip(1);
Name = reader.ReadString();
reader.Skip(0x38 - (uint)Name.Length - 1);
}

public void Write(BinaryWriterExt writer)
{
writer.Write(Version);

VersionInfo.Write(writer);

writer.Write((byte)1);
writer.Write(Name);
writer.Write(new byte[0x38 - Name.Length - 1]);
}
}

public class LVDVersionInfo
{
[ReadOnly(true)]
public byte Version { get; internal set; } = 1;

[ReadOnly(true)]
public uint EditorVersion { get; internal set; }

[ReadOnly(true)]
public uint FormatVersion { get; internal set; }

public void Read(BinaryReaderExt reader)
{
Version = reader.ReadByte();
EditorVersion = reader.ReadUInt32();
FormatVersion = reader.ReadUInt32();
}

public void Write(BinaryWriterExt writer)
{
writer.Write(Version);
writer.Write(EditorVersion);
writer.Write(FormatVersion);
}
}
}
Loading