mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 17:56:50 -06:00
Merge pull request #1959 from Messhias/feat/symbol-registration
G5: Symbol Options Registration 9-point grid
This commit is contained in:
@@ -20,8 +20,10 @@ pub mod inks;
|
||||
mod inline;
|
||||
pub mod intertwine;
|
||||
pub mod shared;
|
||||
mod symbol_registration;
|
||||
pub use inline::{SYMBOL_HALF, SYMBOL_SIZES};
|
||||
pub use shared::Shared;
|
||||
pub use symbol_registration::{SYMBOL_REGISTRATION, SymbolRegistration};
|
||||
pub mod links;
|
||||
pub mod live;
|
||||
pub mod marks;
|
||||
@@ -1518,6 +1520,30 @@ impl Document {
|
||||
}
|
||||
(2..).map(|i| format!("{base} {i}")).find(|n| !taken(n)).unwrap_or_else(|| base.to_string())
|
||||
}
|
||||
|
||||
/// Symbol Options › Registration for `name` (default: centre).
|
||||
pub fn symbol_registration(&self, name: &str) -> SymbolRegistration {
|
||||
self.unknown
|
||||
.get(SYMBOL_REGISTRATION)
|
||||
.and_then(|m| m.get(name))
|
||||
.and_then(|v| v.as_u64())
|
||||
.and_then(SymbolRegistration::from_u64)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Set or clear (when centre) the registration point stored for `name`.
|
||||
pub fn set_symbol_registration(&mut self, name: &str, reg: SymbolRegistration) {
|
||||
let m = self.unknown.entry(SYMBOL_REGISTRATION.to_string()).or_insert_with(|| serde_json::json!({}));
|
||||
let Some(o) = m.as_object_mut() else { return };
|
||||
if reg.is_center() {
|
||||
o.remove(name);
|
||||
if o.is_empty() {
|
||||
self.unknown.remove(SYMBOL_REGISTRATION);
|
||||
}
|
||||
} else {
|
||||
o.insert(name.into(), serde_json::json!(reg.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_graphic_styles() -> Vec<GraphicStyle> {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//! Symbol Options › Registration: the 9-point grid (0 = top-left … 4 = centre … 8 = bottom-right)
|
||||
//! that `symbol.place` uses as the point that lands on the click.
|
||||
|
||||
use vectorcraft_geom::Vec2;
|
||||
|
||||
/// Document unknown key: `{ symbolName: 0..8 }` for each symbol's registration point.
|
||||
pub const SYMBOL_REGISTRATION: &str = "symbolRegistration";
|
||||
|
||||
/// Index on the 9-point grid (row-major, 4 = centre).
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct SymbolRegistration(pub u8);
|
||||
|
||||
impl Default for SymbolRegistration {
|
||||
fn default() -> Self {
|
||||
Self(4)
|
||||
}
|
||||
}
|
||||
|
||||
impl SymbolRegistration {
|
||||
pub const CENTER: Self = Self(4);
|
||||
|
||||
pub fn from_u64(v: u64) -> Option<Self> {
|
||||
(v <= 8).then_some(Self(v as u8))
|
||||
}
|
||||
|
||||
pub fn is_center(self) -> bool {
|
||||
self.0 == 4
|
||||
}
|
||||
|
||||
/// Offset of this registration point from the symbol's centre, in natural-size units
|
||||
/// (right +, down +).
|
||||
pub fn offset_from_center(self, w: f64, h: f64) -> Vec2 {
|
||||
let (col, row) = (self.0 % 3, self.0 / 3);
|
||||
Vec2::new((f64::from(col) - 1.0) * (w * 0.5), (f64::from(row) - 1.0) * (h * 0.5))
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use std::sync::Arc;
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_brush::{self as brush, Brush};
|
||||
use vectorcraft_color::{Color, Paint};
|
||||
use vectorcraft_doc::{AppearanceItem, Document, FillLayer, Node, NodeId, NodeKind, Symbol};
|
||||
use vectorcraft_doc::{AppearanceItem, Document, FillLayer, Node, NodeId, NodeKind, Symbol, SymbolRegistration};
|
||||
use vectorcraft_geom::{Affine, Point, Vec2};
|
||||
|
||||
use super::edit::selected_roots;
|
||||
@@ -95,13 +95,13 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
brush_freehand
|
||||
),
|
||||
// ----- symbols -----
|
||||
cmd!(query "symbol.list", "Symbols", [], None, "{} → {symbols: [{name, instances, size: [w,h]}], current}", has_doc, symbol_list),
|
||||
cmd!(query "symbol.list", "Symbols", [], None, "{} → {symbols: [{name, instances, size: [w,h], registration: 0..8}], current}", has_doc, symbol_list),
|
||||
cmd!(
|
||||
"symbol.new",
|
||||
"New Symbol…",
|
||||
[],
|
||||
None,
|
||||
"{name?, ids?|id?} make a symbol from the selection and replace it with an instance → {name, id}",
|
||||
"{name?, ids?|id?, registration?: 0..8 (9-point grid, 4 = centre; Symbol Options › Registration)} make a symbol from the selection and replace it with an instance → {name, id, registration}",
|
||||
has_selection,
|
||||
symbol_new
|
||||
),
|
||||
@@ -110,7 +110,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Place Symbol Instance",
|
||||
[],
|
||||
None,
|
||||
"{name?, x?, y?} place an instance centred at (x, y) (default: artboard centre; name default: current) → {id}",
|
||||
"{name?, x?, y?} place an instance so its registration point is at (x, y) (default: artboard centre; name default: current) → {id}",
|
||||
has_doc,
|
||||
symbol_place
|
||||
),
|
||||
@@ -511,11 +511,19 @@ fn set_natural_size(d: &mut Document, name: &str, size: Option<(f64, f64)>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Instance transform for a symbol of natural size `(w, h)` centred at `c`.
|
||||
fn place_xf(c: Point, (w, h): (f64, f64)) -> Affine {
|
||||
/// Instance transform for a symbol of natural size `(w, h)` whose registration point is at `at`.
|
||||
fn place_xf(at: Point, (w, h): (f64, f64), reg: SymbolRegistration) -> Affine {
|
||||
let c = at - reg.offset_from_center(w, h);
|
||||
Affine::translate(c.to_vec2()) * Affine::scale_non_uniform(w / (2.0 * HALF), h / (2.0 * HALF))
|
||||
}
|
||||
|
||||
fn registration_param(p: &Value, cmd: &str) -> Result<SymbolRegistration> {
|
||||
match p.get("registration") {
|
||||
None => Ok(SymbolRegistration::CENTER),
|
||||
Some(v) => v.as_u64().and_then(SymbolRegistration::from_u64).ok_or_else(|| bad(cmd, "registration must be 0..8")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Normalise art for a symbol definition: returns (art, natural size, centre in the document).
|
||||
fn normalize(mut art: Node) -> Result<(Node, (f64, f64), Point)> {
|
||||
let b = art.geometric_bounds().ok_or_else(|| EngineError::Other("the art has no bounds".into()))?;
|
||||
@@ -553,7 +561,12 @@ fn symbol_list(s: &mut Session, _: &Value) -> Result<Value> {
|
||||
.iter()
|
||||
.map(|sym| {
|
||||
let (w, h) = natural_size(d, &sym.name);
|
||||
json!({"name": sym.name, "instances": instances_of(d, Some(&sym.name)).len(), "size": [w, h]})
|
||||
json!({
|
||||
"name": sym.name,
|
||||
"instances": instances_of(d, Some(&sym.name)).len(),
|
||||
"size": [w, h],
|
||||
"registration": d.symbol_registration(&sym.name).0,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok(json!({ "symbols": list, "current": current_symbol(d).or_else(|| symbol_names(d).into_iter().next()) }))
|
||||
@@ -580,16 +593,20 @@ fn symbol_new(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let art = selection_art(s, p)?.ok_or_else(|| EngineError::Other("nothing selected".into()))?;
|
||||
let (art, size, c) = normalize(art)?;
|
||||
let name = s.doc()?.doc.unique_symbol_name(str_param(p, "name").filter(|n| !n.trim().is_empty()).unwrap_or("New Symbol"));
|
||||
let reg = registration_param(p, "symbol.new")?;
|
||||
// Keep the art where it was: the geometric centre stays at `c`, whatever the registration is.
|
||||
let place = place_xf(c + reg.offset_from_center(size.0, size.1), size, reg);
|
||||
let id = s.edit("New Symbol", |d, sel| {
|
||||
let art = d.reid(&art);
|
||||
d.symbols.push(Symbol { name: name.clone(), art: Arc::new(art) });
|
||||
set_natural_size(d, &name, Some(size));
|
||||
d.set_symbol_registration(&name, reg);
|
||||
d.unknown.insert(CURRENT_SYMBOL.into(), json!(name));
|
||||
let id = replace_with_instance(d, &ids, &name, place_xf(c, size))?;
|
||||
let id = replace_with_instance(d, &ids, &name, place)?;
|
||||
sel.set([id]);
|
||||
Ok(id)
|
||||
})?;
|
||||
Ok(json!({ "name": name, "id": id.0 }))
|
||||
Ok(json!({ "name": name, "id": id.0, "registration": reg.0 }))
|
||||
}
|
||||
|
||||
fn resolve_symbol(d: &Document, p: &Value, cmd: &str) -> Result<String> {
|
||||
@@ -606,12 +623,13 @@ fn symbol_place(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let d = &s.doc()?.doc;
|
||||
let name = resolve_symbol(d, p, "symbol.place")?;
|
||||
let centre = d.artboards.first().map(|a| a.rect.center()).unwrap_or(Point::ZERO);
|
||||
let c = Point::new(f64_or(p, "x", centre.x), f64_or(p, "y", centre.y));
|
||||
let at = Point::new(f64_or(p, "x", centre.x), f64_or(p, "y", centre.y));
|
||||
let size = natural_size(d, &name);
|
||||
let reg = d.symbol_registration(&name);
|
||||
let parent = s.doc()?.target_parent()?;
|
||||
let id = s.edit("Place Symbol Instance", |d, sel| {
|
||||
let id = d.alloc_id();
|
||||
d.insert(parent, usize::MAX, Node::new(id, NodeKind::SymbolInstance { symbol: name.clone(), xf: place_xf(c, size) }))?;
|
||||
d.insert(parent, usize::MAX, Node::new(id, NodeKind::SymbolInstance { symbol: name.clone(), xf: place_xf(at, size, reg) }))?;
|
||||
sel.set([id]);
|
||||
Ok(id)
|
||||
})?;
|
||||
@@ -720,7 +738,8 @@ fn symbol_update(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
*xf *= fix;
|
||||
}
|
||||
}
|
||||
let id = replace_with_instance(d, &ids, &name, place_xf(c, size))?;
|
||||
let reg = d.symbol_registration(&name);
|
||||
let id = replace_with_instance(d, &ids, &name, place_xf(c + reg.offset_from_center(size.0, size.1), size, reg))?;
|
||||
sel.set([id]);
|
||||
Ok(id)
|
||||
})?;
|
||||
@@ -743,6 +762,7 @@ fn symbol_delete(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
d.symbols.retain(|x| x.name != name);
|
||||
set_natural_size(d, &name, None);
|
||||
d.set_symbol_registration(&name, SymbolRegistration::CENTER);
|
||||
if d.unknown.get(CURRENT_SYMBOL).and_then(Value::as_str) == Some(name.as_str()) {
|
||||
d.unknown.remove(CURRENT_SYMBOL);
|
||||
}
|
||||
@@ -758,10 +778,12 @@ fn symbol_duplicate(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let sym = d.symbols.iter().find(|x| x.name == name).cloned().ok_or_else(|| bad(C, format!("no symbol named `{name}`")))?;
|
||||
let new = d.unique_symbol_name(str_param(p, "newName").unwrap_or(&format!("{name} copy")));
|
||||
let size = natural_size(d, &name);
|
||||
let reg = d.symbol_registration(&name);
|
||||
s.edit("Duplicate Symbol", |d, _| {
|
||||
let art = d.reid(&sym.art);
|
||||
d.symbols.push(Symbol { name: new.clone(), art: Arc::new(art) });
|
||||
set_natural_size(d, &new, Some(size));
|
||||
d.set_symbol_registration(&new, reg);
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(json!({ "name": new }))
|
||||
@@ -882,13 +904,14 @@ fn symbol_spray(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
placed.push(c);
|
||||
}
|
||||
let count = placed.len();
|
||||
let reg = s.doc()?.doc.symbol_registration(&name);
|
||||
let id = s.edit("Symbol Sprayer", |d, sel| {
|
||||
let mut nodes = vec![];
|
||||
for (i, c) in placed.iter().enumerate() {
|
||||
let (_, _, js) = jitter(i + 7, *c);
|
||||
let k = scale * (1.0 + js * 0.1);
|
||||
let id = d.alloc_id();
|
||||
nodes.push(Node::new(id, NodeKind::SymbolInstance { symbol: name.clone(), xf: place_xf(*c, size) * Affine::scale(k) }));
|
||||
nodes.push(Node::new(id, NodeKind::SymbolInstance { symbol: name.clone(), xf: place_xf(*c, size, reg) * Affine::scale(k) }));
|
||||
}
|
||||
let gid = match set {
|
||||
Some(g) => {
|
||||
|
||||
@@ -581,6 +581,7 @@ fn brushes_and_symbols_survive_vectorcraft_round_trip() {
|
||||
assert_eq!(vectorcraft_brush::find(&back, "Mine").map(|b| b.kind.type_id()), Some("calligraphic"));
|
||||
assert_eq!(back.symbols, doc.symbols);
|
||||
assert_eq!(back.unknown.get("symbolSizes"), doc.unknown.get("symbolSizes"));
|
||||
assert_eq!(back.unknown.get(vectorcraft_doc::SYMBOL_REGISTRATION), doc.unknown.get(vectorcraft_doc::SYMBOL_REGISTRATION));
|
||||
let bl = back.node(l).unwrap();
|
||||
assert_eq!(bl.appearance.stroke().unwrap().brush.as_deref(), Some("Mine"));
|
||||
// A reloaded document places instances at the natural size.
|
||||
@@ -590,3 +591,19 @@ fn brushes_and_symbols_survive_vectorcraft_round_trip() {
|
||||
let b = s2.doc().unwrap().doc.node(NodeId(r["id"].as_u64().unwrap())).unwrap().geometric_bounds().unwrap();
|
||||
assert!(close(b, Rect::new(60.0, 80.0, 140.0, 120.0), 1e-9));
|
||||
}
|
||||
|
||||
/// Symbol Options › Registration: place puts the chosen 9-point grid point on (x, y).
|
||||
#[test]
|
||||
fn symbol_registration_places_the_chosen_point_on_xy() {
|
||||
let mut s = session();
|
||||
rect(&mut s, 0.0, 0.0, 80.0, 40.0);
|
||||
let r = s.execute("symbol.new", &json!({"name": "Corner", "registration": 0})).unwrap();
|
||||
assert_eq!(r["registration"], 0);
|
||||
assert_eq!(s.execute("symbol.list", &json!({})).unwrap()["symbols"][0]["registration"], 0);
|
||||
// Creating kept the art where it was (top-left still at the origin of the selection).
|
||||
let inst = NodeId(r["id"].as_u64().unwrap());
|
||||
assert!(close(bounds(&s, inst), Rect::new(0.0, 0.0, 80.0, 40.0), 1e-9), "{:?}", bounds(&s, inst));
|
||||
let p = NodeId(s.execute("symbol.place", &json!({"name": "Corner", "x": 300, "y": 200})).unwrap()["id"].as_u64().unwrap());
|
||||
assert!(close(bounds(&s, p), Rect::new(300.0, 200.0, 380.0, 240.0), 1e-9), "{:?}", bounds(&s, p));
|
||||
assert!(s.execute("symbol.new", &json!({"registration": 9})).is_err());
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Symbol Options: the name of the symbol New Symbol makes from the selection (`symbol.new`), asked
|
||||
//! before the symbol is made, as the Symbols panel's New Symbol button and menu item do.
|
||||
//! Symbol Options: the name and registration point of the symbol New Symbol makes from the
|
||||
//! selection (`symbol.new`), as the Symbols panel's New Symbol button and menu item do.
|
||||
//!
|
||||
//! Fields: `name`.
|
||||
//! Fields: `name`, `registration` (0..8, the 9-point grid; 4 = centre).
|
||||
|
||||
use serde_json::{Value, json};
|
||||
|
||||
@@ -9,6 +9,7 @@ use super::swatch_options::{grid, label};
|
||||
use super::{DialogSpec, form};
|
||||
use crate::VectorcraftApp;
|
||||
use crate::state::Dialog;
|
||||
use crate::widgets;
|
||||
|
||||
/// The dialog kind of Symbol Options.
|
||||
pub const KIND: &str = "symbolOptions";
|
||||
@@ -22,7 +23,7 @@ pub fn open(app: &mut VectorcraftApp) -> Result<Value, String> {
|
||||
return Err("nothing selected".into());
|
||||
}
|
||||
let name = st.doc.unique_symbol_name("New Symbol");
|
||||
app.ui.dialog = Some(Dialog::new(KIND, json!({ "name": name })));
|
||||
app.ui.dialog = Some(Dialog::new(KIND, json!({ "name": name, "registration": 4 })));
|
||||
Ok(Value::Null)
|
||||
}
|
||||
|
||||
@@ -31,13 +32,25 @@ fn body(_: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool {
|
||||
label(ui, tl!("Name:"));
|
||||
form::text(ui, d, "name", 190.0);
|
||||
ui.end_row();
|
||||
label(ui, tl!("Registration:"));
|
||||
let cur = d.fields.get("registration").and_then(Value::as_u64).unwrap_or(4) as usize;
|
||||
if let Some(i) = widgets::reference_point(ui, cur) {
|
||||
d.fields.insert("registration".into(), json!(i));
|
||||
}
|
||||
ui.end_row();
|
||||
});
|
||||
false
|
||||
}
|
||||
|
||||
/// OK: make the symbol from the selection with the name typed.
|
||||
/// OK: make the symbol from the selection with the name and registration chosen.
|
||||
fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result<Value, String> {
|
||||
let r = app.run("symbol.new", json!({ "name": d.str("name") }));
|
||||
let r = app.run(
|
||||
"symbol.new",
|
||||
json!({
|
||||
"name": d.str("name"),
|
||||
"registration": d.fields.get("registration").and_then(Value::as_u64).unwrap_or(4),
|
||||
}),
|
||||
);
|
||||
if r.is_ok() {
|
||||
app.ui.dialog = None;
|
||||
}
|
||||
|
||||
@@ -4877,6 +4877,22 @@ theme Appearance Външен вид
|
||||
@msg span: "selection" places a gradient: give `gradient` span: "selection" поставя градиент: задайте `gradient`
|
||||
@msg span: "selection" places a linear or radial gradient, not a freeform one span: "selection" поставя линеен или радиален градиент, а не свободен
|
||||
@msg span: "selection" places the gradient itself: leave out `start` and `end` (they already place it in document coordinates) span: "selection" поставя самия градиент: пропуснете `start` и `end` (те вече го поставят в координатите на документа)
|
||||
Make Image Dynamic Динамично изображение
|
||||
Import Data Sets… Импортиране на набори от данни…
|
||||
Export Data Sets… Експортиране на набори от данни…
|
||||
Make Graph Dynamic Динамична диаграма
|
||||
Batch… Пакет…
|
||||
Source Folder: Изходна папка:
|
||||
Destination Folder: Целева папка:
|
||||
Overrides Заместване
|
||||
Uses every data set of the open document. Използва всеки набор от данни на отворения документ.
|
||||
@msg Batch: {count} processed Пакет: обработени {count}
|
||||
@msg Batch: {count} processed, {failed} failed Пакет: обработени {count}, неуспешни {failed}
|
||||
@msg choose a destination folder изберете целева папка
|
||||
@msg choose a source folder изберете изходна папка
|
||||
@msg open a document with data sets отворете документ с набори от данни
|
||||
@msg the action has no steps действието няма стъпки
|
||||
Registration: Регистрация:
|
||||
# Layers panel filters (Filter Layers Panel Rows) and Color Panel Options
|
||||
By Layer По слой
|
||||
By Object По обект
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4858,9 +4858,9 @@ mark-style Japanese Japonské
|
||||
Softness Měkkost
|
||||
Ambient Light Okolní světlo
|
||||
Light behind the object Světlo za objektem
|
||||
Registration: Registrace:
|
||||
# Dimension tool (linked dimension annotations)
|
||||
Display Zobrazení
|
||||
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Rozměr
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Výkres : skutečná velikost — 1:10 označí 1 jednotku na stránce jako 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4391,7 +4391,7 @@ theme Appearance Erscheinungsbild
|
||||
Softness Weichheit
|
||||
Ambient Light Umgebungslicht
|
||||
Light behind the object Licht hinter dem Objekt
|
||||
|
||||
Registration: Registrierung:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Bemaßung
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Zeichnung : reale Größe — 1:10 beschriftet 1 Einheit auf der Seite als 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4799,6 +4799,7 @@ mark-style Japanese Japonesas
|
||||
Softness Suavidad
|
||||
Ambient Light Luz ambiental
|
||||
Light behind the object Luz detrás del objeto
|
||||
Registration: Registro:
|
||||
# Dimension tool (linked dimension annotations)
|
||||
Create Dimension Crear cota
|
||||
Dimension Tool Herramienta Cota
|
||||
@@ -4808,7 +4809,6 @@ mark-style Japanese Japonesas
|
||||
Precision: Precisión:
|
||||
Update Dimensions Actualizar cotas
|
||||
Display Visualización
|
||||
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Cota
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Dibujo : tamaño real — 1:10 rotula 1 unidad de la página como 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4858,7 +4858,7 @@ theme Appearance Apparence
|
||||
Softness Douceur
|
||||
Ambient Light Lumière ambiante
|
||||
Light behind the object Lumière derrière l'objet
|
||||
|
||||
Registration: Repère d'alignement :
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Cote
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Dessin : taille réelle — 1:10 étiquette 1 unité de la page comme 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4825,7 +4825,7 @@ imageTrace Outline Körvonal
|
||||
Softness Lágyság
|
||||
Ambient Light Környezeti fény
|
||||
Light behind the object Fény az objektum mögött
|
||||
|
||||
Registration: Regisztráció:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Méret
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Rajz : valós méret — 1:10 esetén az oldalon 1 egység 10-ként jelenik meg.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4431,7 +4431,7 @@ lighting Light Luce
|
||||
Softness Morbidezza
|
||||
Ambient Light Luce ambientale
|
||||
Light behind the object Luce dietro l'oggetto
|
||||
|
||||
Registration: Registrazione:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Quota
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Disegno : dimensione reale — 1:10 indica 1 unità sulla pagina come 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4425,6 +4425,7 @@ lighting Light ライト
|
||||
Softness 柔らかさ
|
||||
Ambient Light 環境光
|
||||
Light behind the object オブジェクトの背後のライト
|
||||
Registration: 基準点:
|
||||
# Dimension tool (linked dimension annotations)
|
||||
Create Dimension 寸法を作成
|
||||
Dimension Tool 寸法ツール
|
||||
@@ -4434,7 +4435,6 @@ lighting Light ライト
|
||||
Precision: 精度:
|
||||
Update Dimensions 寸法を更新
|
||||
Display 表示
|
||||
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension 寸法
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. 図面 : 実寸 — 1:10 では、ページ上の 1 単位を 10 と表示します。
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4395,7 +4395,7 @@ lighting Light 광원
|
||||
Softness 부드러움
|
||||
Ambient Light 주변광
|
||||
Light behind the object 개체 뒤의 조명
|
||||
|
||||
Registration: 기준점:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension 치수
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. 도면 : 실제 크기 — 1:10은 페이지의 1단위를 10으로 표시합니다.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4688,6 +4688,7 @@ mark-style Japanese Japońskie
|
||||
Softness Miękkość
|
||||
Ambient Light Światło otoczenia
|
||||
Light behind the object Światło za obiektem
|
||||
Registration: Punkt rejestracji:
|
||||
Legacy (version 7) Starsza (wersja 7)
|
||||
Transparent Images: Przezroczyste obrazy:
|
||||
Flatten Spłaszcz
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3800,6 +3800,7 @@ axis Both Ambos
|
||||
Softness Suavidade
|
||||
Ambient Light Luz ambiente
|
||||
Light behind the object Luz atrás do objeto
|
||||
Registration: Registro:
|
||||
# Dimension tool (linked dimension annotations)
|
||||
Dimension Tool Ferramenta Cota
|
||||
Create Dimension Criar Cota
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4427,7 +4427,7 @@ lighting Light Свет
|
||||
Softness Мягкость
|
||||
Ambient Light Окружающий свет
|
||||
Light behind the object Свет позади объекта
|
||||
|
||||
Registration: Регистрация:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Размер
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Чертёж : реальный размер — при 1:10 1 единица на странице подписывается как 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4411,7 +4411,7 @@ lighting Light Світло
|
||||
Softness М'якість
|
||||
Ambient Light Навколишнє світло
|
||||
Light behind the object Світло позаду об'єкта
|
||||
|
||||
Registration: Реєстрація:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Розмір
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Креслення : реальний розмір — при 1:10 1 одиниця на сторінці підписується як 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 718 and column 40.
|
@@ -4413,6 +4413,7 @@ theme Appearance Giao diện
|
||||
Softness Độ mềm
|
||||
Ambient Light Ánh sáng môi trường
|
||||
Light behind the object Ánh sáng phía sau đối tượng
|
||||
Registration: Điểm đăng ký:
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension Kích thước
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. Bản vẽ : kích thước thực — 1:10 ghi 1 đơn vị trên trang thành 10.
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3726 and column 10.
|
@@ -3999,6 +3999,7 @@ lighting Light 光源
|
||||
Softness 柔和度
|
||||
Ambient Light 环境光
|
||||
Light behind the object 光源位于对象后方
|
||||
Registration: 对齐点:
|
||||
# Dimension tool (linked dimension annotations)
|
||||
Create Dimension 创建尺寸标注
|
||||
Dimension Tool 尺寸标注工具
|
||||
@@ -4008,7 +4009,6 @@ lighting Light 光源
|
||||
Precision: 精度:
|
||||
Update Dimensions 更新尺寸标注
|
||||
Display 显示
|
||||
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension 尺寸
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. 图纸 : 实际尺寸 — 1:10 会将页面上的 1 个单位标注为 10。
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3784,6 +3784,7 @@ lighting Light 光源
|
||||
Softness 柔和度
|
||||
Ambient Light 環境光
|
||||
Light behind the object 光源位於物件後方
|
||||
Registration: 對齊點:
|
||||
# Dimension tool (linked dimension annotations)
|
||||
Create Dimension 建立尺寸標註
|
||||
Dimension Tool 尺寸標註工具
|
||||
@@ -3793,7 +3794,6 @@ lighting Light 光源
|
||||
Precision: 精確度:
|
||||
Update Dimensions 更新尺寸標註
|
||||
Display 顯示
|
||||
|
||||
# Dimension tool and Object › Dimensions (dimension groups, their dialog and messages).
|
||||
Dimension 尺寸
|
||||
Drawing : real size — 1:10 labels 1 unit on the page as 10. 圖紙 : 實際尺寸 — 1:10 會將頁面上的 1 個單位標示為 10。
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -449,7 +449,7 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
"ui.symbolOptions",
|
||||
"Symbol Options…",
|
||||
"",
|
||||
"{} open Symbol Options for a new symbol made from the selection, what the Symbols panel's New Symbol opens (dialog `symbolOptions`, field `name`, default the first free \"New Symbol\"/\"New Symbol N\"); OK runs symbol.new {name}",
|
||||
"{} open Symbol Options for a new symbol made from the selection, what the Symbols panel's New Symbol opens (dialog `symbolOptions`, fields `name` and `registration` 0..8 on the 9-point grid, default centre; default name the first free \"New Symbol\"/\"New Symbol N\"); OK runs symbol.new {name, registration}",
|
||||
),
|
||||
(
|
||||
"tool.options",
|
||||
|
||||
+4
-3
@@ -25,7 +25,7 @@ stage ([ROADMAP.md](../ROADMAP.md)).
|
||||
| 8 | [G2 Photoshop-style raster effects and the Effect Gallery](#g2-photoshop-style-raster-effects-and-the-effect-gallery) | 23–39 | no | [effects-parity.md](effects-parity.md) |
|
||||
| 9 | [G13 Illustrator 2026 (30.x) additions](#g13-illustrator-2026-30x-additions) | 15–25 | no | [target-app-parity.md](target-app-parity.md) |
|
||||
| 10 | [G14 Pen hardware beyond Windows pressure](#g14-pen-hardware-beyond-windows-pressure) | 8–16 | macOS pressure | [hardware-parity.md](hardware-parity.md) |
|
||||
| 11 | [G5 Brushes, symbols and libraries](#g5-brushes-symbols-and-libraries) | 17–28 | no | [target-app-parity.md](target-app-parity.md) |
|
||||
| 11 | [G5 Brushes, symbols and libraries](#g5-brushes-symbols-and-libraries) | 16–27 | no | [target-app-parity.md](target-app-parity.md) |
|
||||
| 12 | [G3 3D and Materials](#g3-3d-and-materials) | 25–45 | no | [effects-parity.md](effects-parity.md) |
|
||||
| 13 | [G7 Views and windows](#g7-views-and-windows) | 15–25 | no | [ui-parity.md](ui-parity.md) |
|
||||
| 14 | [G6 Automation and scripting](#g6-automation-and-scripting) | 8–14 | no | [target-app-parity.md](target-app-parity.md) |
|
||||
@@ -240,8 +240,9 @@ from G14 and the budget run of G15: **~170–270 h** one agent, ~50–80 h wall
|
||||
|
||||
- **Missing:** the Art brush's Overlap, auto-generated Pattern brush corners, new tile art in Pattern Brush
|
||||
Options, the Key Color eyedropper; original brush, symbol and graphic-style libraries generated in code (never
|
||||
Adobe's); dynamic symbols; Start Global Edit.
|
||||
- **Estimate:** 17–28 h.
|
||||
Adobe's); dynamic symbols; Start Global Edit. Symbol Options › Registration (9-point) is stored and
|
||||
used by `symbol.place`; export type and 9-slice guides still missing.
|
||||
- **Estimate:** 16–27 h.
|
||||
|
||||
## G3 3D and Materials
|
||||
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ panel-menu commands such as Break Link to Symbol), so they can be given shortcut
|
||||
| Pathfinder shape results keep their source names and SVG IDs | done | #1293; Minus Front keeps the back name, Minus Back the front name; Unite/Intersect/Exclude use the backmost named input; compound output carries it once; geometry and paint unchanged |
|
||||
| Attributes fill-rule controls with a compound member selected | done | Edits the compound's rule; direction still edits only the member; rendered-hole and Undo/Redo regression tests (#1197) |
|
||||
| Make Compound Path on a group (such as outlined type) keeps its backmost path's paint; compound paths joined into one keep their holes | done | #1537 |
|
||||
| Symbols panel: New Symbol opens Symbol Options (Name) before making the symbol; Alt-click skips it | partial | #1560 (#1566); the dialog has Name only: export type, static or dynamic, registration and 9-slice settings missing |
|
||||
| Symbols panel: New Symbol opens Symbol Options (Name) before making the symbol; Alt-click skips it | partial | #1560 (#1566); Registration 9-point grid in Symbol Options (`symbol.new` / `symbol.place`); export type, static or dynamic and 9-slice settings still missing |
|
||||
| Pathfinder Trim, Merge and Crop remove strokes; Merge joins same-fill objects whatever their strokes | done | #1570 (#1572) |
|
||||
| Pathfinder panel on one group selected alone; a greyed-out button says what it needs | partial | #1450; the group's members are combined; one plain path selected alone stays disabled (the public documentation doesn't say what the operations do to a single path) |
|
||||
| Pathfinder Divide: an open cutting line splits a filled path | done | #1307; straight, crossed, bent and curved cutters, holes and frontmost appearance regression-tested; native automation: independent piece movement, one Undo/Redo, saved-document round trip and window capture; existing bounded-map fallback remains |
|
||||
|
||||
Reference in New Issue
Block a user