update forge
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

This commit is contained in:
2026-05-17 00:06:44 +02:00
parent 8b54f00814
commit e09714cf83
473 changed files with 13577 additions and 767 deletions

View File

@@ -17,6 +17,11 @@ namespace Gamesmiths.Forge.Godot.Editor.Statescript;
internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISerializationListener
{
private const string ExpandedArraysMetaKey = "_expanded_arrays";
private const string HeaderRowNodeName = "HeaderRow";
private const string AddButtonNodeName = "AddButton";
private const string VariablesScrollNodeName = "VariablesScroll";
private const string VariableListNodeName = "VariableList";
private const string VariableNameButtonMetaKey = "_variable_name_button";
private static readonly Color _variableColor = new(0xe5c07bff);
private static readonly Color _highlightColor = new(0x56b6c2ff);
@@ -64,7 +69,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
SizeFlagsVertical = SizeFlags.ExpandFill;
CustomMinimumSize = new Vector2(360, 0);
var headerHBox = new HBoxContainer();
var headerHBox = new HBoxContainer { Name = HeaderRowNodeName };
AddChild(headerHBox);
var titleLabel = new Label
@@ -77,6 +82,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
_addButton = new Button
{
Name = AddButtonNodeName,
Icon = _addIcon,
Flat = true,
TooltipText = "Add Variable",
@@ -91,6 +97,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
var scrollContainer = new ScrollContainer
{
Name = VariablesScrollNodeName,
SizeFlagsVertical = SizeFlags.ExpandFill,
SizeFlagsHorizontal = SizeFlags.ExpandFill,
};
@@ -99,6 +106,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
_variableList = new VBoxContainer
{
Name = VariableListNodeName,
SizeFlagsHorizontal = SizeFlags.ExpandFill,
};
@@ -108,45 +116,19 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
public override void _ExitTree()
{
base._ExitTree();
if (_addButton is not null)
{
_addButton.Pressed -= OnAddPressed;
}
_creationDialog?.QueueFree();
_creationDialog = null;
_newNameEdit = null;
_newTypeDropdown = null;
_newArrayToggle = null;
ReleaseUiState();
}
public void OnBeforeSerialize()
{
if (_addButton is not null)
{
_addButton.Pressed -= OnAddPressed;
}
if (_variableList is not null)
{
foreach (Node child in _variableList.GetChildren())
{
_variableList.RemoveChild(child);
child.Free();
}
}
_creationDialog?.Free();
_creationDialog = null;
_newNameEdit = null;
_newTypeDropdown = null;
_newArrayToggle = null;
ReleaseUiState();
}
public void OnAfterDeserialize()
{
if (_addButton is not null)
EnsureControlsCached();
if (_addButton is not null && IsInstanceValid(_addButton))
{
_addButton.Pressed += OnAddPressed;
}
@@ -165,6 +147,31 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
RebuildList();
}
public string? GetSelectedVariableName()
{
return _selectedVariableName;
}
public void RestoreSelectedVariable(string? variableName)
{
if (string.IsNullOrEmpty(variableName) || !HasVariableNamed(variableName))
{
_selectedVariableName = null;
}
else
{
_selectedVariableName = variableName;
}
RefreshVariableSelectionVisuals();
VariableHighlightChanged?.Invoke(_selectedVariableName);
}
public void ClearSelectedVariable()
{
RestoreSelectedVariable(null);
}
/// <summary>
/// Sets the <see cref="EditorUndoRedoManager"/> used for undo/redo support.
/// </summary>
@@ -179,26 +186,95 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
/// </summary>
public void RebuildList()
{
EnsureControlsCached();
if (_variableList is null)
{
return;
}
ClearVariableList();
if (_graph is null)
{
return;
}
for (int i = 0; i < _graph.Variables.Count; i++)
{
AddVariableRow(_graph.Variables[i], i);
}
}
private static int FindTypeDropdownIndex(OptionButton dropdown, StatescriptVariableType variableType)
{
for (int i = 0; i < dropdown.ItemCount; i++)
{
if (dropdown.GetItemId(i) == (int)variableType)
{
return i;
}
}
return 0;
}
private static void UpdateVariableNameButtonAppearance(Button button, bool isSelected)
{
Color buttonColor = isSelected ? _highlightColor : _variableColor;
button.AddThemeColorOverride("font_color", buttonColor);
button.AddThemeColorOverride("font_pressed_color", _highlightColor);
button.AddThemeColorOverride("font_hover_color", buttonColor.Lightened(0.2f));
button.AddThemeColorOverride("font_hover_pressed_color", _highlightColor.Lightened(0.2f));
}
private void EnsureControlsCached()
{
_addButton ??= GetNodeOrNull<Button>($"{HeaderRowNodeName}/{AddButtonNodeName}");
_variableList ??= GetNodeOrNull<VBoxContainer>($"{VariablesScrollNodeName}/{VariableListNodeName}");
}
private void ClearVariableList()
{
EnsureControlsCached();
if (_variableList is null || !IsInstanceValid(_variableList))
{
return;
}
foreach (Node child in _variableList.GetChildren())
{
_variableList.RemoveChild(child);
child.Free();
}
}
if (_graph is null)
private void ReleaseUiState()
{
if (_addButton is not null && IsInstanceValid(_addButton))
{
return;
_addButton.Pressed -= OnAddPressed;
}
for (var i = 0; i < _graph.Variables.Count; i++)
ClearVariableList();
if (_creationDialog is not null && IsInstanceValid(_creationDialog))
{
AddVariableRow(_graph.Variables[i], i);
if (_creationDialog is AcceptDialog acceptDialog)
{
acceptDialog.Confirmed -= OnCreationConfirmed;
}
_creationDialog.Free();
}
_creationDialog = null;
_newNameEdit = null;
_newTypeDropdown = null;
_newArrayToggle = null;
_variableList = null;
_addButton = null;
}
private void SaveExpandedArrayState()
@@ -208,7 +284,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
return;
}
var packed = new string[_expandedArrays.Count];
string[] packed = new string[_expandedArrays.Count];
_expandedArrays.CopyTo(packed);
_graph.SetMeta(ExpandedArraysMetaKey, Variant.From(packed));
}
@@ -226,7 +302,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
if (meta.VariantType == Variant.Type.PackedStringArray)
{
foreach (var name in meta.AsStringArray())
foreach (string name in meta.AsStringArray())
{
_expandedArrays.Add(name);
}
@@ -254,7 +330,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
rowContainer.AddChild(headerRow);
var isSelected = _selectedVariableName == variable.VariableName;
bool isSelected = _selectedVariableName == variable.VariableName;
var nameButton = new Button
{
@@ -266,28 +342,15 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
Alignment = HorizontalAlignment.Left,
};
Color buttonColor = isSelected ? _highlightColor : _variableColor;
nameButton.AddThemeColorOverride("font_color", buttonColor);
nameButton.AddThemeColorOverride("font_pressed_color", _highlightColor);
nameButton.AddThemeColorOverride("font_hover_color", buttonColor.Lightened(0.2f));
nameButton.AddThemeColorOverride("font_hover_pressed_color", _highlightColor.Lightened(0.2f));
nameButton.SetMeta(VariableNameButtonMetaKey, variable.VariableName);
UpdateVariableNameButtonAppearance(nameButton, isSelected);
nameButton.AddThemeFontOverride(
"font",
EditorInterface.Singleton.GetEditorTheme().GetFont("bold", "EditorFonts"));
nameButton.Toggled += pressed =>
{
if (pressed)
{
_selectedVariableName = variable.VariableName;
}
else if (_selectedVariableName == variable.VariableName)
{
_selectedVariableName = null;
}
RebuildList();
VariableHighlightChanged?.Invoke(_selectedVariableName);
SetSelectedVariable(variable.VariableName, pressed);
};
headerRow.AddChild(nameButton);
@@ -301,7 +364,7 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
typeLabel.AddThemeColorOverride("font_color", new Color(0.6f, 0.6f, 0.6f));
headerRow.AddChild(typeLabel);
var capturedIndex = index;
int capturedIndex = index;
var deleteButton = new Button
{
@@ -328,6 +391,47 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
rowContainer.AddChild(new HSeparator());
}
private void SetSelectedVariable(string variableName, bool selected)
{
if (selected)
{
_selectedVariableName = variableName;
}
else if (_selectedVariableName == variableName)
{
_selectedVariableName = null;
}
RefreshVariableSelectionVisuals();
VariableHighlightChanged?.Invoke(_selectedVariableName);
}
private void RefreshVariableSelectionVisuals()
{
if (_variableList is null)
{
return;
}
RefreshVariableSelectionVisualsRecursive(_variableList);
}
private void RefreshVariableSelectionVisualsRecursive(Node parent)
{
foreach (Node child in parent.GetChildren())
{
if (child is Button button && button.HasMeta(VariableNameButtonMetaKey))
{
string variableName = button.GetMeta(VariableNameButtonMetaKey).AsString();
bool isSelected = _selectedVariableName == variableName;
button.SetPressedNoSignal(isSelected);
UpdateVariableNameButtonAppearance(button, isSelected);
}
RefreshVariableSelectionVisualsRecursive(child);
}
}
private void OnAddPressed()
{
if (_graph is null)
@@ -373,12 +477,14 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
StatescriptVariableType[] allTypes = StatescriptVariableTypeConverter.GetAllTypes();
for (var t = 0; t < allTypes.Length; t++)
for (int t = 0; t < allTypes.Length; t++)
{
_newTypeDropdown.AddItem(StatescriptVariableTypeConverter.GetDisplayName(allTypes[t]), t);
_newTypeDropdown.AddItem(
StatescriptVariableTypeConverter.GetDisplayName(allTypes[t]),
(int)allTypes[t]);
}
_newTypeDropdown.Selected = (int)StatescriptVariableType.Int;
_newTypeDropdown.Selected = FindTypeDropdownIndex(_newTypeDropdown, StatescriptVariableType.Int);
typeRow.AddChild(_newTypeDropdown);
var arrayRow = new HBoxContainer { SizeFlagsHorizontal = SizeFlags.ExpandFill };
@@ -404,20 +510,20 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
return;
}
var name = _newNameEdit.Text.Trim();
string name = _newNameEdit.Text.Trim();
if (string.IsNullOrEmpty(name) || HasVariableNamed(name))
{
return;
}
var selectedIndex = _newTypeDropdown.Selected;
int selectedIndex = _newTypeDropdown.Selected;
if (selectedIndex < 0)
{
return;
}
var selectedId = _newTypeDropdown.GetItemId(selectedIndex);
int selectedId = _newTypeDropdown.GetItemId(selectedIndex);
var varType = (StatescriptVariableType)selectedId;
var newVariable = new StatescriptGraphVariable
@@ -431,8 +537,8 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
if (_undoRedo is not null)
{
_undoRedo.CreateAction("Add Graph Variable", customContext: _graph);
_undoRedo.AddDoMethod(this, MethodName.DoAddVariable, _graph!, newVariable);
_undoRedo.AddUndoMethod(this, MethodName.UndoAddVariable, _graph!, newVariable);
_undoRedo.AddDoMethod(this, MethodName.DoAddVariable, _graph, newVariable);
_undoRedo.AddUndoMethod(this, MethodName.UndoAddVariable, _graph, newVariable);
_undoRedo.CommitAction();
}
else
@@ -459,8 +565,8 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
if (_undoRedo is not null)
{
_undoRedo.CreateAction("Remove Graph Variable", customContext: _graph);
_undoRedo.AddDoMethod(this, MethodName.DoRemoveVariable, _graph!, variable, index);
_undoRedo.AddUndoMethod(this, MethodName.UndoRemoveVariable, _graph!, variable, index);
_undoRedo.AddDoMethod(this, MethodName.DoRemoveVariable, _graph, variable, index);
_undoRedo.AddUndoMethod(this, MethodName.UndoRemoveVariable, _graph, variable, index);
_undoRedo.CommitAction();
}
else
@@ -497,8 +603,8 @@ internal sealed partial class StatescriptVariablePanel : VBoxContainer, ISeriali
}
const string baseName = "variable";
var counter = 1;
var name = baseName;
int counter = 1;
string name = baseName;
while (HasVariableNamed(name))
{