rosu_renderer/
lib.rs

1pub mod layout;
2
3use crate::layout::mania::{ManiaRenderer, NoteStyle};
4use rosu_map::section::general::GameMode;
5use rosu_map::Beatmap;
6use std::time::Instant;
7
8pub struct Player {
9    beatmap: Beatmap,
10    renderer: GameModeRenderer,
11    start_time: Instant,
12    speed: f64,
13    scroll_time_ms: f32,
14}
15
16enum GameModeRenderer {
17    Mania(ManiaRenderer),
18    // TODO: Ajouter d'autres modes
19    // Standard(StandardRenderer),
20    // Taiko(TaikoRenderer),
21    // Catch(CatchRenderer),
22}
23
24impl Player {
25    pub fn new(beatmap: Beatmap, column_width: f32, note_size: f32, height: f32) -> Option<Self> {
26        // Créer le renderer approprié en fonction du mode de jeu
27        let renderer = match beatmap.mode {
28            GameMode::Mania => {
29                GameModeRenderer::Mania(ManiaRenderer::with_sizes(column_width, note_size, height))
30            }
31            // TODO: Ajouter d'autres modes
32            // GameMode::Osu => GameModeRenderer::Standard(...),
33            // GameMode::Taiko => GameModeRenderer::Taiko(...),
34            // GameMode::Catch => GameModeRenderer::Catch(...),
35            _ => return None, // Mode non supporté
36        };
37
38        Some(Self {
39            beatmap,
40            renderer,
41            start_time: Instant::now(),
42            speed: 1.0,
43            scroll_time_ms: 1000.0,
44        })
45    }
46
47    pub fn set_note_style(&mut self, style: NoteStyle) {
48        #[allow(irrefutable_let_patterns)]
49        if let GameModeRenderer::Mania(mania) = &mut self.renderer {
50            mania.set_note_style(style);
51        }
52    }
53
54    pub fn get_required_size(&self) -> [f32; 2] {
55        match &self.renderer {
56            GameModeRenderer::Mania(mania) => {
57                let keycount = self.beatmap.circle_size as usize;
58                [mania.required_width(keycount), mania.required_height()]
59            }
60            // TODO: Ajouter d'autres modes
61            // GameModeRenderer::Standard(std) => std.get_required_size(),
62            // GameModeRenderer::Taiko(taiko) => taiko.get_required_size(),
63            // GameModeRenderer::Catch(catch) => catch.get_required_size(),
64        }
65    }
66
67    pub fn set_speed(&mut self, speed: f64) {
68        self.speed = speed;
69    }
70
71    pub fn set_scroll_time(&mut self, ms: f32) {
72        self.scroll_time_ms = ms;
73    }
74
75    pub fn render(&mut self, ui: &mut egui::Ui) {
76        self.render_at(ui, egui::pos2(0.0, 0.0))
77    }
78
79    pub fn render_at(&mut self, ui: &mut egui::Ui, position: egui::Pos2) {
80        let current_time = self.start_time.elapsed().as_secs_f64() * 1000.0;
81        let hit_objects = &self.beatmap.hit_objects;
82
83        match &mut self.renderer {
84            GameModeRenderer::Mania(mania) => {
85                let keycount = self.beatmap.circle_size as usize;
86                mania.render_at(
87                    ui,
88                    hit_objects,
89                    current_time,
90                    self.scroll_time_ms,
91                    self.speed,
92                    keycount,
93                    position,
94                );
95            }
96            // TODO: Ajouter d'autres modes
97            // GameModeRenderer::Standard(std) => std.render_at(...),
98            // GameModeRenderer::Taiko(taiko) => taiko.render_at(...),
99            // GameModeRenderer::Catch(catch) => catch.render_at(...),
100        }
101    }
102
103    pub fn reset_time(&mut self) {
104        self.start_time = Instant::now();
105    }
106
107    pub fn set_current_time(&mut self, time_ms: f64) {
108        self.start_time = Instant::now() - std::time::Duration::from_secs_f64(time_ms / 1000.0);
109    }
110
111    pub fn current_time(&self) -> f64 {
112        self.start_time.elapsed().as_secs_f64() * 1000.0
113    }
114}