1use std::marker::PhantomData;
2
3use crate::builder::Plot3DBuilder;
4use crate::{
5 Line3DFlags, Plot3DDataLayout, Plot3DFlags, Quad3DFlags, Scatter3DFlags, Triangle3DFlags,
6 len_i32, plot3d_spec_from, sys,
7};
8use dear_imgui_rs::Ui;
9
10use super::binding::Plot3DContextBinding;
11
12pub struct Plot3DUi<'ui> {
33 pub(crate) _ui: &'ui Ui,
34 pub(crate) binding: Plot3DContextBinding,
35}
36
37impl<'ui> Plot3DUi<'ui> {
38 pub(crate) fn with_bound_context<R>(&self, f: impl FnOnce() -> R) -> R {
39 self.binding.with_bound_context(f)
40 }
41
42 pub fn begin_plot<S: AsRef<str>>(&self, title: S) -> Plot3DBuilder<'ui> {
62 self.with_bound_context(|| Plot3DBuilder {
63 binding: self.binding.clone(),
64 ui: self._ui,
65 title: title.as_ref().into(),
66 size: None,
67 flags: Plot3DFlags::empty(),
68 _lifetime: PhantomData,
69 })
70 }
71
72 pub fn plot_line_f32<S: AsRef<str>>(
97 &self,
98 label: S,
99 xs: &[f32],
100 ys: &[f32],
101 zs: &[f32],
102 flags: Line3DFlags,
103 ) {
104 self.with_bound_context(|| {
105 if xs.len() != ys.len() || ys.len() != zs.len() {
106 return;
107 }
108 let Some(count) = len_i32(xs.len()) else {
109 return;
110 };
111 let label = label.as_ref();
112 if label.contains('\0') {
113 return;
114 }
115 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
116 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
117 sys::ImPlot3D_PlotLine_FloatPtr(
118 label_ptr,
119 xs.as_ptr(),
120 ys.as_ptr(),
121 zs.as_ptr(),
122 count,
123 spec,
124 );
125 })
126 })
127 }
128
129 pub unsafe fn plot_line_f32_raw<S: AsRef<str>>(
136 &self,
137 label: S,
138 xs: &[f32],
139 ys: &[f32],
140 zs: &[f32],
141 flags: Line3DFlags,
142 layout: Plot3DDataLayout,
143 ) {
144 self.with_bound_context(|| {
145 if xs.len() != ys.len() || ys.len() != zs.len() {
146 return;
147 }
148 let Some(count) = len_i32(xs.len()) else {
149 return;
150 };
151 let label = label.as_ref();
152 if label.contains('\0') {
153 return;
154 }
155 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
156 let spec = plot3d_spec_from(flags.bits(), layout);
157 sys::ImPlot3D_PlotLine_FloatPtr(
158 label_ptr,
159 xs.as_ptr(),
160 ys.as_ptr(),
161 zs.as_ptr(),
162 count,
163 spec,
164 );
165 })
166 })
167 }
168
169 pub fn plot_line_f64<S: AsRef<str>>(
171 &self,
172 label: S,
173 xs: &[f64],
174 ys: &[f64],
175 zs: &[f64],
176 flags: Line3DFlags,
177 ) {
178 self.with_bound_context(|| {
179 if xs.len() != ys.len() || ys.len() != zs.len() {
180 return;
181 }
182 let Some(count) = len_i32(xs.len()) else {
183 return;
184 };
185 let label = label.as_ref();
186 if label.contains('\0') {
187 return;
188 }
189 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
190 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
191 sys::ImPlot3D_PlotLine_doublePtr(
192 label_ptr,
193 xs.as_ptr(),
194 ys.as_ptr(),
195 zs.as_ptr(),
196 count,
197 spec,
198 );
199 })
200 })
201 }
202
203 pub unsafe fn plot_line_f64_raw<S: AsRef<str>>(
210 &self,
211 label: S,
212 xs: &[f64],
213 ys: &[f64],
214 zs: &[f64],
215 flags: Line3DFlags,
216 layout: Plot3DDataLayout,
217 ) {
218 self.with_bound_context(|| {
219 if xs.len() != ys.len() || ys.len() != zs.len() {
220 return;
221 }
222 let Some(count) = len_i32(xs.len()) else {
223 return;
224 };
225 let label = label.as_ref();
226 if label.contains('\0') {
227 return;
228 }
229 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
230 let spec = plot3d_spec_from(flags.bits(), layout);
231 sys::ImPlot3D_PlotLine_doublePtr(
232 label_ptr,
233 xs.as_ptr(),
234 ys.as_ptr(),
235 zs.as_ptr(),
236 count,
237 spec,
238 );
239 })
240 })
241 }
242
243 pub fn plot_scatter_f32<S: AsRef<str>>(
245 &self,
246 label: S,
247 xs: &[f32],
248 ys: &[f32],
249 zs: &[f32],
250 flags: Scatter3DFlags,
251 ) {
252 self.with_bound_context(|| {
253 if xs.len() != ys.len() || ys.len() != zs.len() {
254 return;
255 }
256 let Some(count) = len_i32(xs.len()) else {
257 return;
258 };
259 let label = label.as_ref();
260 if label.contains('\0') {
261 return;
262 }
263 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
264 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
265 sys::ImPlot3D_PlotScatter_FloatPtr(
266 label_ptr,
267 xs.as_ptr(),
268 ys.as_ptr(),
269 zs.as_ptr(),
270 count,
271 spec,
272 );
273 })
274 })
275 }
276
277 pub unsafe fn plot_scatter_f32_raw<S: AsRef<str>>(
284 &self,
285 label: S,
286 xs: &[f32],
287 ys: &[f32],
288 zs: &[f32],
289 flags: Scatter3DFlags,
290 layout: Plot3DDataLayout,
291 ) {
292 self.with_bound_context(|| {
293 if xs.len() != ys.len() || ys.len() != zs.len() {
294 return;
295 }
296 let Some(count) = len_i32(xs.len()) else {
297 return;
298 };
299 let label = label.as_ref();
300 if label.contains('\0') {
301 return;
302 }
303 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
304 let spec = plot3d_spec_from(flags.bits(), layout);
305 sys::ImPlot3D_PlotScatter_FloatPtr(
306 label_ptr,
307 xs.as_ptr(),
308 ys.as_ptr(),
309 zs.as_ptr(),
310 count,
311 spec,
312 );
313 })
314 })
315 }
316
317 pub fn plot_scatter_f64<S: AsRef<str>>(
319 &self,
320 label: S,
321 xs: &[f64],
322 ys: &[f64],
323 zs: &[f64],
324 flags: Scatter3DFlags,
325 ) {
326 self.with_bound_context(|| {
327 if xs.len() != ys.len() || ys.len() != zs.len() {
328 return;
329 }
330 let Some(count) = len_i32(xs.len()) else {
331 return;
332 };
333 let label = label.as_ref();
334 if label.contains('\0') {
335 return;
336 }
337 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
338 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
339 sys::ImPlot3D_PlotScatter_doublePtr(
340 label_ptr,
341 xs.as_ptr(),
342 ys.as_ptr(),
343 zs.as_ptr(),
344 count,
345 spec,
346 );
347 })
348 })
349 }
350
351 pub unsafe fn plot_scatter_f64_raw<S: AsRef<str>>(
358 &self,
359 label: S,
360 xs: &[f64],
361 ys: &[f64],
362 zs: &[f64],
363 flags: Scatter3DFlags,
364 layout: Plot3DDataLayout,
365 ) {
366 self.with_bound_context(|| {
367 if xs.len() != ys.len() || ys.len() != zs.len() {
368 return;
369 }
370 let Some(count) = len_i32(xs.len()) else {
371 return;
372 };
373 let label = label.as_ref();
374 if label.contains('\0') {
375 return;
376 }
377 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
378 let spec = plot3d_spec_from(flags.bits(), layout);
379 sys::ImPlot3D_PlotScatter_doublePtr(
380 label_ptr,
381 xs.as_ptr(),
382 ys.as_ptr(),
383 zs.as_ptr(),
384 count,
385 spec,
386 );
387 })
388 })
389 }
390
391 pub fn plot_triangles_f32<S: AsRef<str>>(
393 &self,
394 label: S,
395 xs: &[f32],
396 ys: &[f32],
397 zs: &[f32],
398 flags: Triangle3DFlags,
399 ) {
400 self.with_bound_context(|| {
401 if xs.len() != ys.len() || ys.len() != zs.len() {
402 return;
403 }
404 let Some(count) = len_i32(xs.len()) else {
405 return;
406 };
407 let label = label.as_ref();
408 if label.contains('\0') {
409 return;
410 }
411 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
412 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
413 sys::ImPlot3D_PlotTriangle_FloatPtr(
414 label_ptr,
415 xs.as_ptr(),
416 ys.as_ptr(),
417 zs.as_ptr(),
418 count,
419 spec,
420 );
421 })
422 })
423 }
424
425 pub unsafe fn plot_triangles_f32_raw<S: AsRef<str>>(
432 &self,
433 label: S,
434 xs: &[f32],
435 ys: &[f32],
436 zs: &[f32],
437 flags: Triangle3DFlags,
438 layout: Plot3DDataLayout,
439 ) {
440 self.with_bound_context(|| {
441 if xs.len() != ys.len() || ys.len() != zs.len() {
442 return;
443 }
444 let Some(count) = len_i32(xs.len()) else {
445 return;
446 };
447 let label = label.as_ref();
448 if label.contains('\0') {
449 return;
450 }
451 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
452 let spec = plot3d_spec_from(flags.bits(), layout);
453 sys::ImPlot3D_PlotTriangle_FloatPtr(
454 label_ptr,
455 xs.as_ptr(),
456 ys.as_ptr(),
457 zs.as_ptr(),
458 count,
459 spec,
460 );
461 })
462 })
463 }
464
465 pub fn plot_quads_f32<S: AsRef<str>>(
467 &self,
468 label: S,
469 xs: &[f32],
470 ys: &[f32],
471 zs: &[f32],
472 flags: Quad3DFlags,
473 ) {
474 self.with_bound_context(|| {
475 if xs.len() != ys.len() || ys.len() != zs.len() {
476 return;
477 }
478 let Some(count) = len_i32(xs.len()) else {
479 return;
480 };
481 let label = label.as_ref();
482 if label.contains('\0') {
483 return;
484 }
485 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
486 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
487 sys::ImPlot3D_PlotQuad_FloatPtr(
488 label_ptr,
489 xs.as_ptr(),
490 ys.as_ptr(),
491 zs.as_ptr(),
492 count,
493 spec,
494 );
495 })
496 })
497 }
498
499 pub unsafe fn plot_quads_f32_raw<S: AsRef<str>>(
506 &self,
507 label: S,
508 xs: &[f32],
509 ys: &[f32],
510 zs: &[f32],
511 flags: Quad3DFlags,
512 layout: Plot3DDataLayout,
513 ) {
514 self.with_bound_context(|| {
515 if xs.len() != ys.len() || ys.len() != zs.len() {
516 return;
517 }
518 let Some(count) = len_i32(xs.len()) else {
519 return;
520 };
521 let label = label.as_ref();
522 if label.contains('\0') {
523 return;
524 }
525 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
526 let spec = plot3d_spec_from(flags.bits(), layout);
527 sys::ImPlot3D_PlotQuad_FloatPtr(
528 label_ptr,
529 xs.as_ptr(),
530 ys.as_ptr(),
531 zs.as_ptr(),
532 count,
533 spec,
534 );
535 })
536 })
537 }
538
539 pub fn plot_triangles_f64<S: AsRef<str>>(
541 &self,
542 label: S,
543 xs: &[f64],
544 ys: &[f64],
545 zs: &[f64],
546 flags: Triangle3DFlags,
547 ) {
548 self.with_bound_context(|| {
549 if xs.len() != ys.len() || ys.len() != zs.len() {
550 return;
551 }
552 let Some(count) = len_i32(xs.len()) else {
553 return;
554 };
555 let label = label.as_ref();
556 if label.contains('\0') {
557 return;
558 }
559 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
560 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
561 sys::ImPlot3D_PlotTriangle_doublePtr(
562 label_ptr,
563 xs.as_ptr(),
564 ys.as_ptr(),
565 zs.as_ptr(),
566 count,
567 spec,
568 );
569 })
570 })
571 }
572
573 pub unsafe fn plot_triangles_f64_raw<S: AsRef<str>>(
580 &self,
581 label: S,
582 xs: &[f64],
583 ys: &[f64],
584 zs: &[f64],
585 flags: Triangle3DFlags,
586 layout: Plot3DDataLayout,
587 ) {
588 self.with_bound_context(|| {
589 if xs.len() != ys.len() || ys.len() != zs.len() {
590 return;
591 }
592 let Some(count) = len_i32(xs.len()) else {
593 return;
594 };
595 let label = label.as_ref();
596 if label.contains('\0') {
597 return;
598 }
599 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
600 let spec = plot3d_spec_from(flags.bits(), layout);
601 sys::ImPlot3D_PlotTriangle_doublePtr(
602 label_ptr,
603 xs.as_ptr(),
604 ys.as_ptr(),
605 zs.as_ptr(),
606 count,
607 spec,
608 );
609 })
610 })
611 }
612
613 pub fn plot_quads_f64<S: AsRef<str>>(
615 &self,
616 label: S,
617 xs: &[f64],
618 ys: &[f64],
619 zs: &[f64],
620 flags: Quad3DFlags,
621 ) {
622 self.with_bound_context(|| {
623 if xs.len() != ys.len() || ys.len() != zs.len() {
624 return;
625 }
626 let Some(count) = len_i32(xs.len()) else {
627 return;
628 };
629 let label = label.as_ref();
630 if label.contains('\0') {
631 return;
632 }
633 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
634 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
635 sys::ImPlot3D_PlotQuad_doublePtr(
636 label_ptr,
637 xs.as_ptr(),
638 ys.as_ptr(),
639 zs.as_ptr(),
640 count,
641 spec,
642 );
643 })
644 })
645 }
646
647 pub unsafe fn plot_quads_f64_raw<S: AsRef<str>>(
654 &self,
655 label: S,
656 xs: &[f64],
657 ys: &[f64],
658 zs: &[f64],
659 flags: Quad3DFlags,
660 layout: Plot3DDataLayout,
661 ) {
662 self.with_bound_context(|| {
663 if xs.len() != ys.len() || ys.len() != zs.len() {
664 return;
665 }
666 let Some(count) = len_i32(xs.len()) else {
667 return;
668 };
669 let label = label.as_ref();
670 if label.contains('\0') {
671 return;
672 }
673 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
674 let spec = plot3d_spec_from(flags.bits(), layout);
675 sys::ImPlot3D_PlotQuad_doublePtr(
676 label_ptr,
677 xs.as_ptr(),
678 ys.as_ptr(),
679 zs.as_ptr(),
680 count,
681 spec,
682 );
683 })
684 })
685 }
686}