internal static bool CanHandleTrigger <TState, TTrigger>(TTrigger trigger, RawStateMachineBase <TState, TTrigger> machine, bool exactMatch = false) { var res = FindAndEvaluateTriggerRepresentation(trigger, machine, false); if (res == null) { return(false); } if (StateConfigurationHelper.CheckFlag(res.TransitionFlags, TransitionFlag.DynamicState)) { var dynamicState = ((Func <DynamicState <TState> >)res.NextStateRepresentationWrapper)(); if (!dynamicState.CanTransition) { return(false); } } if (!exactMatch) { return(true); } return(res.OnTriggerAction.GetType() == typeof(Action <Transition <TState, TTrigger> >)); }
internal StateConfiguration(Dictionary <TState, StateRepresentation <TState, TTrigger> > representations, TState currentState) { Representations = representations; CurrentStateRepresentation = StateConfigurationHelper.FindOrCreateStateRepresentation(currentState, representations); }
internal static StateConfiguration <TState, TTrigger> Ignore <TState, TTrigger>( StateConfiguration <TState, TTrigger> config, Func <bool> predicate, TTrigger trigger) { Contract.NotNull(trigger != null, nameof(trigger)); if ( StateConfigurationHelper.FindTriggerRepresentation(trigger, config.CurrentStateRepresentation) != null) { ExceptionHelper.ThrowExclusiveOperation(); } var rep = StateConfigurationHelper.CreateTriggerRepresentation(trigger, config.CurrentStateRepresentation); rep.NextStateRepresentationWrapper = null; rep.ConditionalTriggerPredicate = predicate; return(config); }
internal static TriggerRepresentation <TTrigger> FindAndEvaluateTriggerRepresentation <TState, TTrigger>( TTrigger trigger, RawStateMachineBase <TState, TTrigger> machine, bool raiseInvalidTriggers = true) { var triggerRep = StateConfigurationHelper.FindTriggerRepresentation(trigger, machine.CurrentStateRepresentation); if (triggerRep == null) { if (raiseInvalidTriggers) { machine.RaiseInvalidTrigger(trigger); } return(null); } var predicate = triggerRep.ConditionalTriggerPredicate; if (predicate != null) { if (!predicate()) { if (raiseInvalidTriggers) { machine.RaiseInvalidTrigger(trigger); } return(null); } } // Handle ignored trigger if (triggerRep.NextStateRepresentationWrapper == null) { return(null); } return(triggerRep); }
private static StateConfiguration <TState, TTrigger> PermitCore <TState, TTrigger>( StateConfiguration <TState, TTrigger> config, Func <bool> predicate, TTrigger trigger, TState resultingState, object onTriggerAction) { Contract.NotNull(trigger != null, nameof(trigger)); Contract.NotNull(resultingState != null, nameof(resultingState)); if (StateConfigurationHelper.FindTriggerRepresentation(trigger, config.CurrentStateRepresentation) != null) { ExceptionHelper.ThrowExclusiveOperation(); } var rep = StateConfigurationHelper.CreateTriggerRepresentation(trigger, config.CurrentStateRepresentation); rep.NextStateRepresentationWrapper = StateConfigurationHelper.FindOrCreateStateRepresentation( resultingState, config.Representations); rep.OnTriggerAction = onTriggerAction; rep.ConditionalTriggerPredicate = predicate; return(config); }
private static StateConfiguration <TState, TTrigger> PermitDynamicCore <TState, TTrigger>( StateConfiguration <TState, TTrigger> config, TTrigger trigger, object targetStatePredicate, object onTriggerAction) { Contract.NotNull(trigger != null, nameof(trigger)); Contract.NotNull(targetStatePredicate != null, nameof(targetStatePredicate)); if ( StateConfigurationHelper.FindTriggerRepresentation(trigger, config.CurrentStateRepresentation) != null) { ExceptionHelper.ThrowExclusiveOperation(); } var rep = StateConfigurationHelper.CreateTriggerRepresentation(trigger, config.CurrentStateRepresentation); rep.NextStateRepresentationWrapper = targetStatePredicate; rep.OnTriggerAction = onTriggerAction; rep.ConditionalTriggerPredicate = null; rep.TransitionFlags |= TransitionFlag.DynamicState; return(config); }
internal static bool CanHandleTrigger <TState, TTrigger>(TTrigger trigger, RawStateMachineBase <TState, TTrigger> machine, Type argumentType) { var res = FindAndEvaluateTriggerRepresentation(trigger, machine, false); if (res == null) { return(false); } if (StateConfigurationHelper.CheckFlag(res.TransitionFlags, TransitionFlag.DynamicState)) { var dynamicState = ((Func <DynamicState <TState> >)res.NextStateRepresentationWrapper)(); if (!dynamicState.CanTransition) { return(false); } } var type = typeof(Action <,>).MakeGenericType(typeof(Transition <TState, TTrigger>), argumentType); return(res.OnTriggerAction.GetType() == type); }
internal static void FireCore <TState, TTrigger>(TTrigger trigger, RawStateMachineBase <TState, TTrigger> machine, bool raiseInvalidStateOrTrigger = true) { var currentStateRepresentation = machine.CurrentStateRepresentation; var triggerRep = DiagnosticsHelper.FindAndEvaluateTriggerRepresentation(trigger, machine, raiseInvalidStateOrTrigger); if (triggerRep == null) { return; } // Catch invalid parameters before execution. Action <Transition <TState, TTrigger> > triggerAction = null; try { triggerAction = (Action <Transition <TState, TTrigger> >)triggerRep.OnTriggerAction; } catch (InvalidCastException) { if (raiseInvalidStateOrTrigger) { machine.RaiseInvalidTrigger(trigger); } return; } StateRepresentation <TState, TTrigger> nextStateRep = null; if (StateConfigurationHelper.CheckFlag(triggerRep.TransitionFlags, TransitionFlag.DynamicState)) { var dynamicState = ((Func <DynamicState <TState> >)triggerRep.NextStateRepresentationWrapper)(); if (!dynamicState.CanTransition) { return; } var state = dynamicState.ResultingState; nextStateRep = StateConfigurationHelper.FindStateRepresentation(state, machine.Representations); if (nextStateRep == null) { if (raiseInvalidStateOrTrigger) { machine.RaiseInvalidState(state); } return; } } else { nextStateRep = (StateRepresentation <TState, TTrigger>)triggerRep.NextStateRepresentationWrapper; } var transition = new Transition <TState, TTrigger>(currentStateRepresentation.State, nextStateRep.State, trigger); machine.RaiseTransitionStarted(nextStateRep.State); // Current exit var currentExit = currentStateRepresentation.OnExitAction; currentExit?.Invoke(transition); // Trigger entry triggerAction?.Invoke(transition); // Next entry var nextEntry = nextStateRep.OnEntryAction; nextEntry?.Invoke(transition); var pastState = machine.CurrentState; machine.CurrentStateRepresentation = nextStateRep; machine.RaiseTransitionExecuted(pastState); }