diff --git a/crates/chattyness-user-ui/src/components/avatar.rs b/crates/chattyness-user-ui/src/components/avatar.rs index 369297b..dd0adea 100644 --- a/crates/chattyness-user-ui/src/components/avatar.rs +++ b/crates/chattyness-user-ui/src/components/avatar.rs @@ -27,7 +27,7 @@ use super::canvas_utils::normalize_asset_path; /// Screen boundaries for visual clamping in screen space. /// /// Used by Avatar for clamping avatar positions and bubble positions. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct ScreenBounds { /// Left edge of drawable area (= offset_x) pub min_x: f64, @@ -82,7 +82,7 @@ impl ScreenBounds { /// Transform parameters for converting scene coordinates to screen coordinates. /// /// Used by Avatar and LoosePropCanvas to position elements on screen. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub struct SceneTransform { /// X scale factor (screen pixels per scene unit) pub scale_x: f64, diff --git a/crates/chattyness-user-ui/src/components/scene_viewer.rs b/crates/chattyness-user-ui/src/components/scene_viewer.rs index bcf1e6a..504c0a5 100644 --- a/crates/chattyness-user-ui/src/components/scene_viewer.rs +++ b/crates/chattyness-user-ui/src/components/scene_viewer.rs @@ -444,16 +444,17 @@ pub fn RealmSceneViewer( let text_em_size = Signal::derive(move || settings.get().text_em_size); - // Compute SceneTransform once for all avatars and props - let scene_transform = Signal::derive(move || SceneTransform { + // Compute SceneTransform once for all avatars and props (memoized) + let scene_transform: Signal = Memo::new(move |_| SceneTransform { scale_x: scale_x.get(), scale_y: scale_y.get(), offset_x: offset_x.get(), offset_y: offset_y.get(), - }); + }) + .into(); - // Compute ScreenBounds once for all avatars (for clamping) - let screen_bounds = Signal::derive(move || { + // Compute ScreenBounds once for all avatars (memoized for clamping) + let screen_bounds: Signal = Memo::new(move |_| { let t = scene_transform.get(); ScreenBounds::from_transform( scene_width_f, @@ -463,7 +464,8 @@ pub fn RealmSceneViewer( t.offset_x, t.offset_y, ) - }); + }) + .into(); let members_by_key = Signal::derive(move || { sorted_members.get().into_iter().enumerate()