Skip to content

Commit

Permalink
Simplify adding/removing FarModelDatas
Browse files Browse the repository at this point in the history
  • Loading branch information
sk-zk committed Jan 31, 2024
1 parent 600777f commit 4c1116b
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 12 deletions.
4 changes: 2 additions & 2 deletions TruckLib/ScsMap/FarModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class FarModel : MapItem, IItemReferences
/// Models specific to Far Model items which are only visible inside the Far Model
/// area. Used if UseMapItems is false.
/// </summary>
public List<FarModelData> Models { get; set; }
public FarModelDataList Models { get; set; }

/// <summary>
/// Map items for which the view distance limit is ignored. Used if UseMapItems is true.
Expand Down Expand Up @@ -83,7 +83,7 @@ internal FarModel(bool initFields) : base(initFields)
protected override void Init()
{
base.Init();
Models = new List<FarModelData>();
Models = new FarModelDataList(this);
Children = new List<IMapItem>();
}

Expand Down
19 changes: 13 additions & 6 deletions TruckLib/ScsMap/FarModelData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,25 @@ namespace TruckLib.ScsMap
public struct FarModelData
{
/// <summary>
/// Unit name of the model, as defined in <c>/def/world/far_model.sii</c>.
/// The map node which defines the position and rotation of the model.
/// </summary>
public Token Model;
public INode Node { get; set; }

/// <summary>
/// Relative scale per axis.
/// Unit name of the model, as defined in <c>/def/world/far_model.sii</c>.
/// </summary>
public Vector3 Scale;
public Token Model { get; set; }

/// <summary>
/// This node defines the position and rotation of the model.
/// Relative scale per axis.
/// </summary>
public INode Node;
public Vector3 Scale { get; set; }

public FarModelData(INode node, Token model, Vector3 scale)
{
Node = node;
Model = model;
Scale = scale;
}
}
}
155 changes: 155 additions & 0 deletions TruckLib/ScsMap/FarModelDataList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace TruckLib.ScsMap
{
/// <summary>
/// Reperesents a list of Far Item models.
/// </summary>
public class FarModelDataList : IList<FarModelData>
{
/// <summary>
/// The Far Model item which parents these models.
/// </summary>
public FarModel Parent { get; init; }

private readonly List<FarModelData> list = new();

/// <summary>
/// Instantiates an empty list.
/// </summary>
/// <param name="parent">The Far Model item which parents these models.</param>
public FarModelDataList(FarModel parent)
{
Parent = parent;
}

/// <inheritdoc/>
public FarModelData this[int index]
{
get => list[index];
set => list[index] = value;
}

/// <inheritdoc/>
public int Count => list.Count;

/// <inheritdoc/>
public bool IsReadOnly => false;

/// <inheritdoc/>
public void Add(FarModelData item)
{
list.Add(item);
}

/// <summary>
/// Creates a map node at the specified position and adds a FarModelData object with
/// the given properties to the end of the list.
/// </summary>
/// <param name="position">The position of the node.</param>
/// <param name="model">The unit name of the model.</param>
/// <param name="scale">The scale of the model.</param>
public void Add(Vector3 position, Token model, Vector3 scale)
{
Add(new FarModelData(CreateNode(position), model, scale));
}

/// <inheritdoc/>
public void Clear()
{
foreach (var item in list)
GetRidOfTheNode(item);
list.Clear();
}

/// <inheritdoc/>
public bool Contains(FarModelData item)
{
return list.Contains(item);
}

/// <inheritdoc/>
public void CopyTo(FarModelData[] array, int arrayIndex)
{
list.CopyTo(array, arrayIndex);
}

/// <inheritdoc/>
public IEnumerator<FarModelData> GetEnumerator()
{
return list.GetEnumerator();
}

/// <inheritdoc/>
public int IndexOf(FarModelData item)
{
return list.IndexOf(item);
}

/// <inheritdoc/>
public void Insert(int index, FarModelData item)
{
list.Insert(index, item);
}

/// <summary>
/// Creates a map node at the specified position and inserts a FarModelData object with
/// the given properties at the specified index.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="position">The position of the node.</param>
/// <param name="model">The unit name of the model.</param>
/// <param name="scale">The scale of the model.</param>
public void Insert(int index, Vector3 position, Token model, Vector3 scale)
{
Insert(index, new FarModelData(CreateNode(position), model, scale));
}

/// <summary>
/// Removes the first occurrence of the specified object from the list
/// and deletes its map node if it is not connected to anything else.
/// </summary>
/// <inheritdoc/>
public bool Remove(FarModelData item)
{
var success = list.Remove(item);
if (success)
GetRidOfTheNode(item);
return success;
}

/// <summary>
/// Removes the element at the specified index from the list
/// and deletes its map node if it is not connected to anything else.
/// </summary>
/// <inheritdoc/>
public void RemoveAt(int index)
{
GetRidOfTheNode(list[index]);
list.RemoveAt(index);
}

IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}

private Node CreateNode(Vector3 position)
{
return Parent.Node.Sectors[0].Map.AddNode(position, false, Parent);
}

private static void GetRidOfTheNode(FarModelData item)
{
item.Node.ForwardItem = null;
if (item.Node.IsOrphaned())
item.Node.Sectors[0].Map.Delete(item.Node);
}
}
}
10 changes: 6 additions & 4 deletions TruckLib/ScsMap/Serialization/FarModelSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ public override MapItem Deserialize(BinaryReader r)
fm.Height = r.ReadSingle() * sizeFactor;

// models
fm.Models = new List<FarModelData>();
fm.Models = new FarModelDataList(fm);
var modelCount = r.ReadUInt32();
for (int i = 0; i < modelCount; i++)
{
var model = new FarModelData();
model.Model = r.ReadToken();
model.Scale = r.ReadVector3();
var model = new FarModelData
{
Model = r.ReadToken(),
Scale = r.ReadVector3()
};
fm.Models.Add(model);
}

Expand Down
75 changes: 75 additions & 0 deletions TruckLibTests/TruckLib/ScsMap/FarModelDataListTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using TruckLib.ScsMap;

namespace TruckLibTests.TruckLib.ScsMap
{
public class FarModelDataListTest
{
[Fact]
public void Add()
{
var map = new Map("foo");
var fm = FarModel.Add(map, new Vector3(50, 0, 50), 60, 50);

fm.Models.Add(new Vector3(69, 42, 0), "bar", Vector3.One);

Assert.Single(fm.Models);

Assert.Equal("bar", fm.Models[0].Model);
Assert.Equal(Vector3.One, fm.Models[0].Scale);

Assert.Equal(new Vector3(69, 42, 0), fm.Models[0].Node.Position);
Assert.True(map.Nodes.ContainsKey(fm.Models[0].Node.Uid));
Assert.False(fm.Models[0].Node.IsRed);
Assert.Equal(fm, fm.Models[0].Node.ForwardItem);
}

[Fact]
public void Insert()
{
var map = new Map("foo");
var fm = FarModel.Add(map, new Vector3(50, 0, 50), 60, 50);

fm.Models.Add(new Vector3(69, 42, 0), "bar", Vector3.One);
fm.Models.Insert(0, new Vector3(12, 34, 56), "baz", Vector3.One);

Assert.Equal(2, fm.Models.Count);
Assert.Equal(new Vector3(12, 34, 56), fm.Models[0].Node.Position);
}

[Fact]
public void RemoveAt()
{
var map = new Map("foo");
var fm = FarModel.Add(map, new Vector3(50, 0, 50), 60, 50);

fm.Models.Add(new Vector3(69, 42, 0), "bar", Vector3.One);
var fmData = fm.Models[0];
fm.Models.RemoveAt(0);

Assert.False(map.Nodes.ContainsKey(fmData.Node.Uid));
}

[Fact]
public void Clear()
{
var map = new Map("foo");
var fm = FarModel.Add(map, new Vector3(50, 0, 50), 60, 50);

fm.Models.Add(new Vector3(69, 42, 0), "bar", Vector3.One);
var fmData1 = fm.Models[0];
fm.Models.Add(new Vector3(12, 34, 56), "baz", Vector3.One);
var fmData2 = fm.Models[1];
fm.Models.Clear();

Assert.Empty(fm.Models);
Assert.False(map.Nodes.ContainsKey(fmData1.Node.Uid));
Assert.False(map.Nodes.ContainsKey(fmData2.Node.Uid));
}
}
}
31 changes: 31 additions & 0 deletions TruckLibTests/TruckLib/ScsMap/FarModelTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TruckLib.ScsMap;
using System.Numerics;
using System.Drawing;

namespace TruckLibTests.TruckLib.ScsMap
{
public class FarModelTest
{
[Fact]
public void Add()
{
var map = new Map("foo");
var fm = FarModel.Add(map, new Vector3(50, 0, 50), 60, 50);

Assert.Equal(new Vector3(50, 0, 50), fm.Node.Position);
Assert.True(fm.Node.IsRed);
Assert.Equal(fm, fm.Node.ForwardItem);
Assert.Null(fm.Node.BackwardItem);
Assert.True(fm.Node.Sectors.Length == 1);
Assert.Equal(0, fm.Node.Sectors[0].X);
Assert.Equal(0, fm.Node.Sectors[0].Z);
}

}

}

0 comments on commit 4c1116b

Please sign in to comment.