VGUI Help

I made a button that shows a DLabel, a DTextEntry, and a DImageButton. I tried to make it so that when you press the button, if evidence3 exists, but not evidence4, then it shows evidence4, and if evidence4 exists, but not evidence5, then it shows evidence5. When I pressed the button the first time, it worked as intended and showed evidence4, but when I pressed it again, it copied evidence4 and stacked it on top of the other evidence4.

Here’s my code for the DoClick function:

[lua] addEvidence.DoClick = function()
if (evidence3 and evidence3Box) and (!evidence4 and !evidence4Box) then
local evidence4 = vgui.Create(“DLabel”, evidenceMain)
evidence4:SetPos((evidenceMain:GetWide() * .5) - 35, 160)
evidence4:SetText("")
evidence4.Paint = function()
surface.SetTextColor(0, 255, 0, 255)
surface.SetFont(“ReportTitles”)
surface.SetTextPos(((evidence4:GetWide() * .5) * .7) - 16, (evidence4:GetTall() * .5) * .67)
surface.DrawText(“Link”)
surface.SetTextPos(((evidence4:GetWide() * .5) * .7) + 16, (evidence4:GetTall() * .5) * .67)
surface.DrawText("#4")
end

				local evidence4Box = vgui.Create("DTextEntry", evidenceMain)
				evidence4Box:SetPos(24, 180)
				evidence4Box:SetSize(evidenceMain:GetWide() - 28, 20)
				evidence4Box:SetText("")
				
				local evidence4BoxRemove = vgui.Create("DImageButton", evidenceMain)
				evidence4BoxRemove:SetPos(4, 180)
				evidence4BoxRemove:SetImage("gui/silkicons/delete")
				evidence4BoxRemove:SizeToContents()
				evidence4BoxRemove.DoClick = function()
					evidence4:Remove()
					evidence4Box:Remove()
					evidence4BoxRemove:Remove()
				end
			elseif (evidence4 and evidence4Box) and (!evidence5 and !evidence5Box) then
				local evidence5 = vgui.Create("DLabel", evidenceMain)
				evidence5:SetPos((evidenceMain:GetWide() * .5) - 35, 200)
				evidence5:SetText("")
				evidence5.Paint = function()
					surface.SetTextColor(0, 255, 0, 255)
					surface.SetFont("ReportTitles")
					surface.SetTextPos(((evidence5:GetWide() * .5) * .7) - 16, (evidence5:GetTall() * .5) * .67)
					surface.DrawText("Link")
					surface.SetTextPos(((evidence5:GetWide() * .5) * .7) + 16, (evidence5:GetTall() * .5) * .67)
					surface.DrawText("#5")
				end
				
				local evidence5Box = vgui.Create("DTextEntry", evidenceMain)
				evidence5Box:SetPos(24, 220)
				evidence5Box:SetSize(evidenceMain:GetWide() - 28, 20)
				evidence5Box:SetText("")
				
				local evidence5BoxRemove = vgui.Create("DImageButton", evidenceMain)
				evidence5BoxRemove:SetPos(4, 220)
				evidence5BoxRemove:SetImage("gui/silkicons/delete")
				evidence5BoxRemove:SizeToContents()
				evidence5BoxRemove.DoClick = function()
					evidence5:Remove()
					evidence5Box:Remove()
					evidence5BoxRemove:Remove()
				end
			end
		end[/lua]

I found that in order to check if an element is valid, it needs to be a global variable, I just tested it and if you check for validity, then create it using the local prefix, it won’t work and will always create another.



function CheckForElement()


    -- Won't work
    if !( myElement ) then
    
        local myElement = vgui.Create( 'DPanel' )
    
    end
    
    -- Will Work
    if !( myElement ) then
    
        myElement = vgui.Create( 'DPanel' )
    
    end


end


So I just remove the “local” part? If that’s what you mean, it didn’t work :L

Well, What LuckyLuke posted would create the vgui element but the first one would always go into that if statement because of the scope of the variable. In other words, because local is inside the if, nothing outside of the if will know anything about it.

Here’s an example from one of my tutorials since I have nothing directly based on scope yet:

[lua] // Initialize for scope-control
local _p = NULL;
for k, v in pairs( player.GetAll( ) ) do
// Example of using a check / continue instead of wrapping the inner loop with the inverse of this if ( IsValid( v ) && v != NULL ) then…
if ( !IsValid( v ) || v == NULL ) then continue; end

	// Simple Example which would probably never make it into a work...
	if ( v == LocalPlayer( ) ) then 
		_p = v;
		break; // Showing a break to stop the loop from continuing once the item we're looking for is found.
	end
end
print( "Player: ", _p );[/lua]

Without local _p = NULL before the operation to search for our LocalPlayer( ) – Long way of doing it anyway because LocalPlayer( ) is direct access – print would always be null if we used local _p = v; within the loop. Additionally, if we used _p = v; in the loop it would be a global variable, which isn’t what you’d want.

And another one:
https://dl.dropboxusercontent.com/u/26074909/tutoring/ternary_operations.lua.html

My mind just got fucked…

Simplified explanation:

[lua]local _x = 0;
if ( true ) then
local _x = 1;
end
print( _x ); // Prints 0, because local _x is inside an if and doesn’t override the predefined _x allowing both to exist in different areas. Inside the if, if you print before the 1 assignment, it’ll be 0, after it’ll be 1. But, after the if, its back to 0 because it was never overrided[/lua]

Lets say we have 3 files, this can be simulated with a do within the same file.
[lua]// file 1
do
_x = 0;
end

// file 2
do
print( _x ); // Prints 0 because _x is global
_x = 1;
print( _x ); // Prints 1 because _x has been redefined
end

// file 3
do
print( _x ); // Prints 1 because _x is global
_x = 2;
print( _x ); // Prints 2 because _x has been redefined
end[/lua]

Lets say we have 2 files, this can be simulated with a do within the same file.
[lua]// file 1
do
local _x = 0;
end

// file 2
do
print( _x ); // nil, _x isn’t defined in this file
local _x = 1;
print( _x ); // Prints 1 because _x has been defined as a local in this file
end[/lua]

etc…