Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Playback speed pill #194

Merged
merged 1 commit into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions neothesia-core/src/render/text/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,77 @@ impl TextRenderer {
});
}

pub fn measure(buffer: &glyphon::cosmic_text::Buffer) -> (f32, f32) {
buffer
.layout_runs()
.fold((0.0, 0.0), |(width, height), run| {
(run.line_w.max(width), height + run.line_height)
})
}

pub fn gen_buffer(&mut self, size: f32, text: &str) -> glyphon::Buffer {
self.gen_buffer_with_attr(
size,
text,
glyphon::Attrs::new().family(glyphon::Family::Name("Roboto")),
)
}

pub fn gen_buffer_bold(&mut self, size: f32, text: &str) -> glyphon::Buffer {
self.gen_buffer_with_attr(
size,
text,
glyphon::Attrs::new()
.family(glyphon::Family::Name("Roboto"))
.weight(glyphon::Weight::BOLD),
)
}

pub fn gen_buffer_with_attr(
&mut self,
size: f32,
text: &str,
attrs: glyphon::Attrs,
) -> glyphon::Buffer {
let mut buffer =
glyphon::Buffer::new(&mut self.font_system, glyphon::Metrics::new(size, size));
buffer.set_size(&mut self.font_system, Some(f32::MAX), Some(f32::MAX));
buffer.set_text(&mut self.font_system, text, attrs, glyphon::Shaping::Basic);
buffer.shape_until_scroll(&mut self.font_system, false);
buffer
}

pub fn queue_buffer(&mut self, x: f32, y: f32, buffer: glyphon::Buffer) {
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_buffer_centered(
&mut self,
x: f32,
y: f32,
w: f32,
h: f32,
buffer: glyphon::Buffer,
) {
let (text_w, text_h) = Self::measure(&buffer);

self.queue(TextArea {
buffer,
left: x + w / 2.0 - text_w / 2.0,
top: y + h / 2.0 - text_h / 2.0,
scale: 1.0,
bounds: glyphon::TextBounds::default(),
default_color: glyphon::Color::rgb(255, 255, 255),
});
}

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));
Expand Down
2 changes: 1 addition & 1 deletion neothesia/src/scene/playing_scene/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ impl Scene for PlayingScene {
self.keyboard
.update(&mut self.quad_pipeline, LAYER_FG, &mut ctx.text_renderer);

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

self.quad_pipeline.prepare(&ctx.gpu.device, &ctx.gpu.queue);

Expand Down
21 changes: 16 additions & 5 deletions neothesia/src/scene/playing_scene/top_bar.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::time::Instant;

use neothesia_core::{
render::{QuadInstance, QuadPipeline, TextRenderer},
render::{QuadInstance, QuadPipeline},
utils::Rect,
};
use wgpu_jumpstart::Color;
Expand All @@ -10,7 +10,7 @@ use winit::{
event::{ElementState, MouseButton, WindowEvent},
};

use crate::{context::Context, utils::window::WindowState, NeothesiaEvent};
use crate::{context::Context, NeothesiaEvent};

use super::{
animation::{Animated, Animation, Easing},
Expand All @@ -37,6 +37,8 @@ enum Msg {
SettingsToggle,
ProggresBar(ProgressBarMsg),
LooperEvent(LooperMsg),
SpeedUpdateUp,
SpeedUpdateDown,
}

pub struct TopBar {
Expand Down Expand Up @@ -113,6 +115,13 @@ impl TopBar {
Msg::SettingsToggle => {
scene.top_bar.settings_active = !scene.top_bar.settings_active;
}
Msg::SpeedUpdateUp => {
ctx.config.speed_multiplier += 0.1;
}
Msg::SpeedUpdateDown => {
ctx.config.speed_multiplier -= 0.1;
ctx.config.speed_multiplier = ctx.config.speed_multiplier.max(0.0);
}
Msg::LooperEvent(msg) => {
Looper::on_msg(scene, ctx, msg);
}
Expand Down Expand Up @@ -211,7 +220,7 @@ impl TopBar {
}

#[profiling::function]
pub fn update(scene: &mut PlayingScene, window_state: &WindowState, text: &mut TextRenderer) {
pub fn update(scene: &mut PlayingScene, ctx: &mut Context) {
let PlayingScene {
top_bar,
quad_pipeline,
Expand All @@ -220,6 +229,8 @@ impl TopBar {
..
} = scene;

let window_state = &ctx.window_state;

top_bar.bbox.size.width = window_state.logical_size.width;

let h = top_bar.bbox.size.height;
Expand Down Expand Up @@ -260,12 +271,12 @@ impl TopBar {
Looper::update,
update_settings_card,
] {
f(scene, text, &now);
f(scene, ctx, &now);
}
}
}

fn update_settings_card(scene: &mut PlayingScene, _text: &mut TextRenderer, _now: &Instant) {
fn update_settings_card(scene: &mut PlayingScene, _ctx: &mut Context, _now: &Instant) {
let PlayingScene {
top_bar,
quad_pipeline,
Expand Down
30 changes: 25 additions & 5 deletions neothesia/src/scene/playing_scene/top_bar/header.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::time::Instant;

use neothesia_core::render::TextRenderer;
use speed_pill::SpeedPill;

use crate::scene::playing_scene::PlayingScene;
use crate::{context::Context, scene::playing_scene::PlayingScene};

use super::{looper::LooperMsg, Button, Msg};

mod speed_pill;

fn gear_icon() -> &'static str {
"\u{F3E5}"
}
Expand Down Expand Up @@ -36,6 +38,8 @@ pub struct Header {
play_button: Button,
loop_button: Button,
settings_button: Button,

speed_pill: SpeedPill,
}

impl Header {
Expand Down Expand Up @@ -76,6 +80,8 @@ impl Header {
play_button,
loop_button,
settings_button,

speed_pill: SpeedPill::new(elements),
}
}

Expand Down Expand Up @@ -104,7 +110,7 @@ impl Header {
});
}

pub fn update(scene: &mut PlayingScene, text: &mut TextRenderer, _now: &Instant) {
pub fn update(scene: &mut PlayingScene, ctx: &mut Context, now: &Instant) {
Self::update_button_icons(scene);

let PlayingScene {
Expand All @@ -123,7 +129,12 @@ impl Header {
)
});

top_bar.header.layout.center.once(|_row| {});
let (center_box,) = top_bar.header.layout.center.once(|row| {
(
row.push(90.0),
//
)
});

let (_play, _loop, _settings) = top_bar.header.layout.end.once(|row| {
(
Expand All @@ -136,6 +147,15 @@ impl Header {

top_bar.header.layout.resolve(0.0, w);

top_bar.header.speed_pill.update(
&mut top_bar.elements,
ctx,
quad_pipeline,
y,
&top_bar.header.layout.center.items()[center_box],
now,
);

let start_row = top_bar.header.layout.start.items();
let _center_row = top_bar.header.layout.center.items();
let end_row = top_bar.header.layout.end.items();
Expand Down Expand Up @@ -167,7 +187,7 @@ impl Header {
&top_bar.header.loop_button,
&top_bar.header.settings_button,
] {
btn.draw(quad_pipeline, text);
btn.draw(quad_pipeline, &mut ctx.text_renderer);
}
}
}
114 changes: 114 additions & 0 deletions neothesia/src/scene/playing_scene/top_bar/header/speed_pill.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use std::time::Instant;

use neothesia_core::render::{QuadInstance, QuadPipeline};
use wgpu_jumpstart::Color;

use crate::context::Context;
use crate::scene::playing_scene::animation::{Animated, Easing};
use crate::scene::playing_scene::LAYER_FG;

use super::Msg;

fn minus_icon() -> &'static str {
"\u{F2EA}"
}

fn plus_icon() -> &'static str {
"\u{F4FE}"
}

pub struct SpeedPill {
plus: nuon::ElementId,
minus: nuon::ElementId,

plus_animation: Animated<bool, Instant>,
minus_animation: Animated<bool, Instant>,
}

impl SpeedPill {
pub fn new(elements: &mut nuon::ElementsMap<Msg>) -> Self {
Self {
plus: elements.insert(
nuon::ElementBuilder::new()
.name("PlusButton")
.on_click(Msg::SpeedUpdateUp),
),
minus: elements.insert(
nuon::ElementBuilder::new()
.name("MinusButton")
.on_click(Msg::SpeedUpdateDown),
),

plus_animation: Animated::new(false)
.duration(50.0)
.easing(Easing::EaseInOut)
.delay(0.0),
minus_animation: Animated::new(false)
.duration(50.0)
.easing(Easing::EaseInOut)
.delay(0.0),
}
}

pub fn update(
&mut self,
elements: &mut nuon::ElementsMap<Msg>,
ctx: &mut Context,
quad_pipeline: &mut QuadPipeline,
y: f32,
item: &nuon::RowItem,
now: &Instant,
) {
let text = &mut ctx.text_renderer;

let y = y + 5.0;
let w = item.width;
let half_w = w / 2.0;

let h = 19.0;

elements.update(
self.minus,
nuon::Rect::new((item.x, y).into(), (half_w, h).into()),
);
elements.update(
self.plus,
nuon::Rect::new((item.x + half_w, y).into(), (half_w, h).into()),
);

for (element, animation, border_radius) in [
(
self.minus,
&mut self.minus_animation,
[10.0, 0.0, 10.0, 0.0],
),
(self.plus, &mut self.plus_animation, [0.0, 10.0, 0.0, 10.0]),
] {
if let Some(element) = elements.get(element) {
animation.transition(element.hovered(), *now);

let m = animation.animate(0.0, 20.0, *now) / 255.0;
let c = 67.0 / 255.0;
let color = Color::new(c + m, c + m, c + m, 1.0);

quad_pipeline.push(
LAYER_FG,
QuadInstance {
position: element.rect().origin.into(),
size: element.rect().size.into(),
color: color.into_linear_rgba(),
border_radius,
},
);
}
}

let pad = 2.0;
text.queue_icon(pad + item.x, y, h, minus_icon());
text.queue_icon(item.x + item.width - h - pad, y, h, plus_icon());

let label = format!("{}%", (ctx.config.speed_multiplier * 100.0).round());
let buffer = text.gen_buffer_bold(13.0, &label);
text.queue_buffer_centered(item.x, y, w, h, buffer);
}
}
3 changes: 1 addition & 2 deletions neothesia/src/scene/playing_scene/top_bar/looper.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::time::{Duration, Instant};

use neothesia_core::render::TextRenderer;
use wgpu_jumpstart::Color;

use crate::{context::Context, scene::playing_scene::PlayingScene};
Expand Down Expand Up @@ -132,7 +131,7 @@ impl Looper {
}
}

pub fn update(scene: &mut PlayingScene, _text: &mut TextRenderer, now: &Instant) {
pub fn update(scene: &mut PlayingScene, _ctx: &mut Context, now: &Instant) {
let PlayingScene {
top_bar,
quad_pipeline,
Expand Down
4 changes: 1 addition & 3 deletions neothesia/src/scene/playing_scene/top_bar/progress_bar.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::time::Instant;

use neothesia_core::render::TextRenderer;

use crate::{
context::Context,
scene::playing_scene::{rewind_controller::RewindController, PlayingScene},
Expand Down Expand Up @@ -60,7 +58,7 @@ impl ProgressBar {
}
}

pub fn update(scene: &mut PlayingScene, _text: &mut TextRenderer, _now: &Instant) {
pub fn update(scene: &mut PlayingScene, _ctx: &mut Context, _now: &Instant) {
let PlayingScene {
top_bar,
quad_pipeline,
Expand Down
Loading
Loading