OutlineLayerCollection.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // Copyright (C) 2019-2021 Alexander Bogarsukov. All rights reserved.
  2. // See the LICENSE.md file in the project root for more information.
  3. using System;
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. namespace UnityFx.Outline
  8. {
  9. /// <summary>
  10. /// A serializable collection of outline layers.
  11. /// </summary>
  12. /// <seealso cref="OutlineLayer"/>
  13. /// <seealso cref="OutlineEffect"/>
  14. /// <seealso cref="OutlineSettings"/>
  15. [CreateAssetMenu(fileName = "OutlineLayerCollection", menuName = "UnityFx/Outline/Outline Layer Collection")]
  16. public sealed class OutlineLayerCollection : ScriptableObject, IList<OutlineLayer>, IReadOnlyList<OutlineLayer>
  17. {
  18. #region data
  19. [SerializeField, HideInInspector]
  20. private List<OutlineLayer> _layers = new List<OutlineLayer>();
  21. [SerializeField, HideInInspector]
  22. private int _ignoreLayerMask;
  23. #endregion
  24. #region interface
  25. /// <summary>
  26. /// Gets or sets layer mask to use for ignored <see cref="Renderer"/> components in layer game objects.
  27. /// </summary>
  28. public int IgnoreLayerMask
  29. {
  30. get
  31. {
  32. return _ignoreLayerMask;
  33. }
  34. set
  35. {
  36. if (_ignoreLayerMask != value)
  37. {
  38. _ignoreLayerMask = value;
  39. foreach (var layer in _layers)
  40. {
  41. layer.UpdateRenderers(value);
  42. }
  43. }
  44. }
  45. }
  46. /// <summary>
  47. /// Gets number of game objects in the layers.
  48. /// </summary>
  49. public int NumberOfObjects
  50. {
  51. get
  52. {
  53. var result = 0;
  54. foreach (var layer in _layers)
  55. {
  56. result += layer.Count;
  57. }
  58. return result;
  59. }
  60. }
  61. /// <summary>
  62. /// Gets a layer with the specified index. If layer at the <paramref name="index"/> does not exist, creates one.
  63. /// </summary>
  64. public OutlineLayer GetOrAddLayer(int index)
  65. {
  66. if (index < 0)
  67. {
  68. throw new ArgumentOutOfRangeException(nameof(index));
  69. }
  70. while (index >= _layers.Count)
  71. {
  72. _layers.Add(new OutlineLayer(this));
  73. }
  74. return _layers[index];
  75. }
  76. /// <summary>
  77. /// Adds a new layer.
  78. /// </summary>
  79. public OutlineLayer AddLayer()
  80. {
  81. var layer = new OutlineLayer(this);
  82. _layers.Add(layer);
  83. return layer;
  84. }
  85. /// <summary>
  86. /// Gets the objects for rendering.
  87. /// </summary>
  88. public void GetRenderObjects(IList<OutlineRenderObject> renderObjects)
  89. {
  90. foreach (var layer in _layers)
  91. {
  92. layer.GetRenderObjects(renderObjects);
  93. }
  94. }
  95. /// <summary>
  96. /// Removes the specified <see cref="GameObject"/> from layers.
  97. /// </summary>
  98. /// <param name="go">A <see cref="GameObject"/> to remove.</param>
  99. public void Remove(GameObject go)
  100. {
  101. foreach (var layer in _layers)
  102. {
  103. if (layer.Remove(go))
  104. {
  105. break;
  106. }
  107. }
  108. }
  109. /// <summary>
  110. /// Removes all game objects registered in layers.
  111. /// </summary>
  112. public void ClearLayerContent()
  113. {
  114. foreach (var layer in _layers)
  115. {
  116. layer.Clear();
  117. }
  118. }
  119. #endregion
  120. #region internals
  121. internal void Reset()
  122. {
  123. foreach (var layer in _layers)
  124. {
  125. layer.Reset();
  126. }
  127. }
  128. #endregion
  129. #region ScriptableObject
  130. private void OnEnable()
  131. {
  132. foreach (var layer in _layers)
  133. {
  134. layer.Clear();
  135. layer.SetCollection(this);
  136. }
  137. }
  138. #endregion
  139. #region IList
  140. /// <inheritdoc/>
  141. public OutlineLayer this[int layerIndex]
  142. {
  143. get
  144. {
  145. return _layers[layerIndex];
  146. }
  147. set
  148. {
  149. if (value is null)
  150. {
  151. throw new ArgumentNullException("layer");
  152. }
  153. if (layerIndex < 0 || layerIndex >= _layers.Count)
  154. {
  155. throw new ArgumentOutOfRangeException(nameof(layerIndex));
  156. }
  157. if (_layers[layerIndex] != value)
  158. {
  159. value.SetCollection(this);
  160. _layers[layerIndex].SetCollection(null);
  161. _layers[layerIndex] = value;
  162. }
  163. }
  164. }
  165. /// <inheritdoc/>
  166. public int IndexOf(OutlineLayer layer)
  167. {
  168. if (layer != null)
  169. {
  170. return _layers.IndexOf(layer);
  171. }
  172. return -1;
  173. }
  174. /// <inheritdoc/>
  175. public void Insert(int index, OutlineLayer layer)
  176. {
  177. if (layer is null)
  178. {
  179. throw new ArgumentNullException(nameof(layer));
  180. }
  181. if (layer.ParentCollection != this)
  182. {
  183. layer.SetCollection(this);
  184. _layers.Insert(index, layer);
  185. }
  186. }
  187. /// <inheritdoc/>
  188. public void RemoveAt(int index)
  189. {
  190. if (index >= 0 && index < _layers.Count)
  191. {
  192. _layers[index].SetCollection(null);
  193. _layers.RemoveAt(index);
  194. }
  195. }
  196. #endregion
  197. #region ICollection
  198. /// <inheritdoc/>
  199. public int Count => _layers.Count;
  200. /// <inheritdoc/>
  201. public bool IsReadOnly => false;
  202. /// <inheritdoc/>
  203. public void Add(OutlineLayer layer)
  204. {
  205. if (layer is null)
  206. {
  207. throw new ArgumentNullException(nameof(layer));
  208. }
  209. if (layer.ParentCollection != this)
  210. {
  211. layer.SetCollection(this);
  212. _layers.Add(layer);
  213. }
  214. }
  215. /// <inheritdoc/>
  216. public bool Remove(OutlineLayer layer)
  217. {
  218. if (_layers.Remove(layer))
  219. {
  220. layer.SetCollection(null);
  221. return true;
  222. }
  223. return false;
  224. }
  225. /// <inheritdoc/>
  226. public void Clear()
  227. {
  228. if (_layers.Count > 0)
  229. {
  230. foreach (var layer in _layers)
  231. {
  232. layer.SetCollection(null);
  233. }
  234. _layers.Clear();
  235. }
  236. }
  237. /// <inheritdoc/>
  238. public bool Contains(OutlineLayer layer)
  239. {
  240. if (layer is null)
  241. {
  242. return false;
  243. }
  244. return _layers.Contains(layer);
  245. }
  246. /// <inheritdoc/>
  247. public void CopyTo(OutlineLayer[] array, int arrayIndex)
  248. {
  249. _layers.CopyTo(array, arrayIndex);
  250. }
  251. #endregion
  252. #region IEnumerable
  253. /// <inheritdoc/>
  254. public IEnumerator<OutlineLayer> GetEnumerator()
  255. {
  256. return _layers.GetEnumerator();
  257. }
  258. IEnumerator IEnumerable.GetEnumerator()
  259. {
  260. return _layers.GetEnumerator();
  261. }
  262. #endregion
  263. #region implementation
  264. #endregion
  265. }
  266. }