use crate::mosaic::WidgetContext;
use nightshade::ecs::generational_registry::registry_entry_by_name_mut;
use nightshade::ecs::material::resources::material_registry_insert;
use nightshade::prelude::serde::{Deserialize, Serialize};
use nightshade::prelude::*;
use crate::app_context::AppContext;
use crate::engine_editor::inspector::helpers::material_properties_ui;
use crate::messages::EditorMessage;
fn default_true() -> bool {
true
}
#[derive(Clone, Serialize, Deserialize)]
#[serde(crate = "nightshade::prelude::serde")]
pub struct MaterialsWidget {
pub selected_material: Option<String>,
#[serde(skip)]
pub new_material_name: String,
#[serde(default = "default_true")]
pub materials_list_expanded: bool,
}
impl Default for MaterialsWidget {
fn default() -> Self {
Self {
selected_material: None,
new_material_name: String::new(),
materials_list_expanded: true,
}
}
}
impl MaterialsWidget {
pub(crate) fn render(
&mut self,
ui: &mut egui::Ui,
context: &mut WidgetContext<AppContext, EditorMessage>,
) {
let tile_id = context.current_tile_id;
let world = context.world_mut();
let available_rect = ui.available_rect_before_wrap();
ui.painter()
.rect_filled(available_rect, 0.0, ui.style().visuals.panel_fill);
egui::ScrollArea::vertical()
.id_salt(("materials_widget_scroll", tile_id))
.auto_shrink([false, false])
.show(ui, |ui| {
ui.set_min_width(available_rect.width());
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.label("New material:");
ui.text_edit_singleline(&mut self.new_material_name);
if ui.button("Create").clicked()
&& !self.new_material_name.is_empty()
&& !world
.resources
.material_registry
.registry
.name_to_index
.contains_key(&self.new_material_name)
{
material_registry_insert(
&mut world.resources.material_registry,
self.new_material_name.clone(),
Material::default(),
);
self.selected_material = Some(self.new_material_name.clone());
self.new_material_name.clear();
}
});
ui.separator();
let material_count = world
.resources
.material_registry
.registry
.index_to_name
.iter()
.filter(|opt| opt.is_some())
.count();
let mut slot_to_remove: Option<usize> = None;
let header_response =
ui.collapsing(format!("Materials ({})", material_count), |ui| {
egui::ScrollArea::vertical()
.id_salt(tile_id)
.max_height(200.0)
.show(ui, |ui| {
let registry = &world.resources.material_registry.registry;
for slot_index in 0..registry.index_to_name.len() {
let Some(name) = ®istry.index_to_name[slot_index] else {
continue;
};
let ref_count = registry.reference_counts[slot_index];
let is_selected =
self.selected_material.as_deref() == Some(name.as_str());
ui.horizontal(|ui| {
let label = format!("{} ({})", name, ref_count);
if ui.selectable_label(is_selected, &label).clicked() {
self.selected_material = Some(name.clone());
}
if ref_count == 0
&& ui
.small_button("\u{1f5d1}")
.on_hover_text("Delete")
.clicked()
{
if is_selected {
self.selected_material = None;
}
slot_to_remove = Some(slot_index);
}
});
}
});
});
if let Some(slot_index) = slot_to_remove {
let generation =
world.resources.material_registry.registry.generations[slot_index];
world
.resources
.material_registry
.registry
.remove(slot_index as u32, generation);
}
self.materials_list_expanded = header_response.fully_open();
ui.separator();
if let Some(material_name) = self.selected_material.clone() {
if let Some(material) = registry_entry_by_name_mut(
&mut world.resources.material_registry.registry,
&material_name,
) {
ui.collapsing(format!("Edit: {}", material_name), |ui| {
material_properties_ui(ui, material, &format!("widget_{:?}", tile_id));
ui.separator();
ui.label("Textures:");
let mut base_texture_str =
material.base_texture.clone().unwrap_or_default();
ui.horizontal(|ui| {
ui.label("Base Texture:");
if ui.text_edit_singleline(&mut base_texture_str).changed() {
material.base_texture = if base_texture_str.is_empty() {
None
} else {
Some(base_texture_str)
};
}
});
let mut emissive_texture_str =
material.emissive_texture.clone().unwrap_or_default();
ui.horizontal(|ui| {
ui.label("Emissive Texture:");
if ui.text_edit_singleline(&mut emissive_texture_str).changed() {
material.emissive_texture = if emissive_texture_str.is_empty() {
None
} else {
Some(emissive_texture_str)
};
}
});
});
} else {
self.selected_material = None;
}
}
});
}
}