use crate::material_overrides::MaterialOverridesSet;
use crate::material_name_map::MaterialMetadataName;
use crate::BuiltMaterialsResource;
use crate::material_overrides::{MaterialOverrideComponent, RefreshMaterialOverride};
use crate::materials_config::MaterialShaderType;
use crate::{advanced_materials::foliage_material::FoliageMaterialExtension, materials_config::MaterialTypesConfig};
use bevy::math::Affine2;
use bevy::prelude::*;
use bevy::utils::HashMap;
use bevy::scene::SceneInstanceReady;
use serde:: {Serialize,Deserialize};
pub fn material_replacements_plugin(app: &mut App) {
app
.init_state::<MaterialOverridesLoadingState>()
.add_systems(Update, (
handle_material_replacement_sets ,
handle_material_replacements_when_scene_ready,
handle_material_replacements
).chain().before( MaterialOverridesSet ) )
;
}
#[derive(Clone,Debug,PartialEq,Eq,Hash,States,Default)]
pub enum MaterialOverridesLoadingState{
#[default]
Init,
Extracting,
Building,
Complete
}
#[derive(Component,Debug)]
pub struct MaterialReplacementComponent {
pub material_replacements: HashMap<String,String>
}
#[derive(Component,Debug)]
pub struct RefreshMaterialReplacement ;
#[derive(Component,Debug)]
pub struct MaterialReplacementWhenSceneReadyComponent {
pub material_replacements: HashMap<String,String>
}
#[derive(Component,Debug)]
pub struct MaterialReplacementApplySetWhenSceneReadyComponent(pub String);
fn handle_material_replacements(
mut commands:Commands,
material_override_query: Query<(Entity, &MaterialReplacementComponent),
Changed<MaterialReplacementComponent> >,
children_query: Query<&Children>,
material_metadata_query: Query<&MaterialMetadataName>,
){
for (mat_override_entity, mat_replacement_request) in material_override_query.iter(){
for child in DescendantIter::new(&children_query, mat_override_entity) {
let Some(material_metadata_comp) = material_metadata_query.get(child).ok() else {continue};
for (original_mat_name, new_mat_name) in &mat_replacement_request.material_replacements {
if &material_metadata_comp.0 == original_mat_name {
commands.entity(child).try_insert( MaterialOverrideComponent {material_override: new_mat_name.clone() } );
}
}
}
}
}
fn handle_material_replacement_sets(
mut commands:Commands,
material_override_request_query: Query< (Entity, &MaterialReplacementApplySetWhenSceneReadyComponent ), Added<MaterialReplacementApplySetWhenSceneReadyComponent> >,
material_types_config: Res<MaterialTypesConfig> ,
) {
for (entity, mat_replacement_request) in material_override_request_query.iter() {
let mut material_replacements = None ;
if let Some( material_replacement_sets ) = &material_types_config.material_replacement_sets {
if let Some(matching_set) = material_replacement_sets.get( &mat_replacement_request.0 ){
material_replacements = Some( matching_set.clone() );
}
}
if let Some( material_replacements )= material_replacements {
commands.entity(entity).try_insert(
MaterialReplacementWhenSceneReadyComponent {
material_replacements
}
);
}
}
}
fn handle_material_replacements_when_scene_ready(
mut commands:Commands,
mut scene_instance_evt_reader: EventReader<SceneInstanceReady>,
material_override_request_query: Query<&MaterialReplacementWhenSceneReadyComponent >,
parent_query : Query<&Parent>,
){
for evt in scene_instance_evt_reader.read(){
let parent = evt.parent;
let Some(parent_entity) = parent_query.get(parent).ok().map( |p| p.get() ) else {continue};
if let Some(mat_override_request) = material_override_request_query.get(parent_entity).ok(){
let material_replacements = mat_override_request.material_replacements.clone() ;
if let Some(mut cmd) = commands.get_entity( parent_entity ) {
cmd.try_insert(
MaterialReplacementComponent {
material_replacements
}
);
}
}
}
}