use bevy::diagnostic::FrameTimeDiagnosticsPlugin;
use bevy::diagnostic::LogDiagnosticsPlugin;
use bevy::{
color::palettes::css::*, log::LogPlugin, math::Rect, prelude::*, sprite::Anchor,
window::PrimaryWindow,
};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use bevy_keith::*;
fn main() {
App::new()
.add_plugins(FrameTimeDiagnosticsPlugin::default())
.add_plugins(LogDiagnosticsPlugin::default())
.add_plugins(
DefaultPlugins
.set(LogPlugin {
level: bevy::log::Level::WARN,
filter: "quad=trace,bevy_keith=warn,bevy=info".to_string(),
..default()
})
.set(WindowPlugin {
primary_window: Some(Window {
title: "bevy_keith - quad".to_string(),
..default()
}),
..default()
}),
)
.insert_resource(ClearColor(DARK_GRAY.into()))
.add_plugins(KeithPlugin)
.add_plugins(WorldInspectorPlugin::default())
.add_systems(Startup, setup)
.add_systems(Update, run)
.run();
}
#[derive(Component)]
struct MyRes {
font: Handle<Font>,
image: Handle<Image>,
}
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
text_pipeline: Res<KeithTextPipeline>,
) {
let font = asset_server.load("FiraSans-Regular.ttf");
let image = asset_server.load("uvdev.png");
let mut canvas = Canvas::new(Rect {
min: Vec2::splat(-400.),
max: Vec2::splat(100.),
});
canvas.background_color = Some(BEIGE.into());
commands
.spawn(Camera2dBundle::default())
.insert(canvas)
.insert(MyRes {
font: font.clone(),
image: image.clone(),
});
commands
.spawn(SpriteBundle {
sprite: Sprite {
color: Color::srgba_u8(0, 0, 0, 128),
custom_size: Some(Vec2::splat(512.)),
..default()
},
transform: Transform::from_xyz(400., 0., 0.),
..default()
})
.with_children(|p| {
p.spawn(SpriteBundle {
texture: text_pipeline.atlas_texture_handle.clone(),
sprite: Sprite {
custom_size: Some(Vec2::splat(512.)),
..default()
},
..default()
});
});
}
fn draw_button(
ctx: &mut RenderContext,
rect: Rect,
text: &str,
font: Handle<Font>,
cursor_pos: Vec2,
) {
let (brush, border_brush) = if rect.contains(cursor_pos) {
let border_brush = ctx.solid_brush(Color::srgb(0.6, 0.6, 1.0));
(ctx.solid_brush(Color::srgb(0.7, 0.7, 0.7)), border_brush)
} else {
let border_brush = ctx.solid_brush(Color::srgb(0.8, 0.8, 0.9));
(ctx.solid_brush(Color::srgb(0.6, 0.6, 0.6)), border_brush)
};
ctx.fill(rect, &brush).border(&border_brush, 2.);
let text = ctx
.new_layout(text.to_owned())
.color(Color::srgb(0.2, 0.2, 0.2))
.font(font)
.font_size(16.)
.bounds(rect.size())
.alignment(JustifyText::Center)
.build();
ctx.draw_text(text, (rect.min + rect.max) / 2.);
}
fn run(
time: Res<Time>,
mut query: Query<(&mut Canvas, &MyRes)>,
q_window: Query<&Window, With<PrimaryWindow>>,
) {
let (mut canvas, my_res) = query.single_mut();
canvas.clear();
let mut ctx = canvas.render_context();
let cursor_pos = if let Ok(window) = q_window.get_single() {
window
.cursor_position()
.map(|v| Vec2::new(v.x - 1280. / 2., v.y - 720. / 2.))
} else {
None
}
.unwrap_or(Vec2::NAN);
let border_brush = ctx.solid_brush(DARK_GREEN.into());
let brush = ctx.solid_brush(BISQUE.into());
let rect = Rect {
min: Vec2::new(-10., -30.),
max: Vec2::new(30., 130.),
};
let border_width = (time.elapsed_seconds() * 2.).sin() * 4. + 4.;
ctx.fill(rect, &brush).border(&border_brush, border_width);
let radius = time.elapsed_seconds().sin() * 8. + 8.;
let brush = ctx.solid_brush(PINK.into());
let rounded_rect = RoundedRect {
rect: Rect {
min: Vec2::new(30., -132.),
max: Vec2::new(62., -100.),
},
radius,
};
ctx.fill(rounded_rect, &brush);
let text = ctx
.new_layout("Hello World!")
.color(TEAL.into())
.font(my_res.font.clone())
.font_size(32.)
.anchor(Anchor::BottomLeft)
.build();
ctx.draw_text(text, Vec2::new(0.0, 0.0));
let rect = Rect {
min: Vec2::new(100., 150.),
max: Vec2::new(164., 214.),
};
ctx.draw_image(rect, my_res.image.clone(), ImageScaling::default());
let brush = ctx.solid_brush(GREEN.into());
let delta = time.elapsed_seconds().sin() * 15. + 30.;
for i in 0..=10 {
ctx.line(
Vec2::new(-200.5, 0.5 + i as f32 * 15.),
Vec2::new(0.5, 0.5 + i as f32 * delta),
&brush,
1. + i as f32,
)
.border(&border_brush, border_width);
}
let color = Color::hsl((time.elapsed_seconds() / 3.).fract() * 360., 0.5, 0.5);
let text = ctx
.new_layout("bevy_keith")
.color(color)
.font(my_res.font.clone())
.font_size(128.)
.build();
ctx.draw_text(text, Vec2::new(-350., 300.0));
let rect = Rect {
min: Vec2::new(-200., -100.),
max: Vec2::new(-80., -70.),
};
draw_button(&mut ctx, rect, "Submit", my_res.font.clone(), cursor_pos);
let rect = Rect {
min: Vec2::new(-200., -140.),
max: Vec2::new(-80., -110.),
};
draw_button(&mut ctx, rect, "Cancel", my_res.font.clone(), cursor_pos);
let rect = Rect {
min: Vec2::new(-200., -180.),
max: Vec2::new(-80., -150.),
};
draw_button(
&mut ctx,
rect,
"This is a very long text that will not fit in the button",
my_res.font.clone(),
cursor_pos,
);
let s = "The quick brown fox jumps over the lazy dog THE QUICK BROWN FOX
JUMPS OVER THE LAZY DOG !£$%^&*()_}{][#';~@:";
for (i, st) in s.as_bytes().chunks(10).enumerate() {
let rect = Rect {
min: Vec2::new(-400., -180. + i as f32 * 35.),
max: Vec2::new(-280., -150. + i as f32 * 35.),
};
draw_button(
&mut ctx,
rect,
&format!("Button #{} {}", i, String::from_utf8_lossy(st)),
my_res.font.clone(),
cursor_pos,
);
}
}