mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 09:39:52 +00:00
3D and Materials: Expand as Wireframes takes a compound path member as its compound path
A path inside a compound path given in ids was replaced by a group inside the compound path, which reads its members as paths, so the edges did not draw. The compound path is now expanded in its place. The panel's Quick Actions show on the Object tab of Revolve (Classic), not on its Rotation tab, as for the other effects with an Object tab.
This commit is contained in:
@@ -25,7 +25,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Expand as Wireframes",
|
||||
[],
|
||||
None,
|
||||
"{ids?: [..] (default: the selected objects)} replace each object that has a visible 3D effect (Extrude & Bevel, Revolve, Inflate, Rotate or one of their 3D (Classic) forms, on the object or on its fills and strokes) with a group of paths: the edges of the faces the effect draws, as the object is turned and projected now, each edge once (edges that meet end to end make one path, closed where it comes back to its start; curved edges stay curves; geometry effects after the 3D effect, on the object or on a fill or stroke, reshape them too), stroked 0.5 pt black with round joins and no fill (VectorCraft's own); the group takes the object's place, id, name, opacity, blending mode, opacity mask, attributes, slice and text wrap and is selected (a layer stays a layer holding the edges, which are selected, and its ruler guides and paths made into guides); objects without a visible 3D effect are left as they are; one undo step. An error, with nothing changed, when no object is selected or given, when none has a visible 3D effect, when an object's solid can't be built or the canvas draws its source art in its place, or when one object's wireframe has more than 1,000,000 edges → {ids}",
|
||||
"{ids?: [..] (default: the selected objects)} replace each object that has a visible 3D effect (Extrude & Bevel, Revolve, Inflate, Rotate or one of their 3D (Classic) forms, on the object or on its fills and strokes) with a group of paths: the edges of the faces the effect draws, as the object is turned and projected now, each edge once (edges that meet end to end make one path, closed where it comes back to its start; curved edges stay curves; geometry effects after the 3D effect, on the object or on a fill or stroke, reshape them too), stroked 0.5 pt black with round joins and no fill (VectorCraft's own); the group takes the object's place, id, name, opacity, blending mode, opacity mask, attributes, slice and text wrap and is selected (a layer stays a layer holding the edges, which are selected, and its ruler guides and paths made into guides; a path inside a compound path in ids stands for the compound path); objects without a visible 3D effect are left as they are; one undo step. An error, with nothing changed, when no object is selected or given, when none has a visible 3D effect, when an object's solid can't be built or the canvas draws its source art in its place, or when one object's wireframe has more than 1,000,000 edges → {ids}",
|
||||
has_doc,
|
||||
expand_as_wireframes
|
||||
)]
|
||||
@@ -68,7 +68,9 @@ fn expand_as_wireframes(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let mut wires = vec![];
|
||||
let mut seen = std::collections::HashSet::new();
|
||||
for id in roots {
|
||||
// An id given twice is expanded once.
|
||||
// A path inside a compound path stands for the compound path, which draws it. An id given
|
||||
// twice is expanded once.
|
||||
let id = super::path::compound_or_self(d, id);
|
||||
if !seen.insert(id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -212,6 +212,23 @@ fn a_painted_effect_after_a_fill_s_3d_effect_finds_the_document_s_swatches() {
|
||||
}
|
||||
}
|
||||
|
||||
/// A path inside a compound path in `ids` stands for the compound path: the compound path becomes
|
||||
/// the group, and no member is replaced by a group inside it.
|
||||
#[test]
|
||||
fn a_compound_path_member_in_ids_expands_the_compound_path() {
|
||||
let (mut s, a) = setup(None);
|
||||
let b = NodeId(s.execute("path.create", &json!({"d":"M250 100L350 100L350 200L250 200Z"})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("select.set", &json!({"ids":[a.0, b.0]})).unwrap();
|
||||
let c = NodeId(s.execute("object.compoundPath.make", &json!({})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("effect.apply", &json!({"ids":[c.0],"effect":"threeD.extrude","item":null,"params":{}})).unwrap();
|
||||
let member = s.doc().unwrap().doc.node(c).unwrap().children().unwrap()[0].id;
|
||||
let out = run(&mut s, json!({"ids":[member.0]})).unwrap();
|
||||
assert_eq!(out["ids"], json!([c.0]));
|
||||
let st = s.doc().unwrap();
|
||||
let NodeKind::Group { children, clip: false } = &st.doc.node(c).unwrap().kind else { panic!("the compound path is a group") };
|
||||
assert!(!children.is_empty() && children.iter().all(|ch| ch.path_data().is_some()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_ids_are_errors() {
|
||||
let (mut s, _) = setup(Some("threeD.extrude"));
|
||||
|
||||
@@ -427,6 +427,22 @@ fn expand_as_wireframes_replaces_the_object_with_its_edges() {
|
||||
assert_eq!(undo_len(&app), history);
|
||||
}
|
||||
|
||||
/// The Quick Actions show on the Object tab of the effects that have one (Revolve (Classic)
|
||||
/// included) and not on their Rotation tab; Revolve and Rotate show them on their first tab.
|
||||
#[test]
|
||||
fn quick_actions_show_on_the_object_tab_only() {
|
||||
use crate::state::Dialog;
|
||||
use vectorcraft_effects::{CLASSIC_EXTRUDE, CLASSIC_REVOLVE, EXTRUDE, INFLATE, REVOLVE};
|
||||
for effect in [EXTRUDE, INFLATE, CLASSIC_EXTRUDE, CLASSIC_REVOLVE] {
|
||||
for (tab, shown) in [("object", true), ("rotation", false)] {
|
||||
let d = Dialog::new("x", json!({"__effect": effect, "__tab": tab, "__gizmo": "rotation"}));
|
||||
assert_eq!(super::quick_actions_shown(&d), shown, "{effect} {tab}");
|
||||
}
|
||||
}
|
||||
let d = Dialog::new("x", json!({"__effect": REVOLVE, "__tab": "rotation", "__gizmo": "rotation"}));
|
||||
assert!(super::quick_actions_shown(&d));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn changed_settings_lists_only_new_values() {
|
||||
let before = json!({"depth": 50.0, "cap": true, "bevel": "none"});
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use egui::Ui;
|
||||
use serde_json::{Map, Value, json};
|
||||
use vectorcraft_doc::{Effect, Node};
|
||||
use vectorcraft_effects::{CLASSIC_EXTRUDE, EXTRUDE, INFLATE, THREE_D_TYPES, is_three_d};
|
||||
use vectorcraft_effects::{CLASSIC_EXTRUDE, CLASSIC_REVOLVE, EXTRUDE, INFLATE, THREE_D_TYPES, is_three_d};
|
||||
|
||||
use super::{live_run, pstate, set_pstate};
|
||||
use crate::VectorcraftApp;
|
||||
@@ -261,7 +261,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
/// the first tab of the others (Revolve, Rotate), never on Lighting.
|
||||
fn quick_actions_shown(d: &Dialog) -> bool {
|
||||
let effect = d.str("__effect");
|
||||
let object_tab = [EXTRUDE, INFLATE, CLASSIC_EXTRUDE].contains(&effect.as_str());
|
||||
let object_tab = [EXTRUDE, INFLATE, CLASSIC_EXTRUDE, CLASSIC_REVOLVE].contains(&effect.as_str());
|
||||
!crate::dialogs::revolve_gizmo::lighting(d) && (!object_tab || d.str("__tab") != "rotation")
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -3237,7 +3237,7 @@ on the object or on a fill or stroke, reshape its edges as they reshape the draw
|
||||
black stroke with round joins and no fill (VectorCraft's own choice). The group keeps the object's place, id, name,
|
||||
visibility, lock, opacity, blending mode, knockout, opacity mask, attributes, slice and text wrap, and the groups
|
||||
are selected.
|
||||
A layer in `ids` stays a layer: its members are replaced by the edges, which are selected, and its ruler guides and paths made into guides stay. Objects without a visible 3D effect do not change. It is one undo step and
|
||||
A layer in `ids` stays a layer: its members are replaced by the edges, which are selected, and its ruler guides and paths made into guides stay. A path inside a compound path in `ids` stands for the compound path. Objects without a visible 3D effect do not change. It is one undo step and
|
||||
returns `{ids}`, the groups. It is an error, and nothing changes, when nothing is selected or given, when no object
|
||||
has a visible 3D effect, when an object's solid can't be built or the canvas draws its source art in its place, or when one object's wireframe has more than
|
||||
1,000,000 edges.
|
||||
|
||||
Reference in New Issue
Block a user