use crate::SettingsUI;
use par_term_config::ShaderConfig;
use super::shader_settings::{make_path_relative_to_shaders, show_reset_button};
pub(super) use super::shader_metadata::save_settings_to_shader_metadata;
pub(super) use super::global_channels::{show_cubemap_controls, show_global_channel_textures};
pub(super) fn show_per_shader_channel_settings(
ui: &mut egui::Ui,
settings: &mut SettingsUI,
shader_name: &str,
meta_defaults: Option<&ShaderConfig>,
changes_this_frame: &mut bool,
) {
let current_override = settings.config.shader_configs.get(shader_name).cloned();
for channel_num in 0..4u8 {
let (override_val, meta_val, global_val) = match channel_num {
0 => (
current_override.as_ref().and_then(|o| o.channel0.clone()),
meta_defaults.and_then(|m| m.channel0.clone()),
settings.config.shader.custom_shader_channel0.clone(),
),
1 => (
current_override.as_ref().and_then(|o| o.channel1.clone()),
meta_defaults.and_then(|m| m.channel1.clone()),
settings.config.shader.custom_shader_channel1.clone(),
),
2 => (
current_override.as_ref().and_then(|o| o.channel2.clone()),
meta_defaults.and_then(|m| m.channel2.clone()),
settings.config.shader.custom_shader_channel2.clone(),
),
3 => (
current_override.as_ref().and_then(|o| o.channel3.clone()),
meta_defaults.and_then(|m| m.channel3.clone()),
settings.config.shader.custom_shader_channel3.clone(),
),
_ => continue,
};
let is_explicitly_cleared = override_val.as_ref().is_some_and(|v| v.is_empty());
let effective_value = if is_explicitly_cleared {
None
} else {
override_val
.clone()
.or(meta_val.clone())
.or(global_val.clone())
};
let mut display_value = effective_value.clone().unwrap_or_default();
let has_override = override_val.is_some();
let has_default_value = meta_val.is_some() || global_val.is_some();
let can_clear = has_default_value && !is_explicitly_cleared;
ui.horizontal(|ui| {
ui.label(format!("iChannel{}:", channel_num));
let response = if is_explicitly_cleared {
ui.add(egui::TextEdit::singleline(&mut display_value).hint_text("(cleared)"))
} else {
ui.text_edit_singleline(&mut display_value)
};
if response.changed() {
let override_entry = settings.config.get_or_create_shader_override(shader_name);
let new_val = if display_value.is_empty() {
None
} else {
Some(display_value.clone())
};
match channel_num {
0 => override_entry.channel0 = new_val,
1 => override_entry.channel1 = new_val,
2 => override_entry.channel2 = new_val,
3 => override_entry.channel3 = new_val,
_ => {}
}
settings.has_changes = true;
*changes_this_frame = true;
}
if ui.button("Browse…").clicked()
&& let Some(path) =
settings.pick_file_path(&format!("Select iChannel{} texture", channel_num))
{
let relative_path = make_path_relative_to_shaders(&path);
let override_entry = settings.config.get_or_create_shader_override(shader_name);
match channel_num {
0 => override_entry.channel0 = Some(relative_path),
1 => override_entry.channel1 = Some(relative_path),
2 => override_entry.channel2 = Some(relative_path),
3 => override_entry.channel3 = Some(relative_path),
_ => {}
}
settings.has_changes = true;
*changes_this_frame = true;
}
if can_clear
&& ui
.button("×")
.on_hover_text("Clear texture (override default)")
.clicked()
{
let override_entry = settings.config.get_or_create_shader_override(shader_name);
match channel_num {
0 => override_entry.channel0 = Some(String::new()),
1 => override_entry.channel1 = Some(String::new()),
2 => override_entry.channel2 = Some(String::new()),
3 => override_entry.channel3 = Some(String::new()),
_ => {}
}
settings.has_changes = true;
*changes_this_frame = true;
}
if show_reset_button(ui, has_override)
&& let Some(override_entry) = settings.config.shader_configs.get_mut(shader_name)
{
match channel_num {
0 => override_entry.channel0 = None,
1 => override_entry.channel1 = None,
2 => override_entry.channel2 = None,
3 => override_entry.channel3 = None,
_ => {}
}
settings.has_changes = true;
*changes_this_frame = true;
}
});
}
ui.add_space(4.0);
let cubemap_override = current_override.as_ref().and_then(|o| o.cubemap.clone());
let cubemap_meta = meta_defaults.and_then(|m| m.cubemap.clone());
let cubemap_global = settings.config.shader.custom_shader_cubemap.clone();
let is_cubemap_cleared = cubemap_override.as_ref().is_some_and(|v| v.is_empty());
let effective_cubemap = if is_cubemap_cleared {
None
} else {
cubemap_override
.clone()
.or(cubemap_meta.clone())
.or(cubemap_global.clone())
};
let has_cubemap_override = cubemap_override.is_some();
let has_cubemap_default = cubemap_meta.is_some() || cubemap_global.is_some();
ui.horizontal(|ui| {
ui.label("Cubemap:");
let selected_text = if is_cubemap_cleared {
"(cleared)".to_string()
} else if let Some(ref path) = effective_cubemap {
if path.is_empty() {
"(none)".to_string()
} else {
path.rsplit('/').next().unwrap_or(path).to_string()
}
} else {
"(none)".to_string()
};
let mut cubemap_changed = false;
let combo_id = format!("cubemap_override_{}", shader_name);
egui::ComboBox::from_id_salt(&combo_id)
.selected_text(&selected_text)
.width(150.0)
.show_ui(ui, |ui| {
let using_default = !has_cubemap_override;
if ui
.selectable_label(using_default, "(use default)")
.clicked()
&& !using_default
{
if let Some(override_entry) =
settings.config.shader_configs.get_mut(shader_name)
{
override_entry.cubemap = None;
}
cubemap_changed = true;
}
if has_cubemap_default
&& ui
.selectable_label(is_cubemap_cleared, "(none/clear)")
.clicked()
&& !is_cubemap_cleared
{
let override_entry = settings.config.get_or_create_shader_override(shader_name);
override_entry.cubemap = Some(String::new());
cubemap_changed = true;
}
ui.separator();
for cubemap in &settings.available_cubemaps.clone() {
let display_name = cubemap.rsplit('/').next().unwrap_or(cubemap);
let is_selected = effective_cubemap.as_ref().is_some_and(|c| c == cubemap);
if ui.selectable_label(is_selected, display_name).clicked() {
let override_entry =
settings.config.get_or_create_shader_override(shader_name);
override_entry.cubemap = Some(cubemap.clone());
cubemap_changed = true;
}
}
});
if cubemap_changed {
settings.has_changes = true;
*changes_this_frame = true;
}
if ui
.button("↻")
.on_hover_text("Refresh cubemap list")
.clicked()
{
settings.refresh_cubemaps();
}
if show_reset_button(ui, has_cubemap_override)
&& let Some(override_entry) = settings.config.shader_configs.get_mut(shader_name)
{
override_entry.cubemap = None;
settings.has_changes = true;
*changes_this_frame = true;
}
});
let cubemap_enabled_override = current_override.as_ref().and_then(|o| o.cubemap_enabled);
let cubemap_enabled_meta = meta_defaults.and_then(|m| m.cubemap_enabled);
let effective_cubemap_enabled = cubemap_enabled_override
.or(cubemap_enabled_meta)
.unwrap_or(settings.config.shader.custom_shader_cubemap_enabled);
let has_cubemap_enabled_override = cubemap_enabled_override.is_some();
let mut value = effective_cubemap_enabled;
ui.horizontal(|ui| {
if ui.checkbox(&mut value, "Enable cubemap").changed() {
let override_entry = settings.config.get_or_create_shader_override(shader_name);
override_entry.cubemap_enabled = Some(value);
settings.has_changes = true;
*changes_this_frame = true;
}
if show_reset_button(ui, has_cubemap_enabled_override)
&& let Some(override_entry) = settings.config.shader_configs.get_mut(shader_name)
{
override_entry.cubemap_enabled = None;
settings.has_changes = true;
*changes_this_frame = true;
}
});
}