diff --git a/examples/clipping.rs b/examples/clipping.rs index e36b22a6..b59b2cfe 100644 --- a/examples/clipping.rs +++ b/examples/clipping.rs @@ -44,6 +44,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras sed tellus neque. nine_patch={NinePatch { handle: image, border: Edge::all(30.0), + ..default() }} styles={nine_patch_styles} > diff --git a/examples/main_menu.rs b/examples/main_menu.rs index 410a5a53..45f453a2 100644 --- a/examples/main_menu.rs +++ b/examples/main_menu.rs @@ -78,6 +78,7 @@ fn menu_button_render( nine_patch={NinePatch { handle: button_image_handle, border: Edge::all(10.0), + ..default() }} styles={KStyle { width: Units::Stretch(1.0).into(), @@ -162,6 +163,7 @@ fn startup( nine_patch={NinePatch { handle: panel1_image, border: Edge::all(25.0), + ..default() }} styles={KStyle { width: Units::Pixels(350.0).into(), diff --git a/examples/nine_patch.rs b/examples/nine_patch.rs index 405d59b3..90d44f59 100644 --- a/examples/nine_patch.rs +++ b/examples/nine_patch.rs @@ -45,6 +45,7 @@ fn startup( nine_patch={NinePatch { handle: image, border: Edge::all(15.0), + ..Default::default() }} styles={KStyle { width: StyleProp::Value(Units::Pixels(512.0)), diff --git a/src/render/nine_patch/extract.rs b/src/render/nine_patch/extract.rs index 1bbcb7d5..906a8d32 100644 --- a/src/render/nine_patch/extract.rs +++ b/src/render/nine_patch/extract.rs @@ -13,6 +13,7 @@ pub fn extract_nine_patch( layout: crate::layout::Rect, handle: Handle, border: Edge, + scale: f32, opacity_layer: u32, images: &Assets, dpi: f32, @@ -28,8 +29,8 @@ pub fn extract_nine_patch( let image_size = image .map(|i| { Vec2::new( - i.texture_descriptor.size.width as f32, - i.texture_descriptor.size.height as f32, + i.texture_descriptor.size.width as f32 * scale, + i.texture_descriptor.size.height as f32 * scale, ) }) .unwrap() diff --git a/src/render_primitive.rs b/src/render_primitive.rs index 6b58dcff..2e8adc3a 100644 --- a/src/render_primitive.rs +++ b/src/render_primitive.rs @@ -223,12 +223,17 @@ impl RenderPrimitive for KStyle { ); } } - RenderCommand::NinePatch { border, handle } => { + RenderCommand::NinePatch { + border, + handle, + scale, + } => { let mut nines = crate::render::nine_patch::extract_nine_patch( camera_entity, *layout, handle, border, + scale, opacity_layer, images, dpi, diff --git a/src/styles/render_command.rs b/src/styles/render_command.rs index 27453ed8..4b03efc0 100644 --- a/src/styles/render_command.rs +++ b/src/styles/render_command.rs @@ -34,6 +34,7 @@ pub enum RenderCommand { NinePatch { border: Edge, handle: Handle, + scale: f32, }, #[cfg(feature = "svg")] Svg { diff --git a/src/widgets/nine_patch.rs b/src/widgets/nine_patch.rs index 48ea38e0..f19acdd4 100644 --- a/src/widgets/nine_patch.rs +++ b/src/widgets/nine_patch.rs @@ -1,96 +1,110 @@ -use bevy::prelude::{Bundle, Commands, Component, Entity, Handle, Image, In, Query, Res}; - -use crate::{ - children::KChildren, - context::WidgetName, - on_event::OnEvent, - prelude::KayakWidgetContext, - styles::{ComputedStyles, Edge, KStyle, RenderCommand}, - widget::Widget, -}; - -#[derive(Component, PartialEq, Clone, Default, Debug)] -pub struct NinePatch { - /// The handle to image - pub handle: Handle, - /// The size of each edge (in pixels) - pub border: Edge, -} - -impl Widget for NinePatch {} - -/// -/// Render's a nine-patch image as a UI widget. -/// -/// Also know as 9-slicing. This 2D technique allows users to render UI images at multiple -/// resolutions while maintaining a level of quality. The image in the middle is repeated. -/// -/// Accepts Children and Styles. -/// -/// Example: The border prop splits up the image into 9 quadrants like so: -/// 1----2----3 -/// | | -/// 4 9 5 -/// | | -/// 6----7----8 -/// The sizes of sprites for a 15 pixel border are as follows: -/// TopLeft = (15, 15) -/// TopRight = (15, 15) -/// LeftCenter = (15, image_height) -/// RightCenter = (15, image_height) -/// TopCenter = (image_width, 15) -/// BottomCenter = (image_width, 15) -/// BottomRight = (15, 15) -/// BottomLeft = (15, 15) -/// Middle = ( -/// 30 being left border + right border -/// image_width - 30 -/// 30 being top border + bottom border -/// image_height - 30 -/// ) -#[derive(Bundle)] -pub struct NinePatchBundle { - pub nine_patch: NinePatch, - pub styles: KStyle, - pub computed_styles: ComputedStyles, - pub children: KChildren, - pub on_event: OnEvent, - pub widget_name: WidgetName, -} - -impl Default for NinePatchBundle { - fn default() -> Self { - Self { - nine_patch: Default::default(), - styles: Default::default(), - computed_styles: ComputedStyles::default(), - children: KChildren::default(), - on_event: OnEvent::default(), - widget_name: NinePatch::default().get_name(), - } - } -} - -pub fn nine_patch_render( - In(entity): In, - widget_context: Res, - mut commands: Commands, - mut query: Query<(&KStyle, &mut ComputedStyles, &NinePatch, &KChildren)>, -) -> bool { - if let Ok((style, mut computed_styles, nine_patch, children)) = query.get_mut(entity) { - *computed_styles = KStyle::default() - .with_style(KStyle { - render_command: RenderCommand::NinePatch { - border: nine_patch.border, - handle: nine_patch.handle.clone_weak(), - } - .into(), - ..Default::default() - }) - .with_style(style) - .into(); - children.process(&widget_context, &mut commands, Some(entity)); - } - - true -} +use bevy::prelude::{Bundle, Commands, Component, Entity, Handle, Image, In, Query, Res}; + +use crate::{ + children::KChildren, + context::WidgetName, + on_event::OnEvent, + prelude::KayakWidgetContext, + styles::{ComputedStyles, Edge, KStyle, RenderCommand}, + widget::Widget, +}; + +#[derive(Component, PartialEq, Clone, Debug)] +pub struct NinePatch { + /// The handle to image + pub handle: Handle, + /// The size of each edge (in pixels) + pub border: Edge, + /// Scale of the nine patch + /// defaults to 1.0 + pub scale: f32, +} + +impl Default for NinePatch { + fn default() -> Self { + Self { + handle: Default::default(), + border: Default::default(), + scale: 1.0, + } + } +} + +impl Widget for NinePatch {} + +/// +/// Render's a nine-patch image as a UI widget. +/// +/// Also know as 9-slicing. This 2D technique allows users to render UI images at multiple +/// resolutions while maintaining a level of quality. The image in the middle is repeated. +/// +/// Accepts Children and Styles. +/// +/// Example: The border prop splits up the image into 9 quadrants like so: +/// 1----2----3 +/// | | +/// 4 9 5 +/// | | +/// 6----7----8 +/// The sizes of sprites for a 15 pixel border are as follows: +/// TopLeft = (15, 15) +/// TopRight = (15, 15) +/// LeftCenter = (15, image_height) +/// RightCenter = (15, image_height) +/// TopCenter = (image_width, 15) +/// BottomCenter = (image_width, 15) +/// BottomRight = (15, 15) +/// BottomLeft = (15, 15) +/// Middle = ( +/// 30 being left border + right border +/// image_width - 30 +/// 30 being top border + bottom border +/// image_height - 30 +/// ) +#[derive(Bundle)] +pub struct NinePatchBundle { + pub nine_patch: NinePatch, + pub styles: KStyle, + pub computed_styles: ComputedStyles, + pub children: KChildren, + pub on_event: OnEvent, + pub widget_name: WidgetName, +} + +impl Default for NinePatchBundle { + fn default() -> Self { + Self { + nine_patch: Default::default(), + styles: Default::default(), + computed_styles: ComputedStyles::default(), + children: KChildren::default(), + on_event: OnEvent::default(), + widget_name: NinePatch::default().get_name(), + } + } +} + +pub fn nine_patch_render( + In(entity): In, + widget_context: Res, + mut commands: Commands, + mut query: Query<(&KStyle, &mut ComputedStyles, &NinePatch, &KChildren)>, +) -> bool { + if let Ok((style, mut computed_styles, nine_patch, children)) = query.get_mut(entity) { + *computed_styles = KStyle::default() + .with_style(KStyle { + render_command: RenderCommand::NinePatch { + border: nine_patch.border, + handle: nine_patch.handle.clone_weak(), + scale: nine_patch.scale, + } + .into(), + ..Default::default() + }) + .with_style(style) + .into(); + children.process(&widget_context, &mut commands, Some(entity)); + } + + true +}