use std::collections::HashMap;
use concinnity_core::components::{
GlobalTransform, InstancedProp, PropInstance, RenderHandle, SubMeshRef,
};
use concinnity_core::ecs::asset_id::AssetId;
use concinnity_core::ecs::{Entity, MaterialHandle, PickIndex, PipelineContext};
use concinnity_core::gfx::render_types::DrawIndex;
use concinnity_core::memory::InlineVec;
use concinnity_core::transform::propagation;
use super::{GraphicsSystem, PickCandidate};
use crate::gfx::draw_list::{self, DrawListData, LoadedMesh, RoomGeometry};
use crate::gfx::material_entry::MaterialEntry;
pub(super) struct PropDrawInputs<'a> {
pub(super) model_map: &'a HashMap<AssetId, Vec<SubMeshRef>>,
pub(super) mesh_geometry: &'a [LoadedMesh],
pub(super) room_geometry: &'a [RoomGeometry],
pub(super) texture_count: usize,
pub(super) material_map: &'a HashMap<MaterialHandle, MaterialEntry>,
}
impl GraphicsSystem {
pub(super) fn assemble_prop_draws(
&mut self,
ctx: &mut PipelineContext,
inputs: PropDrawInputs<'_>,
) -> Option<DrawListData> {
let instanced_props = ctx.drain::<InstancedProp>();
let prop_entities: Vec<Entity> = ctx
.query_with_entity::<PropInstance>()
.map(|(entity, _)| entity)
.collect();
let resolved = propagation::resolve_world_matrices(ctx);
let mut items = Vec::with_capacity(prop_entities.len());
let mut world_mats = Vec::with_capacity(prop_entities.len());
for &entity in &prop_entities {
items.push(draw_list::decomposed_renderable_item(ctx, entity));
world_mats.push(
resolved
.get(&entity)
.copied()
.unwrap_or(draw_list::IDENTITY4),
);
}
let data = draw_list::build_draw_list(draw_list::DrawListInputs {
items: &items,
instanced_props: &instanced_props,
world_mats: &world_mats,
model_map: inputs.model_map,
mesh_geometry: inputs.mesh_geometry,
room_geometry: inputs.room_geometry,
texture_count: inputs.texture_count,
material_map: inputs.material_map,
})?;
self.pick_candidates.clear();
let want_pick = ctx.resource::<PickIndex>().is_some();
for (i, &entity) in prop_entities.iter().enumerate() {
let draws: InlineVec<DrawIndex> = data.prop_draw_indices[i].iter().copied().collect();
ctx.insert(entity, RenderHandle { draws });
ctx.insert(entity, GlobalTransform(world_mats[i]));
if want_pick && let Some(asset_id) = items[i].asset_id {
let (local_min, local_max) = data.prop_local_bounds[i];
self.pick_candidates.push(PickCandidate {
asset_id,
entity,
local_min,
local_max,
});
}
}
Some(data)
}
}