apertus-open-source-cinema / narui

Licence: other
A react-inspired UI library for building multimedia desktop apps with rust and vulkan.

Programming Languages

rust
11053 projects

Projects that are alternatives of or similar to narui

Xacor
Experimental Game Engine
Stars: ✭ 24 (-33.33%)
Mutual labels:  vulkan
Vulkan-Tutorial-Java
Vulkan tutorial by Alexander Overvoorde ported to Java
Stars: ✭ 89 (+147.22%)
Mutual labels:  vulkan
Cascade
Node-based image editor with GPU-acceleration.
Stars: ✭ 122 (+238.89%)
Mutual labels:  vulkan
hms-computer-graphics-demo
This is the demo project of CGKit(Short for computer graphics kit). CGKit is a vulkan-based rendering framework, which is designed to improve performance of vulkan devices, especially for Android platform. This project will show you how to load textures, models, add pbr effects and render with vulkan.
Stars: ✭ 19 (-47.22%)
Mutual labels:  vulkan
vuk
vuk - A rendergraph-based abstraction for Vulkan
Stars: ✭ 167 (+363.89%)
Mutual labels:  vulkan
flame
An ECS Game Engine
Stars: ✭ 16 (-55.56%)
Mutual labels:  vulkan
gearoenix
Cross-platform C++ 3D game engine.
Stars: ✭ 33 (-8.33%)
Mutual labels:  vulkan
zig-vulkan-triangle
simple triangle displayed using vulkan, glfw, and zig
Stars: ✭ 55 (+52.78%)
Mutual labels:  vulkan
kool
A Vulkan/OpenGL engine for Desktop Java and Javascript written in Kotlin
Stars: ✭ 76 (+111.11%)
Mutual labels:  vulkan
FidelityFX-SPD
Single Pass Downsampler (SPD)
Stars: ✭ 94 (+161.11%)
Mutual labels:  vulkan
Vulkan.jl
Simplify usage of Vulkan in Julia
Stars: ✭ 77 (+113.89%)
Mutual labels:  vulkan
demos
OpenGL and Vulkan graphics experiments and samples
Stars: ✭ 34 (-5.56%)
Mutual labels:  vulkan
Usagi
A hierarchical component entity system based game engine
Stars: ✭ 44 (+22.22%)
Mutual labels:  vulkan
vulkan
Vulkan bindings for Nim
Stars: ✭ 15 (-58.33%)
Mutual labels:  vulkan
basic-graphics-samples
Basic C++ sample usages of Magma library and Vulkan graphics API
Stars: ✭ 18 (-50%)
Mutual labels:  vulkan
CrossWindow-Graphics
A header only library to simplify creating 🌋 Vulkan / ⚪ OpenGL / 🌐 WebGL / ❎DirectX / 🤖 Metal data structures with CrossWindow.
Stars: ✭ 48 (+33.33%)
Mutual labels:  vulkan
vulkan-raytracing
"Simple" Vulkan raytracing
Stars: ✭ 27 (-25%)
Mutual labels:  vulkan
Yggdrasil-Legacy
Experimental Vulkan Renderer / Game Engine written in C++20.
Stars: ✭ 20 (-44.44%)
Mutual labels:  vulkan
docker-nvidia-glx-desktop
MATE Desktop container designed for Kubernetes supporting OpenGL GLX and Vulkan for NVIDIA GPUs with WebRTC and HTML5, providing an open source remote cloud graphics or game streaming platform. Spawns its own fully isolated X Server instead of using the host X server, therefore not requiring /tmp/.X11-unix host sockets or host configuration.
Stars: ✭ 47 (+30.56%)
Mutual labels:  vulkan
even-laster-engine
Excess demo engine
Stars: ✭ 96 (+166.67%)
Mutual labels:  vulkan

narui

A react-inspired UI library for building multimedia desktop apps with rust and vulkan.

  • declarative UI with Ergonomics similar to React with hooks
  • JSX-like syntax for composing widgets
  • clean, readable & familiar looking application code
  • flutter-style box layout algorithm

narui node graph demo gif

Usage

Here is a small introduction of the basic concepts of narui. Many things might sound familiar if you used modern react or flutter.

Make sure to also check out the examples that cover some more advanced topics and contain more complicated code.

Basics

narui UIs are composed of widgets. These building blocks can be anything from a simple box to a complex node graph node or even a whole application. The widgets of an application form a tree, that is partially re-evaluated when needed.

widgets are functions that are annotated with the widget attribute macro and return either Fragment for composed widgets or FragmentInner for primitive widgets.

#[widget]
pub fn square(context: &mut WidgetContext) -> Fragment {
    rsx! {
        <rect fill=Some(color!(#ffffff)) constraint=BoxConstraints::tight(10.0, 10.0)>
    }
}

The widgets that are defined that way can then be used in other widgets or as the application toplevel via the rsx macro:

fn main() {
    render(
        WindowBuilder::new(),
        rsx_toplevel! {
            <square />
        },
    );
}

Composition

narui follows the principle of composition over inheritance: You build small reusable pieces that then form larger widgets and applications. To enable that, narui widgets can have parameters and children.

#[widget(color = color!(#00aaaa))]  // we assign a default value to the color attribute which is used when color is unspecified
pub fn colored_column(children: FragmentChildren, color: Color, context: &mut WidgetContext) -> Fragment {
    rsx! {
        <rect fill=Some(color)>
            <padding padding=EdgeInsets::all(10.0)>
                <column>
                    {children}
                </column>
            </padding>
        </rect>
    }
}

We can then use that widget like this:

rsx! {
    <colored_container>
        <text>{"Hello, world"}</text>
        <square />
    </colored_container>
}

If we programmatically generate multiple widgets (for example to display a list), we have to manually specify a key so that each widget can be uniquely identified:

rsx! {
    <colored_container>
        {
            (0..10).map(|i| {
                rsx! { 
                    <text key=&i> // <-- explicit key is given here
                        {format!("{}", i)}
                    </text> 
                }
            })
        }
    </colored_container>
}

State, Hooks & Input handling

The context, that is passed to every widget, acts like a pointer into the widget tree (and can therefore be cheaply copied), and is used to associate data to a specific widget.

State management in narui is done using hooks. Hooks work similiar to react hooks. The most simple hook is the context.listenable hook, which is used to store state. Widgets can subscribe to Listenables with the context.listen method and get reevaluated when the state that they listen to changed. Similiarily, the value of a listenable can be updated by using the context.shout method.

#[widget(initial_value = 1)]
pub fn counter(initial_value: i32, context: &mut WidgetContext) -> Fragment {
    let count = context.listenable(initial_value);
    let on_click = move |context: &CallbackContext| {
        context.shout(count, context.spy(count) + 1)
    };

    rsx! {
        <button on_click=on_click>
            <text>
                {format!("{}", context.listen(count))}
            </text>
        </button>
    }
}

Animations

Usually widgets change state in reaction to a outside event like a mouse click or a message sent over a mpsc channel. Sometimes however it can be useful to drive a state change by the widget itself (for example to create animations). Listenables should not be updated during the evaluation of a widget but only in reaction to external events. This way, re-render loops can be avoided in a clean and easy way.

To create animations despite the existance of that rule, one can use the context.after_frame hook, which allows widgets to run a closure after each frame is rendered. This allows widgets to change Listenables in each frame and therefore create animations.

Business logic interaction & interfacing the rest of the world

Interaction with non UI-related code should be done similiar to how interaction with UI related code is done:

  • Listenables should signal the state from business logic to the UI.
  • Events should signal input from the UI to the business logic. This can be simple callbacks as you would to in your UI code, but it can also be more complicated with mpscs or comparable techniques.

The first step of interacting with Business logic is to run it. This can be done with the effect hook manually or by using the thread hook as a utility over that. For a simple example of how that can be acomplished, see examples/stopwatch.rs.

Custom rendering

narui allows widgets defined in downstream application code to emit fully custom vulkan api calls including drawcalls. This is especially important for multimedia applications. Example widgets that could be implemented this way are 3D viewports, image / video views and similiar things.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].