From 831a491efe5cd3dd225eb2ca9ef447e3aaf0ed9f Mon Sep 17 00:00:00 2001 From: NiseVoid Date: Fri, 8 Mar 2024 12:26:53 +0100 Subject: [PATCH 1/6] Make bevy_svg optional --- Cargo.toml | 15 +++- src/render/material/pipeline.rs | 7 +- src/render/mod.rs | 1 + src/render/unified/mod.rs | 26 ++++-- src/render/unified/pipeline.rs | 152 +++++++++++++++++--------------- src/render_primitive.rs | 5 +- src/styles/render_command.rs | 2 + src/widgets/mod.rs | 11 +++ 8 files changed, 138 insertions(+), 81 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dabdad80..d9073d35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,11 +13,14 @@ exclude = ["assets/*", "screenshots/*", "book"] [workspace] members = ["kayak_ui_macros", "kayak_font"] +[features] +svg = ["dep:bevy_svg"] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bevy = { version = "0.12", default-features = false, features = ["bevy_render", "bevy_asset", "bevy_winit", "bevy_core_pipeline"] } -bevy_svg = { version="0.12", default-features = false } +bevy_svg = { version="0.12", default-features = false, optional = true } bitflags = "1.3.2" bytemuck = "1.12" dashmap = "5.4" @@ -47,5 +50,15 @@ path = "examples/tabs/tabs.rs" name = "todo" path = "examples/todo/todo.rs" +[[example]] +name = "svg" +path = "examples/svg.rs" +required-features = ["svg"] + +[[example]] +name = "accordion" +path = "examples/accordion.rs" +required-features = ["svg"] + [package.metadata.docs.rs] features = ["bevy/x11"] diff --git a/src/render/material/pipeline.rs b/src/render/material/pipeline.rs index 8b1177d8..f83eb126 100644 --- a/src/render/material/pipeline.rs +++ b/src/render/material/pipeline.rs @@ -28,10 +28,12 @@ use kayak_font::bevy::FontTextureCache; use std::hash::Hash; use std::marker::PhantomData; +#[cfg(feature = "svg")] +use crate::render::svg::RenderSvgs; + use crate::render::{ extract::UIExtractedView, opacity_layer::OpacityLayerManager, - svg::RenderSvgs, ui_pass::{TransparentOpacityUI, TransparentUI, UIRenderPhase}, unified::pipeline::{ queue_quads_inner, DrawUIDraw, ExtractedQuad, ImageBindGroups, MaterialZ, PreviousClip, @@ -303,7 +305,7 @@ impl RenderCommand

for SetMateri } pub fn queue_material_ui_quads( - render_svgs: Res, + #[cfg(feature = "svg")] render_svgs: Res, opacity_layers: Res, mut commands: Commands, draw_functions: Res>, @@ -410,6 +412,7 @@ pub fn queue_material_ui_quads( &mut image_bind_groups, &gpu_images, &quad_pipeline, + #[cfg(feature = "svg")] &render_svgs, &mut transparent_phase, &mut opacity_transparent_phase, diff --git a/src/render/mod.rs b/src/render/mod.rs index c6d27223..c7ff955e 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -28,6 +28,7 @@ pub mod material; pub(crate) mod nine_patch; mod opacity_layer; pub(crate) mod quad; +#[cfg(feature = "svg")] pub(crate) mod svg; pub(crate) mod texture_atlas; mod ui_pass; diff --git a/src/render/unified/mod.rs b/src/render/unified/mod.rs index 72452168..9762ebe2 100644 --- a/src/render/unified/mod.rs +++ b/src/render/unified/mod.rs @@ -1,5 +1,7 @@ +#[cfg(feature = "svg")] +use bevy::prelude::AssetApp; use bevy::{ - asset::{load_internal_asset, AssetApp, Handle}, + asset::{load_internal_asset, Handle}, prelude::{Commands, IntoSystemConfigs, Plugin, Query, Res, ResMut, Resource, With}, render::{ render_phase::AddRenderCommand, @@ -9,6 +11,7 @@ use bevy::{ }, window::{PrimaryWindow, Window}, }; +#[cfg(feature = "svg")] use bevy_svg::prelude::Svg; use crate::{ @@ -24,7 +27,9 @@ use self::pipeline::{ ImageBindGroups, PreviousClip, PreviousIndex, QuadTypeOffsets, }; -use super::{svg::RenderSvgs, ui_pass::TransparentOpacityUI}; +#[cfg(feature = "svg")] +use super::svg::RenderSvgs; +use super::ui_pass::TransparentOpacityUI; pub mod pipeline; pub mod text; @@ -40,8 +45,9 @@ pub const VERTEX_OUTPUT_HANDLE: Handle = Handle::weak_from_u128(88288962 pub struct UnifiedRenderPlugin; impl Plugin for UnifiedRenderPlugin { fn build(&self, app: &mut bevy::prelude::App) { - app.init_asset::() - .add_plugins(text::TextRendererPlugin); + #[cfg(feature = "svg")] + app.init_asset::(); + app.add_plugins(text::TextRendererPlugin); load_internal_asset!( app, @@ -77,13 +83,19 @@ impl Plugin for UnifiedRenderPlugin { .init_resource::() .init_resource::() .init_resource::() - .init_resource::() - .init_resource::() + .init_resource::(); + #[cfg(feature = "svg")] + render_app.init_resource::(); + render_app .init_resource::() .init_resource::() .add_systems( ExtractSchedule, - (super::svg::extract_svg_asset, extract_baseline), + ( + #[cfg(feature = "svg")] + super::svg::extract_svg_asset, + extract_baseline, + ), ) .add_systems( Render, diff --git a/src/render/unified/pipeline.rs b/src/render/unified/pipeline.rs index 154608d1..c16e7188 100644 --- a/src/render/unified/pipeline.rs +++ b/src/render/unified/pipeline.rs @@ -1,7 +1,10 @@ use bevy::ecs::query::ROQueryItem; use bevy::ecs::system::{SystemParam, SystemParamItem}; -use bevy::prelude::{Commands, Mesh, Rect, Resource, Vec3, With}; +#[cfg(feature = "svg")] +use bevy::prelude::{Mesh, Vec3}; +use bevy::prelude::{Commands, Rect, Resource, With}; use bevy::render::globals::{GlobalsBuffer, GlobalsUniform}; +#[cfg(feature = "svg")] use bevy::render::mesh::VertexAttributeValues; use bevy::render::render_phase::{ DrawFunctionId, PhaseItem, RenderCommand, RenderCommandResult, SetItemPipeline, @@ -35,6 +38,7 @@ use bevy::{ }, utils::HashMap, }; +#[cfg(feature = "svg")] use bevy_svg::prelude::Svg; use bytemuck::{Pod, Zeroable}; use kayak_font::{bevy::FontTextureCache, KayakFont}; @@ -45,6 +49,7 @@ use crate::layout::LayoutCache; use crate::prelude::Corner; use crate::render::extract::{UIExtractedView, UIViewUniform, UIViewUniformOffset, UIViewUniforms}; use crate::render::opacity_layer::OpacityLayerManager; +#[cfg(feature = "svg")] use crate::render::svg::RenderSvgs; use crate::render::ui_pass::{ TransparentOpacityUI, TransparentUI, TransparentUIGeneric, UIRenderPhase, @@ -377,6 +382,7 @@ pub struct ExtractedQuad { pub image: Option>, pub uv_min: Option, pub uv_max: Option, + #[cfg(feature = "svg")] pub svg_handle: (Option>, Option), pub opacity_layer: u32, pub c: char, @@ -398,6 +404,7 @@ impl Default for ExtractedQuad { image: Default::default(), uv_min: Default::default(), uv_max: Default::default(), + #[cfg(feature = "svg")] svg_handle: Default::default(), opacity_layer: 0, c: ' ', @@ -811,6 +818,7 @@ pub struct PreviousIndex { #[derive(SystemParam)] pub struct QueueQuads<'w, 's> { + #[cfg(feature = "svg")] render_svgs: Res<'w, RenderSvgs>, opacity_layers: Res<'w, OpacityLayerManager>, commands: Commands<'w, 's>, @@ -845,6 +853,7 @@ pub struct QueueQuads<'w, 's> { pub fn queue_quads(queue_quads: QueueQuads) { let QueueQuads { + #[cfg(feature = "svg")] render_svgs, opacity_layers, mut commands, @@ -944,6 +953,7 @@ pub fn queue_quads(queue_quads: QueueQuads) { &mut image_bind_groups, &gpu_images, &unified_pipeline, + #[cfg(feature = "svg")] &render_svgs, &mut transparent_phase, &mut opacity_transparent_phase, @@ -1023,7 +1033,7 @@ pub fn queue_quads_inner( image_bind_groups: &mut ImageBindGroups, gpu_images: &RenderAssets, unified_pipeline: &UnifiedPipeline, - render_svgs: &RenderSvgs, + #[cfg(feature = "svg")] render_svgs: &RenderSvgs, transparent_phase: &mut UIRenderPhase, opacity_transparent_phase: &mut UIRenderPhase, draw_opacity_quad: DrawFunctionId, @@ -1279,6 +1289,7 @@ pub fn queue_quads_inner( return; } + #[cfg(feature = "svg")] if let (Some(svg_handle), color) = (quad.svg_handle.0.as_ref(), quad.svg_handle.1.as_ref()) { if let Some((svg, mesh)) = render_svgs.get(&svg_handle.id()) { let new_height = (svg.view_box.h as f32 / svg.view_box.w as f32) * sprite_rect.size().x; @@ -1332,79 +1343,80 @@ pub fn queue_quads_inner( *index += indices.len() as u32; *item_end = *index; } - } else { - let color = quad.color.as_linear_rgba_f32(); + return; + } - let uv_min = quad.uv_min.unwrap_or(Vec2::ZERO); - let uv_max = quad.uv_max.unwrap_or(Vec2::ONE); + let color = quad.color.as_linear_rgba_f32(); - let bottom_left = Vec4::new( - uv_min.x, - uv_min.y, - quad.char_id as f32, - quad.border_radius.bottom_left, - ); - let top_left = Vec4::new( - uv_min.x, - uv_max.y, - quad.char_id as f32, - quad.border_radius.top_left, - ); - let top_right = Vec4::new( - uv_max.x, - uv_max.y, - quad.char_id as f32, - quad.border_radius.top_right, - ); - let bottom_right = Vec4::new( - uv_max.x, - uv_min.y, - quad.char_id as f32, - quad.border_radius.bottom_right, - ); + let uv_min = quad.uv_min.unwrap_or(Vec2::ZERO); + let uv_max = quad.uv_max.unwrap_or(Vec2::ONE); - let uvs: [[f32; 4]; 6] = [ - top_left.into(), - bottom_right.into(), - bottom_left.into(), - top_left.into(), - top_right.into(), - bottom_right.into(), - ]; - - const QUAD_INDICES: [usize; 6] = [0, 2, 3, 0, 1, 2]; - - const QUAD_VERTEX_POSITIONS: [Vec2; 4] = [ - Vec2::new(0.0, 0.0), - Vec2::new(1.0, 0.0), - Vec2::new(1.0, 1.0), - Vec2::new(0.0, 1.0), - ]; - - for (index, vertex_index) in QUAD_INDICES.iter().enumerate() { - let vertex_position = QUAD_VERTEX_POSITIONS[*vertex_index]; - let world = Mat4::from_scale_rotation_translation( - sprite_rect.size().extend(1.0), - Quat::default(), - sprite_rect.min.extend(0.0), - ); - let final_position = (world * vertex_position.extend(0.0).extend(1.0)).truncate(); - quad_meta.vertices.push(QuadVertex { - position: final_position.into(), - color, - uv: uvs[index], - pos_size: [ - sprite_rect.min.x, - sprite_rect.min.y, - sprite_rect.size().x, - sprite_rect.size().y, - ], - }); - } + let bottom_left = Vec4::new( + uv_min.x, + uv_min.y, + quad.char_id as f32, + quad.border_radius.bottom_left, + ); + let top_left = Vec4::new( + uv_min.x, + uv_max.y, + quad.char_id as f32, + quad.border_radius.top_left, + ); + let top_right = Vec4::new( + uv_max.x, + uv_max.y, + quad.char_id as f32, + quad.border_radius.top_right, + ); + let bottom_right = Vec4::new( + uv_max.x, + uv_min.y, + quad.char_id as f32, + quad.border_radius.bottom_right, + ); - *index += QUAD_INDICES.len() as u32; - *item_end = *index; + let uvs: [[f32; 4]; 6] = [ + top_left.into(), + bottom_right.into(), + bottom_left.into(), + top_left.into(), + top_right.into(), + bottom_right.into(), + ]; + + const QUAD_INDICES: [usize; 6] = [0, 2, 3, 0, 1, 2]; + + const QUAD_VERTEX_POSITIONS: [Vec2; 4] = [ + Vec2::new(0.0, 0.0), + Vec2::new(1.0, 0.0), + Vec2::new(1.0, 1.0), + Vec2::new(0.0, 1.0), + ]; + + for (index, vertex_index) in QUAD_INDICES.iter().enumerate() { + let vertex_position = QUAD_VERTEX_POSITIONS[*vertex_index]; + let world = Mat4::from_scale_rotation_translation( + sprite_rect.size().extend(1.0), + Quat::default(), + sprite_rect.min.extend(0.0), + ); + let final_position = (world * vertex_position.extend(0.0).extend(1.0)).truncate(); + quad_meta.vertices.push(QuadVertex { + position: final_position.into(), + color, + uv: uvs[index], + pos_size: [ + sprite_rect.min.x, + sprite_rect.min.y, + sprite_rect.size().x, + sprite_rect.size().y, + ], + }); } + + *index += QUAD_INDICES.len() as u32; + *item_end = *index; } pub type DrawUI = ( diff --git a/src/render_primitive.rs b/src/render_primitive.rs index 26b2ba80..5b0ff369 100644 --- a/src/render_primitive.rs +++ b/src/render_primitive.rs @@ -6,8 +6,10 @@ use crate::{ font::FontMapping, unified::pipeline::{ExtractedQuad, ExtractedQuads, QuadOrMaterial, UIQuadType}, }, - styles::{Corner, KStyle, RenderCommand, StyleProp}, + styles::{Corner, KStyle, RenderCommand} }; +#[cfg(feature = "svg")] +use crate::styles::{StyleProp}; pub trait RenderPrimitive { fn extract( @@ -250,6 +252,7 @@ impl RenderPrimitive for KStyle { ); } } + #[cfg(feature = "svg")] RenderCommand::Svg { handle } => { let mut svgs = crate::render::svg::extract_svg( camera_entity, diff --git a/src/styles/render_command.rs b/src/styles/render_command.rs index cfe3dda3..27453ed8 100644 --- a/src/styles/render_command.rs +++ b/src/styles/render_command.rs @@ -2,6 +2,7 @@ use bevy::{ prelude::{Handle, Image, Vec2}, reflect::Reflect, }; +#[cfg(feature = "svg")] use bevy_svg::prelude::Svg; use kayak_font::{Alignment, TextLayout, TextProperties}; @@ -34,6 +35,7 @@ pub enum RenderCommand { border: Edge, handle: Handle, }, + #[cfg(feature = "svg")] Svg { handle: Handle, }, diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 2f715d98..2ee1a494 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -22,17 +22,20 @@ use bevy::prelude::*; +#[cfg(feature = "svg")] mod accordion; mod app; mod background; mod button; mod clip; mod element; +#[cfg(feature = "svg")] mod icons; mod image; mod modal; mod nine_patch; mod scroll; +#[cfg(feature = "svg")] mod svg; mod text; mod text_box; @@ -41,12 +44,14 @@ mod transition; mod window; mod window_context_provider; +#[cfg(feature = "svg")] pub use accordion::*; pub use app::{KayakApp, KayakAppBundle}; pub use background::{Background, BackgroundBundle}; pub use button::{ButtonState, KButton, KButtonBundle}; pub use clip::{Clip, ClipBundle}; pub use element::{Element, ElementBundle}; +#[cfg(feature = "svg")] pub use icons::*; pub use image::{KImage, KImageBundle}; pub use modal::{Modal, ModalBundle}; @@ -59,6 +64,7 @@ pub use scroll::{ ScrollContext, ScrollContextProvider, ScrollContextProviderBundle, ScrollMode, }, }; +#[cfg(feature = "svg")] pub use svg::{KSvg, KSvgBundle, Svg}; pub use text::{TextProps, TextWidgetBundle}; pub use text_box::{TextBoxBundle, TextBoxProps, TextBoxState}; @@ -83,6 +89,7 @@ use scroll::{ scroll_bar::scroll_bar_render, scroll_box::scroll_box_render, scroll_content::scroll_content_render, scroll_context::scroll_context_render, }; +#[cfg(feature = "svg")] use svg::svg_render; use text::text_render; use text_box::text_box_render; @@ -101,6 +108,7 @@ pub struct KayakWidgets; impl Plugin for KayakWidgets { fn build(&self, app: &mut bevy::prelude::App) { + #[cfg(feature = "svg")] app.add_plugins(icons::IconsPlugin); app.add_systems( PostUpdate, @@ -114,6 +122,7 @@ pub struct KayakWidgetsContextPlugin; impl KayakUIPlugin for KayakWidgetsContextPlugin { fn build(&self, context: &mut KayakRootContext) { + #[cfg(feature = "svg")] context.add_plugin(AccordionPlugin); context.add_widget_data::(); context.add_widget_data::(); @@ -125,6 +134,7 @@ impl KayakUIPlugin for KayakWidgetsContextPlugin { context.add_widget_data::(); context.add_widget_data::(); context.add_widget_data::(); + #[cfg(feature = "svg")] context.add_widget_data::(); context.add_widget_data::(); context.add_widget_data::(); @@ -181,6 +191,7 @@ impl KayakUIPlugin for KayakWidgetsContextPlugin { widget_update::, nine_patch_render, ); + #[cfg(feature = "svg")] context.add_widget_system( KSvg::default().get_name(), widget_update::, From 88dd319582df3f5ca15c2e2f3d4c1ab3961d81f0 Mon Sep 17 00:00:00 2001 From: NiseVoid Date: Fri, 8 Mar 2024 12:32:02 +0100 Subject: [PATCH 2/6] Disable bevy_svg --- Cargo.toml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d9073d35..1f5f3416 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,13 @@ exclude = ["assets/*", "screenshots/*", "book"] members = ["kayak_ui_macros", "kayak_font"] [features] -svg = ["dep:bevy_svg"] +svg = [] #["dep:bevy_svg"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bevy = { version = "0.12", default-features = false, features = ["bevy_render", "bevy_asset", "bevy_winit", "bevy_core_pipeline"] } -bevy_svg = { version="0.12", default-features = false, optional = true } +# bevy_svg = { version="0.12", default-features = false, optional = true } bitflags = "1.3.2" bytemuck = "1.12" dashmap = "5.4" @@ -53,11 +53,17 @@ path = "examples/todo/todo.rs" [[example]] name = "svg" path = "examples/svg.rs" +test = false +doc = false +bench = false required-features = ["svg"] [[example]] name = "accordion" path = "examples/accordion.rs" +test = false +doc = false +bench = false required-features = ["svg"] [package.metadata.docs.rs] From 8bd598ec3e139ca32f9dc41d2db6fe4fc468fd56 Mon Sep 17 00:00:00 2001 From: NiseVoid Date: Fri, 8 Mar 2024 14:00:38 +0100 Subject: [PATCH 3/6] Migrate to bevy 0.13 --- Cargo.toml | 7 +-- examples/avsb.rs | 5 +- examples/bevy_scene.rs | 2 +- examples/demo.rs | 2 +- examples/main_menu.rs | 2 +- examples/render_target.rs | 9 ++-- examples/test_no_startup.rs | 2 +- examples/text.rs | 2 +- examples/texture_atlas.rs | 3 +- kayak_font/Cargo.toml | 4 +- kayak_font/src/bevy/renderer/extract.rs | 1 + kayak_font/src/ttf/loader.rs | 6 ++- src/camera/mod.rs | 6 +-- src/event.rs | 6 +-- src/event_dispatcher.rs | 11 ++-- src/input.rs | 14 ++--- src/input_event.rs | 2 +- src/lib.rs | 2 +- src/render/extract.rs | 2 +- src/render/material/pipeline.rs | 10 ++-- src/render/mod.rs | 59 ++++++++++---------- src/render/ui_pass.rs | 9 ++-- src/render/unified/pipeline.rs | 71 +++++++++++++------------ src/styles/style.rs | 2 +- src/widgets/button.rs | 2 +- src/widgets/modal.rs | 2 +- src/widgets/text_box.rs | 35 ++++++------ src/widgets/window.rs | 2 +- 28 files changed, 146 insertions(+), 134 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1f5f3416..f90ffe15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ svg = [] #["dep:bevy_svg"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bevy = { version = "0.12", default-features = false, features = ["bevy_render", "bevy_asset", "bevy_winit", "bevy_core_pipeline"] } +bevy = { version = "0.13", default-features = false, features = ["bevy_render", "bevy_asset", "bevy_core_pipeline"] } # bevy_svg = { version="0.12", default-features = false, optional = true } bitflags = "1.3.2" bytemuck = "1.12" @@ -36,11 +36,12 @@ reorder = "2.1" resources = "1.1" usvg = "0.27" uuid = { version = "1.3", features = ["v4"] } +smol_str = {version = "0.2", default-features = false} [dev-dependencies] fastrand = "1.8" -bevy-inspector-egui = "0.21" -bevy = { version = "0.12", default-features = true } +bevy-inspector-egui = "0.23" +bevy = { version = "0.13", default-features = true } [[example]] name = "tabs" diff --git a/examples/avsb.rs b/examples/avsb.rs index 836f846f..544df759 100644 --- a/examples/avsb.rs +++ b/examples/avsb.rs @@ -202,7 +202,10 @@ fn startup( commands.spawn((widget_context, EventDispatcher::default())); } -fn swap(input: Res>, mut query: Query<&mut AvsBState, Without>) { +fn swap( + input: Res>, + mut query: Query<&mut AvsBState, Without>, +) { if input.just_pressed(KeyCode::Space) { for mut avsb in query.iter_mut() { avsb.is_a = !avsb.is_a; diff --git a/examples/bevy_scene.rs b/examples/bevy_scene.rs index a33793f8..705938fc 100644 --- a/examples/bevy_scene.rs +++ b/examples/bevy_scene.rs @@ -38,7 +38,7 @@ struct WorldCamera; /// to filter out clicks that occur over the UI fn set_active_tile_target( mut tile: Query<&mut ActiveTile>, - cursor: Res>, + cursor: Res>, event_context: Query<&EventDispatcher, With>, camera_transform: Query<&GlobalTransform, With>, window: Query<&Window, With>, diff --git a/examples/demo.rs b/examples/demo.rs index d4f15421..0b235180 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -57,7 +57,7 @@ fn startup(mut commands: Commands) { // Note this example shows prop changing not state changing which is quite different. // For state changes please see simple_state example. fn update_resource( - keyboard_input: Res>, + keyboard_input: Res>, mut query: Query<&mut MyWidget, Without>, ) { if keyboard_input.just_pressed(KeyCode::Space) { diff --git a/examples/main_menu.rs b/examples/main_menu.rs index 3e2625db..410a5a53 100644 --- a/examples/main_menu.rs +++ b/examples/main_menu.rs @@ -22,7 +22,7 @@ impl Default for MenuButtonBundle { button: Default::default(), styles: KStyle { bottom: Units::Pixels(20.0).into(), - cursor: KCursorIcon(CursorIcon::Hand).into(), + cursor: KCursorIcon(CursorIcon::Pointer).into(), ..Default::default() }, on_event: OnEvent::default(), diff --git a/examples/render_target.rs b/examples/render_target.rs index 1d5bfec1..d1517509 100644 --- a/examples/render_target.rs +++ b/examples/render_target.rs @@ -62,11 +62,10 @@ fn startup( camera: Camera { order: -1, target: RenderTarget::Image(image_handle.clone()), + clear_color: ClearColorConfig::None, ..Camera::default() }, - camera_2d: Camera2d { - clear_color: bevy::core_pipeline::clear_color::ClearColorConfig::Default, - }, + camera_2d: Camera2d, ..Default::default() }) .insert(CameraUIKayak) @@ -107,7 +106,7 @@ fn startup( }); let cube_size = 4.0; - let cube_handle = meshes.add(Mesh::from(shape::Box::new(cube_size, cube_size, cube_size))); + let cube_handle = meshes.add(Mesh::from(Cuboid::from_size(Vec3::splat(cube_size)))); // This material has the texture that has been rendered. let material_handle = materials.add(StandardMaterial { @@ -169,7 +168,7 @@ fn cube_rotator_system(time: Res

for SetMaterialBindGroup { type Param = SRes>; - type ViewWorldQuery = (); - type ItemWorldQuery = Read>; + type ViewQuery = (); + type ItemQuery = Read>; #[inline] fn render<'w>( _item: &P, _view: (), - material2d_handle: ROQueryItem<'_, Self::ItemWorldQuery>, + material2d_handle: Option>, materials: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(material2d_handle) = material2d_handle else { + return RenderCommandResult::Failure; + }; let asset_id: AssetId = material2d_handle.clone_weak().into(); let material2d = materials.into_inner().get(&asset_id).unwrap(); pass.set_bind_group(I, &material2d.bind_group, &[]); diff --git a/src/render/mod.rs b/src/render/mod.rs index c7ff955e..90c0d0d4 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -3,7 +3,7 @@ use bevy::{ render::{ camera::RenderTarget, render_asset::RenderAssets, - render_graph::{RenderGraph, RunGraphOnViewNode}, + render_graph::{RenderGraph, RenderLabel, RenderSubGraph, RunGraphOnViewNode}, render_phase::DrawFunctions, Extract, ExtractSchedule, Render, RenderApp, RenderSet, }, @@ -36,12 +36,11 @@ pub mod unified; pub use opacity_layer::MAX_OPACITY_LAYERS; -pub mod draw_ui_graph { - pub const NAME: &str = "kayak_draw_ui"; - pub mod node { - pub const MAIN_PASS: &str = "kayak_ui_pass"; - } -} +#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderSubGraph)] +pub struct DrawUiGraph; + +#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)] +pub struct KayakUiPass; /// The default Kayak UI rendering plugin. /// Use this to render the UI. @@ -86,43 +85,39 @@ impl Plugin for BevyKayakUIRenderPlugin { let ui_graph_3d = get_ui_graph(render_app); let mut graph = render_app.world.resource_mut::(); - if let Some(graph_2d) = graph.get_sub_graph_mut(bevy::core_pipeline::core_2d::graph::NAME) { - graph_2d.add_sub_graph(draw_ui_graph::NAME, ui_graph_2d); - graph_2d.add_node( - draw_ui_graph::node::MAIN_PASS, - RunGraphOnViewNode::new(draw_ui_graph::NAME), - ); + if let Some(graph_2d) = graph.get_sub_graph_mut(bevy::core_pipeline::core_2d::graph::Core2d) + { + graph_2d.add_sub_graph(DrawUiGraph, ui_graph_2d); + graph_2d.add_node(KayakUiPass, RunGraphOnViewNode::new(DrawUiGraph)); graph_2d.add_node_edge( - bevy::core_pipeline::core_2d::graph::node::MAIN_PASS, - draw_ui_graph::node::MAIN_PASS, + bevy::core_pipeline::core_2d::graph::Node2d::MainPass, + KayakUiPass, ); graph_2d.add_node_edge( - bevy::core_pipeline::core_2d::graph::node::TONEMAPPING, - draw_ui_graph::node::MAIN_PASS, + bevy::core_pipeline::core_2d::graph::Node2d::Tonemapping, + KayakUiPass, ); graph_2d.add_node_edge( - draw_ui_graph::node::MAIN_PASS, - bevy::core_pipeline::core_2d::graph::node::UPSCALING, + KayakUiPass, + bevy::core_pipeline::core_2d::graph::Node2d::Upscaling, ); } - if let Some(graph_3d) = graph.get_sub_graph_mut(bevy::core_pipeline::core_3d::graph::NAME) { - graph_3d.add_sub_graph(draw_ui_graph::NAME, ui_graph_3d); - graph_3d.add_node( - draw_ui_graph::node::MAIN_PASS, - RunGraphOnViewNode::new(draw_ui_graph::NAME), - ); + if let Some(graph_3d) = graph.get_sub_graph_mut(bevy::core_pipeline::core_3d::graph::Core3d) + { + graph_3d.add_sub_graph(DrawUiGraph, ui_graph_3d); + graph_3d.add_node(KayakUiPass, RunGraphOnViewNode::new(DrawUiGraph)); graph_3d.add_node_edge( - bevy::core_pipeline::core_3d::graph::node::END_MAIN_PASS, - draw_ui_graph::node::MAIN_PASS, + bevy::core_pipeline::core_3d::graph::Node3d::EndMainPass, + KayakUiPass, ); graph_3d.add_node_edge( - bevy::core_pipeline::core_3d::graph::node::TONEMAPPING, - draw_ui_graph::node::MAIN_PASS, + bevy::core_pipeline::core_3d::graph::Node3d::Tonemapping, + KayakUiPass, ); graph_3d.add_node_edge( - draw_ui_graph::node::MAIN_PASS, - bevy::core_pipeline::core_3d::graph::node::UPSCALING, + KayakUiPass, + bevy::core_pipeline::core_3d::graph::Node3d::Upscaling, ); } } @@ -131,7 +126,7 @@ impl Plugin for BevyKayakUIRenderPlugin { fn get_ui_graph(render_app: &mut App) -> RenderGraph { let ui_pass_node = MainPassUINode::new(&mut render_app.world); let mut ui_graph = RenderGraph::default(); - ui_graph.add_node(draw_ui_graph::node::MAIN_PASS, ui_pass_node); + ui_graph.add_node(KayakUiPass, ui_pass_node); ui_graph } diff --git a/src/render/ui_pass.rs b/src/render/ui_pass.rs index 5181e7d1..a75221ca 100644 --- a/src/render/ui_pass.rs +++ b/src/render/ui_pass.rs @@ -235,10 +235,11 @@ impl Node for MainPassUINode { resolve_target: None, ops: Operations { load: LoadOp::Clear(Color::rgba(0.0, 0.0, 0.0, 0.0).into()), - store: true, + store: bevy::render::render_resource::StoreOp::Store, }, })], depth_stencil_attachment: None, + ..Default::default() }; let mut tracked_pass = @@ -260,11 +261,9 @@ impl Node for MainPassUINode { { let pass_descriptor = RenderPassDescriptor { label: Some("main_transparent_pass_UI"), - color_attachments: &[Some(target.get_unsampled_color_attachment(Operations { - load: LoadOp::Load, - store: true, - }))], + color_attachments: &[Some(target.get_unsampled_color_attachment())], depth_stencil_attachment: None, + ..Default::default() }; let mut tracked_pass = render_context.begin_tracked_render_pass(pass_descriptor); transparent_phase.render(&mut tracked_pass, world, view_entity); diff --git a/src/render/unified/pipeline.rs b/src/render/unified/pipeline.rs index c16e7188..840c5d34 100644 --- a/src/render/unified/pipeline.rs +++ b/src/render/unified/pipeline.rs @@ -1,8 +1,8 @@ use bevy::ecs::query::ROQueryItem; use bevy::ecs::system::{SystemParam, SystemParamItem}; +use bevy::prelude::{Commands, Rect, Resource, With}; #[cfg(feature = "svg")] use bevy::prelude::{Mesh, Vec3}; -use bevy::prelude::{Commands, Rect, Resource, With}; use bevy::render::globals::{GlobalsBuffer, GlobalsUniform}; #[cfg(feature = "svg")] use bevy::render::mesh::VertexAttributeValues; @@ -24,14 +24,14 @@ use bevy::{ render_asset::RenderAssets, render_phase::{DrawFunctions, TrackedRenderPass}, render_resource::{ - BindGroup, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor, - BindGroupLayoutEntry, BindingResource, BindingType, BlendState, BufferBindingType, - BufferSize, BufferUsages, BufferVec, ColorTargetState, ColorWrites, Extent3d, - FragmentState, FrontFace, MultisampleState, PipelineCache, PolygonMode, PrimitiveState, - PrimitiveTopology, RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, - ShaderStages, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, - TextureUsages, TextureViewDescriptor, TextureViewDimension, VertexAttribute, - VertexBufferLayout, VertexFormat, VertexState, VertexStepMode, + BindGroup, BindGroupEntry, BindGroupLayout, BindGroupLayoutEntry, BindingResource, + BindingType, BlendState, BufferBindingType, BufferSize, BufferUsages, BufferVec, + ColorTargetState, ColorWrites, Extent3d, FragmentState, FrontFace, MultisampleState, + PipelineCache, PolygonMode, PrimitiveState, PrimitiveTopology, + RenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor, ShaderStages, + TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages, + TextureViewDescriptor, TextureViewDimension, VertexAttribute, VertexBufferLayout, + VertexFormat, VertexState, VertexStepMode, }, renderer::{RenderDevice, RenderQueue}, texture::{BevyDefault, GpuImage, Image}, @@ -93,8 +93,9 @@ impl FromWorld for UnifiedPipeline { let world = world.cell(); let render_device = world.resource::(); - let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[ + let view_layout = render_device.create_bind_group_layout( + "ui_view_layout", + &[ BindGroupLayoutEntry { binding: 0, visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT, @@ -116,11 +117,11 @@ impl FromWorld for UnifiedPipeline { count: None, }, ], - label: Some("ui_view_layout"), - }); + ); - let types_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[BindGroupLayoutEntry { + let types_layout = render_device.create_bind_group_layout( + "ui_types_layout", + &[BindGroupLayoutEntry { binding: 0, visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT, ty: BindingType::Buffer { @@ -132,11 +133,11 @@ impl FromWorld for UnifiedPipeline { }, count: None, }], - label: Some("ui_types_layout"), - }); + ); - let image_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[ + let image_layout = render_device.create_bind_group_layout( + "image_layout", + &[ BindGroupLayoutEntry { binding: 0, visibility: ShaderStages::FRAGMENT, @@ -170,8 +171,7 @@ impl FromWorld for UnifiedPipeline { count: None, }, ], - label: Some("image_layout"), - }); + ); let empty_font_texture = FontTextureCache::get_empty(&render_device); @@ -750,31 +750,31 @@ pub fn queue_quad_types( ) { quad_meta.types_buffer.clear(); // sprite_meta.types_buffer.reserve(2, &render_device); - let quad_type_offset = quad_meta.types_buffer.push(QuadType { + let quad_type_offset = quad_meta.types_buffer.push(&QuadType { t: 0, _padding_1: 0, _padding_2: 0, _padding_3: 0, }); - let text_sub_pixel_type_offset = quad_meta.types_buffer.push(QuadType { + let text_sub_pixel_type_offset = quad_meta.types_buffer.push(&QuadType { t: 1, _padding_1: 0, _padding_2: 0, _padding_3: 0, }); - let text_type_offset = quad_meta.types_buffer.push(QuadType { + let text_type_offset = quad_meta.types_buffer.push(&QuadType { t: 2, _padding_1: 0, _padding_2: 0, _padding_3: 0, }); - let image_type_offset = quad_meta.types_buffer.push(QuadType { + let image_type_offset = quad_meta.types_buffer.push(&QuadType { t: 3, _padding_1: 0, _padding_2: 0, _padding_3: 0, }); - let box_shadow_type_offset = quad_meta.types_buffer.push(QuadType { + let box_shadow_type_offset = quad_meta.types_buffer.push(&QuadType { t: 4, _padding_1: 0, _padding_2: 0, @@ -1436,14 +1436,14 @@ pub struct SetUIViewBindGroup { } impl RenderCommand for SetUIViewBindGroup { type Param = (); - type ViewWorldQuery = (Read, Read); - type ItemWorldQuery = (); + type ViewQuery = (Read, Read); + type ItemQuery = (); #[inline] fn render<'w>( _item: &T, - (view_uniform, ui_view_bind_group): ROQueryItem<'w, Self::ViewWorldQuery>, - _: (), + (view_uniform, ui_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, + _: Option<()>, _: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -1460,16 +1460,19 @@ pub struct DrawUIDraw { impl RenderCommand for DrawUIDraw { type Param = (SRes, SRes, SRes); - type ViewWorldQuery = Read; - type ItemWorldQuery = Read; + type ViewQuery = Read; + type ItemQuery = Read; fn render<'w>( item: &T, - view: bevy::ecs::query::ROQueryItem<'w, Self::ViewWorldQuery>, - batch: bevy::ecs::query::ROQueryItem<'w, Self::ItemWorldQuery>, + view: bevy::ecs::query::ROQueryItem<'w, Self::ViewQuery>, + batch: Option>, param: bevy::ecs::system::SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { + let Some(batch) = batch else { + return RenderCommandResult::Failure; + }; let (quad_meta, unified_pipeline, image_bind_groups) = param; let quad_meta = quad_meta.into_inner(); diff --git a/src/styles/style.rs b/src/styles/style.rs index 25538b26..0fa75dc9 100644 --- a/src/styles/style.rs +++ b/src/styles/style.rs @@ -781,7 +781,7 @@ fn hsv_to_rgb(from: &Vec3) -> Color { res += Vec4::new(m, m, m, 0.0); - Color::from(res) + Color::rgba_from_array(res) } fn hsv_lerp(from: &Color, to: &Color, amount: f32) -> Color { diff --git a/src/widgets/button.rs b/src/widgets/button.rs index 65ca9808..a804bf3d 100644 --- a/src/widgets/button.rs +++ b/src/widgets/button.rs @@ -83,7 +83,7 @@ pub fn button_render( font_size: StyleProp::Value(font_size), height: StyleProp::Value(height), width: Units::Stretch(1.0).into(), - cursor: StyleProp::Value(KCursorIcon(CursorIcon::Hand)), + cursor: StyleProp::Value(KCursorIcon(CursorIcon::Pointer)), ..Default::default() }) .into(); diff --git a/src/widgets/modal.rs b/src/widgets/modal.rs index 4da4988d..96973893 100644 --- a/src/widgets/modal.rs +++ b/src/widgets/modal.rs @@ -154,7 +154,7 @@ pub fn render( > | { match event.event_type { EventType::KeyDown(key_event) => { - if key_event.key() == KeyCode::Right { + if key_event.key() == KeyCode::ArrowRight { if let Ok(mut state) = state_query.get_mut(state_entity) { if state.cursor_position < state.graphemes.len() { state.cursor_position += 1; @@ -201,7 +201,7 @@ pub fn text_box_render( ); } } - if key_event.key() == KeyCode::Left { + if key_event.key() == KeyCode::ArrowLeft { if let Ok(mut state) = state_query.get_mut(state_entity) { if state.cursor_position > 0 { state.cursor_position -= 1; @@ -215,30 +215,33 @@ pub fn text_box_render( } } } - EventType::CharInput { c } => { + EventType::CharInput { ref c } => { if let Ok(mut state) = state_query.get_mut(state_entity) { let cloned_on_change = cloned_on_change.clone(); if !state.focused { return; } let cursor_pos = state.cursor_position; - if is_backspace(c) { - if !state.current_value.is_empty() { - let char_pos: usize = state.graphemes[0..cursor_pos - 1] + for c in c.chars() { + if is_backspace(c) { + if !state.current_value.is_empty() { + let char_pos: usize = state.graphemes + [0..cursor_pos - 1] + .iter() + .map(|g| g.len()) + .sum(); + state.current_value.remove(char_pos); + state.cursor_position -= 1; + } + } else if !c.is_control() { + let char_pos: usize = state.graphemes[0..cursor_pos] .iter() .map(|g| g.len()) .sum(); - state.current_value.remove(char_pos); - state.cursor_position -= 1; + state.current_value.insert(char_pos, c); + + state.cursor_position += 1; } - } else if !c.is_control() { - let char_pos: usize = state.graphemes[0..cursor_pos] - .iter() - .map(|g| g.len()) - .sum(); - state.current_value.insert(char_pos, c); - - state.cursor_position += 1; } // Update graphemes diff --git a/src/widgets/window.rs b/src/widgets/window.rs index d6aa262b..731762a3 100644 --- a/src/widgets/window.rs +++ b/src/widgets/window.rs @@ -188,7 +188,7 @@ pub fn window_render( Date: Sun, 10 Mar 2024 20:34:20 +0100 Subject: [PATCH 4/6] Change CI workflow version --- .github/workflows/rust.yml | 4 ++-- src/render/extract.rs | 2 +- src/render/unified/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 645ee232..591bb1d5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -20,7 +20,7 @@ jobs: steps: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.75.0 + toolchain: 1.76.0 components: clippy, rustfmt - uses: actions/checkout@v3 - uses: actions/cache@v3 @@ -31,7 +31,7 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ - key: ${{ runner.os }}-cargo-build-1.75.0-${{ hashFiles('**/Cargo.toml') }} + key: ${{ runner.os }}-cargo-build-1.76.0-${{ hashFiles('**/Cargo.toml') }} - name: Install alsa and udev run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev if: runner.os == 'linux' diff --git a/src/render/extract.rs b/src/render/extract.rs index f1f67dfa..b0e7de47 100644 --- a/src/render/extract.rs +++ b/src/render/extract.rs @@ -62,7 +62,7 @@ pub fn extract( let dpi = if let Ok(camera) = cameras.get(context.camera_entity) { if let bevy::render::camera::RenderTarget::Window(WindowRef::Primary) = &camera.target { if let Ok(window) = primary_window.get_single() { - window.scale_factor() as f32 + window.scale_factor() } else { 1.0 } diff --git a/src/render/unified/mod.rs b/src/render/unified/mod.rs index 9762ebe2..a4939631 100644 --- a/src/render/unified/mod.rs +++ b/src/render/unified/mod.rs @@ -122,7 +122,7 @@ pub fn extract_baseline( window_size: Extract>, ) { let dpi = if let Ok(window) = windows.get_single() { - window.scale_factor() as f32 + window.scale_factor() } else { 1.0 }; From 5371ec19f632fa3f98ecc6c344da6f7576980a2f Mon Sep 17 00:00:00 2001 From: NiseVoid Date: Sun, 10 Mar 2024 20:40:11 +0100 Subject: [PATCH 5/6] Cargo fmt --- src/render_primitive.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render_primitive.rs b/src/render_primitive.rs index 5b0ff369..6b58dcff 100644 --- a/src/render_primitive.rs +++ b/src/render_primitive.rs @@ -1,15 +1,15 @@ use bevy::prelude::*; use kayak_font::KayakFont; +#[cfg(feature = "svg")] +use crate::styles::StyleProp; use crate::{ render::{ font::FontMapping, unified::pipeline::{ExtractedQuad, ExtractedQuads, QuadOrMaterial, UIQuadType}, }, - styles::{Corner, KStyle, RenderCommand} + styles::{Corner, KStyle, RenderCommand}, }; -#[cfg(feature = "svg")] -use crate::styles::{StyleProp}; pub trait RenderPrimitive { fn extract( From 415161458fb6afd24e5976d7a00601bfa6f4a69d Mon Sep 17 00:00:00 2001 From: StarToaster <6656977+StarArawn@users.noreply.github.com> Date: Sun, 24 Mar 2024 12:12:55 -0400 Subject: [PATCH 6/6] Fixed some issues with bevy-0-13. --- Cargo.toml | 4 ++-- src/render/svg/mod.rs | 1 + src/widgets/accordion/summary.rs | 10 +++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f90ffe15..100044e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,13 @@ exclude = ["assets/*", "screenshots/*", "book"] members = ["kayak_ui_macros", "kayak_font"] [features] -svg = [] #["dep:bevy_svg"] +svg = ["dep:bevy_svg"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] bevy = { version = "0.13", default-features = false, features = ["bevy_render", "bevy_asset", "bevy_core_pipeline"] } -# bevy_svg = { version="0.12", default-features = false, optional = true } +bevy_svg = { git = "https://github.com/arnfaldur/bevy_svg", rev="53a53e5af050a7b5b236068546be46c5729674e3", default-features = false, optional = true } bitflags = "1.3.2" bytemuck = "1.12" dashmap = "5.4" diff --git a/src/render/svg/mod.rs b/src/render/svg/mod.rs index 97f3c3c9..b0df765f 100644 --- a/src/render/svg/mod.rs +++ b/src/render/svg/mod.rs @@ -29,6 +29,7 @@ pub fn extract_svg_asset( changed_assets.remove(id); render_assets.remove(id); } + _ => {} } } diff --git a/src/widgets/accordion/summary.rs b/src/widgets/accordion/summary.rs index 70228cb9..37b6a006 100644 --- a/src/widgets/accordion/summary.rs +++ b/src/widgets/accordion/summary.rs @@ -61,7 +61,7 @@ pub fn render( .with_style(styles) .with_style(KStyle { render_command: RenderCommand::Layout.into(), - cursor: KCursorIcon(CursorIcon::Hand).into(), + cursor: KCursorIcon(CursorIcon::Pointer).into(), width: Units::Stretch(1.0).into(), height: Units::Auto.into(), ..Default::default() @@ -97,7 +97,7 @@ pub fn render( height: Units::Auto.into(), padding: Edge::new(Units::Pixels(12.0), Units::Pixels(16.0), Units::Pixels(16.0), Units::Pixels(16.0)).into(), layout_type: LayoutType::Row.into(), - cursor: KCursorIcon(CursorIcon::Hand).into(), + cursor: KCursorIcon(CursorIcon::Pointer).into(), ..Default::default() }} on_event={on_event} @@ -107,7 +107,7 @@ pub fn render( styles={KStyle { width: Units::Pixels(25.0).into(), height: Units::Pixels(20.0).into(), - cursor: KCursorIcon(CursorIcon::Hand).into(), + cursor: KCursorIcon(CursorIcon::Pointer).into(), ..Default::default() }} > @@ -117,7 +117,7 @@ pub fn render(