mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 13:08:07 -06:00
ScriptUI: fix script-drawn colours showing too bright
paint_draw passed a script's 0 to 1 colour values to egui::Rgba, which stores linear light. egui then applied the sRGB curve, so every fillPath, strokePath and drawString colour drew too bright. For example, #2B2B2B drew as RGB 114 and #F28C28 as 249, 196, 110. After Effects treats these values as plain screen colours. Convert them with the existing to_color32 helper instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
eb5108786b
commit
47f55abb87
@@ -241,7 +241,7 @@ fn commit(app: &mut EffectcraftApp, ctx: &egui::Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_color32(c: [f32; 4]) -> Color32 {
|
||||
pub(super) fn to_color32(c: [f32; 4]) -> Color32 {
|
||||
let b = |v: f32| (v.clamp(0.0, 1.0) * 255.0).round() as u8;
|
||||
Color32::from_rgba_unmultiplied(b(c[0]), b(c[1]), b(c[2]), b(c[3]))
|
||||
}
|
||||
|
||||
@@ -256,20 +256,22 @@ fn draw_widget(app: &mut EffectcraftApp, ui: &mut egui::Ui, origin: egui::Pos2,
|
||||
}
|
||||
}
|
||||
|
||||
/// A draw-list colour (`None` is the theme colour). Script colours are display (sRGB) values
|
||||
/// in 0..1, as in After Effects, not linear light: `[43/255, 43/255, 43/255, 1]` is RGB 43.
|
||||
fn draw_color(c: &Option<[f32; 4]>, theme: Color32) -> Color32 {
|
||||
c.map_or(theme, super::gradient_editor::to_color32)
|
||||
}
|
||||
|
||||
/// Paint an onDraw draw list in `rect` (control coordinates → screen).
|
||||
fn paint_draw(ui: &egui::Ui, rect: Rect, ops: &[DrawOp], t: &Tokens, services: &dyn Services) {
|
||||
let p = ui.painter().with_clip_rect(rect.intersect(ui.clip_rect()));
|
||||
let col = |c: &Option<[f32; 4]>, theme: Color32| match c {
|
||||
Some(c) => egui::Rgba::from_rgba_unmultiplied(c[0], c[1], c[2], c[3]).into(),
|
||||
None => theme,
|
||||
};
|
||||
let at = |x: f64, y: f64| rect.min + vec2(x as f32, y as f32);
|
||||
for op in ops {
|
||||
match op {
|
||||
DrawOp::Fill { color, path } => {
|
||||
// Any path shape (concave, self-intersecting, with holes): non-zero winding
|
||||
// triangles, not egui's convex-only polygon fill.
|
||||
let c = col(color, t.field_bg);
|
||||
let c = draw_color(color, t.field_bg);
|
||||
let mut mesh = egui::Mesh::default();
|
||||
for tri in PathSeg::fill_triangles(path, 48, false) {
|
||||
let base = mesh.vertices.len() as u32;
|
||||
@@ -283,14 +285,14 @@ fn paint_draw(ui: &egui::Ui, rect: Rect, ops: &[DrawOp], t: &Tokens, services: &
|
||||
}
|
||||
}
|
||||
DrawOp::Stroke { color, width, path } => {
|
||||
let s = Stroke::new(*width as f32, col(color, t.text));
|
||||
let s = Stroke::new(*width as f32, draw_color(color, t.text));
|
||||
for (pts, closed) in PathSeg::polylines(path, 48) {
|
||||
let pts: Vec<egui::Pos2> = pts.iter().map(|q| at(q[0], q[1])).collect();
|
||||
p.add(if closed { egui::Shape::closed_line(pts, s) } else { egui::Shape::line(pts, s) });
|
||||
}
|
||||
}
|
||||
DrawOp::Text { text, color, x, y, size, .. } => {
|
||||
p.text(at(*x, *y), Align2::LEFT_TOP, text, Tokens::ui(*size as f32), col(color, t.text));
|
||||
p.text(at(*x, *y), Align2::LEFT_TOP, text, Tokens::ui(*size as f32), draw_color(color, t.text));
|
||||
}
|
||||
DrawOp::Image { image, x, y, w, h } => {
|
||||
let tex = image.as_ref().and_then(|i| image_texture(ui.ctx(), i, services));
|
||||
@@ -592,3 +594,18 @@ pub fn sync_panels(app: &mut EffectcraftApp) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Script colours are sRGB, not linear: `#2B2B2B` drew as RGB 114 when read as linear light.
|
||||
#[test]
|
||||
fn draw_colours_are_srgb() {
|
||||
let v = 43.0 / 255.0;
|
||||
assert_eq!(draw_color(&Some([v, v, v, 1.0]), Color32::RED), Color32::from_rgb(43, 43, 43));
|
||||
let orange = [242.0 / 255.0, 140.0 / 255.0, 40.0 / 255.0, 1.0];
|
||||
assert_eq!(draw_color(&Some(orange), Color32::RED), Color32::from_rgb(242, 140, 40));
|
||||
assert_eq!(draw_color(&None, Color32::RED), Color32::RED, "no colour is the theme colour");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user