use shadow_engine_2d::prelude::*;
use winit::keyboard::KeyCode;
fn main() {
env_logger::init();
let mut engine = Engine::builder()
.title("Shadow Engine 2D - UI Demo")
.size(1280, 720)
.build();
let _ui_system = UISystem::new(1280.0, 720.0);
let title = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(title) {
entity.add(UITransform::new(Anchor::TopCenter).with_offset(Vec2::new(-150.0, 20.0)));
entity.add(UIText::new("Shadow Engine 2D UI").with_size(32.0).with_color(Color::CYAN));
}
let fps_text = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(fps_text) {
entity.add(UITransform::new(Anchor::TopLeft).with_offset(Vec2::new(10.0, 10.0)));
entity.add(UIText::new("FPS: 0").with_size(16.0).with_color(Color::GREEN));
}
let health_panel = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(health_panel) {
entity.add(
UITransform::new(Anchor::TopLeft)
.with_offset(Vec2::new(20.0, 50.0))
.with_size(Vec2::new(250.0, 80.0))
);
entity.add(UIPanel::new().with_background(Color::rgb(0.1, 0.1, 0.15)).with_border(Color::CYAN, 2.0));
}
let health_label = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(health_label) {
entity.add(UITransform::new(Anchor::TopLeft).with_offset(Vec2::new(30.0, 60.0)));
entity.add(UIText::new("Health:").with_size(18.0).with_color(Color::WHITE));
}
let health_bar = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(health_bar) {
entity.add(
UITransform::new(Anchor::TopLeft)
.with_offset(Vec2::new(30.0, 85.0))
.with_size(Vec2::new(230.0, 30.0))
);
entity.add(UIProgressBar::new(100.0).with_value(75.0).with_colors(Color::RED, Color::rgb(0.2, 0.0, 0.0)));
}
let energy_panel = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(energy_panel) {
entity.add(
UITransform::new(Anchor::TopLeft)
.with_offset(Vec2::new(20.0, 150.0))
.with_size(Vec2::new(250.0, 80.0))
);
entity.add(UIPanel::new().with_background(Color::rgb(0.1, 0.1, 0.15)).with_border(Color::YELLOW, 2.0));
}
let energy_label = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(energy_label) {
entity.add(UITransform::new(Anchor::TopLeft).with_offset(Vec2::new(30.0, 160.0)));
entity.add(UIText::new("Energy:").with_size(18.0).with_color(Color::WHITE));
}
let energy_bar = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(energy_bar) {
entity.add(
UITransform::new(Anchor::TopLeft)
.with_offset(Vec2::new(30.0, 185.0))
.with_size(Vec2::new(230.0, 30.0))
);
entity.add(UIProgressBar::new(100.0).with_value(50.0).with_colors(Color::BLUE, Color::rgb(0.0, 0.0, 0.2)));
}
let button_y_start = 300.0;
let button_spacing = 70.0;
for i in 0..3 {
let button = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(button) {
entity.add(
UITransform::new(Anchor::TopLeft)
.with_offset(Vec2::new(20.0, button_y_start + i as f32 * button_spacing))
.with_size(Vec2::new(200.0, 50.0))
);
entity.add(UIButton::new().with_colors(
Color::rgb(0.2, 0.5, 0.8),
Color::rgb(0.3, 0.6, 0.9),
Color::rgb(0.1, 0.4, 0.7),
));
entity.add(UIPanel::new());
let label = match i {
0 => "Start Game",
1 => "Settings",
2 => "Quit",
_ => "Button",
};
entity.add(UIText::new(label).with_size(20.0).with_alignment(TextAlignment::Center));
}
}
let instructions = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(instructions) {
entity.add(UITransform::new(Anchor::BottomLeft).with_offset(Vec2::new(20.0, -100.0)));
entity.add(UIText::new("Press Q/E to change health\nPress A/D to change energy").with_size(14.0).with_color(Color::rgb(0.7, 0.7, 0.7)));
}
let score_text = engine.world_mut().spawn();
if let Some(entity) = engine.world_mut().entity_mut(score_text) {
entity.add(UITransform::new(Anchor::TopRight).with_offset(Vec2::new(-200.0, 20.0)));
entity.add(UIText::new("Score: 0").with_size(24.0).with_color(Color::YELLOW));
}
let mut score = 0;
let mut frame_count = 0;
let mut fps_timer = 0.0;
engine.run(move |world, input, time| {
let dt = time.delta();
frame_count += 1;
fps_timer += dt;
if fps_timer >= 0.5 {
let fps = (frame_count as f32 / fps_timer) as i32;
if let Some(entity) = world.entity_mut(fps_text) {
if let Some(text) = entity.get_mut::<UIText>() {
text.text = format!("FPS: {}", fps);
}
}
frame_count = 0;
fps_timer = 0.0;
}
if let Some(entity) = world.entity_mut(health_bar) {
if let Some(bar) = entity.get_mut::<UIProgressBar>() {
if input.key_pressed(KeyCode::KeyQ) {
bar.set_value((bar.value - 20.0 * dt).max(0.0));
}
if input.key_pressed(KeyCode::KeyE) {
bar.set_value((bar.value + 20.0 * dt).min(100.0));
}
}
}
if let Some(entity) = world.entity_mut(energy_bar) {
if let Some(bar) = entity.get_mut::<UIProgressBar>() {
if input.key_pressed(KeyCode::KeyA) {
bar.set_value((bar.value - 30.0 * dt).max(0.0));
}
if input.key_pressed(KeyCode::KeyD) {
bar.set_value((bar.value + 30.0 * dt).min(100.0));
}
}
}
if input.key_just_pressed(KeyCode::Space) {
score += 100;
if let Some(entity) = world.entity_mut(score_text) {
if let Some(text) = entity.get_mut::<UIText>() {
text.text = format!("Score: {}", score);
}
}
}
let mouse_pos = Vec2::new(input.mouse_position().0, input.mouse_position().1);
for entity in world.entities_mut() {
if entity.has::<UIButton>() {
let is_hovered = if let Some(transform) = entity.get::<UITransform>() {
transform.contains_point(mouse_pos, 1280.0, 720.0)
} else {
false
};
if let Some(button) = entity.get_mut::<UIButton>() {
button.state = if is_hovered {
ButtonState::Hovered
} else {
ButtonState::Normal
};
}
let button_color = entity.get::<UIButton>().map(|b| b.get_current_color());
if let (Some(panel), Some(color)) = (entity.get_mut::<UIPanel>(), button_color) {
panel.background_color = color;
}
}
}
});
}