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);
}
}
}
}