From ab4648fe42f778728b190c55b38c156b5e1d4a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Mon, 8 Jul 2024 20:35:08 +0200 Subject: [PATCH] Manually rotate rect --- .../egui/src/widgets/theme_switch/cogwheel.rs | 22 +++++----- crates/egui/src/widgets/theme_switch/mod.rs | 2 +- .../src/widgets/theme_switch/painter_ext.rs | 30 ------------- .../src/widgets/theme_switch/rotated_rect.rs | 44 +++++++++++++++++++ crates/egui/src/widgets/theme_switch/sun.rs | 13 +++--- 5 files changed, 60 insertions(+), 51 deletions(-) delete mode 100644 crates/egui/src/widgets/theme_switch/painter_ext.rs create mode 100644 crates/egui/src/widgets/theme_switch/rotated_rect.rs diff --git a/crates/egui/src/widgets/theme_switch/cogwheel.rs b/crates/egui/src/widgets/theme_switch/cogwheel.rs index 5ad0eb88619..4282f6975a8 100644 --- a/crates/egui/src/widgets/theme_switch/cogwheel.rs +++ b/crates/egui/src/widgets/theme_switch/cogwheel.rs @@ -1,7 +1,7 @@ -use super::painter_ext::PainterExt; +use super::rotated_rect::draw_rotated_rect; use crate::Painter; use emath::{vec2, Pos2, Rect, Rot2}; -use epaint::{Color32, RectShape, Rounding}; +use epaint::{Color32, Rounding}; use std::f32::consts::TAU; pub(crate) fn cogwheel(painter: &Painter, center: Pos2, radius: f32, color: Color32) { @@ -24,15 +24,13 @@ pub(crate) fn cogwheel(painter: &Painter, center: Pos2, radius: f32, color: Colo for n in 0..cogs { let cog_center = center - vec2(0., outer_radius + cog_length / 2. - thickness / 2.); let cog_size = vec2(cog_width, cog_length); - let cog = RectShape::filled( - Rect::from_center_size(cog_center, cog_size), - Rounding { - nw: cog_rounding, - ne: cog_rounding, - ..Default::default() - }, - color, - ); - painter.add_rotated(cog, Rot2::from_angle(TAU / cogs as f32 * n as f32), center); + let rotation = Rot2::from_angle(TAU / cogs as f32 * n as f32); + let rect = Rect::from_center_size(cog_center, cog_size); + let rounding = Rounding { + nw: cog_rounding, + ne: cog_rounding, + ..Default::default() + }; + draw_rotated_rect(painter, rect, rounding, color, rotation, center); } } diff --git a/crates/egui/src/widgets/theme_switch/mod.rs b/crates/egui/src/widgets/theme_switch/mod.rs index 7f33bd60065..038f2bd2ec5 100644 --- a/crates/egui/src/widgets/theme_switch/mod.rs +++ b/crates/egui/src/widgets/theme_switch/mod.rs @@ -6,7 +6,7 @@ use crate::{Painter, Response, ThemePreference, Ui, Widget}; mod arc; mod cogwheel; mod moon; -mod painter_ext; +mod rotated_rect; mod sun; #[must_use = "You should put this widget in an ui with `ui.add(widget);`"] diff --git a/crates/egui/src/widgets/theme_switch/painter_ext.rs b/crates/egui/src/widgets/theme_switch/painter_ext.rs deleted file mode 100644 index 844ac54be96..00000000000 --- a/crates/egui/src/widgets/theme_switch/painter_ext.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::layers::ShapeIdx; -use crate::{ClippedPrimitive, Context, Mesh, Painter, Pos2, Shape}; -use emath::Rot2; -use epaint::{ClippedShape, Primitive}; - -pub(crate) trait PainterExt { - fn add_rotated(&self, shape: impl Into, rot: Rot2, origin: Pos2) -> ShapeIdx; -} - -impl PainterExt for Painter { - fn add_rotated(&self, shape: impl Into, rot: Rot2, origin: Pos2) -> ShapeIdx { - let clip_rect = self.clip_rect(); - let shape = shape.into(); - let mut mesh = tesselate(self.ctx(), ClippedShape { clip_rect, shape }); - mesh.rotate(rot, origin); - self.add(mesh) - } -} - -pub(crate) fn tesselate(ctx: &Context, shape: ClippedShape) -> Mesh { - let primitives = ctx.tessellate(vec![shape], ctx.pixels_per_point()); - match primitives.into_iter().next() { - Some(ClippedPrimitive { - primitive: Primitive::Mesh(mesh), - .. - }) => mesh, - Some(_) => unreachable!(), - None => Mesh::default(), - } -} diff --git a/crates/egui/src/widgets/theme_switch/rotated_rect.rs b/crates/egui/src/widgets/theme_switch/rotated_rect.rs new file mode 100644 index 00000000000..836a7088422 --- /dev/null +++ b/crates/egui/src/widgets/theme_switch/rotated_rect.rs @@ -0,0 +1,44 @@ +use crate::Painter; +use emath::{vec2, Pos2, Rect, Rot2}; +use epaint::{Color32, PathShape, Rounding, Stroke}; + +/// Draws a rectangle with rounded corners, rotated around an origin. +pub(crate) fn draw_rotated_rect( + painter: &Painter, + rect: Rect, + rounding: impl Into, + fill: impl Into, + rot: impl Into, + origin: Pos2, +) { + let rounding = rounding.into(); + let fill = fill.into(); + let rot = rot.into(); + let safe_inset_points = safe_inset_points(rect, rot, origin, rounding); + + painter.add(PathShape::convex_polygon( + safe_inset_points.to_vec(), + fill, + Stroke::NONE, + )); + + // Nobody will notice that we're not actually drawing + // the round bits... 🤫 +} + +fn safe_inset_points(rect: Rect, rot: Rot2, origin: Pos2, rounding: Rounding) -> [Pos2; 8] { + [ + rotate(rect.left_top() + vec2(0.0, rounding.nw), rot, origin), + rotate(rect.left_top() + vec2(rounding.nw, 0.0), rot, origin), + rotate(rect.right_top() - vec2(rounding.ne, 0.0), rot, origin), + rotate(rect.right_top() + vec2(0.0, rounding.ne), rot, origin), + rotate(rect.right_bottom() - vec2(0.0, rounding.se), rot, origin), + rotate(rect.right_bottom() - vec2(rounding.se, 0.0), rot, origin), + rotate(rect.left_bottom() + vec2(rounding.sw, 0.0), rot, origin), + rotate(rect.left_bottom() - vec2(0.0, rounding.sw), rot, origin), + ] +} + +fn rotate(point: Pos2, rot: Rot2, origin: Pos2) -> Pos2 { + origin + rot * (point - origin) +} diff --git a/crates/egui/src/widgets/theme_switch/sun.rs b/crates/egui/src/widgets/theme_switch/sun.rs index a358784eb6a..25a8cb130c9 100644 --- a/crates/egui/src/widgets/theme_switch/sun.rs +++ b/crates/egui/src/widgets/theme_switch/sun.rs @@ -1,7 +1,7 @@ -use super::painter_ext::PainterExt; +use super::rotated_rect::draw_rotated_rect; use crate::Painter; use emath::{vec2, Pos2, Rect, Rot2, Vec2}; -use epaint::{Color32, RectShape, Stroke}; +use epaint::{Color32, Stroke}; use std::f32::consts::TAU; pub(crate) fn sun(painter: &Painter, center: Pos2, radius: f32, color: Color32) { @@ -18,11 +18,8 @@ pub(crate) fn sun(painter: &Painter, center: Pos2, radius: f32, color: Color32) for n in 0..rays { let ray_center = center - vec2(0., sun_radius + ray_spacing + ray_length / 2.); let ray_size = vec2(ray_radius, ray_length); - let ray = RectShape::filled( - Rect::from_center_size(ray_center, ray_size), - ray_radius, - color, - ); - clipped.add_rotated(ray, Rot2::from_angle(TAU / rays as f32 * n as f32), center); + let rect = Rect::from_center_size(ray_center, ray_size); + let rotation = Rot2::from_angle(TAU / rays as f32 * n as f32); + draw_rotated_rect(painter, rect, ray_radius / 2.0, color, rotation, center); } }