Gamua / Starling-Framework

The Cross Platform Game Engine
http://www.starling-framework.org
Other
2.84k stars 819 forks source link

drawToBitmapData not working correctly with ScaleMode.NO_BORDER #943

Closed Selonie closed 7 years ago

Selonie commented 7 years ago

Hi Daniel

Perhaps I'm the only person who ever uses this ScaleMode.NO_BORDER with drawToBitmapData or maybe I am doing something wrong, but one way or the other this is probably the best place to ask.

Problem: Using drawToBitmapData with ScaleMode.NO_BORDER creates distorted images if the device being used requires the stage to zoom to remove borders. This is an issue with the very latest and all previous versions of drawToBitmapData within starling.

I've been 'correcting' the distortion like this (below), but I don't like the way the the screen flickers every time I take a screenshot and the fact I have to mess around with Starling every time I want to use ScaleMode.NO_BORDER. Can someone show me a better solution?

DisplayObject.as

public function drawToBitmapData(out:BitmapData=null):BitmapData
{
    var scale:Number = Starling.contentScaleFactor;         
    var alterX:int = Math.abs(Starling.current.viewPort.x) / scale*2;
    var stage:Stage = Starling.current.stage;
    var stageWidth:Number = stage.stageWidth-alterX ;
    var stageHeight:Number = stage.stageHeight-alterY;

    var painter:Painter = Starling.painter;
    var bounds:Rectangle = this is Stage ?
    stage.getStageBounds(this, sHelperRect) : getBounds(_parent, sHelperRect);

    if (out == null)
            out = new BitmapData(Math.ceil(bounds.width-alterX)  * scale,
                         Math.ceil(bounds.height - (alterY+1)) * scale);                             

    painter.clear();
    painter.pushState();
    painter.state.renderTarget = null;
    painter.state.setModelviewMatricesToIdentity();
    painter.setStateTo(transformationMatrix);

    painter.state.setProjectionMatrix(bounds.x+alterX, bounds.y+alterY, stageWidth, stageHeight,
                    stageWidth, stageHeight, stage.cameraPosition);

    render(painter);

    painter.finishMeshBatch();
    painter.context.drawToBitmapData(out);
    painter.popState();

    return out;
}

Previous attempts at fixing this here: http://forum.starling-framework.org/topic/screenshot-distortion-using-drawtobitmapdata

Anyway thanks for everything - and don't stop doing anything important, cos this can wait!

Regards

Selonie

PrimaryFeather commented 7 years ago

Hi Selonie, I just realized this is not really documented (not anywhere I can find it, that is :wink:), but it's recommended to always use StageScaleMode.NO_SCALE and StageAlign.TOP_LEFT when using Stage3D. That's because the Stage3D object is not scaled, whatever mode used.

In fact, Starling sets those modes when its initialized; but of course that won't help if the setting is changed afterward.

My recommendation: leave that default, and then update Starling's viewPort and stage size yourself whenever there's a ResizeEvent (you need to do this for Starling to behave the way you like, anyway). Then put your standard Flash content on the nativeOverlay. It will automatically be at the right position then.

Does that help in any way? Cheers!

Selonie commented 7 years ago

Hi Daniel Thanks, yes that was useful, I took a look at the new starling manual and realised I was so 2012! The letterbox strategy using ScaleMode.NO_BORDER doesn’t even get a mention now! I’ve implemented your new setup with the ScreenSetup class and everything is looking great and the distortion is history. So many thanks. Regards Selonie

PrimaryFeather commented 7 years ago

Thanks a lot for the update! I'm happy to hear the new manual helped sorting it out! :smile: