Skip to content

Commit d2579bf

Browse files
committed
Port all remaining topbar-UI code to nuon
1 parent 074123b commit d2579bf

File tree

5 files changed

+128
-71
lines changed

5 files changed

+128
-71
lines changed

neothesia/src/scene/playing_scene/top_bar/mod.rs

Lines changed: 14 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
use std::time::{Duration, Instant};
22

3-
use neothesia_core::render::QuadInstance;
43
use ui::{LooperMsg, ProgressBarMsg};
5-
use wgpu_jumpstart::Color;
64

75
use crate::{context::Context, NeothesiaEvent};
86

97
use super::{
108
animation::{Animated, Easing},
119
rewind_controller::RewindController,
12-
PlayingScene, LAYER_FG,
10+
PlayingScene,
1311
};
1412

1513
mod renderer;
@@ -19,7 +17,7 @@ mod widget;
1917
use renderer::NuonRenderer;
2018

2119
pub struct TopBar {
22-
animation: Animated<bool, Instant>,
20+
topbar_expand_animation: Animated<bool, Instant>,
2321
is_expanded: bool,
2422

2523
settings_animation: Animated<bool, Instant>,
@@ -34,7 +32,7 @@ pub struct TopBar {
3432
impl TopBar {
3533
pub fn new() -> Self {
3634
Self {
37-
animation: Animated::new(false)
35+
topbar_expand_animation: Animated::new(false)
3836
.duration(1000.)
3937
.easing(Easing::EaseOutExpo)
4038
.delay(30.0),
@@ -138,19 +136,23 @@ impl TopBar {
138136
}
139137

140138
#[profiling::function]
141-
fn update_nuon(scene: &mut PlayingScene, ctx: &mut Context, _delta: Duration, y: f32) {
139+
fn update_nuon(scene: &mut PlayingScene, ctx: &mut Context, _delta: Duration) {
142140
let globals = nuon::GlobalStore::with(|store| {
143141
store.insert(&scene.player);
144142
});
145143

146144
let mut root = ui::top_bar(ui::UiData {
147-
y,
145+
window_size: ctx.window_state.logical_size,
148146
is_settings_open: scene.top_bar.settings_active,
149147
is_looper_on: scene.top_bar.is_looper_active(),
150148
speed: ctx.config.speed_multiplier(),
151149
player: &scene.player,
152150
loop_start: scene.top_bar.loop_start_timestamp(),
153151
loop_end: scene.top_bar.loop_end_timestamp(),
152+
153+
frame_timestamp: ctx.frame_timestamp,
154+
topbar_expand_animation: &scene.top_bar.topbar_expand_animation,
155+
settings_animation: &scene.top_bar.settings_animation,
154156
})
155157
.into();
156158

@@ -213,64 +215,13 @@ impl TopBar {
213215
top_bar.is_expanded |= top_bar.settings_active;
214216
top_bar.is_expanded |= scene.nuon_event_queue.is_mouse_grabbed();
215217

216-
let now = ctx.frame_timestamp;
217-
218-
top_bar.animation.transition(top_bar.is_expanded, now);
218+
top_bar
219+
.topbar_expand_animation
220+
.transition(top_bar.is_expanded, ctx.frame_timestamp);
219221
top_bar
220222
.settings_animation
221-
.transition(top_bar.settings_active, now);
222-
223-
let y = top_bar.animation.animate_bool(-h + 5.0, 0.0, now);
224-
225-
update_settings_card(scene, ctx, y);
226-
Self::update_nuon(scene, ctx, delta, y);
227-
}
228-
}
229-
230-
fn update_settings_card(scene: &mut PlayingScene, ctx: &mut Context, y: f32) {
231-
let PlayingScene {
232-
top_bar,
233-
quad_pipeline,
234-
..
235-
} = scene;
236-
237-
let h = 75.0;
238-
let w = ctx.window_state.logical_size.width;
239-
let now = ctx.frame_timestamp;
240-
241-
if top_bar.settings_animation.in_progress(now) || top_bar.settings_animation.value {
242-
let card_w = 300.0;
243-
let card_x = top_bar.settings_animation.animate_bool(card_w, 0.0, now);
244-
245-
let bar_bg: Color = Color::from_rgba8(37, 35, 42, 1.0);
246-
247-
let x = card_x + w - card_w;
248-
let y = y + h + 1.0;
249-
250-
let w = card_w;
251-
let h = 100.0;
252-
253-
quad_pipeline.push(
254-
LAYER_FG,
255-
QuadInstance {
256-
position: [x, y],
257-
size: [w, h],
258-
color: bar_bg.into_linear_rgba(),
259-
border_radius: [10.0, 0.0, 10.0, 0.0],
260-
},
261-
);
262-
263-
fn cone_icon() -> &'static str {
264-
"\u{F2D2}"
265-
}
266-
267-
let size = 50.0;
268-
let half_size = size / 2.0;
269-
ctx.text_renderer
270-
.queue_icon(x + w / 2.0 - half_size, y + 10.0, size, cone_icon());
223+
.transition(top_bar.settings_active, ctx.frame_timestamp);
271224

272-
let buffer = ctx.text_renderer.gen_buffer_bold(25.0, "WIP");
273-
ctx.text_renderer
274-
.queue_buffer_centered(x, y + size + 15.0, w, 25.0, buffer);
225+
Self::update_nuon(scene, ctx, delta);
275226
}
276227
}

neothesia/src/scene/playing_scene/top_bar/ui.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use std::time::Duration;
1+
use std::time::{Duration, Instant};
22

3+
use lilt::Animated;
34
use nuon::{
4-
button::Button, column::Column, container::Container, row::Row, stack::Stack,
5+
button::Button, canvas::Canvas, column::Column, container::Container, row::Row, stack::Stack,
56
trilayout::TriLayout, Color, Element,
67
};
8+
use winit::dpi::LogicalSize;
79

810
use crate::scene::playing_scene::midi_player::MidiPlayer;
911

@@ -35,6 +37,10 @@ pub enum Msg {
3537
Looper(LooperMsg),
3638
}
3739

40+
fn cone_icon() -> &'static str {
41+
"\u{F2D2}"
42+
}
43+
3844
fn gear_icon() -> &'static str {
3945
"\u{F3E5}"
4046
}
@@ -65,8 +71,13 @@ pub struct UiData<'a> {
6571
pub loop_start: Duration,
6672
pub loop_end: Duration,
6773
pub speed: f32,
68-
pub y: f32,
74+
6975
pub player: &'a MidiPlayer,
76+
pub window_size: LogicalSize<f32>,
77+
78+
pub frame_timestamp: Instant,
79+
pub topbar_expand_animation: &'a Animated<bool, Instant>,
80+
pub settings_animation: &'a Animated<bool, Instant>,
7081
}
7182

7283
fn header(data: &UiData) -> impl Into<Element<Msg>> {
@@ -145,8 +156,40 @@ pub fn top_bar(data: UiData) -> impl Into<Element<Msg>> {
145156

146157
let body = Column::new().push(header).push(timeline);
147158

148-
Container::new()
149-
.y(data.y)
150-
.background(Color::new_u8(37, 35, 42, 1.0))
151-
.child(body)
159+
let y = data
160+
.topbar_expand_animation
161+
.animate_bool(-75.0 + 5.0, 0.0, data.frame_timestamp);
162+
163+
Stack::new()
164+
.push(
165+
Container::new()
166+
.y(y)
167+
.background(Color::new_u8(37, 35, 42, 1.0))
168+
.child(body),
169+
)
170+
.push({
171+
let card_w = 300.0;
172+
let card_x = data
173+
.settings_animation
174+
.animate_bool(card_w, 0.0, data.frame_timestamp);
175+
let card_x = card_x + data.window_size.width - card_w;
176+
177+
Container::new()
178+
.y(y + 30.0 + 45.0)
179+
.x(card_x)
180+
.height(100.0)
181+
.width(card_w)
182+
.background(Color::new_u8(37, 35, 42, 1.0))
183+
.border_radius([10.0, 0.0, 10.0, 0.0])
184+
.child(Canvas::new(|renderer, layout| {
185+
let x = layout.x;
186+
let y = layout.y;
187+
let w = layout.w;
188+
let size = 50.0;
189+
let half_size = size / 2.0;
190+
191+
renderer.icon(x + w / 2.0 - half_size, y + 10.0, size, cone_icon());
192+
renderer.centered_text(x, y + size + 15.0, w, 25.0, 25.0, "WIP");
193+
}))
194+
})
152195
}

nuon/src/widget/canvas.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use crate::{Element, LayoutCtx, Node, ParentLayout, RenderCtx, Renderer, Tree, Widget};
2+
3+
pub struct Canvas<F> {
4+
draw: F,
5+
}
6+
7+
impl<F: Fn(&mut dyn Renderer, &Node)> Canvas<F> {
8+
pub fn new(draw: F) -> Self {
9+
Self { draw }
10+
}
11+
}
12+
13+
impl<MSG: Clone, F: Fn(&mut dyn Renderer, &Node)> Widget<MSG> for Canvas<F> {
14+
type State = ();
15+
16+
fn layout(
17+
&self,
18+
_tree: &mut Tree<Self::State>,
19+
parent: &ParentLayout,
20+
_ctx: &LayoutCtx,
21+
) -> Node {
22+
Node {
23+
x: parent.x,
24+
y: parent.y,
25+
w: parent.w,
26+
h: parent.h,
27+
children: vec![],
28+
}
29+
}
30+
31+
fn render(
32+
&self,
33+
renderer: &mut dyn Renderer,
34+
layout: &Node,
35+
_tree: &Tree<Self::State>,
36+
_ctx: &RenderCtx,
37+
) {
38+
(self.draw)(renderer, layout)
39+
}
40+
}
41+
42+
impl<MSG: Clone + 'static, F: Fn(&mut dyn Renderer, &Node) + 'static> From<Canvas<F>>
43+
for Element<MSG>
44+
{
45+
fn from(value: Canvas<F>) -> Self {
46+
Element::new(value)
47+
}
48+
}

nuon/src/widget/container.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{Color, Element, LayoutCtx, Node, ParentLayout, RenderCtx, Renderer,
33
pub struct Container<MSG> {
44
child: [Element<MSG>; 1],
55
background: Option<Color>,
6+
border_radius: [f32; 4],
67
x: f32,
78
y: f32,
89
width: Option<f32>,
@@ -20,6 +21,7 @@ impl<MSG: 'static> Container<MSG> {
2021
Self {
2122
child: [Element::null()],
2223
background: None,
24+
border_radius: [0.0; 4],
2325
x: 0.0,
2426
y: 0.0,
2527
width: None,
@@ -37,6 +39,11 @@ impl<MSG: 'static> Container<MSG> {
3739
self
3840
}
3941

42+
pub fn border_radius(mut self, radius: [f32; 4]) -> Self {
43+
self.border_radius = radius;
44+
self
45+
}
46+
4047
pub fn x(mut self, x: f32) -> Self {
4148
self.x = x;
4249
self
@@ -104,7 +111,14 @@ impl<MSG> Widget<MSG> for Container<MSG> {
104111
ctx: &RenderCtx,
105112
) {
106113
if let Some(bg) = self.background {
107-
renderer.quad(layout.x, layout.y, layout.w, layout.h, bg);
114+
renderer.rounded_quad(
115+
layout.x,
116+
layout.y,
117+
layout.w,
118+
layout.h,
119+
bg,
120+
self.border_radius,
121+
);
108122
}
109123
crate::default_render(self, renderer, layout, tree, ctx);
110124
}

nuon/src/widget/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub mod button;
2+
pub mod canvas;
23
pub mod column;
34
pub mod container;
45
pub mod null;

0 commit comments

Comments
 (0)