How to handle dpiScale correctly?

Hey,

I am using latest openfl and latest lime (in -Dv2 mode). In my first version of my game, I ignored “dpiScale”

screen_h = Std.int(flash.Lib.current.stage.stageHeight);
screen_w = Std.int(flash.Lib.current.stage.stageWidth);

discovering that for a iPad3 retina everything is scaled to have its size. So I adjusted the calculations:

screen_h = Std.int(flash.Lib.current.stage.dpiScale * flash.Lib.current.stage.stageHeight);
screen_w = Std.int(flash.Lib.current.stage.dpiScale * flash.Lib.current.stage.stageWidth);

Making it work on the iPad3. But now on the iPhone4 everything is scaled to twice its size.

I am confused. What is the correct way of handling “dpiScale”?

Thanks!
Nathan

I’m experiencing exactly the same issue - certainly with the iPad 3. The original version of my app (OpenFL 2.x) scaled fine on the iPad but now going back to it using OpenFL 3.x with the -Dv2 option renders the same content in the upper left quarter of the screen.

Although I’ve not tested on the iPhone (might try the simulator) I’m very interested in finding the best way to scale content on retina/non-retina displays correctly.

Greg

Does this work better since the recent release, which reverted the ALLOW_HIGHDPI setting in SDL2?

Which version was this release? I am using lime 2.4.7 and openfl 3.1.1 and the problem is there.

Yeah - I’m on the same versions too. Clean built and just tested on an iPod touch 2g (iOS 6.x) non-retina and got the following debug:

Stage W/H:640/960 dpiScale=2

And obviously the screen was scaled to large for the device.

Greg

Is that using -Dlegacy?

I am using -Dv2, so yes

Did this change with an Xcode update, OS update, or between versions of OpenFL?

Yes, it did change. About half a year ago, it was different. I have Upgraded everything in the mean time. Unfortantly I test very seoldom in IOS, especially in my iphone4. Do you have a suspision? Is there an older Version i should test?

Perhaps it is something to do with different SDL2 versions, maybe it is fixed in a newer development build, nothing changed in how initialize except the recent ALLOW_HIGHDPI flag addition, which was subsequently (and currently) removed

I tried with development version from githup (openfl) and it did not change anything.

Now that I think about it, I am actually not sure if it ever worked. The first version ignored dpiScale and was to small on retina displays. I fixed that but I admit I am not sure if I tested on iphone4 after fixing that.

Could there be another way of detecting if it is a retina display?

Does it work if you ignore the DPI scale and just use stage.stageWidth and stage.stageHeight?

In my case, I wasn’t using dpiScale at all - just Lib.current.stage.stageWidth/stageHeight and in openfl 2.x days this was sufficient to work correctly on the non-retina iPod touch and the retina iPad 3.

Now, without using dpiScale renders things fine on the iPod but in the upperLeft on the iPad and quarter the size it should be (half width and height).

I’m gonna check again but it does appear that on the iPad, my background tilesheet sprite does look like it’s full width and height but don’t know why that one is but the others aren’t. Will investigate and get back to you.

Greg

Hey,

I have some information of which I do not yet know what to make of. If I try this code:

class Main {
  static public function main() {
    trace(flash.Lib.current.stage.stageWidth,flash.Lib.current.stage.stageHeight,flash.Lib.current.stage.dpiScale);
    flash.Lib.current.addEventListener(flash.events.Event.ENTER_FRAME, onEnterFrame);
  }
  static public function onEnterFrame(_ : flash.events.Event) {
    trace(flash.Lib.current.stage.stageWidth,flash.Lib.current.stage.stageHeight,flash.Lib.current.stage.dpiScale);
  }
}

Now I run this in the ipad-retina simulator. The first trace gives the output:

480,320,2

All the following traces output:

 960,640,2

Ok, this seems to work:

  1. in main, wait for the first frame (like in my last post).
  2. Then take flash.Lib.current.stage.stageWidth/stageHeight as the drawing size of the app. (ignore dpiScale).

I tested it on an iphone4 device, and the ipad retina simulator. I do not have an ipad3. @Greg209, can you confirm that this works on the ipad3?

Yeah - seems to be the case - kind of. Pre the enter_frame calls, my dimensions (portrait) are returned as:

768/1024/2 - iPad 3
640/960/2 - iPod Touch 4g

whereas the same call in the enter_frame method, shows:

1536/2048/2 - iPad 3
640/960/2 - iPod Touch 4g

Previously in OpenFL 2.x, IIRC, the retina version always returned the non-retina values which is what I was working with. This situation certainly explains why my background sprite is the correct size whilst all others are a quarter size, as it’s being defined before any ENTER_FRAME calls (an I have a few different ones throughout my code).

So for me there are still problems. The DPI scale is wrong for the iPod touch and the pre-enter_frame value is different to those after.

What should the stageWidth & stageHeight be on a retina display? Should it be the scaled or unscaled value e.g. 768/1024 or 1536/2048 ?

I’ll just have to be careful to only reference it after the first frame to be sure I get the correct value.

Thanks for pin-pointing the issue and giving my a path to work-around it :smile:

Greg

You can handle stage Event.RESIZE

Yes, but that is bot sarisfactory. Unless i assume, that there is only one resize event to the correct size, but that seems unnatural.

The Problem is, that i load different sized assets depending on the screen size on load time.

I’d love to see things improved so that all targets have the final (initial) size at runtime, before the code executes. If anyone explores and finds some solutions for this, would be awesome (on the C++ side, not Haxe)