lerping dimage in dframe

attempting to make the image go from almost middle of the screen go up to 1/5 of the screen heights, my code:


local hl = 0.40

local targethl = 0.20

local velohl = 0.5



local imd = vgui.Create( "DImage", md )
imd:SetPos(ScrW() * 0.5 - (498 / 2) , ScrH() * hl)

hl = Lerp(velohl, hl, targethl)

the image is not moving at all, I dont know what I am doing wrong I got no errors

You are only setting the position once, therefore the image is static. I can see that you might think changes to a variable will back propagate as if by reference, however in lua, variables are absolute values.

To have it move dynamically, simply calculate and set its position each frame. Be sure to take into account frame time if you want the speed of the transition to be the same regardless of FPS.

so what do you suggest for me to do exactly?

With regards to my first paragraph, there are exceptions when it comes to the “all variables are absolute values”, such as functions and tables, and userdata, but in this case the variable is a number, and therefore absolute.

[editline]6th September 2017[/editline]

You broke my merge lol. Hook into the Think event and update the position there.

So I would have to make a function that takes the DImages position and changes them there? Does this work on the client side even and how ?

If you want some sort of… Lerp effect of moving the position of a panel from one place to the other you should instead use

Derma_Anim and Easing

Is it possible to make use of https://wiki.garrysmod.com/page/Panel/MoveTo somehow ?
can someone explain me what I need to do exactly ?

Well, you can use MoveTo, but that wouldn’t do a Lerp effect as you want. If you’re going to use the Derma_Anim as i just gave you, you could… sort of use a modified version of MoveTo with this code:



local function inQuad(t, b, c, d)
	t = t / d
	return c * math.pow(t, 2) + b
end

local function outQuad(t, b, c, d)
	t = t / d
	return -c * t * (t - 2) + b
end

local function inOutQuad(t, b, c, d)
	t = t / d * 2
	if t < 1 then
		return c / 2 * math.pow(t, 2) + b
	else
		return -c / 2 * ((t - 1) * (t - 3) - 1) + b
	end
end

local moveType = {
	["in"] = inQuad,
	["out"] = outQuad,
	["inout"] = inOutQuad
}

local function MoveToCustomAnimSetup(pnl, type)
	pnl.OldThink = pnl.Think

	local toFunc = moveType[type]

	pnl.CustomAnim = Derma_Anim("MoveTo", pnl, function(this, anim, delta, data)
		if anim.Started then
			data.startX = this.x
			data.startY = this.y
			data.endX = data.x
			data.endY = data.y
		end

		local endDelta = toFunc(delta, 0, 1, 1)
		local toX, toY = Lerp(endDelta, data.startX, data.endX), Lerp(endDelta, data.startY, data.endY)

		this:SetPos(toX, toY)

		if anim.Finished then
			this:SetPos(data.endX, data.endY)
			if this.CustomAnimCallback then
				this.CustomAnimCallback()
			end
		end
	end)

	pnl.Think = function(this)
		if this.OldThink then
			this:OldThink()
		end

		if this.CustomAnim:Active() then
			this.CustomAnim:Run()
		end

		

		if this.DelayedAnims and !this.CustomAnim:Active() then
			for k, v in pairs(this.DelayedAnims) do
				if v[3] <= RealTime() then
					this.CustomAnim:Start(v[1], v[2])
					this.DelayedAnims[k] = nil
				end
			end
		end
	end

	pnl.MoveTo = function(this, x, y, time, delay, _, callback)
		this.CustomAnimCallback = callback

		local data = {x = x, y = y}

		if delay and delay > 0 then
			if !this.DelayedAnims then
				this.DelayedAnims = {}
			end

			table.insert(this.DelayedAnims, {time, data, RealTime() + delay})
		else
			this.CustomAnim:Start(time, data)
		end
	end
end


and when creating the panel just call the MoveToCustomAnimSetup function with the 1st argument as the panel and the 2nd one as the type of easing you want to use.
Then, after that you can use MoveTo and it’ll use Easing. Ill probably post this in code snippets.

this is a bit lot overwhelming for me, no clue where to start with this

Its just an Util function. You should just put it outside of all of the code and hooks (as its to be used anywhere) and then you can use it on any panel that you wish.

[editline]6th September 2017[/editline]

Example:



local button = vgui.Create("DButton")
button:SetSize(ScrW() * 0.2, ScrH() * 0.2)
button:Center()
button.DoClick = function(this)
	this:MoveTo(0, 0, 2, 0)
end
MoveToCustomAnimSetup(button, "out")


This will make the button “lerp” from the center to the top left of the screen when you click on it

I dont find a way to make it just go from center to top ?

[editline]6th September 2017[/editline]

Oh I got it solved, thanks alot!

idk what’s up with some of the responses, but to clarify the reasoning for the first attempt not working:
the local var “velohl” doesn’t ever change. Therefore your value will always be half-way between the first and second argument in your LERP function (hl, targethl).

To fix your original code you can use something like FrameTime() (since this value constantly changes)


local hl = 0.40
local targethl = 0.20

hl = Lerp(FrameTime(), hl, targethl)

local imd = vgui.Create( "DImage", md )
imd:SetPos(ScrW() * 0.5 - (498 / 2) , ScrH() * hl)