-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Exposes Common Window Resolutions as an Enum. #14158
Conversation
Welcome, new contributor! Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please run cargo fmt
🙂
Should we add a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, we can add the Custom
variant if necessary in another PR
Apologies for that btw. I was working on it while you were reviewing and I didn't notice. I'm fine with adding a Also there are a few questions regarding the resolutions, as an example exposing a 4k variant would also probably be useful, and 360p can technically be one of two resolutions. That is, 480 x 360 which is 4:3 and 680 x 360 which is 16:9. I went with the latter because that's what I tend to use, and it works better with other resolutions (mostly having to do with scaling better to 720p and higher). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having both WindowResolution
and Resolution
could lead to confusion. How about renaming it to CommonScreenResolution
? That's what the doc comment says anyways.
I'm not against Also should it be |
I quite like this: this is a utility that almost every game will want. To make this better:
Long-term I'd like to see more variants and an |
FWIW I've tended to implement things similar to this across a few games now, because it's useful to not have to try and remember the exact details about the resolution I'm using. I'm also more than willing to add in more variants as well. I just started off with what I tend to use (plus 2k). Also, should I change the usage of the default construction of WindowResolution to use the enum? It's currently set to 1280x720 by default. (Also I just realized this could be used to change the default WindowResolutions through some sort of setting or something if desired in the future) |
I was thinking: enum CommonAspectRatio {
FourToThree,
SixteenToNine
} We should also have a |
Fair enough. I'll go ahead and implement That would also be rather useful, although I'm not sure how it would entirely work, but it would help with cases where a resolution can be one of two -- dependent upon the Aspect Ratio. (Technically 360p could be split into "360p" and "nHD" (the former being 4:3 and the latter being 16:9) as those are the Standard Names, according to Wikipedia. However, the class for both is 360p and I don't think a lot of people would recognize nHD tbqh.) |
Please do use it in |
Would we want it to display "w x h" or something like the name ("360p", "720p", etc)? I've created an implementation that does the former based on this comment, as I imagine that it would probably be more useful for in game menus. But thought I would ask just to make sure. |
The former is what I've seen in game menus so I think it's better to stick to that. |
fn toggle_resolutions(input: Res<ButtonInput<KeyCode>>, mut windows: Query<&mut Window>) { | ||
if input.just_pressed(KeyCode::KeyR) { | ||
let mut window = windows.single_mut(); | ||
let current_resolution = CommonScreenResolution::iter() | ||
.find(|&r| WindowResolution::from(r) == window.resolution); | ||
window.resolution = if current_resolution.is_none() { | ||
CommonScreenResolution::R360p.into() | ||
} else { | ||
let resolutions = CommonScreenResolution::iter() | ||
.map(std::convert::Into::into) | ||
.collect::<Vec<CommonScreenResolution>>(); | ||
let current_resolution_index = CommonScreenResolution::iter() | ||
.position(|r| r == current_resolution.unwrap()) | ||
.unwrap(); | ||
|
||
if current_resolution_index + 1 >= resolutions.len() { | ||
resolutions[0].into() | ||
} else { | ||
resolutions[current_resolution_index + 1].into() | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be more idiomatic if CurrentResolution
was a Resource
initialized at CommonScreenResolution::R360p
imo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use Iterator::cycle()
, store that as a resource and call next
every time input is pressed
R1080p, | ||
|
||
/// 2560 x 1440 | ||
R2k, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling QHD resolution 2K is a misnomer. 2K is closer to 1080p (FullHD) than 2.5k (QHD).
Hey, thanks for letting me know about that and I would really like some advice on adapting it to work with that as well, since I'm not entirely certain how it should tbh. |
Paging @miniex, you may have ideas here as well :) |
I like structure that can be dynamically created and extended. First, what about resolution cateogry? ex: pub enum ResolutionCategory {
HD,
FHD,
QHD,
Mobile,
Ultrawide,
}
impl CommonScreenResolution {
pub fn category(&self) -> ResolutionCategory {
...
}
} And, i like a good idea to allow them to be made in Then, that make it easier to add documents or solutions? My english is bad, so I'm not sure if i understood it. ToT |
I'm not sure I understand how this is supposed to work, tbqh. Could you try and elaborate or provide some examples? |
I don't think this should be an enum and I'm not convinced at all it even needs to exists. An ordered list could make sense for a setting menu, but that list should be dynamically generated based on what the hardware supports. It should include ultrawide resolutions for people using an ultrawide. Monitors are not limited to just 16:9. Games or apps should pretty much never hardcode a resolution and they should adapt their game to work at any aspect ratio and resolution. Some games need a fixed aspect ratio for artistic reasons, while I personally disagree that it should ever be done, if a game has to do it, it should not be done at the window level. The window should still be able to scale to any screen size. If we had to make a list, and I really don't think we should, but we should use something like steam hardware survey. We shouldn't encourage people to test at a fixed 16:9 ratio, it just makes things more painful for any player that doesn't have a 16:9 screen. |
My opinion is same as @IceSentry. use bevy_math::AspectRatio;
pub struct Resolution {
width: u32,
height: u32,
category: ResolutionCategory,
}
pub enum ResolutionCategory {
HD,
FHD,
QHD,
Mobile,
Ultrawide,
}
impl Resolution {
pub fn new(width: u32, height: u32, category: ResolutionCategory)
pub fn aspect_ratio(&self) -> AspectRatio
}
pub struct CommonScreenResolutions {
resolutions: HashMap<String, Resolution>,
}
impl CommonScreenResolutions {
// or default
pub fn new() -> Self {
let mut resolutions = HashMap::new();
resolutions.insert("360p_4:3", Resolution::new(480, 360, ResolutionCategory::SD));
resolutions.insert("360p_16:9", Resolution::new(640, 360, ResolutionCategory::SD));
resolutions.insert("720p", Resolution::new(1280, 720, ResolutionCategory::HD));
resolutions.insert("1080p", Resolution::new(1920, 1080, ResolutionCategory::FHD));
Self { resolutions }
}
pub fn add(&mut self, name: String, resolution: Resolution)
pub fn get(&self, name: &str) -> Option<&Resolution>
pub fn find_by_dimensions(&self, width: u32, height: u32) -> Option<(&String, &Resolution)>
pub fn find_by_aspect_ratio(&self, aspect_ratio: AspectRatio) -> Vec<(&String, &Resolution)>
} |
|
I strongly disagree, as this is a common thing that I've had to setup for all of my projects, and it's a pain point that Bevy has, in that this is rather unfriendly IMHO. It's also not uncommon for 2D games in particular to focus on specific resolutions that they support as well, especially if you're doing pixel art. |
Reopening, but marking controversial. |
FWIW, a lot of games in my Steam library either prevent you from resizing the window to a different aspect ratio, or very clearly were not tested on different aspect ratios. Those are real published games. Sure, it would be nice for a game to support any aspect ratio, but evidently it isn't necessary and many developers consider it not worth the effort and artistic compromise. |
We should have an easy way to do letterboxing of course, but hiding this behind something that appears as a "common resolution" is not the way it should be done. Common resolution are a myth and we shoudn't encourage devs to believe there is such a thing as a common resolution. It should be very clear that it is something only used for letterboxing for artistic purposes.
I'm extremely aware of that and it's one of the main reason why I don't want to push people towards a limited set of resolution at a fixed aspect ratio. Most games actually do handle this correctly which makes the ones that don't even more jarring. I really don't think this should be encouraged by making this the easy path and calling it a common resolution. |
I agree. Any "opinionated" view of available resolutions is a user-facing problem to solve (either directly by the app developer, or as a 3rd party ecosystem plugin). I'm pretty adamantly against including this upstream, so in the interest of saving time I'm closing this out. @Sapein I encourage you to create a 3rd party plugin for this! (and register it in Bevy Assets) |
@IceSentry @cart interesting, I didn't know that having such a list hardcoded in the settings was considered bad practice. Thanks for pointing it out :) |
Update: the answer is |
Yup the answer is some combination of querying for supported resolutions, constraining to specific resolutions, and letterboxing. For letterboxing (including how to do it with Render Targets and Bevy UI), see this issue: #15130 Many games choose to constrain to specific aspect ratios or specific resolutions for artistic or gameplay reasons, especially many 2D pixel-perfect games, but also some 3D games (such as competitive shooters like Valorant). Bevy's job isn't to lock in what specific resolutions or aspect ratios to support (or recommend). Bevy's job is to provide the full range of support and let developers adopt whatever constraints they want. |
Objective
Implements: #14153
Solution
Exposes Common Window Resolutions that are likely to be used through an Enum (Resolution) that can be turned into a UVec2 and an iterable.
Testing
I've tested this briefly locally. I wrote a small test just to double check that things worked as expected and it passed.