You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
8.0 KiB
Rust
241 lines
8.0 KiB
Rust
use bevy::{diagnostic::FrameTimeDiagnosticsPlugin, prelude::*};
|
|
|
|
const LOREM: [&str; 5] = [
|
|
"Ullam nostrum aut amet adipisci consequuntur quisquam nemo consequatur. Vel eum et ullam ullam aperiam earum voluptas consequuntur. Blanditiis earum voluptatem voluptas animi dolorum fuga aliquam ea.\n",
|
|
"Velit ratione consequatur modi. Dolores quo quisquam occaecati veniam maxime totam minus et. Laudantium unde optio vel. Et cumque voluptatum dolorem. Odit tempore dolores quibusdam aspernatur vitae labore occaecati. Omnis quia tempora tenetur repellat in.\n",
|
|
"Dolores perspiciatis tempore in consequuntur in minus autem. Voluptatem quas dignissimos quae ut necessitatibus illo ducimus. Quis fuga nisi non ut sunt velit.\n",
|
|
"Sit quia officia alias hic. Incidunt sed vitae optio cumque rerum corrupti perferendis enim. Adipisci necessitatibus illum vero placeat saepe aut et.\n",
|
|
"Velit perspiciatis doloribus consectetur. Doloremque ea non optio itaque. Voluptatem sint voluptatum minus.\n",
|
|
];
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
|
primary_window: Some(Window {
|
|
title: "Text Inspect".into(),
|
|
resolution: (640., 480.).into(),
|
|
..default()
|
|
}),
|
|
..default()
|
|
}))
|
|
.add_startup_system(load_fonts)
|
|
.add_startup_system(init_ui)
|
|
.add_system(manage_buttons)
|
|
.add_system(update)
|
|
.add_system(mouse_cursor)
|
|
.add_system(play)
|
|
.add_system(framerate)
|
|
.run();
|
|
}
|
|
|
|
#[derive(Resource)]
|
|
struct Fonts(Vec<Handle<Font>>);
|
|
|
|
#[derive(Component)]
|
|
struct Marker;
|
|
|
|
#[derive(Component)]
|
|
struct PreviewText;
|
|
|
|
#[derive(Component)]
|
|
struct ButtonShelf;
|
|
|
|
#[derive(Component)]
|
|
struct FontButton(Handle<Font>);
|
|
|
|
fn load_fonts(mut commands: Commands, server: Res<AssetServer>) {
|
|
let handles = server
|
|
.load_folder("fonts")
|
|
.expect("Load fonts folder")
|
|
.iter()
|
|
.map(|untyped| untyped.clone().typed::<Font>())
|
|
.collect();
|
|
commands.insert_resource(Fonts(handles));
|
|
}
|
|
|
|
fn init_ui(mut commands: Commands) {
|
|
commands.spawn(Camera2dBundle { ..default() });
|
|
|
|
commands
|
|
.spawn((
|
|
NodeBundle {
|
|
style: Style {
|
|
size: Size::all(Val::Percent(100.0)),
|
|
..default()
|
|
},
|
|
background_color: BackgroundColor(Color::BLACK),
|
|
..default()
|
|
},
|
|
Marker,
|
|
))
|
|
.with_children(|parent| {
|
|
parent.spawn((
|
|
NodeBundle {
|
|
style: Style {
|
|
flex_direction: FlexDirection::Column,
|
|
align_items: AlignItems::Center,
|
|
size: Size {
|
|
width: Val::Px(200.0),
|
|
height: Val::Undefined,
|
|
},
|
|
align_content: AlignContent::SpaceEvenly,
|
|
..default()
|
|
},
|
|
background_color: BackgroundColor(Color::BLACK),
|
|
..default()
|
|
},
|
|
Marker,
|
|
ButtonShelf,
|
|
));
|
|
|
|
parent.spawn((
|
|
TextBundle::from_sections(LOREM.iter().map(|§ion| TextSection {
|
|
value: section.into(),
|
|
style: TextStyle {
|
|
font_size: 50.0,
|
|
..default()
|
|
},
|
|
}))
|
|
.with_style(Style {
|
|
max_size: Size {
|
|
width: Val::Px(500.),
|
|
height: Val::Undefined,
|
|
},
|
|
..default()
|
|
}),
|
|
Marker,
|
|
PreviewText,
|
|
));
|
|
});
|
|
}
|
|
|
|
// Add/remove buttons from shelf with font name(s)
|
|
fn manage_buttons(
|
|
mut commands: Commands,
|
|
fonts: Res<Fonts>,
|
|
server: Res<AssetServer>,
|
|
query: Query<Entity, (With<Marker>, With<ButtonShelf>)>,
|
|
) {
|
|
if fonts.is_added() || fonts.is_changed() {
|
|
let root = query.get_single().expect("Fetching root UI node");
|
|
let mut root_cmd = commands.get_entity(root).expect("Root UI node commands");
|
|
|
|
root_cmd.clear_children();
|
|
root_cmd.with_children(|root| {
|
|
fonts.0.iter().for_each(|font| {
|
|
let handle_path = server
|
|
.get_handle_path(font.clone())
|
|
.expect("Get handle path");
|
|
let path = handle_path.path().to_str().expect("Convert path to str");
|
|
let fname = path
|
|
.split("/")
|
|
.last()
|
|
.expect("Extracting filename")
|
|
.strip_suffix(".otf")
|
|
.expect("Stripping prefix");
|
|
|
|
let style = TextStyle {
|
|
font: font.clone(),
|
|
color: Color::BLACK,
|
|
font_size: 18.0,
|
|
};
|
|
|
|
root.spawn((
|
|
ButtonBundle {
|
|
style: Style {
|
|
align_content: AlignContent::Center,
|
|
// size: Size {
|
|
// width: Val::Undefined,
|
|
// height: Val::Undefined,
|
|
// },
|
|
padding: UiRect::all(Val::Px(5.0)),
|
|
..default()
|
|
},
|
|
..default()
|
|
},
|
|
FontButton(font.clone()),
|
|
Marker,
|
|
))
|
|
.with_children(|parent| {
|
|
info!("Adding {} button", fname);
|
|
parent.spawn((TextBundle::from_section(fname, style), Marker));
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
fn update(
|
|
mut texts: Query<&mut Text, (With<Marker>, With<PreviewText>)>,
|
|
interaction: Query<(&Interaction, &FontButton), Changed<Interaction>>,
|
|
) {
|
|
for (i, f) in interaction.iter() {
|
|
match (i, f) {
|
|
(Interaction::Clicked, FontButton(font)) => {
|
|
let mut text = texts.single_mut();
|
|
*text = Text::from_sections(LOREM.iter().flat_map(|&l| {
|
|
l.chars().map(|c| TextSection {
|
|
value: c.into(),
|
|
style: TextStyle {
|
|
font: font.clone(),
|
|
font_size: 50.0,
|
|
..default()
|
|
},
|
|
})
|
|
}));
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn mouse_cursor(
|
|
mut windows: Query<&mut Window>,
|
|
interactions: Query<&Interaction, (Changed<Interaction>, With<Button>)>,
|
|
) {
|
|
for interaction in interactions.iter() {
|
|
let mut window = windows.single_mut();
|
|
|
|
window.cursor.icon = match interaction {
|
|
Interaction::Hovered | Interaction::Clicked => CursorIcon::Hand,
|
|
Interaction::None => CursorIcon::Arrow,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn play(
|
|
mut texts: Query<&mut Text, (With<Marker>, With<PreviewText>)>,
|
|
interactions: Query<&Interaction, (Changed<Interaction>, With<FontButton>)>,
|
|
mut playing: Local<bool>,
|
|
time: Res<Time>,
|
|
mut desired: Local<String>,
|
|
) {
|
|
for interaction in interactions.iter() {
|
|
match interaction {
|
|
Interaction::Clicked => *playing = true,
|
|
_ => (),
|
|
}
|
|
}
|
|
if *playing {
|
|
let mut text = texts.single_mut();
|
|
let total_sections = text.sections.len();
|
|
|
|
let curr_cos = time.elapsed().as_secs_f32().cos().abs();
|
|
|
|
for (idx, section) in text.sections.iter_mut().enumerate() {
|
|
let idx_ratio = (total_sections as f32) / ((idx + 1) as f32);
|
|
|
|
let intensity = (curr_cos - idx_ratio).abs() % 1.0;
|
|
|
|
section.style.color.set_a(intensity);
|
|
}
|
|
// Get text sections
|
|
//
|
|
// figure out how far into animation we are
|
|
//
|
|
// Set current vs desired ratio
|
|
//
|
|
// Set current to that % from empty to desired
|
|
}
|
|
}
|