use egui::{ComboBox, DragValue, Ui};
use gled_model::asset::midi_controller::{
MidiController, MidiEffectParameter, MidiMeterOutput, MidiMode, MidiValueOutput,
MidiValueSource, MidiValueSourceKind,
};
use strum::IntoEnumIterator;
use super::{
action_converters::{effect_target_editor, scene_target_editor},
modes_editor::mode_picker,
value_source_converters::{value_source_from_kind, value_source_uses_active_value},
};
pub(super) fn value_output_editor(
ui: &mut Ui,
value: &mut MidiValueOutput,
modes: &[MidiMode],
dirty: &mut bool,
controller_id: gled_model::asset_id::AssetId<MidiController>,
index: usize,
) -> (bool, bool) {
let mut preview_active = false;
let mut blackout_blink_preview_active = false;
value_source_kind_editor(ui, &mut value.source, dirty, controller_id, index);
if value_source_uses_active_value(&value.source) {
let mut r = None;
ui.horizontal(|ui| {
ui.label("Value");
let drag = ui.add(DragValue::new(&mut value.active_value).range(0..=127));
if drag.changed() {
*dirty = true;
}
r = Some(drag);
});
if let Some(r) = r {
preview_active = preview_active || r.hovered() || r.dragged() || r.changed();
}
} else {
let mut any_hovered = false;
let mut any_dragged = false;
ui.horizontal(|ui| {
ui.label("Min");
let r = ui.add(DragValue::new(&mut value.min).range(0..=127));
if r.changed() {
*dirty = true;
}
any_hovered |= r.hovered();
any_dragged |= r.dragged();
ui.label("Max");
let r = ui.add(DragValue::new(&mut value.max).range(0..=127));
if r.changed() {
*dirty = true;
}
any_hovered |= r.hovered();
any_dragged |= r.dragged();
});
preview_active = preview_active || any_hovered || any_dragged;
}
let (settings_preview, blink_preview) =
value_source_settings_editor(ui, &mut value.source, modes, dirty, controller_id, index);
preview_active |= settings_preview;
blackout_blink_preview_active |= blink_preview;
(preview_active, blackout_blink_preview_active)
}
fn value_source_kind_editor(
ui: &mut Ui,
source: &mut MidiValueSource,
dirty: &mut bool,
controller_id: gled_model::asset_id::AssetId<MidiController>,
index: usize,
) {
ComboBox::new(format!("{}_value_source_{index}", controller_id), "")
.selected_text(MidiValueSourceKind::from(&*source).to_string())
.show_ui(ui, |ui| {
let mut kind = MidiValueSourceKind::from(&*source);
let mut changed = false;
for candidate in MidiValueSourceKind::iter() {
changed |= ui
.selectable_value(&mut kind, candidate, candidate.to_string())
.changed();
}
if changed {
*source = value_source_from_kind(kind, source.clone());
*dirty = true;
}
});
}
fn value_source_settings_editor(
ui: &mut Ui,
source: &mut MidiValueSource,
modes: &[MidiMode],
dirty: &mut bool,
controller_id: gled_model::asset_id::AssetId<MidiController>,
index: usize,
) -> (bool, bool) {
let mut preview_active = false;
let mut blackout_blink_preview_active = false;
match source {
MidiValueSource::ModeActive { mode } => {
mode_picker(
ui,
mode,
modes,
dirty,
format!("{controller_id}_value_mode_{index}"),
);
}
MidiValueSource::BeatFlankPulse {
start_beat,
end_beat,
blackout_blink_value,
} => {
let mut any_hovered = false;
let mut any_dragged = false;
ui.horizontal(|ui| {
ui.label("Start Beat");
let r = ui.add(DragValue::new(start_beat).speed(0.01).range(0.0..=4.0));
if r.changed() {
*dirty = true;
}
any_hovered |= r.hovered();
any_dragged |= r.dragged();
ui.label("End Beat");
let r = ui.add(DragValue::new(end_beat).speed(0.01).range(0.0..=4.0));
if r.changed() {
*dirty = true;
}
any_hovered |= r.hovered();
any_dragged |= r.dragged();
});
preview_active = preview_active || any_hovered || any_dragged;
ui.small("Inclusive beat range on 0.0..4.0, wrap supported");
let mut blink_enabled = blackout_blink_value.is_some();
if ui
.checkbox(&mut blink_enabled, "Blink at 4 Hz on blackout")
.changed()
{
*blackout_blink_value = if blink_enabled { Some(127) } else { None };
*dirty = true;
}
if let Some(v) = blackout_blink_value {
let mut blink_hovered = false;
let mut blink_dragged = false;
ui.horizontal(|ui| {
ui.label("Blackout blink value");
let r = ui.add(DragValue::new(v).range(1..=127));
if r.changed() {
*dirty = true;
}
blink_hovered |= r.hovered();
blink_dragged |= r.dragged();
});
blackout_blink_preview_active = blink_hovered || blink_dragged;
}
}
MidiValueSource::Blackout { inverted, blink } => {
let invert_response = ui.checkbox(inverted, "Invert (On when blackout is off)");
if invert_response.changed() {
*dirty = true;
}
let blink_response = ui.checkbox(blink, "Blink at 2 Hz when active");
if blink_response.changed() {
*dirty = true;
}
preview_active = preview_active
|| invert_response.hovered()
|| invert_response.changed()
|| blink_response.hovered()
|| blink_response.changed();
}
MidiValueSource::SceneOpacity { target }
| MidiValueSource::SceneInputDimmer { target }
| MidiValueSource::SceneBeatOffset { target }
| MidiValueSource::SceneIgnoreMainDimmer { target }
| MidiValueSource::SceneSetOffsetOnFlash { target }
| MidiValueSource::SceneActive { target }
| MidiValueSource::SceneFlashed { target }
| MidiValueSource::SceneSelected { target } => {
scene_target_editor(
ui,
target,
dirty,
format!("{}_value_target_{index}", controller_id),
);
}
MidiValueSource::SceneEffectSettingF32 {
target,
effect,
setting_index,
} => {
scene_target_editor(
ui,
target,
dirty,
format!("{}_value_target_{index}", controller_id),
);
let r = effect_target_editor(
ui,
effect,
dirty,
format!("{controller_id}_value_effect_{index}"),
);
preview_active = preview_active || r.hovered();
ui.horizontal(|ui| {
ui.label("Setting Index");
let r = ui.add(DragValue::new(setting_index).range(0..=5));
if r.changed() {
*dirty = true;
}
preview_active = preview_active || r.hovered() || r.dragged();
});
}
MidiValueSource::SceneEffectOpacity { target, effect }
| MidiValueSource::SceneEffectColorShift { target, effect }
| MidiValueSource::SceneEffectBeatProgression { target, effect }
| MidiValueSource::SceneEffectBeatOffset { target, effect }
| MidiValueSource::SceneEffectSpeedExponent { target, effect }
| MidiValueSource::SceneEffectLayout { target, effect } => {
scene_target_editor(
ui,
target,
dirty,
format!("{}_value_target_{index}", controller_id),
);
let r = effect_target_editor(
ui,
effect,
dirty,
format!("{controller_id}_value_effect_{index}"),
);
preview_active = preview_active || r.hovered();
}
MidiValueSource::EffectSelected {
index: effect_index,
} => {
ui.horizontal(|ui| {
ui.label("Effect Index");
let r = ui.add(DragValue::new(effect_index).range(0..=255));
if r.changed() {
*dirty = true;
}
preview_active = preview_active || r.hovered() || r.dragged();
});
}
MidiValueSource::SelectedSceneEffectLive { effect, parameter } => {
let r = effect_target_editor(
ui,
effect,
dirty,
format!("{controller_id}_value_effect_{index}"),
);
preview_active = preview_active || r.hovered();
ui.horizontal(|ui| {
ui.label("Value");
ComboBox::new(format!("{controller_id}_value_parameter_{index}"), "")
.selected_text(parameter.to_string())
.show_ui(ui, |ui| {
for candidate in MidiEffectParameter::iter() {
if ui
.selectable_value(parameter, candidate, candidate.to_string())
.changed()
{
*dirty = true;
}
}
});
});
}
_ => {}
}
(preview_active, blackout_blink_preview_active)
}
pub(super) fn meter_output_editor(
ui: &mut Ui,
meter: &mut MidiMeterOutput,
modes: &[MidiMode],
dirty: &mut bool,
controller_id: gled_model::asset_id::AssetId<MidiController>,
index: usize,
) {
ui.horizontal(|ui| {
ui.label("Strip");
let mut strip = meter.strip + 1;
if ui
.add(DragValue::new(&mut strip).range(1..=8))
.on_hover_text("The channel strip whose meter shows the value")
.changed()
{
meter.strip = strip - 1;
*dirty = true;
}
});
value_source_kind_editor(ui, &mut meter.source, dirty, controller_id, index);
let _ = value_source_settings_editor(ui, &mut meter.source, modes, dirty, controller_id, index);
}