Skip to content

Commit 8b80eb1

Browse files
authored
Implement background method (#1308)
* Implement background. * Install wayland deps.
1 parent f266287 commit 8b80eb1

File tree

7 files changed

+102
-16
lines changed

7 files changed

+102
-16
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
[workspace]
22
resolver = "3"
33
members = ["ffi","renderer"]
4+
5+
[workspace.dependencies]
6+
bevy = { version = "0.17", no-default-features = true, features = [
7+
"bevy_render",
8+
"bevy_color",
9+
] }

ffi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ crate-type = ["cdylib"]
99

1010
[dependencies]
1111
renderer = { path = "../renderer" }
12+
bevy = { workspace = true }
1213

1314
[build-dependencies]
1415
cbindgen = "0.29"

ffi/src/color.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// A sRGB (?) color
2+
#[repr(C)]
3+
pub struct Color {
4+
pub r: f32,
5+
pub g: f32,
6+
pub b: f32,
7+
pub a: f32,
8+
}
9+
10+
impl From<Color> for bevy::color::Color {
11+
fn from(color: Color) -> Self {
12+
bevy::color::Color::srgba(color.r, color.g, color.b, color.a)
13+
}
14+
}

ffi/src/lib.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::color::Color;
2+
use bevy::prelude::Entity;
3+
4+
mod color;
15
mod error;
26

37
/// Initialize libProcessing.
@@ -31,16 +35,41 @@ pub extern "C" fn processing_create_surface(
3135
.unwrap_or(0)
3236
}
3337

38+
/// Destroy the surface associated with the given window ID.
39+
///
40+
/// SAFETY:
41+
/// - Init and create_surface have been called.
42+
/// - window_id is a valid ID returned from create_surface.
43+
/// - This is called from the same thread as init.
44+
#[unsafe(no_mangle)]
45+
pub extern "C" fn processing_destroy_surface(window_id: u64) {
46+
error::clear_error();
47+
let window_entity = Entity::from_bits(window_id);
48+
error::check(|| renderer::destroy_surface(window_entity));
49+
}
50+
3451
/// Update window size when resized.
3552
///
3653
/// SAFETY:
3754
/// - Init and create_surface have been called.
3855
/// - window_id is a valid ID returned from create_surface.
3956
/// - This is called from the same thread as init.
4057
#[unsafe(no_mangle)]
41-
pub extern "C" fn processing_window_resized(window_id: u64, width: u32, height: u32) {
58+
pub extern "C" fn processing_resize_surface(window_id: u64, width: u32, height: u32) {
59+
error::clear_error();
60+
let window_entity = Entity::from_bits(window_id);
61+
error::check(|| renderer::resize_surface(window_entity, width, height));
62+
}
63+
64+
/// Set the background color for the given window.
65+
///
66+
/// SAFETY:
67+
/// - This is called from the same thread as init.
68+
#[unsafe(no_mangle)]
69+
pub extern "C" fn processing_background_color(window_id: u64, color: Color) {
4270
error::clear_error();
43-
error::check(|| renderer::window_resized(window_id, width, height));
71+
let window_entity = Entity::from_bits(window_id);
72+
error::check(|| renderer::background_color(window_entity, color.into()));
4473
}
4574

4675
/// Step the application forward.

renderer/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ edition = "2024"
66
[dependencies]
77
tracing = "0.1"
88
tracing-subscriber = "0.3"
9-
bevy = { version = "0.17", no-default-features = true, features = [
10-
"bevy_render"
11-
] }
9+
bevy = { workspace = true }
1210
thiserror = "2"
1311
raw-window-handle = "0.6"
1412

renderer/src/lib.rs

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,27 @@ use crate::error::Result;
44
use bevy::app::{App, AppExit};
55
use bevy::log::tracing_subscriber;
66
use bevy::prelude::*;
7-
use bevy::window::{
8-
RawHandleWrapper, Window, WindowResolution, WindowWrapper,
9-
};
7+
use bevy::window::{RawHandleWrapper, Window, WindowRef, WindowResolution, WindowWrapper};
108
use raw_window_handle::{
119
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle,
1210
RawWindowHandle, WindowHandle,
1311
};
1412
use std::cell::RefCell;
1513
use std::num::NonZero;
14+
use std::sync::atomic::AtomicU32;
1615
use std::sync::OnceLock;
16+
use bevy::camera::RenderTarget;
17+
use bevy::camera::visibility::RenderLayers;
1718
use tracing::debug;
1819

1920
static IS_INIT: OnceLock<()> = OnceLock::new();
21+
static WINDOW_COUNT: AtomicU32 = AtomicU32::new(0);
2022

2123
thread_local! {
2224
static APP: OnceLock<RefCell<App>> = OnceLock::default();
2325
}
2426

27+
2528
fn app<T>(cb: impl FnOnce(&App) -> Result<T>) -> Result<T> {
2629
let res = APP.with(|app_lock| {
2730
let app = app_lock
@@ -144,7 +147,7 @@ pub fn create_surface(
144147
let handle_wrapper = RawHandleWrapper::new(&window_wrapper)?;
145148

146149
let entity_id = app_mut(|app| {
147-
let entity = app
150+
let mut window = app
148151
.world_mut()
149152
.spawn((
150153
Window {
@@ -153,22 +156,44 @@ pub fn create_surface(
153156
..default()
154157
},
155158
handle_wrapper,
156-
))
157-
.id();
159+
));
160+
161+
let count = WINDOW_COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
162+
let render_layer = RenderLayers::none().with(count as usize);
158163

159-
// TODO: spawn a camera for this window with a render target of this window
164+
let window_entity = window.id();
165+
window.with_children(|parent| {
166+
parent.spawn((
167+
Camera3d::default(),
168+
Camera {
169+
target: RenderTarget::Window(WindowRef::Entity(window_entity)),
170+
..default()
171+
},
172+
Projection::Orthographic(OrthographicProjection::default_3d()),
173+
render_layer,
174+
));
175+
});
160176

161-
Ok(entity.to_bits())
177+
Ok(window_entity.to_bits())
162178
})?;
163179

164180
Ok(entity_id)
165181
}
166182

183+
pub fn destroy_surface(window_entity: Entity) -> Result<()>{
184+
app_mut(|app| {
185+
if app.world_mut().get::<Window>(window_entity).is_some() {
186+
app.world_mut().despawn(window_entity);
187+
WINDOW_COUNT.fetch_sub(1, std::sync::atomic::Ordering::SeqCst);
188+
}
189+
Ok(())
190+
})
191+
}
192+
167193
/// Update window size when resized.
168-
pub fn window_resized(window_id: u64, width: u32, height: u32) -> Result<()> {
194+
pub fn resize_surface(window_entity: Entity, width: u32, height: u32) -> Result<()> {
169195
app_mut(|app| {
170-
let entity = Entity::from_bits(window_id);
171-
if let Some(mut window) = app.world_mut().get_mut::<Window>(entity) {
196+
if let Some(mut window) = app.world_mut().get_mut::<Window>(window_entity) {
172197
window.resolution.set_physical_resolution(width, height);
173198
Ok(())
174199
} else {
@@ -240,6 +265,18 @@ pub fn exit(exit_code: u8) -> Result<()> {
240265
})
241266
}
242267

268+
pub fn background_color(window_entity: Entity, color: Color) -> Result<()> {
269+
app_mut(|app| {
270+
let mut camera_query = app.world_mut().query::<(&mut Camera, &ChildOf)>();
271+
for (mut camera, parent) in camera_query.iter_mut(&mut app.world_mut()) {
272+
if parent.parent() == window_entity {
273+
camera.clear_color = ClearColorConfig::Custom(color);
274+
}
275+
}
276+
Ok(())
277+
})
278+
}
279+
243280
fn setup_tracing() -> Result<()> {
244281
let subscriber = tracing_subscriber::FmtSubscriber::new();
245282
tracing::subscriber::set_global_default(subscriber)?;

0 commit comments

Comments
 (0)