feat(ui): port retained widget foundations
This commit is contained in:
parent
44f9ec13d9
commit
d825572e31
44 changed files with 84813 additions and 292 deletions
|
|
@ -22,6 +22,7 @@ namespace AcDream.App.UI;
|
|||
/// </summary>
|
||||
public sealed class UiField : UiElement
|
||||
{
|
||||
public uint ElementId { get; set; }
|
||||
public UiDatFont? DatFont { get; set; }
|
||||
public AcDream.App.Rendering.BitmapFont? Font { get; set; }
|
||||
public Vector4 TextColor { get; set; } = new(1f, 1f, 1f, 1f);
|
||||
|
|
@ -30,6 +31,8 @@ public sealed class UiField : UiElement
|
|||
public Vector4 SelectionColor { get; set; } = new(0.25f, 0.45f, 0.85f, 0.5f);
|
||||
public float Padding { get; set; } = 4f;
|
||||
public int MaxCharacters { get; set; } = 0xFFFF;
|
||||
public bool OneLine { get; set; } = true;
|
||||
public bool Selectable { get; set; }
|
||||
|
||||
/// <summary>Keyboard device for clipboard (Ctrl+C/X/V) + modifier state (Ctrl/Shift).
|
||||
/// Wired by the host from <see cref="UiHost.Keyboard"/>.</summary>
|
||||
|
|
@ -38,6 +41,8 @@ public sealed class UiField : UiElement
|
|||
/// <summary>Dat sprite resolver (id → GL texture + size) for the focused-field
|
||||
/// background. Null = fall back to the flat <see cref="BackgroundColor"/> rect.</summary>
|
||||
public Func<uint, (uint tex, int w, int h)>? SpriteResolve { get; set; }
|
||||
/// <summary>Unfocused/default state sprite imported from the DAT.</summary>
|
||||
public uint BackgroundSprite { get; set; }
|
||||
/// <summary>Gold "lit" field background drawn when focused (retail Normal_focussed
|
||||
/// state, RenderSurface 0x060011AB). 0 = no focus sprite.</summary>
|
||||
public uint FocusFieldSprite { get; set; }
|
||||
|
|
@ -262,7 +267,8 @@ public sealed class UiField : UiElement
|
|||
protected override void OnDraw(UiRenderContext ctx)
|
||||
{
|
||||
// Focused = "write mode": draw the gold lit field sprite (retail Normal_focussed).
|
||||
// Unfocused: the flat translucent rect. Both go through the sprite bucket
|
||||
// Unfocused: draw the imported default state, then the flat translucent fallback.
|
||||
// Both go through the sprite bucket
|
||||
// (DrawFill / DrawSprite) so the text — also sprite-bucket — draws on top.
|
||||
bool lit = _focused && SpriteResolve is not null && FocusFieldSprite != 0;
|
||||
if (lit)
|
||||
|
|
@ -271,6 +277,16 @@ public sealed class UiField : UiElement
|
|||
if (tex != 0 && tw > 0) ctx.DrawSprite(tex, 0, 0, Width, Height, 0f, 0f, 1f, 1f, Vector4.One);
|
||||
else lit = false;
|
||||
}
|
||||
if (!lit && SpriteResolve is not null && BackgroundSprite != 0)
|
||||
{
|
||||
var (tex, tw, th) = SpriteResolve(BackgroundSprite);
|
||||
if (tex != 0 && tw > 0 && th > 0)
|
||||
{
|
||||
ctx.DrawSprite(tex, 0, 0, Width, Height, 0f, 0f,
|
||||
Width / tw, Height / th, Vector4.One);
|
||||
lit = true;
|
||||
}
|
||||
}
|
||||
if (!lit) ctx.DrawFill(0, 0, Width, Height, BackgroundColor);
|
||||
|
||||
float lh = DatFont?.LineHeight ?? Font?.LineHeight ?? 14f;
|
||||
|
|
@ -366,11 +382,11 @@ public sealed class UiField : UiElement
|
|||
|
||||
case UiEventType.MouseDown:
|
||||
_caret = HitCharX(e.Data1);
|
||||
_selAnchor = _caret; // anchor; a drag will extend, a plain click won't
|
||||
_selecting = true;
|
||||
_selAnchor = Selectable ? _caret : null;
|
||||
_selecting = Selectable;
|
||||
return true;
|
||||
case UiEventType.MouseMove:
|
||||
if (_selecting) _caret = HitCharX(e.Data1);
|
||||
if (Selectable && _selecting) _caret = HitCharX(e.Data1);
|
||||
return true;
|
||||
case UiEventType.MouseUp:
|
||||
_selecting = false;
|
||||
|
|
@ -387,15 +403,15 @@ public sealed class UiField : UiElement
|
|||
{
|
||||
switch (key)
|
||||
{
|
||||
case Silk.NET.Input.Key.A: SelectAll(); return true;
|
||||
case Silk.NET.Input.Key.C: CopySelection(); return true;
|
||||
case Silk.NET.Input.Key.X: CutSelection(); return true;
|
||||
case Silk.NET.Input.Key.A when Selectable: SelectAll(); return true;
|
||||
case Silk.NET.Input.Key.C when Selectable: CopySelection(); return true;
|
||||
case Silk.NET.Input.Key.X when Selectable: CutSelection(); return true;
|
||||
case Silk.NET.Input.Key.V: Paste(); return true;
|
||||
}
|
||||
return true; // swallow other Ctrl combos while typing
|
||||
}
|
||||
|
||||
bool shift = ShiftHeld();
|
||||
bool shift = Selectable && ShiftHeld();
|
||||
switch (key)
|
||||
{
|
||||
case Silk.NET.Input.Key.Enter:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue