123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- // 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 System.Text;
- using UnityEngine;
- namespace UnityFx.Outline
- {
- /// <summary>
- /// A collection of <see cref="GameObject"/> instances that share outline settings. An <see cref="OutlineLayer"/>
- /// can only belong to one <see cref="OutlineLayerCollection"/> at time.
- /// </summary>
- /// <seealso cref="OutlineLayerCollection"/>
- /// <seealso cref="OutlineEffect"/>
- [Serializable]
- public sealed class OutlineLayer : ICollection<GameObject>, IReadOnlyCollection<GameObject>, IOutlineSettings
- {
- #region data
- [SerializeField, HideInInspector]
- private OutlineSettingsInstance _settings = new OutlineSettingsInstance();
- [SerializeField, HideInInspector]
- private string _name;
- [SerializeField, HideInInspector]
- private bool _enabled = true;
- [SerializeField, HideInInspector]
- private bool _mergeLayerObjects;
- private OutlineLayerCollection _parentCollection;
- private Dictionary<GameObject, OutlineRendererCollection> _outlineObjects = new Dictionary<GameObject, OutlineRendererCollection>();
- private List<Renderer> _mergedRenderers;
- #endregion
- #region interface
- /// <summary>
- /// Gets the layer name.
- /// </summary>
- public string Name
- {
- get
- {
- if (string.IsNullOrEmpty(_name))
- {
- return "OutlineLayer #" + Index.ToString();
- }
- return _name;
- }
- }
- /// <summary>
- /// Gets or sets a value indicating whether the layer is enabled.
- /// </summary>
- /// <seealso cref="Priority"/>
- public bool Enabled
- {
- get
- {
- return _enabled;
- }
- set
- {
- _enabled = value;
- }
- }
- /// <summary>
- /// Gets or sets a value indicating whether layer game objects should be trated as one.
- /// </summary>
- public bool MergeLayerObjects
- {
- get
- {
- return _mergeLayerObjects;
- }
- set
- {
- _mergeLayerObjects = value;
- }
- }
- /// <summary>
- /// Gets index of the layer in parent collection.
- /// </summary>
- public int Index
- {
- get
- {
- if (_parentCollection != null)
- {
- return _parentCollection.IndexOf(this);
- }
- return -1;
- }
- }
- /// <summary>
- /// Gets or sets outline settings. Set this to non-<see langword="null"/> value to share settings with other components.
- /// </summary>
- public OutlineSettings OutlineSettings
- {
- get
- {
- return _settings.OutlineSettings;
- }
- set
- {
- _settings.OutlineSettings = value;
- }
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="OutlineLayer"/> class.
- /// </summary>
- public OutlineLayer()
- {
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="OutlineLayer"/> class.
- /// </summary>
- internal OutlineLayer(OutlineLayerCollection parentCollection)
- {
- _parentCollection = parentCollection;
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="OutlineLayer"/> class.
- /// </summary>
- public OutlineLayer(string name)
- {
- _name = name;
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="OutlineLayer"/> class.
- /// </summary>
- /// <exception cref="ArgumentNullException">Thrown if <paramref name="settings"/> is <see langword="null"/>.</exception>
- public OutlineLayer(OutlineSettings settings)
- {
- if (settings is null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
- _settings.OutlineSettings = settings;
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="OutlineLayer"/> class.
- /// </summary>
- /// <exception cref="ArgumentNullException">Thrown if <paramref name="settings"/> is <see langword="null"/>.</exception>
- public OutlineLayer(string name, OutlineSettings settings)
- {
- if (settings is null)
- {
- throw new ArgumentNullException(nameof(settings));
- }
- _name = name;
- _settings.OutlineSettings = settings;
- }
- /// <summary>
- /// Attempts to get renderers assosiated with the specified <see cref="GameObject"/>.
- /// </summary>
- /// <exception cref="ArgumentNullException">Thrown if <paramref name="go"/> is <see langword="null"/>.</exception>
- public bool TryGetRenderers(GameObject go, out ICollection<Renderer> renderers)
- {
- if (go is null)
- {
- throw new ArgumentNullException(nameof(go));
- }
- if (_outlineObjects.TryGetValue(go, out var result))
- {
- renderers = result;
- return true;
- }
- renderers = null;
- return false;
- }
- /// <summary>
- /// Gets the objects for rendering.
- /// </summary>
- public void GetRenderObjects(IList<OutlineRenderObject> renderObjects)
- {
- if (_enabled)
- {
- if (_mergeLayerObjects)
- {
- renderObjects.Add(new OutlineRenderObject(GetRenderers(), this, Name));
- }
- else
- {
- foreach (var kvp in _outlineObjects)
- {
- var go = kvp.Key;
- if (go && go.activeInHierarchy)
- {
- renderObjects.Add(new OutlineRenderObject(kvp.Value.GetList(), _settings, go.name));
- }
- }
- }
- }
- }
- /// <summary>
- /// Gets all layer renderers.
- /// </summary>
- public IReadOnlyList<Renderer> GetRenderers()
- {
- if (_enabled)
- {
- if (_mergedRenderers != null)
- {
- _mergedRenderers.Clear();
- }
- else
- {
- _mergedRenderers = new List<Renderer>();
- }
- foreach (var kvp in _outlineObjects)
- {
- var go = kvp.Key;
- if (go && go.activeInHierarchy)
- {
- var rl = kvp.Value.GetList();
- for (var i = 0; i < rl.Count; i++)
- {
- _mergedRenderers.Add(rl[i]);
- }
- }
- }
- return _mergedRenderers;
- }
- return Array.Empty<Renderer>();
- }
- #endregion
- #region internals
- internal string NameTag
- {
- get
- {
- return _name;
- }
- set
- {
- _name = value;
- }
- }
- internal OutlineLayerCollection ParentCollection => _parentCollection;
- internal void UpdateRenderers(int ignoreLayers)
- {
- foreach (var renderers in _outlineObjects.Values)
- {
- renderers.Reset(false, ignoreLayers);
- }
- }
- internal void Reset()
- {
- _outlineObjects.Clear();
- }
- internal void SetCollection(OutlineLayerCollection collection)
- {
- if (_parentCollection == null || collection == null || _parentCollection == collection)
- {
- _parentCollection = collection;
- }
- else
- {
- throw new InvalidOperationException("OutlineLayer can only belong to a single OutlineLayerCollection.");
- }
- }
- #endregion
- #region IOutlineSettings
- /// <inheritdoc/>
- public Color OutlineColor
- {
- get
- {
- return _settings.OutlineColor;
- }
- set
- {
- _settings.OutlineColor = value;
- }
- }
- /// <inheritdoc/>
- public int OutlineWidth
- {
- get
- {
- return _settings.OutlineWidth;
- }
- set
- {
- _settings.OutlineWidth = value;
- }
- }
- /// <inheritdoc/>
- public float OutlineIntensity
- {
- get
- {
- return _settings.OutlineIntensity;
- }
- set
- {
- _settings.OutlineIntensity = value;
- }
- }
- /// <inheritdoc/>
- public float OutlineAlphaCutoff
- {
- get
- {
- return _settings.OutlineAlphaCutoff;
- }
- set
- {
- _settings.OutlineAlphaCutoff = value;
- }
- }
- /// <inheritdoc/>
- public OutlineRenderFlags OutlineRenderMode
- {
- get
- {
- return _settings.OutlineRenderMode;
- }
- set
- {
- _settings.OutlineRenderMode = value;
- }
- }
- #endregion
- #region ICollection
- /// <inheritdoc/>
- public int Count => _outlineObjects.Count;
- /// <inheritdoc/>
- public bool IsReadOnly => false;
- /// <inheritdoc/>
- public void Add(GameObject go)
- {
- if (go is null)
- {
- throw new ArgumentNullException(nameof(go));
- }
- if (!_outlineObjects.ContainsKey(go))
- {
- var renderers = new OutlineRendererCollection(go);
- renderers.Reset(false, _parentCollection.IgnoreLayerMask);
- _outlineObjects.Add(go, renderers);
- }
- }
- /// <inheritdoc/>
- public bool Remove(GameObject go)
- {
- if (go is null)
- {
- return false;
- }
- return _outlineObjects.Remove(go);
- }
- /// <inheritdoc/>
- public bool Contains(GameObject go)
- {
- if (go is null)
- {
- return false;
- }
- return _outlineObjects.ContainsKey(go);
- }
- /// <inheritdoc/>
- public void Clear()
- {
- _outlineObjects.Clear();
- }
- /// <inheritdoc/>
- public void CopyTo(GameObject[] array, int arrayIndex)
- {
- _outlineObjects.Keys.CopyTo(array, arrayIndex);
- }
- #endregion
- #region IEnumerable
- /// <inheritdoc/>
- public IEnumerator<GameObject> GetEnumerator()
- {
- return _outlineObjects.Keys.GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return _outlineObjects.Keys.GetEnumerator();
- }
- #endregion
- #region IEquatable
- /// <inheritdoc/>
- public bool Equals(IOutlineSettings other)
- {
- return OutlineSettings.Equals(this, other);
- }
- #endregion
- #region Object
- /// <inheritdoc/>
- public override string ToString()
- {
- var text = new StringBuilder();
- if (string.IsNullOrEmpty(_name))
- {
- text.Append("OutlineLayer");
- }
- else
- {
- text.Append(_name);
- }
- if (_parentCollection != null)
- {
- text.Append(" #");
- text.Append(_parentCollection.IndexOf(this));
- }
- if (_outlineObjects.Count > 0)
- {
- text.Append(" (");
- foreach (var go in _outlineObjects.Keys)
- {
- text.Append(go.name);
- text.Append(", ");
- }
- text.Remove(text.Length - 2, 2);
- text.Append(")");
- }
- return string.Format("{0}", text);
- }
- /// <inheritdoc/>
- public override bool Equals(object other)
- {
- return OutlineSettings.Equals(this, other as IOutlineSettings);
- }
- /// <inheritdoc/>
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- #endregion
- #region implementation
- #endregion
- }
- }
|