#if UNITY_EDITOR using System.Linq; using Unity.VisualScripting; using UnityCodeGen; using UnityEditor; namespace Code.Infrastructure.Generators { [Generator] public class StateMachineGenerator : ICodeGenerator { public void Execute(GeneratorContext context) { GenerateStates(context); GenerateStateMachine(context); } private void GenerateStateMachine(GeneratorContext context) { var stateMachines = TypeCache.GetTypesWithAttribute(); foreach (var sm in stateMachines) { var attribute = sm.GetAttribute(); var states = TypeCache.GetTypesWithAttribute() .Where(st => st.GetAttribute().StateMachineContext.FullName == attribute.StateMachineContextType.FullName); var statesCode = ""; var statesNamespacesCode = ""; foreach (var st in states) { statesNamespacesCode += $@" using {st.Namespace}; "; statesCode += $@" var state{st.Name} = new {st.Name}(StateMachineContext,eventBus); States.Add(state{st.Name}.myState, state{st.Name}); "; } var stateMachineCode = $@" // #pragma warning disable CS0105 using Code.Infrastructure.StateMachine; {statesNamespacesCode} #pragma warning restore CS0105 namespace {sm.Namespace} {{ public partial class {sm.Name} : AbstractStateMachine<{attribute.StateMachineEnumType.FullName},{attribute.StateMachineContextType.FullName}> {{ public {sm.Name}({attribute.StateMachineContextType.FullName} context, EventBus.EventBus eventBus) : base(context) {{ {statesCode} }} 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; }} }} }} "; context.AddCode($"{sm.FullName}.Generated.cs", stateMachineCode); } } private void GenerateStates(GeneratorContext context) { var states = TypeCache.GetTypesWithAttribute(); var statesCode = ""; foreach (var st in states) { var attribute = st.GetAttribute(); var fireStatesCode = ""; if(st.HasAttribute()) fireStatesCode = $@" protected override void _fireEnterState() {{ EventBus.RaiseEvent>(h => h.EnterState()); }} protected override void _fireExitState() {{ EventBus.RaiseEvent>(h => h.ExitState()); }} "; var genetics = ""; if(!attribute.SilentBitch) genetics = $@" : BaseState<{attribute.StateEnum.FullName}, {attribute.StateMachineContext.FullName}>"; statesCode = $@" // retard-generated using Code.Infrastructure.StateMachine; namespace {st.Namespace} {{ public partial class {st.Name} {genetics} {{ {fireStatesCode} }} }} "; context.AddCode($"{st.FullName}.Generated.cs", statesCode); } } } } #endif