{"id":21487282,"url":"https://github.com/sbarisic/fishui","last_synced_at":"2026-02-04T01:44:08.802Z","repository":{"id":74385888,"uuid":"78516214","full_name":"sbarisic/FishUI","owner":"sbarisic","description":"Dependency free, simple GUI","archived":false,"fork":false,"pushed_at":"2026-01-29T21:07:30.000Z","size":78295,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-30T03:56:28.838Z","etag":null,"topics":["csharp","game-interface","gui","raylib","retained-mode-gui","skins"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sbarisic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["sbarisic"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2017-01-10T09:07:25.000Z","updated_at":"2026-01-29T21:07:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"fafd5279-b50b-4131-9eef-a00b2e84da23","html_url":"https://github.com/sbarisic/FishUI","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sbarisic/FishUI","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbarisic%2FFishUI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbarisic%2FFishUI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbarisic%2FFishUI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbarisic%2FFishUI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sbarisic","download_url":"https://codeload.github.com/sbarisic/FishUI/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbarisic%2FFishUI/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29063983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T00:26:14.114Z","status":"ssl_error","status_checked_at":"2026-02-04T00:23:06.435Z","response_time":96,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","game-interface","gui","raylib","retained-mode-gui","skins"],"created_at":"2024-11-23T13:27:58.693Z","updated_at":"2026-02-04T01:44:08.796Z","avatar_url":"https://github.com/sbarisic.png","language":"C#","funding_links":["https://github.com/sponsors/sbarisic"],"categories":[],"sub_categories":[],"readme":"﻿# FishUI\n\nA dependency-free, immediate-mode-inspired GUI library for .NET applications with backend-agnostic rendering.\n\n[![.NET 9.0](https://img.shields.io/badge/.NET-9.0-purple.svg)](https://dotnet.microsoft.com/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![NuGet FishUI](https://img.shields.io/nuget/v/FishUI.svg?label=FishUI)](https://www.nuget.org/packages/FishUI)\n[![NuGet RaylibFishGfx](https://img.shields.io/nuget/v/RaylibFishGfx.svg?label=RaylibFishGfx)](https://www.nuget.org/packages/RaylibFishGfx)\n[![DeepWiki](https://img.shields.io/badge/DeepWiki-sbarisic%2FFishUI-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==)](https://deepwiki.com/sbarisic/FishUI)\n\nUses the [GWEN Skin](https://github.com/benelot/CEGUI-GWEN-Skin) atlas for theming.\n\n## Table of Contents\n\n- [Overview](#overview)\n- [Screenshots](#screenshots)\n- [Features](#features)\n- [Installation](#installation)\n- [Projects](#projects)\n- [Quick Start](#quick-start)\n- [Control Examples](#control-examples)\n- [Layout \u0026 Positioning](#layout--positioning)\n- [Theming](#theming)\n- [Serialization](#serialization)\n- [Virtual Cursor](#virtual-cursor-gamepadkeyboard-navigation)\n- [Integrating with Existing Game Loops](#integrating-with-existing-game-loops)\n- [FishUIEditor](#fishuieditor---visual-layout-designer)\n- [Running Samples](#running-samples)\n- [Documentation](#documentation)\n- [Requirements](#requirements)\n- [Project Structure](#project-structure)\n- [License](#license)\n\n## Overview\n\nFishUI 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.\n\n**Key Principles:**\n- **Backend Agnostic**: Implement your own graphics and input handlers via simple interfaces\n- **Dependency Free**: Core library has no external dependencies except YamlDotNet for serialization\n- **Game-Ready**: Designed for real-time applications with features like virtual cursor support\n- **Themeable**: YAML-based theme system with atlas/9-slice support\n\n## Screenshots\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/anim_system.gif\" width=\"600\" alt=\"Animation \u0026 Particle System\"/\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/26.png\" width=\"400\" alt=\"Windows \u0026 Dialogs\"/\u003e\n  \u003cimg src=\"screenshots/new/26_2.png\" width=\"400\" alt=\"Windows \u0026 Dialogs\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/1.png\" width=\"400\" alt=\"Animations\"/\u003e\n  \u003cimg src=\"screenshots/new/3.png\" width=\"400\" alt=\"Button Variants\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/4.png\" width=\"400\" alt=\"DataGrid\"/\u003e\n  \u003cimg src=\"screenshots/new/5.png\" width=\"400\" alt=\"DatePicker\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/6.png\" width=\"400\" alt=\"DropDown\"/\u003e\n  \u003cimg src=\"screenshots/new/7.png\" width=\"400\" alt=\"Editor Layout\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/9.png\" width=\"400\" alt=\"Game Main Menu\"/\u003e\n  \u003cimg src=\"screenshots/new/10.png\" width=\"400\" alt=\"Gauges\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/13.png\" width=\"400\" alt=\"LayoutSystem\"/\u003e\n  \u003cimg src=\"screenshots/new/14.png\" width=\"400\" alt=\"LineChart\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/16.png\" width=\"400\" alt=\"MenuBar\"/\u003e\n  \u003cimg src=\"screenshots/new/17.png\" width=\"400\" alt=\"MultiLineEditbox\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/18.png\" width=\"400\" alt=\"PropertyGrid\"/\u003e\n  \u003cimg src=\"screenshots/new/19.png\" width=\"400\" alt=\"ScrollablePane\"/\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/new/21.png\" width=\"400\" alt=\"SpreadsheetGrid\"/\u003e\n  \u003cimg src=\"screenshots/new/game_window_sample.png\" width=\"400\" alt=\"Game Window Sample\"/\u003e\n\u003c/p\u003e\n\n## Features\n\n### Controls (50+ Built-in)\n\n| Category | Controls |\n|----------|----------|\n| **Input** | Button, Textbox, CheckBox, RadioButton, ToggleSwitch, Slider, NumericUpDown, MultiLineEditbox |\n| **Selection** | ListBox, DropDown (ComboBox), TreeView, SelectionBox, DatePicker, TimePicker |\n| **Display** | Label, StaticText, ImageBox, AnimatedImageBox, ProgressBar, LineChart, Timeline, BigDigitDisplay, ToastNotification |\n| **Containers** | Panel, Window, GroupBox, TabControl, ScrollablePane, StackLayout, FlowLayout, GridLayout |\n| **Navigation** | ScrollBarV, ScrollBarH, MenuBar, ContextMenu, MenuItem |\n| **Gauges** | RadialGauge, BarGauge, VUMeter |\n| **Data** | DataGrid, SpreadsheetGrid, PropertyGrid, ItemListbox |\n| **Effects** | ParticleEmitter |\n| **Utility** | Tooltip, Titlebar |\n\n### Framework Features\n\n- **Layout System**: Absolute positioning, anchoring, margins/padding, StackLayout, FlowLayout, GridLayout\n- **Theme System**: YAML themes with atlas regions, 9-slice/NPatch rendering, color overrides, inheritance\n- **Serialization**: Save/load UI layouts to YAML files with event handler binding\n- **Animation**: Built-in animation system with easing functions, tween helpers, and particle effects\n- **Input**: Mouse, keyboard, touch, and virtual cursor (gamepad/keyboard navigation)\n- **Events**: Control events, serializable event handlers, event broadcasting\n- **UI Scaling**: Resolution-independent UI with configurable scale factor\n\n## Installation\n\n### NuGet Packages\n\nFishUI is available on NuGet. Choose the package that fits your needs:\n\n#### Option 1: Raylib Backend (Recommended for Quick Start)\n\nIf you're using Raylib for graphics/input, install the all-in-one package:\n\n```bash\ndotnet add package RaylibFishGfx\n```\n\nThis includes:\n- **FishUI** - Core library with all controls\n- **Raylib-cs** - Raylib bindings\n- Pre-built `IFishUIGfx` and `IFishUIInput` implementations\n\n#### Option 2: Core Library Only\n\nIf you're implementing your own graphics backend:\n\n```bash\ndotnet add package FishUI\n```\n\nThen implement `IFishUIGfx` and `IFishUIInput` interfaces for your graphics library.\n\n### Data Files\n\nThe NuGet packages automatically include theme files, fonts, and icons. These are copied to your output directory on build under the `data/` folder.\n\n## Projects\n\n| Project | Description |\n|---------|-------------|\n| **FishUI** | Core library - all controls and interfaces |\n| **RaylibFishGfx** | Raylib graphics/input backend (NuGet package) |\n| **FishUIEditor** | Visual layout editor for designing FishUI interfaces |\n| **FishUIDemos** | Sample implementations using ISample interface |\n| **FishUISample** | Raylib-based sample runner with GUI chooser |\n\n## Quick Start\n\n### 1. Implement Required Interfaces\n\nFishUI requires two interfaces for your graphics backend (or use the pre-built Raylib backend):\n\n```csharp\n// Graphics rendering\npublic class MyGfx : IFishUIGfx\n{\n    public void Init() { }\n    public void BeginDrawing(float dt) { }\n    public void EndDrawing() { }\n\n    public int GetWindowWidth() { /* ... */ }\n    public int GetWindowHeight() { /* ... */ }\n\n    public ImageRef LoadImage(string path) { /* ... */ }\n    public FontRef LoadFont(string path, int size) { /* ... */ }\n\n    public void DrawRectangle(Vector2 pos, Vector2 size, FishColor color) { /* ... */ }\n    public void DrawImage(ImageRef img, Vector2 pos, float rot, float scale, FishColor color) { /* ... */ }\n    public void DrawNPatch(NPatch patch, Vector2 pos, Vector2 size, FishColor color) { /* ... */ }\n    public void DrawText(FontRef font, string text, Vector2 pos, float size, float spacing, FishColor color) { /* ... */ }\n\n    public void BeginScissor(Vector2 pos, Vector2 size) { /* ... */ }\n    public void EndScissor() { /* ... */ }\n    // ... see IFishUIGfx for full interface\n}\n\n// Input handling\npublic class MyInput : IFishUIInput\n{\n    public Vector2 GetMousePosition() { /* ... */ }\n    public bool IsMouseDown(FishMouseButton button) { /* ... */ }\n    public bool IsMousePressed(FishMouseButton button) { /* ... */ }\n    public bool IsKeyDown(FishKey key) { /* ... */ }\n    public bool IsKeyPressed(FishKey key) { /* ... */ }\n    public FishKey GetKeyPressed() { /* ... */ }\n    public int GetCharPressed() { /* ... */ }\n    public float GetMouseWheelMove() { /* ... */ }\n    // ... see IFishUIInput for full interface\n}\n\n// Event handling (optional - can use empty implementation)\npublic class MyEvents : IFishUIEvents\n{\n    public void Broadcast(FishUI.FishUI ui, Control sender, string eventName, object[] args) { }\n}\n```\n\n### 2. Initialize FishUI\n\n```csharp\n// Using the Raylib backend (recommended)\nusing RaylibGfx = RaylibFishGfx.RaylibFishGfx;\nusing RaylibInput = RaylibFishGfx.RaylibInput;\n\nFishUISettings settings = new FishUISettings();\nRaylibGfx gfx = new RaylibGfx(800, 600, \"My App\");\ngfx.UseBeginDrawing = false;  // Set to false if managing draw calls yourself\nIFishUIInput input = new RaylibInput();\nIFishUIEvents events = new MyEvents();  // Or use a simple empty implementation\n\nFishUI.FishUI ui = new FishUI.FishUI(settings, gfx, input, events);\nui.Init();\n\n// Load a theme (required for proper rendering)\nsettings.LoadTheme(\"data/themes/gwen.yaml\", applyImmediately: true);\n```\n\n### 3. Add Controls\n\n```csharp\n// Simple button with event\nButton btn = new Button();\nbtn.Text = \"Click Me\";\nbtn.Position = new Vector2(100, 100);\nbtn.Size = new Vector2(150, 40);\nbtn.OnButtonPressed += (sender, mouseBtn, pos) =\u003e Console.WriteLine(\"Clicked!\");\nui.AddControl(btn);\n\n// Panel with children\nPanel panel = new Panel();\npanel.Position = new Vector2(10, 10);\npanel.Size = new Vector2(300, 200);\nui.AddControl(panel);\n\nCheckBox check = new CheckBox(\"Enable Feature\");\ncheck.Position = new Vector2(10, 10);\ncheck.Size = new Vector2(20, 20);  // Size for the checkbox icon\npanel.AddChild(check);\n\n// ListBox with items\nListBox list = new ListBox();\nlist.Position = new Vector2(10, 50);\nlist.Size = new Vector2(150, 120);\nlist.AlternatingRowColors = true;\nfor (int i = 0; i \u003c 10; i++)\n    list.AddItem($\"Item {i + 1}\");\nlist.OnItemSelected += (lb, idx, item) =\u003e Console.WriteLine($\"Selected: {item.Text}\");\npanel.AddChild(list);\n```\n\n### 4. Run the Update Loop\n\n```csharp\n// Main game loop\nwhile (!Raylib.WindowShouldClose())\n{\n    float dt = Raylib.GetFrameTime();\n\n    // Handle window resize\n    if (Raylib.IsWindowResized())\n        ui.Resized(Raylib.GetScreenWidth(), Raylib.GetScreenHeight());\n\n    Raylib.BeginDrawing();\n    Raylib.ClearBackground(Color.DarkGray);\n\n    // Update and render UI\n    ui.Tick(dt, (float)Raylib.GetTime());\n\n    Raylib.EndDrawing();\n}\n\nRaylib.CloseWindow();\n```\n\n### Complete Minimal Example\n\nHere's a complete working example using the Raylib backend:\n\n```csharp\nusing FishUI;\nusing FishUI.Controls;\nusing Raylib_cs;\nusing System.Numerics;\nusing RaylibGfx = RaylibFishGfx.RaylibFishGfx;\nusing RaylibInput = RaylibFishGfx.RaylibInput;\n\n// Simple event handler\nclass SimpleEvents : IFishUIEvents\n{\n    public void Broadcast(FishUI.FishUI ui, Control ctrl, string name, object[] args) { }\n}\n\nclass Program\n{\n    static void Main()\n    {\n        // Setup\n        var settings = new FishUISettings();\n        var gfx = new RaylibGfx(800, 600, \"FishUI Demo\");\n        gfx.UseBeginDrawing = false;\n\n        var ui = new FishUI.FishUI(settings, gfx, new RaylibInput(), new SimpleEvents());\n        ui.Init();\n        settings.LoadTheme(\"data/themes/gwen.yaml\", applyImmediately: true);\n\n        // Create a button\n        var button = new Button { Text = \"Click Me!\", Position = new Vector2(100, 100), Size = new Vector2(120, 40) };\n        button.OnButtonPressed += (btn, mouse, pos) =\u003e Console.WriteLine(\"Clicked!\");\n        ui.AddControl(button);\n\n        // Main loop\n        while (!Raylib.WindowShouldClose())\n        {\n            Raylib.BeginDrawing();\n            Raylib.ClearBackground(Color.DarkGray);\n            ui.Tick(Raylib.GetFrameTime(), (float)Raylib.GetTime());\n            Raylib.EndDrawing();\n        }\n        Raylib.CloseWindow();\n    }\n}\n```\n\n## Control Examples\n\n### Button Variants\n\n```csharp\n// Standard button\nButton btn = new Button { Text = \"Normal\" };\n\n// Image button (icon only)\nButton imgBtn = new Button();\nimgBtn.Icon = gfx.LoadImage(\"icon.png\");\nimgBtn.IsImageButton = true;\n\n// Toggle button\nButton toggleBtn = new Button { Text = \"Toggle\", IsToggle = true };\n\n// Repeat button (fires while held)\nButton repeatBtn = new Button { Text = \"Hold Me\", IsRepeat = true };\n```\n\n### DropDown with Features\n\n```csharp\n// Searchable dropdown\nDropDown searchable = new DropDown();\nsearchable.Searchable = true;  // Type to filter\nsearchable.AddItem(\"Apple\");\nsearchable.AddItem(\"Banana\");\nsearchable.AddItem(\"Cherry\");\n\n// Multi-select dropdown\nDropDown multi = new DropDown();\nmulti.MultiSelect = true;\nmulti.OnMultiSelectionChanged += (dd, indices) =\u003e { /* ... */ };\n```\n\n### ListBox Features\n\n```csharp\nListBox list = new ListBox();\nlist.AlternatingRowColors = true;\nlist.EvenRowColor = new FishColor(200, 220, 255, 40);\nlist.MultiSelect = true;  // Ctrl+click, Shift+click\n\n// Custom item rendering\nlist.CustomItemHeight = 28;\nlist.CustomItemRenderer = (ui, item, index, pos, size, selected, hovered) =\u003e\n{\n    ui.Graphics.DrawRectangle(pos, new Vector2(12, 12), FishColor.Red);\n    ui.Graphics.DrawText(ui.Settings.FontDefault, item.Text, pos + new Vector2(16, 0));\n};\n```\n\n### Window with Titlebar\n\n```csharp\nWindow window = new Window();\nwindow.Title = \"My Window\";\nwindow.Position = new Vector2(100, 100);\nwindow.Size = new Vector2(400, 300);\nwindow.ShowCloseButton = true;\nwindow.Resizable = true;\nwindow.OnClosed += (wnd) =\u003e wnd.Visible = false;\nui.AddControl(window);\n\n// Add content to window\nLabel content = new Label(\"Window content here\");\ncontent.Position = new Vector2(10, 10);\nwindow.AddChild(content);\n```\n\n### Gauges\n\n```csharp\n// Radial gauge (speedometer style)\nRadialGauge radial = new RadialGauge();\nradial.Size = new Vector2(150, 150);\nradial.MinValue = 0;\nradial.MaxValue = 100;\nradial.Value = 75;\n\n// Bar gauge (linear)\nBarGauge bar = new BarGauge();\nbar.Size = new Vector2(200, 30);\nbar.MinValue = 0;\nbar.MaxValue = 100;\nbar.Value = 60;\n\n// VU Meter (audio level)\nVUMeter vu = new VUMeter();\nvu.Size = new Vector2(30, 100);\nvu.Value = 0.7f;\n```\n\n## Layout \u0026 Positioning\n\n### Anchoring\n\n```csharp\n// Anchor to edges (resizes with parent)\nButton btn = new Button();\nbtn.Anchor = FishUIAnchor.Left | FishUIAnchor.Right;  // Stretches horizontally\nbtn.Anchor = FishUIAnchor.All;  // Fills parent\n```\n\n### Margins\n\n```csharp\ncontrol.Margin = new FishUIMargin(10, 10, 10, 10);  // Left, Top, Right, Bottom\n```\n\n### StackLayout\n\n```csharp\nStackLayout stack = new StackLayout();\nstack.Orientation = StackOrientation.Vertical;\nstack.Spacing = 5;\n\nstack.AddChild(new Button { Text = \"First\" });\nstack.AddChild(new Button { Text = \"Second\" });\nstack.AddChild(new Button { Text = \"Third\" });\n```\n\n## Theming\n\n### YAML Theme Files\n\n```yaml\n# Theme file example\nAtlas: \"gwen.png\"\n\nButton.Normal:\n  X: 480\n  Y: 0\n  W: 31\n  H: 31\n  Left: 8\n  Right: 8\n  Top: 8\n  Bottom: 8\n\nButton.Hovered:\n  X: 480\n  Y: 32\n  W: 31\n  H: 31\n  # ...\n```\n\n### Color Overrides\n\n```csharp\n// Per-control color customization\nlabel.SetColorOverride(\"Text\", new FishColor(255, 0, 0, 255));\nbutton.SetColorOverride(\"Text\", new FishColor(100, 200, 255, 255));\n```\n\n### Opacity\n\n```csharp\ncontrol.Opacity = 0.5f;  // 50% transparent (affects children)\n```\n\n## Serialization\n\n```csharp\n// Save UI layout\nLayoutFormat.SerializeToFile(ui, \"layout.yaml\");\n\n// Load UI layout\nLayoutFormat.DeserializeFromFile(ui, \"layout.yaml\");\n```\n\n## Virtual Cursor (Gamepad/Keyboard Navigation)\n\n```csharp\n// Enable virtual cursor\nui.VirtualMouse.Enabled = true;\nui.VirtualMouse.Speed = 300f;\n\n// In update loop, map gamepad to virtual cursor\nif (gamepad.LeftStick.X != 0 || gamepad.LeftStick.Y != 0)\n{\n    ui.VirtualMouse.Move(gamepad.LeftStick * deltaTime);\n}\n```\n\n## Integrating with Existing Game Loops\n\nWhen 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:\n\n```csharp\n// In your graphics backend implementation\npublic class MyRaylibGfx : IFishUIGfx\n{\n    // Set to false to disable automatic BeginDrawing()/EndDrawing() calls\n    public bool UseBeginDrawing { get; set; } = false;\n\n    public void BeginDrawing(float dt)\n    {\n        if (UseBeginDrawing)\n        {\n            Raylib.BeginDrawing();\n            Raylib.ClearBackground(Color.Gray);\n        }\n        // Alpha blending is still enabled\n        Raylib.BeginBlendMode(BlendMode.Alpha);\n    }\n\n    public void EndDrawing()\n    {\n        Raylib.EndBlendMode();\n        if (UseBeginDrawing)\n        {\n            Raylib.EndDrawing();\n        }\n    }\n}\n```\n\nThen in your game loop:\n\n```csharp\n// Your existing game loop\nwhile (!Raylib.WindowShouldClose())\n{\n    Raylib.BeginDrawing();\n    Raylib.ClearBackground(Color.Black);\n\n    // Draw your game content...\n    DrawGameWorld();\n\n    // Draw FishUI on top (it won't call BeginDrawing/EndDrawing)\n    ui.Tick(deltaTime, currentTime);\n\n    Raylib.EndDrawing();\n}\n```\n\nThis allows FishUI to render as an overlay on top of your existing game rendering without interfering with your drawing frame management.\n\n## FishUIEditor - Visual Layout Designer\n\nFishUI includes a visual layout editor for designing interfaces:\n\n```bash\ncd FishUIEditor\ndotnet run\n```\n\n**Features:**\n- Drag-and-drop control placement from toolbox\n- Visual resize handles and selection\n- PropertyGrid for editing control properties\n- Layout hierarchy tree view\n- Save/load layouts to YAML files\n- Parent/child control relationships with reparenting\n- Anchor and Z-ordering support\n- Visual feedback for drop targets\n- Container selection mode (Window/TabControl protect internal controls)\n- Nested control resizing with proper parent offset calculation\n\nLayouts created in the editor can be loaded in your application:\n\n```csharp\n// Load a layout created in FishUIEditor\nLayoutFormat.DeserializeFromFile(ui, \"data/layouts/my_layout.yaml\");\n```\n\n## Running Samples\n\nThe `FishUISample` project includes a GUI-based sample chooser:\n\n```bash\ncd FishUISample\ndotnet run\n```\n\nOr run a specific sample:\n```bash\ndotnet run -- --sample 0\n```\n\n### Available Samples\n\n- **Basic Controls**: Textbox, Slider, NumericUpDown, ProgressBar, ToggleSwitch\n- **Button Variants**: Icon buttons, toggle, repeat, image buttons\n- **DropDown**: Basic, searchable, multi-select, custom rendering\n- **ListBox**: Alternating colors, multi-select, custom rendering\n- **ImageBox**: Scale modes, filter modes, animated images\n- **Gauges**: RadialGauge, BarGauge, VUMeter dashboard\n- **PropertyGrid**: Reflection-based property editor\n- **MenuBar**: Dropdown menus with submenus\n- **ScrollablePane**: Virtual scrolling container\n- **Layout System**: Anchoring, margins, StackLayout, FlowLayout, GridLayout\n- **Theme Switcher**: Runtime theme switching\n- **Virtual Cursor**: Keyboard/gamepad navigation\n- **Game Menu**: Example game-style UI\n- **Editor Layout**: Load and display layouts from FishUIEditor\n- **Data Controls**: DataGrid, SpreadsheetGrid, DatePicker, TimePicker\n- **Serialization**: Layout save/load with event handler binding\n\n## Documentation\n\nAdditional documentation is available in the `docs/` folder:\n\n- **[Custom Control Creation Guide](docs/CUSTOM_CONTROLS.md)** - How to create your own controls\n- **[Theme Creation Guide](docs/THEMING.md)** - Creating custom themes with YAML\n\n## Requirements\n\n- **.NET 9.0**\n- **YamlDotNet** (included via NuGet) - for layout/theme serialization\n\nFor the sample application:\n- **Raylib-cs** - graphics/input backend for demos\n\n## Project Structure\n\n```\nFishUI/\n├── FishUI/                 # Core library (NuGet: FishUI)\n│   ├── Controls/           # All UI controls (50+)\n│   ├── FishUI.cs           # Main UI manager\n│   ├── FishUISettings.cs   # Settings and theme loading\n│   ├── IFishUIGfx.cs       # Graphics interface\n│   ├── IFishUIInput.cs     # Input interface\n│   ├── IFishUIEvents.cs    # Event handling interface\n│   ├── LayoutFormat.cs     # YAML serialization\n│   ├── build/              # NuGet build props/targets\n│   └── data/               # Themes, fonts, icons\n├── RaylibFishUI/           # Raylib backend (NuGet: RaylibFishGfx)\n│   ├── RaylibFishGfx.cs    # IFishUIGfx implementation\n│   └── RaylibInput.cs      # IFishUIInput implementation\n├── FishUIEditor/           # Visual layout editor\n│   ├── Controls/           # Editor-specific controls\n│   └── FishUIEditor.cs     # Editor application\n├── FishUIDemos/            # Sample implementations\n│   ├── Samples/            # ISample implementations\n│   └── Forms/              # Designer form examples\n├── FishUISample/           # Raylib-based sample runner\n│   ├── Program.cs          # Sample chooser entry point\n│   └── SampleChooser.cs    # GUI sample selector\n├── NugetTest/              # NuGet package testing project\n├── docs/                   # Documentation\n│   ├── CUSTOM_CONTROLS.md  # Custom control creation guide\n│   └── THEMING.md          # Theme creation guide\n└── screenshots/            # Screenshot gallery\n```\n\n## License\n\nMIT License - see repository for details.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsbarisic%2Ffishui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsbarisic%2Ffishui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsbarisic%2Ffishui/lists"}