⚠️ Base on
rik
branch.
The Makepad Framework
consists of two main parts:
Makepad Platform serves as the platform abstraction layer, meaning it provides abstractions and encapsulations for various cross-platform operations. It primarily includes the following components::
The platform's code is organized into the following structure:
Source code: https://github.com/makepad/makepad/tree/rik/platform
derive_live / live_compiler / live_tokenizer
are part of the Live system.shader_compiler
: shader compiler.In Makepad's platform/src directory, we find multiple Rust source files (.rs files) and subdirectories, which can be categorized as follows:
cx.rs
): Contains the core data structures and functions for the Makepad platform layer (e.g., context, configuration parameters).draw_list.rs
, draw_matrix.rs
, draw_shader.rs
, draw_vars.rs
): These files handle graphics rendering logic, including shader management, render queues, and transformation matrix processing.event
): Essential for UI frameworks, this directory contains code for handling various user inputs and system events.os
): Contains platform-specific implementations for different operating systems.audio.rs
, audio_stream.rs
, media_api.rs
, midi.rs
): Implements audio playback, media streaming, and MIDI device interaction functionality.web_socket.rs
): WebSocket implementation for network communication and data exchange.window.rs
, cursor.rs
): Implements window creation, management, and cursor handling functionality.It's evident that the src
directory primarily encapsulates cross-platform low-level interfaces related to events, UI rendering, audio/video, and networking. We'll postpone diving into the details and instead explore the Live system.
The Live system is Makepad's solution for real-time coding. Since Rust is a statically compiled language and doesn't support runtime coding like dynamic languages, Makepad provides this Live system to achieve real-time coding effects. As demonstrated in the vision video from chapter one, UI updates can be made through real-time code modifications without recompiling.
Currently, real-time reloading (live reload) with WYSIWYG effects can be seen using Makepad Studio and VSCode. Support for additional IDEs and editors is planned.
The Live system is implemented using Rust macros. Here's an example of Live syntax:
This code defines a "Button" with configurable color.
The procedural macros live_design!
, #[derive(Live)]
, and #[live]
are part of the Live system, working together on the Button
struct to create this widget.
#[derive(Live)]
is a Rust derive macro that automatically implements the Live
trait for the Button
struct, providing all necessary mechanisms for the button control to interact with the Live system.
#[live]
attribute defines which fields of the Button
struct participate in real-time updates, in this case, the color field.
live_design!
macro functions similarly to CSS styling, defining basic styles for the button widget, such as setting the default color to #f00
.
We'll postpone diving into the Live system's working principles and focus on understanding its purpose and syntax.
More details will be presented later in the Live DSL section.
The Live system includes MPSL (Makepad's custom shader language), a unified language that can be translated into shader languages for various graphics APIs (OpenGL/DirectX/Metal).
Here's an example:
MPSL code can be embedded within Live DSL code. The DrawColor
struct's draw_super
field of type DrawQuad
indicates that this struct inherits DrawQuad
behavior (by implementing the deref
trait for this field). This is a Rust/C technique that acts as a form of behavior delegation. DrawQuad
is a feature provided by Makepad's draw crate, representing the basic shader for drawing arbitrary quadrilaterals.
Using the Deref trait for inheritance is considered an anti-pattern, as Deref's implicit behavior contradicts Rust's philosophy of explicitness.
However, this example is acceptable as it conveniently leverages the framework's capabilities without abuse.
The #[repr(C)]
attribute in the example is required by the MPSL shader language, specifying C-ABI compatible layout for the struct to prevent the Rust compiler from reordering fields.
More details will be presented later in the shading language section.
You might question the Live System approach: Why not use JavaScript/Lua, or develop a custom scripting language like Slint? Why specifically use this Rust macro approach?
Code written in scripting languages can be interpreted or recompiled during runtime, shortening the development cycle. Unfortunately, scripting languages lack the performance advantages of compiled languages, conflicting with Makepad's goal of supporting heavily rendered applications. When combining scripting languages with Rust, code ownership becomes difficult to balance, as the optimal solution varies by application.
This hybrid approach was chosen to address these challenges:
Makepad applications are written in Rust, while aspects controlling application appearance (like styling) are written in Live DSL.
The Live language's primary function is similar to CSS: it describes how the application's user interface should be presented. Like CSS, the Live language facilitates easy style overriding.
Unlike Rust code, Live code is compiled and executed at runtime. Additionally, future visual designers for Makepad (like Makepad Studio) will be able to identify which code sections are Live code.
When modifying Live code using a visual designer, the designer won't recompile the application but instead sends the updated Live code to the running application. This allows the application to recompile and execute the new Live code, immediately reflecting code changes without recompiling Rust code or restarting the application.
Makepad's 2D and 3D drawing layer is also included in the Makepad platform.
The drawing layer includes:
More details about the drawing layer will be covered in later dedicated chapters.。
Parallel to Makepad Platform
is Makepad Widget
, built on top of makepad draw.
It includes:
The makepad-widget src
directory contains many files representing different UI controls that can be categorized as follows:
button.rs
, check_box.rs
, slider.rs
, text_input.rs
,implementing various UI controls.image_cache.rs
, keyboard_view.rs
, scroll_bars.rs
,providing additional functionality supporting widget display and interaction.color_picker.rs
, popup_menu.rs
, tab_bar.rs
,representing more complex or specific-purpose controls.dock.rs
, splitter.rs
, view.rs
, used for organizing and managing UI widget layouts.widget_match_event.rs
handles event processing mechanisms.More details will be covered in the Makepad Widget chapter.