Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new nine-patch features #286

Merged
merged 4 commits into from
Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/clipping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}
>
Expand Down
2 changes: 2 additions & 0 deletions examples/main_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
1 change: 1 addition & 0 deletions examples/nine_patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
Expand Down
5 changes: 3 additions & 2 deletions src/render/nine_patch/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn extract_nine_patch(
layout: crate::layout::Rect,
handle: Handle<Image>,
border: Edge<f32>,
scale: f32,
opacity_layer: u32,
images: &Assets<Image>,
dpi: f32,
Expand All @@ -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()
Expand Down
7 changes: 6 additions & 1 deletion src/render_primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/styles/render_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub enum RenderCommand {
NinePatch {
border: Edge<f32>,
handle: Handle<Image>,
scale: f32,
},
#[cfg(feature = "svg")]
Svg {
Expand Down
206 changes: 110 additions & 96 deletions src/widgets/nine_patch.rs
Original file line number Diff line number Diff line change
@@ -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<Image>,
/// The size of each edge (in pixels)
pub border: Edge<f32>,
}

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<Entity>,
widget_context: Res<KayakWidgetContext>,
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<Image>,
/// The size of each edge (in pixels)
pub border: Edge<f32>,
/// 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<Entity>,
widget_context: Res<KayakWidgetContext>,
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
}
Loading