diff --git a/crates/ui-egui/src/dialogs/revolve_lights.rs b/crates/ui-egui/src/dialogs/revolve_lights.rs index dc57cae943..1a4116b7ee 100644 --- a/crates/ui-egui/src/dialogs/revolve_lights.rs +++ b/crates/ui-egui/src/dialogs/revolve_lights.rs @@ -142,7 +142,6 @@ pub(super) fn show(ui: &mut egui::Ui, d: &mut Dialog) { // The selected light last, so it is drawn above the others and a press there takes it. let order = (0..lights.len()).filter(|&i| i != current).chain([current]); let mut moved = None; - let mut picked = None; let enabled = ui.is_enabled(); for index in order { let light = lights.get(index).copied().unwrap_or(first); @@ -150,13 +149,12 @@ pub(super) fn show(ui: &mut egui::Ui, d: &mut Dialog) { let id = Id::unique(("three-d-lighting-widget", index)); let response = ui.interact(Rect::from_center_size(at, Vec2::splat((SUN + 4.0) * 2.0)), id, Sense::click_and_drag()); response.widget_info(|| egui::WidgetInfo::labeled(egui::Role::Slider, enabled, light.name(index))); - if response.drag_started() || response.clicked() { - // A light the pointer took takes the keyboard focus too, so the arrow keys move it next. + // A light the pointer took, or that the keyboard focus reached, becomes the selected light and + // keeps the focus, so the arrow keys move it next. Selecting another light stops the editor + // that had the focus, which clears the focus, so the light asks for it after that. + if response.drag_started() || response.clicked() || response.gained_focus() { + select(ui, d, index); response.request_focus(); - picked = Some(index); - } - if response.gained_focus() { - picked = Some(index); } let origin = ui.input(|i| i.pointer.press_origin()); if response.drag_started() @@ -213,9 +211,6 @@ pub(super) fn show(ui: &mut egui::Ui, d: &mut Dialog) { } response.on_hover_text(tl!("Drag a light to move it. The arrow keys move the focused light; Shift steps 15°.")); } - if let Some(index) = picked { - select(ui, d, index); - } // Only a setting that moved is written: a press that leaves a light where it is, or a key at a // limit, changes nothing, and a key leaves the other setting as each selected effect has it. if let Some((index, (rotation, height))) = moved diff --git a/crates/ui-egui/src/panels/tests_three_d.rs b/crates/ui-egui/src/panels/tests_three_d.rs index 3004195d36..fd3a30c7bf 100644 --- a/crates/ui-egui/src/panels/tests_three_d.rs +++ b/crates/ui-egui/src/panels/tests_three_d.rs @@ -965,6 +965,25 @@ fn the_arrow_keys_move_the_focused_light() { assert_eq!(undo_len(&app), history + 2); } +/// A press on another light selects it and gives it the keyboard focus, so the next arrow key +/// moves that light and leaves the one selected before where it is. +#[test] +fn the_arrow_keys_move_the_light_pressed_last() { + use crate::panels::tests_appearance::{click, frame_events}; + let light = + |rotation: f64| json!({"color": "#ffffff", "intensity": 80.0, "rotation": rotation, "height": 30.0, "softness": 0.0, "behind": false}); + let (mut app, ctx) = lighting_app(json!({"lights": [light(0.0), light(180.0)]})); + let (_, first) = light_node(&mut app, &ctx, 1); + click(&ctx, &mut app, first, show); + let (_, second) = light_node(&mut app, &ctx, 2); + click(&ctx, &mut app, second, show); + let left = egui::Event::Key { key: egui::Key::ArrowLeft, physical_key: None, pressed: true, repeat: false, modifiers: egui::Modifiers::NONE }; + frame_events(&ctx, &mut app, vec![left], show); + frame_events(&ctx, &mut app, vec![], show); + let rotations = effect(&app).1["lights"].as_array().unwrap().iter().map(|l| l["rotation"].clone()).collect::>(); + assert_eq!(rotations, [json!(0.0), json!(-179.0)]); +} + #[test] fn changed_settings_lists_only_new_values() { let before = json!({"depth": 50.0, "cap": true, "bevel": "none"});