From d39602eb0e9e304c5e87ddf31aca6777c694e04a Mon Sep 17 00:00:00 2001 From: Avii Date: Fri, 20 Feb 2026 22:06:28 +0100 Subject: [PATCH] Stuff --- .claude/commands/create-test.md | 13 --- AGENTS.md | 37 ------- CLAUDE.md | 96 ------------------- Cargo.lock | 10 +- Cargo.toml | 18 ++-- Makefile | 19 ---- .../src/browser_process/browsers.rs | 4 +- .../src/browser_process/browsers/keyboard.rs | 2 +- crates/bevy_cef_core/src/util.rs | 3 +- examples/custom_material.rs | 8 +- examples/devtool.rs | 11 ++- examples/simple.rs | 9 +- src/common/components.rs | 2 +- src/common/message_loop.rs | 68 +------------ src/lib.rs | 4 +- .../webview_extend_standard_material.wgsl | 18 ++-- src/webview/mesh/webview_material.rs | 2 +- src/webview/mesh/webview_util.wgsl | 1 + 18 files changed, 59 insertions(+), 266 deletions(-) delete mode 100644 .claude/commands/create-test.md delete mode 100644 AGENTS.md delete mode 100644 CLAUDE.md delete mode 100644 Makefile diff --git a/.claude/commands/create-test.md b/.claude/commands/create-test.md deleted file mode 100644 index 8420309..0000000 --- a/.claude/commands/create-test.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -allowed-tools: Bash(cargo test:*), -description: Create new tests ---- - -1. Reading $ARGUMENTS and understanding the implementation details. -2. Creating new tests for $ARGUMENTS in `tests` module in the same file. -3. Run `cargo test --workspace --all-features` to ensure all tests pass. -4. If any tests fail, fix the issues and re-run the tests. - -## Contracts - -- You have to write the rust-doc that describes the test case for each test function. \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index a81b5d5..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,37 +0,0 @@ -# Repository Guidelines - -## Project Structure & Module Organization -- `src/`: Public `bevy_cef` crate API surface. -- `crates/bevy_cef_core`: Core CEF integration and IPC. -- `crates/bevy_cef_debug_render_process`: Debug render-process tool. -- `examples/`: Runnable samples (e.g., `simple.rs`, `js_emit.rs`, `brp.rs`). -- `assets/`: Local HTML/CSS/JS served via `cef://localhost/`. -- `docs/`: Supporting documentation. - -## Build, Test, and Development Commands -- `cargo build --features debug`: Build with macOS debug tooling enabled. -- `cargo run --example simple --features debug`: Run a basic webview example. -- `cargo test --workspace --all-features`: Run tests (currently no automated tests; validates compilation). -- `make fix`: Run `cargo clippy --fix` and `cargo fmt --all`. -- `make install`: Install and copy the debug render process into the CEF framework (macOS). - -## Coding Style & Naming Conventions -- Rust 2024 edition; format with `cargo fmt` before committing. -- Lint with `cargo clippy` (see `make fix`). -- Naming: `snake_case` for modules/functions/files, `CamelCase` for types/traits, `SCREAMING_SNAKE_CASE` for constants. -- Prefer small, focused modules; keep public API in `src/` and implementation in `crates/`. - -## Testing Guidelines -- No dedicated test suite yet; rely on examples for manual verification. -- Use `examples/` to validate features (IPC, navigation, zoom, devtools). -- If adding tests, keep names descriptive (e.g., `test_ipc_roundtrip`) and run with `cargo test --workspace --all-features`. - -## Commit & Pull Request Guidelines -- Commit subjects are short, imperative; common prefixes include `add:`, `fix:`, `update:`, `remove:`. -- Include PR or issue references when relevant (e.g., `Support Bevy 0.17 (#11)`). -- PRs should describe changes, testing performed, and target platform (macOS/Windows/Linux). -- For webview or UI changes, include screenshots or short clips when possible. - -## Platform & Configuration Notes -- Primary development target is macOS; CEF framework should exist at `$HOME/.local/share/cef`. -- Local assets are served as `cef://localhost/`; prefer `CefWebviewUri::local("file.html")`. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 475edec..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,96 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -This is `bevy_cef`, a Bevy plugin that integrates the Chromium Embedded Framework (CEF) into Bevy applications, allowing webviews to be rendered as 3D objects in the game world or as UI overlays. - -## Architecture - -### Multi-Process Design -- **Browser Process**: Main application process running Bevy (`bevy_cef_core::browser_process`) -- **Render Process**: Separate CEF render process (`bevy_cef_core::render_process`) -- Communication through IPC channels and Bevy Remote Protocol (BRP) - -### Core Components -- `CefWebviewUri`: URL specification (`CefWebviewUri::new("url")` or `CefWebviewUri::local("file.html")`) -- `WebviewSize`: Rendering dimensions (default 800x800), controls texture resolution not 3D size -- `WebviewExtendStandardMaterial`: Primary material for 3D mesh rendering -- `WebviewSpriteMaterial`: Material for 2D sprite rendering -- `HostWindow`: Optional parent window (defaults to PrimaryWindow) -- `ZoomLevel`: f64 zoom control (0.0 = default) -- `AudioMuted`: bool for audio control -- `PreloadScripts`: Vec of scripts to execute before page scripts -- `CefExtensions`: Custom JS extensions via `register_extension` (global to all webviews) - -### Plugin Architecture -The main `CefPlugin` accepts `CommandLineConfig` for CEF command-line switches and `CefExtensions` for custom JavaScript APIs. Sub-plugins: -- `LocalHostPlugin`: Serves local assets via `cef://localhost/` scheme -- `MessageLoopPlugin`: CEF message loop integration (macOS uses `CefDoMessageLoopWork()`) -- `WebviewCoreComponentsPlugin`: Core component registration -- `WebviewPlugin`: Webview lifecycle and DevTools -- `IpcPlugin`: IPC containing `IpcRawEventPlugin` and `HostEmitPlugin` -- `KeyboardPlugin`, `SystemCursorIconPlugin`, `NavigationPlugin`, `ZoomPlugin`, `AudioMutePlugin` -- `RemotePlugin`: Auto-added for BRP support if not present - -### IPC System -Three communication patterns: -1. **JS Emit**: Webview → Bevy via `JsEmitEventPlugin` where E: `DeserializeOwned + Send + Sync + 'static` - - Events wrapped in `Receive` EntityEvent - - JavaScript: `window.cef.emit('event_name', data)` -2. **Host Emit**: Bevy → Webview via `HostEmitEvent` (EntityEvent) - - JavaScript: `window.cef.listen('event_name', callback)` -3. **BRP**: Bidirectional RPC via `bevy_remote` - - JavaScript: `await window.cef.brp({ method: 'method_name', params: {...} })` - -### EntityEvent Pattern -Navigation and DevTools events are `EntityEvent` types requiring explicit `webview: Entity` field: -- `HostEmitEvent`, `RequestGoBack`, `RequestGoForward`, `RequestShowDevTool`, `RequestCloseDevtool` - -## Development Commands - -```bash -# Fix and format code -make fix - -# Run examples (macOS requires debug feature) -cargo run --example simple --features debug - -# Install debug render process tool -make install -``` - -### Debug Tools Setup (macOS) -Manual installation required before running with `debug` feature: -```bash -cargo install export-cef-dir -export-cef-dir --force $HOME/.local/share -cargo install bevy_cef_debug_render_process -mv $HOME/.cargo/bin/bevy_cef_debug_render_process "$HOME/.local/share/Chromium Embedded Framework.framework/Libraries/bevy_cef_debug_render_process" -``` - -## Local Asset Loading - -Local HTML/assets served via `cef://localhost/` scheme: -- Place assets in `assets/` directory -- Reference as `CefWebviewUri::local("filename.html")` - -## Testing - -No automated tests. Testing done through examples: -- `cargo test --workspace --all-features` (for any future tests) -- Examples: simple, js_emit, host_emit, brp, navigation, zoom_level, sprite, devtool, custom_material, preload_scripts, extensions - -## Platform Notes - -- Primary platform: macOS (uses `objc` crate for window handling) -- CEF framework location: `$HOME/.local/share/Chromium Embedded Framework.framework` -- Windows/Linux: Infrastructure ready but needs testing -- Key resources (`Browsers`, library loaders) are `NonSend` - CEF is not thread-safe - -## Workspace Structure - -- Root crate: `bevy_cef` (public API) -- `crates/bevy_cef_core`: Core CEF integration logic -- `crates/bevy_cef_debug_render_process`: Debug render process executable \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index dc8de05..1b21718 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1930,9 +1930,7 @@ dependencies = [ [[package]] name = "cef" -version = "144.4.0+144.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42320c2356f3fe4ed3f875b8fc93cbbabd1be3c59fcc0a8eb1e5b5c25616ac28" +version = "145.3.0+145.0.25" dependencies = [ "anyhow", "cargo_metadata", @@ -1950,9 +1948,7 @@ dependencies = [ [[package]] name = "cef-dll-sys" -version = "144.4.0+144.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d802abd4ac0b8c12be11b6af24100c6e21543c265867ad53067268048bc7e3a" +version = "145.3.0+145.0.25" dependencies = [ "anyhow", "cmake", @@ -2469,8 +2465,6 @@ checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" [[package]] name = "download-cef" version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6002a6b95f9f3bbe5693ac02a03221a8e3af6c9f5f4539f5734a8d6cde1a3616" dependencies = [ "bzip2", "clap", diff --git a/Cargo.toml b/Cargo.toml index 8ee31cb..67308bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,7 @@ exclude = ["assets/"] [workspace] resolver = "2" -members = [ - "crates/*", -] +members = ["crates/*"] [workspace.package] version = "0.2.0-dev" @@ -38,9 +36,9 @@ bevy = { version = "0.18", default-features = false, features = [ "picking", ] } bevy_remote = "0.18" -cef = { version = "144.4.0" } -cef-dll-sys = { version = "144.4.0", features = ["sandbox"] } -bevy_cef = { path = "." , version = "0.2.0-dev" } +cef = { path = "../../cef-rs/cef" } +cef-dll-sys = { path = "../../cef-rs/sys" } +bevy_cef = { path = ".", version = "0.2.0-dev" } bevy_cef_core = { path = "crates/bevy_cef_core", version = "0.2.0-dev" } async-channel = { version = "2.5" } serde = { version = "1", features = ["derive"] } @@ -58,14 +56,18 @@ serde_json = { workspace = true } raw-window-handle = "0.6" [dev-dependencies] -bevy = { workspace = true, default-features = true, features = ["file_watcher"]} +bevy = { workspace = true, default-features = true, features = [ + "file_watcher", +] } bevy_cef = { workspace = true, features = ["debug"] } [target.'cfg(target_os = "macos")'.dependencies] objc = { version = "0.2" } [lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("cargo-clippy"))'] } +unexpected_cfgs = { level = "warn", check-cfg = [ + 'cfg(feature, values("cargo-clippy"))', +] } [features] default = [] diff --git a/Makefile b/Makefile deleted file mode 100644 index ea037ee..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -.PHONY: fix install - -BIN := bevy_cef_debug_render_process -CEF_LIB := $(HOME)/.local/share/Chromium Embedded Framework.framework/Libraries - - -.PHONY: fix install - -BIN := bevy_cef_debug_render_process -CEF_LIB := $(HOME)/.local/share/Chromium Embedded Framework.framework/Libraries -CARGO_BIN := $(HOME)/.cargo/bin - -fix: - cargo clippy --fix --allow-dirty --allow-staged --workspace --all --all-features - cargo fmt --all - -install: - cargo install --path ./crates/bevy_cef_debug_render_process --force - mv "$(CARGO_BIN)/$(BIN)" "$(CEF_LIB)/$(BIN)" \ No newline at end of file diff --git a/crates/bevy_cef_core/src/browser_process/browsers.rs b/crates/bevy_cef_core/src/browser_process/browsers.rs index 08a45a1..a350511 100644 --- a/crates/bevy_cef_core/src/browser_process/browsers.rs +++ b/crates/bevy_cef_core/src/browser_process/browsers.rs @@ -69,7 +69,7 @@ impl Browsers { let browser = browser_host_create_browser_sync( Some(&WindowInfo { windowless_rendering_enabled: true as _, - external_begin_frame_enabled: false as _, + external_begin_frame_enabled: true as _, #[cfg(target_os = "macos")] parent_view: match _window_handle { Some(RawWindowHandle::AppKit(handle)) => handle.ns_view.as_ptr(), @@ -78,7 +78,7 @@ impl Browsers { Some(RawWindowHandle::Wayland(handle)) => handle.surface.as_ptr(), _ => std::ptr::null_mut(), }, - // shared_texture_enabled: true as _, + shared_texture_enabled: false as _, ..Default::default() }), Some(&mut self.client_handler( diff --git a/crates/bevy_cef_core/src/browser_process/browsers/keyboard.rs b/crates/bevy_cef_core/src/browser_process/browsers/keyboard.rs index fdafafb..7db5104 100644 --- a/crates/bevy_cef_core/src/browser_process/browsers/keyboard.rs +++ b/crates/bevy_cef_core/src/browser_process/browsers/keyboard.rs @@ -43,7 +43,7 @@ pub fn create_cef_key_event( // ButtonState::Pressed if input.just_pressed(key_event.key_code) => { // cef_key_event_type_t::KEYEVENT_RAWKEYDOWN // } - ButtonState::Pressed => cef_key_event_type_t::KEYEVENT_CHAR, + ButtonState::Pressed => cef_key_event_type_t::KEYEVENT_RAWKEYDOWN, ButtonState::Released => cef_key_event_type_t::KEYEVENT_KEYUP, }; let windows_key_code = keycode_to_windows_vk(key_event.key_code); diff --git a/crates/bevy_cef_core/src/util.rs b/crates/bevy_cef_core/src/util.rs index 2a2d090..ee91c52 100644 --- a/crates/bevy_cef_core/src/util.rs +++ b/crates/bevy_cef_core/src/util.rs @@ -41,7 +41,8 @@ pub fn debug_chromium_embedded_framework_dir_path() -> PathBuf { .unwrap() .join(".local") .join("share") - .join("Chromium Embedded Framework.framework") + .join("avii") + .join("cef") } pub fn debug_render_process_path() -> PathBuf { diff --git a/examples/custom_material.rs b/examples/custom_material.rs index 9a3aad1..43f61c1 100644 --- a/examples/custom_material.rs +++ b/examples/custom_material.rs @@ -12,7 +12,13 @@ fn main() { App::new() .add_plugins(( DefaultPlugins, - CefPlugin::default(), + CefPlugin { + command_line_config: CommandLineConfig { + switches: ["--in-process-gpu", "--no-sandbox"].to_vec(), + ..Default::default() + }, + ..Default::default() + }, WebviewExtendMaterialPlugin::::default(), )) .add_systems(Startup, (spawn_camera, spawn_webview)) diff --git a/examples/devtool.rs b/examples/devtool.rs index 17ceeea..6954bda 100644 --- a/examples/devtool.rs +++ b/examples/devtool.rs @@ -10,7 +10,16 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin::default())) + .add_plugins(( + DefaultPlugins, + CefPlugin { + command_line_config: CommandLineConfig { + switches: ["--in-process-gpu"].to_vec(), + ..Default::default() + }, + ..Default::default() + }, + )) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/examples/simple.rs b/examples/simple.rs index e7d397b..8873449 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -5,7 +5,14 @@ use bevy_cef::prelude::*; fn main() { App::new() - .add_plugins((DefaultPlugins, CefPlugin::default())) + .add_plugins(DefaultPlugins) + .add_plugins(CefPlugin { + command_line_config: CommandLineConfig { + switches: ["--no-zygote", "--no-sandbox"].to_vec(), + ..Default::default() + }, + ..Default::default() + }) .add_systems( Startup, (spawn_camera, spawn_directional_light, spawn_webview), diff --git a/src/common/components.rs b/src/common/components.rs index d24a84d..309cb72 100644 --- a/src/common/components.rs +++ b/src/common/components.rs @@ -74,7 +74,7 @@ pub struct WebviewSize(pub Vec2); impl Default for WebviewSize { fn default() -> Self { - Self(Vec2::splat(800.0)) + Self(Vec2::new(768.0, 1024.0)) } } diff --git a/src/common/message_loop.rs b/src/common/message_loop.rs index 94d8068..52611a8 100644 --- a/src/common/message_loop.rs +++ b/src/common/message_loop.rs @@ -54,20 +54,10 @@ fn load_cef_library(app: &mut App) { fn cef_initialize(args: &Args, cef_app: &mut cef::App) { let settings = Settings { - #[cfg(all(target_os = "macos", feature = "debug"))] - framework_dir_path: debug_chromium_embedded_framework_dir_path() + root_cache_path: debug_chromium_embedded_framework_dir_path() .to_str() .unwrap() .into(), - #[cfg(all(target_os = "macos", feature = "debug"))] - browser_subprocess_path: debug_render_process_path().to_str().unwrap().into(), - #[cfg(all(target_os = "macos", feature = "debug"))] - no_sandbox: true as _, - windowless_rendering_enabled: true as _, - // #[cfg(any(target_os = "windows", target_os = "linux"))] - // multi_threaded_message_loop: true as _, - multi_threaded_message_loop: false as _, - external_message_pump: true as _, ..Default::default() }; assert_eq!( @@ -86,6 +76,7 @@ fn cef_do_message_loop_work( mut timer: Local>, mut max_delay_timer: Local, ) { + // cef::do_message_loop_work(); while let Ok(t) = receiver.try_recv() { timer.replace(t); } @@ -99,58 +90,3 @@ fn cef_do_message_loop_work( fn cef_shutdown(_: NonSend) { shutdown(); } - -#[cfg(target_os = "macos")] -mod macos { - use core::sync::atomic::AtomicBool; - use objc::runtime::{Class, Object, Sel}; - use objc::{sel, sel_impl}; - use std::os::raw::c_char; - use std::os::raw::c_void; - use std::sync::atomic::Ordering; - - unsafe extern "C" { - fn class_addMethod( - cls: *const Class, - name: Sel, - imp: *const c_void, - types: *const c_char, - ) -> bool; - } - - static IS_HANDLING_SEND_EVENT: AtomicBool = AtomicBool::new(false); - - extern "C" fn is_handling_send_event(_: &Object, _: Sel) -> bool { - IS_HANDLING_SEND_EVENT.load(Ordering::Relaxed) - } - - extern "C" fn set_handling_send_event(_: &Object, _: Sel, flag: bool) { - IS_HANDLING_SEND_EVENT.swap(flag, Ordering::Relaxed); - } - - pub fn install_cef_app_protocol() { - unsafe { - let cls = Class::get("NSApplication").expect("NSApplication クラスが見つかりません"); - let sel_name = sel!(isHandlingSendEvent); - let success = class_addMethod( - cls as *const _, - sel_name, - is_handling_send_event as *const c_void, - c"c@:".as_ptr() as *const c_char, - ); - assert!(success, "メソッド追加に失敗しました"); - - let sel_set = sel!(setHandlingSendEvent:); - let success2 = class_addMethod( - cls as *const _, - sel_set, - set_handling_send_event as *const c_void, - c"v@:c".as_ptr() as *const c_char, - ); - assert!( - success2, - "Failed to add setHandlingSendEvent: to NSApplication" - ); - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 8051034..62d4033 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,7 +21,9 @@ use bevy_remote::RemotePlugin; pub mod prelude { pub use crate::{CefPlugin, RunOnMainThread, common::*, navigation::*, webview::prelude::*}; - pub use bevy_cef_core::prelude::{CefExtensions, CommandLineConfig}; + pub use bevy_cef_core::prelude::{ + Browsers, CefExtensions, CommandLineConfig, create_cef_key_event, + }; } pub struct RunOnMainThread; diff --git a/src/webview/mesh/webview_extend_standard_material.wgsl b/src/webview/mesh/webview_extend_standard_material.wgsl index 41e93c2..cb9908a 100644 --- a/src/webview/mesh/webview_extend_standard_material.wgsl +++ b/src/webview/mesh/webview_extend_standard_material.wgsl @@ -18,15 +18,15 @@ fn fragment( in: VertexOutput, @builtin(front_facing) is_front: bool, ) -> FragmentOutput { - var pbr_input = pbr_input_from_standard_material(in, is_front); - pbr_input.material.base_color *= surface_color(in.uv); - pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color); var out: FragmentOutput; - if (material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) == 0u { - out.color = apply_pbr_lighting(pbr_input); - out.color = main_pass_post_lighting_processing(pbr_input, out.color); - }else{ - out.color = pbr_input.material.base_color; - } + var pbr_input = pbr_input_from_standard_material(in, is_front); + + var alpha = pbr_input.material.base_color.a; + pbr_input.material.base_color *= surface_color(in.uv); + // pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color); + + out.color = pbr_input.material.base_color * alpha; + // out.color.a *= alpha; + return out; } diff --git a/src/webview/mesh/webview_material.rs b/src/webview/mesh/webview_material.rs index 548d1f6..a29cb00 100644 --- a/src/webview/mesh/webview_material.rs +++ b/src/webview/mesh/webview_material.rs @@ -22,7 +22,7 @@ impl Plugin for WebviewMaterialPlugin { } } -#[derive(Asset, TypePath, AsBindGroup, Debug, Clone, PartialEq, Eq, Hash, Default)] +#[derive(Asset, TypePath, AsBindGroup, Debug, Clone, PartialEq, Default)] pub struct WebviewMaterial { /// Holds the texture handle for the webview. /// diff --git a/src/webview/mesh/webview_util.wgsl b/src/webview/mesh/webview_util.wgsl index f9a7cfb..69538d1 100644 --- a/src/webview/mesh/webview_util.wgsl +++ b/src/webview/mesh/webview_util.wgsl @@ -9,5 +9,6 @@ @group(#{MATERIAL_BIND_GROUP}) @binding(102) var surface_sampler: sampler; fn surface_color(uv: vec2) -> vec4 { + // let flip = vec2(1.0 - uv.x, uv.y); return textureSampleBias(surface_texture, surface_sampler, uv, view.mip_bias); } \ No newline at end of file