123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- using System;
- using System.Linq;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using Sirenix.OdinInspector;
- using UniRx;
- using KairoEngine.Core;
- namespace KairoEngine.Core.GameActions
- {
- [System.Serializable]
- public class GameActionsController : ISerializationCallbackReceiver
- {
- /// <summary>A context object that holds a list of GameActionContextVariables to be accessible for GameActions to use.</summary>
- [InlineProperty, HideLabel, ShowIf("showContext")]
- public GameActionContext context = new GameActionContext();
- [HideInInspector] public bool showContext = false;
- /// <summary>A list of GameActions to be executed in order.</summary>
- [ListDrawerSettings(HideAddButton = true, HideRemoveButton = false, DraggableItems = true, Expanded = false, ShowPaging = false, ShowItemCount = true)]
- [ShowInInspector, NonSerialized, OnInspectorInit("InitializeActionList")]
- [Space(4)]
- public List<GameAction> actions = new List<GameAction>();
- [NonSerialized] private CompositeDisposable cancel;
- private int actionIndex = 0;
- public bool started => _started;
- public bool isDone => _done;
- private bool _started = false;
- private bool _done = false;
- [HideInInspector] public int depth = 0;
- #region FlowControl
- /// <summary>Run GameActions on this controller. Each action will be fired after the previous action ended.</summary>
- public void Start()
- {
- actionIndex = 0;
- _done = false;
- _started = true;
- var observable = Observable.EveryUpdate();
- cancel = new CompositeDisposable();
- observable.Subscribe(xs => ExecuteActions()).AddTo(cancel);
- }
- /// <summary>Executes GameActions until it has to wait for an Update or reach the end of the action list.</summary>
- private void ExecuteActions()
- {
- if(actionIndex >= actions.Count)
- {
- // done
- _done = true;
- cancel.Dispose();
- return;
- }
- if(actions[actionIndex].done)
- {
- actionIndex += 1;
- ExecuteActions();
- }
- else
- {
- if(actions[actionIndex].started == false)
- {
- actions[actionIndex].Start();
- ExecuteActions();
- }
- else actions[actionIndex].Update();
- }
- }
- /// <summary>Stop executing GameActions on this controller.</summary>
- public void Stop()
- {
- if(cancel != null) cancel.Dispose();
- }
- public void Restart()
- {
- actionIndex = 0;
- _started = false;
- _done = false;
- foreach (var action in actions) action.Restart();
- }
- #endregion
- #region Serialization
- [SerializeField, HideInInspector] private List<string> serializedActions = new List<string>();
- [SerializeField, HideInInspector] public GameActionObjectSerializer objectSerializer = new GameActionObjectSerializer();
- private void SerializeActions()
- {
- if(actions == null) return;
- serializedActions = new List<string>();
- objectSerializer.ClearGameObjects();
- objectSerializer.ClearScriptableObjects();
- for (int i = 0; i < actions.Count; i++)
- {
- actions[i].OnBeforeSerialize(objectSerializer, i, depth);
- string data = JsonUtility.ToJson(actions[i]);
- serializedActions.Add(data);
- }
- }
- private void DeserializeActions()
- {
- if(serializedActions == null) return;
- if(actions == null) actions = new List<GameAction>();
- if(actions.Count > 0) actions.Clear();
- for (int i = 0; i < serializedActions.Count; i++)
- {
- GameAction action = JsonUtility.FromJson<GameActionBase>(serializedActions[i]);
- action = GameAction.InvokeStringMethod(action.className, action.typeName, serializedActions[i]);
- action.controller = this;
- action.OnBeforeDeserialize(objectSerializer, i, depth);
- actions.Add(action);
- // Type t = Type.GetType(action.typeName);
- // dynamic obj = Convert.ChangeType(action, t);
- // if(obj != null) actions.Add(obj.Duplicate());
- // else if(action != null) actions.Add(action);
- }
- for (int i = 0; i < actions.Count; i++)
- {
- actions[i].Initialize(objectSerializer);
- }
- objectSerializer.ClearGameObjects();
- objectSerializer.ClearScriptableObjects();
- //serializedActions = new List<string>();
- }
- public void OnBeforeSerialize() => SerializeActions();
- public void OnAfterDeserialize() => DeserializeActions();
- #endregion
- #region NewAction
- [OnInspectorInit("GetCompatibleVariablenames"), OnValueChanged("AddNewAction")]
- [ValueDropdown("possibleActions", IsUniqueList = false)]
- [LabelText("Add New Action")]
- [NonSerialized]
- public GameAction newAction;
- [NonSerialized] private IEnumerable possibleActions = new ValueDropdownList<GameAction>();
- private void GetCompatibleVariablenames()
- {
- possibleActions = ReflectiveEnumerator.GetEnumerableOfType<GameAction>(this)
- .Where(x => x.GetTypeName() != "GameActionBase")
- .Where(x => x.GetTypeName() != "GameAction")
- .Select(x => new ValueDropdownItem(x.GetActionName(), x));
- }
- private void AddNewAction()
- {
- if(newAction != null)
- {
- newAction.controller = this;
- newAction.className = newAction.GetType().AssemblyQualifiedName;
- actions.Add(newAction);
- newAction = null;
- }
- }
- #endregion
-
- #region Utilities
- private void InitializeActionList()
- {
- if(actions == null) actions = new List<GameAction>();
- }
- public GameActionsController Duplicate()
- {
- GameActionsController newController = new GameActionsController();
- newController.actions = new List<GameAction>();
- var newSerializedActions = new List<string>();
- objectSerializer.ClearGameObjects();
- for (int i = 0; i < actions.Count; i++)
- {
- actions[i].OnBeforeSerialize(objectSerializer, i, depth);
- string data = JsonUtility.ToJson(actions[i]);
- newSerializedActions.Add(data);
- }
- newController.objectSerializer = objectSerializer;
- objectSerializer = new GameActionObjectSerializer();
- newController.context = this.context.Duplicate();
- for (int i = 0; i < newSerializedActions.Count; i++)
- {
- //Debug.Log(newSerializedActions[i]);
- GameAction action = JsonUtility.FromJson<GameActionBase>(newSerializedActions[i]);
- if(action == null) continue;
- action = GameAction.InvokeStringMethod(action.className, action.typeName, newSerializedActions[i]);
- action.controller = newController;
- action.OnBeforeDeserialize(newController.objectSerializer, i, depth);
- newController.actions.Add(action);
- }
- newController.objectSerializer.ClearGameObjects();
- return newController;
- }
- #endregion
- }
- }
|