mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 13:17:19 -06:00
Plug-ins: filters keep data with the document (G17)
A filter plug-in had nowhere to keep settings that belong to the whole document rather than to one object, such as the pens a plotter holds or a machine profile: it could only ask for them again on every run. - A filter's output may hold documentData: any JSON of at most 1 MiB (objects::MAX_DOCUMENT_DATA) that replaces what the plug-in keeps with the document, null removing it, in the same undo step as its objects (objects::decode_output). Too much refuses the output and the document stays as it was. - A filter gets it back in _context.documentData (null until it keeps something). A filter reads and writes only its own. - It is the document's foreign data, Document::unknown["pluginData"] by plug-in id (vectorcraft_doc::plugin_data), where the perspective grid and the brushes keep theirs. So the native file needs no section of its own for it, and hosts from before keep it when they save. An exporter is given the whole document, so it can read every plug-in's. Nothing else lists it, as the reference app's Document Info lists no plug-in data. A live effect isn't given it: its geometry is worked out from the object alone wherever it is drawn. Tests: plugin_data.rs (each plug-in its own entry, forgetting what isn't kept copies nothing, a damaged value holds nothing), objects/tests.rs (kept, forgotten, refused over the limit), tests_plugins.rs (one undo step with the objects, read back, not given to another filter, kept by the native file among its foreign data, refused over the limit with the document unchanged, null removes it) and tests/plugin_export.rs (an exporter finds another plug-in's). The size error has its row in each complete catalog (COMPLETE_MESSAGES). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhvnnnD5fTFupK8WWq35un
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
e93a73f60b
commit
1505384501
@@ -4,9 +4,10 @@
|
||||
//! [`Session::attach_plugin_store`]) or from every `*.wasm` in the Additional Plug-ins Folder
|
||||
//! preference, and listed with `plugin.list` / `plugin.info`. Object filters run
|
||||
//! with `plugin.run` on the selected paths and compound paths (one undo step, transactional: a
|
||||
//! plug-in that fails leaves the document untouched); live-effect plug-ins are applied like any
|
||||
//! effect (`effect.apply {effect: "plugin.<id>"}`) and drawn by `vectorcraft-effects`; exporters
|
||||
//! add a file format that `document.export` writes (`fileio::plugin_formats`).
|
||||
//! plug-in that fails leaves the document untouched), and read and write the data they keep with
|
||||
//! the document ([`vectorcraft_doc::plugin_data`], theirs alone); live-effect plug-ins are applied
|
||||
//! like any effect (`effect.apply {effect: "plugin.<id>"}`) and drawn by `vectorcraft-effects`;
|
||||
//! exporters add a file format that `document.export` writes (`fileio::plugin_formats`).
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@@ -60,8 +61,9 @@ fn plugin_by_id(cmd: &str, p: &Value) -> Result<Arc<Plugin>> {
|
||||
}
|
||||
|
||||
/// `plugin.run`: runs filter `id` on `ids` (else the selected paths and compound paths) with its
|
||||
/// parameters and `_context`, and applies its output as one undo step ([`objects::apply_output`];
|
||||
/// effect records as [`admit_effects`] admits them). → `{plugin, ids}`: what it made or changed,
|
||||
/// parameters and `_context` (what it keeps with the document included), and applies its output as
|
||||
/// one undo step ([`objects::apply_output`]; effect records as [`admit_effects`] admits them),
|
||||
/// with what it keeps with the document from now on. → `{plugin, ids}`: what it made or changed,
|
||||
/// which is then selected.
|
||||
fn run(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "plugin.run";
|
||||
@@ -85,12 +87,17 @@ fn run(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let bounds = st.doc.bounds_of(&inputs, false);
|
||||
let board = bounds.and_then(|b| st.doc.artboard_at(b.center())).and_then(|i| st.doc.artboards.get(i)).or(st.doc.artboards.first());
|
||||
let rect = |r: vectorcraft_geom::Rect| json!([r.x0, r.y0, r.x1, r.y1]);
|
||||
params["_context"] = json!({"mode": "filter", "bounds": bounds.map(rect), "artboard": board.map(|a| rect(a.rect))});
|
||||
// What the plug-in keeps with the document, as it last wrote it.
|
||||
let data = st.doc.plugin_data(&m.id).cloned().unwrap_or(Value::Null);
|
||||
params["_context"] = json!({"mode": "filter", "bounds": bounds.map(rect), "artboard": board.map(|a| rect(a.rect)), "documentData": data});
|
||||
let input = objects::encode_input(&st.doc, &inputs);
|
||||
let params = serde_json::to_vec(¶ms).map_err(|e| bad(C, e.to_string()))?;
|
||||
let out = objects::decode(&plugin.run(&input, ¶ms).map_err(err)?).map_err(err)?;
|
||||
let out = objects::decode_output(&plugin.run(&input, ¶ms).map_err(err)?).map_err(err)?;
|
||||
let ids = s.edit(m.name.trim_end_matches('…'), |d, sel| {
|
||||
let ids = objects::apply_output(d, &inputs, out, parent, &admit_effects).map_err(err)?;
|
||||
let ids = objects::apply_output(d, &inputs, out.objects, parent, &admit_effects).map_err(err)?;
|
||||
if let Some(data) = out.document_data {
|
||||
d.set_plugin_data(&m.id, data);
|
||||
}
|
||||
sel.set(ids.iter().copied());
|
||||
Ok(ids)
|
||||
})?;
|
||||
|
||||
Reference in New Issue
Block a user