diff --git a/desktop/src/layers.rs b/desktop/src/layers.rs index 74f8ebb8..991413ba 100644 --- a/desktop/src/layers.rs +++ b/desktop/src/layers.rs @@ -172,6 +172,8 @@ pub struct Layers { pub edit_text: Option, /// Layer Opacity asked for the current layer (two fingers tapped on its row). pub layer_opacity: bool, + /// The background's colour asked for (its row tapped off its visibility box), as Procreate. + pub pick_background: bool, /// On a model: the mesh open (its texture set's layers under it), the layer whose channels /// show, the channel whose colour shows, each channel's own colour (hue, saturation, /// brightness) kept while another is painted, the meshes' and channels' pictures, and the @@ -517,7 +519,9 @@ impl Layers { } if model.is_none() { ui.add_space(10.0); - background_row(ui, look, session); + if background_row(ui, look, session) { + self.pick_background = true; + } } ui.add_space(12.0); // the pinched rows over the rest, the upper over the lower @@ -1739,8 +1743,9 @@ fn blend_rows(ui: &Ui, look: &mut Look, list: Rect, modes: &[BlendModeInfo], cho } } -/// The background: its colour and whether it shows. -fn background_row(ui: &mut Ui, look: &mut Look, session: &CanvasSession) { +/// The background: its colour and whether it shows; true when the row is tapped off its +/// visibility box, for its colour to be picked. +fn background_row(ui: &mut Ui, look: &mut Look, session: &CanvasSession) -> bool { let background = session.background(); let (row, _) = ui.allocate_exact_size(vec2(ui.available_width(), 50.0), Sense::hover()); ui.painter().rect_filled(row, 17, argb(BACKGROUND_ROW)); @@ -1760,7 +1765,10 @@ fn background_row(ui: &mut Ui, look: &mut Look, session: &CanvasSession) { check_box(ui, look, visibility.center(), background.visible, argb(CHECK_FILL)); if ui.interact(visibility, ui.scope_id().with("background visible"), Sense::click()).clicked() { session.set_background_visible(!background.visible); + return false; } + let rest = Rect::from_min_max(row.min, pos2(visibility.left() - 4.0, row.max.y)); + ui.interact(rest, ui.scope_id().with("background colour"), Sense::click()).clicked() } /// A visibility box: filled with a check cut out of it when shown, an outline when hidden. diff --git a/desktop/src/ui.rs b/desktop/src/ui.rs index 53515b9d..87365ef6 100644 --- a/desktop/src/ui.rs +++ b/desktop/src/ui.rs @@ -84,6 +84,9 @@ pub struct Interface { /// A Save As being written: where and at which edits, or why it couldn't be. pub saving: Option>>, open: Option, + /// The background's colour being picked in the colour panel: the brush's colour to give back + /// when it closes, and the last colour the background took. + background_pick: Option<(u32, [f32; 3])>, pub(crate) colours: Colours, drop: ColourDrop, library: Library, @@ -202,6 +205,7 @@ impl Default for Interface { saving: None, inserting: Vec::new(), open: None, + background_pick: None, colours: Colours::default(), drop: ColourDrop::default(), library: Library::default(), @@ -713,6 +717,7 @@ impl Interface { if let Some(open) = self.open { self.popover(&ctx, session, open, anchor(open), info.tool, &mut backdrops); } + self.follow_background_pick(session); // the colour panel dragged out by its grabber: a window over the canvas until closed self.colours.show_floating(&ctx, &mut self.look, session, &mut backdrops); // the colour model chosen on the panel, kept; the panel works in the one kept @@ -2066,6 +2071,33 @@ impl Interface { goes_on } + /// The background's row tapped: the colour panel opens on the background's colour, and what + /// is picked in it goes to the background (live, one undo step when it closes), the brush's + /// colour given back then, as Procreate does. + fn start_background_pick(&mut self, session: &CanvasSession) { + let b = session.background(); + let brush = to_hex(self.colours.rgb()); + self.colours.set_rgb(session, to_hex([b.r, b.g, b.b])); + self.background_pick = Some((brush, [b.r, b.g, b.b])); + self.open = Some(Popover::Colour); + } + + /// Takes what the colour panel shows to the background while its colour is picked, and ends + /// the pick when the panel has closed. + fn follow_background_pick(&mut self, session: &CanvasSession) { + let Some((brush, last)) = self.background_pick else { return }; + let now = self.colours.rgb(); + let open = self.open == Some(Popover::Colour); + if !open { + session.set_background_color(now[0], now[1], now[2], true); + self.colours.set_rgb(session, brush); + self.background_pick = None; + } else if now != last { + session.set_background_color(now[0], now[1], now[2], false); + self.background_pick = Some((brush, now)); + } + } + /// The open panel, hanging from its button; a press anywhere else, or Escape, closes it. fn popover( &mut self, @@ -2108,6 +2140,9 @@ impl Interface { if std::mem::take(&mut self.layers.layer_opacity) { self.start_layer_opacity(session); } + if std::mem::take(&mut self.layers.pick_background) { + self.start_background_pick(session); + } shown } Popover::Colour => {