Legacy GM Stop the application surface from being cleared?

TheouAegis

Member
So thinking about it, my current method in a thing I'm working on for myself (like, literally for myself only to use) probably isn't the best way to go about things, but I'm just trying things out.

So I'm working on a map editor and the first thing I worked on was adding a crumby gradient border around the window using a draw_clear() followed by a series of draw_rectangle() loops. I then added a zoomable editor grid using draw_line() calls that displays the current zoom level for a couple seconds. This worked nicely enough for me when it was all set to run every single step. The problem with that was it shouldn't be run every step -- the border should only be drawn when the app starts and the grid should only be drawn when it's resized. So I put all the code into a switch, created a system state variable, disabled clearing the window with the background color, disabled the room's background color, disabled the display buffer fill, and.... it gave me a black screen after one frame of rendering.

So my question is how can I disable the automatic clearing of the application_surface? Is there any way to treat the application_surface just like any other surface whereby its contents are only modified when I say to modify them? Or am I going to have to create my own surface? Or do you have another idea?
 
S

Sn3akyP1xel

Guest
Obvious solution seams to be make your own surface because you're not then tied to the primary application surface, which imo should only be accessed for certain effects (like pause screens).
If you free yourself up from the application surface you can also disable it, which brings a nice performance gain i've noticed. I'm relatively new to GM still, so maybe there are better methods.
 

Binsk

Member
I recall in GMS 1.4 you could disable the "render background color" in the room settings for this. I don't have a PC on hand to check in GMS 2 but you could take a look for yourself to see if the option is still there.

Edit: totally forgot the new version uses layers. Isn't there a background color layer by default?
 
L

Lonewolff

Guest
I recall in GMS 1.4 you could disable the "render background color" in the room settings for this. I don't have a PC on hand to check in GMS 2 but you could take a look for yourself to see if the option is still there.
There is 'Clear Display Buffer' in GMS2. But this doesn't seem to do anything in reality.
 

NightFrost

Member
I'm pretty sure in 1.4, which you are asking about, when you both uncheck "draw background color" in backgrounds, and uncheck "clear background with window colour" in views (views need not be active), a "feature(?)" activates that skips the clearing of app surface. Or maybe it clears with "no colour" with alpha of zero, resulting in no change.
 

TheouAegis

Member
I'm pretty sure in 1.4, which you are asking about, when you both uncheck "draw background color" in backgrounds, and uncheck "clear background with window colour" in views (views need not be active), a "feature(?)" activates that skips the clearing of app surface. Or maybe it clears with "no colour" with alpha of zero, resulting in no change.
It's clearing, but with nothing. It's the same as draw_clear_alpha(0,0), so it just leaves me a black (the window background) image every step, erasing everything I had drawn to the application_surface on the previous step.

Obvious solution seams to be make your own surface because you're not then tied to the primary application surface, which imo should only be accessed for certain effects (like pause screens).
If you free yourself up from the application surface you can also disable it, which brings a nice performance gain i've noticed. I'm relatively new to GM still, so maybe there are better methods.
Yeah so far it seems making my own surface and drawing it is probably what I'm limited to. I just hate having to maintain at least one surface_exists() check each step for this sole purpose.

There is one more issue I'm having, although it's more of a nuisance than anything. The weird thing is I traced it back to the application_surface, which I disabled. So in the Game Start event I disabled the application_surface and its drawing. Nowhere in my code do I ever touch it again. At the start of the first draw event, it resizes the room, window, and GUI to fit the display and then restarts the room. For the first 10 or so frames after the room restarts, the surface is drawn in the GUI layer stretched, then the surface is destroyed automatically for some reason, and then everything's drawn fine (after the surface is recreated). I'm drawing the surface in the GUI event, so I figured something was wrong there. I checked the dimensions of the GUI throughout the duration of the glitch and the dimensions of the GUI didn't change; they also matched up with the values my code was assigning to it (the stretching was a lot worse originally before I remembered to change the GUI size). So then on a whim, I replaced my debugging messages to show the size of the application_surface instead of the GUI. During those first 10 or so frames, the application_surface was the default size GM automatically resized it to when the program was opened; then after those 10 or so frames, the application_surface was automatically resized to match the window and GUI widths, and that's when the surface was no longer getting stretched. My room, surface, GUI, and window are all the same size at all times; the only thing that changed in those frames was the application_size. Somehow, the disabled application surface is messing up the scale of MY surface, then gets resized automatically and destroys MY surface in the process. Like, WTF? I mean, it's just a nuisance -- it causes a flicker for 1/6 of a second, but still...

Edit: Even if I leave the application surface enabled and resize it, the glitch still occurs.


Code:
sys_state = render.test;
prev_state = render.off;

surf = -1;
application_surface_enable(0);
application_surface_draw_enable(0);


Code:
if sys_state == render.test
{
    //Rezize window and room to fit in the room (handled automatically since room is so large by default)
    if room_width > display_get_width()
    {
        var W = display_get_width() & ~8;
        room_set_width(room,W);
        window_scale = (W-48)/256;
        var H = floor(240 * window_scale + 48 + dim.buttons);
        room_set_height(room,H);
        for(i=8; i>0; i-= 0.5)
            if i * 240 < H-48
            {
                room_zoom = i;
                break;
            }
    }
    if room_height > display_get_height()
    {
        var H = (display_get_height() & ~8)-32;
        room_set_height(room,H);
        window_scale = (H - 48)/240;
        var W = floor(256 * window_scale + 48 + dim.workarea);
        room_set_width(room,W);
        for(i=8; i>0; i-= 0.5)
            if i * 240 < H - 48
            {
                room_zoom = i;
                break;
            }
    }

    display_set_gui_size(W,H);
    window_set_size(W, H);
    window_set_position(0,32);
    sys_state = render.off;
    room_restart();
    exit;
}
Art drawing here, unimportant
Code:
else                                                     //SYS_STATE=RENDER.OFF//

{
    if !surface_exists(surf)
    {
        surf = surface_create(room_width,room_height);
        surface_set_target(surf);
        draw_clear($683e08);
        surface_reset_target();
        sys_state = render.init;
    }
}


Code:
draw_surface(surf,0,0);

if alarm[timer.zoom]
{
    alarm[timer.zoom]--;
 
    draw_set_alpha(alarm[timer.zoom]/(room_speed-alarm[timer.zoom]div 2));
    draw_text(28,28,string(room_zoom)+"x");
    draw_set_alpha(1);
}
 
Last edited:

samspade

Member
I did this once, but I can't remember how. Basically though, I think I just disabled the background surface completely and then created my own surface and drew to that. If I were try to do it again, I think what I would do for ease of use would be to disable the automatic draw of the application surface but not disable the surface entirely. Then I would have a surface the size of the application surface that I drew the application surface onto each frame, and I would then draw that to the screen.
 

NightFrost

Member
It's clearing, but with nothing. It's the same as draw_clear_alpha(0,0), so it just leaves me a black (the window background) image every step, erasing everything I had drawn to the application_surface on the previous step.
That's curious. I just created a simple project to test this. I set up a room as I described, added code that runs only once to draw a grid, and an object that follows the mouse. The grid stays visible and I was able to "paint" with the mouse-following object as the surface is not getting cleaned. Maybe there's been changes between 1.4 subversions or it is hardware related.
 
Top