scrolling _kinda_ works; bad feel but good enough... for now

main
Elijah Voigt 2 years ago
parent dd912f420f
commit 6ae7b094ad

@ -35,6 +35,10 @@ path = "bin/audio-inspect.rs"
name = "editor" name = "editor"
path = "bin/editor.rs" path = "bin/editor.rs"
[[bin]]
name = "chars"
path = "bin/chars.rs"
[dependencies] [dependencies]
bevy = "0.11" bevy = "0.11"

@ -0,0 +1,55 @@
use bevy::input::keyboard::KeyboardInput;
use bevy::input::ButtonState;
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, init)
.add_systems(Update, update)
.run();
}
fn init(mut commands: Commands) {
// UI Camera
commands.spawn((
Camera2dBundle { ..default() },
UiCameraConfig { show_ui: true },
));
// Text Box
commands.spawn(TextBundle::from_section(
"Start typing! (Escape to clear)\n",
TextStyle {
color: Color::WHITE,
..default()
},
));
}
fn update(mut query: Query<&mut Text>, mut events: EventReader<KeyboardInput>) {
for KeyboardInput {
key_code,
scan_code,
state,
..
} in events.iter()
{
if *state == ButtonState::Pressed {
let mut text = query.single_mut();
if *key_code == Some(KeyCode::Escape) {
text.sections.drain(1..);
} else {
let style = TextStyle {
color: Color::WHITE,
..default()
};
let added = format!(
"Pressed: KeyCode: {:?} / ScanCode {:?}\n",
key_code, scan_code
);
text.sections.push(TextSection::new(added, style));
}
}
}
}

@ -61,134 +61,147 @@ fn main() {
// CursorIcon::RowResize, // CursorIcon::RowResize,
// ]; // ];
fn spawn_tree(parent: &mut ChildBuilder, pos: UiKitPosition) { fn spawn_tree(parent: &mut ChildBuilder, pos: UiKitPosition, depth: u8, length: u8) {
let pos2 = match pos { let pos2 = match pos {
UiKitPosition::Top => UiKitPosition::Left, UiKitPosition::Top => UiKitPosition::Left,
_ => pos, _ => pos,
}; };
(0..length).for_each(|_| {
parent parent
.spawn(UiKitButton::new(Color::PINK)) .spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| { .with_children(|parent| {
if depth > 1 {
parent parent
.spawn(UiKitContainer::new(pos)) .spawn(UiKitContainer::new(pos))
.with_children(|parent| { .with_children(|parent| {
parent spawn_tree(parent, pos2, depth - 1, length);
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos))
.with_children(|parent| {
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos))
.with_children(|parent| {
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
});
parent
.spawn(UiKitButton::new(Color::PINK))
.with_children(|parent| {
parent
.spawn(UiKitContainer::new(pos2))
.with_children(|parent| {
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
parent.spawn(UiKitButton::new(Color::PINK));
});
}); });
}
}); });
}); });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos))
// .with_children(|parent| {
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos))
// .with_children(|parent| {
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos))
// .with_children(|parent| {
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// parent
// .spawn(UiKitButton::new(Color::PINK))
// .with_children(|parent| {
// parent
// .spawn(UiKitContainer::new(pos2))
// .with_children(|parent| {
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// parent.spawn(UiKitButton::new(Color::PINK));
// });
// });
// });
// });
} }
fn init_ui2(mut commands: Commands) { fn init_ui2(mut commands: Commands) {
@ -209,6 +222,23 @@ fn init_ui2(mut commands: Commands) {
..default() ..default()
}) })
.with_children(|parent| { .with_children(|parent| {
parent
.spawn(ButtonBundle {
style: Style {
border: UiRect::all(Val::Px(1.0)),
width: Val::Px(200.0),
height: Val::Px(150.0),
align_self: AlignSelf::Center,
..default()
},
background_color: BackgroundColor(Color::WHITE),
border_color: BorderColor(Color::BLACK),
..default()
})
.with_children(|parent| {
parent.spawn(UiKitTextInput::new());
});
parent parent
.spawn(NodeBundle { .spawn(NodeBundle {
style: Style { style: Style {
@ -224,7 +254,7 @@ fn init_ui2(mut commands: Commands) {
..default() ..default()
}) })
.with_children(|parent| { .with_children(|parent| {
spawn_tree(parent, UiKitPosition::Left); spawn_tree(parent, UiKitPosition::Left, 3, 7);
}); });
parent parent
@ -242,7 +272,7 @@ fn init_ui2(mut commands: Commands) {
..default() ..default()
}) })
.with_children(|parent| { .with_children(|parent| {
spawn_tree(parent, UiKitPosition::Right); spawn_tree(parent, UiKitPosition::Right, 3, 7);
}); });
parent parent
@ -259,7 +289,7 @@ fn init_ui2(mut commands: Commands) {
..default() ..default()
}) })
.with_children(|parent| { .with_children(|parent| {
spawn_tree(parent, UiKitPosition::Top); spawn_tree(parent, UiKitPosition::Top, 3, 7);
}); });
}); });
} }

@ -7,13 +7,21 @@
/// BUGS: /// BUGS:
/// * When selecting one tree, possible to select another without the first closing. /// * When selecting one tree, possible to select another without the first closing.
/// ///
use bevy::{prelude::*, window::PrimaryWindow}; use bevy::{
input::{
keyboard::KeyboardInput,
mouse::{MouseScrollUnit, MouseWheel},
ButtonState,
},
prelude::*,
window::PrimaryWindow,
};
pub struct GameUiPlugin; pub struct GameUiPlugin;
impl Plugin for GameUiPlugin { impl Plugin for GameUiPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(Update, toggle) app.add_systems(Update, (select_tab, select_textbox, text_editor, scroll))
.add_systems(PostUpdate, selection); .add_systems(PostUpdate, selection);
} }
} }
@ -100,7 +108,7 @@ impl UiKitButton {
} }
} }
#[derive(Debug, Component, Copy, Clone)] #[derive(Debug, Component, Copy, Clone, PartialEq)]
pub enum UiKitSelect { pub enum UiKitSelect {
Active, Active,
None, None,
@ -109,12 +117,23 @@ pub enum UiKitSelect {
#[derive(Debug, Bundle)] #[derive(Debug, Bundle)]
pub struct UiKitTextInput { pub struct UiKitTextInput {
text_bundle: TextBundle, text_bundle: TextBundle,
interaction: Interaction,
select: UiKitSelect,
} }
impl UiKitTextInput { impl UiKitTextInput {
pub fn new() -> Self { pub fn new() -> Self {
UiKitTextInput { UiKitTextInput {
text_bundle: TextBundle { ..default() }, text_bundle: TextBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
..default()
},
..default()
},
interaction: Interaction::None,
select: UiKitSelect::None,
} }
} }
} }
@ -152,7 +171,7 @@ fn selection(
/// ///
// TODO: Should not be able to select multiple children in branch of tree // TODO: Should not be able to select multiple children in branch of tree
// TODO: Port to ui.rs // TODO: Port to ui.rs
fn toggle( fn select_tab(
events: Query<Entity, (Changed<Interaction>, With<Button>)>, events: Query<Entity, (Changed<Interaction>, With<Button>)>,
interactions: Query<&Interaction, With<Button>>, interactions: Query<&Interaction, With<Button>>,
mut selects: Query<&mut UiKitSelect>, mut selects: Query<&mut UiKitSelect>,
@ -230,3 +249,151 @@ fn toggle(
} }
}); });
} }
fn select_textbox(
mut events: Query<(&Interaction, &mut UiKitSelect), (With<Text>, Changed<Interaction>)>,
) {
events.iter_mut().for_each(|(interaction, mut select)| {
*select = match interaction {
Interaction::Pressed => UiKitSelect::Active,
Interaction::Hovered => UiKitSelect::Active,
Interaction::None => UiKitSelect::None,
}
});
}
fn text_editor(
keyboard: Res<Input<KeyCode>>,
mut events: EventReader<KeyboardInput>,
mut query: Query<&mut Text, With<UiKitSelect>>,
) {
events.iter().for_each(
|KeyboardInput {
key_code,
state,
scan_code,
..
}| {
match state {
ButtonState::Pressed => {
if let Some(kc) = key_code {
query.iter_mut().for_each(|mut text| {
use KeyCode::*;
let style = TextStyle {
color: Color::BLACK,
..default()
};
if *kc == Back {
text.sections.pop();
} else {
let c = match kc {
// Letters
A | B | C | D | E | F | G | H | I | J | K | L | M | N | O
| P | Q | R | S | T | U | V | W | X | Y | Z => {
if keyboard.any_pressed([ShiftLeft, ShiftRight]) {
format!("{:?}", kc).to_uppercase()
} else {
format!("{:?}", kc).to_lowercase()
}
}
// Top Row
Grave => "`".to_string(),
Key1 | Numpad1 => "1".to_string(),
Key2 | Numpad2 => "2".to_string(),
Key3 | Numpad3 => "3".to_string(),
Key4 | Numpad4 => "4".to_string(),
Key5 | Numpad5 => "5".to_string(),
Key6 | Numpad6 => "6".to_string(),
Key7 | Numpad7 => "7".to_string(),
Key8 | Numpad8 => "8".to_string(),
Key9 | Numpad9 => "9".to_string(),
Key0 | Numpad0 => "0".to_string(),
Minus => "-".to_string(),
Equals => "=".to_string(),
// Left side
Tab => "\t".to_string(),
// Right side
// Row 2
BracketLeft => "[".to_string(),
BracketRight => "]".to_string(),
Backslash => "\\".to_string(),
// Row 3
Semicolon => ";".to_string(),
Apostrophe => "'".to_string(),
Return => "\n".to_string(),
// Row 4
Comma => ",".to_string(),
Period => ".".to_string(),
Slash => "/".to_string(),
// Space
Space => " ".to_string(),
// None
_ => "".to_string(),
};
if c.len() > 0 {
text.sections.push(TextSection::new(c, style));
}
}
});
}
}
_ => (),
}
},
)
}
// TODO: Reset default position when de-activated
fn scroll(
mut scrolls: EventReader<MouseWheel>,
mut query: Query<(&mut Style, &UiKitSelect, Entity, &Children, &Parent)>,
changes: Query<Entity, Changed<UiKitSelect>>,
) {
// Brute force: When all Actives are set to None (event) reset all style tops...
changes.iter().for_each(|_| {
let all_inactive = query
.iter_mut()
.all(|(_, select, _, _, _)| *select == UiKitSelect::None);
all_inactive.then(|| {
query
.iter_mut()
.for_each(|(mut style, _, _, _, _)| style.top = Val::Px(0.0));
});
});
scrolls.iter().for_each(|MouseWheel { unit, y, .. }| {
// Find the leaf selected entity
let leaf = query
.iter()
.find(|(_, select, _, children, parent)| {
// This node is active
let self_active = **select == UiKitSelect::Active;
// All children are not selected
let children_inactive = children.iter().all(|&child| {
if let Ok((_, select, _, _, _)) = query.get(child) {
*select == UiKitSelect::None
} else {
true
}
});
// Both must be true
self_active && children_inactive
})
.map(|(_, _, _, _, parent)| parent.get());
if let Some(l) = leaf {
if let Ok((mut style, _, _, _, _)) = query.get_mut(l) {
if *y != 0.0 {
let delta = match unit {
MouseScrollUnit::Line => *y,
MouseScrollUnit::Pixel => 5.0,
};
style.top.try_sub_assign(Val::Px(delta));
info!("Top: {:?}", style.top);
}
}
};
});
}

Loading…
Cancel
Save