### Basic Tessera UI Rendering Setup Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer.rs Demonstrates the fundamental steps to register rendering pipelines and run the Tessera UI application. It shows the typical structure for initializing and starting the renderer. ```rust //! //! // Register your rendering pipelines here //! // tessera_ui_basic_components::pipelines::register_pipelines(app); //! } //! )?; //! //! Ok(()) //! } //! ``` ``` -------------------------------- ### Simple Counter Application Example Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer.rs A conceptual example of a simple counter application using Tessera UI. It demonstrates state management with `Arc` and `AtomicU32`, and the use of the `#[tessera]` macro for the UI entry point. ```rust use std::sync::{Arc, atomic::{AtomicU32, Ordering}}; use tessera_ui::{Renderer, Color, Dp}; use tessera_ui_macros::tessera; struct AppState { count: AtomicU32, } #[tessera] // You need to mark every component function with `#[tessera_macros::tessera]` fn counter_app(state: Arc) { let _count = state.count.load(Ordering::Relaxed); // Your UI components would go here // This is a simplified example without actual UI components } fn main() -> Result<(), Box> { let state = Arc::new(AppState { count: AtomicU32::new(0), }); Renderer::run( move || counter_app(state.clone()), |_app| { // Register rendering pipelines } )?; Ok(()) } ``` -------------------------------- ### Tessera UI Simple Counter Application Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/index A complete example of a simple counter application using Tessera UI. It demonstrates state management with `Arc` and the `#[tessera]` macro for the UI component. ```rust use std::sync::{Arc, atomic::{AtomicU32, Ordering}}; use tessera_ui::{Renderer, Color, Dp}; use tessera_ui_macros::tessera; struct AppState { count: AtomicU32, } #[tessera] // You need to mark every component function with `#[tessera_macros::tessera]` fn counter_app(state: Arc) { let _count = state.count.load(Ordering::Relaxed); // Your UI components would go here // This is a simplified example without actual UI components } fn main() -> Result<(), Box> { let state = Arc::new(AppState { count: AtomicU32::new(0), }); Renderer::run( move || counter_app(state.clone()), |_app| { // Register your rendering pipelines here // tessera_ui_basic_components::pipelines::register_pipelines(app); } )?; Ok(()) } ``` -------------------------------- ### DrawablePipeline::draw Example Implementation Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/drawer/trait.DrawablePipeline An example of how to implement the draw method for a DrawablePipeline. It demonstrates updating uniforms, setting the render pipeline and bind group, and issuing a draw call for a quad. ```Rust fn draw(&mut self, gpu: &wgpu::Device, gpu_queue: &wgpu::Queue, config: &wgpu::SurfaceConfiguration, render_pass: &mut wgpu::RenderPass<'_>, command: &MyCommand, size: PxSize, start_pos: PxPosition, scene_texture_view: &wgpu::TextureView) { // Update uniforms with command-specific data let uniforms = MyUniforms { color: command.color, position: [start_pos.x as f32, start_pos.y as f32], size: [size.width as f32, size.height as f32], }; gpu_queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms])); // Set pipeline and resources render_pass.set_pipeline(&self.render_pipeline); render_pass.set_bind_group(0, &self.bind_group, &[]); // Draw a quad (two triangles) render_pass.draw(0..6, 0..1); } ``` -------------------------------- ### Example Usage of TesseraConfig in Rust Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/struct.TesseraConfig Provides examples of how to instantiate the TesseraConfig struct in Rust. Demonstrates creating a default configuration, a custom configuration with a specific sample count, and disabling MSAA. ```rust use tessera_ui::renderer::TesseraConfig; // Default configuration (4x MSAA) let config = TesseraConfig::default(); // Custom configuration with 8x MSAA let config = TesseraConfig { sample_count: 8, }; // Disable MSAA for better performance let config = TesseraConfig { sample_count: 1, }; ``` -------------------------------- ### Tessera UI px Module Overview and Example Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/px.rs Details the physical pixel coordinate system in Tessera UI, including key types like Px, PxPosition, and PxSize. It outlines the coordinate system origin, axes, and support for negative values. An example demonstrates creating positions and sizes, performing arithmetic, and converting between Px and Dp. ```rust use tessera_ui::px::{Px, PxPosition, PxSize}; use tessera_ui::dp::Dp; // Create pixel values let x = Px::new(100); let y = Px::new(200); // Create a position let position = PxPosition::new(x, y); // Create a size let size = PxSize::new(Px::new(300), Px::new(400)); // Arithmetic operations let offset_position = position.offset(Px::new(10), Px::new(-5)); // Convert between Dp and Px let dp_value = Dp::new(16.0); let px_value = Px::from_dp(dp_value); ``` -------------------------------- ### CursorEvent Usage Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.CursorEvent Provides an example of creating and handling CursorEvent instances, demonstrating how to match on different CursorEventContent variants like presses, releases, and scrolls. ```rust use tessera_ui::cursor::{CursorEvent, CursorEventContent, PressKeyEventType}; use std::time::Instant; let event = CursorEvent { timestamp: Instant::now(), content: CursorEventContent::Pressed(PressKeyEventType::Left), }; match event.content { CursorEventContent::Pressed(button) => println!("Button pressed: {:?}", button), CursorEventContent::Released(button) => println!("Button released: {:?}", button), CursorEventContent::Scroll(scroll) => { println!("Scroll: dx={}, dy={}", scroll.delta_x, scroll.delta_y); } } ``` -------------------------------- ### ComputePipelineRegistry Usage Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/compute/pipeline/struct.ComputePipelineRegistry Demonstrates the typical usage pattern for the ComputePipelineRegistry, showing how to create a registry instance and register multiple compute pipelines. ```rust use tessera_ui::renderer::compute::ComputePipelineRegistry; // Create registry and register pipelines let mut registry = ComputePipelineRegistry::new(); registry.register(blur_pipeline); registry.register(contrast_pipeline); registry.register(brightness_pipeline); // Registry is now ready for use by the renderer ``` -------------------------------- ### Handle Touch Start and Process Events in Rust Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/cursor.rs Demonstrates how to initialize CursorState, handle a touch start event, and process the generated cursor events in Rust. This shows the basic interaction flow for touch input. ```rust use tessera_ui::cursor::CursorState; use tessera_ui::PxPosition; let mut cursor_state = CursorState::default(); // Handle touch start cursor_state.handle_touch_start(0, PxPosition::new(100.0, 200.0)); // Process events let events = cursor_state.take_events(); for event in events { match event.content { CursorEventContent::Pressed(_) => println!("Touch started"), CursorEventContent::Scroll(scroll) => { println!("Scroll: dx={}, dy={}", scroll.delta_x, scroll.delta_y); } _ => {} } } ``` -------------------------------- ### Focus Usage Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/focus_state/struct.Focus Demonstrates the basic usage of the Focus struct, including creating an instance, requesting focus, and checking the current focus state. ```Rust use tessera_ui::Focus; // Create a focus instance for a component let button_focus = Focus::new(); // Request focus for this component button_focus.request_focus(); // Check if this component currently has focus if button_focus.is_focused() { println!("Button is focused!"); } // Focus is automatically cleared when the instance is dropped drop(button_focus); ``` -------------------------------- ### Run Tessera App with Defaults Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/struct.Renderer Starts the Tessera application using default configuration on desktop platforms. It takes an entry point function for UI definition and a pipeline registration function. ```APIDOC Renderer::run(entry_point: F, register_pipelines_fn: R) -> Result<(), EventLoopError> - Runs the Tessera application with default configuration on desktop platforms. - Uses default TesseraConfig settings (e.g., 4x MSAA). - Parameters: - entry_point: A function that defines your UI. This function will be called every frame to build the component tree. - register_pipelines_fn: A function that registers rendering pipelines with the WGPU app. Typically, you’ll call `tessera_ui_basic_components::pipelines::register_pipelines(app)` here. - Returns: Ok(()) when the application exits normally, or an EventLoopError if the event loop fails to start or encounters a critical error. - Example: ```rust use tessera_ui::Renderer; fn my_ui() { // Your UI components go here } fn main() -> Result<(), Box> { Renderer::run( my_ui, |_app| { // Register your rendering pipelines here // tessera_ui_basic_components::pipelines::register_pipelines(app); } )?; Ok(()) } ``` ``` -------------------------------- ### Tessera UI Desktop Platform Support Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/index Example for running the Tessera UI renderer on desktop platforms (Windows, Linux, macOS). It requires marking component functions with the `#[tessera]` macro. ```rust use tessera_ui::Renderer; use tessera_ui_macros::tessera; #[tessera] // You need to mark every component function with `#[tessera_macros::tessera]` fn entry_point() {} fn register_pipelines(_: &mut tessera_ui::renderer::WgpuApp) {} Renderer::run(entry_point, register_pipelines)?; ``` -------------------------------- ### Create PipelineRegistry Instance Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer/drawer/pipeline.rs Creates a new, empty `PipelineRegistry`. This is the starting point for managing rendering pipelines. ```rust impl PipelineRegistry { /// Creates a new empty pipeline registry. /// /// # Example /// /// ```rust /// use tessera_ui::renderer::drawer::PipelineRegistry; /// /// let registry = PipelineRegistry::new(); /// ``` pub fn new() -> Self { Self { pipelines: Vec::new(), } } // ... other methods ``` -------------------------------- ### Desktop Platform Usage Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer.rs Illustrates the setup for running Tessera UI applications on desktop platforms (Windows, Linux, macOS). It highlights the need for the `#[tessera]` macro on the entry point function. ```rust use tessera_ui::Renderer; use tessera_ui_macros::tessera; #[tessera] // You need to mark every component function with `#[tessera_macros::tessera]` fn entry_point() {} fn register_pipelines(_: &mut tessera_ui::renderer::WgpuApp) {} fn main() -> Result<(), Box> { Renderer::run(entry_point, register_pipelines)?; Ok(()) } ``` -------------------------------- ### PxPosition Usage Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/px/struct.PxPosition Demonstrates common operations with PxPosition, including creation, offsetting, calculating distances, and arithmetic operations. ```Rust use tessera_ui::px::{Px, PxPosition}; // Create a position let position = PxPosition::new(Px::new(100), Px::new(200)); // Offset the position let offset_position = position.offset(Px::new(10), Px::new(-5)); // Calculate distance between positions let other_position = PxPosition::new(Px::new(103), Px::new(196)); let distance = position.distance_to(other_position); // Arithmetic operations let sum = position + other_position; let diff = position - other_position; ``` -------------------------------- ### WGSL Compute Shader Example Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer/compute/pipeline.rs An example of a WGSL compute shader that adjusts the brightness of an input texture and writes the result to an output texture. It defines bindings for uniforms, input textures, and output storage textures, and implements the main compute logic. ```WGSL @group(0) @binding(0) var brightness: f32; @group(0) @binding(1) var input_texture: texture_2d; @group(0) @binding(2) var output_texture: texture_storage_2d; @compute @workgroup_size(8, 8) fn main(@builtin(global_invocation_id) global_id: vec3) { let coords = vec2(global_id.xy); let input_color = textureLoad(input_texture, coords, 0); let output_color = vec4(input_color.rgb * brightness, input_color.a); textureStore(output_texture, coords, output_color); } ``` -------------------------------- ### Tessera UI Android Platform Support Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/index Example for running the Tessera UI renderer on Android. It involves using `winit::platform::android::activity::AndroidApp` and the `android_main` function. ```rust use tessera_ui::Renderer; use winit::platform::android::activity::AndroidApp; fn entry_point() {} fn register_pipelines(_: &mut tessera_ui::renderer::WgpuApp) {} fn android_main(android_app: AndroidApp) { Renderer::run(entry_point, register_pipelines, android_app).unwrap(); } ``` -------------------------------- ### PipelineRegistry::new() Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/drawer/struct.PipelineRegistry Constructs a new, empty PipelineRegistry. This is the starting point for setting up the rendering pipeline management. ```rust use tessera_ui::renderer::drawer::PipelineRegistry; let registry = PipelineRegistry::new(); ``` -------------------------------- ### Initial Clear Render Pass Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer/app.rs Sets up and begins a WGPU render pass with an initial clear operation for the color attachment. This prepares the rendering target for subsequent drawing operations. ```rust let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Initial Clear Pass"), color_attachments: &[Some(wgpu::RenderPassColorAttachment { view, depth_slice: None, resolve_target, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), store: wgpu::StoreOp::Store, }, })], ..Default::default() }); self.drawer .begin_pass(&self.gpu, &self.queue, &self.config, &mut rpass); self.drawer .end_pass(&self.gpu, &self.queue, &self.config, &mut rpass); ``` -------------------------------- ### Android Platform Usage Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer.rs Provides an example of how to run a Tessera UI application on Android. It requires the `AndroidApp` from `winit` and uses a conditional compilation block for Android targets. ```rust # #[cfg(target_os = "android")] use winit::platform::android::activity::AndroidApp; use tessera_ui::Renderer; fn entry_point() {} fn register_pipelines(_: &mut tessera_ui::renderer::WgpuApp) {} # #[cfg(target_os = "android")] fn android_main(android_app: AndroidApp) { Renderer::run(entry_point, register_pipelines, android_app).unwrap(); } ``` -------------------------------- ### Tessera UI Custom Rendering Pipeline Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/index Illustrates how to set up a custom rendering pipeline for the Tessera UI renderer. It shows a function `register_custom_pipelines` that can be passed to `Renderer::run`. ```rust use tessera_ui::{Renderer, renderer::WgpuApp}; fn register_custom_pipelines(app: &mut WgpuApp) { // Register basic components first // tessera_ui_basic_components::pipelines::register_pipelines(app); // Add your custom pipelines // app.drawer.register_pipeline("my_custom_shader", my_pipeline); } fn main() -> Result<(), Box> { Renderer::run( || { /* your UI */ }, register_custom_pipelines )?; Ok(()) } ``` -------------------------------- ### Dp Usage Examples Source: https://docs.rs/tessera-ui/latest/tessera_ui/dp/struct.Dp Demonstrates common UI measurements using the Dp struct and basic arithmetic operations on its inner value. It also shows how to convert Dp values to pixels for rendering. ```rust use tessera_ui::Dp; // Common UI measurements in dp let small_padding = Dp(8.0); let medium_padding = Dp(16.0); let button_height = Dp(48.0); let large_spacing = Dp(32.0); // Convert to pixels for rendering let pixels = button_height.to_pixels_f64(); // Result depends on the current scale factor let base_size = Dp(16.0); let double_size = Dp(base_size.0 * 2.0); let half_size = Dp(base_size.0 / 2.0); // Example for compile-time constant const BUTTON_HEIGHT: Dp = Dp::new(48.0); let padding = Dp::new(16.0); ``` -------------------------------- ### Rust ComputablePipeline Dispatch Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/compute/pipeline/trait.ComputablePipeline Illustrates the typical implementation pattern for a `ComputablePipeline` in Rust. It shows how to create uniform buffers, bind groups with textures and uniforms, and dispatch workgroups within a compute pass. ```rust impl ComputablePipeline for MyPipeline { fn dispatch(&mut self, device, queue, config, compute_pass, command, resource_manager, input_view, output_view) { // 1. Create or retrieve uniform buffer let uniforms = create_uniforms_from_command(command); let uniform_buffer = device.create_buffer_init(...); // 2. Create bind group with textures and uniforms let bind_group = device.create_bind_group(...); // 3. Set pipeline and dispatch compute_pass.set_pipeline(&self.compute_pipeline); compute_pass.set_bind_group(0, &bind_group, &[]); compute_pass.dispatch_workgroups(workgroup_x, workgroup_y, 1); } } ``` -------------------------------- ### Tessera UI Focus Usage Example (Rust) Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/focus_state.rs Demonstrates how to create a `Focus` instance for a component, request focus, check the current focus state, and clear focus when no longer needed. ```rust use tessera_ui::Focus; // Create a new focus instance let focus = Focus::new(); // Check if this focus is currently active if focus.is_focused() { // Handle focused state } // Request focus for this component focus.request_focus(); // Clear focus when no longer needed focus.unfocus(); ``` -------------------------------- ### Px Usage Examples - Rust Source: https://docs.rs/tessera-ui/latest/tessera_ui/px/struct.Px Demonstrates creating Px instances, performing arithmetic operations, using saturating arithmetic, and converting Px values. Supports negative values for positioning. ```rust use tessera_ui::px::Px; // Create pixel values let px1 = Px::new(100); let px2 = Px::new(-50); // Negative values supported // Arithmetic operations let sum = px1 + px2; // Px(50) let doubled = px1 * 2; // Px(200) // Saturating arithmetic prevents overflow let max_px = Px::new(i32::MAX); let safe_add = max_px.saturating_add(Px::new(1)); // Still Px(i32::MAX) // Convert to absolute value for rendering let abs_value = Px::new(-10).abs(); // 0 (negative becomes 0) ``` -------------------------------- ### Color Usage Examples Source: https://docs.rs/tessera-ui/latest/tessera_ui/color/struct.Color Demonstrates how to use the Color struct, including accessing predefined constants like RED, WHITE, and TRANSPARENT, and creating custom colors using the Color::new() constructor. ```rust use tessera_ui::Color; // Using predefined colors let red = Color::RED; let white = Color::WHITE; let transparent = Color::TRANSPARENT; // Creating custom colors let purple = Color::new(0.5, 0.0, 0.5, 1.0); let semi_transparent_blue = Color::new(0.0, 0.0, 1.0, 0.5); ``` -------------------------------- ### Run Tessera App with Custom Configuration Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/struct.Renderer Starts the Tessera application with custom configuration on desktop platforms. This method allows customization of renderer behavior through `TesseraConfig`, such as MSAA sample count or other rendering parameters. ```APIDOC Renderer::run_with_config(entry_point: F, register_pipelines_fn: R, config: TesseraConfig) -> Result<(), EventLoopError> - Runs the Tessera application with custom configuration on desktop platforms. - Allows customization of renderer behavior through `TesseraConfig`. - Parameters: - entry_point: A function that defines your UI. - register_pipelines_fn: A function that registers rendering pipelines. - config: Custom configuration for the renderer. - Returns: Ok(()) when the application exits normally, or an EventLoopError if the event loop fails to start or encounters a critical error. ``` -------------------------------- ### Configure Tessera UI Renderer Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/index Shows how to customize the renderer's behavior using `TesseraConfig`. This example sets the MSAA sample count to 8 and passes the configuration to `Renderer::run_with_config`. ```rust use tessera_ui::{Renderer, renderer::TesseraConfig}; let config = TesseraConfig { sample_count: 8, // 8x MSAA }; Renderer::run_with_config( || { /* my_app */ }, |_app| { /* register_pipelines */ }, config )?; ``` -------------------------------- ### Rust: Arena get Method Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.Arena Provides examples for the `get` method, which retrieves an immutable reference to a node using its NodeId. It demonstrates successful retrieval and the behavior when the NodeId is not present or belongs to another arena. ```rust let mut arena = Arena::new(); let foo = arena.new_node("foo"); assert_eq!(arena.get(foo).map(|node| *node.get()), Some("foo")); ``` ```rust let mut arena = Arena::new(); let foo = arena.new_node("foo"); let bar = arena.new_node("bar"); assert_eq!(arena.get(foo).map(|node| *node.get()), Some("foo")); let mut another_arena = Arena::new(); let _ = another_arena.new_node("Another arena"); assert_eq!(another_arena.get(foo).map(|node| *node.get()), Some("Another arena")); assert!(another_arena.get(bar).is_none()); ``` -------------------------------- ### Rust: Arena get_mut Method Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.Arena Demonstrates the `get_mut` method for obtaining a mutable reference to a node. The example shows how to modify the node's data and verifies the change using the `get` method. ```rust let mut arena = Arena::new(); let foo = arena.new_node("foo"); assert_eq!(arena.get(foo).map(|node| *node.get()), Some("foo")); *arena.get_mut(foo).expect("The `foo` node exists").get_mut() = "FOO!"; assert_eq!(arena.get(foo).map(|node| *node.get()), Some("FOO!")); ``` -------------------------------- ### Build Basic Tessera Application Source: https://docs.rs/tessera-ui/latest/tessera_ui Demonstrates setting up a simple Tessera UI application. It initializes a Renderer, uses basic components like `surface` and `text`, and applies styling with `Color` and `Dp`. This snippet requires `tessera_ui` and `tessera_ui_basic_components`. ```rust use tessera_ui::{Renderer, Color, Dp}; use tessera_ui_basic_components::*; use tessera_ui_macros::tessera; #[tessera] fn my_app() { surface( SurfaceArgs { color: Color::WHITE, padding: Dp(20.0), ..Default::default() }, None, || text("Hello, Tessera!"), ); } ``` -------------------------------- ### Build Basic Tessera Application Source: https://docs.rs/tessera-ui/latest/tessera_ui/index Demonstrates setting up a simple Tessera UI application. It initializes a Renderer, uses basic components like `surface` and `text`, and applies styling with `Color` and `Dp`. This snippet requires `tessera_ui` and `tessera_ui_basic_components`. ```rust use tessera_ui::{Renderer, Color, Dp}; use tessera_ui_basic_components::*; use tessera_ui_macros::tessera; #[tessera] fn my_app() { surface( SurfaceArgs { color: Color::WHITE, padding: Dp(20.0), ..Default::default() }, None, || text("Hello, Tessera!"), ); } ``` -------------------------------- ### Rust: Get Surface Size Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer/app.rs Retrieves the current physical size of the rendering surface. This is a simple getter method. ```rust /// Get the size of the surface pub(crate) fn size(&self) -> winit::dpi::PhysicalSize { self.size } ``` -------------------------------- ### Build Basic Tessera App with Components Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/lib.rs Demonstrates setting up a basic Tessera application using `Renderer`, `Color`, `Dp`, and `tessera_basic_components`. It shows how to use the `surface` and `text` components for a simple UI element. ```rust use tessera_ui::{Renderer, Color, Dp}; use tessera_ui_basic_components::*; use tessera_ui_macros::tessera; #[tessera] fn my_app() { surface( SurfaceArgs { color: Color::WHITE, padding: Dp(20.0), ..Default::default() }, None, || text("Hello, Tessera!"), ); } ``` -------------------------------- ### Initialize WGPU Application Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer/app.rs Initializes a new WGPU application instance by setting up the WGPU instance, adapter, device, queue, and surface. It configures the surface based on window properties and backend capabilities, preparing the application for rendering operations using the wgpu and winit crates. ```rust use std::{mem, sync::Arc}; use log::{error, info, warn}; use parking_lot::RwLock; use wgpu::TextureFormat; use winit::window::Window; use crate::{ ComputeCommand, PxPosition, compute::resource::ComputeResourceManager, dp::SCALE_FACTOR, px::PxSize, renderer::command::Command, }; use super::{compute::ComputePipelineRegistry, drawer::Drawer}; // Render pass resources for ping-pong operation struct PassTarget { texture: wgpu::Texture, view: wgpu::TextureView, } pub struct WgpuApp { /// Avoiding release the window #[allow(unused)] pub window: Arc, /// WGPU device pub gpu: wgpu::Device, /// WGPU surface surface: wgpu::Surface<'static>, /// WGPU queue pub queue: wgpu::Queue, /// WGPU surface configuration pub config: wgpu::SurfaceConfiguration, /// size of the window size: winit::dpi::PhysicalSize, /// if size is changed size_changed: bool, /// draw pipelines pub drawer: Drawer, /// compute pipelines pub compute_pipeline_registry: ComputePipelineRegistry, // --- New ping-pong rendering resources --- pass_a: PassTarget, pass_b: PassTarget, // --- MSAA resources --- pub sample_count: u32, msaa_texture: Option, msaa_view: Option, // --- Compute resources --- compute_target_a: PassTarget, compute_target_b: PassTarget, compute_commands: Vec>, pub resource_manager: Arc>, } impl WgpuApp { /// Create a new WGPU app, as the root of Tessera pub(crate) async fn new(window: Arc, sample_count: u32) -> Self { // Looking for gpus let instance: wgpu::Instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { backends: wgpu::Backends::all(), ..Default::default() }); // Create a surface let surface = match instance.create_surface(window.clone()) { Ok(surface) => surface, Err(e) => { error!("Failed to create surface: {e:?}"); panic!("Failed to create surface: {e:?}"); } }; // Looking for adapter gpu let adapter = match instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), compatible_surface: Some(&surface), force_fallback_adapter: false, }) .await { Ok(gpu) => gpu, Err(e) => { error!("Failed to find an appropriate adapter: {e:?}"); panic!("Failed to find an appropriate adapter: {e:?}"); } }; // Create a device and queue let (gpu, queue) = match adapter .request_device(&wgpu::DeviceDescriptor { required_features: wgpu::Features::empty(), // WebGL backend does not support all features required_limits: if cfg!(target_arch = "wasm32") { wgpu::Limits::downlevel_webgl2_defaults() } else { wgpu::Limits::default() }, label: None, memory_hints: wgpu::MemoryHints::Performance, trace: wgpu::Trace::Off, }) .await { Ok((gpu, queue)) => (gpu, queue), Err(e) => { error!("Failed to create device: {e:?}"); panic!("Failed to create device: {e:?}"); } }; // Create surface configuration let size = window.inner_size(); let caps = surface.get_capabilities(&adapter); // Choose the present mode let present_mode = if caps.present_modes.contains(&wgpu::PresentMode::Fifo) { // Fifo is the fallback, it is the most compatible and stable wgpu::PresentMode::Fifo } else { // Immediate is the least preferred, it can cause tearing and is not recommended wgpu::PresentMode::Immediate }; info!("Using present mode: {present_mode:?}"); let config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST, format: caps.formats[0], width: size.width, height: size.height, present_mode, alpha_mode: caps.alpha_modes[0], view_formats: vec![], desired_maximum_frame_latency: 2, }; surface.configure(&gpu, &config); // Placeholder for actual initialization of other fields like drawer, pipelines, etc. // This example only shows the WGPU setup part. unimplemented!("Full WgpuApp initialization not shown in this snippet"); } } ``` -------------------------------- ### Rust: Arena is_empty Method Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.Arena Shows how to use the `is_empty` method to check if the Arena contains any nodes. The example verifies its behavior when nodes are added and subsequently removed. ```rust let mut arena = Arena::new(); assert!(arena.is_empty()); let foo = arena.new_node("foo"); assert!(!arena.is_empty()); foo.remove(&mut arena); assert!(!arena.is_empty()); ``` -------------------------------- ### Initialize WGPU App and Window Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer.rs Handles the `resumed` event from winit, creating the application window, initializing the WGPU context, and registering rendering pipelines. It ensures the app is only initialized once. ```rust fn resumed(&mut self, event_loop: &ActiveEventLoop) { // Just return if the app is already created if self.app.is_some() { return; } // Create a new window let window_attributes = Window::default_attributes() .with_title("Tessera") .with_transparent(true); let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); let register_pipelines_fn = self.register_pipelines_fn.clone(); let mut wgpu_app = tokio_runtime::get().block_on(WgpuApp::new(window, self.config.sample_count)); // Register pipelines wgpu_app.register_pipelines(register_pipelines_fn); self.app = Some(wgpu_app); } ``` -------------------------------- ### Depth-First Pre-order Traversal (Rust) Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.NodeId Yields node edges (start and end) during a depth-first pre-order traversal. Children are visited in insertion order, and node edges are visited from start to end. ```rust pub fn traverse<'a, T>(self, arena: &'a Arena) -> Traverse<'a, T> // An iterator of the “sides” of a node visited during a depth-first pre-order traversal, // where node sides are visited start to end and children are visited in insertion order. // i.e. node.start -> first child -> second child -> node.end // Example: // let mut iter = n1.traverse(&arena); // assert_eq!(iter.next(), Some(NodeEdge::Start(n1))); // assert_eq!(iter.next(), Some(NodeEdge::Start(n1_1))); // assert_eq!(iter.next(), Some(NodeEdge::Start(n1_1_1))); // assert_eq!(iter.next(), Some(NodeEdge::End(n1_1_1))); // assert_eq!(iter.next(), Some(NodeEdge::End(n1_1))); // assert_eq!(iter.next(), Some(NodeEdge::Start(n1_2))); // assert_eq!(iter.next(), Some(NodeEdge::End(n1_2))); // assert_eq!(iter.next(), Some(NodeEdge::Start(n1_3))); // assert_eq!(iter.next(), Some(NodeEdge::End(n1_3))); // assert_eq!(iter.next(), Some(NodeEdge::End(n1))); // assert_eq!(iter.next(), None); ``` -------------------------------- ### Basic Renderer Usage Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer.rs Demonstrates the fundamental way to run a Tessera UI application using the `Renderer::run` method. It requires an entry point function for the UI and a callback for registering rendering pipelines. ```rust use tessera_ui::Renderer; // Define your UI entry point fn my_app() { // Your UI components go here } // Run the application Renderer::run( my_app, // Entry point function |_app| { // Register rendering pipelines // tessera_ui_basic_components::pipelines::register_pipelines(app); } ).unwrap(); ``` -------------------------------- ### Rust: Arena count Method Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.Arena Demonstrates the `count` method, which returns the total number of nodes currently present in the Arena. The example shows that removing a node does not decrement the count immediately. ```rust let mut arena = Arena::new(); let foo = arena.new_node("foo"); let _bar = arena.new_node("bar"); assert_eq!(arena.count(), 2); foo.remove(&mut arena); assert_eq!(arena.count(), 2); ``` -------------------------------- ### Run Tessera UI Application Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/index Demonstrates the basic usage of the Tessera UI renderer by calling the `Renderer::run` method. This method takes an application entry point function and a pipeline registration function. ```rust use tessera_ui::Renderer; // Define your UI entry point fn my_app() { // Your UI components go here } // Run the application Renderer::run( my_app, // Entry point function |_app| { // Register rendering pipelines // tessera_ui_basic_components::pipelines::register_pipelines(app); } ).unwrap(); ``` -------------------------------- ### Rust Example: Using PressKeyEventType Enum Source: https://docs.rs/tessera-ui/latest/tessera_ui/enum.PressKeyEventType Demonstrates how to use the PressKeyEventType enum within a Rust match statement to handle different cursor button press events. This example shows mapping enum variants to specific actions or messages. ```rust use tessera_ui::cursor::PressKeyEventType; match button_type { PressKeyEventType::Left => println!("Primary button (usually left-click)"), PressKeyEventType::Right => println!("Secondary button (usually right-click)"), PressKeyEventType::Middle => println!("Middle button (usually scroll wheel click)"), } ``` -------------------------------- ### Handle Touch Start Event (Rust) Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/cursor.rs Manages the initiation of a touch gesture. This function registers a new touch point with its unique ID and initial position, generates a 'Pressed' event, and disables any ongoing inertial scrolling. It requires a touch ID and the starting pixel position. ```rust pub fn handle_touch_start(&mut self, touch_id: u64, position: PxPosition) { self.active_inertia = None; // Stop any existing inertia on new touch let now = Instant::now(); self.touch_points.insert( touch_id, TouchPointState { last_position: position, last_update_time: now, velocity_history: VecDeque::new(), }, ); self.update_position(position); let press_event = CursorEvent { timestamp: now, content: CursorEventContent::Pressed(PressKeyEventType::Left), }; self.push_event(press_event); } ``` -------------------------------- ### Initialize Application State with WGPU and Scale Factor (Rust) Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/renderer/app.rs Initializes the application's state, including WGPU components, render targets, and a global scale factor. The scale factor is retrieved from the window and stored for DP conversion, logging its value upon retrieval. ```rust // --- Create MSAA Target --- let (msaa_texture, msaa_view) = if sample_count > 1 { let texture = gpu.create_texture(&wgpu::TextureDescriptor { label: Some("MSAA Framebuffer"), size: wgpu::Extent3d { width: config.width, height: config.height, depth_or_array_layers: 1, }, mip_level_count: 1, sample_count, dimension: wgpu::TextureDimension::D2, // Use surface format to match pass targets format: config.format, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, view_formats: &[], }); let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); (Some(texture), Some(view)) } else { (None, None) }; // --- Create Pass Targets (A and B and Compute) --- let pass_a = Self::create_pass_target(&gpu, &config, "A"); let pass_b = Self::create_pass_target(&gpu, &config, "B"); let compute_target_a = Self::create_compute_pass_target(&gpu, &config, TextureFormat::Rgba8Unorm, "Compute A"); let compute_target_b = Self::create_compute_pass_target(&gpu, &config, TextureFormat::Rgba8Unorm, "Compute B"); let drawer = Drawer::new(); // Set scale factor for dp conversion let scale_factor = window.scale_factor(); info!("Window scale factor: {scale_factor}"); SCALE_FACTOR .set(RwLock::new(scale_factor)) .expect("Failed to set scale factor"); Self { window, gpu, surface, queue, config, size, size_changed: false, drawer, pass_a, pass_b, compute_pipeline_registry: ComputePipelineRegistry::new(), sample_count, msaa_texture, msaa_view, compute_target_a, compute_target_b, compute_commands: Vec::new(), resource_manager: Arc::new(RwLock::new(ComputeResourceManager::new())), } ``` -------------------------------- ### Rendering System Source: https://docs.rs/tessera-ui/latest/src/tessera_ui/lib.rs Explains the rendering pipeline, including the drawing and compute systems, and the commands used to execute rendering operations. ```rust //! ### Rendering System //! - [`renderer::drawer`] - Drawing pipeline system //! - [`renderer::compute`] - Compute pipeline system //! - [`DrawCommand`], [`ComputeCommand`] - Rendering commands ``` -------------------------------- ### PxPosition to_f64_arr2 Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/px/struct.PxPosition Shows how to convert a PxPosition to a 2D array of f64 values. ```rust use tessera_ui::px::{Px, PxPosition}; let position = PxPosition::new(Px::new(10), Px::new(20)); assert_eq!(position.to_f64_arr2(), [10.0, 20.0]); ``` -------------------------------- ### Run Tessera UI Application Source: https://docs.rs/tessera-ui/latest/tessera_ui/renderer/struct.Renderer Demonstrates how to run the Tessera UI application with custom configuration, including sample count for MSAA. ```rust use tessera_ui::{Renderer, renderer::TesseraConfig}; let config = TesseraConfig { sample_count: 8, // 8x MSAA for higher quality }; Renderer::run_with_config( || { /* my_ui */ }, |_app| { /* register_pipelines */ }, config )?; ``` -------------------------------- ### Node::remove_subtree Example Source: https://docs.rs/tessera-ui/latest/tessera_ui/struct.NodeId Shows how to remove a node and all its descendants from the arena, updating the tree structure accordingly. ```rust // arena // `-- 1 // |-- 1_1 // |-- 1_2 * // | |-- 1_2_1 // | `-- 1_2_2 // `-- 1_3 n1_2.remove_subtree(&mut arena); // arena // `-- 1 // |-- 1_1 // `-- 1_3 let mut iter = n1.descendants(&arena); assert_eq!(iter.next(), Some(n1)); assert_eq!(iter.next(), Some(n1_1)); assert_eq!(iter.next(), Some(n1_3)); assert_eq!(iter.next(), None); ```