Skip to content

Added a few new features for FSMs #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A own print state node is overkill - however this feature should totally be part of a debugging toolset.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved it into examples and removed class_name.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@tool
@icon("res://addons/behaviour_toolkit/icons/BTLeafPrint.svg")
class_name FSMStatePrintOnEnter extends FSMState

@export var custom_text: String


# Executes after the state is entered.
func _on_enter(_actor: Node, _blackboard: Blackboard) -> void:
if custom_text != "":
print(custom_text)
else:
print("Hello World!")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed before, having an always_transition property bool on FSMTransition would be a better idea. This should be checked in the FiniteStateMachine class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sketched this out locally, and ended up implementing a new property (with some dependency juggling with event and use_event) and just replaced is_valid():

## Evaluates true, if the transition conditions are met.
func is_valid(_actor: Node, _blackboard: Blackboard) -> bool:
	if always_transition:
		return true

	return false

This would keep everything else in place, because FiniteStateMachine fundamentally doesn't need to change -- it's just the transition itself that acts differently. Do you seen an advantage to exposing this logic to the FiniteStateMachine class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated this to show what I mean. If you'd like the implementation to change a bit it'll be easier now that it's in Transition.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@tool
@icon("res://addons/behaviour_toolkit/icons/FSMAlwaysTransition.svg")
class_name FSMAlwaysTransition extends FSMTransition
## A transition between two [FSMState]s in a [FiniteStateMachine].
##
## This is a convenience class that always transitions. To implement your
## logic you can override the [code]_on_transition[/code] method when
## extending the node's script.[br]


# Evaluates true, if the transition conditions are met.
func is_valid(_actor: Node, _blackboard: Blackboard) -> bool:
return true


func _get_configuration_warnings() -> PackedStringArray:
var warnings: Array = []

warnings.append_array(super._get_configuration_warnings())

if use_event or event != "":
warnings.append("FSMAlwaysTransition does not use events.")

return warnings
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@tool
@icon("res://addons/behaviour_toolkit/icons/FSMSplitTransition.svg")
class_name FSMSplitTransition extends FSMTransition

## The state to transition to.
@export var next_state_true: FSMState:
set(value):
next_state_true = value
update_configuration_warnings()

@export var next_state_false: FSMState:
set(value):
next_state_false = value
update_configuration_warnings()

# Internal flag that determines which state gets transitioned to
var _transition_flag: bool


# Executed when the transition is taken.
func _on_transition(_delta: float, _actor: Node, _blackboard: Blackboard) -> void:
pass


# Always returns true, because this transition always triggers one way or another.
# Because `get_next_state()` doesn't have access to the actor or blackboard, a flag is
# set internally here which sets up the next transition.
func is_valid(actor: Node, blackboard: Blackboard) -> bool:
set_transition_flag(actor, blackboard)
return true


func set_transition_flag(_actor: Node, _blackboard: Blackboard) -> void:
pass


## Returns which state to transition to, based on internal transition flag set in `set_transition_flag()`.
func get_next_state() -> FSMState:
return next_state_true if _transition_flag else next_state_false


# Add custom configuration warnings
# Note: Can be deleted if you don't want to define your own warnings.
func _get_configuration_warnings() -> PackedStringArray:
var warnings: Array = []

var parent: Node = get_parent()
if not parent is FSMState:
warnings.append("FSMSplitTransition should be a child of FSMState.")

if next_state:
warnings.append("FSMSplitTransition has next state; unset and set true and false states.")

if not next_state_true:
warnings.append("FSMSplitTransition has no next state for true.")

if not next_state_false:
warnings.append("FSMSplitTransition has no next state for false.")

if use_event and event == "":
warnings.append("FSMSplitTransition has no event set.")

return warnings
62 changes: 62 additions & 0 deletions addons/behaviour_toolkit/icons/FSMAlwaysTransition.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions addons/behaviour_toolkit/icons/FSMAlwaysTransition.svg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://do4ajfcbotwd6"
path="res://.godot/imported/FSMAlwaysTransition.svg-d277d25a1a214bba18ffa87b756a2e31.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://addons/behaviour_toolkit/icons/FSMAlwaysTransition.svg"
dest_files=["res://.godot/imported/FSMAlwaysTransition.svg-d277d25a1a214bba18ffa87b756a2e31.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
72 changes: 72 additions & 0 deletions addons/behaviour_toolkit/icons/FSMSplitTransition.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions addons/behaviour_toolkit/icons/FSMSplitTransition.svg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://c4vs4uicrouno"
path="res://.godot/imported/FSMSplitTransition.svg-e6773317add235944b13c8c864f570b3.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://addons/behaviour_toolkit/icons/FSMSplitTransition.svg"
dest_files=["res://.godot/imported/FSMSplitTransition.svg-e6773317add235944b13c8c864f570b3.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false
2 changes: 2 additions & 0 deletions addons/behaviour_toolkit/ui/toolkit_ui.gd
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ func _ready():
%ButtonAddFSM.connect("pressed", _on_button_pressed.bind(FiniteStateMachine, "FiniteStateMachine"))
%ButtonState.connect("pressed", _on_button_pressed.bind(FSMState, "FSMState"))
%ButtonTransition.connect("pressed", _on_button_pressed.bind(FSMTransition, "FSMTransition"))
%ButtonSplitTransition.connect("pressed", _on_button_pressed.bind(FSMSplitTransition, "FSMSplitTransition"))
%ButtonAlwaysTransition.connect("pressed", _on_button_pressed.bind(FSMAlwaysTransition, "FSMAlwaysTransition"))
%ButtonStateIntegratedBT.connect("pressed", _on_button_pressed.bind(FSMStateIntegratedBT, "FSMStateIntegratedBT"))
%ButtonStateIntegrationReturn.connect("pressed", _on_button_pressed.bind(FSMStateIntegrationReturn, "FSMStateIntegrationReturn"))

Expand Down
21 changes: 20 additions & 1 deletion addons/behaviour_toolkit/ui/toolkit_ui.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=39 format=3 uid="uid://o16emp4t4wb1"]
[gd_scene load_steps=41 format=3 uid="uid://o16emp4t4wb1"]

[ext_resource type="Script" path="res://addons/behaviour_toolkit/ui/toolkit_ui.gd" id="1_51rvx"]
[ext_resource type="Texture2D" uid="uid://boof0yioplbqr" path="res://addons/behaviour_toolkit/icons/FSMState.svg" id="1_hqqj5"]
Expand Down Expand Up @@ -26,6 +26,8 @@
[ext_resource type="Texture2D" uid="uid://b45qiy5niriwu" path="res://addons/behaviour_toolkit/icons/BTLeafPrint.svg" id="10_ji4ht"]
[ext_resource type="Texture2D" uid="uid://xi8li3jk2vs6" path="res://addons/behaviour_toolkit/icons/BTLeafWait.svg" id="10_n2nk3"]
[ext_resource type="Texture2D" uid="uid://hn65lqk8tero" path="res://addons/behaviour_toolkit/icons/BTDecoratorRepeat.svg" id="10_nvbp1"]
[ext_resource type="Texture2D" uid="uid://c4vs4uicrouno" path="res://addons/behaviour_toolkit/icons/FSMSplitTransition.svg" id="10_ypexi"]
[ext_resource type="Texture2D" uid="uid://do4ajfcbotwd6" path="res://addons/behaviour_toolkit/icons/FSMAlwaysTransition.svg" id="11_ydeq3"]
[ext_resource type="Texture2D" uid="uid://cwvb6d7kvo53u" path="res://addons/behaviour_toolkit/icons/BTLeafCall.svg" id="12_axgn0"]
[ext_resource type="Texture2D" uid="uid://by4ymq46fp1ra" path="res://addons/behaviour_toolkit/icons/BTLeafCondition.svg" id="13_6h0vl"]
[ext_resource type="Texture2D" uid="uid://ddx7a726xhria" path="res://addons/behaviour_toolkit/icons/BTCompositeIntegration.svg" id="13_gmc6x"]
Expand Down Expand Up @@ -187,6 +189,23 @@ layout_mode = 2
text = "New Transition"
icon = ExtResource("2_24di4")

[node name="Transitions" type="HBoxContainer" parent="ScrollContainer/MarginContainer/VBoxContainer/Panel/ScrollContainer/Toolbox/FiniteStateMachine"]
layout_mode = 2

[node name="ButtonSplitTransition" type="Button" parent="ScrollContainer/MarginContainer/VBoxContainer/Panel/ScrollContainer/Toolbox/FiniteStateMachine/Transitions"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Split"
icon = ExtResource("10_ypexi")

[node name="ButtonAlwaysTransition" type="Button" parent="ScrollContainer/MarginContainer/VBoxContainer/Panel/ScrollContainer/Toolbox/FiniteStateMachine/Transitions"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Always"
icon = ExtResource("11_ydeq3")

[node name="BehaviourTree" type="VBoxContainer" parent="ScrollContainer/MarginContainer/VBoxContainer/Panel/ScrollContainer/Toolbox"]
unique_name_in_owner = true
layout_mode = 2
Expand Down
Loading