mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-25 02:30:15 -06:00
M2.11: before/after top/bottom (⌥Y) and split top/bottom (⇧⌥Y)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
96903a5fff
commit
6015af99b7
@@ -18,6 +18,8 @@ pub const UI_COMMANDS: &[UiCommand] = &[
|
||||
("view.leftPanel", "My Photos Panel", Some("Cmd+Shift+L"), "View"),
|
||||
("view.beforeAfter", "Compare Before and After", Some("Y"), "View"),
|
||||
("view.beforeAfterSplit", "Before/After Split", Some("Shift+Y"), "View"),
|
||||
("view.beforeAfterTopBottom", "Before/After Top/Bottom", Some("Alt+Y"), "View"),
|
||||
("view.beforeAfterSplitTopBottom", "Before/After Split Top/Bottom", Some("Alt+Shift+Y"), "View"),
|
||||
("view.showOriginal", "Show Original", Some("\\"), "View"),
|
||||
("view.zoomFit", "Zoom to Fit", Some("Cmd+0"), "View"),
|
||||
("view.zoom100", "Zoom 100%", Some("Cmd+1"), "View"),
|
||||
@@ -125,6 +127,14 @@ pub fn run_ui_command(app: &mut LightcraftApp, id: &str, p: &Value) -> Option<Re
|
||||
app.ui.before_after = if app.ui.before_after == BeforeAfter::Split { BeforeAfter::Off } else { BeforeAfter::Split };
|
||||
Ok(Value::Null)
|
||||
}
|
||||
"view.beforeAfterTopBottom" => {
|
||||
app.ui.before_after = if app.ui.before_after == BeforeAfter::TopBottom { BeforeAfter::Off } else { BeforeAfter::TopBottom };
|
||||
Ok(Value::Null)
|
||||
}
|
||||
"view.beforeAfterSplitTopBottom" => {
|
||||
app.ui.before_after = if app.ui.before_after == BeforeAfter::SplitTopBottom { BeforeAfter::Off } else { BeforeAfter::SplitTopBottom };
|
||||
Ok(Value::Null)
|
||||
}
|
||||
"view.showOriginal" => {
|
||||
app.ui.before_after = if app.ui.before_after == BeforeAfter::Original { BeforeAfter::Off } else { BeforeAfter::Original };
|
||||
Ok(Value::Null)
|
||||
|
||||
@@ -124,15 +124,25 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui) {
|
||||
let ppp = ui.ctx().pixels_per_point();
|
||||
let area = canvas.shrink(if crop_tool { 48.0 } else { 24.0 });
|
||||
let native = [photo.width.max(1) as usize, photo.height.max(1) as usize];
|
||||
let split = app.ui.before_after == BeforeAfter::SideBySide;
|
||||
let areas: Vec<Rect> = if split {
|
||||
let half = area.width() / 2.0 - 6.0;
|
||||
vec![
|
||||
Rect::from_min_size(area.min, vec2(half, area.height())),
|
||||
Rect::from_min_size(pos2(area.center().x + 6.0, area.top()), vec2(half, area.height())),
|
||||
]
|
||||
} else {
|
||||
vec![area]
|
||||
// two views (before, after): side by side or stacked
|
||||
let split = matches!(app.ui.before_after, BeforeAfter::SideBySide | BeforeAfter::TopBottom);
|
||||
let split_view = matches!(app.ui.before_after, BeforeAfter::Split | BeforeAfter::SplitTopBottom);
|
||||
let areas: Vec<Rect> = match app.ui.before_after {
|
||||
BeforeAfter::SideBySide => {
|
||||
let half = area.width() / 2.0 - 6.0;
|
||||
vec![
|
||||
Rect::from_min_size(area.min, vec2(half, area.height())),
|
||||
Rect::from_min_size(pos2(area.center().x + 6.0, area.top()), vec2(half, area.height())),
|
||||
]
|
||||
}
|
||||
BeforeAfter::TopBottom => {
|
||||
let half = area.height() / 2.0 - 14.0;
|
||||
vec![
|
||||
Rect::from_min_size(area.min, vec2(area.width(), half)),
|
||||
Rect::from_min_size(pos2(area.left(), area.center().y + 14.0), vec2(area.width(), half)),
|
||||
]
|
||||
}
|
||||
_ => vec![area],
|
||||
};
|
||||
let main_area = *areas.last().unwrap_or(&area);
|
||||
let img_rect = fit_rect(main_area, aspect, app.ui.zoom, native, ppp, app.ui.pan);
|
||||
@@ -174,7 +184,7 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui) {
|
||||
app.renderer.request_quick(Slot::Preview, q, 110);
|
||||
}
|
||||
let show_before = app.ui.before_after == BeforeAfter::Original || ui.input(|i| i.key_down(egui::Key::Backslash));
|
||||
if (split || show_before || app.ui.before_after == BeforeAfter::Split)
|
||||
if (split || show_before || split_view)
|
||||
&& let Some(job) = app.session.render_job(id, rw.max(8), rh.max(8), true, !crop_tool)
|
||||
{
|
||||
app.renderer.request(Slot::Before, job, 90);
|
||||
@@ -221,6 +231,14 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui) {
|
||||
}
|
||||
p.line_segment([pos2(mid, img_rect.top()), pos2(mid, img_rect.bottom())], Stroke::new(1.5, Color32::WHITE));
|
||||
}
|
||||
if app.ui.before_after == BeforeAfter::SplitTopBottom {
|
||||
let mid = img_rect.center().y;
|
||||
if let Some(tex) = app.renderer.textures.get(&Slot::Before).filter(|t| t.photo == id) {
|
||||
let top = Rect::from_min_max(img_rect.min, pos2(img_rect.right(), mid));
|
||||
p.image(tex.tex.id(), top, Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 0.5)), Color32::WHITE);
|
||||
}
|
||||
p.line_segment([pos2(img_rect.left(), mid), pos2(img_rect.right(), mid)], Stroke::new(1.5, Color32::WHITE));
|
||||
}
|
||||
if app.ui.show_clipping && !show_before {
|
||||
clipping_overlay(app, &p, img_rect);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ pub enum BeforeAfter {
|
||||
Original,
|
||||
SideBySide,
|
||||
Split,
|
||||
/// Before above after.
|
||||
TopBottom,
|
||||
/// One image split horizontally: before above the line.
|
||||
SplitTopBottom,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
||||
Reference in New Issue
Block a user