FishUI 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package FishUI --version 1.0.0
                    
NuGet\Install-Package FishUI -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FishUI" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FishUI" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="FishUI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FishUI --version 1.0.0
                    
#r "nuget: FishUI, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FishUI@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FishUI&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=FishUI&version=1.0.0
                    
Install as a Cake Tool

FishUI

A dependency-free, immediate-mode-inspired GUI library for .NET applications with backend-agnostic rendering.

.NET 9.0 License DeepWiki

Uses the GWEN Skin atlas for theming.

Table of Contents

Overview

FishUI is a flexible GUI framework that separates UI logic from rendering, allowing integration with any graphics library. It provides a comprehensive set of controls suitable for game development, tools, and applications.

Key Principles:

  • Backend Agnostic: Implement your own graphics and input handlers via simple interfaces
  • Dependency Free: Core library has no external dependencies except YamlDotNet for serialization
  • Game-Ready: Designed for real-time applications with features like virtual cursor support
  • Themeable: YAML-based theme system with atlas/9-slice support

Screenshots

<p align="center"> <img src="screenshots/new/anim_system.gif" width="600" alt="Animation & Particle System"/> </p>

<p align="center"> <img src="screenshots/new/26.png" width="400" alt="Windows & Dialogs"/> <img src="screenshots/new/26_2.png" width="400" alt="Windows & Dialogs"/> </p> <p align="center"> <img src="screenshots/new/1.png" width="400" alt="Animations"/> <img src="screenshots/new/3.png" width="400" alt="Button Variants"/> </p> <p align="center"> <img src="screenshots/new/4.png" width="400" alt="DataGrid"/> <img src="screenshots/new/5.png" width="400" alt="DatePicker"/> </p> <p align="center"> <img src="screenshots/new/6.png" width="400" alt="DropDown"/> <img src="screenshots/new/7.png" width="400" alt="Editor Layout"/> </p> <p align="center"> <img src="screenshots/new/9.png" width="400" alt="Game Main Menu"/> <img src="screenshots/new/10.png" width="400" alt="Gauges"/> </p> <p align="center"> <img src="screenshots/new/13.png" width="400" alt="LayoutSystem"/> <img src="screenshots/new/14.png" width="400" alt="LineChart"/> </p> <p align="center"> <img src="screenshots/new/16.png" width="400" alt="MenuBar"/> <img src="screenshots/new/17.png" width="400" alt="MultiLineEditbox"/> </p> <p align="center"> <img src="screenshots/new/18.png" width="400" alt="PropertyGrid"/> <img src="screenshots/new/19.png" width="400" alt="ScrollablePane"/> </p> <p align="center"> <img src="screenshots/new/21.png" width="400" alt="SpreadsheetGrid"/> <img src="screenshots/new/game_window_sample.png" width="400" alt="Game Window Sample"/> </p>

Features

Controls (47+ Built-in)

Category Controls
Input Button, Textbox, CheckBox, RadioButton, ToggleSwitch, Slider, NumericUpDown, MultiLineEditbox
Selection ListBox, DropDown (ComboBox), TreeView, SelectionBox, DatePicker, TimePicker
Display Label, StaticText, ImageBox, AnimatedImageBox, ProgressBar, LineChart, Timeline, BigDigitDisplay, ToastNotification
Containers Panel, Window, GroupBox, TabControl, ScrollablePane, StackLayout, FlowLayout, GridLayout
Navigation ScrollBarV, ScrollBarH, MenuBar, ContextMenu, MenuItem
Gauges RadialGauge, BarGauge, VUMeter
Data DataGrid, SpreadsheetGrid, PropertyGrid, ItemListbox
Effects ParticleEmitter
Utility Tooltip, Titlebar

Framework Features

  • Layout System: Absolute positioning, anchoring, margins/padding, StackLayout, FlowLayout, GridLayout
  • Theme System: YAML themes with atlas regions, 9-slice/NPatch rendering, color overrides, inheritance
  • Serialization: Save/load UI layouts to YAML files with event handler binding
  • Animation: Built-in animation system with easing functions, tween helpers, and particle effects
  • Input: Mouse, keyboard, touch, and virtual cursor (gamepad/keyboard navigation)
  • Events: Control events, serializable event handlers, event broadcasting
  • UI Scaling: Resolution-independent UI with configurable scale factor

Projects

Project Description
FishUI Core library - all controls and interfaces
FishUIEditor Visual layout editor for designing FishUI interfaces
FishUIDemos Sample implementations using ISample interface
FishUISample Raylib-based sample runner with GUI chooser

Quick Start

1. Implement Required Interfaces

FishUI requires three interfaces for your graphics backend:

// Graphics rendering
public class MyGfx : IFishUIGfx
{
    public int ScreenWidth { get; set; }
    public int ScreenHeight { get; set; }
    
    public void Init() { }
    public void BeginDrawing(float dt) { }
    public void EndDrawing() { }
    
    public ImageRef LoadImage(string path) { /* ... */ }
    public FontRef LoadFont(string path, int size) { /* ... */ }
    
    public void DrawRectangle(Vector2 pos, Vector2 size, FishColor color) { /* ... */ }
    public void DrawImage(ImageRef img, Vector2 pos, float rot, float scale, FishColor color) { /* ... */ }
    public void DrawNPatch(NPatch patch, Vector2 pos, Vector2 size, FishColor color) { /* ... */ }
    public void DrawText(FontRef font, string text, Vector2 pos) { /* ... */ }
    // ... see IFishUIGfx for full interface
}

// Input handling
public class MyInput : IFishUIInput
{
    public Vector2 GetMousePosition() { /* ... */ }
    public bool IsMouseDown(FishMouseButton button) { /* ... */ }
    public bool IsMousePressed(FishMouseButton button) { /* ... */ }
    public bool IsKeyDown(FishKey key) { /* ... */ }
    public bool IsKeyPressed(FishKey key) { /* ... */ }
    public string GetTextInput() { /* ... */ }
    // ... see IFishUIInput for full interface
}

// Event broadcasting (optional)
public class MyEvents : IFishUIEvents
{
    public void Broadcast(FishUI ui, Control sender, string eventName, object[] data) { /* ... */ }
}

2. Initialize FishUI

FishUISettings settings = new FishUISettings();
IFishUIGfx gfx = new MyGfx(800, 600);
IFishUIInput input = new MyInput();
IFishUIEvents events = new MyEvents();

FishUI.FishUI ui = new FishUI.FishUI(settings, gfx, input, events);
ui.Init();

// Load a theme
settings.LoadTheme("data/themes/gwen.yaml", applyImmediately: true);

3. Add Controls

// Simple button with event
Button btn = new Button();
btn.Text = "Click Me";
btn.Position = new Vector2(100, 100);
btn.Size = new Vector2(150, 40);
btn.OnButtonPressed += (sender, mouseBtn, pos) => Console.WriteLine("Clicked!");
ui.AddControl(btn);

// Panel with children
Panel panel = new Panel();
panel.Position = new Vector2(10, 10);
panel.Size = new Vector2(300, 200);
ui.AddControl(panel);

CheckBox check = new CheckBox("Enable Feature");
check.Position = new Vector2(10, 10);
panel.AddChild(check);

// ListBox with items
ListBox list = new ListBox();
list.Position = new Vector2(10, 50);
list.Size = new Vector2(150, 120);
list.AlternatingRowColors = true;
for (int i = 0; i < 10; i++)
    list.AddItem($"Item {i + 1}");
list.OnItemSelected += (lb, idx, item) => Console.WriteLine($"Selected: {item.Text}");
panel.AddChild(list);

4. Run the Update Loop

Stopwatch timer = Stopwatch.StartNew();
float lastTime = 0;

while (running)
{
    float currentTime = (float)timer.Elapsed.TotalSeconds;
    float deltaTime = currentTime - lastTime;
    lastTime = currentTime;
    
    ui.Tick(deltaTime, currentTime);
}

Control Examples

Button Variants

// Standard button
Button btn = new Button { Text = "Normal" };

// Image button (icon only)
Button imgBtn = new Button();
imgBtn.Icon = gfx.LoadImage("icon.png");
imgBtn.IsImageButton = true;

// Toggle button
Button toggleBtn = new Button { Text = "Toggle", IsToggle = true };

// Repeat button (fires while held)
Button repeatBtn = new Button { Text = "Hold Me", IsRepeat = true };
// Searchable dropdown
DropDown searchable = new DropDown();
searchable.Searchable = true;  // Type to filter
searchable.AddItem("Apple");
searchable.AddItem("Banana");
searchable.AddItem("Cherry");

// Multi-select dropdown
DropDown multi = new DropDown();
multi.MultiSelect = true;
multi.OnMultiSelectionChanged += (dd, indices) => { /* ... */ };

ListBox Features

ListBox list = new ListBox();
list.AlternatingRowColors = true;
list.EvenRowColor = new FishColor(200, 220, 255, 40);
list.MultiSelect = true;  // Ctrl+click, Shift+click

// Custom item rendering
list.CustomItemHeight = 28;
list.CustomItemRenderer = (ui, item, index, pos, size, selected, hovered) =>
{
    ui.Graphics.DrawRectangle(pos, new Vector2(12, 12), FishColor.Red);
    ui.Graphics.DrawText(ui.Settings.FontDefault, item.Text, pos + new Vector2(16, 0));
};

Window with Titlebar

Window window = new Window();
window.Title = "My Window";
window.Position = new Vector2(100, 100);
window.Size = new Vector2(400, 300);
window.ShowCloseButton = true;
window.Resizable = true;
window.OnClosed += (wnd) => wnd.Visible = false;
ui.AddControl(window);

// Add content to window
Label content = new Label("Window content here");
content.Position = new Vector2(10, 10);
window.AddChild(content);

Gauges

// Radial gauge (speedometer style)
RadialGauge radial = new RadialGauge();
radial.Size = new Vector2(150, 150);
radial.MinValue = 0;
radial.MaxValue = 100;
radial.Value = 75;

// Bar gauge (linear)
BarGauge bar = new BarGauge();
bar.Size = new Vector2(200, 30);
bar.MinValue = 0;
bar.MaxValue = 100;
bar.Value = 60;

// VU Meter (audio level)
VUMeter vu = new VUMeter();
vu.Size = new Vector2(30, 100);
vu.Value = 0.7f;

Layout & Positioning

Anchoring

// Anchor to edges (resizes with parent)
Button btn = new Button();
btn.Anchor = FishUIAnchor.Left | FishUIAnchor.Right;  // Stretches horizontally
btn.Anchor = FishUIAnchor.All;  // Fills parent

Margins

control.Margin = new FishUIMargin(10, 10, 10, 10);  // Left, Top, Right, Bottom

StackLayout

StackLayout stack = new StackLayout();
stack.Orientation = StackOrientation.Vertical;
stack.Spacing = 5;

stack.AddChild(new Button { Text = "First" });
stack.AddChild(new Button { Text = "Second" });
stack.AddChild(new Button { Text = "Third" });

Theming

YAML Theme Files

# Theme file example
Atlas: "gwen.png"

Button.Normal:
  X: 480
  Y: 0
  W: 31
  H: 31
  Left: 8
  Right: 8
  Top: 8
  Bottom: 8

Button.Hovered:
  X: 480
  Y: 32
  W: 31
  H: 31
  # ...

Color Overrides

// Per-control color customization
label.SetColorOverride("Text", new FishColor(255, 0, 0, 255));
button.SetColorOverride("Text", new FishColor(100, 200, 255, 255));

Opacity

control.Opacity = 0.5f;  // 50% transparent (affects children)

Serialization

// Save UI layout
LayoutFormat.SerializeToFile(ui, "layout.yaml");

// Load UI layout
LayoutFormat.DeserializeFromFile(ui, "layout.yaml");

Virtual Cursor (Gamepad/Keyboard Navigation)

// Enable virtual cursor
ui.VirtualMouse.Enabled = true;
ui.VirtualMouse.Speed = 300f;

// In update loop, map gamepad to virtual cursor
if (gamepad.LeftStick.X != 0 || gamepad.LeftStick.Y != 0)
{
    ui.VirtualMouse.Move(gamepad.LeftStick * deltaTime);
}

Integrating with Existing Game Loops

When integrating FishUI into an existing game that already handles BeginDrawing()/EndDrawing() calls (e.g., in Raylib), you can disable FishUI's automatic drawing frame management:

// In your graphics backend implementation
public class MyRaylibGfx : IFishUIGfx
{
    // Set to false to disable automatic BeginDrawing()/EndDrawing() calls
    public bool UseBeginDrawing { get; set; } = false;

    public void BeginDrawing(float dt)
    {
        if (UseBeginDrawing)
        {
            Raylib.BeginDrawing();
            Raylib.ClearBackground(Color.Gray);
        }
        // Alpha blending is still enabled
        Raylib.BeginBlendMode(BlendMode.Alpha);
    }

    public void EndDrawing()
    {
        Raylib.EndBlendMode();
        if (UseBeginDrawing)
        {
            Raylib.EndDrawing();
        }
    }
}

Then in your game loop:

// Your existing game loop
while (!Raylib.WindowShouldClose())
{
    Raylib.BeginDrawing();
    Raylib.ClearBackground(Color.Black);

    // Draw your game content...
    DrawGameWorld();

    // Draw FishUI on top (it won't call BeginDrawing/EndDrawing)
    ui.Tick(deltaTime, currentTime);

    Raylib.EndDrawing();
}

This allows FishUI to render as an overlay on top of your existing game rendering without interfering with your drawing frame management.

FishUIEditor - Visual Layout Designer

FishUI includes a visual layout editor for designing interfaces:

cd FishUIEditor
dotnet run

Features:

  • Drag-and-drop control placement from toolbox
  • Visual resize handles and selection
  • PropertyGrid for editing control properties
  • Layout hierarchy tree view
  • Save/load layouts to YAML files
  • Parent/child control relationships with reparenting
  • Anchor and Z-ordering support
  • Visual feedback for drop targets
  • Container selection mode (Window/TabControl protect internal controls)
  • Nested control resizing with proper parent offset calculation

Layouts created in the editor can be loaded in your application:

// Load a layout created in FishUIEditor
LayoutFormat.DeserializeFromFile(ui, "data/layouts/my_layout.yaml");

Running Samples

The FishUISample project includes a GUI-based sample chooser:

cd FishUISample
dotnet run

Or run a specific sample:

dotnet run -- --sample 0

Available Samples

  • Basic Controls: Textbox, Slider, NumericUpDown, ProgressBar, ToggleSwitch
  • Button Variants: Icon buttons, toggle, repeat, image buttons
  • DropDown: Basic, searchable, multi-select, custom rendering
  • ListBox: Alternating colors, multi-select, custom rendering
  • ImageBox: Scale modes, filter modes, animated images
  • Gauges: RadialGauge, BarGauge, VUMeter dashboard
  • PropertyGrid: Reflection-based property editor
  • MenuBar: Dropdown menus with submenus
  • ScrollablePane: Virtual scrolling container
  • Layout System: Anchoring, margins, StackLayout, FlowLayout, GridLayout
  • Theme Switcher: Runtime theme switching
  • Virtual Cursor: Keyboard/gamepad navigation
  • Game Menu: Example game-style UI
  • Editor Layout: Load and display layouts from FishUIEditor
  • Data Controls: DataGrid, SpreadsheetGrid, DatePicker, TimePicker
  • Serialization: Layout save/load with event handler binding

Documentation

Additional documentation is available in the docs/ folder:

Requirements

  • .NET 9.0
  • YamlDotNet (included via NuGet) - for layout/theme serialization

For the sample application:

  • Raylib-cs - graphics/input backend for demos

Project Structure

FishUI/
├── FishUI/                 # Core library
│   ├── Controls/           # All UI controls
│   ├── FishUI.cs           # Main UI manager
│   ├── FishUISettings.cs   # Settings and theme loading
│   ├── IFishUIGfx.cs       # Graphics interface
│   ├── IFishUIInput.cs     # Input interface
│   └── LayoutFormat.cs     # YAML serialization
├── FishUIEditor/           # Visual layout editor
│   ├── Controls/           # Editor-specific controls
│   └── FishUIEditor.cs     # Editor application
├── FishUIDemos/            # Sample implementations
│   └── Samples/            # ISample implementations
├── FishUISample/           # Raylib-based runner
│   ├── RaylibGfx.cs        # IFishUIGfx implementation
│   ├── RaylibInput.cs      # IFishUIInput implementation
│   └── SampleChooser.cs    # GUI sample selector
├── docs/                   # Documentation
│   ├── CUSTOM_CONTROLS.md  # Custom control creation guide
│   └── THEMING.md          # Theme creation guide
└── data/                   # Assets
    ├── themes/             # YAML theme files
    ├── layouts/            # Layout files (editor output)
    └── images/             # Sample images

License

MIT License - see repository for details.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on FishUI:

Package Downloads
RaylibFishGfx

Raylib graphics and input backend for FishUI. Provides a complete, production-ready implementation using Raylib-cs.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 103 1/30/2026
1.1.0 94 1/30/2026
1.0.3 93 1/29/2026
1.0.2 93 1/29/2026
1.0.1 97 1/29/2026
1.0.0 97 1/29/2026