Add `Context::layer_transform_to_global` & `layer_transform_from_global` (#5465)
This makes it easy to get the current transform of a layer, and uses consistent naming everywhere. `Memory::layer_transforms` is now called `Memory::to_global`, because the old name was ambiguous (transform into what direction?)
This commit is contained in:
parent
99c1034cfc
commit
de8ac88c0e
|
|
@ -93,8 +93,8 @@ pub fn show_tooltip_at_pointer<R>(
|
|||
pointer_rect.min.x = pointer_pos.x;
|
||||
|
||||
// Transform global coords to layer coords:
|
||||
if let Some(transform) = ctx.memory(|m| m.layer_transforms.get(&parent_layer).copied()) {
|
||||
pointer_rect = transform.inverse() * pointer_rect;
|
||||
if let Some(from_global) = ctx.layer_transform_from_global(parent_layer) {
|
||||
pointer_rect = from_global * pointer_rect;
|
||||
}
|
||||
|
||||
show_tooltip_at_dyn(
|
||||
|
|
@ -162,8 +162,8 @@ fn show_tooltip_at_dyn<'c, R>(
|
|||
) -> R {
|
||||
// Transform layer coords to global coords:
|
||||
let mut widget_rect = *widget_rect;
|
||||
if let Some(transform) = ctx.memory(|m| m.layer_transforms.get(&parent_layer).copied()) {
|
||||
widget_rect = transform * widget_rect;
|
||||
if let Some(to_global) = ctx.layer_transform_to_global(parent_layer) {
|
||||
widget_rect = to_global * widget_rect;
|
||||
}
|
||||
|
||||
remember_that_tooltip_was_shown(ctx);
|
||||
|
|
@ -404,11 +404,12 @@ pub fn popup_above_or_below_widget<R>(
|
|||
AboveOrBelow::Above => (widget_response.rect.left_top(), Align2::LEFT_BOTTOM),
|
||||
AboveOrBelow::Below => (widget_response.rect.left_bottom(), Align2::LEFT_TOP),
|
||||
};
|
||||
if let Some(transform) = parent_ui
|
||||
|
||||
if let Some(to_global) = parent_ui
|
||||
.ctx()
|
||||
.memory(|m| m.layer_transforms.get(&parent_ui.layer_id()).copied())
|
||||
.layer_transform_to_global(parent_ui.layer_id())
|
||||
{
|
||||
pos = transform * pos;
|
||||
pos = to_global * pos;
|
||||
}
|
||||
|
||||
let frame = Frame::popup(parent_ui.style());
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ impl ContextImpl {
|
|||
crate::hit_test::hit_test(
|
||||
&viewport.prev_pass.widgets,
|
||||
&layers,
|
||||
&self.memory.layer_transforms,
|
||||
&self.memory.to_global,
|
||||
pos,
|
||||
interact_radius,
|
||||
)
|
||||
|
|
@ -1329,11 +1329,11 @@ impl Context {
|
|||
res.is_pointer_button_down_on || res.long_touched || clicked || res.drag_stopped;
|
||||
if is_interacted_with {
|
||||
res.interact_pointer_pos = input.pointer.interact_pos();
|
||||
if let (Some(transform), Some(pos)) = (
|
||||
memory.layer_transforms.get(&res.layer_id),
|
||||
if let (Some(to_global), Some(pos)) = (
|
||||
memory.to_global.get(&res.layer_id),
|
||||
&mut res.interact_pointer_pos,
|
||||
) {
|
||||
*pos = transform.inverse() * *pos;
|
||||
*pos = to_global.inverse() * *pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2381,7 +2381,7 @@ impl ContextImpl {
|
|||
|
||||
let shapes = viewport
|
||||
.graphics
|
||||
.drain(self.memory.areas().order(), &self.memory.layer_transforms);
|
||||
.drain(self.memory.areas().order(), &self.memory.to_global);
|
||||
|
||||
let mut repaint_needed = false;
|
||||
|
||||
|
|
@ -2697,6 +2697,7 @@ impl Context {
|
|||
/// Transform the graphics of the given layer.
|
||||
///
|
||||
/// This will also affect input.
|
||||
/// The direction of the given transform is "into the global coordinate system".
|
||||
///
|
||||
/// This is a sticky setting, remembered from one frame to the next.
|
||||
///
|
||||
|
|
@ -2706,13 +2707,28 @@ impl Context {
|
|||
pub fn set_transform_layer(&self, layer_id: LayerId, transform: TSTransform) {
|
||||
self.memory_mut(|m| {
|
||||
if transform == TSTransform::IDENTITY {
|
||||
m.layer_transforms.remove(&layer_id)
|
||||
m.to_global.remove(&layer_id)
|
||||
} else {
|
||||
m.layer_transforms.insert(layer_id, transform)
|
||||
m.to_global.insert(layer_id, transform)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Return how to transform the graphics of the given layer into the global coordinate system.
|
||||
///
|
||||
/// Set this with [`Self::layer_transform_to_global`].
|
||||
pub fn layer_transform_to_global(&self, layer_id: LayerId) -> Option<TSTransform> {
|
||||
self.memory(|m| m.to_global.get(&layer_id).copied())
|
||||
}
|
||||
|
||||
/// Return how to transform the graphics of the global coordinate system into the local coordinate system of the given layer.
|
||||
///
|
||||
/// This returns the inverse of [`Self::layer_transform_to_global`].
|
||||
pub fn layer_transform_from_global(&self, layer_id: LayerId) -> Option<TSTransform> {
|
||||
self.layer_transform_to_global(layer_id)
|
||||
.map(|t| t.inverse())
|
||||
}
|
||||
|
||||
/// Move all the graphics at the given layer.
|
||||
///
|
||||
/// Is used to implement drag-and-drop preview.
|
||||
|
|
@ -2777,12 +2793,11 @@ impl Context {
|
|||
///
|
||||
/// See also [`Response::contains_pointer`].
|
||||
pub fn rect_contains_pointer(&self, layer_id: LayerId, rect: Rect) -> bool {
|
||||
let rect =
|
||||
if let Some(transform) = self.memory(|m| m.layer_transforms.get(&layer_id).copied()) {
|
||||
transform * rect
|
||||
} else {
|
||||
rect
|
||||
};
|
||||
let rect = if let Some(to_global) = self.layer_transform_to_global(layer_id) {
|
||||
to_global * rect
|
||||
} else {
|
||||
rect
|
||||
};
|
||||
if !rect.is_positive() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ pub struct WidgetHits {
|
|||
pub fn hit_test(
|
||||
widgets: &WidgetRects,
|
||||
layer_order: &[LayerId],
|
||||
layer_transforms: &HashMap<LayerId, TSTransform>,
|
||||
layer_to_global: &HashMap<LayerId, TSTransform>,
|
||||
pos: Pos2,
|
||||
search_radius: f32,
|
||||
) -> WidgetHits {
|
||||
|
|
@ -44,9 +44,9 @@ pub fn hit_test(
|
|||
let search_radius_sq = search_radius * search_radius;
|
||||
|
||||
// Transform the position into the local coordinate space of each layer:
|
||||
let pos_in_layers: HashMap<LayerId, Pos2> = layer_transforms
|
||||
let pos_in_layers: HashMap<LayerId, Pos2> = layer_to_global
|
||||
.iter()
|
||||
.map(|(layer_id, t)| (*layer_id, t.inverse() * pos))
|
||||
.map(|(layer_id, to_global)| (*layer_id, to_global.inverse() * pos))
|
||||
.collect();
|
||||
|
||||
let mut closest_dist_sq = f32::INFINITY;
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ impl GraphicLayers {
|
|||
pub fn drain(
|
||||
&mut self,
|
||||
area_order: &[LayerId],
|
||||
transforms: &ahash::HashMap<LayerId, TSTransform>,
|
||||
to_global: &ahash::HashMap<LayerId, TSTransform>,
|
||||
) -> Vec<ClippedShape> {
|
||||
crate::profile_function!();
|
||||
|
||||
|
|
@ -231,10 +231,10 @@ impl GraphicLayers {
|
|||
for layer_id in area_order {
|
||||
if layer_id.order == order {
|
||||
if let Some(list) = order_map.get_mut(&layer_id.id) {
|
||||
if let Some(transform) = transforms.get(layer_id) {
|
||||
if let Some(to_global) = to_global.get(layer_id) {
|
||||
for clipped_shape in &mut list.0 {
|
||||
clipped_shape.clip_rect = *transform * clipped_shape.clip_rect;
|
||||
clipped_shape.shape.transform(*transform);
|
||||
clipped_shape.clip_rect = *to_global * clipped_shape.clip_rect;
|
||||
clipped_shape.shape.transform(*to_global);
|
||||
}
|
||||
}
|
||||
all_shapes.append(&mut list.0);
|
||||
|
|
@ -246,10 +246,10 @@ impl GraphicLayers {
|
|||
for (id, list) in order_map {
|
||||
let layer_id = LayerId::new(order, *id);
|
||||
|
||||
if let Some(transform) = transforms.get(&layer_id) {
|
||||
if let Some(to_global) = to_global.get(&layer_id) {
|
||||
for clipped_shape in &mut list.0 {
|
||||
clipped_shape.clip_rect = *transform * clipped_shape.clip_rect;
|
||||
clipped_shape.shape.transform(*transform);
|
||||
clipped_shape.clip_rect = *to_global * clipped_shape.clip_rect;
|
||||
clipped_shape.shape.transform(*to_global);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,8 +95,13 @@ pub struct Memory {
|
|||
#[cfg_attr(feature = "persistence", serde(skip))]
|
||||
everything_is_visible: bool,
|
||||
|
||||
/// Transforms per layer
|
||||
pub layer_transforms: HashMap<LayerId, TSTransform>,
|
||||
/// Transforms per layer.
|
||||
///
|
||||
/// Instead of using this directly, use:
|
||||
/// * [`crate::Context::set_transform_layer`]
|
||||
/// * [`crate::Context::layer_transform_to_global`]
|
||||
/// * [`crate::Context::layer_transform_from_global`]
|
||||
pub to_global: HashMap<LayerId, TSTransform>,
|
||||
|
||||
// -------------------------------------------------
|
||||
// Per-viewport:
|
||||
|
|
@ -120,7 +125,7 @@ impl Default for Memory {
|
|||
focus: Default::default(),
|
||||
viewport_id: Default::default(),
|
||||
areas: Default::default(),
|
||||
layer_transforms: Default::default(),
|
||||
to_global: Default::default(),
|
||||
popup: Default::default(),
|
||||
everything_is_visible: Default::default(),
|
||||
add_fonts: Default::default(),
|
||||
|
|
@ -819,7 +824,7 @@ impl Memory {
|
|||
/// Top-most layer at the given position.
|
||||
pub fn layer_id_at(&self, pos: Pos2) -> Option<LayerId> {
|
||||
self.areas()
|
||||
.layer_id_at(pos, &self.layer_transforms)
|
||||
.layer_id_at(pos, &self.to_global)
|
||||
.and_then(|layer_id| {
|
||||
if self.is_above_modal_layer(layer_id) {
|
||||
Some(layer_id)
|
||||
|
|
@ -829,6 +834,12 @@ impl Memory {
|
|||
})
|
||||
}
|
||||
|
||||
/// The currently set transform of a layer.
|
||||
#[deprecated = "Use `Context::layer_transform_to_global` instead"]
|
||||
pub fn layer_transforms(&self, layer_id: LayerId) -> Option<TSTransform> {
|
||||
self.to_global.get(&layer_id).copied()
|
||||
}
|
||||
|
||||
/// An iterator over all layers. Back-to-front, top is last.
|
||||
pub fn layer_ids(&self) -> impl ExactSizeIterator<Item = LayerId> + '_ {
|
||||
self.areas().order().iter().copied()
|
||||
|
|
@ -1194,15 +1205,15 @@ impl Areas {
|
|||
pub fn layer_id_at(
|
||||
&self,
|
||||
pos: Pos2,
|
||||
layer_transforms: &HashMap<LayerId, TSTransform>,
|
||||
layer_to_global: &HashMap<LayerId, TSTransform>,
|
||||
) -> Option<LayerId> {
|
||||
for layer in self.order.iter().rev() {
|
||||
if self.is_visible(layer) {
|
||||
if let Some(state) = self.areas.get(&layer.id) {
|
||||
let mut rect = state.rect();
|
||||
if state.interactable {
|
||||
if let Some(transform) = layer_transforms.get(layer) {
|
||||
rect = *transform * rect;
|
||||
if let Some(to_global) = layer_to_global.get(layer) {
|
||||
rect = *to_global * rect;
|
||||
}
|
||||
|
||||
if rect.contains(pos) {
|
||||
|
|
|
|||
|
|
@ -406,11 +406,8 @@ impl MenuRoot {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(transform) = button
|
||||
.ctx
|
||||
.memory(|m| m.layer_transforms.get(&button.layer_id).copied())
|
||||
{
|
||||
pos = transform * pos;
|
||||
if let Some(to_global) = button.ctx.layer_transform_to_global(button.layer_id) {
|
||||
pos = to_global * pos;
|
||||
}
|
||||
|
||||
return MenuResponse::Create(pos, id);
|
||||
|
|
|
|||
|
|
@ -392,11 +392,8 @@ impl Response {
|
|||
pub fn drag_delta(&self) -> Vec2 {
|
||||
if self.dragged() {
|
||||
let mut delta = self.ctx.input(|i| i.pointer.delta());
|
||||
if let Some(scaling) = self
|
||||
.ctx
|
||||
.memory(|m| m.layer_transforms.get(&self.layer_id).map(|t| t.scaling))
|
||||
{
|
||||
delta /= scaling;
|
||||
if let Some(from_global) = self.ctx.layer_transform_from_global(self.layer_id) {
|
||||
delta *= from_global.scaling;
|
||||
}
|
||||
delta
|
||||
} else {
|
||||
|
|
@ -478,11 +475,8 @@ impl Response {
|
|||
pub fn hover_pos(&self) -> Option<Pos2> {
|
||||
if self.hovered() {
|
||||
let mut pos = self.ctx.input(|i| i.pointer.hover_pos())?;
|
||||
if let Some(transform) = self
|
||||
.ctx
|
||||
.memory(|m| m.layer_transforms.get(&self.layer_id).copied())
|
||||
{
|
||||
pos = transform.inverse() * pos;
|
||||
if let Some(from_global) = self.ctx.layer_transform_from_global(self.layer_id) {
|
||||
pos = from_global * pos;
|
||||
}
|
||||
Some(pos)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -766,14 +766,15 @@ impl<'t> TextEdit<'t> {
|
|||
}
|
||||
|
||||
// Set IME output (in screen coords) when text is editable and visible
|
||||
let transform = ui
|
||||
.memory(|m| m.layer_transforms.get(&ui.layer_id()).copied())
|
||||
let to_global = ui
|
||||
.ctx()
|
||||
.layer_transform_to_global(ui.layer_id())
|
||||
.unwrap_or_default();
|
||||
|
||||
ui.ctx().output_mut(|o| {
|
||||
o.ime = Some(crate::output::IMEOutput {
|
||||
rect: transform * rect,
|
||||
cursor_rect: transform * primary_cursor_rect,
|
||||
rect: to_global * rect,
|
||||
cursor_rect: to_global * primary_cursor_rect,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue