You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

Paper

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

Paper

A powerful immediate mode .net UI Library powering the Prowl Game Engine!

0.1.1
unpublished
nugetNuGet
Maintainers
1
Source
Paper logo image

Github top languages GitHub version GitHub license GitHub issues GitHub stars Discord

[!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.

Join our Discord server! 🎉

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:

// Create a simple button
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!
        • DirectX, Web, Unity
    • 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);

// Resize with
Paper.SetResolution(screenWidth, screenHeight);

// Load a font
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

// In your main loop:
void RenderUI()
{
    // Begin the UI frame
    Paper.BeginFrame(deltaTime);
    
    // Define your UI
    using (Paper.Column("MainContainer")
        .BackgroundColor(240, 240, 240)
        .Enter())
    {
        // A header
        using (Paper.Box("Header")
            .Height(60)
            .BackgroundColor(50, 120, 200)
            .Text(Text.Center("My Application", myFont, Color.White))
            .Enter()) { }
            
        // Content area
        using (Paper.Row("Content").Enter())
        {
            // Sidebar
            Paper.Box("Sidebar")
                .Width(200)
                .BackgroundColor(220, 220, 220);
                
            // Main content
            Paper.Box("MainContent");
        }
    }
    
    // End the UI frame
    Paper.EndFrame();
}

That should result in the following UI:

Layouting

Paper provides a mighty layout engine based on the Morphorm library.

// Row container (horizontal layout)
using (Paper.Row("MyRow")
    .Enter())
{
    // Children will be arranged horizontally
}

// Column container (vertical layout)
using (Paper.Column("MyColumn")
    .Enter())
{
    // Children will be arranged vertically
}

// Custom positioning
using (Paper.Box("CustomPositionedElement")
    .PositionType(PositionType.SelfDirected) // Absolute positioning
    .Left(100)
    .Top(50)
    .Enter())
{
    // This element is positioned exactly at (100, 50) relative to its parent
}

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)).

// Basic styling
using (Paper.Box("StyledElement")
    .BackgroundColor(Color.Blue)
    .BorderColor(Color.White)
    .BorderWidth(2)
    .Rounded(8)
    .Enter()) { }

// State-based styling
using (Paper.Box("InteractiveElement")
    .BackgroundColor(Color.Gray)
    .Hovered
        .BackgroundColor(Color.LightGray)
        .End()
    .Active
        .BackgroundColor(Color.DarkGray)
        .End()
    .If(YourCondition)
        .BackgroundColor(Color.Gray)
        .End()
    .Enter()) { }

// Transitions/animations
using (Paper.Box("AnimatedElement")
    .BackgroundColor(Color.Red)
    .Hovered
        .BackgroundColor(Color.Green)
        .End()
    .Transition(GuiProp.BackgroundColor, 0.3, Paper.Easing.SineInOut)
    .Enter()) { }

// Various built-in easing functions
Paper.Easing.Linear
Paper.Easing.EaseIn
Paper.Easing.EaseOut
Paper.Easing.EaseInOut
Paper.Easing.CubicIn
Paper.Easing.ElasticOut
// ... and many more

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:

// Call this every frame before you draw your UI
void UpdatePaperUIInput()
{
    // Update mouse position
    Paper.SetPointerPosition(mousePos);
    
    // Forward mouse button events
    if (IsMouseButtonPressed(MouseButton.Left))
        Paper.SetPointerState(PaperMouseBtn.Left, mousePos, true);
    if (IsMouseButtonReleased(MouseButton.Left))
        Paper.SetPointerState(PaperMouseBtn.Left, mousePos, false);
    // Repeat for Right & Middle
        
    // Forward mouse wheel events
    float wheelDelta = GetMouseWheelMove();
    if (wheelDelta != 0)
        Paper.SetPointerWheel(wheelDelta);
        
    // Forward text input
    int key = GetCharPressed();
    while (key > 0)
    {
        Paper.AddInputCharacter(((char)key).ToString());
        key = GetCharPressed();
    }
    
    // Forward key states
    // keyMappings being an array storing the mapping from a PaperKey enum to your Projects Key Enum
    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 🌟

contrib.rocks image

Dependencies 📦

(back to top)

📜 License 📜

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Join our Discord server! 🎉

Discord

Keywords

UI

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts