-
-
Notifications
You must be signed in to change notification settings - Fork 16
π§ Extending FlowKit
CG-Tespy edited this page Feb 9, 2026
·
6 revisions
FlowKit's provider system makes it easy to extend functionality. Providers are automatically discovered through the registry system.
You need to make sure that your custom actions, conditions, and events are in the right places on disk. Otherwise, the registry system won't detect them.
- Actions: addons/flowkit/actions
- Conditions: addons/flowkit/conditions
- Events: addons/flowkit/events
- Behaviors: addons/flowkit/behaviors
extends FKAction
func get_id() -> String:
return "my_custom_action"
func get_name() -> String:
return "My Custom Action" # In other words, the display name. This is what shows up in the Actions list after you pick a Node to target.
func get_supported_types() -> Array:
return ["Node2D"]
func get_inputs() -> Array:
return [
{"name": "amount", "type": "float", "description": Insert desc here"},
{"name": "message", "type": "String", "description": Insert desc here"}
]
func execute(targetNode: Node, inputs: Dictionary) -> void:
var amount = inputs.get("amount", 0.0)
var message = inputs.get("message", "")
print(message, " - ", amount)extends FKCondition
func get_id() -> String:
return "my_custom_condition"
func get_name() -> String:
return "My Custom Condition"
func get_supported_types() -> Array:
return ["Node"]
func get_inputs() -> Array:
return [{"name": "threshold", "type": "float"}]
func check(node: Node, inputs: Dictionary) -> bool:
var threshold = inputs.get("threshold", 0.0)
return trueextends FKEvent
func get_description() -> String:
return "Insert desc here"
func get_id() -> String:
return "on_custom_event"
func get_name() -> String:
return "On Custom Event"
## Totally optional. Feel free to avoid overriding this func if you don't want your Event
## to take any inputs.
func get_inputs() -> Array:
return [{"name": "eventInput", "type": "float"}]
func get_supported_types() -> Array:
return ["Node"]
## This runs every frame. When it returns true, the Actions tied to this event run.
func poll(node: Node) -> bool:
return false
## Would you rather execute the Action list in response to a signal without having to
## check every frame? Override the func below to return true. That makes it so poll() is
## skipped, and your code gets the option to execute the Action list manually.
## As for how to do that execution...
func is_signal_event() -> bool:
return false
## First, you override the setup method below. In runtime, it gets called once the engine loads
## the Event Sheet containing this Event instance. Use this to connect to Godot signals on the
## target node. Using trigger_callback.call() fires this event's Actions immediately. Note that
## the default implementation does nothing.
func setup(targetNode: Node, trigger_callback: Callable, instance_id: String = "") -> void:
# Insert signal-connection code here
exec_actions = trigger_callback ## <- You don't have to do this, but storing the
# list-executor this way lets you access it outside the scope of this func.
var exec_actions: Callable
func hypothetical_signal_response() -> void:
exec_actions.call() # Fires the Actions
## Called when the engine unloads an event sheet (e.g. on scene change).
## Use this to disconnect signals or clean up any state created in setup().
## The default implementation does nothing.
func teardown(targetNode: Node, instance_id: String = "") -> void:
# Insert signal-DISconnection code here
exec_actions = Callable() ## <- One way you can let go of the reference to the list-executor
pass
These are advanced providers that require more complex logic and have additional methods to implement.
Behaviors are configurable scripts that can be edited within the Godot editor, here is the template for a behavior
extends Resource
func get_description() -> String: # <-- Description of the behavior
return "A simple behavior."
func get_id() -> String: # <-- Id of the behavior
return "my_behavior"
func get_name() -> String: # <-- Name of the behavior
return "My Behavior"
func get_inputs() -> Array[Dictionary]: # <-- Define inputs to appear in the inspector.
## Returns an array of input definitions
## Each dictionary should have:
## - "name": String - the input parameter name
## - "type": String - the type of the input (e.g., "String", "float", "int")
## - "default": Variant - the default value for this input
return []
func get_supported_types() -> Array[String]: # <-- Define supported nodes.
## Returns an array of node class names this behavior supports
## e.g., ["CharacterBody2D"] or ["Node2D", "Node3D"]
return []
func apply(node: Node, inputs: Dictionary) -> void:
## Called to apply/activate this behavior on a node
## This is where the behavior logic should be implemented
pass
func remove(node: Node) -> void:
## Called to remove/deactivate this behavior from a node
pass
func process(node: Node, delta: float, inputs: Dictionary) -> void:
## Called every frame while the behavior is active on a node
## Override this for behaviors that need per-frame updates
pass
func physics_process(node: Node, delta: float, inputs: Dictionary) -> void:
## Called every physics frame while the behavior is active on a node
## Override this for behaviors that need physics-based updates
pass