Appearance dialog (MODIFY > Appearance, A)

Library swatches by category (the engine's library when it offers one, else built-in looks:
metals, plastics, paints, woods, glass with opacity), the looks in this design, a colour picker
and opacity, and the objects to apply to (bodies/components or faces). A swatch dragged onto a
body or face in the viewport, or onto a body's row in the Browser, applies at once; Apply and
OK give the picked objects the current look; pre-selected bodies become the objects.

Browser: rows under a drag of another kind count as hovered, and the Browser's own drops no
longer swallow other payloads (egui's take_payload takes any type), so swatches dropped on its
rows land.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 10:22:53 +00:00
1 parent 187e9a97b9
commit d0a9ef27ca
6 files changed
+429 -2

No files matched your search

+8 -1
View File
@@ -257,7 +257,10 @@ fn draw_row(ui: &mut egui::Ui, id: egui::Id, row: &Row) -> RowResp {
return RowResp { rect: Some(r), ..Default::default() };
}
let (r, resp) = ui.allocate_exact_size(vec2(ui.available_width(), ROW_H), Sense::click_and_drag());
let mut out = RowResp { rect: Some(r), hovered: resp.hovered(), ..Default::default() };
// While something is dragged (an appearance swatch, drawn under the pointer) `hovered` is
// off; the row under the pointer still counts, so a drop lands on it.
let dragged_over = egui::DragAndDrop::has_any_payload(ui.ctx()) && ui.input(|i| i.pointer.hover_pos()).is_some_and(|p| r.contains(p));
let mut out = RowResp { rect: Some(r), hovered: resp.hovered() || dragged_over, ..Default::default() };
if row.selected {
ui.painter().rect_filled(r, 3.0, t.accent_soft);
} else if resp.hovered() {
@@ -1177,6 +1180,10 @@ fn drop_target(ui: &egui::Ui, resp: &egui::Response, accept: impl Fn(&Drag) -> b
DropMark::Box => ui.painter().rect_stroke(r.shrink(0.5), 3.0, Stroke::new(1.5, t.accent), egui::StrokeKind::Inside),
};
}
// Taking a payload takes it whatever its type: leave other drags (appearance swatches) be.
if !egui::DragAndDrop::has_payload_of_type::<Drag>(ui.ctx()) {
return None;
}
resp.dnd_release_payload::<Drag>().filter(|d| accept(d))
}