| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657 | 
							- /**
 
-  * 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;
 
- using System;
 
- using UnityEngine;
 
- using Object = UnityEngine.Object;
 
- namespace Live2D.Cubism.Rendering
 
- {
 
-     /// <summary>
 
-     /// Controls rendering of a <see cref="CubismModel"/>.
 
-     /// </summary>
 
-     [ExecuteInEditMode, CubismDontMoveOnReimport]
 
-     public sealed class CubismRenderController : MonoBehaviour, ICubismUpdatable
 
-     {
 
-         /// <summary>
 
-         /// Model opacity.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// This is turned into a field to be available to <see cref="AnimationClip"/>s...
 
-         /// </remarks>
 
-         [SerializeField, HideInInspector]
 
-         public float Opacity = 1f;
 
-         /// <summary>
 
-         /// <see cref="LastOpacity"/> backing field.
 
-         /// </summary>
 
-         [SerializeField, HideInInspector]
 
-         private float _lastOpacity;
 
-         /// <summary>
 
-         /// Last model opacity.
 
-         /// </summary>
 
-         private float LastOpacity
 
-         {
 
-             get { return _lastOpacity; }
 
-             set { _lastOpacity = value; }
 
-         }
 
-         /// <summary>
 
-         /// Sorting layer name.
 
-         /// </summary>
 
-         public string SortingLayer
 
-         {
 
-             get
 
-             {
 
-                 return UnityEngine.SortingLayer.IDToName(SortingLayerId);
 
-             }
 
-             set
 
-             {
 
-                 SortingLayerId = UnityEngine.SortingLayer.NameToID(value);
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="SortingLayerId"/> backing field.
 
-         /// </summary>
 
-         [SerializeField, HideInInspector]
 
-         private int _sortingLayerId;
 
-         /// <summary>
 
-         /// Sorting layer Id.
 
-         /// </summary>
 
-         public int SortingLayerId
 
-         {
 
-             get
 
-             {
 
-                 return _sortingLayerId;
 
-             }
 
-             set
 
-             {
 
-                 if (value == _sortingLayerId)
 
-                 {
 
-                     return;
 
-                 }
 
-                 _sortingLayerId = value;
 
-                 // Apply sorting layer.
 
-                 var renderers = Renderers;
 
-                 for (var i = 0; i < renderers.Length; ++i)
 
-                 {
 
-                     renderers[i].OnControllerSortingLayerDidChange(_sortingLayerId);
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="SortingMode"/> backing field.
 
-         /// </summary>
 
-         [SerializeField, HideInInspector]
 
-         private CubismSortingMode _sortingMode;
 
-         /// <summary>
 
-         /// <see cref="CubismDrawable"/> sorting.
 
-         /// </summary>
 
-         public CubismSortingMode SortingMode
 
-         {
 
-             get
 
-             {
 
-                 return _sortingMode;
 
-             }
 
-             set
 
-             {
 
-                 // Return early if same value given.
 
-                 if (value == _sortingMode)
 
-                 {
 
-                     return;
 
-                 }
 
-                 _sortingMode = value;
 
-                 // Flip sorting.
 
-                 var renderers = Renderers;
 
-                 for (var i = 0; i < renderers.Length; ++i)
 
-                 {
 
-                     renderers[i].OnControllerSortingModeDidChange(_sortingMode);
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Order in sorting layer.
 
-         /// </summary>
 
-         [SerializeField, HideInInspector]
 
-         private int _sortingOrder;
 
-         /// <summary>
 
-         /// Order in sorting layer.
 
-         /// </summary>
 
-         public int SortingOrder
 
-         {
 
-             get
 
-             {
 
-                 return _sortingOrder;
 
-             }
 
-             set
 
-             {
 
-                 // Return early in case same value given.
 
-                 if (value == _sortingOrder)
 
-                 {
 
-                     return;
 
-                 }
 
-                 _sortingOrder = value;
 
-                 // Apply new sorting order.
 
-                 var renderers = Renderers;
 
-                 for (var i = 0; i < renderers.Length; ++i)
 
-                 {
 
-                     renderers[i].OnControllerSortingOrderDidChange(SortingOrder);
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// [Optional] Camera to face.
 
-         /// </summary>
 
-         [SerializeField]
 
-         public Camera CameraToFace;
 
-         /// <summary>
 
-         /// <see cref="DrawOrderHandler"/> backing field.
 
-         /// </summary>
 
-         [SerializeField, HideInInspector]
 
-         private Object _drawOrderHandler;
 
-         /// <summary>
 
-         /// Draw order handler proxy object.
 
-         /// </summary>
 
-         public Object DrawOrderHandler
 
-         {
 
-             get { return _drawOrderHandler; }
 
-             set { _drawOrderHandler = value.ToNullUnlessImplementsInterface<ICubismDrawOrderHandler>(); }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="DrawOrderHandlerInterface"/> backing field.
 
-         /// </summary>
 
-         [NonSerialized]
 
-         private ICubismDrawOrderHandler _drawOrderHandlerInterface;
 
-         /// <summary>
 
-         /// Listener for draw order changes.
 
-         /// </summary>
 
-         private ICubismDrawOrderHandler DrawOrderHandlerInterface
 
-         {
 
-             get
 
-             {
 
-                 if (_drawOrderHandlerInterface == null)
 
-                 {
 
-                     _drawOrderHandlerInterface = DrawOrderHandler.GetInterface<ICubismDrawOrderHandler>();
 
-                 }
 
-                 return _drawOrderHandlerInterface;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="OpacityHandler"/> backing field.
 
-         /// </summary>
 
-         [SerializeField, HideInInspector]
 
-         private Object _opacityHandler;
 
-         /// <summary>
 
-         /// Opacity handler proxy object.
 
-         /// </summary>
 
-         public Object OpacityHandler
 
-         {
 
-             get { return _opacityHandler; }
 
-             set { _opacityHandler = value.ToNullUnlessImplementsInterface<ICubismOpacityHandler>(); }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="OpacityHandler"/> backing field.
 
-         /// </summary>
 
-         private ICubismOpacityHandler _opacityHandlerInterface;
 
-         /// <summary>
 
-         /// Listener for opacity changes.
 
-         /// </summary>
 
-         private ICubismOpacityHandler OpacityHandlerInterface
 
-         {
 
-             get
 
-             {
 
-                 if (_opacityHandlerInterface == null)
 
-                 {
 
-                     _opacityHandlerInterface = OpacityHandler.GetInterface<ICubismOpacityHandler>();
 
-                 }
 
-                 return _opacityHandlerInterface;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// The value to offset the <see cref="CubismDrawable"/>s by.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// You only need to adjust this value when using perspective cameras.
 
-         /// </remarks>
 
-         [SerializeField, HideInInspector]
 
-         public float _depthOffset = 0.00001f;
 
-         /// <summary>
 
-         /// Depth offset used when sorting by depth.
 
-         /// </summary>
 
-         public float DepthOffset
 
-         {
 
-             get { return _depthOffset; }
 
-             set
 
-             {
 
-                 // Return if same value given.
 
-                 if (Mathf.Abs(value - _depthOffset) < Mathf.Epsilon)
 
-                 {
 
-                     return;
 
-                 }
 
-                 // Store value.
 
-                 _depthOffset = value;
 
-                 // Apply it.
 
-                 var renderers = Renderers;
 
-                 for (var i = 0; i < renderers.Length; ++i)
 
-                 {
 
-                     renderers[i].OnControllerDepthOffsetDidChange(_depthOffset);
 
-                 }
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Model the controller belongs to.
 
-         /// </summary>
 
-         private CubismModel Model
 
-         {
 
-             get { return this.FindCubismModel(); }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="DrawablesRootTransform"/> backing field.
 
-         /// </summary>
 
-         private Transform _drawablesRootTransform;
 
-         /// <summary>
 
-         /// Root transform of all <see cref="CubismDrawable"/>s of the model.
 
-         /// </summary>
 
-         private Transform DrawablesRootTransform
 
-         {
 
-             get
 
-             {
 
-                 if (_drawablesRootTransform == null)
 
-                 {
 
-                     _drawablesRootTransform = Model.Drawables[0].transform.parent;
 
-                 }
 
-                 return _drawablesRootTransform;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// <see cref="Renderers"/>s backing field.
 
-         /// </summary>
 
-         [NonSerialized]
 
-         private CubismRenderer[] _renderers;
 
-         /// <summary>
 
-         /// <see cref="CubismRenderer"/>s.
 
-         /// </summary>
 
-         public CubismRenderer[] Renderers
 
-         {
 
-             get
 
-             {
 
-                 if (_renderers== null)
 
-                 {
 
-                     _renderers = Model.Drawables.GetComponentsMany<CubismRenderer>();
 
-                 }
 
-                 return _renderers;
 
-             }
 
-             private set { _renderers = value; }
 
-         }
 
-         /// <summary>
 
-         /// Model has update controller component.
 
-         /// </summary>
 
-         [HideInInspector]
 
-         public bool HasUpdateController { get; set; }
 
-         /// <summary>
 
-         /// Makes sure all <see cref="CubismDrawable"/>s have <see cref="CubismRenderer"/>s attached to them.
 
-         /// </summary>
 
-         private void TryInitializeRenderers()
 
-         {
 
-             // Try get renderers.
 
-             var renderers = Renderers;
 
-             // Create renderers if necesssary.
 
-             if (renderers == null || renderers.Length == 0)
 
-             {
 
-                 // Create renders and apply it to backing field...
 
-                 var drawables = this
 
-                 .FindCubismModel()
 
-                 .Drawables;
 
-                 renderers = drawables.AddComponentEach<CubismRenderer>();
 
-                 // Store renderers.
 
-                 Renderers = renderers;
 
-             }
 
-             // Make sure renderers are initialized.
 
-             for (var i = 0; i < renderers.Length; ++i)
 
-             {
 
-                 renderers[i].TryInitialize();
 
-             }
 
-             // Initialize sorting layer.
 
-             // We set the backing field here directly because we pull the sorting layer directly from the renderer.
 
-             _sortingLayerId = renderers[0]
 
-                 .MeshRenderer
 
-                 .sortingLayerID;
 
-         }
 
-         /// <summary>
 
-         /// Updates opacity if necessary.
 
-         /// </summary>
 
-         private void UpdateOpacity()
 
-         {
 
-             // Return if same value given.
 
-             if (Mathf.Abs(Opacity - LastOpacity) < Mathf.Epsilon)
 
-             {
 
-                 return;
 
-             }
 
-             // Store value.
 
-             Opacity = Mathf.Clamp(Opacity, 0f, 1f);
 
-             LastOpacity = Opacity;
 
-             // Apply opacity.
 
-             var applyOpacityToRenderers = (OpacityHandlerInterface == null || Opacity > (1f - Mathf.Epsilon));
 
-             if (applyOpacityToRenderers)
 
-             {
 
-                 var renderers = Renderers;
 
-                 for (var i = 0; i < renderers.Length; ++i)
 
-                 {
 
-                     renderers[i].OnModelOpacityDidChange(Opacity);
 
-                 }
 
-             }
 
-             // Call handler.
 
-             if (OpacityHandlerInterface != null)
 
-             {
 
-                 OpacityHandlerInterface.OnOpacityDidChange(this, Opacity);
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Called by cubism update controller. Order to invoke OnLateUpdate.
 
-         /// </summary>
 
-         public int ExecutionOrder
 
-         {
 
-             get { return CubismUpdateExecutionOrder.CubismRenderController; }
 
-         }
 
-         /// <summary>
 
-         /// Called by cubism update controller. Needs to invoke OnLateUpdate on Editing.
 
-         /// </summary>
 
-         public bool NeedsUpdateOnEditing
 
-         {
 
-             get { return true; }
 
-         }
 
-         /// <summary>
 
-         /// Called by cubism update controller. Applies billboarding.
 
-         /// </summary>
 
-         public void OnLateUpdate()
 
-         {
 
-             // Fail silently...
 
-             if(!enabled)
 
-             {
 
-                 return;
 
-             }
 
-             // Update opacity if necessary.
 
-             UpdateOpacity();
 
-             // Return early in case no camera is to be faced.
 
-             if (CameraToFace == null)
 
-             {
 
-                 return;
 
-             }
 
-             // Face camera.
 
-             DrawablesRootTransform.rotation = (Quaternion.LookRotation(CameraToFace.transform.forward, Vector3.up));
 
-         }
 
-         #region Unity Event Handling
 
-         /// <summary>
 
-         /// Called by Unity.
 
-         /// </summary>
 
-         private void Start()
 
-         {
 
-             // Get cubism update controller.
 
-             HasUpdateController = (GetComponent<CubismUpdateController>() != null);
 
-         }
 
-         /// <summary>
 
-         /// Called by Unity. Enables listening to render data updates.
 
-         /// </summary>
 
-         private void OnEnable()
 
-         {
 
-             // Fail silently.
 
-             if (Model == null)
 
-             {
 
-                 return;
 
-             }
 
-             // Make sure renderers are available.
 
-             TryInitializeRenderers();
 
-             // Register listener.
 
-             Model.OnDynamicDrawableData += OnDynamicDrawableData;
 
-         }
 
-         /// <summary>
 
-         /// Called by Unity. Disables listening to render data updates.
 
-         /// </summary>
 
-         private void OnDisable()
 
-         {
 
-             // Fail silently.
 
-             if (Model == null)
 
-             {
 
-                 return;
 
-             }
 
-             // Deregister listener.
 
-             Model.OnDynamicDrawableData -= OnDynamicDrawableData;
 
-         }
 
-         #endregion
 
-         #region Cubism Event Handling
 
-         /// <summary>
 
-         /// Called by Unity.
 
-         /// </summary>
 
-         private void LateUpdate()
 
-         {
 
-             if(!HasUpdateController)
 
-             {
 
-                 OnLateUpdate();
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Called whenever new render data is available.
 
-         /// </summary>
 
-         /// <param name="sender">Model with new render data.</param>
 
-         /// <param name="data">New render data.</param>
 
-         private void OnDynamicDrawableData(CubismModel sender, CubismDynamicDrawableData[] data)
 
-         {
 
-             // Get drawables.
 
-             var drawables = sender.Drawables;
 
-             var renderers = Renderers;
 
-             // Handle render data changes.
 
-             for (var i = 0; i < data.Length; ++i)
 
-             {
 
-                 // Controls whether mesh buffers are to be swapped.
 
-                 var swapMeshes = false;
 
-                 // Update visibility if last SwapInfo flag is true.
 
-                 renderers[i].UpdateVisibility();
 
-                 // Update render order if last SwapInfo flags is true.
 
-                 renderers[i].UpdateRenderOrder();
 
-                 // Skip completely non-dirty data.
 
-                 if (!data[i].IsAnyDirty)
 
-                 {
 
-                     continue;
 
-                 }
 
-                 // Update visibility.
 
-                 if (data[i].IsVisibilityDirty)
 
-                 {
 
-                     renderers[i].OnDrawableVisiblityDidChange(data[i].IsVisible);
 
-                     swapMeshes = true;
 
-                 }
 
-                 // Update render order.
 
-                 if (data[i].IsRenderOrderDirty)
 
-                 {
 
-                     renderers[i].OnDrawableRenderOrderDidChange(data[i].RenderOrder);
 
-                     swapMeshes = true;
 
-                 }
 
-                 // Update opacity.
 
-                 if (data[i].IsOpacityDirty)
 
-                 {
 
-                     renderers[i].OnDrawableOpacityDidChange(data[i].Opacity);
 
-                     swapMeshes = true;
 
-                 }
 
-                 // Update vertex positions.
 
-                 if (data[i].AreVertexPositionsDirty)
 
-                 {
 
-                     renderers[i].OnDrawableVertexPositionsDidChange(data[i].VertexPositions);
 
-                     swapMeshes = true;
 
-                 }
 
-                 // Swap buffers if necessary.
 
-                 // [INV] Swapping only half of the meshes might improve performance even. Would that be visually feasible?
 
-                 if (swapMeshes)
 
-                 {
 
-                     renderers[i].SwapMeshes();
 
-                 }
 
-             }
 
-             // Pass draw order changes to handler (if available).
 
-             var drawOrderHandler = DrawOrderHandlerInterface;
 
-             if (drawOrderHandler != null)
 
-             {
 
-                 for (var i = 0; i < data.Length; ++i)
 
-                 {
 
-                     if (data[i].IsDrawOrderDirty)
 
-                     {
 
-                         drawOrderHandler.OnDrawOrderDidChange(this, drawables[i], data[i].DrawOrder);
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         #endregion
 
-     }
 
- }
 
 
  |