Skip to content

Commit 711a5d8

Browse files
authored
Merge pull request #3 from ThePat02/feature-editor-ui
Add new editor UI for creating FDG Nodes
2 parents 5e03baf + cf2e1ad commit 711a5d8

File tree

4 files changed

+136
-0
lines changed

4 files changed

+136
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ is a simple implementation of a [Force-Directed Graph](https://en.wikipedia.org/
44
#### Features
55
- 2D implementation of a Force-Directed Graph
66
- Flexible and easy to use Graph Nodes that can be extended and customized
7+
- Editor UI for adding new nodes to your graph
78
- Real-time graph simulation in the editor (optional)
89

910
#### Supported Versions

addons/force_directed_graph/plugin.gd

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
extends EditorPlugin
33

44

5+
var _graph_ui = preload("res://addons/force_directed_graph/ui/graph_ui.tscn")
6+
7+
58
# Icons
69
const icon_force_directed_graph = preload("res://addons/force_directed_graph/icons/ForceDirectedGraph.svg")
710
const icon_fdg_node = preload("res://addons/force_directed_graph/icons/FDGNode.svg")
@@ -19,9 +22,40 @@ func _enter_tree():
1922
add_custom_type("FDGNode", "Node2D", fdg_node, icon_fdg_node)
2023
add_custom_type("FDGSpring", "Node2D", fdg_spring, icon_fdg_spring)
2124

25+
# Add UI
26+
_graph_ui = _graph_ui.instantiate()
27+
add_control_to_container(EditorPlugin.CONTAINER_CANVAS_EDITOR_SIDE_LEFT, _graph_ui)
28+
_graph_ui.visible = false
29+
30+
# Connect editor signals
31+
get_editor_interface().get_selection().selection_changed.connect(_on_selection_changed)
32+
2233

2334
func _exit_tree():
2435
# Remove custom types
2536
remove_custom_type("ForceDirectedGraph")
2637
remove_custom_type("FDGNode")
2738
remove_custom_type("FDGSpring")
39+
40+
# Remove UI
41+
remove_control_from_container(EditorPlugin.CONTAINER_CANVAS_EDITOR_SIDE_LEFT, _graph_ui)
42+
43+
44+
func _on_selection_changed() -> void:
45+
46+
# Get current selection
47+
var selection = get_editor_interface().get_selection().get_selected_nodes()
48+
49+
if selection.size() == 0:
50+
_graph_ui.visible = false
51+
return
52+
53+
54+
_graph_ui.set_current_selection(selection[0])
55+
56+
for node in selection:
57+
if node is ForceDirectedGraph or node is FDGNode or node is FDGSpring:
58+
_graph_ui.visible = true
59+
return
60+
61+
_graph_ui.visible = false
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@tool
2+
extends MarginContainer
3+
4+
5+
var current_selection
6+
7+
8+
func _ready():
9+
# Connect buttons
10+
%ButtonGraph.connect("pressed", _on_button_pressed.bind(ForceDirectedGraph, "ForceDirectedGraph"))
11+
%ButtonNode.connect("pressed", _on_button_pressed.bind(FDGNode, "FDGNode"))
12+
%ButtonSpring.connect("pressed", _on_button_pressed.bind(FDGSpring, "FDGSpring"))
13+
14+
15+
func set_current_selection(selection):
16+
current_selection = selection
17+
18+
19+
func _on_button_pressed(type, name: String):
20+
var new_node = type.new()
21+
22+
# Check if name already exists
23+
var already_exists = false
24+
var count = 0
25+
for child in current_selection.get_children():
26+
if child.name.begins_with(name):
27+
count += 1
28+
already_exists = true
29+
30+
if not already_exists:
31+
new_node.name = name
32+
else:
33+
new_node.name = name + str(count + 1)
34+
35+
36+
current_selection.add_child(new_node)
37+
new_node.set_owner(current_selection.get_tree().edited_scene_root)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
[gd_scene load_steps=11 format=3 uid="uid://csom57ywvasf5"]
2+
3+
[ext_resource type="Texture2D" uid="uid://3i6spt2g10rr" path="res://addons/force_directed_graph/icons/ForceDirectedGraph.svg" id="1_p4yg8"]
4+
[ext_resource type="Script" path="res://addons/force_directed_graph/ui/graph_ui.gd" id="1_t3d8u"]
5+
[ext_resource type="Texture2D" uid="uid://dvsr10wvptj0j" path="res://addons/force_directed_graph/icons/FDGNode.svg" id="2_mtvv5"]
6+
[ext_resource type="Texture2D" uid="uid://dydh7pbp8qiqm" path="res://addons/force_directed_graph/icons/FDGSpring.svg" id="3_7jlyv"]
7+
8+
[sub_resource type="InputEventKey" id="InputEventKey_gf45o"]
9+
device = -1
10+
alt_pressed = true
11+
keycode = 71
12+
13+
[sub_resource type="Shortcut" id="Shortcut_m2piv"]
14+
events = [SubResource("InputEventKey_gf45o")]
15+
16+
[sub_resource type="InputEventKey" id="InputEventKey_odhcc"]
17+
device = -1
18+
alt_pressed = true
19+
keycode = 78
20+
21+
[sub_resource type="Shortcut" id="Shortcut_tdywb"]
22+
events = [SubResource("InputEventKey_odhcc")]
23+
24+
[sub_resource type="InputEventKey" id="InputEventKey_1tft4"]
25+
device = -1
26+
alt_pressed = true
27+
keycode = 83
28+
29+
[sub_resource type="Shortcut" id="Shortcut_6inb6"]
30+
events = [SubResource("InputEventKey_1tft4")]
31+
32+
[node name="GraphUI" type="MarginContainer"]
33+
custom_minimum_size = Vector2(100, 0)
34+
anchors_preset = 9
35+
anchor_bottom = 1.0
36+
grow_vertical = 2
37+
theme_override_constants/margin_left = 5
38+
theme_override_constants/margin_top = 5
39+
theme_override_constants/margin_bottom = 5
40+
script = ExtResource("1_t3d8u")
41+
42+
[node name="VBoxContainer" type="VBoxContainer" parent="."]
43+
layout_mode = 2
44+
45+
[node name="ButtonGraph" type="Button" parent="VBoxContainer"]
46+
unique_name_in_owner = true
47+
layout_mode = 2
48+
shortcut = SubResource("Shortcut_m2piv")
49+
text = "Graph"
50+
icon = ExtResource("1_p4yg8")
51+
52+
[node name="ButtonNode" type="Button" parent="VBoxContainer"]
53+
unique_name_in_owner = true
54+
layout_mode = 2
55+
shortcut = SubResource("Shortcut_tdywb")
56+
text = "Node"
57+
icon = ExtResource("2_mtvv5")
58+
59+
[node name="ButtonSpring" type="Button" parent="VBoxContainer"]
60+
unique_name_in_owner = true
61+
layout_mode = 2
62+
shortcut = SubResource("Shortcut_6inb6")
63+
text = "Spring"
64+
icon = ExtResource("3_7jlyv")

0 commit comments

Comments
 (0)