diff --git a/Cargo.lock b/Cargo.lock index 6952b31856aae93917848862495a449e796d2ac1..4c7aa96b1b83743d78f886d939dab68a07127c14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -421,7 +421,6 @@ dependencies = [ "crevice", "kayak_core", "kayak_font", - "kayak_render_macros", "serde", "serde_json", "serde_path_to_error", @@ -1923,6 +1922,7 @@ dependencies = [ name = "kayak_widgets" version = "0.1.0" dependencies = [ + "bevy", "kayak_ui", ] diff --git a/Cargo.toml b/Cargo.toml index 06240ea2d36be1d38fb3136744e291fdd7bc4ce1..fcfd8e00fdaab5a80810e6081ec4b9316f6b887b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,4 @@ kayak_render_macros = { path = "kayak_render_macros" } [dev-dependencies] bevy = { git = "https://github.com/StarArawn/bevy", rev = "bcca341d696c66d0173d8b0ac7a1b23b4b9e775c" } -kayak_widgets = { path = "kayak_widgets" } +kayak_widgets = { path = "kayak_widgets", features = ["bevy_renderer"] } diff --git a/bevy_kayak_ui/Cargo.toml b/bevy_kayak_ui/Cargo.toml index 1b1d89f6e943368084cf63593dc22395185749c9..e0bf20227966435777b8b9a093e33bdcd608f0f1 100644 --- a/bevy_kayak_ui/Cargo.toml +++ b/bevy_kayak_ui/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" bytemuck = "1.7.2" bevy = { git = "https://github.com/StarArawn/bevy", rev = "bcca341d696c66d0173d8b0ac7a1b23b4b9e775c" } kayak_core = { path = "../kayak_core" } -kayak_render_macros = { path = "../kayak_render_macros" } kayak_font = { path = "../kayak_font" } #kayak_font = { path = "../kayak_font" } crevice = { git = "https://github.com/StarArawn/bevy", rev = "bcca341d696c66d0173d8b0ac7a1b23b4b9e775c" } diff --git a/bevy_kayak_ui/src/bevy_context.rs b/bevy_kayak_ui/src/bevy_context.rs index 5eb9cfe732618bfef4450c4c14a44fb4a3a7e7a8..847d6c8e53a39c83aafc3909df98bf54beedd189 100644 --- a/bevy_kayak_ui/src/bevy_context.rs +++ b/bevy_kayak_ui/src/bevy_context.rs @@ -1,28 +1,17 @@ use std::sync::{Arc, RwLock}; -use kayak_core::{ - context::KayakContext, - render_command::RenderCommand, - styles::{Style, StyleProp, Units}, -}; +use kayak_core::context::KayakContext; pub struct BevyContext { pub kayak_context: Arc<RwLock<KayakContext>>, } impl BevyContext { - pub fn new<F: Fn(&mut Style, &mut KayakContext)>(width: f32, height: f32, f: F) -> Self { - let mut app_styles = Style { - render_command: StyleProp::Value(RenderCommand::Window), - width: StyleProp::Value(Units::Pixels(width)), - height: StyleProp::Value(Units::Pixels(height)), - ..Style::default() - }; - + pub fn new<F: Fn(&mut KayakContext)>(f: F) -> Self { let kayak_context = Arc::new(RwLock::new(KayakContext::new())); if let Ok(mut kayak_context) = kayak_context.write() { - f(&mut app_styles, &mut kayak_context); + f(&mut kayak_context); kayak_context.widget_manager.dirty(true); } diff --git a/bevy_kayak_ui/src/lib.rs b/bevy_kayak_ui/src/lib.rs index 9fe1162e19277e95b4cb2938715876b67bc8becb..16511b328c2cf152460c6891c9f4a853699f9403 100644 --- a/bevy_kayak_ui/src/lib.rs +++ b/bevy_kayak_ui/src/lib.rs @@ -3,7 +3,7 @@ use bevy::{ math::Vec2, prelude::{EventReader, IntoExclusiveSystem, MouseButton, Plugin, Res, World}, render::color::Color, - window::{CursorMoved, Windows}, + window::{CursorMoved, WindowCreated, WindowResized, Windows}, }; mod bevy_context; @@ -12,7 +12,7 @@ mod render; pub use bevy_context::BevyContext; pub use camera::*; -use kayak_core::InputEvent; +use kayak_core::{bind, Binding, InputEvent, MutableBound}; pub use render::unified::font::FontMapping; pub use render::unified::image::ImageManager; @@ -21,8 +21,10 @@ pub struct BevyKayakUIPlugin; impl Plugin for BevyKayakUIPlugin { fn build(&self, app: &mut bevy::prelude::App) { - app.add_plugin(render::BevyKayakUIRenderPlugin) + app.insert_resource(bind(WindowSize::default())) + .add_plugin(render::BevyKayakUIRenderPlugin) .add_plugin(camera::KayakUICameraPlugin) + .add_system(update_window_size) .add_system(process_events) .add_system(update.exclusive_system()); } @@ -79,3 +81,43 @@ pub fn process_events( context.process_events(input_events); } } + +/// Tracks the bevy window size. +#[derive(Default, Debug, Clone, Copy, PartialEq)] +pub struct WindowSize(pub f32, pub f32); + +fn update_window_size( + mut window_resized_events: EventReader<WindowResized>, + mut window_created_events: EventReader<WindowCreated>, + windows: Res<Windows>, + window_size: Res<Binding<WindowSize>>, +) { + let mut changed_window_ids = Vec::new(); + // handle resize events. latest events are handled first because we only want to resize each + // window once + for event in window_resized_events.iter().rev() { + if changed_window_ids.contains(&event.id) { + continue; + } + + changed_window_ids.push(event.id); + } + + // handle resize events. latest events are handled first because we only want to resize each + // window once + for event in window_created_events.iter().rev() { + if changed_window_ids.contains(&event.id) { + continue; + } + + changed_window_ids.push(event.id); + } + + for window_id in changed_window_ids { + if let Some(window) = windows.get(window_id) { + let width = window.width(); + let height = window.height(); + window_size.set(WindowSize(width, height)); + } + } +} diff --git a/bevy_kayak_ui/src/render/unified/mod.rs b/bevy_kayak_ui/src/render/unified/mod.rs index a88be611c5ae1bc90ca23feadbe7d33e16ab6f47..1c8da6a231580b38aecb97d6bdafbd59c05695f2 100644 --- a/bevy_kayak_ui/src/render/unified/mod.rs +++ b/bevy_kayak_ui/src/render/unified/mod.rs @@ -8,7 +8,7 @@ use bevy::{ }, sprite::Rect, }; -use kayak_core::render_primitive::RenderPrimitive; +use kayak_core::{render_primitive::RenderPrimitive, Binding, Bound}; use kayak_font::KayakFont; use crate::{ @@ -16,7 +16,7 @@ use crate::{ ui_pass::TransparentUI, unified::pipeline::{DrawUI, QuadMeta, UnifiedPipeline}, }, - BevyContext, FontMapping, ImageManager, + BevyContext, FontMapping, ImageManager, WindowSize, }; use self::pipeline::{ExtractQuadBundle, ExtractedQuad, ImageBindGroups, UIQuadType}; @@ -68,6 +68,7 @@ pub fn extract( font_mapping: Res<FontMapping>, image_manager: Res<ImageManager>, images: Res<Assets<Image>>, + window_size: Res<Binding<WindowSize>>, ) { let render_primitives = if let Ok(context) = context.kayak_context.read() { context.widget_manager.build_render_primitives() @@ -75,6 +76,8 @@ pub fn extract( vec![] }; + // dbg!(&render_primitives); + let mut extracted_quads = Vec::new(); for render_primitive in render_primitives { match render_primitive { @@ -120,5 +123,6 @@ pub fn extract( } } + commands.insert_resource(window_size.get()); commands.spawn_batch(extracted_quads); } diff --git a/bevy_kayak_ui/src/render/unified/pipeline.rs b/bevy_kayak_ui/src/render/unified/pipeline.rs index cbc8651609bfabd318ed9eed39a46737dceaa2c0..b09888438c059a0e263810087da7e7aaca6c6573 100644 --- a/bevy_kayak_ui/src/render/unified/pipeline.rs +++ b/bevy_kayak_ui/src/render/unified/pipeline.rs @@ -34,7 +34,7 @@ use crevice::std140::AsStd140; use kayak_font::{FontRenderingPipeline, FontTextureCache, KayakFont}; use super::UNIFIED_SHADER_HANDLE; -use crate::render::ui_pass::TransparentUI; +use crate::{render::ui_pass::TransparentUI, WindowSize}; pub struct UnifiedPipeline { view_layout: BindGroupLayout, @@ -547,6 +547,7 @@ pub struct DrawUI { SRes<RenderPipelineCache>, SRes<FontTextureCache>, SRes<ImageBindGroups>, + SRes<WindowSize>, SQuery<Read<ViewUniformOffset>>, SQuery<Read<ExtractedQuad>>, )>, @@ -574,6 +575,7 @@ impl Draw<TransparentUI> for DrawUI { pipelines, font_texture_cache, image_bind_groups, + window_size, views, quads, ) = self.params.get(world); @@ -585,8 +587,13 @@ impl Draw<TransparentUI> for DrawUI { if extracted_quad.quad_type == UIQuadType::Clip { let x = extracted_quad.rect.min.x as u32; let y = extracted_quad.rect.min.y as u32; - let width = extracted_quad.rect.width() as u32; - let height = extracted_quad.rect.height() as u32; + let mut width = extracted_quad.rect.width() as u32; + let mut height = extracted_quad.rect.height() as u32; + width = width.min(window_size.0 as u32); + height = height.min(window_size.1 as u32); + if width == 0 || height == 0 { + return; + } pass.set_scissor_rect(x, y, width, height); return; } diff --git a/examples/bevy.rs b/examples/bevy.rs index 6f7ff8f9a1bfacb933ee58c3fd11a771b3407e75..b15a55082dd16854c37c1f9d11d9b3ede2be9199 100644 --- a/examples/bevy.rs +++ b/examples/bevy.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle}; @@ -25,7 +24,6 @@ fn CustomWidget() { fn startup( mut commands: Commands, - windows: Res<Windows>, mut font_mapping: ResMut<FontMapping>, asset_server: Res<AssetServer>, ) { @@ -33,15 +31,9 @@ fn startup( font_mapping.add(asset_server.load("roboto.kayak_font")); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { render! { - <App styles={Some(styles.clone())}> + <App> <CustomWidget/> </App> } diff --git a/examples/clipping.rs b/examples/clipping.rs index d33210b7f2cadfd03bc76ea6b2957f22317702b2..84d279635579f51abf8326e2a87e30af0fbac8ba 100644 --- a/examples/clipping.rs +++ b/examples/clipping.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager, UICameraBundle}; @@ -15,25 +14,18 @@ use kayak_widgets::{App, Clip, NinePatch, Text}; fn startup( mut commands: Commands, - windows: Res<Windows>, asset_server: Res<AssetServer>, mut image_manager: ResMut<ImageManager>, mut font_mapping: ResMut<FontMapping>, ) { commands.spawn_bundle(UICameraBundle::new()); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - font_mapping.add(asset_server.load("roboto.kayak_font")); let handle: Handle<bevy::render::texture::Image> = asset_server.load("kenny/panel_brown.png"); let panel_brown_handle = image_manager.get(&handle); - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { let nine_patch_styles = Style { width: StyleProp::Value(Units::Pixels(512.0)), height: StyleProp::Value(Units::Pixels(512.0)), @@ -69,7 +61,7 @@ Vestibulum rutrum imperdiet nisl, et consequat massa porttitor vel. Ut velit jus "#.to_string(); render! { - <App styles={Some(styles.clone())}> + <App> <NinePatch styles={Some(nine_patch_styles)} border={Space { diff --git a/examples/counter.rs b/examples/counter.rs index 8cc9258fcaebfd658185374c643f0d494025a21d..a443d5c5a54d6b1e2eb5d4524975c59750332fb1 100644 --- a/examples/counter.rs +++ b/examples/counter.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle}; @@ -58,7 +57,6 @@ fn Counter(context: &mut KayakContext) { fn startup( mut commands: Commands, - windows: Res<Windows>, mut font_mapping: ResMut<FontMapping>, asset_server: Res<AssetServer>, ) { @@ -66,15 +64,9 @@ fn startup( font_mapping.add(asset_server.load("roboto.kayak_font")); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { render! { - <App styles={Some(styles.clone())}> + <App> <Counter /> </App> } diff --git a/examples/full_ui.rs b/examples/full_ui.rs index 141c5e1cdfe221e71beb6fec700047af67c5274e..9295e4e6d3a3086fb60d39667f148e32a212c530 100644 --- a/examples/full_ui.rs +++ b/examples/full_ui.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut, World}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, ImageManager, UICameraBundle}; @@ -82,25 +81,18 @@ fn BlueButton(context: KayakContext, children: Children, styles: Option<Style>) fn startup( mut commands: Commands, - windows: Res<Windows>, asset_server: Res<AssetServer>, mut image_manager: ResMut<ImageManager>, mut font_mapping: ResMut<FontMapping>, ) { commands.spawn_bundle(UICameraBundle::new()); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - font_mapping.add(asset_server.load("roboto.kayak_font")); let handle: Handle<bevy::render::texture::Image> = asset_server.load("kenny/panel_brown.png"); let panel_brown_handle = image_manager.get(&handle); - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { let nine_patch_styles = Style { layout_type: StyleProp::Value(LayoutType::Column), width: StyleProp::Value(Units::Pixels(512.0)), @@ -117,7 +109,7 @@ fn startup( padding_right: StyleProp::Value(Units::Stretch(1.0)), padding_top: StyleProp::Value(Units::Stretch(1.0)), padding_bottom: StyleProp::Value(Units::Stretch(1.0)), - ..styles.clone() + ..Style::default() }; let header_styles = Style { diff --git a/examples/global_counter.rs b/examples/global_counter.rs index 6a0691dce00d55fba538bbca5955cfdb556e9895..e6f0ee7cf0ee7dc38bfaacfbba9a07145bc479a7 100644 --- a/examples/global_counter.rs +++ b/examples/global_counter.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Res, ResMut, World}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle}; @@ -40,7 +39,6 @@ fn Counter(context: &mut KayakContext) { fn startup( mut commands: Commands, - windows: Res<Windows>, mut font_mapping: ResMut<FontMapping>, asset_server: Res<AssetServer>, ) { @@ -48,17 +46,11 @@ fn startup( font_mapping.add(asset_server.load("roboto.kayak_font")); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - commands.insert_resource(bind(GlobalCount(0))); - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { render! { - <App styles={Some(styles.clone())}> + <App> <Counter /> </App> } diff --git a/examples/if.rs b/examples/if.rs index cb57cb2028da689a7dbbce3aeb6c68536c4761cf..2fb918b45d45a271fad0b008b695df8e57ef5f7d 100644 --- a/examples/if.rs +++ b/examples/if.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, FontMapping, UICameraBundle}; @@ -60,7 +59,6 @@ fn Removal(context: &mut KayakContext) { fn startup( mut commands: Commands, - windows: Res<Windows>, mut font_mapping: ResMut<FontMapping>, asset_server: Res<AssetServer>, ) { @@ -68,15 +66,9 @@ fn startup( font_mapping.add(asset_server.load("roboto.kayak_font")); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { render! { - <App styles={Some(styles.clone())}> + <App> <Removal /> </App> } diff --git a/examples/image.rs b/examples/image.rs index e43484da180f1f00d0c5b274a5a05b8d6324e47d..e8ca07f45e7299dd9904d4c32c0003d2e4f2b1d3 100644 --- a/examples/image.rs +++ b/examples/image.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle}; @@ -14,22 +13,15 @@ use kayak_widgets::{App, Image}; fn startup( mut commands: Commands, - windows: Res<Windows>, asset_server: Res<AssetServer>, mut image_manager: ResMut<ImageManager>, ) { commands.spawn_bundle(UICameraBundle::new()); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - let handle: Handle<bevy::render::texture::Image> = asset_server.load("generic-rpg-vendor.png"); let ui_image_handle = image_manager.get(&handle); - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { let image_styles = Style { width: StyleProp::Value(Units::Pixels(200.0)), height: StyleProp::Value(Units::Pixels(182.0)), @@ -37,7 +29,7 @@ fn startup( }; render! { - <App styles={Some(styles.clone())}> + <App> <Image styles={Some(image_styles)} handle={ui_image_handle} /> </App> } diff --git a/examples/nine_patch.rs b/examples/nine_patch.rs index f608f7de1eb7c326741cf32c5bb28dba9c486d2f..0262434e435e409ac46bf77962e389f85f621cf7 100644 --- a/examples/nine_patch.rs +++ b/examples/nine_patch.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Handle, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle}; @@ -15,22 +14,15 @@ use kayak_widgets::{App, NinePatch}; fn startup( mut commands: Commands, - windows: Res<Windows>, asset_server: Res<AssetServer>, mut image_manager: ResMut<ImageManager>, ) { commands.spawn_bundle(UICameraBundle::new()); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - let handle: Handle<bevy::render::texture::Image> = asset_server.load("panel.png"); let ui_image_handle = image_manager.get(&handle); - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { // The border prop splits up the image into 9 quadrants like so: // 1----2----3 // | | @@ -61,7 +53,7 @@ fn startup( }; render! { - <App styles={Some(styles.clone())}> + <App> <NinePatch styles={Some(nine_patch_styles)} border={Space { diff --git a/examples/vec_widget.rs b/examples/vec_widget.rs index 9c2d7de249f94d6d02f8c7393982bf88a610f479..03d5f2f82de9297e6fb9775581283190a994eb02 100644 --- a/examples/vec_widget.rs +++ b/examples/vec_widget.rs @@ -1,7 +1,6 @@ use bevy::{ - math::Vec2, prelude::{App as BevyApp, AssetServer, Commands, Res, ResMut}, - window::{WindowDescriptor, Windows}, + window::WindowDescriptor, DefaultPlugins, }; use kayak_core::constructor; @@ -11,7 +10,6 @@ use kayak_widgets::{App, Text}; fn startup( mut commands: Commands, - windows: Res<Windows>, mut font_mapping: ResMut<FontMapping>, asset_server: Res<AssetServer>, ) { @@ -19,16 +17,10 @@ fn startup( font_mapping.add(asset_server.load("roboto.kayak_font")); - let window_size = if let Some(window) = windows.get_primary() { - Vec2::new(window.width(), window.height()) - } else { - panic!("Couldn't find primary window!"); - }; - - let context = BevyContext::new(window_size.x, window_size.y, |styles, context| { + let context = BevyContext::new(|context| { let data = vec!["Text1", "Text2", "Text3", "Text4"]; render! { - <App styles={Some(styles.clone())}> + <App> {VecTracker::from(data.iter().map(|data| { constructor! { <Text content={data.clone().to_string()} size={16.0} /> diff --git a/kayak_core/src/context.rs b/kayak_core/src/context.rs index f75ddb7619560185f40bba90d178b0b34c7878b0..19300e25d7d55a3c27cdfea62b6ebb8a5f95e37c 100644 --- a/kayak_core/src/context.rs +++ b/kayak_core/src/context.rs @@ -209,16 +209,10 @@ impl KayakContext { panic!("Couldn't get lock on dirty nodes!") }; for node_index in dirty_nodes { - // if self - // .widget_manager - // .dirty_nodes - // .iter() - // .any(|dirty_index| node_index == *dirty_index) - // { let mut widget = self.widget_manager.take(node_index); widget.render(self); self.widget_manager.repossess(widget); - // } + self.widget_manager.dirty_render_nodes.insert(node_index); } // self.widget_manager.dirty_nodes.clear(); diff --git a/kayak_core/src/widget_manager.rs b/kayak_core/src/widget_manager.rs index 3237ba076703341a5a9b75193f17f40b1919bb5e..3d9e1c321443f8fe0d61ea7f726370682faeae4d 100644 --- a/kayak_core/src/widget_manager.rs +++ b/kayak_core/src/widget_manager.rs @@ -17,7 +17,7 @@ use crate::{ #[derive(Debug)] pub struct WidgetManager { pub(crate) current_widgets: Arena<Option<Box<dyn Widget>>>, - pub(crate) dirty_render_nodes: Vec<Index>, + pub(crate) dirty_render_nodes: HashSet<Index>, pub(crate) dirty_nodes: Arc<Mutex<HashSet<Index>>>, pub(crate) nodes: Arena<Option<Node>>, pub tree: Tree, @@ -30,7 +30,7 @@ impl WidgetManager { pub fn new() -> Self { Self { current_widgets: Arena::new(), - dirty_render_nodes: Vec::new(), + dirty_render_nodes: HashSet::new(), dirty_nodes: Arc::new(Mutex::new(HashSet::new())), nodes: Arena::new(), tree: Tree::default(), @@ -51,7 +51,7 @@ impl WidgetManager { if force { for (node_index, _) in self.current_widgets.iter() { dirty_nodes.insert(node_index); - self.dirty_render_nodes.push(node_index); + self.dirty_render_nodes.insert(node_index); } } } @@ -86,7 +86,7 @@ impl WidgetManager { let boxed_widget: Box<dyn Widget> = Box::new(widget); *self.current_widgets[*widget_id].as_mut().unwrap() = boxed_widget; // Tell renderer that the nodes changed. - self.dirty_render_nodes.push(*widget_id); + self.dirty_render_nodes.insert(*widget_id); return (true, *widget_id); // } else { // return (false, *widget_id); @@ -106,7 +106,7 @@ impl WidgetManager { .set_id(widget_id); // Tell renderer that the nodes changed. - self.dirty_render_nodes.push(widget_id); + self.dirty_render_nodes.insert(widget_id); // Remove from the dirty nodes lists. // if let Some(index) = self.dirty_nodes.iter().position(|id| widget_id == *id) { @@ -148,7 +148,7 @@ impl WidgetManager { width: crate::styles::StyleProp::Default, ..Style::default() }; - for dirty_node_index in self.dirty_render_nodes.drain(..) { + for dirty_node_index in self.dirty_render_nodes.drain() { let dirty_widget = self.current_widgets[dirty_node_index].as_ref().unwrap(); let parent_styles = if let Some(parent_widget_id) = self.tree.parents.get(&dirty_node_index) { @@ -198,6 +198,7 @@ impl WidgetManager { .cloned() .unwrap_or(vec![]); let styles = styles.unwrap_or(default_styles.clone()); + if matches!(styles.render_command.resolve(), RenderCommand::Empty) { continue; } diff --git a/kayak_widgets/Cargo.toml b/kayak_widgets/Cargo.toml index 1f4158e6d2ac69130ae8adbc6288a65024f1987b..a1c7814859b98717503b005bfc47b951ad883195 100644 --- a/kayak_widgets/Cargo.toml +++ b/kayak_widgets/Cargo.toml @@ -4,5 +4,10 @@ version = "0.1.0" edition = "2021" resolver = "2" +[features] +default = [] +bevy_renderer = ["bevy", "kayak_ui/bevy_renderer"] + [dependencies] kayak_ui = { path = "../", version = "0.1.0" } +bevy = { git = "https://github.com/StarArawn/bevy", rev = "bcca341d696c66d0173d8b0ac7a1b23b4b9e775c", optional = true } diff --git a/kayak_widgets/src/app.rs b/kayak_widgets/src/app.rs index 0ff42b42141a9dab9d846945a8537d0966c551c4..a77f39dce391a987130c28dced02a2392750ea4f 100644 --- a/kayak_widgets/src/app.rs +++ b/kayak_widgets/src/app.rs @@ -1,10 +1,42 @@ +use kayak_ui::bevy::WindowSize; use kayak_ui::core::derivative::*; -use kayak_ui::core::{rsx, widget, Children}; +use kayak_ui::core::{ + render_command::RenderCommand, + rsx, + styles::{Style, StyleProp, Units}, + widget, Binding, Bound, Children, +}; use crate::Clip; #[widget] pub fn App(children: Children) { + *styles = Some(Style { + render_command: StyleProp::Value(RenderCommand::Window), + ..styles.clone().unwrap_or_default() + }); + + #[cfg(feature = "bevy_renderer")] + { + let window_size = if let Ok(world) = context.get_global_state::<bevy::prelude::World>() { + if let Some(window_size) = world.get_resource::<Binding<WindowSize>>() { + window_size.clone() + } else { + return; + } + } else { + return; + }; + + context.bind(&window_size); + let window_size = window_size.get(); + *styles = Some(Style { + width: StyleProp::Value(Units::Pixels(window_size.0)), + height: StyleProp::Value(Units::Pixels(window_size.1)), + ..styles.clone().unwrap_or_default() + }); + } + rsx! { <Clip> {children}