123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- /**
- * 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 UnityEngine;
- using Object = UnityEngine.Object;
- namespace Live2D.Cubism.Framework.LookAt
- {
- /// <summary>
- /// Controls <see cref="CubismLookParameter"/>s.
- /// </summary>
- public sealed class CubismLookController : MonoBehaviour, ICubismUpdatable
- {
- /// <summary>
- /// Blend mode.
- /// </summary>
- [SerializeField]
- public CubismParameterBlendMode BlendMode = CubismParameterBlendMode.Additive;
- /// <summary>
- /// <see cref="Target"/> backing field.
- /// </summary>
- [SerializeField, HideInInspector] private Object _target;
- /// <summary>
- /// Target.
- /// </summary>
- public Object Target
- {
- get { return _target; }
- set { _target = value.ToNullUnlessImplementsInterface<ICubismLookTarget>(); }
- }
- /// <summary>
- /// <see cref="TargetInterface"/> backing field.
- /// </summary>
- private ICubismLookTarget _targetInterface;
- /// <summary>
- /// Interface of target.
- /// </summary>
- private ICubismLookTarget TargetInterface
- {
- get
- {
- if (_targetInterface == null)
- {
- _targetInterface = Target.GetInterface<ICubismLookTarget>();
- }
- return _targetInterface;
- }
- }
- /// <summary>
- /// Local center position.
- /// </summary>
- public Transform Center;
- /// <summary>
- /// Damping to apply.
- /// </summary>
- public float Damping = 0.15f;
- /// <summary>
- /// Source parameters.
- /// </summary>
- private CubismLookParameter[] Sources { get; set; }
- /// <summary>
- /// The actual parameters to apply the source values to.
- /// </summary>
- private CubismParameter[] Destinations { get; set; }
- /// <summary>
- /// Position at last frame.
- /// </summary>
- private Vector3 LastPosition { get; set; }
- /// <summary>
- /// Goal position.
- /// </summary>
- private Vector3 GoalPosition { get; set; }
- /// <summary>
- /// Buffer for <see cref="Mathf.SmoothDamp(float, float, ref float, float)"/> velocity.
- /// </summary>
- // ReSharper disable once InconsistentNaming
- private Vector3 VelocityBuffer;
- /// <summary>
- /// Model has update controller component.
- /// </summary>
- [HideInInspector]
- public bool HasUpdateController { get; set; }
- /// <summary>
- /// Refreshes the controller. Call this method after adding and/or removing <see cref="CubismLookParameter"/>s.
- /// </summary>
- public void Refresh()
- {
- var model = this.FindCubismModel();
- // Catch sources and destinations.
- Sources = model
- .Parameters
- .GetComponentsMany<CubismLookParameter>();
- Destinations = new CubismParameter[Sources.Length];
- for (var i = 0; i < Sources.Length; ++i)
- {
- Destinations[i] = Sources[i].GetComponent<CubismParameter>();
- }
- // Get cubism update controller.
- HasUpdateController = (GetComponent<CubismUpdateController>() != null);
- }
- /// <summary>
- /// Called by cubism update controller. Order to invoke OnLateUpdate.
- /// </summary>
- public int ExecutionOrder
- {
- get { return CubismUpdateExecutionOrder.CubismLookController; }
- }
- /// <summary>
- /// Called by cubism update controller. Needs to invoke OnLateUpdate on Editing.
- /// </summary>
- public bool NeedsUpdateOnEditing
- {
- get { return false; }
- }
- /// <summary>
- /// Called by cubism update controller. Updates controller.
- /// </summary>
- public void OnLateUpdate()
- {
- // Return if it is not valid or there's nothing to update.
- if (!enabled || Destinations == null)
- {
- return;
- }
- // Return early if no target is available or if target is inactive.
- var target = TargetInterface;
- if (target == null || !target.IsActive())
- {
- return;
- }
- // Update position.
- var position = LastPosition;
- GoalPosition = transform.InverseTransformPoint(target.GetPosition()) - Center.localPosition;
- if (position != GoalPosition)
- {
- position = Vector3.SmoothDamp(
- position,
- GoalPosition,
- ref VelocityBuffer,
- Damping);
- }
- // Update sources and destinations.
- for (var i = 0; i < Destinations.Length; ++i)
- {
- Destinations[i].BlendToValue(BlendMode, Sources[i].TickAndEvaluate(position));
- }
- // Store position.
- LastPosition = position;
- }
- #region Unity Events Handling
- /// <summary>
- /// Called by Unity. Makes sure cache is initialized.
- /// </summary>
- private void Start()
- {
- // Default center if necessary.
- if (Center == null)
- {
- Center = transform;
- }
- // Initialize cache.
- Refresh();
- }
- /// <summary>
- /// Called by Unity. Updates controller.
- /// </summary>
- private void LateUpdate()
- {
- if (!HasUpdateController)
- {
- OnLateUpdate();
- }
- }
- #endregion
- }
- }
|