Stage align and scale mode

Is there any way to set

stage.align

and

stage.scaleMode

?

OpenFL currently ignores stage.align and stage.scaleMode. It follows two modes:

  1. When the window parameters include “resizable” as true (default) OpenFL will scale content to match the target window area and allow black borders. This is similar to StageScaleMode.SHOW_ALL in ActionScript
  2. When “resizable” is false the window will be the size specified and will not resize or align. This is similar to StageScaleMode.NO_SCALE I believe

I’d like to see this properly supported if we can decide how to handle backward compatibility – I think the default stage align and scale mode could be set based upon the window parameters (assuming it’s a match with the current behavior)?

There are openfl default values:
image

How to set scaleMode as StageScaleMode.SHOW_ALL ?
The following settings do not work. :thinking:
image

I think that this behavior may be somewhat different between the NPM release and the Haxelib version – I am only getting 0 width x 0 height (resizing) or set width x set height (not resizing) working.

I think it might be easiest to handle the SHOW_ALL style approach manually for now.

I just got it working in this sample:

The strategy is to resize completely and then to handle the letterboxing yourself within the OpenFL code

I think it’s best way to support by an root matrix. :thinking:
This will take h5 app a stronger adaptability of window’s inner size than flash,and it helps to maintain the render dirty area.
Most of other h5 engines have this export setting.
I will try my best to study the relevant source code first and see if I can implement this function. (Unfortunately, I am better at typescript rather than haxe, so this may take a long time…) :rofl:

Now, the stage’s align and scale mode is supported perfectly(Only tested HTML5 target).

  1. Active this api as follow:
    Suggestion realization about HTML5Window

  2. Modify Stage.__resize

    • append @access to function

      @:access(lime.ui.Window) // access private member
      @:noCompletion private function __resize():Void
      
    • change __logicalWidth and __logicalHeight:
      https://github.com/openfl/openfl/blob/17bbd9f7ae65bfc9051d61275a9fa4a98644be5e/src/openfl/display/Stage.hx#L2830-L2831

      switch (this.scaleMode)
      {
         case StageScaleMode.NO_SCALE:
            __logicalWidth = windowWidth;
            __logicalHeight = windowHeight;
         case StageScaleMode.SHOW_ALL, StageScaleMode.EXACT_FIT, StageScaleMode.NO_BORDER:
            __logicalWidth = this.window.__attributes.width;
            __logicalHeight = this.window.__attributes.height;
      }
      
    • change __displayMatrix: https://github.com/openfl/openfl/blob/17bbd9f7ae65bfc9051d61275a9fa4a98644be5e/src/openfl/display/Stage.hx#L2851-L2870

      if (__logicalWidth == 0 && __logicalHeight == 0) 
      {
         this.stageWidth = windowWidth;
         this.stageHeight = windowHeight;
      }
      else
      {
         this.stageWidth = __logicalWidth;
         this.stageHeight = __logicalHeight;
      
         var scaleX = windowWidth / this.stageWidth;
         var scaleY = windowHeight / this.stageHeight;
      
         switch (this.scaleMode)
         {
            case StageScaleMode.NO_SCALE:
               scaleX = scaleY = 1;
            case StageScaleMode.SHOW_ALL:
               scaleX = scaleY = Math.min(scaleX, scaleY);
            case StageScaleMode.NO_BORDER:
               scaleX = scaleY = Math.max(scaleX, scaleY);
            case StageScaleMode.EXACT_FIT:
        }
      
        var top_y = 0;
        var middle_y = (windowHeight - (this.stageHeight * scaleY)) / 2;
        var bottom_y = windowHeight - this.stageHeight * scaleY;
      
        var left_x = 0;
        var right_x = windowWidth - this.stageWidth * scaleX;
        var middle_x = (windowWidth - (this.stageWidth * scaleX)) / 2;
      
        var offsetX = middle_x;
        var offsetY = middle_y;
      
        switch (this.align)
        {
        	case StageAlign.TOP:
        		offsetY = top_y;
        	case StageAlign.TOP_RIGHT:
        		offsetX = right_x;
        		offsetY = top_y;
        	case StageAlign.RIGHT:
        		offsetX = right_x;
        	case StageAlign.BOTTOM_RIGHT:
        		offsetX = right_x;
        		offsetY = bottom_y;
        	case StageAlign.BOTTOM:
        		offsetY = bottom_y;
        	case StageAlign.BOTTOM_LEFT:
        		offsetX = left_x;
        		offsetY = bottom_y;
        		case StageAlign.LEFT:
        		offsetX = left_x;
        	case StageAlign.TOP_LEFT:
        		offsetX = left_x;
        		offsetY = top_y;
        }
        this.__displayMatrix.scale(scaleX, scaleY);
        this.__displayMatrix.translate(offsetX, offsetY);
      }
      
  3. modify OpenGLRenderer.__resize
    https://github.com/openfl/openfl/blob/17bbd9f7ae65bfc9051d61275a9fa4a98644be5e/src/openfl/display/OpenGLRenderer.hx#L880-L886

    __offsetX = 0;
    __offsetY = 0;
    __displayWidth = width;
    __displayHeight = height;
    

Done, and there is useage:

// set stage size.
let stage = new Stage(800, 600, 0x000000, App);
// it seems stage.window need to open.
stage.window.resizable = true;
// flash default value
stage.align = "";
stage.scaleMode = StageScaleMode.SHOW_ALL;

Finally, I propose to amend some other places (or open existed API).

  1. Add stage.setStageSize(width, height) to enable change stage.stageWidth and stage.stageHeight.`
  2. Open stage.canvas to get real size of canvas element.
  3. Change stage.align and stage.scaleMode to setter and getter to enable update stage size immediately.
  4. Add a param to Stage constructor to enable put in resizable option.

:grinning:
Through above means, the characteristics of adaptive window will be strengthened.

Do you think you could put these changes into a pull request?

Other platforms have not been fully tested, and the operation of passing resizable parameters is best done with a public api.

I recommend that the original author perform the code merge operation. :rofl:

Bug: It will be render error when TextField instance’s text changed

Is there any way to fix the TextField rendering error caused by the global matrix?

Allowing changing the align, scaleMode and adjusting the size of the stage (stageWidth and stageHeight) will take the openfl project more powerful window size adaptability.

So I think it is necessary to fix it.:rofl:

Do you have a simple way of showing the bug you are seeing? Thanks :slight_smile:

After merging the above code, adding any TextFiled instance to the stage, and change the text, it will render errors.