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 pub(crate) imgui_alive: Option<dear_imgui_rs::ContextAliveToken>,
36}
37
38impl<'ui> Plot3DUi<'ui> {
39 pub(crate) fn bind(&self) -> super::binding::Plot3DContextBindingGuard {
40 if let Some(alive) = &self.imgui_alive {
41 assert!(
42 alive.is_alive(),
43 "dear-implot3d: ImGui context has been dropped"
44 );
45 }
46 self.binding.bind()
47 }
48
49 pub fn begin_plot<S: AsRef<str>>(&self, title: S) -> Plot3DBuilder<'ui> {
69 let _guard = self.bind();
70 Plot3DBuilder {
71 binding: self.binding,
72 imgui_alive: self.imgui_alive.clone(),
73 ui: self._ui,
74 title: title.as_ref().into(),
75 size: None,
76 flags: Plot3DFlags::empty(),
77 _lifetime: PhantomData,
78 }
79 }
80
81 pub fn plot_line_f32<S: AsRef<str>>(
106 &self,
107 label: S,
108 xs: &[f32],
109 ys: &[f32],
110 zs: &[f32],
111 flags: Line3DFlags,
112 ) {
113 let _guard = self.bind();
114 if xs.len() != ys.len() || ys.len() != zs.len() {
115 return;
116 }
117 let Some(count) = len_i32(xs.len()) else {
118 return;
119 };
120 let label = label.as_ref();
121 if label.contains('\0') {
122 return;
123 }
124 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
125 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
126 sys::ImPlot3D_PlotLine_FloatPtr(
127 label_ptr,
128 xs.as_ptr(),
129 ys.as_ptr(),
130 zs.as_ptr(),
131 count,
132 spec,
133 );
134 })
135 }
136
137 pub fn plot_line_f32_raw<S: AsRef<str>>(
139 &self,
140 label: S,
141 xs: &[f32],
142 ys: &[f32],
143 zs: &[f32],
144 flags: Line3DFlags,
145 layout: Plot3DDataLayout,
146 ) {
147 let _guard = self.bind();
148 if xs.len() != ys.len() || ys.len() != zs.len() {
149 return;
150 }
151 let Some(count) = len_i32(xs.len()) else {
152 return;
153 };
154 let label = label.as_ref();
155 if label.contains('\0') {
156 return;
157 }
158 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
159 let spec = plot3d_spec_from(flags.bits(), layout);
160 sys::ImPlot3D_PlotLine_FloatPtr(
161 label_ptr,
162 xs.as_ptr(),
163 ys.as_ptr(),
164 zs.as_ptr(),
165 count,
166 spec,
167 );
168 })
169 }
170
171 pub fn plot_line_f64<S: AsRef<str>>(
173 &self,
174 label: S,
175 xs: &[f64],
176 ys: &[f64],
177 zs: &[f64],
178 flags: Line3DFlags,
179 ) {
180 let _guard = self.bind();
181 if xs.len() != ys.len() || ys.len() != zs.len() {
182 return;
183 }
184 let Some(count) = len_i32(xs.len()) else {
185 return;
186 };
187 let label = label.as_ref();
188 if label.contains('\0') {
189 return;
190 }
191 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
192 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
193 sys::ImPlot3D_PlotLine_doublePtr(
194 label_ptr,
195 xs.as_ptr(),
196 ys.as_ptr(),
197 zs.as_ptr(),
198 count,
199 spec,
200 );
201 })
202 }
203
204 pub fn plot_line_f64_raw<S: AsRef<str>>(
206 &self,
207 label: S,
208 xs: &[f64],
209 ys: &[f64],
210 zs: &[f64],
211 flags: Line3DFlags,
212 layout: Plot3DDataLayout,
213 ) {
214 let _guard = self.bind();
215 if xs.len() != ys.len() || ys.len() != zs.len() {
216 return;
217 }
218 let Some(count) = len_i32(xs.len()) else {
219 return;
220 };
221 let label = label.as_ref();
222 if label.contains('\0') {
223 return;
224 }
225 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
226 let spec = plot3d_spec_from(flags.bits(), layout);
227 sys::ImPlot3D_PlotLine_doublePtr(
228 label_ptr,
229 xs.as_ptr(),
230 ys.as_ptr(),
231 zs.as_ptr(),
232 count,
233 spec,
234 );
235 })
236 }
237
238 pub fn plot_scatter_f32<S: AsRef<str>>(
240 &self,
241 label: S,
242 xs: &[f32],
243 ys: &[f32],
244 zs: &[f32],
245 flags: Scatter3DFlags,
246 ) {
247 let _guard = self.bind();
248 if xs.len() != ys.len() || ys.len() != zs.len() {
249 return;
250 }
251 let Some(count) = len_i32(xs.len()) else {
252 return;
253 };
254 let label = label.as_ref();
255 if label.contains('\0') {
256 return;
257 }
258 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
259 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
260 sys::ImPlot3D_PlotScatter_FloatPtr(
261 label_ptr,
262 xs.as_ptr(),
263 ys.as_ptr(),
264 zs.as_ptr(),
265 count,
266 spec,
267 );
268 })
269 }
270
271 pub fn plot_scatter_f32_raw<S: AsRef<str>>(
273 &self,
274 label: S,
275 xs: &[f32],
276 ys: &[f32],
277 zs: &[f32],
278 flags: Scatter3DFlags,
279 layout: Plot3DDataLayout,
280 ) {
281 let _guard = self.bind();
282 if xs.len() != ys.len() || ys.len() != zs.len() {
283 return;
284 }
285 let Some(count) = len_i32(xs.len()) else {
286 return;
287 };
288 let label = label.as_ref();
289 if label.contains('\0') {
290 return;
291 }
292 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
293 let spec = plot3d_spec_from(flags.bits(), layout);
294 sys::ImPlot3D_PlotScatter_FloatPtr(
295 label_ptr,
296 xs.as_ptr(),
297 ys.as_ptr(),
298 zs.as_ptr(),
299 count,
300 spec,
301 );
302 })
303 }
304
305 pub fn plot_scatter_f64<S: AsRef<str>>(
307 &self,
308 label: S,
309 xs: &[f64],
310 ys: &[f64],
311 zs: &[f64],
312 flags: Scatter3DFlags,
313 ) {
314 let _guard = self.bind();
315 if xs.len() != ys.len() || ys.len() != zs.len() {
316 return;
317 }
318 let Some(count) = len_i32(xs.len()) else {
319 return;
320 };
321 let label = label.as_ref();
322 if label.contains('\0') {
323 return;
324 }
325 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
326 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
327 sys::ImPlot3D_PlotScatter_doublePtr(
328 label_ptr,
329 xs.as_ptr(),
330 ys.as_ptr(),
331 zs.as_ptr(),
332 count,
333 spec,
334 );
335 })
336 }
337
338 pub fn plot_scatter_f64_raw<S: AsRef<str>>(
340 &self,
341 label: S,
342 xs: &[f64],
343 ys: &[f64],
344 zs: &[f64],
345 flags: Scatter3DFlags,
346 layout: Plot3DDataLayout,
347 ) {
348 let _guard = self.bind();
349 if xs.len() != ys.len() || ys.len() != zs.len() {
350 return;
351 }
352 let Some(count) = len_i32(xs.len()) else {
353 return;
354 };
355 let label = label.as_ref();
356 if label.contains('\0') {
357 return;
358 }
359 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
360 let spec = plot3d_spec_from(flags.bits(), layout);
361 sys::ImPlot3D_PlotScatter_doublePtr(
362 label_ptr,
363 xs.as_ptr(),
364 ys.as_ptr(),
365 zs.as_ptr(),
366 count,
367 spec,
368 );
369 })
370 }
371
372 pub fn plot_triangles_f32<S: AsRef<str>>(
374 &self,
375 label: S,
376 xs: &[f32],
377 ys: &[f32],
378 zs: &[f32],
379 flags: Triangle3DFlags,
380 ) {
381 let _guard = self.bind();
382 if xs.len() != ys.len() || ys.len() != zs.len() {
383 return;
384 }
385 let Some(count) = len_i32(xs.len()) else {
386 return;
387 };
388 let label = label.as_ref();
389 if label.contains('\0') {
390 return;
391 }
392 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
393 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
394 sys::ImPlot3D_PlotTriangle_FloatPtr(
395 label_ptr,
396 xs.as_ptr(),
397 ys.as_ptr(),
398 zs.as_ptr(),
399 count,
400 spec,
401 );
402 })
403 }
404
405 pub fn plot_triangles_f32_raw<S: AsRef<str>>(
406 &self,
407 label: S,
408 xs: &[f32],
409 ys: &[f32],
410 zs: &[f32],
411 flags: Triangle3DFlags,
412 layout: Plot3DDataLayout,
413 ) {
414 let _guard = self.bind();
415 if xs.len() != ys.len() || ys.len() != zs.len() {
416 return;
417 }
418 let Some(count) = len_i32(xs.len()) else {
419 return;
420 };
421 let label = label.as_ref();
422 if label.contains('\0') {
423 return;
424 }
425 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
426 let spec = plot3d_spec_from(flags.bits(), layout);
427 sys::ImPlot3D_PlotTriangle_FloatPtr(
428 label_ptr,
429 xs.as_ptr(),
430 ys.as_ptr(),
431 zs.as_ptr(),
432 count,
433 spec,
434 );
435 })
436 }
437
438 pub fn plot_quads_f32<S: AsRef<str>>(
440 &self,
441 label: S,
442 xs: &[f32],
443 ys: &[f32],
444 zs: &[f32],
445 flags: Quad3DFlags,
446 ) {
447 let _guard = self.bind();
448 if xs.len() != ys.len() || ys.len() != zs.len() {
449 return;
450 }
451 let Some(count) = len_i32(xs.len()) else {
452 return;
453 };
454 let label = label.as_ref();
455 if label.contains('\0') {
456 return;
457 }
458 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
459 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
460 sys::ImPlot3D_PlotQuad_FloatPtr(
461 label_ptr,
462 xs.as_ptr(),
463 ys.as_ptr(),
464 zs.as_ptr(),
465 count,
466 spec,
467 );
468 })
469 }
470
471 pub fn plot_quads_f32_raw<S: AsRef<str>>(
472 &self,
473 label: S,
474 xs: &[f32],
475 ys: &[f32],
476 zs: &[f32],
477 flags: Quad3DFlags,
478 layout: Plot3DDataLayout,
479 ) {
480 let _guard = self.bind();
481 if xs.len() != ys.len() || ys.len() != zs.len() {
482 return;
483 }
484 let Some(count) = len_i32(xs.len()) else {
485 return;
486 };
487 let label = label.as_ref();
488 if label.contains('\0') {
489 return;
490 }
491 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
492 let spec = plot3d_spec_from(flags.bits(), layout);
493 sys::ImPlot3D_PlotQuad_FloatPtr(
494 label_ptr,
495 xs.as_ptr(),
496 ys.as_ptr(),
497 zs.as_ptr(),
498 count,
499 spec,
500 );
501 })
502 }
503
504 pub fn plot_triangles_f64<S: AsRef<str>>(
506 &self,
507 label: S,
508 xs: &[f64],
509 ys: &[f64],
510 zs: &[f64],
511 flags: Triangle3DFlags,
512 ) {
513 let _guard = self.bind();
514 if xs.len() != ys.len() || ys.len() != zs.len() {
515 return;
516 }
517 let Some(count) = len_i32(xs.len()) else {
518 return;
519 };
520 let label = label.as_ref();
521 if label.contains('\0') {
522 return;
523 }
524 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
525 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
526 sys::ImPlot3D_PlotTriangle_doublePtr(
527 label_ptr,
528 xs.as_ptr(),
529 ys.as_ptr(),
530 zs.as_ptr(),
531 count,
532 spec,
533 );
534 })
535 }
536
537 pub fn plot_triangles_f64_raw<S: AsRef<str>>(
538 &self,
539 label: S,
540 xs: &[f64],
541 ys: &[f64],
542 zs: &[f64],
543 flags: Triangle3DFlags,
544 layout: Plot3DDataLayout,
545 ) {
546 let _guard = self.bind();
547 if xs.len() != ys.len() || ys.len() != zs.len() {
548 return;
549 }
550 let Some(count) = len_i32(xs.len()) else {
551 return;
552 };
553 let label = label.as_ref();
554 if label.contains('\0') {
555 return;
556 }
557 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
558 let spec = plot3d_spec_from(flags.bits(), layout);
559 sys::ImPlot3D_PlotTriangle_doublePtr(
560 label_ptr,
561 xs.as_ptr(),
562 ys.as_ptr(),
563 zs.as_ptr(),
564 count,
565 spec,
566 );
567 })
568 }
569
570 pub fn plot_quads_f64<S: AsRef<str>>(
572 &self,
573 label: S,
574 xs: &[f64],
575 ys: &[f64],
576 zs: &[f64],
577 flags: Quad3DFlags,
578 ) {
579 let _guard = self.bind();
580 if xs.len() != ys.len() || ys.len() != zs.len() {
581 return;
582 }
583 let Some(count) = len_i32(xs.len()) else {
584 return;
585 };
586 let label = label.as_ref();
587 if label.contains('\0') {
588 return;
589 }
590 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
591 let spec = plot3d_spec_from(flags.bits(), Plot3DDataLayout::DEFAULT);
592 sys::ImPlot3D_PlotQuad_doublePtr(
593 label_ptr,
594 xs.as_ptr(),
595 ys.as_ptr(),
596 zs.as_ptr(),
597 count,
598 spec,
599 );
600 })
601 }
602
603 pub fn plot_quads_f64_raw<S: AsRef<str>>(
604 &self,
605 label: S,
606 xs: &[f64],
607 ys: &[f64],
608 zs: &[f64],
609 flags: Quad3DFlags,
610 layout: Plot3DDataLayout,
611 ) {
612 let _guard = self.bind();
613 if xs.len() != ys.len() || ys.len() != zs.len() {
614 return;
615 }
616 let Some(count) = len_i32(xs.len()) else {
617 return;
618 };
619 let label = label.as_ref();
620 if label.contains('\0') {
621 return;
622 }
623 dear_imgui_rs::with_scratch_txt(label, |label_ptr| unsafe {
624 let spec = plot3d_spec_from(flags.bits(), layout);
625 sys::ImPlot3D_PlotQuad_doublePtr(
626 label_ptr,
627 xs.as_ptr(),
628 ys.as_ptr(),
629 zs.as_ptr(),
630 count,
631 spec,
632 );
633 })
634 }
635}