mickelson / attract

A graphical front-end for command line emulators that hides the underlying operating system and is intended to be controlled with a joystick or gamepad.
http://attractmode.org
GNU General Public License v3.0
393 stars 115 forks source link

Nested Surfaces frame delay and potential fix #599

Closed oomek closed 4 years ago

oomek commented 4 years ago

As it was reported some time ago the nature of nesting surfaces causes a 1 frame delay on each nesting level. Some time ago I've discovered that this could be overcome by defining all nested surfaces in reverse order on fe and then cloning them to their appropriate parents. This trick was to ensure that most nested ones are drawn first during redraw_surfaces()

Today I've managed to implement a simple sorting based on nesting level. It works for conventional way of adding surfaces and those rearranged using my trick.

I'm leaving it here up for discussion and if you give me a green light I'm gonna prepare a PR:

Here is the link to the branch with the fix: https://github.com/oomek/attract/commits/pr-surface-delay-fix

And an example layout:

local flw = fe.layout.width
local flh = fe.layout.height
local n = 8 // Snaps count
local s = flw / n

local surf = []
local snap = []
local text = []

local surf2 = []
local snap2 = []
local text2 = []

local background = fe.add_text( "", 0, 0, flw, flh )
background.set_bg_rgb( 0, 100, 150 )

// NORMAL ORDER

// Snap on Fe
local snap_fe = fe.add_artwork( "snap", 0, 0, s, s )
snap_fe.video_flags = Vid.ImagesOnly
local txt_fe = fe.add_text( "Fe", 0, s, s, s/8 )

// Surface on Fe
surf.push( fe.add_surface( s*n, s+s/8 ))
surf[0].set_pos( s, 0 )
snap.push( surf[0].add_clone( snap_fe ))
snap[0].video_flags = Vid.ImagesOnly
text.push( surf[0].add_text( "Surface 0", 0, s, s, s/8 ))

// Nested Surfaces
for ( local i = 1; i < n; i++ )
{
    surf.push( surf[i-1].add_surface( s*(n-i), s+s/8 ))
    surf[i].set_pos( s, 0 )
    snap.push( surf[i].add_clone( snap_fe ))
    snap[i].video_flags = Vid.ImagesOnly
    text.push( surf[i].add_text( "Surface "+i, 0, s, s, s/8 ))
}

// REVERSED ORDER WITH SURFACE REASIGNMENT TRICK

// Snap on Fe
local snap_fe2 = fe.add_clone( snap_fe )
snap_fe2.set_pos( 0, s*2 )
snap_fe2.video_flags = Vid.ImagesOnly
local txt_fe2 = fe.add_text( "Fe", 0, s*3, s, s/8 )

// Nested Surfaces initialised in reverse order
for ( local i = 0; i < n; i++ )
{
    surf2.push( fe.add_surface( s*(i+1), s+s/8 ))
    surf2[i].set_pos( s, 0 )
}
surf2[n-1].set_pos( s, s*2 )

// Nested Surfaces reasignment to their parents
for ( local i = 1; i < n; i++ )
{
    surf2[i-1].visible = false
    surf2[i-1] = surf2[i].add_clone( surf2[i-1] )
    surf2[i-1].visible = true
}

text2.push( surf2[0].add_text( "Surface 0", 0, s, s, s/8 ))
snap2.push( surf2[0].add_clone( snap_fe ))
snap2[0].video_flags = Vid.ImagesOnly

for ( local i = 1; i < n; i++ )
{
    snap2.push( surf2[i].add_clone( snap_fe ))
    snap2[i].video_flags = Vid.ImagesOnly
    text2.push( surf2[i].add_text( "Surface " + (n-i-1), 0, s, s, s/8 ))
}
oomek commented 4 years ago

Fixed in https://github.com/mickelson/attract/pull/619