//! Show a custom window frame instead of the default OS window chrome decorations. #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release #![allow(rustdoc::missing_crate_level_docs)] // it's an example use eframe::egui::{self, ViewportCommand}; use eframe::epaint::Stroke; use egui::epaint::text::FontInsert; use egui::{ Atom, Button, Color32, ComboBox, CornerRadius, FontData, FontDefinitions, FontFamily, FontId, Id, RichText, TextEdit, Vec2, include_image, }; use std::ops::Deref; use std::sync::{Arc, Mutex}; use std::thread::sleep; use std::time::Duration; fn main() -> eframe::Result { let options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default() .with_decorations(false) // Hide the OS-specific "chrome" around the window .with_inner_size([400.0, 200.0]) .with_min_inner_size([400.0, 200.0]) .with_max_inner_size([400.0, 200.0]), ..Default::default() }; //let mut cli_lock: Arc>> = Arc::new(Mutex::new(None)); //let c2 = cli_lock.clone(); eframe::run_native( "Custom window frame", // unused title options, Box::new(|cc| { egui_extras::install_image_loaders(&cc.egui_ctx); let mut fonts = FontDefinitions::empty(); fonts.font_data.insert( "Inter-Regular".to_string(), Arc::new(FontData::from_static(include_bytes!("Inter-Regular.otf"))), ); fonts.font_data.insert( "Inter-SemiBold".to_string(), Arc::new(FontData::from_static(include_bytes!("Inter-SemiBold.otf"))), ); fonts .families .insert(FontFamily::Proportional, vec!["Inter-Regular".to_string()]); fonts.families.insert( FontFamily::Name("semibold".into()), vec!["Inter-SemiBold".to_string()], ); cc.egui_ctx.set_fonts(fonts); cc.egui_ctx.style_mut(|u| { u.visuals.override_text_color = Some(egui::Color32::from_hex("#cdd6f4").unwrap()); u.visuals.weak_text_color = Some(egui::Color32::from_hex("#7f849c").unwrap()); u.compact_menu_style = true; }); Ok(Box::new(MyApp { selected_server: Server { name: "US - East".to_string(), is_prod: true, url: "wss://stk.e3t.cc".to_string(), }, username: "core".to_string(), //cli_lock })) }), ) .unwrap(); //if let Some(cli) = c2.lock().as_ref().unwrap().deref() { // starkingdoms::native_entrypoint::start(cli.clone()); //} Ok(()) } struct MyApp { selected_server: Server, //cli_lock: Arc>>, username: String, } #[derive(PartialEq)] struct Server { name: String, is_prod: bool, url: String, } impl eframe::App for MyApp { fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] { egui::Rgba::TRANSPARENT.to_array() // Make sure we don't paint anything behind the rounded corners } fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { custom_window_frame(ctx, "starkingdoms", |ui| { ui.heading( RichText::new("StarKingdoms") .font(FontId::new(24.0, FontFamily::Name("semibold".into()))), ); ui.add_space(10.0); ui.style_mut().visuals.widgets.inactive.weak_bg_fill = Color32::TRANSPARENT; ui.style_mut().visuals.widgets.inactive.bg_stroke = Stroke::new(1.0, Color32::from_hex("#89b4fa").unwrap()); ui.style_mut().visuals.widgets.inactive.fg_stroke = Stroke::new(1.0, Color32::from_hex("#89b4fa").unwrap()); if ui .add(Button::new(( Atom::custom(Id::new("left-space"), Vec2::new(64.0, 24.0)), RichText::new("Launch!") .font(FontId::new(12.0, FontFamily::Name("semibold".into()))) .color(Color32::from_hex("#89b4fa").unwrap()), Atom::custom(Id::new("right-space"), Vec2::new(64.0, 24.0)), ))) .clicked() { //let cli = Cli::Client { // server: self.selected_server.url.clone(), //}; //println!("starting client with arguments: {:?}", cli); //*self.cli_lock.lock().unwrap() = Some(cli); let ctx = ctx.clone(); std::thread::spawn(move || { ctx.send_viewport_cmd(egui::ViewportCommand::Close); }); } ui.style_mut().visuals.widgets.inactive.bg_stroke = Stroke::NONE; ui.add_space(10.0); ui.style_mut().visuals.widgets.active.weak_bg_fill = Color32::TRANSPARENT; ui.style_mut().visuals.widgets.hovered.weak_bg_fill = Color32::TRANSPARENT; ui.vertical(|ui| { ui.horizontal(|ui| { ui.label(RichText::new("joining as").size(10.0).weak()); ui.add( TextEdit::singleline(&mut self.username) .text_color(Color32::from_hex("#89b4fa").unwrap()) .font(FontId::new(10.0, FontFamily::Name("semibold".into()))), ); }); ui.horizontal(|ui| { ui.label(RichText::new("connecting to").size(10.0).weak()); let servers = vec![ Server { name: "US - East".to_string(), is_prod: true, url: "wss://stk.e3t.cc".to_string(), }, Server { name: "Local Development".to_string(), is_prod: false, url: "ws://localhost:5151".to_string(), }, ]; ComboBox::new("combobox", "") .selected_text(match self.selected_server.is_prod { true => srv_string(&self.selected_server.name), false => nonprod_srv_string(&self.selected_server.name), }) .icon(|_, _, _, _| {}) .show_ui(ui, |ui| { for srv in servers { let s = match srv.is_prod { true => srv_string(&srv.name), false => nonprod_srv_string(&srv.name), }; ui.selectable_value(&mut self.selected_server, srv, s); } }); }); }); }); } } fn custom_window_frame(ctx: &egui::Context, title: &str, add_contents: impl FnOnce(&mut egui::Ui)) { use egui::{CentralPanel, UiBuilder}; let panel_frame = egui::Frame::new() .fill(ctx.style().visuals.window_fill()) .corner_radius(10); CentralPanel::default().frame(panel_frame).show(ctx, |ui| { egui::Image::new(egui::include_image!("../bg.png")).paint_at(ui, ui.ctx().screen_rect()); //ui.image(include_image!("bg.png")); let app_rect = ui.max_rect(); // Add the contents: let content_rect = app_rect.shrink(8.0); let mut content_ui = ui.new_child(UiBuilder::new().max_rect(content_rect)); add_contents(&mut content_ui); }); } fn srv_string(lbl: &str) -> RichText { RichText::new(lbl) .color(Color32::from_hex("#89b4fa").unwrap()) .font(FontId::new(10.0, FontFamily::Name("semibold".into()))) } fn nonprod_srv_string(lbl: &str) -> RichText { RichText::new(format!("⚠ {lbl}")) .color(Color32::from_hex("#f9e2af").unwrap()) .font(FontId::new(10.0, FontFamily::Name("semibold".into()))) }