-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Add a gizmo-based overlay to show UI node outlines (Adopted) #11237
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
Merged
Merged
Changes from 66 commits
Commits
Show all changes
71 commits
Select commit
Hold shift + click to select a range
d929a43
Add a gizmo-based overlay to show UI node outlines
nicopap 2b94433
Document cargo feature
nicopap 09900de
Merge branch 'main' into debug-ui-rects
7e6092c
[alt] Changed debug feature name
pablo-lua e9dd91b
[alt] Changed DebugUiPlugin to DefaultPlugins
pablo-lua c1b88de
[fix] Fixed new changes conflicts
pablo-lua 981e519
[alt] Changed types make easier customize toggle_key
pablo-lua 6766d90
[rem] Removed unnecessary import
pablo-lua 59729e0
[style] Cargo fmt
pablo-lua 7ea6b57
[fix] Clippy warnings
pablo-lua 15ad9ec
[fix] Fixed missing semicolon
pablo-lua 1dd32a5
[alt] Removed DebugUiPlugin from DefaultPlugins
pablo-lua d822a29
[alt] Removed keybinding and changed DebugOptions name
pablo-lua c35f8f2
[add] Added suport to Hidden visibility
pablo-lua 19fd896
Merge branch 'main' into debug-ui-rects
pablo-lua fad14d7
[add] Added support to UiScale
pablo-lua c5bbbc6
[fix] Clippy warning
pablo-lua 5f2f9f3
[doc] Added extra docs
pablo-lua 0b8ef8f
Merge branch 'main' into debug-ui-rects
pablo-lua 47022f2
[add] Added toggle_overlay system in ui example
pablo-lua cb57e6e
[add] Added text to warn the user about the feature
pablo-lua 27332f7
[fix] Fixed comment position
pablo-lua bfee273
[add] Added info to enabled feature
pablo-lua 4089834
[doc] Fixed docs
pablo-lua 202fb95
[add] Added text when user doesn't enable bevy_ui_debug
pablo-lua 15353a0
[style] Cargo fmt
pablo-lua 81f2566
Merge branch 'debug-ui-rects' of github.com:pablo-lua/bevy into debug…
pablo-lua cf74585
Merge branch 'main' into debug-ui-rects
pablo-lua 2dfbe86
Merge branch 'main' into debug-ui-rects
pablo-lua d51bcf2
Merge branch 'main' into debug-ui-rects
pablo-lua 7aa6540
Merge branch 'main' into debug-ui-rects
pablo-lua ff0d3da
Merge branch 'main' into debug-ui-rects
pablo-lua 4e3b422
[fix] Fixed wrong behavior caused by update in ui
pablo-lua 95cfd6e
[alt] Improved warn message to warn only once
pablo-lua affc06c
[add] Added marker component to Ui example camera
pablo-lua 61d90d5
[style] Cargo fmt
pablo-lua 8455720
[style] Improved Code quality
pablo-lua 60ed352
[docs] Fix docs
pablo-lua 29f8022
Merge branch 'main' into debug-ui-rects
pablo-lua ec3cd72
Merge branch 'main' into debug-ui-rects
alice-i-cecile 9c52af9
[fix] Little fix on comment
pablo-lua 12f4e64
[doc] Changed docs note
pablo-lua d20a5d8
[alt] Improvements on options settings
pablo-lua 494c4dd
[doc] Fixed docs mention to extern crate
pablo-lua cedc4ab
Merge branch 'main' into debug-ui-rects
pablo-lua 4fd89f2
[cargo] Fix version requirement
pablo-lua 3c52c7b
Merge branch 'main' into debug-ui-rects
pablo-lua 61a0eee
Merge branch 'main' into debug-ui-rects
pablo-lua 56509e6
[style] Cargo fmt
pablo-lua a50f02a
Update docs.yml
pablo-lua dd1d3bb
Merge branch 'main' into debug-ui-rects
pablo-lua 785538a
Merge branch 'main' of https://github.com/bevyengine/bevy
pablo-lua 6c1a1ec
Merge branch 'bevyengine:main' into debug-ui-rects
pablo-lua 2f22e53
Merge branch 'main' of github.com:pablo-lua/bevy
pablo-lua d6a674b
Merge branch 'main' of github.com:pablo-lua/bevy
pablo-lua d2060e8
Merge branch 'main' into debug-ui-rects
pablo-lua e3e0061
Merge branch 'main' of github.com:pablo-lua/bevy
pablo-lua 36d4f1f
Merge branch 'main' into debug-ui-rects
pablo-lua 7419481
[alt] Move debug_overlay to bevy_dev_tools crate
pablo-lua 3f978ad
[alt] Revert local change added by mistake
pablo-lua 51ef533
[alt] Revert changes on ui toml
pablo-lua bd26750
[alt] Revert changes on ui toml
pablo-lua f78f747
Merge branch 'debug-ui-rects' of github.com:pablo-lua/bevy into debug…
pablo-lua 6477000
[style] Cargo fmt
pablo-lua 44c728c
Merge branch 'main' into debug-ui-rects
pablo-lua 0d74b08
Merge branch 'main' into debug-ui-rects
pablo-lua d1787a5
[rem] Removed bevy_ui_debug from top level features
pablo-lua 434cd2e
[rem] Removed trait ApproxF32
pablo-lua 5fc4458
[alt] Fixed CI
pablo-lua 13985d6
Merge branch 'main' into debug-ui-rects
pablo-lua 2cfffd8
[fix] Duplicate entry on dev_tools TOML
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
use bevy_color::Color; | ||
use bevy_gizmos::{config::GizmoConfigGroup, prelude::Gizmos}; | ||
use bevy_math::{Vec2, Vec2Swizzles}; | ||
use bevy_reflect::Reflect; | ||
use bevy_transform::prelude::GlobalTransform; | ||
use bevy_utils::HashMap; | ||
|
||
use super::{CameraQuery, LayoutRect}; | ||
|
||
trait ApproxF32 { | ||
pablo-lua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fn is(self, other: f32) -> bool; | ||
} | ||
impl ApproxF32 for f32 { | ||
fn is(self, other: f32) -> bool { | ||
let diff = (self - other).abs(); | ||
diff < 0.001 | ||
pablo-lua marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
fn rect_border_axis(rect: LayoutRect) -> (f32, f32, f32, f32) { | ||
let pos = rect.pos; | ||
let size = rect.size; | ||
let offset = pos + size; | ||
(pos.x, offset.x, pos.y, offset.y) | ||
} | ||
|
||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] | ||
enum Dir { | ||
Start, | ||
End, | ||
} | ||
impl Dir { | ||
const fn increments(self) -> i64 { | ||
match self { | ||
Dir::Start => 1, | ||
Dir::End => -1, | ||
} | ||
} | ||
} | ||
impl From<i64> for Dir { | ||
fn from(value: i64) -> Self { | ||
if value.is_positive() { | ||
Dir::Start | ||
} else { | ||
Dir::End | ||
} | ||
} | ||
} | ||
/// Collection of axis aligned "lines" (actually just their coordinate on | ||
/// a given axis). | ||
#[derive(Debug, Clone)] | ||
struct DrawnLines { | ||
lines: HashMap<i64, Dir>, | ||
width: f32, | ||
} | ||
#[allow(clippy::cast_precision_loss, clippy::cast_possible_truncation)] | ||
impl DrawnLines { | ||
fn new(width: f32) -> Self { | ||
DrawnLines { | ||
lines: HashMap::new(), | ||
width, | ||
} | ||
} | ||
/// Return `value` offset by as many `increment`s as necessary to make it | ||
/// not overlap with already drawn lines. | ||
fn inset(&self, value: f32) -> f32 { | ||
let scaled = value / self.width; | ||
let fract = scaled.fract(); | ||
let mut on_grid = scaled.floor() as i64; | ||
for _ in 0..10 { | ||
let Some(dir) = self.lines.get(&on_grid) else { | ||
break; | ||
}; | ||
// TODO(clean): This fixes a panic, but I'm not sure how valid this is | ||
let Some(added) = on_grid.checked_add(dir.increments()) else { | ||
break; | ||
}; | ||
on_grid = added; | ||
} | ||
((on_grid as f32) + fract) * self.width | ||
} | ||
/// Remove a line from the collection of drawn lines. | ||
/// | ||
/// Typically, we only care for pre-existing lines when drawing the children | ||
/// of a container, nothing more. So we remove it after we are done with | ||
/// the children. | ||
fn remove(&mut self, value: f32, increment: i64) { | ||
let mut on_grid = (value / self.width).floor() as i64; | ||
loop { | ||
// TODO(clean): This fixes a panic, but I'm not sure how valid this is | ||
let Some(next_cell) = on_grid.checked_add(increment) else { | ||
return; | ||
}; | ||
if !self.lines.contains_key(&next_cell) { | ||
self.lines.remove(&on_grid); | ||
return; | ||
} | ||
on_grid = next_cell; | ||
} | ||
} | ||
/// Add a line from the collection of drawn lines. | ||
fn add(&mut self, value: f32, increment: i64) { | ||
let mut on_grid = (value / self.width).floor() as i64; | ||
loop { | ||
let old_value = self.lines.insert(on_grid, increment.into()); | ||
if old_value.is_none() { | ||
return; | ||
} | ||
// TODO(clean): This fixes a panic, but I'm not sure how valid this is | ||
let Some(added) = on_grid.checked_add(increment) else { | ||
return; | ||
}; | ||
on_grid = added; | ||
} | ||
} | ||
} | ||
|
||
#[derive(GizmoConfigGroup, Reflect, Default)] | ||
pub struct UiGizmosDebug; | ||
|
||
pub(super) struct InsetGizmo<'w, 's> { | ||
draw: Gizmos<'w, 's, UiGizmosDebug>, | ||
cam: CameraQuery<'w, 's>, | ||
known_y: DrawnLines, | ||
known_x: DrawnLines, | ||
} | ||
impl<'w, 's> InsetGizmo<'w, 's> { | ||
pub(super) fn new( | ||
draw: Gizmos<'w, 's, UiGizmosDebug>, | ||
cam: CameraQuery<'w, 's>, | ||
line_width: f32, | ||
) -> Self { | ||
InsetGizmo { | ||
draw, | ||
cam, | ||
known_y: DrawnLines::new(line_width), | ||
known_x: DrawnLines::new(line_width), | ||
} | ||
} | ||
fn relative(&self, mut position: Vec2) -> Vec2 { | ||
let zero = GlobalTransform::IDENTITY; | ||
let Ok(cam) = self.cam.get_single() else { | ||
return Vec2::ZERO; | ||
}; | ||
if let Some(new_position) = cam.world_to_viewport(&zero, position.extend(0.)) { | ||
position = new_position; | ||
}; | ||
position.xy() | ||
} | ||
fn line_2d(&mut self, mut start: Vec2, mut end: Vec2, color: Color) { | ||
if start.x.is(end.x) { | ||
start.x = self.known_x.inset(start.x); | ||
end.x = start.x; | ||
} else if start.y.is(end.y) { | ||
start.y = self.known_y.inset(start.y); | ||
end.y = start.y; | ||
} | ||
let (start, end) = (self.relative(start), self.relative(end)); | ||
self.draw.line_2d(start, end, color); | ||
} | ||
pub(super) fn set_scope(&mut self, rect: LayoutRect) { | ||
let (left, right, top, bottom) = rect_border_axis(rect); | ||
self.known_x.add(left, 1); | ||
self.known_x.add(right, -1); | ||
self.known_y.add(top, 1); | ||
self.known_y.add(bottom, -1); | ||
} | ||
pub(super) fn clear_scope(&mut self, rect: LayoutRect) { | ||
let (left, right, top, bottom) = rect_border_axis(rect); | ||
self.known_x.remove(left, 1); | ||
self.known_x.remove(right, -1); | ||
self.known_y.remove(top, 1); | ||
self.known_y.remove(bottom, -1); | ||
} | ||
pub(super) fn rect_2d(&mut self, rect: LayoutRect, color: Color) { | ||
let (left, right, top, bottom) = rect_border_axis(rect); | ||
if left.is(right) { | ||
self.line_2d(Vec2::new(left, top), Vec2::new(left, bottom), color); | ||
} else if top.is(bottom) { | ||
self.line_2d(Vec2::new(left, top), Vec2::new(right, top), color); | ||
} else { | ||
let inset_x = |v| self.known_x.inset(v); | ||
let inset_y = |v| self.known_y.inset(v); | ||
let (left, right) = (inset_x(left), inset_x(right)); | ||
let (top, bottom) = (inset_y(top), inset_y(bottom)); | ||
let strip = [ | ||
Vec2::new(left, top), | ||
Vec2::new(left, bottom), | ||
Vec2::new(right, bottom), | ||
Vec2::new(right, top), | ||
Vec2::new(left, top), | ||
]; | ||
self.draw | ||
.linestrip_2d(strip.map(|v| self.relative(v)), color); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.