make gizmo groups ordering stable when rendering (#12034)
# Objective - During rendering of different gizmo groups, the ordering is random between executions ## Solution - Make the ordering stable - It's using a `TypeIdMap`, its iteration order depends on the insertion order. so insert when adding a group instead of when adding a gizmo - Also changed `extract_gizmo_data` to not be group dependent. there will be only one of those systems, no matter the number of gizmo groups added --------- Co-authored-by: pablo-lua <126117294+pablo-lua@users.noreply.github.com>
This commit is contained in:
parent
1b1934f4fb
commit
ebdda09fc3
@ -116,6 +116,8 @@ impl Plugin for GizmoPlugin {
|
||||
prepare_line_gizmo_bind_group.in_set(RenderSet::PrepareBindGroups),
|
||||
);
|
||||
|
||||
render_app.add_systems(ExtractSchedule, extract_gizmo_data);
|
||||
|
||||
#[cfg(feature = "bevy_sprite")]
|
||||
app.add_plugins(pipeline_2d::LineGizmo2dPlugin);
|
||||
#[cfg(feature = "bevy_pbr")]
|
||||
@ -163,6 +165,12 @@ impl AppGizmoBuilder for App {
|
||||
return self;
|
||||
}
|
||||
|
||||
let mut handles = self
|
||||
.world
|
||||
.get_resource_or_insert_with::<LineGizmoHandles>(Default::default);
|
||||
handles.list.insert(TypeId::of::<T>(), None);
|
||||
handles.strip.insert(TypeId::of::<T>(), None);
|
||||
|
||||
self.init_resource::<GizmoStorage<T>>()
|
||||
.add_systems(Last, update_gizmo_meshes::<T>);
|
||||
|
||||
@ -170,12 +178,6 @@ impl AppGizmoBuilder for App {
|
||||
.get_resource_or_insert_with::<GizmoConfigStore>(Default::default)
|
||||
.register::<T>();
|
||||
|
||||
let Ok(render_app) = self.get_sub_app_mut(RenderApp) else {
|
||||
return self;
|
||||
};
|
||||
|
||||
render_app.add_systems(ExtractSchedule, extract_gizmo_data::<T>);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
@ -192,23 +194,28 @@ impl AppGizmoBuilder for App {
|
||||
return self;
|
||||
}
|
||||
|
||||
let mut handles = self
|
||||
.world
|
||||
.get_resource_or_insert_with::<LineGizmoHandles>(Default::default);
|
||||
handles.list.insert(TypeId::of::<T>(), None);
|
||||
handles.strip.insert(TypeId::of::<T>(), None);
|
||||
|
||||
self.init_resource::<GizmoStorage<T>>()
|
||||
.add_systems(Last, update_gizmo_meshes::<T>);
|
||||
|
||||
let Ok(render_app) = self.get_sub_app_mut(RenderApp) else {
|
||||
return self;
|
||||
};
|
||||
|
||||
render_app.add_systems(ExtractSchedule, extract_gizmo_data::<T>);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds handles to the line gizmos for each gizmo configuration group
|
||||
// As `TypeIdMap` iteration order depends on the order of insertions and deletions, this uses
|
||||
// `Option<Handle>` to be able to reserve the slot when creating the gizmo configuration group.
|
||||
// That way iteration order is stable accross executions and depends on the order of configuration
|
||||
// group creation.
|
||||
#[derive(Resource, Default)]
|
||||
struct LineGizmoHandles {
|
||||
list: TypeIdMap<Handle<LineGizmo>>,
|
||||
strip: TypeIdMap<Handle<LineGizmo>>,
|
||||
list: TypeIdMap<Option<Handle<LineGizmo>>>,
|
||||
strip: TypeIdMap<Option<Handle<LineGizmo>>>,
|
||||
}
|
||||
|
||||
fn update_gizmo_meshes<T: GizmoConfigGroup>(
|
||||
@ -217,63 +224,66 @@ fn update_gizmo_meshes<T: GizmoConfigGroup>(
|
||||
mut storage: ResMut<GizmoStorage<T>>,
|
||||
) {
|
||||
if storage.list_positions.is_empty() {
|
||||
handles.list.remove(&TypeId::of::<T>());
|
||||
} else if let Some(handle) = handles.list.get(&TypeId::of::<T>()) {
|
||||
let list = line_gizmos.get_mut(handle).unwrap();
|
||||
handles.list.insert(TypeId::of::<T>(), None);
|
||||
} else if let Some(handle) = handles.list.get_mut(&TypeId::of::<T>()) {
|
||||
if let Some(handle) = handle {
|
||||
let list = line_gizmos.get_mut(handle.id()).unwrap();
|
||||
|
||||
list.positions = mem::take(&mut storage.list_positions);
|
||||
list.colors = mem::take(&mut storage.list_colors);
|
||||
} else {
|
||||
let mut list = LineGizmo {
|
||||
strip: false,
|
||||
..Default::default()
|
||||
};
|
||||
list.positions = mem::take(&mut storage.list_positions);
|
||||
list.colors = mem::take(&mut storage.list_colors);
|
||||
} else {
|
||||
let mut list = LineGizmo {
|
||||
strip: false,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
list.positions = mem::take(&mut storage.list_positions);
|
||||
list.colors = mem::take(&mut storage.list_colors);
|
||||
list.positions = mem::take(&mut storage.list_positions);
|
||||
list.colors = mem::take(&mut storage.list_colors);
|
||||
|
||||
handles
|
||||
.list
|
||||
.insert(TypeId::of::<T>(), line_gizmos.add(list));
|
||||
*handle = Some(line_gizmos.add(list));
|
||||
}
|
||||
}
|
||||
|
||||
if storage.strip_positions.is_empty() {
|
||||
handles.strip.remove(&TypeId::of::<T>());
|
||||
} else if let Some(handle) = handles.strip.get(&TypeId::of::<T>()) {
|
||||
let strip = line_gizmos.get_mut(handle).unwrap();
|
||||
handles.strip.insert(TypeId::of::<T>(), None);
|
||||
} else if let Some(handle) = handles.strip.get_mut(&TypeId::of::<T>()) {
|
||||
if let Some(handle) = handle {
|
||||
let strip = line_gizmos.get_mut(handle.id()).unwrap();
|
||||
|
||||
strip.positions = mem::take(&mut storage.strip_positions);
|
||||
strip.colors = mem::take(&mut storage.strip_colors);
|
||||
} else {
|
||||
let mut strip = LineGizmo {
|
||||
strip: true,
|
||||
..Default::default()
|
||||
};
|
||||
strip.positions = mem::take(&mut storage.strip_positions);
|
||||
strip.colors = mem::take(&mut storage.strip_colors);
|
||||
} else {
|
||||
let mut strip = LineGizmo {
|
||||
strip: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
strip.positions = mem::take(&mut storage.strip_positions);
|
||||
strip.colors = mem::take(&mut storage.strip_colors);
|
||||
strip.positions = mem::take(&mut storage.strip_positions);
|
||||
strip.colors = mem::take(&mut storage.strip_colors);
|
||||
|
||||
handles
|
||||
.strip
|
||||
.insert(TypeId::of::<T>(), line_gizmos.add(strip));
|
||||
*handle = Some(line_gizmos.add(strip));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_gizmo_data<T: GizmoConfigGroup>(
|
||||
fn extract_gizmo_data(
|
||||
mut commands: Commands,
|
||||
handles: Extract<Res<LineGizmoHandles>>,
|
||||
config: Extract<Res<GizmoConfigStore>>,
|
||||
) {
|
||||
let (config, _) = config.config::<T>();
|
||||
|
||||
if !config.enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
for map in [&handles.list, &handles.strip].into_iter() {
|
||||
let Some(handle) = map.get(&TypeId::of::<T>()) else {
|
||||
for (group_type_id, handle) in handles.list.iter().chain(handles.strip.iter()) {
|
||||
let Some((config, _)) = config.get_config_dyn(group_type_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !config.enabled {
|
||||
continue;
|
||||
}
|
||||
|
||||
let Some(handle) = handle else {
|
||||
continue;
|
||||
};
|
||||
|
||||
commands.spawn((
|
||||
LineGizmoUniform {
|
||||
line_width: config.line_width,
|
||||
|
Loading…
Reference in New Issue
Block a user