Skip to content

Instantly share code, notes, and snippets.

@sampettersson
Created March 1, 2023 14:19
Show Gist options
  • Save sampettersson/b9cc5979592d63cd331c4fe2e61c4606 to your computer and use it in GitHub Desktop.
Save sampettersson/b9cc5979592d63cd331c4fe2e61c4606 to your computer and use it in GitHub Desktop.
A circle that is clipped to a rounded rect in EGUI
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