Files
Outline-Toolkit/Runtime/Scripts/OutlineLayerCollection.cs
2025-07-20 21:01:09 +08:00

321 lines
5.6 KiB
C#

// Copyright (C) 2019-2021 Alexander Bogarsukov. All rights reserved.
// See the LICENSE.md file in the project root for more information.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UnityFx.Outline
{
/// <summary>
/// A serializable collection of outline layers.
/// </summary>
/// <seealso cref="OutlineLayer"/>
/// <seealso cref="OutlineEffect"/>
/// <seealso cref="OutlineSettings"/>
[CreateAssetMenu(fileName = "OutlineLayerCollection", menuName = "UnityFx/Outline/Outline Layer Collection")]
public sealed class OutlineLayerCollection : ScriptableObject, IList<OutlineLayer>, IReadOnlyList<OutlineLayer>
{
#region data
[SerializeField, HideInInspector]
private List<OutlineLayer> _layers = new List<OutlineLayer>();
[SerializeField, HideInInspector]
private int _ignoreLayerMask;
#endregion
#region interface
/// <summary>
/// Gets or sets layer mask to use for ignored <see cref="Renderer"/> components in layer game objects.
/// </summary>
public int IgnoreLayerMask
{
get
{
return _ignoreLayerMask;
}
set
{
if (_ignoreLayerMask != value)
{
_ignoreLayerMask = value;
foreach (var layer in _layers)
{
layer.UpdateRenderers(value);
}
}
}
}
/// <summary>
/// Gets number of game objects in the layers.
/// </summary>
public int NumberOfObjects
{
get
{
var result = 0;
foreach (var layer in _layers)
{
result += layer.Count;
}
return result;
}
}
/// <summary>
/// Gets a layer with the specified index. If layer at the <paramref name="index"/> does not exist, creates one.
/// </summary>
public OutlineLayer GetOrAddLayer(int index)
{
if (index < 0)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
while (index >= _layers.Count)
{
_layers.Add(new OutlineLayer(this));
}
return _layers[index];
}
/// <summary>
/// Adds a new layer.
/// </summary>
public OutlineLayer AddLayer()
{
var layer = new OutlineLayer(this);
_layers.Add(layer);
return layer;
}
/// <summary>
/// Gets the objects for rendering.
/// </summary>
public void GetRenderObjects(IList<OutlineRenderObject> renderObjects)
{
foreach (var layer in _layers)
{
layer.GetRenderObjects(renderObjects);
}
}
/// <summary>
/// Removes the specified <see cref="GameObject"/> from layers.
/// </summary>
/// <param name="go">A <see cref="GameObject"/> to remove.</param>
public void Remove(GameObject go)
{
foreach (var layer in _layers)
{
if (layer.Remove(go))
{
break;
}
}
}
/// <summary>
/// Removes all game objects registered in layers.
/// </summary>
public void ClearLayerContent()
{
foreach (var layer in _layers)
{
layer.Clear();
}
}
#endregion
#region internals
internal void Reset()
{
foreach (var layer in _layers)
{
layer.Reset();
}
}
#endregion
#region ScriptableObject
private void OnEnable()
{
foreach (var layer in _layers)
{
layer.Clear();
layer.SetCollection(this);
}
}
#endregion
#region IList
/// <inheritdoc/>
public OutlineLayer this[int layerIndex]
{
get
{
return _layers[layerIndex];
}
set
{
if (value is null)
{
throw new ArgumentNullException("layer");
}
if (layerIndex < 0 || layerIndex >= _layers.Count)
{
throw new ArgumentOutOfRangeException(nameof(layerIndex));
}
if (_layers[layerIndex] != value)
{
value.SetCollection(this);
_layers[layerIndex].SetCollection(null);
_layers[layerIndex] = value;
}
}
}
/// <inheritdoc/>
public int IndexOf(OutlineLayer layer)
{
if (layer != null)
{
return _layers.IndexOf(layer);
}
return -1;
}
/// <inheritdoc/>
public void Insert(int index, OutlineLayer layer)
{
if (layer is null)
{
throw new ArgumentNullException(nameof(layer));
}
if (layer.ParentCollection != this)
{
layer.SetCollection(this);
_layers.Insert(index, layer);
}
}
/// <inheritdoc/>
public void RemoveAt(int index)
{
if (index >= 0 && index < _layers.Count)
{
_layers[index].SetCollection(null);
_layers.RemoveAt(index);
}
}
#endregion
#region ICollection
/// <inheritdoc/>
public int Count => _layers.Count;
/// <inheritdoc/>
public bool IsReadOnly => false;
/// <inheritdoc/>
public void Add(OutlineLayer layer)
{
if (layer is null)
{
throw new ArgumentNullException(nameof(layer));
}
if (layer.ParentCollection != this)
{
layer.SetCollection(this);
_layers.Add(layer);
}
}
/// <inheritdoc/>
public bool Remove(OutlineLayer layer)
{
if (_layers.Remove(layer))
{
layer.SetCollection(null);
return true;
}
return false;
}
/// <inheritdoc/>
public void Clear()
{
if (_layers.Count > 0)
{
foreach (var layer in _layers)
{
layer.SetCollection(null);
}
_layers.Clear();
}
}
/// <inheritdoc/>
public bool Contains(OutlineLayer layer)
{
if (layer is null)
{
return false;
}
return _layers.Contains(layer);
}
/// <inheritdoc/>
public void CopyTo(OutlineLayer[] array, int arrayIndex)
{
_layers.CopyTo(array, arrayIndex);
}
#endregion
#region IEnumerable
/// <inheritdoc/>
public IEnumerator<OutlineLayer> GetEnumerator()
{
return _layers.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _layers.GetEnumerator();
}
#endregion
#region implementation
#endregion
}
}