1
0
Fork 0
forked from wry/wry

Use live content for normal animations

This commit is contained in:
atagen 2026-05-27 22:08:09 +10:00
parent 6c133018aa
commit 502a93a00a
5 changed files with 134 additions and 52 deletions

View file

@ -809,7 +809,7 @@ fn plan_axis_crossing_lanes(
.copied()
.filter(|window| window.from != window.to)
.collect();
if moving_windows.len() != 2 {
if moving_windows.len() < 2 {
return Err(MultiphasePlanFailure::NoPattern);
}
let orth_min = request
@ -855,12 +855,7 @@ fn plan_axis_crossing_lanes(
}
let mut windows = moving_windows;
windows.sort_by_key(|window| lane_index_for_direction(*window, axis));
if windows.windows(2).any(|pair| {
lane_index_for_direction(pair[0], axis) == lane_index_for_direction(pair[1], axis)
}) {
return Err(MultiphasePlanFailure::NoPattern);
}
windows.sort_by_key(|window| lane_sort_key(*window, axis));
let mut phase1 = vec![];
let mut phase2 = vec![];
let mut phase3 = vec![];
@ -935,13 +930,19 @@ fn crossing_lane_move_rect(from: Rect, target: Rect, axis: PhaseAxis) -> Rect {
}
}
fn lane_index_for_direction(window: MultiphaseWindow, axis: PhaseAxis) -> Option<usize> {
fn lane_sort_key(window: MultiphaseWindow, axis: PhaseAxis) -> (usize, i32, i32, u32) {
let delta = main_start(window.to, axis) - main_start(window.from, axis);
match delta.cmp(&0) {
std::cmp::Ordering::Greater => Some(0),
std::cmp::Ordering::Less => Some(1),
std::cmp::Ordering::Equal => None,
}
let direction = match delta.cmp(&0) {
std::cmp::Ordering::Greater => 0,
std::cmp::Ordering::Less => 1,
std::cmp::Ordering::Equal => 2,
};
(
direction,
main_start(window.from, axis),
main_start(window.to, axis),
window.node_id.0,
)
}
fn plan_space_then_orthogonal_growth(
@ -2151,6 +2152,41 @@ mod tests {
assert!(validate_plan_continuous(&req, &planned.plan));
}
#[test]
fn horizontal_rotation_uses_crossing_lanes() {
let req = request(vec![
window(1, rect(0, 0, 100, 100), rect(100, 0, 200, 100)),
window(2, rect(100, 0, 200, 100), rect(200, 0, 300, 100)),
window(3, rect(200, 0, 300, 100), rect(0, 0, 100, 100)),
]);
let planned = plan_no_overlap_explained(&req).unwrap();
assert_eq!(
planned.explanation.strategy,
PlanStrategy::SwapLanes {
axis: PhaseAxis::Horizontal,
}
);
assert_eq!(
actions(&planned.plan),
vec![
PhaseAction {
kind: PhaseKind::Scale,
axis: PhaseAxis::Vertical,
},
PhaseAction {
kind: PhaseKind::Move,
axis: PhaseAxis::Horizontal,
},
PhaseAction {
kind: PhaseKind::Scale,
axis: PhaseAxis::Vertical,
},
]
);
assert!(validate_plan_continuous(&req, &planned.plan));
}
#[test]
fn vertical_swap_lanes_follow_motion_direction_not_node_id() {
let req = request(vec![
@ -2875,6 +2911,36 @@ mod tests {
assert!(validate_plan_continuous(&req, &plan));
}
#[test]
fn vertical_stack_extraction_with_clearance_still_plans() {
let old = split(
20,
PhaseAxis::Vertical,
&[1, 1],
vec![
leaf(1),
split(21, PhaseAxis::Horizontal, &[1, 1], vec![leaf(2), leaf(3)]),
],
);
let new = split(
20,
PhaseAxis::Vertical,
&[1, 2, 1],
vec![leaf(1), leaf(2), leaf(3)],
);
let mut req = generated_request(&old, &new, rect(0, 0, 100, 400));
req.clearance = 10;
let planned = plan_no_overlap_explained(&req).unwrap();
assert_eq!(
planned.explanation.strategy,
PlanStrategy::SpaceThenOrthogonalGrowth {
axis: PhaseAxis::Vertical,
}
);
assert!(validate_plan_continuous(&req, &planned.plan));
}
#[test]
fn vertical_stack_extraction_reverse_replays_phases_in_reverse() {
let req = request(vec![