优化项目结构

This commit is contained in:
limil 2025-12-19 22:28:23 +08:00
parent dd2703418a
commit c3d826991c
11 changed files with 248 additions and 201 deletions

View File

@ -1,25 +1,19 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using Godot; using Godot;
using Learn.Inspector;
using Learn.Models; using Learn.Models;
namespace Learn.Component;
public partial class MainTreePanel : Tree public partial class MainTreePanel : Tree
{ {
[Export] private FileDirSelector _dirSelector;
[Export] private NodeInfoEditPanel _nodeInfoEditPanel;
[Export] private ParsedInfoPanel _parsedInfoPanel;
[Export] private LineEdit _columnText;
[Export] private Button _addColumnButton;
[Export] private Button _removeColumnButton;
private readonly HashSet<string> _columns = new(); private readonly HashSet<string> _columns = new();
private bool _updateItemInfoPanel;
private readonly HashSet<TreeNode> _selectingNodes = new (); private readonly HashSet<TreeNode> _selectingNodes = new ();
private readonly Dictionary<TreeItem, TreeNode> _mapper = new(); private readonly Dictionary<TreeItem, TreeNode> _mapper = new();
public HashSet<TreeNode> SelectingNodes => _selectingNodes;
public override void _Ready() public override void _Ready()
{ {
Columns = 1; Columns = 1;
@ -30,28 +24,23 @@ public partial class MainTreePanel : Tree
SetColumnExpand(0, true); SetColumnExpand(0, true);
MultiSelected += OnMultiSelected; MultiSelected += OnMultiSelected;
_addColumnButton.Pressed += OnAddColumn;
_removeColumnButton.Pressed += OnRemoveColumn;
_nodeInfoEditPanel.OnNodeInfoEdited += OnUpdateColumns;
} }
private void OnAddColumn() public void AddColumn(string columnName)
{ {
if (string.IsNullOrEmpty(_columnText.Text)) return; if (string.IsNullOrEmpty(columnName)) return;
_columns.Add(_columnText.Text); _columns.Add(columnName);
OnUpdateColumns(); UpdateColumns();
} }
private void OnRemoveColumn() public void RemoveColumn(string columnName)
{ {
if (string.IsNullOrEmpty(_columnText.Text)) return; if (string.IsNullOrEmpty(columnName)) return;
_columns.Remove(_columnText.Text); _columns.Remove(columnName);
OnUpdateColumns(); UpdateColumns();
} }
private void OnUpdateColumns() public void UpdateColumns()
{ {
Columns = _columns.Count + 1; Columns = _columns.Count + 1;
int index = 1; int index = 1;
@ -80,23 +69,11 @@ public partial class MainTreePanel : Tree
} }
} }
} }
public override void _Process(double delta)
{
if (_updateItemInfoPanel)
{
_updateItemInfoPanel = false;
_nodeInfoEditPanel.SetNodes(_selectingNodes);
_parsedInfoPanel.SetNode(_selectingNodes.FirstOrDefault());
}
}
private void OnMultiSelected(TreeItem item, long column, bool selected) private void OnMultiSelected(TreeItem item, long column, bool selected)
{ {
if(selected) _selectingNodes.Add(_mapper[item]); if(selected) _selectingNodes.Add(_mapper[item]);
else _selectingNodes.Remove(_mapper[item]); else _selectingNodes.Remove(_mapper[item]);
_updateItemInfoPanel = true;
} }
@ -117,6 +94,16 @@ public partial class MainTreePanel : Tree
return item; return item;
} }
public void Build(string path)
{
Clear();
_mapper.Clear();
_selectingNodes.Clear();
TreeItem root = CreateItem();
BuildTree(root, path);
}
private void BuildTree(TreeItem root, string path) private void BuildTree(TreeItem root, string path)
{ {
var nodes = new Stack<(TreeItem node, string path)>(); var nodes = new Stack<(TreeItem node, string path)>();
@ -148,26 +135,4 @@ public partial class MainTreePanel : Tree
} }
} }
} }
private async void Open()
{
var path = await _dirSelector.SelectFolderAsync();
if (string.IsNullOrEmpty(path))
{
return;
}
Clear();
_mapper.Clear();
_selectingNodes.Clear();
TreeItem root = CreateItem();
BuildTree(root, path);
_updateItemInfoPanel = true;
}
private void DoParse()
{
var nodes = _mapper.Values.ToList();
}
} }

View File

@ -4,6 +4,8 @@ using System.Linq;
using Godot; using Godot;
using Learn.Models; using Learn.Models;
namespace Learn.Component;
public partial class NodeInfoEditPanel : Tree public partial class NodeInfoEditPanel : Tree
{ {
public event Action OnNodeInfoEdited; public event Action OnNodeInfoEdited;
@ -96,7 +98,7 @@ public partial class NodeInfoEditPanel : Tree
} }
} }
private void AddKeyValue() public void AddKeyValue()
{ {
if(_itemGroup == null) return; if(_itemGroup == null) return;
var newFieldName = "newField"; var newFieldName = "newField";
@ -108,7 +110,7 @@ public partial class NodeInfoEditPanel : Tree
OnNodesChanged(); OnNodesChanged();
} }
private void RemoveKeyValue() public void RemoveKeyValue()
{ {
if(_itemGroup == null) return; if(_itemGroup == null) return;
@ -118,6 +120,7 @@ public partial class NodeInfoEditPanel : Tree
_itemGroup.Remove(_nodeKeys[node]); _itemGroup.Remove(_nodeKeys[node]);
root.RemoveChild(node); root.RemoveChild(node);
} }
_selectingNodes.Clear();
OnNodeInfoEdited?.Invoke(); OnNodeInfoEdited?.Invoke();
} }
} }

View File

@ -2,7 +2,7 @@ using System.Collections.Generic;
using Godot; using Godot;
using Learn.Models; using Learn.Models;
namespace Learn.Inspector; namespace Learn.Component;
public partial class ParsedInfoPanel : Tree public partial class ParsedInfoPanel : Tree
{ {

69
Main.cs Normal file
View File

@ -0,0 +1,69 @@
using Godot;
using System.Linq;
using Learn.Component;
public partial class Main : Node
{
[ExportGroup("文件夹操作")][Export] private FileDirSelector _dirSelector;
[ExportGroup("操作面板")][Export] private Button _openDirButton;
[ExportGroup("操作面板")][Export] private Button _doParseButton;
[ExportGroup("编辑面板")][Export] private NodeInfoEditPanel _nodeInfoEditPanel;
[ExportGroup("编辑面板")][Export] private Button _addKeyButton;
[ExportGroup("编辑面板")][Export] private Button _removeKeyButton;
[ExportGroup("解析面板")][Export] private ParsedInfoPanel _parsedInfoPanel;
[ExportGroup("主展示面板")] [Export] private MainTreePanel _mainTreePanel;
[ExportGroup("主展示面板")][Export] private LineEdit _columnText;
[ExportGroup("主展示面板")][Export] private Button _addColumnButton;
[ExportGroup("主展示面板")][Export] private Button _removeColumnButton;
private bool _refreshPanels;
public override void _Ready()
{
_nodeInfoEditPanel.OnNodeInfoEdited += _mainTreePanel.UpdateColumns;
_addKeyButton.Pressed += _nodeInfoEditPanel.AddKeyValue;
_removeKeyButton.Pressed += _nodeInfoEditPanel.RemoveKeyValue;
_mainTreePanel.MultiSelected += (_, _, _) => { _refreshPanels = true; };
_addColumnButton.Pressed += () => _mainTreePanel.AddColumn(_columnText.Text);
_removeColumnButton.Pressed += () => _mainTreePanel.RemoveColumn(_columnText.Text);
// 功能区
_openDirButton.Pressed += OpenDir;
_doParseButton.Pressed += DoParse;
}
public override void _Process(double delta)
{
if (_refreshPanels)
{
_refreshPanels = false;
_nodeInfoEditPanel.SetNodes(_mainTreePanel.SelectingNodes);
_parsedInfoPanel.SetNode(_mainTreePanel.SelectingNodes.FirstOrDefault());
}
}
#region Commands
private async void OpenDir()
{
var path = await _dirSelector.SelectFolderAsync();
if (string.IsNullOrEmpty(path))
{
return;
}
_mainTreePanel.Build(path);
_refreshPanels = true;
}
private void DoParse()
{
// todo;
}
#endregion
}

1
Main.cs.uid Normal file
View File

@ -0,0 +1 @@
uid://biwhkhqrhpf6a

147
MediaTreeEditor.tscn Normal file
View File

@ -0,0 +1,147 @@
[gd_scene load_steps=6 format=3 uid="uid://b3ypva4l8wfoh"]
[ext_resource type="Script" uid="uid://dqs5segp8tixm" path="res://Utils/FileDirSelector.cs" id="1_d2g23"]
[ext_resource type="Script" uid="uid://bmepprx2mndih" path="res://Component/MainTreePanel.cs" id="2_44ud8"]
[ext_resource type="Script" uid="uid://biwhkhqrhpf6a" path="res://Main.cs" id="2_0727o"]
[ext_resource type="Script" uid="uid://bkx2esr711e68" path="res://Component/ParsedInfoPanel.cs" id="3_d2g23"]
[ext_resource type="Script" uid="uid://bbgo6drfpvv2a" path="res://Component/NodeInfoEditPanel.cs" id="4_d2g23"]
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="FileDirDialog" type="FileDialog" parent="."]
script = ExtResource("1_d2g23")
[node name="Main" type="Node" parent="." node_paths=PackedStringArray("_dirSelector", "_openDirButton", "_doParseButton", "_nodeInfoEditPanel", "_addKeyButton", "_removeKeyButton", "_parsedInfoPanel", "_mainTreePanel", "_columnText", "_addColumnButton", "_removeColumnButton")]
script = ExtResource("2_0727o")
_dirSelector = NodePath("../FileDirDialog")
_openDirButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer/OpenDir")
_doParseButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer/DoParse")
_nodeInfoEditPanel = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/NodeEditPanel")
_addKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/AddKey")
_removeKeyButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/RemoveKey")
_parsedInfoPanel = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer2/ParsedNodePanel")
_mainTreePanel = NodePath("../MarginContainer/HSplitContainer/MainTreePanel")
_columnText = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer/ColunmText")
_addColumnButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer/AddColumn")
_removeColumnButton = NodePath("../MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer/RemoveColumn")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="HSplitContainer" type="HSplitContainer" parent="MarginContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="MainTreePanel" type="Tree" parent="MarginContainer/HSplitContainer"]
custom_minimum_size = Vector2(600, 0)
layout_mode = 2
allow_search = false
hide_root = true
select_mode = 2
script = ExtResource("2_44ud8")
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/HSplitContainer"]
layout_mode = 2
[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="FoldableContainer4" type="FoldableContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "功能操作"
[node name="HFlowContainer" type="HFlowContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4"]
visible = false
layout_mode = 2
[node name="OpenDir" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer"]
layout_mode = 2
size_flags_vertical = 4
text = "打开文件夹"
[node name="DoParse" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer4/HFlowContainer"]
layout_mode = 2
size_flags_vertical = 4
text = "开始解析"
[node name="FoldableContainer3" type="FoldableContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "添加显示字段"
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3"]
visible = false
layout_mode = 2
[node name="ColunmText" type="LineEdit" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
[node name="AddColumn" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer"]
layout_mode = 2
text = "显示"
[node name="RemoveColumn" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer"]
layout_mode = 2
text = "隐藏"
[node name="FoldableContainer2" type="FoldableContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "解析数据"
[node name="ParsedNodePanel" type="Tree" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer2" node_paths=PackedStringArray("_editPanel")]
visible = false
custom_minimum_size = Vector2(0, 400)
layout_mode = 2
hide_root = true
select_mode = 1
script = ExtResource("3_d2g23")
_editPanel = NodePath("../../FoldableContainer/VBoxContainer/NodeEditPanel")
[node name="FoldableContainer" type="FoldableContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "数据编辑"
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer"]
visible = false
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer"]
layout_mode = 2
[node name="AddKey" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 0
text = "添加字段"
[node name="RemoveKey" type="Button" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "移除选中"
[node name="NodeEditPanel" type="Tree" parent="MarginContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 400)
layout_mode = 2
size_flags_vertical = 3
allow_search = false
hide_root = true
select_mode = 2
script = ExtResource("4_d2g23")

View File

@ -11,7 +11,7 @@ config_version=5
[application] [application]
config/name="Learn" config/name="Learn"
run/main_scene="res://tree.tscn" run/main_scene="res://MediaTreeEditor.tscn"
config/features=PackedStringArray("4.5", "C#", "Forward Plus") config/features=PackedStringArray("4.5", "C#", "Forward Plus")
config/icon="res://icon.svg" config/icon="res://icon.svg"

138
tree.tscn
View File

@ -1,138 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://b3ypva4l8wfoh"]
[ext_resource type="Script" uid="uid://dqs5segp8tixm" path="res://Utils/FileDirSelector.cs" id="1_d2g23"]
[ext_resource type="Script" uid="uid://bmepprx2mndih" path="res://MainTreePanel.cs" id="2_44ud8"]
[ext_resource type="Script" uid="uid://bkx2esr711e68" path="res://Inspector/ParsedInfoPanel.cs" id="3_d2g23"]
[ext_resource type="Script" uid="uid://bbgo6drfpvv2a" path="res://Inspector/NodeInfoEditPanel.cs" id="4_d2g23"]
[node name="Control" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="FileDirDialog" type="FileDialog" parent="."]
script = ExtResource("1_d2g23")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="Toolbar" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="OpenDir" type="Button" parent="MarginContainer/VBoxContainer/Toolbar"]
layout_mode = 2
size_flags_vertical = 4
text = "打开文件夹"
[node name="DoParse" type="Button" parent="MarginContainer/VBoxContainer/Toolbar"]
layout_mode = 2
size_flags_vertical = 4
text = "开始解析"
[node name="HSplitContainer" type="HSplitContainer" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="MainTreePanel" type="Tree" parent="MarginContainer/VBoxContainer/HSplitContainer" node_paths=PackedStringArray("_dirSelector", "_nodeInfoEditPanel", "_parsedInfoPanel", "_columnText", "_addColumnButton", "_removeColumnButton")]
custom_minimum_size = Vector2(600, 0)
layout_mode = 2
allow_search = false
hide_root = true
select_mode = 2
script = ExtResource("2_44ud8")
_dirSelector = NodePath("../../../../FileDirDialog")
_nodeInfoEditPanel = NodePath("../ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/NodeEditPanel")
_parsedInfoPanel = NodePath("../ScrollContainer/VBoxContainer2/FoldableContainer2/ParsedNodePanel")
_columnText = NodePath("../ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer/ColunmText")
_addColumnButton = NodePath("../ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer/AddColumn")
_removeColumnButton = NodePath("../ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer/RemoveColumn")
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer/HSplitContainer"]
layout_mode = 2
[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="FoldableContainer3" type="FoldableContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "添加显示字段"
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3"]
visible = false
layout_mode = 2
[node name="ColunmText" type="LineEdit" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer"]
custom_minimum_size = Vector2(100, 0)
layout_mode = 2
[node name="AddColumn" type="Button" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer"]
layout_mode = 2
text = "显示"
[node name="RemoveColumn" type="Button" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer3/HBoxContainer"]
layout_mode = 2
text = "隐藏"
[node name="FoldableContainer2" type="FoldableContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
title = "解析数据"
[node name="ParsedNodePanel" type="Tree" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer2" node_paths=PackedStringArray("_editPanel")]
custom_minimum_size = Vector2(0, 400)
layout_mode = 2
hide_root = true
select_mode = 1
script = ExtResource("3_d2g23")
_editPanel = NodePath("../../FoldableContainer/VBoxContainer/NodeEditPanel")
[node name="FoldableContainer" type="FoldableContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2"]
layout_mode = 2
folded = true
title = "数据编辑"
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer"]
visible = false
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer"]
layout_mode = 2
[node name="Add" type="Button" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 0
text = "添加字段"
[node name="Remove" type="Button" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "移除选中"
[node name="NodeEditPanel" type="Tree" parent="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer"]
custom_minimum_size = Vector2(0, 400)
layout_mode = 2
size_flags_vertical = 3
allow_search = false
hide_root = true
select_mode = 2
script = ExtResource("4_d2g23")
[connection signal="pressed" from="MarginContainer/VBoxContainer/Toolbar/OpenDir" to="MarginContainer/VBoxContainer/HSplitContainer/MainTreePanel" method="Open"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/Toolbar/DoParse" to="MarginContainer/VBoxContainer/HSplitContainer/MainTreePanel" method="DoParse"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/Add" to="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/NodeEditPanel" method="AddKeyValue"]
[connection signal="pressed" from="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/HBoxContainer/Remove" to="MarginContainer/VBoxContainer/HSplitContainer/ScrollContainer/VBoxContainer2/FoldableContainer/VBoxContainer/NodeEditPanel" method="RemoveKeyValue"]