Skip to content

πŸ”§ Extending FlowKit

CG-Tespy edited this page Feb 9, 2026 · 6 revisions

πŸ”§ Creating Custom Providers

FlowKit's provider system makes it easy to extend functionality. Providers are automatically discovered through the registry system.

πŸ—‚οΈ File Locations

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

βš™οΈ Creating a Custom Action

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)

πŸ”€ Creating a Custom Condition

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 true

⚑ Creating a Custom Event

extends 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

πŸ“ Advanced providers

These are advanced providers that require more complex logic and have additional methods to implement.

▢️ Creating a Custom Behavior

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

Clone this wiki locally