
[!IMPORTANT]
Paper is a very new library. While an earlier iteration is actively used within the Prowl Game Engine, this specific library hasn't yet established a track record of reliability in production environments.
An Immediate-Mode UI Library
Table of Contents
📝 About The Project 📝
Paper is an open-source, MIT-licensed immediate-mode UI library built for the Prowl Game Engine. It provides a lightweight, flexible way to create highly reactive user interfaces with minimal effort.
https://github.com/user-attachments/assets/d8206009-5a0f-4769-85a2-90cb5d434757
Paper follows the immediate-mode GUI (IMGUI) paradigm, where UI elements are created and configured on every frame. Unlike retained-mode systems, it doesn't maintain persistent widget objects, making code simpler and more direct.
Here's a basic example:
Paper.Box("MyButton")
.Size(100)
.BackgroundColor(Color.ForestGreen)
.Rounded(8)
.Text(Text.Center("Click Me", myFont, Color.White))
.OnClick((rect) => Console.WriteLine("Button clicked!"));
Which produces this button you can click on:
Unlike Retained, you don't need to find elements or store references to change values.
For example, If you want to animate the roundness it is as simple as
.Rounded(YourAnimatedFloat)
✨ Features ✨
- General:
- Cross-Platform! Windows, Linux & Mac!
- Immediate Mode Architecture
- 100% C#!
- Highly Portable
- Very easy to integrate
- OpenTK Example
- Raylib Example (Less than 500 loc including shaders!)
- With more to come!
- Fluent API
- Flexible Layout System
- Rows, Columns & Custom Positioning
- Pixel, Percentage, Stretch or Auto for Positioning and Sizing
- A Powerful Built-in Animation System
- Many built-in Easing functions
- Easily provide your own Easing functions
- Automatic transitions for each individual Property of any node at any time
- Rich Event Handling
- Comprehensive Mouse & Keyboard support
- Parent-Child Event Bubbling
- OnClick, OnDragStart, OnHover and many more
- Transformations
- Scale, Rotate, Translate & Skew any Element
- Vector Graphics
- Highly Performant
- Hardware accelerated
- Anti-Aliased
- Scissoring
- MoveTo, LineTo, CurveTo, Fill, Stroke, etc
- Draw custom shapes at any time any where
(back to top)
🚀 Getting Started 🚀
Installation
dotnet add package Prowl.Paper
Initialization
You will need a Renderer, Theres examples in the repository under Samples for OpenTK and Raylib, with more to come.
Paper.Initialize(yourRenderer, screenWidth, screenHeight);
Paper.SetResolution(screenWidth, screenHeight);
var fontSystem = new FontSystem();
fontSystem.AddFont(File.ReadAllBytes("path/to/font.ttf"));
var myFont = fontSystem.GetFont(24);
Basic Usage
Paper is very easy to use, Simply call BeginFrame, Do your UI then call EndFrame
void RenderUI()
{
Paper.BeginFrame(deltaTime);
using (Paper.Column("MainContainer")
.BackgroundColor(240, 240, 240)
.Enter())
{
using (Paper.Box("Header")
.Height(60)
.BackgroundColor(50, 120, 200)
.Text(Text.Center("My Application", myFont, Color.White))
.Enter()) { }
using (Paper.Row("Content").Enter())
{
Paper.Box("Sidebar")
.Width(200)
.BackgroundColor(220, 220, 220);
Paper.Box("MainContent");
}
}
Paper.EndFrame();
}
That should result in the following UI:
Layouting
Paper provides a mighty layout engine based on the Morphorm library.
using (Paper.Row("MyRow")
.Enter())
{
}
using (Paper.Column("MyColumn")
.Enter())
{
}
using (Paper.Box("CustomPositionedElement")
.PositionType(PositionType.SelfDirected)
.Left(100)
.Top(50)
.Enter())
{
}
Styling and Animation
Paper provides a very powerful yet simple way to both draw and animate your UI
[!TIP]
Styling is executed in order of calls, so in this case, if YourCondition is true, even if it's being hovered, If(YourCondition) will take priority since it comes after.
Also .Hovered, .Active and so on, are all just automatic versions of .If() like .If(Paper.IsNodeHovered(TheNode)).
using (Paper.Box("StyledElement")
.BackgroundColor(Color.Blue)
.BorderColor(Color.White)
.BorderWidth(2)
.Rounded(8)
.Enter()) { }
using (Paper.Box("InteractiveElement")
.BackgroundColor(Color.Gray)
.Hovered
.BackgroundColor(Color.LightGray)
.End()
.Active
.BackgroundColor(Color.DarkGray)
.End()
.If(YourCondition)
.BackgroundColor(Color.Gray)
.End()
.Enter()) { }
using (Paper.Box("AnimatedElement")
.BackgroundColor(Color.Red)
.Hovered
.BackgroundColor(Color.Green)
.End()
.Transition(GuiProp.BackgroundColor, 0.3, Paper.Easing.SineInOut)
.Enter()) { }
Paper.Easing.Linear
Paper.Easing.EaseIn
Paper.Easing.EaseOut
Paper.Easing.EaseInOut
Paper.Easing.CubicIn
Paper.Easing.ElasticOut
Event Handling
Events will bubble upwards through their parents.
So hovering a child will also call OnHover for the parent.
Paper.Box("InteractiveElement")
.OnClick((rect) => HandleClick())
.OnHover((rect) => ShowTooltip())
.OnEnter((rect) => PlayHoverSound())
.OnLeave((rect) => HideTooltip())
.OnDragStart((rect) => StartDragging())
.OnDragging((start, rect) => UpdateDragPosition(start))
.OnDragEnd((start, total, rect) => FinishDragging())
.OnScroll((delta, rect) => Scroll(delta))
Input Handling
To integrate Paper's input system with your project, you need to forward input events from your project to PaperUI.
Here's a simplified example using Raylib:
void UpdatePaperUIInput()
{
Paper.SetPointerPosition(mousePos);
if (IsMouseButtonPressed(MouseButton.Left))
Paper.SetPointerState(PaperMouseBtn.Left, mousePos, true);
if (IsMouseButtonReleased(MouseButton.Left))
Paper.SetPointerState(PaperMouseBtn.Left, mousePos, false);
float wheelDelta = GetMouseWheelMove();
if (wheelDelta != 0)
Paper.SetPointerWheel(wheelDelta);
int key = GetCharPressed();
while (key > 0)
{
Paper.AddInputCharacter(((char)key).ToString());
key = GetCharPressed();
}
foreach (var keyMapping in keyMappings)
{
if (IsKeyPressed(keyMapping.EngineKey))
Paper.SetKeyState(keyMapping.PaperKey, true);
else if (IsKeyReleased(keyMapping.EngineKey))
Paper.SetKeyState(keyMapping.PaperKey, false);
}
}
So much more!
There's so much more I couldn't possibly fit it all into this Readme file.
A more complete documentation & tutorial will be coming in the near future!
🤝 Contributing 🤝
Check our Contributing guide to see how to be part of this team.
(back to top)
Contributors 🌟
Dependencies 📦
(back to top)
📜 License 📜
Distributed under the MIT License. See LICENSE for more information.
(back to top)
