using System; using UnityEngine; namespace AibisDream.Kit { public enum ActionStatus { NotStart, Started, Finished, } public enum ActionUpdateModes { ScaledDeltaTime, UnscaledDeltaTime, } public interface IActionController { ulong ActionID { get; set; } IAction Action { get; set; } ActionUpdateModes UpdateMode { get; set; } bool Paused { get; set; } void Reset(); void Deinit(); void Recycle(); } public interface IAction { ulong ActionID { get; set; } ActionStatus Status { get; set; } void OnStart(); void OnExecute(float dt); void OnFinish(); bool IsFinalized { get; set; } bool Paused { get; set; } void Reset(); void Deinit(); } public class ActionController : IActionController { private static readonly SimpleObjectPool Pool = new( () => new ActionController(), controller => { controller.UpdateMode = ActionUpdateModes.ScaledDeltaTime; controller.ActionID = 0; controller.Action = null; }, 50); public ulong ActionID { get; set; } public IAction Action { get; set; } public ActionUpdateModes UpdateMode { get; set; } private bool _recycled; public bool Paused { get => Action.Paused; set => Action.Paused = value; } public void Reset() { if (Action.ActionID == ActionID) { Action.Reset(); } } public static IActionController Allocate() { var controller = Pool.Allocate(); controller._recycled = false; return controller; } public void Deinit() { if (Action != null && Action.ActionID == ActionID) { Action.Deinit(); } } public void Recycle() { Pool.Recycle(this); } } public static class IActionExtensions { public static IActionController Start(this IAction self, MonoBehaviour monoBehaviour, Action onFinish = null) { var controller = ActionController.Allocate(); controller.ActionID = self.ActionID; controller.Action = self; controller.UpdateMode = ActionUpdateModes.ScaledDeltaTime; monoBehaviour.ExecuteByUpdate(self, controller, onFinish); return controller; } public static IActionController Start(this IAction self, MonoBehaviour monoBehaviour, Action onFinish) { var controller = ActionController.Allocate(); controller.ActionID = self.ActionID; controller.Action = self; controller.UpdateMode = ActionUpdateModes.ScaledDeltaTime; monoBehaviour.ExecuteByUpdate(self, controller, _ => onFinish()); return controller; } // public static IActionController StartCurrentScene(this IAction self, Action onFinish = null) // { // return self.Start(ActionKitCurrentScene.SceneComponent, onFinish); // } // // public static IActionController StartCurrentScene(this IAction self, Action onFinish) // { // return self.Start(ActionKitCurrentScene.SceneComponent, onFinish); // } public static IActionController StartGlobal(this IAction self, Action onFinish = null) { return self.Start(ActionKitMonoBehaviourEvents.GetOrCreate(), onFinish); } public static IActionController StartGlobal(this IAction self, Action onFinish) { return self.Start(ActionKitMonoBehaviourEvents.GetOrCreate(), onFinish); } public static void Pause(this IActionController self) { if (self.ActionID == self.Action.ActionID) { self.Action.Paused = true; } } public static void Resume(this IActionController self) { if (self.ActionID == self.Action.ActionID) { self.Action.Paused = false; } } public static void Finish(this IAction self) { self.Status = ActionStatus.Finished; } public static bool Execute(this IAction self, float dt) { if (self.Status == ActionStatus.NotStart) { self.OnStart(); if (self.Status == ActionStatus.Finished) { self.OnFinish(); return true; } self.Status = ActionStatus.Started; } else if (self.Status == ActionStatus.Started) { if (self.Paused) return false; self.OnExecute(dt); if (self.Status == ActionStatus.Finished) { self.OnFinish(); return true; } } else if (self.Status == ActionStatus.Finished) { self.OnFinish(); return true; } return false; } } public static class IActionControllerExtensions { public static IActionController IgnoreTimeScale(this IActionController self) { self.UpdateMode = ActionUpdateModes.UnscaledDeltaTime; return self; } } public interface IActionExecutor { void Execute(IActionController controller, Action onFinish = null); } public static class IActionExecutorExtensions { public static bool UpdateAction(this IActionExecutor self, IActionController controller, float dt, Action onFinish = null) { if (!controller.Action.IsFinalized && controller.Action.Execute(dt)) { onFinish?.Invoke(controller); controller.Deinit(); return true; } return controller.Action.IsFinalized; } } }