1#![allow(
2 clippy::cast_possible_truncation,
3 clippy::cast_sign_loss,
4 clippy::as_conversions,
5 clippy::unnecessary_cast
6)]
7use crate::texture::TextureId;
8use bitflags::bitflags;
9use std::marker::PhantomData;
10
11use crate::colors::Color;
12use crate::sys;
13
14#[repr(transparent)]
18#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
19pub struct ImColor32(u32);
20
21impl ImColor32 {
22 pub const BLACK: Self = Self(0xff_00_00_00);
24 pub const WHITE: Self = Self(0xff_ff_ff_ff);
26 pub const TRANSPARENT: Self = Self(0);
28
29 #[inline]
31 pub const fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
32 Self(((a as u32) << 24) | (r as u32) | ((g as u32) << 8) | ((b as u32) << 16))
33 }
34
35 #[inline]
37 pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self {
38 Self::from_rgba(r, g, b, 0xff)
39 }
40
41 pub fn from_rgba_f32s(r: f32, g: f32, b: f32, a: f32) -> Self {
43 Self::from_rgba(
44 (r.clamp(0.0, 1.0) * 255.0) as u8,
45 (g.clamp(0.0, 1.0) * 255.0) as u8,
46 (b.clamp(0.0, 1.0) * 255.0) as u8,
47 (a.clamp(0.0, 1.0) * 255.0) as u8,
48 )
49 }
50
51 #[inline]
53 pub const fn to_bits(self) -> u32 {
54 self.0
55 }
56}
57
58impl From<Color> for ImColor32 {
59 fn from(color: Color) -> Self {
60 Self::from_rgba_f32s(color.r, color.g, color.b, color.a)
61 }
62}
63
64impl From<[f32; 4]> for ImColor32 {
65 fn from(arr: [f32; 4]) -> Self {
66 Self::from_rgba_f32s(arr[0], arr[1], arr[2], arr[3])
67 }
68}
69
70impl From<(f32, f32, f32, f32)> for ImColor32 {
71 fn from((r, g, b, a): (f32, f32, f32, f32)) -> Self {
72 Self::from_rgba_f32s(r, g, b, a)
73 }
74}
75
76impl From<[f32; 3]> for ImColor32 {
77 fn from(arr: [f32; 3]) -> Self {
78 Self::from_rgba_f32s(arr[0], arr[1], arr[2], 1.0)
79 }
80}
81
82impl From<(f32, f32, f32)> for ImColor32 {
83 fn from((r, g, b): (f32, f32, f32)) -> Self {
84 Self::from_rgba_f32s(r, g, b, 1.0)
85 }
86}
87
88impl From<ImColor32> for u32 {
89 fn from(color: ImColor32) -> Self {
90 color.0
91 }
92}
93
94impl From<u32> for ImColor32 {
95 fn from(color: u32) -> Self {
96 ImColor32(color)
97 }
98}
99
100bitflags! {
102 #[repr(transparent)]
104 pub struct DrawListFlags: i32 {
105 const NONE = sys::ImDrawListFlags_None as i32;
107 const ANTI_ALIASED_LINES = sys::ImDrawListFlags_AntiAliasedLines as i32;
109 const ANTI_ALIASED_LINES_USE_TEX = sys::ImDrawListFlags_AntiAliasedLinesUseTex as i32;
111 const ANTI_ALIASED_FILL = sys::ImDrawListFlags_AntiAliasedFill as i32;
113 const ALLOW_VTX_OFFSET = sys::ImDrawListFlags_AllowVtxOffset as i32;
115 }
116}
117
118bitflags! {
119 #[repr(transparent)]
122 pub struct DrawFlags: u32 {
123 const NONE = sys::ImDrawFlags_None as u32;
124 const CLOSED = sys::ImDrawFlags_Closed as u32;
125 const ROUND_CORNERS_TOP_LEFT = sys::ImDrawFlags_RoundCornersTopLeft as u32;
126 const ROUND_CORNERS_TOP_RIGHT = sys::ImDrawFlags_RoundCornersTopRight as u32;
127 const ROUND_CORNERS_BOT_LEFT = sys::ImDrawFlags_RoundCornersBottomLeft as u32;
128 const ROUND_CORNERS_BOT_RIGHT = sys::ImDrawFlags_RoundCornersBottomRight as u32;
129 const ROUND_CORNERS_TOP = sys::ImDrawFlags_RoundCornersTop as u32;
130 const ROUND_CORNERS_BOT = sys::ImDrawFlags_RoundCornersBottom as u32;
131 const ROUND_CORNERS_LEFT = sys::ImDrawFlags_RoundCornersLeft as u32;
132 const ROUND_CORNERS_RIGHT = sys::ImDrawFlags_RoundCornersRight as u32;
133 const ROUND_CORNERS_ALL = sys::ImDrawFlags_RoundCornersAll as u32;
134 const ROUND_CORNERS_NONE = sys::ImDrawFlags_RoundCornersNone as u32;
135 }
136}
137
138#[repr(transparent)]
143pub struct DrawList(*mut sys::ImDrawList);
144
145impl DrawList {
146 pub(crate) unsafe fn from_raw(ptr: *mut sys::ImDrawList) -> Self {
150 Self(ptr)
151 }
152
153 unsafe fn cmd_buffer(&self) -> &[sys::ImDrawCmd] {
155 unsafe {
156 if (*self.0).CmdBuffer.Size <= 0 || (*self.0).CmdBuffer.Data.is_null() {
157 return &[];
158 }
159 std::slice::from_raw_parts(
160 (*self.0).CmdBuffer.Data as *const sys::ImDrawCmd,
161 (*self.0).CmdBuffer.Size as usize,
162 )
163 }
164 }
165
166 pub fn vtx_buffer(&self) -> &[crate::render::DrawVert] {
168 unsafe {
169 if (*self.0).VtxBuffer.Size <= 0 || (*self.0).VtxBuffer.Data.is_null() {
170 return &[];
171 }
172 std::slice::from_raw_parts(
173 (*self.0).VtxBuffer.Data as *const crate::render::DrawVert,
174 (*self.0).VtxBuffer.Size as usize,
175 )
176 }
177 }
178
179 pub fn idx_buffer(&self) -> &[crate::render::DrawIdx] {
181 unsafe {
182 if (*self.0).IdxBuffer.Size <= 0 || (*self.0).IdxBuffer.Data.is_null() {
183 return &[];
184 }
185 std::slice::from_raw_parts((*self.0).IdxBuffer.Data, (*self.0).IdxBuffer.Size as usize)
186 }
187 }
188
189 pub fn commands(&self) -> DrawCmdIterator<'_> {
191 unsafe {
192 DrawCmdIterator {
193 iter: self.cmd_buffer().iter(),
194 }
195 }
196 }
197}
198
199pub struct OwnedDrawList(*mut sys::ImDrawList);
203
204impl Drop for OwnedDrawList {
205 fn drop(&mut self) {
206 unsafe { sys::ImDrawList_destroy(self.0) }
207 }
208}
209
210impl OwnedDrawList {
211 pub(crate) unsafe fn from_raw(ptr: *mut sys::ImDrawList) -> Self {
215 Self(ptr)
216 }
217
218 pub fn as_view(&self) -> DrawList {
220 DrawList(self.0)
221 }
222
223 pub fn clear_free_memory(&mut self) {
225 unsafe { sys::ImDrawList__ClearFreeMemory(self.0) }
226 }
227
228 pub fn reset_for_new_frame(&mut self) {
230 unsafe { sys::ImDrawList__ResetForNewFrame(self.0) }
231 }
232}
233
234pub struct DrawCmdIterator<'a> {
236 iter: std::slice::Iter<'a, sys::ImDrawCmd>,
237}
238
239impl Iterator for DrawCmdIterator<'_> {
240 type Item = DrawCmd;
241
242 fn next(&mut self) -> Option<Self::Item> {
243 self.iter.next().map(|cmd| {
244 let cmd_params = DrawCmdParams {
245 clip_rect: [
246 cmd.ClipRect.x,
247 cmd.ClipRect.y,
248 cmd.ClipRect.z,
249 cmd.ClipRect.w,
250 ],
251 texture_id: TextureId::from(unsafe {
252 sys::ImDrawCmd_GetTexID(cmd as *const _ as *mut sys::ImDrawCmd)
253 }),
254 vtx_offset: cmd.VtxOffset as usize,
255 idx_offset: cmd.IdxOffset as usize,
256 };
257
258 match cmd.UserCallback {
259 Some(raw_callback) if raw_callback as usize == usize::MAX => {
260 DrawCmd::ResetRenderState
261 }
262 Some(raw_callback) => DrawCmd::RawCallback {
263 callback: raw_callback,
264 raw_cmd: cmd,
265 },
266 None => DrawCmd::Elements {
267 count: cmd.ElemCount as usize,
268 cmd_params,
269 },
270 }
271 })
272 }
273}
274
275#[derive(Copy, Clone, Debug, PartialEq)]
277pub struct DrawCmdParams {
278 pub clip_rect: [f32; 4],
280 pub texture_id: TextureId,
282 pub vtx_offset: usize,
284 pub idx_offset: usize,
286}
287
288#[derive(Debug, Clone)]
290pub enum DrawCmd {
291 Elements {
293 count: usize,
295 cmd_params: DrawCmdParams,
297 },
298 ResetRenderState,
300 RawCallback {
302 callback: unsafe extern "C" fn(*const sys::ImDrawList, cmd: *const sys::ImDrawCmd),
304 raw_cmd: *const sys::ImDrawCmd,
306 },
307}
308
309enum DrawListType {
310 Window,
311 Background,
312 Foreground,
313}
314
315pub struct DrawListMut<'ui> {
321 draw_list_type: DrawListType,
322 draw_list: *mut sys::ImDrawList,
323 _phantom: PhantomData<&'ui ()>,
324}
325
326static DRAW_LIST_LOADED_WINDOW: std::sync::atomic::AtomicBool =
328 std::sync::atomic::AtomicBool::new(false);
329static DRAW_LIST_LOADED_BACKGROUND: std::sync::atomic::AtomicBool =
330 std::sync::atomic::AtomicBool::new(false);
331static DRAW_LIST_LOADED_FOREGROUND: std::sync::atomic::AtomicBool =
332 std::sync::atomic::AtomicBool::new(false);
333
334impl Drop for DrawListMut<'_> {
335 fn drop(&mut self) {
336 match self.draw_list_type {
337 DrawListType::Window => &DRAW_LIST_LOADED_WINDOW,
338 DrawListType::Background => &DRAW_LIST_LOADED_BACKGROUND,
339 DrawListType::Foreground => &DRAW_LIST_LOADED_FOREGROUND,
340 }
341 .store(false, std::sync::atomic::Ordering::Release);
342 }
343}
344
345impl DrawListMut<'_> {
346 fn lock_draw_list(t: DrawListType) {
347 let lock = match t {
348 DrawListType::Window => &DRAW_LIST_LOADED_WINDOW,
349 DrawListType::Background => &DRAW_LIST_LOADED_BACKGROUND,
350 DrawListType::Foreground => &DRAW_LIST_LOADED_FOREGROUND,
351 };
352
353 if lock
354 .compare_exchange(
355 false,
356 true,
357 std::sync::atomic::Ordering::Acquire,
358 std::sync::atomic::Ordering::Relaxed,
359 )
360 .is_err()
361 {
362 panic!(
363 "A DrawListMut is already in use! You can only have one DrawListMut in use at a time."
364 );
365 }
366 }
367
368 pub(crate) fn window(_ui: &crate::Ui) -> Self {
369 Self::lock_draw_list(DrawListType::Window);
370 Self {
371 draw_list: unsafe { sys::igGetWindowDrawList() },
372 draw_list_type: DrawListType::Window,
373 _phantom: PhantomData,
374 }
375 }
376
377 pub(crate) fn background(_ui: &crate::Ui) -> Self {
378 Self::lock_draw_list(DrawListType::Background);
379 Self {
380 draw_list: unsafe { sys::igGetBackgroundDrawList(std::ptr::null_mut()) },
381 draw_list_type: DrawListType::Background,
382 _phantom: PhantomData,
383 }
384 }
385
386 pub(crate) fn foreground(_ui: &crate::Ui) -> Self {
387 Self::lock_draw_list(DrawListType::Foreground);
388 Self {
389 draw_list: unsafe { sys::igGetForegroundDrawList_ViewportPtr(std::ptr::null_mut()) },
390 draw_list_type: DrawListType::Foreground,
391 _phantom: PhantomData,
392 }
393 }
394}
395
396impl<'ui> DrawListMut<'ui> {
398 #[doc(alias = "ChannelsSplit")]
400 pub fn channels_split<F: FnOnce(&ChannelsSplit<'ui>)>(&'ui self, channels_count: u32, f: F) {
401 unsafe { sys::ImDrawList_ChannelsSplit(self.draw_list, channels_count as i32) };
402 f(&ChannelsSplit {
403 draw_list: self,
404 channels_count,
405 });
406 unsafe { sys::ImDrawList_ChannelsMerge(self.draw_list) };
407 }
408 pub fn add_line<C>(
410 &'ui self,
411 p1: impl Into<sys::ImVec2>,
412 p2: impl Into<sys::ImVec2>,
413 c: C,
414 ) -> Line<'ui>
415 where
416 C: Into<ImColor32>,
417 {
418 Line::new(self, p1, p2, c)
419 }
420
421 pub fn add_rect<C>(
424 &'ui self,
425 p1: impl Into<sys::ImVec2>,
426 p2: impl Into<sys::ImVec2>,
427 c: C,
428 ) -> Rect<'ui>
429 where
430 C: Into<ImColor32>,
431 {
432 Rect::new(self, p1, p2, c)
433 }
434
435 #[doc(alias = "AddRectFilledMultiColor")]
437 pub fn add_rect_filled_multicolor<C1, C2, C3, C4>(
438 &self,
439 p1: impl Into<sys::ImVec2>,
440 p2: impl Into<sys::ImVec2>,
441 col_upr_left: C1,
442 col_upr_right: C2,
443 col_bot_right: C3,
444 col_bot_left: C4,
445 ) where
446 C1: Into<ImColor32>,
447 C2: Into<ImColor32>,
448 C3: Into<ImColor32>,
449 C4: Into<ImColor32>,
450 {
451 let p_min: sys::ImVec2 = p1.into();
452 let p_max: sys::ImVec2 = p2.into();
453 let c_ul: u32 = col_upr_left.into().into();
454 let c_ur: u32 = col_upr_right.into().into();
455 let c_br: u32 = col_bot_right.into().into();
456 let c_bl: u32 = col_bot_left.into().into();
457 unsafe {
458 sys::ImDrawList_AddRectFilledMultiColor(
459 self.draw_list,
460 p_min,
461 p_max,
462 c_ul,
463 c_ur,
464 c_br,
465 c_bl,
466 );
467 }
468 }
469
470 pub fn add_circle<C>(
472 &'ui self,
473 center: impl Into<sys::ImVec2>,
474 radius: f32,
475 color: C,
476 ) -> Circle<'ui>
477 where
478 C: Into<ImColor32>,
479 {
480 Circle::new(self, center, radius, color)
481 }
482
483 #[doc(alias = "AddBezier", alias = "AddBezierCubic")]
486 pub fn add_bezier_curve(
487 &'ui self,
488 pos0: impl Into<sys::ImVec2>,
489 cp0: impl Into<sys::ImVec2>,
490 cp1: impl Into<sys::ImVec2>,
491 pos1: impl Into<sys::ImVec2>,
492 color: impl Into<ImColor32>,
493 ) -> BezierCurve<'ui> {
494 BezierCurve::new(self, pos0, cp0, cp1, pos1, color)
495 }
496
497 #[doc(alias = "AddTriangleFilled", alias = "AddTriangle")]
499 pub fn add_triangle<C>(
500 &'ui self,
501 p1: impl Into<sys::ImVec2>,
502 p2: impl Into<sys::ImVec2>,
503 p3: impl Into<sys::ImVec2>,
504 c: C,
505 ) -> Triangle<'ui>
506 where
507 C: Into<ImColor32>,
508 {
509 Triangle::new(self, p1, p2, p3, c)
510 }
511
512 #[doc(alias = "AddPolyline", alias = "AddConvexPolyFilled")]
516 pub fn add_polyline<C, P>(&'ui self, points: Vec<P>, c: C) -> Polyline<'ui>
517 where
518 C: Into<ImColor32>,
519 P: Into<sys::ImVec2>,
520 {
521 Polyline::new(self, points, c)
522 }
523
524 #[doc(alias = "PathClear")]
528 pub fn path_clear(&self) {
529 unsafe {
530 let draw_list = self.draw_list;
532 (*draw_list)._Path.Size = 0;
533 }
534 }
535
536 #[doc(alias = "PathLineTo")]
538 pub fn path_line_to(&self, pos: impl Into<sys::ImVec2>) {
539 unsafe { sys::ImDrawList_PathLineTo(self.draw_list, pos.into()) }
540 }
541
542 #[doc(alias = "PathLineToMergeDuplicate")]
544 pub fn path_line_to_merge_duplicate(&self, pos: impl Into<sys::ImVec2>) {
545 unsafe { sys::ImDrawList_PathLineToMergeDuplicate(self.draw_list, pos.into()) }
546 }
547
548 #[doc(alias = "PathArcTo")]
550 pub fn path_arc_to(
551 &self,
552 center: impl Into<sys::ImVec2>,
553 radius: f32,
554 a_min: f32,
555 a_max: f32,
556 num_segments: i32,
557 ) {
558 unsafe {
559 let center_vec: sys::ImVec2 = center.into();
560 sys::ImDrawList_PathArcTo(
561 self.draw_list,
562 center_vec,
563 radius,
564 a_min,
565 a_max,
566 num_segments,
567 );
568 }
569 }
570
571 #[doc(alias = "PathArcToFast")]
573 pub fn path_arc_to_fast(
574 &self,
575 center: impl Into<sys::ImVec2>,
576 radius: f32,
577 a_min_of_12: i32,
578 a_max_of_12: i32,
579 ) {
580 unsafe {
581 let center_vec: sys::ImVec2 = center.into();
582 sys::ImDrawList_PathArcToFast(
583 self.draw_list,
584 center_vec,
585 radius,
586 a_min_of_12,
587 a_max_of_12,
588 );
589 }
590 }
591
592 #[doc(alias = "PathRect")]
594 pub fn path_rect(
595 &self,
596 rect_min: impl Into<sys::ImVec2>,
597 rect_max: impl Into<sys::ImVec2>,
598 rounding: f32,
599 flags: DrawFlags,
600 ) {
601 unsafe {
602 let min_vec: sys::ImVec2 = rect_min.into();
603 let max_vec: sys::ImVec2 = rect_max.into();
604 sys::ImDrawList_PathRect(
605 self.draw_list,
606 min_vec,
607 max_vec,
608 rounding,
609 flags.bits() as sys::ImDrawFlags,
610 );
611 }
612 }
613
614 #[doc(alias = "PathEllipticalArcTo")]
616 pub fn path_elliptical_arc_to(
617 &self,
618 center: impl Into<sys::ImVec2>,
619 radius: impl Into<sys::ImVec2>,
620 rot: f32,
621 a_min: f32,
622 a_max: f32,
623 num_segments: i32,
624 ) {
625 unsafe {
626 sys::ImDrawList_PathEllipticalArcTo(
627 self.draw_list,
628 center.into(),
629 radius.into(),
630 rot,
631 a_min,
632 a_max,
633 num_segments,
634 )
635 }
636 }
637
638 #[doc(alias = "PathBezierQuadraticCurveTo")]
640 pub fn path_bezier_quadratic_curve_to(
641 &self,
642 p2: impl Into<sys::ImVec2>,
643 p3: impl Into<sys::ImVec2>,
644 num_segments: i32,
645 ) {
646 unsafe {
647 sys::ImDrawList_PathBezierQuadraticCurveTo(
648 self.draw_list,
649 p2.into(),
650 p3.into(),
651 num_segments,
652 )
653 }
654 }
655
656 #[doc(alias = "PathBezierCubicCurveTo")]
658 pub fn path_bezier_cubic_curve_to(
659 &self,
660 p2: impl Into<sys::ImVec2>,
661 p3: impl Into<sys::ImVec2>,
662 p4: impl Into<sys::ImVec2>,
663 num_segments: i32,
664 ) {
665 unsafe {
666 sys::ImDrawList_PathBezierCubicCurveTo(
667 self.draw_list,
668 p2.into(),
669 p3.into(),
670 p4.into(),
671 num_segments,
672 )
673 }
674 }
675
676 #[doc(alias = "PathStroke")]
678 pub fn path_stroke(&self, color: impl Into<ImColor32>, flags: DrawFlags, thickness: f32) {
679 unsafe {
680 let draw_list = self.draw_list;
682 let path = &mut (*draw_list)._Path;
683
684 if path.Size > 0 {
685 sys::ImDrawList_AddPolyline(
686 self.draw_list,
687 path.Data,
688 path.Size,
689 color.into().into(),
690 flags.bits() as sys::ImDrawFlags,
691 thickness,
692 );
693 path.Size = 0; }
695 }
696 }
697
698 #[doc(alias = "PathFillConvex")]
700 pub fn path_fill_convex(&self, color: impl Into<ImColor32>) {
701 unsafe {
702 let draw_list = self.draw_list;
704 let path = &mut (*draw_list)._Path;
705
706 if path.Size > 0 {
707 sys::ImDrawList_AddConvexPolyFilled(
708 self.draw_list,
709 path.Data,
710 path.Size,
711 color.into().into(),
712 );
713 path.Size = 0; }
715 }
716 }
717
718 pub fn add_text(
720 &self,
721 pos: impl Into<sys::ImVec2>,
722 col: impl Into<ImColor32>,
723 text: impl AsRef<str>,
724 ) {
725 use std::os::raw::c_char;
726
727 let text = text.as_ref();
728 let pos: sys::ImVec2 = pos.into();
729 let col = col.into();
730
731 unsafe {
732 let start = text.as_ptr() as *const c_char;
733 let end = (start as usize + text.len()) as *const c_char;
734 sys::ImDrawList_AddText_Vec2(self.draw_list, pos, col.into(), start, end);
735 }
736 }
737
738 #[doc(alias = "AddText")]
742 pub fn add_text_with_font(
743 &self,
744 font: &crate::fonts::Font,
745 font_size: f32,
746 pos: impl Into<sys::ImVec2>,
747 col: impl Into<ImColor32>,
748 text: impl AsRef<str>,
749 wrap_width: f32,
750 cpu_fine_clip_rect: Option<[f32; 4]>,
751 ) {
752 use std::os::raw::c_char;
753 let text = text.as_ref();
754 let pos: sys::ImVec2 = pos.into();
755 let col = col.into();
756 let font_ptr = font.raw();
757
758 let clip_vec4 = cpu_fine_clip_rect.map(|r| sys::ImVec4 {
759 x: r[0],
760 y: r[1],
761 z: r[2],
762 w: r[3],
763 });
764 let clip_ptr = match clip_vec4.as_ref() {
765 Some(v) => v as *const sys::ImVec4,
766 None => std::ptr::null(),
767 };
768
769 unsafe {
770 let start = text.as_ptr() as *const c_char;
771 let end = (start as usize + text.len()) as *const c_char;
772 sys::ImDrawList_AddText_FontPtr(
773 self.draw_list,
774 font_ptr,
775 font_size,
776 pos,
777 col.into(),
778 start,
779 end,
780 wrap_width,
781 clip_ptr,
782 );
783 }
784 }
785
786 #[doc(alias = "PushTexture")]
804 pub fn push_texture(&self, texture: impl Into<crate::texture::TextureRef>) {
805 let tex_ref = texture.into().raw();
806 unsafe { sys::ImDrawList_PushTexture(self.draw_list, tex_ref) }
807 }
808
809 #[doc(alias = "PopTexture")]
811 pub fn pop_texture(&self) {
812 unsafe {
813 sys::ImDrawList_PopTexture(self.draw_list);
814 }
815 }
816
817 #[doc(alias = "PushClipRect")]
819 pub fn push_clip_rect(
820 &self,
821 clip_rect_min: impl Into<sys::ImVec2>,
822 clip_rect_max: impl Into<sys::ImVec2>,
823 intersect_with_current: bool,
824 ) {
825 unsafe {
826 sys::ImDrawList_PushClipRect(
827 self.draw_list,
828 clip_rect_min.into(),
829 clip_rect_max.into(),
830 intersect_with_current,
831 )
832 }
833 }
834
835 #[doc(alias = "PushClipRectFullScreen")]
837 pub fn push_clip_rect_full_screen(&self) {
838 unsafe { sys::ImDrawList_PushClipRectFullScreen(self.draw_list) }
839 }
840
841 #[doc(alias = "PopClipRect")]
843 pub fn pop_clip_rect(&self) {
844 unsafe { sys::ImDrawList_PopClipRect(self.draw_list) }
845 }
846
847 pub fn clip_rect_min(&self) -> [f32; 2] {
849 let mut out = sys::ImVec2 { x: 0.0, y: 0.0 };
850 unsafe { sys::ImDrawList_GetClipRectMin(&mut out as *mut sys::ImVec2, self.draw_list) };
851 out.into()
852 }
853
854 pub fn clip_rect_max(&self) -> [f32; 2] {
856 let mut out = sys::ImVec2 { x: 0.0, y: 0.0 };
857 unsafe { sys::ImDrawList_GetClipRectMax(&mut out as *mut sys::ImVec2, self.draw_list) };
858 out.into()
859 }
860
861 pub fn with_clip_rect<F>(
863 &self,
864 clip_rect_min: impl Into<sys::ImVec2>,
865 clip_rect_max: impl Into<sys::ImVec2>,
866 f: F,
867 ) where
868 F: FnOnce(),
869 {
870 self.push_clip_rect(clip_rect_min, clip_rect_max, false);
871 f();
872 self.pop_clip_rect();
873 }
874
875 #[doc(alias = "AddImage")]
877 pub fn add_image(
878 &self,
879 texture: impl Into<crate::texture::TextureRef>,
880 p_min: impl Into<sys::ImVec2>,
881 p_max: impl Into<sys::ImVec2>,
882 uv_min: impl Into<sys::ImVec2>,
883 uv_max: impl Into<sys::ImVec2>,
884 col: impl Into<ImColor32>,
885 ) {
886 let p_min: sys::ImVec2 = p_min.into();
890 let p_max: sys::ImVec2 = p_max.into();
891 let uv_min: sys::ImVec2 = uv_min.into();
892 let uv_max: sys::ImVec2 = uv_max.into();
893 let col = col.into().to_bits();
894 let tex_ref = texture.into().raw();
895 unsafe {
896 sys::ImDrawList_AddImage(self.draw_list, tex_ref, p_min, p_max, uv_min, uv_max, col)
897 }
898 }
899
900 #[doc(alias = "AddImageQuad")]
902 pub fn add_image_quad(
903 &self,
904 texture: impl Into<crate::texture::TextureRef>,
905 p1: impl Into<sys::ImVec2>,
906 p2: impl Into<sys::ImVec2>,
907 p3: impl Into<sys::ImVec2>,
908 p4: impl Into<sys::ImVec2>,
909 uv1: impl Into<sys::ImVec2>,
910 uv2: impl Into<sys::ImVec2>,
911 uv3: impl Into<sys::ImVec2>,
912 uv4: impl Into<sys::ImVec2>,
913 col: impl Into<ImColor32>,
914 ) {
915 let p1: sys::ImVec2 = p1.into();
924 let p2: sys::ImVec2 = p2.into();
925 let p3: sys::ImVec2 = p3.into();
926 let p4: sys::ImVec2 = p4.into();
927 let uv1: sys::ImVec2 = uv1.into();
928 let uv2: sys::ImVec2 = uv2.into();
929 let uv3: sys::ImVec2 = uv3.into();
930 let uv4: sys::ImVec2 = uv4.into();
931 let col = col.into().to_bits();
932 let tex_ref = texture.into().raw();
933 unsafe {
934 sys::ImDrawList_AddImageQuad(
935 self.draw_list,
936 tex_ref,
937 p1,
938 p2,
939 p3,
940 p4,
941 uv1,
942 uv2,
943 uv3,
944 uv4,
945 col,
946 )
947 }
948 }
949
950 #[doc(alias = "AddImageRounded")]
952 pub fn add_image_rounded(
953 &self,
954 texture: impl Into<crate::texture::TextureRef>,
955 p_min: impl Into<sys::ImVec2>,
956 p_max: impl Into<sys::ImVec2>,
957 uv_min: impl Into<sys::ImVec2>,
958 uv_max: impl Into<sys::ImVec2>,
959 col: impl Into<ImColor32>,
960 rounding: f32,
961 flags: DrawFlags,
962 ) {
963 let p_min: sys::ImVec2 = p_min.into();
974 let p_max: sys::ImVec2 = p_max.into();
975 let uv_min: sys::ImVec2 = uv_min.into();
976 let uv_max: sys::ImVec2 = uv_max.into();
977 let col = col.into().to_bits();
978 let tex_ref = texture.into().raw();
979 unsafe {
980 sys::ImDrawList_AddImageRounded(
981 self.draw_list,
982 tex_ref,
983 p_min,
984 p_max,
985 uv_min,
986 uv_max,
987 col,
988 rounding,
989 flags.bits() as sys::ImDrawFlags,
990 )
991 }
992 }
993
994 #[doc(alias = "AddQuad")]
996 pub fn add_quad<C>(
997 &self,
998 p1: impl Into<sys::ImVec2>,
999 p2: impl Into<sys::ImVec2>,
1000 p3: impl Into<sys::ImVec2>,
1001 p4: impl Into<sys::ImVec2>,
1002 col: C,
1003 thickness: f32,
1004 ) where
1005 C: Into<ImColor32>,
1006 {
1007 unsafe {
1008 sys::ImDrawList_AddQuad(
1009 self.draw_list,
1010 p1.into(),
1011 p2.into(),
1012 p3.into(),
1013 p4.into(),
1014 col.into().into(),
1015 thickness,
1016 )
1017 }
1018 }
1019
1020 #[doc(alias = "AddQuadFilled")]
1022 pub fn add_quad_filled<C>(
1023 &self,
1024 p1: impl Into<sys::ImVec2>,
1025 p2: impl Into<sys::ImVec2>,
1026 p3: impl Into<sys::ImVec2>,
1027 p4: impl Into<sys::ImVec2>,
1028 col: C,
1029 ) where
1030 C: Into<ImColor32>,
1031 {
1032 unsafe {
1033 sys::ImDrawList_AddQuadFilled(
1034 self.draw_list,
1035 p1.into(),
1036 p2.into(),
1037 p3.into(),
1038 p4.into(),
1039 col.into().into(),
1040 )
1041 }
1042 }
1043
1044 #[doc(alias = "AddNgon")]
1046 pub fn add_ngon<C>(
1047 &self,
1048 center: impl Into<sys::ImVec2>,
1049 radius: f32,
1050 col: C,
1051 num_segments: i32,
1052 thickness: f32,
1053 ) where
1054 C: Into<ImColor32>,
1055 {
1056 unsafe {
1057 sys::ImDrawList_AddNgon(
1058 self.draw_list,
1059 center.into(),
1060 radius,
1061 col.into().into(),
1062 num_segments,
1063 thickness,
1064 )
1065 }
1066 }
1067
1068 #[doc(alias = "AddNgonFilled")]
1070 pub fn add_ngon_filled<C>(
1071 &self,
1072 center: impl Into<sys::ImVec2>,
1073 radius: f32,
1074 col: C,
1075 num_segments: i32,
1076 ) where
1077 C: Into<ImColor32>,
1078 {
1079 unsafe {
1080 sys::ImDrawList_AddNgonFilled(
1081 self.draw_list,
1082 center.into(),
1083 radius,
1084 col.into().into(),
1085 num_segments,
1086 )
1087 }
1088 }
1089
1090 #[doc(alias = "AddEllipse")]
1092 pub fn add_ellipse<C>(
1093 &self,
1094 center: impl Into<sys::ImVec2>,
1095 radius: impl Into<sys::ImVec2>,
1096 col: C,
1097 rot: f32,
1098 num_segments: i32,
1099 thickness: f32,
1100 ) where
1101 C: Into<ImColor32>,
1102 {
1103 unsafe {
1104 sys::ImDrawList_AddEllipse(
1105 self.draw_list,
1106 center.into(),
1107 radius.into(),
1108 col.into().into(),
1109 rot,
1110 num_segments,
1111 thickness,
1112 )
1113 }
1114 }
1115
1116 #[doc(alias = "AddEllipseFilled")]
1118 pub fn add_ellipse_filled<C>(
1119 &self,
1120 center: impl Into<sys::ImVec2>,
1121 radius: impl Into<sys::ImVec2>,
1122 col: C,
1123 rot: f32,
1124 num_segments: i32,
1125 ) where
1126 C: Into<ImColor32>,
1127 {
1128 unsafe {
1129 sys::ImDrawList_AddEllipseFilled(
1130 self.draw_list,
1131 center.into(),
1132 radius.into(),
1133 col.into().into(),
1134 rot,
1135 num_segments,
1136 )
1137 }
1138 }
1139
1140 #[doc(alias = "AddBezierQuadratic")]
1142 pub fn add_bezier_quadratic<C>(
1143 &self,
1144 p1: impl Into<sys::ImVec2>,
1145 p2: impl Into<sys::ImVec2>,
1146 p3: impl Into<sys::ImVec2>,
1147 col: C,
1148 thickness: f32,
1149 num_segments: i32,
1150 ) where
1151 C: Into<ImColor32>,
1152 {
1153 unsafe {
1154 sys::ImDrawList_AddBezierQuadratic(
1155 self.draw_list,
1156 p1.into(),
1157 p2.into(),
1158 p3.into(),
1159 col.into().into(),
1160 thickness,
1161 num_segments,
1162 )
1163 }
1164 }
1165
1166 #[doc(alias = "AddConcavePolyFilled")]
1168 pub fn add_concave_poly_filled<C, P>(&self, points: &[P], col: C)
1169 where
1170 C: Into<ImColor32>,
1171 P: Copy + Into<sys::ImVec2>,
1172 {
1173 let mut buf: Vec<sys::ImVec2> = Vec::with_capacity(points.len());
1174 for p in points.iter().copied() {
1175 buf.push(p.into());
1176 }
1177 unsafe {
1178 sys::ImDrawList_AddConcavePolyFilled(
1179 self.draw_list,
1180 buf.as_ptr(),
1181 buf.len() as i32,
1182 col.into().into(),
1183 )
1184 }
1185 }
1186
1187 #[doc(alias = "PathFillConcave")]
1189 pub fn path_fill_concave(&self, color: impl Into<ImColor32>) {
1190 unsafe { sys::ImDrawList_PathFillConcave(self.draw_list, color.into().into()) }
1191 }
1192
1193 #[doc(alias = "AddCallback")]
1201 pub unsafe fn add_callback(
1202 &self,
1203 callback: sys::ImDrawCallback,
1204 userdata: *mut std::os::raw::c_void,
1205 userdata_size: usize,
1206 ) {
1207 unsafe { sys::ImDrawList_AddCallback(self.draw_list, callback, userdata, userdata_size) }
1208 }
1209
1210 #[doc(alias = "AddDrawCmd")]
1212 pub fn add_draw_cmd(&self) {
1213 unsafe { sys::ImDrawList_AddDrawCmd(self.draw_list) }
1214 }
1215
1216 #[doc(alias = "CloneOutput")]
1220 pub fn clone_output(&self) -> OwnedDrawList {
1221 unsafe { OwnedDrawList::from_raw(sys::ImDrawList_CloneOutput(self.draw_list)) }
1222 }
1223}
1224
1225pub struct ChannelsSplit<'ui> {
1227 draw_list: &'ui DrawListMut<'ui>,
1228 channels_count: u32,
1229}
1230
1231impl ChannelsSplit<'_> {
1232 #[doc(alias = "ChannelsSetCurrent")]
1234 pub fn set_current(&self, channel_index: u32) {
1235 assert!(
1236 channel_index < self.channels_count,
1237 "Channel index {} out of range {}",
1238 channel_index,
1239 self.channels_count
1240 );
1241 unsafe {
1242 sys::ImDrawList_ChannelsSetCurrent(self.draw_list.draw_list, channel_index as i32)
1243 };
1244 }
1245}
1246
1247#[must_use = "call .build() to register the callback"]
1249pub struct Callback<'ui, F> {
1250 draw_list: &'ui DrawListMut<'ui>,
1251 callback: F,
1252}
1253
1254impl<'ui, F: FnOnce() + 'static> Callback<'ui, F> {
1255 pub fn new(draw_list: &'ui DrawListMut<'_>, callback: F) -> Self {
1257 Self {
1258 draw_list,
1259 callback,
1260 }
1261 }
1262
1263 pub fn build(self) {
1265 use std::os::raw::c_void;
1266 let ptr: *mut F = Box::into_raw(Box::new(self.callback));
1268 unsafe {
1269 sys::ImDrawList_AddCallback(
1270 self.draw_list.draw_list,
1271 Some(Self::run_callback),
1272 ptr as *mut c_void,
1273 std::mem::size_of::<F>(),
1274 );
1275 }
1276 }
1277
1278 unsafe extern "C" fn run_callback(
1279 _parent_list: *const sys::ImDrawList,
1280 cmd: *const sys::ImDrawCmd,
1281 ) {
1282 let cmd = &mut *(cmd as *mut sys::ImDrawCmd);
1284 let data_ptr =
1286 (cmd.UserCallbackData as *mut u8).add(cmd.UserCallbackDataOffset as usize) as *mut F;
1287 if data_ptr.is_null() {
1288 return;
1289 }
1290 cmd.UserCallbackData = std::ptr::null_mut();
1292 cmd.UserCallbackDataSize = 0;
1293 cmd.UserCallbackDataOffset = 0;
1294 let cb = Box::from_raw(data_ptr);
1295 cb();
1296 }
1297}
1298
1299impl<'ui> DrawListMut<'ui> {
1300 pub fn add_callback_safe<F: FnOnce() + 'static>(&'ui self, callback: F) -> Callback<'ui, F> {
1303 Callback::new(self, callback)
1304 }
1305}
1306
1307impl<'ui> DrawListMut<'ui> {
1308 pub unsafe fn prim_reserve(&self, idx_count: i32, vtx_count: i32) {
1312 sys::ImDrawList_PrimReserve(self.draw_list, idx_count, vtx_count)
1313 }
1314
1315 pub unsafe fn prim_unreserve(&self, idx_count: i32, vtx_count: i32) {
1319 sys::ImDrawList_PrimUnreserve(self.draw_list, idx_count, vtx_count)
1320 }
1321
1322 pub unsafe fn prim_rect(
1326 &self,
1327 a: impl Into<sys::ImVec2>,
1328 b: impl Into<sys::ImVec2>,
1329 col: impl Into<ImColor32>,
1330 ) {
1331 sys::ImDrawList_PrimRect(self.draw_list, a.into(), b.into(), col.into().into())
1332 }
1333
1334 pub unsafe fn prim_rect_uv(
1338 &self,
1339 a: impl Into<sys::ImVec2>,
1340 b: impl Into<sys::ImVec2>,
1341 uv_a: impl Into<sys::ImVec2>,
1342 uv_b: impl Into<sys::ImVec2>,
1343 col: impl Into<ImColor32>,
1344 ) {
1345 sys::ImDrawList_PrimRectUV(
1346 self.draw_list,
1347 a.into(),
1348 b.into(),
1349 uv_a.into(),
1350 uv_b.into(),
1351 col.into().into(),
1352 )
1353 }
1354
1355 pub unsafe fn prim_quad_uv(
1359 &self,
1360 a: impl Into<sys::ImVec2>,
1361 b: impl Into<sys::ImVec2>,
1362 c: impl Into<sys::ImVec2>,
1363 d: impl Into<sys::ImVec2>,
1364 uv_a: impl Into<sys::ImVec2>,
1365 uv_b: impl Into<sys::ImVec2>,
1366 uv_c: impl Into<sys::ImVec2>,
1367 uv_d: impl Into<sys::ImVec2>,
1368 col: impl Into<ImColor32>,
1369 ) {
1370 sys::ImDrawList_PrimQuadUV(
1371 self.draw_list,
1372 a.into(),
1373 b.into(),
1374 c.into(),
1375 d.into(),
1376 uv_a.into(),
1377 uv_b.into(),
1378 uv_c.into(),
1379 uv_d.into(),
1380 col.into().into(),
1381 )
1382 }
1383
1384 pub unsafe fn prim_write_vtx(
1388 &self,
1389 pos: impl Into<sys::ImVec2>,
1390 uv: impl Into<sys::ImVec2>,
1391 col: impl Into<ImColor32>,
1392 ) {
1393 sys::ImDrawList_PrimWriteVtx(self.draw_list, pos.into(), uv.into(), col.into().into())
1394 }
1395
1396 pub unsafe fn prim_write_idx(&self, idx: sys::ImDrawIdx) {
1400 sys::ImDrawList_PrimWriteIdx(self.draw_list, idx)
1401 }
1402
1403 pub unsafe fn prim_vtx(
1407 &self,
1408 pos: impl Into<sys::ImVec2>,
1409 uv: impl Into<sys::ImVec2>,
1410 col: impl Into<ImColor32>,
1411 ) {
1412 sys::ImDrawList_PrimVtx(self.draw_list, pos.into(), uv.into(), col.into().into())
1413 }
1414}
1415
1416#[must_use = "should call .build() to draw the object"]
1418pub struct Line<'ui> {
1419 p1: [f32; 2],
1420 p2: [f32; 2],
1421 color: ImColor32,
1422 thickness: f32,
1423 draw_list: &'ui DrawListMut<'ui>,
1424}
1425
1426impl<'ui> Line<'ui> {
1427 fn new<C>(
1428 draw_list: &'ui DrawListMut<'_>,
1429 p1: impl Into<sys::ImVec2>,
1430 p2: impl Into<sys::ImVec2>,
1431 c: C,
1432 ) -> Self
1433 where
1434 C: Into<ImColor32>,
1435 {
1436 Self {
1437 p1: {
1438 let v: sys::ImVec2 = p1.into();
1439 v.into()
1440 },
1441 p2: {
1442 let v: sys::ImVec2 = p2.into();
1443 v.into()
1444 },
1445 color: c.into(),
1446 thickness: 1.0,
1447 draw_list,
1448 }
1449 }
1450
1451 pub fn thickness(mut self, thickness: f32) -> Self {
1453 self.thickness = thickness;
1454 self
1455 }
1456
1457 pub fn build(self) {
1459 unsafe {
1460 let p1 = sys::ImVec2 {
1461 x: self.p1[0],
1462 y: self.p1[1],
1463 };
1464 let p2 = sys::ImVec2 {
1465 x: self.p2[0],
1466 y: self.p2[1],
1467 };
1468 sys::ImDrawList_AddLine(
1469 self.draw_list.draw_list,
1470 p1,
1471 p2,
1472 self.color.into(),
1473 self.thickness,
1474 )
1475 }
1476 }
1477}
1478
1479#[must_use = "should call .build() to draw the object"]
1481pub struct Rect<'ui> {
1482 p1: [f32; 2],
1483 p2: [f32; 2],
1484 color: ImColor32,
1485 rounding: f32,
1486 flags: DrawFlags,
1487 thickness: f32,
1488 filled: bool,
1489 draw_list: &'ui DrawListMut<'ui>,
1490}
1491
1492impl<'ui> Rect<'ui> {
1493 fn new<C>(
1494 draw_list: &'ui DrawListMut<'_>,
1495 p1: impl Into<sys::ImVec2>,
1496 p2: impl Into<sys::ImVec2>,
1497 c: C,
1498 ) -> Self
1499 where
1500 C: Into<ImColor32>,
1501 {
1502 Self {
1503 p1: {
1504 let v: sys::ImVec2 = p1.into();
1505 v.into()
1506 },
1507 p2: {
1508 let v: sys::ImVec2 = p2.into();
1509 v.into()
1510 },
1511 color: c.into(),
1512 rounding: 0.0,
1513 flags: DrawFlags::ROUND_CORNERS_ALL,
1514 thickness: 1.0,
1515 filled: false,
1516 draw_list,
1517 }
1518 }
1519
1520 pub fn rounding(mut self, rounding: f32) -> Self {
1522 self.rounding = rounding;
1523 self
1524 }
1525
1526 pub fn thickness(mut self, thickness: f32) -> Self {
1528 self.thickness = thickness;
1529 self
1530 }
1531
1532 pub fn filled(mut self, filled: bool) -> Self {
1534 self.filled = filled;
1535 self
1536 }
1537
1538 pub fn flags(mut self, flags: DrawFlags) -> Self {
1540 self.flags = flags;
1541 self
1542 }
1543
1544 pub fn build(self) {
1546 let p1 = sys::ImVec2 {
1547 x: self.p1[0],
1548 y: self.p1[1],
1549 };
1550 let p2 = sys::ImVec2 {
1551 x: self.p2[0],
1552 y: self.p2[1],
1553 };
1554
1555 if self.filled {
1556 unsafe {
1557 sys::ImDrawList_AddRectFilled(
1558 self.draw_list.draw_list,
1559 p1,
1560 p2,
1561 self.color.into(),
1562 self.rounding,
1563 self.flags.bits() as sys::ImDrawFlags,
1564 )
1565 }
1566 } else {
1567 unsafe {
1568 sys::ImDrawList_AddRect(
1569 self.draw_list.draw_list,
1570 p1,
1571 p2,
1572 self.color.into(),
1573 self.rounding,
1574 self.flags.bits() as sys::ImDrawFlags,
1575 self.thickness,
1576 )
1577 }
1578 }
1579 }
1580}
1581
1582#[must_use = "should call .build() to draw the object"]
1584pub struct Circle<'ui> {
1585 center: [f32; 2],
1586 radius: f32,
1587 color: ImColor32,
1588 num_segments: i32,
1589 thickness: f32,
1590 filled: bool,
1591 draw_list: &'ui DrawListMut<'ui>,
1592}
1593
1594impl<'ui> Circle<'ui> {
1595 fn new<C>(
1596 draw_list: &'ui DrawListMut<'_>,
1597 center: impl Into<sys::ImVec2>,
1598 radius: f32,
1599 color: C,
1600 ) -> Self
1601 where
1602 C: Into<ImColor32>,
1603 {
1604 Self {
1605 center: {
1606 let v: sys::ImVec2 = center.into();
1607 v.into()
1608 },
1609 radius,
1610 color: color.into(),
1611 num_segments: 0, thickness: 1.0,
1613 filled: false,
1614 draw_list,
1615 }
1616 }
1617
1618 pub fn thickness(mut self, thickness: f32) -> Self {
1620 self.thickness = thickness;
1621 self
1622 }
1623
1624 pub fn filled(mut self, filled: bool) -> Self {
1626 self.filled = filled;
1627 self
1628 }
1629
1630 pub fn num_segments(mut self, num_segments: i32) -> Self {
1632 self.num_segments = num_segments;
1633 self
1634 }
1635
1636 pub fn build(self) {
1638 let center = sys::ImVec2 {
1639 x: self.center[0],
1640 y: self.center[1],
1641 };
1642
1643 if self.filled {
1644 unsafe {
1645 sys::ImDrawList_AddCircleFilled(
1646 self.draw_list.draw_list,
1647 center,
1648 self.radius,
1649 self.color.into(),
1650 self.num_segments,
1651 )
1652 }
1653 } else {
1654 unsafe {
1655 sys::ImDrawList_AddCircle(
1656 self.draw_list.draw_list,
1657 center,
1658 self.radius,
1659 self.color.into(),
1660 self.num_segments,
1661 self.thickness,
1662 )
1663 }
1664 }
1665 }
1666}
1667
1668#[must_use = "should call .build() to draw the object"]
1670pub struct BezierCurve<'ui> {
1671 pos0: [f32; 2],
1672 cp0: [f32; 2],
1673 pos1: [f32; 2],
1674 cp1: [f32; 2],
1675 color: ImColor32,
1676 thickness: f32,
1677 num_segments: Option<u32>,
1679 draw_list: &'ui DrawListMut<'ui>,
1680}
1681
1682impl<'ui> BezierCurve<'ui> {
1683 pub fn new<C>(
1685 draw_list: &'ui DrawListMut<'_>,
1686 pos0: impl Into<sys::ImVec2>,
1687 cp0: impl Into<sys::ImVec2>,
1688 cp1: impl Into<sys::ImVec2>,
1689 pos1: impl Into<sys::ImVec2>,
1690 c: C,
1691 ) -> Self
1692 where
1693 C: Into<ImColor32>,
1694 {
1695 Self {
1696 pos0: {
1697 let v: sys::ImVec2 = pos0.into();
1698 v.into()
1699 },
1700 cp0: {
1701 let v: sys::ImVec2 = cp0.into();
1702 v.into()
1703 },
1704 cp1: {
1705 let v: sys::ImVec2 = cp1.into();
1706 v.into()
1707 },
1708 pos1: {
1709 let v: sys::ImVec2 = pos1.into();
1710 v.into()
1711 },
1712 color: c.into(),
1713 thickness: 1.0,
1714 num_segments: None,
1715 draw_list,
1716 }
1717 }
1718
1719 pub fn thickness(mut self, thickness: f32) -> Self {
1721 self.thickness = thickness;
1722 self
1723 }
1724
1725 pub fn num_segments(mut self, num_segments: u32) -> Self {
1728 self.num_segments = Some(num_segments);
1729 self
1730 }
1731
1732 pub fn build(self) {
1734 unsafe {
1735 let pos0: sys::ImVec2 = self.pos0.into();
1736 let cp0: sys::ImVec2 = self.cp0.into();
1737 let cp1: sys::ImVec2 = self.cp1.into();
1738 let pos1: sys::ImVec2 = self.pos1.into();
1739
1740 sys::ImDrawList_AddBezierCubic(
1741 self.draw_list.draw_list,
1742 pos0,
1743 cp0,
1744 cp1,
1745 pos1,
1746 self.color.into(),
1747 self.thickness,
1748 self.num_segments.unwrap_or(0) as i32,
1749 )
1750 }
1751 }
1752}
1753
1754#[must_use = "should call .build() to draw the object"]
1756pub struct Polyline<'ui> {
1757 points: Vec<[f32; 2]>,
1758 thickness: f32,
1759 filled: bool,
1760 color: ImColor32,
1761 draw_list: &'ui DrawListMut<'ui>,
1762}
1763
1764impl<'ui> Polyline<'ui> {
1765 fn new<C, P>(draw_list: &'ui DrawListMut<'_>, points: Vec<P>, c: C) -> Self
1766 where
1767 C: Into<ImColor32>,
1768 P: Into<sys::ImVec2>,
1769 {
1770 Self {
1771 points: points
1772 .into_iter()
1773 .map(|p| {
1774 let v: sys::ImVec2 = p.into();
1775 v.into()
1776 })
1777 .collect(),
1778 color: c.into(),
1779 thickness: 1.0,
1780 filled: false,
1781 draw_list,
1782 }
1783 }
1784
1785 pub fn thickness(mut self, thickness: f32) -> Self {
1788 self.thickness = thickness;
1789 self
1790 }
1791
1792 pub fn filled(mut self, filled: bool) -> Self {
1794 self.filled = filled;
1795 self
1796 }
1797
1798 pub fn build(self) {
1800 if self.filled {
1801 unsafe {
1802 sys::ImDrawList_AddConvexPolyFilled(
1803 self.draw_list.draw_list,
1804 self.points.as_ptr() as *const sys::ImVec2,
1805 self.points.len() as i32,
1806 self.color.into(),
1807 )
1808 }
1809 } else {
1810 unsafe {
1811 sys::ImDrawList_AddPolyline(
1812 self.draw_list.draw_list,
1813 self.points.as_ptr() as *const sys::ImVec2,
1814 self.points.len() as i32,
1815 self.color.into(),
1816 sys::ImDrawFlags::default(),
1817 self.thickness,
1818 )
1819 }
1820 }
1821 }
1822}
1823
1824#[must_use = "should call .build() to draw the object"]
1826pub struct Triangle<'ui> {
1827 p1: [f32; 2],
1828 p2: [f32; 2],
1829 p3: [f32; 2],
1830 color: ImColor32,
1831 thickness: f32,
1832 filled: bool,
1833 draw_list: &'ui DrawListMut<'ui>,
1834}
1835
1836impl<'ui> Triangle<'ui> {
1837 fn new<C>(
1838 draw_list: &'ui DrawListMut<'_>,
1839 p1: impl Into<sys::ImVec2>,
1840 p2: impl Into<sys::ImVec2>,
1841 p3: impl Into<sys::ImVec2>,
1842 c: C,
1843 ) -> Self
1844 where
1845 C: Into<ImColor32>,
1846 {
1847 Self {
1848 p1: {
1849 let v: sys::ImVec2 = p1.into();
1850 v.into()
1851 },
1852 p2: {
1853 let v: sys::ImVec2 = p2.into();
1854 v.into()
1855 },
1856 p3: {
1857 let v: sys::ImVec2 = p3.into();
1858 v.into()
1859 },
1860 color: c.into(),
1861 thickness: 1.0,
1862 filled: false,
1863 draw_list,
1864 }
1865 }
1866
1867 pub fn thickness(mut self, thickness: f32) -> Self {
1869 self.thickness = thickness;
1870 self
1871 }
1872
1873 pub fn filled(mut self, filled: bool) -> Self {
1875 self.filled = filled;
1876 self
1877 }
1878
1879 pub fn build(self) {
1881 let p1 = sys::ImVec2 {
1882 x: self.p1[0],
1883 y: self.p1[1],
1884 };
1885 let p2 = sys::ImVec2 {
1886 x: self.p2[0],
1887 y: self.p2[1],
1888 };
1889 let p3 = sys::ImVec2 {
1890 x: self.p3[0],
1891 y: self.p3[1],
1892 };
1893
1894 if self.filled {
1895 unsafe {
1896 sys::ImDrawList_AddTriangleFilled(
1897 self.draw_list.draw_list,
1898 p1,
1899 p2,
1900 p3,
1901 self.color.into(),
1902 )
1903 }
1904 } else {
1905 unsafe {
1906 sys::ImDrawList_AddTriangle(
1907 self.draw_list.draw_list,
1908 p1,
1909 p2,
1910 p3,
1911 self.color.into(),
1912 self.thickness,
1913 )
1914 }
1915 }
1916 }
1917}