mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 21:44:57 +00:00
Live Paint Bucket Options gets a Cursor Swatch Preview checkbox (on at first, saved with the other options). With the Bucket selected, Left and Right set the active fill, or the stroke when the Stroke proxy is in front, to the color swatch before or after it in the Swatches panel, wrapping around at the ends, with the preview on or off. The selected art keeps its paint. The preview shows the active paint above the pointer between the swatches before and after it; a color that is no swatch shows alone until Right picks the first swatch or Left the last, and a paint that is not a solid color shows no chip. The chips hide during a fill drag and while Alt samples with the eyedropper. The fill and the stroke each remember the swatch picked for them, so swatches of the same color are each reached in turn. The Bucket and the Shape Builder now take the arrows for swatches only without Shift, Alt or Cmd/Ctrl, judged by the modifiers held when the key went down, so modified arrows keep their shortcuts (Tool::claims_key_with, Session::tool_claims_key_with). Docs: docs/mcp.md, docs/target-app-parity.md, tool.options params text.
139 lines
6.3 KiB
Rust
139 lines
6.3 KiB
Rust
//! Tool options that persist: a tool keeps them when another tool is chosen and they are saved
|
|
//! with the preferences, as the reference app keeps each tool's options. Options that are the
|
|
//! state of an interaction (pins, a reference point, the text being edited, the files a place
|
|
//! cursor holds) aren't listed: they start afresh.
|
|
//!
|
|
//! Each row names the tools it covers, the store their values live in and the option keys. A row
|
|
//! with a shared store gives every tool it lists one set of values: the Liquify tools share their
|
|
//! Global Brush Dimensions, the Symbolism tools their brush. Otherwise each tool has its own store,
|
|
//! named after its id.
|
|
|
|
/// (tools, the store they share (None: each tool's own), option keys).
|
|
type Row = (&'static [&'static str], Option<&'static str>, &'static [&'static str]);
|
|
|
|
/// The Liquify tools.
|
|
pub const LIQUIFY: &[&str] = &["warp", "twirl", "pucker", "bloat", "scallop", "crystallize", "wrinkle"];
|
|
|
|
/// The Symbolism tools.
|
|
pub const SYMBOLISM: &[&str] =
|
|
&["symbolSprayer", "symbolShifter", "symbolScruncher", "symbolSizer", "symbolSpinner", "symbolStainer", "symbolScreener", "symbolStyler"];
|
|
|
|
const ROWS: &[Row] = &[
|
|
(&["dimension"], None, &["mode", "style"]),
|
|
// Global Brush Dimensions.
|
|
(LIQUIFY, Some("liquify"), &["width", "height", "angle", "intensity", "usePressure", "showBrush"]),
|
|
(LIQUIFY, None, &["detail", "simplify", "simplifyOn", "rate", "complexity", "horizontal", "vertical", "affectAnchors", "affectIn", "affectOut"]),
|
|
(SYMBOLISM, Some("symbolism"), &["diameter", "intensity", "density"]),
|
|
(&["mirrorCut"], None, &["axis", "keep"]),
|
|
(&["puppetWarp"], None, &["showMesh", "expand"]),
|
|
(&["arc"], None, &["closed", "lengthX", "lengthY", "reference", "baseAlong", "slope", "fillArc"]),
|
|
(&["spiral"], None, &["decay", "segments", "clockwise"]),
|
|
// The grids' Tool Options: the dividers and switches the drag uses, the Default Size and
|
|
// Reference Point a click's dialog opens with.
|
|
(&["rectangularGrid"], None, &["rows", "columns", "rowSkew", "columnSkew", "frame", "fill", "width", "height", "reference"]),
|
|
(&["polarGrid"], None, &["concentric", "radial", "concentricSkew", "radialSkew", "compound", "fill", "width", "height", "reference"]),
|
|
// Line Segment Tool Options: the Length and Angle a click's dialog opens with, Fill Line.
|
|
(&["lineSegment"], None, &["length", "angle", "fillLine"]),
|
|
(&["pencil", "paintbrush"], None, &["fidelity", "fill", "keepSelected", "editWithin", "closeWithin"]),
|
|
// Pencil Tool Options' Alt key toggles to Smooth Tool, Live preview and Live curve fitting (the
|
|
// Paintbrush has none of them).
|
|
(&["pencil"], None, &["altSmooth", "livePreview", "liveFit"]),
|
|
(&["smooth"], None, &["fidelity"]),
|
|
(&["blobBrush", "eraser"], None, &["size", "sizeMode", "sizeVariation"]),
|
|
(&["blobBrush"], None, &["fidelity", "keepSelected", "mergeOnlySelection"]),
|
|
// Eraser Tool Options' tip shape.
|
|
(&["blobBrush", "eraser"], None, &["angle", "roundness"]),
|
|
// Live Paint Selection Tool Options (`builder::LivePaintSelectionTool`).
|
|
(&["livePaintSelection"], None, &["selectFills", "selectStrokes", "color", "width"]),
|
|
// Live Paint Bucket Options (`builder::LivePaintBucketTool`).
|
|
(&["livePaintBucket"], None, &["paintFills", "paintStrokes", "cursorSwatchPreview", "highlight", "color", "width"]),
|
|
(&["polygon"], None, &["sides"]),
|
|
(&["star"], None, &["points"]),
|
|
(&["freeTransform"], None, &["constrain"]),
|
|
// Shape Builder Tool Options (`builder::ShapeBuilderOptions`).
|
|
(
|
|
&["shapeBuilder"],
|
|
None,
|
|
&[
|
|
"openFilledAsClosed",
|
|
"pickColorFrom",
|
|
"cursorSwatchPreview",
|
|
"selection",
|
|
"highlightFill",
|
|
"gapDetection",
|
|
"gapLength",
|
|
"clickStrokeSplitsPath",
|
|
"highlightStroke",
|
|
"highlightColor",
|
|
],
|
|
),
|
|
// Objects on Path Tool Options: the Pivot and Rotate of the objects attached next.
|
|
(&["objectsOnPath"], None, &["pivot", "rotate"]),
|
|
(&["artboard"], None, &["moveArt", "scaleArt"]),
|
|
// The add-ons' tools (`crate::addons`).
|
|
(&[crate::addons::anchor_eraser::ID], None, &["size", "tolerance", "pressure"]),
|
|
(&[crate::addons::extend_path::ID], None, &["mode"]),
|
|
(&[crate::addons::corner_tool::ID], None, &["radius", "kind"]),
|
|
(&[crate::addons::shared_edge::ID], None, &["diameter", "tolerance", "together"]),
|
|
(&[crate::addons::smart_pen::ID], None, &["next"]),
|
|
// The kind first: a new kind resets the values after it.
|
|
(&[crate::addons::parametric_shape::ID], None, &["kind", "count", "a", "b", "radius", "width", "height", "rotation"]),
|
|
// Flare Tool Options (`extra::FLARE_OPTIONS` and the Rays and Rings checkboxes).
|
|
(
|
|
&["flare"],
|
|
None,
|
|
&[
|
|
"diameter",
|
|
"opacity",
|
|
"brightness",
|
|
"growth",
|
|
"fuzziness",
|
|
"raysOn",
|
|
"rays",
|
|
"longest",
|
|
"rayFuzziness",
|
|
"ringsOn",
|
|
"pathLength",
|
|
"rings",
|
|
"largest",
|
|
"direction",
|
|
],
|
|
),
|
|
];
|
|
|
|
/// The stores `tool`'s persistent options live in, each with the option keys it holds.
|
|
pub fn stores(tool: &str) -> impl Iterator<Item = (&'static str, &'static [&'static str])> + '_ {
|
|
ROWS.iter().filter_map(move |(tools, shared, keys)| {
|
|
let id = tools.iter().find(|t| **t == tool)?;
|
|
Some((shared.unwrap_or(id), *keys))
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn every_listed_option_is_one_the_tool_reports() {
|
|
for (tools, _, keys) in ROWS {
|
|
for id in *tools {
|
|
assert!(crate::tool_info(id).is_some(), "{id} is a tool");
|
|
let opts = crate::create(id).options();
|
|
for k in *keys {
|
|
assert!(opts.get(*k).is_some(), "{id} reports `{k}` in {opts}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn liquify_tools_share_the_global_brush() {
|
|
let warp: Vec<_> = stores("warp").collect();
|
|
let twirl: Vec<_> = stores("twirl").collect();
|
|
assert_eq!(warp[0], twirl[0]);
|
|
assert_eq!(warp[0].0, "liquify");
|
|
assert_eq!((warp[1].0, twirl[1].0), ("warp", "twirl"));
|
|
assert_eq!(stores("selection").count(), 0);
|
|
}
|
|
}
|