👋Getting Started with Paper
Welcome to the documentation for Paper! Paper is a lightweight, powerful, and easy-to-use immediate-mode UI library for .NET, designed with flexibility and performance in mind.
What is Immediate-Mode?
Unlike traditional "retained-mode" UI frameworks, where you create UI objects and then later find and modify them, Paper uses an immediate-mode approach. This means you declare your entire UI from scratch every single frame.
This sounds inefficient, but it makes your UI code incredibly simple, declarative, and easy to reason about. Want to change a property? Just pass a different value in your next frame's code.
// In a retained-mode system, you might do this:
var myButton = FindElementById("MyButton");
myButton.Roundness = 10;
// If MyButton's Name or ID ever changes, this could break silently.
// In Paper, it's as simple as this:
paper.Box("MyButton").Rounded(10); // The roundness is set directly, every frame
This paradigm eliminates complex state management and the need for data binding, making your UI code more reactive and fun to write.
Installation
Paper is available as a NuGet package. You can add it to your .NET project using the following command:
dotnet add package Prowl.Paper
You could also use a NuGet Package Manager like in Visual Studio.
Your First UI: Setup and Initialization
Let's get Paper up and running. The process involves three main steps: initializing Paper, loading a font, and running the render loop.
1. Initialization
First, you need to initialize Paper with a renderer. Paper is a "bring-your-own-renderer" library, meaning it handles the UI logic and drawing commands, but you provide the code that actually renders the shapes to the screen. The repository includes samples for OpenTK and Raylib.
You'll also need to provide the initial screen dimensions.
// In your application's startup code:
ICanvasRenderer myRenderer = new MyCustomRenderer(); // Or use one from the samples
double screenWidth = 1280;
double screenHeight = 720;
var paper = new Paper()(myRenderer, screenWidth, screenHeight);
If the window resizes, you can inform Paper by calling SetResolution
:
paper.SetResolution(newWidth, newHeight);
2. Loading a Font
To display text, you need to load at least one font file. Paper is currently using FontStashSharp
for font management. However, this may change in the future as we have been working on Prowl.Scribe, our own Font library.
using FontStashSharp;
// Load font data from a file
var fontSystem = new FontSystem();
fontSystem.AddFont(File.ReadAllBytes("path/to/your/font.ttf"));
// Get a specific font size to use for drawing
var myFont = fontSystem.GetFont(18);
3. The Render Loop
The core of a Paper application is the render loop. In your main game or application loop, you will call BeginFrame()
at the start and EndFrame()
at the end. All your UI code goes in between.
Here is a complete example that draws a simple, centered green box with some text.
// In your main application loop (e.g., OnRenderFrame or similar)
void RenderUI(Paper paper, double deltaTime)
{
// 1. Begin the UI frame
paper.BeginFrame(deltaTime);
// 2. Define your UI
P.Box("MyFirstElement")
.Size(250, 80)
.Margin(P.Stretch())
.BackgroundColor(System.Drawing.Color.ForestGreen)
.Rounded(12)
.Text(Text.Center("Hello, Paper!", Fonts.fontMedium, System.Drawing.Color.White));
// 3. End the frame, which triggers layout and rendering
paper.EndFrame();
}

And that's it! You've successfully created your first UI with Paper. In the next section, we'll dive deeper into the Core Concepts that make this library so powerful.
Last updated