Skip to main content

siglus_scene_vm/runtime/
int_event.rs

1//! Integer event (linear interpolation / loop / turn) used by a few engine subsystems.
2//!
3//! This follows the original Siglus behavior:
4//! - `value` is the "current" stored value (for oneshot, it is set to the target immediately).
5//! - `cur_value` is the animated/interpolated value computed each frame.
6
7#[derive(Debug, Clone)]
8pub struct IntEvent {
9    pub def_value: i32,
10    pub value: i32,
11    pub cur_time: i32,
12    pub end_time: i32,
13    pub delay_time: i32,
14    pub start_value: i32,
15    pub cur_value: i32,
16    pub end_value: i32,
17    /// -1: none, 0: oneshot, 1: loop, 2: turn
18    pub loop_type: i32,
19    /// -1: none, 0: linear, 1: speed_up, 2: speed_down
20    pub speed_type: i32,
21    /// 0: game time, 1: real time
22    pub real_flag: i32,
23}
24
25impl IntEvent {
26    pub fn new(def_value: i32) -> Self {
27        let mut s = Self {
28            def_value,
29            value: def_value,
30            cur_time: 0,
31            end_time: 0,
32            delay_time: 0,
33            start_value: def_value,
34            cur_value: def_value,
35            end_value: def_value,
36            loop_type: -1,
37            speed_type: -1,
38            real_flag: 0,
39        };
40        s.reinit();
41        s
42    }
43
44    pub fn reinit(&mut self) {
45        self.value = self.def_value;
46        self.cur_time = 0;
47        self.end_time = 0;
48        self.delay_time = 0;
49        self.start_value = self.def_value;
50        self.cur_value = self.def_value;
51        self.end_value = self.def_value;
52        self.loop_type = -1;
53        self.speed_type = -1;
54        self.real_flag = 0;
55    }
56
57    pub fn set_value(&mut self, v: i32) {
58        self.value = v;
59        // Note: the original does not touch the event fields here.
60    }
61
62    pub fn get_value(&self) -> i32 {
63        self.value
64    }
65
66    pub fn get_total_value(&self) -> i32 {
67        self.cur_value
68    }
69
70    pub fn set_event(
71        &mut self,
72        value: i32,
73        total_time: i32,
74        delay_time: i32,
75        speed_type: i32,
76        real_flag: i32,
77    ) {
78        self.cur_time = 0;
79        self.end_time = total_time;
80        self.delay_time = delay_time;
81        self.start_value = self.value;
82        self.cur_value = self.value;
83        self.end_value = value;
84        self.loop_type = 0; // oneshot
85        self.speed_type = speed_type;
86        self.real_flag = real_flag;
87
88        // The original updates the stored value immediately.
89        self.value = value;
90    }
91
92    pub fn loop_event(
93        &mut self,
94        start_value: i32,
95        end_value: i32,
96        loop_time: i32,
97        delay_time: i32,
98        speed_type: i32,
99        real_flag: i32,
100    ) {
101        self.cur_time = 0;
102        self.end_time = loop_time;
103        self.delay_time = delay_time;
104        self.start_value = start_value;
105        self.cur_value = start_value;
106        self.end_value = end_value;
107        self.loop_type = 1; // loop
108        self.speed_type = speed_type;
109        self.real_flag = real_flag;
110    }
111
112    pub fn turn_event(
113        &mut self,
114        start_value: i32,
115        end_value: i32,
116        loop_time: i32,
117        delay_time: i32,
118        speed_type: i32,
119        real_flag: i32,
120    ) {
121        self.cur_time = 0;
122        self.end_time = loop_time;
123        self.delay_time = delay_time;
124        self.start_value = start_value;
125        self.cur_value = start_value;
126        self.end_value = end_value;
127        self.loop_type = 2; // turn
128        self.speed_type = speed_type;
129        self.real_flag = real_flag;
130    }
131
132    pub fn end_event(&mut self) {
133        self.loop_type = -1;
134        self.cur_value = self.value;
135    }
136
137    pub fn check_event(&self) -> bool {
138        self.loop_type != -1
139    }
140
141    pub fn update_time(&mut self, past_game_time: i32, past_real_time: i32) {
142        if self.loop_type == -1 {
143            return;
144        }
145        if self.real_flag == 0 {
146            self.cur_time = self.cur_time.saturating_add(past_game_time);
147        } else {
148            self.cur_time = self.cur_time.saturating_add(past_real_time);
149        }
150    }
151
152    pub fn frame(&mut self) {
153        self.cur_value = self.value;
154        if self.loop_type == -1 {
155            return;
156        }
157        self.frame_sub();
158    }
159
160    fn frame_sub(&mut self) {
161        let end_time = self.end_time;
162        let start_value = self.start_value;
163        let end_value = self.end_value;
164        let mut cur_time = self.cur_time - self.delay_time;
165
166        // oneshot: if time is over, stop the event.
167        if self.loop_type == 0 {
168            if cur_time - end_time >= 0 {
169                self.loop_type = -1;
170                return;
171            }
172        }
173
174        // Not started yet.
175        if cur_time <= 0 {
176            self.cur_value = start_value;
177            return;
178        }
179
180        if end_time <= 0 {
181            // Avoid division by zero / modulo by zero.
182            self.cur_value = end_value;
183            return;
184        }
185
186        if self.loop_type == 1 {
187            cur_time %= end_time;
188        }
189
190        if self.loop_type == 2 {
191            cur_time %= end_time * 2;
192            if cur_time - end_time > 0 {
193                cur_time = end_time - (cur_time - end_time);
194            }
195        }
196
197        match self.speed_type {
198            0 => {
199                self.cur_value = (((end_value - start_value) as f64) * (cur_time as f64)
200                    / (end_time as f64)
201                    + (start_value as f64)) as i32;
202            }
203            1 => {
204                let ct = cur_time as f64;
205                let et = end_time as f64;
206                self.cur_value = (((end_value - start_value) as f64) * ct * ct / et / et
207                    + (start_value as f64)) as i32;
208            }
209            2 => {
210                let ct = (cur_time - end_time) as f64;
211                let et = end_time as f64;
212                self.cur_value = (-(end_value - start_value) as f64 * ct * ct / et / et
213                    + (end_value as f64)) as i32;
214            }
215            _ => {
216                // Unknown/none: keep the last computed value.
217            }
218        }
219    }
220
221    /// Convenience: advance by one "tick".
222    pub fn tick(&mut self, delta: i32) {
223        self.update_time(delta, delta);
224        self.frame();
225    }
226}