use eframe::egui::{
self, Color32, CornerRadius, Margin, Stroke, Style, Vec2, Visuals,
epaint::Shadow,
style::{Interaction, ScrollStyle, Selection, Spacing, TextCursorStyle, WidgetVisuals, Widgets},
};
use eframe::egui_wgpu;
use henad_compute::gpu::GpuNeeds;
use crate::ui::mcs;
pub fn setup_custom_fonts(ctx: &egui::Context) {
let mut fonts = egui::FontDefinitions::default();
fonts.font_data.insert(
"ibm_plex_sans_font".to_owned(),
egui::FontData::from_static(include_bytes!("../assets/fonts/Henad Sans Regular.ttf")).into(),
);
fonts.font_data.insert(
"ibm_plex_mono_font".to_owned(),
egui::FontData::from_static(include_bytes!("../assets/fonts/Henad Mono Regular.ttf")).into(),
);
fonts.font_data.insert(
"material_design_icons_font".to_owned(),
egui::FontData::from_static(include_bytes!("../assets/fonts/Material Design Icons.ttf")).into(),
);
fonts.font_data.insert(
"material_symbols_font".to_owned(),
egui::FontData::from_static(include_bytes!("../assets/fonts/Material Symbols Outlined.ttf")).into(),
);
fonts
.families
.entry(egui::FontFamily::Proportional)
.or_default()
.insert(0, "ibm_plex_sans_font".to_owned());
fonts
.families
.entry(egui::FontFamily::Proportional)
.or_default()
.insert(1, "material_design_icons_font".to_owned());
fonts
.families
.entry(egui::FontFamily::Proportional)
.or_default()
.insert(2, "material_symbols_font".to_owned());
fonts
.families
.entry(egui::FontFamily::Monospace)
.or_default()
.insert(0, "ibm_plex_mono_font".to_owned());
ctx.set_fonts(fonts);
}
pub fn wgpu_configuration(needs: GpuNeeds) -> egui_wgpu::WgpuConfiguration {
egui_wgpu::WgpuConfiguration {
wgpu_setup: egui_wgpu::WgpuSetup::CreateNew(egui_wgpu::WgpuSetupCreateNew {
device_descriptor: std::sync::Arc::new(move |adapter| device_descriptor(adapter, needs)),
..egui_wgpu::WgpuSetupCreateNew::without_display_handle()
}),
..Default::default()
}
}
pub fn device_descriptor(adapter: &wgpu::Adapter, needs: GpuNeeds) -> wgpu::DeviceDescriptor<'static> {
let base = egui_wgpu::WgpuSetupCreateNew::without_display_handle();
let mut descriptor = (base.device_descriptor)(adapter);
#[cfg(not(target_arch = "wasm32"))]
if adapter.features().contains(wgpu::Features::TIMESTAMP_QUERY) {
descriptor.required_features |= wgpu::Features::TIMESTAMP_QUERY;
}
descriptor.required_limits = henad_compute::gpu::limits::raise(adapter, &descriptor.required_limits, needs);
descriptor
}
#[expect(clippy::too_many_lines, reason = "I don't care.")]
pub fn style() -> Style {
Style {
spacing: Spacing {
item_spacing: Vec2 { x: 8.0, y: 3.0 },
window_margin: Margin {
left: 6,
right: 6,
top: 6,
bottom: 6,
},
button_padding: Vec2 { x: 4.0, y: 1.0 },
menu_margin: Margin {
left: 6,
right: 6,
top: 6,
bottom: 6,
},
indent: 18.0,
interact_size: Vec2 { x: 40.0, y: 18.0 },
slider_width: 100.0,
combo_width: 100.0,
text_edit_width: 280.0,
icon_width: 14.0,
icon_width_inner: 8.0,
icon_spacing: 4.0,
tooltip_width: 500.0,
indent_ends_with_horizontal_line: false,
combo_height: 200.0,
scroll: ScrollStyle {
bar_width: 10.0,
handle_min_length: 12.0,
bar_inner_margin: 4.0,
bar_outer_margin: 0.0,
..Default::default()
},
..Default::default()
},
interaction: Interaction {
resize_grab_radius_side: 5.0,
resize_grab_radius_corner: 10.0,
show_tooltips_only_when_still: true,
..Default::default()
},
visuals: Visuals {
dark_mode: true,
override_text_color: None,
widgets: Widgets {
noninteractive: WidgetVisuals {
bg_fill: Color32::from_rgba_premultiplied(27, 27, 27, 255),
weak_bg_fill: Color32::from_rgba_premultiplied(27, 27, 27, 255),
bg_stroke: Stroke {
width: 1.0,
color: Color32::from_rgba_premultiplied(60, 60, 60, 255),
},
corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
fg_stroke: Stroke {
width: 1.0,
color: mcs::GRAY_300,
},
expansion: 0.0,
},
inactive: WidgetVisuals {
bg_fill: Color32::from_rgba_premultiplied(60, 60, 60, 255),
weak_bg_fill: Color32::from_rgba_premultiplied(60, 60, 60, 255),
bg_stroke: Stroke {
width: 0.0,
color: Color32::from_rgba_premultiplied(0, 0, 0, 0),
},
corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
fg_stroke: Stroke {
width: 1.0,
color: mcs::GRAY_200,
},
expansion: 0.0,
},
hovered: WidgetVisuals {
bg_fill: Color32::from_rgba_premultiplied(70, 70, 70, 255),
weak_bg_fill: Color32::from_rgba_premultiplied(70, 70, 70, 255),
bg_stroke: Stroke {
width: 1.0,
color: Color32::from_rgba_premultiplied(150, 150, 150, 255),
},
corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
fg_stroke: Stroke {
width: 1.5,
color: mcs::GRAY_50,
},
expansion: 1.0,
},
active: WidgetVisuals {
bg_fill: Color32::from_rgba_premultiplied(55, 55, 55, 255),
weak_bg_fill: Color32::from_rgba_premultiplied(55, 55, 55, 255),
bg_stroke: Stroke {
width: 1.0,
color: Color32::from_rgba_premultiplied(255, 255, 255, 255),
},
corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
fg_stroke: Stroke {
width: 2.0,
color: Color32::from_rgba_premultiplied(255, 255, 255, 255),
},
expansion: 1.0,
},
open: WidgetVisuals {
bg_fill: Color32::from_rgba_premultiplied(27, 27, 27, 255),
weak_bg_fill: Color32::from_rgba_premultiplied(45, 45, 45, 255),
bg_stroke: Stroke {
width: 1.0,
color: Color32::from_rgba_premultiplied(60, 60, 60, 255),
},
corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
fg_stroke: Stroke {
width: 1.0,
color: Color32::from_rgba_premultiplied(210, 210, 210, 255),
},
expansion: 0.0,
},
},
selection: Selection {
bg_fill: mcs::BLUE_700,
stroke: Stroke {
width: 1.0,
color: Color32::from_rgba_premultiplied(192, 222, 255, 255),
},
},
hyperlink_color: mcs::BLUE_200,
faint_bg_color: Color32::from_rgba_premultiplied(5, 5, 5, 0),
extreme_bg_color: Color32::from_rgba_premultiplied(10, 10, 10, 255),
code_bg_color: Color32::from_rgba_premultiplied(64, 64, 64, 255),
warn_fg_color: mcs::ORANGE_500,
error_fg_color: mcs::RED_500,
window_corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
window_shadow: Shadow {
spread: 0,
color: Color32::from_rgba_premultiplied(0, 0, 0, 96),
blur: 15,
offset: [10, 20],
},
window_fill: mcs::GRAY_900,
window_stroke: Stroke {
width: 1.0,
color: mcs::GRAY_800,
},
menu_corner_radius: CornerRadius {
nw: 0,
ne: 0,
sw: 0,
se: 0,
},
panel_fill: Color32::from_rgba_premultiplied(21, 21, 21, 255),
popup_shadow: Shadow {
spread: 0,
color: Color32::from_rgba_premultiplied(0, 0, 0, 96),
blur: 8,
offset: [6, 10],
},
resize_corner_size: 12.0,
text_cursor: TextCursorStyle {
stroke: Stroke {
width: 2.0,
color: Color32::from_rgba_premultiplied(192, 222, 255, 255),
},
preview: false,
..Default::default()
},
button_frame: true,
collapsing_header_frame: true,
indent_has_left_vline: true,
striped: false,
slider_trailing_fill: true,
..Default::default()
},
animation_time: 0.083_333_336,
explanation_tooltips: false,
..Default::default()
}
}
pub fn setup_custom_styles(ctx: &egui::Context) {
let style = std::sync::Arc::new(style());
ctx.set_style_of(egui::Theme::Dark, style.clone());
ctx.set_style_of(egui::Theme::Light, style);
}