private void CheckMenuAvailable() { IBehaviorItem selected = null; if (_TreeView.SelectedItem != null) { selected = _TreeView.SelectedItem as IBehaviorItem; } bool canDelete = true; bool canNew = false; bool canMoveUp = false; bool canMoveDown = false; if (selected != null) { if (selected.Data.BehaviorType == Framework.AI.BehaviorType.Composite) { CompositeData composite = (CompositeData)selected.Data; if (composite.CompositeType == Framework.AI.CompositeType.State) { canDelete = false; } canNew = true; } else if (selected.Data.BehaviorType == Framework.AI.BehaviorType.Decorator) { DecoratorData decorator = (DecoratorData)selected.Data; canNew = decorator.Count == 0; } else { canNew = false; } canMoveUp = selected.CanMoveUp; canMoveDown = selected.CanMoveDown; } else { canDelete = false; canNew = false; canMoveUp = false; canMoveDown = false; } _BtnMoveUp.IsEnabled = canMoveUp; _BtnMoveDown.IsEnabled = canMoveDown; _BtnRemoveBehavior.IsEnabled = canDelete; //_BtnCopyBehavior.IsEnabled = canDelete; _AddBehaviorMenuItem.IsEnabled = canNew; _InsertBehaviorMenuItem.IsEnabled = canNew; }
/// <summary> /// Create view model based on CompositeType /// </summary> /// <param name="behavior">selector data</param> /// <returns>Create view model</returns> static DecoratorItem CreateDecoratorItem(DecoratorData decorator) { switch (decorator.Type) { case Skill.Framework.AI.DecoratorType.Default: return(new DecoratorItem(decorator)); case Skill.Framework.AI.DecoratorType.AccessLimit: return(new AccessLimitDecoratorItem((AccessLimitDecoratorData)decorator)); default: throw new System.InvalidCastException("Invalid DecoratorType"); } }
private static void CheckAccessKey(DecoratorData decorator) { if (decorator.Type == Framework.AI.DecoratorType.AccessLimit) { AccessLimitDecoratorData accessLimitDecorator = (AccessLimitDecoratorData)decorator; if (string.IsNullOrEmpty(accessLimitDecorator.AccessKey)) { Debug.LogError(string.Format("The provided AccessKey '{0}' for behavior node '{1}' does not exist.", accessLimitDecorator.AccessKey, accessLimitDecorator.Name)); _ErrorFound = true; return; } if (string.IsNullOrEmpty(accessLimitDecorator.ClassName)) { Debug.LogError(string.Format(" Invalid AccessKey for behavior node '{0}'", accessLimitDecorator.Name)); _ErrorFound = true; } else { SharedAccessKeysData ac = null; foreach (var item in _AccessKeys) { if (item != null) { if (item.Name == accessLimitDecorator.ClassName) { ac = item; break; } } } if (ac == null) { Debug.LogError(string.Format(" Invalid AccessKey for behavior node '{0}'", accessLimitDecorator.Name)); _ErrorFound = true; } else { if (ac.Keys.Count(c => c.Key == accessLimitDecorator.AccessKey) < 1) { Debug.LogError(string.Format("The provided AccessKey '{0}' for behavior node '{1}' does not exist.", accessLimitDecorator.AccessKey, accessLimitDecorator.Name)); _ErrorFound = true; } } } } }
private static void SearchForBehaviorErrors() { List <string> nameList = new List <string>(50); foreach (BehaviorData b in _Behaviors) { if (string.IsNullOrEmpty(b.Name)) { Debug.LogError("There is a Behavior node with empty name."); _ErrorFound = true; } else { if (!nameList.Contains(b.Name)) { int count = _Behaviors.Count(c => c.Name == b.Name); if (count > 1) { Debug.LogError(string.Format("There are {0} behaviors node in BehaviorTree with same name ({1}).", count, b.Name)); _ErrorFound = true; } nameList.Add(b.Name); } CheckParameterError(b); if (b.BehaviorType == Framework.AI.BehaviorType.Decorator) { DecoratorData decorator = (DecoratorData)b; if (decorator.Count == 0) { Debug.LogError(string.Format("Decorator node {0} has not any children.", decorator.Name)); _ErrorFound = true; } CheckAccessKey(decorator); } if (b.Weight <= 0) { Debug.LogError(string.Format("Weight of Behavior node {0} is invalid (must be greater than 0).", b.Name)); _ErrorFound = true; } } } nameList.Clear(); }
/// <summary> /// Detect Behavior data from Given XmlElement and load it /// </summary> /// <param name="behavior">XmlElement contains Behavior data</param> /// <returns>Loaded Behavior</returns> public static BehaviorData CreateBehaviorFrom(XmlElement behavior) { BehaviorData result = null; Skill.Framework.AI.BehaviorType behaviorType = Skill.Framework.AI.BehaviorType.Action; bool isCorrect = false; try { behaviorType = behavior.GetAttributeValueAsEnum <Skill.Framework.AI.BehaviorType>("BehaviorType", Skill.Framework.AI.BehaviorType.Condition); isCorrect = true; } catch (Exception) { isCorrect = false; } if (isCorrect) { switch (behaviorType) { case Skill.Framework.AI.BehaviorType.Action: result = new ActionData(); break; case Skill.Framework.AI.BehaviorType.Condition: result = new ConditionData(); break; case Skill.Framework.AI.BehaviorType.Decorator: Skill.Framework.AI.DecoratorType decoratorType = behavior.GetAttributeValueAsEnum <Skill.Framework.AI.DecoratorType>("DecoratorType", Skill.Framework.AI.DecoratorType.Default); switch (decoratorType) { case Skill.Framework.AI.DecoratorType.Default: result = new DecoratorData(); break; case Skill.Framework.AI.DecoratorType.AccessLimit: result = new AccessLimitDecoratorData(); break; default: break; } break; case Skill.Framework.AI.BehaviorType.Composite: Skill.Framework.AI.CompositeType selectorType = behavior.GetAttributeValueAsEnum <Skill.Framework.AI.CompositeType>("CompositeType", Skill.Framework.AI.CompositeType.Sequence); switch (selectorType) { case Skill.Framework.AI.CompositeType.Sequence: result = new SequenceSelectorData(); break; case Skill.Framework.AI.CompositeType.Concurrent: result = new ConcurrentSelectorData(); break; case Skill.Framework.AI.CompositeType.Random: result = new RandomSelectorData(); break; case Skill.Framework.AI.CompositeType.Priority: result = new PrioritySelectorData(); break; case Skill.Framework.AI.CompositeType.Loop: result = new LoopSelectorData(); break; case Skill.Framework.AI.CompositeType.State: result = new BehaviorTreeStateData(); break; } break; case Skill.Framework.AI.BehaviorType.ChangeState: result = new ChangeStateData(); break; } } return(result); }
private static void SearchForBehaviorWarnings() { foreach (var b in _Behaviors) { if (b.BehaviorType == Framework.AI.BehaviorType.Composite) { CompositeData composite = (CompositeData)b; if (composite.Count == 0) { Debug.LogError(string.Format("Composite node {0} has not any children.", composite.Name)); _ErrorFound = true; } if (composite.CompositeType == Framework.AI.CompositeType.Priority || composite.CompositeType == Framework.AI.CompositeType.Concurrent || composite.CompositeType == Framework.AI.CompositeType.State) // check if a Decorator with NeverFaile property is child of PrioritySelector or ConcurrentSelector { foreach (var child in composite) { if (child != null && child.BehaviorType == Framework.AI.BehaviorType.Decorator) { if (((DecoratorData)child).NeverFail) { if (composite.CompositeType == Framework.AI.CompositeType.Priority || composite.CompositeType == Framework.AI.CompositeType.State) { Debug.LogWarning(string.Format("Decorator '{0}' with 'NeverFail' property setted to 'true' is child of PrioritySelector '{1}'. This cause next children unreachable.", child.Name, b.Name)); } else if (composite.CompositeType == Framework.AI.CompositeType.Concurrent) { if (((ConcurrentSelectorData)composite).SuccessPolicy == Framework.AI.SuccessPolicy.SucceedOnOne) { Debug.LogWarning(string.Format("Decorator '{0}' with 'NeverFail' property setted to 'true' is child of ConcurrentSelector '{1}' width 'SuccessPolicy' property setted to 'SucceedOnOne' . This cause ConcurrentSelector never fail.", child.Name, b.Name)); } } } } } } if (composite.CompositeType != Framework.AI.CompositeType.Random) { foreach (var child in composite) { if (child != null && child.BehaviorType == Framework.AI.BehaviorType.ChangeState) { int index = composite.IndexOf(child); if (index < composite.Count - 1) { Debug.LogWarning(string.Format("There are unreachable behaviors in Composite '{0}', after ChangeState '{1}'", composite.Name, child.Name)); } } } } } else if (b.BehaviorType == Framework.AI.BehaviorType.Decorator) { DecoratorData decorator = (DecoratorData)b; if (decorator.Type == Framework.AI.DecoratorType.AccessLimit) { AccessLimitDecoratorData al = (AccessLimitDecoratorData)decorator; if (decorator.Child.BehaviorType == Framework.AI.BehaviorType.ChangeState && al.KeyType == Framework.AI.AccessKeyType.CounterLimit) { Debug.LogWarning(string.Format("AccessLimitDecorator '{0} with CounterLimit accesskey' has a ChangeState child '{1}'. CounterLimit key will be unlocked after change state.", decorator.Name, decorator.Child.Name)); } } } } }
void AddMenuItem_Click(object sender, System.EventArgs e) { if (_TreeView.SelectedItem == null) { return; } if (!(_TreeView.SelectedItem is TreeViewFolder)) { return; } Skill.Editor.UI.MenuItem item = (Skill.Editor.UI.MenuItem)sender; BehaviorData behavior = null; if (string.IsNullOrEmpty(item.Tag)) { Skill.Framework.AI.BehaviorType type = (Framework.AI.BehaviorType)item.UserData; switch (type) { case Skill.Framework.AI.BehaviorType.Action: behavior = new ActionData() { Name = _Editor.GetUniqueName("NewAction") }; break; case Skill.Framework.AI.BehaviorType.Condition: behavior = new ConditionData() { Name = _Editor.GetUniqueName("NewCondition") }; break; default: behavior = null; break; } } else if (item.Tag == "Decorator") { Skill.Framework.AI.DecoratorType type = (Framework.AI.DecoratorType)item.UserData; switch (type) { case Skill.Framework.AI.DecoratorType.Default: behavior = new DecoratorData() { Name = _Editor.GetUniqueName("NewDecorator") }; break; case Skill.Framework.AI.DecoratorType.AccessLimit: behavior = new AccessLimitDecoratorData() { Name = _Editor.GetUniqueName("NewAccessDecorator") }; break; default: behavior = null; break; } } else if (item.Tag == "Composite") { Skill.Framework.AI.CompositeType type = (Framework.AI.CompositeType)item.UserData; switch (type) { case Skill.Framework.AI.CompositeType.Sequence: behavior = new SequenceSelectorData() { Name = _Editor.GetUniqueName("NewSequence") }; break; case Skill.Framework.AI.CompositeType.Concurrent: behavior = new ConcurrentSelectorData() { Name = _Editor.GetUniqueName("NewConcurrent") }; break; case Skill.Framework.AI.CompositeType.Random: behavior = new RandomSelectorData() { Name = _Editor.GetUniqueName("NewRandom") }; break; case Skill.Framework.AI.CompositeType.Priority: behavior = new PrioritySelectorData() { Name = _Editor.GetUniqueName("NewPriority") }; break; case Skill.Framework.AI.CompositeType.Loop: behavior = new LoopSelectorData() { Name = _Editor.GetUniqueName("NewLoop") }; break; default: behavior = null; break; } } if (behavior != null) { TreeViewFolder tvf = (TreeViewFolder)_TreeView.SelectedItem; tvf.Foldout.IsOpen = true; tvf.AddBehavior(behavior); _Editor.AddToList(behavior); _Editor.RefreshTree(); SelectItem(tvf, behavior); } }
public DecoratorItem(DecoratorData data) : base(data) { }