Files
StoryGame_Unity/Assets/Live2D/Cubism/Rendering/CubismRenderer.cs

1317 lines
35 KiB
C#

/**
* Copyright(c) Live2D Inc. All rights reserved.
*
* Use of this source code is governed by the Live2D Open Software license
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
*/
using Live2D.Cubism.Core;
using Live2D.Cubism.Framework.Json;
using Live2D.Cubism.Rendering.Util;
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Serialization;
namespace Live2D.Cubism.Rendering
{
/// <summary>
/// Wrapper for drawing <see cref="CubismDrawable"/>s.
/// </summary>
[ExecuteInEditMode, RequireComponent(typeof(MeshRenderer))]
public sealed partial class CubismRenderer : MonoBehaviour
{
/// <summary>
/// <see cref="LocalSortingOrder"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private int _localSortingOrder;
/// <summary>
/// Local sorting order.
/// </summary>
public int LocalSortingOrder
{
get
{
return _localSortingOrder;
}
set
{
// Return early if same value given.
if (value == _localSortingOrder)
{
return;
}
// Store value.
_localSortingOrder = value;
// Apply it.
ApplySorting();
}
}
/// <summary>
/// <see cref="Color"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private Color _color = Color.white;
/// <summary>
/// Color.
/// </summary>
public Color Color
{
get { return _color; }
set
{
// Return early if same value given.
if (value == _color)
{
return;
}
// Store value.
_color = value;
// Apply color.
ApplyVertexColors();
}
}
/// <summary>
/// <see cref="DrawObjectMultiplyColorEnabled"/> backing field.
/// </summary>
[FormerlySerializedAs("_isOverriddenDrawableMultiplyColors")] [SerializeField, HideInInspector]
private bool isOverriddenDrawObjectMultiplyColors;
/// <summary>
/// Whether to override with multiply color from the model.
/// </summary>
public bool DrawObjectMultiplyColorEnabled
{
get { return isOverriddenDrawObjectMultiplyColors; }
set { isOverriddenDrawObjectMultiplyColors = value; }
}
/// <summary>
/// Last <see cref="DrawObjectMultiplyColorEnabled"/>.
/// </summary>
public bool LastIsUseUserMultiplyColor { get; set; }
/// <summary>
/// <see cref="DrawObjectScreenColorEnabled"/> backing field.
/// </summary>
[FormerlySerializedAs("_isOverriddenDrawableScreenColors")] [SerializeField, HideInInspector]
private bool _isOverriddenDrawObjectScreenColors;
/// <summary>
/// Whether to override with screen color from the model.
/// </summary>
public bool DrawObjectScreenColorEnabled
{
get { return _isOverriddenDrawObjectScreenColors; }
set { _isOverriddenDrawObjectScreenColors = value; }
}
/// <summary>
/// Last <see cref="DrawObjectScreenColorEnabled"/>.
/// </summary>
public bool LastIsUseUserScreenColors { get; set; }
/// <summary>
/// <see cref="MultiplyColor"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private Color _multiplyColor = Color.white;
/// <summary>
/// Drawable Multiply Color.
/// </summary>
public Color MultiplyColor
{
get
{
// If it can overwrite multiply color, return it.
if (RenderController.MultiplyColorEnabled
|| DrawObjectMultiplyColorEnabled)
{
return _multiplyColor;
}
switch (DrawObjectType)
{
case CubismModelTypes.DrawObjectType.Drawable:
return Drawable.MultiplyColor;
case CubismModelTypes.DrawObjectType.Offscreen:
return Offscreen.MultiplyColor;
default:
// If we are not a drawable or offscreen, return the default value.
return _multiplyColor;
}
}
set
{
// Return early if same value given.
if (value == _multiplyColor)
{
return;
}
// Store value.
_multiplyColor = (value != null)
? value
: Color.white;
}
}
/// <summary>
/// Last Drawable Multiply Color.
/// </summary>
public Color LastMultiplyColor { get; set; }
/// <summary>
/// <see cref="ScreenColor"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private Color _screenColor = Color.clear;
/// <summary>
/// Drawable Screen Color.
/// </summary>
public Color ScreenColor
{
get
{
if (RenderController.ScreenColorEnabled
|| DrawObjectScreenColorEnabled)
{
return _screenColor;
}
switch (DrawObjectType)
{
case CubismModelTypes.DrawObjectType.Drawable:
return Drawable.ScreenColor;
case CubismModelTypes.DrawObjectType.Offscreen:
return Offscreen.ScreenColor;
default:
// If we are not a drawable or offscreen, return the default value.
return _screenColor;
}
}
set
{
// Return early if same value given.
if (value == _screenColor)
{
return;
}
// Store value.
_screenColor = (value != null)
? value
: Color.black;
}
}
/// <summary>
/// Last Drawable Screen Color.
/// </summary>
public Color LastScreenColor { get; set; }
/// <summary>
/// <see cref="UnityEngine.Material"/>.
/// </summary>
public Material Material
{
get
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
if (!MeshRenderer.sharedMaterial)
{
MeshRenderer.sharedMaterial = SetMaterialFromPicker();
}
return MeshRenderer.sharedMaterial;
}
#endif
if (!MeshRenderer.material)
{
MeshRenderer.material = SetMaterialFromPicker();
}
return MeshRenderer.material;
}
set
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
MeshRenderer.sharedMaterial = value;
return;
}
#endif
MeshRenderer.material = value;
}
}
/// <summary>
/// <see cref="MainTexture"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private Texture2D _mainTexture;
/// <summary>
/// <see cref="MeshRenderer"/>'s main texture.
/// </summary>
public Texture2D MainTexture
{
get
{
if (_mainTexture == null && DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
_mainTexture = new Texture2D(1, 1);
_mainTexture.SetPixel(1, 1, Color.clear);
}
return _mainTexture;
}
set
{
// Return early if same value given and main texture is valid.
if (value == _mainTexture && _mainTexture != null)
{
return;
}
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
_mainTexture = new Texture2D(1, 1);
_mainTexture.SetPixel(1, 1, Color.clear);
}
else
{
// Store value.
_mainTexture = (value != null)
? value
: Texture2D.whiteTexture;
}
// Apply it.
ApplyMainTexture();
}
}
/// <summary>
/// Meshes.
/// </summary>
/// <remarks>
/// Double buffering dynamic meshes increases performance on mobile, so we double-buffer them here.
/// </remarks>
private Mesh[] Meshes { get; set; }
/// <summary>
/// Index of front buffer mesh.
/// </summary>
private int FrontMesh { get; set; }
/// <summary>
/// Index of back buffer mesh.
/// </summary>
private int BackMesh { get; set; }
/// <summary>
/// <see cref="UnityEngine.Mesh"/>.
/// </summary>
public Mesh Mesh
{
get
{
if (DrawObjectType == CubismModelTypes.DrawObjectType.Offscreen)
{
return _offscreenMesh;
}
return FrontMesh < Meshes?.Length ? Meshes?[FrontMesh] : null;
}
}
/// <summary>
/// <see cref="MeshRenderer"/> backing field.
/// </summary>
[NonSerialized]
private MeshRenderer _meshRenderer;
/// <summary>
/// <see cref="UnityEngine.MeshRenderer"/>.
/// </summary>
public MeshRenderer MeshRenderer
{
get
{
TryInitializeMeshRenderer();
return _meshRenderer;
}
}
/// <summary>
/// <see cref="MeshFilter"/>'s backing field.
/// </summary>
[NonSerialized]
private MeshFilter _meshFilter;
/// <summary>
/// <see cref="UnityEngine.MeshFilter"/> for Scene View picking support.
/// </summary>
public MeshFilter MeshFilter
{
get
{
TryInitializeMeshFilter();
return _meshFilter;
}
set
{
if (value == _meshFilter || value == null)
{
return;
}
_meshFilter = value;
}
}
/// <summary>
/// <see cref="DrawMaterial"/>'s backing field.
/// </summary>
[SerializeField, HideInInspector]
private Material _drawMaterial;
/// <summary>
/// Material used for CommandBuffer rendering (the actual rendering material).
/// </summary>
public Material DrawMaterial
{
get
{
// Only return _drawMaterial for Drawable type (picking is only for Drawable).
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
return null;
}
return _drawMaterial;
}
set { _drawMaterial = value; }
}
/// <summary>
/// <see cref="CubismDrawable"/>.
/// </summary>
public CubismDrawable Drawable { get; set; }
/// <summary>
/// <see cref="CubismRenderController"/>.
/// </summary>
internal CubismRenderController RenderController { get; set; }
#region Interface For CubismRenderController
/// <summary>
/// <see cref="SortingMode"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private CubismSortingMode _sortingMode;
/// <summary>
/// Sorting mode.
/// </summary>
internal CubismSortingMode SortingMode
{
get
{
return _sortingMode;
}
set { _sortingMode = value; }
}
/// <summary>
/// <see cref="SortingOrder"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private int _sortingOrder;
/// <summary>
/// Sorting mode.
/// </summary>
private int SortingOrder
{
get { return _sortingOrder; }
set { _sortingOrder = value; }
}
/// <summary>
/// <see cref="RenderOrder"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private int _renderOrder;
/// <summary>
/// Sorting mode.
/// </summary>
private int RenderOrder
{
get { return _renderOrder; }
set { _renderOrder = value; }
}
/// <summary>
/// <see cref="DepthOffset"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private float _depthOffset = 0.00001f;
/// <summary>
/// Offset to apply in case of depth sorting.
/// </summary>
private float DepthOffset
{
get { return _depthOffset; }
set { _depthOffset = value; }
}
/// <summary>
/// <see cref="Opacity"/> backing field.
/// </summary>
[SerializeField, HideInInspector]
private float _opacity;
/// <summary>
/// Opacity.
/// </summary>
internal float Opacity
{
get { return _opacity; }
set { _opacity = value; }
}
/// <summary>
/// Buffer for vertex colors.
/// </summary>
private Color[] VertexColors { get; set; }
/// <summary>
/// Allows tracking of what vertex data was updated last swap.
/// </summary>
private SwapInfo LastSwap { get; set; }
/// <summary>
/// Allows tracking of what vertex data will be swapped.
/// </summary>
private SwapInfo ThisSwap { get; set; }
/// <summary>
/// Swaps mesh buffers.
/// </summary>
/// <remarks>
/// Make sure to manually call this method in case you changed the <see cref="Color"/>.
/// </remarks>
public void SwapMeshes()
{
// Perform internal swap.
BackMesh = FrontMesh;
FrontMesh = (FrontMesh == 0) ? 1 : 0;
// Update colors.
Meshes[BackMesh].colors = VertexColors;
// Update swap info.
LastSwap = ThisSwap;
ResetSwapInfoFlags();
#if UNITY_EDITOR
SyncMeshFilterForPicking();
#endif
}
/// <summary>
/// Updates visibility.
/// </summary>
public void UpdateVisibility()
{
if (LastSwap.DidBecomeVisible)
{
MeshRenderer.enabled = true;
}
else if (LastSwap.DidBecomeInvisible)
{
MeshRenderer.enabled = false;
}
ResetVisibilityFlags();
}
/// <summary>
/// Updates render order.
/// </summary>
public void UpdateRenderOrder()
{
if (LastSwap.NewRenderOrder)
{
ApplySorting();
}
ResetRenderOrderFlag();
}
/// <summary>
/// Updates sorting layer.
/// </summary>
/// <param name="newSortingLayer">New sorting layer.</param>
internal void OnControllerSortingLayerDidChange(int newSortingLayer)
{
MeshRenderer.sortingLayerID = newSortingLayer;
}
/// <summary>
/// Updates sorting mode.
/// </summary>
/// <param name="newSortingMode">New sorting mode.</param>
internal void OnControllerSortingModeDidChange(CubismSortingMode newSortingMode)
{
SortingMode = newSortingMode;
ApplySorting();
}
/// <summary>
/// Updates sorting order.
/// </summary>
/// <param name="newSortingOrder">New sorting order.</param>
internal void OnControllerSortingOrderDidChange(int newSortingOrder)
{
SortingOrder = newSortingOrder;
ApplySorting();
}
/// <summary>
/// Updates depth offset.
/// </summary>
/// <param name="newDepthOffset">New depth offset value.</param>
internal void OnControllerDepthOffsetDidChange(float newDepthOffset)
{
DepthOffset = newDepthOffset;
ApplySorting();
}
/// <summary>
/// Sets the opacity.
/// </summary>
/// <param name="newOpacity">New opacity.</param>
internal void OnDrawableOpacityDidChange(float newOpacity)
{
Opacity = newOpacity;
ApplyVertexColors();
}
/// <summary>
/// Updates render order.
/// </summary>
/// <param name="newRenderOrder">New render order.</param>
internal void OnDrawableRenderOrderDidChange(int newRenderOrder)
{
if (RenderOrder == newRenderOrder) return;
RenderOrder = newRenderOrder;
SetNewRenderOrder();
}
/// <summary>
/// Sets the <see cref="UnityEngine.Mesh.vertices"/>.
/// </summary>
/// <param name="newVertexPositions">Vertex positions to set.</param>
internal void OnDrawableVertexPositionsDidChange(Vector3[] newVertexPositions)
{
var mesh = Mesh;
// Apply positions and update bounds.
mesh.vertices = newVertexPositions;
mesh.RecalculateBounds();
// Set swap flag.
SetNewVertexPositions();
}
/// <summary>
/// Sets visibility.
/// </summary>
/// <param name="newVisibility">New visibility.</param>
internal void OnDrawableVisiblityDidChange(bool newVisibility)
{
// Set swap flag if visible.
if (newVisibility)
{
BecomeVisible();
}
else
{
BecomeInvisible();
}
}
/// <summary>
/// Sets model opacity.
/// </summary>
/// <param name="newModelOpacity">Opacity to set.</param>
internal void OnModelOpacityDidChange(float newModelOpacity)
{
var property = PropertyBlock;
_meshRenderer.GetPropertyBlock(property);
// Write property.
property.SetFloat(CubismShaderVariables.ModelOpacity, newModelOpacity);
MeshRenderer.SetPropertyBlock(property);
}
#endregion
/// <summary>
/// Applies main texture for rendering.
/// </summary>
private void ApplyMainTexture()
{
var property = PropertyBlock;
MeshRenderer.GetPropertyBlock(property);
// Write property.
property.SetTexture(CubismShaderVariables.MainTexture, MainTexture);
MeshRenderer.SetPropertyBlock(property);
}
/// <summary>
/// Applies sorting.
/// </summary>
private void ApplySorting()
{
// Return early if no controller or model.
if (!RenderController
|| !RenderController.Model)
{
return;
}
RenderController.DidChangeSorting = true;
// Sort by order.
if (SortingMode.SortByOrder())
{
MeshRenderer.sortingOrder = SortingOrder + ((SortingMode == CubismSortingMode.BackToFrontOrder)
? (RenderOrder + LocalSortingOrder)
: -(RenderOrder + LocalSortingOrder));
transform.localPosition = Vector3.zero;
return;
}
// Sort by depth.
var offset = (SortingMode == CubismSortingMode.BackToFrontZ)
? -DepthOffset
: DepthOffset;
MeshRenderer.sortingOrder = SortingOrder + LocalSortingOrder;
transform.localPosition = new Vector3(0f, 0f, RenderOrder * offset);
}
/// <summary>
/// Uploads mesh vertex colors.
/// </summary>
public void ApplyVertexColors()
{
var vertexColors = VertexColors;
var color = Color;
color.a *= Opacity;
for (var i = 0; i < vertexColors.Length; ++i)
{
vertexColors[i] = color;
}
// Set swap flag.
SetNewVertexColors();
}
/// <summary>
/// Uploads diffuse colors.
/// </summary>
public void ApplyMultiplyColor()
{
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
return;
}
var property = PropertyBlock;
MeshRenderer.GetPropertyBlock(property);
// Write property.
property.SetColor(CubismShaderVariables.MultiplyColor, MultiplyColor);
MeshRenderer.SetPropertyBlock(property);
}
/// <summary>
/// Initializes the main texture if possible.
/// </summary>
private void TryInitializeMultiplyColor()
{
LastIsUseUserMultiplyColor = false;
LastMultiplyColor = MultiplyColor;
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
return;
}
ApplyMultiplyColor();
}
/// <summary>
/// Uploads tint colors.
/// </summary>
public void ApplyScreenColor()
{
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
return;
}
var property = PropertyBlock;
MeshRenderer.GetPropertyBlock(property);
// Write property.
property.SetColor(CubismShaderVariables.ScreenColor, ScreenColor);
MeshRenderer.SetPropertyBlock(property);
}
/// <summary>
/// Initializes the main texture if possible.
/// </summary>
private void TryInitializeScreenColor()
{
LastIsUseUserScreenColors = false;
LastScreenColor = ScreenColor;
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
return;
}
ApplyScreenColor();
}
/// <summary>
/// Sets material from picker.
/// </summary>
public Material SetMaterialFromPicker()
{
Material material = null;
switch (DrawObjectType)
{
case CubismModelTypes.DrawObjectType.Drawable:
if (!Drawable)
{
break;
}
material = CubismBuiltinPickers.DrawableMaterialPicker(null, Drawable);
break;
case CubismModelTypes.DrawObjectType.Offscreen:
if (!Offscreen)
{
break;
}
material = CubismBuiltinPickers.OffscreenMaterialPicker(null, Offscreen);
break;
default:
material = CubismBuiltinMaterials.GetBlendModeMaterial("UnlitBlendMode", BlendTypes.ColorBlend.Normal, BlendTypes.AlphaBlend.Over, false, false, true);
Debug.LogError("Unsupported DrawObjectType.");
break;
}
return material;
}
/// <summary>
/// Initializes the mesh renderer.
/// </summary>
private void TryInitializeMeshRenderer()
{
if (!_meshRenderer)
{
_meshRenderer = GetComponent<MeshRenderer>();
// Lazily add component.
if (!_meshRenderer)
{
_meshRenderer = gameObject.AddComponent<MeshRenderer>();
_meshRenderer.hideFlags = HideFlags.HideInInspector;
_meshRenderer.receiveShadows = false;
_meshRenderer.shadowCastingMode = ShadowCastingMode.Off;
_meshRenderer.lightProbeUsage = LightProbeUsage.BlendProbes;
}
}
#if UNITY_EDITOR
if (!Application.isPlaying)
{
if (!_meshRenderer.sharedMaterial)
{
_meshRenderer.sharedMaterial = SetMaterialFromPicker();
}
return;
}
#endif
if (!_meshRenderer.material)
{
_meshRenderer.material = SetMaterialFromPicker();
}
}
/// <summary>
/// Initializes the mesh filter for Scene View picking.
/// </summary>
private void TryInitializeMeshFilter()
{
#if UNITY_EDITOR
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable
|| Application.isPlaying)
{
return;
}
if (_meshFilter != null)
{
return;
}
_meshFilter = GetComponent<MeshFilter>();
// Lazily add component if missing.
if (_meshFilter == null)
{
_meshFilter = gameObject.AddComponent<MeshFilter>();
_meshFilter.hideFlags = HideFlags.HideInInspector;
}
_meshFilter.sharedMesh = Mesh;
SetupPickingMaterial();
#endif
}
#if UNITY_EDITOR
/// <summary>
/// Sets up materials for Scene View picking.
/// </summary>
private void SetupPickingMaterial()
{
if (_meshRenderer == null)
{
return;
}
var currentMaterial = _meshRenderer.sharedMaterial;
if (_drawMaterial == null)
{
// If current material is TransparentPicking or null, get the correct material via picker.
if (currentMaterial == null
|| currentMaterial == CubismBuiltinMaterials.TransparentPicking
|| (currentMaterial.shader != null && currentMaterial.shader.name == "Live2D Cubism/TransparentPicking"))
{
_drawMaterial = SetMaterialFromPicker();
}
else
{
_drawMaterial = currentMaterial;
}
}
_meshRenderer.sharedMaterial = CubismBuiltinMaterials.TransparentPicking;
// Set MainTexture for alpha test in picking shader.
if (MainTexture != null)
{
ApplyMainTexture();
}
}
/// <summary>
/// Syncs the current mesh to the MeshFilter for Scene View picking.
/// </summary>
private void SyncMeshFilterForPicking()
{
if (DrawObjectType != CubismModelTypes.DrawObjectType.Drawable)
{
return;
}
if (_meshFilter == null || Mesh == null)
{
return;
}
_meshFilter.sharedMesh = Mesh;
}
#endif
/// <summary>
/// Initializes the mesh if necessary.
/// </summary>
private void TryInitializeMesh()
{
// Only create mesh if necessary.
// HACK: 'Mesh != null' is individually implemented to avoid errors caused by the absence of a backing field.
// HACK: 'Mesh.vertex > 0' makes sure mesh is recreated in case of runtime instantiation.
if ((Meshes != null && Meshes.Length == 2
&& Mesh != null && Mesh.vertexCount > 0
&& Drawable?.VertexPositions != null && Mesh.vertexCount == Drawable?.VertexPositions.Length)
|| (DrawObjectType == CubismModelTypes.DrawObjectType.Offscreen && _offscreenMesh))
{
return;
}
if (DrawObjectType == CubismModelTypes.DrawObjectType.Offscreen)
{
Meshes = new Mesh[1];
_offscreenMesh = new Mesh
{
vertices = OffscreenVertices,
uv = OffscreenUVs,
triangles = OffscreenTriangle
};
Meshes[0] = _offscreenMesh;
return;
}
if (Meshes != null)
{
for (var i = 0; i < Meshes.Length; i++)
{
DestroyImmediate(Meshes[i]);
}
}
Meshes = new Mesh[2];
for (var i = 0; i < 2; ++i)
{
var mesh = new Mesh();
mesh.name = Drawable.name;
mesh.vertices = Drawable.VertexPositions;
mesh.uv = Drawable.VertexUvs;
mesh.triangles = Drawable.Indices;
mesh.MarkDynamic();
mesh.RecalculateBounds();
// Store mesh.
Meshes[i] = mesh;
}
}
/// <summary>
/// Initializes vertex colors.
/// </summary>
private void TryInitializeVertexColor()
{
if (Mesh == null)
{
return;
}
var mesh = Mesh;
VertexColors = new Color[mesh.vertexCount];
for (var i = 0; i < VertexColors.Length; ++i)
{
VertexColors[i] = Color;
VertexColors[i].a *= Opacity;
}
}
/// <summary>
/// Initializes the main texture if possible.
/// </summary>
private void TryInitializeMainTexture()
{
if (!MainTexture)
{
MainTexture = Texture2D.whiteTexture;
}
ApplyMainTexture();
}
/// <summary>
/// Initializes components if possible.
/// </summary>
public void TryInitialize(CubismRenderController renderController)
{
RenderController = renderController;
if (!RenderController.Model)
{
return;
}
InitializeDrawObject();
TryInitializeMeshRenderer();
TryInitializeMesh();
TryInitializeMeshFilter();
TryInitializeVertexColor();
TryInitializeMainTexture();
TryInitializeMultiplyColor();
TryInitializeScreenColor();
_previousOffscreenUnmanagedIndex = -1;
ApplySorting();
#if UNITY_EDITOR
SyncMeshFilterForPicking();
#endif
}
#region Swap Info
/// <summary>
/// Sets <see cref="NewVertexPositions"/>.
/// </summary>
private void SetNewVertexPositions()
{
var swapInfo = ThisSwap;
swapInfo.NewVertexPositions = true;
ThisSwap = swapInfo;
}
/// <summary>
/// Sets <see cref="NewVertexColors"/>.
/// </summary>
private void SetNewVertexColors()
{
var swapInfo = ThisSwap;
swapInfo.NewVertexColors = true;
ThisSwap = swapInfo;
}
/// <summary>
/// Sets <see cref="DidBecomeVisible"/> on visible.
/// </summary>
private void BecomeVisible()
{
var swapInfo = ThisSwap;
swapInfo.DidBecomeVisible = true;
ThisSwap = swapInfo;
}
/// <summary>
/// Sets <see cref="DidBecomeInvisible"/> on invisible.
/// </summary>
private void BecomeInvisible()
{
var swapInfo = ThisSwap;
swapInfo.DidBecomeInvisible = true;
ThisSwap = swapInfo;
}
/// <summary>
/// Sets <see cref="SetNewRenderOrder"/>.
/// </summary>
private void SetNewRenderOrder()
{
var swapInfo = ThisSwap;
swapInfo.NewRenderOrder = true;
ThisSwap = swapInfo;
}
/// <summary>
/// Resets flags.
/// </summary>
private void ResetSwapInfoFlags()
{
ThisSwap = default;
}
/// <summary>
/// Reset visibility flags.
/// </summary>
private void ResetVisibilityFlags()
{
var swapInfo = LastSwap;
swapInfo.DidBecomeVisible = false;
swapInfo.DidBecomeInvisible = false;
LastSwap = swapInfo;
}
/// <summary>
/// Reset render order flag.
/// </summary>
private void ResetRenderOrderFlag()
{
var swapInfo = LastSwap;
swapInfo.NewRenderOrder = false;
LastSwap = swapInfo;
}
/// <summary>
/// Allows tracking of <see cref="Mesh"/> data changed on a swap.
/// </summary>
private struct SwapInfo
{
/// <summary>
/// Vertex positions were changed.
/// </summary>
public bool NewVertexPositions { get; set; }
/// <summary>
/// Vertex colors were changed.
/// </summary>
public bool NewVertexColors { get; set; }
/// <summary>
/// Visibility were changed to visible.
/// </summary>
public bool DidBecomeVisible { get; set; }
/// <summary>
/// Visibility were changed to invisible.
/// </summary>
public bool DidBecomeInvisible { get; set; }
/// <summary>
/// Render order were changed.
/// </summary>
public bool NewRenderOrder { get; set; }
}
#endregion
#region Unity Events Handling
/// <summary>
/// Finalizes instance.
/// </summary>
private void OnDestroy()
{
if (Meshes == null)
{
return;
}
for (var i = 0; i < Meshes.Length; i++)
{
DestroyImmediate(Meshes[i]);
}
}
#endregion
}
}