mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 14:20:04 -04:00
Now InputState is stored per viewport!
This fixes input collisions between viewports
This commit is contained in:
@@ -186,7 +186,7 @@ struct ContextImpl {
|
|||||||
|
|
||||||
os: OperatingSystem,
|
os: OperatingSystem,
|
||||||
|
|
||||||
input: InputState,
|
input: HashMap<u64, InputState>,
|
||||||
|
|
||||||
/// State that is collected during a frame and then cleared
|
/// State that is collected during a frame and then cleared
|
||||||
frame_state: FrameState,
|
frame_state: FrameState,
|
||||||
@@ -226,9 +226,10 @@ impl ContextImpl {
|
|||||||
if let Some(new_pixels_per_point) = self.memory.new_pixels_per_point.take() {
|
if let Some(new_pixels_per_point) = self.memory.new_pixels_per_point.take() {
|
||||||
new_raw_input.pixels_per_point = Some(new_pixels_per_point);
|
new_raw_input.pixels_per_point = Some(new_pixels_per_point);
|
||||||
|
|
||||||
|
let input = self.input.entry(viewport_id).or_default();
|
||||||
// This is a bit hacky, but is required to avoid jitter:
|
// This is a bit hacky, but is required to avoid jitter:
|
||||||
let ratio = self.input.pixels_per_point / new_pixels_per_point;
|
let ratio = input.pixels_per_point / new_pixels_per_point;
|
||||||
let mut rect = self.input.screen_rect;
|
let mut rect = input.screen_rect;
|
||||||
rect.min = (ratio * rect.min.to_vec2()).to_pos2();
|
rect.min = (ratio * rect.min.to_vec2()).to_pos2();
|
||||||
rect.max = (ratio * rect.max.to_vec2()).to_pos2();
|
rect.max = (ratio * rect.max.to_vec2()).to_pos2();
|
||||||
new_raw_input.screen_rect = Some(rect);
|
new_raw_input.screen_rect = Some(rect);
|
||||||
@@ -236,17 +237,26 @@ impl ContextImpl {
|
|||||||
|
|
||||||
self.layer_rects_prev_frame = std::mem::take(&mut self.layer_rects_this_frame);
|
self.layer_rects_prev_frame = std::mem::take(&mut self.layer_rects_this_frame);
|
||||||
|
|
||||||
self.memory.begin_frame(&self.input, &new_raw_input);
|
self.memory.begin_frame(
|
||||||
|
self.input.get(&viewport_id).unwrap_or(&Default::default()),
|
||||||
|
&new_raw_input,
|
||||||
|
);
|
||||||
|
|
||||||
self.input = std::mem::take(&mut self.input)
|
let input = self
|
||||||
|
.input
|
||||||
|
.remove(&viewport_id)
|
||||||
|
.unwrap_or_default()
|
||||||
.begin_frame(new_raw_input, self.repaint.requested_repaint_last_frame);
|
.begin_frame(new_raw_input, self.repaint.requested_repaint_last_frame);
|
||||||
|
self.input.insert(viewport_id, input);
|
||||||
|
|
||||||
self.frame_state.begin_frame(&self.input);
|
self.frame_state
|
||||||
|
.begin_frame(self.input.get(&viewport_id).unwrap());
|
||||||
|
|
||||||
self.update_fonts_mut();
|
self.update_fonts_mut();
|
||||||
|
|
||||||
// Ensure we register the background area so panels and background ui can catch clicks:
|
// Ensure we register the background area so panels and background ui can catch clicks:
|
||||||
let screen_rect = self.input.screen_rect();
|
let input = self.input.get(&viewport_id).unwrap();
|
||||||
|
let screen_rect = input.screen_rect();
|
||||||
self.memory.areas.set_state(
|
self.memory.areas.set_state(
|
||||||
LayerId::background(),
|
LayerId::background(),
|
||||||
containers::area::State {
|
containers::area::State {
|
||||||
@@ -262,9 +272,7 @@ impl ContextImpl {
|
|||||||
use crate::frame_state::AccessKitFrameState;
|
use crate::frame_state::AccessKitFrameState;
|
||||||
let id = crate::accesskit_root_id();
|
let id = crate::accesskit_root_id();
|
||||||
let mut builder = accesskit::NodeBuilder::new(accesskit::Role::Window);
|
let mut builder = accesskit::NodeBuilder::new(accesskit::Role::Window);
|
||||||
builder.set_transform(accesskit::Affine::scale(
|
builder.set_transform(accesskit::Affine::scale(input.pixels_per_point().into()));
|
||||||
self.input.pixels_per_point().into(),
|
|
||||||
));
|
|
||||||
let mut node_builders = IdMap::default();
|
let mut node_builders = IdMap::default();
|
||||||
node_builders.insert(id, builder);
|
node_builders.insert(id, builder);
|
||||||
self.frame_state.accesskit_state = Some(AccessKitFrameState {
|
self.frame_state.accesskit_state = Some(AccessKitFrameState {
|
||||||
@@ -276,8 +284,12 @@ impl ContextImpl {
|
|||||||
|
|
||||||
/// Load fonts unless already loaded.
|
/// Load fonts unless already loaded.
|
||||||
fn update_fonts_mut(&mut self) {
|
fn update_fonts_mut(&mut self) {
|
||||||
let pixels_per_point = self.input.pixels_per_point();
|
let input = self
|
||||||
let max_texture_side = self.input.max_texture_side;
|
.input
|
||||||
|
.entry(self.current_rendering_viewport)
|
||||||
|
.or_default();
|
||||||
|
let pixels_per_point = input.pixels_per_point();
|
||||||
|
let max_texture_side = input.max_texture_side;
|
||||||
|
|
||||||
if let Some(font_definitions) = self.memory.new_font_definitions.take() {
|
if let Some(font_definitions) = self.memory.new_font_definitions.take() {
|
||||||
let fonts = Fonts::new(pixels_per_point, max_texture_side, font_definitions);
|
let fonts = Fonts::new(pixels_per_point, max_texture_side, font_definitions);
|
||||||
@@ -474,13 +486,19 @@ impl Context {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn input<R>(&self, reader: impl FnOnce(&InputState) -> R) -> R {
|
pub fn input<R>(&self, reader: impl FnOnce(&InputState) -> R) -> R {
|
||||||
self.read(move |ctx| reader(&ctx.input))
|
self.read(move |ctx| {
|
||||||
|
reader(
|
||||||
|
ctx.input
|
||||||
|
.get(&ctx.current_rendering_viewport)
|
||||||
|
.unwrap_or(&Default::default()),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read-write access to [`InputState`].
|
/// Read-write access to [`InputState`].
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn input_mut<R>(&self, writer: impl FnOnce(&mut InputState) -> R) -> R {
|
pub fn input_mut<R>(&self, writer: impl FnOnce(&mut InputState) -> R) -> R {
|
||||||
self.write(move |ctx| writer(&mut ctx.input))
|
self.write(move |ctx| writer(ctx.input.entry(ctx.viewport_counter).or_default()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read-only access to [`Memory`].
|
/// Read-only access to [`Memory`].
|
||||||
@@ -723,7 +741,12 @@ impl Context {
|
|||||||
.push((id, interact_rect));
|
.push((id, interact_rect));
|
||||||
|
|
||||||
if hovered {
|
if hovered {
|
||||||
let pointer_pos = ctx.input.pointer.interact_pos();
|
let pointer_pos = ctx
|
||||||
|
.input
|
||||||
|
.get(&ctx.current_rendering_viewport)
|
||||||
|
.unwrap()
|
||||||
|
.pointer
|
||||||
|
.interact_pos();
|
||||||
if let Some(pointer_pos) = pointer_pos {
|
if let Some(pointer_pos) = pointer_pos {
|
||||||
if let Some(rects) = ctx.layer_rects_prev_frame.get(&layer_id) {
|
if let Some(rects) = ctx.layer_rects_prev_frame.get(&layer_id) {
|
||||||
for &(prev_id, prev_rect) in rects.iter().rev() {
|
for &(prev_id, prev_rect) in rects.iter().rev() {
|
||||||
@@ -818,12 +841,13 @@ impl Context {
|
|||||||
let clicked_elsewhere = response.clicked_elsewhere();
|
let clicked_elsewhere = response.clicked_elsewhere();
|
||||||
self.write(|ctx| {
|
self.write(|ctx| {
|
||||||
let memory = &mut ctx.memory;
|
let memory = &mut ctx.memory;
|
||||||
let input = &mut ctx.input;
|
|
||||||
|
|
||||||
if sense.focusable {
|
if sense.focusable {
|
||||||
memory.interested_in_focus(id);
|
memory.interested_in_focus(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let input = ctx.input.get_mut(&ctx.current_rendering_viewport).unwrap();
|
||||||
|
|
||||||
if sense.click
|
if sense.click
|
||||||
&& memory.has_focus(response.id)
|
&& memory.has_focus(response.id)
|
||||||
&& (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter))
|
&& (input.key_pressed(Key::Space) || input.key_pressed(Key::Enter))
|
||||||
@@ -1280,7 +1304,10 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let textures_delta = self.write(|ctx| {
|
let textures_delta = self.write(|ctx| {
|
||||||
ctx.memory.end_frame(&ctx.input, &ctx.frame_state.used_ids);
|
ctx.memory.end_frame(
|
||||||
|
ctx.input.get(&ctx.current_rendering_viewport).unwrap(),
|
||||||
|
&ctx.frame_state.used_ids,
|
||||||
|
);
|
||||||
|
|
||||||
let font_image_delta = ctx.fonts.as_ref().unwrap().font_image_delta();
|
let font_image_delta = ctx.fonts.as_ref().unwrap().font_image_delta();
|
||||||
if let Some(font_image_delta) = font_image_delta {
|
if let Some(font_image_delta) = font_image_delta {
|
||||||
@@ -1333,6 +1360,8 @@ impl Context {
|
|||||||
});
|
});
|
||||||
viewports.push(0);
|
viewports.push(0);
|
||||||
|
|
||||||
|
self.write(|ctx| ctx.input.retain(|id, _| viewports.contains(&id)));
|
||||||
|
|
||||||
let repaint_after = self.write(|ctx| {
|
let repaint_after = self.write(|ctx| {
|
||||||
ctx.repaint
|
ctx.repaint
|
||||||
.end_frame(ctx.current_rendering_viewport, viewports)
|
.end_frame(ctx.current_rendering_viewport, viewports)
|
||||||
@@ -1387,7 +1416,11 @@ impl Context {
|
|||||||
|
|
||||||
// here we expect that we are the only user of context, since frame is ended
|
// here we expect that we are the only user of context, since frame is ended
|
||||||
self.write(|ctx| {
|
self.write(|ctx| {
|
||||||
let pixels_per_point = ctx.input.pixels_per_point();
|
let pixels_per_point = ctx
|
||||||
|
.input
|
||||||
|
.entry(ctx.current_rendering_viewport)
|
||||||
|
.or_default()
|
||||||
|
.pixels_per_point();
|
||||||
let tessellation_options = ctx.memory.options.tessellation_options;
|
let tessellation_options = ctx.memory.options.tessellation_options;
|
||||||
let texture_atlas = ctx
|
let texture_atlas = ctx
|
||||||
.fonts
|
.fonts
|
||||||
@@ -1599,8 +1632,12 @@ impl Context {
|
|||||||
/// Like [`Self::animate_bool`] but allows you to control the animation time.
|
/// Like [`Self::animate_bool`] but allows you to control the animation time.
|
||||||
pub fn animate_bool_with_time(&self, id: Id, target_value: bool, animation_time: f32) -> f32 {
|
pub fn animate_bool_with_time(&self, id: Id, target_value: bool, animation_time: f32) -> f32 {
|
||||||
let animated_value = self.write(|ctx| {
|
let animated_value = self.write(|ctx| {
|
||||||
ctx.animation_manager
|
ctx.animation_manager.animate_bool(
|
||||||
.animate_bool(&ctx.input, animation_time, id, target_value)
|
ctx.input.get(&ctx.current_rendering_viewport).unwrap(),
|
||||||
|
animation_time,
|
||||||
|
id,
|
||||||
|
target_value,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
let animation_in_progress = 0.0 < animated_value && animated_value < 1.0;
|
let animation_in_progress = 0.0 < animated_value && animated_value < 1.0;
|
||||||
if animation_in_progress {
|
if animation_in_progress {
|
||||||
@@ -1615,8 +1652,12 @@ impl Context {
|
|||||||
/// When it is called with a new value, it linearly interpolates to it in the given time.
|
/// When it is called with a new value, it linearly interpolates to it in the given time.
|
||||||
pub fn animate_value_with_time(&self, id: Id, target_value: f32, animation_time: f32) -> f32 {
|
pub fn animate_value_with_time(&self, id: Id, target_value: f32, animation_time: f32) -> f32 {
|
||||||
let animated_value = self.write(|ctx| {
|
let animated_value = self.write(|ctx| {
|
||||||
ctx.animation_manager
|
ctx.animation_manager.animate_value(
|
||||||
.animate_value(&ctx.input, animation_time, id, target_value)
|
ctx.input.get(&ctx.current_rendering_viewport).unwrap(),
|
||||||
|
animation_time,
|
||||||
|
id,
|
||||||
|
target_value,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
let animation_in_progress = animated_value != target_value;
|
let animation_in_progress = animated_value != target_value;
|
||||||
if animation_in_progress {
|
if animation_in_progress {
|
||||||
|
|||||||
Reference in New Issue
Block a user