mod colors;
mod widgets;
use std::f32;
use bevy_ecs::entity::Entity;
use bevy_ecs::event::Events;
use bevy_ecs::prelude::With;
use bevy_ecs::world::World;
use egui::{Align, Align2, CursorIcon, Layout, Margin, Order, RichText, Shadow, Visuals};
use starkingdoms_common::packet::Packet;
use crate::components::{Camera, Chat, Menu, Player, PlayerResources, SendPacket, Transform};
use crate::ui::widgets::{progress_bar, RichTextExt};
pub fn init_ui(ctx: egui::Context) {
// set colors
let mut style = egui::Style::default();
let mut visuals = Visuals::default();
visuals.dark_mode = true;
// TODO(core): code_bg_colors
visuals.warn_fg_color = colors::YELLOW; // used for warning text
visuals.error_fg_color = colors::RED; // used for error text
visuals.window_shadow = Shadow::NONE;
visuals.window_fill = colors::MANTLE; // window background color
visuals.extreme_bg_color = colors::CRUST; // must be darker than window_fill
visuals.faint_bg_color = colors::BASE; // slightly different than window background color
visuals.window_stroke.color = colors::SURFACE_0;
visuals.window_highlight_topmost = false;
visuals.text_cursor.stroke.color = colors::ROSEWATER;
// TODO(core): button_frame, collapsing_header_frame
visuals.striped = true;
visuals.interact_cursor = Some(CursorIcon::PointingHand);
visuals.selection.bg_fill = colors::OVERLAY_2.gamma_multiply(0.2); // selection background
visuals.hyperlink_color = colors::BLUE;
visuals.widgets.noninteractive.fg_stroke.color = colors::TEXT; // standard text color
style.visuals = visuals;
ctx.set_style(style);
}
pub fn draw_ui(ctx: &egui::Context, world: &mut World, send_packet_events: &mut Events<SendPacket>) {
draw_status_bar(ctx, world);
draw_chat(ctx, world, send_packet_events);
draw_crafting(ctx, world);
}
pub fn draw_status_bar(ctx: &egui::Context, world: &mut World) {
let mut player = world.query_filtered::<&Transform, With<Player>>();
let player_position = player.single(&world);
let player_resources = world.resource::<PlayerResources>();
egui::Window::new("status_bar")
.title_bar(false)
.movable(false)
.resizable(false)
.order(Order::Foreground)
.anchor(Align2::CENTER_BOTTOM, [0.0, -5.0])
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.vertical(|ui| {
ui.label(RichText::new("Position:").stk_weak());
ui.label(RichText::new(format!("{:.0}, {:.0}", player_position.translation.x / 10.0, player_position.translation.y / 10.0)))
});
ui.add_space(8.0);
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.label(RichText::new("Fuel:").stk_weak());
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
ui.label(RichText::new(format!("{}/{} ({:.2}%)", player_resources.fuel_amount, player_resources.fuel_max, player_resources.fuel_amount as f32 / player_resources.fuel_max as f32 * 100.0)))
});
});
ui.add(
progress_bar(player_resources.fuel_amount as f32 / player_resources.fuel_max as f32)
);
})
});
});
}
pub fn draw_chat(ctx: &egui::Context, world: &mut World, send_packet_events: &mut Events<SendPacket>) {
let mut chat = world.get_resource_mut::<Chat>().unwrap();
egui::Window::new("Chat")
.movable(true)
.order(Order::Foreground)
.show(ctx, |ui| {
egui::Frame::new()
.inner_margin(Margin::same(5))
.corner_radius(2)
.fill(colors::CRUST)
.show(ui, |ui| {
egui::ScrollArea::vertical()
.max_width(f32::INFINITY)
.max_height(100.0)
.auto_shrink(false)
.stick_to_bottom(true)
.show(ui, |ui| {
for message in &chat.messages {
ui.label(message);
}
});
});
ui.horizontal(|ui| {
let output = egui::TextEdit::singleline(&mut chat.textbox).show(ui);
if ui.button("Send").clicked() ||
(ctx.input(|i| i.key_pressed(egui::Key::Enter)) && output.response.lost_focus()) {
send_packet_events.send(SendPacket(Packet::SendMessage {
target: None,
content: chat.textbox.clone(),
}));
chat.textbox.clear();
}
});
});
}
pub fn draw_crafting(ctx: &egui::Context, world: &mut World) {
let mut menus = world.query_filtered::<(Entity, &Transform), With<Menu>>();
let camera = world.resource::<Camera>();
for (entity, menu) in menus.iter(&world) {
egui::Window::new("Crafting")
.id(format!("Crafting{}", entity.index()).into())
.pivot(Align2::LEFT_BOTTOM)
.fixed_pos(((menu.translation.x + camera.x) * camera.zoom + camera.width as f32 / 2.0,
(menu.translation.y + camera.y) * camera.zoom + camera.height as f32 / 2.0))
.show(ctx, |ui| {
});
}
}