Skip to content

Commit f113342

Browse files
committed
first commit
1 parent a3432c1 commit f113342

File tree

13 files changed

+829
-0
lines changed

13 files changed

+829
-0
lines changed

.editorconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/.gitattributes export-ignore
2+
/.gitignore export-ignore
3+
/LICENSE export-ignore
4+
/README.md export-ignore

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Godot 4+ specific ignores
2+
.godot/
3+
4+
# Godot-specific ignores
5+
.import/
6+
*.import
7+
!addons/treegraphdrawer/icon.svg.import
8+
project.godot

addons/treegraphdrawer/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# TreeGraphDrawer
2+
3+
A control node that arranges its children and sub-children as a tree graph and optionally draws connecting lines between them, with some customization options.
4+
5+
I did this for my own game, I'm not sure how useful this is as an addon, but I think it's a good tool to learn how to lay out trees or even to create other addons from this.
6+
7+
## To-do list for v1.0:
8+
9+
- Bug fixing: there's still some cases where the tree isn't drawn completely correct so there must be some bug in the algorithm that I haven't found yet.
10+
- A way of setting the node's bounding rectangle to nicely fit all of the tree. I think this would be useful to put the tree inside containers and things like that. Right now there's the ``get_bounding_rect()`` method but I don't think it's very good and I haven't tested it.
11+
12+
After that I don't think I'm adding anything else to the addon unless I have a need for it, since I am now procrastinating my own game which I originally created this addon for...
13+
14+
## How to use
15+
16+
Place a TreeGraphDrawer node in your scene tree and add whatever Control nodes you want to it. The TreeGraphDrawer node will take all its visible Control-inheriting children and subchildren and programatically set their positions as if they were nodes in a tree graph with the same hierarchy as they have in the scene.
17+
18+
This is not a Container, so **it will not be automatically updated when its children are edited, added, or removed**. The TreeGraphDrawer node positions its children in its ``_ready()`` function, but you can also manually re-arrange it by calling its ``layout()`` method and with the "Re-arrange Tree" button in the inspector.
19+
20+
### Customization options and public methods
21+
22+
TreeGraphDrawer has a few customization options to choose how it is laid out, whether it draws lines or not, and the format of those lines. There's also a few methods that can be called on a TreeGraphDrawer node.
23+
24+
All of this can be seen in the in-editor documentation or in the node's script.
25+
26+
#### Per-node configuration
27+
28+
You can customize how specific nodes behave by setting the following metadata keys (through the inspector or using ``set_meta()`` on them):
29+
30+
- ``"treegraph_ignore"``: set a node's metadata with this key to true to ignore it while building the tree, effectively treating it as part of its parent node. All its children will be ignored as well.
31+
- ``"treegraph_ignore_children"``: set a node's metadata with this key to true to ignore its children while building the tree, effectively treating it and its children as one single node (same effect as setting the ``"treegraph_ignore"`` key to true on all its children).
32+
- ``"treegraph_origin_point"``: set a node's metadata with this key to a ``Vector2`` to manually set its origin point.
33+
- ``"treegraph_no_incoming_lines"``: set a node's metadata with this key to true to avoid drawing connecting lines towards it from its parent.
34+
- ``treegraph_no_outgoing_lines``: set a node's metadata with this key to true to avoid drawing connecting lines from it to its children.
35+
- ``treegraph_lines_start_point``: set a node's metadata with this key to a ``Vector2`` to manually set the point from where connecting lines start.
36+
- ``treegraph_lines_end_point``: set a node's metadata with this key to a ``Vector2`` to manually set the point where connecting lines end.
37+
38+
If a node is an instance of a scene file, the tree will ignore all of its children by default, treating it as a single tree node. To avoid this, set it as an editable instance (check "Editable Children" in the editor or use [``Node.set_editable_instance()``](https://docs.godotengine.org/en/stable/classes/class_node.html#class-node-method-set-editable-instance) in a script).
39+
40+
## Why not a Container?
41+
42+
A container controls the positioning of its children, but not of its sub-children, so all tree nodes would need to be direct children of the container and you would need to stablish their hierarchy in some other way. It would be possible to do so, but once I realized that I could just re-use the existing tree structure of scenes, I wanted to do it that way instead, since it's much simpler to implement and to use.
43+
44+
I don't have plans of making the equivalent Container class, so feel free to reuse this code to do it yourself if you want.
45+
46+
## Acknowledgements
47+
48+
Most of the logic is based on the algorithms explained in [*Drawing Presentable Trees* by Bill Mill](https://llimllib.github.io/pymag-trees/), specifically on the Wetherell-Shannon algorithm, although with some modifications.
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
[gd_scene load_steps=3 format=3 uid="uid://cc3s38v0ms44a"]
2+
3+
[ext_resource type="Script" uid="uid://ktd38g6ib676" path="res://addons/treegraphdrawer/tree_graph_drawer.gd" id="1_0gi0j"]
4+
[ext_resource type="PackedScene" uid="uid://spegwrpaddra" path="res://addons/treegraphdrawer/test_packed_scene.tscn" id="2_gbj7f"]
5+
6+
[node name="Example" type="Control"]
7+
layout_mode = 3
8+
anchors_preset = 15
9+
anchor_right = 1.0
10+
anchor_bottom = 1.0
11+
grow_horizontal = 2
12+
grow_vertical = 2
13+
14+
[node name="TreeGraphDrawer" type="Control" parent="."]
15+
anchors_preset = 0
16+
offset_right = 42.0
17+
offset_bottom = 26.0
18+
mouse_filter = 1
19+
script = ExtResource("1_0gi0j")
20+
metadata/_treegraph_tree_position = Vector2(0, -20)
21+
metadata/treegraph_tree_position = Vector2(145.625, -20)
22+
metadata/_TGC_tree_position = Vector2(228, 0)
23+
24+
[node name="TEST" type="Panel" parent="TreeGraphDrawer"]
25+
unique_name_in_owner = true
26+
layout_mode = 2
27+
offset_left = 38.75
28+
offset_right = 78.7502
29+
offset_bottom = 40.0
30+
metadata/_TGC_tree_position = Vector2(52, 64)
31+
metadata/_treegraph_tree_position = Vector2(0, 0)
32+
metadata/treegraph_tree_position = Vector2(58.75, 0)
33+
34+
[node name="TEST2" type="Panel" parent="TreeGraphDrawer/TEST"]
35+
unique_name_in_owner = true
36+
layout_mode = 0
37+
offset_left = -51.25
38+
offset_top = 60.0
39+
offset_right = 23.75
40+
offset_bottom = 121.0
41+
pivot_offset = Vector2(33.5, 28)
42+
metadata/_TGC_tree_position = Vector2(52, 128)
43+
metadata/_treegraph_tree_position = Vector2(0, 20)
44+
metadata/treegraph_tree_position = Vector2(25, 20)
45+
46+
[node name="TEST3" type="Panel" parent="TreeGraphDrawer/TEST/TEST2"]
47+
unique_name_in_owner = true
48+
layout_mode = 0
49+
offset_left = -7.5
50+
offset_top = 81.0
51+
offset_right = 32.5
52+
offset_bottom = 121.0
53+
metadata/_TGC_tree_position = Vector2(0, 192)
54+
metadata/_treegraph_tree_position = Vector2(0, 40)
55+
metadata/treegraph_tree_position = Vector2(0, 40)
56+
57+
[node name="Panel2" type="Panel" parent="TreeGraphDrawer/TEST/TEST2"]
58+
layout_mode = 0
59+
offset_left = 42.5
60+
offset_top = 81.0
61+
offset_right = 82.5
62+
offset_bottom = 121.0
63+
metadata/_TGC_tree_position = Vector2(104, 192)
64+
metadata/_treegraph_tree_position = Vector2(30, 40)
65+
metadata/treegraph_tree_position = Vector2(50, 40)
66+
67+
[node name="@Line2D@46600" type="Line2D" parent="TreeGraphDrawer/TEST/TEST2"]
68+
show_behind_parent = true
69+
points = PackedVector2Array(37.5, 61, 12.5, 81)
70+
width = 2.0
71+
antialiased = true
72+
metadata/_treegraph_line = true
73+
74+
[node name="@Line2D@46601" type="Line2D" parent="TreeGraphDrawer/TEST/TEST2"]
75+
show_behind_parent = true
76+
points = PackedVector2Array(37.5, 61, 62.5, 81)
77+
width = 2.0
78+
antialiased = true
79+
metadata/_treegraph_line = true
80+
81+
[node name="TestPackedScene" parent="TreeGraphDrawer/TEST" instance=ExtResource("2_gbj7f")]
82+
layout_mode = 1
83+
offset_left = 33.75
84+
offset_top = 60.0
85+
offset_right = 33.75
86+
offset_bottom = 60.0
87+
metadata/_treegraph_tree_position = Vector2(47.5, 20)
88+
metadata/treegraph_tree_position = Vector2(92.5001, 20)
89+
90+
[node name="@Line2D@46599" type="Line2D" parent="TreeGraphDrawer/TEST"]
91+
show_behind_parent = true
92+
points = PackedVector2Array(20.0001, 40, -13.75, 60)
93+
width = 2.0
94+
antialiased = true
95+
metadata/_treegraph_line = true
96+
97+
[node name="@Line2D@46602" type="Line2D" parent="TreeGraphDrawer/TEST"]
98+
show_behind_parent = true
99+
points = PackedVector2Array(20.0001, 40, 53.7501, 60)
100+
width = 2.0
101+
antialiased = true
102+
metadata/_treegraph_line = true
103+
104+
[node name="Panel2" type="Panel" parent="TreeGraphDrawer"]
105+
layout_mode = 2
106+
offset_left = 212.499
107+
offset_right = 252.499
108+
offset_bottom = 40.0
109+
tooltip_text = "test"
110+
metadata/_TGC_tree_position = Vector2(404, 64)
111+
metadata/TGC_tree_position = Vector2(32, 0)
112+
metadata/_treegraph_tree_position = Vector2(276.499, 0)
113+
metadata/treegraph_tree_position = Vector2(232.499, 0)
114+
115+
[node name="Panel25" type="Panel" parent="TreeGraphDrawer/Panel2"]
116+
layout_mode = 0
117+
offset_left = -89.9988
118+
offset_top = 60.0
119+
offset_right = -50.0
120+
offset_bottom = 100.0
121+
metadata/_TGC_tree_position = Vector2(208, 128)
122+
metadata/_treegraph_tree_position = Vector2(162.499, 20)
123+
metadata/treegraph_tree_position = Vector2(142.5, 20)
124+
metadata/_treegraph_ws_offset = 42.4996
125+
metadata/treegraph_ws_offset = 42.4996
126+
127+
[node name="Panel33" type="Panel" parent="TreeGraphDrawer/Panel2/Panel25"]
128+
layout_mode = 0
129+
offset_left = -0.000595093
130+
offset_top = 81.0
131+
offset_right = 39.9994
132+
offset_bottom = 121.0
133+
metadata/_TGC_tree_position = Vector2(208, 192)
134+
metadata/_treegraph_tree_position = Vector2(162.499, 40)
135+
metadata/treegraph_tree_position = Vector2(142.5, 40)
136+
137+
[node name="@Line2D@46604" type="Line2D" parent="TreeGraphDrawer/Panel2/Panel25"]
138+
show_behind_parent = true
139+
points = PackedVector2Array(19.9994, 40, 19.9994, 81)
140+
width = 2.0
141+
antialiased = true
142+
metadata/_treegraph_line = true
143+
144+
[node name="LongPanel" type="Panel" parent="TreeGraphDrawer/Panel2"]
145+
layout_mode = 0
146+
offset_left = 2.4996
147+
offset_top = 60.0
148+
offset_right = 122.499
149+
offset_bottom = 100.0
150+
metadata/_TGC_tree_position = Vector2(386, 128)
151+
metadata/_treegraph_tree_position = Vector2(318.998, 20)
152+
metadata/treegraph_tree_position = Vector2(274.998, 20)
153+
metadata/_treegraph_ws_offset = 48.4988
154+
metadata/treegraph_ws_offset = 24.4988
155+
156+
[node name="Panel" type="Panel" parent="TreeGraphDrawer/Panel2/LongPanel"]
157+
layout_mode = 0
158+
offset_left = -18.0002
159+
offset_top = 81.0
160+
offset_right = 65.9998
161+
offset_bottom = 121.0
162+
metadata/_TGC_tree_position = Vector2(312, 192)
163+
metadata/TGC_tree_position = Vector2(32, 128)
164+
metadata/_treegraph_tree_position = Vector2(282.998, 40)
165+
metadata/treegraph_tree_position = Vector2(238.998, 40)
166+
167+
[node name="Panel2" type="Panel" parent="TreeGraphDrawer/Panel2/LongPanel"]
168+
layout_mode = 0
169+
offset_left = 75.9998
170+
offset_top = 81.0
171+
offset_right = 116.0
172+
offset_bottom = 121.0
173+
metadata/_TGC_tree_position = Vector2(460, 192)
174+
metadata/TGC_tree_position = Vector2(96, 128)
175+
metadata/_treegraph_tree_position = Vector2(354.998, 40)
176+
metadata/treegraph_tree_position = Vector2(310.998, 40)
177+
178+
[node name="Label" type="Label" parent="TreeGraphDrawer/Panel2/LongPanel"]
179+
layout_mode = 0
180+
offset_right = 40.0
181+
offset_bottom = 23.0
182+
text = "test"
183+
metadata/treegraph_ignore = true
184+
185+
[node name="@Line2D@46606" type="Line2D" parent="TreeGraphDrawer/Panel2/LongPanel"]
186+
show_behind_parent = true
187+
points = PackedVector2Array(59.9998, 40, 23.9998, 81)
188+
width = 2.0
189+
antialiased = true
190+
metadata/_treegraph_line = true
191+
192+
[node name="@Line2D@46607" type="Line2D" parent="TreeGraphDrawer/Panel2/LongPanel"]
193+
show_behind_parent = true
194+
points = PackedVector2Array(59.9998, 40, 95.9998, 81)
195+
width = 2.0
196+
antialiased = true
197+
metadata/_treegraph_line = true
198+
199+
[node name="Panel4" type="Panel" parent="TreeGraphDrawer/Panel2"]
200+
layout_mode = 0
201+
offset_left = 156.998
202+
offset_top = 60.0
203+
offset_right = 196.998
204+
offset_bottom = 100.0
205+
metadata/_TGC_tree_position = Vector2(618, 128)
206+
metadata/_treegraph_tree_position = Vector2(481.497, 20)
207+
metadata/treegraph_tree_position = Vector2(389.497, 20)
208+
metadata/_treegraph_ws_offset = 51.4987
209+
metadata/treegraph_ws_offset = 3.4986
210+
211+
[node name="Panel5" type="Panel" parent="TreeGraphDrawer/Panel2/Panel4"]
212+
layout_mode = 0
213+
offset_left = -25.0
214+
offset_top = 81.0
215+
offset_right = 15.0
216+
offset_bottom = 121.0
217+
metadata/_TGC_tree_position = Vector2(564, 192)
218+
metadata/_treegraph_tree_position = Vector2(456.497, 40)
219+
metadata/treegraph_tree_position = Vector2(364.497, 40)
220+
221+
[node name="Panel2" type="Panel" parent="TreeGraphDrawer/Panel2/Panel4"]
222+
layout_mode = 0
223+
offset_left = 25.0
224+
offset_top = 81.0
225+
offset_right = 65.0
226+
offset_bottom = 121.0
227+
metadata/_TGC_tree_position = Vector2(668, 192)
228+
metadata/TGC_tree_position = Vector2(96, 128)
229+
metadata/_treegraph_tree_position = Vector2(506.497, 40)
230+
metadata/treegraph_tree_position = Vector2(414.497, 40)
231+
232+
[node name="@Line2D@46609" type="Line2D" parent="TreeGraphDrawer/Panel2/Panel4"]
233+
show_behind_parent = true
234+
points = PackedVector2Array(20, 40, -5, 81)
235+
width = 2.0
236+
antialiased = true
237+
metadata/_treegraph_line = true
238+
239+
[node name="@Line2D@46610" type="Line2D" parent="TreeGraphDrawer/Panel2/Panel4"]
240+
show_behind_parent = true
241+
points = PackedVector2Array(20, 40, 45, 81)
242+
width = 2.0
243+
antialiased = true
244+
metadata/_treegraph_line = true
245+
246+
[node name="@Line2D@46603" type="Line2D" parent="TreeGraphDrawer/Panel2"]
247+
show_behind_parent = true
248+
points = PackedVector2Array(20, 40, -69.9994, 60)
249+
width = 2.0
250+
antialiased = true
251+
metadata/_treegraph_line = true
252+
253+
[node name="@Line2D@46605" type="Line2D" parent="TreeGraphDrawer/Panel2"]
254+
show_behind_parent = true
255+
points = PackedVector2Array(20, 40, 62.4994, 60)
256+
width = 2.0
257+
antialiased = true
258+
metadata/_treegraph_line = true
259+
260+
[node name="@Line2D@46608" type="Line2D" parent="TreeGraphDrawer/Panel2"]
261+
show_behind_parent = true
262+
points = PackedVector2Array(20, 40, 176.998, 60)
263+
width = 2.0
264+
antialiased = true
265+
metadata/_treegraph_line = true

addons/treegraphdrawer/icon.svg

Lines changed: 41 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)