Colours in exports from materials and appearances; Appearance command
- Bodies export (STEP, 3MF) in the colour they are shown in: an appearance,
else the physical material's look, else the colour the body was imported
with (Document::body_color / painted). Physical materials used to export
no colour at all.
- AppearanceCommand (Modify): a colour per body ("#rrggbb" or [r, g, b];
null follows the material again), kept in the design and across renames.
- Material looks move to solvecraft-doc (material_color); the viewport draws
appearance, material or imported colour, as exported.
- Engine test: brass and red ABS bodies export, re-import with their RGB, and
keep it through open and export again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
578b35e88a
commit
ae4570ed39
8 files changed
+200
-86
No files matched your search
@@ -951,6 +951,42 @@ fn sample_plate_step_round_trip() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Bodies export in the colour they are shown in: a material's look, an appearance over it,
|
||||
/// none for the default; and colours read from a STEP file survive the next export.
|
||||
#[test]
|
||||
fn material_and_appearance_colours_export_to_step() {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "PrimitiveBox", json!({"length": 10, "width": 10, "height": 10, "body_name": "BrassBox"}));
|
||||
run(&mut s, "PrimitiveBox", json!({"corner": [20, 0, 0], "length": 10, "width": 10, "height": 10, "body_name": "RedAbs"}));
|
||||
run(&mut s, "PrimitiveBox", json!({"corner": [40, 0, 0], "length": 10, "width": 10, "height": 10, "body_name": "Plain"}));
|
||||
run(&mut s, "PhysicalMaterialCommand", json!({"bodies": ["BrassBox"], "material": "Brass"}));
|
||||
run(&mut s, "PhysicalMaterialCommand", json!({"bodies": ["RedAbs"], "material": "ABS Plastic"}));
|
||||
run(&mut s, "AppearanceCommand", json!({"bodies": ["RedAbs"], "color": "#d01c1c"}));
|
||||
assert!(s.execute("AppearanceCommand", &json!({"bodies": ["RedAbs"], "color": "#12"})).is_err());
|
||||
let rgb = |c: [u8; 3]| c.map(|x| x as f32 / 255.0);
|
||||
let want =
|
||||
[("BrassBox", Some(rgb(solvecraft_doc::material_color("Brass").unwrap()))), ("RedAbs", Some(rgb([0xd0, 0x1c, 0x1c]))), ("Plain", None)];
|
||||
let same = |a: Option<[f32; 3]>, b: Option<[f32; 3]>| match (a, b) {
|
||||
(Some(a), Some(b)) => a.iter().zip(b).all(|(x, y)| (x - y).abs() < 1e-3),
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
};
|
||||
let check = |imp: &solvecraft_kernel::StepImport| {
|
||||
for (name, c) in want {
|
||||
let b = imp.bodies.iter().find(|b| b.name == name).unwrap_or_else(|| panic!("no body {name}"));
|
||||
assert!(same(b.body.color(), c), "{name}: {:?} vs {c:?}", b.body.color());
|
||||
}
|
||||
};
|
||||
check(&step_round_trip(&mut s, "colours"));
|
||||
// Open the export and export again: the file's colours are kept.
|
||||
let p = std::env::temp_dir().join(format!("solvecraft-colours-{}.step", std::process::id()));
|
||||
run(&mut s, "ExportCommand", json!({"path": p.to_string_lossy()}));
|
||||
let mut s2 = Session::default();
|
||||
run(&mut s2, "doc.open", json!({"path": p.to_string_lossy()}));
|
||||
let _ = std::fs::remove_file(&p);
|
||||
check(&step_round_trip(&mut s2, "colours2"));
|
||||
}
|
||||
|
||||
/// Components export as a STEP assembly: products, occurrences, placements.
|
||||
#[test]
|
||||
fn components_export_as_step_assembly() {
|
||||
|
||||
Reference in new issue
Block a user