Creating Fadein-Pause-Fadeout using GUI (SOLVED)

Hello!..I’m new to defold!..BTW i want to learn something about GUI and transition…can you tell me how can i make a simple fadein-pause-fadeout animation…i know already how to make a fade-in and fade-out transitions(thanks for some cool examples) but what i need is on how can i put a pause(probably 1-2sec) between the fadein and fadeout transitions?..any help is appreciated!..

here’s my code so far:

function init(self)

	intro_fadein(self)
	intro_fadeout(self)	

end


function intro_fadein(self)
	for i=1,2 do
	gui.set_color(gui.get_node("intro"..i), vmath.vector4(1,1,1,0))
	gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(1,1,1,1), gui.EASING_LINEAR, 2.5, 0)
	end	
end

function intro_fadeout(self)
	for i=1,2 do
	gui.set_color(gui.get_node("intro"..i), vmath.vector4(1,1,1,1))
	gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(0,0,0,0), gui.EASING_LINEAR, 2.5, 0)
	end
end

The thing to understand here is that animations (and a great deal of other things) in Defold are asynchronous. That means that this code:

gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(1,1,1,1), gui.EASING_LINEAR, 2.5, 0)
gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(0,0,0,0), gui.EASING_LINEAR, 2.5, 0)

will not play one animation after the other. The call to gui.animate() will return immediately, even though the animation has not yet started. The engine then starts the animation at the end of the frame.

The way to get control back to the user is to provide callbacks. The user can send a function to the animation call, which will be called by the engine when the animation finishes. So in your case:

local function init(self)
  -- start fade in, which will then start fade out.
  intro_fadein(self)
end

local function intro_fadein(self)
  for i=1,2 do
    gui.set_color(gui.get_node("intro"..i), vmath.vector4(1,1,1,0))

    -- start animation and provide callback for what's gonna happen next.
    gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(1,1,1,1), gui.EASING_LINEAR, 2.5, 0, fadeout)
  end	
end

function intro_fadeout(self)
  for i=1,2 do
    gui.set_color(gui.get_node("intro"..i), vmath.vector4(1,1,1,1))
    gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(0,0,0,0), gui.EASING_LINEAR, 2.5, 0)
  end
end

Check out the API docs where there’s another example: https://www.defold.com/ref/go/#go.animate

1 Like

Your current init() function will start the intro_fadein and intro_fadeout animations simultaneously. gui.animate() will start an animation but it will not wait until it is done before executing the next line of code. What you need to do is to use the callback functionality to achieve a fadein and then a fadeout. Like this:

-- quick'n'dirty wait achieved by animating the position but not actually moving the node
local function wait(node, duration, callback)
	gui.animate(node, gui.PROP_POSITION, gui.get_position(node), gui.EASING_LINEAR, duration, 0, callback)
end

local function intro_fadein(node, duration, callback)
	gui.set_color(node, vmath.vector4(1,1,1,0))
	gui.animate(node, gui.PROP_COLOR, vmath.vector4(1,1,1,1), gui.EASING_LINEAR, duration, 0, callback)
end

local function intro_fadeout(node, duration)
	gui.set_color(node, vmath.vector4(1,1,1,1))
	gui.animate(node, gui.PROP_COLOR, vmath.vector4(0,0,0,0), gui.EASING_LINEAR, duration, 0)
end

function init(self)
	local nodes = { gui.get_node("intro1"), gui.get_node("intro2") }
	for i=1,#nodes do
		local node = nodes[i]
		intro_fadein(node, 2.5, function()
			wait(node, 2, function()
				intro_fadeout(node, 2.5)
			end)
		end)
	end
end

Note that I’ve converted your functions to local functions. You should make a habit of creating local functions to avoid problems with global functions that accidentally replace each other. The code above is untested btw.

1 Like

Actually, while the general concept of async and callbacks is important to understand, if you simply want to delay the fadeout, you can do that with the delay parameter:

-- play animation 1 now and for 2.5 seconds
gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(1,1,1,1), gui.EASING_LINEAR, 2.5)
-- play animation 2 for 2.5 seconds, starting in 4.5 seconds:
gui.animate(gui.get_node("intro"..i), gui.PROP_COLOR, vmath.vector4(0,0,0,0), gui.EASING_LINEAR, 2.5, 4.5)

Hmm, yes, that would probably be a quicker and better solution than my example with callbacks…

Yes, but at some point you probably want to trigger some logic at animation end, then you must use a callback.

I should have linked to the gui animation function. It is very similar to go.animate() and is here: https://www.defold.com/ref/gui/#gui.animate