DrawOrigin Single Frame Positional Issue

Description: When drawing multiple sprites/text/etc with DrawOrigin and different positions passed, when you decide to stop drawing any of them (best way to set this up, is to draw 3 things in a loop, then intermittently stop drawing either the 2nd or 3rd in list) the draw origin swaps positions for one single frame with the first drawn (??? maybe not specific to just the first in draw order), with the one not being drawn.

Server artifact version: Latest Recommended 7290

Expected behavior: When looping and drawing multiple sprites or text, the draw origin position should be respected, and not swap index/order/position with another when one down the chain decides to stop drawing.

Current behavior: Draw origin seems to swap positions with a lower draw order position for a single frame when that draw decides to no longer be called.

Error screenshot:

.dmp/crash files: None needed

Files/Code to reproduce bug: This example code will put up 3 draw sprites with 3 draw origins (they are located in Blackwater, in the construction yard) - It will intermittently turn off the 2nd drawn in order, if you look, for a single frame, it will swap with either 1 or 3 in position for a single frame when it decides not to draw anymore. There may also be issues when one comes in, when others are being drawn, you may notice a slight flicker on 1 or 3 sometimes when the 2 sprite decides to draw again. So it could be a double sided issue, coming and going.

public class DrawOriginTest : BaseScript
{
    private static int _gameTimeSinceLastSwap = 0;
    private static bool _showSecond = false;

    [Tick]
    private async Task DrawSprites()
    {
        // CHANGE THESE FOR CORRECT RESOLUTION SCALING (so scale calcs make things look good on current resolution)
        var overallScaleFactor = 1.0f;
        var screenResolution = new Vector2(1920f, 1080f);

        List<Vector3> spriteLocations = new List<Vector3>()
        {
            new Vector3(-800.9131f, -1238.78f, 43.81535f),
            new Vector3(-802.5263f, -1238.749f, 43.82928f),
            new Vector3(-804.2942f, -1238.716f, 43.82634f)
        };

        var textureName = "blip_mp_base_";
        var index = 1;

        // LOOP AND DRAW
        foreach (var spriteLoc in spriteLocations)
        {
            if (API.GetGameTimer() - _gameTimeSinceLastSwap > 2000)
            {
                _showSecond = !_showSecond;
                _gameTimeSinceLastSwap = API.GetGameTimer();
            }

            if (index != 2 || _showSecond)
            {
                // DRAW ORIGIN
                Function.Call((Hash)((ulong)0xE10198D5 & 0xFFFFFFFF), spriteLoc.X, spriteLoc.Y, spriteLoc.Z, 0);

                DrawSpriteRespectResolution("blips_mp", textureName + index, new Vector2(0f, 0f),
                    new Vector2(46f * overallScaleFactor, 46f * overallScaleFactor), screenResolution,
                    new Vector2(512f, 512f), 0f, Color.FromArgb(255, 255, 255, 255), false);

                Function.Call((Hash)((ulong)0xDD76B263 & 0xFFFFFFFF));
            }

            index++;
        }
    }

    private async void DrawSpriteRespectResolution(string textureDictionary, string textureName, Vector2 positionInPixels, Vector2 scaleInPixels, Vector2 screenResolution,
        Vector2 textureResolution, float heading, Color color, bool p11)
    {
        var requestTimeout = API.GetGameTimer() + 5000;

        if (Function.Call<bool>((Hash)0x54D6900929CCF162, textureDictionary) == false)
        {
            Function.Call((Hash)0xC1BA29DF5631B0F8, textureDictionary, false);

            while (Function.Call<bool>((Hash)0x54D6900929CCF162, textureDictionary) == false && requestTimeout > API.GetGameTimer())
            {
                Function.Call((Hash)0xC1BA29DF5631B0F8, textureDictionary, true);
                await BaseScript.Delay(0);
            }
        }

        var widthScale = (scaleInPixels.X / screenResolution.X); // * scale.X;
        var heightScale = (scaleInPixels.Y / screenResolution.Y); //* scale.Y;

        var posX = (positionInPixels.X / screenResolution.X);
        var posY = (positionInPixels.Y / screenResolution.Y);

        // DRAW_SPRITE
        Function.Call((Hash)0xC9884ECADE94CB34, textureDictionary, textureName, posX, posY, widthScale, heightScale, heading, color.R, color.G, color.B, color.A, p11);
    }
}

Extra information:

2 Likes

I should also add, this exists on Canary/Production as well at the moment too (tested on both).

1 Like

Here also are three images to show the problem (if one does not want to try the reproducible code)

Frame 1: All 3 are being drawn fine

Frame2: I stop calling DRAW_SPRITE for number 2 on this frame, you can see it jump over/replace 3

Frame 3: Everything back to normal

2 Likes