WIP: BlendTree editor.
This commit is contained in:
parent
fd13c53e52
commit
d3fe4afc57
@ -1,16 +1,222 @@
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
@onready var blend_tree_graph_edit: GraphEdit = %BlendTreeGraphEdit
|
||||
@onready var file_name_line_edit: LineEdit = %FileNameLineEdit
|
||||
@onready var tree_option_button: OptionButton = %TreeOptionButton
|
||||
@onready var add_node_popup_menu: PopupMenu = %AddNodePopupMenu
|
||||
|
||||
var blend_tree:BLTAnimationNodeBlendTree = BLTAnimationNodeBlendTree.new()
|
||||
var blend_tree_node_to_graph_node = {}
|
||||
var graph_node_to_blend_tree_node = {}
|
||||
var selected_nodes = {}
|
||||
var new_node_position = Vector2.INF
|
||||
|
||||
var registered_nodes = [
|
||||
"BLTAnimationNodeSampler",
|
||||
"BLTAnimationNodeBlend2",
|
||||
"BLTAnimationNodeBlendTree",
|
||||
]
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
for node_name in registered_nodes:
|
||||
add_node_popup_menu.add_item(node_name)
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
func create_node_for_blt_node(blt_node: BLTAnimationNode) -> GraphNode:
|
||||
var result_graph_node:GraphNode = GraphNode.new()
|
||||
result_graph_node.name = blt_node.resource_name
|
||||
result_graph_node.title = blt_node.resource_name
|
||||
result_graph_node.position_offset = blt_node.position
|
||||
|
||||
func _on_hit_me_button_pressed() -> void:
|
||||
print("Hello from the main screen plugin!")
|
||||
var result_slot_offset = 0
|
||||
|
||||
if (blt_node.get_class() != "BLTAnimationNodeOutput"):
|
||||
result_slot_offset = 1
|
||||
var output_slot_label:Label = Label.new()
|
||||
output_slot_label.text = "Result"
|
||||
result_graph_node.add_child(output_slot_label)
|
||||
result_graph_node.set_slot(0, false, 1, Color.WHITE, true, 1, Color.WHITE)
|
||||
|
||||
var inputs = blt_node.get_input_names()
|
||||
for i in range(len(inputs)):
|
||||
var slot_label:Label = Label.new()
|
||||
slot_label.text = inputs[i]
|
||||
result_graph_node.add_child(slot_label)
|
||||
result_graph_node.set_slot(i + result_slot_offset, true, 1, Color.WHITE, false, 1, Color.BLACK)
|
||||
|
||||
return result_graph_node
|
||||
|
||||
|
||||
func _on_add_node_button_pressed() -> void:
|
||||
blend_tree_graph_edit.add_child(create_node_for_blt_node(BLTAnimationNodeOutput.new()))
|
||||
blend_tree_graph_edit.add_child(create_node_for_blt_node(BLTAnimationNodeBlend2.new()))
|
||||
|
||||
|
||||
func _on_reset_graph_button_pressed() -> void:
|
||||
_reset_editor()
|
||||
_update_editor_from_blend_tree()
|
||||
|
||||
|
||||
func _reset_editor():
|
||||
for child in blend_tree_graph_edit.get_children():
|
||||
if child.name == "_connection_layer":
|
||||
continue
|
||||
|
||||
child.get_parent().remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
blend_tree_graph_edit.clear_connections()
|
||||
|
||||
blend_tree = BLTAnimationNodeBlendTree.new()
|
||||
blend_tree_node_to_graph_node = {}
|
||||
graph_node_to_blend_tree_node = {}
|
||||
selected_nodes = {}
|
||||
|
||||
|
||||
func _update_editor_nodes_from_blend_tree():
|
||||
for node_name in blend_tree.get_node_names():
|
||||
var blend_tree_node:BLTAnimationNode = blend_tree.get_node(node_name)
|
||||
var graph_node:GraphNode = create_node_for_blt_node(blend_tree_node)
|
||||
blend_tree_graph_edit.add_child(graph_node)
|
||||
|
||||
blend_tree_node_to_graph_node[blend_tree_node] = graph_node
|
||||
graph_node_to_blend_tree_node[graph_node] = blend_tree_node
|
||||
|
||||
|
||||
func _update_editor_connections_from_blend_tree():
|
||||
var connection_array = blend_tree.get_connections()
|
||||
|
||||
for i in range(len(connection_array) / 3):
|
||||
var source_node:BLTAnimationNode = connection_array[i * 3]
|
||||
var target_node:BLTAnimationNode = connection_array[i * 3 + 1]
|
||||
var target_port = connection_array[i * 3 + 2]
|
||||
|
||||
var source_graph_node = blend_tree_node_to_graph_node[source_node]
|
||||
|
||||
var connect_result = blend_tree_graph_edit.connect_node(source_node.resource_name, 0, target_node.resource_name, target_node.get_input_index(target_port), true)
|
||||
|
||||
|
||||
func _update_editor_from_blend_tree():
|
||||
_update_editor_nodes_from_blend_tree()
|
||||
_update_editor_connections_from_blend_tree()
|
||||
|
||||
|
||||
func _on_save_button_pressed() -> void:
|
||||
ResourceSaver.save(blend_tree, "res://" + file_name_line_edit.text)
|
||||
|
||||
|
||||
func _on_load_button_pressed() -> void:
|
||||
var loaded_blend_tree:BLTAnimationNodeBlendTree = ResourceLoader.load("res://" + file_name_line_edit.text, "BLTAnimationNodeBlendTree", 0)
|
||||
|
||||
if loaded_blend_tree:
|
||||
_reset_editor()
|
||||
blend_tree = loaded_blend_tree
|
||||
_update_editor_from_blend_tree()
|
||||
|
||||
|
||||
func _on_instantiate_tree_button_pressed() -> void:
|
||||
var graph_name = tree_option_button.get_item_text(tree_option_button.selected)
|
||||
|
||||
if graph_name == "AnimationSampler":
|
||||
_reset_editor()
|
||||
|
||||
var sampler_node:BLTAnimationNodeSampler = BLTAnimationNodeSampler.new()
|
||||
sampler_node.animation = "SampleLibrary/Idle"
|
||||
|
||||
blend_tree.add_node(sampler_node)
|
||||
blend_tree.add_connection(sampler_node, blend_tree.get_output_node(), "Output")
|
||||
|
||||
_update_editor_from_blend_tree()
|
||||
elif graph_name == "Blend2":
|
||||
_reset_editor()
|
||||
|
||||
var sampler_node_walk:BLTAnimationNodeSampler = BLTAnimationNodeSampler.new()
|
||||
sampler_node_walk.animation = "SampleLibrary/Walk"
|
||||
|
||||
var sampler_node_run:BLTAnimationNodeSampler = BLTAnimationNodeSampler.new()
|
||||
sampler_node_run.animation = "SampleLibrary/Run"
|
||||
|
||||
var blend2_node:BLTAnimationNodeBlend2 = BLTAnimationNodeBlend2.new()
|
||||
|
||||
blend_tree.add_node(sampler_node_walk)
|
||||
blend_tree.add_node(sampler_node_run)
|
||||
blend_tree.add_node(blend2_node)
|
||||
|
||||
blend_tree.add_connection(blend2_node, blend_tree.get_output_node(), "Output")
|
||||
|
||||
blend_tree.add_connection(sampler_node_walk, blend2_node, "Input0")
|
||||
blend_tree.add_connection(sampler_node_run, blend2_node, "Input1")
|
||||
|
||||
_update_editor_from_blend_tree()
|
||||
|
||||
|
||||
func _on_blend_tree_graph_edit_connection_request(from_node: StringName, from_port: int, to_node: StringName, to_port: int) -> void:
|
||||
print("Trying to connect '%s' port %d to node '%s' port %d" % [from_node, from_port, to_node, to_port])
|
||||
|
||||
var source_node:BLTAnimationNode = blend_tree.get_node(from_node)
|
||||
var target_node:BLTAnimationNode = blend_tree.get_node(to_node)
|
||||
|
||||
if target_node == null:
|
||||
push_error("Invalid connection, target node %s not found." % to_node)
|
||||
return
|
||||
|
||||
var target_node_port_name = target_node.get_input_names()[to_port]
|
||||
|
||||
var connection_result = blend_tree.is_connection_valid(source_node, target_node, target_node_port_name)
|
||||
if connection_result != blend_tree.CONNECTION_OK:
|
||||
push_error("Could not add connection (error %d)" % connection_result)
|
||||
return
|
||||
|
||||
blend_tree.add_connection(source_node, target_node, target_node_port_name)
|
||||
|
||||
var connect_result = blend_tree_graph_edit.connect_node(from_node, from_port, to_node, to_port, true)
|
||||
print("graph connect result: " + str(connect_result))
|
||||
|
||||
print("Success!")
|
||||
|
||||
|
||||
func _on_blend_tree_graph_edit_end_node_move() -> void:
|
||||
for graph_node:GraphNode in selected_nodes.keys():
|
||||
graph_node_to_blend_tree_node[graph_node].position = graph_node.position
|
||||
|
||||
|
||||
func _on_blend_tree_graph_edit_begin_node_move() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
func _on_blend_tree_graph_edit_node_selected(node: Node) -> void:
|
||||
selected_nodes[node] = node
|
||||
|
||||
|
||||
func _on_blend_tree_graph_edit_node_deselected(node: Node) -> void:
|
||||
if selected_nodes.has(node):
|
||||
selected_nodes.erase(node)
|
||||
|
||||
|
||||
func _on_blend_tree_graph_edit_popup_request(at_position: Vector2) -> void:
|
||||
add_node_popup_menu.position = get_screen_position() + get_local_mouse_position()
|
||||
add_node_popup_menu.reset_size()
|
||||
add_node_popup_menu.popup()
|
||||
new_node_position = at_position
|
||||
|
||||
|
||||
func _on_add_node_popup_menu_index_pressed(index: int) -> void:
|
||||
var new_blend_tree_node: BLTAnimationNode = ClassDB.instantiate(registered_nodes[index])
|
||||
blend_tree.add_node(new_blend_tree_node)
|
||||
var graph_node:GraphNode = create_node_for_blt_node(new_blend_tree_node)
|
||||
|
||||
graph_node_to_blend_tree_node[graph_node] = new_blend_tree_node
|
||||
blend_tree_node_to_graph_node[new_blend_tree_node] = graph_node
|
||||
|
||||
blend_tree_graph_edit.add_child(graph_node)
|
||||
|
||||
if new_node_position != Vector2.INF:
|
||||
graph_node.position_offset = new_node_position
|
||||
|
||||
new_node_position = Vector2.INF
|
||||
|
||||
@ -13,7 +13,7 @@ size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource("1_427jg")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=2044593527]
|
||||
[node name="BlendTreeEditorContainer" type="VBoxContainer" parent="." unique_id=2044593527]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
@ -21,13 +21,78 @@ anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="HitMeButton" type="Button" parent="VBoxContainer" unique_id=1060776498]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="BlendTreeEditorContainer" unique_id=1742071203]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ResetGraphButton" type="Button" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=1060776498]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Hit me!"
|
||||
text = "Reset"
|
||||
|
||||
[node name="GraphFrame" type="GraphFrame" parent="VBoxContainer" unique_id=184673233]
|
||||
[node name="FileNameLineEdit" type="LineEdit" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=2033619565]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(250, 0)
|
||||
layout_mode = 2
|
||||
text = "editor_test_tree.tres"
|
||||
|
||||
[node name="SaveButton" type="Button" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=597228263]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Save
|
||||
"
|
||||
|
||||
[node name="LoadButton" type="Button" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=559146765]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Load
|
||||
"
|
||||
|
||||
[node name="AddNodeButton" type="Button" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=985452697]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Add Node"
|
||||
|
||||
[node name="TreeOptionButton" type="OptionButton" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=760974122]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
selected = 0
|
||||
item_count = 2
|
||||
popup/item_0/text = "AnimationSampler"
|
||||
popup/item_0/id = 1
|
||||
popup/item_1/text = "Blend2"
|
||||
popup/item_1/id = 2
|
||||
|
||||
[node name="InstantiateTreeButton" type="Button" parent="BlendTreeEditorContainer/HBoxContainer" unique_id=127759440]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Instantiate"
|
||||
|
||||
[node name="Panel" type="Panel" parent="BlendTreeEditorContainer" unique_id=424652158]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[connection signal="pressed" from="VBoxContainer/HitMeButton" to="." method="_on_hit_me_button_pressed"]
|
||||
[node name="AddNodePopupMenu" type="PopupMenu" parent="BlendTreeEditorContainer/Panel" unique_id=2020489213]
|
||||
unique_name_in_owner = true
|
||||
oversampling_override = 1.0
|
||||
|
||||
[node name="BlendTreeGraphEdit" type="GraphEdit" parent="BlendTreeEditorContainer/Panel" unique_id=387715755]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[connection signal="pressed" from="BlendTreeEditorContainer/HBoxContainer/ResetGraphButton" to="." method="_on_reset_graph_button_pressed"]
|
||||
[connection signal="pressed" from="BlendTreeEditorContainer/HBoxContainer/SaveButton" to="." method="_on_save_button_pressed"]
|
||||
[connection signal="pressed" from="BlendTreeEditorContainer/HBoxContainer/LoadButton" to="." method="_on_load_button_pressed"]
|
||||
[connection signal="pressed" from="BlendTreeEditorContainer/HBoxContainer/AddNodeButton" to="." method="_on_add_node_button_pressed"]
|
||||
[connection signal="pressed" from="BlendTreeEditorContainer/HBoxContainer/InstantiateTreeButton" to="." method="_on_instantiate_tree_button_pressed"]
|
||||
[connection signal="index_pressed" from="BlendTreeEditorContainer/Panel/AddNodePopupMenu" to="." method="_on_add_node_popup_menu_index_pressed"]
|
||||
[connection signal="begin_node_move" from="BlendTreeEditorContainer/Panel/BlendTreeGraphEdit" to="." method="_on_blend_tree_graph_edit_begin_node_move"]
|
||||
[connection signal="connection_request" from="BlendTreeEditorContainer/Panel/BlendTreeGraphEdit" to="." method="_on_blend_tree_graph_edit_connection_request"]
|
||||
[connection signal="end_node_move" from="BlendTreeEditorContainer/Panel/BlendTreeGraphEdit" to="." method="_on_blend_tree_graph_edit_end_node_move"]
|
||||
[connection signal="node_deselected" from="BlendTreeEditorContainer/Panel/BlendTreeGraphEdit" to="." method="_on_blend_tree_graph_edit_node_deselected"]
|
||||
[connection signal="node_selected" from="BlendTreeEditorContainer/Panel/BlendTreeGraphEdit" to="." method="_on_blend_tree_graph_edit_node_selected"]
|
||||
[connection signal="popup_request" from="BlendTreeEditorContainer/Panel/BlendTreeGraphEdit" to="." method="_on_blend_tree_graph_edit_popup_request"]
|
||||
|
||||
@ -43,3 +43,7 @@ func _get_plugin_name():
|
||||
|
||||
func _get_plugin_icon():
|
||||
return EditorInterface.get_editor_theme().get_icon("Node", "EditorIcons")
|
||||
|
||||
|
||||
func _handles(obj: Object) -> bool:
|
||||
return obj is BLTAnimationNodeBlendTree
|
||||
|
||||
@ -23,3 +23,7 @@ window/size/viewport_height=1024
|
||||
[dotnet]
|
||||
|
||||
project/assembly_name="Synced Blend Tree Test"
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
enabled=PackedStringArray("res://addons/blendalot/plugin.cfg")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user