Add descriptions, touch basic support
This commit is contained in:
parent
eff6b3b06f
commit
a2643d1cae
|
|
@ -0,0 +1,5 @@
|
||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## [0.1.0]
|
||||||
|
|
||||||
|
- Initial version
|
||||||
File diff suppressed because it is too large
Load Diff
13
Cargo.toml
13
Cargo.toml
|
|
@ -2,9 +2,11 @@
|
||||||
name = "bevy_simple_scroll_view"
|
name = "bevy_simple_scroll_view"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
exclude = [".github/","wasm/"]
|
exclude = [".github/","wasm/", "record.gif"]
|
||||||
categories = ["game-development", "gui"]
|
categories = ["game-development", "gui"]
|
||||||
keywords = ["bevy","ui"]
|
keywords = ["bevy","ui"]
|
||||||
|
repository = "https://github.com/Leinnan/bevy_simple_scroll_view"
|
||||||
|
homepage = "https://github.com/Leinnan/bevy_simple_scroll_view"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
@ -12,12 +14,9 @@ license = "MIT OR Apache-2.0"
|
||||||
[dependencies.bevy]
|
[dependencies.bevy]
|
||||||
version = "0.13"
|
version = "0.13"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["bevy_ui", "bevy_asset", "bevy_text"]
|
features = ["bevy_ui", "bevy_asset", "bevy_text", "bevy_winit"]
|
||||||
|
|
||||||
[dev-dependencies.bevy]
|
[dev-dependencies.bevy]
|
||||||
version = "0.13"
|
version = "0.13"
|
||||||
default-features = true
|
default-features = false
|
||||||
|
features = ["bevy_ui", "bevy_asset", "bevy_text", "bevy_winit", "default_font"]
|
||||||
[dev-dependencies]
|
|
||||||
bevy_egui = "0.25"
|
|
||||||
bevy-inspector-egui = "0.23"
|
|
||||||
|
|
|
||||||
31
README.md
31
README.md
|
|
@ -1,11 +1,40 @@
|
||||||
# Bevy Simple Scroll View
|
# Bevy Simple Scroll View
|
||||||
|
|
||||||
|
[](https://crates.io/crates/bevy_simple_scroll_view)
|
||||||
|
[](https://docs.rs/bevy_simple_scroll_view)
|
||||||
|
[](https://github.com/Leinnan/bevy_simple_scroll_view#license)
|
||||||
|
[](https://bevyengine.org/learn/quick-start/plugin-development/#main-branch-tracking)
|
||||||
|
[](https://crates.io/crates/bevy_simple_scroll_view)
|
||||||
|
|
||||||
Simple to use plugin implementing ScrollView into Bevy engine. Supports scroll using dragging and scrolling.
|
Simple to use plugin implementing ScrollView into Bevy engine. Supports scroll using dragging and scrolling.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
More details available in [simple.rs example](examples/simple.rs).
|
More details available in [simple.rs example](examples/simple.rs).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo add --git https://github.com/Leinnan/bevy_simple_scroll_view.git
|
cargo add bevy_simple_scroll_view
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Please feel free to open a PR, but keep in mind this project's goals. This is meant to be a simple scroll view widget.
|
||||||
|
|
||||||
|
The code should be simple enough for users to quickly understand and modify for their own purposes.
|
||||||
|
|
||||||
|
Please keep PRs small and scoped to a single feature or fix.
|
||||||
|
|
||||||
|
## Planned features
|
||||||
|
|
||||||
|
- one big thing missing is support for the [TouchInput events](https://docs.rs/bevy/latest/bevy/input/touch/struct.TouchInput.html) so the mobile platforms would work well.
|
||||||
|
- horizontal scroll, should be pretty simple.
|
||||||
|
- **DOCS**
|
||||||
|
- _optional_ if there would be simple enough implementation I would consider adding scrollbars.
|
||||||
|
|
||||||
|
## Bevy compatibility table
|
||||||
|
|
||||||
|
Bevy version | crate version
|
||||||
|
--- | ---
|
||||||
|
0.13 | 0.1
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_inspector_egui::quick::WorldInspectorPlugin;
|
|
||||||
use bevy_simple_scroll_view::*;
|
use bevy_simple_scroll_view::*;
|
||||||
|
|
||||||
const BORDER_COLOR_ACTIVE: Color = Color::rgb(0.75, 0.52, 0.99);
|
const CLR_1: Color = Color::rgb(0.168, 0.168, 0.168);
|
||||||
const BACKGROUND_COLOR: Color = Color::rgb(0.15, 0.15, 0.15);
|
const CLR_2: Color = Color::rgb(0.109, 0.109, 0.109);
|
||||||
|
const CLR_3: Color = Color::rgb(0.569, 0.592, 0.647);
|
||||||
|
const CLR_4: Color = Color::rgb(0.902, 0.4, 0.004);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
.add_plugins((
|
.add_plugins((DefaultPlugins, ScrollViewPlugin))
|
||||||
DefaultPlugins,
|
|
||||||
ScrollViewPlugin,
|
|
||||||
WorldInspectorPlugin::new(),
|
|
||||||
))
|
|
||||||
.add_systems(Startup, prepare)
|
.add_systems(Startup, prepare)
|
||||||
.add_systems(Update, reset_scroll)
|
.add_systems(Update, reset_scroll)
|
||||||
.run();
|
.run();
|
||||||
|
|
@ -24,20 +21,24 @@ fn prepare(mut commands: Commands) {
|
||||||
style: Style {
|
style: Style {
|
||||||
width: Val::Percent(100.0),
|
width: Val::Percent(100.0),
|
||||||
height: Val::Percent(100.0),
|
height: Val::Percent(100.0),
|
||||||
margin: UiRect::all(Val::Px(15.0)),
|
padding: UiRect::all(Val::Px(15.0)),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
background_color: Color::rgb(0.05, 0.05, 0.05).into(),
|
background_color: CLR_1.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|p| {
|
.with_children(|p| {
|
||||||
p.spawn(ButtonBundle {
|
p.spawn(ButtonBundle {
|
||||||
style: Style {
|
style: Style {
|
||||||
margin: UiRect::all(Val::Px(5.0)),
|
margin: UiRect::all(Val::Px(15.0)),
|
||||||
padding: UiRect::all(Val::Px(5.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()
|
..default()
|
||||||
},
|
},
|
||||||
background_color: BORDER_COLOR_ACTIVE.into(),
|
background_color: CLR_2.into(),
|
||||||
|
border_color: CLR_4.into(),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|p| {
|
.with_children(|p| {
|
||||||
|
|
@ -45,7 +46,7 @@ fn prepare(mut commands: Commands) {
|
||||||
"Reset scroll",
|
"Reset scroll",
|
||||||
TextStyle {
|
TextStyle {
|
||||||
font_size: 25.0,
|
font_size: 25.0,
|
||||||
color: Color::ANTIQUE_WHITE,
|
color: CLR_4,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
@ -54,11 +55,10 @@ fn prepare(mut commands: Commands) {
|
||||||
NodeBundle {
|
NodeBundle {
|
||||||
style: Style {
|
style: Style {
|
||||||
width: Val::Percent(80.0),
|
width: Val::Percent(80.0),
|
||||||
height: Val::Percent(50.0),
|
|
||||||
margin: UiRect::all(Val::Px(15.0)),
|
margin: UiRect::all(Val::Px(15.0)),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
background_color: BACKGROUND_COLOR.into(),
|
background_color: CLR_2.into(),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
ScrollView::default(),
|
ScrollView::default(),
|
||||||
|
|
@ -68,6 +68,7 @@ fn prepare(mut commands: Commands) {
|
||||||
NodeBundle {
|
NodeBundle {
|
||||||
style: Style {
|
style: Style {
|
||||||
flex_direction: bevy::ui::FlexDirection::Column,
|
flex_direction: bevy::ui::FlexDirection::Column,
|
||||||
|
width: Val::Percent(100.0),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
..default()
|
..default()
|
||||||
|
|
@ -75,18 +76,17 @@ fn prepare(mut commands: Commands) {
|
||||||
ScrollableContent::default(),
|
ScrollableContent::default(),
|
||||||
))
|
))
|
||||||
.with_children(|scroll_area| {
|
.with_children(|scroll_area| {
|
||||||
for i in 0..10 {
|
for i in 0..21 {
|
||||||
scroll_area
|
scroll_area
|
||||||
.spawn(NodeBundle {
|
.spawn(NodeBundle {
|
||||||
style: Style {
|
style: Style {
|
||||||
width: Val::Percent(150.0),
|
min_width: Val::Px(200.0),
|
||||||
margin: UiRect::all(Val::Px(5.0)),
|
margin: UiRect::all(Val::Px(15.0)),
|
||||||
border: UiRect::all(Val::Px(3.0)),
|
border: UiRect::all(Val::Px(5.0)),
|
||||||
padding: UiRect::all(Val::Px(25.0)),
|
padding: UiRect::all(Val::Px(30.0)),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
border_color: BORDER_COLOR_ACTIVE.into(),
|
border_color: CLR_3.into(),
|
||||||
background_color: BACKGROUND_COLOR.into(),
|
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
.with_children(|p| {
|
.with_children(|p| {
|
||||||
|
|
@ -95,7 +95,7 @@ fn prepare(mut commands: Commands) {
|
||||||
format!("Nr {}", i),
|
format!("Nr {}", i),
|
||||||
TextStyle {
|
TextStyle {
|
||||||
font_size: 25.0,
|
font_size: 25.0,
|
||||||
color: Color::ANTIQUE_WHITE,
|
color: CLR_3,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 340 KiB |
54
src/lib.rs
54
src/lib.rs
|
|
@ -1,9 +1,21 @@
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
input::mouse::{MouseMotion, MouseWheel},
|
input::mouse::{MouseMotion, MouseWheel},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A `Plugin` providing the systems and components required to make a ScrollView work.
|
/// A `Plugin` providing the systems and components required to make a ScrollView work.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use bevy::prelude::*;
|
||||||
|
/// use bevy_simple_scroll_view::;
|
||||||
|
///
|
||||||
|
/// App::new()
|
||||||
|
/// .add_plugins((DefaultPlugins,ScrollViewPlugin))
|
||||||
|
/// .run();
|
||||||
|
/// ```
|
||||||
pub struct ScrollViewPlugin;
|
pub struct ScrollViewPlugin;
|
||||||
|
|
||||||
impl Plugin for ScrollViewPlugin {
|
impl Plugin for ScrollViewPlugin {
|
||||||
|
|
@ -15,6 +27,7 @@ impl Plugin for ScrollViewPlugin {
|
||||||
(
|
(
|
||||||
create_scroll_view,
|
create_scroll_view,
|
||||||
input_mouse_pressed_move,
|
input_mouse_pressed_move,
|
||||||
|
input_touch_pressed_move,
|
||||||
scroll_events,
|
scroll_events,
|
||||||
scroll_update,
|
scroll_update,
|
||||||
)
|
)
|
||||||
|
|
@ -23,21 +36,27 @@ impl Plugin for ScrollViewPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Root component of scroll, it should have clipped style.
|
||||||
#[derive(Component, Debug, Reflect)]
|
#[derive(Component, Debug, Reflect)]
|
||||||
pub struct ScrollView {
|
pub struct ScrollView {
|
||||||
|
/// Field which control speed of the scrolling.
|
||||||
|
/// Could be negative number to implement invert scroll
|
||||||
pub scroll_speed: f32,
|
pub scroll_speed: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ScrollView {
|
impl Default for ScrollView {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
scroll_speed: 100.0,
|
scroll_speed: 200.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)]
|
#[derive(Component, Debug, Reflect, Default)]
|
||||||
pub struct ScrollableContent {
|
pub struct ScrollableContent {
|
||||||
|
/// Scroll container offset to the `ScrollView`.
|
||||||
pub pos_y: f32,
|
pub pos_y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,9 +96,30 @@ fn input_mouse_pressed_move(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_update(mut q: Query<(&ScrollableContent, &mut Style), Changed<ScrollableContent>>) {
|
fn input_touch_pressed_move(
|
||||||
for (scroll, mut style) in q.iter_mut() {
|
touches: Res<Touches>,
|
||||||
style.top = Val::Px(scroll.pos_y);
|
mut q: Query<(&Children, &Interaction, &Node), With<ScrollView>>,
|
||||||
|
mut content_q: Query<(&mut ScrollableContent, &Node)>,
|
||||||
|
) {
|
||||||
|
for t in touches.iter() {
|
||||||
|
let Some(touch) = touches.get_pressed(t.id()) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (children, &interaction, node) in q.iter_mut() {
|
||||||
|
if interaction != Interaction::Pressed {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let container_height = node.size().y;
|
||||||
|
for &child in children.iter() {
|
||||||
|
if let Ok(item) = content_q.get_mut(child) {
|
||||||
|
let mut scroll = item.0;
|
||||||
|
let max_scroll = (item.1.size().y - container_height).max(0.0);
|
||||||
|
scroll.pos_y += touch.delta().y;
|
||||||
|
scroll.pos_y = scroll.pos_y.clamp(-max_scroll, 0.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,3 +155,9 @@ fn scroll_events(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scroll_update(mut q: Query<(&ScrollableContent, &mut Style), Changed<ScrollableContent>>) {
|
||||||
|
for (scroll, mut style) in q.iter_mut() {
|
||||||
|
style.top = Val::Px(scroll.pos_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue