// 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 { /// /// A serializable collection of outline layers. /// /// /// /// [CreateAssetMenu(fileName = "OutlineLayerCollection", menuName = "UnityFx/Outline/Outline Layer Collection")] public sealed class OutlineLayerCollection : ScriptableObject, IList, IReadOnlyList { #region data [SerializeField, HideInInspector] private List _layers = new List(); [SerializeField, HideInInspector] private int _ignoreLayerMask; #endregion #region interface /// /// Gets or sets layer mask to use for ignored components in layer game objects. /// public int IgnoreLayerMask { get { return _ignoreLayerMask; } set { if (_ignoreLayerMask != value) { _ignoreLayerMask = value; foreach (var layer in _layers) { layer.UpdateRenderers(value); } } } } /// /// Gets number of game objects in the layers. /// public int NumberOfObjects { get { var result = 0; foreach (var layer in _layers) { result += layer.Count; } return result; } } /// /// Gets a layer with the specified index. If layer at the does not exist, creates one. /// 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]; } /// /// Adds a new layer. /// public OutlineLayer AddLayer() { var layer = new OutlineLayer(this); _layers.Add(layer); return layer; } /// /// Gets the objects for rendering. /// public void GetRenderObjects(IList renderObjects) { foreach (var layer in _layers) { layer.GetRenderObjects(renderObjects); } } /// /// Removes the specified from layers. /// /// A to remove. public void Remove(GameObject go) { foreach (var layer in _layers) { if (layer.Remove(go)) { break; } } } /// /// Removes all game objects registered in layers. /// 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 /// 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; } } } /// public int IndexOf(OutlineLayer layer) { if (layer != null) { return _layers.IndexOf(layer); } return -1; } /// 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); } } /// public void RemoveAt(int index) { if (index >= 0 && index < _layers.Count) { _layers[index].SetCollection(null); _layers.RemoveAt(index); } } #endregion #region ICollection /// public int Count => _layers.Count; /// public bool IsReadOnly => false; /// public void Add(OutlineLayer layer) { if (layer is null) { throw new ArgumentNullException(nameof(layer)); } if (layer.ParentCollection != this) { layer.SetCollection(this); _layers.Add(layer); } } /// public bool Remove(OutlineLayer layer) { if (_layers.Remove(layer)) { layer.SetCollection(null); return true; } return false; } /// public void Clear() { if (_layers.Count > 0) { foreach (var layer in _layers) { layer.SetCollection(null); } _layers.Clear(); } } /// public bool Contains(OutlineLayer layer) { if (layer is null) { return false; } return _layers.Contains(layer); } /// public void CopyTo(OutlineLayer[] array, int arrayIndex) { _layers.CopyTo(array, arrayIndex); } #endregion #region IEnumerable /// public IEnumerator GetEnumerator() { return _layers.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _layers.GetEnumerator(); } #endregion #region implementation #endregion } }