diff --git a/daw-backend/src/audio/engine.rs b/daw-backend/src/audio/engine.rs index 4991346..476a5d5 100644 --- a/daw-backend/src/audio/engine.rs +++ b/daw-backend/src/audio/engine.rs @@ -116,7 +116,6 @@ pub struct Engine { // Current tempo map — kept in sync with SetTempo/SetTempoMap commands. tempo_map: crate::TempoMap, - current_fps: f64, // Current time signature — updated by SetTempo, used when SetTempoMap fires. time_sig: (u32, u32), } @@ -197,7 +196,6 @@ impl Engine { timing_sum_total_us: 0, timing_overrun_count: 0, tempo_map: crate::TempoMap::constant(120.0), - current_fps: 30.0, time_sig: (4, 4), } } diff --git a/lightningbeam-ui/lightningbeam-core/src/actions/raster_diff.rs b/lightningbeam-ui/lightningbeam-core/src/actions/raster_diff.rs index f1abb7e..15a5f16 100644 --- a/lightningbeam-ui/lightningbeam-core/src/actions/raster_diff.rs +++ b/lightningbeam-ui/lightningbeam-core/src/actions/raster_diff.rs @@ -12,7 +12,7 @@ //! correct). If the base is somehow not resident we skip rather than corrupt. /// Normalize a buffer to full length `n`; an empty/short buffer becomes transparent. -fn normalize(buf: &[u8], n: usize) -> std::borrow::Cow<[u8]> { +fn normalize(buf: &[u8], n: usize) -> std::borrow::Cow<'_, [u8]> { if buf.len() == n { std::borrow::Cow::Borrowed(buf) } else { diff --git a/lightningbeam-ui/lightningbeam-core/src/vector_graph/mod.rs b/lightningbeam-ui/lightningbeam-core/src/vector_graph/mod.rs index 627cc72..e5744a6 100644 --- a/lightningbeam-ui/lightningbeam-core/src/vector_graph/mod.rs +++ b/lightningbeam-ui/lightningbeam-core/src/vector_graph/mod.rs @@ -1161,7 +1161,7 @@ impl VectorGraph { /// faces that lie inside it (inheriting its colour/rule); faces outside it — or in a /// hole — are dropped. fn retrace_fills_after_cut(&mut self, new_edges: &[EdgeId]) { - use kurbo::{ParamCurve, Shape}; + use kurbo::Shape; let new_set: HashSet = new_edges .iter() .filter(|&&e| !e.is_none() && !self.edges[e.idx()].deleted) @@ -1642,21 +1642,6 @@ impl VectorGraph { // Boundary tracing internals // ------------------------------------------------------------------- - /// Find the nearest non-deleted edge to a point. Returns (EdgeId, t, distance). - fn nearest_edge_to_point(&self, point: Point) -> Option<(EdgeId, f64, f64)> { - let mut best: Option<(EdgeId, f64, f64)> = None; - for (i, e) in self.edges.iter().enumerate() { - if e.deleted { - continue; - } - let eid = EdgeId(i as u32); - let (t, dist) = nearest_point_on_cubic(&e.curve, point); - if best.is_none() || dist < best.unwrap().2 { - best = Some((eid, t, dist)); - } - } - best - } /// Build a BezPath from a boundary (without storing it as a fill). /// Handles `EdgeId::NONE` separators to start new contours (holes). diff --git a/lightningbeam-ui/lightningbeam-editor/src/curve_editor.rs b/lightningbeam-ui/lightningbeam-editor/src/curve_editor.rs index 6f57c9b..98fbabb 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/curve_editor.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/curve_editor.rs @@ -43,8 +43,6 @@ pub enum CurveEditAction { #[derive(Clone, Debug)] pub struct CurveDragState { pub keyframe_index: usize, - pub original_time: f64, - pub original_value: f32, pub current_time: f64, pub current_value: f32, } @@ -263,8 +261,6 @@ pub fn render_curve_lane( let kf = &keyframes[idx]; *drag_state = Some(CurveDragState { keyframe_index: idx, - original_time: kf.time, - original_value: kf.value, current_time: kf.time, current_value: kf.value, }); diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs b/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs index 3f68aa2..11eb248 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/dialog.rs @@ -17,8 +17,6 @@ pub struct DocumentHint { pub has_raster: bool, pub has_vector: bool, pub current_time: f64, - pub doc_width: u32, - pub doc_height: u32, } /// Export type selection @@ -577,7 +575,7 @@ impl ExportDialog { if ui.button("Choose location...").clicked() { let ext = self.current_extension(); - let mut dialog = rfd::FileDialog::new() + let dialog = rfd::FileDialog::new() .set_directory(&self.output_dir) .set_file_name(&self.output_filename) .add_filter(ext.to_uppercase(), &[ext]); diff --git a/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs index 7515764..2aa53c6 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/export/mod.rs @@ -567,7 +567,7 @@ impl ExportOrchestrator { let gpu = state.gpu_resources.as_mut().unwrap(); let output_view = state.output_texture_view.as_ref().unwrap(); - let mut encoder = video_exporter::render_frame_to_gpu_rgba( + let encoder = video_exporter::render_frame_to_gpu_rgba( document, state.settings.time, w, h, diff --git a/lightningbeam-ui/lightningbeam-editor/src/gpu_brush.rs b/lightningbeam-ui/lightningbeam-editor/src/gpu_brush.rs index 0c83c56..d2ae716 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/gpu_brush.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/gpu_brush.rs @@ -1586,11 +1586,6 @@ impl GpuBrushEngine { crate::debug_overlay::update_gpu_memory(count, total); } - /// Get the cached display texture for a raster layer keyframe. - pub fn get_layer_texture(&self, kf_id: &Uuid) -> Option<&CanvasPair> { - self.raster_layer_cache.get(kf_id) - } - /// Ensure a low-res proxy texture exists for `kf_id` (uploaded once; proxies are /// immutable). Bumps recency and evicts the least-recently-used past the budget. /// `pixels` is sRGB-premultiplied RGBA of length `w * h * 4`. @@ -1778,18 +1773,6 @@ impl GpuBrushEngine { self.displacement_bufs.insert(id, DisplacementBuffer { buf, width, height }); } - /// Overwrite the displacement buffer contents with the provided data. - pub fn upload_displacement_buf( - &self, - queue: &wgpu::Queue, - id: &Uuid, - data: &[[f32; 2]], - ) { - if let Some(db) = self.displacement_bufs.get(id) { - queue.write_buffer(&db.buf, 0, bytemuck::cast_slice(data)); - } - } - /// Zero out a displacement buffer (reset all displacements to (0,0)). pub fn clear_displacement_buf(&self, queue: &wgpu::Queue, id: &Uuid) { if let Some(db) = self.displacement_bufs.get(id) { diff --git a/lightningbeam-ui/lightningbeam-editor/src/main.rs b/lightningbeam-ui/lightningbeam-editor/src/main.rs index 6ae9f3e..cc55b97 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/main.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/main.rs @@ -2234,40 +2234,6 @@ impl EditorApp { } } - /// Porter-Duff "over" composite of `src` onto `dst` at canvas offset `(ox, oy)`. - /// Both buffers are sRGB-encoded premultiplied RGBA. - fn composite_over( - dst: &mut [u8], dst_w: u32, dst_h: u32, - src: &[u8], src_w: u32, src_h: u32, - ox: i32, oy: i32, - ) { - for row in 0..src_h { - let dy = oy + row as i32; - if dy < 0 || dy >= dst_h as i32 { continue; } - for col in 0..src_w { - let dx = ox + col as i32; - if dx < 0 || dx >= dst_w as i32 { continue; } - let si = ((row * src_w + col) * 4) as usize; - let di = ((dy as u32 * dst_w + dx as u32) * 4) as usize; - let sa = src[si + 3] as u32; - if sa == 0 { continue; } - let da = dst[di + 3] as u32; - // out_a = src_a + dst_a * (255 - src_a) / 255 - let out_a = sa + da * (255 - sa) / 255; - dst[di + 3] = out_a as u8; - if out_a > 0 { - for c in 0..3 { - // premul over: out = src + dst*(1-src_a/255) - // v is in [0, 255²], so one /255 brings it back to [0, 255] - let v = src[si + c] as u32 * 255 - + dst[di + c] as u32 * (255 - sa); - dst[di + c] = (v / 255).min(255) as u8; - } - } - } - } - } - /// Commit a floating raster selection: composite it into the keyframe's /// `raw_pixels` and record a `RasterStrokeAction` for undo. /// Clears `selection.raster_floating` and `selection.raster_selection`. @@ -2824,7 +2790,7 @@ impl EditorApp { let canvas_before = kf.raw_pixels.clone(); let canvas_w = kf.width; let canvas_h = kf.height; - drop(kf); // release immutable borrow before taking mutable + let _ = kf; // release immutable borrow before taking mutable use lightningbeam_core::selection::{RasterFloatingSelection, RasterSelection}; self.selection.raster_floating = Some(RasterFloatingSelection { @@ -3276,8 +3242,6 @@ impl EditorApp { has_raster: false, has_vector: false, current_time: doc.current_time, - doc_width: doc.width as u32, - doc_height: doc.height as u32, }; scan(&doc.root.children, &mut h); h @@ -3636,7 +3600,7 @@ impl EditorApp { let doc = self.action_executor.document(); let (doc_w, doc_h) = (doc.width as u32, doc.height as u32); - drop(doc); + let _ = doc; let mut layer = RasterLayer::new(layer_name); layer.ensure_keyframe_at(self.playback_time, doc_w, doc_h); let action = lightningbeam_core::actions::AddLayerAction::new(AnyLayer::Raster(layer)) @@ -5775,7 +5739,7 @@ impl eframe::App for EditorApp { .map(|(&lid, _)| lid); if let Some(layer_id) = recording_layer { // First, find the clip instance and clip id - let (clip_id, instance_id, timeline_start, trim_start) = { + let (clip_id, instance_id, _timeline_start, _trim_start) = { let document = self.action_executor.document(); document.get_layer(&layer_id) .and_then(|layer| { @@ -6551,7 +6515,6 @@ impl eframe::App for EditorApp { pending_graph_loads: &self.pending_graph_loads, clipboard_consumed: &mut clipboard_consumed, keymap: &self.keymap, - commit_raster_floating_if_any: &mut self.commit_raster_floating_if_any, pending_node_group: &mut self.pending_node_group, pending_node_ungroup: &mut self.pending_node_ungroup, #[cfg(debug_assertions)] @@ -7512,7 +7475,7 @@ fn render_pane( // Active tab highlight with per-corner rounding if is_active { let cr = corner_r as u8; - let rounding = egui::Rounding { + let rounding = egui::CornerRadius { nw: if i == 0 { cr } else { 0 }, sw: if i == 0 { cr } else { 0 }, ne: if i == n - 1 { cr } else { 0 }, @@ -7557,7 +7520,7 @@ fn render_pane( if tab_response.hovered() && !is_active { ui.painter().rect_filled( tab_rect, - egui::Rounding { + egui::CornerRadius { nw: if i == 0 { corner_r as u8 } else { 0 }, sw: if i == 0 { corner_r as u8 } else { 0 }, ne: if i == n - 1 { corner_r as u8 } else { 0 }, diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/gradient_editor.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/gradient_editor.rs index 2a1e2af..3333f01 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/gradient_editor.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/gradient_editor.rs @@ -238,7 +238,7 @@ pub fn gradient_stop_editor( // ── Paint handles ───────────────────────────────────────────────────── // handle_rects was built before any deletions this frame; guard against OOB. for (i, h_rect) in handle_rects.iter().enumerate().take(gradient.stops.len()) { - let col = ShapeColor_to_Color32(gradient.stops[i].color); + let col = shape_color_to_color32(gradient.stops[i].color); let is_selected = *selected_stop == Some(i); let stroke = Stroke::new( if is_selected { 2.0 } else { 1.0 }, @@ -308,7 +308,7 @@ pub fn gradient_stop_editor( // ── Helpers ────────────────────────────────────────────────────────────────── -fn ShapeColor_to_Color32(c: ShapeColor) -> Color32 { +fn shape_color_to_color32(c: ShapeColor) -> Color32 { Color32::from_rgba_unmultiplied(c.r, c.g, c.b, c.a) } diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/infopanel.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/infopanel.rs index ba4b56a..5813e8e 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/infopanel.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/infopanel.rs @@ -11,7 +11,7 @@ /// - Document settings (when nothing is focused) use eframe::egui::{self, DragValue, Ui}; -use lightningbeam_core::brush_settings::{bundled_brushes, BrushSettings}; +use lightningbeam_core::brush_settings::bundled_brushes; use lightningbeam_core::actions::{SetDocumentPropertiesAction, SetShapePropertiesAction, SetFillPaintAction, SetImageFillAction}; use lightningbeam_core::gradient::ShapeGradient; use lightningbeam_core::layer::{AnyLayer, LayerTrait}; @@ -1439,40 +1439,6 @@ impl InfopanelPane { } } -/// Draw a brush dab preview into `rect` approximating the brush falloff shape. -/// -/// Renders N concentric filled circles from outermost to innermost. Because each -/// inner circle overwrites the pixels of all outer circles beneath it, the visible -/// alpha at distance `d` from the centre equals the alpha of the innermost circle -/// whose radius ≥ `d`. This step-approximates the actual brush falloff formula: -/// `opa = ((1 − r) / (1 − hardness))²` for `r > hardness`, 1 inside the hard core. -fn paint_brush_dab(painter: &egui::Painter, rect: egui::Rect, s: &BrushSettings) { - let center = rect.center(); - let max_r = (rect.width().min(rect.height()) / 2.0 - 2.0).max(1.0); - let h = s.hardness; - let a = s.opaque; - - const N: usize = 12; - for i in 0..N { - // t: normalized radial position of this ring, 1.0 = outermost edge - let t = 1.0 - i as f32 / N as f32; - let r = max_r * t; - - let opa_weight = if h >= 1.0 || t <= h { - 1.0f32 - } else { - let x = (1.0 - t) / (1.0 - h).max(1e-4); - (x * x).min(1.0) - }; - - let alpha = (opa_weight * a * 220.0).min(220.0) as u8; - painter.circle_filled( - center, r, - egui::Color32::from_rgba_unmultiplied(200, 200, 220, alpha), - ); - } -} - /// Convert MIDI note number to note name (e.g. 60 -> "C4") fn midi_note_name(note: u8) -> String { const NAMES: [&str; 12] = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs index ae78e67..7d1acb8 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/mod.rs @@ -342,9 +342,6 @@ pub struct SharedPaneState<'a> { pub clipboard_consumed: &'a mut bool, /// Remappable keyboard shortcut manager pub keymap: &'a crate::keymap::KeymapManager, - /// Set by raster selection tools when they need main to commit the floating - /// selection before starting a new interaction. - pub commit_raster_floating_if_any: &'a mut bool, /// Set by MenuAction::Group when focus is Nodes — consumed by node graph pane pub pending_node_group: &'a mut bool, /// Set by MenuAction::Group (ungroup variant) when focus is Nodes — consumed by node graph pane diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/piano_roll.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/piano_roll.rs index 8589c51..64e5390 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/piano_roll.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/piano_roll.rs @@ -240,12 +240,6 @@ impl PianoRollPane { matches!(note % 12, 1 | 3 | 6 | 8 | 10) } - fn note_name(note: u8) -> String { - let names = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]; - let octave = (note / 12) as i32 - 1; - format!("{}{}", names[note as usize % 12], octave) - } - // ── Note resolution ────────────────────────────────────────────────── fn resolve_notes(events: &[daw_backend::audio::midi::MidiEvent]) -> Vec { @@ -736,45 +730,6 @@ impl PianoRollPane { } } - /// Generate pitch bend MIDI events for a note based on the zone and target semitones. - fn generate_pitch_bend_events( - note_start: f64, - note_duration: f64, - zone: PitchBendZone, - semitones: f32, - channel: u8, - pitch_bend_range: f32, - ) -> Vec { - use daw_backend::audio::midi::MidiEvent; - let num_steps: usize = 128; - let mut events = Vec::new(); - let encode_bend = |normalized: f32| -> (u8, u8) { - let value_14 = (normalized * 8191.0 + 8192.0).clamp(0.0, 16383.0) as i16; - ((value_14 & 0x7F) as u8, ((value_14 >> 7) & 0x7F) as u8) - }; - // Use t directly (0..=1 across the full note) — same formula as the visual ghost. - // Start: peak → 0 (ramps down over full note) - // Middle: 0 → peak → 0 (sine arch, peaks at center) - // End: 0 → peak (ramps up over full note) - for i in 0..=num_steps { - let t = i as f64 / num_steps as f64; - let t_f32 = t as f32; - // Cosine ease curves: Start+End at equal value = perfectly flat (partition of unity). - // Start: (1+cos(πt))/2 — peaks at t=0, smooth decay to 0 at t=1 - // End: (1-cos(πt))/2 — 0 at t=0, smooth rise to peak at t=1 - // Middle: sin(πt) — arch peaking at t=0.5 - let normalized = match zone { - PitchBendZone::Start => semitones / pitch_bend_range * (1.0 + (std::f32::consts::PI * t_f32).cos()) * 0.5, - PitchBendZone::Middle => semitones / pitch_bend_range * (std::f32::consts::PI * t_f32).sin(), - PitchBendZone::End => semitones / pitch_bend_range * (1.0 - (std::f32::consts::PI * t_f32).cos()) * 0.5, - }; - let timestamp = note_start + t * note_duration; - let (lsb, msb) = encode_bend(normalized); - events.push(MidiEvent::new(daw_backend::Beats(timestamp), 0xE0 | channel, lsb, msb)); - } - events - } - /// Find the lowest available MIDI channel (1–15) not already used by any note /// overlapping [note_start, note_end], excluding the note being assigned itself. /// Returns the note's current channel unchanged if it is already uniquely assigned (non-zero). @@ -2408,7 +2363,7 @@ impl PaneRenderer for PianoRollPane { let doc = shared.action_executor.document(); let is_measures = doc.timeline_mode == lightningbeam_core::document::TimelineMode::Measures; let tempo_map = doc.tempo_map(); - drop(doc); + let _ = doc; if is_measures { // Auto-detect grid when selection changes diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs index bbf139b..c28e116 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/stage.rs @@ -682,17 +682,13 @@ impl egui_wgpu::CallbackTrait for VelloCallback { if let Some(b_id) = self.ctx.pending_tool_readback_b { if let Ok(mut gpu_brush) = shared.gpu_brush.lock() { let dims = gpu_brush.canvases.get(&b_id).map(|c| (c.width, c.height)); - if let Some((w, h)) = dims { + if let Some((_w, _h)) = dims { if let Some(pixels) = gpu_brush.readback_canvas(device, queue, b_id) { let results = RASTER_READBACK_RESULTS.get_or_init(|| { Arc::new(Mutex::new(std::collections::HashMap::new())) }); if let Ok(mut map) = results.lock() { map.insert(self.ctx.instance_id_for_readback, RasterReadbackResult { - layer_id: uuid::Uuid::nil(), // unused; routing via pending_undo_before - time: 0.0, - canvas_width: w, - canvas_height: h, pixels, }); } @@ -763,10 +759,6 @@ impl egui_wgpu::CallbackTrait for VelloCallback { }); if let Ok(mut map) = results.lock() { map.insert(self.ctx.instance_id_for_readback, RasterReadbackResult { - layer_id: pending.layer_id, - time: pending.time, - canvas_width: pending.canvas_width, - canvas_height: pending.canvas_height, pixels, }); } @@ -3173,7 +3165,6 @@ enum PendingWarpOp { disp_data: Option>, grid_cols: u32, grid_rows: u32, - w: u32, h: u32, final_commit: bool, layer_id: uuid::Uuid, time: f64, @@ -3190,7 +3181,6 @@ enum PendingWarpOp { anchor_canvas_id: uuid::Uuid, disp_buf_id: uuid::Uuid, display_canvas_id: uuid::Uuid, - w: u32, h: u32, final_commit: bool, layer_id: uuid::Uuid, time: f64, @@ -3251,10 +3241,6 @@ static EYEDROPPER_RESULTS: OnceLock, } @@ -4201,7 +4183,7 @@ impl StagePane { // Update connected edges: shift the adjacent control point by the same delta for &edge_id in &connected_edges { - let [v0, v1] = graph.edge(edge_id).vertices; + let [v0, _v1] = graph.edge(edge_id).vertices; let mut curve = graph.edge(edge_id).curve; if v0 == vertex_id { @@ -5609,58 +5591,6 @@ impl StagePane { } } - /// Lift the pixels enclosed by the current `raster_selection` into a - /// `RasterFloatingSelection`, punching a transparent hole in `raw_pixels`. - /// - /// Call this immediately after a marquee / lasso selection is finalized so - /// that all downstream operations (drag-move, copy, cut, stroke-masking) - /// see a consistent `raster_floating` whenever a selection is active. - /// Build an R8 mask buffer (0 = outside, 255 = inside) from a selection. - fn build_selection_mask( - sel: &lightningbeam_core::selection::RasterSelection, - width: u32, - height: u32, - ) -> Vec { - let mut mask = vec![0u8; (width * height) as usize]; - let (x0, y0, x1, y1) = sel.bounding_rect(); - let bx0 = x0.max(0) as u32; - let by0 = y0.max(0) as u32; - let bx1 = (x1 as u32).min(width); - let by1 = (y1 as u32).min(height); - for y in by0..by1 { - for x in bx0..bx1 { - if sel.contains_pixel(x as i32, y as i32) { - mask[(y * width + x) as usize] = 255; - } - } - } - mask - } - - /// Build an R8 mask buffer for the float canvas (0 = outside selection, 255 = inside). - /// Coordinates are in float-local space: pixel (fx, fy) corresponds to document pixel - /// (float_x+fx, float_y+fy). - fn build_float_mask( - sel: &lightningbeam_core::selection::RasterSelection, - float_x: i32, float_y: i32, - float_w: u32, float_h: u32, - ) -> Vec { - let mut mask = vec![0u8; (float_w * float_h) as usize]; - let (x0, y0, x1, y1) = sel.bounding_rect(); - let bx0 = (x0 - float_x).max(0) as u32; - let by0 = (y0 - float_y).max(0) as u32; - let bx1 = ((x1 - float_x) as u32).min(float_w); - let by1 = ((y1 - float_y) as u32).min(float_h); - for fy in by0..by1 { - for fx in bx0..bx1 { - if sel.contains_pixel(float_x + fx as i32, float_y + fy as i32) { - mask[(fy * float_w + fx) as usize] = 255; - } - } - } - mask - } - /// Allocate the three A/B/C GPU canvases and build a [`crate::raster_tool::RasterWorkspace`] /// for a new raster tool operation. /// @@ -5699,7 +5629,6 @@ impl StagePane { a_canvas_id: a_id, b_canvas_id: b_id, c_canvas_id: c_id, - mask_texture: None, width: w, height: h, x, @@ -5724,7 +5653,7 @@ impl StagePane { let layer_id = (*shared.active_layer_id)?; let time = *shared.playback_time; - let (doc_w, doc_h) = { + let (_doc_w, _doc_h) = { let doc = shared.action_executor.document(); (doc.width as u32, doc.height as u32) }; @@ -5733,7 +5662,7 @@ impl StagePane { // returns None (no workspace) if there's no active keyframe to lift from. // Read keyframe id and pixels. - let (kf_id, w, h, pixels) = { + let (_kf_id, w, h, pixels) = { let doc = shared.action_executor.document(); let AnyLayer::Raster(rl) = doc.get_layer(&layer_id)? else { return None }; let kf = rl.keyframe_at(time)?; @@ -5753,7 +5682,6 @@ impl StagePane { a_canvas_id: a_id, b_canvas_id: b_id, c_canvas_id: c_id, - mask_texture: None, width: w, height: h, x: 0, @@ -5761,9 +5689,6 @@ impl StagePane { source: WorkspaceSource::Layer { layer_id, time, - kf_id, - canvas_w: doc_w, - canvas_h: doc_h, }, before_pixels: pixels.clone(), }; @@ -6135,8 +6060,6 @@ impl StagePane { )); self.pending_raster_dabs = Some(PendingRasterDabs { keyframe_id: canvas_id, - layer_id, - time, canvas_width, canvas_height, initial_pixels: None, // canvas already initialized via lazy GPU init @@ -6220,8 +6143,6 @@ impl StagePane { )); self.pending_raster_dabs = Some(PendingRasterDabs { keyframe_id, - layer_id: active_layer_id, - time: kf_time, canvas_width, canvas_height, initial_pixels: Some(initial_pixels), @@ -6299,8 +6220,6 @@ impl StagePane { let (dabs, dab_bbox) = BrushEngine::compute_dabs(&seg, stroke_state, dt); self.pending_raster_dabs = Some(PendingRasterDabs { keyframe_id: canvas_id, - layer_id, - time, canvas_width: cw, canvas_height: ch, initial_pixels: None, @@ -6363,8 +6282,6 @@ impl StagePane { if !dabs.is_empty() { self.pending_raster_dabs = Some(PendingRasterDabs { keyframe_id: canvas_id, - layer_id, - time, canvas_width: cw, canvas_height: ch, initial_pixels: None, @@ -6424,8 +6341,6 @@ impl StagePane { if let Some(kf_id) = kf_id { self.pending_raster_dabs = Some(PendingRasterDabs { keyframe_id: kf_id, - layer_id: ub_layer, - time: ub_time, canvas_width: ub_cw, canvas_height: ub_ch, initial_pixels: None, @@ -6941,7 +6856,7 @@ impl StagePane { fn handle_quick_select_tool( &mut self, - ui: &mut egui::Ui, + _ui: &mut egui::Ui, response: &egui::Response, world_pos: egui::Vec2, shared: &mut SharedPaneState, @@ -8431,7 +8346,6 @@ impl StagePane { world_pos: egui::Vec2, shared: &mut SharedPaneState, ) { - use lightningbeam_core::tool::Tool; use uuid::Uuid; // Ensure we're on a raster layer. @@ -8469,7 +8383,6 @@ impl StagePane { disp_data: Some(disp_data), grid_cols: ws.grid_cols, grid_rows: ws.grid_rows, - w: ws.anchor_w, h: ws.anchor_h, final_commit: true, layer_id: ws.layer_id, time: ws.time, @@ -8695,7 +8608,6 @@ impl StagePane { disp_data: Some(disp_data), grid_cols: ws.grid_cols, grid_rows: ws.grid_rows, - w: ws.anchor_w, h: ws.anchor_h, final_commit: false, layer_id: ws.layer_id, time: ws.time, @@ -8705,7 +8617,7 @@ impl StagePane { None }; let (ws_layer_id, ws_display_id, ws_float_offset) = (ws.layer_id, ws.display_canvas_id, ws.float_offset); - drop(ws); // release borrow of warp_state + let _ = ws; // release borrow of warp_state // Display canvas is initialised by Init (zero-displacement apply), so it always // has valid content. For full-layer warp, override the layer blit unconditionally. @@ -8778,7 +8690,6 @@ impl StagePane { anchor_canvas_id: ls.anchor_canvas_id, disp_buf_id: ls.disp_buf_id, display_canvas_id: ls.display_canvas_id, - w: ls.anchor_w, h: ls.anchor_h, final_commit: true, layer_id: ls.layer_id, time: ls.time, @@ -8950,7 +8861,6 @@ impl StagePane { anchor_canvas_id: anchor_id, disp_buf_id: disp_buf, display_canvas_id: display_id, - w, h, final_commit: false, layer_id: ls_layer_id, time, @@ -9013,7 +8923,7 @@ impl StagePane { } else { None } } else { None } } else { None }; - drop(doc); + let _ = doc; r } else { None }; @@ -10706,7 +10616,6 @@ impl StagePane { // Alt+click: set source point for clone/healing tools. { - use lightningbeam_core::tool::Tool; let tool_uses_alt = crate::tools::raster_tool_def(shared.selected_tool) .map_or(false, |d| d.uses_alt_click()); if tool_uses_alt @@ -11602,7 +11511,6 @@ impl PaneRenderer for StagePane { disp_data: Some(disp_data), grid_cols: ws.grid_cols, grid_rows: ws.grid_rows, - w: ws.anchor_w, h: ws.anchor_h, final_commit: true, layer_id: ws.layer_id, time: ws.time, @@ -11623,7 +11531,6 @@ impl PaneRenderer for StagePane { anchor_canvas_id: ls.anchor_canvas_id, disp_buf_id: ls.disp_buf_id, display_canvas_id: ls.display_canvas_id, - w: ls.anchor_w, h: ls.anchor_h, final_commit: true, layer_id: ls.layer_id, time: ls.time, diff --git a/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs b/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs index 2d7e5ca..7762112 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/panes/timeline.rs @@ -483,7 +483,6 @@ struct AutomationLaneRender { value_max: f32, accent_color: egui::Color32, playback_time: f64, - kind: AutomationLaneKind, } /// Pending automation keyframe edit action from curve lane interaction @@ -1160,7 +1159,7 @@ impl TimelinePane { *shared.recording_clips.get(&layer_id).unwrap_or(&0), daw_backend::Beats::ZERO); let doc_clip_id = shared.action_executor.document_mut().add_audio_clip(doc_clip); - let mut clip_instance = ClipInstance::new(doc_clip_id) + let clip_instance = ClipInstance::new(doc_clip_id) .with_timeline_start(start_time); if let Some(layer) = shared.action_executor.document_mut().get_layer_mut(&layer_id) { @@ -3230,7 +3229,6 @@ impl TimelinePane { value_max: lane.value_max, accent_color: lane_accent, playback_time, - kind: lane.kind, }); } } @@ -4054,7 +4052,6 @@ impl TimelinePane { value_max: lane.value_max, accent_color: lane_accent, playback_time, - kind: lane.kind, }); } } @@ -5409,12 +5406,10 @@ impl PaneRenderer for TimelinePane { let editing_clip_id = shared.editing_clip_id; let mut context_layers = document.context_layers(editing_clip_id.as_ref()); // Prepend master track as the first row when enabled (only at root context, not inside clips) - let master_any_layer; + let _master_any_layer; if self.show_master_track && editing_clip_id.is_none() { - master_any_layer = Some(AnyLayer::Group(document.master_layer.clone())); - context_layers.insert(0, master_any_layer.as_ref().unwrap()); - } else { - master_any_layer = None; + _master_any_layer = Some(AnyLayer::Group(document.master_layer.clone())); + context_layers.insert(0, _master_any_layer.as_ref().unwrap()); } // Use virtual row count (includes expanded group children) for height calculations let layer_count = build_timeline_rows(&context_layers).len(); diff --git a/lightningbeam-ui/lightningbeam-editor/src/raster_tool.rs b/lightningbeam-ui/lightningbeam-editor/src/raster_tool.rs index 8244976..3157a40 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/raster_tool.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/raster_tool.rs @@ -12,7 +12,6 @@ //! allocates and validates them in [`begin_raster_workspace`]; tools only //! dispatch shaders. -use std::sync::Arc; use uuid::Uuid; use eframe::egui; @@ -25,11 +24,6 @@ pub enum WorkspaceSource { Layer { layer_id: Uuid, time: f64, - /// The keyframe's own UUID (the A-canvas key in `GpuBrushEngine`). - kf_id: Uuid, - /// Full canvas dimensions (may differ from workspace dims for floating selections). - canvas_w: u32, - canvas_h: u32, }, /// Operating on the floating selection. Float, @@ -51,9 +45,6 @@ pub struct RasterWorkspace { pub b_canvas_id: Uuid, /// C canvas (Rgba16Float) — scratch; tools accumulate dabs here across the stroke. pub c_canvas_id: Uuid, - /// Optional R8Unorm selection mask (same pixel dimensions as A/B/C). - /// `None` means the entire workspace is selected. - pub mask_texture: Option>, /// Pixel dimensions. A, B, C, and mask are all guaranteed to be this size. pub width: u32, pub height: u32, @@ -69,40 +60,6 @@ pub struct RasterWorkspace { } impl RasterWorkspace { - /// Panic-safe bounds check. Asserts that every GPU canvas exists and has - /// the dimensions declared by this workspace. Called by the framework - /// before `begin()` and before each `update()`. - pub fn validate(&self, gpu: &crate::gpu_brush::GpuBrushEngine) { - for (name, id) in [ - ("A", self.a_canvas_id), - ("B", self.b_canvas_id), - ("C", self.c_canvas_id), - ] { - let canvas = gpu.canvases.get(&id).unwrap_or_else(|| { - panic!( - "RasterWorkspace::validate: buffer '{}' (id={}) not found in GpuBrushEngine", - name, id - ) - }); - assert_eq!( - canvas.width, self.width, - "RasterWorkspace::validate: buffer '{}' width {} != workspace width {}", - name, canvas.width, self.width - ); - assert_eq!( - canvas.height, self.height, - "RasterWorkspace::validate: buffer '{}' height {} != workspace height {}", - name, canvas.height, self.height - ); - } - let expected = (self.width * self.height * 4) as usize; - assert_eq!( - self.before_pixels.len(), expected, - "RasterWorkspace::validate: before_pixels.len()={} != expected {}", - self.before_pixels.len(), expected - ); - } - /// Returns the three canvas UUIDs as an array (convenient for bulk removal). pub fn canvas_ids(&self) -> [Uuid; 3] { [self.a_canvas_id, self.b_canvas_id, self.c_canvas_id] @@ -208,11 +165,6 @@ pub trait RasterTool: Send + Sync { /// the operation was a no-op (e.g. the pointer never moved). fn finish(&mut self, ws: &RasterWorkspace) -> bool; - /// Called on **Escape** or tool switch mid-stroke. The caller restores the - /// source pixels from `ws.before_pixels` without creating an undo entry; the - /// tool just cleans up internal state. - fn cancel(&mut self, ws: &RasterWorkspace); - /// Called once per frame (in the VelloCallback construction, UI thread) to /// extract pending GPU work accumulated by `begin()` / `update()`. /// @@ -377,384 +329,7 @@ impl RasterTool for BrushRasterTool { self.has_dabs } - fn cancel(&mut self, _ws: &RasterWorkspace) { - self.pending = None; - self.has_dabs = false; - } - fn take_pending_gpu_work(&mut self) -> Option> { self.pending.take().map(|w| w as Box) } } - -// ── EffectBrushTool ─────────────────────────────────────────────────────────── - -/// Raster tool for effect brushes (Blur, Sharpen, Dodge, Burn, Sponge, Desaturate). -/// -/// C accumulates a per-pixel influence weight (R channel, 0–255). -/// The composite pass applies the effect to A, scaled by C.r, writing to B: -/// `B = lerp(A, effect(A), C.r)` -/// -/// Using C as an influence map (rather than accumulating modified pixels) prevents -/// overlapping dabs from compounding the effect beyond the C.r cap (255). -/// -/// # GPU implementation (TODO) -/// Requires a dedicated `effect_brush_composite.wgsl` shader that reads A and C, -/// applies the blend-mode-specific filter to A, and blends by C.r → B. -pub struct EffectBrushTool { - brush: BrushSettings, - blend_mode: RasterBlendMode, - has_dabs: bool, -} - -impl EffectBrushTool { - pub fn new(brush: BrushSettings, blend_mode: RasterBlendMode) -> Self { - Self { brush, blend_mode, has_dabs: false } - } -} - -impl RasterTool for EffectBrushTool { - fn begin(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) {} - fn update(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - self.has_dabs = true; // placeholder - } - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { self.has_dabs } - fn cancel(&mut self, _ws: &RasterWorkspace) { self.has_dabs = false; } - // GPU shaders not yet implemented; take_pending_gpu_work returns None (default). -} - -// ── SmudgeTool ──────────────────────────────────────────────────────────────── - -/// Raster tool for the smudge brush. -/// -/// `begin()`: copy A → C so C starts with the source pixels for color pickup. -/// `update()`: dispatch smudge dabs using `blend_mode=2` (reads C as source, -/// writes smear to C); then composite C over A → B. -/// Because the smudge shader reads from `canvas_src` (C.src) and writes to -/// `canvas_dst` (C.dst), existing dabs are preserved in the smear history. -/// -/// # GPU implementation (TODO) -/// Requires an initial A → C copy in `begin()` (via GPU copy command). -/// The smudge dab dispatch then uses `render_dabs(c_id, smudge_dabs, ...)`. -/// The composite pass is `composite_a_c_to_b` (same as BrushRasterTool). -pub struct SmudgeTool { - brush: BrushSettings, - has_dabs: bool, -} - -impl SmudgeTool { - pub fn new(brush: BrushSettings) -> Self { - Self { brush, has_dabs: false } - } -} - -impl RasterTool for SmudgeTool { - fn begin(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) {} - fn update(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - self.has_dabs = true; // placeholder - } - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { self.has_dabs } - fn cancel(&mut self, _ws: &RasterWorkspace) { self.has_dabs = false; } - // GPU shaders not yet implemented; take_pending_gpu_work returns None (default). -} - -// ── GradientRasterTool ──────────────────────────────────────────────────────── - -use crate::gpu_brush::GpuGradientStop; -use lightningbeam_core::gradient::{GradientExtend, GradientType, ShapeGradient}; - -fn gradient_stops_to_gpu(gradient: &ShapeGradient) -> Vec { - gradient.stops.iter().map(|s| { - GpuGradientStop::from_srgb_u8(s.position, s.color.r, s.color.g, s.color.b, s.color.a) - }).collect() -} - -fn gradient_extend_to_u32(extend: GradientExtend) -> u32 { - match extend { - GradientExtend::Pad => 0, - GradientExtend::Reflect => 1, - GradientExtend::Repeat => 2, - } -} - -fn gradient_kind_to_u32(kind: GradientType) -> u32 { - match kind { - GradientType::Linear => 0, - GradientType::Radial => 1, - } -} - -struct PendingGradientWork { - a_id: Uuid, - b_id: Uuid, - stops: Vec, - start: (f32, f32), - end: (f32, f32), - opacity: f32, - extend_mode: u32, - kind: u32, -} - -impl PendingGpuWork for PendingGradientWork { - fn execute(&self, device: &wgpu::Device, queue: &wgpu::Queue, gpu: &mut crate::gpu_brush::GpuBrushEngine) { - gpu.apply_gradient_fill( - device, queue, - &self.a_id, &self.b_id, - &self.stops, - self.start, self.end, - self.opacity, self.extend_mode, self.kind, - ); - } -} - -/// Raster tool for gradient fills. -/// -/// `begin()` records the canvas-local start position. -/// `update()` recomputes gradient parameters from settings and queues a -/// `PendingGradientWork` that calls `apply_gradient_fill` in `prepare()`. -/// `finish()` returns whether any gradient was dispatched. -pub struct GradientRasterTool { - start_canvas: egui::Vec2, - end_canvas: egui::Vec2, - pending: Option>, - has_dispatched: bool, -} - -impl GradientRasterTool { - pub fn new() -> Self { - Self { - start_canvas: egui::Vec2::ZERO, - end_canvas: egui::Vec2::ZERO, - pending: None, - has_dispatched: false, - } - } -} - -impl RasterTool for GradientRasterTool { - fn begin(&mut self, ws: &RasterWorkspace, pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - let canvas_pos = pos - egui::vec2(ws.x as f32, ws.y as f32); - self.start_canvas = canvas_pos; - self.end_canvas = canvas_pos; - } - - fn update(&mut self, ws: &RasterWorkspace, pos: egui::Vec2, _dt: f32, settings: &crate::tools::RasterToolSettings) { - self.end_canvas = pos - egui::vec2(ws.x as f32, ws.y as f32); - let gradient = &settings.gradient; - self.pending = Some(Box::new(PendingGradientWork { - a_id: ws.a_canvas_id, - b_id: ws.b_canvas_id, - stops: gradient_stops_to_gpu(gradient), - start: (self.start_canvas.x, self.start_canvas.y), - end: (self.end_canvas.x, self.end_canvas.y), - opacity: settings.gradient_opacity, - extend_mode: gradient_extend_to_u32(gradient.extend), - kind: gradient_kind_to_u32(gradient.kind), - })); - self.has_dispatched = true; - } - - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { self.has_dispatched } - - fn cancel(&mut self, _ws: &RasterWorkspace) { - self.pending = None; - self.has_dispatched = false; - } - - fn take_pending_gpu_work(&mut self) -> Option> { - self.pending.take().map(|w| w as Box) - } -} - -// ── TransformRasterTool ─────────────────────────────────────────────────────── - -use crate::gpu_brush::RasterTransformGpuParams; - -struct PendingTransformWork { - a_id: Uuid, - b_id: Uuid, - params: RasterTransformGpuParams, -} - -impl PendingGpuWork for PendingTransformWork { - fn execute(&self, device: &wgpu::Device, queue: &wgpu::Queue, gpu: &mut crate::gpu_brush::GpuBrushEngine) { - gpu.render_transform(device, queue, &self.a_id, &self.b_id, self.params); - } -} - -/// Raster tool for affine transforms (move, scale, rotate, shear). -/// -/// `begin()` stores the initial canvas dimensions and queues an identity -/// transform so B is initialised on the first frame. -/// `update()` recomputes the inverse affine matrix from the current handle -/// positions and queues a new `PendingTransformWork`. -/// -/// The inverse matrix maps output pixel coordinates back to source pixel -/// coordinates: `src = M_inv * dst + b` -/// where `M_inv = [[a00, a01], [a10, a11]]` and `b = [b0, b1]`. -/// -/// # GPU implementation -/// Fully wired — uses `GpuBrushEngine::render_transform`. Handle interaction -/// logic (drag, rotate, scale) is handled by the tool's `update()` caller in -/// `stage.rs` which computes and passes in the `RasterTransformGpuParams`. -pub struct TransformRasterTool { - pending: Option>, - has_dispatched: bool, - canvas_w: u32, - canvas_h: u32, -} - -impl TransformRasterTool { - pub fn new() -> Self { - Self { - pending: None, - has_dispatched: false, - canvas_w: 0, - canvas_h: 0, - } - } - - /// Queue a transform with the given inverse-affine matrix. - /// Called by the stage handler after computing handle positions. - pub fn set_transform( - &mut self, - ws: &RasterWorkspace, - params: RasterTransformGpuParams, - ) { - self.pending = Some(Box::new(PendingTransformWork { - a_id: ws.a_canvas_id, - b_id: ws.b_canvas_id, - params, - })); - self.has_dispatched = true; - } -} - -impl RasterTool for TransformRasterTool { - fn begin(&mut self, ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - self.canvas_w = ws.width; - self.canvas_h = ws.height; - // Queue identity transform so B shows the source immediately. - let identity = RasterTransformGpuParams { - a00: 1.0, a01: 0.0, - a10: 0.0, a11: 1.0, - b0: 0.0, b1: 0.0, - src_w: ws.width, src_h: ws.height, - dst_w: ws.width, dst_h: ws.height, - _pad0: 0, _pad1: 0, - }; - self.set_transform(ws, identity); - } - - fn update(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - // Handle interaction and matrix updates are driven from stage.rs via set_transform(). - } - - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { self.has_dispatched } - - fn cancel(&mut self, _ws: &RasterWorkspace) { - self.pending = None; - self.has_dispatched = false; - } - - fn take_pending_gpu_work(&mut self) -> Option> { - self.pending.take().map(|w| w as Box) - } -} - -// ── WarpRasterTool ──────────────────────────────────────────────────────────── - -/// Raster tool for warp / mesh deformation. -/// -/// Uses a displacement buffer (managed by `GpuBrushEngine`) that maps each -/// output pixel to a source offset. The displacement grid is updated by -/// dragging control points; the warp shader reads anchor pixels + displacement -/// → B each frame. -/// -/// # GPU implementation (TODO) -/// Requires: `create_displacement_buf`, `apply_warp` already exist in -/// `GpuBrushEngine`. Wire brush-drag interaction to update displacement -/// entries and call `apply_warp`. -pub struct WarpRasterTool { - has_dispatched: bool, -} - -impl WarpRasterTool { - pub fn new() -> Self { Self { has_dispatched: false } } -} - -impl RasterTool for WarpRasterTool { - fn begin(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) {} - fn update(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - self.has_dispatched = true; // placeholder - } - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { self.has_dispatched } - fn cancel(&mut self, _ws: &RasterWorkspace) { self.has_dispatched = false; } - // take_pending_gpu_work: default (None) — full GPU wiring is TODO. -} - -// ── LiquifyRasterTool ───────────────────────────────────────────────────────── - -/// Raster tool for liquify (per-pixel displacement painting). -/// -/// Similar to `WarpRasterTool` but uses a full per-pixel displacement map -/// (grid_cols = grid_rows = 0 in `apply_warp`) painted by brush strokes. -/// Each dab accumulates displacement in the push/pull/swirl direction. -/// -/// # GPU implementation (TODO) -/// Requires: a dab-to-displacement shader that accumulates per-pixel offsets -/// into the displacement buffer, then `apply_warp` reads it → B. -pub struct LiquifyRasterTool { - has_dispatched: bool, -} - -impl LiquifyRasterTool { - pub fn new() -> Self { Self { has_dispatched: false } } -} - -impl RasterTool for LiquifyRasterTool { - fn begin(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) {} - fn update(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - self.has_dispatched = true; // placeholder - } - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { self.has_dispatched } - fn cancel(&mut self, _ws: &RasterWorkspace) { self.has_dispatched = false; } - // take_pending_gpu_work: default (None) — full GPU wiring is TODO. -} - -// ── SelectionTool ───────────────────────────────────────────────────────────── - -/// Raster selection tool (Magic Wand / Quick Select). -/// -/// C (RGBA8) acts as the growing selection; C.r = mask value (0 or 255). -/// Each `update()` frame a flood-fill / region-grow shader extends C.r. -/// The composite pass draws A + a tinted overlay from C.r → B so the user -/// sees the growing selection boundary. -/// -/// `finish()` returns false (commit does not write pixels back to the layer; -/// instead the caller extracts C.r into the standalone `R8Unorm` selection -/// texture via `shared.raster_selection`). -/// -/// # GPU implementation (TODO) -/// Requires: a flood-fill compute shader seeded by the click position that -/// grows the selection in C.r; and a composite shader that tints selected -/// pixels blue/cyan for preview. -pub struct SelectionTool { - has_selection: bool, -} - -impl SelectionTool { - pub fn new() -> Self { Self { has_selection: false } } -} - -impl RasterTool for SelectionTool { - fn begin(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) {} - fn update(&mut self, _ws: &RasterWorkspace, _pos: egui::Vec2, _dt: f32, _settings: &crate::tools::RasterToolSettings) { - self.has_selection = true; // placeholder - } - /// Selection tools never trigger a pixel readback/commit on mouseup. - /// The caller reads C.r directly into the selection mask texture. - fn finish(&mut self, _ws: &RasterWorkspace) -> bool { false } - fn cancel(&mut self, _ws: &RasterWorkspace) { self.has_selection = false; } - // take_pending_gpu_work: default (None) — full GPU wiring is TODO. -} diff --git a/lightningbeam-ui/lightningbeam-editor/src/test_mode.rs b/lightningbeam-ui/lightningbeam-editor/src/test_mode.rs index 0872fe7..9c8a94b 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/test_mode.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/test_mode.rs @@ -232,15 +232,6 @@ impl TestModeState { } } - /// Store geometry context for panic capture. - /// Called before risky operations (e.g. region select) so the panic hook - /// can include it in the crash file for easier reproduction. - pub fn set_pending_geometry(&self, context: serde_json::Value) { - if let Ok(mut guard) = self.pending_geometry.try_lock() { - *guard = Some(context); - } - } - /// Clear the pending geometry context (call after the operation succeeds). pub fn clear_pending_geometry(&self) { if let Ok(mut guard) = self.pending_geometry.try_lock() { diff --git a/lightningbeam-ui/lightningbeam-editor/src/theme.rs b/lightningbeam-ui/lightningbeam-editor/src/theme.rs index 638c676..78cdccb 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/theme.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/theme.rs @@ -42,6 +42,7 @@ impl ThemeMode { /// Background type for CSS backgrounds #[derive(Debug, Clone)] +#[allow(dead_code)] pub enum Background { Solid(egui::Color32), LinearGradient { @@ -456,6 +457,7 @@ impl Theme { } /// Invalidate the cache (call on stylesheet reload or mode change) + #[allow(dead_code)] pub fn invalidate_cache(&self) { self.cache.borrow_mut().clear(); } @@ -518,6 +520,7 @@ impl Theme { } /// Convenience: resolve and extract a dimension with fallback + #[allow(dead_code)] pub fn dimension(&self, context: &[&str], ctx: &egui::Context, property: &str, fallback: f32) -> f32 { let style = self.resolve(context, ctx); match property { @@ -534,6 +537,7 @@ impl Theme { } /// Paint background for a region (handles solid/gradient/image) + #[allow(dead_code)] pub fn paint_bg( &self, context: &[&str], diff --git a/lightningbeam-ui/lightningbeam-editor/src/theme_render.rs b/lightningbeam-ui/lightningbeam-editor/src/theme_render.rs index 2e13cbb..311ee52 100644 --- a/lightningbeam-ui/lightningbeam-editor/src/theme_render.rs +++ b/lightningbeam-ui/lightningbeam-editor/src/theme_render.rs @@ -7,6 +7,7 @@ use eframe::egui; use crate::theme::Background; /// Paint a background into the given rect +#[allow(dead_code)] pub fn paint_background( painter: &egui::Painter, rect: egui::Rect, @@ -35,6 +36,7 @@ pub fn paint_background( /// - 90deg = left to right /// - 180deg = top to bottom (default) /// - 270deg = right to left +#[allow(dead_code)] pub fn paint_linear_gradient( painter: &egui::Painter, rect: egui::Rect,