pub struct HoverMap(pub HashMap<PointerId, HashMap<Entity, HitData>>);
Expand description
The source of truth for all hover state. This is used to determine what events to send, and what state components should be in.
Maps pointers to the entities they are hovering over.
“Hovering” refers to the hover state, which is not the same as whether or not a picking backend is reporting hits between a pointer and an entity. A pointer is “hovering” an entity only if the pointer is hitting the entity (as reported by a picking backend) and no entities between it and the pointer block interactions.
For example, if a pointer is hitting a UI button and a 3d mesh, but the button is in front of
the mesh, the UI button will be hovered, but the mesh will not. Unless, the Pickable
component is present with should_block_lower
set to false
.
§Advanced Users
If you want to completely replace the provided picking events or state produced by this plugin,
you can use this resource to do that. All of the event systems for picking are built on top of
this authoritative hover state, and you can do the same. You can also use the
PreviousHoverMap
as a robust way of determining changes in hover state from the previous
update.
Tuple Fields§
§0: HashMap<PointerId, HashMap<Entity, HitData>>
Methods from Deref<Target = HashMap<PointerId, HashMap<Entity, HitData>>>§
Sourcepub fn hasher(&self) -> &S
pub fn hasher(&self) -> &S
Returns a reference to the map’s BuildHasher
, or S
parameter.
Refer to hasher
for further details.
Sourcepub fn keys(&self) -> Keys<'_, K, V> ⓘ
pub fn keys(&self) -> Keys<'_, K, V> ⓘ
An iterator visiting all keys in arbitrary order.
The iterator element type is &'a K
.
Refer to keys
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
for key in map.keys() {
// foo, bar, baz
// Note that the above order is not guaranteed
}
Sourcepub fn values(&self) -> Values<'_, K, V> ⓘ
pub fn values(&self) -> Values<'_, K, V> ⓘ
An iterator visiting all values in arbitrary order.
The iterator element type is &'a V
.
Refer to values
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
for key in map.values() {
// 0, 1, 2
// Note that the above order is not guaranteed
}
Sourcepub fn values_mut(&mut self) -> ValuesMut<'_, K, V> ⓘ
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> ⓘ
An iterator visiting all values mutably in arbitrary order.
The iterator element type is &'a mut V
.
Refer to values
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
for key in map.values_mut() {
// 0, 1, 2
// Note that the above order is not guaranteed
}
Sourcepub fn iter(&self) -> Iter<'_, K, V> ⓘ
pub fn iter(&self) -> Iter<'_, K, V> ⓘ
An iterator visiting all key-value pairs in arbitrary order.
The iterator element type is (&'a K, &'a V)
.
Refer to iter
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
for (key, value) in map.iter() {
// ("foo", 0), ("bar", 1), ("baz", 2)
// Note that the above order is not guaranteed
}
Examples found in repository?
410pub fn update_scroll_position(
411 mut mouse_wheel_events: EventReader<MouseWheel>,
412 hover_map: Res<HoverMap>,
413 mut scrolled_node_query: Query<&mut ScrollPosition>,
414 keyboard_input: Res<ButtonInput<KeyCode>>,
415) {
416 for mouse_wheel_event in mouse_wheel_events.read() {
417 let (mut dx, mut dy) = match mouse_wheel_event.unit {
418 MouseScrollUnit::Line => (mouse_wheel_event.x * 20., mouse_wheel_event.y * 20.),
419 MouseScrollUnit::Pixel => (mouse_wheel_event.x, mouse_wheel_event.y),
420 };
421
422 if keyboard_input.pressed(KeyCode::ShiftLeft) || keyboard_input.pressed(KeyCode::ShiftRight)
423 {
424 std::mem::swap(&mut dx, &mut dy);
425 }
426
427 for (_pointer, pointer_map) in hover_map.iter() {
428 for (entity, _hit) in pointer_map.iter() {
429 if let Ok(mut scroll_position) = scrolled_node_query.get_mut(*entity) {
430 scroll_position.offset_x -= dx;
431 scroll_position.offset_y -= dy;
432 }
433 }
434 }
435 }
436}
More examples
329pub fn update_scroll_position(
330 mut mouse_wheel_events: EventReader<MouseWheel>,
331 hover_map: Res<HoverMap>,
332 mut scrolled_node_query: Query<&mut ScrollPosition>,
333 keyboard_input: Res<ButtonInput<KeyCode>>,
334) {
335 for mouse_wheel_event in mouse_wheel_events.read() {
336 let (mut dx, mut dy) = match mouse_wheel_event.unit {
337 MouseScrollUnit::Line => (
338 mouse_wheel_event.x * LINE_HEIGHT,
339 mouse_wheel_event.y * LINE_HEIGHT,
340 ),
341 MouseScrollUnit::Pixel => (mouse_wheel_event.x, mouse_wheel_event.y),
342 };
343
344 if keyboard_input.pressed(KeyCode::ControlLeft)
345 || keyboard_input.pressed(KeyCode::ControlRight)
346 {
347 std::mem::swap(&mut dx, &mut dy);
348 }
349
350 for (_pointer, pointer_map) in hover_map.iter() {
351 for (entity, _hit) in pointer_map.iter() {
352 if let Ok(mut scroll_position) = scrolled_node_query.get_mut(*entity) {
353 scroll_position.offset_x -= dx;
354 scroll_position.offset_y -= dy;
355 }
356 }
357 }
358 }
359}
Sourcepub fn iter_mut(&mut self) -> IterMut<'_, K, V> ⓘ
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> ⓘ
An iterator visiting all key-value pairs in arbitrary order,
with mutable references to the values.
The iterator element type is (&'a K, &'a mut V)
.
Refer to iter_mut
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
for (key, value) in map.iter_mut() {
// ("foo", 0), ("bar", 1), ("baz", 2)
// Note that the above order is not guaranteed
}
Examples found in repository?
333fn update_color_grading_settings(
334 keys: Res<ButtonInput<KeyCode>>,
335 time: Res<Time>,
336 mut per_method_settings: ResMut<PerMethodSettings>,
337 tonemapping: Single<&Tonemapping>,
338 current_scene: Res<CurrentScene>,
339 mut selected_parameter: ResMut<SelectedParameter>,
340) {
341 let color_grading = per_method_settings.settings.get_mut(*tonemapping).unwrap();
342 let mut dt = time.delta_secs() * 0.25;
343 if keys.pressed(KeyCode::ArrowLeft) {
344 dt = -dt;
345 }
346
347 if keys.just_pressed(KeyCode::ArrowDown) {
348 selected_parameter.next();
349 }
350 if keys.just_pressed(KeyCode::ArrowUp) {
351 selected_parameter.prev();
352 }
353 if keys.pressed(KeyCode::ArrowLeft) || keys.pressed(KeyCode::ArrowRight) {
354 match selected_parameter.value {
355 0 => {
356 color_grading.global.exposure += dt;
357 }
358 1 => {
359 color_grading
360 .all_sections_mut()
361 .for_each(|section| section.gamma += dt);
362 }
363 2 => {
364 color_grading
365 .all_sections_mut()
366 .for_each(|section| section.saturation += dt);
367 }
368 3 => {
369 color_grading.global.post_saturation += dt;
370 }
371 _ => {}
372 }
373 }
374
375 if keys.just_pressed(KeyCode::Space) {
376 for (_, grading) in per_method_settings.settings.iter_mut() {
377 *grading = ColorGrading::default();
378 }
379 }
380
381 if keys.just_pressed(KeyCode::Enter) && current_scene.0 == 1 {
382 for (mapper, grading) in per_method_settings.settings.iter_mut() {
383 *grading = PerMethodSettings::basic_scene_recommendation(*mapper);
384 }
385 }
386}
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in the map.
Refer to len
for further details.
§Examples
let mut map = HashMap::new();
assert_eq!(map.len(), 0);
map.insert("foo", 0);
assert_eq!(map.len(), 1);
Examples found in repository?
166fn print_visible_light_count(
167 time: Res<Time>,
168 mut timer: Local<PrintingTimer>,
169 visible: Query<&ExtractedPointLight>,
170 global_light_meta: Res<GlobalClusterableObjectMeta>,
171) {
172 timer.0.tick(time.delta());
173
174 if timer.0.just_finished() {
175 info!(
176 "Visible Lights: {}, Rendered Lights: {}",
177 visible.iter().len(),
178 global_light_meta.entity_to_index.len()
179 );
180 }
181}
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if the map contains no elements.
Refer to is_empty
for further details.
§Examples
let mut map = HashMap::new();
assert!(map.is_empty());
map.insert("foo", 0);
assert!(!map.is_empty());
Examples found in repository?
375pub fn queue_colored_mesh2d(
376 transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
377 colored_mesh2d_pipeline: Res<ColoredMesh2dPipeline>,
378 mut pipelines: ResMut<SpecializedRenderPipelines<ColoredMesh2dPipeline>>,
379 pipeline_cache: Res<PipelineCache>,
380 render_meshes: Res<RenderAssets<RenderMesh>>,
381 render_mesh_instances: Res<RenderColoredMesh2dInstances>,
382 mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
383 views: Query<(&RenderVisibleEntities, &ExtractedView, &Msaa)>,
384) {
385 if render_mesh_instances.is_empty() {
386 return;
387 }
388 // Iterate each view (a camera is a view)
389 for (visible_entities, view, msaa) in &views {
390 let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity)
391 else {
392 continue;
393 };
394
395 let draw_colored_mesh2d = transparent_draw_functions.read().id::<DrawColoredMesh2d>();
396
397 let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples())
398 | Mesh2dPipelineKey::from_hdr(view.hdr);
399
400 // Queue all entities visible to that view
401 for (render_entity, visible_entity) in visible_entities.iter::<Mesh2d>() {
402 if let Some(mesh_instance) = render_mesh_instances.get(visible_entity) {
403 let mesh2d_handle = mesh_instance.mesh_asset_id;
404 let mesh2d_transforms = &mesh_instance.transforms;
405 // Get our specialized pipeline
406 let mut mesh2d_key = mesh_key;
407 let Some(mesh) = render_meshes.get(mesh2d_handle) else {
408 continue;
409 };
410 mesh2d_key |= Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology());
411
412 let pipeline_id =
413 pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh2d_key);
414
415 let mesh_z = mesh2d_transforms.world_from_local.translation.z;
416 transparent_phase.add(Transparent2d {
417 entity: (*render_entity, *visible_entity),
418 draw_function: draw_colored_mesh2d,
419 pipeline: pipeline_id,
420 // The 2d render items are sorted according to their z value before rendering,
421 // in order to get correct transparency
422 sort_key: FloatOrd(mesh_z),
423 // This material is not batched
424 batch_range: 0..1,
425 extra_index: PhaseItemExtraIndex::None,
426 extracted_index: usize::MAX,
427 indexed: mesh.indexed(),
428 });
429 }
430 }
431 }
432}
Sourcepub fn drain(&mut self) -> Drain<'_, K, V> ⓘ
pub fn drain(&mut self) -> Drain<'_, K, V> ⓘ
Clears the map, returning all key-value pairs as an iterator. Keeps the allocated memory for reuse.
Refer to drain
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
for (key, value) in map.drain() {
// ("foo", 0), ("bar", 1), ("baz", 2)
// Note that the above order is not guaranteed
}
assert!(map.is_empty());
Sourcepub fn retain<F>(&mut self, f: F)
pub fn retain<F>(&mut self, f: F)
Retains only the elements specified by the predicate. Keeps the allocated memory for reuse.
Refer to retain
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
map.retain(|key, value| *value == 2);
assert_eq!(map.len(), 1);
Examples found in repository?
476fn extract_camera_phases(
477 mut stencil_phases: ResMut<ViewSortedRenderPhases<Stencil3d>>,
478 cameras: Extract<Query<(Entity, &Camera), With<Camera3d>>>,
479 mut live_entities: Local<HashSet<RetainedViewEntity>>,
480) {
481 live_entities.clear();
482 for (main_entity, camera) in &cameras {
483 if !camera.is_active {
484 continue;
485 }
486 // This is the main camera, so we use the first subview index (0)
487 let retained_view_entity = RetainedViewEntity::new(main_entity.into(), None, 0);
488
489 stencil_phases.insert_or_clear(retained_view_entity);
490 live_entities.insert(retained_view_entity);
491 }
492
493 // Clear out all dead views.
494 stencil_phases.retain(|camera_entity, _| live_entities.contains(camera_entity));
495}
Sourcepub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, K, V, F> ⓘ
pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, K, V, F> ⓘ
Drains elements which are true under the given predicate, and returns an iterator over the removed items.
Refer to extract_if
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
let extracted = map
.extract_if(|key, value| *value == 2)
.collect::<Vec<_>>();
assert_eq!(map.len(), 2);
assert_eq!(extracted.len(), 1);
Sourcepub fn reserve(&mut self, additional: usize)
pub fn reserve(&mut self, additional: usize)
Reserves capacity for at least additional
more elements to be inserted
in the HashMap
. The collection may reserve more space to avoid
frequent reallocations.
Refer to reserve
for further details.
§Examples
let mut map = HashMap::with_capacity(5);
assert!(map.capacity() >= 5);
map.reserve(10);
assert!(map.capacity() - map.len() >= 10);
Sourcepub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
Tries to reserve capacity for at least additional
more elements to be inserted
in the given HashMap<K,V>
. The collection may reserve more space to avoid
frequent reallocations.
Refer to try_reserve
for further details.
§Examples
let mut map = HashMap::with_capacity(5);
assert!(map.capacity() >= 5);
map.try_reserve(10).expect("Out of Memory!");
assert!(map.capacity() - map.len() >= 10);
Sourcepub fn shrink_to_fit(&mut self)
pub fn shrink_to_fit(&mut self)
Shrinks the capacity of the map as much as possible. It will drop down as much as possible while maintaining the internal rules and possibly leaving some space in accordance with the resize policy.
Refer to shrink_to_fit
for further details.
§Examples
let mut map = HashMap::with_capacity(5);
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
assert!(map.capacity() >= 5);
map.shrink_to_fit();
assert_eq!(map.capacity(), 3);
Sourcepub fn shrink_to(&mut self, min_capacity: usize)
pub fn shrink_to(&mut self, min_capacity: usize)
Shrinks the capacity of the map with a lower limit. It will drop down no lower than the supplied limit while maintaining the internal rules and possibly leaving some space in accordance with the resize policy.
Refer to shrink_to
for further details.
Sourcepub fn entry(&mut self, key: K) -> Entry<'_, K, V, S>
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S>
Gets the given key’s corresponding entry in the map for in-place manipulation.
Refer to entry
for further details.
§Examples
let mut map = HashMap::new();
let value = map.entry("foo").or_insert(0);
Examples found in repository?
115fn on_add_mine(
116 trigger: Trigger<OnAdd, Mine>,
117 query: Query<&Mine>,
118 mut index: ResMut<SpatialIndex>,
119) {
120 let mine = query.get(trigger.target()).unwrap();
121 let tile = (
122 (mine.pos.x / CELL_SIZE).floor() as i32,
123 (mine.pos.y / CELL_SIZE).floor() as i32,
124 );
125 index.map.entry(tile).or_default().insert(trigger.target());
126}
127
128// Remove despawned mines from our index
129fn on_remove_mine(
130 trigger: Trigger<OnRemove, Mine>,
131 query: Query<&Mine>,
132 mut index: ResMut<SpatialIndex>,
133) {
134 let mine = query.get(trigger.target()).unwrap();
135 let tile = (
136 (mine.pos.x / CELL_SIZE).floor() as i32,
137 (mine.pos.y / CELL_SIZE).floor() as i32,
138 );
139 index.map.entry(tile).and_modify(|set| {
140 set.remove(&trigger.target());
141 });
142}
Sourcepub fn get<Q>(&self, k: &Q) -> Option<&V>
pub fn get<Q>(&self, k: &Q) -> Option<&V>
Returns a reference to the value corresponding to the key.
Refer to get
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert_eq!(map.get("foo"), Some(&0));
Examples found in repository?
More examples
204 fn get_nearby(&self, pos: Vec2) -> Vec<Entity> {
205 let tile = (
206 (pos.x / CELL_SIZE).floor() as i32,
207 (pos.y / CELL_SIZE).floor() as i32,
208 );
209 let mut nearby = Vec::new();
210 for x in -1..2 {
211 for y in -1..2 {
212 if let Some(mines) = self.map.get(&(tile.0 + x, tile.1 + y)) {
213 nearby.extend(mines.iter());
214 }
215 }
216 }
217 nearby
218 }
286fn toggle_tonemapping_method(
287 keys: Res<ButtonInput<KeyCode>>,
288 mut tonemapping: Single<&mut Tonemapping>,
289 mut color_grading: Single<&mut ColorGrading>,
290 per_method_settings: Res<PerMethodSettings>,
291) {
292 if keys.just_pressed(KeyCode::Digit1) {
293 **tonemapping = Tonemapping::None;
294 } else if keys.just_pressed(KeyCode::Digit2) {
295 **tonemapping = Tonemapping::Reinhard;
296 } else if keys.just_pressed(KeyCode::Digit3) {
297 **tonemapping = Tonemapping::ReinhardLuminance;
298 } else if keys.just_pressed(KeyCode::Digit4) {
299 **tonemapping = Tonemapping::AcesFitted;
300 } else if keys.just_pressed(KeyCode::Digit5) {
301 **tonemapping = Tonemapping::AgX;
302 } else if keys.just_pressed(KeyCode::Digit6) {
303 **tonemapping = Tonemapping::SomewhatBoringDisplayTransform;
304 } else if keys.just_pressed(KeyCode::Digit7) {
305 **tonemapping = Tonemapping::TonyMcMapface;
306 } else if keys.just_pressed(KeyCode::Digit8) {
307 **tonemapping = Tonemapping::BlenderFilmic;
308 }
309
310 **color_grading = (*per_method_settings
311 .settings
312 .get::<Tonemapping>(&tonemapping)
313 .as_ref()
314 .unwrap())
315 .clone();
316}
347 fn get_batch_data(
348 (mesh_instances, _render_assets, mesh_allocator): &SystemParamItem<Self::Param>,
349 (_entity, main_entity): (Entity, MainEntity),
350 ) -> Option<(Self::BufferData, Option<Self::CompareData>)> {
351 let RenderMeshInstances::CpuBuilding(ref mesh_instances) = **mesh_instances else {
352 error!(
353 "`get_batch_data` should never be called in GPU mesh uniform \
354 building mode"
355 );
356 return None;
357 };
358 let mesh_instance = mesh_instances.get(&main_entity)?;
359 let first_vertex_index =
360 match mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id) {
361 Some(mesh_vertex_slice) => mesh_vertex_slice.range.start,
362 None => 0,
363 };
364 let mesh_uniform = {
365 let mesh_transforms = &mesh_instance.transforms;
366 let (local_from_world_transpose_a, local_from_world_transpose_b) =
367 mesh_transforms.world_from_local.inverse_transpose_3x3();
368 MeshUniform {
369 world_from_local: mesh_transforms.world_from_local.to_transpose(),
370 previous_world_from_local: mesh_transforms.previous_world_from_local.to_transpose(),
371 lightmap_uv_rect: UVec2::ZERO,
372 local_from_world_transpose_a,
373 local_from_world_transpose_b,
374 flags: mesh_transforms.flags,
375 first_vertex_index,
376 current_skin_index: u32::MAX,
377 material_and_lightmap_bind_group_slot: 0,
378 tag: 0,
379 pad: 0,
380 }
381 };
382 Some((mesh_uniform, None))
383 }
384}
385impl GetFullBatchData for StencilPipeline {
386 type BufferInputData = MeshInputUniform;
387
388 fn get_index_and_compare_data(
389 (mesh_instances, _, _): &SystemParamItem<Self::Param>,
390 main_entity: MainEntity,
391 ) -> Option<(NonMaxU32, Option<Self::CompareData>)> {
392 // This should only be called during GPU building.
393 let RenderMeshInstances::GpuBuilding(ref mesh_instances) = **mesh_instances else {
394 error!(
395 "`get_index_and_compare_data` should never be called in CPU mesh uniform building \
396 mode"
397 );
398 return None;
399 };
400 let mesh_instance = mesh_instances.get(&main_entity)?;
401 Some((
402 mesh_instance.current_uniform_index,
403 mesh_instance
404 .should_batch()
405 .then_some(mesh_instance.mesh_asset_id),
406 ))
407 }
408
409 fn get_binned_batch_data(
410 (mesh_instances, _render_assets, mesh_allocator): &SystemParamItem<Self::Param>,
411 main_entity: MainEntity,
412 ) -> Option<Self::BufferData> {
413 let RenderMeshInstances::CpuBuilding(ref mesh_instances) = **mesh_instances else {
414 error!(
415 "`get_binned_batch_data` should never be called in GPU mesh uniform building mode"
416 );
417 return None;
418 };
419 let mesh_instance = mesh_instances.get(&main_entity)?;
420 let first_vertex_index =
421 match mesh_allocator.mesh_vertex_slice(&mesh_instance.mesh_asset_id) {
422 Some(mesh_vertex_slice) => mesh_vertex_slice.range.start,
423 None => 0,
424 };
425
426 Some(MeshUniform::new(
427 &mesh_instance.transforms,
428 first_vertex_index,
429 mesh_instance.material_bindings_index.slot,
430 None,
431 None,
432 None,
433 ))
434 }
435
436 fn write_batch_indirect_parameters_metadata(
437 indexed: bool,
438 base_output_index: u32,
439 batch_set_index: Option<NonMaxU32>,
440 indirect_parameters_buffers: &mut UntypedPhaseIndirectParametersBuffers,
441 indirect_parameters_offset: u32,
442 ) {
443 // Note that `IndirectParameters` covers both of these structures, even
444 // though they actually have distinct layouts. See the comment above that
445 // type for more information.
446 let indirect_parameters = IndirectParametersCpuMetadata {
447 base_output_index,
448 batch_set_index: match batch_set_index {
449 None => !0,
450 Some(batch_set_index) => u32::from(batch_set_index),
451 },
452 };
453
454 if indexed {
455 indirect_parameters_buffers
456 .indexed
457 .set(indirect_parameters_offset, indirect_parameters);
458 } else {
459 indirect_parameters_buffers
460 .non_indexed
461 .set(indirect_parameters_offset, indirect_parameters);
462 }
463 }
464
465 fn get_binned_index(
466 _param: &SystemParamItem<Self::Param>,
467 _query_item: MainEntity,
468 ) -> Option<NonMaxU32> {
469 None
470 }
471}
472
473// When defining a phase, we need to extract it from the main world and add it to a resource
474// that will be used by the render world. We need to give that resource all views that will use
475// that phase
476fn extract_camera_phases(
477 mut stencil_phases: ResMut<ViewSortedRenderPhases<Stencil3d>>,
478 cameras: Extract<Query<(Entity, &Camera), With<Camera3d>>>,
479 mut live_entities: Local<HashSet<RetainedViewEntity>>,
480) {
481 live_entities.clear();
482 for (main_entity, camera) in &cameras {
483 if !camera.is_active {
484 continue;
485 }
486 // This is the main camera, so we use the first subview index (0)
487 let retained_view_entity = RetainedViewEntity::new(main_entity.into(), None, 0);
488
489 stencil_phases.insert_or_clear(retained_view_entity);
490 live_entities.insert(retained_view_entity);
491 }
492
493 // Clear out all dead views.
494 stencil_phases.retain(|camera_entity, _| live_entities.contains(camera_entity));
495}
496
497// This is a very important step when writing a custom phase.
498//
499// This system determines which meshes will be added to the phase.
500fn queue_custom_meshes(
501 custom_draw_functions: Res<DrawFunctions<Stencil3d>>,
502 mut pipelines: ResMut<SpecializedMeshPipelines<StencilPipeline>>,
503 pipeline_cache: Res<PipelineCache>,
504 custom_draw_pipeline: Res<StencilPipeline>,
505 render_meshes: Res<RenderAssets<RenderMesh>>,
506 render_mesh_instances: Res<RenderMeshInstances>,
507 mut custom_render_phases: ResMut<ViewSortedRenderPhases<Stencil3d>>,
508 mut views: Query<(&ExtractedView, &RenderVisibleEntities, &Msaa)>,
509 has_marker: Query<(), With<DrawStencil>>,
510) {
511 for (view, visible_entities, msaa) in &mut views {
512 let Some(custom_phase) = custom_render_phases.get_mut(&view.retained_view_entity) else {
513 continue;
514 };
515 let draw_custom = custom_draw_functions.read().id::<DrawMesh3dStencil>();
516
517 // Create the key based on the view.
518 // In this case we only care about MSAA and HDR
519 let view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
520 | MeshPipelineKey::from_hdr(view.hdr);
521
522 let rangefinder = view.rangefinder3d();
523 // Since our phase can work on any 3d mesh we can reuse the default mesh 3d filter
524 for (render_entity, visible_entity) in visible_entities.iter::<Mesh3d>() {
525 // We only want meshes with the marker component to be queued to our phase.
526 if has_marker.get(*render_entity).is_err() {
527 continue;
528 }
529 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity)
530 else {
531 continue;
532 };
533 let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
534 continue;
535 };
536
537 // Specialize the key for the current mesh entity
538 // For this example we only specialize based on the mesh topology
539 // but you could have more complex keys and that's where you'd need to create those keys
540 let mut mesh_key = view_key;
541 mesh_key |= MeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
542
543 let pipeline_id = pipelines.specialize(
544 &pipeline_cache,
545 &custom_draw_pipeline,
546 mesh_key,
547 &mesh.layout,
548 );
549 let pipeline_id = match pipeline_id {
550 Ok(id) => id,
551 Err(err) => {
552 error!("{}", err);
553 continue;
554 }
555 };
556 let distance = rangefinder.distance_translation(&mesh_instance.translation);
557 // At this point we have all the data we need to create a phase item and add it to our
558 // phase
559 custom_phase.add(Stencil3d {
560 // Sort the data based on the distance to the view
561 sort_key: FloatOrd(distance),
562 entity: (*render_entity, *visible_entity),
563 pipeline: pipeline_id,
564 draw_function: draw_custom,
565 // Sorted phase items aren't batched
566 batch_range: 0..1,
567 extra_index: PhaseItemExtraIndex::None,
568 indexed: mesh.indexed(),
569 });
570 }
571 }
572}
573
574// Render label used to order our render graph node that will render our phase
575#[derive(RenderLabel, Debug, Clone, Hash, PartialEq, Eq)]
576struct CustomDrawPassLabel;
577
578#[derive(Default)]
579struct CustomDrawNode;
580impl ViewNode for CustomDrawNode {
581 type ViewQuery = (
582 &'static ExtractedCamera,
583 &'static ExtractedView,
584 &'static ViewTarget,
585 );
586
587 fn run<'w>(
588 &self,
589 graph: &mut RenderGraphContext,
590 render_context: &mut RenderContext<'w>,
591 (camera, view, target): QueryItem<'w, Self::ViewQuery>,
592 world: &'w World,
593 ) -> Result<(), NodeRunError> {
594 // First, we need to get our phases resource
595 let Some(stencil_phases) = world.get_resource::<ViewSortedRenderPhases<Stencil3d>>() else {
596 return Ok(());
597 };
598
599 // Get the view entity from the graph
600 let view_entity = graph.view_entity();
601
602 // Get the phase for the current view running our node
603 let Some(stencil_phase) = stencil_phases.get(&view.retained_view_entity) else {
604 return Ok(());
605 };
606
607 // Render pass setup
608 let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
609 label: Some("stencil pass"),
610 // For the purpose of the example, we will write directly to the view target. A real
611 // stencil pass would write to a custom texture and that texture would be used in later
612 // passes to render custom effects using it.
613 color_attachments: &[Some(target.get_color_attachment())],
614 // We don't bind any depth buffer for this pass
615 depth_stencil_attachment: None,
616 timestamp_writes: None,
617 occlusion_query_set: None,
618 });
619
620 if let Some(viewport) = camera.viewport.as_ref() {
621 render_pass.set_camera_viewport(viewport);
622 }
623
624 // Render the phase
625 // This will execute each draw functions of each phase items queued in this phase
626 if let Err(err) = stencil_phase.render(&mut render_pass, world, view_entity) {
627 error!("Error encountered while rendering the stencil phase {err:?}");
628 }
629
630 Ok(())
631 }
419 fn run<'w>(
420 &self,
421 _: &mut RenderGraphContext,
422 render_context: &mut RenderContext<'w>,
423 world: &'w World,
424 ) -> Result<(), NodeRunError> {
425 // Extract the buffers that hold the GPU indirect draw parameters from
426 // the world resources. We're going to read those buffers to determine
427 // how many meshes were actually drawn.
428 let (Some(indirect_parameters_buffers), Some(indirect_parameters_mapping_buffers)) = (
429 world.get_resource::<IndirectParametersBuffers>(),
430 world.get_resource::<IndirectParametersStagingBuffers>(),
431 ) else {
432 return Ok(());
433 };
434
435 // Get the indirect parameters buffers corresponding to the opaque 3D
436 // phase, since all our meshes are in that phase.
437 let Some(phase_indirect_parameters_buffers) =
438 indirect_parameters_buffers.get(&TypeId::of::<Opaque3d>())
439 else {
440 return Ok(());
441 };
442
443 // Grab both the buffers we're copying from and the staging buffers
444 // we're copying to. Remember that we can't map the indirect parameters
445 // buffers directly, so we have to copy their contents to a staging
446 // buffer.
447 let (
448 Some(indexed_data_buffer),
449 Some(indexed_batch_sets_buffer),
450 Some(indirect_parameters_staging_data_buffer),
451 Some(indirect_parameters_staging_batch_sets_buffer),
452 ) = (
453 phase_indirect_parameters_buffers.indexed.data_buffer(),
454 phase_indirect_parameters_buffers
455 .indexed
456 .batch_sets_buffer(),
457 indirect_parameters_mapping_buffers.data.as_ref(),
458 indirect_parameters_mapping_buffers.batch_sets.as_ref(),
459 )
460 else {
461 return Ok(());
462 };
463
464 // Copy from the indirect parameters buffers to the staging buffers.
465 render_context.command_encoder().copy_buffer_to_buffer(
466 indexed_data_buffer,
467 0,
468 indirect_parameters_staging_data_buffer,
469 0,
470 indexed_data_buffer.size(),
471 );
472 render_context.command_encoder().copy_buffer_to_buffer(
473 indexed_batch_sets_buffer,
474 0,
475 indirect_parameters_staging_batch_sets_buffer,
476 0,
477 indexed_batch_sets_buffer.size(),
478 );
479
480 Ok(())
481 }
482}
483
484/// Creates the staging buffers that we use to read back the indirect parameters
485/// from the GPU to the CPU.
486///
487/// We read the indirect parameters from the GPU to the CPU in order to display
488/// the number of meshes that were culled each frame.
489///
490/// We need these staging buffers because `wgpu` doesn't allow us to read the
491/// contents of the indirect parameters buffers directly. We must first copy
492/// them from the GPU to a staging buffer, and then read the staging buffer.
493fn create_indirect_parameters_staging_buffers(
494 mut indirect_parameters_staging_buffers: ResMut<IndirectParametersStagingBuffers>,
495 indirect_parameters_buffers: Res<IndirectParametersBuffers>,
496 render_device: Res<RenderDevice>,
497) {
498 let Some(phase_indirect_parameters_buffers) =
499 indirect_parameters_buffers.get(&TypeId::of::<Opaque3d>())
500 else {
501 return;
502 };
503
504 // Fetch the indirect parameters buffers that we're going to copy from.
505 let (Some(indexed_data_buffer), Some(indexed_batch_set_buffer)) = (
506 phase_indirect_parameters_buffers.indexed.data_buffer(),
507 phase_indirect_parameters_buffers
508 .indexed
509 .batch_sets_buffer(),
510 ) else {
511 return;
512 };
513
514 // Build the staging buffers. Make sure they have the same sizes as the
515 // buffers we're copying from.
516 indirect_parameters_staging_buffers.data =
517 Some(render_device.create_buffer(&BufferDescriptor {
518 label: Some("indexed data staging buffer"),
519 size: indexed_data_buffer.size(),
520 usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
521 mapped_at_creation: false,
522 }));
523 indirect_parameters_staging_buffers.batch_sets =
524 Some(render_device.create_buffer(&BufferDescriptor {
525 label: Some("indexed batch set staging buffer"),
526 size: indexed_batch_set_buffer.size(),
527 usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
528 mapped_at_creation: false,
529 }));
530}
375pub fn queue_colored_mesh2d(
376 transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
377 colored_mesh2d_pipeline: Res<ColoredMesh2dPipeline>,
378 mut pipelines: ResMut<SpecializedRenderPipelines<ColoredMesh2dPipeline>>,
379 pipeline_cache: Res<PipelineCache>,
380 render_meshes: Res<RenderAssets<RenderMesh>>,
381 render_mesh_instances: Res<RenderColoredMesh2dInstances>,
382 mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
383 views: Query<(&RenderVisibleEntities, &ExtractedView, &Msaa)>,
384) {
385 if render_mesh_instances.is_empty() {
386 return;
387 }
388 // Iterate each view (a camera is a view)
389 for (visible_entities, view, msaa) in &views {
390 let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity)
391 else {
392 continue;
393 };
394
395 let draw_colored_mesh2d = transparent_draw_functions.read().id::<DrawColoredMesh2d>();
396
397 let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples())
398 | Mesh2dPipelineKey::from_hdr(view.hdr);
399
400 // Queue all entities visible to that view
401 for (render_entity, visible_entity) in visible_entities.iter::<Mesh2d>() {
402 if let Some(mesh_instance) = render_mesh_instances.get(visible_entity) {
403 let mesh2d_handle = mesh_instance.mesh_asset_id;
404 let mesh2d_transforms = &mesh_instance.transforms;
405 // Get our specialized pipeline
406 let mut mesh2d_key = mesh_key;
407 let Some(mesh) = render_meshes.get(mesh2d_handle) else {
408 continue;
409 };
410 mesh2d_key |= Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology());
411
412 let pipeline_id =
413 pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh2d_key);
414
415 let mesh_z = mesh2d_transforms.world_from_local.translation.z;
416 transparent_phase.add(Transparent2d {
417 entity: (*render_entity, *visible_entity),
418 draw_function: draw_colored_mesh2d,
419 pipeline: pipeline_id,
420 // The 2d render items are sorted according to their z value before rendering,
421 // in order to get correct transparency
422 sort_key: FloatOrd(mesh_z),
423 // This material is not batched
424 batch_range: 0..1,
425 extra_index: PhaseItemExtraIndex::None,
426 extracted_index: usize::MAX,
427 indexed: mesh.indexed(),
428 });
429 }
430 }
431 }
432}
Sourcepub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
Returns the key-value pair corresponding to the supplied key.
Refer to get_key_value
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert_eq!(map.get_key_value("foo"), Some((&"foo", &0)));
Sourcepub fn get_key_value_mut<Q>(&mut self, k: &Q) -> Option<(&K, &mut V)>
pub fn get_key_value_mut<Q>(&mut self, k: &Q) -> Option<(&K, &mut V)>
Returns the key-value pair corresponding to the supplied key, with a mutable reference to value.
Refer to get_key_value_mut
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert_eq!(map.get_key_value_mut("foo"), Some((&"foo", &mut 0)));
Sourcepub fn contains_key<Q>(&self, k: &Q) -> bool
pub fn contains_key<Q>(&self, k: &Q) -> bool
Returns true
if the map contains a value for the specified key.
Refer to contains_key
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert!(map.contains_key("foo"));
Sourcepub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
Returns a mutable reference to the value corresponding to the key.
Refer to get_mut
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert_eq!(map.get_mut("foo"), Some(&mut 0));
Examples found in repository?
333fn update_color_grading_settings(
334 keys: Res<ButtonInput<KeyCode>>,
335 time: Res<Time>,
336 mut per_method_settings: ResMut<PerMethodSettings>,
337 tonemapping: Single<&Tonemapping>,
338 current_scene: Res<CurrentScene>,
339 mut selected_parameter: ResMut<SelectedParameter>,
340) {
341 let color_grading = per_method_settings.settings.get_mut(*tonemapping).unwrap();
342 let mut dt = time.delta_secs() * 0.25;
343 if keys.pressed(KeyCode::ArrowLeft) {
344 dt = -dt;
345 }
346
347 if keys.just_pressed(KeyCode::ArrowDown) {
348 selected_parameter.next();
349 }
350 if keys.just_pressed(KeyCode::ArrowUp) {
351 selected_parameter.prev();
352 }
353 if keys.pressed(KeyCode::ArrowLeft) || keys.pressed(KeyCode::ArrowRight) {
354 match selected_parameter.value {
355 0 => {
356 color_grading.global.exposure += dt;
357 }
358 1 => {
359 color_grading
360 .all_sections_mut()
361 .for_each(|section| section.gamma += dt);
362 }
363 2 => {
364 color_grading
365 .all_sections_mut()
366 .for_each(|section| section.saturation += dt);
367 }
368 3 => {
369 color_grading.global.post_saturation += dt;
370 }
371 _ => {}
372 }
373 }
374
375 if keys.just_pressed(KeyCode::Space) {
376 for (_, grading) in per_method_settings.settings.iter_mut() {
377 *grading = ColorGrading::default();
378 }
379 }
380
381 if keys.just_pressed(KeyCode::Enter) && current_scene.0 == 1 {
382 for (mapper, grading) in per_method_settings.settings.iter_mut() {
383 *grading = PerMethodSettings::basic_scene_recommendation(*mapper);
384 }
385 }
386}
More examples
126fn queue_custom(
127 transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
128 custom_pipeline: Res<CustomPipeline>,
129 mut pipelines: ResMut<SpecializedMeshPipelines<CustomPipeline>>,
130 pipeline_cache: Res<PipelineCache>,
131 meshes: Res<RenderAssets<RenderMesh>>,
132 render_mesh_instances: Res<RenderMeshInstances>,
133 material_meshes: Query<(Entity, &MainEntity), With<InstanceMaterialData>>,
134 mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
135 views: Query<(&ExtractedView, &Msaa)>,
136) {
137 let draw_custom = transparent_3d_draw_functions.read().id::<DrawCustom>();
138
139 for (view, msaa) in &views {
140 let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity)
141 else {
142 continue;
143 };
144
145 let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples());
146
147 let view_key = msaa_key | MeshPipelineKey::from_hdr(view.hdr);
148 let rangefinder = view.rangefinder3d();
149 for (entity, main_entity) in &material_meshes {
150 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*main_entity)
151 else {
152 continue;
153 };
154 let Some(mesh) = meshes.get(mesh_instance.mesh_asset_id) else {
155 continue;
156 };
157 let key =
158 view_key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
159 let pipeline = pipelines
160 .specialize(&pipeline_cache, &custom_pipeline, key, &mesh.layout)
161 .unwrap();
162 transparent_phase.add(Transparent3d {
163 entity: (entity, *main_entity),
164 pipeline,
165 draw_function: draw_custom,
166 distance: rangefinder.distance_translation(&mesh_instance.translation),
167 batch_range: 0..1,
168 extra_index: PhaseItemExtraIndex::None,
169 indexed: true,
170 });
171 }
172 }
173}
375pub fn queue_colored_mesh2d(
376 transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
377 colored_mesh2d_pipeline: Res<ColoredMesh2dPipeline>,
378 mut pipelines: ResMut<SpecializedRenderPipelines<ColoredMesh2dPipeline>>,
379 pipeline_cache: Res<PipelineCache>,
380 render_meshes: Res<RenderAssets<RenderMesh>>,
381 render_mesh_instances: Res<RenderColoredMesh2dInstances>,
382 mut transparent_render_phases: ResMut<ViewSortedRenderPhases<Transparent2d>>,
383 views: Query<(&RenderVisibleEntities, &ExtractedView, &Msaa)>,
384) {
385 if render_mesh_instances.is_empty() {
386 return;
387 }
388 // Iterate each view (a camera is a view)
389 for (visible_entities, view, msaa) in &views {
390 let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity)
391 else {
392 continue;
393 };
394
395 let draw_colored_mesh2d = transparent_draw_functions.read().id::<DrawColoredMesh2d>();
396
397 let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples())
398 | Mesh2dPipelineKey::from_hdr(view.hdr);
399
400 // Queue all entities visible to that view
401 for (render_entity, visible_entity) in visible_entities.iter::<Mesh2d>() {
402 if let Some(mesh_instance) = render_mesh_instances.get(visible_entity) {
403 let mesh2d_handle = mesh_instance.mesh_asset_id;
404 let mesh2d_transforms = &mesh_instance.transforms;
405 // Get our specialized pipeline
406 let mut mesh2d_key = mesh_key;
407 let Some(mesh) = render_meshes.get(mesh2d_handle) else {
408 continue;
409 };
410 mesh2d_key |= Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology());
411
412 let pipeline_id =
413 pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh2d_key);
414
415 let mesh_z = mesh2d_transforms.world_from_local.translation.z;
416 transparent_phase.add(Transparent2d {
417 entity: (*render_entity, *visible_entity),
418 draw_function: draw_colored_mesh2d,
419 pipeline: pipeline_id,
420 // The 2d render items are sorted according to their z value before rendering,
421 // in order to get correct transparency
422 sort_key: FloatOrd(mesh_z),
423 // This material is not batched
424 batch_range: 0..1,
425 extra_index: PhaseItemExtraIndex::None,
426 extracted_index: usize::MAX,
427 indexed: mesh.indexed(),
428 });
429 }
430 }
431 }
432}
222fn queue_custom_phase_item(
223 pipeline_cache: Res<PipelineCache>,
224 custom_phase_pipeline: Res<CustomPhasePipeline>,
225 mut opaque_render_phases: ResMut<ViewBinnedRenderPhases<Opaque3d>>,
226 opaque_draw_functions: Res<DrawFunctions<Opaque3d>>,
227 mut specialized_render_pipelines: ResMut<SpecializedRenderPipelines<CustomPhasePipeline>>,
228 views: Query<(&ExtractedView, &RenderVisibleEntities, &Msaa)>,
229 mut next_tick: Local<Tick>,
230) {
231 let draw_custom_phase_item = opaque_draw_functions
232 .read()
233 .id::<DrawCustomPhaseItemCommands>();
234
235 // Render phases are per-view, so we need to iterate over all views so that
236 // the entity appears in them. (In this example, we have only one view, but
237 // it's good practice to loop over all views anyway.)
238 for (view, view_visible_entities, msaa) in views.iter() {
239 let Some(opaque_phase) = opaque_render_phases.get_mut(&view.retained_view_entity) else {
240 continue;
241 };
242
243 // Find all the custom rendered entities that are visible from this
244 // view.
245 for &entity in view_visible_entities.get::<CustomRenderedEntity>().iter() {
246 // Ordinarily, the [`SpecializedRenderPipeline::Key`] would contain
247 // some per-view settings, such as whether the view is HDR, but for
248 // simplicity's sake we simply hard-code the view's characteristics,
249 // with the exception of number of MSAA samples.
250 let pipeline_id = specialized_render_pipelines.specialize(
251 &pipeline_cache,
252 &custom_phase_pipeline,
253 *msaa,
254 );
255
256 // Bump the change tick in order to force Bevy to rebuild the bin.
257 let this_tick = next_tick.get() + 1;
258 next_tick.set(this_tick);
259
260 // Add the custom render item. We use the
261 // [`BinnedRenderPhaseType::NonMesh`] type to skip the special
262 // handling that Bevy has for meshes (preprocessing, indirect
263 // draws, etc.)
264 //
265 // The asset ID is arbitrary; we simply use [`AssetId::invalid`],
266 // but you can use anything you like. Note that the asset ID need
267 // not be the ID of a [`Mesh`].
268 opaque_phase.add(
269 Opaque3dBatchSetKey {
270 draw_function: draw_custom_phase_item,
271 pipeline: pipeline_id,
272 material_bind_group_index: None,
273 lightmap_slab: None,
274 vertex_slab: default(),
275 index_slab: None,
276 },
277 Opaque3dBinKey {
278 asset_id: AssetId::<Mesh>::invalid().untyped(),
279 },
280 entity,
281 InputUniformIndex::default(),
282 BinnedRenderPhaseType::NonMesh,
283 *next_tick,
284 );
285 }
286 }
287}
500fn queue_custom_meshes(
501 custom_draw_functions: Res<DrawFunctions<Stencil3d>>,
502 mut pipelines: ResMut<SpecializedMeshPipelines<StencilPipeline>>,
503 pipeline_cache: Res<PipelineCache>,
504 custom_draw_pipeline: Res<StencilPipeline>,
505 render_meshes: Res<RenderAssets<RenderMesh>>,
506 render_mesh_instances: Res<RenderMeshInstances>,
507 mut custom_render_phases: ResMut<ViewSortedRenderPhases<Stencil3d>>,
508 mut views: Query<(&ExtractedView, &RenderVisibleEntities, &Msaa)>,
509 has_marker: Query<(), With<DrawStencil>>,
510) {
511 for (view, visible_entities, msaa) in &mut views {
512 let Some(custom_phase) = custom_render_phases.get_mut(&view.retained_view_entity) else {
513 continue;
514 };
515 let draw_custom = custom_draw_functions.read().id::<DrawMesh3dStencil>();
516
517 // Create the key based on the view.
518 // In this case we only care about MSAA and HDR
519 let view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
520 | MeshPipelineKey::from_hdr(view.hdr);
521
522 let rangefinder = view.rangefinder3d();
523 // Since our phase can work on any 3d mesh we can reuse the default mesh 3d filter
524 for (render_entity, visible_entity) in visible_entities.iter::<Mesh3d>() {
525 // We only want meshes with the marker component to be queued to our phase.
526 if has_marker.get(*render_entity).is_err() {
527 continue;
528 }
529 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(*visible_entity)
530 else {
531 continue;
532 };
533 let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
534 continue;
535 };
536
537 // Specialize the key for the current mesh entity
538 // For this example we only specialize based on the mesh topology
539 // but you could have more complex keys and that's where you'd need to create those keys
540 let mut mesh_key = view_key;
541 mesh_key |= MeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
542
543 let pipeline_id = pipelines.specialize(
544 &pipeline_cache,
545 &custom_draw_pipeline,
546 mesh_key,
547 &mesh.layout,
548 );
549 let pipeline_id = match pipeline_id {
550 Ok(id) => id,
551 Err(err) => {
552 error!("{}", err);
553 continue;
554 }
555 };
556 let distance = rangefinder.distance_translation(&mesh_instance.translation);
557 // At this point we have all the data we need to create a phase item and add it to our
558 // phase
559 custom_phase.add(Stencil3d {
560 // Sort the data based on the distance to the view
561 sort_key: FloatOrd(distance),
562 entity: (*render_entity, *visible_entity),
563 pipeline: pipeline_id,
564 draw_function: draw_custom,
565 // Sorted phase items aren't batched
566 batch_range: 0..1,
567 extra_index: PhaseItemExtraIndex::None,
568 indexed: mesh.indexed(),
569 });
570 }
571 }
572}
274fn queue_custom_mesh_pipeline(
275 pipeline_cache: Res<PipelineCache>,
276 custom_mesh_pipeline: Res<CustomMeshPipeline>,
277 (mut opaque_render_phases, opaque_draw_functions): (
278 ResMut<ViewBinnedRenderPhases<Opaque3d>>,
279 Res<DrawFunctions<Opaque3d>>,
280 ),
281 mut specialized_mesh_pipelines: ResMut<SpecializedMeshPipelines<CustomMeshPipeline>>,
282 views: Query<(
283 &RenderVisibleEntities,
284 &ExtractedView,
285 &Msaa,
286 Has<NoIndirectDrawing>,
287 Has<OcclusionCulling>,
288 )>,
289 (render_meshes, render_mesh_instances): (
290 Res<RenderAssets<RenderMesh>>,
291 Res<RenderMeshInstances>,
292 ),
293 param: StaticSystemParam<<MeshPipeline as GetBatchData>::Param>,
294 mut phase_batched_instance_buffers: ResMut<
295 PhaseBatchedInstanceBuffers<Opaque3d, <MeshPipeline as GetBatchData>::BufferData>,
296 >,
297 mut phase_indirect_parameters_buffers: ResMut<PhaseIndirectParametersBuffers<Opaque3d>>,
298 mut change_tick: Local<Tick>,
299) {
300 let system_param_item = param.into_inner();
301
302 let UntypedPhaseBatchedInstanceBuffers {
303 ref mut data_buffer,
304 ref mut work_item_buffers,
305 ref mut late_indexed_indirect_parameters_buffer,
306 ref mut late_non_indexed_indirect_parameters_buffer,
307 ..
308 } = phase_batched_instance_buffers.buffers;
309
310 // Get the id for our custom draw function
311 let draw_function_id = opaque_draw_functions
312 .read()
313 .id::<DrawSpecializedPipelineCommands>();
314
315 // Render phases are per-view, so we need to iterate over all views so that
316 // the entity appears in them. (In this example, we have only one view, but
317 // it's good practice to loop over all views anyway.)
318 for (view_visible_entities, view, msaa, no_indirect_drawing, gpu_occlusion_culling) in
319 views.iter()
320 {
321 let Some(opaque_phase) = opaque_render_phases.get_mut(&view.retained_view_entity) else {
322 continue;
323 };
324
325 // Create *work item buffers* if necessary. Work item buffers store the
326 // indices of meshes that are to be rendered when indirect drawing is
327 // enabled.
328 let work_item_buffer = gpu_preprocessing::get_or_create_work_item_buffer::<Opaque3d>(
329 work_item_buffers,
330 view.retained_view_entity,
331 no_indirect_drawing,
332 gpu_occlusion_culling,
333 );
334
335 // Initialize those work item buffers in preparation for this new frame.
336 gpu_preprocessing::init_work_item_buffers(
337 work_item_buffer,
338 late_indexed_indirect_parameters_buffer,
339 late_non_indexed_indirect_parameters_buffer,
340 );
341
342 // Create the key based on the view. In this case we only care about MSAA and HDR
343 let view_key = MeshPipelineKey::from_msaa_samples(msaa.samples())
344 | MeshPipelineKey::from_hdr(view.hdr);
345
346 // Set up a slot to hold information about the batch set we're going to
347 // create. If there are any of our custom meshes in the scene, we'll
348 // need this information in order for Bevy to kick off the rendering.
349 let mut mesh_batch_set_info = None;
350
351 // Find all the custom rendered entities that are visible from this
352 // view.
353 for &(render_entity, visible_entity) in
354 view_visible_entities.get::<CustomRenderedEntity>().iter()
355 {
356 // Get the mesh instance
357 let Some(mesh_instance) = render_mesh_instances.render_mesh_queue_data(visible_entity)
358 else {
359 continue;
360 };
361
362 // Get the mesh data
363 let Some(mesh) = render_meshes.get(mesh_instance.mesh_asset_id) else {
364 continue;
365 };
366
367 // Specialize the key for the current mesh entity
368 // For this example we only specialize based on the mesh topology
369 // but you could have more complex keys and that's where you'd need to create those keys
370 let mut mesh_key = view_key;
371 mesh_key |= MeshPipelineKey::from_primitive_topology(mesh.primitive_topology());
372
373 // Initialize the batch set information if this was the first custom
374 // mesh we saw. We'll need that information later to create the
375 // batch set.
376 if mesh_batch_set_info.is_none() {
377 mesh_batch_set_info = Some(MeshBatchSetInfo {
378 indirect_parameters_index: phase_indirect_parameters_buffers
379 .buffers
380 .allocate(mesh.indexed(), 1),
381 is_indexed: mesh.indexed(),
382 });
383 }
384 let mesh_info = mesh_batch_set_info.unwrap();
385
386 // Allocate some input and output indices. We'll need these to
387 // create the *work item* below.
388 let Some(input_index) =
389 MeshPipeline::get_binned_index(&system_param_item, visible_entity)
390 else {
391 continue;
392 };
393 let output_index = data_buffer.add() as u32;
394
395 // Finally, we can specialize the pipeline based on the key
396 let pipeline_id = specialized_mesh_pipelines
397 .specialize(
398 &pipeline_cache,
399 &custom_mesh_pipeline,
400 mesh_key,
401 &mesh.layout,
402 )
403 // This should never with this example, but if your pipeline specialization
404 // can fail you need to handle the error here
405 .expect("Failed to specialize mesh pipeline");
406
407 // Bump the change tick so that Bevy is forced to rebuild the bin.
408 let next_change_tick = change_tick.get() + 1;
409 change_tick.set(next_change_tick);
410
411 // Add the mesh with our specialized pipeline
412 opaque_phase.add(
413 Opaque3dBatchSetKey {
414 draw_function: draw_function_id,
415 pipeline: pipeline_id,
416 material_bind_group_index: None,
417 vertex_slab: default(),
418 index_slab: None,
419 lightmap_slab: None,
420 },
421 // The asset ID is arbitrary; we simply use [`AssetId::invalid`],
422 // but you can use anything you like. Note that the asset ID need
423 // not be the ID of a [`Mesh`].
424 Opaque3dBinKey {
425 asset_id: AssetId::<Mesh>::invalid().untyped(),
426 },
427 (render_entity, visible_entity),
428 mesh_instance.current_uniform_index,
429 // This example supports batching, but if your pipeline doesn't
430 // support it you can use `BinnedRenderPhaseType::UnbatchableMesh`
431 BinnedRenderPhaseType::BatchableMesh,
432 *change_tick,
433 );
434
435 // Create a *work item*. A work item tells the Bevy renderer to
436 // transform the mesh on GPU.
437 work_item_buffer.push(
438 mesh.indexed(),
439 PreprocessWorkItem {
440 input_index: input_index.into(),
441 output_or_indirect_parameters_index: if no_indirect_drawing {
442 output_index
443 } else {
444 mesh_info.indirect_parameters_index
445 },
446 },
447 );
448 }
449
450 // Now if there were any meshes, we need to add a command to the
451 // indirect parameters buffer, so that the renderer will end up
452 // enqueuing a command to draw the mesh.
453 if let Some(mesh_info) = mesh_batch_set_info {
454 phase_indirect_parameters_buffers
455 .buffers
456 .add_batch_set(mesh_info.is_indexed, mesh_info.indirect_parameters_index);
457 }
458 }
459}
Sourcepub fn get_many_mut<Q, const N: usize>(
&mut self,
ks: [&Q; N],
) -> [Option<&mut V>; N]
pub fn get_many_mut<Q, const N: usize>( &mut self, ks: [&Q; N], ) -> [Option<&mut V>; N]
Attempts to get mutable references to N
values in the map at once.
Refer to get_many_mut
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
let result = map.get_many_mut(["foo", "bar"]);
assert_eq!(result, [Some(&mut 0), Some(&mut 1)]);
Sourcepub fn get_many_key_value_mut<Q, const N: usize>(
&mut self,
ks: [&Q; N],
) -> [Option<(&K, &mut V)>; N]
pub fn get_many_key_value_mut<Q, const N: usize>( &mut self, ks: [&Q; N], ) -> [Option<(&K, &mut V)>; N]
Attempts to get mutable references to N
values in the map at once, with immutable
references to the corresponding keys.
Refer to get_many_key_value_mut
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
map.insert("bar", 1);
map.insert("baz", 2);
let result = map.get_many_key_value_mut(["foo", "bar"]);
assert_eq!(result, [Some((&"foo", &mut 0)), Some((&"bar", &mut 1))]);
Sourcepub fn insert(&mut self, k: K, v: V) -> Option<V>
pub fn insert(&mut self, k: K, v: V) -> Option<V>
Inserts a key-value pair into the map.
Refer to insert
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert_eq!(map.get("foo"), Some(&0));
Examples found in repository?
More examples
574 fn default() -> Self {
575 let mut settings = <HashMap<_, _>>::default();
576
577 for method in [
578 Tonemapping::None,
579 Tonemapping::Reinhard,
580 Tonemapping::ReinhardLuminance,
581 Tonemapping::AcesFitted,
582 Tonemapping::AgX,
583 Tonemapping::SomewhatBoringDisplayTransform,
584 Tonemapping::TonyMcMapface,
585 Tonemapping::BlenderFilmic,
586 ] {
587 settings.insert(
588 method,
589 PerMethodSettings::basic_scene_recommendation(method),
590 );
591 }
592
593 Self { settings }
594 }
328pub fn extract_colored_mesh2d(
329 mut commands: Commands,
330 mut previous_len: Local<usize>,
331 // When extracting, you must use `Extract` to mark the `SystemParam`s
332 // which should be taken from the main world.
333 query: Extract<
334 Query<
335 (
336 Entity,
337 RenderEntity,
338 &ViewVisibility,
339 &GlobalTransform,
340 &Mesh2d,
341 ),
342 With<ColoredMesh2d>,
343 >,
344 >,
345 mut render_mesh_instances: ResMut<RenderColoredMesh2dInstances>,
346) {
347 let mut values = Vec::with_capacity(*previous_len);
348 for (entity, render_entity, view_visibility, transform, handle) in &query {
349 if !view_visibility.get() {
350 continue;
351 }
352
353 let transforms = Mesh2dTransforms {
354 world_from_local: (&transform.affine()).into(),
355 flags: MeshFlags::empty().bits(),
356 };
357
358 values.push((render_entity, ColoredMesh2d));
359 render_mesh_instances.insert(
360 entity.into(),
361 RenderMesh2dInstance {
362 mesh_asset_id: handle.0.id(),
363 transforms,
364 material_bind_group_id: Material2dBindGroupId::default(),
365 automatic_batching: false,
366 tag: 0,
367 },
368 );
369 }
370 *previous_len = values.len();
371 commands.try_insert_batch(values);
372}
67fn setup() {
68 let mut z = <HashMap<_, _>>::default();
69 z.insert("Hello".to_string(), 1.0);
70 let value: Box<dyn Reflect> = Box::new(A {
71 x: 1,
72 y: vec![1, 2],
73 z,
74 });
75
76 // There are a number of different "reflect traits", which each expose different operations on
77 // the underlying type
78 match value.reflect_ref() {
79 // `Struct` is a trait automatically implemented for structs that derive Reflect. This trait
80 // allows you to interact with fields via their string names or indices
81 ReflectRef::Struct(value) => {
82 info!(
83 "This is a 'struct' type with an 'x' value of {}",
84 value.get_field::<usize>("x").unwrap()
85 );
86 }
87 // `TupleStruct` is a trait automatically implemented for tuple structs that derive Reflect.
88 // This trait allows you to interact with fields via their indices
89 ReflectRef::TupleStruct(_) => {}
90 // `Tuple` is a special trait that can be manually implemented (instead of deriving
91 // Reflect). This exposes "tuple" operations on your type, allowing you to interact
92 // with fields via their indices. Tuple is automatically implemented for tuples of
93 // arity 12 or less.
94 ReflectRef::Tuple(_) => {}
95 // `Enum` is a trait automatically implemented for enums that derive Reflect. This trait allows you
96 // to interact with the current variant and its fields (if it has any)
97 ReflectRef::Enum(_) => {}
98 // `List` is a special trait that can be manually implemented (instead of deriving Reflect).
99 // This exposes "list" operations on your type, such as insertion. `List` is automatically
100 // implemented for relevant core types like Vec<T>.
101 ReflectRef::List(_) => {}
102 // `Array` is a special trait that can be manually implemented (instead of deriving Reflect).
103 // This exposes "array" operations on your type, such as indexing. `Array`
104 // is automatically implemented for relevant core types like [T; N].
105 ReflectRef::Array(_) => {}
106 // `Map` is a special trait that can be manually implemented (instead of deriving Reflect).
107 // This exposes "map" operations on your type, such as getting / inserting by key.
108 // Map is automatically implemented for relevant core types like HashMap<K, V>
109 ReflectRef::Map(_) => {}
110 // `Set` is a special trait that can be manually implemented (instead of deriving Reflect).
111 // This exposes "set" operations on your type, such as getting / inserting by value.
112 // Set is automatically implemented for relevant core types like HashSet<T>
113 ReflectRef::Set(_) => {}
114 // `Function` is a special trait that can be manually implemented (instead of deriving Reflect).
115 // This exposes "function" operations on your type, such as calling it with arguments.
116 // This trait is automatically implemented for types like DynamicFunction.
117 // This variant only exists if the `reflect_functions` feature is enabled.
118 #[cfg(feature = "reflect_functions")]
119 ReflectRef::Function(_) => {}
120 // `Opaque` types do not implement any of the other traits above. They are simply a Reflect
121 // implementation. Opaque is implemented for opaque types like String and Instant,
122 // but also include primitive types like i32, usize, and f32 (despite not technically being opaque).
123 ReflectRef::Opaque(_) => {}
124 #[expect(
125 clippy::allow_attributes,
126 reason = "`unreachable_patterns` is not always linted"
127 )]
128 #[allow(
129 unreachable_patterns,
130 reason = "This example cannot always detect when `bevy_reflect/functions` is enabled."
131 )]
132 _ => {}
133 }
134
135 let mut dynamic_list = DynamicList::default();
136 dynamic_list.push(3u32);
137 dynamic_list.push(4u32);
138 dynamic_list.push(5u32);
139
140 let mut value: A = value.take::<A>().unwrap();
141 value.y.apply(&dynamic_list);
142 assert_eq!(value.y, vec![3u32, 4u32, 5u32]);
143}
103fn setup_ui(
104 mut commands: Commands,
105 mut directional_nav_map: ResMut<DirectionalNavigationMap>,
106 mut input_focus: ResMut<InputFocus>,
107) {
108 const N_ROWS: u16 = 5;
109 const N_COLS: u16 = 3;
110
111 // Rendering UI elements requires a camera
112 commands.spawn(Camera2d);
113
114 // Create a full-screen background node
115 let root_node = commands
116 .spawn(Node {
117 width: Val::Percent(100.0),
118 height: Val::Percent(100.0),
119 ..default()
120 })
121 .id();
122
123 // Add instruction to the left of the grid
124 let instructions = commands
125 .spawn((
126 Text::new("Use arrow keys or D-pad to navigate. \
127 Click the buttons, or press Enter / the South gamepad button to interact with the focused button."),
128 Node {
129 width: Val::Px(300.0),
130 justify_content: JustifyContent::Center,
131 align_items: AlignItems::Center,
132 margin: UiRect::all(Val::Px(12.0)),
133 ..default()
134 },
135 ))
136 .id();
137
138 // Set up the root entity to hold the grid
139 let grid_root_entity = commands
140 .spawn(Node {
141 display: Display::Grid,
142 // Allow the grid to take up the full height and the rest of the width of the window
143 width: Val::Percent(100.),
144 height: Val::Percent(100.),
145 // Set the number of rows and columns in the grid
146 // allowing the grid to automatically size the cells
147 grid_template_columns: RepeatedGridTrack::auto(N_COLS),
148 grid_template_rows: RepeatedGridTrack::auto(N_ROWS),
149 ..default()
150 })
151 .id();
152
153 // Add the instructions and grid to the root node
154 commands
155 .entity(root_node)
156 .add_children(&[instructions, grid_root_entity]);
157
158 let mut button_entities: HashMap<(u16, u16), Entity> = HashMap::default();
159 for row in 0..N_ROWS {
160 for col in 0..N_COLS {
161 let button_name = format!("Button {}-{}", row, col);
162
163 let button_entity = commands
164 .spawn((
165 Button,
166 Node {
167 width: Val::Px(200.0),
168 height: Val::Px(120.0),
169 // Add a border so we can show which element is focused
170 border: UiRect::all(Val::Px(4.0)),
171 // Center the button's text label
172 justify_content: JustifyContent::Center,
173 align_items: AlignItems::Center,
174 // Center the button within the grid cell
175 align_self: AlignSelf::Center,
176 justify_self: JustifySelf::Center,
177 ..default()
178 },
179 ResetTimer::default(),
180 BorderRadius::all(Val::Px(16.0)),
181 BackgroundColor::from(NORMAL_BUTTON),
182 Name::new(button_name.clone()),
183 ))
184 // Add a text element to the button
185 .with_child((
186 Text::new(button_name),
187 // And center the text if it flows onto multiple lines
188 TextLayout {
189 justify: JustifyText::Center,
190 ..default()
191 },
192 ))
193 .id();
194
195 // Add the button to the grid
196 commands.entity(grid_root_entity).add_child(button_entity);
197
198 // Keep track of the button entities so we can set up our navigation graph
199 button_entities.insert((row, col), button_entity);
200 }
201 }
202
203 // Connect all of the buttons in the same row to each other,
204 // looping around when the edge is reached.
205 for row in 0..N_ROWS {
206 let entities_in_row: Vec<Entity> = (0..N_COLS)
207 .map(|col| button_entities.get(&(row, col)).unwrap())
208 .copied()
209 .collect();
210 directional_nav_map.add_looping_edges(&entities_in_row, CompassOctant::East);
211 }
212
213 // Connect all of the buttons in the same column to each other,
214 // but don't loop around when the edge is reached.
215 // While looping is a very reasonable choice, we're not doing it here to demonstrate the different options.
216 for col in 0..N_COLS {
217 let entities_in_column: Vec<Entity> = (0..N_ROWS)
218 .map(|row| button_entities.get(&(row, col)).unwrap())
219 .copied()
220 .collect();
221
222 directional_nav_map.add_edges(&entities_in_column, CompassOctant::South);
223 }
224
225 // When changing scenes, remember to set an initial focus!
226 let top_left_entity = *button_entities.get(&(0, 0)).unwrap();
227 input_focus.set(top_left_entity);
228}
Sourcepub fn try_insert(
&mut self,
key: K,
value: V,
) -> Result<&mut V, OccupiedError<'_, K, V, S>>
pub fn try_insert( &mut self, key: K, value: V, ) -> Result<&mut V, OccupiedError<'_, K, V, S>>
Tries to insert a key-value pair into the map, and returns a mutable reference to the value in the entry.
Refer to try_insert
for further details.
§Examples
let mut map = HashMap::new();
map.try_insert("foo", 0).unwrap();
assert!(map.try_insert("foo", 1).is_err());
Sourcepub fn remove<Q>(&mut self, k: &Q) -> Option<V>
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
Sourcepub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)>
pub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)>
Removes a key from the map, returning the stored key and value if the key was previously in the map. Keeps the allocated memory for reuse.
Refer to remove_entry
for further details.
§Examples
let mut map = HashMap::new();
map.insert("foo", 0);
assert_eq!(map.remove_entry("foo"), Some(("foo", 0)));
assert!(map.is_empty());
Sourcepub fn allocation_size(&self) -> usize
pub fn allocation_size(&self) -> usize
Returns the total amount of memory allocated internally by the hash set, in bytes.
Refer to allocation_size
for further details.
§Examples
let mut map = HashMap::new();
assert_eq!(map.allocation_size(), 0);
map.insert("foo", 0u32);
assert!(map.allocation_size() >= size_of::<&'static str>() + size_of::<u32>());
Sourcepub unsafe fn insert_unique_unchecked(
&mut self,
key: K,
value: V,
) -> (&K, &mut V)
pub unsafe fn insert_unique_unchecked( &mut self, key: K, value: V, ) -> (&K, &mut V)
Insert a key-value pair into the map without checking if the key already exists in the map.
Refer to insert_unique_unchecked
for further details.
§Safety
This operation is safe if a key does not exist in the map.
However, if a key exists in the map already, the behavior is unspecified: this operation may panic, loop forever, or any following operation with the map may panic, loop forever or return arbitrary result.
That said, this operation (and following operations) are guaranteed to not violate memory safety.
However this operation is still unsafe because the resulting HashMap
may be passed to unsafe code which does expect the map to behave
correctly, and would cause unsoundness as a result.
Sourcepub unsafe fn get_many_unchecked_mut<Q, const N: usize>(
&mut self,
keys: [&Q; N],
) -> [Option<&mut V>; N]
pub unsafe fn get_many_unchecked_mut<Q, const N: usize>( &mut self, keys: [&Q; N], ) -> [Option<&mut V>; N]
Attempts to get mutable references to N
values in the map at once, without validating that
the values are unique.
Refer to get_many_unchecked_mut
for further details.
Returns an array of length N
with the results of each query. None
will be used if
the key is missing.
For a safe alternative see get_many_mut
.
§Safety
Calling this method with overlapping keys is undefined behavior even if the resulting references are not used.
Sourcepub unsafe fn get_many_key_value_unchecked_mut<Q, const N: usize>(
&mut self,
keys: [&Q; N],
) -> [Option<(&K, &mut V)>; N]
pub unsafe fn get_many_key_value_unchecked_mut<Q, const N: usize>( &mut self, keys: [&Q; N], ) -> [Option<(&K, &mut V)>; N]
Attempts to get mutable references to N
values in the map at once, with immutable
references to the corresponding keys, without validating that the values are unique.
Refer to get_many_key_value_unchecked_mut
for further details.
Returns an array of length N
with the results of each query. None
will be returned if
any of the keys are missing.
For a safe alternative see get_many_key_value_mut
.
§Safety
Calling this method with overlapping keys is undefined behavior even if the resulting references are not used.
Methods from Deref<Target = HashMap<K, V, S>>§
Sourcepub fn hasher(&self) -> &S
pub fn hasher(&self) -> &S
Returns a reference to the map’s BuildHasher
.
§Examples
use hashbrown::HashMap;
use hashbrown::DefaultHashBuilder;
let hasher = DefaultHashBuilder::default();
let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
let hasher: &DefaultHashBuilder = map.hasher();
Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the number of elements the map can hold without reallocating.
This number is a lower bound; the HashMap<K, V>
might be able to hold
more, but is guaranteed to be able to hold at least this many.
§Examples
use hashbrown::HashMap;
let map: HashMap<i32, i32> = HashMap::with_capacity(100);
assert_eq!(map.len(), 0);
assert!(map.capacity() >= 100);
Sourcepub fn keys(&self) -> Keys<'_, K, V> ⓘ
pub fn keys(&self) -> Keys<'_, K, V> ⓘ
An iterator visiting all keys in arbitrary order.
The iterator element type is &'a K
.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
assert_eq!(map.len(), 3);
let mut vec: Vec<&str> = Vec::new();
for key in map.keys() {
println!("{}", key);
vec.push(*key);
}
// The `Keys` iterator produces keys in arbitrary order, so the
// keys must be sorted to test them against a sorted array.
vec.sort_unstable();
assert_eq!(vec, ["a", "b", "c"]);
assert_eq!(map.len(), 3);
Sourcepub fn values(&self) -> Values<'_, K, V> ⓘ
pub fn values(&self) -> Values<'_, K, V> ⓘ
An iterator visiting all values in arbitrary order.
The iterator element type is &'a V
.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
assert_eq!(map.len(), 3);
let mut vec: Vec<i32> = Vec::new();
for val in map.values() {
println!("{}", val);
vec.push(*val);
}
// The `Values` iterator produces values in arbitrary order, so the
// values must be sorted to test them against a sorted array.
vec.sort_unstable();
assert_eq!(vec, [1, 2, 3]);
assert_eq!(map.len(), 3);
Sourcepub fn values_mut(&mut self) -> ValuesMut<'_, K, V> ⓘ
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> ⓘ
An iterator visiting all values mutably in arbitrary order.
The iterator element type is &'a mut V
.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
for val in map.values_mut() {
*val = *val + 10;
}
assert_eq!(map.len(), 3);
let mut vec: Vec<i32> = Vec::new();
for val in map.values() {
println!("{}", val);
vec.push(*val);
}
// The `Values` iterator produces values in arbitrary order, so the
// values must be sorted to test them against a sorted array.
vec.sort_unstable();
assert_eq!(vec, [11, 12, 13]);
assert_eq!(map.len(), 3);
Sourcepub fn iter(&self) -> Iter<'_, K, V> ⓘ
pub fn iter(&self) -> Iter<'_, K, V> ⓘ
An iterator visiting all key-value pairs in arbitrary order.
The iterator element type is (&'a K, &'a V)
.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
assert_eq!(map.len(), 3);
let mut vec: Vec<(&str, i32)> = Vec::new();
for (key, val) in map.iter() {
println!("key: {} val: {}", key, val);
vec.push((*key, *val));
}
// The `Iter` iterator produces items in arbitrary order, so the
// items must be sorted to test them against a sorted array.
vec.sort_unstable();
assert_eq!(vec, [("a", 1), ("b", 2), ("c", 3)]);
assert_eq!(map.len(), 3);
Sourcepub fn iter_mut(&mut self) -> IterMut<'_, K, V> ⓘ
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> ⓘ
An iterator visiting all key-value pairs in arbitrary order,
with mutable references to the values.
The iterator element type is (&'a K, &'a mut V)
.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert("a", 1);
map.insert("b", 2);
map.insert("c", 3);
// Update all values
for (_, val) in map.iter_mut() {
*val *= 2;
}
assert_eq!(map.len(), 3);
let mut vec: Vec<(&str, i32)> = Vec::new();
for (key, val) in &map {
println!("key: {} val: {}", key, val);
vec.push((*key, *val));
}
// The `Iter` iterator produces items in arbitrary order, so the
// items must be sorted to test them against a sorted array.
vec.sort_unstable();
assert_eq!(vec, [("a", 2), ("b", 4), ("c", 6)]);
assert_eq!(map.len(), 3);
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements in the map.
§Examples
use hashbrown::HashMap;
let mut a = HashMap::new();
assert_eq!(a.len(), 0);
a.insert(1, "a");
assert_eq!(a.len(), 1);
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if the map contains no elements.
§Examples
use hashbrown::HashMap;
let mut a = HashMap::new();
assert!(a.is_empty());
a.insert(1, "a");
assert!(!a.is_empty());
Sourcepub fn drain(&mut self) -> Drain<'_, K, V, A> ⓘ
pub fn drain(&mut self) -> Drain<'_, K, V, A> ⓘ
Clears the map, returning all key-value pairs as an iterator. Keeps the allocated memory for reuse.
If the returned iterator is dropped before being fully consumed, it drops the remaining key-value pairs. The returned iterator keeps a mutable borrow on the vector to optimize its implementation.
§Examples
use hashbrown::HashMap;
let mut a = HashMap::new();
a.insert(1, "a");
a.insert(2, "b");
let capacity_before_drain = a.capacity();
for (k, v) in a.drain().take(1) {
assert!(k == 1 || k == 2);
assert!(v == "a" || v == "b");
}
// As we can see, the map is empty and contains no element.
assert!(a.is_empty() && a.len() == 0);
// But map capacity is equal to old one.
assert_eq!(a.capacity(), capacity_before_drain);
let mut a = HashMap::new();
a.insert(1, "a");
a.insert(2, "b");
{ // Iterator is dropped without being consumed.
let d = a.drain();
}
// But the map is empty even if we do not use Drain iterator.
assert!(a.is_empty());
Sourcepub fn retain<F>(&mut self, f: F)
pub fn retain<F>(&mut self, f: F)
Retains only the elements specified by the predicate. Keeps the allocated memory for reuse.
In other words, remove all pairs (k, v)
such that f(&k, &mut v)
returns false
.
The elements are visited in unsorted (and unspecified) order.
§Examples
use hashbrown::HashMap;
let mut map: HashMap<i32, i32> = (0..8).map(|x|(x, x*10)).collect();
assert_eq!(map.len(), 8);
map.retain(|&k, _| k % 2 == 0);
// We can see, that the number of elements inside map is changed.
assert_eq!(map.len(), 4);
let mut vec: Vec<(i32, i32)> = map.iter().map(|(&k, &v)| (k, v)).collect();
vec.sort_unstable();
assert_eq!(vec, [(0, 0), (2, 20), (4, 40), (6, 60)]);
Sourcepub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, K, V, F, A> ⓘ
pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, K, V, F, A> ⓘ
Drains elements which are true under the given predicate, and returns an iterator over the removed items.
In other words, move all pairs (k, v)
such that f(&k, &mut v)
returns true
out
into another iterator.
Note that extract_if
lets you mutate every value in the filter closure, regardless of
whether you choose to keep or remove it.
If the returned ExtractIf
is not exhausted, e.g. because it is dropped without iterating
or the iteration short-circuits, then the remaining elements will be retained.
Use retain()
with a negated predicate if you do not need the returned iterator.
Keeps the allocated memory for reuse.
§Examples
use hashbrown::HashMap;
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
let drained: HashMap<i32, i32> = map.extract_if(|k, _v| k % 2 == 0).collect();
let mut evens = drained.keys().cloned().collect::<Vec<_>>();
let mut odds = map.keys().cloned().collect::<Vec<_>>();
evens.sort();
odds.sort();
assert_eq!(evens, vec![0, 2, 4, 6]);
assert_eq!(odds, vec![1, 3, 5, 7]);
let mut map: HashMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
{ // Iterator is dropped without being consumed.
let d = map.extract_if(|k, _v| k % 2 != 0);
}
// ExtractIf was not exhausted, therefore no elements were drained.
assert_eq!(map.len(), 8);
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clears the map, removing all key-value pairs. Keeps the allocated memory for reuse.
§Examples
use hashbrown::HashMap;
let mut a = HashMap::new();
a.insert(1, "a");
let capacity_before_clear = a.capacity();
a.clear();
// Map is empty.
assert!(a.is_empty());
// But map capacity is equal to old one.
assert_eq!(a.capacity(), capacity_before_clear);
Sourcepub fn reserve(&mut self, additional: usize)
pub fn reserve(&mut self, additional: usize)
Reserves capacity for at least additional
more elements to be inserted
in the HashMap
. The collection may reserve more space to avoid
frequent reallocations.
§Panics
Panics if the new capacity exceeds isize::MAX
bytes and abort
the program
in case of allocation error. Use try_reserve
instead
if you want to handle memory allocation failure.
§Examples
use hashbrown::HashMap;
let mut map: HashMap<&str, i32> = HashMap::new();
// Map is empty and doesn't allocate memory
assert_eq!(map.capacity(), 0);
map.reserve(10);
// And now map can hold at least 10 elements
assert!(map.capacity() >= 10);
Sourcepub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
Tries to reserve capacity for at least additional
more elements to be inserted
in the given HashMap<K,V>
. The collection may reserve more space to avoid
frequent reallocations.
§Errors
If the capacity overflows, or the allocator reports a failure, then an error is returned.
§Examples
use hashbrown::HashMap;
let mut map: HashMap<&str, isize> = HashMap::new();
// Map is empty and doesn't allocate memory
assert_eq!(map.capacity(), 0);
map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
// And now map can hold at least 10 elements
assert!(map.capacity() >= 10);
If the capacity overflows, or the allocator reports a failure, then an error is returned:
use hashbrown::HashMap;
use hashbrown::TryReserveError;
let mut map: HashMap<i32, i32> = HashMap::new();
match map.try_reserve(usize::MAX) {
Err(error) => match error {
TryReserveError::CapacityOverflow => {}
_ => panic!("TryReserveError::AllocError ?"),
},
_ => panic!(),
}
Sourcepub fn shrink_to_fit(&mut self)
pub fn shrink_to_fit(&mut self)
Shrinks the capacity of the map as much as possible. It will drop down as much as possible while maintaining the internal rules and possibly leaving some space in accordance with the resize policy.
§Examples
use hashbrown::HashMap;
let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
map.insert(1, 2);
map.insert(3, 4);
assert!(map.capacity() >= 100);
map.shrink_to_fit();
assert!(map.capacity() >= 2);
Sourcepub fn shrink_to(&mut self, min_capacity: usize)
pub fn shrink_to(&mut self, min_capacity: usize)
Shrinks the capacity of the map with a lower limit. It will drop down no lower than the supplied limit while maintaining the internal rules and possibly leaving some space in accordance with the resize policy.
This function does nothing if the current capacity is smaller than the supplied minimum capacity.
§Examples
use hashbrown::HashMap;
let mut map: HashMap<i32, i32> = HashMap::with_capacity(100);
map.insert(1, 2);
map.insert(3, 4);
assert!(map.capacity() >= 100);
map.shrink_to(10);
assert!(map.capacity() >= 10);
map.shrink_to(0);
assert!(map.capacity() >= 2);
map.shrink_to(10);
assert!(map.capacity() >= 2);
Sourcepub fn entry(&mut self, key: K) -> Entry<'_, K, V, S, A>
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S, A>
Gets the given key’s corresponding entry in the map for in-place manipulation.
§Examples
use hashbrown::HashMap;
let mut letters = HashMap::new();
for ch in "a short treatise on fungi".chars() {
let counter = letters.entry(ch).or_insert(0);
*counter += 1;
}
assert_eq!(letters[&'s'], 2);
assert_eq!(letters[&'t'], 3);
assert_eq!(letters[&'u'], 1);
assert_eq!(letters.get(&'y'), None);
Sourcepub fn entry_ref<'a, 'b, Q>(
&'a mut self,
key: &'b Q,
) -> EntryRef<'a, 'b, K, Q, V, S, A>
pub fn entry_ref<'a, 'b, Q>( &'a mut self, key: &'b Q, ) -> EntryRef<'a, 'b, K, Q, V, S, A>
Gets the given key’s corresponding entry by reference in the map for in-place manipulation.
§Examples
use hashbrown::HashMap;
let mut words: HashMap<String, usize> = HashMap::new();
let source = ["poneyland", "horseyland", "poneyland", "poneyland"];
for (i, &s) in source.iter().enumerate() {
let counter = words.entry_ref(s).or_insert(0);
*counter += 1;
}
assert_eq!(words["poneyland"], 3);
assert_eq!(words["horseyland"], 1);
Sourcepub fn get<Q>(&self, k: &Q) -> Option<&V>
pub fn get<Q>(&self, k: &Q) -> Option<&V>
Returns a reference to the value corresponding to the key.
The key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.get(&1), Some(&"a"));
assert_eq!(map.get(&2), None);
Sourcepub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
Returns the key-value pair corresponding to the supplied key.
The supplied key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.get_key_value(&1), Some((&1, &"a")));
assert_eq!(map.get_key_value(&2), None);
Sourcepub fn get_key_value_mut<Q>(&mut self, k: &Q) -> Option<(&K, &mut V)>
pub fn get_key_value_mut<Q>(&mut self, k: &Q) -> Option<(&K, &mut V)>
Returns the key-value pair corresponding to the supplied key, with a mutable reference to value.
The supplied key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
let (k, v) = map.get_key_value_mut(&1).unwrap();
assert_eq!(k, &1);
assert_eq!(v, &mut "a");
*v = "b";
assert_eq!(map.get_key_value_mut(&1), Some((&1, &mut "b")));
assert_eq!(map.get_key_value_mut(&2), None);
Sourcepub fn contains_key<Q>(&self, k: &Q) -> bool
pub fn contains_key<Q>(&self, k: &Q) -> bool
Returns true
if the map contains a value for the specified key.
The key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.contains_key(&1), true);
assert_eq!(map.contains_key(&2), false);
Sourcepub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
Returns a mutable reference to the value corresponding to the key.
The key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
map.insert(1, "a");
if let Some(x) = map.get_mut(&1) {
*x = "b";
}
assert_eq!(map[&1], "b");
assert_eq!(map.get_mut(&2), None);
Sourcepub fn get_many_mut<Q, const N: usize>(
&mut self,
ks: [&Q; N],
) -> [Option<&mut V>; N]
pub fn get_many_mut<Q, const N: usize>( &mut self, ks: [&Q; N], ) -> [Option<&mut V>; N]
Attempts to get mutable references to N
values in the map at once.
Returns an array of length N
with the results of each query. For soundness, at most one
mutable reference will be returned to any value. None
will be used if the key is missing.
§Panics
Panics if any keys are overlapping.
§Examples
use hashbrown::HashMap;
let mut libraries = HashMap::new();
libraries.insert("Bodleian Library".to_string(), 1602);
libraries.insert("Athenæum".to_string(), 1807);
libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
libraries.insert("Library of Congress".to_string(), 1800);
// Get Athenæum and Bodleian Library
let [Some(a), Some(b)] = libraries.get_many_mut([
"Athenæum",
"Bodleian Library",
]) else { panic!() };
// Assert values of Athenæum and Library of Congress
let got = libraries.get_many_mut([
"Athenæum",
"Library of Congress",
]);
assert_eq!(
got,
[
Some(&mut 1807),
Some(&mut 1800),
],
);
// Missing keys result in None
let got = libraries.get_many_mut([
"Athenæum",
"New York Public Library",
]);
assert_eq!(
got,
[
Some(&mut 1807),
None
]
);
use hashbrown::HashMap;
let mut libraries = HashMap::new();
libraries.insert("Athenæum".to_string(), 1807);
// Duplicate keys panic!
let got = libraries.get_many_mut([
"Athenæum",
"Athenæum",
]);
Sourcepub unsafe fn get_many_unchecked_mut<Q, const N: usize>(
&mut self,
ks: [&Q; N],
) -> [Option<&mut V>; N]
pub unsafe fn get_many_unchecked_mut<Q, const N: usize>( &mut self, ks: [&Q; N], ) -> [Option<&mut V>; N]
Attempts to get mutable references to N
values in the map at once, without validating that
the values are unique.
Returns an array of length N
with the results of each query. None
will be used if
the key is missing.
For a safe alternative see get_many_mut
.
§Safety
Calling this method with overlapping keys is undefined behavior even if the resulting references are not used.
§Examples
use hashbrown::HashMap;
let mut libraries = HashMap::new();
libraries.insert("Bodleian Library".to_string(), 1602);
libraries.insert("Athenæum".to_string(), 1807);
libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
libraries.insert("Library of Congress".to_string(), 1800);
// SAFETY: The keys do not overlap.
let [Some(a), Some(b)] = (unsafe { libraries.get_many_unchecked_mut([
"Athenæum",
"Bodleian Library",
]) }) else { panic!() };
// SAFETY: The keys do not overlap.
let got = unsafe { libraries.get_many_unchecked_mut([
"Athenæum",
"Library of Congress",
]) };
assert_eq!(
got,
[
Some(&mut 1807),
Some(&mut 1800),
],
);
// SAFETY: The keys do not overlap.
let got = unsafe { libraries.get_many_unchecked_mut([
"Athenæum",
"New York Public Library",
]) };
// Missing keys result in None
assert_eq!(got, [Some(&mut 1807), None]);
Sourcepub fn get_many_key_value_mut<Q, const N: usize>(
&mut self,
ks: [&Q; N],
) -> [Option<(&K, &mut V)>; N]
pub fn get_many_key_value_mut<Q, const N: usize>( &mut self, ks: [&Q; N], ) -> [Option<(&K, &mut V)>; N]
Attempts to get mutable references to N
values in the map at once, with immutable
references to the corresponding keys.
Returns an array of length N
with the results of each query. For soundness, at most one
mutable reference will be returned to any value. None
will be used if the key is missing.
§Panics
Panics if any keys are overlapping.
§Examples
use hashbrown::HashMap;
let mut libraries = HashMap::new();
libraries.insert("Bodleian Library".to_string(), 1602);
libraries.insert("Athenæum".to_string(), 1807);
libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
libraries.insert("Library of Congress".to_string(), 1800);
let got = libraries.get_many_key_value_mut([
"Bodleian Library",
"Herzogin-Anna-Amalia-Bibliothek",
]);
assert_eq!(
got,
[
Some((&"Bodleian Library".to_string(), &mut 1602)),
Some((&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691)),
],
);
// Missing keys result in None
let got = libraries.get_many_key_value_mut([
"Bodleian Library",
"Gewandhaus",
]);
assert_eq!(got, [Some((&"Bodleian Library".to_string(), &mut 1602)), None]);
use hashbrown::HashMap;
let mut libraries = HashMap::new();
libraries.insert("Bodleian Library".to_string(), 1602);
libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
// Duplicate keys result in panic!
let got = libraries.get_many_key_value_mut([
"Bodleian Library",
"Herzogin-Anna-Amalia-Bibliothek",
"Herzogin-Anna-Amalia-Bibliothek",
]);
Sourcepub unsafe fn get_many_key_value_unchecked_mut<Q, const N: usize>(
&mut self,
ks: [&Q; N],
) -> [Option<(&K, &mut V)>; N]
pub unsafe fn get_many_key_value_unchecked_mut<Q, const N: usize>( &mut self, ks: [&Q; N], ) -> [Option<(&K, &mut V)>; N]
Attempts to get mutable references to N
values in the map at once, with immutable
references to the corresponding keys, without validating that the values are unique.
Returns an array of length N
with the results of each query. None
will be returned if
any of the keys are missing.
For a safe alternative see get_many_key_value_mut
.
§Safety
Calling this method with overlapping keys is undefined behavior even if the resulting references are not used.
§Examples
use hashbrown::HashMap;
let mut libraries = HashMap::new();
libraries.insert("Bodleian Library".to_string(), 1602);
libraries.insert("Athenæum".to_string(), 1807);
libraries.insert("Herzogin-Anna-Amalia-Bibliothek".to_string(), 1691);
libraries.insert("Library of Congress".to_string(), 1800);
let got = libraries.get_many_key_value_mut([
"Bodleian Library",
"Herzogin-Anna-Amalia-Bibliothek",
]);
assert_eq!(
got,
[
Some((&"Bodleian Library".to_string(), &mut 1602)),
Some((&"Herzogin-Anna-Amalia-Bibliothek".to_string(), &mut 1691)),
],
);
// Missing keys result in None
let got = libraries.get_many_key_value_mut([
"Bodleian Library",
"Gewandhaus",
]);
assert_eq!(
got,
[
Some((&"Bodleian Library".to_string(), &mut 1602)),
None,
],
);
Sourcepub fn insert(&mut self, k: K, v: V) -> Option<V>
pub fn insert(&mut self, k: K, v: V) -> Option<V>
Inserts a key-value pair into the map.
If the map did not have this key present, None
is returned.
If the map did have this key present, the value is updated, and the old
value is returned. The key is not updated, though; this matters for
types that can be ==
without being identical. See the std::collections
module-level documentation for more.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
assert_eq!(map.insert(37, "a"), None);
assert_eq!(map.is_empty(), false);
map.insert(37, "b");
assert_eq!(map.insert(37, "c"), Some("b"));
assert_eq!(map[&37], "c");
Sourcepub unsafe fn insert_unique_unchecked(&mut self, k: K, v: V) -> (&K, &mut V)
pub unsafe fn insert_unique_unchecked(&mut self, k: K, v: V) -> (&K, &mut V)
Insert a key-value pair into the map without checking if the key already exists in the map.
This operation is faster than regular insert, because it does not perform lookup before insertion.
This operation is useful during initial population of the map. For example, when constructing a map from another map, we know that keys are unique.
Returns a reference to the key and value just inserted.
§Safety
This operation is safe if a key does not exist in the map.
However, if a key exists in the map already, the behavior is unspecified: this operation may panic, loop forever, or any following operation with the map may panic, loop forever or return arbitrary result.
That said, this operation (and following operations) are guaranteed to not violate memory safety.
However this operation is still unsafe because the resulting HashMap
may be passed to unsafe code which does expect the map to behave
correctly, and would cause unsoundness as a result.
§Examples
use hashbrown::HashMap;
let mut map1 = HashMap::new();
assert_eq!(map1.insert(1, "a"), None);
assert_eq!(map1.insert(2, "b"), None);
assert_eq!(map1.insert(3, "c"), None);
assert_eq!(map1.len(), 3);
let mut map2 = HashMap::new();
for (key, value) in map1.into_iter() {
unsafe {
map2.insert_unique_unchecked(key, value);
}
}
let (key, value) = unsafe { map2.insert_unique_unchecked(4, "d") };
assert_eq!(key, &4);
assert_eq!(value, &mut "d");
*value = "e";
assert_eq!(map2[&1], "a");
assert_eq!(map2[&2], "b");
assert_eq!(map2[&3], "c");
assert_eq!(map2[&4], "e");
assert_eq!(map2.len(), 4);
Sourcepub fn try_insert(
&mut self,
key: K,
value: V,
) -> Result<&mut V, OccupiedError<'_, K, V, S, A>>
pub fn try_insert( &mut self, key: K, value: V, ) -> Result<&mut V, OccupiedError<'_, K, V, S, A>>
Tries to insert a key-value pair into the map, and returns a mutable reference to the value in the entry.
§Errors
If the map already had this key present, nothing is updated, and an error containing the occupied entry and the value is returned.
§Examples
Basic usage:
use hashbrown::HashMap;
use hashbrown::hash_map::OccupiedError;
let mut map = HashMap::new();
assert_eq!(map.try_insert(37, "a").unwrap(), &"a");
match map.try_insert(37, "b") {
Err(OccupiedError { entry, value }) => {
assert_eq!(entry.key(), &37);
assert_eq!(entry.get(), &"a");
assert_eq!(value, "b");
}
_ => panic!()
}
Sourcepub fn remove<Q>(&mut self, k: &Q) -> Option<V>
pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
Removes a key from the map, returning the value at the key if the key was previously in the map. Keeps the allocated memory for reuse.
The key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
// The map is empty
assert!(map.is_empty() && map.capacity() == 0);
map.insert(1, "a");
assert_eq!(map.remove(&1), Some("a"));
assert_eq!(map.remove(&1), None);
// Now map holds none elements
assert!(map.is_empty());
Sourcepub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)>
pub fn remove_entry<Q>(&mut self, k: &Q) -> Option<(K, V)>
Removes a key from the map, returning the stored key and value if the key was previously in the map. Keeps the allocated memory for reuse.
The key may be any borrowed form of the map’s key type, but
Hash
and Eq
on the borrowed form must match those for
the key type.
§Examples
use hashbrown::HashMap;
let mut map = HashMap::new();
// The map is empty
assert!(map.is_empty() && map.capacity() == 0);
map.insert(1, "a");
assert_eq!(map.remove_entry(&1), Some((1, "a")));
assert_eq!(map.remove(&1), None);
// Now map hold none elements
assert!(map.is_empty());
Sourcepub fn allocation_size(&self) -> usize
pub fn allocation_size(&self) -> usize
Returns the total amount of memory allocated internally by the hash set, in bytes.
The returned number is informational only. It is intended to be primarily used for memory profiling.
Sourcepub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S, A>
pub fn raw_entry_mut(&mut self) -> RawEntryBuilderMut<'_, K, V, S, A>
Creates a raw entry builder for the HashMap
.
Raw entries provide the lowest level of control for searching and manipulating a map. They must be manually initialized with a hash and then manually searched. After this, insertions into a vacant entry still require an owned key to be provided.
Raw entries are useful for such exotic situations as:
- Hash memoization
- Deferring the creation of an owned key until it is known to be required
- Using a search key that doesn’t work with the Borrow trait
- Using custom comparison logic without newtype wrappers
Because raw entries provide much more low-level control, it’s much easier
to put the HashMap
into an inconsistent state which, while memory-safe,
will cause the map to produce seemingly random results. Higher-level and
more foolproof APIs like entry
should be preferred when possible.
In particular, the hash used to initialized the raw entry must still be
consistent with the hash of the key that is ultimately stored in the entry.
This is because implementations of HashMap
may need to recompute hashes
when resizing, at which point only the keys are available.
Raw entries give mutable access to the keys. This must not be used to modify how the key would compare or hash, as the map will not re-evaluate where the key should go, meaning the keys may become “lost” if their location does not reflect their state. For instance, if you change a key so that the map now contains keys which compare equal, search may start acting erratically, with two keys randomly masking each other. Implementations are free to assume this doesn’t happen (within the limits of memory-safety).
§Examples
use core::hash::{BuildHasher, Hash};
use hashbrown::hash_map::{HashMap, RawEntryMut};
let mut map = HashMap::new();
map.extend([("a", 100), ("b", 200), ("c", 300)]);
fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
use core::hash::Hasher;
let mut state = hash_builder.build_hasher();
key.hash(&mut state);
state.finish()
}
// Existing key (insert and update)
match map.raw_entry_mut().from_key(&"a") {
RawEntryMut::Vacant(_) => unreachable!(),
RawEntryMut::Occupied(mut view) => {
assert_eq!(view.get(), &100);
let v = view.get_mut();
let new_v = (*v) * 10;
*v = new_v;
assert_eq!(view.insert(1111), 1000);
}
}
assert_eq!(map[&"a"], 1111);
assert_eq!(map.len(), 3);
// Existing key (take)
let hash = compute_hash(map.hasher(), &"c");
match map.raw_entry_mut().from_key_hashed_nocheck(hash, &"c") {
RawEntryMut::Vacant(_) => unreachable!(),
RawEntryMut::Occupied(view) => {
assert_eq!(view.remove_entry(), ("c", 300));
}
}
assert_eq!(map.raw_entry().from_key(&"c"), None);
assert_eq!(map.len(), 2);
// Nonexistent key (insert and update)
let key = "d";
let hash = compute_hash(map.hasher(), &key);
match map.raw_entry_mut().from_hash(hash, |q| *q == key) {
RawEntryMut::Occupied(_) => unreachable!(),
RawEntryMut::Vacant(view) => {
let (k, value) = view.insert("d", 4000);
assert_eq!((*k, *value), ("d", 4000));
*value = 40000;
}
}
assert_eq!(map[&"d"], 40000);
assert_eq!(map.len(), 3);
match map.raw_entry_mut().from_hash(hash, |q| *q == key) {
RawEntryMut::Vacant(_) => unreachable!(),
RawEntryMut::Occupied(view) => {
assert_eq!(view.remove_entry(), ("d", 40000));
}
}
assert_eq!(map.get(&"d"), None);
assert_eq!(map.len(), 2);
Sourcepub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S, A>
pub fn raw_entry(&self) -> RawEntryBuilder<'_, K, V, S, A>
Creates a raw immutable entry builder for the HashMap
.
Raw entries provide the lowest level of control for searching and manipulating a map. They must be manually initialized with a hash and then manually searched.
This is useful for
- Hash memoization
- Using a search key that doesn’t work with the Borrow trait
- Using custom comparison logic without newtype wrappers
Unless you are in such a situation, higher-level and more foolproof APIs like
get
should be preferred.
Immutable raw entries have very limited use; you might instead want raw_entry_mut
.
§Examples
use core::hash::{BuildHasher, Hash};
use hashbrown::HashMap;
let mut map = HashMap::new();
map.extend([("a", 100), ("b", 200), ("c", 300)]);
fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 {
use core::hash::Hasher;
let mut state = hash_builder.build_hasher();
key.hash(&mut state);
state.finish()
}
for k in ["a", "b", "c", "d", "e", "f"] {
let hash = compute_hash(map.hasher(), k);
let v = map.get(&k).cloned();
let kv = v.as_ref().map(|v| (&k, v));
println!("Key: {} and value: {:?}", k, v);
assert_eq!(map.raw_entry().from_key(&k), kv);
assert_eq!(map.raw_entry().from_hash(hash, |q| *q == k), kv);
assert_eq!(map.raw_entry().from_key_hashed_nocheck(hash, &k), kv);
}
Trait Implementations§
impl Resource for HoverMap
Auto Trait Implementations§
impl Freeze for HoverMap
impl RefUnwindSafe for HoverMap
impl Send for HoverMap
impl Sync for HoverMap
impl Unpin for HoverMap
impl UnwindSafe for HoverMap
Blanket Implementations§
Source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.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> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self
using default()
.
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
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 moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.