Visualization now works

main
Yan Wittmann 2024-12-13 18:56:39 +01:00
parent 655e00fb2e
commit e74ec6f3ec
8 changed files with 170 additions and 110 deletions

View File

@ -127,37 +127,6 @@
} }
} }
] ]
},
{
"target": "Idle",
"conditions": [
{
"type": ">=",
"left": {
"value": 10
},
"right": {
"function": "distance",
"args": [
{
"accessor": [
"character",
"position"
]
},
{
"accessor": [
"root_nodes",
"StateMachineWorld",
"child_nodes",
"TrashBin",
"position"
]
}
]
}
}
]
} }
] ]
} }

View File

@ -23,6 +23,6 @@ window/stretch/mode="viewport"
spawn_trash={ spawn_trash={
"deadzone": 0.5, "deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":2,"canceled":false,"pressed":false,"double_click":false,"script":null)
] ]
} }

View File

@ -82,7 +82,7 @@ func check_transitions() -> void:
var condition_met: bool = transition_check_condition(condition) var condition_met: bool = transition_check_condition(condition)
if not condition_met: if not condition_met:
all_conditions_met = false all_conditions_met = false
%StateMachineInfoPanel.values["condition failed for " + transition["target"]] = condition %StateMachineInfoPanel.values["condition failed for " + transition["target"]] = human_readable_condition(condition)
break break
if not all_conditions_met: if not all_conditions_met:
continue continue
@ -151,6 +151,7 @@ func transition_resolve_function(function: Dictionary) -> Variant:
if function["function"] == "distance": if function["function"] == "distance":
var result = args[0].distance_to(args[1]) var result = args[0].distance_to(args[1])
%StateMachineInfoPanel.values["distance()"] = result
# print("[resolve_function] distance(", args[0], ", ", args[1], ") = ", result) # print("[resolve_function] distance(", args[0], ", ", args[1], ") = ", result)
return result return result
else: else:
@ -262,3 +263,67 @@ func objects_equal(a: Variant, b: Variant) -> bool:
if typeof(a) != typeof(b): if typeof(a) != typeof(b):
return false return false
return a == b return a == b
func human_readable_transition(condition: Dictionary) -> String:
var parts: Array[Variant] = []
if condition.has("signal"):
parts.append(condition["signal"])
if condition.has("conditions"):
parts.append(human_readable_condition(condition))
return " & ".join(parts)
func human_readable_condition(condition: Dictionary) -> String:
if condition.has("conditions"):
var parts: Array[Variant] = []
for cond in condition["conditions"]:
parts.append(human_readable_condition(cond))
return " & ".join(parts)
if condition.has("left") and condition.has("right") and condition.has("type"):
var left: Variant = condition["left"]
var right: Variant = condition["right"]
var type: String = condition["type"]
return human_readable_parameter(left) + " " + type + " " + human_readable_parameter(right)
return "Unknown condition"
func human_readable_parameter(parameter: Dictionary) -> String:
if "value" in parameter:
return str(parameter["value"])
elif "function" in parameter:
return human_readable_function(parameter)
elif "accessor" in parameter:
return human_readable_accessor(parameter["accessor"])
else:
return "Unknown parameter type"
func human_readable_function(function: Dictionary) -> String:
var args: Array = []
if "args" in function:
for arg in function["args"]:
if arg is Dictionary:
args.append(human_readable_parameter(arg))
else:
args.append(str(arg))
if function["function"] == "distance":
return "distance(" + ", ".join(args) + ")"
else:
return "Unknown function"
func human_readable_accessor(accessor: Array) -> String:
var parts: Array[Variant] = []
var ignore_parts: Array[Variant] = ["signals", "child_nodes", "root_nodes"]
for part in accessor:
if not part in ignore_parts:
parts.append(str(part))
return ".".join(parts)

View File

@ -3,8 +3,8 @@
[ext_resource type="Script" path="res://scenes/state/visualization/tree_visualizer.gd" id="1_62kxn"] [ext_resource type="Script" path="res://scenes/state/visualization/tree_visualizer.gd" id="1_62kxn"]
[node name="TreeVisualizer" type="Window"] [node name="TreeVisualizer" type="Window"]
position = Vector2i(50, 36) position = Vector2i(20, 331)
size = Vector2i(1055, 560) size = Vector2i(1115, 300)
script = ExtResource("1_62kxn") script = ExtResource("1_62kxn")
[node name="GraphEdit" type="GraphEdit" parent="."] [node name="GraphEdit" type="GraphEdit" parent="."]
@ -16,6 +16,7 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
scroll_offset = Vector2(-35, -30)
show_menu = false show_menu = false
show_zoom_buttons = false show_zoom_buttons = false
show_grid_buttons = false show_grid_buttons = false

View File

@ -3,10 +3,13 @@ extends GraphNode
var left_slots: Array[String] = [] var left_slots: Array[String] = []
var right_slots: Array[String] = [] var right_slots: Array[String] = []
var color_highlighted: StyleBoxFlat = StyleBoxFlat.new()
var color_normal: StyleBoxFlat = StyleBoxFlat.new()
func _ready() -> void: func _ready() -> void:
pass color_highlighted.bg_color = Color(0.67058825, 1.0, 0.5411765)
color_normal.bg_color = Color(1.0, 1.0, 1.0)
func add_label(label_text: String, left: bool, right: bool) -> Vector3i: func add_label(label_text: String, left: bool, right: bool) -> Vector3i:
@ -28,3 +31,11 @@ func add_label(label_text: String, left: bool, right: bool) -> Vector3i:
# the port index is counted separately from the left and right slots. # the port index is counted separately from the left and right slots.
return Vector3i(child_index, left_slots.size() - 1, right_slots.size() - 1) return Vector3i(child_index, left_slots.size() - 1, right_slots.size() - 1)
func set_highlighted(highlight: bool) -> void:
# set the background color of the node
if highlight:
self.add_theme_stylebox_override("panel", color_highlighted)
else:
self.add_theme_stylebox_override("panel", color_normal)

View File

@ -14,7 +14,5 @@ offset_bottom = 184.0
mouse_filter = 1 mouse_filter = 1
theme_override_styles/panel = SubResource("StyleBoxFlat_k54lu") theme_override_styles/panel = SubResource("StyleBoxFlat_k54lu")
theme_override_styles/titlebar = SubResource("StyleBoxFlat_dmqj2") theme_override_styles/titlebar = SubResource("StyleBoxFlat_dmqj2")
draggable = false
selectable = false
title = "TITEL" title = "TITEL"
script = ExtResource("1_o2ffa") script = ExtResource("1_o2ffa")

View File

@ -5,6 +5,7 @@ var values: Dictionary = {}
var last_values: Dictionary = {} var last_values: Dictionary = {}
var value_order: Array = [] # Keep track of the order of values var value_order: Array = [] # Keep track of the order of values
func to_str(value) -> String: func to_str(value) -> String:
if value is float: if value is float:
return str(round(value * 100) / 100) return str(round(value * 100) / 100)
@ -16,6 +17,7 @@ func to_str(value) -> String:
return "(" + to_str(value.x) + ", " + to_str(value.y) + ", " + to_str(value.z) + ", " + to_str(value.w) + ")" return "(" + to_str(value.x) + ", " + to_str(value.y) + ", " + to_str(value.z) + ", " + to_str(value.w) + ")"
return str(value) return str(value)
func _process(delta: float) -> void: func _process(delta: float) -> void:
for child in self.get_children(): for child in self.get_children():
if child is Label: if child is Label:

View File

@ -10,8 +10,21 @@ var all_nodes: Array[DTreeNode] = []
var all_node_names_to_nodes: Dictionary = {} var all_node_names_to_nodes: Dictionary = {}
func _ready(): func _process(delta: float) -> void:
pass if Input.is_action_just_pressed("ui_accept"):
if is_visible():
hide()
else:
show()
# highlight the current state
for node in all_nodes:
node.set_highlighted(false)
if state_machine and state_machine.current_state:
var current_state_name: StringName = state_machine.current_state.get_name()
if all_node_names_to_nodes.has(current_state_name):
all_node_names_to_nodes[current_state_name].set_highlighted(true)
func build_tree(): func build_tree():
@ -20,8 +33,8 @@ func build_tree():
return return
var node_positions: Array[DTreeNode] = [] var node_positions: Array[DTreeNode] = []
var y_spacing: int = 400 var y_spacing: int = 300
var x_spacing: int = 400 var x_spacing: int = 600
var depths: Dictionary = calculate_node_depths() var depths: Dictionary = calculate_node_depths()
var states = state_machine.state_machine_data["states"] var states = state_machine.state_machine_data["states"]
@ -68,7 +81,7 @@ func populate_node_labels(node: DTreeNode, state_name: String, state_data: Dicti
var output_transitions: Array = state_data.get("transitions", []) var output_transitions: Array = state_data.get("transitions", [])
for transition in output_transitions: for transition in output_transitions:
var target_state_name: String = transition['target'] var target_state_name: String = transition['target']
var port_out: Vector3i = node.add_label("%s" % [target_state_name], false, true) var port_out: Vector3i = node.add_label(state_machine.human_readable_transition(transition), false, true)
var target_node: DTreeNode = node_names_to_nodes[target_state_name] var target_node: DTreeNode = node_names_to_nodes[target_state_name]
if target_node: if target_node:
@ -105,3 +118,4 @@ func get_nodes_at_depth(depth: int, depths: Dictionary) -> Array:
if depths[i] == depth: if depths[i] == depth:
nodes_at_depth.append(i) nodes_at_depth.append(i)
return nodes_at_depth return nodes_at_depth