using System; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; namespace AibisDream.Kit { internal class MonoUpdateActionExecutor : MonoBehaviour, IActionExecutor { public class ActionTask { public IAction action; public IActionController controller; public Action onFinish; } private List _prepareExecutionActions = new(); private Dictionary _executingActions = new(); private static SimpleObjectPool _actionTaskPool = new( () => new ActionTask(), (task) => { task.action = null; task.controller = null; task.onFinish = null; }, 50); public void Execute(IActionController controller, Action onFinish = null) { if (controller.Action.Status == ActionStatus.Finished) controller.Action.Reset(); if (this.UpdateAction(controller, 0, onFinish)) return; var actionTask = _actionTaskPool.Allocate(); actionTask.action = controller.Action; actionTask.controller = controller; actionTask.onFinish = onFinish; _prepareExecutionActions.Add(actionTask); } private List _toActionRemove = new(); private void Update() { if (_prepareExecutionActions.Count > 0) { foreach (var prepareExecutionAction in _prepareExecutionActions) { _executingActions[prepareExecutionAction.action] = prepareExecutionAction; } _prepareExecutionActions.Clear(); } foreach (var actionAndFinishCallback in _executingActions) { if (actionAndFinishCallback.Value.controller.UpdateMode == ActionUpdateModes.ScaledDeltaTime) { if (this.UpdateAction(actionAndFinishCallback.Value.controller, Time.deltaTime, actionAndFinishCallback.Value.onFinish)) { _toActionRemove.Add(actionAndFinishCallback.Value.controller); } } else if (actionAndFinishCallback.Value.controller.UpdateMode == ActionUpdateModes.UnscaledDeltaTime) { if (this.UpdateAction(actionAndFinishCallback.Value.controller, Time.unscaledDeltaTime, actionAndFinishCallback.Value.onFinish)) { _toActionRemove.Add(actionAndFinishCallback.Value.controller); } } } if (_toActionRemove.Count > 0) { foreach (var controller in _toActionRemove) { _executingActions.Remove(controller.Action); controller.Recycle(); } _toActionRemove.Clear(); } } } public static class MonoUpdateActionExecutorExtension { public static IAction ExecuteByUpdate(this T self, IAction action, IActionController controller, Action onFinish = null) where T : MonoBehaviour { if (action.Status == ActionStatus.Finished) action.Reset(); self.gameObject.GetOrAddComponent().Execute(controller, onFinish); return action; } } }