1use crate::input::{Key, MouseButton};
8use crate::{StyleColor, sys};
9use bitflags::bitflags;
10
11bitflags! {
12 #[repr(transparent)]
14 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15 pub struct HoveredFlags: i32 {
16 const NONE = sys::ImGuiHoveredFlags_None as i32;
18 const CHILD_WINDOWS = sys::ImGuiHoveredFlags_ChildWindows as i32;
20 const ROOT_WINDOW = sys::ImGuiHoveredFlags_RootWindow as i32;
22 const ANY_WINDOW = sys::ImGuiHoveredFlags_AnyWindow as i32;
24 const NO_POPUP_HIERARCHY = sys::ImGuiHoveredFlags_NoPopupHierarchy as i32;
26 const DOCK_HIERARCHY = sys::ImGuiHoveredFlags_DockHierarchy as i32;
28 const ALLOW_WHEN_BLOCKED_BY_POPUP = sys::ImGuiHoveredFlags_AllowWhenBlockedByPopup as i32;
30 const ALLOW_WHEN_BLOCKED_BY_ACTIVE_ITEM = sys::ImGuiHoveredFlags_AllowWhenBlockedByActiveItem as i32;
32 const ALLOW_WHEN_OVERLAPPED = sys::ImGuiHoveredFlags_AllowWhenOverlapped as i32;
34 const ALLOW_WHEN_DISABLED = sys::ImGuiHoveredFlags_AllowWhenDisabled as i32;
36 const NO_NAV_OVERRIDE = sys::ImGuiHoveredFlags_NoNavOverride as i32;
38 const FOR_TOOLTIP = sys::ImGuiHoveredFlags_ForTooltip as i32;
40 const STATIONARY = sys::ImGuiHoveredFlags_Stationary as i32;
42 const DELAY_NONE = sys::ImGuiHoveredFlags_DelayNone as i32;
44 const DELAY_SHORT = sys::ImGuiHoveredFlags_DelayShort as i32;
46 const DELAY_NORMAL = sys::ImGuiHoveredFlags_DelayNormal as i32;
48 const NO_SHARED_DELAY = sys::ImGuiHoveredFlags_NoSharedDelay as i32;
50 }
51}
52
53impl Default for HoveredFlags {
54 fn default() -> Self {
55 HoveredFlags::NONE
56 }
57}
58
59impl crate::ui::Ui {
61 #[doc(alias = "IsItemToggledOpen")]
67 pub fn is_item_toggled_open(&self) -> bool {
68 unsafe { sys::igIsItemToggledOpen() }
69 }
70
71 #[doc(alias = "GetItemRectMin")]
73 pub fn item_rect_min(&self) -> [f32; 2] {
74 unsafe {
75 let mut rect = sys::ImVec2 { x: 0.0, y: 0.0 };
76 sys::igGetItemRectMin(&mut rect);
77 [rect.x, rect.y]
78 }
79 }
80
81 #[doc(alias = "GetItemRectMax")]
83 pub fn item_rect_max(&self) -> [f32; 2] {
84 unsafe {
85 let mut rect = sys::ImVec2 { x: 0.0, y: 0.0 };
86 sys::igGetItemRectMax(&mut rect);
87 [rect.x, rect.y]
88 }
89 }
90
91 #[doc(alias = "IsWindowHovered")]
97 pub fn is_window_hovered(&self) -> bool {
98 unsafe { sys::igIsWindowHovered(HoveredFlags::NONE.bits()) }
99 }
100
101 #[doc(alias = "IsWindowHovered")]
103 pub fn is_window_hovered_with_flags(&self, flags: HoveredFlags) -> bool {
104 unsafe { sys::igIsWindowHovered(flags.bits()) }
105 }
106
107 #[doc(alias = "IsWindowFocused")]
109 pub fn is_window_focused(&self) -> bool {
110 unsafe { sys::igIsWindowFocused(0) }
111 }
112
113 #[doc(alias = "IsWindowAppearing")]
115 pub fn is_window_appearing(&self) -> bool {
116 unsafe { sys::igIsWindowAppearing() }
117 }
118
119 #[doc(alias = "IsWindowCollapsed")]
121 pub fn is_window_collapsed(&self) -> bool {
122 unsafe { sys::igIsWindowCollapsed() }
123 }
124
125 #[doc(alias = "GetKeyPressedAmount")]
131 pub fn get_key_pressed_amount(&self, key: Key, repeat_delay: f32, rate: f32) -> i32 {
132 unsafe { sys::igGetKeyPressedAmount(key.into(), repeat_delay, rate) }
133 }
134
135 #[doc(alias = "GetKeyName")]
137 pub fn get_key_name(&self, key: Key) -> &str {
138 unsafe {
139 let name_ptr = sys::igGetKeyName(key.into());
140 let c_str = std::ffi::CStr::from_ptr(name_ptr);
141 c_str.to_str().unwrap_or("Unknown")
142 }
143 }
144
145 #[doc(alias = "GetMouseClickedCount")]
147 pub fn get_mouse_clicked_count(&self, button: MouseButton) -> i32 {
148 unsafe { sys::igGetMouseClickedCount(button.into()) }
149 }
150
151 #[doc(alias = "GetMousePos")]
153 pub fn get_mouse_pos(&self) -> [f32; 2] {
154 unsafe {
155 let mut pos = sys::ImVec2 { x: 0.0, y: 0.0 };
156 sys::igGetMousePos(&mut pos);
157 [pos.x, pos.y]
158 }
159 }
160
161 #[doc(alias = "GetMousePosOnOpeningCurrentPopup")]
163 pub fn get_mouse_pos_on_opening_current_popup(&self) -> [f32; 2] {
164 unsafe {
165 let mut pos = sys::ImVec2 { x: 0.0, y: 0.0 };
166 sys::igGetMousePosOnOpeningCurrentPopup(&mut pos);
167 [pos.x, pos.y]
168 }
169 }
170
171 #[doc(alias = "GetMouseDragDelta")]
173 pub fn get_mouse_drag_delta(&self, button: MouseButton, lock_threshold: f32) -> [f32; 2] {
174 unsafe {
175 let mut delta = sys::ImVec2 { x: 0.0, y: 0.0 };
176 sys::igGetMouseDragDelta(&mut delta, button.into(), lock_threshold);
177 [delta.x, delta.y]
178 }
179 }
180
181 #[doc(alias = "GetIO")]
183 pub fn get_mouse_wheel(&self) -> f32 {
184 unsafe { (*sys::igGetIO_Nil()).MouseWheel }
185 }
186
187 #[doc(alias = "GetIO")]
189 pub fn get_mouse_wheel_h(&self) -> f32 {
190 unsafe { (*sys::igGetIO_Nil()).MouseWheelH }
191 }
192
193 #[doc(alias = "IsAnyMouseDown")]
195 pub fn is_any_mouse_down(&self) -> bool {
196 unsafe { sys::igIsAnyMouseDown() }
197 }
198
199 #[doc(alias = "GetTime")]
205 pub fn time(&self) -> f64 {
206 unsafe { sys::igGetTime() }
207 }
208
209 #[doc(alias = "GetFrameCount")]
211 pub fn frame_count(&self) -> i32 {
212 unsafe { sys::igGetFrameCount() }
213 }
214
215 #[doc(alias = "GetStyle")]
220 pub fn style_color(&self, style_color: StyleColor) -> [f32; 4] {
221 unsafe {
222 let style_ptr = sys::igGetStyle();
223 let colors = (*style_ptr).Colors.as_ptr();
224 let color = *colors.add(style_color as usize);
225 [color.x, color.y, color.z, color.w]
226 }
227 }
228
229 #[doc(alias = "GetStyleColorName")]
235 pub fn style_color_name(&self, style_color: StyleColor) -> &'static str {
236 unsafe {
237 let name_ptr = sys::igGetStyleColorName(style_color as sys::ImGuiCol);
238 let c_str = std::ffi::CStr::from_ptr(name_ptr);
239 c_str.to_str().unwrap_or("Unknown")
240 }
241 }
242
243 #[doc(alias = "IsRectVisible")]
245 pub fn is_rect_visible(&self, size: [f32; 2]) -> bool {
246 unsafe {
247 let size = sys::ImVec2 {
248 x: size[0],
249 y: size[1],
250 };
251 sys::igIsRectVisible_Nil(size)
252 }
253 }
254
255 #[doc(alias = "IsRectVisible")]
257 pub fn is_rect_visible_ex(&self, rect_min: [f32; 2], rect_max: [f32; 2]) -> bool {
258 unsafe {
259 let rect_min = sys::ImVec2 {
260 x: rect_min[0],
261 y: rect_min[1],
262 };
263 let rect_max = sys::ImVec2 {
264 x: rect_max[0],
265 y: rect_max[1],
266 };
267 sys::igIsRectVisible_Vec2(rect_min, rect_max)
268 }
269 }
270
271 #[doc(alias = "GetCursorScreenPos")]
275 pub fn get_cursor_screen_pos(&self) -> [f32; 2] {
276 unsafe {
277 let mut pos = sys::ImVec2 { x: 0.0, y: 0.0 };
278 sys::igGetCursorScreenPos(&mut pos);
279 [pos.x, pos.y]
280 }
281 }
282
283 #[doc(alias = "GetContentRegionAvail")]
285 pub fn get_content_region_avail(&self) -> [f32; 2] {
286 unsafe {
287 let mut size = sys::ImVec2 { x: 0.0, y: 0.0 };
288 sys::igGetContentRegionAvail(&mut size);
289 [size.x, size.y]
290 }
291 }
292
293 pub fn is_point_in_rect(
295 &self,
296 point: [f32; 2],
297 rect_min: [f32; 2],
298 rect_max: [f32; 2],
299 ) -> bool {
300 point[0] >= rect_min[0]
301 && point[0] <= rect_max[0]
302 && point[1] >= rect_min[1]
303 && point[1] <= rect_max[1]
304 }
305
306 pub fn distance(&self, p1: [f32; 2], p2: [f32; 2]) -> f32 {
308 let dx = p2[0] - p1[0];
309 let dy = p2[1] - p1[1];
310 (dx * dx + dy * dy).sqrt()
311 }
312
313 pub fn distance_squared(&self, p1: [f32; 2], p2: [f32; 2]) -> f32 {
315 let dx = p2[0] - p1[0];
316 let dy = p2[1] - p1[1];
317 dx * dx + dy * dy
318 }
319
320 pub fn line_segments_intersect(
322 &self,
323 p1: [f32; 2],
324 p2: [f32; 2],
325 p3: [f32; 2],
326 p4: [f32; 2],
327 ) -> bool {
328 let d1 = self.cross_product(
329 [p4[0] - p3[0], p4[1] - p3[1]],
330 [p1[0] - p3[0], p1[1] - p3[1]],
331 );
332 let d2 = self.cross_product(
333 [p4[0] - p3[0], p4[1] - p3[1]],
334 [p2[0] - p3[0], p2[1] - p3[1]],
335 );
336 let d3 = self.cross_product(
337 [p2[0] - p1[0], p2[1] - p1[1]],
338 [p3[0] - p1[0], p3[1] - p1[1]],
339 );
340 let d4 = self.cross_product(
341 [p2[0] - p1[0], p2[1] - p1[1]],
342 [p4[0] - p1[0], p4[1] - p1[1]],
343 );
344
345 (d1 > 0.0) != (d2 > 0.0) && (d3 > 0.0) != (d4 > 0.0)
346 }
347
348 fn cross_product(&self, v1: [f32; 2], v2: [f32; 2]) -> f32 {
350 v1[0] * v2[1] - v1[1] * v2[0]
351 }
352
353 pub fn normalize(&self, v: [f32; 2]) -> [f32; 2] {
355 let len = (v[0] * v[0] + v[1] * v[1]).sqrt();
356 if len > f32::EPSILON {
357 [v[0] / len, v[1] / len]
358 } else {
359 [0.0, 0.0]
360 }
361 }
362
363 pub fn dot_product(&self, v1: [f32; 2], v2: [f32; 2]) -> f32 {
365 v1[0] * v2[0] + v1[1] * v2[1]
366 }
367
368 pub fn angle_between_vectors(&self, v1: [f32; 2], v2: [f32; 2]) -> f32 {
370 let dot = self.dot_product(v1, v2);
371 let len1 = (v1[0] * v1[0] + v1[1] * v1[1]).sqrt();
372 let len2 = (v2[0] * v2[0] + v2[1] * v2[1]).sqrt();
373
374 if len1 > f32::EPSILON && len2 > f32::EPSILON {
375 (dot / (len1 * len2)).acos()
376 } else {
377 0.0
378 }
379 }
380
381 pub fn is_point_in_circle(&self, point: [f32; 2], center: [f32; 2], radius: f32) -> bool {
383 self.distance_squared(point, center) <= radius * radius
384 }
385
386 pub fn triangle_area(&self, p1: [f32; 2], p2: [f32; 2], p3: [f32; 2]) -> f32 {
388 let cross = self.cross_product(
389 [p2[0] - p1[0], p2[1] - p1[1]],
390 [p3[0] - p1[0], p3[1] - p1[1]],
391 );
392 cross.abs() * 0.5
393 }
394
395 #[doc(alias = "SetNextItemAllowOverlap")]
399 pub fn set_next_item_allow_overlap(&self) {
400 unsafe { sys::igSetNextItemAllowOverlap() };
401 }
402}