-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do all widget interaction at the start of the frame #3936
Comments
Side note for drag-sensitive areas, in the context of e.g. hierarchical list (as in #3903). It's rather important that the drop zone be exactly contiguous. Otherwise, this could introduce a discontinuity when the mouse moves from the bottom of a widget to the top of the next one, with the insertion marker disappearing and the drop potentially failing. Here are the drop zones for this example: This is easy to achieve with custom widget and |
I just realized this is going to make styling a lot easier, since we know before adding a widget wether or not it is hovered, dragged etc, which means we can pick its colors (and margins) based on ints interaction state before allocating space for the widget! This makes this issue an important part of: |
* Closes #3936 * Closes #3923 * Closes #4058 The interaction code is now done at the start of the frame, using stored `WidgetRect`s from the previous frame. The intention is that the new interaction code should be more accurate, making it easier to hit widgets, and better respecting the rules of overlapping widgets. There is a new `style::Interaction::interact_radius` controlling how far away from a widget the cursor can be and still hit it. This helps big fat fingers hit small widgets on touch screens. This PR adds a new `Context::read_response` which lets you read the `Response` of a `Widget` _before_ you create the widget. This can be used for styling, or for reading the result of an interaction early (to prevent frame-delay) for a widget you add late (so it is on top of other widgets). #⚠️ BREAKING CHANGES `Memory::dragged_id`, `Memory::set_dragged_id` etc have been moved to `Context`. The semantics for `Context::dragged_id` is slightly different: a widget is not considered dragged until egui it is sure this is not a click-in-progress. For a widget that is only sensitive to drags, that is right away, but for widgets sensitive to both clicks and drags it is not until the mouse has moved a certain distance. # TODO * [x] Fix panel resizing * [x] Fix scroll hover weirdness * [x] Fix Resize widget * [x] Fix drag-and-drop * [x] Test all of egui_demo_app * [x] Change `is_dragging` API * [x] Consistent naming of start/stop or begin/end drag * [x] Test `egui_tiles` * [x] Test Rerun * [x] Document * [x] Document breaking changes in PR description * [x] Test one final time # Saving for a later PR * [ ] Fix #4047 * [ ] Specify what the response order for e.g. `ui.horizontal` is I think both these can be fixed if each `Ui` registers themselves as a `WidgetRect`, with the possibility to interact with it later, as if the interaction was under all widgets on top of it.
* Closes emilk/egui#3936 * Closes emilk/egui#3923 * Closes emilk/egui#4058 The interaction code is now done at the start of the frame, using stored `WidgetRect`s from the previous frame. The intention is that the new interaction code should be more accurate, making it easier to hit widgets, and better respecting the rules of overlapping widgets. There is a new `style::Interaction::interact_radius` controlling how far away from a widget the cursor can be and still hit it. This helps big fat fingers hit small widgets on touch screens. This PR adds a new `Context::read_response` which lets you read the `Response` of a `Widget` _before_ you create the widget. This can be used for styling, or for reading the result of an interaction early (to prevent frame-delay) for a widget you add late (so it is on top of other widgets). #⚠️ BREAKING CHANGES `Memory::dragged_id`, `Memory::set_dragged_id` etc have been moved to `Context`. The semantics for `Context::dragged_id` is slightly different: a widget is not considered dragged until egui it is sure this is not a click-in-progress. For a widget that is only sensitive to drags, that is right away, but for widgets sensitive to both clicks and drags it is not until the mouse has moved a certain distance. # TODO * [x] Fix panel resizing * [x] Fix scroll hover weirdness * [x] Fix Resize widget * [x] Fix drag-and-drop * [x] Test all of egui_demo_app * [x] Change `is_dragging` API * [x] Consistent naming of start/stop or begin/end drag * [x] Test `egui_tiles` * [x] Test Rerun * [x] Document * [x] Document breaking changes in PR description * [x] Test one final time # Saving for a later PR * [ ] Fix emilk/egui#4047 * [ ] Specify what the response order for e.g. `ui.horizontal` is I think both these can be fixed if each `Ui` registers themselves as a `WidgetRect`, with the possibility to interact with it later, as if the interaction was under all widgets on top of it.
* Closes emilk/egui#3936 * Closes emilk/egui#3923 * Closes emilk/egui#4058 The interaction code is now done at the start of the frame, using stored `WidgetRect`s from the previous frame. The intention is that the new interaction code should be more accurate, making it easier to hit widgets, and better respecting the rules of overlapping widgets. There is a new `style::Interaction::interact_radius` controlling how far away from a widget the cursor can be and still hit it. This helps big fat fingers hit small widgets on touch screens. This PR adds a new `Context::read_response` which lets you read the `Response` of a `Widget` _before_ you create the widget. This can be used for styling, or for reading the result of an interaction early (to prevent frame-delay) for a widget you add late (so it is on top of other widgets). #⚠️ BREAKING CHANGES `Memory::dragged_id`, `Memory::set_dragged_id` etc have been moved to `Context`. The semantics for `Context::dragged_id` is slightly different: a widget is not considered dragged until egui it is sure this is not a click-in-progress. For a widget that is only sensitive to drags, that is right away, but for widgets sensitive to both clicks and drags it is not until the mouse has moved a certain distance. # TODO * [x] Fix panel resizing * [x] Fix scroll hover weirdness * [x] Fix Resize widget * [x] Fix drag-and-drop * [x] Test all of egui_demo_app * [x] Change `is_dragging` API * [x] Consistent naming of start/stop or begin/end drag * [x] Test `egui_tiles` * [x] Test Rerun * [x] Document * [x] Document breaking changes in PR description * [x] Test one final time # Saving for a later PR * [ ] Fix emilk/egui#4047 * [ ] Specify what the response order for e.g. `ui.horizontal` is I think both these can be fixed if each `Ui` registers themselves as a `WidgetRect`, with the possibility to interact with it later, as if the interaction was under all widgets on top of it.
* Closes emilk#3936 * Closes emilk#3923 * Closes emilk#4058 The interaction code is now done at the start of the frame, using stored `WidgetRect`s from the previous frame. The intention is that the new interaction code should be more accurate, making it easier to hit widgets, and better respecting the rules of overlapping widgets. There is a new `style::Interaction::interact_radius` controlling how far away from a widget the cursor can be and still hit it. This helps big fat fingers hit small widgets on touch screens. This PR adds a new `Context::read_response` which lets you read the `Response` of a `Widget` _before_ you create the widget. This can be used for styling, or for reading the result of an interaction early (to prevent frame-delay) for a widget you add late (so it is on top of other widgets). #⚠️ BREAKING CHANGES `Memory::dragged_id`, `Memory::set_dragged_id` etc have been moved to `Context`. The semantics for `Context::dragged_id` is slightly different: a widget is not considered dragged until egui it is sure this is not a click-in-progress. For a widget that is only sensitive to drags, that is right away, but for widgets sensitive to both clicks and drags it is not until the mouse has moved a certain distance. # TODO * [x] Fix panel resizing * [x] Fix scroll hover weirdness * [x] Fix Resize widget * [x] Fix drag-and-drop * [x] Test all of egui_demo_app * [x] Change `is_dragging` API * [x] Consistent naming of start/stop or begin/end drag * [x] Test `egui_tiles` * [x] Test Rerun * [x] Document * [x] Document breaking changes in PR description * [x] Test one final time # Saving for a later PR * [ ] Fix emilk#4047 * [ ] Specify what the response order for e.g. `ui.horizontal` is I think both these can be fixed if each `Ui` registers themselves as a `WidgetRect`, with the possibility to interact with it later, as if the interaction was under all widgets on top of it.
Context
usesWidgetRects
to store the rectangles of all widgets from the previous frame.Context::interact
uses this to check that no tother widget is covering the current widget.This code could be simplified by doing the hit-test once at the start of the frame, using the
WidgetRects
from the previous frame.With full knowledge, we could to a smart hit-test where we look for all widget within a certain small radius of the pointer, and hover/click/drag the closest one. This allows for slightly bigger hit-boxes, making things easier to click. This could replace the current hack of growing hit boxes by
item_spacing / 2
.Note that we needs to find the top widget for clicks and for drags separately, because the top widget that is click-sensitive (e.g. a button) can be different from the top widget that is drag-sensitive (e.g. a ScrollArea).
The text was updated successfully, but these errors were encountered: