Introduction to bevy_cef
bevy_cef is a powerful Bevy plugin that integrates the Chromium Embedded Framework (CEF) into Bevy applications, enabling you to render web content as 3D objects in your game world or as UI overlays.
What is bevy_cef?
bevy_cef bridges the gap between modern web technologies and Bevy's 3D engine by:
- Embedding webviews as textures on 3D meshes or 2D sprites
- Supporting bidirectional communication between JavaScript and Bevy systems
- Providing a multi-process architecture for stability and performance
- Offering local asset serving through a custom URL scheme
- Enabling developer tools integration for debugging web content
Key Features
🌐 Web Content Rendering
- Render any web page as a texture on 3D objects
- Support for HTML5, CSS3, and modern JavaScript
- Local file serving via the
cef://localhost/
scheme - Remote web page loading with full browser compatibility
🔄 Inter-Process Communication (IPC)
- JS Emit: Send events from JavaScript to Bevy systems
- Host Emit: Send events from Bevy to JavaScript
- Bevy Remote Protocol (BRP): Bidirectional RPC communication
🎮 Interactive Controls
- Keyboard input forwarding to webviews
- Mouse interaction support
- Navigation controls (back, forward, refresh)
- Zoom level management
- Audio muting capabilities
🔧 Developer Experience
- Chrome DevTools integration for debugging
- Hot-reload support for local assets
- Comprehensive error handling and logging
- Extensive customization options
Architecture Overview
bevy_cef uses a multi-process architecture similar to modern web browsers:
- Browser Process: The main Bevy application process
- Render Process: Separate CEF process for web content rendering
- IPC Communication: Secure inter-process communication channels
This design ensures stability - if a web page crashes, it won't bring down your entire application.
Use Cases
Game UI
Create rich, responsive game interfaces using familiar web technologies:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("ui/main-menu.html"), // Render as 2D sprite overlay )); }
In-World Displays
Embed interactive web content directly in your 3D world:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::new("https://example.com"), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
Data Visualization
Display real-time data using web-based charting libraries:
#![allow(unused)] fn main() { // Load a local HTML file with Chart.js or D3.js commands.spawn(( CefWebviewUri::local("charts/dashboard.html"), WebviewSize(Vec2::new(1920.0, 1080.0)), )); }
Development Tools
Integrate web-based development and debugging interfaces directly into your game editor or development build.
Getting Started
Ready to integrate web content into your Bevy application? Check out the Quick Start guide to get up and running in minutes, or dive into Basic Concepts to understand the fundamental components and systems.
Platform Support
Currently, bevy_cef focuses on macOS development with plans for expanded platform support. The plugin automatically handles CEF framework installation and configuration on supported platforms.
Installation
This guide will help you set up bevy_cef in your Bevy project.
Prerequisites
System Requirements
- macOS: Currently the primary supported platform
- Rust: 1.70 or later
- Bevy: 0.16 or later
Adding bevy_cef to Your Project
1. Add the Dependency
Add bevy_cef to your Cargo.toml
:
[dependencies]
bevy = "0.16"
bevy_cef = { version = "0.1", features = ["debug"] }
2. Enable the Plugin
Add the CefPlugin
to your Bevy app:
use bevy::prelude::*; use bevy_cef::prelude::*; fn main() { App::new() .add_plugins((DefaultPlugins, CefPlugin)) .run(); }
Automatic Setup with Debug Feature
When you enable the debug
feature (recommended for development), the build system automatically handles everything for you:
✅ Downloads and extracts CEF framework to $HOME/.local/share/cef
✅ Installs the bevy_cef_debug_render_process
tool
✅ Installs the export-cef-dir
tool
✅ Configures all necessary environment variables
Simply run your project:
cargo run
That's it! No manual installation required.
Production Builds
For production builds where you want to minimize dependencies, you can omit the debug feature:
[dependencies]
bevy = "0.16"
bevy_cef = "0.1" # No debug feature
However, you'll need to ensure the CEF framework is available at runtime. The debug feature is recommended for most development scenarios.
Verification
To verify your installation is working correctly, try running this simple example:
use bevy::prelude::*; use bevy_cef::prelude::*; fn main() { App::new() .add_plugins((DefaultPlugins, CefPlugin)) .add_systems(Startup, setup) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<WebviewExtendStandardMaterial>>, ) { // Camera commands.spawn(( Camera3d::default(), Transform::from_xyz(0.0, 0.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y), )); // Light commands.spawn(( DirectionalLight::default(), Transform::from_xyz(1.0, 1.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y), )); // Webview commands.spawn(( CefWebviewUri::new("https://bevy.org"), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
If you see the Bevy website rendered on a plane in your 3D scene, your installation is successful!
Troubleshooting
Common Installation Issues
Build Fails with Debug Feature
- Ensure you have internet connection for CEF download
- Check available disk space in
$HOME/.local/share/
- Try cleaning and rebuilding:
cargo clean && cargo build
CEF Framework Issues
- The debug feature handles CEF installation automatically
- If issues persist, delete
$HOME/.local/share/cef
and rebuild
Linker Errors on macOS
- Verify Xcode Command Line Tools are installed:
xcode-select --install
- The debug feature should handle DYLD environment variables automatically
For more troubleshooting information, see the Troubleshooting section.
Next Steps
Now that you have bevy_cef installed, check out:
- Quick Start - Build your first webview in minutes
- Basic Concepts - Understand the core components
- Examples - Explore practical examples
Quick Start
Get up and running with bevy_cef in just a few minutes! This guide will walk you through creating your first webview-enabled Bevy application.
Create a New Project
Start by creating a new Bevy project:
cargo new my_webview_app
cd my_webview_app
Add Dependencies
Add bevy_cef to your Cargo.toml
:
[dependencies]
bevy = "0.16"
bevy_cef = { version = "0.1", features = ["debug"] }
Your First Webview
Replace the contents of src/main.rs
with:
use bevy::prelude::*; use bevy_cef::prelude::*; fn main() { App::new() .add_plugins((DefaultPlugins, CefPlugin)) .add_systems(Startup, setup) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<WebviewExtendStandardMaterial>>, ) { // Spawn a camera commands.spawn(( Camera3d::default(), Transform::from_translation(Vec3::new(0.0, 0.0, 3.0)) .looking_at(Vec3::ZERO, Vec3::Y), )); // Spawn a light commands.spawn(( DirectionalLight::default(), Transform::from_translation(Vec3::new(1.0, 1.0, 1.0)) .looking_at(Vec3::ZERO, Vec3::Y), )); // Spawn a webview on a 3D plane commands.spawn(( CefWebviewUri::new("https://bevy.org"), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
Run Your Application
cargo run
That's it! You should see the Bevy website rendered on a 3D plane in your application. The first run might take a moment as bevy_cef downloads and sets up the CEF framework automatically.
What Just Happened?
Let's break down the key components:
1. CefPlugin
#![allow(unused)] fn main() { .add_plugins((DefaultPlugins, CefPlugin)) }
The CefPlugin
initializes the CEF framework and sets up all necessary systems for webview rendering.
2. CefWebviewUri
#![allow(unused)] fn main() { CefWebviewUri::new("https://bevy.org") }
This component specifies what web content to load. You can use:
- Remote URLs:
"https://example.com"
- Local files:
CefWebviewUri::local("index.html")
3. WebviewExtendStandardMaterial
#![allow(unused)] fn main() { MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())) }
This special material renders the webview content as a texture on your 3D mesh.
Try Local Content
Create an assets/
directory and add a simple HTML file:
mkdir assets
Create assets/hello.html
:
<!DOCTYPE html>
<html>
<head>
<title>Hello bevy_cef!</title>
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
color: white;
text-align: center;
padding: 50px;
}
</style>
</head>
<body>
<h1>Hello from bevy_cef! 🎮</h1>
<p>This HTML is rendered directly on a 3D mesh!</p>
<p>Current time: <span id="time"></span></p>
<script>
function updateTime() {
document.getElementById('time').textContent = new Date().toLocaleTimeString();
}
setInterval(updateTime, 1000);
updateTime();
</script>
</body>
</html>
Update your webview URI in main.rs
:
#![allow(unused)] fn main() { CefWebviewUri::local("hello.html"), // Load local file }
Run again:
cargo run
You'll see your custom HTML content with a live-updating clock!
Next Steps
Explore More Features
- JavaScript Communication: Send data from web pages to Bevy
- Host Communication: Send data from Bevy to web pages
- 2D Sprites: Render webviews as UI elements
- Developer Tools: Debug your web content
Try More Examples
- Navigation: Add back/forward buttons
- Zoom Controls: Implement zoom in/out functionality
- Multiple Webviews: Render different content on multiple objects
Learn the Architecture
- Basic Concepts: Understand core components
- Multi-Process Design: How CEF integration works
- Plugin System: Deep dive into the plugin architecture
Common First Steps
Adding Interaction
Make your webview interactive by enabling input:
#![allow(unused)] fn main() { // In your setup system, also spawn input handling commands.spawn(( CefWebviewUri::local("interactive.html"), WebviewSize(Vec2::new(800.0, 600.0)), // Webview will automatically receive keyboard and mouse input Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
Sizing Your Webview
Control the resolution of your webview:
#![allow(unused)] fn main() { WebviewSize(Vec2::new(1920.0, 1080.0)), // High resolution WebviewSize(Vec2::new(800.0, 600.0)), // Standard resolution }
Multiple Webviews
You can have multiple webviews in the same scene:
#![allow(unused)] fn main() { // First webview commands.spawn(( CefWebviewUri::new("https://news.ycombinator.com"), Transform::from_translation(Vec3::new(-2.0, 0.0, 0.0)), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); // Second webview commands.spawn(( CefWebviewUri::local("dashboard.html"), Transform::from_translation(Vec3::new(2.0, 0.0, 0.0)), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
You're now ready to build amazing applications that blend 3D graphics with modern web technologies!
Basic Concepts
Understanding these fundamental concepts will help you make the most of bevy_cef in your projects.
Multi-Process Architecture
bevy_cef follows a multi-process architecture similar to modern web browsers:
Browser Process
- Main Application: Your Bevy game/app runs here
- CEF Management: Handles browser creation and management
- IPC Coordination: Manages communication with render processes
Render Process
- Web Content: Each webview runs in a separate process
- Isolation: Crashes in web content don't affect your main application
- Sandboxing: Enhanced security through process separation
Benefits
- Stability: Web content crashes won't crash your game
- Performance: CPU-intensive web content won't block your game loop
- Security: Sandboxed execution of untrusted web content
Core Components
bevy_cef provides several key components that work together:
CefWebviewUri
The primary component that defines what web content to display:
#![allow(unused)] fn main() { // Remote web page CefWebviewUri::new("https://example.com") // Local HTML file from assets/ CefWebviewUri::local("ui/menu.html") // Equivalent to above CefWebviewUri::new("cef://localhost/ui/menu.html") }
WebviewSize
Controls the rendering resolution of the webview (not the 3D object size):
#![allow(unused)] fn main() { WebviewSize(Vec2::new(1920.0, 1080.0)) // High resolution WebviewSize(Vec2::new(800.0, 600.0)) // Standard resolution WebviewSize::default() // 800x800 pixels }
Material Integration
Webviews integrate with Bevy's material system:
#![allow(unused)] fn main() { // Standard material with webview texture WebviewExtendStandardMaterial::default() // Custom material properties WebviewExtendStandardMaterial { base: StandardMaterial { unlit: true, emissive: Color::WHITE.into(), ..default() }, ..default() } }
Component Requirements
When you add a CefWebviewUri
component, bevy_cef automatically requires several other components:
#![allow(unused)] fn main() { #[require(WebviewSize, ZoomLevel, AudioMuted)] pub struct CefWebviewUri(pub String); }
This means every webview entity automatically gets:
- WebviewSize: Default 800x800 resolution
- ZoomLevel: Default zoom (0.0 = browser default)
- AudioMuted: Default unmuted (false)
Rendering Modes
bevy_cef supports different rendering approaches:
3D Mesh Rendering
Render web content on 3D objects in your world:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("interface.html"), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
2D Sprite Rendering
Render web content as UI overlays:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("hud.html"), Sprite::default(), WebviewSpriteMaterial::default(), )); }
Local Asset Serving
bevy_cef includes a built-in web server that serves files from your assets/
directory:
Custom Scheme
- Scheme:
cef://localhost/
- Path Mapping:
assets/
directory maps to the root - Example:
assets/ui/menu.html
→cef://localhost/ui/menu.html
Supported File Types
- HTML, CSS, JavaScript
- Images (PNG, JPG, SVG, etc.)
- Fonts (WOFF, TTF, etc.)
- JSON, XML, and other data files
Asset Organization
assets/
├── ui/
│ ├── menu.html
│ ├── styles.css
│ └── script.js
├── images/
│ └── logo.png
└── data/
└── config.json
Inter-Process Communication (IPC)
bevy_cef provides three communication patterns:
1. JavaScript to Bevy (JS Emit)
Send events from web content to Bevy systems:
// In your HTML/JavaScript
window.cef.emit('player_action', { action: 'jump', power: 10 });
fn main(){ App::new() .add_plugins(JsEmitEventPlugin::<PlayerAction>::default()) // ... } // In your Bevy system #[derive(Event, Deserialize)] struct PlayerAction { action: String, power: i32, } fn handle_player_action(trigger: Trigger<PlayerAction>) { let action = trigger.event(); info!("Player action: {} with power {}", action.action, action.power); }
2. Bevy to JavaScript (Host Emit)
Send events from Bevy to web content:
#![allow(unused)] fn main() { // In your Bevy system commands.entity(webview_entity).trigger(HostEmitEvent { event_name: "score_update".to_string(), data: json!({ "score": 1000, "level": 3 }), }); }
// In your HTML/JavaScript
window.cef.listen('score_update', (data) => {
document.getElementById('score').textContent = data.score;
document.getElementById('level').textContent = data.level;
});
3. Bevy Remote Protocol (BRP)
Please see here for about the Bevy Remote Protocol (BRP).
Bidirectional RPC calls for complex interactions:
#![allow(unused)] fn main() { // Register BRP method in Bevy app.add_plugins(RemotePlugin::default().with_method("get_player_stats", get_stats)); }
// Call from JavaScript
const stats = await window.cef.brp({
method: 'get_player_stats',
params: { playerId: 42 }
});
User Interaction
Input Handling
Webviews automatically receive keyboard and mouse input when focused:
- Keyboard: All keyboard events are forwarded
- Mouse: Click, scroll, and hover events work naturally
- Focus: Multiple webviews can coexist; input goes to the focused one
Navigation
Control web navigation programmatically:
#![allow(unused)] fn main() { commands.entity(webview).trigger(RequestGoBack); commands.entity(webview).trigger(ReqeustGoForward); }
Zoom Control
Manage zoom levels per webview:
#![allow(unused)] fn main() { // Set zoom level (0.0 = default, positive = zoom in, negative = zoom out) commands.entity(webview).insert(ZoomLevel(1.2)); // Reset to default zoom commands.entity(webview).insert(ZoomLevel(0.0)); }
Developer Experience
Developer Tools
Access Chrome DevTools for debugging:
#![allow(unused)] fn main() { // Show developer tools for a webview commands.entity(webview).trigger(RequestShowDevTool); // Close developer tools commands.entity(webview).trigger(RequestCloseDevtool); }
Hot Reload
Local assets automatically reload when changed during development.
Best Practices
Component Organization
#![allow(unused)] fn main() { // Good: Group related components commands.spawn(( // The uri convert to `cef://localhost/index.html` CefWebviewUri::local("index.html"), WebviewSize(Vec2::new(1920.0, 200.0)), ZoomLevel(0.8), AudioMuted(true), Transform::from_translation(Vec3::new(0.0, 5.0, 0.0)), Mesh3d(meshes.add(Quad::new(Vec2::new(4.0, 1.0)))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); }
Next Steps
Now that you understand the basic concepts:
- Explore Core Components in detail
- Learn about Webview Rendering techniques
- Dive into Inter-Process Communication patterns
- Check out practical Examples
Core Components
bevy_cef provides several essential components that control webview behavior. Understanding these components is crucial for effective use of the library.
Component Overview
Component | Purpose | Default Value | Required |
---|---|---|---|
CefWebviewUri | Specifies web content URL | None | ✅ Primary |
WebviewSize | Controls rendering resolution | 800×800 | ✅ Auto-added |
ZoomLevel | Controls webview zoom | 0.0 (default) | ✅ Auto-added |
AudioMuted | Controls audio output | false (unmuted) | ✅ Auto-added |
HostWindow | Parent window specification | Primary window | ❌ Optional |
CefWebviewUri
The primary component that defines what web content to display.
Usage
#![allow(unused)] fn main() { use bevy_cef::prelude::*; // Remote web page let webview = CefWebviewUri::new("https://example.com"); // Local HTML file from assets/ directory let webview = CefWebviewUri::local("ui/menu.html"); // Equivalent to local() method let webview = CefWebviewUri::new("cef://localhost/ui/menu.html"); }
Implementation Details
#![allow(unused)] fn main() { #[derive(Component, Debug, Clone, PartialEq, Eq, Hash, Reflect)] #[require(WebviewSize, ZoomLevel, AudioMuted)] pub struct CefWebviewUri(pub String); }
The #[require(...)]
attribute ensures that every webview automatically gets the essential supporting components.
Methods
new(uri)
: Create with any valid URL (http, https, cef://localhost/)local(path)
: Create with local file path, automatically prefixed withcef://localhost/
Local File Serving
When using local files, bevy_cef serves them through a custom scheme:
- Scheme:
cef://localhost/
- Root Directory: Your project's
assets/
folder - Path Resolution: Relative paths from assets/ root
Example File Structure:
assets/
├── index.html → cef://localhost/index.html
├── ui/
│ ├── menu.html → cef://localhost/ui/menu.html
│ └── styles.css → cef://localhost/ui/styles.css
└── js/
└── app.js → cef://localhost/js/app.js
WebviewSize
Controls the internal rendering resolution of the webview, independent of the 3D object size.
Usage
#![allow(unused)] fn main() { use bevy::math::Vec2; // High resolution webview WebviewSize(Vec2::new(1920.0, 1080.0)) // Standard resolution WebviewSize(Vec2::new(800.0, 600.0)) // Square webview WebviewSize(Vec2::splat(512.0)) // Default size WebviewSize::default () // 800×800 }
Performance Considerations
- Higher Resolution: Better quality, more memory usage
- Lower Resolution: Better performance, potential pixelation
- Aspect Ratio: Match your 3D mesh proportions for best results
#![allow(unused)] fn main() { // Example: Widescreen webview for cinematic content commands.spawn(( CefWebviewUri::local("video-player.html"), WebviewSize(Vec2::new(1920.0, 800.0)), // 21:9 aspect ratio Mesh3d(meshes.add(Quad::new(Vec2::new(4.8, 2.0)))), // Match aspect in 3D MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default ())), )); }
Dynamic Resizing
You can change webview size at runtime:
#![allow(unused)] fn main() { fn resize_webview( mut webviews: Query<&mut WebviewSize>, keyboard: Res<ButtonInput<KeyCode>>, ) { if keyboard.just_pressed(KeyCode::KeyR) { for mut size in webviews.iter_mut() { size.0 *= 1.5; // Increase resolution by 50% } } } }
ZoomLevel
Controls the zoom level of web content within the webview.
Usage
#![allow(unused)] fn main() { // Default zoom (browser default) ZoomLevel(0.0) // Zoom in 20% ZoomLevel(1.2) // Zoom out 20% ZoomLevel(0.8) // Maximum zoom in ZoomLevel(3.0) // Maximum zoom out ZoomLevel(0.25) }
Zoom Behavior
- 0.0: Browser default zoom level
- Positive values: Zoom in (1.2 = 120% of default)
- Negative values: Zoom out (0.8 = 80% of default)
- Range: Typically 0.25 to 3.0 (25% to 300%)
Dynamic Zoom Control
#![allow(unused)] fn main() { fn zoom_control( mut webviews: Query<&mut ZoomLevel>, keyboard: Res<ButtonInput<KeyCode>>, ) { for mut zoom in webviews.iter_mut() { if keyboard.just_pressed(KeyCode::Equal) { zoom.0 = (zoom.0 + 0.1).min(3.0); // Zoom in } if keyboard.just_pressed(KeyCode::Minus) { zoom.0 = (zoom.0 - 0.1).max(0.25); // Zoom out } if keyboard.just_pressed(KeyCode::Digit0) { zoom.0 = 0.0; // Reset zoom } } } }
Use Cases
- Accessibility: Larger text for readability
- Dense Content: Fit more information in limited space
- Responsive Design: Adapt to different screen sizes
- User Preference: Allow users to adjust comfortable viewing size
AudioMuted
Controls whether audio from the webview is muted.
Usage
#![allow(unused)] fn main() { // Audio enabled (default) AudioMuted(false) // Audio muted AudioMuted(true) }
Dynamic Audio Control
#![allow(unused)] fn main() { fn toggle_audio( mut webviews: Query<&mut AudioMuted>, keyboard: Res<ButtonInput<KeyCode>>, ) { if keyboard.just_pressed(KeyCode::KeyM) { for mut muted in webviews.iter_mut() { muted.0 = !muted.0; // Toggle mute state } } } }
Use Cases
- Background Content: Mute decorative webviews
- Multiple Webviews: Prevent audio conflicts
- User Control: Provide mute/unmute functionality
- Game State: Mute during pause or cutscenes
HostWindow (Optional)
Specifies which Bevy window should be the parent of the webview. If not provided, the primary window is used.
Usage
#![allow(unused)] fn main() { // Use primary window (default behavior) commands.spawn(( CefWebviewUri::local("ui.html"), // No HostWindow component needed )); // Specify a particular window commands.spawn(( CefWebviewUri::local("ui.html"), HostWindow(secondary_window_entity), )); }
Multi-Window Applications
#![allow(unused)] fn main() { fn setup_multi_window( mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<WebviewExtendStandardMaterial>>, ) { // Create secondary window let secondary_window = commands.spawn(Window { title: "Secondary Display".to_string(), resolution: (800.0, 600.0).into(), ..default() }).id(); // Main webview in primary window commands.spawn(( CefWebviewUri::local("main-ui.html"), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); // Secondary webview in secondary window commands.spawn(( CefWebviewUri::local("secondary-ui.html"), HostWindow(secondary_window), Mesh3d(meshes.add(Plane3d::new(Vec3::Z, Vec2::ONE))), MeshMaterial3d(materials.add(WebviewExtendStandardMaterial::default())), )); } }
Component Combinations
Common Patterns
High-Resolution Interactive Display:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("dashboard.html"), WebviewSize(Vec2::new(2560.0, 1440.0)), ZoomLevel(0.0), AudioMuted(false), )); }
Compact Information Panel:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("info-panel.html"), WebviewSize(Vec2::new(400.0, 300.0)), ZoomLevel(0.8), AudioMuted(true), )); }
Video Player:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::new("https://player.example.com"), WebviewSize(Vec2::new(1920.0, 1080.0)), ZoomLevel(0.0), AudioMuted(false), // Keep audio for video )); }
Background Decoration:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("animated-bg.html"), WebviewSize(Vec2::new(1024.0, 1024.0)), ZoomLevel(0.0), AudioMuted(true), // No audio for decoration )); }
Component Lifecycle
Automatic Requirements
When you add CefWebviewUri
, the required components are automatically added with default values:
#![allow(unused)] fn main() { // You only need to specify this: commands.spawn(CefWebviewUri::local("page.html")); // But the entity automatically gets: // - WebviewSize(Vec2::splat(800.0)) // - ZoomLevel(0.0) // - AudioMuted(false) }
Manual Override
You can override the defaults by adding components explicitly:
#![allow(unused)] fn main() { commands.spawn(( CefWebviewUri::local("page.html"), WebviewSize(Vec2::new(1024.0, 768.0)), // Override default ZoomLevel(1.2), // Override default AudioMuted(true), // Override default )); }
Runtime Modification
All components can be modified at runtime through standard Bevy systems:
#![allow(unused)] fn main() { fn modify_webview_properties( mut query: Query<(&mut WebviewSize, &mut ZoomLevel, &mut AudioMuted)>, time: Res<Time>, ) { for (mut size, mut zoom, mut muted) in query.iter_mut() { // Dynamic effects based on time, input, game state, etc. let scale = (time.elapsed_secs().sin() + 1.0) / 2.0; zoom.0 = 0.8 + scale * 0.4; // Oscillate between 0.8 and 1.2 } } }
Best Practices
Performance Optimization
#![allow(unused)] fn main() { // Good: Appropriate resolution for use case WebviewSize(Vec2::new(800.0, 600.0)) // Standard UI // Avoid: Excessive resolution unless needed WebviewSize(Vec2::new(4096.0, 4096.0)) // Only for high-detail content }
Memory Management
#![allow(unused)] fn main() { // Good: Mute background content commands.spawn(( CefWebviewUri::local("ambient-display.html"), AudioMuted(true), // Prevent memory usage for audio processing )); }
User Experience
#![allow(unused)] fn main() { // Good: Consistent zoom across related webviews let ui_zoom = ZoomLevel(1.1); for ui_component in ["menu.html", "inventory.html", "settings.html"] { commands.spawn(( CefWebviewUri::local(ui_component), ui_zoom, )); } }
Next Steps
- Learn about Webview Rendering techniques
- Explore Inter-Process Communication patterns
- Check component-specific guides: