diff --git a/crates/ui-egui/src/panels/swatches.rs b/crates/ui-egui/src/panels/swatches.rs index e47ca4c1a..511447e65 100644 --- a/crates/ui-egui/src/panels/swatches.rs +++ b/crates/ui-egui/src/panels/swatches.rs @@ -609,11 +609,11 @@ pub(crate) fn drag_preview(app: &VectorcraftApp, ctx: &egui::Context) { }, PanelDrag::GraphicStyle(name) => return pointer_chip(ctx, |ui, r| super::graphic_styles::paint_style(app, ui, r, name)), PanelDrag::Symbol(name) => match app.session.active() { - Some(st) => return pointer_chip(ctx, |ui, r| super::symbols::chip(ui, &st.doc, r, name)), + Some(st) => return pointer_chip(ctx, |ui, r| super::symbols::chip(ui, &st.doc, super::symbols::resources_key(&st.doc), r, name)), None => return, }, PanelDrag::LibrarySymbol { library, name } => match vectorcraft_engine::cmd::symbollib::library(&app.session, library) { - Some((_, lib)) => return pointer_chip(ctx, |ui, r| super::symbols::chip(ui, &lib.doc, r, name)), + Some((_, lib)) => return pointer_chip(ctx, |ui, r| super::symbols::chip(ui, &lib.doc, super::symbols::resources_key(&lib.doc), r, name)), None => return, }, PanelDrag::Brush { def, .. } => return pointer_chip(ctx, |ui, r| super::brushes::chip(ui, r, def)), diff --git a/crates/ui-egui/src/panels/symbols.rs b/crates/ui-egui/src/panels/symbols.rs index 3cc70c803..213004330 100644 --- a/crates/ui-egui/src/panels/symbols.rs +++ b/crates/ui-egui/src/panels/symbols.rs @@ -20,15 +20,15 @@ use crate::theme::Tokens; use crate::widgets::{self, PanelDrag, menu_item}; /// A thumbnail of symbol `name` (an instance at its natural size), cached by the identity of the -/// art it shows: its own and that of the symbols and patterns it may use. -fn thumb(ui: &Ui, doc: &Document, name: &str, size: f32) -> Option { +/// art it shows: its own and `resources`, [`resources_key`] of `doc`. +fn thumb(ui: &Ui, doc: &Document, resources: u64, name: &str, size: f32) -> Option { thread_local! { static RENDERER: RefCell = RefCell::new(vectorcraft_render::Renderer::new()); static CACHE: crate::graphics::TexCache> = crate::graphics::TexCache::default(); } let sym = doc.symbols.iter().find(|s| s.name == name)?; let px = (size * ui.ctx().pixels_per_point()).round().max(8.0) as u32; - let key = (Arc::as_ptr(&sym.art) as usize, resources_key(doc), name.to_string(), px); + let key = (Arc::as_ptr(&sym.art) as usize, resources, name.to_string(), px); if let Some(t) = CACHE.with(|c| c.borrow().get(&key).cloned()) { return Some(t); } @@ -45,8 +45,9 @@ fn thumb(ui: &Ui, doc: &Document, name: &str, size: f32) -> Option u64 { +/// The identity of `doc`'s symbol and pattern art, which a symbol's thumbnail may show. It takes a +/// pass over them: work it out once per panel frame, not per thumbnail. +pub(crate) fn resources_key(doc: &Document) -> u64 { use std::hash::{Hash, Hasher}; let mut h = std::collections::hash_map::DefaultHasher::new(); for s in &doc.symbols { @@ -73,10 +74,10 @@ fn render_thumb(r: &mut vectorcraft_render::Renderer, doc: &Document, name: &str } /// Symbol `name`'s thumbnail on white in `r` (the panel's tiles and the chip a dragged symbol -/// shows at the pointer). -pub(crate) fn chip(ui: &Ui, doc: &Document, r: egui::Rect, name: &str) { +/// shows at the pointer); `resources` is [`resources_key`] of `doc`. +pub(crate) fn chip(ui: &Ui, doc: &Document, resources: u64, r: egui::Rect, name: &str) { ui.painter().rect_filled(r, 0.0, egui::Color32::WHITE); - if let Some(tex) = thumb(ui, doc, name, r.width()) { + if let Some(tex) = thumb(ui, doc, resources, name, r.width()) { ui.painter().image(tex.id(), r, egui::Rect::from_min_max(egui::pos2(0.0, 0.0), egui::pos2(1.0, 1.0)), egui::Color32::WHITE); } } @@ -101,6 +102,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { let t = Tokens::get(ui.ctx()); let Some(doc) = app.session.active().map(|d| d.doc.clone()) else { return }; let names: Vec = doc.symbols.iter().map(|s| s.name.clone()).collect(); + let resources = resources_key(&doc); let list: bool = pstate(ui.ctx(), "sym-list"); let sel = current(app); let mut clicked: Option<(String, bool)> = None; @@ -121,7 +123,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { } else if resp.hovered() { ui.painter().rect_filled(r, 0.0, t.hover); } - chip(ui, &doc, egui::Rect::from_center_size(r.left_center() + vec2(14.0, 0.0), vec2(22.0, 22.0)), n); + chip(ui, &doc, resources, egui::Rect::from_center_size(r.left_center() + vec2(14.0, 0.0), vec2(22.0, 22.0)), n); ui.painter().text(r.left_center() + vec2(32.0, 0.0), egui::Align2::LEFT_CENTER, n, egui::FontId::proportional(12.5), t.text); if resp.double_clicked() { clicked = Some((n.clone(), true)); @@ -134,7 +136,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) { for n in &names { let (r, resp) = ui.allocate_exact_size(vec2(44.0, 44.0), Sense::click_and_drag()); widgets::drag_source(ui, &resp, || PanelDrag::Symbol(n.clone())); - chip(ui, &doc, r.shrink(2.0), n); + chip(ui, &doc, resources, r.shrink(2.0), n); let on = sel.as_deref() == Some(n.as_str()); ui.painter().rect_stroke( r, @@ -245,6 +247,8 @@ fn save_library(app: &mut VectorcraftApp, names: Vec) { pub(crate) struct LibSymbol { lib: Arc, index: usize, + /// [`resources_key`] of the library's document. + resources: u64, } impl LibSymbol { @@ -274,7 +278,8 @@ impl LibraryKind for SymbolLibraries { } fn get(app: &VectorcraftApp, id: &str) -> Option<(String, Self::Lib)> { let (info, lib) = symbollib::library(&app.session, id)?; - let shown = (0..lib.len()).map(|index| LibSymbol { lib: lib.clone(), index }).collect(); + let resources = resources_key(&lib.doc); + let shown = (0..lib.len()).map(|index| LibSymbol { lib: lib.clone(), index, resources }).collect(); Some((info.name, Arc::new(shown))) } fn find(app: &VectorcraftApp, key: &str) -> library_panel::Found { @@ -289,7 +294,7 @@ impl LibraryKind for SymbolLibraries { } /// The symbol's art on white, as the Symbols panel shows it. fn draw(_: &VectorcraftApp, ui: &Ui, r: egui::Rect, s: &LibSymbol, selected: bool, hovered: bool) { - chip(ui, &s.lib.doc, r, s.name()); + chip(ui, &s.lib.doc, s.resources, r, s.name()); super::graphic_styles::outline(ui, r, selected, hovered); } fn row_icons(_: &Ui, _: egui::Rect, _: &LibSymbol) {}