public void LoadStateMachine(StateMachineNodeUI stateMachineUI) { CreateGraphView(); void SetNodePositionAndExpansion(Node node, NodeVisualInfo info) { node.SetPosition(new Rect(info.Position, Vector2.zero)); node.expanded = info.IsExpanded; } NodeUI = stateMachineUI; var stateMachine = (StateMachineNode)stateMachineUI.StateMachineNodeAsset.Data; var parameterMap = new Dictionary <Parameter, ParameterNodeUI>(); var valueProviderMap = new Dictionary <IValueProvider, StateMachineBaseNodeUI>(); foreach (var parameter in stateMachine.Parameters.Values) { var parameterNode = new ParameterNodeUI(); GraphView.AddNode(parameterNode); SetNodePositionAndExpansion(parameterNode, stateMachineUI.StateMachineNodeAsset.ParameterMap[parameter.Id]); parameterNode.LoadData(parameter); parameterMap.Add(parameter, parameterNode); valueProviderMap.Add(parameter.ValueProvider, parameterNode); } var stateToNodeMap = new Dictionary <State, StateNodeUI>(); var nodeToStateMap = new Dictionary <StateNodeUI, State>(); for (int i = 0; i < stateMachine.States.Count; i++) { string stateName = stateMachine.States.KeyAt(i); State state = stateMachine.States.At(i); var stateNode = new StateNodeUI(); stateNode.Name = stateName; GraphView.AddNode(stateNode); SetNodePositionAndExpansion(stateNode, stateMachineUI.StateMachineNodeAsset.StateMap[state.Id]); stateToNodeMap.Add(state, stateNode); nodeToStateMap.Add(stateNode, state); valueProviderMap.Add(state.Time, stateNode); valueProviderMap.Add(state.PreviousTime, stateNode); valueProviderMap.Add(state.NormalizedTime, stateNode); valueProviderMap.Add(state.PreviousNormalizedTime, stateNode); } var anyStateMap = new Dictionary <AnyState, AnyStateNodeUI>(); for (int i = 0; i < stateMachine.AnyStates.Items.Count; i++) { string anyStateName = stateMachine.AnyStates.Items.KeyAt(i); AnyState anyState = stateMachine.AnyStates.Items.At(i); //if (anyState == null) { continue; } var anyStateNode = new AnyStateNodeUI(); anyStateNode.Name = anyStateName; GraphView.AddNode(anyStateNode); SetNodePositionAndExpansion(anyStateNode, stateMachineUI.StateMachineNodeAsset.AnyStateMap[anyState.Id]); anyStateNode.LoadData(GraphView, anyState, stateToNodeMap); anyStateMap.Add(anyState, anyStateNode); foreach (var transition in anyState.ExitTransitions) { var transitionConnection = (TransitionConnectionUI)CreateConnection(anyStateNode, stateToNodeMap[transition.DestinationState], false); LoadTransitionInfo(transitionConnection.Transitions[transitionConnection.Transitions.Count - 1], transition); } } if (NodeUI.StateMachineNodeAsset.AnyStatePriorityManager != null) { var anyStatePriorityManagerNode = new AnyStatePriorityManagerNodeUI(); GraphView.AddNode(anyStatePriorityManagerNode); SetNodePositionAndExpansion(anyStatePriorityManagerNode, stateMachineUI.StateMachineNodeAsset.AnyStatePriorityManager); anyStatePriorityManagerNode.LoadData(GraphView, stateMachine.AnyStates.Items.Values, anyStateMap); } foreach (var state in stateMachine.States.Values) { foreach (var transition in state.ExitTransitions) { StateNodeUI stateNode = stateToNodeMap[(State)transition.SourceState]; var transitionConnection = (TransitionConnectionUI)CreateConnection(stateNode, stateToNodeMap[transition.DestinationState], false); LoadTransitionInfo(transitionConnection.Transitions[transitionConnection.Transitions.Count - 1], transition); } } void LoadTransitionInfo(TransitionInfo transitionInfo, Transition transition) { transitionInfo.DurationType = transition.DurationType; transitionInfo.Duration = transition.Duration; transitionInfo.OffsetType = transition.OffsetType; transitionInfo.Offset = transition.Offset; transitionInfo.InterruptionSource = transition.InterruptionSource; transitionInfo.OrderedInterruption = transition.OrderedInterruption; transitionInfo.InterruptableByAnyState = transition.InterruptableByAnyState; transitionInfo.PlayAfterTransition = transition.PlayAfterTransition; transition.Conditions.ForEach(condition => { TransitionInfoCondition infoCondition = new TransitionInfoCondition(); transitionInfo.Conditions.Add(infoCondition); if (condition.ValueProvider == null) { return; } StateMachineBaseNodeUI node = valueProviderMap[condition.ValueProvider]; if (node is StateNodeUI stateNode) { State state = nodeToStateMap[stateNode]; infoCondition.ProviderSourceType = ValueProviderSourceType.State; infoCondition.State = stateNode; infoCondition.StateValueProvider = condition.ValueProvider == state.PreviousTime ? StateValueProviders.PreviousTime : condition.ValueProvider == state.Time ? StateValueProviders.Time : condition.ValueProvider == state.NormalizedTime ? StateValueProviders.NormalizedTime : StateValueProviders.PreviousNormalizedTime; FloatConditionEvaluator floatEvaluator = (FloatConditionEvaluator)condition.Evaluator; infoCondition.FloatComparison = floatEvaluator.Comparison; infoCondition.FloatComparisonValue = floatEvaluator.ComparisonValue; } else { ParameterNodeUI parameterNode = (ParameterNodeUI)node; infoCondition.ProviderSourceType = ValueProviderSourceType.Parameter; infoCondition.Parameter = parameterNode; switch (condition.Evaluator) { case BoolConditionEvaluator boolEvaluator: infoCondition.BoolComparisonValue = boolEvaluator.ComparisonValue == Bool.True; break; case IntConditionEvaluator intEvaluator: infoCondition.IntComparison = intEvaluator.Comparison; infoCondition.IntComparisonValue = intEvaluator.ComparisonValue; break; case FloatConditionEvaluator floatEvaluator: infoCondition.FloatComparison = floatEvaluator.Comparison; infoCondition.FloatComparisonValue = floatEvaluator.ComparisonValue; break; } } }); } EntryNodeUI entryStateNode = new EntryNodeUI(); GraphView.AddNode(entryStateNode); GraphView.EntryNode = entryStateNode; if (NodeUI.StateMachineNodeAsset.EntryState != null) { SetNodePositionAndExpansion(entryStateNode, NodeUI.StateMachineNodeAsset.EntryState); } entryStateNode.LoadData(GraphView, stateMachine.EntryState, stateToNodeMap); }
private void SaveStateMachine() { var stateMachine = new StateMachineNode(); NodeUI.StateMachineNodeAsset = new StateMachineNodeAsset { Data = stateMachine }; var parameterMap = new Dictionary <ParameterNodeUI, Parameter>(); var stateMap = new Dictionary <StateNodeUI, State>(); var anyStateMap = new Dictionary <AnyStateNodeUI, AnyState>(); var transitionMap = new Dictionary <TransitionInfo, Transition>(); Parameters.Items.Values.ForEach(p => { var parameter = stateMachine.AddParameter(p.Name); parameter.Type = (ValueProviderType)p.ParameterTypeField.value; NodeUI.StateMachineNodeAsset.ParameterMap.Add(parameter.Id, new NodeVisualInfo(p.GetPosition().position, p.expanded)); switch (parameter.ValueProvider) { case BoolProvider boolProvider: boolProvider.Value = p.BoolField.value; break; case IntProvider intProvider: intProvider.Value = p.IntField.value; break; case FloatProvider floatProvider: floatProvider.Value = p.FloatField.value; break; default: break; } parameterMap.Add(p, parameter); }); TransitionConnections.ForEach(transitionConnection => { transitionConnection.Transitions.ForEach(transitionInfo => { Transition transition = new Transition() { DurationType = transitionInfo.DurationType, Duration = transitionInfo.Duration, OffsetType = transitionInfo.OffsetType, Offset = transitionInfo.Offset, InterruptionSource = transitionInfo.InterruptionSource, OrderedInterruption = transitionInfo.OrderedInterruption, InterruptableByAnyState = transitionInfo.InterruptableByAnyState, PlayAfterTransition = transitionInfo.PlayAfterTransition }; stateMachine.Transitions.Add(transition); transitionMap.Add(transitionInfo, transition); }); }); States.Items.Values.ForEach(stateNode => { var state = stateMachine.AddState(stateNode.Name); stateNode.ExitConnections.ForEach(connection => { ((TransitionConnectionUI)connection).Transitions.ForEach(transitionInfo => { Transition transition = transitionMap[transitionInfo]; transition.SourceState = state; state.ExitTransitions.Add(transition); }); }); stateNode.EntryConnections.ForEach(connection => { if (!(connection is TransitionConnectionUI transitionConnection)) { return; } transitionConnection.Transitions.ForEach(transitionInfo => { Transition transition = transitionMap[transitionInfo]; transition.DestinationState = state; state.EntryTransitions.Add(transition); }); }); NodeUI.StateMachineNodeAsset.StateMap.Add(state.Id, new NodeVisualInfo(stateNode.GetPosition().position, stateNode.expanded)); stateMap.Add(stateNode, state); }); HashSet <AnyStateNodeUI> alreadyAddedAnyStates = new HashSet <AnyStateNodeUI>(); if (GraphView.AnyStatePriorityManager == null) { NodeUI.StateMachineNodeAsset.AnyStatePriorityManager = null; } else { NodeUI.StateMachineNodeAsset.AnyStatePriorityManager = new NodeVisualInfo(GraphView.AnyStatePriorityManager.GetPosition().position, GraphView.AnyStatePriorityManager.expanded); foreach (var anyStateNode in GraphView.AnyStatePriorityManager.AnyStates) { if (anyStateNode == null) { continue; } AnyState anyState = anyStateNode.GenerateData(stateMap); anyStateNode.ExitConnections.ForEach(connection => { ((TransitionConnectionUI)connection).Transitions.ForEach(transitionInfo => { Transition transition = transitionMap[transitionInfo]; transition.SourceState = anyState; anyState.ExitTransitions.Add(transition); }); }); stateMachine.AnyStates.AddItem(anyState); NodeUI.StateMachineNodeAsset.AnyStateMap.Add(anyState.Id, new NodeVisualInfo(anyStateNode.GetPosition().position, anyStateNode.expanded)); alreadyAddedAnyStates.Add(anyStateNode); anyStateMap.Add(anyStateNode, anyState); } } AnyStates.Items.Values.ForEach(anyStateNode => { if (alreadyAddedAnyStates.Contains(anyStateNode)) { return; } AnyState anyState = anyStateNode.GenerateData(stateMap); anyStateNode.ExitConnections.ForEach(connection => { ((TransitionConnectionUI)connection).Transitions.ForEach(transitionInfo => { Transition transition = transitionMap[transitionInfo]; transition.SourceState = anyState; anyState.ExitTransitions.Add(transition); }); }); stateMachine.AnyStates.AddItem(anyState); NodeUI.StateMachineNodeAsset.AnyStateMap.Add(anyState.Id, new NodeVisualInfo(anyStateNode.GetPosition().position, anyStateNode.expanded)); anyStateMap.Add(anyStateNode, anyState); }); TransitionConnections.ForEach(transitionConnection => { transitionConnection.Transitions.ForEach(transitionInfo => { Transition transition = transitionMap[transitionInfo]; transition.Conditions.Capacity = transitionInfo.Conditions.Count; transitionInfo.Conditions.ForEach(infoCondition => { TransitionCondition condition = new TransitionCondition(); if (infoCondition.ProviderSourceType == ValueProviderSourceType.State) { if (infoCondition.State != null) { State state = stateMap[infoCondition.State]; switch (infoCondition.StateValueProvider) { case StateValueProviders.PreviousTime: condition.SetValueProvider(state.PreviousTime); break; case StateValueProviders.Time: condition.SetValueProvider(state.Time); break; case StateValueProviders.PreviousNormalizedTime: condition.SetValueProvider(state.PreviousNormalizedTime); break; case StateValueProviders.NormalizedTime: condition.SetValueProvider(state.NormalizedTime); break; } FloatConditionEvaluator floatEvaluator = (FloatConditionEvaluator)condition.Evaluator; floatEvaluator.Comparison = infoCondition.FloatComparison; floatEvaluator.ComparisonValue = infoCondition.FloatComparisonValue; } } else if (infoCondition.Parameter != null) { condition.SetValueProvider(parameterMap[infoCondition.Parameter].ValueProvider); switch (condition.Evaluator) { case BoolConditionEvaluator boolEvaluator: boolEvaluator.ComparisonValue = infoCondition.BoolComparisonValue ? Bool.True : Bool.False; break; case IntConditionEvaluator intEvaluator: intEvaluator.Comparison = infoCondition.IntComparison; intEvaluator.ComparisonValue = infoCondition.IntComparisonValue; break; case FloatConditionEvaluator floatEvaluator: floatEvaluator.Comparison = infoCondition.FloatComparison; floatEvaluator.ComparisonValue = infoCondition.FloatComparisonValue; break; default: break; } } transition.Conditions.Add(condition); }); }); }); GraphView.EntryNode.GenerateData(stateMachine, stateMap); NodeUI.StateMachineNodeAsset.EntryState = new NodeVisualInfo(GraphView.EntryNode.GetPosition().position, GraphView.EntryNode.expanded); NodeUI.UpdateStatePorts(); }