Add Image::rotate and Mesh::rotate (#1371)

Co-authored-by: Hunter Morgan <hmorgan@bellflight.com>
This commit is contained in:
Hunter522 2022-03-22 02:44:23 -05:00 committed by GitHub
parent 805539b50d
commit 0a400a5bcc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 2 deletions

View file

@ -4,7 +4,10 @@ use eframe::egui;
use egui_extras::RetainedImage; use egui_extras::RetainedImage;
fn main() { fn main() {
let options = eframe::NativeOptions::default(); let options = eframe::NativeOptions {
initial_window_size: Some(egui::vec2(500.0, 900.0)),
..Default::default()
};
eframe::run_native( eframe::run_native(
"Show an image with eframe/egui", "Show an image with eframe/egui",
options, options,
@ -34,6 +37,12 @@ impl eframe::App for MyApp {
ui.heading("This is an image:"); ui.heading("This is an image:");
self.image.show(ui); self.image.show(ui);
ui.heading("This is a rotated image:");
ui.add(
egui::Image::new(self.image.texture_id(ctx), self.image.size_vec2())
.rotate(45.0_f32.to_radians(), egui::Vec2::splat(0.5)),
);
ui.heading("This is an image you can click:"); ui.heading("This is an image you can click:");
ui.add(egui::ImageButton::new( ui.add(egui::ImageButton::new(
self.image.texture_id(ctx), self.image.texture_id(ctx),

View file

@ -1,4 +1,5 @@
use crate::*; use crate::*;
use emath::Rot2;
/// An widget to show an image of a given size. /// An widget to show an image of a given size.
/// ///
@ -36,6 +37,7 @@ pub struct Image {
bg_fill: Color32, bg_fill: Color32,
tint: Color32, tint: Color32,
sense: Sense, sense: Sense,
rotation: Option<(Rot2, Vec2)>,
} }
impl Image { impl Image {
@ -47,6 +49,7 @@ impl Image {
bg_fill: Default::default(), bg_fill: Default::default(),
tint: Color32::WHITE, tint: Color32::WHITE,
sense: Sense::hover(), sense: Sense::hover(),
rotation: None,
} }
} }
@ -75,6 +78,17 @@ impl Image {
self.sense = sense; self.sense = sense;
self self
} }
/// Rotate the image about an origin by some angle
///
/// Positive angle is clockwise.
/// Origin is a vector in normalized UV space ((0,0) in top-left, (1,1) bottom right).
///
/// To rotate about the center you can pass `Vec2::splat(0.5)` as the origin.
pub fn rotate(mut self, angle: f32, origin: Vec2) -> Self {
self.rotation = Some((Rot2::from_angle(angle), origin));
self
}
} }
impl Image { impl Image {
@ -88,10 +102,11 @@ impl Image {
let Self { let Self {
texture_id, texture_id,
uv, uv,
size: _, size,
bg_fill, bg_fill,
tint, tint,
sense: _, sense: _,
rotation,
} = self; } = self;
if *bg_fill != Default::default() { if *bg_fill != Default::default() {
@ -104,6 +119,9 @@ impl Image {
// TODO: builder pattern for Mesh // TODO: builder pattern for Mesh
let mut mesh = Mesh::with_texture(*texture_id); let mut mesh = Mesh::with_texture(*texture_id);
mesh.add_rect_with_uv(rect, *uv, *tint); mesh.add_rect_with_uv(rect, *uv, *tint);
if let Some((rot, origin)) = rotation {
mesh.rotate(*rot, rect.min + *origin * *size);
}
ui.painter().add(Shape::mesh(mesh)); ui.painter().add(Shape::mesh(mesh));
} }
} }

View file

@ -254,6 +254,15 @@ impl Mesh {
v.pos += delta; v.pos += delta;
} }
} }
/// Rotate by some angle about an origin, in-place.
///
/// Origin is a position in screen space.
pub fn rotate(&mut self, rot: Rot2, origin: Pos2) {
for v in &mut self.vertices {
v.pos = origin + rot * (v.pos - origin);
}
}
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------