Animation Tree style expressions

Godot Version

4.4

Question

I am trying to create an Expression that can be used similar to the AnimationNodeStateMachineTransaction expressions. I have the source node set as a NodePath but I am having trouble on figuring out how to get all its properties pushed into the expression execute without having define each one individually.

The goal of this is to get up a system where the code is only triggered when some condition is true while the object is active. In this case it is for my trigger system which would have optional guards preventing it from activating until the property it is monitoring is the correct value.

func is_guard_satisfied(target_node: NodePath, guard_expression: String) -> bool:
	var target = get_node(target_node)
	
	var expression = Expression.new()
	var error = expression.parse(guard_expression)
	if error != OK:
		push_error(expression.get_error_text())
		return false
	
	var result = expression.execute(target.get_property_list(), target)

	if typeof(result) != TYPE_BOOL:
		push_error("Expression: ", guard_expression ," result: ", result,  " is not a boolean. Returning false.")
		return false

	return result

There’s no need to pass the base_instance properties as inputs, The Expression is able to access them automatically when calling execute()

extends Node

func _ready():
	var n = Node2D.new()
	n.position = Vector2(100, 500)
	var ex = Expression.new()
	# Only passing "my_int" as an input.
	# No need to pass "position" as it will use the "base_instance" object as a fallback to resolve it.
	var status = ex.parse("int(position.x + my_int) % 2 == 0", ["my_int"])
	if status != OK:
		print(ex.get_error_text())
	else:
		for i in 4:
			# Only passing the value to "my_int"
			var result = ex.execute([i + 999], n)
			if ex.has_execute_failed():
				print("Failed to execute " + ex.get_error_text())
			else:
				prints(i, result)

Thank you for the reply. The main issue was that I wanted to have a class that could execute a comparison against any node via the expression text box. The same way that you assign an advance expression base node in the AnimationTree node.

I did end up figuring it out late last night. I’ll post my code here for anyone that is curious.

func _process_trigger() -> void:
	for trigger in triggers:
		if _is_guard_satisfied(trigger.guard_target_node, trigger.guard_expression):
			if trigger is TriggerFunctionEvent:
				_function_event(trigger)
			else:
				trigger.execute()

func _is_guard_satisfied(target_node: NodePath, guard_expression: String) -> bool:
	if !target_node or guard_expression == "":
		return true
		
	var target = get_node(target_node)
	
	var expression = Expression.new()
	var error = expression.parse(guard_expression)
	if error != OK:
		push_error(expression.get_error_text())
		return false
	
	var result = expression.execute([], target)

	if typeof(result) != TYPE_BOOL:
		push_error("Expression: ", guard_expression ," result: ", result,  " is not a boolean. Returning false.")
		return false

	return result

This allows me to use a NodePath to target a specific node in the scene and then do simple expression such as “!enabled” as in the image below.