Files
2025-10-12 14:33:16 +03:00

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;
}
}