1#![warn(missing_docs)]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6#![allow(rustdoc::private_intra_doc_links)]
7#![doc(
8 html_logo_url = "https://raw.githubusercontent.com/AzurIce/ranim/refs/heads/main/assets/ranim.svg",
9 html_favicon_url = "https://raw.githubusercontent.com/AzurIce/ranim/refs/heads/main/assets/ranim.svg"
10)]
11pub mod animation;
12pub mod color;
14pub mod components;
16pub mod timeline;
18pub mod traits;
20pub mod utils;
22
23pub mod core_item;
24pub mod store;
26
27pub mod anchor;
28
29pub use glam;
30pub use num;
31
32pub mod prelude {
34 pub use crate::color::prelude::*;
35 pub use crate::traits::*;
36
37 pub use crate::core_item::camera_frame::CameraFrame;
38 pub use crate::timeline::{TimelineFunc, TimelinesFunc};
39 pub use crate::{RanimScene, TimeMark, TimelineId};
40}
41
42use crate::{animation::StaticAnim, core_item::CoreItem, timeline::Timeline};
43
44pub trait Extract {
46 type Target: Clone;
48 fn extract_into(&self, buf: &mut Vec<Self::Target>);
50 fn extract(&self) -> Vec<Self::Target> {
52 let mut buf = Vec::new();
53 self.extract_into(&mut buf);
54 buf
55 }
56}
57
58impl<E: Extract, I> Extract for I
59where
60 for<'a> &'a I: IntoIterator<Item = &'a E>,
61{
62 type Target = E::Target;
63 fn extract_into(&self, buf: &mut Vec<Self::Target>) {
64 for e in self {
65 e.extract_into(buf);
66 }
67 }
68}
69
70use crate::timeline::{AnimationInfo, TimelineFunc, TimelinesFunc};
71use tracing::trace;
72
73use std::fmt::Debug;
74
75#[derive(Debug, Clone)]
77pub enum TimeMark {
78 Capture(String),
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
84pub struct TimelineId(usize);
85
86impl TimelineId {
87 pub fn id(&self) -> usize {
89 self.0
90 }
91}
92
93#[derive(Default)]
96pub struct RanimScene {
97 pub(crate) timelines: Vec<Timeline>,
98 pub(crate) time_marks: Vec<(f64, TimeMark)>,
99}
100
101impl RanimScene {
102 pub fn seal(mut self) -> SealedRanimScene {
104 let total_secs = self.timelines.max_total_secs();
105 self.timelines.forward_to(total_secs);
106 self.timelines.seal();
107 SealedRanimScene {
108 total_secs,
109 timelines: self.timelines,
110 time_marks: self.time_marks,
111 }
112 }
113 pub fn new() -> Self {
115 Self::default()
116 }
117
118 pub fn insert_empty(&mut self) -> TimelineId {
120 self.insert_empty_at(0.0)
121 }
122
123 pub fn insert_empty_at(&mut self, sec: f64) -> TimelineId {
125 self.insert_with(|t| {
126 t.forward_to(sec);
127 })
128 }
129
130 pub fn insert<T: Extract<Target = CoreItem> + Clone + 'static>(
132 &mut self,
133 item: T,
134 ) -> TimelineId {
135 self.insert_at(item, 0.0)
136 }
137
138 pub fn insert_at<T: Extract<Target = CoreItem> + Clone + 'static>(
140 &mut self,
141 item: T,
142 sec: f64,
143 ) -> TimelineId {
144 self.insert_with(|t| {
145 t.forward_to(sec);
146 t.play(item.show());
147 })
148 }
149
150 pub fn insert_with(&mut self, mut f: impl FnMut(&mut Timeline)) -> TimelineId {
152 let id = TimelineId(self.timelines.len());
153 let mut timeline = Timeline::new();
154 f(&mut timeline);
155 self.timelines.push(timeline);
156 id
157 }
158
159 pub fn timelines(&self) -> &[Timeline] {
161 trace!("timelines");
162 &self.timelines
163 }
164 pub fn timelines_mut(&mut self) -> &mut [Timeline] {
166 trace!("timelines_mut");
167 &mut self.timelines
168 }
169 pub fn timeline<'a, T: TimelineIndex<'a>>(&'a self, index: T) -> T::RefOutput {
171 index.get_index_ref(&self.timelines)
172 }
173 pub fn timeline_mut<'a, T: TimelineIndex<'a>>(&'a mut self, index: T) -> T::MutOutput {
175 index.get_index_mut(&mut self.timelines)
176 }
177 pub fn insert_time_mark(&mut self, sec: f64, time_mark: TimeMark) {
179 self.time_marks.push((sec, time_mark));
180 }
181}
182
183pub struct TimelineInfo {
185 pub id: usize,
187 pub animation_infos: Vec<AnimationInfo>,
189}
190
191impl Debug for RanimScene {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 f.write_fmt(format_args!("Timeline: {} timelines", self.timelines.len()))?;
194 Ok(())
195 }
196}
197
198pub struct SealedRanimScene {
204 pub(crate) total_secs: f64,
205 pub(crate) timelines: Vec<Timeline>,
206 pub(crate) time_marks: Vec<(f64, TimeMark)>,
207}
208
209impl SealedRanimScene {
210 pub fn total_secs(&self) -> f64 {
212 self.total_secs
213 }
214 pub fn time_marks(&self) -> &[(f64, TimeMark)] {
216 &self.time_marks
217 }
218
219 pub fn timelines_iter(&self) -> impl Iterator<Item = &Timeline> {
221 self.timelines.iter()
222 }
223
224 pub fn timelines_cnt(&self) -> usize {
226 self.timelines.len()
227 }
228
229 pub fn get_timeline_infos(&self) -> Vec<TimelineInfo> {
231 self.timelines
233 .iter()
234 .enumerate()
235 .map(|(id, timeline)| TimelineInfo {
237 id,
238 animation_infos: timeline.get_animation_infos(),
239 })
240 .collect()
241 }
242
243 pub fn eval_at_sec(&self, target_sec: f64) -> impl Iterator<Item = ((usize, usize), CoreItem)> {
245 self.timelines_iter()
246 .enumerate()
247 .filter_map(move |(t_id, t)| {
248 t.eval_primitives_at_sec(target_sec)
249 .map(move |(a_id, res)| res.into_iter().map(move |x| ((t_id, a_id), x)))
250 })
251 .flatten()
252 }
253
254 pub fn eval_at_alpha(&self, alpha: f64) -> impl Iterator<Item = ((usize, usize), CoreItem)> {
256 self.eval_at_sec(self.total_secs() * alpha)
257 }
258}
259
260pub trait TimelineIndex<'a> {
275 type RefOutput;
277 type MutOutput;
279 fn get_index_ref(self, timelines: &'a [Timeline]) -> Self::RefOutput;
281 fn get_index_mut(self, timelines: &'a mut [Timeline]) -> Self::MutOutput;
283}
284
285pub trait TimelineQuery<'a> {
291 type RessembleResult;
293 type RessembleMutResult;
295 fn id(&self) -> TimelineId;
297 fn ressemble(self, timeline: &'a Timeline) -> Self::RessembleResult;
299 fn ressemble_mut(self, timeline: &'a mut Timeline) -> Self::RessembleMutResult;
301}
302
303impl<'a> TimelineQuery<'a> for TimelineId {
304 type RessembleResult = &'a Timeline;
305 type RessembleMutResult = &'a mut Timeline;
306 fn id(&self) -> TimelineId {
307 *self
308 }
309 fn ressemble(self, timeline: &'a Timeline) -> Self::RessembleResult {
310 timeline
311 }
312 fn ressemble_mut(self, timeline: &'a mut Timeline) -> Self::RessembleMutResult {
313 timeline
314 }
315}
316
317impl<'a, TI: AsRef<TimelineId>, T> TimelineQuery<'a> for (TI, T) {
318 type RessembleResult = (&'a Timeline, T);
319 type RessembleMutResult = (&'a mut Timeline, T);
320 fn id(&self) -> TimelineId {
321 *self.0.as_ref()
322 }
323 fn ressemble(self, timeline: &'a Timeline) -> Self::RessembleResult {
324 (timeline, self.1)
325 }
326 fn ressemble_mut(self, timeline: &'a mut Timeline) -> Self::RessembleMutResult {
327 (timeline, self.1)
328 }
329}
330
331impl<'a: 'b, 'b, TI: AsRef<TimelineId>, T> TimelineQuery<'a> for &'b (TI, T) {
332 type RessembleResult = (&'b Timeline, &'b T);
333 type RessembleMutResult = (&'b mut Timeline, &'b T);
334 fn id(&self) -> TimelineId {
335 *self.0.as_ref()
336 }
337 fn ressemble(self, timeline: &'a Timeline) -> Self::RessembleResult {
338 (timeline, &self.1)
339 }
340 fn ressemble_mut(self, timeline: &'a mut Timeline) -> Self::RessembleMutResult {
341 (timeline, &self.1)
342 }
343}
344
345impl<'a: 'b, 'b, TI: AsRef<TimelineId>, T> TimelineQuery<'a> for &'b mut (TI, T) {
346 type RessembleResult = (&'b Timeline, &'b mut T);
347 type RessembleMutResult = (&'b mut Timeline, &'b mut T);
348 fn id(&self) -> TimelineId {
349 *self.0.as_ref()
350 }
351 fn ressemble(self, timeline: &'a Timeline) -> Self::RessembleResult {
352 (timeline, &mut self.1)
353 }
354 fn ressemble_mut(self, timeline: &'a mut Timeline) -> Self::RessembleMutResult {
355 (timeline, &mut self.1)
356 }
357}
358
359impl<'a> TimelineIndex<'a> for usize {
360 type RefOutput = Option<&'a Timeline>;
361 type MutOutput = Option<&'a mut Timeline>;
362 fn get_index_ref(self, timelines: &'a [Timeline]) -> Self::RefOutput {
363 timelines.get(self)
364 }
365 fn get_index_mut(self, timelines: &'a mut [Timeline]) -> Self::MutOutput {
366 timelines.get_mut(self)
367 }
368}
369
370impl AsRef<TimelineId> for TimelineId {
371 fn as_ref(&self) -> &TimelineId {
372 self
373 }
374}
375
376impl<'a, TQ: TimelineQuery<'a>> TimelineIndex<'a> for TQ {
377 type RefOutput = TQ::RessembleResult;
378 type MutOutput = TQ::RessembleMutResult;
379 fn get_index_ref(self, timelines: &'a [Timeline]) -> Self::RefOutput {
380 let id = self.id();
381 self.ressemble(id.0.get_index_ref(timelines).unwrap())
382 }
383 fn get_index_mut(self, timelines: &'a mut [Timeline]) -> Self::MutOutput {
384 let id = self.id();
385 self.ressemble_mut(id.0.get_index_mut(timelines).unwrap())
386 }
387}
388
389#[derive(Debug)]
391pub enum TimelineIndexMutError {
392 IndexOverlapping,
394}
395
396impl<'a, TI: TimelineQuery<'a>, const N: usize> TimelineIndex<'a> for [TI; N] {
397 type RefOutput = [TI::RessembleResult; N];
398 type MutOutput = Result<[TI::RessembleMutResult; N], TimelineIndexMutError>;
399 fn get_index_ref(self, timelines: &'a [Timeline]) -> Self::RefOutput {
400 self.map(|x| {
401 let id = x.id();
402 x.ressemble(id.0.get_index_ref(timelines).unwrap())
403 })
404 }
405 fn get_index_mut(self, timelines: &'a mut [Timeline]) -> Self::MutOutput {
407 for (i, idx) in self.iter().enumerate() {
409 for idx2 in self[i + 1..].iter() {
410 if idx.id() == idx2.id() {
411 return Err(TimelineIndexMutError::IndexOverlapping);
412 }
413 }
414 }
415
416 let indices: [usize; N] = std::array::from_fn(|i| self[i].id().0);
418
419 let mut arr: std::mem::MaybeUninit<[TI::RessembleMutResult; N]> =
424 std::mem::MaybeUninit::uninit();
425 let arr_ptr = arr.as_mut_ptr();
426 let timelines_ptr: *mut Timeline = timelines.as_mut_ptr();
427 let self_manually_drop = std::mem::ManuallyDrop::new(self);
428
429 let res = unsafe {
435 for (i, &idx) in indices.iter().enumerate() {
436 let timeline_ref = &mut *timelines_ptr.add(idx);
437 let ti = std::ptr::read(self_manually_drop.as_ptr().add(i));
438 arr_ptr
439 .cast::<TI::RessembleMutResult>()
440 .add(i)
441 .write(ti.ressemble_mut(timeline_ref));
442 }
443 arr.assume_init()
444 };
445
446 Ok(res)
447 }
448}