Files
MovementTests/addons/forge/editor/attributes/AttributeEditorProperty.cs
Minimata e09714cf83
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 27s
Create tag and build when new code gets to main / Export (push) Successful in 7m25s
update forge
2026-05-17 00:06:44 +02:00

168 lines
3.6 KiB
C#

// Copyright © Gamesmiths Guild.
#if TOOLS
using Godot;
namespace Gamesmiths.Forge.Godot.Editor.Attributes;
[Tool]
public partial class AttributeEditorProperty : EditorProperty, ISerializationListener
{
private const int ButtonSize = 26;
private const int PopupSize = 300;
private Label? _label;
private Button? _button;
private Popup? _popup;
private Tree? _tree;
public override void _Ready()
{
Texture2D dropdownIcon = EditorInterface.Singleton.GetEditorTheme().GetIcon("GuiDropdown", "EditorIcons");
var hBox = new HBoxContainer();
_label = new Label { Text = "None", SizeFlagsHorizontal = SizeFlags.ExpandFill };
_button = new Button { Icon = dropdownIcon, CustomMinimumSize = new Vector2(ButtonSize, 0) };
hBox.AddChild(_label);
hBox.AddChild(_button);
AddChild(hBox);
_popup = new Popup { Size = new Vector2I(PopupSize, PopupSize) };
_tree = new Tree
{
HideRoot = true,
AnchorRight = 1,
AnchorBottom = 1,
};
_popup.AddChild(_tree);
var bg = new StyleBoxFlat
{
BgColor = EditorInterface.Singleton
.GetEditorTheme()
.GetColor("dark_color_2", "Editor"),
};
_tree.AddThemeStyleboxOverride("panel", bg);
AddChild(_popup);
BuildAttributeTree(_tree);
_button.Pressed += OnButtonPressed;
_tree.ItemActivated += OnTreeItemActivated;
}
public override void _UpdateProperty()
{
if (_label is null || !IsInstanceValid(_label))
{
return;
}
string value = GetEditedObject().Get(GetEditedProperty()).AsString();
_label.Text = string.IsNullOrEmpty(value) ? "None" : value;
}
public override void _ExitTree()
{
ReleaseUiState();
FreeAllChildren();
base._ExitTree();
}
public void OnBeforeSerialize()
{
ReleaseUiState();
FreeAllChildren();
}
public void OnAfterDeserialize()
{
// This method was intentionally left blank.
}
private static void BuildAttributeTree(Tree tree)
{
TreeItem root = tree.CreateItem();
foreach (string attributeSet in EditorUtils.GetAttributeSetOptions())
{
TreeItem setItem = tree.CreateItem(root);
setItem.SetText(0, attributeSet);
setItem.Collapsed = true;
foreach (string attribute in EditorUtils.GetAttributeOptions(attributeSet))
{
TreeItem attributeItem = tree.CreateItem(setItem);
string attributePath = $"{attributeSet}.{attribute}";
attributeItem.SetText(0, attribute);
attributeItem.SetMeta("attribute_path", attributePath);
}
}
}
private void OnButtonPressed()
{
if (_button is null || _popup is null || !IsInstanceValid(_button) || !IsInstanceValid(_popup))
{
return;
}
Window win = GetWindow();
_popup.Position = (Vector2I)_button.GlobalPosition
+ win.Position
- new Vector2I(PopupSize - ButtonSize, -30);
_popup.Popup();
}
private void OnTreeItemActivated()
{
if (_tree is null || _popup is null || _label is null
|| !IsInstanceValid(_tree) || !IsInstanceValid(_popup) || !IsInstanceValid(_label))
{
return;
}
TreeItem item = _tree.GetSelected();
if (item?.HasMeta("attribute_path") != true)
{
return;
}
string fullPath = item.GetMeta("attribute_path").AsString();
_label.Text = fullPath;
EmitChanged(GetEditedProperty(), fullPath);
_popup.Hide();
}
private void ReleaseUiState()
{
if (_button is not null && IsInstanceValid(_button))
{
_button.Pressed -= OnButtonPressed;
}
if (_tree is not null && IsInstanceValid(_tree))
{
_tree.ItemActivated -= OnTreeItemActivated;
}
_label = null;
_button = null;
_popup = null;
_tree = null;
}
private void FreeAllChildren()
{
for (int i = GetChildCount() - 1; i >= 0; i--)
{
Node child = GetChild(i);
RemoveChild(child);
child.Free();
}
}
}
#endif