use crate::ecs::ui::components::UiWidgetState;
use crate::ecs::ui::state::UiStateTrait as _;
use crate::ecs::world::World;
use nalgebra_glm::Vec2;
use super::InteractionSnapshot;
pub(super) fn handle_toggle(
world: &mut World,
entity: freecs::Entity,
interaction: &InteractionSnapshot,
data: &crate::ecs::ui::components::UiToggleData,
delta_time: f32,
) {
let mut value = data.value;
let mut changed = false;
let mut animated_position = data.animated_position;
if interaction.clicked {
value = !value;
changed = true;
}
let target = if value { 1.0 } else { 0.0 };
let speed = 8.0;
let diff = target - animated_position;
if diff.abs() > 0.001 {
animated_position += diff.signum() * speed * delta_time;
animated_position = animated_position.clamp(0.0, 1.0);
} else {
animated_position = target;
}
let theme = world.resources.retained_ui.theme_state.active_theme();
let toggle_height = theme.toggle_height;
let toggle_width = theme.toggle_width;
let on_color = theme.accent_color;
let off_color = theme.background_color;
let knob_padding = 2.0;
let knob_size = toggle_height - knob_padding * 2.0;
let knob_travel = toggle_width - knob_size - knob_padding * 2.0;
let knob_x = knob_padding + animated_position * knob_travel;
if let Some(knob_node) = world.ui.get_ui_layout_node_mut(data.knob_entity)
&& let Some(crate::ecs::ui::layout_types::UiLayoutType::Window(window)) =
knob_node.layouts[crate::ecs::ui::state::UiBase::INDEX].as_mut()
{
window.position = crate::ecs::ui::units::Ab(Vec2::new(knob_x, knob_padding)).into();
}
let blended = off_color + (on_color - off_color) * animated_position;
if let Some(color) = world.ui.get_ui_node_color_mut(entity) {
color.colors[crate::ecs::ui::state::UiBase::INDEX] = Some(blended);
}
if let Some(UiWidgetState::Toggle(widget_data)) = world.ui.get_ui_widget_state_mut(entity) {
widget_data.value = value;
widget_data.changed = changed;
widget_data.animated_position = animated_position;
}
if changed {
world
.resources
.retained_ui
.frame_events
.push(crate::ecs::ui::resources::UiEvent::ToggleChanged { entity, value });
}
}
pub(super) fn handle_checkbox(
world: &mut World,
entity: freecs::Entity,
interaction: &InteractionSnapshot,
data: &crate::ecs::ui::components::UiCheckboxData,
) {
if interaction.clicked {
let new_value = !data.value;
if let Some(node) = world.ui.get_ui_layout_node_mut(data.inner_entity) {
node.visible = new_value;
}
if let Some(UiWidgetState::Checkbox(widget_data)) = world.ui.get_ui_widget_state_mut(entity)
{
widget_data.value = new_value;
widget_data.changed = true;
}
world.resources.retained_ui.frame_events.push(
crate::ecs::ui::resources::UiEvent::CheckboxChanged {
entity,
value: new_value,
},
);
} else if let Some(UiWidgetState::Checkbox(widget_data)) =
world.ui.get_ui_widget_state_mut(entity)
{
widget_data.changed = false;
}
}
pub(super) fn handle_radio(
world: &mut World,
entity: freecs::Entity,
interaction: &InteractionSnapshot,
data: &crate::ecs::ui::components::UiRadioData,
) {
if let Some(UiWidgetState::Radio(widget_data)) = world.ui.get_ui_widget_state_mut(entity) {
widget_data.changed = false;
}
if interaction.clicked && !data.selected {
if let Some(node) = world.ui.get_ui_layout_node_mut(data.inner_entity) {
node.visible = true;
}
let siblings = world
.resources
.retained_ui
.radio_groups
.get(&data.group_id)
.cloned()
.unwrap_or_default();
for other_entity in siblings {
if other_entity == entity {
continue;
}
let other_data_clone = world.ui.get_ui_widget_state(other_entity).cloned();
if let Some(UiWidgetState::Radio(other_radio)) = other_data_clone
&& other_radio.selected
{
if let Some(node) = world.ui.get_ui_layout_node_mut(other_radio.inner_entity) {
node.visible = false;
}
if let Some(UiWidgetState::Radio(wd)) =
world.ui.get_ui_widget_state_mut(other_entity)
{
wd.selected = false;
}
}
}
if let Some(UiWidgetState::Radio(widget_data)) = world.ui.get_ui_widget_state_mut(entity) {
widget_data.selected = true;
widget_data.changed = true;
}
world.resources.retained_ui.frame_events.push(
crate::ecs::ui::resources::UiEvent::RadioChanged {
entity,
group_id: data.group_id,
option_index: data.option_index,
},
);
}
}
pub(super) fn handle_collapsing_header(
world: &mut World,
entity: freecs::Entity,
interaction: &InteractionSnapshot,
data: &crate::ecs::ui::components::UiCollapsingHeaderData,
) {
if let Some(UiWidgetState::CollapsingHeader(widget_data)) =
world.ui.get_ui_widget_state_mut(entity)
{
widget_data.changed = false;
}
if interaction.clicked {
let new_open = !data.open;
if let Some(node) = world.ui.get_ui_layout_node_mut(data.content_entity) {
node.visible = new_open;
}
world.resources.text_cache.set_text(
data.arrow_text_slot,
if new_open { "\u{25BC}" } else { "\u{25B6}" },
);
if let Some(UiWidgetState::CollapsingHeader(widget_data)) =
world.ui.get_ui_widget_state_mut(entity)
{
widget_data.open = new_open;
widget_data.changed = true;
}
}
}