Closed karai17 closed 9 years ago
ROBLOX actually has a nice UI system using a unit called UDim2. You get a percent scale (of the parent element) and an absolute pixel size, which makes sizing things to scale relatively easy.
Additionally, you can set modes like RelativeXX, RelativeXY, and RelativeYY to tell the system which screen dimensions to use for the corresponding scale in the UDim2. This lets you deal with weird aspect ratio screens the same way you would with a screen you prepared for.
Also remember to use HighDPI when available, so that the user interface looks better.
Percentage and Normal Pixel should be mandatory.
Also think about what CSS does with @media
that allows you to change how you style in screens bigger or smaller than a known amount:
@media (min-width:767px){
.nav-pills>li>a{
text-align: left
}
}
I'm fine if I have those
Question... Elements have border, padding, margin, width, height and float, maybe even top,left,right and bottom, position relative and absolute? If they do then I can just do with normal pixels plus the @media
thingy
We can also do our math... with standard Lua so most of the things can be solved with positioning and pixels. Not even the media is needed if you can do:
screen.width > 100 and 50
or if screen.width > 100 then some-styling-here end
Pixels are unpleasant to work with since screens can vary so much in size, both pixels and pixel density. One major issue is aspect ratio. Many games these days have scalable UIs where a user can scale up or down the whole UI (Minecraft does this, as so several modern MMOs) to fit their screen without affecting the UI objects themselves. Positioning can also be a pain: do you want the minimap to be 20 pixels from the top on both a 1080p 23 inch screen and a 720p 19 inch screen, or do you want it to be 1 centimetre? Do you want the object itself to be exactly 200 pixels in size on both screens, or do you want it to be 5 centimetres, or perhaps some scale value? You wouldn't want fixed-pixel objects overlapping each other because someone has an old CRT screen.
Percentage is the best option, plus getting the PixelScale of the device where available (all Android phones, iOS and MacOSx support it) also the media thingy I talked about, with those you can get away pretty fine... For examples on this check bootstrap they do it so nicely and so simple!
Yeah, percentage is what I had in mind as a primary coordinate system (using floating points). But obviously percentage isn't ideal for everything. It's great for positioning root objects such as window frames, but the actual size of most objects should be more defined, though I don't think pixels is the way to go. Android's XML GUI framework promotes the use of pt over px, would that be a useful unit of measurement? Would em or ex be more useful? I've always been fond of using pt at least when dealing with fonts in CSS since the font will always scale appropriately to the display it is being rendered on, whereas px will be a static size.
Pt is actually pixels multiplied by the PixelScale so yeah! We are talking about the same thing here
A note from the barely awake @shakesoda, using dp and sp units would be more useful than pt or px:
http://stackoverflow.com/questions/2025282/difference-between-px-dp-dip-and-sp-in-android
http://blog.edwinevans.me/?p=131
http://developer.android.com/guide/practices/screens_support.html
According to @slime73, LOVE (more specifically, SDL) does not currently support retrieving physical screen size, only number of pixels. Here are his thoughts on the matter:
[20:28:10] <Karai> slime: does love have access to pixel density on all supported OSs?
[20:28:25] <Karai> and system font scale?
[20:44:16] <+slime> Karai: no
[20:44:29] <Karai> slime: Is that something that is planned for the future?
[20:44:38] <+slime> Karai: maybe, i dunno
[20:44:39] <Karai> Basically, I need a way to define dp and sp units
[20:45:13] <+slime> Karai: in OSX and iOS and Android it exposes the scale needed to go from pixels to the size expected by users
[20:45:25] <+slime> Karai: Windows and Linux hasn't been hooked up to that in SDL yet though
[20:45:32] <Karai> Hrm..
[20:45:51] <Karai> Any possible work around?
[20:46:06] <+slime> Karai: or rather, it will always be 1 in Windows and Linux because there's no way to change it so that pixels aren't the size expected by users, on those operating systems
[20:46:07] <+slime> (yet)
[20:46:45] <+slime> that whole thing isn't quite the same as pixel density though, although it's similar
[20:47:08] <Karai> I suppose it's relatively safe to assume if the OS is Windows or Linux, then the screen resolution roughly matches screen size
[20:47:26] <Karai> a 1080p screen is probably 23 inches, 720 is probably 19 (maybe 17)
[20:47:40] <Karai> and in cases where it is not, the ability for a user to quickly scale would be nice
[20:48:09] <+slime> Karai: basically you should be wanting your app to have the same scale as the rest of the programs on that system
[20:48:15] <+slime> and that works fine on all OS' right now
[20:48:39] <Karai> Well I'm thinking about UI scaling
[20:50:21] <+slime> Karai: right, but the only time that won't be consistent with other apps on the system is when high-dpi mode is enabled, but on the systems where you can do that you can also account for it with love's apis
[20:51:53] <Karai> slime: I suppose...
I'm not really sure then how we could define proper units such as dp and sp if we cannot determine the pixel density of the display we are trying to account for.
A note from the barely awake @shakesoda, using dp and sp units would be more useful than pt or px
Indeed, if you use love.window.getPixelScale()
(or love.window.toPixels
/ love.window.fromPixels
– new in 0.9.2 – which are a nicer way to think about getPixelScale
) appropriately then you'll be using dp units on Android, and 'points' (Apple's equivalent) in OS X and iOS. Once SDL gets support for high-DPI mode in Windows and Linux it will do the same thing there as well.
That only leaves the most significant (and possibly second most significant) OS at a disadvantage since Windows and Linux only report a pixel scale of 1 regardless of dpi.
A side-question, how does Apple define its PixelScale? What is the base dpi that Apple (and possibly others) consider 1.0, and does it scale accordingly or is there only a jump from 1.0 to 2.0?
That only leaves the most significant (and possibly second most significant) OS at a disadvantage since Windows and Linux only report a pixel scale of 1 regardless of dpi.
That is fine and expected. It should be 1, since (as far as I know) the OS scales the window's contents up so that a pixel scale of 1 looks normal. Once SDL's Windows and Linux backends get hooked up to the right thing, you'll be able to disable the OS' scaling and then getPixelScale
will return variable results on those operating systems when you do that.
A side-question, how does Apple define its PixelScale? What is the base dpi that Apple (and possibly others) consider 1.0, and does it scale accordingly or is there only a jump from 1.0 to 2.0?
The idea is that you as a programmer don't need to care about the screen's actual DPI, you just care that it looks consistent with the rest of the system on that screen. So far there are only single- and double-resolution (1x and 2x) screens for OS X, and single-, double-, and ~2.6x resolution screens for iOS.
Android has the same idea with its mdpi (1x), hdpi (1.5x), xdpi (2x), etc.
So using getPixelScale, I can define my dp unit (and perhaps my sp unit) and in time, Windows and Linux will eventually fall into place.
Yeah, I don't think a programmer should need to worry about dpi which is why I want to define a dp unit for programmers to work with. My only concern I guess is that, lining up several devices, depending on how getPixelScale reports back the scale, would all objects have the same physical size?
Apple's very controlling over their hardware so it makes sense that their PixelScales are very specific, but will Android be reporting 1.0, 1.23, 2.28, etc? Would Windows and Linux in the future report those variances?
My only concern I guess is that, lining up several devices, depending on how getPixelScale reports back the scale, would all objects have the same physical size?
Not necessarily, but in those cases nothing in the system will be the same physical size on both devices, so the user won't expect your app to act any differently.
will Android be reporting 1.0, 1.23, 2.28, etc?
Android has a set of standard pixel scales (density ratios): http://developer.android.com/guide/practices/screens_support.html#range (re: its note about the 'new technique', you can do that with love.window.fromPixels(love.graphics.getDimensions())
, or love.graphics.getWidth() / love.window.getPixelScale()
)
Would Windows and Linux in the future report those variances?
I don't know the details of how things work on Windows and Linux, but I think Windows usually does 1.5x, 2x, etc. I'm not positive.
Alright, well I suppose if the idea here isn't so much as "Have the same physical size across devices" as it is "Do what the OS does and everyone is happy". This will allow me to... sort of... create my dp unit and base the rest of the library off of that.
That being said, I suppose there is no real way to get the system font scale on any OS for an sp unit?
That being said, I suppose there is no real way to get the system font scale on any OS for an sp unit?
I haven't looked into it. At the very least it's not exposed by LÖVE, but I don't know whether the concept exists (programatically) on each OS or whether it would be easy to add an API for.
I suspect there are OS-specific APIs for it, but I have no idea if the concept even exists in SDL. If you set your system font scale in Windows to 125%, I believe (but don't quote me on this) that Firefox et al adjust for that. That may just be a Windows override though, I really don't know much about it.
I think in the case of an sp unit, It should be defined as dp * scale. All text should be rendered in sp and the programmer can decide to allow users to define their preferred fond scale or not. If no scale is given, it defaults to 1.
Some resources for you: love.window.getPixelScale Display metrics in LÖVE for Android love.window.getPixelScale in Android
That would allow us to get something similar to the PT unit
Yeah, I think I am mostly decided now on using %, DP, and SP units. I'll try to include the ability to define things in PX if necessary, but it will never be the default unit.
How are you going to do DP and SP?
@slime73 mentioned a way to define DP up above. SP is simply DP * scale, where scale is defined as the system/app font scale.
So something like DP * 12 would be the standard? Or I didnt quite get it
scale would be a percentage. An example of this is on Windows where you can set the system font size to 125%. That would mean SP = DP * 1.25. Setting a font to 12 SP would give you a properly scaled, density-independent size that the user expects.
Floats are evil. Don't make users keep track of 0.0001 changes. Let them code in a fixed resolution window where they can position thing in pixels accurately and let the library do the relative transformation and scaling for different resolutions.
Floats are not evil. Users do not need to keep track of such values, they can define positions based on percentages. "This window is 25% of the screen's width and positioned 5% from the left". This would produce a float value and that's okay.
Floats are also important for animations.
I will clarify PERCENTAGES ARE EVIL. Do not let users code in percentages, its not accurate.
Percentages are fine.
Pixels Percentages Points (DP) and SP (Scaled Pixels?) should all be possible Variables with the screen width and height should be available
The screens true width and height need not be revealed. What is important is the scale factor. For instance, if we have a "Retina" or hidpi screen with a true resolution of 2560x1440 and it reports to love a PixelScale of 2.0, then we want both love and dominatrix to see a 1280x720 screen. Using dp units will allow us to position objects within that 720p screen but have it properly scale up to 1440p in px units.
sp units are strictly for scaling text.
So when asked what the screen resolution is, we should expect to see 1280x720 and we should use our dp unit in that space.
I wanna see how big a screen is... so that I know if an element should be displayed or not, for example, a navigation bar will be collapsed into a menu button in Android while it will be shown entirely in a large screen.
Also if I want to position an element 40px (not dp) from the right I would want to do: screen.width - 40px
I think you are misunderstanding how PixelScale works.
If you have a screen with a high pixel density (such as Apple's Retina displays), you probably don't want to use the "true resolution of the screen because everything would be very, very tiny. This is where PixelScale comes in. PixelScale effectively turns a 1440p screen into a 720p screen and allows you to position and size thingsin a more reasonable screen space while using higher quality images that look nice on high density screens.
with a PixelScale of 2.0, 1 dp == 2 px. This means that in your 720p space, you are using the screen's full resolution when it gets translated back to pixels.
If you have a true 720p screen and a true 1440p screen and you create a 200x200px square, it is going to take up half the screen area (on both axes) on the 1440p screen than it is on the 720p screen. But if we use dp instead of px, then on the 1440p screen you are really creating a 400x400px box so on both screens it takes up the same screen area allowing for a more consistant UI across all screens.
Yeah I got it... I was the one that suggest it how to do it... But sometimes pixels are nice... because we dont care about looking right in every screen... or at least it is not important for that one thing
Can you come up with a use case where px would be more useful than dp?
Nope, but they are there so if you cannot use them then it's not quite right for them to exist... Also think about how the game will be coded, probably it wont use the GUI for everything, I would want my game to be coded separately and there I wont use "dp" I'll use pixels... If I want to align a GUI element with my game I will run into headaches
LOVE has a property that allows you to enable or disable hidpi mode. If a game developer enables this feature then they are likely to be aware what it is and how to use it. By enabling that feature, it will allow the developer to create their own dp unit.
If they do not enable it, the GUI library will default to 1.0 PixelScale, making dp == px.
The Android version effectively always has it enabled, even if you don't enable it yourself.
Good.
My feeling is that we should toss the idea of pixels right out the window. All objects should have their own local coordinate system, both X and Y valued from 0 to 1. This will allow consistent spacing and positioning across all screens.
This may also bring an issue where persons with box screens (4:3, 5:4) may have skinny GUIs or persons with wide screens (16:9, 16:10) may have fat GUIs depending on how the GUI designer is putting things together. A fix for this may be to use a Point (pt) system where an object can be set to a fixed size based on more relevant metrics than pixels. I believe Android and CSS both allow for various point systems such as pt, em, ex, and px on top of the % system.
EDIT:
We will be going with %, dp, and sp units.
http://stackoverflow.com/questions/2025282/difference-between-px-dp-dip-and-sp-in-android
http://blog.edwinevans.me/?p=131
http://developer.android.com/guide/practices/screens_support.html