use egui::{Color32, FontData, FontDefinitions};
pub const CANVAS_BACKGROUND: Color32 = Color32::from_rgb(0x06, 0x08, 0x14);
pub const PANEL_BACKGROUND: Color32 = Color32::from_rgb(0x0b, 0x0f, 0x22);
pub mod curve_color {
pub const R: u8 = 0x1f;
pub const G: u8 = 0xf2;
pub const B: u8 = 0xff;
}
pub mod accent_color {
pub const R: u8 = 0xff;
pub const G: u8 = 0x4d;
pub const B: u8 = 0xf6;
}
pub const TEXT_PRIMARY: Color32 = Color32::from_rgb(0xe6, 0xed, 0xff);
pub const TEXT_SECONDARY: Color32 = Color32::from_rgb(0x9f, 0xb4, 0xe5);
pub const TEXT_BODY: Color32 = Color32::from_rgb(0xcb, 0xd7, 0xff);
pub const TEXT_DIM: Color32 = Color32::from_rgb(0x69, 0x73, 0x92);
pub const TEXT_HEADING: Color32 = Color32::from_rgb(0xff, 0x5a, 0xf1);
pub const TEXT_LINK: Color32 = Color32::from_rgb(0x55, 0xf0, 0xff);
pub const WIDGET_BACKGROUND: Color32 = Color32::from_rgb(0x16, 0x14, 0x28);
pub const WIDGET_HOVERED: Color32 = Color32::from_rgb(0x23, 0x20, 0x38);
pub const WIDGET_ACTIVE: Color32 = Color32::from_rgb(0x2f, 0x28, 0x4e);
pub const TOGGLE_BG: Color32 = Color32::from_rgb(0x1c, 0x1a, 0x32);
pub const TOGGLE_BG_ACTIVE: Color32 = Color32::from_rgb(0x28, 0x22, 0x4b);
pub const SETTINGS_PANEL_BG: Color32 = Color32::from_rgba_premultiplied(0x16, 0x14, 0x28, 250);
pub const SELECTION: Color32 = Color32::from_rgb(0x25, 0x1e, 0x3a);
pub const BORDER: Color32 = Color32::from_rgb(0x38, 0x35, 0x57);
pub const SLIDER_RAIL: Color32 = Color32::from_rgb(0x2a, 0x27, 0x40);
pub const SLIDER_FILL: Color32 = Color32::from_rgb(0x29, 0xf0, 0xff);
pub const BUTTON_PLAY: Color32 = Color32::from_rgb(0x0f, 0x6e, 0xa8);
pub const BUTTON_PAUSE: Color32 = Color32::from_rgb(0x4a, 0x14, 0x63);
pub const MODAL_DIM_ALPHA: u8 = 180;
pub const POPUP_SHADOW_ALPHA: u8 = 140;
pub const DIALOG_SHADOW_ALPHA: u8 = 160;
const FONT_ORBITRON_REGULAR: &[u8] = include_bytes!("../assets/fonts/Orbitron-Regular.ttf");
const FONT_ORBITRON_BOLD: &[u8] = include_bytes!("../assets/fonts/Orbitron-Bold.ttf");
pub mod font_size {
pub const TITLE: f32 = 18.0;
pub const HEADING_LARGE: f32 = 28.0;
pub const CLOSE_BUTTON: f32 = 18.0;
pub const LABEL: f32 = 14.0;
pub const INFO: f32 = 13.0;
pub const VERSION: f32 = 12.0;
}
pub mod spacing {
pub const SMALL: f32 = 4.0;
pub const MEDIUM: f32 = 8.0;
pub const LARGE: f32 = 16.0;
}
pub mod menu_bar {
pub const PADDING_VERTICAL: f32 = 6.0;
pub const PADDING_HORIZONTAL: f32 = 12.0;
pub const TITLE_SPACING: f32 = 16.0;
pub const TAB_SPACING: f32 = 4.0;
pub const BUTTON_PADDING: f32 = 8.0;
}
pub mod control_bar {
pub const PADDING_VERTICAL: f32 = 4.0;
pub const PADDING_HORIZONTAL: f32 = 8.0;
}
pub mod window {
pub const DEFAULT_SIZE: [f32; 2] = [800.0, 600.0];
pub const ABOUT_DIALOG_SIZE: (f32, f32) = (550.0, 450.0);
pub const ABOUT_SCROLL_HEIGHT: f32 = 300.0;
}
pub mod popup {
pub const INNER_MARGIN: i8 = 10;
pub const SETTINGS_MARGIN: i8 = 10;
pub const SETTINGS_WIDTH: f32 = 220.0;
pub const SETTINGS_OFFSET_X: f32 = 28.0;
pub const INFO_PANE_WIDTH: f32 = 320.0;
pub const CORNER_RADIUS: u8 = 2;
pub const ANCHOR_OFFSET: f32 = 4.0;
pub const SETTINGS_OFFSET_Y: f32 = 4.0;
}
pub mod shadow {
pub const OFFSET: [i8; 2] = [1, 2];
pub const BLUR: u8 = 6;
pub const SPREAD: u8 = 0;
}
pub mod canvas_2d {
pub const MARGIN: f32 = 10.0;
pub const SIZE_FRACTION: f32 = 0.85;
pub const MIN_SIZE: f32 = 200.0;
pub const LINE_WIDTH: f32 = 2.5;
pub const SNAKE_WIDTH_MULTIPLIER: f32 = 1.8;
}
pub mod canvas_3d {
use std::f32::consts::PI;
pub const MARGIN: f32 = 50.0;
pub const SCALE_FACTOR: f32 = 0.25;
pub const MIN_SCALE: f32 = 25.0;
pub const DRAG_SENSITIVITY: f32 = 0.01;
pub const PERSPECTIVE_DISTANCE: f32 = 4.0;
pub const CAMERA_TILT: f32 = PI / 6.0;
pub const DEPTH_MIN: f32 = -2.0;
pub const DEPTH_MAX: f32 = 2.0;
pub const CAP_SHORTEN_FACTOR: f32 = 0.6;
pub const BASE_LINE_WIDTH: f32 = 2.0;
pub const HEAD_MARKER_RADIUS: f32 = 5.0;
pub const HEAD_MARKER_GLOW_RADIUS: f32 = 10.0;
pub const HEAD_MARKER_GLOW_ALPHA: u8 = 80;
}
pub mod animation {
pub const BASE_ROTATION_SPEED: f32 = 0.35;
}
#[inline]
pub fn curve_color_with_brightness(brightness: f32, opacity: f32) -> Color32 {
Color32::from_rgba_unmultiplied(
(curve_color::R as f32 * brightness) as u8,
(curve_color::G as f32 * brightness) as u8,
(curve_color::B as f32 * brightness) as u8,
(255.0 * opacity) as u8,
)
}
#[inline]
pub fn curve_color_opaque(brightness: f32) -> Color32 {
Color32::from_rgb(
(curve_color::R as f32 * brightness) as u8,
(curve_color::G as f32 * brightness) as u8,
(curve_color::B as f32 * brightness) as u8,
)
}
#[inline]
pub fn snake_color_with_brightness(brightness: f32) -> Color32 {
Color32::from_rgb(
(accent_color::R as f32 * brightness) as u8,
(accent_color::G as f32 * brightness) as u8,
(accent_color::B as f32 * brightness) as u8,
)
}
#[inline]
pub fn curve_glow_color(brightness: f32) -> Color32 {
let glow_blend = 0.6; let r = curve_color::R as f32 * brightness;
let g = curve_color::G as f32 * brightness;
let b = curve_color::B as f32 * brightness;
Color32::from_rgb(
(r + (255.0 - r) * glow_blend) as u8,
(g + (255.0 - g) * glow_blend) as u8,
(b + (255.0 - b) * glow_blend) as u8,
)
}
#[inline]
pub fn curve_glow_color_alpha(brightness: f32, alpha: u8) -> Color32 {
let glow_blend = 0.6;
let r = curve_color::R as f32 * brightness;
let g = curve_color::G as f32 * brightness;
let b = curve_color::B as f32 * brightness;
Color32::from_rgba_unmultiplied(
(r + (255.0 - r) * glow_blend) as u8,
(g + (255.0 - g) * glow_blend) as u8,
(b + (255.0 - b) * glow_blend) as u8,
alpha,
)
}
#[inline]
pub fn segment_brightness(depth: f32) -> f32 {
0.3 + 0.7 * normalize_depth(depth)
}
#[inline]
pub fn isolated_point_brightness(depth: f32) -> f32 {
0.4 + 0.6 * normalize_depth(depth)
}
#[inline]
pub fn segment_line_width(brightness: f32) -> f32 {
canvas_3d::BASE_LINE_WIDTH * (0.5 + 0.5 * brightness)
}
#[inline]
pub fn isolated_point_line_width(brightness: f32) -> f32 {
canvas_3d::BASE_LINE_WIDTH * (0.6 + 0.4 * brightness)
}
#[inline]
pub fn normalize_depth(depth: f32) -> f32 {
((depth - canvas_3d::DEPTH_MIN) / (canvas_3d::DEPTH_MAX - canvas_3d::DEPTH_MIN)).clamp(0.0, 1.0)
}
pub fn configure_visuals(ctx: &egui::Context) {
use egui::{FontFamily, FontId, TextStyle, Visuals, epaint::Shadow};
let mut visuals = Visuals::dark();
visuals.window_fill = PANEL_BACKGROUND;
visuals.panel_fill = PANEL_BACKGROUND;
visuals.extreme_bg_color = CANVAS_BACKGROUND;
visuals.faint_bg_color = WIDGET_BACKGROUND;
visuals.override_text_color = Some(TEXT_BODY);
visuals.widgets.noninteractive.bg_fill = WIDGET_BACKGROUND;
visuals.widgets.noninteractive.fg_stroke.color = TEXT_BODY;
visuals.widgets.noninteractive.bg_stroke.color = BORDER;
visuals.widgets.inactive.bg_fill = WIDGET_BACKGROUND;
visuals.widgets.inactive.fg_stroke.color = TEXT_PRIMARY;
visuals.widgets.inactive.bg_stroke.color = BORDER;
visuals.widgets.hovered.bg_fill = WIDGET_HOVERED;
visuals.widgets.hovered.fg_stroke.color = TEXT_PRIMARY;
visuals.widgets.hovered.bg_stroke.color = TEXT_SECONDARY;
visuals.widgets.active.bg_fill = WIDGET_ACTIVE;
visuals.widgets.active.fg_stroke.color = TEXT_PRIMARY;
visuals.widgets.active.bg_stroke.color = TEXT_PRIMARY;
visuals.widgets.open.bg_fill = WIDGET_ACTIVE;
visuals.widgets.open.fg_stroke.color = TEXT_PRIMARY;
visuals.widgets.open.bg_stroke.color = TEXT_PRIMARY;
visuals.selection.bg_fill = SELECTION;
visuals.selection.stroke.color = TEXT_HEADING;
visuals.hyperlink_color = TEXT_LINK;
visuals.warn_fg_color = TEXT_HEADING;
visuals.slider_trailing_fill = true;
visuals.window_corner_radius = egui::CornerRadius::same(2);
visuals.menu_corner_radius = egui::CornerRadius::same(2);
visuals.window_stroke.color = BORDER;
visuals.popup_shadow = Shadow {
offset: [1, 2],
blur: 10,
spread: 0,
color: Color32::from_rgba_unmultiplied(0xff, 0x5a, 0xf1, 110),
};
let mut fonts = FontDefinitions::default();
fonts.font_data.insert(
"orbitron-regular".to_owned(),
FontData::from_static(FONT_ORBITRON_REGULAR).into(),
);
fonts.font_data.insert(
"orbitron-bold".to_owned(),
FontData::from_static(FONT_ORBITRON_BOLD).into(),
);
let mut orbitron_stack = fonts
.families
.get(&FontFamily::Proportional)
.cloned()
.unwrap_or_default();
orbitron_stack.insert(0, "orbitron-regular".into());
let mut orbitron_bold_stack = fonts
.families
.get(&FontFamily::Proportional)
.cloned()
.unwrap_or_default();
orbitron_bold_stack.insert(0, "orbitron-bold".into());
fonts
.families
.insert(FontFamily::Proportional, orbitron_stack.clone());
fonts
.families
.insert(FontFamily::Name("Orbitron".into()), orbitron_stack);
fonts.families.insert(
FontFamily::Name("Orbitron-Bold".into()),
orbitron_bold_stack,
);
ctx.set_fonts(fonts);
ctx.set_visuals(visuals);
let mut style = (*ctx.style()).clone();
style.text_styles = [
(
TextStyle::Small,
FontId::new(11.0, FontFamily::Name("Orbitron".into())),
),
(
TextStyle::Body,
FontId::new(13.0, FontFamily::Name("Orbitron".into())),
),
(
TextStyle::Button,
FontId::new(13.0, FontFamily::Name("Orbitron".into())),
),
(
TextStyle::Heading,
FontId::new(18.0, FontFamily::Name("Orbitron-Bold".into())),
),
(
TextStyle::Monospace,
FontId::new(13.0, FontFamily::Monospace),
),
]
.into();
style.spacing.item_spacing = egui::vec2(6.0, 4.0);
style.spacing.button_padding = egui::vec2(6.0, 3.0);
style.spacing.indent = 16.0;
ctx.set_style(style);
}