Files
aibis-dream/Assets/Scripts/Framework/ActionKit/IAction.cs
T
2026-01-28 16:20:19 +08:00

234 lines
6.3 KiB
C#

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<ActionController> 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<IActionController> 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<IActionController> 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<IActionController> 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<IActionController> onFinish = null);
}
public static class IActionExecutorExtensions
{
public static bool UpdateAction(this IActionExecutor self, IActionController controller, float dt,
Action<IActionController> onFinish = null)
{
if (!controller.Action.IsFinalized && controller.Action.Execute(dt))
{
onFinish?.Invoke(controller);
controller.Deinit();
return true;
}
return controller.Action.IsFinalized;
}
}
}