pub struct SelectionModifier<G: GaussianPod, M: Modifier<G>> {
pub selection_expr: SelectionExpr,
pub selection_buffer: SelectionBuffer,
pub selection: SelectionBundle<G>,
pub modifier: M,
}Expand description
A struct to handle custom selection and custom modifier together.
§Overview
This modifier holdes a SelectionBundle and a Modifier along with necessary
buffers, and applies the selection followed by the basic modifier in order.
The Modifier can use the SelectionModifier::selection_buffer to determine which
Gaussians to modify.
§Usage
You can supply your own selection bundles and modifier when creating a
SelectionModifier.
The creation expects a modifier factory function instead of a modifier, so that the modifier can be created with a reference to the selection buffer.
// Create an editor that holds the buffers for the Gaussians and will apply the modifier
let editor = Editor::new(
&device,
&vec![core::Gaussian {
rot: Quat::IDENTITY,
pos: Vec3::ZERO,
color: U8Vec4::ZERO,
sh: [Vec3::ZERO; 15],
scale: Vec3::ONE,
}],
);
// Create your selection bundles
let selection_bundles = vec![
// The built-in sphere selection bundle as example
SelectionBundle::<GaussianPod>::create_sphere_bundle(&device),
];
struct MyCustomModifier(core::ComputeBundle);
impl MyCustomModifier {
pub fn new(
device: &wgpu::Device,
// My buffers,
selection: &SelectionBuffer,
) -> Self {
// Build your compute bundle here,
// and include the selection buffer to only modify selected Gaussians
let compute_bundle = core::ComputeBundleBuilder::new()
// Configure the modifier compute bundle here
.build(
&device,
[
[selection.buffer().as_entire_binding()].to_vec(),
[/* Your buffers */].to_vec(),
],
)
.unwrap();
Self(compute_bundle)
}
}
impl Modifier<GaussianPod> for MyCustomModifier {
fn apply(
&self,
_device: &wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
gaussians: &core::GaussiansBuffer<GaussianPod>,
_model_transform: &core::ModelTransformBuffer,
_gaussian_transform: &core::GaussianTransformBuffer,
) {
self.0.dispatch(encoder, gaussians.len() as u32);
}
}
let selection_modifier = SelectionModifier::new(
&device,
&editor.gaussians_buffer,
selection_bundles,
|selection_buffer| {
// The factory closure
MyCustomModifier::new(
&device,
// Your buffers,
selection_buffer,
)
},
);Alternatively, you can use a modifier closure instead of a struct (but be reminded this could harm readability of your code).
let selection_modifier = SelectionModifier::new(
&device,
&editor.gaussians_buffer,
selection_bundles,
|selection_buffer| {
// The factory closure
// Build your compute bundle here,
// and include the selection buffer to only modify selected Gaussians
let modifier_bundle = core::ComputeBundleBuilder::new()
.build(
&device,
[
[selection_buffer.buffer().as_entire_binding()].to_vec(),
[/* Your buffers */].to_vec(),
],
)
.unwrap();
// This function signature has blanket impl of the modifier trait
move |_device: &wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
gaussians: &core::GaussiansBuffer<GaussianPod>,
_model_transform: &core::ModelTransformBuffer,
_gaussian_transform: &core::GaussianTransformBuffer| {
modifier_bundle.dispatch(encoder, gaussians.len() as u32);
}
},
);Fields§
§selection_expr: SelectionExpr§selection_buffer: SelectionBuffer§selection: SelectionBundle<G>§modifier: MImplementations§
Source§impl<G: GaussianPod, M: Modifier<G>> SelectionModifier<G, M>
impl<G: GaussianPod, M: Modifier<G>> SelectionModifier<G, M>
Sourcepub fn new(
device: &Device,
gaussians_buffer: &GaussiansBuffer<G>,
selection_bundles: Vec<ComputeBundle<()>>,
modifier: impl FnOnce(&SelectionBuffer) -> M,
) -> Self
pub fn new( device: &Device, gaussians_buffer: &GaussiansBuffer<G>, selection_bundles: Vec<ComputeBundle<()>>, modifier: impl FnOnce(&SelectionBuffer) -> M, ) -> Self
Create a new selection modifier.
bundles are used for SelectionExpr::Unary, SelectionExpr::Binary, or
SelectionExpr::Selection, they must have the same bind group 0 as the
SelectionBundle::GAUSSIANS_BIND_GROUP_LAYOUT_DESCRIPTOR, see documentation of
SelectionBundle for more details.
Examples found in repository?
68async fn main() {
69 env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
70
71 let args = Args::parse();
72 let model_path = &args.model;
73 let pos = Vec3::from_slice(&args.pos);
74 let radius = args.radius;
75
76 log::debug!("Creating wgpu instance");
77 let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default());
78
79 log::debug!("Requesting adapter");
80 let adapter = instance
81 .request_adapter(&wgpu::RequestAdapterOptions::default())
82 .await
83 .expect("adapter");
84
85 log::debug!("Requesting device");
86 let (device, queue) = adapter
87 .request_device(&wgpu::DeviceDescriptor {
88 label: Some("Device"),
89 required_limits: adapter.limits(),
90 ..Default::default()
91 })
92 .await
93 .expect("device");
94
95 log::debug!("Creating gaussians");
96 let gaussians = [
97 gs::core::GaussiansSource::Ply,
98 gs::core::GaussiansSource::Spz,
99 ]
100 .into_iter()
101 .find_map(|source| gs::core::Gaussians::read_from_file(model_path, source).ok())
102 .expect("gaussians");
103
104 log::debug!("Creating editor");
105 let editor = gs::Editor::<GaussianPod>::new(&device, &gaussians);
106
107 log::debug!("Creating buffers");
108 let pos_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
109 label: Some("Position Buffer"),
110 contents: bytemuck::bytes_of(&pos),
111 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
112 });
113
114 let radius_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
115 label: Some("Radius Buffer"),
116 contents: bytemuck::bytes_of(&radius),
117 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
118 });
119
120 const BIND_GROUP_LAYOUT_DESCRIPTOR: wgpu::BindGroupLayoutDescriptor =
121 wgpu::BindGroupLayoutDescriptor {
122 label: Some("Bind Group Layout"),
123 entries: &[
124 // Position uniform buffer
125 wgpu::BindGroupLayoutEntry {
126 binding: 0,
127 visibility: wgpu::ShaderStages::COMPUTE,
128 ty: wgpu::BindingType::Buffer {
129 ty: wgpu::BufferBindingType::Uniform,
130 has_dynamic_offset: false,
131 min_binding_size: None,
132 },
133 count: None,
134 },
135 // Radius uniform buffer
136 wgpu::BindGroupLayoutEntry {
137 binding: 1,
138 visibility: wgpu::ShaderStages::COMPUTE,
139 ty: wgpu::BindingType::Buffer {
140 ty: wgpu::BufferBindingType::Uniform,
141 has_dynamic_offset: false,
142 min_binding_size: None,
143 },
144 count: None,
145 },
146 // Selection buffer (only in modifier pipeline)
147 wgpu::BindGroupLayoutEntry {
148 binding: 2,
149 visibility: wgpu::ShaderStages::COMPUTE,
150 ty: wgpu::BindingType::Buffer {
151 ty: wgpu::BufferBindingType::Storage { read_only: true },
152 has_dynamic_offset: false,
153 min_binding_size: None,
154 },
155 count: None,
156 },
157 ],
158 };
159
160 log::debug!("Creating cylinder selection compute bundle");
161 let cylinder_selection_bundle = gs::core::ComputeBundleBuilder::new()
162 .label("Selection")
163 .bind_group_layouts([
164 &gs::SelectionBundle::<GaussianPod>::GAUSSIANS_BIND_GROUP_LAYOUT_DESCRIPTOR,
165 &wgpu::BindGroupLayoutDescriptor {
166 entries: &BIND_GROUP_LAYOUT_DESCRIPTOR.entries[..2],
167 ..BIND_GROUP_LAYOUT_DESCRIPTOR
168 },
169 ])
170 .main_shader("package::selection".parse().unwrap())
171 .entry_point("main")
172 .wesl_compile_options(wesl::CompileOptions {
173 features: GaussianPod::wesl_features(),
174 ..Default::default()
175 })
176 .resolver({
177 let mut resolver =
178 wesl::StandardResolver::new("examples/shader/custom_modify_selection");
179 resolver.add_package(&gs::core::shader::PACKAGE);
180 resolver
181 })
182 .build_without_bind_groups(&device)
183 .map_err(|e| log::error!("{e}"))
184 .expect("selection bundle");
185
186 log::debug!("Creating custom modifier");
187 #[allow(dead_code)]
188 let modifier_factory = |selection_buffer: &gs::SelectionBuffer| /* -> impl gs::Modifier<GaussianPod> */ {
189 log::debug!("Creating custom modifier compute bundle");
190 let modifier_bundle = gs::core::ComputeBundleBuilder::new()
191 .label("Modifier")
192 .bind_group_layouts([
193 &gs::MODIFIER_GAUSSIANS_BIND_GROUP_LAYOUT_DESCRIPTOR,
194 &BIND_GROUP_LAYOUT_DESCRIPTOR,
195 ])
196 .resolver({
197 let mut resolver =
198 wesl::StandardResolver::new("examples/shader/custom_modify_selection");
199 resolver.add_package(&gs::core::shader::PACKAGE);
200 resolver.add_package(&gs::shader::PACKAGE);
201 resolver
202 })
203 .main_shader("package::modifier".parse().unwrap())
204 .entry_point("main")
205 .wesl_compile_options(wesl::CompileOptions {
206 features: GaussianPod::wesl_features(),
207 ..Default::default()
208 })
209 .build(
210 &device,
211 [
212 vec![
213 editor.gaussians_buffer.buffer().as_entire_binding(),
214 editor.model_transform_buffer.buffer().as_entire_binding(),
215 editor
216 .gaussian_transform_buffer
217 .buffer()
218 .as_entire_binding(),
219 ],
220 vec![
221 pos_buffer.as_entire_binding(),
222 radius_buffer.as_entire_binding(),
223 selection_buffer.buffer().as_entire_binding(),
224 ],
225 ],
226 )
227 .map_err(|e| log::error!("{e}"))
228 .expect("modifier bundle");
229
230 // This is a modifier closure because this function signature has blanket impl of the modifier trait
231 move |_device: &wgpu::Device,
232 encoder: &mut wgpu::CommandEncoder,
233 gaussians: &gs::core::GaussiansBuffer<GaussianPod>,
234 _model_transform: &gs::core::ModelTransformBuffer,
235 _gaussian_transform: &gs::core::GaussianTransformBuffer| {
236 modifier_bundle.dispatch(encoder, gaussians.len() as u32);
237 }
238 };
239
240 #[allow(dead_code)]
241 struct Modifier<G: gs::core::GaussianPod>(gs::core::ComputeBundle, std::marker::PhantomData<G>);
242
243 impl<G: gs::core::GaussianPod> Modifier<G> {
244 #[allow(dead_code)]
245 fn new(
246 device: &wgpu::Device,
247 editor: &gs::Editor<G>,
248 pos_buffer: &wgpu::Buffer,
249 radius_buffer: &wgpu::Buffer,
250 selection_buffer: &gs::SelectionBuffer,
251 ) -> Self {
252 log::debug!("Creating custom modifier compute bundle");
253 let modifier_bundle = gs::core::ComputeBundleBuilder::new()
254 .label("Modifier")
255 .bind_group_layouts([
256 &gs::MODIFIER_GAUSSIANS_BIND_GROUP_LAYOUT_DESCRIPTOR,
257 &BIND_GROUP_LAYOUT_DESCRIPTOR,
258 ])
259 .resolver({
260 let mut resolver =
261 wesl::StandardResolver::new("examples/shader/custom_modify_selection");
262 resolver.add_package(&gs::core::shader::PACKAGE);
263 resolver.add_package(&gs::shader::PACKAGE);
264 resolver
265 })
266 .main_shader("package::modifier".parse().unwrap())
267 .entry_point("main")
268 .wesl_compile_options(wesl::CompileOptions {
269 features: GaussianPod::wesl_features(),
270 ..Default::default()
271 })
272 .build(
273 device,
274 [
275 vec![
276 editor.gaussians_buffer.buffer().as_entire_binding(),
277 editor.model_transform_buffer.buffer().as_entire_binding(),
278 editor
279 .gaussian_transform_buffer
280 .buffer()
281 .as_entire_binding(),
282 ],
283 vec![
284 pos_buffer.as_entire_binding(),
285 radius_buffer.as_entire_binding(),
286 selection_buffer.buffer().as_entire_binding(),
287 ],
288 ],
289 )
290 .map_err(|e| log::error!("{e}"))
291 .expect("modifier bundle");
292
293 Self(modifier_bundle, std::marker::PhantomData)
294 }
295 }
296
297 impl<G: gs::core::GaussianPod> gs::Modifier<G> for Modifier<G> {
298 fn apply(
299 &self,
300 _device: &wgpu::Device,
301 encoder: &mut wgpu::CommandEncoder,
302 gaussians: &gs::core::GaussiansBuffer<G>,
303 _model_transform: &gs::core::ModelTransformBuffer,
304 _gaussian_transform: &gs::core::GaussianTransformBuffer,
305 ) {
306 self.0.dispatch(encoder, gaussians.len() as u32);
307 }
308 }
309
310 log::debug!("Creating selection modifier");
311 let mut selection_modifier = gs::SelectionModifier::<GaussianPod, _>::new(
312 &device,
313 &editor.gaussians_buffer,
314 vec![cylinder_selection_bundle],
315 modifier_factory,
316 // Uncomment the following line to use modifier struct instead of closure
317 // |selection_buffer| {
318 // Modifier::new(
319 // &device,
320 // &editor,
321 // &pos_buffer,
322 // &radius_buffer,
323 // selection_buffer,
324 // )
325 // },
326 );
327
328 log::debug!("Creating selection expression");
329 selection_modifier.selection_expr = gs::SelectionExpr::selection(
330 0,
331 vec![
332 selection_modifier.selection.bundles[0]
333 .create_bind_group(
334 &device,
335 1, // index 0 is the Gaussians buffer, so we use 1,
336 [
337 pos_buffer.as_entire_binding(),
338 radius_buffer.as_entire_binding(),
339 ],
340 )
341 .expect("selection expr bind group"),
342 ],
343 );
344
345 log::info!("Starting editing process");
346 let time = std::time::Instant::now();
347
348 log::debug!("Editing Gaussians");
349 let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
350 label: Some("Edit Encoder"),
351 });
352
353 editor.apply(
354 &device,
355 &mut encoder,
356 [&selection_modifier as &dyn gs::Modifier<GaussianPod>],
357 );
358
359 queue.submit(Some(encoder.finish()));
360
361 device
362 .poll(wgpu::PollType::wait_indefinitely())
363 .expect("poll");
364
365 log::info!("Editing process completed in {:?}", time.elapsed());
366
367 log::debug!("Downloading Gaussians");
368 let modified_gaussians = editor
369 .gaussians_buffer
370 .download_gaussians(&device, &queue)
371 .await
372 .map(|gs| {
373 match &args.output[args.output.len().saturating_sub(4)..] {
374 ".ply" => {
375 gs::core::Gaussians::Ply(gs::core::PlyGaussians::from_iter(gs.into_iter()))
376 }
377 ".spz" => {
378 gs::core::Gaussians::Spz(
379 gs::core::SpzGaussians::from_gaussians_with_options(
380 gs,
381 &gs::core::SpzGaussiansFromGaussianSliceOptions {
382 version: 2, // Version 2 is more widely supported as of now
383 ..Default::default()
384 },
385 )
386 .expect("SpzGaussians from gaussians"),
387 )
388 }
389 _ => panic!("Unsupported output file extension, expected .ply or .spz"),
390 }
391 })
392 .expect("gaussians download");
393
394 log::debug!("Writing modified Gaussians to output file");
395 modified_gaussians
396 .write_to_file(&args.output)
397 .expect("write modified Gaussians to output file");
398
399 log::info!("Modified Gaussians written to {}", args.output);
400}Source§impl<G: GaussianPod> SelectionModifier<G, BasicModifier<G, WithSelection>>
impl<G: GaussianPod> SelectionModifier<G, BasicModifier<G, WithSelection>>
Sourcepub fn new_with_basic_modifier(
device: &Device,
gaussians_buffer: &GaussiansBuffer<G>,
model_transform: &ModelTransformBuffer,
gaussian_transform: &GaussianTransformBuffer,
selection_bundles: Vec<ComputeBundle<()>>,
) -> Self
pub fn new_with_basic_modifier( device: &Device, gaussians_buffer: &GaussiansBuffer<G>, model_transform: &ModelTransformBuffer, gaussian_transform: &GaussianTransformBuffer, selection_bundles: Vec<ComputeBundle<()>>, ) -> Self
Create a new selection modifier with BasicModifier.
bundles are used for SelectionExpr::Unary, SelectionExpr::Binary, or
SelectionExpr::Selection, they must have the same bind group 0 as the
SelectionBundle::GAUSSIANS_BIND_GROUP_LAYOUT_DESCRIPTOR, see documentation of
SelectionBundle for more details.
Examples found in repository?
137async fn main() {
138 env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
139
140 let args = Args::parse();
141 let model_path = &args.model;
142 let pos = Vec3::from_slice(&args.pos);
143 let rot = Quat::from_slice(&args.rot);
144 let scale = Vec3::from_slice(&args.scale);
145 let shape = match args.shape {
146 Shape::Sphere => gs::SelectionBundle::<GaussianPod>::create_sphere_bundle,
147 Shape::Box => gs::SelectionBundle::<GaussianPod>::create_box_bundle,
148 };
149 let repeat = args.repeat;
150 let offset = Vec3::from_slice(&args.offset);
151
152 log::debug!("Creating wgpu instance");
153 let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor::default());
154
155 log::debug!("Requesting adapter");
156 let adapter = instance
157 .request_adapter(&wgpu::RequestAdapterOptions::default())
158 .await
159 .expect("adapter");
160
161 log::debug!("Requesting device");
162 let (device, queue) = adapter
163 .request_device(&wgpu::DeviceDescriptor {
164 label: Some("Device"),
165 required_limits: adapter.limits(),
166 ..Default::default()
167 })
168 .await
169 .expect("device");
170
171 log::debug!("Creating gaussians");
172 let gaussians = [
173 gs::core::GaussiansSource::Ply,
174 gs::core::GaussiansSource::Spz,
175 ]
176 .into_iter()
177 .find_map(|source| gs::core::Gaussians::read_from_file(model_path, source).ok())
178 .expect("gaussians");
179
180 log::debug!("Creating editor");
181 let editor = gs::Editor::<GaussianPod>::new(&device, &gaussians);
182
183 log::debug!("Creating shape selection compute bundle");
184 let shape_selection = shape(&device);
185
186 log::debug!("Creating basic selection modifier");
187 let mut basic_selection_modifier = gs::SelectionModifier::new_with_basic_modifier(
188 &device,
189 &editor.gaussians_buffer,
190 &editor.model_transform_buffer,
191 &editor.gaussian_transform_buffer,
192 vec![shape_selection],
193 );
194
195 log::debug!("Configuring modifiers");
196 basic_selection_modifier
197 .modifier
198 .basic_color_modifiers_buffer
199 .update(
200 &queue,
201 match args.override_rgb {
202 true => gs::BasicColorRgbOverrideOrHsvModifiersPod::new_rgb_override,
203 false => gs::BasicColorRgbOverrideOrHsvModifiersPod::new_hsv_modifiers,
204 }(Vec3::from_slice(&args.rgb_or_hsv)),
205 args.alpha,
206 args.contrast,
207 args.exposure,
208 args.gamma,
209 );
210
211 log::debug!("Creating shape selection buffers");
212 let shape_selection_buffers = (0..repeat)
213 .map(|i| {
214 let offset_pos = pos + offset * i as f32;
215 let buffer = gs::InvTransformBuffer::new(&device);
216 buffer.update_with_scale_rot_pos(&queue, scale, rot, offset_pos);
217 buffer
218 })
219 .collect::<Vec<_>>();
220
221 log::debug!("Creating shape selection bind groups");
222 let shape_selection_bind_groups = shape_selection_buffers
223 .iter()
224 .map(|buffer| {
225 basic_selection_modifier.selection.bundles[0]
226 .create_bind_group(
227 &device,
228 // index 0 is the Gaussians buffer, so we use 1,
229 // see docs of create_sphere_bundle or create_box_bundle
230 1,
231 [buffer.buffer().as_entire_binding()],
232 )
233 .expect("bind group")
234 })
235 .collect::<Vec<_>>();
236
237 log::debug!("Creating selection expression");
238 basic_selection_modifier.selection_expr = shape_selection_bind_groups.into_iter().fold(
239 gs::SelectionExpr::Identity,
240 |acc, bind_group| {
241 acc.union(gs::SelectionExpr::selection(
242 0, // the 0 here is the bundle index in the selection bundle
243 vec![bind_group],
244 ))
245 },
246 );
247
248 log::info!("Starting editing process");
249 let time = std::time::Instant::now();
250
251 log::debug!("Editing Gaussians");
252 let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
253 label: Some("Edit Encoder"),
254 });
255
256 editor.apply(
257 &device,
258 &mut encoder,
259 [&basic_selection_modifier as &dyn gs::Modifier<GaussianPod>],
260 );
261
262 queue.submit(Some(encoder.finish()));
263
264 device
265 .poll(wgpu::PollType::wait_indefinitely())
266 .expect("poll");
267
268 log::info!("Editing process completed in {:?}", time.elapsed());
269
270 log::debug!("Downloading Gaussians");
271 let modified_gaussians = editor
272 .gaussians_buffer
273 .download_gaussians(&device, &queue)
274 .await
275 .map(|gs| {
276 match &args.output[args.output.len().saturating_sub(4)..] {
277 ".ply" => {
278 gs::core::Gaussians::Ply(gs::core::PlyGaussians::from_iter(gs.into_iter()))
279 }
280 ".spz" => {
281 gs::core::Gaussians::Spz(
282 gs::core::SpzGaussians::from_gaussians_with_options(
283 gs,
284 &gs::core::SpzGaussiansFromGaussianSliceOptions {
285 version: 2, // Version 2 is more widely supported as of now
286 ..Default::default()
287 },
288 )
289 .expect("SpzGaussians from gaussians"),
290 )
291 }
292 _ => panic!("Unsupported output file extension, expected .ply or .spz"),
293 }
294 })
295 .expect("gaussians download");
296
297 log::debug!("Writing modified Gaussians to output file");
298 modified_gaussians
299 .write_to_file(&args.output)
300 .expect("write modified Gaussians to output file");
301
302 log::info!("Modified Gaussians written to {}", args.output);
303}Trait Implementations§
Source§impl<G: Debug + GaussianPod, M: Debug + Modifier<G>> Debug for SelectionModifier<G, M>
impl<G: Debug + GaussianPod, M: Debug + Modifier<G>> Debug for SelectionModifier<G, M>
Source§impl<G: GaussianPod, M: Modifier<G>> Modifier<G> for SelectionModifier<G, M>
impl<G: GaussianPod, M: Modifier<G>> Modifier<G> for SelectionModifier<G, M>
Source§fn apply(
&self,
device: &Device,
encoder: &mut CommandEncoder,
gaussians: &GaussiansBuffer<G>,
model_transform: &ModelTransformBuffer,
gaussian_transform: &GaussianTransformBuffer,
)
fn apply( &self, device: &Device, encoder: &mut CommandEncoder, gaussians: &GaussiansBuffer<G>, model_transform: &ModelTransformBuffer, gaussian_transform: &GaussianTransformBuffer, )
Auto Trait Implementations§
impl<G, M> Freeze for SelectionModifier<G, M>where
M: Freeze,
impl<G, M> !RefUnwindSafe for SelectionModifier<G, M>
impl<G, M> Send for SelectionModifier<G, M>where
M: Send,
impl<G, M> Sync for SelectionModifier<G, M>where
M: Sync,
impl<G, M> Unpin for SelectionModifier<G, M>
impl<G, M> !UnwindSafe for SelectionModifier<G, M>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more