mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 20:36:02 +00:00
Merge pull request #7208 from dotCooCoo/feat/live-paint-selection-cursors
Live Paint Selection: cursor shows a face, an edge or nothing to select
This commit is contained in:
@@ -756,6 +756,9 @@ fn precise_cursors_replace_every_pen_state() {
|
||||
Cursor::LivePaintBucket,
|
||||
Cursor::LivePaintBucketFace,
|
||||
Cursor::LivePaintBucketEdge,
|
||||
Cursor::LivePaintSelectFace,
|
||||
Cursor::LivePaintSelectEdge,
|
||||
Cursor::LivePaintSelectOutside,
|
||||
] {
|
||||
assert_eq!(c.precise(), Cursor::Crosshair, "{c:?}");
|
||||
}
|
||||
|
||||
@@ -480,6 +480,8 @@ pub const LP_SELECT_WIDTH_RANGE: (f64, f64) = (1.0, 20.0);
|
||||
/// Select Strokes off, Alt-click selects the face under the pointer as a click does and a marquee
|
||||
/// takes no edges; with Select Fills off, a click selects the edge nearest the pointer as Alt-click
|
||||
/// does and a marquee takes no faces; with both off, a click or a marquee selects no face or edge.
|
||||
/// The pointer shows what a click at that point selects ([`LivePaintSelectionTool::pick_at`]): a
|
||||
/// face, an edge, or nothing. From the press to the release it keeps the look it had at the press.
|
||||
pub struct LivePaintSelectionTool {
|
||||
pub(super) cache: RegionCache,
|
||||
pub(super) hover: LpHover,
|
||||
@@ -502,6 +504,8 @@ struct LpDrag {
|
||||
shift: bool,
|
||||
/// The face or edge under the press, which a click selects (or with Shift toggles).
|
||||
hit: Option<NodeId>,
|
||||
/// The cursor at the press, which the drag keeps.
|
||||
cursor: Cursor,
|
||||
}
|
||||
|
||||
impl LpDrag {
|
||||
@@ -538,6 +542,22 @@ impl LivePaintSelectionTool {
|
||||
(false, false) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The face or edge a click at `p` selects, Alt held or not, with its cursor: the visible part of
|
||||
/// the kind [`LivePaintSelectionTool::picks_edge`] asks for, of a Live Paint group the tool takes
|
||||
/// ([`lp_part_at`], [`lp_selectable`]), and [`Cursor::LivePaintSelectFace`] or
|
||||
/// [`Cursor::LivePaintSelectEdge`]; None and [`Cursor::LivePaintSelectOutside`] where a click
|
||||
/// selects no face or edge.
|
||||
fn pick_at(&self, cx: &ToolContext, p: Point, alt: bool) -> (Option<NodeId>, Cursor) {
|
||||
let Some(edge) = self.picks_edge(alt) else { return (None, Cursor::LivePaintSelectOutside) };
|
||||
let hit = lp_part_at(cx.doc, p, cx.tol(4.0), edge, &|id| lp_selectable(cx, id)).and_then(|(_, part)| part).map(|n| n.id);
|
||||
let cursor = match (hit, edge) {
|
||||
(None, _) => Cursor::LivePaintSelectOutside,
|
||||
(Some(_), true) => Cursor::LivePaintSelectEdge,
|
||||
(Some(_), false) => Cursor::LivePaintSelectFace,
|
||||
};
|
||||
(hit, cursor)
|
||||
}
|
||||
}
|
||||
|
||||
/// The faces (with `faces`) and edges (with `edges`) that marquee `r` touches, among the faces and
|
||||
@@ -592,9 +612,8 @@ impl Tool for LivePaintSelectionTool {
|
||||
vec![]
|
||||
}
|
||||
PointerKind::Down => {
|
||||
let part = edge.and_then(|e| lp_part_at(cx.doc, p, cx.tol(4.0), e, &|id| lp_selectable(cx, id)));
|
||||
let hit = part.and_then(|(_, part)| part).map(|n| n.id);
|
||||
self.drag = Some(LpDrag { start: p, cur: p, shift: ev.mods.shift, hit });
|
||||
let (hit, cursor) = self.pick_at(cx, p, ev.mods.alt);
|
||||
self.drag = Some(LpDrag { start: p, cur: p, shift: ev.mods.shift, hit, cursor });
|
||||
vec![]
|
||||
}
|
||||
PointerKind::Drag => {
|
||||
@@ -652,8 +671,11 @@ impl Tool for LivePaintSelectionTool {
|
||||
lp_overlays(&self.hover, &self.cache, self.color, self.width as f32, self.width as f32)
|
||||
}
|
||||
|
||||
fn cursor(&self, _cx: &ToolContext, _p: Point, _m: Mods) -> Cursor {
|
||||
Cursor::Arrow
|
||||
fn cursor(&self, cx: &ToolContext, p: Point, m: Mods) -> Cursor {
|
||||
match &self.drag {
|
||||
Some(d) => d.cursor,
|
||||
None => self.pick_at(cx, p, m.alt).1,
|
||||
}
|
||||
}
|
||||
|
||||
fn options(&self) -> Value {
|
||||
|
||||
@@ -1636,6 +1636,84 @@ fn live_paint_selection_click_outside_the_faces_selects_the_edge_it_highlights()
|
||||
assert_eq!(lp_click(&mut t, &cx, ev(PointerKind::Down, 106.0, 50.0)), vec![Action::Exec("select.none".into(), json!({}))]);
|
||||
}
|
||||
|
||||
/// The Live Paint Selection pointer shows what a click at the point selects, from the point and
|
||||
/// the modifier keys alone (no move first): a face, an edge, or nothing. Groups the tool does not
|
||||
/// take (locked, hidden, outside isolation) show nothing to select. A press keeps its look until
|
||||
/// the release.
|
||||
#[test]
|
||||
fn live_paint_selection_cursor_shows_what_a_click_selects() {
|
||||
let mut d = Document::new(500.0, 500.0);
|
||||
let (g, _) = live_square(&mut d, Rect::new(0.0, 0.0, 100.0, 100.0));
|
||||
let (other, _) = live_square(&mut d, Rect::new(200.0, 0.0, 300.0, 100.0));
|
||||
let s = Selection::default();
|
||||
let p = paint();
|
||||
let plain = Mods::default();
|
||||
let alt = Mods { alt: true, ..Default::default() };
|
||||
let (face, edge, out) = (Cursor::LivePaintSelectFace, Cursor::LivePaintSelectEdge, Cursor::LivePaintSelectOutside);
|
||||
let at = |t: &LivePaintSelectionTool, cx: &ToolContext, x: f64, m: Mods| t.cursor(cx, Point::new(x, 50.0), m);
|
||||
let mut t = LivePaintSelectionTool::default();
|
||||
{
|
||||
let cx = cx(&d, &s, &p);
|
||||
// Both options on: a face inside the square; with Alt the side within reach, inside or
|
||||
// outside the face; nothing away from the groups or from every side.
|
||||
assert_eq!(
|
||||
[at(&t, &cx, 50.0, plain), at(&t, &cx, 98.5, plain), at(&t, &cx, 102.0, plain), at(&t, &cx, 150.0, plain)],
|
||||
[face, face, out, out]
|
||||
);
|
||||
assert_eq!([at(&t, &cx, 98.5, alt), at(&t, &cx, 102.0, alt), at(&t, &cx, 50.0, alt), at(&t, &cx, 150.0, alt)], [edge, edge, out, out]);
|
||||
// The cursor agrees with what a click there selects.
|
||||
let face_id = faces(d.node(g).unwrap())[0].id;
|
||||
assert_eq!(lp_click(&mut t, &cx, ev(PointerKind::Down, 50.0, 50.0)), vec![Action::Exec("select.set".into(), json!({ "ids": [face_id.0] }))]);
|
||||
assert_eq!(lp_click(&mut t, &cx, ev(PointerKind::Down, 50.0, 50.0).with_mods(alt)), vec![Action::Exec("select.none".into(), json!({}))]);
|
||||
// Select Fills off: a side without Alt too, never a face.
|
||||
t.set_option("selectFills", &json!(false));
|
||||
assert_eq!([at(&t, &cx, 98.5, plain), at(&t, &cx, 50.0, plain), at(&t, &cx, 98.5, alt)], [edge, out, edge]);
|
||||
// Select Strokes off: the face with Alt too, never a side.
|
||||
t.set_option("selectFills", &json!(true));
|
||||
t.set_option("selectStrokes", &json!(false));
|
||||
assert_eq!([at(&t, &cx, 98.5, alt), at(&t, &cx, 102.0, alt)], [face, out]);
|
||||
// Both off: nothing.
|
||||
t.set_option("selectFills", &json!(false));
|
||||
assert_eq!([at(&t, &cx, 50.0, plain), at(&t, &cx, 98.5, alt)], [out, out]);
|
||||
}
|
||||
let mut t = LivePaintSelectionTool::default();
|
||||
// A locked group shows nothing to select; the other group still does.
|
||||
d.node_mut(g).unwrap().locked = true;
|
||||
{
|
||||
let cx = cx(&d, &s, &p);
|
||||
assert_eq!([at(&t, &cx, 50.0, plain), at(&t, &cx, 98.5, alt), at(&t, &cx, 250.0, plain)], [out, out, face]);
|
||||
}
|
||||
d.node_mut(g).unwrap().locked = false;
|
||||
// In isolation mode, a group outside the isolated art shows nothing to select.
|
||||
{
|
||||
let cx = ToolContext { isolation: Some(other), ..cx(&d, &s, &p) };
|
||||
assert_eq!([at(&t, &cx, 50.0, plain), at(&t, &cx, 250.0, plain)], [out, face]);
|
||||
}
|
||||
// A hidden group shows nothing to select.
|
||||
d.node_mut(g).unwrap().visible = false;
|
||||
{
|
||||
let cx = cx(&d, &s, &p);
|
||||
assert_eq!([at(&t, &cx, 50.0, plain), at(&t, &cx, 98.5, alt)], [out, out]);
|
||||
}
|
||||
d.node_mut(g).unwrap().visible = true;
|
||||
// A press keeps its look while the drag goes elsewhere, and the release lets it follow again.
|
||||
let cx = cx(&d, &s, &p);
|
||||
t.pointer(&cx, &ev(PointerKind::Down, 50.0, 50.0));
|
||||
t.pointer(&cx, &ev(PointerKind::Drag, 150.0, 50.0));
|
||||
assert_eq!(at(&t, &cx, 150.0, plain), face);
|
||||
t.pointer(&cx, &ev(PointerKind::Up, 150.0, 50.0));
|
||||
assert_eq!(at(&t, &cx, 150.0, plain), out);
|
||||
t.pointer(&cx, &ev(PointerKind::Down, 150.0, 50.0));
|
||||
t.pointer(&cx, &ev(PointerKind::Drag, 50.0, 50.0));
|
||||
assert_eq!(at(&t, &cx, 50.0, plain), out);
|
||||
t.key(&cx, ToolKey::Escape, plain);
|
||||
assert_eq!(at(&t, &cx, 50.0, plain), face, "Escape ends the press");
|
||||
for c in [face, edge, out] {
|
||||
assert_eq!(c.precise(), Cursor::Crosshair, "{c:?}");
|
||||
assert_eq!(c.stand_in(), None, "{c:?} is drawn");
|
||||
}
|
||||
}
|
||||
|
||||
/// Presses at `from` with `m`, drags to `to` and releases there; returns what the release does
|
||||
/// (the press and the drag do nothing).
|
||||
fn lp_drag(t: &mut LivePaintSelectionTool, cx: &ToolContext, from: (f64, f64), to: (f64, f64), m: Mods) -> Vec<Action> {
|
||||
|
||||
@@ -148,6 +148,14 @@ pub enum Cursor {
|
||||
LivePaintBucketFace,
|
||||
/// The Live Paint Bucket where a click paints an edge of a Live Paint group: a brush.
|
||||
LivePaintBucketEdge,
|
||||
/// Live Paint Selection over a face of a Live Paint group that a click selects: the arrow with a
|
||||
/// filled square.
|
||||
LivePaintSelectFace,
|
||||
/// Live Paint Selection over an edge of a Live Paint group that a click selects: the arrow with
|
||||
/// a short line.
|
||||
LivePaintSelectEdge,
|
||||
/// Live Paint Selection where a click selects no face or edge: the arrow with an x.
|
||||
LivePaintSelectOutside,
|
||||
/// The Measure tool.
|
||||
Measure,
|
||||
/// The Print Tiling tool.
|
||||
@@ -248,7 +256,8 @@ impl Cursor {
|
||||
}
|
||||
|
||||
/// General › Use Precise Cursors: the drawing tools' pointers (the Pen's in every state, the
|
||||
/// Anchor Point and Curvature tools', the Eyedropper's, the Slice and Blend tools') become a plain crosshair at the hotspot.
|
||||
/// Anchor Point and Curvature tools', the Eyedropper's, the Slice and Blend tools', the Live
|
||||
/// Paint tools') become a plain crosshair at the hotspot.
|
||||
pub fn precise(self) -> Self {
|
||||
match self {
|
||||
Cursor::Pen
|
||||
@@ -287,6 +296,9 @@ impl Cursor {
|
||||
| Cursor::LivePaintBucket
|
||||
| Cursor::LivePaintBucketFace
|
||||
| Cursor::LivePaintBucketEdge
|
||||
| Cursor::LivePaintSelectFace
|
||||
| Cursor::LivePaintSelectEdge
|
||||
| Cursor::LivePaintSelectOutside
|
||||
| Cursor::Measure
|
||||
| Cursor::PrintTiling
|
||||
| Cursor::SymbolSprayer
|
||||
|
||||
@@ -28,7 +28,7 @@ shown_when = [
|
||||
"The Selection tool over empty canvas or over an unselected object (no Alt).",
|
||||
"Dragging with the Selection tool (a move), with Direct Selection (an anchor, a segment or a handle), or with a shape tool (from the selection's centre point).",
|
||||
"Any tool with no cursor of its own (Touch Type, Rotate View).",
|
||||
"The resting state of Live Paint Selection, Reshape (away from a path), Free Transform, Puppet Warp and Crop Image (nothing selected or outside the box), the Perspective Grid (locked or away from handles) and Perspective Selection.",
|
||||
"The resting state of Reshape (away from a path), Free Transform, Puppet Warp and Crop Image (nothing selected or outside the box), the Perspective Grid (locked or away from handles) and Perspective Selection.",
|
||||
]
|
||||
hotspot = "The arrow's tip."
|
||||
look = "The default pointer: a solid arrow. ArrowHollow is its hollow twin."
|
||||
@@ -89,6 +89,39 @@ shown_when = [
|
||||
hotspot = "The front arrowhead's tip."
|
||||
look = "Says \"a copy\": a double arrowhead, one in front of the other."
|
||||
|
||||
[[cursor]]
|
||||
id = "LivePaintSelectFace"
|
||||
group = "Selection"
|
||||
shown_when = [
|
||||
"Live Paint Selection over a face of a Live Paint group that a click selects: inside the face, with Select Fills on, and without Alt unless Select Strokes is off.",
|
||||
"From a press there until the release, wherever the drag goes.",
|
||||
"With Use Precise Cursors on, the crosshair shows instead.",
|
||||
]
|
||||
hotspot = "The arrow's tip."
|
||||
look = "Arrow with a small filled square badge (a face). LivePaintSelectEdge and LivePaintSelectOutside share the arrow."
|
||||
|
||||
[[cursor]]
|
||||
id = "LivePaintSelectEdge"
|
||||
group = "Selection"
|
||||
shown_when = [
|
||||
"Live Paint Selection within reach of an edge of a Live Paint group that a click selects: Select Strokes is on, and Alt is held or Select Fills is off.",
|
||||
"From a press there until the release, wherever the drag goes.",
|
||||
"With Use Precise Cursors on, the crosshair shows instead.",
|
||||
]
|
||||
hotspot = "The arrow's tip."
|
||||
look = "Arrow with a short line badge (an edge)."
|
||||
|
||||
[[cursor]]
|
||||
id = "LivePaintSelectOutside"
|
||||
group = "Selection"
|
||||
shown_when = [
|
||||
"Live Paint Selection where a click selects no face or edge: away from Live Paint groups, over a group that is locked, hidden or outside the isolated art, inside a face with Alt held and no edge within reach, or with Select Fills and Select Strokes both off.",
|
||||
"From a press there until the release, wherever the drag goes.",
|
||||
"With Use Precise Cursors on, the crosshair shows instead.",
|
||||
]
|
||||
hotspot = "The arrow's tip."
|
||||
look = "Arrow with a small x badge (nothing to select)."
|
||||
|
||||
[[cursor]]
|
||||
id = "Move"
|
||||
group = "Selection"
|
||||
|
||||
@@ -83,7 +83,10 @@ pub(super) fn cursor_icon(c: Cursor) -> egui::CursorIcon {
|
||||
| Cursor::CornerRadius
|
||||
| Cursor::PathBracket
|
||||
| Cursor::TypeWidget
|
||||
| Cursor::LoadedText => C::Default,
|
||||
| Cursor::LoadedText
|
||||
| Cursor::LivePaintSelectFace
|
||||
| Cursor::LivePaintSelectEdge
|
||||
| Cursor::LivePaintSelectOutside => C::Default,
|
||||
Cursor::SelectionCopy => C::Copy,
|
||||
Cursor::Move => C::Move,
|
||||
Cursor::Crosshair => C::Crosshair,
|
||||
|
||||
@@ -468,6 +468,27 @@ fn paint_brush(p: &mut Ink, o: Pos2) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Live Paint Selection: the solid arrow with a badge at its lower right saying what a click
|
||||
/// selects: a filled square over a face ([`Cursor::LivePaintSelectFace`]), a short line between two
|
||||
/// anchor marks over an edge ([`Cursor::LivePaintSelectEdge`]), an x where it selects nothing.
|
||||
fn live_paint_select(p: &mut Ink, o: Pos2, part: Cursor) {
|
||||
arrow(p, o, false);
|
||||
let b = o + vec2(12.0, 13.0);
|
||||
match part {
|
||||
Cursor::LivePaintSelectFace => {
|
||||
poly(p, [(0.0, 0.0), (6.0, 0.0), (6.0, 6.0), (0.0, 6.0)].map(|(x, y)| b + vec2(x, y)).to_vec(), INK, INK);
|
||||
}
|
||||
Cursor::LivePaintSelectEdge => {
|
||||
let (a, c) = (b + vec2(0.0, 7.0), b + vec2(7.0, 0.0));
|
||||
strokes(p, &[vec![a, c]]);
|
||||
for m in [a, c] {
|
||||
poly(p, [(-1.5, -1.5), (1.5, -1.5), (1.5, 1.5), (-1.5, 1.5)].map(|(x, y)| m + vec2(x, y)).to_vec(), INK, INK);
|
||||
}
|
||||
}
|
||||
_ => strokes(p, &[vec![b, b + vec2(6.0, 6.0)], vec![b + vec2(6.0, 0.0), b + vec2(0.0, 6.0)]]),
|
||||
}
|
||||
}
|
||||
|
||||
/// The Hand tool and Space: an open hand (palm and four fingers, thumb to the left), or the same
|
||||
/// hand closed while it drags the view. Windows has no system hand that isn't a pointing finger
|
||||
/// (winit maps egui's Grab and Grabbing to the four-headed move cursor), so it is drawn like the
|
||||
@@ -516,7 +537,7 @@ fn magnifier(p: &mut Ink, o: Pos2, out: bool) {
|
||||
|
||||
/// Every cursor with a glyph: its own, drawn here, or the one it borrows.
|
||||
#[cfg(test)]
|
||||
const GLYPHS: [Cursor; 95] = [
|
||||
const GLYPHS: [Cursor; 98] = [
|
||||
Cursor::Hand,
|
||||
Cursor::HandGrab,
|
||||
Cursor::ZoomIn,
|
||||
@@ -586,6 +607,9 @@ const GLYPHS: [Cursor; 95] = [
|
||||
Cursor::LivePaintBucket,
|
||||
Cursor::LivePaintBucketFace,
|
||||
Cursor::LivePaintBucketEdge,
|
||||
Cursor::LivePaintSelectFace,
|
||||
Cursor::LivePaintSelectEdge,
|
||||
Cursor::LivePaintSelectOutside,
|
||||
Cursor::Measure,
|
||||
Cursor::PrintTiling,
|
||||
Cursor::SymbolSprayer,
|
||||
@@ -710,6 +734,7 @@ fn glyph(c: Cursor, p: Pos2) -> Option<Vec<Shape>> {
|
||||
Cursor::LivePaintBucket => paint_bucket(ink, p, false),
|
||||
Cursor::LivePaintBucketFace => paint_bucket(ink, p, true),
|
||||
Cursor::LivePaintBucketEdge => paint_brush(ink, p),
|
||||
Cursor::LivePaintSelectFace | Cursor::LivePaintSelectEdge | Cursor::LivePaintSelectOutside => live_paint_select(ink, p, c),
|
||||
Cursor::Hand => hand(ink, p, false),
|
||||
Cursor::HandGrab => hand(ink, p, true),
|
||||
Cursor::ZoomIn => magnifier(ink, p, false),
|
||||
|
||||
@@ -331,6 +331,45 @@ fn the_live_paint_bucket_shows_a_bucket_or_a_brush() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Live Paint Selection's cursors are the solid arrow, its tip on the hotspot, with a badge at its
|
||||
/// lower right: a filled square over a face, a line between two anchor marks over an edge, and an x
|
||||
/// where a click selects nothing.
|
||||
#[test]
|
||||
fn live_paint_selection_shows_the_arrow_with_a_face_edge_or_x_badge() {
|
||||
for ppp in [2.0f32, 3.0] {
|
||||
let img = |c| rasterize(c, ppp).unwrap_or_else(|| panic!("{c:?} at {ppp}"));
|
||||
let (arrow, cross) = (img(Cursor::Arrow), img(Cursor::Crosshair));
|
||||
let (face, edge, out) = (img(Cursor::LivePaintSelectFace), img(Cursor::LivePaintSelectEdge), img(Cursor::LivePaintSelectOutside));
|
||||
// The pixel at (dx, dy) points from the hotspot.
|
||||
let at = |img: &CustomCursorImage, dx: f32, dy: f32| {
|
||||
let [hx, hy] = img.hotspot.map(usize::from);
|
||||
let (x, y) = ((hx as f32 + dx * ppp) as usize, (hy as f32 + dy * ppp) as usize);
|
||||
if x < img.size[0] as usize && y < img.size[1] as usize { pixel(img, x, y) } else { [0; 4] }
|
||||
};
|
||||
let inked = |p: [u8; 4]| p[3] > 200 && p[0] < 64;
|
||||
// Inside the square, away from the x's strokes and the edge's line.
|
||||
let square = (15.0, 14.0);
|
||||
// The edge's upper anchor mark, beyond the square and the x.
|
||||
let mark = (19.0, 13.0);
|
||||
// On the x's stroke from top left to bottom right, away from the edge's line.
|
||||
let x_stroke = (13.0, 14.0);
|
||||
for (c, i, want) in [
|
||||
(Cursor::LivePaintSelectFace, &face, [true, false, true]),
|
||||
(Cursor::LivePaintSelectEdge, &edge, [false, true, false]),
|
||||
(Cursor::LivePaintSelectOutside, &out, [false, false, true]),
|
||||
] {
|
||||
assert_eq!(i.hotspot, arrow.hotspot, "{c:?} has the arrow's hotspot at {ppp}");
|
||||
assert!(inked(at(i, 1.5, 6.0)), "{c:?} is the solid arrow at {ppp}");
|
||||
let got = [square, mark, x_stroke].map(|(x, y)| inked(at(i, x, y)));
|
||||
assert_eq!(got, want, "{c:?} at {ppp}");
|
||||
assert!(c.stand_in().is_none(), "{c:?} is drawn");
|
||||
assert_ne!(i, &arrow, "{c:?} is not the plain arrow at {ppp}");
|
||||
assert_eq!(rasterize(c.precise(), ppp).as_ref(), Some(&cross), "{c:?} with Use Precise Cursors at {ppp}");
|
||||
}
|
||||
assert!(face != edge && edge != out && face != out, "three looks at {ppp}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn each_bitmap_is_made_once_so_the_os_cursor_is_kept() {
|
||||
let mut images = Images::default();
|
||||
|
||||
+3
-1
@@ -3398,7 +3398,9 @@ already walks Image Trace. Short agent entry points:
|
||||
nothing when it touches none. `selectFills` off leaves the faces out, and `selectStrokes` off leaves the edges out. A click and a marquee run their command on the
|
||||
release, and Escape between the press and the release removes the marquee so that the release runs nothing. The
|
||||
tool does not highlight or select the faces and edges of a Live Paint group that is locked, on a locked layer or on
|
||||
a locked artboard, or in isolation mode outside the isolated art.
|
||||
a locked artboard, or in isolation mode outside the isolated art. In the app, the tool's cursor shows what a click
|
||||
at the pointer selects under these rules: the arrow with a filled square for a face, with a short line for an edge,
|
||||
and with an x for nothing. It keeps the look it had at the press until the release.
|
||||
The Live Paint Bucket's options (`tool.setOption {tool: "livePaintBucket", values}`; double-clicking the tool opens
|
||||
them, dialog `livePaintBucketOptions`) are `paintFills` (on), `paintStrokes` (off), `highlight` (on), `color` (the
|
||||
highlight color, `#rrggbb` or a layer color's name; `#ff2a2a`) and `width` (the face highlight's width, 1 to 20 screen
|
||||
|
||||
@@ -2235,6 +2235,16 @@ Edit › Copy and Cut put the selected ruler guides on the clipboard, with the s
|
||||
`the_live_paint_bucket_shows_a_bucket_or_a_brush`. Behavior source:
|
||||
[the help page](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html).
|
||||
The cursor swatch preview is not built. Scores and estimates unchanged.
|
||||
- **Live Paint Selection cursors:** the pointer changes over a face, over an edge and outside the
|
||||
Live Paint groups ([the help page](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/modify-live-paint-groups.html)).
|
||||
The cursor is the arrow with a filled square where a click selects a face, with a short line
|
||||
where it selects an edge, and with an x where it selects nothing. It follows Alt, Select Fills
|
||||
and Select Strokes as a click does, shows nothing to select over a locked or hidden group or
|
||||
outside the isolated art, keeps its look from the press to the release, and turns into the
|
||||
crosshair with Use Precise Cursors. The drawings and these rules are VectorCraft's own. Tests:
|
||||
`live_paint_selection_cursor_shows_what_a_click_selects`,
|
||||
`live_paint_selection_shows_the_arrow_with_a_face_edge_or_x_badge`. An edge is still selected
|
||||
with Alt-click while both options are on. Scores and estimates unchanged.
|
||||
|
||||
## Revision history
|
||||
|
||||
|
||||
Reference in New Issue
Block a user