From 777d3ef6be5ef3c0bb6c9f5b83629d4400632832 Mon Sep 17 00:00:00 2001 From: Skyler Lehmkuhl Date: Sat, 14 Feb 2026 11:07:32 -0500 Subject: [PATCH] Clean up build warnings --- daw-backend/src/audio/export.rs | 35 +--- daw-backend/src/audio/waveform_cache.rs | 4 +- .../src/actions/move_clip_instances.rs | 2 +- .../src/actions/paint_bucket.rs | 8 +- .../src/actions/set_instance_properties.rs | 20 --- .../src/actions/trim_clip_instances.rs | 6 +- .../src/curve_intersections.rs | 21 --- .../lightningbeam-core/src/effect_layer.rs | 16 -- .../src/intersection_graph.rs | 26 +-- .../lightningbeam-core/src/path_fitting.rs | 2 +- .../lightningbeam-core/src/planar_graph.rs | 9 +- .../lightningbeam-core/src/segment_builder.rs | 20 +-- .../lightningbeam-core/src/video.rs | 12 +- .../src/effect_thumbnails.rs | 7 +- .../src/export/audio_exporter.rs | 3 +- .../lightningbeam-editor/src/export/dialog.rs | 22 +-- .../lightningbeam-editor/src/export/mod.rs | 12 +- .../src/export/readback_pipeline.rs | 9 +- .../src/export/video_exporter.rs | 1 + .../lightningbeam-editor/src/main.rs | 153 ++++-------------- .../lightningbeam-editor/src/menu.rs | 16 +- .../src/panes/asset_library.rs | 37 +++-- .../lightningbeam-editor/src/panes/mod.rs | 5 +- .../src/panes/node_graph/actions.rs | 3 + .../src/panes/node_graph/audio_backend.rs | 60 +++---- .../src/panes/node_graph/backend.rs | 1 + .../src/panes/node_graph/mod.rs | 23 +-- .../src/panes/node_graph/node_types.rs | 1 + .../src/panes/node_graph/palette.rs | 2 +- .../src/panes/shader_editor.rs | 1 + .../lightningbeam-editor/src/panes/stage.rs | 75 ++------- .../src/panes/timeline.rs | 17 +- .../src/panes/virtual_piano.rs | 4 +- .../src/preferences/dialog.rs | 14 +- .../src/preferences/mod.rs | 1 - .../lightningbeam-editor/src/theme.rs | 31 +--- .../lightningbeam-editor/src/waveform_gpu.rs | 10 +- .../src/widgets/text_field.rs | 1 + 38 files changed, 210 insertions(+), 480 deletions(-) diff --git a/daw-backend/src/audio/export.rs b/daw-backend/src/audio/export.rs index 7aa8b7d..5ca541a 100644 --- a/daw-backend/src/audio/export.rs +++ b/daw-backend/src/audio/export.rs @@ -72,7 +72,7 @@ pub fn export_audio>( midi_pool: &MidiClipPool, settings: &ExportSettings, output_path: P, - mut event_tx: Option<&mut rtrb::Producer>, + event_tx: Option<&mut rtrb::Producer>, ) -> Result<(), String> { // Route to appropriate export implementation based on format @@ -435,8 +435,6 @@ fn export_mp3>( channel_layout, pts, )?; - - frames_rendered += final_frame_size; } // Flush encoder @@ -602,8 +600,6 @@ fn export_aac>( channel_layout, pts, )?; - - frames_rendered += final_frame_size; } // Flush encoder @@ -617,35 +613,6 @@ fn export_aac>( Ok(()) } -/// Convert interleaved f32 samples to planar i16 format -fn convert_to_planar_i16(interleaved: &[f32], channels: u32) -> Vec> { - let num_frames = interleaved.len() / channels as usize; - let mut planar = vec![vec![0i16; num_frames]; channels as usize]; - - for (i, chunk) in interleaved.chunks(channels as usize).enumerate() { - for (ch, &sample) in chunk.iter().enumerate() { - let clamped = sample.max(-1.0).min(1.0); - planar[ch][i] = (clamped * 32767.0) as i16; - } - } - - planar -} - -/// Convert interleaved f32 samples to planar f32 format -fn convert_to_planar_f32(interleaved: &[f32], channels: u32) -> Vec> { - let num_frames = interleaved.len() / channels as usize; - let mut planar = vec![vec![0.0f32; num_frames]; channels as usize]; - - for (i, chunk) in interleaved.chunks(channels as usize).enumerate() { - for (ch, &sample) in chunk.iter().enumerate() { - planar[ch][i] = sample; - } - } - - planar -} - /// Convert a chunk of interleaved f32 samples to planar i16 format fn convert_chunk_to_planar_i16(interleaved: &[f32], channels: u32) -> Vec> { let num_frames = interleaved.len() / channels as usize; diff --git a/daw-backend/src/audio/waveform_cache.rs b/daw-backend/src/audio/waveform_cache.rs index d1ac570..feb3913 100644 --- a/daw-backend/src/audio/waveform_cache.rs +++ b/daw-backend/src/audio/waveform_cache.rs @@ -64,7 +64,7 @@ pub struct WaveformCache { chunks: HashMap>, /// Maximum memory usage in MB (for future LRU eviction) - max_memory_mb: usize, + _max_memory_mb: usize, /// Current memory usage estimate in bytes current_memory_bytes: usize, @@ -75,7 +75,7 @@ impl WaveformCache { pub fn new(max_memory_mb: usize) -> Self { Self { chunks: HashMap::new(), - max_memory_mb, + _max_memory_mb: max_memory_mb, current_memory_bytes: 0, } } diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs b/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs index a34b15c..752a235 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/move_clip_instances.rs @@ -32,7 +32,7 @@ impl Action for MoveClipInstancesAction { let mut expanded_moves = self.layer_moves.clone(); let mut already_processed = std::collections::HashSet::new(); - for (layer_id, moves) in &self.layer_moves { + for (_layer_id, moves) in &self.layer_moves { for (instance_id, old_start, new_start) in moves { // Skip if already processed if already_processed.contains(instance_id) { diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/paint_bucket.rs b/lightningbeam-ui/lightningbeam-core/src/actions/paint_bucket.rs index f580d61..4e78b1a 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/paint_bucket.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/paint_bucket.rs @@ -26,10 +26,10 @@ pub struct PaintBucketAction { fill_color: ShapeColor, /// Tolerance for gap bridging (in pixels) - tolerance: f64, + _tolerance: f64, /// Gap handling mode - gap_mode: GapHandlingMode, + _gap_mode: GapHandlingMode, /// ID of the created shape (set after execution) created_shape_id: Option, @@ -59,8 +59,8 @@ impl PaintBucketAction { layer_id, click_point, fill_color, - tolerance, - gap_mode, + _tolerance: tolerance, + _gap_mode: gap_mode, created_shape_id: None, created_shape_instance_id: None, } diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/set_instance_properties.rs b/lightningbeam-ui/lightningbeam-core/src/actions/set_instance_properties.rs index 25e7645..9a9dac1 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/set_instance_properties.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/set_instance_properties.rs @@ -68,26 +68,6 @@ impl SetInstancePropertiesAction { } } - fn get_instance_value(&self, document: &Document, instance_id: &Uuid) -> Option { - if let Some(layer) = document.get_layer(&self.layer_id) { - if let AnyLayer::Vector(vector_layer) = layer { - if let Some(instance) = vector_layer.get_object(instance_id) { - return Some(match &self.property { - InstancePropertyChange::X(_) => instance.transform.x, - InstancePropertyChange::Y(_) => instance.transform.y, - InstancePropertyChange::Rotation(_) => instance.transform.rotation, - InstancePropertyChange::ScaleX(_) => instance.transform.scale_x, - InstancePropertyChange::ScaleY(_) => instance.transform.scale_y, - InstancePropertyChange::SkewX(_) => instance.transform.skew_x, - InstancePropertyChange::SkewY(_) => instance.transform.skew_y, - InstancePropertyChange::Opacity(_) => instance.opacity, - }); - } - } - } - None - } - fn apply_to_instance(&self, document: &mut Document, instance_id: &Uuid, value: f64) { if let Some(layer) = document.get_layer_mut(&self.layer_id) { if let AnyLayer::Vector(vector_layer) = layer { diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs b/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs index 0fba827..95cc545 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/trim_clip_instances.rs @@ -68,7 +68,7 @@ impl Action for TrimClipInstancesAction { let mut expanded_trims = self.layer_trims.clone(); let mut already_processed = std::collections::HashSet::new(); - for (layer_id, trims) in &self.layer_trims { + for (_layer_id, trims) in &self.layer_trims { for (instance_id, trim_type, old, new) in trims { // Skip if already processed if already_processed.contains(instance_id) { @@ -189,7 +189,7 @@ impl Action for TrimClipInstancesAction { match trim_type { TrimType::TrimLeft => { - if let (Some(old_trim), Some(new_trim), Some(old_timeline), Some(new_timeline)) = + if let (Some(old_trim), Some(new_trim), Some(old_timeline), Some(_new_timeline)) = (old.trim_value, new.trim_value, old.timeline_start, new.timeline_start) { // If extending to the left (new_trim < old_trim) @@ -365,7 +365,7 @@ impl Action for TrimClipInstancesAction { .ok_or_else(|| format!("Layer {} not mapped to backend track", layer_id))?; // Process each clip instance trim - for (instance_id, trim_type, _old, new) in trims { + for (instance_id, _trim_type, _old, _new) in trims { // Get clip instances from the layer let clip_instances = match layer { AnyLayer::Audio(al) => &al.clip_instances, diff --git a/lightningbeam-ui/lightningbeam-core/src/curve_intersections.rs b/lightningbeam-ui/lightningbeam-core/src/curve_intersections.rs index 6ec1174..7d97680 100644 --- a/lightningbeam-ui/lightningbeam-core/src/curve_intersections.rs +++ b/lightningbeam-ui/lightningbeam-core/src/curve_intersections.rs @@ -229,27 +229,6 @@ pub fn find_closest_approach( } } -/// Refine intersection parameters using Newton's method -fn refine_intersection( - curve1: &CubicBez, - curve2: &CubicBez, - mut t1: f64, - mut t2: f64, -) -> (f64, f64) { - // Simple refinement: just find nearest points iteratively - for _ in 0..5 { - let p1 = curve1.eval(t1); - let nearest2 = curve2.nearest(p1, 1e-6); - t2 = nearest2.t; - - let p2 = curve2.eval(t2); - let nearest1 = curve1.nearest(p2, 1e-6); - t1 = nearest1.t; - } - - (t1.clamp(0.0, 1.0), t2.clamp(0.0, 1.0)) -} - /// Refine self-intersection parameters fn refine_self_intersection(curve: &CubicBez, mut t1: f64, mut t2: f64) -> (f64, f64) { // Refine by moving parameters closer to where curves actually meet diff --git a/lightningbeam-ui/lightningbeam-core/src/effect_layer.rs b/lightningbeam-ui/lightningbeam-core/src/effect_layer.rs index 9d4d658..0ce50d2 100644 --- a/lightningbeam-ui/lightningbeam-core/src/effect_layer.rs +++ b/lightningbeam-ui/lightningbeam-core/src/effect_layer.rs @@ -189,22 +189,6 @@ impl EffectLayer { self.clip_instances = new_order; } - // === MUTATION METHODS (pub(crate) - only accessible to action module) === - - /// Add a clip instance (internal, for actions only) - pub(crate) fn add_clip_instance_internal(&mut self, instance: ClipInstance) -> Uuid { - self.add_clip_instance(instance) - } - - /// Remove a clip instance (internal, for actions only) - pub(crate) fn remove_clip_instance_internal(&mut self, id: &Uuid) -> Option { - self.remove_clip_instance(id) - } - - /// Insert a clip instance at a specific index (internal, for actions only) - pub(crate) fn insert_clip_instance_internal(&mut self, index: usize, instance: ClipInstance) -> Uuid { - self.insert_clip_instance(index, instance) - } } #[cfg(test)] diff --git a/lightningbeam-ui/lightningbeam-core/src/intersection_graph.rs b/lightningbeam-ui/lightningbeam-core/src/intersection_graph.rs index abac6e9..ccdb206 100644 --- a/lightningbeam-ui/lightningbeam-core/src/intersection_graph.rs +++ b/lightningbeam-ui/lightningbeam-core/src/intersection_graph.rs @@ -455,23 +455,23 @@ struct CurveIntersection { t_on_current: f64, /// Parameter on other curve - t_on_other: f64, + _t_on_other: f64, /// ID of the other curve - other_curve_id: usize, + _other_curve_id: usize, /// Intersection point point: Point, /// Whether this is a gap (within tolerance but not exact intersection) - is_gap: bool, + _is_gap: bool, } /// Find all intersections on a given curve fn find_intersections_on_curve( curve_id: usize, curves: &[CubicBez], - processed_curves: &HashSet, + _processed_curves: &HashSet, quadtree: &ToleranceQuadtree, tolerance: f64, debug_info: &mut WalkDebugInfo, @@ -489,10 +489,10 @@ fn find_intersections_on_curve( for int in self_ints { intersections.push(CurveIntersection { t_on_current: int.t1, - t_on_other: int.t2.unwrap_or(int.t1), - other_curve_id: curve_id, + _t_on_other: int.t2.unwrap_or(int.t1), + _other_curve_id: curve_id, point: int.point, - is_gap: false, + _is_gap: false, }); debug_info.intersections_found += 1; } @@ -504,10 +504,10 @@ fn find_intersections_on_curve( for int in exact_ints { intersections.push(CurveIntersection { t_on_current: int.t1, - t_on_other: int.t2.unwrap_or(0.0), - other_curve_id: other_id, + _t_on_other: int.t2.unwrap_or(0.0), + _other_curve_id: other_id, point: int.point, - is_gap: false, + _is_gap: false, }); debug_info.intersections_found += 1; } @@ -516,10 +516,10 @@ fn find_intersections_on_curve( if let Some(approach) = find_closest_approach(current_curve, other_curve, tolerance) { intersections.push(CurveIntersection { t_on_current: approach.t1, - t_on_other: approach.t2, - other_curve_id: other_id, + _t_on_other: approach.t2, + _other_curve_id: other_id, point: approach.p1, - is_gap: true, + _is_gap: true, }); } } diff --git a/lightningbeam-ui/lightningbeam-core/src/path_fitting.rs b/lightningbeam-ui/lightningbeam-core/src/path_fitting.rs index 9b7f998..79bfd60 100644 --- a/lightningbeam-ui/lightningbeam-core/src/path_fitting.rs +++ b/lightningbeam-ui/lightningbeam-core/src/path_fitting.rs @@ -478,7 +478,7 @@ fn map_t_to_relative_distances(bez: &[Point; 4], b_parts: usize) -> Vec { } /// Find t value for a given parameter distance -fn find_t(bez: &[Point; 4], param: f64, t_dist_map: &[f64], b_parts: usize) -> f64 { +fn find_t(_bez: &[Point; 4], param: f64, t_dist_map: &[f64], b_parts: usize) -> f64 { if param < 0.0 { return 0.0; } diff --git a/lightningbeam-ui/lightningbeam-core/src/planar_graph.rs b/lightningbeam-ui/lightningbeam-core/src/planar_graph.rs index b49cd72..f616703 100644 --- a/lightningbeam-ui/lightningbeam-core/src/planar_graph.rs +++ b/lightningbeam-ui/lightningbeam-core/src/planar_graph.rs @@ -122,7 +122,7 @@ impl PlanarGraph { // Initialize with endpoints for all curves for (i, curve) in curves.iter().enumerate() { - let mut curve_intersections = vec![ + let curve_intersections = vec![ (0.0, curve.p0), (1.0, curve.p3), ]; @@ -202,7 +202,7 @@ impl PlanarGraph { /// Build nodes and edges from curves and their intersections fn build_nodes_and_edges( - curves: &[CubicBez], + _curves: &[CubicBez], intersections: HashMap>, ) -> (Vec, Vec) { let mut nodes = Vec::new(); @@ -459,11 +459,6 @@ impl PlanarGraph { // Get the end node of this half-edge let edge = &self.edges[current_edge]; - let start_node_this_edge = if current_forward { - edge.start_node - } else { - edge.end_node - }; let end_node = if current_forward { edge.end_node } else { diff --git a/lightningbeam-ui/lightningbeam-core/src/segment_builder.rs b/lightningbeam-ui/lightningbeam-core/src/segment_builder.rs index 3051e4b..c5ef3ee 100644 --- a/lightningbeam-ui/lightningbeam-core/src/segment_builder.rs +++ b/lightningbeam-ui/lightningbeam-core/src/segment_builder.rs @@ -32,9 +32,9 @@ struct ExtractedSegment { /// Original curve index curve_index: usize, /// Minimum parameter value from boundary points - t_min: f64, + _t_min: f64, /// Maximum parameter value from boundary points - t_max: f64, + _t_max: f64, /// The curve segment (trimmed to [t_min, t_max]) segment: CurveSegment, } @@ -148,8 +148,8 @@ fn split_segments_at_intersections(segments: Vec) -> Vec Option> { if extracted.is_empty() { println!("connect_segments: No segments to connect"); @@ -575,7 +575,7 @@ fn connect_segments( connected.push(ConnectedSegment::Curve { segment: current.segment.clone(), start: current.segment.eval_at(0.0), - end: current_end, + _end: current_end, }); // Check if we need to connect to the next segment @@ -794,7 +794,7 @@ mod tests { // If it found segments, verify they're valid assert!(!segments.is_empty()); for seg in &segments { - assert!(seg.t_min <= seg.t_max); + assert!(seg._t_min <= seg._t_max); } } // If None, the algorithm couldn't form a cycle - that's okay for this test diff --git a/lightningbeam-ui/lightningbeam-core/src/video.rs b/lightningbeam-ui/lightningbeam-core/src/video.rs index 084e818..555dcdb 100644 --- a/lightningbeam-ui/lightningbeam-core/src/video.rs +++ b/lightningbeam-ui/lightningbeam-core/src/video.rs @@ -23,12 +23,12 @@ pub struct VideoMetadata { /// Video decoder with LRU frame caching pub struct VideoDecoder { path: String, - width: u32, // Original video width - height: u32, // Original video height + _width: u32, // Original video width + _height: u32, // Original video height output_width: u32, // Scaled output width output_height: u32, // Scaled output height fps: f64, - duration: f64, + _duration: f64, time_base: f64, stream_index: usize, frame_cache: LruCache>, // timestamp -> RGBA data @@ -107,12 +107,12 @@ impl VideoDecoder { Ok(Self { path, - width, - height, + _width: width, + _height: height, output_width, output_height, fps, - duration, + _duration: duration, time_base, stream_index, frame_cache: LruCache::new( diff --git a/lightningbeam-ui/lightningbeam-editor/src/effect_thumbnails.rs b/lightningbeam-ui/lightningbeam-editor/src/effect_thumbnails.rs index 7099ca5..698b4a9 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/effect_thumbnails.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/effect_thumbnails.rs @@ -4,7 +4,7 @@ //! using the actual WGSL shaders. use lightningbeam_core::effect::{EffectDefinition, EffectInstance}; -use lightningbeam_core::gpu::effect_processor::{EffectProcessor, EffectUniforms}; +use lightningbeam_core::gpu::effect_processor::EffectProcessor; use std::collections::HashMap; use uuid::Uuid; @@ -19,6 +19,7 @@ pub struct EffectThumbnailGenerator { /// Effect processor for compiling and applying shaders effect_processor: EffectProcessor, /// Source texture (still-life image scaled to thumbnail size) + #[allow(dead_code)] // Must stay alive โ€” source_view is a view into this texture source_texture: wgpu::Texture, /// View of the source texture source_view: wgpu::TextureView, @@ -101,7 +102,7 @@ impl EffectThumbnailGenerator { let dest_view = dest_texture.create_view(&wgpu::TextureViewDescriptor::default()); // Create readback buffer - let buffer_size = (EFFECT_THUMBNAIL_SIZE * EFFECT_THUMBNAIL_SIZE * 4) as u64; + let _buffer_size = (EFFECT_THUMBNAIL_SIZE * EFFECT_THUMBNAIL_SIZE * 4) as u64; // Align to 256 bytes for wgpu requirements let aligned_bytes_per_row = ((EFFECT_THUMBNAIL_SIZE * 4 + 255) / 256) * 256; let readback_buffer = device.create_buffer(&wgpu::BufferDescriptor { @@ -160,11 +161,13 @@ impl EffectThumbnailGenerator { } /// Get a cached thumbnail, or None if not yet generated + #[allow(dead_code)] pub fn get_thumbnail(&self, effect_id: &Uuid) -> Option<&Vec> { self.thumbnail_cache.get(effect_id) } /// Check if a thumbnail is cached + #[allow(dead_code)] pub fn has_thumbnail(&self, effect_id: &Uuid) -> bool { self.thumbnail_cache.contains_key(effect_id) } diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/audio_exporter.rs b/lightningbeam-ui/lightningbeam-editor/src/export/audio_exporter.rs index a8ca034..b3b75a3 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/audio_exporter.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/audio_exporter.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] //! Audio export functionality //! //! Exports audio from the timeline to various formats: @@ -168,7 +169,7 @@ fn export_audio_ffmpeg_mp3>( // Step 3: Encode frames and write to output // Convert interleaved f32 samples to planar i16 format let num_frames = pcm_samples.len() / settings.channels as usize; - let mut planar_samples = convert_to_planar_i16(&pcm_samples, settings.channels); + let planar_samples = convert_to_planar_i16(&pcm_samples, settings.channels); // Get encoder frame size let frame_size = encoder.frame_size(); diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs b/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs index d099073..5317be4 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs @@ -182,7 +182,7 @@ impl ExportDialog { ("Podcast AAC", AudioExportSettings::podcast_aac()), ]; - egui::ComboBox::from_id_source("export_preset") + egui::ComboBox::from_id_salt("export_preset") .selected_text(presets[self.selected_audio_preset].0) .show_ui(ui, |ui| { for (i, (name, _)) in presets.iter().enumerate() { @@ -207,7 +207,7 @@ impl ExportDialog { ui.heading("Format"); ui.horizontal(|ui| { ui.label("Format:"); - egui::ComboBox::from_id_source("audio_format") + egui::ComboBox::from_id_salt("audio_format") .selected_text(self.audio_settings.format.name()) .show_ui(ui, |ui| { ui.selectable_value(&mut self.audio_settings.format, AudioFormat::Wav, "WAV (Uncompressed)"); @@ -222,7 +222,7 @@ impl ExportDialog { // Audio settings ui.horizontal(|ui| { ui.label("Sample Rate:"); - egui::ComboBox::from_id_source("sample_rate") + egui::ComboBox::from_id_salt("sample_rate") .selected_text(format!("{} Hz", self.audio_settings.sample_rate)) .show_ui(ui, |ui| { ui.selectable_value(&mut self.audio_settings.sample_rate, 44100, "44100 Hz"); @@ -251,7 +251,7 @@ impl ExportDialog { if self.audio_settings.format.uses_bitrate() { ui.horizontal(|ui| { ui.label("Bitrate:"); - egui::ComboBox::from_id_source("bitrate") + egui::ComboBox::from_id_salt("bitrate") .selected_text(format!("{} kbps", self.audio_settings.bitrate_kbps)) .show_ui(ui, |ui| { ui.selectable_value(&mut self.audio_settings.bitrate_kbps, 128, "128 kbps"); @@ -269,7 +269,7 @@ impl ExportDialog { ui.heading("Codec"); ui.horizontal(|ui| { ui.label("Codec:"); - egui::ComboBox::from_id_source("video_codec") + egui::ComboBox::from_id_salt("video_codec") .selected_text(format!("{:?}", self.video_settings.codec)) .show_ui(ui, |ui| { ui.selectable_value(&mut self.video_settings.codec, VideoCodec::H264, "H.264 (Most Compatible)"); @@ -287,13 +287,13 @@ impl ExportDialog { ui.horizontal(|ui| { ui.label("Width:"); let mut custom_width = self.video_settings.width.unwrap_or(1920); - if ui.add(egui::DragValue::new(&mut custom_width).clamp_range(1..=7680)).changed() { + if ui.add(egui::DragValue::new(&mut custom_width).range(1..=7680)).changed() { self.video_settings.width = Some(custom_width); } ui.label("Height:"); let mut custom_height = self.video_settings.height.unwrap_or(1080); - if ui.add(egui::DragValue::new(&mut custom_height).clamp_range(1..=4320)).changed() { + if ui.add(egui::DragValue::new(&mut custom_height).range(1..=4320)).changed() { self.video_settings.height = Some(custom_height); } }); @@ -320,7 +320,7 @@ impl ExportDialog { ui.heading("Framerate"); ui.horizontal(|ui| { ui.label("FPS:"); - egui::ComboBox::from_id_source("framerate") + egui::ComboBox::from_id_salt("framerate") .selected_text(format!("{}", self.video_settings.framerate as u32)) .show_ui(ui, |ui| { ui.selectable_value(&mut self.video_settings.framerate, 24.0, "24"); @@ -335,7 +335,7 @@ impl ExportDialog { ui.heading("Quality"); ui.horizontal(|ui| { ui.label("Quality:"); - egui::ComboBox::from_id_source("video_quality") + egui::ComboBox::from_id_salt("video_quality") .selected_text(self.video_settings.quality.name()) .show_ui(ui, |ui| { ui.selectable_value(&mut self.video_settings.quality, VideoQuality::Low, VideoQuality::Low.name()); @@ -363,13 +363,13 @@ impl ExportDialog { ui.label("Start:"); ui.add(egui::DragValue::new(start_time) .speed(0.1) - .clamp_range(0.0..=*end_time) + .range(0.0..=*end_time) .suffix(" s")); ui.label("End:"); ui.add(egui::DragValue::new(end_time) .speed(0.1) - .clamp_range(*start_time..=f64::MAX) + .range(*start_time..=f64::MAX) .suffix(" s")); }); diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs index adafe96..255d7d4 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs @@ -42,6 +42,7 @@ pub struct VideoExportState { /// Start time in seconds start_time: f64, /// End time in seconds + #[allow(dead_code)] end_time: f64, /// Frames per second framerate: f64, @@ -163,7 +164,7 @@ impl ExportOrchestrator { /// For parallel video+audio exports, returns combined progress. pub fn poll_progress(&mut self) -> Option { // Handle parallel video+audio export - if let Some(ref mut parallel) = self.parallel_export { + if let Some(ref mut _parallel) = self.parallel_export { return self.poll_parallel_progress(); } @@ -461,6 +462,7 @@ impl ExportOrchestrator { /// Wait for the export to complete /// /// This blocks until the export thread finishes. + #[allow(dead_code)] pub fn wait_for_completion(&mut self) { if let Some(handle) = self.thread_handle.take() { handle.join().ok(); @@ -915,7 +917,7 @@ impl ExportOrchestrator { } // Render to GPU (timed) - let render_start = Instant::now(); + let _render_start = Instant::now(); let encoder = video_exporter::render_frame_to_gpu_rgba( document, timestamp, width, height, device, queue, renderer, image_cache, video_manager, @@ -1049,7 +1051,7 @@ impl ExportOrchestrator { // Determine dimensions from first frame let (width, height) = if let Some((_, _, ref y_plane, _, _)) = first_frame { // Calculate dimensions from Y plane size (full resolution, 1 byte per pixel) - let pixel_count = y_plane.len(); + let _pixel_count = y_plane.len(); // Use settings dimensions if provided, otherwise infer from buffer let w = settings.width.unwrap_or(1920); // Default to 1920 if not specified let h = settings.height.unwrap_or(1080); // Default to 1080 if not specified @@ -1088,7 +1090,7 @@ impl ExportOrchestrator { println!("๐Ÿงต [ENCODER] Encoder initialized, ready to encode frames"); // Process first frame - if let Some((frame_num, timestamp, y_plane, u_plane, v_plane)) = first_frame { + if let Some((_frame_num, timestamp, y_plane, u_plane, v_plane)) = first_frame { Self::encode_frame( &mut encoder, &mut output, @@ -1115,7 +1117,7 @@ impl ExportOrchestrator { } match frame_rx.recv() { - Ok(VideoFrameMessage::Frame { frame_num, timestamp, y_plane, u_plane, v_plane }) => { + Ok(VideoFrameMessage::Frame { frame_num: _, timestamp, y_plane, u_plane, v_plane }) => { Self::encode_frame( &mut encoder, &mut output, diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/readback_pipeline.rs b/lightningbeam-ui/lightningbeam-editor/src/export/readback_pipeline.rs index 8668891..727bce6 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/readback_pipeline.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/readback_pipeline.rs @@ -216,7 +216,7 @@ impl ReadbackPipeline { /// Call this frequently to process completed transfers. pub fn poll_nonblocking(&mut self) -> Vec { // Poll GPU without blocking - self.device.poll(wgpu::PollType::Poll); + let _ = self.device.poll(wgpu::PollType::Poll); // Collect all completed readbacks let mut results = Vec::new(); @@ -269,13 +269,14 @@ impl ReadbackPipeline { /// Flush pipeline and wait for all pending operations /// /// Call this at the end of export to ensure all frames are processed + #[allow(dead_code)] pub fn flush(&mut self) -> Vec { let mut all_results = Vec::new(); // Keep polling until all buffers are Free loop { // Poll for new completions - self.device.poll(wgpu::PollType::Poll); + let _ = self.device.poll(wgpu::PollType::Poll); while let Ok(result) = self.readback_rx.try_recv() { self.buffers[result.buffer_id].state = BufferState::Mapped; @@ -310,8 +311,4 @@ impl ReadbackPipeline { all_results } - /// Get buffer count currently in flight (for monitoring) - pub fn buffers_in_flight(&self) -> usize { - self.buffers.iter().filter(|b| b.state != BufferState::Free).count() - } } diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/video_exporter.rs b/lightningbeam-ui/lightningbeam-editor/src/export/video_exporter.rs index d8263fc..3df3059 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/video_exporter.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/video_exporter.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] //! Video export functionality //! //! Exports video from the timeline using FFmpeg encoding: diff --git a/lightningbeam-ui/lightningbeam-editor/src/main.rs b/lightningbeam-ui/lightningbeam-editor/src/main.rs index 88414e4..8d34909 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/main.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/main.rs @@ -403,6 +403,7 @@ enum FileCommand { } /// Progress updates from file operations worker +#[allow(dead_code)] // EncodingAudio/DecodingAudio planned for granular progress reporting enum FileProgress { SerializingAudioPool, EncodingAudio { current: usize, total: usize }, @@ -428,6 +429,7 @@ enum FileOperation { /// Information about an imported asset (for auto-placement) #[derive(Debug, Clone)] +#[allow(dead_code)] // name/duration populated for future import UX features struct ImportedAssetInfo { clip_id: uuid::Uuid, clip_type: panes::DragClipType, @@ -619,6 +621,7 @@ enum RecordingArmMode { #[default] Auto, /// User explicitly arms tracks (multi-track recording workflow) + #[allow(dead_code)] Manual, } @@ -650,12 +653,15 @@ struct EditorApp { rdp_tolerance: f64, // RDP simplification tolerance (default: 10.0) schneider_max_error: f64, // Schneider curve fitting max error (default: 30.0) // Audio engine integration - audio_stream: Option, // Audio stream (must be kept alive) - audio_controller: Option>>, // Shared audio controller - audio_event_rx: Option>, // Audio event receiver - audio_events_pending: std::sync::Arc, // Flag set when audio events arrive - audio_sample_rate: u32, // Audio sample rate - audio_channels: u32, // Audio channel count + #[allow(dead_code)] // Must be kept alive to maintain audio output + audio_stream: Option, + audio_controller: Option>>, + audio_event_rx: Option>, + audio_events_pending: std::sync::Arc, + #[allow(dead_code)] // Stored for future export/recording configuration + audio_sample_rate: u32, + #[allow(dead_code)] + audio_channels: u32, // Video decoding and management video_manager: std::sync::Arc>, // Shared video manager // Track ID mapping (Document layer UUIDs <-> daw-backend TrackIds) @@ -667,8 +673,10 @@ struct EditorApp { playback_time: f64, // Current playback position in seconds (persistent - save with document) is_playing: bool, // Whether playback is currently active (transient - don't save) // Recording state - recording_arm_mode: RecordingArmMode, // How tracks are armed for recording - armed_layers: HashSet, // Explicitly armed layers (used in Manual mode) + #[allow(dead_code)] // Infrastructure for Manual recording mode + recording_arm_mode: RecordingArmMode, + #[allow(dead_code)] + armed_layers: HashSet, is_recording: bool, // Whether recording is currently active recording_clips: HashMap, // layer_id -> backend clip_id during recording recording_start_time: f64, // Playback time when recording started @@ -942,7 +950,7 @@ impl EditorApp { egui::vec2(content_width, content_height), ); - ui.allocate_ui_at_rect(content_rect, |ui| { + ui.scope_builder(egui::UiBuilder::new().max_rect(content_rect), |ui| { ui.vertical_centered(|ui| { // Title ui.heading(egui::RichText::new("Welcome to Lightningbeam!") @@ -1472,10 +1480,6 @@ impl EditorApp { self.pane_instances.clear(); } - fn current_layout_def(&self) -> &LayoutDefinition { - &self.layouts[self.current_layout_index] - } - fn apply_layout_action(&mut self, action: LayoutAction) { match action { LayoutAction::SplitHorizontal(path, percent) => { @@ -2511,7 +2515,7 @@ impl EditorApp { }; // Create video clip with real metadata - let mut clip = VideoClip::new( + let clip = VideoClip::new( &name, path_str.clone(), metadata.width as f64, @@ -3776,12 +3780,11 @@ impl eframe::App for EditorApp { // Poll export orchestrator for progress if let Some(orchestrator) = &mut self.export_orchestrator { // Only log occasionally to avoid spam - static mut POLL_COUNT: u32 = 0; - unsafe { - POLL_COUNT += 1; - if POLL_COUNT % 60 == 0 { - println!("๐Ÿ” [MAIN] Polling orchestrator (poll #{})...", POLL_COUNT); - } + use std::sync::atomic::{AtomicU32, Ordering as AtomicOrdering}; + static POLL_COUNT: AtomicU32 = AtomicU32::new(0); + let count = POLL_COUNT.fetch_add(1, AtomicOrdering::Relaxed) + 1; + if count % 60 == 0 { + println!("๐Ÿ” [MAIN] Polling orchestrator (poll #{})...", count); } if let Some(progress) = orchestrator.poll_progress() { match progress { @@ -4275,12 +4278,12 @@ fn render_layout_node( if ui.button("Split Horizontal ->").clicked() { *layout_action = Some(LayoutAction::EnterSplitPreviewHorizontal); - ui.close_menu(); + ui.close(); } if ui.button("Split Vertical |").clicked() { *layout_action = Some(LayoutAction::EnterSplitPreviewVertical); - ui.close_menu(); + ui.close(); } ui.separator(); @@ -4289,14 +4292,14 @@ fn render_layout_node( let mut path_keep_right = path.clone(); path_keep_right.push(1); // Remove left, keep right child *layout_action = Some(LayoutAction::RemoveSplit(path_keep_right)); - ui.close_menu(); + ui.close(); } if ui.button("Join Right >").clicked() { let mut path_keep_left = path.clone(); path_keep_left.push(0); // Remove right, keep left child *layout_action = Some(LayoutAction::RemoveSplit(path_keep_left)); - ui.close_menu(); + ui.close(); } }); @@ -4397,12 +4400,12 @@ fn render_layout_node( if ui.button("Split Horizontal ->").clicked() { *layout_action = Some(LayoutAction::EnterSplitPreviewHorizontal); - ui.close_menu(); + ui.close(); } if ui.button("Split Vertical |").clicked() { *layout_action = Some(LayoutAction::EnterSplitPreviewVertical); - ui.close_menu(); + ui.close(); } ui.separator(); @@ -4411,14 +4414,14 @@ fn render_layout_node( let mut path_keep_bottom = path.clone(); path_keep_bottom.push(1); // Remove top, keep bottom child *layout_action = Some(LayoutAction::RemoveSplit(path_keep_bottom)); - ui.close_menu(); + ui.close(); } if ui.button("Join Down v").clicked() { let mut path_keep_top = path.clone(); path_keep_top.push(0); // Remove bottom, keep top child *layout_action = Some(LayoutAction::RemoveSplit(path_keep_top)); - ui.close_menu(); + ui.close(); } }); @@ -4828,100 +4831,6 @@ fn render_pane( } } -/// Render toolbar with tool buttons -fn render_toolbar( - ui: &mut egui::Ui, - rect: egui::Rect, - tool_icon_cache: &mut ToolIconCache, - selected_tool: &mut Tool, - path: &NodePath, -) { - let button_size = 60.0; // 50% bigger (was 40.0) - let button_padding = 8.0; - let button_spacing = 4.0; - - // Calculate how many columns we can fit - let available_width = rect.width() - (button_padding * 2.0); - let columns = ((available_width + button_spacing) / (button_size + button_spacing)).floor() as usize; - let columns = columns.max(1); // At least 1 column - - let mut x = rect.left() + button_padding; - let mut y = rect.top() + button_padding; - let mut col = 0; - - for tool in Tool::all() { - let button_rect = egui::Rect::from_min_size( - egui::pos2(x, y), - egui::vec2(button_size, button_size), - ); - - // Check if this is the selected tool - let is_selected = *selected_tool == *tool; - - // Button background - let bg_color = if is_selected { - egui::Color32::from_rgb(70, 100, 150) // Highlighted blue - } else { - egui::Color32::from_rgb(50, 50, 50) - }; - ui.painter().rect_filled(button_rect, 4.0, bg_color); - - // Load and render tool icon - if let Some(icon) = tool_icon_cache.get_or_load(*tool, ui.ctx()) { - let icon_rect = button_rect.shrink(8.0); // Padding inside button - ui.painter().image( - icon.id(), - icon_rect, - egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)), - egui::Color32::WHITE, - ); - } - - // Make button interactive (include path to ensure unique IDs across panes) - let button_id = ui.id().with(("tool_button", path, *tool as usize)); - let response = ui.interact(button_rect, button_id, egui::Sense::click()); - - // Check for click first - if response.clicked() { - *selected_tool = *tool; - } - - if response.hovered() { - ui.painter().rect_stroke( - button_rect, - 4.0, - egui::Stroke::new(2.0, egui::Color32::from_gray(180)), - egui::StrokeKind::Middle, - ); - } - - // Show tooltip with tool name and shortcut (consumes response) - response.on_hover_text(format!("{} ({})", tool.display_name(), tool.shortcut_hint())); - - // Draw selection border - if is_selected { - ui.painter().rect_stroke( - button_rect, - 4.0, - egui::Stroke::new(2.0, egui::Color32::from_rgb(100, 150, 255)), - egui::StrokeKind::Middle, - ); - } - - // Move to next position in grid - col += 1; - if col >= columns { - // Move to next row - col = 0; - x = rect.left() + button_padding; - y += button_size + button_spacing; - } else { - // Move to next column - x += button_size + button_spacing; - } - } -} - /// Get a color for each pane type for visualization fn pane_color(pane_type: PaneType) -> egui::Color32 { match pane_type { diff --git a/lightningbeam-ui/lightningbeam-editor/src/menu.rs b/lightningbeam-ui/lightningbeam-editor/src/menu.rs index 95b0337..535ec0c 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/menu.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/menu.rs @@ -29,7 +29,9 @@ pub enum ShortcutKey { // Numbers Num0, // Symbols - Comma, Minus, Equals, Plus, + Comma, Minus, Equals, + #[allow(dead_code)] // Completes keyboard mapping set + Plus, BracketLeft, BracketRight, // Special Delete, @@ -189,6 +191,7 @@ pub enum MenuAction { RecenterView, NextLayout, PreviousLayout, + #[allow(dead_code)] // Handler exists in main.rs, menu item not yet wired SwitchLayout(usize), // Help menu @@ -219,6 +222,7 @@ pub enum MenuDef { // Shortcut constants for clarity const CTRL: bool = true; const SHIFT: bool = true; +#[allow(dead_code)] const ALT: bool = true; const NO_CTRL: bool = false; const NO_SHIFT: bool = false; @@ -288,7 +292,9 @@ impl MenuItemDef { // macOS app menu items const SETTINGS: Self = Self { label: "Settings", action: MenuAction::Settings, shortcut: Some(Shortcut::new(ShortcutKey::Comma, CTRL, NO_SHIFT, NO_ALT)) }; const CLOSE_WINDOW: Self = Self { label: "Close Window", action: MenuAction::CloseWindow, shortcut: Some(Shortcut::new(ShortcutKey::W, CTRL, NO_SHIFT, NO_ALT)) }; + #[allow(dead_code)] // Used in #[cfg(target_os = "macos")] block const QUIT_MACOS: Self = Self { label: "Quit Lightningbeam", action: MenuAction::Quit, shortcut: Some(Shortcut::new(ShortcutKey::Q, CTRL, NO_SHIFT, NO_ALT)) }; + #[allow(dead_code)] const ABOUT_MACOS: Self = Self { label: "About Lightningbeam", action: MenuAction::About, shortcut: None }; /// Get all menu items with shortcuts (for keyboard handling) @@ -593,7 +599,7 @@ impl MenuSystem { pub fn render_egui_menu_bar(&self, ui: &mut egui::Ui, recent_files: &[std::path::PathBuf]) -> Option { let mut action = None; - egui::menu::bar(ui, |ui| { + egui::MenuBar::new().ui(ui, |ui| { for menu_def in MenuItemDef::menu_structure() { if let Some(a) = self.render_menu_def(ui, menu_def, recent_files) { action = Some(a); @@ -632,7 +638,7 @@ impl MenuSystem { if ui.button(display_name).clicked() { action = Some(MenuAction::OpenRecent(index)); - ui.close_menu(); + ui.close(); } } @@ -643,14 +649,14 @@ impl MenuSystem { if ui.button("Clear Recent Files").clicked() { action = Some(MenuAction::ClearRecentFiles); - ui.close_menu(); + ui.close(); } } else { // Normal submenu rendering for child in *children { if let Some(a) = self.render_menu_def(ui, child, recent_files) { action = Some(a); - ui.close_menu(); + ui.close(); } } } diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs index 0bb2c79..74696c9 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/asset_library.rs @@ -62,6 +62,7 @@ const SEARCH_BAR_HEIGHT: f32 = 30.0; const CATEGORY_TAB_HEIGHT: f32 = 28.0; const BREADCRUMB_HEIGHT: f32 = 24.0; const ITEM_HEIGHT: f32 = 40.0; +#[allow(dead_code)] const ITEM_PADDING: f32 = 4.0; const LIST_THUMBNAIL_SIZE: f32 = 32.0; const GRID_ITEM_SIZE: f32 = 80.0; @@ -137,6 +138,7 @@ impl ThumbnailCache { } /// Check if a thumbnail is already cached (and not dirty) + #[allow(dead_code)] pub fn has(&self, asset_id: &Uuid) -> bool { self.textures.contains_key(asset_id) && !self.dirty.contains(asset_id) } @@ -146,11 +148,6 @@ impl ThumbnailCache { self.dirty.insert(*asset_id); } - /// Clear all cached thumbnails - pub fn clear(&mut self) { - self.textures.clear(); - self.dirty.clear(); - } } // ============================================================================ @@ -285,7 +282,7 @@ fn generate_waveform_thumbnail( // Draw waveform let center_y = size / 2; - let num_peaks = waveform_peaks.len().min(size); + let _num_peaks = waveform_peaks.len().min(size); for (x, &(min_val, max_val)) in waveform_peaks.iter().take(size).enumerate() { // Scale peaks to pixel range (center ยฑ half height) @@ -552,6 +549,7 @@ fn shape_color_to_tiny_skia(color: &ShapeColor) -> tiny_skia::Color { } /// Generate a simple effect thumbnail with a pink gradient +#[allow(dead_code)] fn generate_effect_thumbnail() -> Vec { let size = THUMBNAIL_SIZE as usize; let mut rgba = vec![0u8; size * size * 4]; @@ -628,6 +626,7 @@ fn generate_effect_thumbnail() -> Vec { } /// Ellipsize a string to fit within a maximum character count +#[allow(dead_code)] fn ellipsize(s: &str, max_chars: usize) -> String { if s.chars().count() <= max_chars { s.to_string() @@ -706,6 +705,7 @@ pub struct AssetEntry { pub struct FolderEntry { pub id: Uuid, pub name: String, + #[allow(dead_code)] pub category: AssetCategory, pub item_count: usize, } @@ -718,6 +718,7 @@ pub enum LibraryItem { } impl LibraryItem { + #[allow(dead_code)] pub fn id(&self) -> Uuid { match self { LibraryItem::Folder(f) => f.id, @@ -810,6 +811,7 @@ pub struct AssetLibraryPane { current_folders: HashMap>, /// Set of expanded folder IDs (for tree view - future enhancement) + #[allow(dead_code)] expanded_folders: HashSet, /// Cached folder icon texture @@ -1283,6 +1285,7 @@ impl AssetLibraryPane { } /// Filter assets based on current category and search text + #[allow(dead_code)] fn filter_assets<'a>(&self, assets: &'a [AssetEntry]) -> Vec<&'a AssetEntry> { let search_lower = self.search_filter.to_lowercase(); @@ -1727,6 +1730,7 @@ impl AssetLibraryPane { } /// Render a section header for effect categories + #[allow(dead_code)] // Part of List/Grid view rendering subsystem, not yet wired fn render_section_header(ui: &mut egui::Ui, label: &str, color: egui::Color32) { ui.add_space(4.0); let (header_rect, _) = ui.allocate_exact_size( @@ -1744,7 +1748,7 @@ impl AssetLibraryPane { } /// Render a grid of asset items - #[allow(clippy::too_many_arguments)] + #[allow(clippy::too_many_arguments, dead_code)] fn render_grid_items( &mut self, ui: &mut egui::Ui, @@ -1755,7 +1759,7 @@ impl AssetLibraryPane { shared: &mut SharedPaneState, document: &Document, text_color: egui::Color32, - secondary_text_color: egui::Color32, + _secondary_text_color: egui::Color32, ) { if assets.is_empty() { return; @@ -2003,7 +2007,7 @@ impl AssetLibraryPane { &mut self, ui: &mut egui::Ui, rect: egui::Rect, - path: &NodePath, + _path: &NodePath, shared: &mut SharedPaneState, items: &[&LibraryItem], document: &Document, @@ -2012,7 +2016,7 @@ impl AssetLibraryPane { let folder_icon = self.get_folder_icon(ui.ctx()).cloned(); let _scroll_area = egui::ScrollArea::vertical() - .id_source("asset_library_scroll") + .id_salt("asset_library_scroll") .show_viewport(ui, |ui, viewport| { ui.set_min_width(rect.width()); @@ -2171,7 +2175,7 @@ impl AssetLibraryPane { // Load folder icon if needed let folder_icon = self.get_folder_icon(ui.ctx()).cloned(); - ui.allocate_new_ui(egui::UiBuilder::new().max_rect(rect), |ui| { + ui.scope_builder(egui::UiBuilder::new().max_rect(rect), |ui| { egui::ScrollArea::vertical() .id_salt(("asset_library_grid_scroll", path)) .auto_shrink([false, false]) @@ -2661,6 +2665,7 @@ impl AssetLibraryPane { } /// Render assets based on current view mode + #[allow(dead_code)] fn render_assets( &mut self, ui: &mut egui::Ui, @@ -2681,6 +2686,7 @@ impl AssetLibraryPane { } /// Render the asset list view + #[allow(dead_code)] fn render_asset_list_view( &mut self, ui: &mut egui::Ui, @@ -2724,7 +2730,7 @@ impl AssetLibraryPane { // Use egui's built-in ScrollArea for scrolling let scroll_area_rect = rect; - ui.allocate_new_ui(egui::UiBuilder::new().max_rect(scroll_area_rect), |ui| { + ui.scope_builder(egui::UiBuilder::new().max_rect(scroll_area_rect), |ui| { egui::ScrollArea::vertical() .id_salt(("asset_list_scroll", path)) .auto_shrink([false, false]) @@ -2757,7 +2763,7 @@ impl AssetLibraryPane { }; let mut rendered_builtin_header = false; let mut rendered_custom_header = false; - let mut builtin_rendered = 0; + let mut _builtin_rendered = 0; for asset in assets_to_render { // Render section headers for Effects tab @@ -2781,7 +2787,7 @@ impl AssetLibraryPane { rendered_custom_header = true; } if asset.is_builtin { - builtin_rendered += 1; + _builtin_rendered += 1; } } @@ -3093,6 +3099,7 @@ impl AssetLibraryPane { } /// Render the asset grid view + #[allow(dead_code)] fn render_asset_grid_view( &mut self, ui: &mut egui::Ui, @@ -3165,7 +3172,7 @@ impl AssetLibraryPane { 0 }; - ui.allocate_new_ui(egui::UiBuilder::new().max_rect(rect), |ui| { + ui.scope_builder(egui::UiBuilder::new().max_rect(rect), |ui| { egui::ScrollArea::vertical() .id_salt(("asset_grid_scroll", path)) .auto_shrink([false, false]) diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs index 3c49a04..652b7f5 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs @@ -47,6 +47,7 @@ pub struct DraggingAsset { /// Display name pub name: String, /// Duration in seconds + #[allow(dead_code)] // Populated during drag, consumed when drag-and-drop features expand pub duration: f64, /// Dimensions (width, height) for vector/video clips, None for audio pub dimensions: Option<(f64, f64)>, @@ -132,6 +133,7 @@ pub fn find_sampled_audio_track(document: &lightningbeam_core::document::Documen /// Shared state that all panes can access pub struct SharedPaneState<'a> { pub tool_icon_cache: &'a mut crate::ToolIconCache, + #[allow(dead_code)] // Used by pane chrome rendering in main.rs pub icon_cache: &'a mut crate::IconCache, pub selected_tool: &'a mut Tool, pub fill_color: &'a mut egui::Color32, @@ -220,7 +222,7 @@ pub trait PaneRenderer { /// Render the optional header section with controls /// /// Returns true if a header was rendered, false if no header - fn render_header(&mut self, ui: &mut egui::Ui, shared: &mut SharedPaneState) -> bool { + fn render_header(&mut self, _ui: &mut egui::Ui, _shared: &mut SharedPaneState) -> bool { false // Default: no header } @@ -234,6 +236,7 @@ pub trait PaneRenderer { ); /// Get the display name of this pane + #[allow(dead_code)] // Implemented by all panes, dispatch infrastructure complete fn name(&self) -> &str; } diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/actions.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/actions.rs index 0963a12..d4e3e00 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/actions.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/actions.rs @@ -15,6 +15,7 @@ use uuid::Uuid; pub enum NodeGraphAction { AddNode(AddNodeAction), RemoveNode(RemoveNodeAction), + #[allow(dead_code)] MoveNode(MoveNodeAction), Connect(ConnectAction), Disconnect(DisconnectAction), @@ -240,6 +241,7 @@ impl RemoveNodeAction { // MoveNodeAction // ============================================================================ +#[allow(dead_code)] pub struct MoveNodeAction { layer_id: Uuid, backend_node_id: BackendNodeId, @@ -248,6 +250,7 @@ pub struct MoveNodeAction { } impl MoveNodeAction { + #[allow(dead_code)] pub fn new(layer_id: Uuid, backend_node_id: BackendNodeId, new_position: (f32, f32)) -> Self { Self { layer_id, diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/audio_backend.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/audio_backend.rs index acddee6..17f7801 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/audio_backend.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/audio_backend.rs @@ -17,8 +17,8 @@ pub struct AudioGraphBackend { audio_controller: Arc>, /// Maps backend NodeIndex to stable IDs for round-trip serialization - node_index_to_stable: HashMap, - next_stable_id: u32, + _node_index_to_stable: HashMap, + _next_stable_id: u32, } impl AudioGraphBackend { @@ -26,8 +26,8 @@ impl AudioGraphBackend { Self { track_id, audio_controller, - node_index_to_stable: HashMap::new(), - next_stable_id: 0, + _node_index_to_stable: HashMap::new(), + _next_stable_id: 0, } } } @@ -41,25 +41,23 @@ impl GraphBackend for AudioGraphBackend { // Generate placeholder node ID // This will be replaced with actual backend NodeIndex from sync query - let stable_id = self.next_stable_id; - self.next_stable_id += 1; + let stable_id = self._next_stable_id; + self._next_stable_id += 1; // Placeholder: use stable_id as backend index (will be wrong, but compiles) let node_idx = NodeIndex::new(stable_id as usize); - self.node_index_to_stable.insert(node_idx, stable_id); + self._node_index_to_stable.insert(node_idx, stable_id); Ok(BackendNodeId::Audio(node_idx)) } fn remove_node(&mut self, backend_id: BackendNodeId) -> Result<(), String> { - let BackendNodeId::Audio(node_idx) = backend_id else { - return Err("Invalid backend node type".to_string()); - }; + let BackendNodeId::Audio(node_idx) = backend_id; let mut controller = self.audio_controller.lock().unwrap(); controller.graph_remove_node(self.track_id, node_idx.index() as u32); - self.node_index_to_stable.remove(&node_idx); + self._node_index_to_stable.remove(&node_idx); Ok(()) } @@ -71,12 +69,8 @@ impl GraphBackend for AudioGraphBackend { input_node: BackendNodeId, input_port: usize, ) -> Result<(), String> { - let BackendNodeId::Audio(from_idx) = output_node else { - return Err("Invalid output node type".to_string()); - }; - let BackendNodeId::Audio(to_idx) = input_node else { - return Err("Invalid input node type".to_string()); - }; + let BackendNodeId::Audio(from_idx) = output_node; + let BackendNodeId::Audio(to_idx) = input_node; let mut controller = self.audio_controller.lock().unwrap(); controller.graph_connect( @@ -97,12 +91,8 @@ impl GraphBackend for AudioGraphBackend { input_node: BackendNodeId, input_port: usize, ) -> Result<(), String> { - let BackendNodeId::Audio(from_idx) = output_node else { - return Err("Invalid output node type".to_string()); - }; - let BackendNodeId::Audio(to_idx) = input_node else { - return Err("Invalid input node type".to_string()); - }; + let BackendNodeId::Audio(from_idx) = output_node; + let BackendNodeId::Audio(to_idx) = input_node; let mut controller = self.audio_controller.lock().unwrap(); controller.graph_disconnect( @@ -122,9 +112,7 @@ impl GraphBackend for AudioGraphBackend { param_id: u32, value: f64, ) -> Result<(), String> { - let BackendNodeId::Audio(node_idx) = backend_id else { - return Err("Invalid backend node type".to_string()); - }; + let BackendNodeId::Audio(node_idx) = backend_id; let mut controller = self.audio_controller.lock().unwrap(); controller.graph_set_parameter( @@ -180,9 +168,7 @@ impl GraphBackend for AudioGraphBackend { x: f32, y: f32, ) -> Result { - let BackendNodeId::Audio(allocator_idx) = voice_allocator_id else { - return Err("Invalid voice allocator node type".to_string()); - }; + let BackendNodeId::Audio(allocator_idx) = voice_allocator_id; let mut controller = self.audio_controller.lock().unwrap(); controller.graph_add_node_to_template( @@ -194,8 +180,8 @@ impl GraphBackend for AudioGraphBackend { ); // Placeholder return - let stable_id = self.next_stable_id; - self.next_stable_id += 1; + let stable_id = self._next_stable_id; + self._next_stable_id += 1; let node_idx = NodeIndex::new(stable_id as usize); Ok(BackendNodeId::Audio(node_idx)) @@ -209,15 +195,9 @@ impl GraphBackend for AudioGraphBackend { input_node: BackendNodeId, input_port: usize, ) -> Result<(), String> { - let BackendNodeId::Audio(allocator_idx) = voice_allocator_id else { - return Err("Invalid voice allocator node type".to_string()); - }; - let BackendNodeId::Audio(from_idx) = output_node else { - return Err("Invalid output node type".to_string()); - }; - let BackendNodeId::Audio(to_idx) = input_node else { - return Err("Invalid input node type".to_string()); - }; + let BackendNodeId::Audio(allocator_idx) = voice_allocator_id; + let BackendNodeId::Audio(from_idx) = output_node; + let BackendNodeId::Audio(to_idx) = input_node; let mut controller = self.audio_controller.lock().unwrap(); controller.graph_connect_in_template( diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/backend.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/backend.rs index 2619a9c..de31a5f 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/backend.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/backend.rs @@ -18,6 +18,7 @@ pub enum BackendNodeId { /// Implementations: /// - AudioGraphBackend: Wraps daw_backend::AudioGraph via EngineController /// - VfxGraphBackend (future): GPU-based shader graph +#[allow(dead_code)] pub trait GraphBackend: Send { /// Add a node to the backend graph fn add_node(&mut self, node_type: &str, x: f32, y: f32) -> Result; diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs index 88315e4..d5e3468 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/mod.rs @@ -67,6 +67,7 @@ impl NodeGraphPane { } } + #[allow(dead_code)] pub fn with_track_id( track_id: Uuid, audio_controller: std::sync::Arc>, @@ -207,7 +208,7 @@ impl NodeGraphPane { // Set parameter values for (¶m_id, &value) in &node.parameters { // Find the input param in the graph and set its value - if let Some(node_data) = self.state.graph.nodes.get_mut(frontend_id) { + if let Some(_node_data) = self.state.graph.nodes.get_mut(frontend_id) { // TODO: Set parameter values on the node's input params // This requires matching param_id to the input param by index let _ = (param_id, value); // Silence unused warning for now @@ -428,25 +429,25 @@ impl NodeGraphPane { fn check_parameter_changes(&mut self) { // Check all input parameters for value changes - let mut checked_count = 0; - let mut connection_only_count = 0; - let mut non_float_count = 0; + let mut _checked_count = 0; + let mut _connection_only_count = 0; + let mut _non_float_count = 0; for (input_id, input_param) in &self.state.graph.inputs { // Only check parameters that can have constant values (not ConnectionOnly) if matches!(input_param.kind, InputParamKind::ConnectionOnly) { - connection_only_count += 1; + _connection_only_count += 1; continue; } // Get current value let current_value = match &input_param.value { ValueType::Float { value } => { - checked_count += 1; + _checked_count += 1; *value }, other => { - non_float_count += 1; + _non_float_count += 1; eprintln!("[DEBUG] Non-float parameter type: {:?}", std::mem::discriminant(other)); continue; } @@ -572,7 +573,7 @@ impl crate::panes::PaneRenderer for NodeGraphPane { // Check if track is MIDI or Audio if let Some(audio_controller) = &shared.audio_controller { let is_valid_track = { - let controller = audio_controller.lock().unwrap(); + let _controller = audio_controller.lock().unwrap(); // TODO: Query track type from backend // For now, assume it's valid if we have a track ID mapping true @@ -624,7 +625,7 @@ impl crate::panes::PaneRenderer for NodeGraphPane { let grid_color = grid_style.background_color.unwrap_or(egui::Color32::from_gray(55)); // Allocate the rect and render the graph editor within it - ui.allocate_ui_at_rect(rect, |ui| { + ui.scope_builder(egui::UiBuilder::new().max_rect(rect), |ui| { // Check for scroll input to override library's default zoom behavior // Only handle scroll when mouse is over the node graph area let pointer_over_graph = ui.rect_contains_pointer(rect); @@ -705,8 +706,8 @@ impl crate::panes::PaneRenderer for NodeGraphPane { // Draw menu button in top-left corner let button_pos = rect.min + egui::vec2(8.0, 8.0); - ui.allocate_ui_at_rect( - egui::Rect::from_min_size(button_pos, egui::vec2(100.0, 24.0)), + ui.scope_builder( + egui::UiBuilder::new().max_rect(egui::Rect::from_min_size(button_pos, egui::vec2(100.0, 24.0))), |ui| { if ui.button("โž• Add Node").clicked() { // Open node finder at button's top-left position diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/node_types.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/node_types.rs index 131281c..3a6d325 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/node_types.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/node_types.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] //! Node Type Registry //! //! Defines metadata for all available node types diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/palette.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/palette.rs index e143141..c732e7f 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/palette.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/node_graph/palette.rs @@ -38,7 +38,7 @@ impl NodePalette { .rect_filled(rect, 0.0, egui::Color32::from_rgb(30, 30, 30)); // Create UI within the palette rect - ui.allocate_ui_at_rect(rect, |ui| { + ui.scope_builder(egui::UiBuilder::new().max_rect(rect), |ui| { ui.vertical(|ui| { ui.add_space(8.0); diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/shader_editor.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/shader_editor.rs index 4ca29f3..239efc4 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/shader_editor.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/shader_editor.rs @@ -219,6 +219,7 @@ pub struct ShaderEditorPane { /// The shader source code being edited shader_code: String, /// Whether to show the template selector + #[allow(dead_code)] show_templates: bool, /// Error message from last compilation attempt (if any) compile_error: Option, diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs index 431b464..f679005 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs @@ -6,8 +6,8 @@ use eframe::egui; use lightningbeam_core::action::Action; use lightningbeam_core::clip::ClipInstance; -use lightningbeam_core::gpu::{BufferPool, BufferFormat, BufferSpec, Compositor, EffectProcessor, HDR_FORMAT, SrgbToLinearConverter}; -use lightningbeam_core::layer::{AnyLayer, AudioLayer, AudioLayerType, VideoLayer, VectorLayer}; +use lightningbeam_core::gpu::{BufferPool, BufferFormat, BufferSpec, Compositor, EffectProcessor, SrgbToLinearConverter}; +use lightningbeam_core::layer::{AnyLayer, AudioLayer}; use lightningbeam_core::renderer::RenderedLayerType; use super::{DragClipType, NodePath, PaneRenderer, SharedPaneState}; use std::sync::{Arc, Mutex, OnceLock}; @@ -872,7 +872,7 @@ impl egui_wgpu::CallbackTrait for VelloCallback { } // Also draw selection outlines for clip instances - let clip_instance_count = self.selection.clip_instances().len(); + let _clip_instance_count = self.selection.clip_instances().len(); for &clip_id in self.selection.clip_instances() { if let Some(clip_instance) = vector_layer.clip_instances.iter().find(|ci| ci.id == clip_id) { // Calculate clip-local time @@ -1865,7 +1865,7 @@ impl egui_wgpu::CallbackTrait for VelloCallback { // Clamp to texture bounds if tex_x < width && tex_y < height { // Create a staging buffer to read back the pixel - let bytes_per_pixel = 4; // RGBA8 + let _bytes_per_pixel = 4; // RGBA8 // Align bytes_per_row to 256 (wgpu::COPY_BYTES_PER_ROW_ALIGNMENT) let bytes_per_row_alignment = 256u32; let bytes_per_row = bytes_per_row_alignment; // Single pixel, use minimum alignment @@ -2128,7 +2128,6 @@ impl StagePane { use lightningbeam_core::tool::ToolState; use lightningbeam_core::layer::AnyLayer; use lightningbeam_core::hit_test::{self, hit_test_vector_editing, EditingHitTolerance, VectorEditHit}; - use lightningbeam_core::bezpath_editing::{extract_editable_curves, mold_curve}; use vello::kurbo::{Point, Rect as KurboRect, Affine}; // Check if we have an active vector layer @@ -2618,9 +2617,8 @@ impl StagePane { mouse_pos: vello::kurbo::Point, shared: &mut SharedPaneState, ) { - use lightningbeam_core::bezpath_editing::{mold_curve, rebuild_bezpath}; + use lightningbeam_core::bezpath_editing::mold_curve; use lightningbeam_core::tool::ToolState; - use vello::kurbo::Point; // Clone tool state to get owned values let tool_state = shared.tool_state.clone(); @@ -2799,12 +2797,12 @@ impl StagePane { ui: &mut egui::Ui, response: &egui::Response, world_pos: egui::Vec2, - shift_held: bool, + _shift_held: bool, shared: &mut SharedPaneState, ) { use lightningbeam_core::tool::ToolState; use lightningbeam_core::layer::AnyLayer; - use lightningbeam_core::hit_test::{self, hit_test_vector_editing, EditingHitTolerance, VectorEditHit}; + use lightningbeam_core::hit_test::{hit_test_vector_editing, EditingHitTolerance, VectorEditHit}; use vello::kurbo::{Point, Affine}; // Check if we have an active vector layer @@ -2897,7 +2895,7 @@ impl StagePane { shape_instance_id: uuid::Uuid, curve_index: usize, point_index: u8, - mouse_pos: vello::kurbo::Point, + _mouse_pos: vello::kurbo::Point, active_layer_id: uuid::Uuid, shared: &mut SharedPaneState, ) { @@ -3606,7 +3604,7 @@ impl StagePane { // Mouse drag: add points to path if response.dragged() { - if let ToolState::DrawingPath { points, simplify_mode } = &mut *shared.tool_state { + if let ToolState::DrawingPath { points, simplify_mode: _ } = &mut *shared.tool_state { // Only add point if it's far enough from the last point (reduce noise) const MIN_POINT_DISTANCE: f64 = 2.0; @@ -3760,63 +3758,12 @@ impl StagePane { } } - /// Decompose an affine matrix into transform components - /// Returns (translation_x, translation_y, rotation_deg, scale_x, scale_y, skew_x_deg, skew_y_deg) - fn decompose_affine(affine: kurbo::Affine) -> (f64, f64, f64, f64, f64, f64, f64) { - let coeffs = affine.as_coeffs(); - let a = coeffs[0]; - let b = coeffs[1]; - let c = coeffs[2]; - let d = coeffs[3]; - let e = coeffs[4]; // translation_x - let f = coeffs[5]; // translation_y - - // Extract translation - let tx = e; - let ty = f; - - // Decompose linear part [[a, c], [b, d]] into rotate * scale * skew - // Using QR-like decomposition - - // Extract rotation - let rotation_rad = b.atan2(a); - let cos_r = rotation_rad.cos(); - let sin_r = rotation_rad.sin(); - - // Remove rotation to get scale * skew - // R^(-1) * M where M = [[a, c], [b, d]] - let m11 = a * cos_r + b * sin_r; - let m12 = c * cos_r + d * sin_r; - let m21 = -a * sin_r + b * cos_r; - let m22 = -c * sin_r + d * cos_r; - - // Now [[m11, m12], [m21, m22]] = scale * skew - // scale * skew = [[sx, 0], [0, sy]] * [[1, tan(skew_y)], [tan(skew_x), 1]] - // = [[sx, sx*tan(skew_y)], [sy*tan(skew_x), sy]] - - let scale_x = m11; - let scale_y = m22; - - let skew_x_rad = if scale_y.abs() > 0.001 { (m21 / scale_y).atan() } else { 0.0 }; - let skew_y_rad = if scale_x.abs() > 0.001 { (m12 / scale_x).atan() } else { 0.0 }; - - ( - tx, - ty, - rotation_rad.to_degrees(), - scale_x, - scale_y, - skew_x_rad.to_degrees(), - skew_y_rad.to_degrees(), - ) - } - /// Apply transform preview to objects based on current mouse position fn apply_transform_preview( vector_layer: &mut lightningbeam_core::layer::VectorLayer, mode: &lightningbeam_core::tool::TransformMode, original_transforms: &std::collections::HashMap, - pivot: vello::kurbo::Point, + _pivot: vello::kurbo::Point, start_mouse: vello::kurbo::Point, current_mouse: vello::kurbo::Point, original_bbox: vello::kurbo::Rect, @@ -4784,7 +4731,6 @@ impl StagePane { _ => egui::CursorIcon::Default, }; ui.ctx().set_cursor_icon(cursor); - hovering_handle = true; break; } } @@ -5219,7 +5165,6 @@ impl StagePane { } } } - _ => {} } } } else if let AnyLayer::Video(video_layer) = layer { diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs index 338cf64..684660d 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs @@ -125,6 +125,7 @@ impl TimelinePane { /// Execute a view action with the given parameters /// Called from main.rs after determining this is the best handler + #[allow(dead_code)] // Mirrors StagePane; wiring in main.rs pending (see TODO at view action dispatch) pub fn execute_view_action(&mut self, action: &crate::menu::MenuAction, zoom_center: egui::Vec2) { use crate::menu::MenuAction; match action { @@ -781,7 +782,7 @@ impl TimelinePane { // Mute button // TODO: Replace with SVG icon (volume-up-fill.svg / volume-mute.svg) - let mute_response = ui.allocate_new_ui(egui::UiBuilder::new().max_rect(mute_button_rect), |ui| { + let mute_response = ui.scope_builder(egui::UiBuilder::new().max_rect(mute_button_rect), |ui| { let mute_text = if is_muted { "๐Ÿ”‡" } else { "๐Ÿ”Š" }; let button = egui::Button::new(mute_text) .fill(if is_muted { @@ -805,7 +806,7 @@ impl TimelinePane { // Solo button // TODO: Replace with SVG headphones icon - let solo_response = ui.allocate_new_ui(egui::UiBuilder::new().max_rect(solo_button_rect), |ui| { + let solo_response = ui.scope_builder(egui::UiBuilder::new().max_rect(solo_button_rect), |ui| { let button = egui::Button::new("๐ŸŽง") .fill(if is_soloed { egui::Color32::from_rgba_unmultiplied(100, 200, 100, 100) @@ -828,7 +829,7 @@ impl TimelinePane { // Lock button // TODO: Replace with SVG lock/lock-open icons - let lock_response = ui.allocate_new_ui(egui::UiBuilder::new().max_rect(lock_button_rect), |ui| { + let lock_response = ui.scope_builder(egui::UiBuilder::new().max_rect(lock_button_rect), |ui| { let lock_text = if is_locked { "๐Ÿ”’" } else { "๐Ÿ”“" }; let button = egui::Button::new(lock_text) .fill(if is_locked { @@ -851,7 +852,7 @@ impl TimelinePane { } // Volume slider (nonlinear: 0-70% slider = 0-100% volume, 70-100% slider = 100-200% volume) - let volume_response = ui.allocate_new_ui(egui::UiBuilder::new().max_rect(volume_slider_rect), |ui| { + let volume_response = ui.scope_builder(egui::UiBuilder::new().max_rect(volume_slider_rect), |ui| { // Map volume (0.0-2.0) to slider position (0.0-1.0) let slider_value = if current_volume <= 1.0 { // 0.0-1.0 volume maps to 0.0-0.7 slider (70%) @@ -1217,7 +1218,7 @@ impl TimelinePane { if let Some((samples, sr, ch)) = raw_audio_cache.get(audio_pool_index) { let total_frames = samples.len() / (*ch).max(1) as usize; let audio_file_duration = total_frames as f64 / *sr as f64; - let screen_size = ui.ctx().screen_rect().size(); + let screen_size = ui.ctx().content_rect().size(); let pending_upload = if waveform_gpu_dirty.contains(audio_pool_index) { waveform_gpu_dirty.remove(audio_pool_index); @@ -1347,7 +1348,7 @@ impl TimelinePane { fn handle_input( &mut self, ui: &mut egui::Ui, - full_timeline_rect: egui::Rect, + _full_timeline_rect: egui::Rect, ruler_rect: egui::Rect, content_rect: egui::Rect, header_rect: egui::Rect, @@ -1357,7 +1358,7 @@ impl TimelinePane { selection: &mut lightningbeam_core::selection::Selection, pending_actions: &mut Vec>, playback_time: &mut f64, - is_playing: &mut bool, + _is_playing: &mut bool, audio_controller: Option<&std::sync::Arc>>, ) { // Don't allocate the header area for input - let widgets handle it directly @@ -2296,7 +2297,7 @@ impl PaneRenderer for TimelinePane { *shared.dragging_asset = None; } else { // Get document dimensions for centering and create clip instance - let (center_x, center_y, mut clip_instance) = { + let (_center_x, _center_y, clip_instance) = { let doc = shared.action_executor.document(); let center_x = doc.width / 2.0; let center_y = doc.height / 2.0; diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/virtual_piano.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/virtual_piano.rs index 2c51049..e64e8c4 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/virtual_piano.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/virtual_piano.rs @@ -215,7 +215,7 @@ impl VirtualPianoPane { // Handle interaction (skip if a black key is being interacted with) let key_id = ui.id().with(("white_key", note)); - let response = ui.interact(key_rect, key_id, egui::Sense::click_and_drag()); + let _response = ui.interact(key_rect, key_id, egui::Sense::click_and_drag()); // Visual feedback for pressed keys (check both pressed_notes and current pointer state) let pointer_over_key = ui.input(|i| { @@ -298,7 +298,7 @@ impl VirtualPianoPane { // Handle interaction (same as white keys) let key_id = ui.id().with(("black_key", note)); - let response = ui.interact(key_rect, key_id, egui::Sense::click_and_drag()); + let _response = ui.interact(key_rect, key_id, egui::Sense::click_and_drag()); // Visual feedback for pressed keys (check both pressed_notes and current pointer state) let pointer_over_key = ui.input(|i| { diff --git a/lightningbeam-ui/lightningbeam-editor/src/preferences/dialog.rs b/lightningbeam-ui/lightningbeam-editor/src/preferences/dialog.rs index 3769593..8b66fd4 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/preferences/dialog.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/preferences/dialog.rs @@ -192,7 +192,7 @@ impl PreferencesDialog { ui.label("Default BPM:"); ui.add( egui::DragValue::new(&mut self.working_prefs.bpm) - .clamp_range(20..=300) + .range(20..=300) .speed(1.0), ); }); @@ -201,7 +201,7 @@ impl PreferencesDialog { ui.label("Default Framerate:"); ui.add( egui::DragValue::new(&mut self.working_prefs.framerate) - .clamp_range(1..=120) + .range(1..=120) .speed(1.0) .suffix(" fps"), ); @@ -211,7 +211,7 @@ impl PreferencesDialog { ui.label("Default File Width:"); ui.add( egui::DragValue::new(&mut self.working_prefs.file_width) - .clamp_range(100..=10000) + .range(100..=10000) .speed(10.0) .suffix(" px"), ); @@ -221,7 +221,7 @@ impl PreferencesDialog { ui.label("Default File Height:"); ui.add( egui::DragValue::new(&mut self.working_prefs.file_height) - .clamp_range(100..=10000) + .range(100..=10000) .speed(10.0) .suffix(" px"), ); @@ -231,7 +231,7 @@ impl PreferencesDialog { ui.label("Scroll Speed:"); ui.add( egui::DragValue::new(&mut self.working_prefs.scroll_speed) - .clamp_range(0.1..=10.0) + .range(0.1..=10.0) .speed(0.1), ); }); @@ -245,7 +245,7 @@ impl PreferencesDialog { ui.horizontal(|ui| { ui.label("Audio Buffer Size:"); - egui::ComboBox::from_id_source("audio_buffer_size") + egui::ComboBox::from_id_salt("audio_buffer_size") .selected_text(format!("{} samples", self.working_prefs.audio_buffer_size)) .show_ui(ui, |ui| { ui.selectable_value( @@ -292,7 +292,7 @@ impl PreferencesDialog { ui.horizontal(|ui| { ui.label("Theme:"); - egui::ComboBox::from_id_source("theme_mode") + egui::ComboBox::from_id_salt("theme_mode") .selected_text(format!("{:?}", self.working_prefs.theme_mode)) .show_ui(ui, |ui| { ui.selectable_value( diff --git a/lightningbeam-ui/lightningbeam-editor/src/preferences/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/preferences/mod.rs index 3f83e9b..b8dda53 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/preferences/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/preferences/mod.rs @@ -4,4 +4,3 @@ pub mod dialog; -pub use dialog::{PreferencesDialog, PreferencesSaveResult}; diff --git a/lightningbeam-ui/lightningbeam-editor/src/theme.rs b/lightningbeam-ui/lightningbeam-editor/src/theme.rs index 6e96b7a..3779f42 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/theme.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/theme.rs @@ -46,27 +46,6 @@ pub struct Style { // Add more properties as needed } -impl Style { - /// Merge another style into this one (other's properties override if present) - pub fn merge(&mut self, other: &Style) { - if other.background_color.is_some() { - self.background_color = other.background_color; - } - if other.border_color.is_some() { - self.border_color = other.border_color; - } - if other.text_color.is_some() { - self.text_color = other.text_color; - } - if other.width.is_some() { - self.width = other.width; - } - if other.height.is_some() { - self.height = other.height; - } - } -} - #[derive(Debug, Clone)] pub struct Theme { light_variables: HashMap, @@ -229,21 +208,13 @@ impl Theme { } } - /// Get a CSS variable value and parse as color (backward compatibility helper) - /// This allows old code using theme.color("variable-name") to work - pub fn color(&self, var_name: &str) -> Option { - // Try light variables first, then dark variables - let value = self.light_variables.get(var_name) - .or_else(|| self.dark_variables.get(var_name))?; - parse_hex_color(value) - } - /// Get the number of loaded selectors pub fn len(&self) -> usize { self.light_styles.len() } /// Check if theme has no styles + #[allow(dead_code)] // Used in tests pub fn is_empty(&self) -> bool { self.light_styles.is_empty() } diff --git a/lightningbeam-ui/lightningbeam-editor/src/waveform_gpu.rs b/lightningbeam-ui/lightningbeam-editor/src/waveform_gpu.rs index afe6bd1..3d62975 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/waveform_gpu.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/waveform_gpu.rs @@ -14,9 +14,6 @@ use wgpu::util::DeviceExt; /// Fixed texture width (power of 2) for all waveform textures const TEX_WIDTH: u32 = 2048; -/// Maximum number of texture segments per audio clip -const MAX_SEGMENTS: u32 = 16; - /// GPU resources for all waveform textures, stored in CallbackResources pub struct WaveformGpuResources { /// Per-audio-pool-index GPU data @@ -34,6 +31,7 @@ pub struct WaveformGpuResources { } /// GPU data for a single audio file +#[allow(dead_code)] // textures/texture_views must stay alive to back bind groups; metadata for future use pub struct WaveformGpuEntry { /// One texture per segment (for long audio split across multiple textures) pub textures: Vec, @@ -612,12 +610,6 @@ fn compute_mip_count(width: u32, height: u32) -> u32 { (max_dim as f32).log2().floor() as u32 + 1 } -/// Calculate how many texture segments are needed for a given frame count -pub fn segment_count_for_frames(total_frames: u64, max_texture_height: u32) -> u32 { - let max_frames_per_segment = TEX_WIDTH as u64 * max_texture_height as u64; - ((total_frames + max_frames_per_segment - 1) / max_frames_per_segment) as u32 -} - /// Get the fixed texture width used for all waveform textures pub fn tex_width() -> u32 { TEX_WIDTH diff --git a/lightningbeam-ui/lightningbeam-editor/src/widgets/text_field.rs b/lightningbeam-ui/lightningbeam-editor/src/widgets/text_field.rs index 9aac4b3..613f864 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/widgets/text_field.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/widgets/text_field.rs @@ -72,6 +72,7 @@ fn key_to_char(key: egui::Key, shift: bool) -> Option { } /// Response from the IME text field widget +#[allow(dead_code)] // Standard widget response fields; callers will use as features expand pub struct ImeTextFieldResponse { /// The egui response for the text field area pub response: egui::Response,