Created
March 1, 2023 14:19
-
-
Save sampettersson/b9cc5979592d63cd331c4fe2e61c4606 to your computer and use it in GitHub Desktop.
A circle that is clipped to a rounded rect in EGUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn nearest_point_within_rounded_rect( | |
point: Pos2, | |
rect: Rect, | |
corner_radius: f32, | |
) -> Pos2 { | |
let mut x = point.x; | |
let mut y = point.y; | |
// Check if point is inside or outside the rounded corners | |
let mut in_top_left_corner = false; | |
let mut in_top_right_corner = false; | |
let mut in_bottom_left_corner = false; | |
let mut in_bottom_right_corner = false; | |
if x < rect.min.x + corner_radius && y < rect.min.y + corner_radius { | |
in_top_left_corner = true; | |
} | |
if x > rect.max.x - corner_radius && y < rect.min.y + corner_radius { | |
in_top_right_corner = true; | |
} | |
if x < rect.min.x + corner_radius && y > rect.max.y - corner_radius { | |
in_bottom_left_corner = true; | |
} | |
if x > rect.max.x - corner_radius && y > rect.max.y - corner_radius { | |
in_bottom_right_corner = true; | |
} | |
// Check if point is inside or outside the rounded corners | |
let top_left_corner = pos2(rect.min.x + corner_radius, rect.min.y + corner_radius); | |
let top_right_corner = pos2(rect.max.x - corner_radius, rect.min.y + corner_radius); | |
let bottom_left_corner = pos2(rect.min.x + corner_radius, rect.max.y - corner_radius); | |
let bottom_right_corner = pos2(rect.max.x - corner_radius, rect.max.y - corner_radius); | |
let distance_to_top_left_corner = (point - top_left_corner).length(); | |
let distance_to_top_right_corner = (point - top_right_corner).length(); | |
let distance_to_bottom_left_corner = (point - bottom_left_corner).length(); | |
let distance_to_bottom_right_corner = (point - bottom_right_corner).length(); | |
if distance_to_top_left_corner > corner_radius && in_top_left_corner { | |
let to_point = point - top_left_corner; | |
let to_point_normalized = to_point.normalized(); | |
let closest_point = top_left_corner + to_point_normalized * corner_radius; | |
return closest_point; | |
} | |
if distance_to_top_right_corner > corner_radius && in_top_right_corner { | |
let to_point = point - top_right_corner; | |
let to_point_normalized = to_point.normalized(); | |
let closest_point = top_right_corner + to_point_normalized * corner_radius; | |
return closest_point; | |
} | |
if distance_to_bottom_left_corner > corner_radius && in_bottom_left_corner { | |
let to_point = point - bottom_left_corner; | |
let to_point_normalized = to_point.normalized(); | |
let closest_point = bottom_left_corner + to_point_normalized * corner_radius; | |
return closest_point; | |
} | |
if distance_to_bottom_right_corner > corner_radius && in_bottom_right_corner { | |
let to_point = point - bottom_right_corner; | |
let to_point_normalized = to_point.normalized(); | |
let closest_point = bottom_right_corner + to_point_normalized * corner_radius; | |
return closest_point; | |
} | |
// Clamp x and y to flat edges | |
if x < rect.min.x { | |
x = rect.min.x; | |
} else if x > rect.max.x { | |
x = rect.max.x; | |
} | |
if y < rect.min.y { | |
y = rect.min.y; | |
} else if y > rect.max.y { | |
y = rect.max.y; | |
} | |
pos2(x, y) | |
} | |
fn ui(ui: &Ui) { | |
let mut mesh = Mesh::default(); | |
let mut path = epaint::tessellator::Path::default(); | |
pub const CIRCLE_128: [Vec2; 129] = [ | |
vec2(1.000000, 0.000000), | |
vec2(0.998795, 0.049068), | |
vec2(0.995185, 0.098017), | |
vec2(0.989177, 0.146730), | |
vec2(0.980785, 0.195090), | |
vec2(0.970031, 0.242980), | |
vec2(0.956940, 0.290285), | |
vec2(0.941544, 0.336890), | |
vec2(0.923880, 0.382683), | |
vec2(0.903989, 0.427555), | |
vec2(0.881921, 0.471397), | |
vec2(0.857729, 0.514103), | |
vec2(0.831470, 0.555570), | |
vec2(0.803208, 0.595699), | |
vec2(0.773010, 0.634393), | |
vec2(0.740951, 0.671559), | |
vec2(0.707107, 0.707107), | |
vec2(0.671559, 0.740951), | |
vec2(0.634393, 0.773010), | |
vec2(0.595699, 0.803208), | |
vec2(0.555570, 0.831470), | |
vec2(0.514103, 0.857729), | |
vec2(0.471397, 0.881921), | |
vec2(0.427555, 0.903989), | |
vec2(0.382683, 0.923880), | |
vec2(0.336890, 0.941544), | |
vec2(0.290285, 0.956940), | |
vec2(0.242980, 0.970031), | |
vec2(0.195090, 0.980785), | |
vec2(0.146730, 0.989177), | |
vec2(0.098017, 0.995185), | |
vec2(0.049068, 0.998795), | |
vec2(0.000000, 1.000000), | |
vec2(-0.049068, 0.998795), | |
vec2(-0.098017, 0.995185), | |
vec2(-0.146730, 0.989177), | |
vec2(-0.195090, 0.980785), | |
vec2(-0.242980, 0.970031), | |
vec2(-0.290285, 0.956940), | |
vec2(-0.336890, 0.941544), | |
vec2(-0.382683, 0.923880), | |
vec2(-0.427555, 0.903989), | |
vec2(-0.471397, 0.881921), | |
vec2(-0.514103, 0.857729), | |
vec2(-0.555570, 0.831470), | |
vec2(-0.595699, 0.803208), | |
vec2(-0.634393, 0.773010), | |
vec2(-0.671559, 0.740951), | |
vec2(-0.707107, 0.707107), | |
vec2(-0.740951, 0.671559), | |
vec2(-0.773010, 0.634393), | |
vec2(-0.803208, 0.595699), | |
vec2(-0.831470, 0.555570), | |
vec2(-0.857729, 0.514103), | |
vec2(-0.881921, 0.471397), | |
vec2(-0.903989, 0.427555), | |
vec2(-0.923880, 0.382683), | |
vec2(-0.941544, 0.336890), | |
vec2(-0.956940, 0.290285), | |
vec2(-0.970031, 0.242980), | |
vec2(-0.980785, 0.195090), | |
vec2(-0.989177, 0.146730), | |
vec2(-0.995185, 0.098017), | |
vec2(-0.998795, 0.049068), | |
vec2(-1.000000, 0.000000), | |
vec2(-0.998795, -0.049068), | |
vec2(-0.995185, -0.098017), | |
vec2(-0.989177, -0.146730), | |
vec2(-0.980785, -0.195090), | |
vec2(-0.970031, -0.242980), | |
vec2(-0.956940, -0.290285), | |
vec2(-0.941544, -0.336890), | |
vec2(-0.923880, -0.382683), | |
vec2(-0.903989, -0.427555), | |
vec2(-0.881921, -0.471397), | |
vec2(-0.857729, -0.514103), | |
vec2(-0.831470, -0.555570), | |
vec2(-0.803208, -0.595699), | |
vec2(-0.773010, -0.634393), | |
vec2(-0.740951, -0.671559), | |
vec2(-0.707107, -0.707107), | |
vec2(-0.671559, -0.740951), | |
vec2(-0.634393, -0.773010), | |
vec2(-0.595699, -0.803208), | |
vec2(-0.555570, -0.831470), | |
vec2(-0.514103, -0.857729), | |
vec2(-0.471397, -0.881921), | |
vec2(-0.427555, -0.903989), | |
vec2(-0.382683, -0.923880), | |
vec2(-0.336890, -0.941544), | |
vec2(-0.290285, -0.956940), | |
vec2(-0.242980, -0.970031), | |
vec2(-0.195090, -0.980785), | |
vec2(-0.146730, -0.989177), | |
vec2(-0.098017, -0.995185), | |
vec2(-0.049068, -0.998795), | |
vec2(-0.000000, -1.000000), | |
vec2(0.049068, -0.998795), | |
vec2(0.098017, -0.995185), | |
vec2(0.146730, -0.989177), | |
vec2(0.195090, -0.980785), | |
vec2(0.242980, -0.970031), | |
vec2(0.290285, -0.956940), | |
vec2(0.336890, -0.941544), | |
vec2(0.382683, -0.923880), | |
vec2(0.427555, -0.903989), | |
vec2(0.471397, -0.881921), | |
vec2(0.514103, -0.857729), | |
vec2(0.555570, -0.831470), | |
vec2(0.595699, -0.803208), | |
vec2(0.634393, -0.773010), | |
vec2(0.671559, -0.740951), | |
vec2(0.707107, -0.707107), | |
vec2(0.740951, -0.671559), | |
vec2(0.773010, -0.634393), | |
vec2(0.803208, -0.595699), | |
vec2(0.831470, -0.555570), | |
vec2(0.857729, -0.514103), | |
vec2(0.881921, -0.471397), | |
vec2(0.903989, -0.427555), | |
vec2(0.923880, -0.382683), | |
vec2(0.941544, -0.336890), | |
vec2(0.956940, -0.290285), | |
vec2(0.970031, -0.242980), | |
vec2(0.980785, -0.195090), | |
vec2(0.989177, -0.146730), | |
vec2(0.995185, -0.098017), | |
vec2(0.998795, -0.049068), | |
vec2(1.000000, -0.000000), | |
]; | |
let rounding = 8.0; | |
let circle_rect = Rect::new(size, size); | |
for circle_point in CIRCLE_128 { | |
let pos = circle_rect.center() + vec2(circle_rect.size().x, circle_rect.size().x) * circle_point; | |
let closest_point = nearest_point_within_rounded_rect(pos, rect, rounding); | |
path.add_point(closest_point, circle_point); | |
} | |
path.fill(0.0, Color32::BLACK.linear_multiply(0.1), &mut mesh); | |
ui.painter().with_clip_rect(rect).add(egui::Shape::mesh(mesh)); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment