diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index d728462..764a95e 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -92,12 +92,23 @@ pub fn start( NonZeroU32::new(height).unwrap(), ); - let surface = unsafe { gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() }; + let surface = unsafe { + gl_config + .display() + .create_window_surface(&gl_config, &attrs) + .unwrap() + }; - let gl_context = not_current_gl_context.take().unwrap().make_current(&surface).unwrap(); + let gl_context = not_current_gl_context + .take() + .unwrap() + .make_current(&surface) + .unwrap(); - let renderer = unsafe { OpenGl::new_from_function_cstr(|s| gl_display.get_proc_address(s) as *const _) } - .expect("Cannot create renderer"); + let renderer = unsafe { + OpenGl::new_from_function_cstr(|s| gl_display.get_proc_address(s) as *const _) + } + .expect("Cannot create renderer"); let mut canvas = Canvas::new(renderer).expect("Cannot create canvas"); canvas.set_size(width, height, window.scale_factor() as f32); diff --git a/src/helpers/perf_graph.rs b/src/helpers/perf_graph.rs index 7fb7dd7..4c50588 100644 --- a/src/helpers/perf_graph.rs +++ b/src/helpers/perf_graph.rs @@ -60,7 +60,12 @@ impl PerfGraph { text_paint.set_font_size(14.0); text_paint.set_text_align(Align::Right); text_paint.set_text_baseline(Baseline::Top); - let _ = canvas.fill_text(x + w - 5.0, y, &format!("{:.2} FPS", 1.0 / avg), &text_paint); + let _ = canvas.fill_text( + x + w - 5.0, + y, + &format!("{:.2} FPS", 1.0 / avg), + &text_paint, + ); let mut text_paint = Paint::color(Color::rgba(240, 240, 240, 200)); text_paint.set_font_size(12.0); diff --git a/src/main.rs b/src/main.rs index deb33af..89bb355 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,9 @@ -use femtovg::{renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageFlags, ImageId, Paint, Path, Renderer}; +use core::panic; + +use femtovg::{ + renderer::OpenGl, Align, Baseline, Canvas, Color, FontId, ImageFlags, ImageId, Paint, Path, + Renderer, +}; use instant::Instant; use resource::resource; use winit::{ @@ -21,6 +26,8 @@ fn main() { use glutin::prelude::*; +mod roundy_math; +mod ui; fn run( mut canvas: Canvas, @@ -36,11 +43,12 @@ fn run( bold: canvas .add_font_mem(&resource!("assets/Roboto-Bold.ttf")) .expect("Cannot add font"), - light: canvas - .add_font_mem(&resource!("assets/Roboto-Light.ttf")) - .expect("Cannot add font"), }; + let beo = ui::Beo::new(); + for app in &beo.apps { + println!("{}", app.name()); + } let flags = ImageFlags::GENERATE_MIPMAPS | ImageFlags::REPEAT_X | ImageFlags::REPEAT_Y; let image_id = canvas @@ -100,7 +108,7 @@ fn run( x += 0.1; } - if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B{ + if *keycode == VirtualKeyCode::NumpadAdd || *keycode == VirtualKeyCode::B { println!("Add"); font_size += 1.0; } @@ -134,7 +142,6 @@ fn run( _ => (), }, Event::RedrawRequested(_) => { - println!("Redraw"); let dpi_factor = window.scale_factor(); let size = window.inner_size(); canvas.set_size(size.width, size.height, dpi_factor as f32); @@ -147,7 +154,8 @@ fn run( perf.update(dt); - + draw_main_menu(&mut canvas, &fonts, &beo); + /* draw_baselines(&mut canvas, &fonts, 5.0, 50.0, font_size); draw_alignments(&mut canvas, &fonts, 120.0, 200.0, font_size); //draw_paragraph(&mut canvas, &fonts, x, y, font_size, LOREM_TEXT); @@ -176,10 +184,11 @@ fn run( format!("Click to show font atlas texture. Current: {:?}", font_texture_to_show), paint, ); + */ canvas.save(); canvas.reset(); - perf.render(&mut canvas, 5.0, 5.0); + perf.render(&mut canvas, 500.0, 5.0); canvas.restore(); #[cfg(feature = "debug_inspector")] @@ -202,6 +211,50 @@ fn run( }); } +fn draw_main_menu(canvas: &mut Canvas, fonts: &Fonts, beo: &ui::Beo) { + let canvas_width = canvas.width(); + let canvas_height = canvas.height(); + + // circle is centered on the right side of the screen + let main_menu_circle = roundy_math::VirtualCircle { + center: roundy_math::Point { + x: canvas_width as f64, + y: canvas_height as f64 / 2.0 + 10., + }, + //radius: canvas_width as f64 - 30.0, + radius: 400.0, + }; + + println!("Canvas width: {}, height: {}", canvas_width, canvas_height); + + let canvas_size = roundy_math::Point { + x: canvas_width as f64, + y: canvas_height as f64, + }; + + let pts = main_menu_circle.get_equidistant_points(8, canvas_size); + for i in 0..pts.len() { + println!(">>> {:?}", pts[i]); + let mut paint = Paint::color(Color::hex("B7410E")); + paint.set_font(&[fonts.bold]); + paint.set_text_baseline(Baseline::Top); + let _ = canvas.fill_text(pts[i].x as f32, pts[i].y as f32, format!("XX {i}"), &paint); + } + + /* + let mut y = 40.0; + for app in &beo.apps { + println!("{}", app.name()); + let mut paint = Paint::color(Color::hex("B7410E")); + paint.set_font(&[fonts.bold]); + paint.set_text_baseline(Baseline::Top); + paint.set_text_align(Align::Right); + let _ = canvas.fill_text(50.0, y, app.name(), &paint); + y += 20.0; + } + */ +} + fn draw_baselines( canvas: &mut Canvas, fonts: &Fonts, @@ -209,7 +262,12 @@ fn draw_baselines( y: f32, font_size: f32, ) { - let baselines = [Baseline::Top, Baseline::Middle, Baseline::Alphabetic, Baseline::Bottom]; + let baselines = [ + Baseline::Top, + Baseline::Middle, + Baseline::Alphabetic, + Baseline::Bottom, + ]; let mut paint = Paint::color(Color::black()); paint.set_font(&[fonts.sans]); @@ -227,7 +285,9 @@ fn draw_baselines( paint.set_text_baseline(*baseline); - if let Ok(res) = canvas.fill_text(x, y, format!("{base_text} Baseline::{baseline:?}"), &paint) { + if let Ok(res) = + canvas.fill_text(x, y, format!("{base_text} Baseline::{baseline:?}"), &paint) + { //let res = canvas.fill_text(10.0, y, format!("d النص العربي جميل جدا {:?}", baseline), &paint); let mut path = Path::new(); @@ -237,7 +297,13 @@ fn draw_baselines( } } -fn draw_alignments(canvas: &mut Canvas, fonts: &Fonts, x: f32, y: f32, font_size: f32) { +fn draw_alignments( + canvas: &mut Canvas, + fonts: &Fonts, + x: f32, + y: f32, + font_size: f32, +) { let alignments = [Align::Left, Align::Center, Align::Right]; let mut path = Path::new(); @@ -252,7 +318,12 @@ fn draw_alignments(canvas: &mut Canvas, fonts: &Fonts, x: f32, y for (i, alignment) in alignments.iter().enumerate() { paint.set_text_align(*alignment); - if let Ok(res) = canvas.fill_text(x, y + i as f32 * 30.0, format!("Align::{alignment:?}"), &paint) { + if let Ok(res) = canvas.fill_text( + x, + y + i as f32 * 30.0, + format!("Align::{alignment:?}"), + &paint, + ) { let mut path = Path::new(); path.rect(res.x, res.y, res.width(), res.height()); canvas.stroke_path(&path, &Paint::color(Color::rgba(100, 100, 100, 64))); @@ -260,9 +331,16 @@ fn draw_alignments(canvas: &mut Canvas, fonts: &Fonts, x: f32, y } } -fn draw_paragraph(canvas: &mut Canvas, fonts: &Fonts, x: f32, y: f32, font_size: f32, text: &str) { +fn draw_paragraph( + canvas: &mut Canvas, + fonts: &Fonts, + x: f32, + y: f32, + font_size: f32, + text: &str, +) { let mut paint = Paint::color(Color::black()); - paint.set_font(&[fonts.light]); + paint.set_font(&[fonts.bold]); //paint.set_text_align(Align::Right); paint.set_font_size(font_size); @@ -308,7 +386,12 @@ fn draw_inc_size(canvas: &mut Canvas, fonts: &Fonts, x: f32, y: let font_metrics = canvas.measure_font(&paint).expect("Error measuring font"); - if let Ok(_res) = canvas.fill_text(x, cursor_y, "The quick brown fox jumps over the lazy dog", &paint) { + if let Ok(_res) = canvas.fill_text( + x, + cursor_y, + "The quick brown fox jumps over the lazy dog", + &paint, + ) { cursor_y += font_metrics.height(); } } @@ -353,7 +436,14 @@ fn draw_gradient_fill(canvas: &mut Canvas, fonts: &Fonts, x: f32 let _ = canvas.fill_text(x, y, "RUST", &paint); } -fn draw_image_fill(canvas: &mut Canvas, fonts: &Fonts, x: f32, y: f32, image_id: ImageId, t: f32) { +fn draw_image_fill( + canvas: &mut Canvas, + fonts: &Fonts, + x: f32, + y: f32, + image_id: ImageId, + t: f32, +) { let mut paint = Paint::color(Color::hex("#7300AB")); paint.set_line_width(3.0); let mut path = Path::new(); @@ -389,4 +479,3 @@ fn draw_complex(canvas: &mut Canvas, x: f32, y: f32, font_size: //let _ = canvas.fill_text(x, y, "اللغة العربية", &paint); //canvas.fill_text(x, y, "Traditionally, text is composed to create a readable, coherent, and visually satisfying", &paint); } - diff --git a/src/roundy_math.rs b/src/roundy_math.rs new file mode 100644 index 0000000..c821d45 --- /dev/null +++ b/src/roundy_math.rs @@ -0,0 +1,63 @@ +use std::f64::consts::PI; +//use std::f64; + +#[derive(Debug)] +pub struct Point { + pub x: f64, + pub y: f64, +} + +pub struct VirtualCircle { + pub center: Point, + // radius of the circle in pixels + pub radius: f64, +} + +impl VirtualCircle { + pub fn get_equidistant_points(&self, n: usize, viewport_size: Point) -> Vec { + // Note: this only works when the circle's origin is at the middle right of the viewport. + // because I'm not clever enough to figure out how to calculate the intersection points + // in the general case. + + println!( + "center: {:?}, radius: {}, viewport_size: {:?}", + self.center, self.radius, viewport_size + ); + // Calculate the angles at which the circle intersects with the viewport + let upper_x = self.center.x - (self.radius.powf(2.) - (0. - self.center.y).powf(2.)).sqrt(); + let lower_x = self.center.x + - (self.radius.powf(2.) - (viewport_size.y - self.center.y).powf(2.)).sqrt(); + + let upper_point = Point { x: upper_x, y: 0. }; + + let lower_point = Point { + x: lower_x, + y: viewport_size.y, + }; + + println!("up/low: {:?} {:?}", upper_point, lower_point); + + let intersection_angles = ( + (upper_point.x - self.center.x).atan2(upper_point.y - self.center.y), + (lower_point.x - self.center.x).atan2(lower_point.y - self.center.y), + ); + println!("int angles: {:?}", intersection_angles); + + let mut points = Vec::new(); + + // Calculate the angle step to distribute points evenly + let angle_step = (intersection_angles.1 - intersection_angles.0) / (n as f64); + println!("angle step: {}", angle_step); + + // Generate the points + for i in 0..n { + let theta = intersection_angles.0 + angle_step * (i as f64 + 0.5); + let x = theta.sin() * self.radius + viewport_size.x; + let y = theta.cos() * self.radius + viewport_size.y - self.center.y; + println!("x: {}, y: {}", x, y); + points.push(Point { x: x, y: y }); + } + + points + } +} diff --git a/src/ui.rs b/src/ui.rs index 3068bd1..26c8c1d 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,8 +1,8 @@ -struct Beo { - apps: Vec, +pub struct Beo { + pub apps: Vec>, } -trait App { +pub trait App { fn name(&self) -> &str; } @@ -19,6 +19,12 @@ impl App for Radio { } } -fn get_apps() -> Vec { - vec![Stotify{}, Radio{}] -} \ No newline at end of file +impl Beo { + pub fn new() -> Beo { + Beo { apps: get_apps() } + } +} + +fn get_apps() -> Vec> { + vec![Box::new(Spotify {}), Box::new(Radio {})] +}