diff --git a/bin/editor.rs b/bin/editor.rs index e96e3e4..b1ea166 100644 --- a/bin/editor.rs +++ b/bin/editor.rs @@ -40,7 +40,10 @@ fn main() { )) .init_resource::() .add_systems(Startup, initialize_ui) - .add_systems(Update, (import_files, import_audio, play_audio)) + .add_systems( + Update, + (import_files, import_audio, import_gltf, play_audio), + ) .run(); } @@ -63,8 +66,8 @@ fn initialize_ui(mut commands: Commands) { let base_style = Style { border: UiRect::all(Val::Px(1.0)), padding: UiRect::all(Val::Px(5.0)), - flex_direction: FlexDirection::Column, overflow: Overflow::clip(), + flex_direction: FlexDirection::Column, ..default() }; @@ -73,6 +76,7 @@ fn initialize_ui(mut commands: Commands) { style: Style { width: Val::Percent(50.0), height: Val::Percent(50.0), + flex_direction: FlexDirection::Row, ..base_style.clone() }, background_color: Color::WHITE.into(), @@ -81,62 +85,71 @@ fn initialize_ui(mut commands: Commands) { ..default() }) .with_children(|parent| { - { - parent - .spawn(NodeBundle { + spawn_tabtree::(parent, "Audio".into(), &base_style); + spawn_tabtree::(parent, "Gltf".into(), &base_style); + }); + + commands.insert_resource(Styles { + button: Style { ..default() }, + button_hovered: Style { ..default() }, + container: Style { ..default() }, + }) +} + +fn spawn_tabtree( + parent: &mut ChildBuilder, + title: String, + base_style: &Style, +) { + parent + .spawn(( + NodeBundle { + style: Style { + ..base_style.clone() + }, + background_color: Color::WHITE.into(), + border_color: Color::BLACK.into(), + z_index: ZIndex::Local(20), + ..default() + }, + Interaction::default(), + )) + .with_children(|parent| { + // Spawn button container + let container = parent + .spawn(( + NodeBundle { style: Style { ..base_style.clone() }, background_color: Color::WHITE.into(), border_color: Color::BLACK.into(), - z_index: ZIndex::Local(20), + z_index: ZIndex::Local(10), ..default() - }) - .with_children(|parent| { - // Spawn button container - let container = parent - .spawn(( - NodeBundle { - style: Style { - ..base_style.clone() - }, - background_color: Color::WHITE.into(), - border_color: Color::BLACK.into(), - z_index: ZIndex::Local(10), - ..default() - }, - AudioWidget, - ui::Scroll, - ui::Sorting(2), - )) - .id(); + }, + T::default(), + ui::Scroll, + Interaction::default(), + ui::Sorting(2), + )) + .id(); - // Spawn widget - parent.spawn(( - ButtonBundle { - style: Style { - ..base_style.clone() - }, - background_color: Color::WHITE.into(), - border_color: Color::BLACK.into(), - z_index: ZIndex::Local(15), - ..default() - }, - ui::Title { - name: "Audio".into(), - }, - ui::Collapse { target: container }, - ui::Sorting(1), - )); - }); - } + // Spawn widget + parent.spawn(( + ButtonBundle { + style: Style { + ..base_style.clone() + }, + background_color: Color::WHITE.into(), + border_color: Color::BLACK.into(), + z_index: ZIndex::Local(15), + ..default() + }, + ui::Title { name: title }, + ui::Collapse { target: container }, + ui::Sorting(1), + )); }); - - commands.insert_resource(Styles { - button: Style { ..default() }, - button_hovered: Style { ..default() }, - container: Style { ..default() }, - }) } fn import_files( @@ -166,7 +179,7 @@ mod audio { use super::*; - #[derive(Debug, Component)] + #[derive(Debug, Component, Default)] pub struct AudioWidget; pub fn import_audio( @@ -176,10 +189,9 @@ mod audio { current: Query<(Entity, &Handle)>, server: Res, ) { - // TODO: Filter to just audio files events .iter() - .filter(|event| match event { + .filter(|&event| match event { AssetEvent::Created { handle } | AssetEvent::Removed { handle } | AssetEvent::Modified { handle } => { @@ -282,3 +294,98 @@ mod audio { }); } } + +use gltf::*; +mod gltf { + use super::*; + + #[derive(Debug, Component, Default)] + pub struct GltfWidget; + + pub fn import_gltf( + mut events: EventReader>, + mut commands: Commands, + root: Query>, + current: Query<(Entity, &Handle)>, + server: Res, + ) { + events + .iter() + .filter(|&event| match event { + AssetEvent::Created { handle } + | AssetEvent::Removed { handle } + | AssetEvent::Modified { handle } => { + if let Some(asset_path) = server.get_handle_path(handle.clone()) { + if let Some(extension) = asset_path.path().extension() { + extension == "gltf" || extension == "glb" + } else { + false + } + } else { + false + } + } + }) + .for_each(|event| { + let create = |commands: &mut Commands, handle: Handle| { + commands.entity(root.single()).with_children(|parent| { + let name = { + if let Some(asset_path) = server.get_handle_path(handle.clone()) { + if let Some(stem) = asset_path.path().file_stem() { + if let Some(val) = stem.to_str() { + String::from(val) + } else { + String::from("???") + } + } else { + String::from("???") + } + } else { + String::from("???") + } + }; + parent.spawn(( + handle, + ButtonBundle { + style: Style { + border: UiRect::all(Val::Px(1.0)), + margin: UiRect::all(Val::Px(5.0)), + padding: UiRect::all(Val::Px(5.0)), + ..default() + }, + border_color: Color::BLACK.into(), + ..default() + }, + ui::Title { name }, + )); + }); + }; + let destroy = |commands: &mut Commands, handle: Handle| { + if let Some(entity) = current.iter().find_map(|(entity, current)| { + if *current == handle { + Some(entity) + } else { + None + } + }) { + commands.entity(entity).despawn_recursive(); + } + }; + match event { + AssetEvent::Created { handle } => { + info!("Asset created! {:?}", event); + create(&mut commands, handle.clone()); + } + AssetEvent::Removed { handle } => { + info!("Asset removed! {:?}", event); + destroy(&mut commands, handle.clone()); + } + AssetEvent::Modified { handle } => { + info!("Asset modified! {:?}", event); + destroy(&mut commands, handle.clone()); + create(&mut commands, handle.clone()); + } + } + }); + } +} diff --git a/src/ui.rs b/src/ui.rs index 6ccf319..640e027 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -135,23 +135,40 @@ mod scroll { pub fn manage_scroll( mut events: EventReader, - mut query: Query<&mut Style, With>, + mut query: Query<(&Interaction, &Parent, &Children, &mut Style), With>, + interactions: Query<&Interaction>, ) { events.iter().for_each(|MouseWheel { unit, y, .. }| { - query.iter_mut().for_each(|mut style| { - let factor = 2.0; - let val = match unit { - MouseScrollUnit::Line => match style.top { - Val::Px(v) => v + (y * factor), - _ => (*y) * factor, - }, - MouseScrollUnit::Pixel => match style.top { - Val::Px(v) => v + (y * factor), - _ => (*y) * factor, - }, - }; - style.top = Val::Px(val.min(0.0)); - }); + query + .iter_mut() + .filter(|(&interaction, parent, children, _)| { + let self_hover = interaction == Interaction::Hovered; + let child_hover = children.iter().any(|&child| { + if let Ok(&interaction) = interactions.get(child) { + interaction == Interaction::Hovered + } else { + false + } + }); + let parent_hover = interactions + .get(parent.get()) + .map_or(false, |&interaction| interaction == Interaction::Hovered); + self_hover || child_hover || parent_hover + }) + .for_each(|(_, _, _, mut style)| { + let factor = 2.0; + let val = match unit { + MouseScrollUnit::Line => match style.top { + Val::Px(v) => v + (y * factor), + _ => (*y) * factor, + }, + MouseScrollUnit::Pixel => match style.top { + Val::Px(v) => v + (y * factor), + _ => (*y) * factor, + }, + }; + style.top = Val::Px(val.min(0.0)); + }); }); } }