1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use ratatui_core::layout::Rect;
use crate::{RangeSampler, SimpleRng};
/// Specifies the direction of movement for visual effects like sweeps and slides.
///
/// This enum defines the four cardinal directions that effects can move in. It is used by
/// various effects to determine their direction of animation, such as sweep effects,
/// slide transitions, and other directional visual effects.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum Motion {
/// Movement from left to right
LeftToRight,
/// Movement from right to left
RightToLeft,
/// Movement from top to bottom
UpToDown,
/// Movement from bottom to top
DownToUp,
}
impl Motion {
/// Returns the opposite direction of the current motion.
///
/// This is used internally by effects that need to reverse their direction,
/// such as when implementing ping-pong animations or transitioning between states.
///
/// # Returns
///
/// The opposite direction of the current motion
pub(crate) fn flipped(self) -> Self {
match self {
Self::LeftToRight => Self::RightToLeft,
Self::RightToLeft => Self::LeftToRight,
Self::UpToDown => Self::DownToUp,
Self::DownToUp => Self::UpToDown,
}
}
/// Determines whether this motion direction requires timer reversal.
///
/// Some motions (RightToLeft and DownToUp) require the effect timer to be reversed
/// to maintain consistent animation behavior. This method is used internally by
/// effects to determine if they should reverse their timer.
///
/// # Returns
///
/// `true` if the motion requires timer reversal (RightToLeft or DownToUp),
/// `false` otherwise.
pub(crate) fn flips_timer(self) -> bool {
self == Motion::RightToLeft || self == Motion::DownToUp
}
}
/// Generates random variances for directional effects.
pub(crate) struct DirectionalVariance {
rng: SimpleRng,
direction: Motion,
max: i16,
}
impl DirectionalVariance {
/// Creates a new `DirectionalVariance` instance.
///
/// This method initializes a `DirectionalVariance` with a seed based on the given
/// area's dimensions, the specified direction for the sliding effect, and the
/// maximum variance allowed.
///
/// # Arguments
///
/// * `area` - The `Rect` representing the area of the effect. Used to seed the RNG.
/// * `direction` - The `Direction` of the sliding effect.
/// * `max` - The maximum variance that can be generated.
///
/// # Returns
///
/// A new `DirectionalVariance` instance.
#[allow(dead_code)]
pub(super) fn from(area: Rect, direction: Motion, max: u16) -> Self {
Self {
rng: SimpleRng::new(((area.width as u32) << 16) | area.height as u32),
direction,
max: max as i16,
}
}
/// Creates a new `DirectionalVariance` instance with a provided RNG.
///
/// # Arguments
///
/// * `rng` - The `SimpleRng` to use for generating variances.
/// * `direction` - The `Direction` of the sliding effect.
/// * `max` - The maximum variance that can be generated.
///
/// # Returns
///
/// A new `DirectionalVariance` instance.
pub(super) fn with_rng(rng: SimpleRng, direction: Motion, max: u16) -> Self {
Self { rng, direction, max: max as i16 }
}
/// Generates the next variance value.
///
/// This method produces a tuple representing an (x, y) offset based on the
/// configured direction and maximum variance. The generated variance is always
/// within the range [-max, max] for the relevant axis, and 0 for the other axis.
///
/// # Returns
///
/// A tuple `(i16, i16)` representing the (x, y) variance to be applied.
/// If the maximum variance is set to 0, it always returns (0, 0).
pub(crate) fn next(&mut self) -> (i16, i16) {
if self.max == 0 {
return (0, 0);
}
let variance = self.rng.gen_range(0..self.max);
match self.direction {
Motion::LeftToRight => (variance, 0),
Motion::RightToLeft => (-variance, 0),
Motion::UpToDown => (0, variance),
Motion::DownToUp => (0, -variance),
}
}
}