use eframe::egui;
use egui::{Align2, Color32, FontId, Pos2, Sense, Stroke, Vec2};
use crate::theme::{caps, play_bold};
use crate::{BG, CREAM, MINT, MUTE};
pub fn meter(ui: &mut egui::Ui, label: &str, mine: f32, total: f32, val: &str, tint: Color32) {
ui.vertical(|ui| {
caps(ui, label, 9.0, tint.gamma_multiply(0.9));
ui.add_space(4.0);
let w = ui.available_width();
let (rect, resp) = ui.allocate_exact_size(Vec2::new(w, 9.0), Sense::hover());
ui.painter().rect_filled(rect, 4.5, Color32::from_rgb(24, 34, 29));
let total = total.clamp(0.0, 1.0);
let mine = mine.clamp(0.0, total);
ui.painter().rect_filled(
egui::Rect::from_min_size(rect.min, Vec2::new(w * total, 9.0)),
4.5,
tint.gamma_multiply(0.26),
);
if mine > 0.0005 {
ui.painter().rect_filled(
egui::Rect::from_min_size(rect.min, Vec2::new((w * mine).max(3.0), 9.0)),
4.5,
tint,
);
}
for i in 1..8 {
let x = rect.min.x + w * i as f32 / 8.0;
ui.painter().line_segment(
[Pos2::new(x, rect.min.y + 1.0), Pos2::new(x, rect.max.y - 1.0)],
Stroke::new(1.0, BG),
);
}
if resp.hovered() {
resp.on_hover_text(format!(
"erga {:.0}% ยท everything else {:.0}%",
mine * 100.0,
(total - mine).max(0.0) * 100.0
));
}
ui.add_space(4.0);
let mut job = egui::text::LayoutJob::default();
job.append(
val,
0.0,
egui::TextFormat {
font_id: play_bold(14.0),
color: CREAM.gamma_multiply(0.92),
..Default::default()
},
);
ui.label(job);
});
}
pub fn card_row_tinted(ui: &mut egui::Ui, key: &str, val: &str, tint: Color32) {
ui.horizontal(|ui| {
ui.label(egui::RichText::new(key).color(MINT.gamma_multiply(0.85)).size(11.5));
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.label(egui::RichText::new(val).color(tint).size(12.0).monospace());
});
});
}
pub fn card_row(ui: &mut egui::Ui, key: &str, val: &str) {
ui.horizontal(|ui| {
ui.label(egui::RichText::new(key).color(MINT.gamma_multiply(0.85)).size(11.0));
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.label(egui::RichText::new(val).color(CREAM.gamma_multiply(0.88)).size(11.5).monospace());
});
});
}
pub fn panel_frame(ui: &mut egui::Ui, w: f32, h: f32, add: impl FnOnce(&mut egui::Ui)) {
egui::Frame::none()
.stroke(Stroke::new(1.0, MINT.gamma_multiply(0.22)))
.rounding(14.0)
.inner_margin(egui::Margin::symmetric(18.0, 16.0))
.show(ui, |ui| {
ui.vertical(|ui| {
ui.set_width(w - 36.0);
if h > 0.0 {
ui.set_height(h - 32.0);
}
add(ui);
});
});
}
pub fn draw_crystal(ui: &egui::Ui, c: Pos2, r: f32, on: bool, spin: f32, hover: bool) {
let painter = ui.painter();
let hept = |radius: f32, phase: f32| -> Vec<Pos2> {
(0..7)
.map(|i| {
let a = phase - std::f32::consts::FRAC_PI_2
+ i as f32 * std::f32::consts::TAU / 7.0;
Pos2::new(c.x + radius * a.cos(), c.y + radius * a.sin())
})
.collect()
};
let outer = hept(r * if hover && !on { 1.05 } else { 1.0 }, 0.0);
if on {
for i in 1..=4 {
let k = i as f32;
painter.add(egui::Shape::closed_line(
hept(r * (1.0 + k * 0.06), 0.0),
Stroke::new(2.0, MINT.gamma_multiply(0.10 / k)),
));
}
painter.add(egui::Shape::convex_polygon(outer.clone(), MINT, Stroke::new(1.5, MINT)));
let inner = hept(r * 0.62, -spin);
painter.add(egui::Shape::closed_line(inner, Stroke::new(1.0, BG.gamma_multiply(0.6))));
} else {
for i in 1..=3 {
let k = i as f32;
painter.add(egui::Shape::closed_line(
hept(r * (1.0 + k * 0.05), 0.0),
Stroke::new(1.5, MINT.gamma_multiply(0.06 / k)),
));
}
painter.add(egui::Shape::closed_line(outer, Stroke::new(1.5, MINT.gamma_multiply(0.85))));
let inner = hept(r * 0.62, spin);
painter.add(egui::Shape::closed_line(inner, Stroke::new(1.0, MINT.gamma_multiply(0.35))));
}
}
pub fn big_balance(ui: &mut egui::Ui, on_chain: Option<f64>, w: f32) {
let text = match on_chain {
Some(e) => format!("{e:.4}"),
None => "0.0000".to_string(),
};
let colour = MINT;
let avail = (w - 90.0).max(80.0);
let mut size = 60.0f32;
while size > 18.0 {
let g = ui.painter().layout_no_wrap(text.clone(), play_bold(size), colour);
if g.size().x <= avail {
break;
}
size -= 2.0;
}
ui.vertical_centered(|ui| {
ui.horizontal(|ui| {
let g = ui.painter().layout_no_wrap(text.clone(), play_bold(size), colour);
let row = g.size().x + 46.0;
ui.add_space(((ui.available_width() - row) / 2.0).max(0.0));
let mut job = egui::text::LayoutJob::default();
job.append(
&text,
0.0,
egui::TextFormat { font_id: play_bold(size), color: colour, ..Default::default() },
);
ui.label(job);
ui.add_space(7.0);
caps(ui, "erg", 12.0, MUTE);
});
});
}
pub fn start_hint(ui: &mut egui::Ui) {
let t = ui.input(|i| i.time);
let a = 0.66 + 0.34 * (0.5 - 0.5 * ((t * 0.9).cos() as f32));
ui.vertical_centered(|ui| {
caps(ui, "press the crystal to begin ยท or space", 10.5, MINT.gamma_multiply(a));
});
}
pub fn human(n: u64) -> String {
if n >= 1_000_000_000_000 {
format!("{:.2} T", n as f64 / 1e12)
} else if n >= 1_000_000_000 {
format!("{:.2} B", n as f64 / 1e9)
} else if n >= 1_000_000 {
format!("{:.1} M", n as f64 / 1e6)
} else {
format!("{n}")
}
}
pub fn crystal_button(
ui: &mut egui::Ui,
w: f32,
cr: f32,
running: bool,
spin: f32,
press: f32,
mhs: f64,
) -> bool {
let (rect, resp) = ui.allocate_exact_size(Vec2::new(w, cr * 2.0), Sense::click());
draw_crystal(ui, rect.center(), cr * press, running, spin, resp.hovered());
let c = rect.center();
if running {
ui.painter().text(
c - Vec2::new(0.0, cr * 0.06),
Align2::CENTER_CENTER,
format!("{mhs:.1}"),
play_bold((cr * 0.42).clamp(34.0, 88.0)),
BG,
);
ui.painter().text(
c + Vec2::new(0.0, cr * 0.30),
Align2::CENTER_CENTER,
"MH/S",
FontId::proportional((cr * 0.10).clamp(11.0, 18.0)),
BG.gamma_multiply(0.75),
);
} else {
ui.painter().text(
c,
Align2::CENTER_CENTER,
"START",
FontId::proportional((cr * 0.19).clamp(22.0, 38.0)),
MINT,
);
}
if resp.hovered() {
ui.output_mut(|o| o.cursor_icon = egui::CursorIcon::PointingHand);
}
resp.clicked()
}
pub fn battery(ui: &mut egui::Ui, frac: f32, glow: f32) {
const W: f32 = 30.0;
const H: f32 = 13.0;
let (rect, _) = ui.allocate_exact_size(Vec2::new(W + 4.0, H), Sense::hover());
let body = egui::Rect::from_min_size(rect.min, Vec2::new(W, H));
let lit = MINT.gamma_multiply(0.45 + 0.55 * glow);
ui.painter().rect_filled(body, 3.0, Color32::from_rgb(18, 26, 22));
ui.painter().rect_stroke(body, 3.0, Stroke::new(1.0, lit.gamma_multiply(0.75)));
ui.painter().rect_filled(
egui::Rect::from_min_size(
Pos2::new(body.max.x + 1.0, body.center().y - 3.0),
Vec2::new(3.0, 6.0),
),
1.0,
lit.gamma_multiply(0.75),
);
let f = frac.clamp(0.0, 1.0);
if f > 0.001 {
let inner = body.shrink(2.5);
ui.painter().rect_filled(
egui::Rect::from_min_size(inner.min, Vec2::new(inner.width() * f, inner.height())),
1.5,
lit,
);
}
for i in 1..4 {
let x = body.min.x + W * i as f32 / 4.0;
ui.painter().line_segment(
[Pos2::new(x, body.min.y + 2.5), Pos2::new(x, body.max.y - 2.5)],
Stroke::new(1.0, BG),
);
}
}