Skip to content
Snippets Groups Projects
Commit 2bfe65b9 authored by Per Lindgren's avatar Per Lindgren
Browse files

ADSR with a viev

parent ee261c4a
No related branches found
No related tags found
No related merge requests found
// Copyright 2019 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! An example of an animating widget.
use std::f64::consts::PI;
use druid::kurbo::{BezPath, Line};
use druid::widget::{Flex, Label, WidgetExt};
use druid::{
AppLauncher, BoxConstraints, Color, Data, Env, Event, EventCtx, LayoutCtx, Lens,
LinearGradient, PaintCtx, PlatformError, Point, RenderContext, Size, UnitPoint, UpdateCtx,
Vec2, WheelEvent, Widget, WindowDesc,
};
use druid_widgets::Dial;
use log::info;
#[derive(Clone, Data, Lens, Default)]
struct DialLabel {
value: f64,
}
impl DialLabel {
fn new(text: &str, value: f64) -> impl Widget<DialLabel> {
let text = text.to_string();
let label =
Label::new(move |data: &DialLabel, _env: &_| format!("{} {:.3}", text, data.value));
let solid = Color::rgb8(0x3a, 0x3a, 0x3a);
let mut col = Flex::column();
col.add_child(
Dial::new(value, Size::new(100.0, 100.0))
.lens(DialLabel::value)
.background(solid.clone())
.padding(5.0),
0.0,
);
col.add_child(label.padding(5.0).background(solid.clone()), 0.0);
col
}
}
#[derive(Clone, Data, Lens, Default)]
struct Envelope {
attack: DialLabel,
decay: DialLabel,
sustain: DialLabel,
release: DialLabel,
}
impl Envelope {
fn new() -> impl Widget<Envelope> {
let solid = Color::rgb8(0x3a, 0x3a, 0x3a);
Flex::row()
.with_child(
DialLabel::new("Attack", 0.0)
.lens(Envelope::attack)
.background(solid.clone())
.padding(5.0),
0.0,
)
.with_child(
DialLabel::new("Decay", 0.0)
.lens(Envelope::decay)
.background(solid.clone())
.padding(5.0),
0.0,
)
.with_child(
DialLabel::new("Sustain", 0.0)
.lens(Envelope::sustain)
.background(solid.clone())
.padding(5.0),
0.0,
)
.with_child(
DialLabel::new("Release", 0.0)
.lens(Envelope::release)
.background(solid.clone())
.padding(5.0),
0.0,
)
}
}
// Draw has no internal state, just reflects the associated type
#[derive(Clone, Data, Lens)]
struct Draw {}
impl Widget<Envelope> for Draw {
fn event(&mut self, _ctx: &mut EventCtx, _event: &Event, _data: &mut Envelope, _env: &Env) {}
fn update(
&mut self,
ctx: &mut UpdateCtx,
_old_data: Option<&Envelope>,
_data: &Envelope,
env: &Env,
) {
//info!("update {:?}", env.get());
ctx.invalidate();
}
fn layout(
&mut self,
_layout_ctx: &mut LayoutCtx,
bc: &BoxConstraints,
_data: &Envelope,
_env: &Env,
) -> Size {
bc.constrain((100.0, 100.0))
}
fn paint(&mut self, paint_ctx: &mut PaintCtx, data: &Envelope, _env: &Env) {
let size = paint_ctx.size();
info!("paint : {:?}", paint_ctx.size());
let mut path = BezPath::new();
let a = data.attack.value;
let d = data.decay.value;
let s = data.sustain.value;
let r = data.release.value;
let adr_time = a + d + r;
let sustain_time = adr_time / 3.0; // adjust the sustain time
let env_time = adr_time + sustain_time;
let x_scale = size.width / env_time;
let y_scale = size.height;
path.move_to(Point {
x: 0.,
y: size.height,
});
path.line_to(Point {
x: a * x_scale,
y: 0.,
});
path.line_to(Point {
x: (a + d) * x_scale,
y: size.height - s * y_scale,
});
path.line_to(Point {
x: (a + d + sustain_time) * x_scale,
y: size.height - s * y_scale,
});
path.line_to(Point {
x: size.width,
y: size.height,
});
paint_ctx.stroke(path, &Color::WHITE, 1.0);
// if let Some(p) = self.points.iter().next() {
// let mut path = BezPath::new();
// path.move_to(*p);
// for p in self.points.iter() {
// path.line_to(*p);
// }
// paint_ctx.stroke(path, &Color::WHITE, 1.0);
// }
}
}
#[derive(Clone, Data, Lens)]
struct Adsr {
envelope: Envelope,
}
impl Adsr {
pub fn new() -> impl Widget<Adsr> {
let solid = Color::rgb8(0x3a, 0x3a, 0x3a);
Flex::column()
.with_child(
Draw {}
.lens(Adsr::envelope)
.background(solid.clone())
.padding(5.0),
0.0,
)
.with_child(Envelope::new().lens(Adsr::envelope).padding(5.0), 0.0)
}
}
fn main() -> Result<(), PlatformError> {
AppLauncher::with_window(WindowDesc::new(Adsr::new))
.use_simple_logger()
.launch(Adsr {
envelope: Envelope {
attack: DialLabel { value: 0.1 },
decay: DialLabel { value: 0.2 },
sustain: DialLabel { value: 0.3 },
release: DialLabel { value: 0.4 },
},
})?;
Ok(())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment