diff --git a/StudioSB/GUI/Attachments/LVDAttachment.cs b/StudioSB/GUI/Attachments/LVDAttachment.cs
index 69db07a..213ff65 100644
--- a/StudioSB/GUI/Attachments/LVDAttachment.cs
+++ b/StudioSB/GUI/Attachments/LVDAttachment.cs
@@ -47,7 +47,7 @@ private bool IsActive
private LevelData LVD;
// Options
- private float PlatformWidth = 8f;
+ private float CollisionDepth = 8.0f;
private static float PickRange = 2.5f;
public LVDAttachment()
@@ -70,7 +70,7 @@ public LVDAttachment()
ExportLVD.Click += (sender, args) =>
{
string fileName;
- if(FileTools.TrySaveFile(out fileName, "Smash Level Data |*.lvd;*.ssf"))
+ if (FileTools.TrySaveFile(out fileName, "Smash Level Data |*.lvd;*.ssf"))
{
if (fileName.EndsWith(".ssf"))
{
@@ -86,8 +86,8 @@ public LVDAttachment()
ToolStripButton addVertex = new ToolStripButton();
addVertex.Text = "Add";
addVertex.Click += (object sender, EventArgs args) => {
- if(PropertyGrid.SelectedObject is LVDVector2 point)
- AddNewPoint(point);
+ if (PropertyGrid.SelectedObject is LVDVector2 point)
+ AddVertex(point);
};
ToolStripButton deleteVertex = new ToolStripButton();
deleteVertex.Text = "Delete";
@@ -116,45 +116,181 @@ public LVDAttachment()
}
///
- /// Reads LVD data
+ /// Reads LVD file data from the given file name.
///
///
public void Open(string FileName)
{
- LevelData lvd = new LevelData();
- lvd.Open(FileName);
+ LevelData lvd = new LevelData(FileName);
LVD = lvd;
RefreshNodes();
}
///
- /// refreshes lvd nodes list
+ /// Refreshes the LVD object node list.
///
private void RefreshNodes()
{
- var lvdNode = new TreeNode() { Text = "LVD", Tag = LVD };
+ var levelDataNode = new TreeNode() { Text = "LVD", Tag = LVD };
+
NodeTree.Nodes.Clear();
- NodeTree.Nodes.Add(lvdNode);
+ NodeTree.Nodes.Add(levelDataNode);
+
+ var collisionNodes = new TreeNode() { Text = "Collisions" };
+ var startPositionNodes = new TreeNode() { Text = "Start Positions" };
+ var restartPositionNodes = new TreeNode() { Text = "Restart Positions" };
+ var cameraRegionNodes = new TreeNode() { Text = "Camera Regions" };
+ var deathRegionNodes = new TreeNode() { Text = "Death Regions" };
+ var enemyGeneratorNodes = new TreeNode() { Text = "Enemy Generators" };
+ var damageShapeNodes = new TreeNode() { Text = "Damage Shapes" };
+ var itemPopupRegionNodes = new TreeNode() { Text = "Item Popup Regions" };
+ var ptrainerRangeNodes = new TreeNode() { Text = "Pokémon Trainer Ranges" };
+ var ptrainerFloatingFloorNodes = new TreeNode() { Text = "Pokémon Trainer Platforms" };
+ var generalShape2DNodes = new TreeNode() { Text = "General Shapes (2D)" };
+ var generalShape3DNodes = new TreeNode() { Text = "General Shapes (3D)" };
+ var shrinkedCameraRegionNodes = new TreeNode() { Text = "Shrinked Camera Regions" };
+ var shrinkedDeathRegionNodes = new TreeNode() { Text = "Shrinked Death Regions" };
+
+ levelDataNode.Nodes.Add(collisionNodes);
+ levelDataNode.Nodes.Add(startPositionNodes);
+ levelDataNode.Nodes.Add(restartPositionNodes);
+ levelDataNode.Nodes.Add(cameraRegionNodes);
+ levelDataNode.Nodes.Add(deathRegionNodes);
+ levelDataNode.Nodes.Add(enemyGeneratorNodes);
+ levelDataNode.Nodes.Add(damageShapeNodes);
+ levelDataNode.Nodes.Add(itemPopupRegionNodes);
+ levelDataNode.Nodes.Add(ptrainerRangeNodes);
+ levelDataNode.Nodes.Add(ptrainerFloatingFloorNodes);
+ levelDataNode.Nodes.Add(generalShape2DNodes);
+ levelDataNode.Nodes.Add(generalShape3DNodes);
+ levelDataNode.Nodes.Add(shrinkedCameraRegionNodes);
+ levelDataNode.Nodes.Add(shrinkedDeathRegionNodes);
+
+ foreach (var collision in LVD.Collisions)
+ {
+ var collisionNode = new TreeNode();
+
+ collisionNode.Text = collision.MetaInfo.Name;
+ collisionNode.Tag = collision;
+ collisionNodes.Nodes.Add(collisionNode);
+ }
+
+ foreach (var startPosition in LVD.StartPositions)
+ {
+ var startPositionNode = new TreeNode();
+
+ startPositionNode.Text = startPosition.MetaInfo.Name;
+ startPositionNode.Tag = startPosition;
+ startPositionNodes.Nodes.Add(startPositionNode);
+ }
+
+ foreach (var restartPosition in LVD.RestartPositions)
+ {
+ var restartPositionNode = new TreeNode();
+
+ restartPositionNode.Text = restartPosition.MetaInfo.Name;
+ restartPositionNode.Tag = restartPosition;
+ restartPositionNodes.Nodes.Add(restartPositionNode);
+ }
+
+ foreach (var cameraRegion in LVD.CameraRegions)
+ {
+ var cameraRegionNode = new TreeNode();
+
+ cameraRegionNode.Text = cameraRegion.MetaInfo.Name;
+ cameraRegionNode.Tag = cameraRegion;
+ cameraRegionNodes.Nodes.Add(cameraRegionNode);
+ }
+
+ foreach (var deathRegion in LVD.DeathRegions)
+ {
+ var deathRegionNode = new TreeNode();
+
+ deathRegionNode.Text = deathRegion.MetaInfo.Name;
+ deathRegionNode.Tag = deathRegion;
+ deathRegionNodes.Nodes.Add(deathRegionNode);
+ }
+
+ foreach (var enemyGenerator in LVD.EnemyGenerators)
+ {
+ var enemyGeneratorNode = new TreeNode();
+
+ enemyGeneratorNode.Text = enemyGenerator.MetaInfo.Name;
+ enemyGeneratorNode.Tag = enemyGenerator;
+ enemyGeneratorNodes.Nodes.Add(enemyGeneratorNode);
+ }
+
+ foreach (var damageShape in LVD.DamageShapes)
+ {
+ var damageShapeNode = new TreeNode();
+
+ damageShapeNode.Text = damageShape.MetaInfo.Name;
+ damageShapeNode.Tag = damageShape;
+ damageShapeNodes.Nodes.Add(damageShapeNode);
+ }
+
+ foreach (var itemPopupRegion in LVD.ItemPopupRegions)
+ {
+ var itemPopupRegionNode = new TreeNode();
+
+ itemPopupRegionNode.Text = itemPopupRegion.MetaInfo.Name;
+ itemPopupRegionNode.Tag = itemPopupRegion;
+ itemPopupRegionNodes.Nodes.Add(itemPopupRegionNode);
+ }
+
+ foreach (var ptrainerRange in LVD.PTrainerRanges)
+ {
+ var ptrainerRangeNode = new TreeNode();
+
+ ptrainerRangeNode.Text = ptrainerRange.MetaInfo.Name;
+ ptrainerRangeNode.Tag = ptrainerRange;
+ ptrainerRangeNodes.Nodes.Add(ptrainerRangeNode);
+ }
+
+ foreach (var ptrainerFloatingFloor in LVD.PTrainerFloatingFloors)
+ {
+ var ptrainerFloatingFloorNode = new TreeNode();
+
+ ptrainerFloatingFloorNode.Text = ptrainerFloatingFloor.MetaInfo.Name;
+ ptrainerFloatingFloorNode.Tag = ptrainerFloatingFloor;
+ ptrainerFloatingFloorNodes.Nodes.Add(ptrainerFloatingFloorNode);
+ }
+
+ foreach (var generalShape2D in LVD.GeneralShapes2D)
+ {
+ var generalShape2DNode = new TreeNode();
- var collisionNode = new TreeNode() { Text = "Collisions" };
- var itemSpawnerNode = new TreeNode() { Text = "ItemSpawners" };
- lvdNode.Nodes.Add(collisionNode);
- lvdNode.Nodes.Add(itemSpawnerNode);
+ generalShape2DNode.Text = generalShape2D.MetaInfo.Name;
+ generalShape2DNode.Tag = generalShape2D;
+ generalShape2DNodes.Nodes.Add(generalShape2DNode);
+ }
- foreach (var col in LVD.Collisions)
+ foreach (var generalShape3D in LVD.GeneralShapes3D)
{
- var colNode = new TreeNode();
- colNode.Text = col.EntryLabel;
- colNode.Tag = col;
- collisionNode.Nodes.Add(colNode);
+ var generalShape3DNode = new TreeNode();
+
+ generalShape3DNode.Text = generalShape3D.MetaInfo.Name;
+ generalShape3DNode.Tag = generalShape3D;
+ generalShape3DNodes.Nodes.Add(generalShape3DNode);
+ }
+
+ foreach (var shrinkedCameraRegion in LVD.ShrinkedCameraRegions)
+ {
+ var shrinkedCameraRegionNode = new TreeNode();
+
+ shrinkedCameraRegionNode.Text = shrinkedCameraRegion.MetaInfo.Name;
+ shrinkedCameraRegionNode.Tag = shrinkedCameraRegion;
+ shrinkedCameraRegionNodes.Nodes.Add(shrinkedCameraRegionNode);
}
- foreach (var item in LVD.ItemSpawners)
+
+ foreach (var shrinkedDeathRegion in LVD.ShrinkedDeathRegions)
{
- var itemNode = new TreeNode();
- itemNode.Text = item.EntryLabel;
- itemNode.Tag = item;
- itemSpawnerNode.Nodes.Add(itemNode);
+ var shrinkedDeathRegionNode = new TreeNode();
+
+ shrinkedDeathRegionNode.Text = shrinkedDeathRegion.MetaInfo.Name;
+ shrinkedDeathRegionNode.Tag = shrinkedDeathRegion;
+ shrinkedDeathRegionNodes.Nodes.Add(shrinkedDeathRegionNode);
}
}
@@ -167,6 +303,7 @@ private void SelectObjectChanged(object sender, EventArgs args)
{
ToolPanel.Controls.Clear();
ToolPanel.Text = "LVD Options";
+
if (PropertyGrid.SelectedObject is LVDVector2)
{
ToolPanel.Text = "Point Options";
@@ -185,9 +322,9 @@ private void SelectObjectChanged(object sender, EventArgs args)
///
private void SelectNode(object sender, EventArgs args)
{
- if(NodeTree.SelectedNode != null)
+ if (NodeTree.SelectedNode != null)
{
- if(NodeTree.SelectedNode.Tag != null)
+ if (NodeTree.SelectedNode.Tag != null)
{
PropertyGrid.SelectedObject = NodeTree.SelectedNode.Tag;
}
@@ -219,105 +356,118 @@ public void OnAttach(SBViewportPanel viewportPanel)
public void Pick(Ray ray)
{
if (!IsActive)
+ {
return;
+ }
PropertyGrid.SelectedObject = null;
- var depthPicked = ray.GetPlaneIntersection(-Vector3.UnitZ, new Vector3(0, 0, -PlatformWidth / 2));
+ var depthPicked = ray.GetPlaneIntersection(-Vector3.UnitZ, new Vector3(0.0f, 0.0f, -CollisionDepth / 2.0f));
Picked = ray.GetPlaneIntersection(-Vector3.UnitZ, Vector3.Zero);
Vector2 nearestLine;
float closest = float.MaxValue;
- LVDCollisionMaterial collisionMat = null;
-
- foreach(var point in LVD.GeneralPoints)
+ LVDCollisionAttribute collisionAttribute = null;
+
+ foreach (var collision in LVD.Collisions)
{
- if (CrossMath.FastDistance(Picked, new Vector3(point.X, point.Y, point.Z), PickRange * 2.5f))
+ Vector2 startPos = (collision.IsDynamic && collision.Dynamic) ? new Vector2(collision.DynamicOffset.X, collision.DynamicOffset.Y) : new Vector2(0.0f, 0.0f);
+
+ for (int i = 0; i < collision.Vertices.Count; i++)
{
- PropertyGrid.SelectedObject = point;
- return;
+ var v1 = collision.Vertices[i];
+
+ if (i < collision.Attributes.Count)
+ {
+ var v2 = collision.Vertices[i + 1];
+ var distance = Ray.GetDistanceToSegment(depthPicked.Xy, new Vector2(v1.X + startPos.X, v1.Y + startPos.Y), new Vector2(v2.X + startPos.X, v2.Y + startPos.Y), out nearestLine);
+
+ if (distance < CollisionDepth / 4.0f & distance < closest)
+ {
+ closest = distance;
+ collisionAttribute = collision.Attributes[i];
+ }
+ }
+
+ if (CrossMath.FastDistance(Picked, new Vector3(v1.X + startPos.X, v1.Y + startPos.Y, 0.0f), PickRange))
+ {
+ PropertyGrid.SelectedObject = v1;
+ return;
+ }
}
}
- foreach (var bound in LVD.CameraBounds)
+
+ foreach (var startPosition in LVD.StartPositions)
{
- if (Ray.CheckBoundHit(Picked.Xy, new Vector2(bound.Left, bound.Top), new Vector2(bound.Right, bound.Bottom), PickRange))
+ if (CrossMath.FastDistance(Picked, new Vector3(startPosition.Position.X, startPosition.Position.Y, 0.0f), PickRange * 2.5f))
{
- PropertyGrid.SelectedObject = bound;
+ PropertyGrid.SelectedObject = startPosition;
return;
}
}
- foreach (var bound in LVD.BlastZoneBounds)
+
+ foreach (var restartPosition in LVD.RestartPositions)
{
- if(Ray.CheckBoundHit(Picked.Xy, new Vector2(bound.Left, bound.Top), new Vector2(bound.Right, bound.Bottom), PickRange))
+ if (CrossMath.FastDistance(Picked, new Vector3(restartPosition.Position.X, restartPosition.Position.Y, 0.0f), PickRange * 2.5f))
{
- PropertyGrid.SelectedObject = bound;
+ PropertyGrid.SelectedObject = restartPosition;
return;
}
}
- foreach (var bound in LVD.ShrunkBlastZoneBounds)
+
+ foreach (var cameraRegion in LVD.CameraRegions)
{
- if (Ray.CheckBoundHit(Picked.Xy, new Vector2(bound.Left, bound.Top), new Vector2(bound.Right, bound.Bottom), PickRange))
+ if (Ray.CheckBoundHit(Picked.Xy, new Vector2(cameraRegion.Rectangle.Left, cameraRegion.Rectangle.Top), new Vector2(cameraRegion.Rectangle.Right, cameraRegion.Rectangle.Bottom), PickRange))
{
- PropertyGrid.SelectedObject = bound;
+ PropertyGrid.SelectedObject = cameraRegion;
return;
}
}
- foreach (var bound in LVD.ShrunkCameraBounds)
+
+ foreach (var deathRegion in LVD.DeathRegions)
{
- if (Ray.CheckBoundHit(Picked.Xy, new Vector2(bound.Left, bound.Top), new Vector2(bound.Right, bound.Bottom), PickRange))
+ if (Ray.CheckBoundHit(Picked.Xy, new Vector2(deathRegion.Rectangle.Left, deathRegion.Rectangle.Top), new Vector2(deathRegion.Rectangle.Right, deathRegion.Rectangle.Bottom), PickRange))
{
- PropertyGrid.SelectedObject = bound;
+ PropertyGrid.SelectedObject = deathRegion;
return;
}
}
- foreach (var spawn in LVD.Spawns)
+
+ foreach (var generalShape3D in LVD.GeneralShapes3D)
{
- if(CrossMath.FastDistance(Picked, new Vector3(spawn.X, spawn.Y, 0), PickRange * 2.5f))
+ if (generalShape3D.Shape.Type == LVDShape3Type.Point && CrossMath.FastDistance(Picked, new Vector3(generalShape3D.Shape.X, generalShape3D.Shape.Y, generalShape3D.Shape.Z), PickRange * 2.5f))
{
- PropertyGrid.SelectedObject = spawn;
+ PropertyGrid.SelectedObject = generalShape3D;
return;
}
}
- foreach (var spawn in LVD.Respawns)
+
+ foreach (var shrinkedCameraRegion in LVD.ShrinkedCameraRegions)
{
- if (CrossMath.FastDistance(Picked, new Vector3(spawn.X, spawn.Y, 0), PickRange * 2.5f))
+ if (Ray.CheckBoundHit(Picked.Xy, new Vector2(shrinkedCameraRegion.Rectangle.Left, shrinkedCameraRegion.Rectangle.Top), new Vector2(shrinkedCameraRegion.Rectangle.Right, shrinkedCameraRegion.Rectangle.Bottom), PickRange))
{
- PropertyGrid.SelectedObject = spawn;
+ PropertyGrid.SelectedObject = shrinkedCameraRegion;
return;
}
}
- foreach (var col in LVD.Collisions)
+
+ foreach (var shrinkedDeathRegion in LVD.ShrinkedDeathRegions)
{
- for(int i =0; i < col.Vertices.Count; i++)
+ if (Ray.CheckBoundHit(Picked.Xy, new Vector2(shrinkedDeathRegion.Rectangle.Left, shrinkedDeathRegion.Rectangle.Top), new Vector2(shrinkedDeathRegion.Rectangle.Right, shrinkedDeathRegion.Rectangle.Bottom), PickRange))
{
- var vert = col.Vertices[i];
- if (i < col.Materials.Count)
- {
- var vert2 = col.Vertices[i+1];
- var dis = Ray.GetDistanceToSegment(depthPicked.Xy, new Vector2(vert.X, vert.Y), new Vector2(vert2.X, vert2.Y), out nearestLine);
- if (dis < PlatformWidth / 4 & dis < closest)
- {
- closest = dis;
- collisionMat = col.Materials[i];
- }
- }
- if (CrossMath.FastDistance(Picked, new Vector3(vert.X, vert.Y, 0), PickRange))
- {
- PropertyGrid.SelectedObject = vert;
- return;
- }
+ PropertyGrid.SelectedObject = shrinkedDeathRegion;
+ return;
}
}
- if (PropertyGrid.SelectedObject == null && collisionMat != null)
- PropertyGrid.SelectedObject = collisionMat;
+ if (PropertyGrid.SelectedObject == null && collisionAttribute != null)
+ PropertyGrid.SelectedObject = collisionAttribute;
}
public void OnRemove(SBViewportPanel viewportPanel)
{
}
-
bool DeleteDown = false;
bool ADown = false;
@@ -326,8 +476,12 @@ public void Step(SBViewport viewport)
var mouseP = viewport.GetMousePosition();
var deltaMouse = PrevMousePosition - mouseP;
PrevMousePosition = mouseP;
+
if (!IsActive)
+ {
return;
+ }
+
if (Keyboard.GetState().IsKeyDown(Key.AltLeft))
{
if (Keyboard.GetState().IsKeyDown(Key.A))
@@ -337,52 +491,70 @@ public void Step(SBViewport viewport)
ADown = true;
if (PropertyGrid.SelectedObject is LVDVector2 v)
- AddNewPoint(v);
+ {
+ AddVertex(v);
+ }
}
}
else
+ {
ADown = false;
+ }
+
if (Mouse.GetState().IsButtonDown(MouseButton.Left))
{
- if (PropertyGrid.SelectedObject is LVDGeneralPoint point)
+ if (PropertyGrid.SelectedObject is LVDPoint point)
{
- point.StartPosition.X -= deltaMouse.X / 4;
- point.StartPosition.Y += deltaMouse.Y / 4;
- point.X -= deltaMouse.X / 4;
- point.Y += deltaMouse.Y / 4;
+ point.DynamicOffset.X -= deltaMouse.X / 4.0f;
+ point.DynamicOffset.Y += deltaMouse.Y / 4.0f;
+ point.Position.X -= deltaMouse.X / 4.0f;
+ point.Position.Y += deltaMouse.Y / 4.0f;
PropertyGrid.SelectedObject = PropertyGrid.SelectedObject;
}
- if (PropertyGrid.SelectedObject is LVDSpawn spawn)
+
+ if (PropertyGrid.SelectedObject is LVDGeneralShape3 generalShape3D)
{
- spawn.StartPosition.X -= deltaMouse.X / 4;
- spawn.StartPosition.Y += deltaMouse.Y / 4;
- spawn.X -= deltaMouse.X / 4;
- spawn.Y += deltaMouse.Y / 4;
+ generalShape3D.DynamicOffset.X -= deltaMouse.X / 4.0f;
+ generalShape3D.DynamicOffset.Y += deltaMouse.Y / 4.0f;
+ generalShape3D.Shape.X -= deltaMouse.X / 4.0f;
+ generalShape3D.Shape.Y += deltaMouse.Y / 4.0f;
PropertyGrid.SelectedObject = PropertyGrid.SelectedObject;
}
+
if (PropertyGrid.SelectedObject is LVDVector2 v)
{
- v.X -= deltaMouse.X / 4;
- v.Y += deltaMouse.Y / 4;
+ v.X -= deltaMouse.X / 4.0f;
+ v.Y += deltaMouse.Y / 4.0f;
- // recalculate normals
- // is there a better way to do this?
- foreach (var col in LVD.Collisions)
+ // Recalculate all collision unit normal vectors.
+ // TODO: Is there a better way to do this?
+ foreach (var collision in LVD.Collisions)
{
- int index = col.Vertices.IndexOf(v);
- if (index == -1) continue;
+ int index = collision.Vertices.IndexOf(v);
+
+ if (index == -1)
+ {
+ continue;
+ }
+
+ if (index < collision.Normals.Count)
+ {
+ collision.Normals[index] = LVDVector2.GenerateNormal(v, collision.Vertices[index + 1]);
+ }
- if (index < col.Normals.Count)
- col.Normals[index] = LVDVector2.GenerateNormal(v, col.Vertices[index + 1]);
if (index > 0)
- col.Normals[index - 1] = LVDVector2.GenerateNormal(col.Vertices[index - 1], v);
+ {
+ collision.Normals[index - 1] = LVDVector2.GenerateNormal(collision.Vertices[index - 1], v);
+ }
+
break;
}
+
PropertyGrid.SelectedObject = PropertyGrid.SelectedObject;
}
-
}
}
+
if (Keyboard.GetState().IsKeyDown(Key.Delete))
{
if (!DeleteDown)
@@ -390,12 +562,15 @@ public void Step(SBViewport viewport)
DeleteDown = true;
if (PropertyGrid.SelectedObject is LVDVector2 v)
+ {
DeleteVertex(v);
+ }
}
}
else
+ {
DeleteDown = false;
-
+ }
}
private Vector2 PrevMousePosition;
@@ -408,32 +583,36 @@ public void Update(SBViewport viewport)
/// adds new point after vector
///
///
- private void AddNewPoint(LVDVector2 v)
+ private void AddVertex(LVDVector2 v)
{
- foreach (var col in LVD.Collisions)
+ foreach (var collision in LVD.Collisions)
{
- int index = col.Vertices.IndexOf(v);
- if (index == -1) continue;
+ int index = collision.Vertices.IndexOf(v);
- if (index == col.Vertices.Count - 1)
+ if (index == -1)
{
- var newPoint = new LVDVector2(v.X + 3, v.Y);
- var newMaterial = new LVDCollisionMaterial();
- newMaterial.Physics = col.Materials[index - 1].Physics;
- col.Vertices.Add(newPoint);
- col.Normals.Add(LVDVector2.GenerateNormal(v, newPoint));
- col.Materials.Add(newMaterial);
+ continue;
+ }
+
+ if (index == collision.Vertices.Count - 1)
+ {
+ var newPoint = new LVDVector2(v.X + 3.0f, v.Y);
+ var newAttribute = new LVDCollisionAttribute();
+ newAttribute.Type = collision.Attributes[index - 1].Type;
+ collision.Vertices.Add(newPoint);
+ collision.Normals.Add(LVDVector2.GenerateNormal(v, newPoint));
+ collision.Attributes.Add(newAttribute);
PropertyGrid.SelectedObject = newPoint;
}
else
{
- var newPoint = new LVDVector2((v.X + col.Vertices[index + 1].X) / 2, (v.Y + col.Vertices[index + 1].Y) / 2);
- var newMaterial = new LVDCollisionMaterial();
- newMaterial.Physics = col.Materials[index].Physics;
- var newNormal = LVDVector2.GenerateNormal(newPoint, col.Vertices[index + 1]);
- col.Normals.Insert(index + 1, newNormal);
- col.Materials.Insert(index + 1, newMaterial);
- col.Vertices.Insert(index + 1, newPoint);
+ var newPoint = new LVDVector2((v.X + collision.Vertices[index + 1].X) / 2.0f, (v.Y + collision.Vertices[index + 1].Y) / 2.0f);
+ var newAttribute = new LVDCollisionAttribute();
+ newAttribute.Type = collision.Attributes[index].Type;
+ var newNormal = LVDVector2.GenerateNormal(newPoint, collision.Vertices[index + 1]);
+ collision.Normals.Insert(index + 1, newNormal);
+ collision.Attributes.Insert(index + 1, newAttribute);
+ collision.Vertices.Insert(index + 1, newPoint);
PropertyGrid.SelectedObject = newPoint;
}
@@ -442,54 +621,63 @@ private void AddNewPoint(LVDVector2 v)
}
///
- /// deletes lvdvector2
+ /// Deletes a vertex.
///
///
private void DeleteVertex(LVDVector2 v)
{
LVDCollision remove = null;
- foreach (var col in LVD.Collisions)
+
+ foreach (var collision in LVD.Collisions)
{
- int index = col.Vertices.IndexOf(v);
- if (index == -1) continue;
+ int index = collision.Vertices.IndexOf(v);
+
+ if (index == -1)
+ {
+ continue;
+ }
if (index >= 1)
- PropertyGrid.SelectedObject = col.Vertices[index - 1];
+ {
+ PropertyGrid.SelectedObject = collision.Vertices[index - 1];
+ }
- if(col.Normals.Count > 0)
+ if (collision.Normals.Count > 0)
{
- if (index == col.Normals.Count)
+ if (index == collision.Normals.Count)
{
- col.Normals.RemoveAt(index - 1);
- col.Materials.RemoveAt(index - 1);
+ collision.Normals.RemoveAt(index - 1);
+ collision.Attributes.RemoveAt(index - 1);
}
else
{
- col.Normals.RemoveAt(index);
- col.Materials.RemoveAt(index);
+ collision.Normals.RemoveAt(index);
+ collision.Attributes.RemoveAt(index);
}
}
- col.Vertices.RemoveAt(index);
+ collision.Vertices.RemoveAt(index);
- if (index == col.Vertices.Count)
+ if (index == collision.Vertices.Count)
+ {
index--;
+ }
- if (col.Normals.Count > 0 && index > 0)
+ if (collision.Normals.Count > 0 && index > 0)
{
- col.Normals[index - 1] = LVDVector2.GenerateNormal(col.Vertices[index - 1], col.Vertices[index]);
+ collision.Normals[index - 1] = LVDVector2.GenerateNormal(collision.Vertices[index - 1], collision.Vertices[index]);
}
- if (col.Vertices.Count < 2)
+ if (collision.Vertices.Count < 2)
{
- remove = col;
+ remove = collision;
}
break;
}
- // remove collision that is marked for removal
- if(remove != null)
+ // Remove collision that is marked for removal
+ if (remove != null)
{
LVD.Collisions.Remove(remove);
RefreshNodes();
@@ -498,34 +686,37 @@ private void DeleteVertex(LVDVector2 v)
public void Save(string FilePath)
{
-
}
#region Rendering
private int FlashTimer = 0;
private int FlashInterval = 15;
- private static Vector3 FlashColor1 = new Vector3(1f, 1f, 1f);
- private static Vector3 FlashColor2 = new Vector3(1f, 1f, 0f);
+ private static Vector3 FlashColor1 = new Vector3(1.0f, 1.0f, 1.0f);
+ private static Vector3 FlashColor2 = new Vector3(1.0f, 1.0f, 0.0f);
private Vector3 FlashColor = FlashColor1;
- public void Render(SBViewport viewport, float frame = 0)
+ public void Render(SBViewport viewport, float frame = 0.0f)
{
//if (!IsActive)
// return;
FlashTimer++;
+
if (FlashTimer > FlashInterval)
{
FlashTimer = 0;
+
if (FlashColor == FlashColor1)
{
FlashColor = FlashColor2;
}
else
+ {
FlashColor = FlashColor1;
+ }
}
- // TODO: draw with shader
+ // TODO: Draw with shader
if (LVD != null)
{
GL.PushAttrib(AttribMask.AllAttribBits);
@@ -535,317 +726,421 @@ public void Render(SBViewport viewport, float frame = 0)
GL.UseProgram(0);
- GL.Color3(1f, 1f, 0);
- GL.LineWidth(2f);
+ GL.Color3(1.0f, 1.0f, 0.0f);
+ GL.LineWidth(2.0f);
- GL.PointSize(5f);
+ GL.PointSize(5.0f);
GL.Begin(PrimitiveType.Points);
GL.Vertex3(Picked.X, Picked.Y, Picked.Z);
GL.End();
RenderCollisions();
- foreach(var blast in LVD.BlastZoneBounds)
- RenderBounds(blast, Color.LightPink);
+ int playerIndex = 1;
- foreach (var camera in LVD.CameraBounds)
- RenderBounds(camera, Color.SkyBlue);
+ foreach (var startPosition in LVD.StartPositions)
+ {
+ if (PropertyGrid.SelectedObject == startPosition)
+ {
+ Rendering.TextRenderer.Draw(viewport.Camera, "P" + playerIndex++, Matrix4.CreateTranslation(new Vector3(startPosition.Position.X, startPosition.Position.Y, 0.0f)), FlashColor);
+ }
+ else
+ {
+ Rendering.TextRenderer.Draw(viewport.Camera, "P" + playerIndex++, Matrix4.CreateTranslation(new Vector3(startPosition.Position.X, startPosition.Position.Y, 0.0f)));
+ }
+ }
- foreach (var blast in LVD.ShrunkBlastZoneBounds)
- RenderBounds(blast, Color.LightPink);
+ foreach (var restartPosition in LVD.RestartPositions)
+ {
+ if (PropertyGrid.SelectedObject == restartPosition)
+ {
+ Rendering.Shapes.Spawn.RenderSpawn(restartPosition.Position.X, restartPosition.Position.Y, 5.0f, FlashColor);
+ }
+ else
+ {
+ Rendering.Shapes.Spawn.RenderSpawn(restartPosition.Position.X, restartPosition.Position.Y, 5.0f, new Vector3(0.95f, 0.95f, 0.95f));
+ }
+ }
- foreach (var camera in LVD.ShrunkCameraBounds)
- RenderBounds(camera, Color.SkyBlue);
+ foreach (var cameraRegion in LVD.CameraRegions)
+ {
+ RenderRegion(cameraRegion, Color.SkyBlue);
+ }
- int playerIndex = 1;
- foreach (var spawn in LVD.Spawns)
+ foreach (var deathRegion in LVD.DeathRegions)
{
- if (PropertyGrid.SelectedObject == spawn)
- Rendering.TextRenderer.Draw(viewport.Camera, "P" + playerIndex++, Matrix4.CreateTranslation(new Vector3(spawn.X, spawn.Y, 0)), FlashColor);
- else
- Rendering.TextRenderer.Draw(viewport.Camera, "P" + playerIndex++, Matrix4.CreateTranslation(new Vector3(spawn.X, spawn.Y, 0)));
-
+ RenderRegion(deathRegion, Color.LightPink);
}
- foreach (var spawn in LVD.Respawns)
+ foreach (var itemPopupRegion in LVD.ItemPopupRegions)
{
- if(PropertyGrid.SelectedObject == spawn)
- Rendering.Shapes.Spawn.RenderSpawn(spawn.X, spawn.Y, 5, FlashColor);
- else
- Rendering.Shapes.Spawn.RenderSpawn(spawn.X, spawn.Y, 5, new Vector3(0.95f, 0.95f, 0.95f));
+ foreach (var region in itemPopupRegion.Regions)
+ {
+ RenderShape(region);
+ }
}
-
- foreach (var point in LVD.GeneralPoints)
+
+ foreach (var generalShape3D in LVD.GeneralShapes3D)
{
- Rendering.Shapes.VectorGraphicType graphic = Rendering.Shapes.VectorGraphicType.StarStorm;
- Vector3 col = new Vector3(0.75f, 0.85f, 1);
- if (point.EntryLabel.Contains("Ike"))
+ Rendering.Shapes.VectorGraphicType graphic;
+ Vector3 color;
+
+ if (generalShape3D.DynamicName.Contains("KirifudaPit"))
{
graphic = Rendering.Shapes.VectorGraphicType.FireEmblem;
- col = new Vector3(1, 0.85f, 0.75f);
+ color = new Vector3(1.0f, 0.85f, 0.75f);
}
- if (point.EntryLabel.Contains("Pikmin"))
+ else if (generalShape3D.DynamicName.Contains("KirifudaPikmin"))
{
graphic = Rendering.Shapes.VectorGraphicType.Pikmin;
- col = new Vector3(0.65f, 1, 0.65f);
+ color = new Vector3(0.65f, 1.0f, 0.65f);
+ }
+ else if (generalShape3D.DynamicName.Contains("KirifudaIke"))
+ {
+ graphic = Rendering.Shapes.VectorGraphicType.FireEmblem;
+ color = new Vector3(1.0f, 0.85f, 0.75f);
+ }
+ else
+ {
+ graphic = Rendering.Shapes.VectorGraphicType.StarStorm;
+ color = new Vector3(0.75f, 0.85f, 1.0f);
}
- if (PropertyGrid.SelectedObject == point)
- col = FlashColor;
- Rendering.Shapes.VectorGraphic.RenderGraphic(graphic, Matrix4.CreateTranslation(point.X, point.Y, point.Z), col, 8);
- }
- foreach(var spawner in LVD.ItemSpawners)
- {
- foreach(var shape in spawner.Sections)
+ if (generalShape3D == PropertyGrid.SelectedObject)
{
- RenderShape(shape);
+ color = FlashColor;
}
+
+ Rendering.Shapes.VectorGraphic.RenderGraphic(graphic, Matrix4.CreateTranslation(generalShape3D.Shape.X, generalShape3D.Shape.Y, generalShape3D.Shape.Z), color, 8.0f);
+ }
+
+ foreach (var shrinkedCameraRegion in LVD.ShrinkedCameraRegions)
+ {
+ RenderRegion(shrinkedCameraRegion, Color.SkyBlue);
+ }
+
+ foreach (var shrinkedDeathRegion in LVD.ShrinkedDeathRegions)
+ {
+ RenderRegion(shrinkedDeathRegion, Color.LightPink);
}
GL.PopAttrib();
}
- if(PropertyGrid.SelectedObject is LVDVector2)
+ if (PropertyGrid.SelectedObject is LVDVector2)
{
- Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Alt+Mouse: Move Point", new Vector2(4, viewport.Camera.RenderHeight - 30));
- Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Alt + A : Add Point", new Vector2(4, viewport.Camera.RenderHeight - 16));
- Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Delete : Delete", new Vector2(4, viewport.Camera.RenderHeight - 2));
+ Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Alt+Mouse: Move Point", new Vector2(4.0f, (float)(viewport.Camera.RenderHeight - 30)));
+ Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Alt + A : Add Point", new Vector2(4.0f, (float)(viewport.Camera.RenderHeight - 16)));
+ Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Delete : Delete", new Vector2(4.0f, (float)(viewport.Camera.RenderHeight - 2)));
}
else
{
- Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Double Click to Select", new Vector2(4, viewport.Camera.RenderHeight - 16));
+ Rendering.TextRenderer.DrawOrtho(viewport.Camera, "Double Click to Select", new Vector2(4.0f, (float)(viewport.Camera.RenderHeight - 16)));
}
}
///
- /// Renders collisions from LVD
+ /// Renders all collisions to the viewport using legacy OpenGL.
///
private void RenderCollisions()
{
- foreach (var col in LVD.Collisions)
+ foreach (var collision in LVD.Collisions)
{
- for (int i = 0; i < col.Materials.Count; i++)
+ for (int i = 0; i < collision.Normals.Count; i++)
{
- if(PropertyGrid.SelectedObject == col.Vertices[i])
+ if (PropertyGrid.SelectedObject == collision.Vertices[i] || PropertyGrid.SelectedObject == collision.Vertices[i + 1])
{
- GL.Color3(1f, 1f, 0);
- GL.PointSize(12f);
+ Vector3 startPos = (collision.IsDynamic && collision.Dynamic) ? new Vector3(collision.DynamicOffset.X, collision.DynamicOffset.Y, collision.DynamicOffset.Z) : new Vector3(0.0f, 0.0f, 0.0f);
+
+ GL.Color3(1.0f, 1.0f, 0.0f);
+ GL.PointSize(12.0f);
GL.Begin(PrimitiveType.Points);
- GL.Vertex3(col.Vertices[i].X, col.Vertices[i].Y, 0);
+ GL.Vertex3(
+ (PropertyGrid.SelectedObject == collision.Vertices[i] ? collision.Vertices[i].X : collision.Vertices[i + 1].X) + startPos.X,
+ (PropertyGrid.SelectedObject == collision.Vertices[i] ? collision.Vertices[i].Y : collision.Vertices[i + 1].Y) + startPos.Y,
+ startPos.Z
+ );
GL.End();
}
- RenderWall(col, col.Vertices[i], col.Vertices[i+1], col.Materials[i], new Vector2(col.Normals[i].X, col.Normals[i].Y));
+
+ RenderEdge(
+ collision,
+ collision.Vertices[i],
+ collision.Vertices[i + 1],
+ collision.Attributes.Count != 0 ? collision.Attributes[i] : new LVDCollisionAttribute(),
+ new Vector2(collision.Normals[i].X, collision.Normals[i].Y)
+ );
}
}
}
///
- /// Renders a collision wall
+ /// Renders an edge to the viewport using legacy OpenGL.
///
- ///
+ ///
///
///
- ///
+ ///
///
- private void RenderWall(LVDCollision col, LVDVector2 p1, LVDVector2 p2, LVDCollisionMaterial mat, Vector2 normal)
+ private void RenderEdge(LVDCollision collision, LVDVector2 p1, LVDVector2 p2, LVDCollisionAttribute attribute, Vector2 normal)
{
+ Vector2 startPos = (collision.IsDynamic && collision.Dynamic) ? new Vector2(collision.DynamicOffset.X, collision.DynamicOffset.Y) : new Vector2(0.0f, 0.0f);
Vector2 v1 = new Vector2(p1.X, p1.Y);
Vector2 v2 = new Vector2(p2.X, p2.Y);
- Vector2 mid = (v1 + v2) / 2;
- Vector2 nrm = mid + normal * 3;
+ Vector2 mid = (v1 + v2) / 2.0f;
+ Vector2 nrm = mid + normal * 3.0f;
Vector3 p1Color = GetElementColor(p1);
Vector3 p2Color = GetElementColor(p2);
- if(PropertyGrid.SelectedObject == col)
+
+ if (PropertyGrid.SelectedObject == collision)
{
p1Color = FlashColor;
p2Color = FlashColor;
}
// material
- var materialColor = GetMatlColor(mat);
- GL.Color4(materialColor.R / 255f, materialColor.G / 255f, materialColor.B / 255f, 0.75f);
+ var materialColor = GetMaterialColor(attribute);
+ GL.Color4(materialColor.R / 255.0f, materialColor.G / 255.0f, materialColor.B / 255.0f, 0.75f);
GL.Begin(PrimitiveType.Quads);
- GL.Vertex3(p1.X, p1.Y, 0);
- GL.Vertex3(p1.X, p1.Y, -PlatformWidth);
- GL.Vertex3(p2.X, p2.Y, -PlatformWidth);
- GL.Vertex3(p2.X, p2.Y, 0);
+ GL.Vertex3(p1.X + startPos.X, p1.Y + startPos.Y, 0.0f);
+ GL.Vertex3(p1.X + startPos.X, p1.Y + startPos.Y, -CollisionDepth);
+ GL.Vertex3(p2.X + startPos.X, p2.Y + startPos.Y, -CollisionDepth);
+ GL.Vertex3(p2.X + startPos.X, p2.Y + startPos.Y, 0.0f);
GL.End();
- GL.LineWidth(2f);
+ GL.LineWidth(2.0f);
GL.Begin(PrimitiveType.Lines);
// point line 1
GL.Color3(p1Color);
- GL.Vertex3(v1.X, v1.Y, 0);
+ GL.Vertex3(v1.X + startPos.X, v1.Y + startPos.Y, 0.0f);
GL.Color3(p1Color);
- GL.Vertex3(v1.X, v1.Y, -PlatformWidth);
+ GL.Vertex3(v1.X + startPos.X, v1.Y + startPos.Y, -CollisionDepth);
// point line 2
GL.Color3(p2Color);
- GL.Vertex3(v2.X, v2.Y, 0);
+ GL.Vertex3(v2.X + startPos.X, v2.Y + startPos.Y, 0.0f);
GL.Color3(p2Color);
- GL.Vertex3(v2.X, v2.Y, -PlatformWidth);
+ GL.Vertex3(v2.X + startPos.X, v2.Y + startPos.Y, -CollisionDepth);
// front line
GL.Color3(p1Color);
- GL.Vertex3(v1.X, v1.Y, 0);
+ GL.Vertex3(v1.X + startPos.X, v1.Y + startPos.Y , 0.0f);
GL.Color3(p2Color);
- GL.Vertex3(v2.X, v2.Y, 0);
+ GL.Vertex3(v2.X + startPos.X, v2.Y + startPos.Y, 0.0f);
// back line
GL.Color3(p1Color);
- GL.Vertex3(v1.X, v1.Y, -PlatformWidth);
+ GL.Vertex3(v1.X + startPos.X, v1.Y + startPos.Y, -CollisionDepth);
GL.Color3(p2Color);
- GL.Vertex3(v2.X, v2.Y, -PlatformWidth);
+ GL.Vertex3(v2.X + startPos.X, v2.Y + startPos.Y, -CollisionDepth);
// normal
- GL.Color3(GetNormalColor(col, normal, mat));
- GL.Vertex3(mid.X, mid.Y, -PlatformWidth/2);
- GL.Color3(GetNormalColor(col, normal, mat));
- GL.Vertex3(nrm.X, nrm.Y, -PlatformWidth/2);
+ GL.Color3(GetNormalColor(collision, normal, attribute));
+ GL.Vertex3(mid.X + startPos.X, mid.Y + startPos.Y, -CollisionDepth / 2.0f);
+ GL.Color3(GetNormalColor(collision, normal, attribute));
+ GL.Vertex3(nrm.X + startPos.X, nrm.Y + startPos.Y, -CollisionDepth / 2.0f);
GL.End();
}
-
///
- /// Renders the bounds using legacy opengl camera, blastzones ect...
+ /// Renders a rectangular region to the viewport using legacy OpenGL.
///
- ///
+ ///
///
- private void RenderBounds(LVDBounds b, Color color)
+ private void RenderRegion(LVDRegion region, Color color)
{
- Vector3 sPos = b.UseStartPosition ? new Vector3(b.StartPosition.X, b.StartPosition.Y, b.StartPosition.Z) : new Vector3(0, 0, 0);
-
GL.Color4(Color.FromArgb(128, color));
- if (PropertyGrid.SelectedObject == b)
+
+ if (PropertyGrid.SelectedObject == region)
+ {
GL.Color3(FlashColor);
+ }
- GL.LineWidth(2);
+ GL.LineWidth(2.0f);
GL.Begin(PrimitiveType.LineLoop);
- GL.Vertex3(b.Left + sPos.X, b.Top + sPos.Y, sPos.Z);
- GL.Vertex3(b.Right + sPos.X, b.Top + sPos.Y, sPos.Z);
- GL.Vertex3(b.Right + sPos.X, b.Bottom + sPos.Y, sPos.Z);
- GL.Vertex3(b.Left + sPos.X, b.Bottom + sPos.Y, sPos.Z);
+ GL.Vertex3(region.Rectangle.Left, region.Rectangle.Top, 0.0f);
+ GL.Vertex3(region.Rectangle.Right, region.Rectangle.Top, 0.0f);
+ GL.Vertex3(region.Rectangle.Right, region.Rectangle.Bottom, 0.0f);
+ GL.Vertex3(region.Rectangle.Left, region.Rectangle.Bottom, 0.0f);
GL.End();
}
///
- /// Returns color of normal
+ /// Returns color of the unit normal vector.
///
- ///
- ///
- ///
+ ///
+ ///
+ ///
///
- private Color GetNormalColor(LVDCollision c, Vector2 normals, LVDCollisionMaterial material)
+ private Color GetNormalColor(LVDCollision collision, Vector2 normal, LVDCollisionAttribute attribute)
{
- float angle = (float)(Math.Atan2(normals.Y, normals.X) * 180 / Math.PI);
+ float angle = (float)Math.Atan2(normal.Y, normal.X) * 180.0f / (float)Math.PI;
- if (c.PassThrough)
+ // Check edge attributes first, then determine unit normal vector color from the angle of the edge.
+ if (collision.DropThrough || attribute.DropThrough)
+ {
return Color.FromArgb(128, Color.Yellow);
- else if (material.GetFlag(4) && ((angle <= 0 && angle >= -70) || (angle <= -110 && angle >= -180) || angle == 180))
- return Color.FromArgb(128, Color.Purple);
- else if ((angle <= 0 && angle >= -70) || (angle <= -110 && angle >= -180) || angle == 180)
+ }
+ else if (attribute.RightWallOverride || attribute.LeftWallOverride)
+ {
return Color.FromArgb(128, Color.Lime);
- else if (normals.Y < 0)
+ }
+ else if (attribute.CeilingOverride)
+ {
return Color.FromArgb(128, Color.Red);
- else
+ }
+ else if (attribute.FloorOverride || (angle > 40.0f && angle < 140.0f))
+ {
return Color.FromArgb(128, Color.Cyan);
+ }
+ else if (((angle >= 140.0f && angle <= 180.0f) || angle < -110.0f) || (angle <= 40.0f && angle > -70.0f))
+ {
+ return attribute.NoWallJump ? Color.FromArgb(128, Color.Purple) : Color.FromArgb(128, Color.Lime);
+ }
+ else if (angle >= -110.0f && angle <= -70.0f)
+ {
+ return Color.FromArgb(128, Color.Red);
+ }
+ else
+ {
+ return Color.FromArgb(128, Color.Black);
+ }
}
///
- /// render lvd shape to the viewport
+ /// Renders an LVD shape to the viewport using legacy OpenGL.
///
///
- private void RenderShape(LVDShape shape)
+ private void RenderShape(LVDShape2 shape)
{
switch (shape.Type)
{
- case LVDShapeType.Circle:
+ case LVDShape2Type.Point:
+ break;
+ case LVDShape2Type.Circle:
break;
- case LVDShapeType.Path:
+ case LVDShape2Type.Rectangle:
+ break;
+ case LVDShape2Type.Path:
GL.Color3(Color.Bisque);
GL.Begin(PrimitiveType.LineStrip);
+
foreach (var p in shape.Points)
- GL.Vertex3(p.X, p.Y, 0);
+ {
+ GL.Vertex3(p.X, p.Y, 0.0f);
+ }
+
GL.End();
break;
- case LVDShapeType.Point:
- break;
- case LVDShapeType.Rectangle:
- break;
}
}
///
- /// returns color of Collision Material
+ /// Returns the color of the collision's edge's assigned material.
///
- ///
+ ///
///
- private Color GetMatlColor(LVDCollisionMaterial mat)
+ private Color GetMaterialColor(LVDCollisionAttribute attribute)
{
- if (PropertyGrid.SelectedObject == mat)
- return Color.FromArgb(255, (int)(FlashColor.X * 255), (int)(FlashColor.Y * 255), (int)(FlashColor.Z * 255));
- switch (mat.Physics)
+ if (PropertyGrid.SelectedObject == attribute)
{
- case CollisionMatType.Basic:
- return Color.AliceBlue;
- case CollisionMatType.Brick:
- return Color.SaddleBrown;
- case CollisionMatType.Cloud:
- return Color.FromArgb(0xFF, 0xF6, 0x9A, 0xB0);
- case CollisionMatType.Alien:
- return Color.DarkGreen;
- case CollisionMatType.Cardboard:
- return Color.SandyBrown;
- case CollisionMatType.Carpet:
- return Color.PaleVioletRed;
- case CollisionMatType.Electroplankton:
- return Color.DarkSeaGreen;
- case CollisionMatType.GameWatch:
- return Color.LightGray;
- case CollisionMatType.Grass:
+ return Color.FromArgb(255, (int)(FlashColor.X * 255.0f), (int)(FlashColor.Y * 255.0f), (int)(FlashColor.Z * 255.0f));
+ }
+
+ switch (attribute.Type)
+ {
+ case LVDCollisionMaterialType.Basic:
+ return Color.WhiteSmoke;
+ case LVDCollisionMaterialType.Rock:
+ return Color.SlateGray;
+ case LVDCollisionMaterialType.Grass:
return Color.ForestGreen;
- case CollisionMatType.Grate:
- return Color.Gray;
- case CollisionMatType.Hazard2SSEOnly:
- return Color.Gray;
- case CollisionMatType.Hazard3SSEOnly:
- return Color.Gray;
- case CollisionMatType.HeavyMetal:
+ case LVDCollisionMaterialType.Soil:
+ return Color.Sienna;
+ case LVDCollisionMaterialType.Wood:
+ return Color.BurlyWood;
+ case LVDCollisionMaterialType.LightMetal:
return Color.LightGray;
- case CollisionMatType.Homerun:
- return Color.LawnGreen;
- case CollisionMatType.Hurt:
- return Color.IndianRed;
- case CollisionMatType.Ice:
+ case LVDCollisionMaterialType.HeavyMetal:
+ return Color.DarkGray;
+ case LVDCollisionMaterialType.Carpet:
+ return Color.Tomato;
+ case LVDCollisionMaterialType.Slimy:
+ return Color.Goldenrod;
+ case LVDCollisionMaterialType.Creature:
+ return Color.DarkOliveGreen;
+ case LVDCollisionMaterialType.Shoal:
+ return Color.LightSkyBlue;
+ case LVDCollisionMaterialType.Soft:
+ return Color.LightPink;
+ case LVDCollisionMaterialType.Slippery:
+ return Color.LightGreen;
+ case LVDCollisionMaterialType.Snow:
+ return Color.Snow;
+ case LVDCollisionMaterialType.Ice:
return Color.CornflowerBlue;
- case CollisionMatType.LightMetal:
- return Color.LightGray;
- case CollisionMatType.MasterFortress:
+ case LVDCollisionMaterialType.GameWatch:
+ return Color.DarkKhaki;
+ case LVDCollisionMaterialType.Oil:
return Color.DarkSlateGray;
- case CollisionMatType.NES8Bit:
+ case LVDCollisionMaterialType.Cardboard:
+ return Color.Peru;
+ case LVDCollisionMaterialType.Damage1:
+ case LVDCollisionMaterialType.Damage2:
+ case LVDCollisionMaterialType.Damage3:
return Color.Gray;
- case CollisionMatType.Oil:
- return Color.DarkSlateGray;
- case CollisionMatType.Rock:
- return Color.RosyBrown;
- case CollisionMatType.Sand:
+ case LVDCollisionMaterialType.Hanenbow:
+ return Color.DarkSeaGreen;
+ case LVDCollisionMaterialType.Cloud:
+ return Color.FromArgb(0xFF, 0xF6, 0x9A, 0xB0);
+ case LVDCollisionMaterialType.Subspace:
+ return Color.PaleVioletRed;
+ case LVDCollisionMaterialType.Brick:
+ return Color.DarkSalmon;
+ case LVDCollisionMaterialType.NoAttr:
+ return Color.AliceBlue;
+ case LVDCollisionMaterialType.Famicom:
+ return Color.OrangeRed;
+ case LVDCollisionMaterialType.WireNetting:
+ return Color.DimGray;
+ case LVDCollisionMaterialType.Sand:
return Color.SandyBrown;
- case CollisionMatType.Snow:
- return Color.LightBlue;
- case CollisionMatType.Soft:
- return Color.LightPink;
- case CollisionMatType.Soil:
- return Color.Brown;
- case CollisionMatType.SpikesTargetTest:
+ case LVDCollisionMaterialType.Homerun:
+ return Color.Gray;
+ case LVDCollisionMaterialType.AsaseEarth:
+ return Color.LightSkyBlue;
+ case LVDCollisionMaterialType.Death:
return Color.IndianRed;
- case CollisionMatType.Wood:
- return Color.Brown;
+ case LVDCollisionMaterialType.BoxingRing:
+ return Color.DeepSkyBlue;
+ case LVDCollisionMaterialType.Glass:
+ return Color.GhostWhite;
+ case LVDCollisionMaterialType.SlipDx:
+ return Color.LightSlateGray;
+ case LVDCollisionMaterialType.SpPoison:
+ return Color.MediumOrchid;
+ case LVDCollisionMaterialType.SpFlame:
+ return Color.DarkOrange;
+ case LVDCollisionMaterialType.SpElectricShock:
+ return Color.Yellow;
+ case LVDCollisionMaterialType.SpSleep:
+ return Color.Violet;
+ case LVDCollisionMaterialType.SpFreezing:
+ return Color.RoyalBlue;
+ case LVDCollisionMaterialType.SpAdhesion:
+ return Color.FromArgb(0xFF, 0x70, 0x64, 0x4A);
+ case LVDCollisionMaterialType.IceNoSlip:
+ return Color.CornflowerBlue;
+ case LVDCollisionMaterialType.CloudNoThrough:
+ return Color.FromArgb(0xFF, 0xF6, 0x9A, 0xB0);
+ case LVDCollisionMaterialType.Metaverse:
+ return Color.Crimson;
default:
return Color.Black;
}
@@ -859,9 +1154,13 @@ private Color GetMatlColor(LVDCollisionMaterial mat)
private Vector3 GetElementColor(object o)
{
if (PropertyGrid.SelectedObject == o)
+ {
return (FlashColor);
+ }
else
- return new Vector3(0f, 0f, 0f);
+ {
+ return new Vector3(0.0f, 0.0f, 0.0f);
+ }
}
#endregion
}
diff --git a/StudioSB/IO/Formats/IO_SSF.cs b/StudioSB/IO/Formats/IO_SSF.cs
index d7cc519..25451fc 100644
--- a/StudioSB/IO/Formats/IO_SSF.cs
+++ b/StudioSB/IO/Formats/IO_SSF.cs
@@ -7,89 +7,107 @@ public class IO_SSF
///
///
///
- ///
+ ///
///
- 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);
}
}
-
-
}
diff --git a/StudioSB/IO/Formats/SSF.cs b/StudioSB/IO/Formats/SSF.cs
index 7acc0af..c7dbc3e 100644
--- a/StudioSB/IO/Formats/SSF.cs
+++ b/StudioSB/IO/Formats/SSF.cs
@@ -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]
@@ -48,17 +58,17 @@ public class SSFPoint
public class SSFGroup
{
public string Name;
- public string Bone;
- public List Lines = new List();
+ public string JointName;
public List Vertices = new List();
+ public List Edges = new List();
}
- 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;
}
diff --git a/StudioSB/Scenes/LVD/LVDBase.cs b/StudioSB/Scenes/LVD/LVDBase.cs
new file mode 100644
index 0000000..b0e9f9d
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDBase.cs
@@ -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);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDBounds.cs b/StudioSB/Scenes/LVD/LVDBounds.cs
deleted file mode 100644
index 7cd3118..0000000
--- a/StudioSB/Scenes/LVD/LVDBounds.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDBounds : LVDEntry
- {
- public float Left { get; set; }
- public float Right { get; set; }
- public float Top { get; set; }
- public float Bottom { get; set; }
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- r.Skip(1);
- Left = r.ReadSingle();
- Right = r.ReadSingle();
- Top = r.ReadSingle();
- Bottom = r.ReadSingle();
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(Left);
- writer.Write(Right);
- writer.Write(Top);
- writer.Write(Bottom);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDCollision.cs b/StudioSB/Scenes/LVD/LVDCollision.cs
index add844e..79eae7a 100644
--- a/StudioSB/Scenes/LVD/LVDCollision.cs
+++ b/StudioSB/Scenes/LVD/LVDCollision.cs
@@ -1,75 +1,19 @@
using StudioSB.Tools;
-using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace StudioSB.Scenes.LVD
{
- public class LVDVector2
+ public class LVDCollision : LVDBase
{
- public float X { get; set; }
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 4;
- public float Y { get; set; }
+ [Category("CollisionFlags")]
+ public bool Dynamic { get; set; } = false;
- public LVDVector2(float x, float y)
- {
- X = x;
- Y = y;
- }
-
- public override string ToString()
- {
- return $"({X}, {Y})";
- }
-
- public LVDVector2 Normalized()
- {
- float length = (float)Math.Sqrt(X * X + Y * Y);
- return new LVDVector2(X / length, Y / length);
- }
-
- public static LVDVector2 GenerateNormal(LVDVector2 v1, LVDVector2 v2)
- {
- LVDVector2 normal = new LVDVector2(v2.Y - v1.Y, v2.X - v1.X).Normalized();
- normal.X *= -1;
- return normal;
- }
- }
-
- public class LVDVector3
- {
- public float X { get; set; }
-
- public float Y { get; set; }
-
- public float Z { get; set; }
-
- public LVDVector3(float x, float y, float z)
- {
- X = x;
- Y = y;
- Z = z;
- }
-
- public override string ToString()
- {
- return $"({X}, {Y}, {Z})";
- }
- }
-
- public class LVDCollision : LVDEntry
- {
- [Category("Collision")]
- public bool Flag1 { get; set; } = false;
-
- [Category("Collision")]
- public bool Rigged { get; set; } = false;
-
- [Category("Collision")]
- public bool Flag3 { get; set; } = false;
-
- [Category("Collision")]
- public bool PassThrough { get; set; } = false;
+ [Category("CollisionFlags")]
+ public bool DropThrough { get; set; } = false;
[Category("Collision")]
public List Vertices { get; set; } = new List();
@@ -81,94 +25,120 @@ public class LVDCollision : LVDEntry
public List Cliffs { get; set; } = new List();
[Category("Collision")]
- public List Materials { get; set; } = new List();
-
+ public List Attributes { get; set; } = new List();
+
[Category("Collision")]
- public List Curves = new List();
+ public List SpiritsFloors { get; set; } = new List();
- public void Read(BinaryReaderExt r, int VersionMinor)
+ public override void Read(BinaryReaderExt reader)
{
- base.Read(r);
+ Version = reader.ReadByte();
- Flag1 = r.ReadBoolean();
- Rigged = r.ReadBoolean();
- Flag3 = r.ReadBoolean();
- PassThrough = r.ReadBoolean();
+ if (Version < 2)
+ {
+ MetaInfo.Read(reader);
+ }
+ else
+ {
+ base.Read(reader);
+ }
+
+ reader.Skip(1);
+ Dynamic = reader.ReadBoolean();
+ reader.Skip(1);
+ DropThrough = reader.ReadBoolean();
- r.ReadByte();
- int vertCount = r.ReadInt32();
- for (int i = 0; i < vertCount; i++)
+ reader.Skip(1);
+ uint vertexCount = reader.ReadUInt32();
+ for (uint i = 0; i < vertexCount; i++)
{
- r.ReadByte();
- Vertices.Add(new LVDVector2(r.ReadSingle(), r.ReadSingle()));
+ LVDVector2 vertex = new LVDVector2(0.0f, 0.0f);
+
+ vertex.Read(reader);
+ Vertices.Add(vertex);
}
-
- r.ReadByte();
- int normalCount = r.ReadInt32();
- for (int i = 0; i < normalCount; i++)
+
+ reader.Skip(1);
+ uint normalCount = reader.ReadUInt32();
+ for (uint i = 0; i < normalCount; i++)
{
- r.ReadByte();
- Normals.Add(new LVDVector2(r.ReadSingle(), r.ReadSingle()));
+ LVDVector2 normal = new LVDVector2(0.0f, 0.0f);
+
+ normal.Read(reader);
+ Normals.Add(normal);
}
- r.ReadByte();
- int cliffCount = r.ReadInt32();
- for (int i = 0; i < cliffCount; i++)
+ reader.Skip(1);
+ uint cliffCount = reader.ReadUInt32();
+ for (uint i = 0; i < cliffCount; i++)
{
- var cliff = new LVDCollisionCliff();
- cliff.Read(r);
+ LVDCollisionCliff cliff = new LVDCollisionCliff();
+
+ cliff.Read(reader);
Cliffs.Add(cliff);
}
-
- r.ReadByte();
- int materialCount = r.ReadInt32();
- for (int i = 0; i < materialCount; i++)
+
+ if (Version < 3)
{
- var material = new LVDCollisionMaterial();
- material.Read(r);
- Materials.Add(material);
+ return;
}
- // Ultimate Only?
+ reader.Skip(1);
+ uint attributeCount = reader.ReadUInt32();
+ for (uint i = 0; i < attributeCount; i++)
+ {
+ LVDCollisionAttribute attribute = new LVDCollisionAttribute();
- if(VersionMinor > 10)
+ attribute.Read(reader);
+ Attributes.Add(attribute);
+ }
+
+ if (Version < 4)
{
- r.ReadByte();
- var vecCount = r.ReadInt32();
- for(int i = 0; i < vecCount; i++)
- {
- var vec = new LVDCollisionCurve();
- vec.Read(r);
- Curves.Add(vec);
- }
+ return;
+ }
+
+ reader.Skip(1);
+ uint spiritsFloorCount = reader.ReadUInt32();
+ for (uint i = 0; i < spiritsFloorCount; i++)
+ {
+ LVDCollisionSpiritsFloor spiritsFloor = new LVDCollisionSpiritsFloor();
+
+ spiritsFloor.Read(reader);
+ SpiritsFloors.Add(spiritsFloor);
}
}
- public void Write(BinaryWriterExt writer, int VersionMinor)
+ public override void Write(BinaryWriterExt writer)
{
- base.Write(writer);
+ writer.Write(Version);
- writer.Write(Flag1);
- writer.Write(Rigged);
- writer.Write(Flag3);
- writer.Write(PassThrough);
+ if (Version < 2)
+ {
+ MetaInfo.Write(writer);
+ }
+ else
+ {
+ base.Write(writer);
+ }
+
+ writer.Write((byte)0);
+ writer.Write(Dynamic);
+ writer.Write((byte)0);
+ writer.Write(DropThrough);
writer.Write((byte)1);
writer.Write(Vertices.Count);
- foreach(var v in Vertices)
+ foreach (var v in Vertices)
{
- writer.Write((byte)1);
- writer.Write(v.X);
- writer.Write(v.Y);
+ v.Write(writer);
}
writer.Write((byte)1);
writer.Write(Normals.Count);
foreach (var v in Normals)
{
- writer.Write((byte)1);
- writer.Write(v.X);
- writer.Write(v.Y);
+ v.Write(writer);
}
writer.Write((byte)1);
@@ -178,21 +148,28 @@ public void Write(BinaryWriterExt writer, int VersionMinor)
v.Write(writer);
}
+ if (Version < 3)
+ {
+ return;
+ }
+
writer.Write((byte)1);
- writer.Write(Materials.Count);
- foreach (var v in Materials)
+ writer.Write(Attributes.Count);
+ foreach (var v in Attributes)
{
v.Write(writer);
}
-
- if (VersionMinor > 10)
- {
- writer.Write((byte)1);
- writer.Write(Curves.Count);
- foreach (var v in Curves)
- {
- v.Write(writer);
- }
+
+ if (Version < 4)
+ {
+ return;
+ }
+
+ writer.Write((byte)1);
+ writer.Write(SpiritsFloors.Count);
+ foreach (var v in SpiritsFloors)
+ {
+ v.Write(writer);
}
}
}
diff --git a/StudioSB/Scenes/LVD/LVDCollisionAttribute.cs b/StudioSB/Scenes/LVD/LVDCollisionAttribute.cs
new file mode 100644
index 0000000..c08d8ee
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDCollisionAttribute.cs
@@ -0,0 +1,191 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public enum LVDCollisionMaterialType : uint
+ {
+ Basic = 0x00, //
+ Rock = 0x01, //
+ Grass = 0x02, // Produces a grass shard effect.
+ Soil = 0x03, // Produces a soil particle effect when landing.
+ Wood = 0x04, //
+ LightMetal = 0x05, // Internally "Iron"
+ HeavyMetal = 0x06, // Internally "NibuIron"
+ Carpet = 0x07, //
+ Slimy = 0x08, // Internally "Numenume"
+ Creature = 0x09, //
+ Shoal = 0x0A, // Internally "Asase." Produces a water splash effect.
+ Soft = 0x0B, //
+ Slippery = 0x0C, // Internally "Turuturu." Friction value of 0.1.
+ Snow = 0x0D, //
+ Ice = 0x0E, // Friction value of 0.2. Produces an ice particle effect when landing.
+ GameWatch = 0x0F, // Used on the Flat Zone X stage.
+ Oil = 0x10, // Used on the Flat Zone X stage on the Helmet game. Friction value of 0.1.
+ Cardboard = 0x11, // Internally "Danbouru"
+ Damage1 = 0x12, // "damage_id" value of 1.
+ Damage2 = 0x13, // "damage_id" value of 2.
+ Damage3 = 0x14, // "damage_id" value of 3.
+ Hanenbow = 0x15, // Used on the Hanenbow stage.
+ Cloud = 0x16, // Force-enables supersoft properties.
+ Subspace = 0x17, // Internally "Akuukan"
+ Brick = 0x18, //
+ NoAttr = 0x19, // Same as the "Basic" material but does not produce any special graphical or sound effects.
+ Famicom = 0x1A, // Used on the Mario Bros. stage.
+ WireNetting = 0x1B, //
+ Sand = 0x1C, // Produces a sand particle effect when landing.
+ Homerun = 0x1D, //
+ AsaseEarth = 0x1E, //
+ Death = 0x1F, // "damage_id" value of 4.
+ BoxingRing = 0x20, // Used on the Boxing Ring stage.
+ Glass = 0x21, //
+ SlipDx = 0x22, // Used for slippery surfaces on newly-returning Melee stages. Friction value of 0.4.
+ SpPoison = 0x23, // Used for environmental floor hazards in spirit battles.
+ SpFlame = 0x24, // Used for environmental floor hazards in spirit battles.
+ SpElectricShock = 0x25, // Used for environmental floor hazards in spirit battles.
+ SpSleep = 0x26, // Used for environmental floor hazards in spirit battles.
+ SpFreezing = 0x27, // Used for environmental floor hazards in spirit battles. Same as the "Ice" material.
+ SpAdhesion = 0x28, // Used for environmental floor hazards in spirit battles.
+ IceNoSlip = 0x29, // Same as the "Ice" material but does not have any reduced traction.
+ CloudNoThrough = 0x2A, // Same as the "Cloud" material but does not force-enable supersoft properties.
+ Metaverse = 0x2B, // Internally "Jack_Mementoes." Produces the Metaverse splash effect.
+ }
+
+ public class LVDCollisionAttribute
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ private uint[] MaterialData = new uint[3];
+
+ [Category("Material")]
+ public LVDCollisionMaterialType Type
+ {
+ get { return (LVDCollisionMaterialType)MaterialData[0]; }
+ set { MaterialData[0] = (uint)value; }
+ }
+
+ [Category("Attributes")]
+ public bool Unpaintable
+ {
+ get { return GetFlag(5); }
+ set { SetFlag(5, value); }
+ }
+
+ [Category("Attributes")]
+ public bool RightWallOverride
+ {
+ get { return GetFlag(8); }
+ set { SetFlag(8, value); }
+ }
+
+ [Category("Attributes")]
+ public bool LeftWallOverride
+ {
+ get { return GetFlag(9); }
+ set { SetFlag(9, value); }
+ }
+
+ [Category("Attributes")]
+ public bool CeilingOverride
+ {
+ get { return GetFlag(10); }
+ set { SetFlag(10, value); }
+ }
+
+ [Category("Attributes")]
+ public bool FloorOverride
+ {
+ get { return GetFlag(11); }
+ set { SetFlag(11, value); }
+ }
+
+ [Category("Attributes")]
+ public bool NoWallJump
+ {
+ get { return GetFlag(12); }
+ set { SetFlag(12, value); }
+ }
+
+ [Category("Attributes")]
+ public bool DropThrough
+ {
+ get { return GetFlag(13); }
+ set { SetFlag(13, value); }
+ }
+
+ [Category("Attributes")]
+ public bool LeftLedge
+ {
+ get { return GetFlag(14); }
+ set { SetFlag(14, value); }
+ }
+
+ [Category("Attributes")]
+ public bool RightLedge
+ {
+ get { return GetFlag(15); }
+ set { SetFlag(15, value); }
+ }
+
+ [Category("Attributes")]
+ public bool IgnoreLinkFromLeft
+ {
+ get { return GetFlag(16); }
+ set { SetFlag(16, value); }
+ }
+
+ [Category("Attributes")]
+ public bool Supersoft
+ {
+ get { return GetFlag(17); }
+ set { SetFlag(17, value); }
+ }
+
+ [Category("Attributes")]
+ public bool IgnoreLinkFromRight
+ {
+ get { return GetFlag(18); }
+ set { SetFlag(18, value); }
+ }
+
+ public bool GetFlag(int n)
+ {
+ return (MaterialData[2] & 1 << n) != 0;
+ }
+
+ public void SetFlag(int flag, bool value)
+ {
+ uint mask = (uint)(1 << flag);
+
+ if (value)
+ {
+ MaterialData[2] |= mask;
+ }
+ else
+ {
+ MaterialData[2] &= ~mask;
+ }
+ }
+
+ public void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ for (int i = 0; i < MaterialData.Length; i++)
+ {
+ MaterialData[i] = reader.ReadUInt32();
+ }
+ }
+
+ public void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ for (int i = 0; i < MaterialData.Length; i++)
+ {
+ writer.Write(MaterialData[i]);
+ }
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDCollisionCliff.cs b/StudioSB/Scenes/LVD/LVDCollisionCliff.cs
index c70a67b..b8b51ff 100644
--- a/StudioSB/Scenes/LVD/LVDCollisionCliff.cs
+++ b/StudioSB/Scenes/LVD/LVDCollisionCliff.cs
@@ -1,34 +1,61 @@
using StudioSB.Tools;
+using System.ComponentModel;
namespace StudioSB.Scenes.LVD
{
- public class LVDCollisionCliff : LVDEntry
+ public class LVDCollisionCliff : LVDBase
{
- public LVDVector2 Position { get; set; } = new LVDVector2(0, 0);
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 3;
- public float Angle { get; set; } = 0;
+ [Category("Values"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDVector2 Position { get; set; } = new LVDVector2(0.0f, 0.0f);
- public int LineIndex { get; set; } = 0;
+ [Category("Values")]
+ public float Lr { get; set; }
- public override void Read(BinaryReaderExt r)
+ [Category("Values")]
+ public int LineIndex { get; set; }
+
+ public override void Read(BinaryReaderExt reader)
{
- base.Read(r);
-
- r.Skip(1);
- Position.X = r.ReadSingle();
- Position.Y = r.ReadSingle();
- Angle = r.ReadSingle();
- LineIndex = r.ReadInt32();
+ Version = reader.ReadByte();
+
+ if (Version > 1)
+ {
+ base.Read(reader);
+ }
+
+ Position.Read(reader);
+
+ Lr = reader.ReadSingle();
+
+ if (Version < 3)
+ {
+ return;
+ }
+
+ LineIndex = reader.ReadInt32();
}
public override void Write(BinaryWriterExt writer)
{
- base.Write(writer);
+ writer.Write(Version);
+
+ if (Version > 1)
+ {
+ base.Write(writer);
+ }
+
+ Position.Write(writer);
+
+ writer.Write(Lr);
+
+ if (Version < 3)
+ {
+ return;
+ }
- writer.Write((byte)1);
- writer.Write(Position.X);
- writer.Write(Position.Y);
- writer.Write(Angle);
writer.Write(LineIndex);
}
}
diff --git a/StudioSB/Scenes/LVD/LVDCollisionCurve.cs b/StudioSB/Scenes/LVD/LVDCollisionCurve.cs
deleted file mode 100644
index 15286d3..0000000
--- a/StudioSB/Scenes/LVD/LVDCollisionCurve.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDCollisionCurve : LVDEntry
- {
- public int ID { get; set; }
-
- public string Name { get; set; }
-
- public float X { get; set; } = 1;
-
- public float Y { get; set; } = 1;
-
- public float Z { get; set; } = 1;
-
- public float W { get; set; } = 1;
-
- public int Unknown1 { get; set; } = 0;
-
- public int Unknown2 { get; set; } = 0;
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- ID = r.ReadInt32();
-
- r.Skip(1);
- Name = r.ReadString(0x40);
-
- X = r.ReadSingle();
- Y = r.ReadSingle();
- Z = r.ReadSingle();
- W = r.ReadSingle();
-
- Unknown1 = r.ReadInt32();
- Unknown2 = r.ReadInt32();
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write(ID);
-
- writer.Write((byte)1);
- writer.Write(Name.ToCharArray());
- writer.Write(new byte[0x40 - Name.Length]);
-
- writer.Write(X);
- writer.Write(Y);
- writer.Write(Z);
- writer.Write(W);
-
- writer.Write(Unknown1);
- writer.Write(Unknown2);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDCollisionMaterial.cs b/StudioSB/Scenes/LVD/LVDCollisionMaterial.cs
deleted file mode 100644
index 1df422a..0000000
--- a/StudioSB/Scenes/LVD/LVDCollisionMaterial.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public enum CollisionMatType : byte
- {
- Basic = 0x00, //
- Rock = 0x01, //
- Grass = 0x02, //Increased traction (1.5)
- Soil = 0x03, //
- Wood = 0x04, //
- LightMetal = 0x05, //"Iron" internally.
- HeavyMetal = 0x06, //"NibuIron" (Iron2) internally.
- Carpet = 0x07, //Used for Delfino Plaza roof things
- Alien = 0x08, //"NumeNume" (squelch sound) internally. Used on Brinstar
- MasterFortress = 0x09, //"Creature" internally.
- WaterShallow = 0x0a, //"Asase" (shallows) internally. Used for Delfino Plaza shallow water
- Soft = 0x0b, //Used on Woolly World
- TuruTuru = 0x0c, //Reduced traction (0.1). Unknown meaning and use
- Snow = 0x0d, //
- Ice = 0x0e, //Reduced traction (0.2). Used on P. Stadium 2 ice form
- GameWatch = 0x0f, //Used on Flat Zone
- Oil = 0x10, //Reduced traction (0.1). Used for Flat Zone oil spill (presumably; not found in any collisions)
- Cardboard = 0x11, //"Danbouru" (corrugated cardboard) internally. Used on Paper Mario
- SpikesTargetTest = 0x12, //Unknown. From Brawl, and appears to still be hazard-related but is probably not functional
- Hazard2SSEOnly = 0x13, //See above
- Hazard3SSEOnly = 0x14, //See above
- Electroplankton = 0x15, //"ElectroP" internally. Not known to be used anywhere in this game
- Cloud = 0x16, //Used on Skyworld, Magicant
- Subspace = 0x17, //"Akuukan" (subspace) internally. Not known to be used anywhere in this game
- Brick = 0x18, //Used on Skyworld, Gerudo V., Smash Run
- Unknown1 = 0x19, //Unknown. From Brawl
- NES8Bit = 0x1a, //"Famicom" internally. Not known to be used anywhere in this game
- Grate = 0x1b, //Used on Delfino and P. Stadium 2
- Sand = 0x1c, //
- Homerun = 0x1d, //From Brawl, may not be functional
- WaterNoSplash = 0x1e, //From Brawl, may not be functional
- Hurt = 0x1f, //Takes hitbox data from stdat. Used for Cave and M. Fortress Danger Zones
- Unknown2 = 0x20 //Unknown. Uses bomb SFX?
- }
-
- public class LVDCollisionMaterial
- {
- private byte[] MaterialData = new byte[0xC];
-
- public CollisionMatType Physics
- {
- get { return (CollisionMatType)MaterialData[3]; }
- set { MaterialData[3] = (byte)value; }
- }
-
- public bool LeftLedge
- {
- get { return GetFlag(6); }
- set { SetFlag(6, value); }
- }
-
- public bool RightLedge
- {
- get { return GetFlag(7); }
- set { SetFlag(7, value); }
- }
-
- public bool NoWallJump
- {
- get { return GetFlag(4); }
- set { SetFlag(4, value); }
- }
-
- public bool GetFlag(int n)
- {
- return ((MaterialData[10] & (1 << n)) != 0);
- }
-
- public void SetFlag(int flag, bool value)
- {
- byte mask = (byte)(1 << flag);
- bool isSet = (MaterialData[10] & mask) != 0;
- if (value)
- MaterialData[10] |= mask;
- else
- MaterialData[10] &= (byte)~mask;
- }
-
- public void Read(BinaryReaderExt r)
- {
- r.ReadByte();
- MaterialData = r.ReadBytes(0xC);
- }
-
- public void Write(BinaryWriterExt writer)
- {
- writer.Write((byte)1);
- writer.Write(MaterialData);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDCollisionSpiritsFloor.cs b/StudioSB/Scenes/LVD/LVDCollisionSpiritsFloor.cs
new file mode 100644
index 0000000..cbbcc18
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDCollisionSpiritsFloor.cs
@@ -0,0 +1,85 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDCollisionSpiritsFloor : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 2;
+
+ [Category("Line")]
+ public uint LineIndex { get; set; }
+
+ [Category("Line")]
+ public string LineGroup { get; set; }
+
+ [Category("Values")]
+ public float Unknown1 { get; set; } = 1.0f;
+
+ [Category("Values")]
+ public float Unknown2 { get; set; } = 1.0f;
+
+ [Category("Values")]
+ public float Unknown3 { get; set; } = 1.0f;
+
+ [Category("Values")]
+ public float Unknown4 { get; set; } = 1.0f;
+
+ [Category("Values")]
+ public float Unknown5 { get; set; } = 0.0f;
+
+ [Category("Values")]
+ public float Unknown6 { get; set; } = 0.0f;
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ base.Read(reader);
+
+ LineIndex = reader.ReadUInt32();
+
+ reader.Skip(1);
+ LineGroup = reader.ReadString();
+ reader.Skip(0x40 - (uint)LineGroup.Length - 1);
+
+ if (Version < 2)
+ {
+ return;
+ }
+
+ Unknown1 = reader.ReadSingle();
+ Unknown2 = reader.ReadSingle();
+ Unknown3 = reader.ReadSingle();
+ Unknown4 = reader.ReadSingle();
+ Unknown5 = reader.ReadSingle();
+ Unknown6 = reader.ReadSingle();
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ base.Write(writer);
+
+ writer.Write(LineIndex);
+
+ writer.Write((byte)1);
+ writer.Write(LineGroup);
+ writer.Write(new byte[0x40 - LineGroup.Length - 1]);
+
+ if (Version < 2)
+ {
+ return;
+ }
+
+ writer.Write(Unknown1);
+ writer.Write(Unknown2);
+ writer.Write(Unknown3);
+ writer.Write(Unknown4);
+ writer.Write(Unknown5);
+ writer.Write(Unknown6);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDDamageShape.cs b/StudioSB/Scenes/LVD/LVDDamageShape.cs
index a88728a..44da912 100644
--- a/StudioSB/Scenes/LVD/LVDDamageShape.cs
+++ b/StudioSB/Scenes/LVD/LVDDamageShape.cs
@@ -1,86 +1,42 @@
-using System;
-using StudioSB.Tools;
+using StudioSB.Tools;
+using System.ComponentModel;
namespace StudioSB.Scenes.LVD
{
- public enum LVDDamageShapeType
+ public class LVDDamageShape : LVDBase
{
- Sphere = 2,
- Capsule = 3
- }
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
- public class LVDDamageShape : LVDEntry
- {
- public LVDDamageShapeType Type { get; set; }
+ [Category("Shape"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDShape3 Shape { get; set; } = new LVDShape3();
+
+ public bool IsDamager { get; set; }
- public float X { get; set; }
- public float Y { get; set; }
- public float Z { get; set; }
- public float Dx { get; set; }
- public float Dy { get; set; }
- public float Dz { get; set; }
- public float Radius { get; set; }
- public byte Unknown1 { get; set; }
- public int Unknown2 { get; set; }
+ public uint ID { get; set; }
- public override void Read(BinaryReaderExt r)
+ public override void Read(BinaryReaderExt reader)
{
- base.Read(r);
+ Version = reader.ReadByte();
- r.Skip(1);
- Type = (LVDDamageShapeType)r.ReadInt32();
- if (!Enum.IsDefined(typeof(LVDDamageShapeType), Type))
- throw new NotImplementedException($"Unknown damage shape type {Type} at offset {r.BaseStream.Position - 4}");
+ base.Read(reader);
- X = r.ReadSingle();
- Y = r.ReadSingle();
- Z = r.ReadSingle();
- if (Type == LVDDamageShapeType.Sphere)
- {
- Radius = r.ReadSingle();
- Dx = r.ReadSingle();
- Dy = r.ReadSingle();
- Dz = r.ReadSingle();
- }
- if (Type == LVDDamageShapeType.Capsule)
- {
- Dx = r.ReadSingle();
- Dy = r.ReadSingle();
- Dz = r.ReadSingle();
- Radius = r.ReadSingle();
- }
- Unknown1 = r.ReadByte();
- Unknown2 = r.ReadInt32();
+ Shape.Read(reader);
+
+ IsDamager = reader.ReadBoolean();
+ ID = reader.ReadUInt32();
}
public override void Write(BinaryWriterExt writer)
{
- base.Write(writer);
+ writer.Write(Version);
- writer.Write((byte)1);
- writer.Write((int)Type);
+ base.Write(writer);
- writer.Write(X);
- writer.Write(Y);
- writer.Write(Z);
-
- if (Type == LVDDamageShapeType.Sphere)
- {
- writer.Write(Radius);
- writer.Write(Dx);
- writer.Write(Dy);
- writer.Write(Dz);
- }
- if (Type == LVDDamageShapeType.Capsule)
- {
- writer.Write(Dx);
- writer.Write(Dy);
- writer.Write(Dz);
- writer.Write(Radius);
- }
+ Shape.Write(writer);
- writer.Write(Unknown1);
- writer.Write(Unknown2);
+ writer.Write(IsDamager);
+ writer.Write(ID);
}
}
}
diff --git a/StudioSB/Scenes/LVD/LVDEnemyGenerator.cs b/StudioSB/Scenes/LVD/LVDEnemyGenerator.cs
index f701633..7dbd969 100644
--- a/StudioSB/Scenes/LVD/LVDEnemyGenerator.cs
+++ b/StudioSB/Scenes/LVD/LVDEnemyGenerator.cs
@@ -1,77 +1,116 @@
-using System;
+using StudioSB.Tools;
using System.Collections.Generic;
-using StudioSB.Tools;
+using System.ComponentModel;
namespace StudioSB.Scenes.LVD
{
- public class LVDEnemyGenerator : LVDEntry
+ public class LVDEnemyGenerator : LVDBase
{
- public List Spawns { get; set; } = new List();
- public List Zones { get; set; } = new List();
- public int Unknown1 { get; set; } = 0;
- public int ID { get; set; }
- public List SpawnIDs { get; set; } = new List();
- public int Unknown2 { get; set; } = 0;
- public List ZoneIDs { get; set; } = new List();
-
- public override void Read(BinaryReaderExt r)
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 3;
+
+ public List Unknown1 { get; set; } = new List();
+
+ public List Unknown2 { get; set; } = new List();
+
+ public List Unknown3 { get; set; } = new List();
+
+ [Category("ID")]
+ public int Tag { get; set; }
+
+ public List Unknown4 { get; set; } = new List();
+
+ public List Unknown5 { get; set; } = new List();
+
+ public List Unknown6 { get; set; } = new List();
+
+ public override void Read(BinaryReaderExt reader)
{
- base.Read(r);
+ Version = reader.ReadByte();
- r.Skip(0x2); //x01 01
- int spawnCount = r.ReadInt32();
- for (int i = 0; i < spawnCount; i++)
+ base.Read(reader);
+
+ reader.Skip(1);
+ reader.Skip(1);
+ var unknown1Count = reader.ReadUInt32();
+ for (uint i = 0; i < unknown1Count; i++)
{
- r.Skip(1);
- var shape = new LVDShape();
- shape.Read(r);
- Spawns.Add(shape);
+ reader.Skip(1);
+ var shape = new LVDShape2();
+ shape.Read(reader);
+ Unknown1.Add(shape);
}
- r.Skip(0x2); //x01 01
- int zoneCount = r.ReadInt32();
- for (int i = 0; i < zoneCount; i++)
+ reader.Skip(1);
+ reader.Skip(1);
+ var unknown2Count = reader.ReadUInt32();
+ for (uint i = 0; i < unknown2Count; i++)
{
- r.Skip(1);
- var shape = new LVDShape();
- shape.Read(r);
- Zones.Add(shape);
+ reader.Skip(1);
+ var shape = new LVDShape2();
+ shape.Read(reader);
+ Unknown2.Add(shape);
}
- r.Skip(0x2); //x01 01
- Unknown1 = r.ReadInt32() ; //Only seen as 0
+ reader.Skip(1);
+ reader.Skip(1);
+ var unknown3Count = reader.ReadUInt32();
+ for (uint i = 0; i < unknown3Count; i++)
+ {
+ reader.Skip(1);
+ var shape = new LVDShape2();
+ shape.Read(reader);
+ Unknown3.Add(shape);
+ }
- r.Skip(1); //x01
- ID = r.ReadInt32();
+ reader.Skip(1);
+ Tag = reader.ReadInt32();
- r.Skip(1); //x01
- int spawnIdCount = r.ReadInt32();
- for (int i = 0; i < spawnIdCount; i++)
+ if (Version < 2)
{
- r.Skip(1);
- SpawnIDs.Add(r.ReadInt32());
+ return;
}
- r.Skip(1); //x01
- Unknown2 = r.ReadInt32(); //Only seen as 0
+ reader.Skip(1);
+ var unknown4Count = reader.ReadUInt32();
+ for (int i = 0; i < unknown4Count; i++)
+ {
+ reader.Skip(1);
+ Unknown4.Add(reader.ReadInt32());
+ }
+
+ reader.Skip(1);
+ var unknown5Count = reader.ReadUInt32();
+ for (int i = 0; i < unknown5Count; i++)
+ {
+ reader.Skip(1);
+ Unknown5.Add(reader.ReadInt32());
+ }
+
+ if (Version < 3)
+ {
+ return;
+ }
- r.Skip(1); //x01
- int zoneIdCount = r.ReadInt32();
- for (int i = 0; i < zoneIdCount; i++)
+ reader.Skip(1);
+ var unknown6Count = reader.ReadUInt32();
+ for (int i = 0; i < unknown6Count; i++)
{
- r.Skip(1);
- ZoneIDs.Add(r.ReadInt32());
+ reader.Skip(1);
+ Unknown6.Add(reader.ReadInt32());
}
}
public override void Write(BinaryWriterExt writer)
{
+ writer.Write(Version);
+
base.Write(writer);
writer.Write((byte)1);
writer.Write((byte)1);
- writer.Write(Spawns.Count);
- foreach (var v in Spawns)
+ writer.Write(Unknown1.Count);
+ foreach (var v in Unknown1)
{
writer.Write((byte)1);
v.Write(writer);
@@ -79,8 +118,8 @@ public override void Write(BinaryWriterExt writer)
writer.Write((byte)1);
writer.Write((byte)1);
- writer.Write(Zones.Count);
- foreach (var v in Zones)
+ writer.Write(Unknown2.Count);
+ foreach (var v in Unknown2)
{
writer.Write((byte)1);
v.Write(writer);
@@ -88,25 +127,45 @@ public override void Write(BinaryWriterExt writer)
writer.Write((byte)1);
writer.Write((byte)1);
- writer.Write(0);
-
+ writer.Write(Unknown3.Count);
+ foreach (var v in Unknown3)
+ {
+ writer.Write((byte)1);
+ v.Write(writer);
+ }
+
writer.Write((byte)1);
- writer.Write(ID);
-
+ writer.Write(Tag);
+
+ if (Version < 2)
+ {
+ return;
+ }
+
writer.Write((byte)1);
- writer.Write(SpawnIDs.Count);
- foreach (var v in SpawnIDs)
+ writer.Write(Unknown4.Count);
+ foreach (var v in Unknown4)
{
writer.Write((byte)1);
writer.Write(v);
}
writer.Write((byte)1);
- writer.Write(0);
-
+ writer.Write(Unknown5.Count);
+ foreach (var v in Unknown5)
+ {
+ writer.Write((byte)1);
+ writer.Write(v);
+ }
+
+ if (Version < 3)
+ {
+ return;
+ }
+
writer.Write((byte)1);
- writer.Write(ZoneIDs.Count);
- foreach (var v in ZoneIDs)
+ writer.Write(Unknown6.Count);
+ foreach (var v in Unknown6)
{
writer.Write((byte)1);
writer.Write(v);
diff --git a/StudioSB/Scenes/LVD/LVDEntry.cs b/StudioSB/Scenes/LVD/LVDEntry.cs
deleted file mode 100644
index 83b5f0f..0000000
--- a/StudioSB/Scenes/LVD/LVDEntry.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using OpenTK;
-using StudioSB.Tools;
-using System.ComponentModel;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDEntry
- {
- [ReadOnly(true), Category("Entry")]
- public long EntryFlags { get; internal set; }
-
- [ReadOnly(true), Category("Entry")]
- public int EntryNumber { get; internal set; }
-
- [Category("Entry")]
- public string EntryName { get; set; }
-
- [Category("Entry")]
- public string EntryLabel { get; set; }
-
- [Category("Entry")]
- public LVDVector3 StartPosition { get; set; } = new LVDVector3(0, 0, 0);
-
- [Category("Entry")]
- public bool UseStartPosition { get; set; } = false;
-
- [Category("Entry")]
- public LVDVector3 UnknownVector { get; set; } = new LVDVector3(0, 0, 0);
-
- [Category("Entry")]
- public int UnknownIndex { get; set; } = 0;
-
- [Category("Entry")]
- public int UnknownIndex2 { get; set; } = 0; // usually 0; related to connecting to bones? wily has 1 and 2
-
- [Category("Entry")]
- public string BoneName { get; set; }
-
- public virtual void Read(BinaryReaderExt r)
- {
- EntryFlags = r.ReadInt64();
- EntryNumber = r.ReadInt32();
-
- bool hasString = r.ReadBoolean();
- EntryName = r.ReadString(0x38);
-
- bool hasLabel = r.ReadBoolean();
- EntryLabel = r.ReadString(0x40);
-
- bool hasStartPosition = r.ReadBoolean();
- StartPosition = new LVDVector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
- UseStartPosition = r.ReadBoolean();
-
- // Unknown
- r.Skip(1);
- UnknownIndex2 = r.ReadInt32();
-
- r.Skip(1);
- UnknownVector = new LVDVector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
- UnknownIndex = r.ReadInt32();
-
- r.Skip(1);
- BoneName = r.ReadString(0x40);
- }
-
- public virtual void Write(BinaryWriterExt writer)
- {
- writer.Write(EntryFlags);
- writer.Write(EntryNumber);
-
- writer.Write((byte)1);
- writer.Write(EntryName);
- writer.Write(new byte[0x38 - EntryName.Length - 1]);
-
- writer.Write((byte)1);
- writer.Write(EntryLabel);
- writer.Write(new byte[0x40 - EntryLabel.Length - 1]);
-
- writer.Write((byte)1);
- writer.Write(StartPosition.X);
- writer.Write(StartPosition.Y);
- writer.Write(StartPosition.Z);
- writer.Write(UseStartPosition);
-
- writer.Write((byte)1);
- writer.Write(UnknownIndex2);
-
- writer.Write((byte)1);
- writer.Write(UnknownVector.X);
- writer.Write(UnknownVector.Y);
- writer.Write(UnknownVector.Z);
- writer.Write(UnknownIndex);
-
- writer.Write((byte)1);
- writer.Write(BoneName);
- writer.Write(new byte[0x40 - BoneName.Length - 1]);
-
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDGeneralPoint.cs b/StudioSB/Scenes/LVD/LVDGeneralPoint.cs
deleted file mode 100644
index d600dd1..0000000
--- a/StudioSB/Scenes/LVD/LVDGeneralPoint.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDGeneralPoint : LVDEntry
- {
- public int ID { get; set; }
- public int Type { get; set; } = 4;
- public float X { get; set; }
- public float Y { get; set; }
- public float Z { get; set; }
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- r.Skip(1);
- ID = r.ReadInt32();
-
- r.Skip(1);
- Type = r.ReadInt32();
-
- X = r.ReadSingle();
- Y = r.ReadSingle();
- Z = r.ReadSingle();
- r.Skip(0x10);
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(ID);
-
- writer.Write((byte)1);
- writer.Write(Type);
-
- writer.Write(X);
- writer.Write(Y);
- writer.Write(Z);
- writer.Write(new byte[0x10]);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDGeneralShape.cs b/StudioSB/Scenes/LVD/LVDGeneralShape.cs
deleted file mode 100644
index 8e26d9a..0000000
--- a/StudioSB/Scenes/LVD/LVDGeneralShape.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDGeneralShape : LVDEntry
- {
- public int ID { get; set; }
- public LVDShape Shape { get; set; }
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- r.Skip(1);
- ID = r.ReadInt32();
-
- Shape = new LVDShape();
- Shape.Read(r);
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(ID);
-
- Shape.Write(writer);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDGeneralShape2.cs b/StudioSB/Scenes/LVD/LVDGeneralShape2.cs
new file mode 100644
index 0000000..be65c5e
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDGeneralShape2.cs
@@ -0,0 +1,42 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDGeneralShape2 : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("ID")]
+ public int Tag { get; set; }
+
+ [Category("Shape"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDShape2 Shape { get; set; }
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ base.Read(reader);
+
+ reader.Skip(1);
+ Tag = reader.ReadInt32();
+
+ Shape = new LVDShape2();
+ Shape.Read(reader);
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ base.Write(writer);
+
+ writer.Write((byte)1);
+ writer.Write(Tag);
+
+ Shape.Write(writer);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDGeneralShape3.cs b/StudioSB/Scenes/LVD/LVDGeneralShape3.cs
new file mode 100644
index 0000000..392f3aa
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDGeneralShape3.cs
@@ -0,0 +1,42 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDGeneralShape3 : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("ID")]
+ public int Tag { get; set; }
+
+ [Category("Shape"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDShape3 Shape { get; set; }
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ base.Read(reader);
+
+ reader.Skip(1);
+ Tag = reader.ReadInt32();
+
+ Shape = new LVDShape3();
+ Shape.Read(reader);
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ base.Write(writer);
+
+ writer.Write((byte)1);
+ writer.Write(Tag);
+
+ Shape.Write(writer);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDGeneralVector.cs b/StudioSB/Scenes/LVD/LVDGeneralVector.cs
deleted file mode 100644
index 47f750c..0000000
--- a/StudioSB/Scenes/LVD/LVDGeneralVector.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDGeneralVector : LVDEntry
- {
- public float X { get; set; }
- public float Y { get; set; }
- public float Z { get; set; }
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- r.ReadByte();
-
- X = r.ReadSingle();
- Y = r.ReadSingle();
- Z = r.ReadSingle();
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
-
- writer.Write(X);
- writer.Write(Y);
- writer.Write(Z);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDItemPopupRegion.cs b/StudioSB/Scenes/LVD/LVDItemPopupRegion.cs
new file mode 100644
index 0000000..b0bb35f
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDItemPopupRegion.cs
@@ -0,0 +1,58 @@
+using StudioSB.Tools;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDItemPopupRegion : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("ID")]
+ public int Tag { get; set; }
+
+ [Category("Regions")]
+ public List Regions { get; set; } = new List();
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ base.Read(reader);
+
+ reader.Skip(1);
+ Tag = reader.ReadInt32();
+
+ reader.Skip(1);
+ reader.Skip(1);
+ uint regionCount = reader.ReadUInt32();
+ for (uint i = 0; i < regionCount; i++)
+ {
+ reader.Skip(1);
+ var region = new LVDShape2();
+ region.Read(reader);
+ Regions.Add(region);
+ }
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ base.Write(writer);
+
+ writer.Write((byte)1);
+ writer.Write(Tag);
+
+ writer.Write((byte)1);
+ writer.Write((byte)1);
+ writer.Write(Regions.Count);
+ foreach (var v in Regions)
+ {
+ writer.Write((byte)1);
+ v.Write(writer);
+ }
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDItemSpawner.cs b/StudioSB/Scenes/LVD/LVDItemSpawner.cs
deleted file mode 100644
index c802d5d..0000000
--- a/StudioSB/Scenes/LVD/LVDItemSpawner.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Collections.Generic;
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDItemSpawner : LVDEntry
- {
- public int ID { get; internal set; } = 0x09840001;
- public List Sections { get; set; } = new List();
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- r.Skip(1);
- ID = r.ReadInt32();
-
- r.Skip(1);
- r.Skip(1);
- int sectionCount = r.ReadInt32();
- for (int i = 0; i < sectionCount; i++)
- {
- r.Skip(1);
- var shape = new LVDShape();
- shape.Read(r);
- Sections.Add(shape);
- }
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(ID);
-
- writer.Write((byte)1);
- writer.Write((byte)1);
-
- writer.Write(Sections.Count);
- foreach(var v in Sections)
- {
- writer.Write((byte)1);
- v.Write(writer);
- }
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDPTrainerFloatingFloor.cs b/StudioSB/Scenes/LVD/LVDPTrainerFloatingFloor.cs
new file mode 100644
index 0000000..ce29266
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDPTrainerFloatingFloor.cs
@@ -0,0 +1,32 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDPTrainerFloatingFloor : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("Position"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDVector3 Position { get; set; } = new LVDVector3(0.0f, 0.0f, 0.0f);
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ base.Read(reader);
+
+ Position.Read(reader);
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ base.Write(writer);
+
+ Position.Write(writer);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDPTrainerRange.cs b/StudioSB/Scenes/LVD/LVDPTrainerRange.cs
new file mode 100644
index 0000000..073a065
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDPTrainerRange.cs
@@ -0,0 +1,88 @@
+using StudioSB.Tools;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDPTrainerRange : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 4;
+
+ [Category("Range"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDVector3 BoundaryMin { get; set; } = new LVDVector3(0.0f, 0.0f, 0.0f);
+
+ [Category("Range"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDVector3 BoundaryMax { get; set; } = new LVDVector3(0.0f, 0.0f, 0.0f);
+
+ [Category("Range")]
+ public List Trainers { get; set; } = new List();
+
+ [Category("Parent")]
+ public string ParentModelName { get; set; }
+
+ [Category("Parent")]
+ public string ParentJointName { get; set; }
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ base.Read(reader);
+
+ BoundaryMin.Read(reader);
+
+ BoundaryMax.Read(reader);
+
+ reader.Skip(1);
+ uint trainerCount = reader.ReadUInt32();
+ for (uint i = 0; i < trainerCount; i++)
+ {
+ LVDVector3 trainer = new LVDVector3(0.0f, 0.0f, 0.0f);
+
+ trainer.Read(reader);
+ Trainers.Add(trainer);
+ }
+
+ if (Version > 1)
+ {
+ reader.Skip(1);
+ ParentModelName = reader.ReadString();
+ reader.Skip(0x40 - (uint)ParentModelName.Length - 1);
+
+ reader.Skip(1);
+ ParentJointName = reader.ReadString();
+ reader.Skip(0x40 - (uint)ParentJointName.Length - 1);
+ }
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ base.Write(writer);
+
+ BoundaryMin.Write(writer);
+
+ BoundaryMax.Write(writer);
+
+ writer.Write((byte)1);
+ writer.Write(Trainers.Count);
+ foreach (var v in Trainers)
+ {
+ v.Write(writer);
+ }
+
+ if (Version > 1)
+ {
+ writer.Write((byte)1);
+ writer.Write(ParentModelName);
+ writer.Write(new byte[0x40 - ParentModelName.Length - 1]);
+
+ writer.Write((byte)1);
+ writer.Write(ParentJointName);
+ writer.Write(new byte[0x40 - ParentJointName.Length - 1]);
+ }
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDPoint.cs b/StudioSB/Scenes/LVD/LVDPoint.cs
new file mode 100644
index 0000000..5287c96
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDPoint.cs
@@ -0,0 +1,46 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDPoint : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 2;
+
+ [Category("Position"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDVector2 Position { get; set; } = new LVDVector2(0.0f, 0.0f);
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ if (Version < 2)
+ {
+ MetaInfo.Read(reader);
+ }
+ else
+ {
+ base.Read(reader);
+ }
+
+ Position.Read(reader);
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ if (Version < 2)
+ {
+ MetaInfo.Write(writer);
+ }
+ else
+ {
+ base.Write(writer);
+ }
+
+ Position.Write(writer);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDRangeCurve.cs b/StudioSB/Scenes/LVD/LVDRangeCurve.cs
deleted file mode 100644
index 8e5936b..0000000
--- a/StudioSB/Scenes/LVD/LVDRangeCurve.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDRangeCurve : LVDEntry
- {
- public LVDVector3 Vector1 { get; set; }
- public LVDVector3 Vector2 { get; set; }
-
- public List Vectors { get; set; } = new List();
-
- public float[] Mat4x4_1 { get; set; } = new float[16];
-
- public float[] Mat4x4_2 { get; set; } = new float[16];
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
- r.ReadByte();
- Vector1 = new LVDVector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
- r.ReadByte();
- Vector2 = new LVDVector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
- r.ReadByte();
-
- int vec3Count = r.ReadInt32();
- for(int i = 0; i < vec3Count; i++)
- {
- r.ReadByte();
- Vectors.Add(new LVDVector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()));
- }
-
- r.ReadByte();
- Mat4x4_1 = new float[16];
- for (int i = 0; i < 16; i++)
- Mat4x4_1[i] = r.ReadSingle();
-
- r.ReadByte();
- Mat4x4_2 = new float[16];
- for (int i = 0; i < 16; i++)
- Mat4x4_2[i] = r.ReadSingle();
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(Vector1.X);
- writer.Write(Vector1.Y);
- writer.Write(Vector1.Z);
-
- writer.Write((byte)1);
- writer.Write(Vector2.X);
- writer.Write(Vector2.Y);
- writer.Write(Vector2.Z);
-
- writer.Write((byte)1);
- writer.Write(Vectors.Count);
- foreach(var v in Vectors)
- {
- writer.Write((byte)1);
- writer.Write(v.X);
- writer.Write(v.Y);
- writer.Write(v.Z);
- }
-
- writer.Write((byte)1);
- foreach (var v in Mat4x4_1)
- writer.Write(v);
-
- writer.Write((byte)1);
- foreach (var v in Mat4x4_2)
- writer.Write(v);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDRect.cs b/StudioSB/Scenes/LVD/LVDRect.cs
new file mode 100644
index 0000000..35902dd
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDRect.cs
@@ -0,0 +1,45 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDRect
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("Rectangle")]
+ public float Left { get; set; }
+
+ [Category("Rectangle")]
+ public float Right { get; set; }
+
+ [Category("Rectangle")]
+ public float Top { get; set; }
+
+ [Category("Rectangle")]
+ public float Bottom { get; set; }
+
+ public override string ToString()
+ {
+ return $"({Left}, {Right}, {Top}, {Bottom})";
+ }
+ public void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+ Left = reader.ReadSingle();
+ Right = reader.ReadSingle();
+ Top = reader.ReadSingle();
+ Bottom = reader.ReadSingle();
+ }
+
+ public void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+ writer.Write(Left);
+ writer.Write(Right);
+ writer.Write(Top);
+ writer.Write(Bottom);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDRegion.cs b/StudioSB/Scenes/LVD/LVDRegion.cs
new file mode 100644
index 0000000..4fe08b9
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDRegion.cs
@@ -0,0 +1,46 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDRegion : LVDBase
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 2;
+
+ [Category("Rectangle"), TypeConverter(typeof(ExpandableObjectConverter))]
+ public LVDRect Rectangle { get; set; } = new LVDRect();
+
+ public override void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+
+ if (Version < 2)
+ {
+ MetaInfo.Read(reader);
+ }
+ else
+ {
+ base.Read(reader);
+ }
+
+ Rectangle.Read(reader);
+ }
+
+ public override void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+
+ if (Version < 2)
+ {
+ MetaInfo.Write(writer);
+ }
+ else
+ {
+ base.Write(writer);
+ }
+
+ Rectangle.Write(writer);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDShape.cs b/StudioSB/Scenes/LVD/LVDShape.cs
deleted file mode 100644
index 5ca9bf1..0000000
--- a/StudioSB/Scenes/LVD/LVDShape.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-using StudioSB.Tools;
-using System.Collections.Generic;
-
-namespace StudioSB.Scenes.LVD
-{
- public enum LVDShapeType : int
- {
- Point = 1,
- Circle = 2,
- Rectangle = 3,
- Path = 4
- }
-
- public class LVDShape
- {
- public LVDShapeType Type { get; set; }
- public float X { get; set; }
- public float Y { get; set; }
- public float Z { get; set; }
- public float W { get; set; }
- public List Points { get; set; } = new List();
-
- public override string ToString()
- {
- return Type.ToString();
- }
-
- public void Read(BinaryReaderExt r)
- {
- r.ReadByte();
- Type = (LVDShapeType)r.ReadInt32();
- X = r.ReadSingle();
- Y = r.ReadSingle();
- Z = r.ReadSingle();
- W = r.ReadSingle();
-
- r.ReadByte();
-
- r.ReadByte();
- int pointCount = r.ReadInt32();
- for (int i = 0; i < pointCount; i++)
- {
- r.Skip(1);
- Points.Add(new LVDVector2(r.ReadSingle(), r.ReadSingle()));
- }
- }
-
- public void Write(BinaryWriterExt writer)
- {
- writer.Write((byte)3);
- writer.Write((int)Type);
- writer.Write(X);
- writer.Write(Y);
- writer.Write(Z);
- writer.Write(W);
-
- writer.Write((byte)1);
- writer.Write((byte)1);
- writer.Write(Points.Count);
- foreach(var v in Points)
- {
- writer.Write((byte)1);
- writer.Write(v.X);
- writer.Write(v.Y);
- }
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDShape2.cs b/StudioSB/Scenes/LVD/LVDShape2.cs
new file mode 100644
index 0000000..7f29d45
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDShape2.cs
@@ -0,0 +1,82 @@
+using StudioSB.Tools;
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public enum LVDShape2Type : uint
+ {
+ Point = 1,
+ Circle = 2,
+ Rectangle = 3,
+ Path = 4
+ }
+
+ public class LVDShape2
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 3;
+
+ [Category("Type")]
+ public LVDShape2Type Type { get; set; }
+
+ [Category("Values")]
+ public float X { get; set; }
+
+ [Category("Values")]
+ public float Y { get; set; }
+
+ [Category("Values")]
+ public float Z { get; set; }
+
+ [Category("Values")]
+ public float W { get; set; }
+
+ [Category("Values (Path)")]
+ public List Points { get; set; } = new List();
+
+ public override string ToString()
+ {
+ return Type.ToString();
+ }
+
+ public void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+ Type = (LVDShape2Type)reader.ReadUInt32();
+ X = reader.ReadSingle();
+ Y = reader.ReadSingle();
+ Z = reader.ReadSingle();
+ W = reader.ReadSingle();
+
+ reader.Skip(1);
+ reader.Skip(1);
+ uint pointCount = reader.ReadUInt32();
+ for (uint i = 0; i < pointCount; i++)
+ {
+ LVDVector2 point = new LVDVector2(0.0f, 0.0f);
+
+ point.Read(reader);
+ Points.Add(point);
+ }
+ }
+
+ public void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+ writer.Write((uint)Type);
+ writer.Write(X);
+ writer.Write(Y);
+ writer.Write(Z);
+ writer.Write(W);
+
+ writer.Write((byte)1);
+ writer.Write((byte)1);
+ writer.Write(Points.Count);
+ foreach (var v in Points)
+ {
+ v.Write(writer);
+ }
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDShape3.cs b/StudioSB/Scenes/LVD/LVDShape3.cs
new file mode 100644
index 0000000..9dec0dc
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDShape3.cs
@@ -0,0 +1,74 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public enum LVDShape3Type : uint
+ {
+ Box = 1,
+ Sphere = 2,
+ Capsule = 3,
+ Point = 4
+ }
+
+ public class LVDShape3
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("Type")]
+ public LVDShape3Type Type { get; set; }
+
+ [Category("Values")]
+ public float X { get; set; }
+
+ [Category("Values")]
+ public float Y { get; set; }
+
+ [Category("Values")]
+ public float Z { get; set; }
+
+ [Category("Values")]
+ public float W { get; set; }
+
+ [Category("Values")]
+ public float S { get; set; }
+
+ [Category("Values")]
+ public float R { get; set; }
+
+ [Category("Values")]
+ public float T { get; set; }
+
+ public override string ToString()
+ {
+ return Type.ToString();
+ }
+
+ public void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+ Type = (LVDShape3Type)reader.ReadUInt32();
+ X = reader.ReadSingle();
+ Y = reader.ReadSingle();
+ Z = reader.ReadSingle();
+ W = reader.ReadSingle();
+ S = reader.ReadSingle();
+ R = reader.ReadSingle();
+ T = reader.ReadSingle();
+ }
+
+ public void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+ writer.Write((uint)Type);
+ writer.Write(X);
+ writer.Write(Y);
+ writer.Write(Z);
+ writer.Write(W);
+ writer.Write(S);
+ writer.Write(R);
+ writer.Write(T);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDSpawn.cs b/StudioSB/Scenes/LVD/LVDSpawn.cs
deleted file mode 100644
index 9bc01d4..0000000
--- a/StudioSB/Scenes/LVD/LVDSpawn.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using StudioSB.Tools;
-
-namespace StudioSB.Scenes.LVD
-{
- public class LVDSpawn : LVDEntry
- {
- public float X { get; set; } = 0;
- public float Y { get; set; } = 0;
-
- public override void Read(BinaryReaderExt r)
- {
- base.Read(r);
-
- r.ReadByte();
- X = r.ReadSingle();
- Y = r.ReadSingle();
- }
-
- public override void Write(BinaryWriterExt writer)
- {
- base.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(X);
- writer.Write(Y);
- }
- }
-}
diff --git a/StudioSB/Scenes/LVD/LVDVector2.cs b/StudioSB/Scenes/LVD/LVDVector2.cs
new file mode 100644
index 0000000..bb5fcee
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDVector2.cs
@@ -0,0 +1,58 @@
+using StudioSB.Tools;
+using System;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDVector2
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("Component")]
+ public float X { get; set; }
+
+ [Category("Component")]
+ public float Y { get; set; }
+
+ public LVDVector2(float x, float y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public override string ToString()
+ {
+ return $"({X}, {Y})";
+ }
+
+ public LVDVector2 Normalized()
+ {
+ float length = (float)Math.Sqrt(X * X + Y * Y);
+
+ return new LVDVector2(X / length, Y / length);
+ }
+
+ public static LVDVector2 GenerateNormal(LVDVector2 v1, LVDVector2 v2)
+ {
+ LVDVector2 normal = new LVDVector2(v2.Y - v1.Y, v2.X - v1.X).Normalized();
+ normal.X *= -1.0f;
+
+ return normal;
+ }
+
+ public void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+ X = reader.ReadSingle();
+ Y = reader.ReadSingle();
+ }
+
+ public void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+ writer.Write(X);
+ writer.Write(Y);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LVDVector3.cs b/StudioSB/Scenes/LVD/LVDVector3.cs
new file mode 100644
index 0000000..f7aa045
--- /dev/null
+++ b/StudioSB/Scenes/LVD/LVDVector3.cs
@@ -0,0 +1,48 @@
+using StudioSB.Tools;
+using System.ComponentModel;
+
+namespace StudioSB.Scenes.LVD
+{
+ public class LVDVector3
+ {
+ [ReadOnly(true), Category("Version")]
+ public byte Version { get; internal set; } = 1;
+
+ [Category("Component")]
+ public float X { get; set; }
+
+ [Category("Component")]
+ public float Y { get; set; }
+
+ [Category("Component")]
+ public float Z { get; set; }
+
+ public LVDVector3(float x, float y, float z)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ }
+
+ public override string ToString()
+ {
+ return $"({X}, {Y}, {Z})";
+ }
+
+ public void Read(BinaryReaderExt reader)
+ {
+ Version = reader.ReadByte();
+ X = reader.ReadSingle();
+ Y = reader.ReadSingle();
+ Z = reader.ReadSingle();
+ }
+
+ public void Write(BinaryWriterExt writer)
+ {
+ writer.Write(Version);
+ writer.Write(X);
+ writer.Write(Y);
+ writer.Write(Z);
+ }
+ }
+}
diff --git a/StudioSB/Scenes/LVD/LevelData.cs b/StudioSB/Scenes/LVD/LevelData.cs
index 485fbf6..9dfd69e 100644
--- a/StudioSB/Scenes/LVD/LevelData.cs
+++ b/StudioSB/Scenes/LVD/LevelData.cs
@@ -9,371 +9,524 @@ namespace StudioSB.Scenes.LVD
[Serializable]
public class LevelData
{
- [ReadOnly(true)]
- public int Heading { get; internal set; } = 0x01;
+ [ReadOnly(true), Category("Header")]
+ public uint Unknown { get; internal set; } = 1;
- [ReadOnly(true)]
- public byte VersionMinor { get; internal set; } = 0x0D;
+ [ReadOnly(true), Category("Header")]
+ public byte Version { get; internal set; } = 13;
- [ReadOnly(true)]
- public byte VersionMajor { get; internal set; } = 0x01;
-
- [ReadOnly(true)]
- public string Magic { get; internal set; } = "LVD1";
+ [ReadOnly(true), Category("Header")]
+ public string Signature { get; internal set; } = "LVD1";
public List Collisions = new List();
+ public List StartPositions = new List();
+ public List RestartPositions = new List();
+ public List CameraRegions = new List();
+ public List DeathRegions = new List();
+ public List EnemyGenerators = new List();
+ public List DamageShapes = new List();
+ public List ItemPopupRegions = new List();
+ public List PTrainerRanges = new List();
+ public List PTrainerFloatingFloors = new List();
+ public List GeneralShapes2D = new List();
+ public List GeneralShapes3D = new List();
+ public List ShrinkedCameraRegions = new List();
+ public List ShrinkedDeathRegions = new List();
- public List Spawns = new List();
+ public LevelData()
+ {
+ }
- public List Respawns = new List();
+ public LevelData(string FileName)
+ {
+ Open(FileName);
+ }
- public List CameraBounds = new List();
+ public void Open(string FileName)
+ {
+ using (BinaryReaderExt stream = new BinaryReaderExt(new FileStream(FileName, FileMode.Open)))
+ {
+ Read(stream);
- public List BlastZoneBounds = new List();
+ if (stream.BaseStream.Length != stream.BaseStream.Position)
+ {
+ stream.PrintPosition();
+ throw new Exception("Error fully parsing LVD file " + stream.BaseStream.Position.ToString("X"));
+ }
+ }
+ }
- public List EnemyGenerators = new List();
+ public void Save(string FileName)
+ {
+ File.WriteAllBytes(FileName, GetData());
+ }
+
+ public byte[] GetData()
+ {
+ MemoryStream stream = new MemoryStream();
- public List ItemSpawners = new List();
+ using (BinaryWriterExt writer = new BinaryWriterExt(stream))
+ {
+ Write(writer);
+ }
- public List DamageShapes = new List();
+ byte[] output = stream.ToArray();
+ stream.Close();
+ stream.Dispose();
+ return output;
+ }
- public List GeneralPoints = new List();
+ public void Read(BinaryReaderExt reader)
+ {
+ reader.BigEndian = true;
- public List GeneralShapes = new List();
+ Unknown = reader.ReadUInt32();
+ Version = reader.ReadByte();
- // version > 10 ie Smash Ultimate
+ reader.ReadByte();
+ Signature = new string(reader.ReadChars(Signature.Length));
- public List RangeCurves = new List();
+ reader.ReadByte();
+ uint collisionCount = reader.ReadUInt32();
+ for (uint i = 0; i < collisionCount; i++)
+ {
+ LVDCollision collision = new LVDCollision();
- public List GeneralVectors = new List();
+ collision.Read(reader);
+ Collisions.Add(collision);
+ }
- public List ShrunkCameraBounds = new List();
+ reader.ReadByte();
+ uint startPositionCount = reader.ReadUInt32();
+ for (uint i = 0; i < startPositionCount; i++)
+ {
+ LVDPoint startPosition = new LVDPoint();
- public List ShrunkBlastZoneBounds = new List();
+ startPosition.Read(reader);
+ StartPositions.Add(startPosition);
+ }
- public LevelData()
- {
- //TODO: make defaults?
- }
+ reader.ReadByte();
+ uint restartPositionCount = reader.ReadUInt32();
+ for (uint i = 0; i < restartPositionCount; i++)
+ {
+ LVDPoint restartPosition = new LVDPoint();
- public LevelData(string FileName)
- {
- Open(FileName);
- }
+ restartPosition.Read(reader);
+ RestartPositions.Add(restartPosition);
+ }
- public void Open(string FileName)
- {
- using (BinaryReaderExt stream = new BinaryReaderExt(new FileStream(FileName, FileMode.Open)))
+ reader.ReadByte();
+ uint cameraRegionCount = reader.ReadUInt32();
+ for (uint i = 0; i < cameraRegionCount; i++)
{
- stream.BigEndian = true;
+ LVDRegion cameraRegion = new LVDRegion();
- Heading = stream.ReadInt32();
- VersionMinor = stream.ReadByte();
- VersionMajor = stream.ReadByte();
- Magic = new string(stream.ReadChars(4));
+ cameraRegion.Read(reader);
+ CameraRegions.Add(cameraRegion);
+ }
- stream.ReadByte();
- var collisionCount = stream.ReadInt32();
- for(int i = 0; i < collisionCount; i++)
- {
- LVDCollision col = new LVDCollision();
- col.Read(stream, VersionMinor);
- Collisions.Add(col);
- }
+ reader.ReadByte();
+ uint deathRegionCount = reader.ReadUInt32();
+ for (uint i = 0; i < deathRegionCount; i++)
+ {
+ LVDRegion deathRegion = new LVDRegion();
- stream.ReadByte();
- var spawnCount = stream.ReadInt32();
- for (int i = 0; i < spawnCount; i++)
- {
- LVDSpawn spawn = new LVDSpawn();
- spawn.Read(stream);
- Spawns.Add(spawn);
- }
+ deathRegion.Read(reader);
+ DeathRegions.Add(deathRegion);
+ }
- stream.ReadByte();
- var respawnCount = stream.ReadInt32();
- for (int i = 0; i < respawnCount; i++)
- {
- LVDSpawn respawn = new LVDSpawn();
- respawn.Read(stream);
- Respawns.Add(respawn);
- }
-
- stream.ReadByte();
- var boundsCount = stream.ReadInt32();
- for (int i = 0; i < boundsCount; i++)
- {
- LVDBounds bound = new LVDBounds();
- bound.Read(stream);
- CameraBounds.Add(bound);
- }
+ reader.ReadByte();
+ uint enemyGeneratorCount = reader.ReadUInt32();
+ for (uint i = 0; i < enemyGeneratorCount; i++)
+ {
+ LVDEnemyGenerator enemyGenerator = new LVDEnemyGenerator();
- stream.ReadByte();
- var blastCount = stream.ReadInt32();
- for (int i = 0; i < blastCount; i++)
- {
- LVDBounds blast = new LVDBounds();
- blast.Read(stream);
- BlastZoneBounds.Add(blast);
- }
-
- stream.ReadByte();
- int enemyGenCount = stream.ReadInt32();
- for(int i = 0; i < enemyGenCount; i++)
- {
- LVDEnemyGenerator enGen = new LVDEnemyGenerator();
- enGen.Read(stream);
- EnemyGenerators.Add(enGen);
- }
+ enemyGenerator.Read(reader);
+ EnemyGenerators.Add(enemyGenerator);
+ }
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
+ if (Version < 2)
+ {
+ return;
+ }
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
+ if (Version < 3)
+ {
+ return;
+ }
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
- stream.ReadByte();
- int damageCount = stream.ReadInt32();
- for (int i = 0; i < damageCount; i++)
- {
- LVDDamageShape shape = new LVDDamageShape();
- shape.Read(stream);
- DamageShapes.Add(shape);
- }
-
- stream.ReadByte();
- int itemSpawnCount = stream.ReadInt32();
- for (int i = 0; i < itemSpawnCount; i++)
- {
- LVDItemSpawner spawn = new LVDItemSpawner();
- spawn.Read(stream);
- ItemSpawners.Add(spawn);
- }
-
- if (VersionMinor > 0xA)
- {
- stream.ReadByte();
- int genCurveCount = stream.ReadInt32();
- for (int i = 0; i < genCurveCount; i++)
- {
- LVDRangeCurve point = new LVDRangeCurve();
- point.Read(stream);
- RangeCurves.Add(point);
- }
-
- stream.ReadByte();
- int genCurveCount2 = stream.ReadInt32();
- for (int i = 0; i < genCurveCount2; i++)
- {
- LVDGeneralVector point = new LVDGeneralVector();
- point.Read(stream);
- GeneralVectors.Add(point);
- }
- }
-
- stream.ReadByte();
- int genShapeCount = stream.ReadInt32();
- for (int i = 0; i < genShapeCount; i++)
- {
- LVDGeneralShape shape = new LVDGeneralShape();
- shape.Read(stream);
- GeneralShapes.Add(shape);
- }
-
- stream.ReadByte();
- int genPointCount = stream.ReadInt32();
- for (int i = 0; i < genPointCount; i++)
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
+
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
+
+ if (Version < 4)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ uint damageShapeCount = reader.ReadUInt32();
+ for (uint i = 0; i < damageShapeCount; i++)
+ {
+ LVDDamageShape damageShape = new LVDDamageShape();
+
+ damageShape.Read(reader);
+ DamageShapes.Add(damageShape);
+ }
+
+ if (Version < 5)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ uint itemPopupRegionCount = reader.ReadUInt32();
+ for (uint i = 0; i < itemPopupRegionCount; i++)
+ {
+ LVDItemPopupRegion itemPopupRegion = new LVDItemPopupRegion();
+
+ itemPopupRegion.Read(reader);
+ ItemPopupRegions.Add(itemPopupRegion);
+ }
+
+ if (Version > 11)
+ {
+ reader.ReadByte();
+ uint ptrainerRangeCount = reader.ReadUInt32();
+ for (uint i = 0; i < ptrainerRangeCount; i++)
{
- LVDGeneralPoint point = new LVDGeneralPoint();
- point.Read(stream);
- GeneralPoints.Add(point);
+ LVDPTrainerRange ptrainerRange = new LVDPTrainerRange();
+
+ ptrainerRange.Read(reader);
+ PTrainerRanges.Add(ptrainerRange);
}
-
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
-
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
-
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
-
- stream.ReadByte();
- if (stream.ReadInt32() > 0)
- throw new NotImplementedException("Unknown LVD Section at 0x" + stream.BaseStream.Position.ToString("X"));
-
- if(VersionMinor > 0xA)
+
+ if (Version > 12)
{
- stream.ReadByte();
- var shrunkboundsCount = stream.ReadInt32();
- for (int i = 0; i < shrunkboundsCount; i++)
+ reader.ReadByte();
+ uint ptrainerFloatingFloorCount = reader.ReadUInt32();
+ for (uint i = 0; i < ptrainerFloatingFloorCount; i++)
{
- LVDBounds bound = new LVDBounds();
- bound.Read(stream);
- ShrunkCameraBounds.Add(bound);
- }
+ LVDPTrainerFloatingFloor ptrainerFloatingFloor = new LVDPTrainerFloatingFloor();
- stream.ReadByte();
- var shrunkblastCount = stream.ReadInt32();
- for (int i = 0; i < shrunkblastCount; i++)
- {
- LVDBounds blast = new LVDBounds();
- blast.Read(stream);
- ShrunkBlastZoneBounds.Add(blast);
+ ptrainerFloatingFloor.Read(reader);
+ PTrainerFloatingFloors.Add(ptrainerFloatingFloor);
}
}
+ }
- if(stream.BaseStream.Length != stream.BaseStream.Position)
- {
- stream.PrintPosition();
- throw new Exception("Error fully parsing LVD " + stream.BaseStream.Position.ToString("X"));
- }
+ if (Version < 6)
+ {
+ return;
}
- }
- public void Save(string FileName)
- {
- File.WriteAllBytes(FileName, GetData());
+ reader.ReadByte();
+ uint generalShape2Count = reader.ReadUInt32();
+ for (uint i = 0; i < generalShape2Count; i++)
+ {
+ LVDGeneralShape2 generalShape2 = new LVDGeneralShape2();
+
+ generalShape2.Read(reader);
+ GeneralShapes2D.Add(generalShape2);
+ }
+
+ reader.ReadByte();
+ uint generalShape3Count = reader.ReadUInt32();
+ for (uint i = 0; i < generalShape3Count; i++)
+ {
+ LVDGeneralShape3 generalShape3 = new LVDGeneralShape3();
+
+ generalShape3.Read(reader);
+ GeneralShapes3D.Add(generalShape3);
+ }
+
+ if (Version < 7)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
+
+ if (Version < 8)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
+
+ if (Version < 9)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
+
+ if (Version < 10)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ if (reader.ReadUInt32() > 0)
+ {
+ throw new NotImplementedException("Unknown LVD Section at 0x" + reader.BaseStream.Position.ToString("X"));
+ }
+
+ if (Version < 11)
+ {
+ return;
+ }
+
+ reader.ReadByte();
+ uint shrinkedCameraRegionCount = reader.ReadUInt32();
+ for (uint i = 0; i < shrinkedCameraRegionCount; i++)
+ {
+ LVDRegion shrinkedCameraRegion = new LVDRegion();
+
+ shrinkedCameraRegion.Read(reader);
+ ShrinkedCameraRegions.Add(shrinkedCameraRegion);
+ }
+
+ reader.ReadByte();
+ uint shrinkedDeathRegionCount = reader.ReadUInt32();
+ for (uint i = 0; i < shrinkedDeathRegionCount; i++)
+ {
+ LVDRegion shrinkedDeathRegion = new LVDRegion();
+
+ shrinkedDeathRegion.Read(reader);
+ ShrinkedDeathRegions.Add(shrinkedDeathRegion);
+ }
}
- public byte[] GetData()
+ public void Write(BinaryWriterExt writer)
{
- MemoryStream stream = new MemoryStream();
+ writer.BigEndian = true;
- using (BinaryWriterExt writer = new BinaryWriterExt(stream))
+ writer.Write(Unknown);
+ writer.Write(Version);
+
+ writer.Write((byte)1);
+ writer.Write(Signature.ToCharArray());
+
+ writer.Write((byte)1);
+ writer.Write(Collisions.Count);
+ foreach (var v in Collisions)
{
- writer.BigEndian = true;
+ v.Write(writer);
+ }
- writer.Write(Heading);
- writer.Write(VersionMinor);
- writer.Write(VersionMajor);
- writer.Write(Magic.ToCharArray());
+ writer.Write((byte)1);
+ writer.Write(StartPositions.Count);
+ foreach (var v in StartPositions)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(Collisions.Count);
- foreach (var v in Collisions)
- v.Write(writer, VersionMinor);
+ writer.Write((byte)1);
+ writer.Write(RestartPositions.Count);
+ foreach (var v in RestartPositions)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(Spawns.Count);
- foreach (var v in Spawns)
- v.Write(writer);
+ writer.Write((byte)1);
+ writer.Write(CameraRegions.Count);
+ foreach (var v in CameraRegions)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(Respawns.Count);
- foreach (var v in Respawns)
- v.Write(writer);
+ writer.Write((byte)1);
+ writer.Write(DeathRegions.Count);
+ foreach (var v in DeathRegions)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(CameraBounds.Count);
- foreach (var v in CameraBounds)
- v.Write(writer);
+ writer.Write((byte)1);
+ writer.Write(EnemyGenerators.Count);
+ foreach (var v in EnemyGenerators)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(BlastZoneBounds.Count);
- foreach (var v in BlastZoneBounds)
- v.Write(writer);
+ if (Version < 2)
+ {
+ return;
+ }
- writer.Write((byte)1);
- writer.Write(EnemyGenerators.Count);
- foreach (var v in EnemyGenerators)
- v.Write(writer);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(0);
+ if (Version < 3)
+ {
+ return;
+ }
- writer.Write((byte)1);
- writer.Write(0);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(0);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(0);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(0);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(DamageShapes.Count);
- foreach (var v in DamageShapes)
- v.Write(writer);
+ if (Version < 4)
+ {
+ return;
+ }
+ writer.Write((byte)1);
+ writer.Write(DamageShapes.Count);
+ foreach (var v in DamageShapes)
+ {
+ v.Write(writer);
+ }
+
+ if (Version < 5)
+ {
+ return;
+ }
+
+ writer.Write((byte)1);
+ writer.Write(ItemPopupRegions.Count);
+ foreach (var v in ItemPopupRegions)
+ {
+ v.Write(writer);
+ }
+
+ if (Version > 11)
+ {
writer.Write((byte)1);
- writer.Write(ItemSpawners.Count);
- foreach (var v in ItemSpawners)
+ writer.Write(PTrainerRanges.Count);
+ foreach (var v in PTrainerRanges)
+ {
v.Write(writer);
+ }
- if (VersionMinor > 0xA)
+ if (Version > 12)
{
writer.Write((byte)1);
- writer.Write(RangeCurves.Count);
- foreach (var v in RangeCurves)
- v.Write(writer);
-
- writer.Write((byte)1);
- writer.Write(GeneralVectors.Count);
- foreach (var v in GeneralVectors)
+ writer.Write(PTrainerFloatingFloors.Count);
+ foreach (var v in PTrainerFloatingFloors)
+ {
v.Write(writer);
+ }
}
+ }
- writer.Write((byte)1);
- writer.Write(GeneralShapes.Count);
- foreach (var v in GeneralShapes)
- v.Write(writer);
+ if (Version < 6)
+ {
+ return;
+ }
- writer.Write((byte)1);
- writer.Write(GeneralPoints.Count);
- foreach (var v in GeneralPoints)
- v.Write(writer);
+ writer.Write((byte)1);
+ writer.Write(GeneralShapes2D.Count);
+ foreach (var v in GeneralShapes2D)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(0);
+ writer.Write((byte)1);
+ writer.Write(GeneralShapes3D.Count);
+ foreach (var v in GeneralShapes3D)
+ {
+ v.Write(writer);
+ }
- writer.Write((byte)1);
- writer.Write(0);
+ if (Version < 7)
+ {
+ return;
+ }
- writer.Write((byte)1);
- writer.Write(0);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(0);
+ if (Version < 8)
+ {
+ return;
+ }
- if (VersionMinor > 0xA)
- {
- writer.Write((byte)1);
- writer.Write(ShrunkCameraBounds.Count);
- foreach (var v in ShrunkCameraBounds)
- v.Write(writer);
+ writer.Write((byte)1);
+ writer.Write(0);
- writer.Write((byte)1);
- writer.Write(ShrunkBlastZoneBounds.Count);
- foreach (var v in ShrunkBlastZoneBounds)
- v.Write(writer);
- }
+ if (Version < 9)
+ {
+ return;
}
- byte[] output = stream.ToArray(); ;
- stream.Close();
- stream.Dispose();
- return output;
+ writer.Write((byte)1);
+ writer.Write(0);
+
+ if (Version < 10)
+ {
+ return;
+ }
+
+ writer.Write((byte)1);
+ writer.Write(0);
+
+ if (Version < 11)
+ {
+ return;
+ }
+
+ writer.Write((byte)1);
+ writer.Write(ShrinkedCameraRegions.Count);
+ foreach (var v in ShrinkedCameraRegions)
+ {
+ v.Write(writer);
+ }
+
+ writer.Write((byte)1);
+ writer.Write(ShrinkedDeathRegions.Count);
+ foreach (var v in ShrinkedDeathRegions)
+ {
+ v.Write(writer);
+ }
}
}
}
diff --git a/StudioSB/StudioSB.csproj b/StudioSB/StudioSB.csproj
index 19bf71c..1f18866 100644
--- a/StudioSB/StudioSB.csproj
+++ b/StudioSB/StudioSB.csproj
@@ -85,6 +85,7 @@
+
False
@@ -221,21 +222,25 @@
-
+
+
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+