use concinnity_core::components::{FrameInput, SettingCommand, SettingOp, TextLabel};
use concinnity_core::ecs::asset_id::AssetId;
use concinnity_core::ecs::{PipelineContext, StepResult};
use concinnity_core::settings::SettingKey;
use super::UiInputSystem;
pub(super) const REBIND_PROMPT: &str = "Press a key...";
const PAD_REBIND_PROMPT: &str = "Press a button...";
#[derive(Debug)]
pub(super) struct Capture {
setting_key: SettingKey,
value_label: Option<AssetId>,
prev_text: String,
}
fn captures_button(setting_key: SettingKey) -> bool {
matches!(setting_key, SettingKey::PadRebind(_))
}
impl UiInputSystem {
pub(super) fn step_rebind_capture(
&mut self,
input: &FrameInput,
ctx: &mut PipelineContext,
) -> StepResult {
let Some(cap) = self.capturing.as_ref() else {
return StepResult::Continue;
};
let op = if captures_button(cap.setting_key) {
input.captured_button.map(SettingOp::RebindButton)
} else {
input.captured_key.map(SettingOp::Rebind)
};
if input.escape {
self.cancel_capture(ctx);
} else if let Some(op) = op
&& let Some(cap) = self.capturing.take()
{
ctx.events_mut::<SettingCommand>().send(SettingCommand {
setting: cap.setting_key,
op,
value_label: cap.value_label,
persist: true,
});
}
StepResult::Continue
}
pub(super) fn begin_capture(
&mut self,
setting_key: SettingKey,
value_label: Option<AssetId>,
ctx: &mut PipelineContext,
) {
let prev_text = value_label
.and_then(|id| ctx.get_by_id::<TextLabel>(id).map(|l| l.content.clone()))
.unwrap_or_default();
if let Some(id) = value_label {
let prompt = if captures_button(setting_key) {
PAD_REBIND_PROMPT
} else {
REBIND_PROMPT
};
crate::ecs::by_asset_id::set_text(ctx, id, prompt);
}
self.capturing = Some(Capture {
setting_key,
value_label,
prev_text,
});
}
pub(super) fn cancel_capture(&mut self, ctx: &mut PipelineContext) {
if let Some(cap) = self.capturing.take()
&& let Some(id) = cap.value_label
{
crate::ecs::by_asset_id::set_text(ctx, id, &cap.prev_text);
}
}
}
#[cfg(test)]
mod tests {
use concinnity_core::components::GamepadAction;
use concinnity_core::input::keymap::Bindable;
use super::*;
#[test]
fn pad_settings_capture_a_button() {
assert!(captures_button(SettingKey::PadRebind(GamepadAction::Jump)));
assert!(!captures_button(SettingKey::KeyRebind(Bindable::Forward)));
}
}