mic level bar
This commit is contained in:
parent
07233e0e12
commit
022f414acb
|
@ -3,13 +3,17 @@
|
|||
left: 0px;
|
||||
}
|
||||
|
||||
.right {
|
||||
position-type: absolute;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.frames-container {
|
||||
width: 150px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
.frame {
|
||||
|
@ -33,3 +37,36 @@
|
|||
height: auto;
|
||||
max-height: 75%;
|
||||
}
|
||||
|
||||
.levels-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.levels-container div {
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.levels-container range {
|
||||
padding: 0px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.range-back {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mic-level {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.levels-container .active .range-low {
|
||||
background-color: green
|
||||
}
|
||||
|
||||
.levels-container .range-low {
|
||||
background-color: blue
|
||||
}
|
||||
|
||||
|
||||
|
|
42
src/audio.rs
42
src/audio.rs
|
@ -10,39 +10,57 @@ use anyhow::{anyhow, Result};
|
|||
|
||||
pub struct MicMonitor(Stream);
|
||||
|
||||
pub type Level = Arc<Mutex<f32>>;
|
||||
#[derive(Resource, Deref)]
|
||||
pub struct MicLevel(Level);
|
||||
pub type Level = Mutex<f32>;
|
||||
|
||||
pub static MIC_LEVEL_RAW: Level = Mutex::new(0.);
|
||||
pub static MIC_SENS_RAW: Level = Mutex::new(1.);
|
||||
|
||||
#[derive(Resource, Deref, Default)]
|
||||
pub struct MicLevel(f32);
|
||||
|
||||
impl MicLevel {
|
||||
pub fn value(&self) -> f32 {
|
||||
**self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Deref)]
|
||||
pub struct MicSens(Level);
|
||||
pub struct MicSens(f32);
|
||||
|
||||
pub struct AudioPlugin;
|
||||
|
||||
impl Plugin for AudioPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_startup_system(monitor);
|
||||
app.add_startup_system(monitor)
|
||||
.add_systems((update_mic_level, update_mic_sens).in_base_set(CoreSet::PreUpdate))
|
||||
.insert_resource(MicSens(1.))
|
||||
.init_resource::<MicLevel>();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_mic_level(mut level: ResMut<MicLevel>) {
|
||||
level.0 = *MIC_LEVEL_RAW.lock().expect("Poisoned mutex");
|
||||
}
|
||||
|
||||
pub fn update_mic_sens(mut sens: ResMut<MicSens>) {
|
||||
sens.0 = *MIC_SENS_RAW.lock().expect("Poisoned mutex");
|
||||
}
|
||||
|
||||
pub fn monitor(world: &mut World) {
|
||||
let device = initialize().expect("Unable to init audio");
|
||||
info!("Using device {}", device.name().unwrap());
|
||||
let config = device.default_input_config().unwrap();
|
||||
|
||||
let level = Arc::new(Mutex::new(0.));
|
||||
world.insert_resource(MicLevel(level.clone()));
|
||||
let sens = Arc::new(Mutex::new(1.));
|
||||
world.insert_resource(MicSens(sens.clone()));
|
||||
*MIC_SENS_RAW.lock().expect("Poisoned sens mutex") = 100.0;
|
||||
|
||||
let stream = device
|
||||
.build_input_stream(
|
||||
&config.config(),
|
||||
move |data: &[f32], _: &InputCallbackInfo| {
|
||||
let cur_level = { *level.lock().unwrap() };
|
||||
*level.lock().unwrap() = (data
|
||||
let cur_level = { *MIC_LEVEL_RAW.lock().unwrap() };
|
||||
*MIC_LEVEL_RAW.lock().unwrap() = (data
|
||||
.iter()
|
||||
.map(|e| e.abs() * *sens.lock().unwrap())
|
||||
.map(|e| e.abs() * *MIC_SENS_RAW.lock().unwrap())
|
||||
.max_by(|a, b| a.total_cmp(b))
|
||||
.unwrap()
|
||||
* 0.5)
|
||||
|
|
|
@ -64,14 +64,12 @@ fn main() {
|
|||
}
|
||||
|
||||
fn logging(level: Res<MicLevel>, threshold: Res<TriggerThreshold>) {
|
||||
info!("Audio in: {}", level.lock().unwrap());
|
||||
info!("Audio in: {}", **level);
|
||||
info!("Mic thresh: {}", **threshold);
|
||||
}
|
||||
|
||||
fn setup(mut commands: Commands, sens: ResMut<MicSens>) {
|
||||
fn setup(mut commands: Commands) {
|
||||
commands.spawn(Camera2dBundle::default());
|
||||
|
||||
*sens.lock().expect("Poisoned sens mutex") = 100.0;
|
||||
}
|
||||
|
||||
// window systems
|
||||
|
@ -87,7 +85,7 @@ fn react_to_focus(
|
|||
}
|
||||
|
||||
if event.focused {
|
||||
commands.insert_resource(ClearColor(Color::ALICE_BLUE));
|
||||
commands.insert_resource(ClearColor(Color::PURPLE));
|
||||
ui_events.send(UiMessage::Show);
|
||||
} else {
|
||||
commands.insert_resource(ClearColor(Color::NONE));
|
||||
|
|
13
src/tube.rs
13
src/tube.rs
|
@ -3,7 +3,7 @@ use bevy::prelude::*;
|
|||
use bevy_tweening::{lens::TransformPositionLens, Animator, EaseMethod, Tween};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::audio::MicLevel;
|
||||
use crate::audio::{update_mic_level, MicLevel};
|
||||
|
||||
#[derive(Resource, Clone, Copy)]
|
||||
pub enum MouthState {
|
||||
|
@ -42,7 +42,11 @@ pub struct TubePlugin;
|
|||
impl Plugin for TubePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_startup_system(setup)
|
||||
.add_system(audio_trigger.in_base_set(CoreSet::PreUpdate))
|
||||
.add_system(
|
||||
audio_trigger
|
||||
.in_base_set(CoreSet::PreUpdate)
|
||||
.after(update_mic_level),
|
||||
)
|
||||
.add_system(run_animation.run_if(resource_changed::<MouthState>()))
|
||||
.add_system(sync_images)
|
||||
.insert_resource(MouthState::Closed)
|
||||
|
@ -87,15 +91,14 @@ fn setup(mut commands: Commands, ass: Res<AssetServer>) {
|
|||
const MAX_THRESHOLD: f32 = 10.0;
|
||||
fn audio_trigger(
|
||||
mut mouth_state: ResMut<MouthState>,
|
||||
mic_level: Res<MicLevel>,
|
||||
level: Res<MicLevel>,
|
||||
threshold: Res<TriggerThreshold>,
|
||||
mut buffer: ResMut<ActivationBuffer>,
|
||||
mut was_zero: Local<bool>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
let level = mic_level.lock().expect("Poisoned mutex");
|
||||
// info!("{}", ((**threshold / 100.) * MAX_THRESHOLD));
|
||||
if *level > ((**threshold / 100.) * MAX_THRESHOLD) {
|
||||
if level.value() > ((**threshold / 100.) * MAX_THRESHOLD) {
|
||||
if buffer.finished() {
|
||||
info!("Open mouth");
|
||||
*mouth_state = MouthState::Opened;
|
||||
|
|
460
src/ui/levels.rs
460
src/ui/levels.rs
|
@ -1,9 +1,9 @@
|
|||
use std::{collections::HashMap, marker::PhantomData, time::Duration};
|
||||
|
||||
use belly::prelude::*;
|
||||
use bevy::prelude::*;
|
||||
use bevy_eventlistener::callbacks::ListenerInput;
|
||||
use bevy_mod_picking::prelude::*;
|
||||
use bevy_ninepatch::*;
|
||||
use bevy_tweening::{lens::UiPositionLens, *};
|
||||
|
||||
use crate::{
|
||||
|
@ -12,19 +12,21 @@ use crate::{
|
|||
utils::UiSizeLens,
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
use super::setup_ui;
|
||||
|
||||
#[derive(Component, Default)]
|
||||
pub struct LevelBars;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Default)]
|
||||
pub struct MicLevelBar;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Default)]
|
||||
pub struct MicLevelContainer;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Default)]
|
||||
pub struct ActivationLevelBar;
|
||||
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Default)]
|
||||
pub struct MicLevelArrow;
|
||||
|
||||
pub struct ArrowDrag<C: Component> {
|
||||
|
@ -70,250 +72,240 @@ pub(super) struct LevelsPlugin;
|
|||
|
||||
impl Plugin for LevelsPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_startup_system(spawn_levels)
|
||||
.add_systems((set_max_size::<MicLevelContainer, MicLevelArrow>
|
||||
.after(spawn_levels)
|
||||
.in_base_set(CoreSet::Last)
|
||||
.run_if(run_once()),))
|
||||
.add_event::<ArrowDrag<MicLevelArrow>>()
|
||||
app.add_event::<ArrowDrag<MicLevelArrow>>()
|
||||
.add_system(
|
||||
handle_mic_thresh_set.run_if(resource_exists::<MaxPercent<MicLevelContainer>>()),
|
||||
)
|
||||
.add_system(react_mic_level_color.run_if(resource_changed::<MouthState>()))
|
||||
.add_system(animate_mic_level)
|
||||
.add_system(animate_active_level);
|
||||
.add_system(react_mic_level_color.run_if(resource_changed::<MouthState>()));
|
||||
}
|
||||
}
|
||||
|
||||
const RESTING_POS: f32 = 20.;
|
||||
|
||||
pub(super) fn spawn_levels(
|
||||
mut commands: Commands,
|
||||
ass: Res<AssetServer>,
|
||||
mut patches: ResMut<Assets<NinePatchBuilder<()>>>,
|
||||
mic_threshold: Res<TriggerThreshold>,
|
||||
// mut commands: Commands,
|
||||
// mic_threshold: Res<TriggerThreshold>,
|
||||
mut elements: Elements,
|
||||
) {
|
||||
let bar_img: Handle<Image> = ass.load("square-small.png");
|
||||
let bar_patch = patches.add(NinePatchBuilder::by_margins(2, 2, 2, 2));
|
||||
let mic_bar = commands
|
||||
.spawn(NodeBundle {
|
||||
background_color: Color::GREEN.into(),
|
||||
style: Style {
|
||||
position_type: PositionType::Absolute,
|
||||
size: Size::new(Val::Percent(100.), Val::Percent(0.)),
|
||||
position: UiRect::bottom(Val::Px(0.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.insert(MicLevelBar)
|
||||
.id();
|
||||
|
||||
let active_bar = commands
|
||||
.spawn(NodeBundle {
|
||||
background_color: Color::PURPLE.into(),
|
||||
style: Style {
|
||||
position_type: PositionType::Absolute,
|
||||
size: Size::new(Val::Percent(100.), Val::Percent(0.)),
|
||||
position: UiRect::bottom(Val::Px(0.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.insert(ActivationLevelBar)
|
||||
.id();
|
||||
// let bar_img: Handle<Image> = ass.load("square-small.png");
|
||||
// let bar_patch = patches.add(NinePatchBuilder::by_margins(2, 2, 2, 2));
|
||||
// let mic_bar = commands
|
||||
// .spawn(NodeBundle {
|
||||
// background_color: Color::GREEN.into(),
|
||||
// style: Style {
|
||||
// position_type: PositionType::Absolute,
|
||||
// size: Size::new(Val::Percent(100.), Val::Percent(0.)),
|
||||
// position: UiRect::bottom(Val::Px(0.)),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .insert(MicLevelBar)
|
||||
// .id();
|
||||
|
||||
commands
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
size: Size::new(Val::Px(200.), Val::Percent(100.)),
|
||||
position_type: PositionType::Absolute,
|
||||
gap: Size::all(Val::Px(20.)),
|
||||
position: UiRect::right(Val::Px(RESTING_POS)),
|
||||
justify_content: JustifyContent::FlexEnd,
|
||||
padding: UiRect::vertical(Val::Px(20.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.insert(LevelBars)
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
flex_direction: FlexDirection::Column,
|
||||
gap: Size::height(Val::Px(10.)),
|
||||
// size: Size::all(Val::Percent(100.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.with_children(|parent| {
|
||||
parent.spawn(ImageBundle {
|
||||
image: UiImage::new(ass.load("microphone.png")),
|
||||
background_color: Color::BLACK.into(),
|
||||
..default()
|
||||
});
|
||||
// let active_bar = commands
|
||||
// .spawn(NodeBundle {
|
||||
// background_color: Color::PURPLE.into(),
|
||||
// style: Style {
|
||||
// position_type: PositionType::Absolute,
|
||||
// size: Size::new(Val::Percent(100.), Val::Percent(0.)),
|
||||
// position: UiRect::bottom(Val::Px(0.)),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .insert(ActivationLevelBar)
|
||||
// .id();
|
||||
|
||||
let mut content = HashMap::new();
|
||||
content.insert((), mic_bar);
|
||||
parent
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
size: Size::height(Val::Percent(100.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.with_children(|parent| {
|
||||
parent
|
||||
.spawn(ImageBundle {
|
||||
image: UiImage::new(ass.load("plain-arrow.png")),
|
||||
background_color: Color::BLACK.into(),
|
||||
style: Style {
|
||||
size: Size::all(Val::Px(16.)),
|
||||
position_type: PositionType::Absolute,
|
||||
position: UiRect::new(
|
||||
Val::Px(-16.),
|
||||
Val::Auto,
|
||||
Val::Auto,
|
||||
Val::Percent(**mic_threshold),
|
||||
),
|
||||
..default()
|
||||
},
|
||||
z_index: ZIndex::Global(100),
|
||||
..default()
|
||||
})
|
||||
.insert(MicLevelArrow)
|
||||
.insert(
|
||||
On::<Pointer<Drag>>::send_event::<ArrowDrag<MicLevelArrow>>(),
|
||||
);
|
||||
parent
|
||||
.spawn(NinePatchBundle {
|
||||
style: Style {
|
||||
size: Size::new(Val::Px(32.), Val::Percent(100.)),
|
||||
..default()
|
||||
},
|
||||
nine_patch_data: NinePatchData {
|
||||
texture: bar_img.clone(),
|
||||
nine_patch: bar_patch.clone(),
|
||||
content: Some(content),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.insert(MicLevelContainer);
|
||||
});
|
||||
});
|
||||
parent
|
||||
.spawn(NodeBundle {
|
||||
style: Style {
|
||||
flex_direction: FlexDirection::Column,
|
||||
gap: Size::height(Val::Px(10.)),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
})
|
||||
.with_children(|parent| {
|
||||
parent.spawn(ImageBundle {
|
||||
image: UiImage::new(ass.load("lips.png")),
|
||||
background_color: Color::BLACK.into(),
|
||||
..default()
|
||||
});
|
||||
let mut content = HashMap::new();
|
||||
content.insert((), active_bar);
|
||||
parent.spawn(NinePatchBundle {
|
||||
style: Style {
|
||||
size: Size::new(Val::Px(32.), Val::Percent(100.)),
|
||||
..default()
|
||||
},
|
||||
nine_patch_data: NinePatchData {
|
||||
texture: bar_img.clone(),
|
||||
nine_patch: bar_patch.clone(),
|
||||
content: Some(content),
|
||||
..default()
|
||||
},
|
||||
..default()
|
||||
});
|
||||
});
|
||||
});
|
||||
// commands
|
||||
// .spawn(NodeBundle {
|
||||
// style: Style {
|
||||
// size: Size::new(Val::Px(200.), Val::Percent(100.)),
|
||||
// position_type: PositionType::Absolute,
|
||||
// gap: Size::all(Val::Px(20.)),
|
||||
// position: UiRect::right(Val::Px(RESTING_POS)),
|
||||
// justify_content: JustifyContent::FlexEnd,
|
||||
// padding: UiRect::vertical(Val::Px(20.)),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .insert(LevelBars)
|
||||
// .with_children(|parent| {
|
||||
// parent
|
||||
// .spawn(NodeBundle {
|
||||
// style: Style {
|
||||
// flex_direction: FlexDirection::Column,
|
||||
// gap: Size::height(Val::Px(10.)),
|
||||
// // size: Size::all(Val::Percent(100.)),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .with_children(|parent| {
|
||||
// parent.spawn(ImageBundle {
|
||||
// image: UiImage::new(ass.load("microphone.png")),
|
||||
// background_color: Color::BLACK.into(),
|
||||
// ..default()
|
||||
// });
|
||||
|
||||
// let mut content = HashMap::new();
|
||||
// content.insert((), mic_bar);
|
||||
// parent
|
||||
// .spawn(NodeBundle {
|
||||
// style: Style {
|
||||
// size: Size::height(Val::Percent(100.)),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .with_children(|parent| {
|
||||
// parent
|
||||
// .spawn(ImageBundle {
|
||||
// image: UiImage::new(ass.load("plain-arrow.png")),
|
||||
// background_color: Color::BLACK.into(),
|
||||
// style: Style {
|
||||
// size: Size::all(Val::Px(16.)),
|
||||
// position_type: PositionType::Absolute,
|
||||
// position: UiRect::new(
|
||||
// Val::Px(-16.),
|
||||
// Val::Auto,
|
||||
// Val::Auto,
|
||||
// Val::Percent(**mic_threshold),
|
||||
// ),
|
||||
// ..default()
|
||||
// },
|
||||
// z_index: ZIndex::Global(100),
|
||||
// ..default()
|
||||
// })
|
||||
// .insert(MicLevelArrow)
|
||||
// .insert(
|
||||
// On::<Pointer<Drag>>::send_event::<ArrowDrag<MicLevelArrow>>(),
|
||||
// );
|
||||
// parent
|
||||
// .spawn(NinePatchBundle {
|
||||
// style: Style {
|
||||
// size: Size::new(Val::Px(32.), Val::Percent(100.)),
|
||||
// ..default()
|
||||
// },
|
||||
// nine_patch_data: NinePatchData {
|
||||
// texture: bar_img.clone(),
|
||||
// nine_patch: bar_patch.clone(),
|
||||
// content: Some(content),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .insert(MicLevelContainer);
|
||||
// });
|
||||
// });
|
||||
// parent
|
||||
// .spawn(NodeBundle {
|
||||
// style: Style {
|
||||
// flex_direction: FlexDirection::Column,
|
||||
// gap: Size::height(Val::Px(10.)),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// })
|
||||
// .with_children(|parent| {
|
||||
// parent.spawn(ImageBundle {
|
||||
// image: UiImage::new(ass.load("lips.png")),
|
||||
// background_color: Color::BLACK.into(),
|
||||
// ..default()
|
||||
// });
|
||||
// let mut content = HashMap::new();
|
||||
// content.insert((), active_bar);
|
||||
// parent.spawn(NinePatchBundle {
|
||||
// style: Style {
|
||||
// size: Size::new(Val::Px(32.), Val::Percent(100.)),
|
||||
// ..default()
|
||||
// },
|
||||
// nine_patch_data: NinePatchData {
|
||||
// texture: bar_img.clone(),
|
||||
// nine_patch: bar_patch.clone(),
|
||||
// content: Some(content),
|
||||
// ..default()
|
||||
// },
|
||||
// ..default()
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
fn set_max_size<B: Component, C: Component>(
|
||||
mut commands: Commands,
|
||||
bar_q: Query<&Node, With<B>>,
|
||||
other: Query<&Node, With<C>>,
|
||||
) {
|
||||
let Ok(bar) = bar_q.get_single() else { return };
|
||||
let Ok(other) = other.get_single() else { return };
|
||||
let size = ((bar.size().y - (other.size().y / 2.)) / bar.size().y) * 100.;
|
||||
info!("{size}");
|
||||
commands.insert_resource(MaxPercent::<B>::new(size));
|
||||
}
|
||||
// fn set_max_size<B: Component, C: Component>(
|
||||
// mut commands: Commands,
|
||||
// bar_q: Query<&Node, With<B>>,
|
||||
// other: Query<&Node, With<C>>,
|
||||
// ) {
|
||||
// let Ok(bar) = bar_q.get_single() else { return };
|
||||
// let Ok(other) = other.get_single() else {
|
||||
// return;
|
||||
// };
|
||||
// let size = ((bar.size().y - (other.size().y / 2.)) / bar.size().y) * 100.;
|
||||
// info!("{size}");
|
||||
// commands.insert_resource(MaxPercent::<B>::new(size));
|
||||
// }
|
||||
|
||||
pub(super) fn animate_mic_level(
|
||||
mut commands: Commands,
|
||||
bar_q: Query<(Entity, &Style), With<MicLevelBar>>,
|
||||
level: Res<MicLevel>,
|
||||
) {
|
||||
const SCALE: f32 = 10.;
|
||||
for (ent, style) in bar_q.iter() {
|
||||
let current = style.size;
|
||||
let new = Size::new(
|
||||
style.size.width,
|
||||
Val::Percent((*level.lock().expect("Poisoned mic level") * SCALE).clamp(0., 100.)),
|
||||
);
|
||||
let tween = Tween::new(
|
||||
EaseMethod::Linear,
|
||||
Duration::from_millis(1),
|
||||
UiSizeLens {
|
||||
start: current,
|
||||
end: new,
|
||||
},
|
||||
);
|
||||
commands.entity(ent).insert(Animator::new(tween));
|
||||
}
|
||||
}
|
||||
// pub(super) fn animate_mic_level(
|
||||
// mut commands: Commands,
|
||||
// bar_q: Query<(Entity, &Style), With<MicLevelBar>>,
|
||||
// level: Res<MicLevel>,
|
||||
// ) {
|
||||
// const SCALE: f32 = 10.;
|
||||
// for (ent, style) in bar_q.iter() {
|
||||
// let current = style.size;
|
||||
// let new = Size::new(
|
||||
// style.size.width,
|
||||
// Val::Percent((level.value() * SCALE).clamp(0., 100.)),
|
||||
// );
|
||||
// let tween = Tween::new(
|
||||
// EaseMethod::Linear,
|
||||
// Duration::from_millis(1),
|
||||
// UiSizeLens {
|
||||
// start: current,
|
||||
// end: new,
|
||||
// },
|
||||
// );
|
||||
// commands.entity(ent).insert(Animator::new(tween));
|
||||
// }
|
||||
// }
|
||||
|
||||
pub(super) fn animate_active_level(
|
||||
mut commands: Commands,
|
||||
bar_q: Query<(Entity, &Style), With<ActivationLevelBar>>,
|
||||
level: Res<ActivationBuffer>,
|
||||
) {
|
||||
const SCALE: f32 = 100.;
|
||||
for (ent, style) in bar_q.iter() {
|
||||
let current = style.size;
|
||||
let new = Size::new(
|
||||
style.size.width,
|
||||
Val::Percent((level.percent_left() * SCALE).clamp(0., 100.)),
|
||||
);
|
||||
// pub(super) fn animate_active_level(
|
||||
// mut commands: Commands,
|
||||
// bar_q: Query<(Entity, &Style), With<ActivationLevelBar>>,
|
||||
// level: Res<ActivationBuffer>,
|
||||
// ) {
|
||||
// const SCALE: f32 = 100.;
|
||||
// for (ent, style) in bar_q.iter() {
|
||||
// let current = style.size;
|
||||
// let new = Size::new(
|
||||
// style.size.width,
|
||||
// Val::Percent((level.percent_left() * SCALE).clamp(0., 100.)),
|
||||
// );
|
||||
|
||||
// info!("UI mic level: {:?}", new.height);
|
||||
let tween = Tween::new(
|
||||
EaseMethod::Linear,
|
||||
Duration::from_millis(1),
|
||||
UiSizeLens {
|
||||
start: current,
|
||||
end: new,
|
||||
},
|
||||
);
|
||||
commands.entity(ent).insert(Animator::new(tween));
|
||||
}
|
||||
}
|
||||
// // info!("UI mic level: {:?}", new.height);
|
||||
// let tween = Tween::new(
|
||||
// EaseMethod::Linear,
|
||||
// Duration::from_millis(1),
|
||||
// UiSizeLens {
|
||||
// start: current,
|
||||
// end: new,
|
||||
// },
|
||||
// );
|
||||
// commands.entity(ent).insert(Animator::new(tween));
|
||||
// }
|
||||
// }
|
||||
|
||||
pub(super) fn react_mic_level_color(
|
||||
mut bar_q: Query<&mut BackgroundColor, With<MicLevelBar>>,
|
||||
mouth_state: Res<MouthState>,
|
||||
) {
|
||||
for mut color in bar_q.iter_mut() {
|
||||
match *mouth_state {
|
||||
MouthState::Opened => {
|
||||
*color = Color::GREEN.into();
|
||||
}
|
||||
pub(super) fn react_mic_level_color(mut elements: Elements, mouth_state: Res<MouthState>) {
|
||||
match *mouth_state {
|
||||
MouthState::Opened => {
|
||||
elements.select(".mic-level").add_class("active");
|
||||
}
|
||||
|
||||
MouthState::Closed => {
|
||||
*color = Color::BLUE.into();
|
||||
}
|
||||
MouthState::Closed => {
|
||||
elements.select(".mic-level").remove_class("active");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -326,8 +318,12 @@ fn handle_mic_thresh_set(
|
|||
max_size: Res<MaxPercent<MicLevelContainer>>,
|
||||
) {
|
||||
for event in events.iter() {
|
||||
let Ok((mut style, arrow)) = styles.get_mut(event.target) else { continue };
|
||||
let Ok(bar) = bar_q.get_single() else { continue };
|
||||
let Ok((mut style, arrow)) = styles.get_mut(event.target) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(bar) = bar_q.get_single() else {
|
||||
continue;
|
||||
};
|
||||
if let Val::Percent(pos) = style.position.bottom {
|
||||
let delta = (event.delta.y / bar.size().y) * 100.;
|
||||
let new_percent = (delta + pos).clamp(0., **max_size);
|
||||
|
|
|
@ -2,13 +2,15 @@ mod frames;
|
|||
mod levels;
|
||||
mod widgets;
|
||||
|
||||
use belly::prelude::*;
|
||||
use belly::{prelude::*, widgets::range::RangeWidgetExtension};
|
||||
use bevy::prelude::*;
|
||||
use bevy_ninepatch::NinePatchPlugin;
|
||||
|
||||
use crate::audio::MicLevel;
|
||||
|
||||
use self::{
|
||||
frames::{CardImages, FrameCards},
|
||||
levels::LevelBars,
|
||||
levels::{ActivationLevelBar, LevelBars, MicLevelArrow, MicLevelContainer},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -23,15 +25,10 @@ impl Plugin for UiPlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
app.add_plugin(BellyPlugin)
|
||||
.add_event::<UiMessage>()
|
||||
.add_plugin(levels::LevelsPlugin)
|
||||
.add_startup_system(setup_ui)
|
||||
.add_system(handle_msg)
|
||||
.add_system(frames::update_card_images);
|
||||
// app.add_plugin(NinePatchPlugin::<()>::default())
|
||||
// .add_plugin(levels::LevelsPlugin)
|
||||
// .init_resource::<CardImages>()
|
||||
// .add_startup_system(frames::update_card_images)
|
||||
// .add_system(frames::update_card_images.before(frames::render_cards))
|
||||
// .add_startup_system(frames::render_cards);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +42,16 @@ fn setup_ui(mut commands: Commands) {
|
|||
</div>
|
||||
</for>
|
||||
</div>
|
||||
<div c:right c:levels-container with=LevelBars s:right="0px">
|
||||
<div s:flex-direction="column">
|
||||
<range c:mic-level s:height="75%" s:width="50px" mode="vertical" maximum=5.0 bind:value=from!(MicLevel:value())/>
|
||||
<img src="microphone.png" modulate=Color::BLACK/>
|
||||
</div>
|
||||
|
||||
<div c:level-container>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
});
|
||||
}
|
||||
|
@ -56,7 +63,9 @@ fn handle_msg(
|
|||
levels_q: Query<(Entity, &Style), With<LevelBars>>,
|
||||
) {
|
||||
for event in events.iter() {
|
||||
let Ok((frames, frame_style)) = frame_q.get_single() else { return };
|
||||
let Ok((frames, frame_style)) = frame_q.get_single() else {
|
||||
return;
|
||||
};
|
||||
// let Ok((bars, bar_style)) = levels_q.get_single() else { return };
|
||||
match event {
|
||||
UiMessage::Hide => {
|
||||
|
|
Loading…
Reference in New Issue