Initial commit: AetherBags + KamiToolKit for FC Gitea
Debug Build and Test / Build against Latest Dalamud (push) Has been cancelled
Debug Build and Test / Build against Staging Dalamud (push) Has been cancelled

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-08 14:46:31 -05:00
commit 8db4ce6094
375 changed files with 34124 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using KamiToolKit.Nodes;
using Lumina.Text.ReadOnly;
namespace KamiToolKit.Premade.Widgets;
/// <summary>
/// Represents a search element that has a searchbar, and a dropdown for reordering elements.
/// </summary>
public unsafe class SearchWidget : SimpleComponentNode {
public readonly TextInputNode InputNode;
public readonly TextDropDownNode SortOrderDropDown;
public readonly CircleButtonNode ReverseButtonNode;
public bool IsReversed { get; private set; }
public string SearchText { get; private set; } = string.Empty;
public string SortMode { get; private set; } = string.Empty;
public delegate void SearchUpdated(string searchString);
public delegate void SortUpdated(string sortingString, bool reversed);
public SearchWidget() {
InputNode = new TextInputNode {
PlaceholderString = "Search . . .",
String = SearchText,
OnInputReceived = SearchTextChanged,
};
InputNode.AttachNode(this);
SortOrderDropDown = new TextDropDownNode {
MaxListOptions = 0,
Options = [],
IsVisible = false,
SelectedOption = SortMode == string.Empty ? null : SortMode,
OnOptionSelected = DropDownChanged,
};
SortOrderDropDown.AttachNode(this);
ReverseButtonNode = new CircleButtonNode {
Icon = ButtonIcon.Sort,
OnClick = OnReverseButtonClicked,
TextTooltip = "Reverse Sort Direction",
IsVisible = false,
};
ReverseButtonNode.AttachNode(this);
ResNode->SetHeight(38);
}
public required SortUpdated OnSortOrderChanged { get; set; }
private void OnReverseButtonClicked() {
IsReversed = !IsReversed;
OnSortOrderChanged(SortMode, IsReversed);
}
private void DropDownChanged(string newOption) {
SortMode = newOption;
OnSortOrderChanged(SortMode, IsReversed);
}
public required SearchUpdated OnSearchUpdated { get; set; }
private void SearchTextChanged(ReadOnlySeString newSearchString) {
SearchText = newSearchString.ToString();
OnSearchUpdated(SearchText);
}
protected override void OnSizeChanged() {
base.OnSizeChanged();
InputNode.Size = new Vector2(Width - 10.0f, 28.0f);
InputNode.Position = new Vector2(5.0f, 5.0f);
ReverseButtonNode.Size = new Vector2(28.0f, 28.0f);
ReverseButtonNode.Position = new Vector2(Width - 5.0f - ReverseButtonNode.Width, InputNode.Height + 8.0f);
SortOrderDropDown.Size = new Vector2(Width - 5.0f - ReverseButtonNode.Width - 5.0f - 5.0f, 28.0f);
SortOrderDropDown.Position = new Vector2(5.0f, InputNode.Height + 8.0f);
}
// Disallow modifying the height of this element.
public override float Height { get => base.Height; set { } }
public int MaxDropdownOptions {
get => SortOrderDropDown.MaxListOptions;
set => SortOrderDropDown.MaxListOptions = value;
}
public List<string> SortingOptions {
get => SortOrderDropDown.Options ?? [];
set {
SortOrderDropDown.Options = value;
SortOrderDropDown.MaxListOptions = value.Count / 2 + 1;
SortOrderDropDown.IsVisible = value.Count > 0;
ReverseButtonNode.IsVisible = value.Count > 0;
ResNode->SetHeight((ushort)(value.Count > 0 ? 69 : 38));
if (SortingOptions.Count > 0) {
SortMode = value.First();
}
}
}
public string? SelectedOption => SortOrderDropDown.SelectedOption;
}
@@ -0,0 +1,94 @@
using System;
using System.Numerics;
using FFXIVClientStructs.FFXIV.Component.GUI;
using KamiToolKit.Classes;
using KamiToolKit.Nodes;
namespace KamiToolKit.Premade.Widgets;
public class Vector2EditWidget : SimpleComponentNode {
public readonly GridNode GridNode;
public readonly TextNode WidthTextNode;
public readonly TextNode HeightTextNode;
public readonly NumericInputNode WidthInputNode;
public readonly NumericInputNode HeightInputNode;
public Vector2EditWidget() {
GridNode = new GridNode {
GridSize = new GridSize(2, 2),
};
GridNode.AttachNode(this);
WidthTextNode = new TextNode {
AlignmentType = AlignmentType.Bottom,
FontType = FontType.Axis,
FontSize = 14,
LineSpacing = 14,
TextColor = ColorHelper.GetColor(8),
TextOutlineColor = ColorHelper.GetColor(7),
TextFlags = TextFlags.Edge | TextFlags.AutoAdjustNodeSize,
String = XLabel ?? "Width",
};
WidthTextNode.AttachNode(GridNode[0, 0]);
HeightTextNode = new TextNode {
AlignmentType = AlignmentType.Bottom,
FontType = FontType.Axis,
FontSize = 14,
LineSpacing = 14,
TextColor = ColorHelper.GetColor(8),
TextOutlineColor = ColorHelper.GetColor(7),
TextFlags = TextFlags.Edge | TextFlags.AutoAdjustNodeSize,
String = YLabel ?? "Height",
};
HeightTextNode.AttachNode(GridNode[1, 0]);
WidthInputNode = new NumericInputNode {
Position = new Vector2(2.0f, 2.0f),
OnValueUpdate = OnXValueUpdated,
};
WidthInputNode.AttachNode(GridNode[0, 1]);
HeightInputNode = new NumericInputNode {
Position = new Vector2(2.0f, 2.0f),
OnValueUpdate = OnYValueUpdated,
};
HeightInputNode.AttachNode(GridNode[1, 1]);
}
protected override void OnSizeChanged() {
base.OnSizeChanged();
GridNode.Size = Size;
WidthTextNode.Size = GridNode[0, 0].Size;
HeightTextNode.Size = GridNode[1, 0].Size;
WidthInputNode.Size = GridNode[0, 1].Size;
HeightInputNode.Size = GridNode[1, 1].Size;
}
private void OnXValueUpdated(int newValue) {
Value = Value with { X = newValue };
OnValueChanged?.Invoke(Value);
}
private void OnYValueUpdated(int newValue) {
Value = Value with { Y = newValue };
OnValueChanged?.Invoke(Value);
}
public Vector2 Value {
get;
set {
field = value;
WidthInputNode.Value = (int) value.X;
HeightInputNode.Value = (int) value.Y;
}
}
public Action<Vector2>? OnValueChanged { get; set; }
public string? XLabel { get; set; }
public string? YLabel { get; set; }
}