1use eframe::egui;
2
3use crate::rect_helpers::{debug_paint, quantized_intersection, rotate};
4use crate::value_interpretation::ValueInterpretation;
5
6pub const NO_TINT: egui::Color32 = egui::Color32::WHITE;
7
8#[derive(Debug)]
9pub struct TextureRequest {
10 pub client: String,
11 pub desired_rect: egui::Rect,
12 pub tint: egui::Color32,
13 pub color_to_alpha: Option<egui::Color32>,
14 pub thresholding: Option<ValueInterpretation>,
15 pub sense: egui::Sense,
16 pub texture_options: Option<egui::TextureOptions>,
17}
18
19impl TextureRequest {
20 pub fn new(client: String, desired_rect: egui::Rect) -> TextureRequest {
21 TextureRequest {
22 client,
23 desired_rect,
24 tint: NO_TINT,
25 color_to_alpha: None,
26 thresholding: None,
27 sense: egui::Sense::hover(),
28 texture_options: None,
29 }
30 }
31
32 pub fn with_sense(mut self, sense: egui::Sense) -> TextureRequest {
33 self.sense = sense;
34 self
35 }
36
37 pub fn with_tint(mut self, tint: Option<egui::Color32>) -> TextureRequest {
38 match tint {
39 Some(tint) => {
40 self.tint = tint;
41 }
42 None => {
43 self.tint = NO_TINT;
44 }
45 }
46 self
47 }
48
49 pub fn with_color_to_alpha(mut self, color_to_alpha: Option<egui::Color32>) -> TextureRequest {
50 self.color_to_alpha = color_to_alpha;
51 self
52 }
53
54 pub fn with_thresholding(
55 mut self,
56 thresholding: Option<&ValueInterpretation>,
57 ) -> TextureRequest {
58 self.thresholding = thresholding.copied();
59 self
60 }
61
62 pub fn with_texture_options(
63 mut self,
64 texture_options: &egui::TextureOptions,
65 ) -> TextureRequest {
66 self.texture_options = Some(*texture_options);
67 self
68 }
69}
70
71#[derive(Debug)]
72pub struct RotatedCropRequest {
73 pub uncropped: TextureRequest,
74 pub visible_rect: egui::Rect,
75 pub uv: [egui::Pos2; 2],
76 pub rotation: eframe::emath::Rot2,
77 pub translation: egui::Vec2,
78 pub rotation_center_in_uv: egui::Vec2,
79 pub points_per_pixel: f32,
80}
81
82impl RotatedCropRequest {
83 fn min_crop(
87 ui: &egui::Ui,
88 image_rect: &egui::Rect,
89 rotation: &eframe::emath::Rot2,
90 translation: &egui::Vec2,
91 rotation_center_in_points: &egui::Vec2,
92 points_per_pixel: f32,
93 ) -> egui::Rect {
94 let viewport_rect = ui.clip_rect();
95 let origin_in_points = (image_rect.min - *rotation_center_in_points).to_vec2();
96
97 let rotated = rotate(&image_rect, *rotation, origin_in_points);
98 let transformed = rotated.translate(*translation);
99 debug_paint(ui, transformed, egui::Color32::RED, "transformed");
100
101 let transformed_visible = transformed.intersect(viewport_rect);
102 debug_paint(
103 ui,
104 transformed_visible,
105 egui::Color32::GOLD,
106 "transformed_visible",
107 );
108
109 let min_crop = rotate(
110 &transformed_visible.translate(-*translation),
111 rotation.inverse(),
112 origin_in_points,
113 );
114 debug_paint(ui, min_crop, egui::Color32::BLUE, "min_crop");
115
116 let visible_rect = quantized_intersection(&image_rect, &min_crop, points_per_pixel);
121 debug_paint(
122 ui,
123 visible_rect,
124 egui::Color32::GREEN,
125 "visible_rect_quantized",
126 );
127 visible_rect
128 }
129
130 pub fn from_visible(
131 ui: &egui::Ui,
132 uncropped: TextureRequest,
133 rotation: egui::emath::Rot2,
134 translation: egui::Vec2,
135 rotation_center_in_points: egui::Vec2,
136 points_per_pixel: f32,
137 crop_threshold: u32,
138 original_image_size: egui::Vec2,
139 ) -> RotatedCropRequest {
140 let image_rect = uncropped.desired_rect;
141 let visible_rect = if uncropped.desired_rect.size().max_elem() as u32 <= crop_threshold
142 || original_image_size.max_elem() as u32 <= crop_threshold
143 {
144 image_rect
146 } else {
147 Self::min_crop(
149 ui,
150 &image_rect,
151 &rotation,
152 &translation,
153 &rotation_center_in_points,
154 points_per_pixel,
155 )
156 };
157
158 RotatedCropRequest {
159 uncropped,
160 visible_rect,
161 uv: [
162 egui::Pos2::new(
163 (visible_rect.min.x - image_rect.min.x) / image_rect.width(),
164 (visible_rect.min.y - image_rect.min.y) / image_rect.height(),
165 ),
166 egui::Pos2::new(
167 (visible_rect.max.x - image_rect.min.x) / image_rect.width(),
168 (visible_rect.max.y - image_rect.min.y) / image_rect.height(),
169 ),
170 ],
171 rotation,
172 translation,
173 rotation_center_in_uv: egui::Vec2::new(
174 -(rotation_center_in_points.x + (visible_rect.min.x - image_rect.min.x))
175 / visible_rect.width(),
176 -(rotation_center_in_points.y + (visible_rect.min.y - image_rect.min.y))
177 / visible_rect.height(),
178 ),
179 points_per_pixel,
180 }
181 }
182}