CubismRenderController.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  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 Live2D.Cubism.Core;
  8. using Live2D.Cubism.Framework;
  9. using System;
  10. using UnityEngine;
  11. using Object = UnityEngine.Object;
  12. namespace Live2D.Cubism.Rendering
  13. {
  14. /// <summary>
  15. /// Controls rendering of a <see cref="CubismModel"/>.
  16. /// </summary>
  17. [ExecuteInEditMode, CubismDontMoveOnReimport]
  18. public sealed class CubismRenderController : MonoBehaviour, ICubismUpdatable
  19. {
  20. /// <summary>
  21. /// Model opacity.
  22. /// </summary>
  23. /// <remarks>
  24. /// This is turned into a field to be available to <see cref="AnimationClip"/>s...
  25. /// </remarks>
  26. [SerializeField, HideInInspector]
  27. public float Opacity = 1f;
  28. /// <summary>
  29. /// <see cref="LastOpacity"/> backing field.
  30. /// </summary>
  31. [SerializeField, HideInInspector]
  32. private float _lastOpacity;
  33. /// <summary>
  34. /// Last model opacity.
  35. /// </summary>
  36. private float LastOpacity
  37. {
  38. get { return _lastOpacity; }
  39. set { _lastOpacity = value; }
  40. }
  41. /// <summary>
  42. /// Sorting layer name.
  43. /// </summary>
  44. public string SortingLayer
  45. {
  46. get
  47. {
  48. return UnityEngine.SortingLayer.IDToName(SortingLayerId);
  49. }
  50. set
  51. {
  52. SortingLayerId = UnityEngine.SortingLayer.NameToID(value);
  53. }
  54. }
  55. /// <summary>
  56. /// <see cref="SortingLayerId"/> backing field.
  57. /// </summary>
  58. [SerializeField, HideInInspector]
  59. private int _sortingLayerId;
  60. /// <summary>
  61. /// Sorting layer Id.
  62. /// </summary>
  63. public int SortingLayerId
  64. {
  65. get
  66. {
  67. return _sortingLayerId;
  68. }
  69. set
  70. {
  71. if (value == _sortingLayerId)
  72. {
  73. return;
  74. }
  75. _sortingLayerId = value;
  76. // Apply sorting layer.
  77. var renderers = Renderers;
  78. for (var i = 0; i < renderers.Length; ++i)
  79. {
  80. renderers[i].OnControllerSortingLayerDidChange(_sortingLayerId);
  81. }
  82. }
  83. }
  84. /// <summary>
  85. /// <see cref="SortingMode"/> backing field.
  86. /// </summary>
  87. [SerializeField, HideInInspector]
  88. private CubismSortingMode _sortingMode;
  89. /// <summary>
  90. /// <see cref="CubismDrawable"/> sorting.
  91. /// </summary>
  92. public CubismSortingMode SortingMode
  93. {
  94. get
  95. {
  96. return _sortingMode;
  97. }
  98. set
  99. {
  100. // Return early if same value given.
  101. if (value == _sortingMode)
  102. {
  103. return;
  104. }
  105. _sortingMode = value;
  106. // Flip sorting.
  107. var renderers = Renderers;
  108. for (var i = 0; i < renderers.Length; ++i)
  109. {
  110. renderers[i].OnControllerSortingModeDidChange(_sortingMode);
  111. }
  112. }
  113. }
  114. /// <summary>
  115. /// Order in sorting layer.
  116. /// </summary>
  117. [SerializeField, HideInInspector]
  118. private int _sortingOrder;
  119. /// <summary>
  120. /// Order in sorting layer.
  121. /// </summary>
  122. public int SortingOrder
  123. {
  124. get
  125. {
  126. return _sortingOrder;
  127. }
  128. set
  129. {
  130. // Return early in case same value given.
  131. if (value == _sortingOrder)
  132. {
  133. return;
  134. }
  135. _sortingOrder = value;
  136. // Apply new sorting order.
  137. var renderers = Renderers;
  138. for (var i = 0; i < renderers.Length; ++i)
  139. {
  140. renderers[i].OnControllerSortingOrderDidChange(SortingOrder);
  141. }
  142. }
  143. }
  144. /// <summary>
  145. /// [Optional] Camera to face.
  146. /// </summary>
  147. [SerializeField]
  148. public Camera CameraToFace;
  149. /// <summary>
  150. /// <see cref="DrawOrderHandler"/> backing field.
  151. /// </summary>
  152. [SerializeField, HideInInspector]
  153. private Object _drawOrderHandler;
  154. /// <summary>
  155. /// Draw order handler proxy object.
  156. /// </summary>
  157. public Object DrawOrderHandler
  158. {
  159. get { return _drawOrderHandler; }
  160. set { _drawOrderHandler = value.ToNullUnlessImplementsInterface<ICubismDrawOrderHandler>(); }
  161. }
  162. /// <summary>
  163. /// <see cref="DrawOrderHandlerInterface"/> backing field.
  164. /// </summary>
  165. [NonSerialized]
  166. private ICubismDrawOrderHandler _drawOrderHandlerInterface;
  167. /// <summary>
  168. /// Listener for draw order changes.
  169. /// </summary>
  170. private ICubismDrawOrderHandler DrawOrderHandlerInterface
  171. {
  172. get
  173. {
  174. if (_drawOrderHandlerInterface == null)
  175. {
  176. _drawOrderHandlerInterface = DrawOrderHandler.GetInterface<ICubismDrawOrderHandler>();
  177. }
  178. return _drawOrderHandlerInterface;
  179. }
  180. }
  181. /// <summary>
  182. /// <see cref="OpacityHandler"/> backing field.
  183. /// </summary>
  184. [SerializeField, HideInInspector]
  185. private Object _opacityHandler;
  186. /// <summary>
  187. /// Opacity handler proxy object.
  188. /// </summary>
  189. public Object OpacityHandler
  190. {
  191. get { return _opacityHandler; }
  192. set { _opacityHandler = value.ToNullUnlessImplementsInterface<ICubismOpacityHandler>(); }
  193. }
  194. /// <summary>
  195. /// <see cref="OpacityHandler"/> backing field.
  196. /// </summary>
  197. private ICubismOpacityHandler _opacityHandlerInterface;
  198. /// <summary>
  199. /// Listener for opacity changes.
  200. /// </summary>
  201. private ICubismOpacityHandler OpacityHandlerInterface
  202. {
  203. get
  204. {
  205. if (_opacityHandlerInterface == null)
  206. {
  207. _opacityHandlerInterface = OpacityHandler.GetInterface<ICubismOpacityHandler>();
  208. }
  209. return _opacityHandlerInterface;
  210. }
  211. }
  212. /// <summary>
  213. /// The value to offset the <see cref="CubismDrawable"/>s by.
  214. /// </summary>
  215. /// <remarks>
  216. /// You only need to adjust this value when using perspective cameras.
  217. /// </remarks>
  218. [SerializeField, HideInInspector]
  219. public float _depthOffset = 0.00001f;
  220. /// <summary>
  221. /// Depth offset used when sorting by depth.
  222. /// </summary>
  223. public float DepthOffset
  224. {
  225. get { return _depthOffset; }
  226. set
  227. {
  228. // Return if same value given.
  229. if (Mathf.Abs(value - _depthOffset) < Mathf.Epsilon)
  230. {
  231. return;
  232. }
  233. // Store value.
  234. _depthOffset = value;
  235. // Apply it.
  236. var renderers = Renderers;
  237. for (var i = 0; i < renderers.Length; ++i)
  238. {
  239. renderers[i].OnControllerDepthOffsetDidChange(_depthOffset);
  240. }
  241. }
  242. }
  243. /// <summary>
  244. /// Model the controller belongs to.
  245. /// </summary>
  246. private CubismModel Model
  247. {
  248. get { return this.FindCubismModel(); }
  249. }
  250. /// <summary>
  251. /// <see cref="DrawablesRootTransform"/> backing field.
  252. /// </summary>
  253. private Transform _drawablesRootTransform;
  254. /// <summary>
  255. /// Root transform of all <see cref="CubismDrawable"/>s of the model.
  256. /// </summary>
  257. private Transform DrawablesRootTransform
  258. {
  259. get
  260. {
  261. if (_drawablesRootTransform == null)
  262. {
  263. _drawablesRootTransform = Model.Drawables[0].transform.parent;
  264. }
  265. return _drawablesRootTransform;
  266. }
  267. }
  268. /// <summary>
  269. /// <see cref="Renderers"/>s backing field.
  270. /// </summary>
  271. [NonSerialized]
  272. private CubismRenderer[] _renderers;
  273. /// <summary>
  274. /// <see cref="CubismRenderer"/>s.
  275. /// </summary>
  276. public CubismRenderer[] Renderers
  277. {
  278. get
  279. {
  280. if (_renderers== null)
  281. {
  282. _renderers = Model.Drawables.GetComponentsMany<CubismRenderer>();
  283. }
  284. return _renderers;
  285. }
  286. private set { _renderers = value; }
  287. }
  288. /// <summary>
  289. /// Model has update controller component.
  290. /// </summary>
  291. [HideInInspector]
  292. public bool HasUpdateController { get; set; }
  293. /// <summary>
  294. /// Makes sure all <see cref="CubismDrawable"/>s have <see cref="CubismRenderer"/>s attached to them.
  295. /// </summary>
  296. private void TryInitializeRenderers()
  297. {
  298. // Try get renderers.
  299. var renderers = Renderers;
  300. // Create renderers if necesssary.
  301. if (renderers == null || renderers.Length == 0)
  302. {
  303. // Create renders and apply it to backing field...
  304. var drawables = this
  305. .FindCubismModel()
  306. .Drawables;
  307. renderers = drawables.AddComponentEach<CubismRenderer>();
  308. // Store renderers.
  309. Renderers = renderers;
  310. }
  311. // Make sure renderers are initialized.
  312. for (var i = 0; i < renderers.Length; ++i)
  313. {
  314. renderers[i].TryInitialize();
  315. }
  316. // Initialize sorting layer.
  317. // We set the backing field here directly because we pull the sorting layer directly from the renderer.
  318. _sortingLayerId = renderers[0]
  319. .MeshRenderer
  320. .sortingLayerID;
  321. }
  322. /// <summary>
  323. /// Updates opacity if necessary.
  324. /// </summary>
  325. private void UpdateOpacity()
  326. {
  327. // Return if same value given.
  328. if (Mathf.Abs(Opacity - LastOpacity) < Mathf.Epsilon)
  329. {
  330. return;
  331. }
  332. // Store value.
  333. Opacity = Mathf.Clamp(Opacity, 0f, 1f);
  334. LastOpacity = Opacity;
  335. // Apply opacity.
  336. var applyOpacityToRenderers = (OpacityHandlerInterface == null || Opacity > (1f - Mathf.Epsilon));
  337. if (applyOpacityToRenderers)
  338. {
  339. var renderers = Renderers;
  340. for (var i = 0; i < renderers.Length; ++i)
  341. {
  342. renderers[i].OnModelOpacityDidChange(Opacity);
  343. }
  344. }
  345. // Call handler.
  346. if (OpacityHandlerInterface != null)
  347. {
  348. OpacityHandlerInterface.OnOpacityDidChange(this, Opacity);
  349. }
  350. }
  351. /// <summary>
  352. /// Called by cubism update controller. Order to invoke OnLateUpdate.
  353. /// </summary>
  354. public int ExecutionOrder
  355. {
  356. get { return CubismUpdateExecutionOrder.CubismRenderController; }
  357. }
  358. /// <summary>
  359. /// Called by cubism update controller. Needs to invoke OnLateUpdate on Editing.
  360. /// </summary>
  361. public bool NeedsUpdateOnEditing
  362. {
  363. get { return true; }
  364. }
  365. /// <summary>
  366. /// Called by cubism update controller. Applies billboarding.
  367. /// </summary>
  368. public void OnLateUpdate()
  369. {
  370. // Fail silently...
  371. if(!enabled)
  372. {
  373. return;
  374. }
  375. // Update opacity if necessary.
  376. UpdateOpacity();
  377. // Return early in case no camera is to be faced.
  378. if (CameraToFace == null)
  379. {
  380. return;
  381. }
  382. // Face camera.
  383. DrawablesRootTransform.rotation = (Quaternion.LookRotation(CameraToFace.transform.forward, Vector3.up));
  384. }
  385. #region Unity Event Handling
  386. /// <summary>
  387. /// Called by Unity.
  388. /// </summary>
  389. private void Start()
  390. {
  391. // Get cubism update controller.
  392. HasUpdateController = (GetComponent<CubismUpdateController>() != null);
  393. }
  394. /// <summary>
  395. /// Called by Unity. Enables listening to render data updates.
  396. /// </summary>
  397. private void OnEnable()
  398. {
  399. // Fail silently.
  400. if (Model == null)
  401. {
  402. return;
  403. }
  404. // Make sure renderers are available.
  405. TryInitializeRenderers();
  406. // Register listener.
  407. Model.OnDynamicDrawableData += OnDynamicDrawableData;
  408. }
  409. /// <summary>
  410. /// Called by Unity. Disables listening to render data updates.
  411. /// </summary>
  412. private void OnDisable()
  413. {
  414. // Fail silently.
  415. if (Model == null)
  416. {
  417. return;
  418. }
  419. // Deregister listener.
  420. Model.OnDynamicDrawableData -= OnDynamicDrawableData;
  421. }
  422. #endregion
  423. #region Cubism Event Handling
  424. /// <summary>
  425. /// Called by Unity.
  426. /// </summary>
  427. private void LateUpdate()
  428. {
  429. if(!HasUpdateController)
  430. {
  431. OnLateUpdate();
  432. }
  433. }
  434. /// <summary>
  435. /// Called whenever new render data is available.
  436. /// </summary>
  437. /// <param name="sender">Model with new render data.</param>
  438. /// <param name="data">New render data.</param>
  439. private void OnDynamicDrawableData(CubismModel sender, CubismDynamicDrawableData[] data)
  440. {
  441. // Get drawables.
  442. var drawables = sender.Drawables;
  443. var renderers = Renderers;
  444. // Handle render data changes.
  445. for (var i = 0; i < data.Length; ++i)
  446. {
  447. // Controls whether mesh buffers are to be swapped.
  448. var swapMeshes = false;
  449. // Update visibility if last SwapInfo flag is true.
  450. renderers[i].UpdateVisibility();
  451. // Update render order if last SwapInfo flags is true.
  452. renderers[i].UpdateRenderOrder();
  453. // Skip completely non-dirty data.
  454. if (!data[i].IsAnyDirty)
  455. {
  456. continue;
  457. }
  458. // Update visibility.
  459. if (data[i].IsVisibilityDirty)
  460. {
  461. renderers[i].OnDrawableVisiblityDidChange(data[i].IsVisible);
  462. swapMeshes = true;
  463. }
  464. // Update render order.
  465. if (data[i].IsRenderOrderDirty)
  466. {
  467. renderers[i].OnDrawableRenderOrderDidChange(data[i].RenderOrder);
  468. swapMeshes = true;
  469. }
  470. // Update opacity.
  471. if (data[i].IsOpacityDirty)
  472. {
  473. renderers[i].OnDrawableOpacityDidChange(data[i].Opacity);
  474. swapMeshes = true;
  475. }
  476. // Update vertex positions.
  477. if (data[i].AreVertexPositionsDirty)
  478. {
  479. renderers[i].OnDrawableVertexPositionsDidChange(data[i].VertexPositions);
  480. swapMeshes = true;
  481. }
  482. // Swap buffers if necessary.
  483. // [INV] Swapping only half of the meshes might improve performance even. Would that be visually feasible?
  484. if (swapMeshes)
  485. {
  486. renderers[i].SwapMeshes();
  487. }
  488. }
  489. // Pass draw order changes to handler (if available).
  490. var drawOrderHandler = DrawOrderHandlerInterface;
  491. if (drawOrderHandler != null)
  492. {
  493. for (var i = 0; i < data.Length; ++i)
  494. {
  495. if (data[i].IsDrawOrderDirty)
  496. {
  497. drawOrderHandler.OnDrawOrderDidChange(this, drawables[i], data[i].DrawOrder);
  498. }
  499. }
  500. }
  501. }
  502. #endregion
  503. }
  504. }