// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System; using UltimateXR.Core; using UltimateXR.Core.Components.Composite; using UnityEngine; namespace UltimateXR.Animation.IK { /// /// Base IK Solver class. IK solvers should inherit from it and override the method. /// Not all solvers need to be part of an avatar, but the inheritance is used to /// be able to enumerate all the solvers that are part of an avatar. /// public abstract class UxrIKSolver : UxrAvatarComponent { #region Inspector Properties/Serialized Fields [SerializeField] private bool _enabled = true; [SerializeField] private bool _manualUpdate; #endregion #region Public Types & Data /// /// Called right before the IK is about to be solved during the current frame /// public event Action Solving; /// /// Called right after the IK was solved during the current frame /// public event Action Solved; /// /// Gets whether the component is initialized. /// public abstract bool Initialized { get; } /// /// Gets if the solver needs to be updated automatically. /// public bool NeedsAutoUpdate => gameObject.activeInHierarchy && enabled && SolverEnabled && !ManualUpdate; /// /// Gets or sets the IK solver enabled state? /// public bool SolverEnabled { get => _enabled; set => _enabled = value; } /// /// Gets if the IK solver will update itself. Otherwise the user will be responsible of calling . /// public bool ManualUpdate { get => _manualUpdate; set => _manualUpdate = value; } #endregion #region Public Methods /// /// Solves the IK. Calls ,which is implemented in child classes, but calls the /// appropriate and events. /// public void SolveIK() { Solving?.Invoke(); InternalSolveIK(); Solved?.Invoke(); } #endregion #region Unity /// /// Subscribes to events /// protected override void OnEnable() { base.OnEnable(); UxrManager.StageUpdating += UxrManager_StageUpdating; } /// /// Unsubscribes from events /// protected override void OnDisable() { base.OnDisable(); UxrManager.StageUpdating -= UxrManager_StageUpdating; } #endregion #region Event Handling Methods /// /// Will solve the IK chain in case it is not part of an avatar. If it is part of a VR avatar, the VR avatar will take /// care of calling the SolveIK method so that it is processed in the correct order, after the hands are updated. /// private void UxrManager_StageUpdating(UxrUpdateStage stage) { if (stage == UxrUpdateStage.PostProcess && Avatar == null && NeedsAutoUpdate) { SolveIK(); } } #endregion #region Protected Methods /// /// To be implemented in child classes to execute the actual IK solving algorithm for the current frame /// protected abstract void InternalSolveIK(); #endregion } }