210 lines
4.5 KiB
C#
Executable File
210 lines
4.5 KiB
C#
Executable File
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace ReFuel.Gltf
|
|
{
|
|
public abstract class GltfIdObject : GltfObject
|
|
{
|
|
public int Id { get; internal set; }
|
|
|
|
public GltfIdObject(GltfDocument document) : base(document)
|
|
{
|
|
}
|
|
}
|
|
|
|
public class GltfIdList<T> : IReadOnlyList<T>
|
|
where T : GltfIdObject
|
|
{
|
|
private readonly List<T> items = new List<T>();
|
|
|
|
public T this[int index]
|
|
{
|
|
get => items[index];
|
|
}
|
|
|
|
public int Count => items.Count;
|
|
|
|
public int Append(T item)
|
|
{
|
|
int i = items.Count;
|
|
|
|
item.Id = i;
|
|
items.Add(item);
|
|
|
|
return i;
|
|
}
|
|
|
|
public bool IsSet(int i)
|
|
{
|
|
return i >= 0 && i <= Count;
|
|
}
|
|
|
|
public void RemoveAt(int index)
|
|
{
|
|
items.RemoveAt(index);
|
|
|
|
for (int i = index; i < Count; i++)
|
|
{
|
|
items[i].Id = i;
|
|
}
|
|
}
|
|
|
|
public IEnumerator<T> GetEnumerator()
|
|
{
|
|
return items.GetEnumerator();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return items.GetEnumerator();
|
|
}
|
|
}
|
|
|
|
public class GltfRefList<T> : ICollection<T>, IReadOnlyList<T> where T : GltfIdObject
|
|
{
|
|
private readonly List<ItemTuple> items = new List<ItemTuple>();
|
|
private readonly GltfIdList<T> list;
|
|
|
|
public IEnumerable<int> Ids
|
|
{
|
|
get
|
|
{
|
|
foreach (ItemTuple tuple in items)
|
|
{
|
|
yield return tuple.Item?.Id ?? tuple.Id;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int Count => items.Count;
|
|
public bool IsReadOnly => false;
|
|
|
|
public T this[int index]
|
|
{
|
|
get
|
|
{
|
|
ItemTuple item = items[index];
|
|
|
|
if (item.Item != null)
|
|
return item.Item;
|
|
|
|
item.Item = list[item.Id];
|
|
items[index] = item;
|
|
return item.Item;
|
|
}
|
|
}
|
|
|
|
public GltfRefList(GltfIdList<T> referencedList)
|
|
{
|
|
list = referencedList;
|
|
}
|
|
|
|
public void Add(T item)
|
|
{
|
|
items.Add(new ItemTuple(item.Id, item));
|
|
}
|
|
|
|
public void Add(int item)
|
|
{
|
|
items.Add(new ItemTuple(item, null));
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
items.Clear();
|
|
}
|
|
|
|
public bool Contains(T item)
|
|
{
|
|
return items.FindIndex(x => (x.Item?.Id ?? x.Id) == item.Id) != -1;
|
|
}
|
|
|
|
public void CopyTo(T[] array, int arrayIndex)
|
|
{
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
array[arrayIndex + i] = this[i];
|
|
}
|
|
}
|
|
|
|
public IEnumerator<T> GetEnumerator()
|
|
{
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
yield return this[i];
|
|
}
|
|
}
|
|
|
|
public bool Remove(T item)
|
|
{
|
|
int idx = items.FindIndex(x => (x.Item?.Id ?? x.Id) == item.Id);
|
|
|
|
if (idx == -1)
|
|
return false;
|
|
|
|
items.RemoveAt(idx);
|
|
return true;
|
|
}
|
|
|
|
public bool Remove(int item)
|
|
{
|
|
int idx = items.FindIndex(x => (x.Item?.Id ?? x.Id) == item);
|
|
|
|
if (idx == -1)
|
|
return false;
|
|
|
|
items.RemoveAt(idx);
|
|
return true;
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return GetEnumerator();
|
|
}
|
|
|
|
private record struct ItemTuple(int Id, T? Item);
|
|
}
|
|
|
|
public struct GltfSmartId<T> where T : GltfIdObject
|
|
{
|
|
private readonly GltfIdList<T> list;
|
|
private int id = -1;
|
|
private T? value = null;
|
|
|
|
public int Id
|
|
{
|
|
get => value?.Id ?? id;
|
|
set
|
|
{
|
|
Reset();
|
|
id = value;
|
|
}
|
|
}
|
|
|
|
public T Value
|
|
{
|
|
get => value ?? (value = list[id]);
|
|
set
|
|
{
|
|
id = value.Id;
|
|
this.value = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSet => list.IsSet(id);
|
|
|
|
public GltfSmartId(GltfIdList<T> list)
|
|
{
|
|
this.list = list;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
id = -1;
|
|
value = null;
|
|
}
|
|
|
|
public static implicit operator T(GltfSmartId<T> id) => id.Value;
|
|
}
|
|
}
|