Batch fix: Effect Controls: the Curves graph draws the natural spline the effect renders (#1872)

This commit is contained in:
aiongg
2026-10-23 23:22:30 +00:00
parent d17c2e86cd
commit d6ff173833
3 changed files with 19 additions and 9 deletions
+1 -1
View File
@@ -980,7 +980,7 @@ fn curves_editor(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter,
let col = channel_color(ch);
p.rect_filled(Rect::from_min_max(pos2(gr.min.x, gr.max.y + 3.0), pos2(gr.max.x, gr.max.y + 8.0)), 0.0, col.gamma_multiply(0.5));
let id = egui::Id::new(("ec-curves", euid, ch));
let (resp, edit) = fw::curves_graph(ui, gr, &cur, ch, pencil, id, &t);
let (resp, edit) = fw::curves_graph(ui, gr, &cur, ch, pencil, true, id, &t);
app.auto.add(&format!("effectControls.effect.{euid}.curves.graph"), gr, "Curves");
let started = resp.drag_started() || resp.clicked();
if let Some(np) = edit.changed {
+2 -2
View File
@@ -193,7 +193,7 @@ fn rgb_curves(
}
let gr = Rect::from_min_size(pos2(x0, r.min.y + 30.0), vec2(size, size));
let gid = egui::Id::new(("lumetri-rgb", euid, ch));
let (resp, edit) = fw::curves_graph(ui, gr, &cur, ch, false, gid, &t);
let (resp, edit) = fw::curves_graph(ui, gr, &cur, ch, false, false, gid, &t);
app.auto.add(&format!("{prefix}.graph"), gr, "RGB Curves");
register_points(app, &prefix, gr, &cur.0);
let key = gesture_key(ui, gid, resp.drag_started() || resp.clicked());
@@ -713,7 +713,7 @@ fn glow_map(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter, laye
}
let gr = Rect::from_min_size(pos2(x0, r.min.y + 30.0), vec2(size, size));
let gid = egui::Id::new(("glow-map", euid, ch));
let (resp, edit) = fw::curves_graph(ui, gr, &map[ch], ch + 1, false, gid, &t);
let (resp, edit) = fw::curves_graph(ui, gr, &map[ch], ch + 1, false, false, gid, &t);
app.auto.add(&format!("{prefix}.graph"), gr, "Arbitrary Map");
register_points(app, &prefix, gr, &map[ch].0);
let key = gesture_key(ui, gid, resp.drag_started() || resp.clicked());
+16 -6
View File
@@ -291,7 +291,8 @@ impl CurvePoints {
pub fn hit(&self, x: f32, y: f32, r: f32) -> Option<usize> {
self.0.iter().enumerate().map(|(i, p)| (i, (p[0] - x).hypot(p[1] - y))).filter(|(_, d)| *d <= r).min_by(|a, b| a.1.total_cmp(&b.1)).map(|(i, _)| i)
}
/// The curve the effect renders (the same monotone spline), evaluated at `x`.
/// The monotone spline (`Curve::parse`) through the points, evaluated at `x`: the curve
/// Lumetri's RGB curves and Glow's arbitrary map render.
pub fn eval(&self, x: f32) -> f32 {
effectcraft_engine::effects::Curve::parse(&self.format()).map(|c| c.eval(x)).unwrap_or(x)
}
@@ -326,8 +327,9 @@ pub struct CurveEdit {
/// The Curves graph: grid, identity diagonal, the curve, its points. Click adds a point, drag
/// moves one, dragging a point off the graph (or Alt-clicking it) removes it. In pencil mode a
/// drag draws the curve freehand.
pub fn curves_graph(ui: &mut egui::Ui, rect: Rect, pts: &CurvePoints, channel: usize, pencil: bool, id: egui::Id, t: &Tokens) -> (egui::Response, CurveEdit) {
/// drag draws the curve freehand. `natural` draws the natural spline the Curves effect renders
/// (`Curve::parse_natural`) instead of the monotone one.
pub fn curves_graph(ui: &mut egui::Ui, rect: Rect, pts: &CurvePoints, channel: usize, pencil: bool, natural: bool, id: egui::Id, t: &Tokens) -> (egui::Response, CurveEdit) {
let resp = ui.interact(rect.expand(6.0), id, Sense::click_and_drag());
let p = ui.painter().with_clip_rect(rect.expand(8.0));
p.rect_filled(rect, 0.0, Color32::from_rgb(0x1c, 0x1c, 0x1c));
@@ -349,7 +351,15 @@ pub fn curves_graph(ui: &mut egui::Ui, rect: Rect, pts: &CurvePoints, channel: u
};
let to_s = |x: f32, y: f32| pos2(rect.min.x + x * rect.width(), rect.max.y - y * rect.height());
let to_g = |s: Pos2| [((s.x - rect.min.x) / rect.width()), ((rect.max.y - s.y) / rect.height())];
let spline = effectcraft_engine::effects::Curve::parse(&pts.format());
let spline = if natural { effectcraft_engine::effects::Curve::parse_natural(&pts.format()) } else { effectcraft_engine::effects::Curve::parse(&pts.format()) };
let seed = || {
(0..=64)
.map(|i| {
let x = i as f32 / 64.0;
spline.as_ref().map(|c| c.eval(x)).unwrap_or(x)
})
.collect::<Vec<f32>>()
};
let line: Vec<Pos2> = (0..=96)
.map(|i| {
let x = i as f32 / 96.0;
@@ -375,12 +385,12 @@ pub fn curves_graph(ui: &mut egui::Ui, rect: Rect, pts: &CurvePoints, channel: u
let alt = ui.input(|i| i.modifiers.alt);
if pencil {
if resp.drag_started() {
ui.data_mut(|d| d.insert_temp(pencil_id, (0..=64).map(|i| pts.eval(i as f32 / 64.0)).collect::<Vec<f32>>()));
ui.data_mut(|d| d.insert_temp(pencil_id, seed()));
}
if (resp.dragged() || resp.clicked())
&& let Some(pt) = resp.interact_pointer_pos()
{
let mut samples: Vec<f32> = ui.data(|d| d.get_temp(pencil_id)).unwrap_or_else(|| (0..=64).map(|i| pts.eval(i as f32 / 64.0)).collect());
let mut samples: Vec<f32> = ui.data(|d| d.get_temp(pencil_id)).unwrap_or_else(seed);
let g = to_g(pt);
let i = (g[0].clamp(0.0, 1.0) * 64.0).round() as usize;
samples[i.min(64)] = g[1].clamp(0.0, 1.0);