Skip to content

Commit ac08b77

Browse files
committed
Finish song select scene
1 parent 8e953d9 commit ac08b77

File tree

12 files changed

+239
-4332
lines changed

12 files changed

+239
-4332
lines changed

sample_config.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ osu_hitsound_enable = false
2424

2525
[game.skins.o2jamu]
2626
type = "osu"
27-
path = "test/test_skin"
27+
path = "test/o2jamuskin"
2828

2929
[game.skins.jhlee]
3030
type = "osu"
31-
path = "jhlee"
31+
path = "test/jhlee"
3232

3333
[game.skins.o2jamdefault]
3434
type = "o2jam"

src/chart/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,6 @@ pub struct ChartSet {
167167

168168
#[derive(Clone, Debug, PartialEq, Eq)]
169169
pub struct Difficulty {
170-
name: String,
171-
path: path::PathBuf,
170+
pub name: String,
171+
pub path: path::PathBuf,
172172
}

src/chart/osu.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,8 @@ pub fn gen_song_list<P: AsRef<Path>>(path: P) -> Result<Vec<super::ChartSet>, io
10371037
chart_set.song_name = c.song_name;
10381038
chart_set.song_name_unicode = c.song_name_unicode;
10391039
}
1040-
Err(e) => remani_warn!("Error parsing osu file `{}': {}", path.display(), e),
1040+
// Err(e) => remani_warn!("Error parsing osu file `{}': {}", path.display(), e),
1041+
Err(_) => (), // ignore for now since they're annoying
10411042
}
10421043
}
10431044
if chart_set != super::ChartSet::default() {

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![deny(rust_2018_idioms)]
2+
#![feature(fnbox)]
3+
#![feature(inner_deref)]
24

35
macro_rules! remani_warn {
46
($fmt:expr) => (eprintln!(concat!("WARNING: ", $fmt)));

src/window/game/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod model;
1212
mod view;
1313

1414
use self::{model::Model, view::View};
15-
use super::WindowContext;
15+
use super::{song_select::SongSelect, WindowContext};
1616

1717
use crate::{audio, chart::Chart, config::Config, judgement::Judgement, gameskin};
1818

@@ -26,6 +26,7 @@ pub struct GameScene {
2626
first_playhead_received: bool,
2727
first_playhead_request: bool,
2828
current_autoplay_sound_index: usize,
29+
chart_end_time: Option<f64>,
2930
}
3031

3132
impl GameScene {
@@ -54,6 +55,7 @@ impl GameScene {
5455
first_playhead_received: false,
5556
first_playhead_request: false,
5657
current_autoplay_sound_index: 0,
58+
chart_end_time: None,
5759
}
5860
}
5961

@@ -97,9 +99,11 @@ impl GameScene {
9799

98100
if let Some(u) = e.update_args() {
99101
let view = &mut self.view;
102+
// Update notes in model, draw any misses that occurred
100103
self.model.update(u, config, &*self.chart, self.time, |k| {
101104
view.draw_judgement(k, Judgement::Miss, false)
102105
});
106+
// Play the autoplay sounds if one needs to be played
103107
if let Some(autoplay_sound) = self.chart.autoplay_sounds().get(self.current_autoplay_sound_index) {
104108
// Unapply the offset to make sure the autoplay sound lines up with the music
105109
if self.time - config.game.offset >= autoplay_sound.time {
@@ -112,6 +116,16 @@ impl GameScene {
112116
);
113117
}
114118
}
119+
if view.chart_ended(&*self.chart) && self.chart_end_time.is_none() {
120+
self.chart_end_time = Some(self.time);
121+
}
122+
123+
if let Some(chart_end_time) = self.chart_end_time {
124+
if self.time - 10.0 > chart_end_time {
125+
let song_select_scene = SongSelect::new(window, config);
126+
window.change_scene(song_select_scene);
127+
}
128+
}
115129
}
116130

117131
if let Some(i) = e.press_args() {

src/window/game/view.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ impl<G: Graphics> View<G> {
166166
self.skin.key_up(column);
167167
self.skin.long_note_hit_anim_stop(column);
168168
}
169+
170+
pub fn chart_ended(&self, chart: &dyn chart::Chart) -> bool {
171+
self.next_note_index >= chart.notes().len()
172+
&& self.notes_on_screen_indices.len() == 0
173+
&& self.notes_below_screen_indices.len() == 0
174+
}
169175
}
170176

171177
/// Given the time in seconds from the start of the song, calculate the position, taking into

src/window/main_menu.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ use piston::{
66
};
77
use texture::{ImageSize, TextureSettings};
88

9-
// use super::{options, game, WindowContext};
109
use super::{options, song_select, WindowContext};
11-
use crate::{audio, chart, config::Config};
10+
use crate::{audio, config::Config};
1211

1312
pub struct MainMenu {
1413
play_texture: Texture,
@@ -43,11 +42,8 @@ impl MainMenu {
4342
) {
4443
if let Some(i) = e.press_args() {
4544
if i == Button::Mouse(mouse::MouseButton::Left) && window.mouse_position[1] < self.window_height / 3.0 {
46-
// match chart::osu::from_path("test/test_chart/test.osu") {
47-
// Ok(x) => window.change_scene(game::GameScene::new(Box::new(x), config, audio)),
48-
// Err(e) => println!("{}", e),
49-
// }
50-
window.change_scene(song_select::SongSelect::new(window, config));
45+
let song_select = song_select::SongSelect::new(window, config);
46+
window.change_scene(song_select);
5147
} else if i == Button::Mouse(mouse::MouseButton::Left) && window.mouse_position[1] < self.window_height / 3.0 * 2.0 {
5248
window.change_scene(options::Options::new(window, config));
5349
}

src/window/mod.rs

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use glutin_window::GlutinWindow;
44
use opengl_graphics::GlGraphics;
55
use piston::{input::MouseCursorEvent, event_loop::EventLoop};
66

7-
use crate::{audio, config::Config};
7+
use crate::{audio, chart, config::Config};
88

99
mod game;
1010
mod main_menu;
@@ -59,21 +59,83 @@ impl From<song_select::SongSelect> for Scene {
5959
}
6060
}
6161

62+
impl From<Scene> for Option<main_menu::MainMenu> {
63+
fn from(t: Scene) -> Self {
64+
match t {
65+
Scene::MainMenu(s) => Some(s),
66+
_ => None,
67+
}
68+
}
69+
}
70+
71+
impl From<Scene> for Option<options::Options> {
72+
fn from(t: Scene) -> Self {
73+
match t {
74+
Scene::Options(s) => Some(s),
75+
_ => None,
76+
}
77+
}
78+
}
79+
80+
impl From<Scene> for Option<game::GameScene> {
81+
fn from(t: Scene) -> Self {
82+
match t {
83+
Scene::Game(s) => Some(s),
84+
_ => None,
85+
}
86+
}
87+
}
88+
89+
impl From<Scene> for Option<song_select::SongSelect> {
90+
fn from(t: Scene) -> Self {
91+
match t {
92+
Scene::SongSelect(s) => Some(s),
93+
_ => None,
94+
}
95+
}
96+
}
97+
98+
/// A struct for caching things scenes use so e.g. the song list scene doesn't have to regenerate
99+
/// the song list everytime it's viewed.
100+
#[derive(Default)]
101+
struct SceneResources {
102+
song_list: Option<Vec<chart::ChartSet>>,
103+
last_selected_song_index: usize,
104+
}
105+
106+
enum NextScene {
107+
Plain(Scene),
108+
Function(Box<dyn std::boxed::FnBox(Scene, &mut WindowContext) -> Scene>),
109+
}
110+
62111
struct WindowContext {
63112
gl: GlGraphics,
64113
font: conrod::text::Font, // one font for now
65114

66115
/// Kept track of here so that mouse coordinates don't get messed up when changing scenes.
67116
mouse_position: [f64; 2],
68-
next_scene: Option<Scene>,
117+
next_scene: Option<NextScene>,
69118

70119
/// The underlying window
71120
window: GlutinWindow,
121+
122+
resources: SceneResources,
72123
}
73124

74125
impl WindowContext {
75126
fn change_scene<T: Into<Scene>>(&mut self, next_scene: T) {
76-
self.next_scene = Some(next_scene.into());
127+
self.next_scene = Some(NextScene::Plain(next_scene.into()));
128+
}
129+
fn change_scene_with<S, T, F>(&mut self, next_scene: F)
130+
where
131+
Option<S>: From<Scene>,
132+
T: Into<Scene>,
133+
for<'a> F: FnOnce(S, &'a mut WindowContext) -> T + 'static,
134+
{
135+
self.next_scene = Some(NextScene::Function(Box::new(move |scene: Scene, wc: &mut WindowContext| {
136+
let scene = Option::from(scene).expect("Wrong scene type");
137+
next_scene(scene, wc).into()
138+
})));
77139
}
78140
}
79141

@@ -109,19 +171,24 @@ pub fn start(mut config: Config) {
109171
.expect("Failed to load Wen Quan Yi Micro Hei font"),
110172
mouse_position: [-1.0, -1.0],
111173
window: glutin_window,
174+
resources: SceneResources::default(),
112175
};
113-
let mut current_scene = Scene::MainMenu(main_menu::MainMenu::new());
176+
let mut current_scene = Some(Scene::MainMenu(main_menu::MainMenu::new()));
114177

115178
// the UI scenes need to be able to manually swap buffers to allow lazy redrawing
116179
let mut events = Events::new(EventSettings::new().swap_buffers(false));
117180
while let Some(e) = events.next(&mut window.window) {
118181
if let Some(p) = e.mouse_cursor_args() {
119182
window.mouse_position = p;
120183
}
121-
current_scene.event(e, &mut config, &audio, &mut window);
184+
current_scene.as_mut().unwrap().event(e, &mut config, &audio, &mut window);
122185

123186
if window.next_scene.is_some() {
124-
current_scene = window.next_scene.take().unwrap();
187+
current_scene = Some(match window.next_scene.take() {
188+
Some(NextScene::Plain(s)) => s,
189+
Some(NextScene::Function(f)) => f.call_box((current_scene.take().unwrap(), &mut window)),
190+
None => unreachable!(),
191+
});
125192
}
126193
}
127194
}

0 commit comments

Comments
 (0)