compute ScreenBounds once

This commit is contained in:
Evan Carroll 2026-01-26 23:03:54 -06:00
parent c434321376
commit 30722bed8f
2 changed files with 22 additions and 22 deletions

View file

@ -354,12 +354,8 @@ pub fn Avatar(
/// Opacity for fade-out animation (0.0 to 1.0, default 1.0).
#[prop(default = 1.0)]
opacity: f64,
/// Scene width in scene coordinates (for boundary calculations).
#[prop(optional)]
scene_width: Option<Signal<f64>>,
/// Scene height in scene coordinates (for boundary calculations).
#[prop(optional)]
scene_height: Option<Signal<f64>>,
/// Screen bounds for clamping (computed once at scene level).
screen_bounds: Signal<ScreenBounds>,
/// Active speech bubble for this avatar (None if not speaking).
#[prop(optional)]
active_bubble: Option<Signal<Option<ActiveBubble>>>,
@ -397,12 +393,8 @@ pub fn Avatar(
&m.avatar.emotion_layer,
);
// Get scene dimensions (use large defaults if not provided)
let sw = scene_width.map(|s| s.get()).unwrap_or(10000.0);
let sh = scene_height.map(|s| s.get()).unwrap_or(10000.0);
// Compute screen boundaries and avatar screen position
let boundaries = ScreenBounds::from_transform(sw, sh, sx, sy, ox, oy);
// Use passed-in screen bounds (computed once at scene level)
let boundaries = screen_bounds.get();
let avatar_screen_x = m.member.position_x * sx + ox;
let avatar_screen_y = m.member.position_y * sy + oy;
@ -513,16 +505,14 @@ pub fn Avatar(
&m.avatar.emotion_layer,
);
// Get scene dimensions and transform parameters
// Get transform parameters for computing avatar screen position
let sx = scale_x.get();
let sy = scale_y.get();
let ox = offset_x.get();
let oy = offset_y.get();
let sw = scene_width.map(|s| s.get()).unwrap_or(10000.0);
let sh = scene_height.map(|s| s.get()).unwrap_or(10000.0);
// Create unified layout - same calculation as style closure
let boundaries = ScreenBounds::from_transform(sw, sh, sx, sy, ox, oy);
// Use passed-in screen bounds (computed once at scene level)
let boundaries = screen_bounds.get();
let avatar_screen_x = m.member.position_x * sx + ox;
let avatar_screen_y = m.member.position_y * sy + oy;

View file

@ -22,7 +22,7 @@ use uuid::Uuid;
use chattyness_db::models::{ChannelMemberWithAvatar, LooseProp, Scene};
use super::avatar::{Avatar, member_key};
use super::avatar::{Avatar, ScreenBounds, member_key};
#[cfg(feature = "hydrate")]
use super::canvas_utils::hit_test_canvas;
use super::chat_types::ActiveBubble;
@ -450,6 +450,18 @@ pub fn RealmSceneViewer(
let scene_width_signal = Signal::derive(move || scene_width_f);
let scene_height_signal = Signal::derive(move || scene_height_f);
// Compute ScreenBounds once for all avatars (instead of each avatar computing it)
let screen_bounds = Signal::derive(move || {
ScreenBounds::from_transform(
scene_width_signal.get(),
scene_height_signal.get(),
scale_x_signal.get(),
scale_y_signal.get(),
offset_x_signal.get(),
offset_y_signal.get(),
)
});
let members_by_key = Signal::derive(move || {
sorted_members.get().into_iter().enumerate()
.map(|(idx, m)| (member_key(&m), (idx, m)))
@ -520,8 +532,7 @@ pub fn RealmSceneViewer(
prop_size=prop_size
z_index=z
text_em_size=text_em_size
scene_width=scene_width_signal
scene_height=scene_height_signal
screen_bounds=screen_bounds
active_bubble=bubble_signal
/>
}
@ -553,8 +564,7 @@ pub fn RealmSceneViewer(
z_index=5
text_em_size=text_em_size
opacity=opacity
scene_width=scene_width_signal
scene_height=scene_height_signal
screen_bounds=screen_bounds
/>
})
} else { None }