CubismMaskCommandBuffer.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /**
  2. * Copyright(c) Live2D Inc. All rights reserved.
  3. *
  4. * Use of this source code is governed by the Live2D Open Software license
  5. * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
  6. */
  7. using System.Collections.Generic;
  8. using UnityEngine;
  9. using UnityEngine.Rendering;
  10. namespace Live2D.Cubism.Rendering.Masking
  11. {
  12. /// <summary>
  13. /// Singleton buffer for Cubism mask related draw commands.
  14. /// </summary>
  15. [ExecuteInEditMode]
  16. public sealed class CubismMaskCommandBuffer : MonoBehaviour
  17. {
  18. /// <summary>
  19. /// Draw command sources.
  20. /// </summary>
  21. private static List<ICubismMaskCommandSource> Sources { get; set; }
  22. /// <summary>
  23. /// Command buffer.
  24. /// </summary>
  25. private static CommandBuffer Buffer { get; set; }
  26. /// <summary>
  27. /// True if <see cref="Sources"/> are empty.
  28. /// </summary>
  29. private static bool ContainsSources
  30. {
  31. get { return Sources != null && Sources.Count > 0; }
  32. }
  33. /// <summary>
  34. /// Makes sure class is initialized for static usage.
  35. /// </summary>
  36. private static void Initialize()
  37. {
  38. // Initialize containers.
  39. if (Sources == null)
  40. {
  41. Sources = new List<ICubismMaskCommandSource>();
  42. }
  43. if (Buffer == null)
  44. {
  45. Buffer = new CommandBuffer
  46. {
  47. name = "cubism_MaskCommandBuffer"
  48. };
  49. }
  50. // Spawn update proxy.
  51. const string proxyName = "cubism_MaskCommandBuffer";
  52. var proxy = GameObject.Find(proxyName);
  53. if (proxy == null)
  54. {
  55. proxy = new GameObject(proxyName)
  56. {
  57. hideFlags = HideFlags.HideAndDontSave
  58. };
  59. if (!Application.isEditor || Application.isPlaying)
  60. {
  61. DontDestroyOnLoad(proxy);
  62. }
  63. proxy.AddComponent<CubismMaskCommandBuffer>();
  64. }
  65. }
  66. /// <summary>
  67. /// Registers a new draw command source.
  68. /// </summary>
  69. /// <param name="source">Source to add.</param>
  70. internal static void AddSource(ICubismMaskCommandSource source)
  71. {
  72. // Make sure singleton is initialized.
  73. Initialize();
  74. // Prevent same source from being added twice.
  75. if (Sources.Contains(source))
  76. {
  77. return;
  78. }
  79. // Add source and force refresh.
  80. Sources.Add(source);
  81. }
  82. /// <summary>
  83. /// Deregisters a draw command source.
  84. /// </summary>
  85. /// <param name="source">Source to remove.</param>
  86. internal static void RemoveSource(ICubismMaskCommandSource source)
  87. {
  88. // Make sure singleton is initialized.
  89. Initialize();
  90. // Remove source and force refresh.
  91. Sources.RemoveAll(s => s == source);
  92. }
  93. /// <summary>
  94. /// Forces the command buffer to be refreshed.
  95. /// </summary>
  96. private static void RefreshCommandBuffer()
  97. {
  98. // Clear buffer.
  99. Buffer.Clear();
  100. // Enqueue sources.
  101. for (var i = 0; i < Sources.Count; ++i)
  102. {
  103. Sources[i].AddToCommandBuffer(Buffer);
  104. }
  105. }
  106. #region Unity Event Handling
  107. /// <summary>
  108. /// Executes <see cref="Buffer"/>.
  109. /// </summary>
  110. private void LateUpdate()
  111. {
  112. if (!ContainsSources)
  113. {
  114. return;
  115. }
  116. // Refresh and execute buffer.
  117. RefreshCommandBuffer();
  118. Graphics.ExecuteCommandBuffer(Buffer);
  119. }
  120. #endregion
  121. }
  122. }