Add Has Goal decorator to BT
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FlaxEditor.GUI;
|
using FlaxEditor.GUI;
|
||||||
using FlaxEditor.GUI.Tree;
|
using FlaxEditor.GUI.Tree;
|
||||||
using FlaxEditor.Scripting;
|
using FlaxEditor.Scripting;
|
||||||
@@ -89,6 +90,15 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
typed = new ScriptType(valueType.GenericTypeArguments[0]);
|
typed = new ScriptType(valueType.GenericTypeArguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get customization options
|
||||||
|
var attributes = Values.GetAttributes();
|
||||||
|
var attribute = (BehaviorKnowledgeSelectorAttribute)attributes?.FirstOrDefault(x => x is BehaviorKnowledgeSelectorAttribute);
|
||||||
|
bool isGoalSelector = false;
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
isGoalSelector = attribute.IsGoalSelector;
|
||||||
|
}
|
||||||
|
|
||||||
// Create menu with tree-like structure and search box
|
// Create menu with tree-like structure and search box
|
||||||
var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree, 0, true);
|
var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree, 0, true);
|
||||||
var selected = Path;
|
var selected = Path;
|
||||||
@@ -111,8 +121,11 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
if (string.IsNullOrEmpty(selected))
|
if (string.IsNullOrEmpty(selected))
|
||||||
tree.Select(noneNode);
|
tree.Select(noneNode);
|
||||||
|
|
||||||
|
if (!isGoalSelector)
|
||||||
|
{
|
||||||
// Blackboard
|
// Blackboard
|
||||||
SetupPickerTypeItems(tree, typed, selected, "Blackboard", "Blackboard/", rootNode.BlackboardType);
|
SetupPickerTypeItems(tree, typed, selected, "Blackboard", "Blackboard/", rootNode.BlackboardType);
|
||||||
|
}
|
||||||
|
|
||||||
// Goals
|
// Goals
|
||||||
var goalTypes = rootNode.GoalTypes;
|
var goalTypes = rootNode.GoalTypes;
|
||||||
@@ -129,7 +142,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
var goalType = TypeUtils.GetType(goalTypeName);
|
var goalType = TypeUtils.GetType(goalTypeName);
|
||||||
if (goalType == null)
|
if (goalType == null)
|
||||||
continue;
|
continue;
|
||||||
var goalTypeNode = SetupPickerTypeItems(tree, typed, selected, goalType.Name, "Goal/" + goalTypeName + "/", goalTypeName);
|
var goalTypeNode = SetupPickerTypeItems(tree, typed, selected, goalType.Name, "Goal/" + goalTypeName + "/", goalTypeName, !isGoalSelector);
|
||||||
goalTypeNode.Parent = goalsNode;
|
goalTypeNode.Parent = goalsNode;
|
||||||
}
|
}
|
||||||
goalsNode.ExpandAll(true);
|
goalsNode.ExpandAll(true);
|
||||||
@@ -138,12 +151,11 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
menu.Show(_label, new Float2(0, _label.Height));
|
menu.Show(_label, new Float2(0, _label.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
private TreeNode SetupPickerTypeItems(Tree tree, ScriptType typed, string selected, string text, string typePath, string typeName)
|
private TreeNode SetupPickerTypeItems(Tree tree, ScriptType typed, string selected, string text, string typePath, string typeName, bool addItems = true)
|
||||||
{
|
{
|
||||||
var type = TypeUtils.GetType(typeName);
|
var type = TypeUtils.GetType(typeName);
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return null;
|
return null;
|
||||||
var items = GenericEditor.GetItemsForType(type, type.IsClass, true);
|
|
||||||
var typeNode = new TreeNode
|
var typeNode = new TreeNode
|
||||||
{
|
{
|
||||||
Text = text,
|
Text = text,
|
||||||
@@ -155,6 +167,9 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
typeNode.Tag = null;
|
typeNode.Tag = null;
|
||||||
if (string.Equals(selected, (string)typeNode.Tag, StringComparison.Ordinal))
|
if (string.Equals(selected, (string)typeNode.Tag, StringComparison.Ordinal))
|
||||||
tree.Select(typeNode);
|
tree.Select(typeNode);
|
||||||
|
if (addItems)
|
||||||
|
{
|
||||||
|
var items = GenericEditor.GetItemsForType(type, type.IsClass, true);
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
if (typed && !typed.IsAssignableFrom(item.Info.ValueType))
|
if (typed && !typed.IsAssignableFrom(item.Info.ValueType))
|
||||||
@@ -172,6 +187,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
// TODO: add support for nested items (eg. field from blackboard structure field)
|
// TODO: add support for nested items (eg. field from blackboard structure field)
|
||||||
}
|
}
|
||||||
typeNode.Expand(true);
|
typeNode.Expand(true);
|
||||||
|
}
|
||||||
return typeNode;
|
return typeNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ bool AccessVariant(Variant& instance, const StringAnsiView& member, Variant& val
|
|||||||
if (member.IsEmpty())
|
if (member.IsEmpty())
|
||||||
{
|
{
|
||||||
// Whole blackboard value
|
// Whole blackboard value
|
||||||
CHECK_RETURN(instance.Type == value.Type, false);
|
|
||||||
if (set)
|
if (set)
|
||||||
|
{
|
||||||
|
CHECK_RETURN(instance.Type == value.Type, false);
|
||||||
instance = value;
|
instance = value;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
value = instance;
|
value = instance;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -4,6 +4,28 @@ using System;
|
|||||||
|
|
||||||
namespace FlaxEngine
|
namespace FlaxEngine
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Customizes editor of <see cref="BehaviorKnowledgeSelector{T}"/> or <see cref="BehaviorKnowledgeSelectorAny"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="System.Attribute" />
|
||||||
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
|
public sealed class BehaviorKnowledgeSelectorAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Changes selector editor to allow to pick only whole goals.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsGoalSelector;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BehaviorKnowledgeSelectorAttribute"/> structure.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="isGoalSelector">Changes selector editor to allow to pick only whole goals.</param>
|
||||||
|
public BehaviorKnowledgeSelectorAttribute(bool isGoalSelector = false)
|
||||||
|
{
|
||||||
|
IsGoalSelector = isGoalSelector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if FLAX_EDITOR
|
#if FLAX_EDITOR
|
||||||
[CustomEditor(typeof(FlaxEditor.CustomEditors.Editors.BehaviorKnowledgeSelectorEditor))]
|
[CustomEditor(typeof(FlaxEditor.CustomEditors.Editors.BehaviorKnowledgeSelectorEditor))]
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -456,3 +456,9 @@ bool BehaviorTreeHasTagDecorator::CanUpdate(const BehaviorUpdateContext& context
|
|||||||
result ^= Invert;
|
result ^= Invert;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BehaviorTreeHasGoalDecorator::CanUpdate(const BehaviorUpdateContext& context)
|
||||||
|
{
|
||||||
|
Variant value; // TODO: use HasGoal in Knowledge to optimize this (goal struct is copied by selector accessor)
|
||||||
|
return Goal.TryGet(context.Knowledge, value);
|
||||||
|
}
|
||||||
|
|||||||
@@ -374,3 +374,20 @@ public:
|
|||||||
// [BehaviorTreeNode]
|
// [BehaviorTreeNode]
|
||||||
bool CanUpdate(const BehaviorUpdateContext& context) override;
|
bool CanUpdate(const BehaviorUpdateContext& context) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if certain goal has been added to Behavior knowledge.
|
||||||
|
/// </summary>
|
||||||
|
API_CLASS(Sealed) class FLAXENGINE_API BehaviorTreeHasGoalDecorator : public BehaviorTreeDecorator
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(BehaviorTreeHasGoalDecorator, BehaviorTreeDecorator);
|
||||||
|
API_AUTO_SERIALIZATION();
|
||||||
|
|
||||||
|
// The goal type to check.
|
||||||
|
API_FIELD(Attributes="EditorOrder(0), BehaviorKnowledgeSelector(IsGoalSelector = true)")
|
||||||
|
BehaviorKnowledgeSelectorAny Goal;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// [BehaviorTreeNode]
|
||||||
|
bool CanUpdate(const BehaviorUpdateContext& context) override;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user