Best way to modify contents of Derma?

Hey all

What is the best way to structure my derma code to respond to changes in game state outside of the panel itself?

For example, I have created a derma panel inside of a function, meaning the panel is local to that function and inaccessible outside of that scope. I need to alter text on that panel when the game state changes, ie. I need to call text:SetText again in order to change text content.

My problem is that I can’t simply re-draw the panel in the same way that I would use HUDPaint as that would create a new instance each frame and cause many panels to be displayed. I also can’t see a way to re-open a panel once I have called Close() on it meaning my current solution of declaring the panel once globally outside of any functions doesn’t work either.

This is probably a simpler question than how I have worded it, I just need someone to look at what I’m saying and point me at an example of what I need.

Thanks so much,
Tangles

I think I finally managed to solve this myself by assigning the Close() function pointer to a variable of wider scope, doing the same for the content that I wish to change, and then just calling the Close and re-calling the draw functions when I want to update the vgui elements

local closeDerma
local textValue = "Default Text To Display"
local function drawDerma()
    
    --if this function is called and the panel is already being displayed, remove the old instance
    if closeDerma then
        closeDerma()
    end

    local frame = vgui.Create("DFrame")
    frame:MakePopup()
    closeDerma = function ()
        frame:Close()
    end

    local text = vgui.Create("DLabel")
    text:SetText(textValue)

end

...then, elsewhere in the script:

net.Receive("ClosePanel",function(len)
    closeDerma()
end)

net.Receive("ChangeText",function(len)
    textValue = "New Text To Display"
    drawDerma()
end)

Thats probably not the best way to do it as you are recreating the derma each time the value changes. A better alternative is using hooks, example:

local closeDerma
local function drawDerma()
    
    --if this function is called and the panel is already being displayed, remove the old instance
    if closeDerma then
        closeDerma()
    end

    local frame = vgui.Create("DFrame")
    frame:MakePopup()
    closeDerma = function ()
        frame:Close()
    end

    local text = vgui.Create("DLabel")
    text:SetText("Default Text To Display")

	hook.Add( "CustomHookName", frame, function( self, textValue )
		text:SetText(textValue)
	end )
end

net.Receive("ClosePanel",function(len)
    closeDerma()
end)

net.Receive("ChangeText",function(len)
    local textValue = "New Text To Display"
    hook.Run( "CustomHookName", textValue )
end)

You could also do it more similar to how you had it before where the textValue isn’t passed through and is just a global variable that is updated and then you can run the hook to tell all panels to update.

1 Like

Ah perfect, thank you

Still learning and hadn’t dived much into hooks yet so that’s excellent, thanks

1 Like