123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- using System;
- using UnityEngine;
- namespace Animancer.FSM
- {
-
-
-
-
-
-
-
-
- public interface IState
- {
-
-
-
-
-
-
-
- bool CanEnterState { get; }
-
-
-
-
-
-
-
- bool CanExitState { get; }
-
-
-
-
-
- void OnEnterState();
-
-
-
-
-
- void OnExitState();
- }
-
-
-
-
-
-
-
-
- public interface IOwnedState<TState> : IState where TState : class, IState
- {
-
- StateMachine<TState> OwnerStateMachine { get; }
- }
-
-
-
-
-
-
-
- public abstract class State : IState
- {
-
-
-
- public virtual bool CanEnterState => true;
-
-
- public virtual bool CanExitState => true;
-
- public virtual void OnEnterState() { }
-
- public virtual void OnExitState() { }
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [HelpURL(APIDocumentationURL + nameof(StateExtensions))]
- public static class StateExtensions
- {
-
-
- public const string APIDocumentationURL = "https://kybernetik.com.au/animancer/api/Animancer.FSM/";
-
-
- public static TState GetPreviousState<TState>(this TState state)
- where TState : class, IState
- => StateChange<TState>.PreviousState;
-
- public static TState GetNextState<TState>(this TState state)
- where TState : class, IState
- => StateChange<TState>.NextState;
-
-
-
-
-
- public static bool IsCurrentState<TState>(this TState state)
- where TState : class, IOwnedState<TState>
- => state.OwnerStateMachine.CurrentState == state;
-
-
-
-
-
-
-
-
- public static bool TryEnterState<TState>(this TState state)
- where TState : class, IOwnedState<TState>
- => state.OwnerStateMachine.TrySetState(state);
-
-
-
-
-
-
-
- public static bool TryReEnterState<TState>(this TState state)
- where TState : class, IOwnedState<TState>
- => state.OwnerStateMachine.TryResetState(state);
-
-
-
-
-
-
-
-
- public static void ForceEnterState<TState>(this TState state)
- where TState : class, IOwnedState<TState>
- => state.OwnerStateMachine.ForceSetState(state);
-
- #pragma warning disable IDE0079 // Remove unnecessary suppression.
- #pragma warning disable CS1587 // XML comment is not placed on a valid language element.
- #pragma warning restore IDE0079 // Remove unnecessary suppression.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #if UNITY_ASSERTIONS
-
- internal static string GetChangeError(Type stateType, Type machineType, string changeType = "State")
- {
- Type previousType = null;
- Type baseStateType = null;
- System.Collections.Generic.HashSet<Type> activeChangeTypes = null;
- var stackTrace = new System.Diagnostics.StackTrace(1, false).GetFrames();
- for (int i = 0; i < stackTrace.Length; i++)
- {
- var type = stackTrace[i].GetMethod().DeclaringType;
- if (type != previousType &&
- type.IsGenericType &&
- type.GetGenericTypeDefinition() == machineType)
- {
- var argument = type.GetGenericArguments()[0];
- if (argument.IsAssignableFrom(stateType))
- {
- baseStateType = argument;
- break;
- }
- else
- {
- if (activeChangeTypes == null)
- activeChangeTypes = new System.Collections.Generic.HashSet<Type>();
- if (!activeChangeTypes.Contains(argument))
- activeChangeTypes.Add(argument);
- }
- }
- previousType = type;
- }
- var text = new System.Text.StringBuilder()
- .Append("Attempted to access ")
- .Append(changeType)
- .Append("Change<")
- .Append(stateType.FullName)
- .Append($"> but no {nameof(StateMachine<IState>)} of that type is currently changing its ")
- .Append(changeType)
- .AppendLine(".");
- if (baseStateType != null)
- {
- text.Append(" - ")
- .Append(changeType)
- .Append(" changes must be accessed using the base ")
- .Append(changeType)
- .Append(" type, which is ")
- .Append(changeType)
- .Append("Change<")
- .Append(baseStateType.FullName)
- .AppendLine("> in this case.");
- var caller = stackTrace[1].GetMethod();
- if (caller.DeclaringType == typeof(StateExtensions))
- {
- var propertyName = stackTrace[0].GetMethod().Name;
- propertyName = propertyName.Substring(4, propertyName.Length - 4);
- text.Append(" - This may be caused by the compiler incorrectly inferring the generic argument of the Get")
- .Append(propertyName)
- .Append(" method, in which case it must be manually specified like so: state.Get")
- .Append(propertyName)
- .Append('<')
- .Append(baseStateType.FullName)
- .AppendLine(">()");
- }
- }
- else
- {
- if (activeChangeTypes == null)
- {
- text.Append(" - No other ")
- .Append(changeType)
- .AppendLine(" changes are currently occurring either.");
- }
- else
- {
- if (activeChangeTypes.Count == 1)
- {
- text.Append(" - There is 1 ")
- .Append(changeType)
- .AppendLine(" change currently occurring:");
- }
- else
- {
- text.Append(" - There are ")
- .Append(activeChangeTypes.Count)
- .Append(' ')
- .Append(changeType)
- .AppendLine(" changes currently occurring:");
- }
- foreach (var type in activeChangeTypes)
- {
- text.Append(" - ")
- .AppendLine(type.FullName);
- }
- }
- }
- text.Append(" - ")
- .Append(changeType)
- .Append("Change<")
- .Append(stateType.FullName)
- .AppendLine($">.{nameof(StateChange<IState>.IsActive)} can be used to check if a change of that type is currently occurring.")
- .AppendLine(" - See the documentation for more information: " +
- "https://kybernetik.com.au/animancer/docs/manual/fsm/changing-states");
- return text.ToString();
- }
- #endif
-
- }
- }
|