namespace Zinnia.Visual { using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using Zinnia.Data.Attribute; using Zinnia.Data.Collection.List; using Zinnia.Extension; /// /// Modifies the enabled state of the mesh associated with given . /// public class MeshStateModifier : MonoBehaviour { /// /// Defines the event with the . /// [Serializable] public class UnityEvent : UnityEvent { } /// /// Mesh types that can be modified. /// [Flags] public enum MeshTypes { /// /// The component. /// MeshRenderer = 1 << 0, /// /// The component. /// SkinnedMeshRenderer = 1 << 1 } #region Mesh Settings [Header("Mesh Settings")] [Tooltip("The mesh components to modify.")] [SerializeField] [UnityFlags] private MeshTypes meshesToModifiy = (MeshTypes)(-1); /// /// The mesh components to modify. /// public MeshTypes MeshesToModifiy { get { return meshesToModifiy; } set { meshesToModifiy = value; } } [Tooltip("A relationship connection between a given GameObject and any meshes to modify upon matching.")] [SerializeField] private GameObjectMultiRelationObservableList meshCollections; /// /// A relationship connection between a given and any meshes to modify upon matching. /// public GameObjectMultiRelationObservableList MeshCollections { get { return meshCollections; } set { meshCollections = value; } } #endregion #region Visibility Events /// /// Emitted when the mesh is shown. /// [Header("Visibility Events")] public UnityEvent Shown = new UnityEvent(); /// /// Emitted when the mesh is hidden. /// public UnityEvent Hidden = new UnityEvent(); #endregion /// /// Shows the mesh found on the given . /// /// The to search for a mesh on. public virtual void ShowMesh(GameObject container) { if (!this.IsValidState()) { return; } ToggleMesh(container, true); } /// /// Shows the mesh found on the given . /// /// The to search for a mesh on. public virtual void ShowMesh(Component container) { if (!this.IsValidState() || container == null) { return; } ShowMesh(container.gameObject); } /// /// Shows any meshes found on any children of the given . /// /// The to begin the descendant search from. public virtual void ShowMeshInChildren(GameObject container) { if (!this.IsValidState()) { return; } ToggleAllMeshesInChildren(container, true); } /// /// Shows any meshes found on any children of the given . /// /// The to begin the descendant search from. public virtual void ShowMeshInChildren(Component container) { if (!this.IsValidState() || container == null) { return; } ShowMeshInChildren(container.gameObject); } /// /// Shows the meshes found for any relation matched to the given . /// /// The key to match on the . public virtual void ShowMeshInCollections(GameObject key) { if (!this.IsValidState()) { return; } ToggleMeshInCollections(key, true); } /// /// Shows the meshes found for any relation matched to the given . /// /// The key to match on the . public virtual void ShowMeshInCollections(Component key) { if (!this.IsValidState() || key == null) { return; } ShowMeshInCollections(key.gameObject); } /// /// Hides the mesh found on the given . /// /// The to search for a mesh on. public virtual void HideMesh(GameObject container) { if (!this.IsValidState()) { return; } ToggleMesh(container, false); } /// /// Hides the mesh found on the given . /// /// The to search for a mesh on. public virtual void HideMesh(Component container) { if (!this.IsValidState() || container == null) { return; } HideMesh(container.gameObject); } /// /// Hides any meshes found on any children of the given . /// /// The to begin the descendant search from. public virtual void HideMeshInChildren(GameObject container) { if (!this.IsValidState()) { return; } ToggleAllMeshesInChildren(container, false); } /// /// Hides any meshes found on any children of the given . /// /// The to begin the descendant search from. public virtual void HideMeshInChildren(Component container) { if (!this.IsValidState() || container == null) { return; } HideMeshInChildren(container.gameObject); } /// /// Hides the meshes found for any relation matched to the given . /// /// The key to match on the . public virtual void HideMeshInCollections(GameObject key) { if (!this.IsValidState()) { return; } ToggleMeshInCollections(key, false); } /// /// Hides the meshes found for any relation matched to the given . /// /// The key to match on the . public virtual void HideMeshInCollections(Component key) { if (!this.IsValidState() || key == null) { return; } HideMeshInCollections(key.gameObject); } /// /// Toggles the state of the meshes in the collection for the matching key. /// /// The key to match in the . /// The state to toggle the mesh to. protected virtual void ToggleMeshInCollections(GameObject key, bool state) { if (MeshCollections.HasRelationship(key, out List relations)) { if (relations.Count == 0) { ToggleAllMeshesInChildren(key, state); } else { foreach (GameObject relation in relations) { ToggleMesh(relation, state); } } } } /// /// Toggles all meshes found in the container and the children. /// /// The container to begin the search from. /// The state to toggle the mesh to. protected virtual void ToggleAllMeshesInChildren(GameObject container, bool state) { if ((MeshesToModifiy & MeshTypes.MeshRenderer) != 0) { foreach (MeshRenderer mesh in container.GetComponentsInChildren()) { mesh.enabled = state; EmitEvent(mesh, state); } } if ((MeshesToModifiy & MeshTypes.SkinnedMeshRenderer) != 0) { foreach (SkinnedMeshRenderer mesh in container.GetComponentsInChildren()) { mesh.enabled = state; EmitEvent(mesh, state); } } } /// /// Toggles all meshes found on the given container. /// /// The container to search on. /// The state to toggle the mesh to. protected virtual void ToggleMesh(GameObject container, bool state) { MeshRenderer meshRenderer = (MeshesToModifiy & MeshTypes.MeshRenderer) != 0 ? container.GetComponent() : null; SkinnedMeshRenderer skinnedMeshRenderer = (MeshesToModifiy & MeshTypes.SkinnedMeshRenderer) != 0 ? container.GetComponent() : null; if (meshRenderer != null) { meshRenderer.enabled = state; EmitEvent(meshRenderer, state); } if (skinnedMeshRenderer != null) { skinnedMeshRenderer.enabled = state; EmitEvent(skinnedMeshRenderer, state); } } /// /// Emits the appropriate state event. /// /// The to emit with the event. /// The event type to raise. protected virtual void EmitEvent(Renderer renderer, bool state) { if (state) { Shown?.Invoke(renderer); } else { Hidden?.Invoke(renderer); } } } }