1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! Particle selection utilities.
//!
//! This module provides helpers for working with particle selection,
//! particularly in egui UI callbacks.
//!
//! # Example
//!
//! ```ignore
//! use rdpe::selection::{selected_particle, selected_particle_data};
//!
//! #[derive(Particle, Clone)]
//! struct MyParticle {
//! position: Vec3,
//! velocity: Vec3,
//! energy: f32,
//! }
//!
//! Simulation::<MyParticle>::new()
//! .with_egui()
//! .with_ui(|ctx| {
//! egui::Window::new("Selection").show(ctx, |ui| {
//! if let Some(particle) = selected_particle_data::<MyParticle>(ctx) {
//! ui.label(format!("Position: {:?}", particle.position));
//! ui.label(format!("Velocity: {:?}", particle.velocity));
//! ui.label(format!("Energy: {:.2}", particle.energy));
//! } else {
//! ui.label("Click a particle to select it");
//! }
//! });
//! })
//! .run();
//! ```
use crateParticleTrait;
/// Internal wrapper for storing selection index in egui's data.
;
/// Internal wrapper for storing selection data in egui's data.
;
/// Internal wrapper for storing pending particle writes.
/// Contains (particle_index, gpu_bytes) when a particle has been edited.
>);
/// Get the currently selected particle index from an egui context.
///
/// Returns `Some(index)` if a particle is selected, `None` otherwise.
///
/// This works by reading from egui's temporary data storage, which is
/// populated by the simulation's render loop before calling your UI callback.
///
/// # Example
///
/// ```ignore
/// .with_ui(|ctx| {
/// if let Some(particle_idx) = rdpe::selection::selected_particle(ctx) {
/// // Show info about the selected particle
/// }
/// })
/// ```
/// Get the currently selected particle's data from an egui context.
///
/// Returns `Some(particle)` if a particle is selected and its data has been
/// read back from the GPU, `None` otherwise.
///
/// The particle data is read from the GPU one frame after selection, so this
/// may return `None` briefly after a new selection is made.
///
/// # Type Parameter
///
/// `P` must be the same particle type used in your simulation. The function
/// will convert the raw GPU bytes back into your particle struct.
///
/// # Example
///
/// ```ignore
/// .with_ui(|ctx| {
/// if let Some(particle) = selected_particle_data::<MyParticle>(ctx) {
/// ui.label(format!("Position: {:?}", particle.position));
/// ui.label(format!("Energy: {:.2}", particle.energy));
/// }
/// })
/// ```
/// Queue a modified particle to be written back to the GPU.
///
/// Call this after editing a particle's fields to push the changes to the GPU.
/// The write will be applied on the next frame.
///
/// # Example
///
/// ```ignore
/// .with_ui(|ctx| {
/// if let Some(mut particle) = selected_particle_data::<MyParticle>(ctx) {
/// // Edit the particle
/// particle.velocity = Vec3::ZERO;
///
/// // Queue the write
/// if let Some(idx) = selected_particle(ctx) {
/// write_particle(ctx, idx, &particle);
/// }
/// }
/// })
/// ```