Initial commit
This commit is contained in:
commit
662f4a1d05
89 files changed
+8008
No files matched your search
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3487788d480845039f84f7aa89195d0b
|
||||
timeCreated: 1765564013
|
||||
@@ -0,0 +1,19 @@
|
||||
using Reflex.Core;
|
||||
|
||||
namespace Code.Debug
|
||||
{
|
||||
public class DebugInstaller : IInstaller
|
||||
{
|
||||
public void InstallBindings(ContainerBuilder containerBuilder)
|
||||
{
|
||||
containerBuilder.AddSingleton(typeof(DebugStateMachine));
|
||||
|
||||
containerBuilder.OnContainerBuilt += Bootstrap;
|
||||
}
|
||||
|
||||
private void Bootstrap(Container container)
|
||||
{
|
||||
container.Resolve<DebugStateMachine>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35352cf8cf4f4b638e1a1693a704f052
|
||||
timeCreated: 1765565958
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using Code.StateMachine;
|
||||
|
||||
namespace Code.Debug
|
||||
{
|
||||
public enum DebugStates
|
||||
{
|
||||
First,
|
||||
Second,
|
||||
Third
|
||||
}
|
||||
public class DebugStateMachineContext
|
||||
{
|
||||
public int SomeValue;
|
||||
}
|
||||
|
||||
[Generators.StateMachine(typeof(DebugStateMachineContext), typeof(DebugStates))]
|
||||
public partial class DebugStateMachine
|
||||
{ }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71d501bd1540463496c6df3fa0bbb0ca
|
||||
timeCreated: 1765564028
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e84c82fd2ce4c449bee71acf27ed874
|
||||
timeCreated: 1765566284
|
||||
@@ -0,0 +1,24 @@
|
||||
using Code.Generators;
|
||||
using Code.StateMachine;
|
||||
|
||||
namespace Code.Debug.States
|
||||
{
|
||||
[State(typeof(DebugStateMachineContext) )]
|
||||
public partial class FirstState : BaseState<DebugStates, DebugStateMachineContext>
|
||||
{
|
||||
public FirstState(DebugStateMachineContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override DebugStates myState => DebugStates.First;
|
||||
}
|
||||
[State(typeof(DebugStateMachineContext) )]
|
||||
public partial class SecondState : BaseState<DebugStates, DebugStateMachineContext>
|
||||
{
|
||||
public SecondState(DebugStateMachineContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
public override DebugStates myState => DebugStates.First;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24af5a4d2545481589242a5945bbafa5
|
||||
timeCreated: 1765566292
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56928494c304465d8dea6fe4bac75de2
|
||||
timeCreated: 1765563811
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace Code.Generators
|
||||
{
|
||||
public class StateMachine : Attribute
|
||||
{
|
||||
public Type StateMachineContextType;
|
||||
public Type StateMachineEnumType;
|
||||
|
||||
public StateMachine(Type stateMachineContextType, Type stateMachineEnumType)
|
||||
{
|
||||
StateMachineContextType = stateMachineContextType;
|
||||
StateMachineEnumType = stateMachineEnumType;
|
||||
}
|
||||
}
|
||||
|
||||
public class State : Attribute
|
||||
{
|
||||
public Type StateMachineContextType;
|
||||
public State (Type stateMachineContextType )
|
||||
{
|
||||
StateMachineContextType = stateMachineContextType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03e07712b53c4a3d8f6c8033af003369
|
||||
timeCreated: 1765563884
|
||||
@@ -0,0 +1,95 @@
|
||||
using System.Linq;
|
||||
using Code.StateMachine;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEditor;
|
||||
using UnityCodeGen;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Generators
|
||||
{
|
||||
[Generator]
|
||||
public class StateMachineGenerator : ICodeGenerator
|
||||
{
|
||||
public void Execute(GeneratorContext context)
|
||||
{
|
||||
var stateMachines = TypeCache.GetTypesWithAttribute<StateMachine>();
|
||||
|
||||
foreach (var sm in stateMachines)
|
||||
{
|
||||
var attribute = sm.GetAttribute<StateMachine>();
|
||||
|
||||
var states = TypeCache.GetTypesWithAttribute<State>()
|
||||
.Where(st =>
|
||||
st.GetAttribute<State>().StateMachineContextType.FullName ==
|
||||
attribute.StateMachineContextType.FullName);
|
||||
|
||||
var statesCode = "";
|
||||
var statesNamespacesCode = "";
|
||||
|
||||
foreach (var st in states)
|
||||
{
|
||||
var stateAttribute = st.GetAttribute<State>();
|
||||
statesNamespacesCode += $@"
|
||||
using {st.Namespace};
|
||||
";
|
||||
statesCode += $@"
|
||||
var state{st.Name} = new {st.Name}(StateMachineContext);
|
||||
States.Add(state{st.Name}.myState, state{st.Name});
|
||||
";
|
||||
}
|
||||
|
||||
var stateMachineCode =
|
||||
$@"
|
||||
// <auto-generated/>
|
||||
using Code.StateMachine;
|
||||
{statesNamespacesCode}
|
||||
namespace {sm.Namespace}
|
||||
{{
|
||||
|
||||
public partial class {sm.Name} : AbstractStateMachine<{attribute.StateMachineEnumType.FullName},{attribute.StateMachineContextType.FullName}>
|
||||
{{
|
||||
|
||||
public {sm.Name}()
|
||||
{{
|
||||
{statesCode}
|
||||
CurrentBaseState = States[default({attribute.StateMachineEnumType.FullName})];
|
||||
}}
|
||||
|
||||
protected override bool CheckTransitionAllowed({attribute.StateMachineEnumType.FullName} nextState) => AllowedStates.HasFlag(nextState);
|
||||
protected override void ResetAllowedTransitions() => AllowedStates = 0;
|
||||
}}
|
||||
|
||||
public static class {sm.Name}Extensions
|
||||
{{
|
||||
public static AbstractStateMachine<{attribute.StateMachineEnumType.FullName}, {attribute.StateMachineContextType.FullName}> AllowStateTransition(
|
||||
this AbstractStateMachine<{attribute.StateMachineEnumType.FullName}, {attribute.StateMachineContextType.FullName}> stateMachine, {attribute.StateMachineEnumType.FullName} state)
|
||||
{{
|
||||
if (stateMachine == null) return null;
|
||||
|
||||
stateMachine.AllowedStates |= state;
|
||||
return stateMachine;
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
|
||||
";
|
||||
|
||||
// var publicFields = t.GetFields()
|
||||
// .Where(x => x.IsPublic && !x.IsStatic)
|
||||
// .Select(x => $"{x.Name}:{{{x.Name}}}");
|
||||
|
||||
// var toString = string.Join(", ", publicFields);
|
||||
// var code =
|
||||
// $@"// <auto-generated/>
|
||||
// partial class {t.Name}
|
||||
// {{
|
||||
// public override string ToString()
|
||||
// {{
|
||||
// return $""{toString}"";
|
||||
// }}
|
||||
// }}";
|
||||
context.AddCode($"{sm.FullName}.Generated.cs", stateMachineCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fb4b6961cd0471d8183511316c15000
|
||||
timeCreated: 1765563824
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1c4dc7e83794f978e68900a1be81bc2
|
||||
timeCreated: 1765563491
|
||||
@@ -0,0 +1,70 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.StateMachine
|
||||
{
|
||||
public abstract class AbstractStateMachine<TStateEnum, TStateMachineContext>
|
||||
where TStateMachineContext : new()
|
||||
{
|
||||
public TStateEnum CurrentState { get; protected set; }
|
||||
public BaseState<TStateEnum, TStateMachineContext> CurrentBaseState { get; protected set; }
|
||||
private BaseState<TStateEnum, TStateMachineContext> _previousBaseState;
|
||||
|
||||
protected Dictionary<TStateEnum, BaseState<TStateEnum, TStateMachineContext>> States = new();
|
||||
public TStateEnum AllowedStates { get; set; }
|
||||
|
||||
public TStateMachineContext StateMachineContext { get; protected set; } = new();
|
||||
|
||||
// protected virtual void Update()
|
||||
// {
|
||||
// CurrentBaseState.Tick();
|
||||
// }
|
||||
//
|
||||
// protected void LateUpdate()
|
||||
// {
|
||||
// CurrentBaseState.LateTick();
|
||||
// }
|
||||
|
||||
// Костыли 2 шт. для флагового енама в шаблонах
|
||||
protected abstract bool CheckTransitionAllowed(TStateEnum nextState);
|
||||
protected abstract void ResetAllowedTransitions();
|
||||
|
||||
// TODO Если в EnterState вызывается ExitState, то будет гарантированная поломка
|
||||
public virtual AbstractStateMachine<TStateEnum, TStateMachineContext> SwitchState(TStateEnum nextState)
|
||||
{
|
||||
if (!CheckTransitionAllowed(nextState))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ResetAllowedTransitions();
|
||||
|
||||
_previousBaseState = CurrentBaseState;
|
||||
|
||||
CurrentBaseState = States[nextState];
|
||||
|
||||
if (_previousBaseState != null)
|
||||
{
|
||||
_previousBaseState.OnExited += CurrentBaseState.EnterState;
|
||||
_previousBaseState.OnExited += FinishBaseStateTransition;
|
||||
_previousBaseState.ExitState();
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentBaseState.EnterState();
|
||||
}
|
||||
|
||||
CurrentState = nextState;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected virtual void FinishBaseStateTransition()
|
||||
{
|
||||
_previousBaseState.OnExited -= CurrentBaseState.EnterState;
|
||||
_previousBaseState.OnExited -= FinishBaseStateTransition;
|
||||
|
||||
_previousBaseState = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f6ce15c93464753a99851fc5d46440f
|
||||
timeCreated: 1765563731
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Code.StateMachine
|
||||
{
|
||||
public abstract class BaseState<TEnum, TStateMachineContext>
|
||||
{
|
||||
public abstract TEnum myState { get; }
|
||||
|
||||
public delegate void Entered();
|
||||
public event Entered OnEntered;
|
||||
|
||||
public delegate void Exited();
|
||||
public event Exited OnExited;
|
||||
|
||||
protected BaseState(TStateMachineContext context)
|
||||
{
|
||||
Context = context;
|
||||
}
|
||||
public TStateMachineContext Context { get; protected set; }
|
||||
|
||||
public virtual void EnterState() => OnEntered?.Invoke();
|
||||
public virtual void ExitState() => OnExited?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c348c251b644c3c941d2bd91bbb290c
|
||||
timeCreated: 1765563748
|
||||
Reference in new issue
Block a user