From bf2f27231a7adbf802918a7a4a2277e1632375b1 Mon Sep 17 00:00:00 2001 From: Piotr Siuszko Date: Mon, 27 Jan 2025 10:56:04 +0100 Subject: [PATCH] Docs, default scroll view node function, updated sample --- CHANGELOG.md | 11 ++++ Cargo.toml | 5 +- examples/simple.rs | 133 ++++++++++++++------------------------------- src/lib.rs | 51 +++++++++++++---- 4 files changed, 95 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee9dee2..318f39b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # CHANGELOG +## [0.3.2] + +## Added + +- `scroll_view_node` function with default values for `ScrollView` node +- documentation to the code + +## Fixed + +- `ScrollableContent` default Node values fix + ## [0.3.1] ## Fixed diff --git a/Cargo.toml b/Cargo.toml index 10df567..937183e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bevy_simple_scroll_view" -version = "0.3.1" +version = "0.3.2" edition = "2021" exclude = [".github/", "wasm/", "record.gif"] categories = ["game-development", "gui"] @@ -22,3 +22,6 @@ default-features = true [features] default = [] extra_logs = [] + +[lints.rust] +missing_docs = "warn" diff --git a/examples/simple.rs b/examples/simple.rs index de29b16..cd1dc71 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -1,135 +1,84 @@ +#![allow(missing_docs)] + +use bevy::picking::events::{Up, Pointer}; use bevy::prelude::*; use bevy_simple_scroll_view::*; -const CLR_1: Color = Color::srgb(0.168, 0.168, 0.168); -const CLR_2: Color = Color::srgb(0.109, 0.109, 0.109); +const BG_COLOR: BackgroundColor = BackgroundColor(Color::srgb(0.168, 0.168, 0.168)); +const BG_COLOR_2: BackgroundColor = BackgroundColor(Color::srgb(0.109, 0.109, 0.109)); const CLR_3: Color = Color::srgb(0.569, 0.592, 0.647); -const CLR_4: Color = Color::srgb(0.902, 0.4, 0.004); +const TEXT_COLOR: TextColor = TextColor(Color::srgb(0.902, 0.4, 0.004)); fn main() { App::new() .add_plugins((DefaultPlugins, ScrollViewPlugin)) - .add_systems(Startup, prepare) - .add_systems(Update, reset_scroll) + .add_systems(Startup, setup) .run(); } -fn prepare(mut commands: Commands) { +fn setup(mut commands: Commands) { + let base_node = Node { + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + min_width: Val::Px(200.0), + margin: UiRect::all(Val::Px(10.0)), + border: UiRect::all(Val::Px(3.0)), + padding: UiRect::all(Val::Px(15.0)), + ..default() + }; commands.spawn(Camera2d); commands .spawn(( - BackgroundColor(CLR_1), + BG_COLOR, Node { width: Val::Percent(100.0), height: Val::Percent(100.0), - padding: UiRect::all(Val::Px(15.0)), ..default() }, )) .with_children(|p| { p.spawn(Node { width: Val::Percent(20.0), - margin: UiRect::all(Val::Px(10.0)), + margin: UiRect::all(Val::Px(15.0)), flex_direction: FlexDirection::Column, ..default() }) .with_children(|p| { - for btn_action in [ScrollButton::MoveToTop, ScrollButton::MoveToBottom] { - p.spawn(( - Node { - margin: UiRect::all(Val::Px(15.0)), - padding: UiRect::all(Val::Px(15.0)), - max_height: Val::Px(100.0), - border: UiRect::all(Val::Px(3.0)), - align_items: AlignItems::Center, - ..default() - }, - BackgroundColor(CLR_2), - BorderColor(CLR_4), - Button, - btn_action, - )) - .with_children(|p| { - p.spawn(( - Text::new(format!("{:#?}", btn_action)), - TextFont { - font_size: 25.0, - ..default() - }, - TextColor(CLR_4), - )); - }); - } + p.spawn((Text::new("Scroll to:"), TEXT_COLOR)); + let btn = (base_node.clone(), BG_COLOR_2, Button); + p.spawn(btn.clone()) + .observe(scroll_to_top) + .with_child((Text::new("top"), TEXT_COLOR)); + p.spawn(btn) + .observe(scroll_to_bottom) + .with_child((Text::new("bottom"), TEXT_COLOR)); }); p.spawn(( Node { width: Val::Percent(80.0), margin: UiRect::all(Val::Px(15.0)), - ..default() + ..scroll_view_node() }, - BackgroundColor(CLR_2), + BG_COLOR_2, ScrollView::default(), )) .with_children(|p| { - p.spawn(( - Node { - flex_direction: bevy::ui::FlexDirection::Column, - width: Val::Percent(100.0), - ..default() - }, - ScrollableContent::default(), - )) - .with_children(|scroll_area| { - for i in 0..21 { - scroll_area - .spawn(( - Node { - min_width: Val::Px(200.0), - margin: UiRect::all(Val::Px(15.0)), - border: UiRect::all(Val::Px(5.0)), - padding: UiRect::all(Val::Px(30.0)), - ..default() - }, - BorderColor(CLR_3), - )) - .with_children(|p| { - p.spawn(( - Text::new(format!("Nr {}", i)), - TextFont { - font_size: 25.0, - ..default() - }, - TextColor(CLR_3), - TextLayout::new_with_justify(JustifyText::Center), - )); - }); - } - }); + p.spawn(ScrollableContent::default()) + .with_children(|scroll_area| { + for i in 1..21 { + scroll_area + .spawn((base_node.clone(), BorderColor(CLR_3))) + .with_child((Text::new(format!("Nr {} out of 20", i)), TEXT_COLOR)); + } + }); }); }); } -#[derive(Component, PartialEq, Debug, Clone, Copy)] -#[require(Button)] -enum ScrollButton { - MoveToTop, - MoveToBottom, +fn scroll_to_top(_t: Trigger>, mut scroll: Single<&mut ScrollableContent>) { + scroll.scroll_to_top(); } -fn reset_scroll( - q: Query<(&Interaction, &ScrollButton), Changed>, - mut scrolls_q: Query<&mut ScrollableContent>, -) { - let Ok(mut scroll) = scrolls_q.get_single_mut() else { - return; - }; - for (interaction, action) in q.iter() { - if interaction != &Interaction::Pressed { - continue; - } - match action { - ScrollButton::MoveToTop => scroll.scroll_to_top(), - ScrollButton::MoveToBottom => scroll.scroll_to_bottom(), - } - } +fn scroll_to_bottom(_t: Trigger>, mut scroll: Single<&mut ScrollableContent>) { + scroll.scroll_to_bottom(); } diff --git a/src/lib.rs b/src/lib.rs index af190d2..4183bd4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ impl Plugin for ScrollViewPlugin { /// Root component of scroll, it should have clipped style. #[derive(Component, Debug, Reflect)] -#[require(Interaction, Node)] +#[require(Interaction, Node(scroll_view_node))] pub struct ScrollView { /// Field which control speed of the scrolling. /// Could be negative number to implement invert scroll @@ -57,13 +57,40 @@ impl Default for ScrollView { /// Component containing offset value of the scroll container to the parent. /// It is possible to update the field `pos_y` manually to move scrollview to desired location. #[derive(Component, Debug, Reflect, Default)] -#[require(Node(scroll_view_node))] +#[require(Node(scroll_content_node))] pub struct ScrollableContent { /// Scroll container offset to the `ScrollView`. pub pos_y: f32, + /// Maximum value for the scroll. It is updated automatically based on the size of the children nodes. pub max_scroll: f32, } +impl ScrollableContent { + /// Scrolls to the top of the scroll view. + pub fn scroll_to_top(&mut self) { + self.pos_y = 0.0; + } + /// Scrolls to the bottom of the scroll view. + pub fn scroll_to_bottom(&mut self) { + self.pos_y = -self.max_scroll; + } + + /// Scrolls by a specified amount. + /// + /// # Parameters + /// - `value`: The amount to scroll vertically. Positive values scroll down, + /// and negative values scroll up. + /// + /// Ensures the new position is clamped between the valid scroll range. + pub fn scroll_by(&mut self, value: f32) { + self.pos_y += value; + self.pos_y = self.pos_y.clamp(-self.max_scroll, 0.); + } +} + +/// Creates a default scroll view node. +/// +/// This function defines the visual and layout properties of a scrollable container. pub fn scroll_view_node() -> Node { Node { overflow: Overflow::clip(), @@ -74,19 +101,19 @@ pub fn scroll_view_node() -> Node { } } -impl ScrollableContent { - pub fn scroll_to_top(&mut self) { - self.pos_y = 0.0; - } - pub fn scroll_to_bottom(&mut self) { - self.pos_y = -self.max_scroll; - } - pub fn scroll_by(&mut self, value: f32) { - self.pos_y += value; - self.pos_y = self.pos_y.clamp(-self.max_scroll, 0.); +/// Creates a default scroll content node. +pub fn scroll_content_node() -> Node { + Node { + flex_direction: bevy::ui::FlexDirection::Column, + width: Val::Percent(100.0), + ..default() } } +/// Applies the default scroll view style to newly added `ScrollView` components. +/// +/// This function updates the style of all new `ScrollView` nodes with the default +/// properties defined in `scroll_view_node`. pub fn create_scroll_view(mut q: Query<&mut Node, Added>) { let Node { overflow,