Skip to content

Commit

Permalink
Initial work on playback controls bar (#144)
Browse files Browse the repository at this point in the history
* Looping implementation

* Button strip above progresses bar

* Remove handle_mouse_input from rewind controller in favor of top bar mod
  • Loading branch information
PolyMeilex authored Feb 18, 2024
1 parent fc2f5e7 commit b5f4342
Show file tree
Hide file tree
Showing 7 changed files with 437 additions and 60 deletions.
31 changes: 28 additions & 3 deletions neothesia-core/src/render/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ pub struct TextRenderer {

impl TextRenderer {
pub fn new(gpu: &Gpu) -> Self {
let font_system = glyphon::FontSystem::new_with_fonts([glyphon::fontdb::Source::Binary(
Arc::new(include_bytes!("./Roboto-Regular.ttf")),
)]);
let font_system = glyphon::FontSystem::new_with_fonts([
glyphon::fontdb::Source::Binary(Arc::new(include_bytes!("./Roboto-Regular.ttf"))),
glyphon::fontdb::Source::Binary(Arc::new(include_bytes!(
"../../../../neothesia/src/iced_utils/bootstrap-icons.ttf"
))),
]);

let cache = glyphon::SwashCache::new();
let mut atlas = glyphon::TextAtlas::new(&gpu.device, &gpu.queue, gpu.texture_format);
Expand Down Expand Up @@ -91,6 +94,28 @@ impl TextRenderer {
});
}

pub fn queue_icon(&mut self, x: f32, y: f32, size: f32, icon: &str) {
let mut buffer =
glyphon::Buffer::new(&mut self.font_system, glyphon::Metrics::new(size, size));
buffer.set_size(&mut self.font_system, f32::MAX, f32::MAX);
buffer.set_text(
&mut self.font_system,
icon,
glyphon::Attrs::new().family(glyphon::Family::Name("bootstrap-icons")),
glyphon::Shaping::Basic,
);
buffer.shape_until_scroll(&mut self.font_system);

self.queue(TextArea {
buffer,
left: x,
top: y,
scale: 1.0,
bounds: glyphon::TextBounds::default(),
default_color: glyphon::Color::rgb(255, 255, 255),
});
}

pub fn queue_fps(&mut self, fps: f64) {
let text = format!("FPS: {}", fps.round() as u32);
let mut buffer =
Expand Down
Binary file modified neothesia/src/iced_utils/bootstrap-icons.ttf
Binary file not shown.
4 changes: 2 additions & 2 deletions neothesia/src/scene/menu_scene/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use super::Renderer;
static ICONS: iced_core::Font = iced_core::Font::with_name("bootstrap-icons");

pub fn play_icon<'a>() -> iced_widget::Text<'a, Theme, Renderer> {
iced_widget::text('\u{f49d}').font(ICONS)
iced_widget::text('\u{f4f4}').font(ICONS)
}

pub fn note_list_icon<'a>() -> iced_widget::Text<'a, Theme, Renderer> {
iced_widget::text('\u{f451}').font(ICONS)
iced_widget::text('\u{f49f}').font(ICONS)
}

pub fn left_arrow_icon<'a>() -> iced_widget::Text<'a, Theme, Renderer> {
Expand Down
18 changes: 14 additions & 4 deletions neothesia/src/scene/playing_scene/midi_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl MidiPlayer {
}
}

fn set_time(&mut self, time: Duration) {
pub fn set_time(&mut self, time: Duration) {
self.playback.set_time(time);

// Discard all of the events till that point
Expand All @@ -142,10 +142,16 @@ impl MidiPlayer {
self.set_time(time);
}

pub fn percentage_to_time(&self, p: f32) -> Duration {
Duration::from_secs_f32((p * self.playback.lenght().as_secs_f32()).max(0.0))
}

pub fn time_to_percentage(&self, time: &Duration) -> f32 {
time.as_secs_f32() / self.playback.lenght().as_secs_f32()
}

pub fn set_percentage_time(&mut self, p: f32) {
self.set_time(Duration::from_secs_f32(
(p * self.playback.lenght().as_secs_f32()).max(0.0),
));
self.set_time(self.percentage_to_time(p));
}

pub fn leed_in(&self) -> &Duration {
Expand All @@ -160,6 +166,10 @@ impl MidiPlayer {
self.playback.percentage()
}

pub fn time(&self) -> Duration {
self.playback.time()
}

pub fn time_without_lead_in(&self) -> f32 {
self.playback.time().as_secs_f32() - self.playback.leed_in().as_secs_f32()
}
Expand Down
16 changes: 14 additions & 2 deletions neothesia/src/scene/playing_scene/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ use toast_manager::ToastManager;
mod animation;
mod top_bar;

const EVENT_CAPTURED: bool = true;
const EVENT_IGNORED: bool = false;

pub struct PlayingScene {
keyboard: Keyboard,
waterfall: WaterfallRenderer,
Expand Down Expand Up @@ -89,11 +92,16 @@ impl PlayingScene {
bg_quad_pipeline: QuadPipeline::new(&target.gpu, &target.transform),
fg_quad_pipeline: QuadPipeline::new(&target.gpu, &target.transform),
toast_manager: ToastManager::default(),
top_bar: TopBar::default(),
top_bar: TopBar::new(),
}
}

fn update_midi_player(&mut self, target: &Target, delta: Duration) -> f32 {
if self.top_bar.loop_active && self.player.time() > self.top_bar.loop_end {
self.player.set_time(self.top_bar.loop_start);
self.keyboard.reset_notes();
}

if self.player.play_along().are_required_keys_pressed() {
let delta = (delta / 10) * (target.config.speed_multiplier * 10.0) as u32;
let midi_events = self.player.update(delta);
Expand Down Expand Up @@ -135,7 +143,7 @@ impl Scene for PlayingScene {
self.keyboard
.update(&mut self.fg_quad_pipeline, &mut target.text_renderer);

TopBar::update(self, &target.window_state);
TopBar::update(self, &target.window_state, &mut target.text_renderer);

self.bg_quad_pipeline.prepare(&target.gpu.queue);
self.fg_quad_pipeline.prepare(&target.gpu.queue);
Expand All @@ -152,6 +160,10 @@ impl Scene for PlayingScene {
}

fn window_event(&mut self, target: &mut Target, event: &WindowEvent) {
if TopBar::handle_window_event(self, target, event) {
return;
}

self.rewind_controler
.handle_window_event(target, event, &mut self.player);

Expand Down
40 changes: 3 additions & 37 deletions neothesia/src/scene/playing_scene/rewind_controller.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use winit::{
dpi::PhysicalPosition,
event::{ElementState, MouseButton, WindowEvent},
event::{ElementState, WindowEvent},
};

use super::MidiPlayer;
Expand All @@ -21,7 +21,7 @@ impl RewindController {
!matches!(self, RewindController::None)
}

fn start_mouse_rewind(&mut self, player: &mut MidiPlayer) {
pub fn start_mouse_rewind(&mut self, player: &mut MidiPlayer) {
let was_paused = player.is_paused();
self.start_rewind(player, RewindController::Mouse { was_paused });
}
Expand All @@ -36,7 +36,7 @@ impl RewindController {
*self = controller;
}

fn stop_rewind(&mut self, player: &mut MidiPlayer) {
pub fn stop_rewind(&mut self, player: &mut MidiPlayer) {
let controller = std::mem::replace(self, RewindController::None);

let was_paused = match controller {
Expand Down Expand Up @@ -72,9 +72,6 @@ impl RewindController {
WindowEvent::KeyboardInput { event, .. } => {
self.handle_keyboard_input(player, event);
}
WindowEvent::MouseInput { state, button, .. } => {
self.handle_mouse_input(player, &target.window_state, state, button);
}
WindowEvent::CursorMoved { position, .. } => {
self.handle_cursor_moved(player, &target.window_state, position);
}
Expand Down Expand Up @@ -118,37 +115,6 @@ impl RewindController {
}
}

fn handle_mouse_input(
&mut self,
player: &mut MidiPlayer,
window_state: &WindowState,
state: &ElementState,
button: &MouseButton,
) {
match (state, button) {
(ElementState::Pressed, MouseButton::Left) => {
let pos = &window_state.cursor_logical_position;

if pos.y < 45.0 && !self.is_rewinding() {
self.start_mouse_rewind(player);

let x = window_state.cursor_logical_position.x;
let w = window_state.logical_size.width;

let p = x / w;
log::debug!("Progressbar: x:{},p:{}", x, p);
player.set_percentage_time(p);
}
}
(ElementState::Released, MouseButton::Left) => {
if let RewindController::Mouse { .. } = self {
self.stop_rewind(player);
}
}
_ => {}
}
}

fn handle_cursor_moved(
&mut self,
player: &mut MidiPlayer,
Expand Down
Loading

0 comments on commit b5f4342

Please sign in to comment.