From aa3d5c8a680af44d41f79f072cab63a5ca47c9a5 Mon Sep 17 00:00:00 2001 From: Wichamir <53086728+Wichamir@users.noreply.github.com> Date: Mon, 19 Dec 2022 18:33:08 +0100 Subject: [PATCH] Show editor warnings on wrong configuration (#80), closes #77 * Show editor warnings * Update BeehaveRoot warning condition Co-authored-by: miguel --- addons/beehave/nodes/beehave_node.gd | 1 + addons/beehave/nodes/beehave_root.gd | 16 ++++++++++++++++ addons/beehave/nodes/beehave_tree.gd | 10 ++++++++++ addons/beehave/nodes/composites/composite.gd | 17 ++++++++++++++--- addons/beehave/nodes/composites/selector.gd | 5 ++--- .../beehave/nodes/composites/selector_star.gd | 5 ++--- addons/beehave/nodes/composites/sequence.gd | 5 ++--- .../beehave/nodes/composites/sequence_star.gd | 5 ++--- addons/beehave/nodes/decorators/decorator.gd | 17 ++++++++++++++--- addons/beehave/nodes/decorators/failer.gd | 5 ++--- addons/beehave/nodes/decorators/inverter.gd | 5 ++--- addons/beehave/nodes/decorators/limiter.gd | 5 ++--- addons/beehave/nodes/decorators/succeeder.gd | 5 ++--- addons/beehave/nodes/leaves/action.gd | 5 ++--- addons/beehave/nodes/leaves/condition.gd | 5 ++--- addons/beehave/nodes/leaves/leaf.gd | 16 +++++++++++++--- tests/BeehaveTestScene.tscn | 1 + 17 files changed, 89 insertions(+), 39 deletions(-) diff --git a/addons/beehave/nodes/beehave_node.gd b/addons/beehave/nodes/beehave_node.gd index 80fd5e81..5c4b9af3 100644 --- a/addons/beehave/nodes/beehave_node.gd +++ b/addons/beehave/nodes/beehave_node.gd @@ -1,5 +1,6 @@ ## A node in the behaviour tree. Every node must return `SUCCESS`, `FAILURE` or ## `RUNNING` when ticked. +@tool class_name BeehaveNode extends BeehaveTree @icon("../icons/action.svg") diff --git a/addons/beehave/nodes/beehave_root.gd b/addons/beehave/nodes/beehave_root.gd index 2113268b..e04a43a3 100644 --- a/addons/beehave/nodes/beehave_root.gd +++ b/addons/beehave/nodes/beehave_root.gd @@ -1,4 +1,5 @@ ## Controls the flow of execution of the entire behaviour tree. +@tool class_name BeehaveRoot extends BeehaveTree @icon("../icons/tree.svg") @@ -18,6 +19,9 @@ var actor : Node func _ready() -> void: + if Engine.is_editor_hint(): + return + if self.get_child_count() != 1: push_error("Beehave error: Root %s should have one child (NodePath: %s)" % [self.name, self.get_path()]) disable() @@ -31,6 +35,9 @@ func _ready() -> void: func _physics_process(delta: float) -> void: + if Engine.is_editor_hint(): + return + blackboard.set_value("delta", delta) var status = self.get_child(0).tick(actor, blackboard) @@ -39,6 +46,15 @@ func _physics_process(delta: float) -> void: blackboard.set_value("running_action", running_action) +func _get_configuration_warnings() -> PackedStringArray: + var warnings: PackedStringArray = super._get_configuration_warnings() + + if get_child_count() != 1: + warnings.append("BeehaveRoot should have exactly one child node.") + + return warnings + + func get_running_action() -> ActionLeaf: var node = get_child(0) while node != null: diff --git a/addons/beehave/nodes/beehave_tree.gd b/addons/beehave/nodes/beehave_tree.gd index 3b8e73b1..f68003e4 100644 --- a/addons/beehave/nodes/beehave_tree.gd +++ b/addons/beehave/nodes/beehave_tree.gd @@ -1,4 +1,5 @@ ## Base class for all parts of the behaviour tree. +@tool class_name BeehaveTree extends Node @icon("../icons/icon.svg") @@ -8,3 +9,12 @@ enum { FAILURE, RUNNING } + + +func _get_configuration_warnings() -> PackedStringArray: + var warnings: PackedStringArray = [] + + if get_children().any(func(x): return not (x is BeehaveNode)): + warnings.append("All children of this node should inherit from BeehaveNode class.") + + return warnings diff --git a/addons/beehave/nodes/composites/composite.gd b/addons/beehave/nodes/composites/composite.gd index 147f3582..0d5ab771 100644 --- a/addons/beehave/nodes/composites/composite.gd +++ b/addons/beehave/nodes/composites/composite.gd @@ -1,7 +1,6 @@ ## A Composite node controls the flow of execution of its children in a specific manner. -extends BeehaveNode - -class_name Composite +@tool +class_name Composite extends BeehaveNode @icon("../../icons/category_composite.svg") @@ -9,10 +8,22 @@ var running_child: BeehaveNode = null func _ready(): + if Engine.is_editor_hint(): + return + if self.get_child_count() < 1: push_error("BehaviorTree Error: Composite %s should have at least one child (NodePath: %s)" % [self.name, self.get_path()]) +func _get_configuration_warnings() -> PackedStringArray: + var warnings: PackedStringArray = super._get_configuration_warnings() + + if get_children().filter(func(x): return x is BeehaveNode).size() < 2: + warnings.append("Any composite node should have at least two children. Otherwise it is not useful.") + + return warnings + + func interrupt(actor: Node, blackboard: Blackboard) -> void: if running_child != null: running_child.interrupt(actor, blackboard) diff --git a/addons/beehave/nodes/composites/selector.gd b/addons/beehave/nodes/composites/selector.gd index 504c3680..137571d0 100644 --- a/addons/beehave/nodes/composites/selector.gd +++ b/addons/beehave/nodes/composites/selector.gd @@ -2,9 +2,8 @@ ## them return `SUCCESS`. If all children return `FAILURE`, this node will also ## return `FAILURE`. This node will attempt to process all its children every ## single tick, even if one of them is currently `RUNNING` already. -extends Composite - -class_name SelectorComposite +@tool +class_name SelectorComposite extends Composite @icon("../../icons/selector.svg") func tick(actor: Node, blackboard: Blackboard) -> int: diff --git a/addons/beehave/nodes/composites/selector_star.gd b/addons/beehave/nodes/composites/selector_star.gd index 3915e2aa..6db07d9d 100644 --- a/addons/beehave/nodes/composites/selector_star.gd +++ b/addons/beehave/nodes/composites/selector_star.gd @@ -2,9 +2,8 @@ ## them return `SUCCESS`. If all children return `FAILURE`, this node will also ## return `FAILURE`. This node will skip all previous child nodes that were ## executed prior, in case one of the children is currently in `RUNNING` state. -extends Composite - -class_name SelectorStarComposite +@tool +class_name SelectorStarComposite extends Composite @icon("../../icons/selector_star.svg") var last_execution_index = 0 diff --git a/addons/beehave/nodes/composites/sequence.gd b/addons/beehave/nodes/composites/sequence.gd index 36098c73..2d19a95f 100644 --- a/addons/beehave/nodes/composites/sequence.gd +++ b/addons/beehave/nodes/composites/sequence.gd @@ -3,9 +3,8 @@ ## If at least one child reports a `FAILURE` status code, this node will also ## return `FAILURE`. This node will attempt to process all its children every ## single tick, even if one of them is currently `RUNNING` already. -extends Composite - -class_name SequenceComposite +@tool +class_name SequenceComposite extends Composite @icon("../../icons/sequencer.svg") func tick(actor: Node, blackboard: Blackboard) -> int: diff --git a/addons/beehave/nodes/composites/sequence_star.gd b/addons/beehave/nodes/composites/sequence_star.gd index 34a3d4c6..06dd29a5 100644 --- a/addons/beehave/nodes/composites/sequence_star.gd +++ b/addons/beehave/nodes/composites/sequence_star.gd @@ -3,9 +3,8 @@ ## If at least one child reports a `FAILURE` status code, this node will also ## return `FAILURE`. This node will skip all previous child nodes that succeeded ## prior, in case one of the children is currently in `RUNNING` state -extends Composite - -class_name SequenceStarComposite +@tool +class_name SequenceStarComposite extends Composite @icon("../../icons/sequencer_star.svg") var successful_index = 0 diff --git a/addons/beehave/nodes/decorators/decorator.gd b/addons/beehave/nodes/decorators/decorator.gd index 6ad7fbfe..e2ec4fcd 100644 --- a/addons/beehave/nodes/decorators/decorator.gd +++ b/addons/beehave/nodes/decorators/decorator.gd @@ -1,11 +1,22 @@ ## Decorator nodes are used to transform the result received by its child. ## Must only have one child. -extends BeehaveNode - -class_name Decorator +@tool +class_name Decorator extends BeehaveNode @icon("../../icons/category_decorator.svg") func _ready(): + if Engine.is_editor_hint(): + return + if self.get_child_count() != 1: push_error("Beehave Error: Decorator %s should have only one child (NodePath: %s)" % [self.name, self.get_path()]) + + +func _get_configuration_warnings() -> PackedStringArray: + var warnings: PackedStringArray = super._get_configuration_warnings() + + if get_child_count() != 1: + warnings.append("Decorator should have exactly one child node.") + + return warnings diff --git a/addons/beehave/nodes/decorators/failer.gd b/addons/beehave/nodes/decorators/failer.gd index 4c62624a..0b164563 100644 --- a/addons/beehave/nodes/decorators/failer.gd +++ b/addons/beehave/nodes/decorators/failer.gd @@ -1,7 +1,6 @@ ## A Failer node will always return a `FAILURE` status code. -extends Decorator - -class_name AlwaysFailDecorator +@tool +class_name AlwaysFailDecorator extends Decorator @icon("../../icons/fail.svg") diff --git a/addons/beehave/nodes/decorators/inverter.gd b/addons/beehave/nodes/decorators/inverter.gd index c5aaa8ad..e834011a 100644 --- a/addons/beehave/nodes/decorators/inverter.gd +++ b/addons/beehave/nodes/decorators/inverter.gd @@ -1,8 +1,7 @@ ## An inverter will return `FAILURE` in case it's child returns a `SUCCESS` status ## code or `SUCCESS` in case its child returns a `FAILURE` status code. -extends Decorator - -class_name InverterDecorator +@tool +class_name InverterDecorator extends Decorator @icon("../../icons/inverter.svg") func tick(actor: Node, blackboard: Blackboard) -> int: diff --git a/addons/beehave/nodes/decorators/limiter.gd b/addons/beehave/nodes/decorators/limiter.gd index 093e2bef..deddaf9c 100644 --- a/addons/beehave/nodes/decorators/limiter.gd +++ b/addons/beehave/nodes/decorators/limiter.gd @@ -1,8 +1,7 @@ ## The limiter will execute its child `x` amount of times. When the number of ## maximum ticks is reached, it will return a `FAILURE` status code. -extends Decorator - -class_name LimiterDecorator +@tool +class_name LimiterDecorator extends Decorator @icon("../../icons/limiter.svg") @onready var cache_key = 'limiter_%s' % self.get_instance_id() diff --git a/addons/beehave/nodes/decorators/succeeder.gd b/addons/beehave/nodes/decorators/succeeder.gd index 276f1aff..61d3550b 100644 --- a/addons/beehave/nodes/decorators/succeeder.gd +++ b/addons/beehave/nodes/decorators/succeeder.gd @@ -1,7 +1,6 @@ ## A succeeder node will always return a `SUCCESS` status code. -extends Decorator - -class_name AlwaysSucceedDecorator +@tool +class_name AlwaysSucceedDecorator extends Decorator @icon("../../icons/succeed.svg") diff --git a/addons/beehave/nodes/leaves/action.gd b/addons/beehave/nodes/leaves/action.gd index 49a80655..81f46557 100644 --- a/addons/beehave/nodes/leaves/action.gd +++ b/addons/beehave/nodes/leaves/action.gd @@ -2,7 +2,6 @@ ## Their execution can be long running, potentially being called across multiple ## frame executions. In this case, the node should return `RUNNING` until the ## action is completed. -extends Leaf - -class_name ActionLeaf +@tool +class_name ActionLeaf extends Leaf @icon("../../icons/action.svg") diff --git a/addons/beehave/nodes/leaves/condition.gd b/addons/beehave/nodes/leaves/condition.gd index 8d9798ac..e3bda68c 100644 --- a/addons/beehave/nodes/leaves/condition.gd +++ b/addons/beehave/nodes/leaves/condition.gd @@ -1,6 +1,5 @@ ## Conditions are leaf nodes that either return SUCCESS or FAILURE depending on ## a single simple condition. They should never return `RUNNING`. -extends Leaf - -class_name ConditionLeaf +@tool +class_name ConditionLeaf extends Leaf @icon("../../icons/condition.svg") diff --git a/addons/beehave/nodes/leaves/leaf.gd b/addons/beehave/nodes/leaves/leaf.gd index 7f84f00c..9e885063 100644 --- a/addons/beehave/nodes/leaves/leaf.gd +++ b/addons/beehave/nodes/leaves/leaf.gd @@ -1,5 +1,15 @@ ## Base class for all leaf nodes of the tree. -extends BeehaveNode - -class_name Leaf +@tool +class_name Leaf extends BeehaveNode @icon("../../icons/action.svg") + + +func _get_configuration_warnings() -> PackedStringArray: + var warnings: PackedStringArray = [] + + var children: Array[Node] = get_children() + + if children.any(func(x): return x is BeehaveNode): + warnings.append("Leaf nodes should not have any child nodes. They won't be ticked.") + + return warnings diff --git a/tests/BeehaveTestScene.tscn b/tests/BeehaveTestScene.tscn index f9230ae8..1e5c816f 100644 --- a/tests/BeehaveTestScene.tscn +++ b/tests/BeehaveTestScene.tscn @@ -7,6 +7,7 @@ [node name="BeehaveRoot" type="Node" parent="."] script = ExtResource("1_as4vk") +actor_node_path = NodePath("") [node name="BeehaveNode" type="Node" parent="BeehaveRoot"] script = ExtResource("2_chxav")