VGUI Question

Hello people
If I were to have something like this, how would I make it so I can open the actual panel with a console command and a chat command? Both using something like…



ConsoleCommand = "openmenu"
ChatCommand = "!openmenu"


I don’t really know what to look for, for console and chat commands to open the panel… Help would be appreciated.



function UserPanel()

		frame = vgui.Create( "DFrame" )
		frame:SetPos( 50, 50 )
		frame:SetSize( 400, 1000 )
		frame:SetTitle( "Test" )
		frame:SetVisible( true )
		frame:SetDraggable( false )
		frame:ShowCloseButton( true )
		frame:MakePopup()
		
end


For a Console command use concommand.Add

While for a chat command you’ll have to use the PlayerSay Hook check when the player types the keywords and trigger the menu using the net library as the Hook is Server Side.

So would the PlayerSay for chat command be something like…



hook.Add( "PlayerSay", 0, function( ply, text )
	if ( string.sub( text, 1, 5 ) == "!menu" ) then
		UserPanel:MakePopup()
	end
end)


I’m assuming the UserPanel:MakePopup is incorrect, And as for this line



if ( string.sub( text, 1, 5 ) == "!menu" ) then


I couldn’t think in my head how I would physically make it use a variable ( ChatCommand )

Yeah that would work, however due to the VGUI been created on Client and the hook running on the Server. You will have to do something like this




if SERVER then

util.AddNetworkString("chatCommand") -- caches the message to be sent later on

hook.Add( "PlayerSay", "ThisNeedsToBeAString", function( ply, text )
	if ( string.sub( text, 1, 5 ) == "!menu" ) then
		net.Start("chatCommand") -- Starts the message to client to trigger the panel
                net.Send(ply) -- Sends the message to the player who typed "!menu"
	end
end)


else

    function UserPanel()

    end
    net.Receive("chatCommand",UserPanel) -- Once the message is sent, this will fire the userPanel function creating the menu

end



Think this should work, but that’s the general idea I believe.

EDIT: Sorry messed up, fixed it now.

It seems that it gives me a shot ton of ulx errors, and at the same time Doesn’t do anything when I type !menu I’ll give it a go with how you did it, and see the result.

EDIT: I can’t seem to figure out how to do it, from what I can tell the error is pointing to this line
hook.Add( “PlayerSay”, 0, function( ply, text )

Sorry fixed it the unique identifier on the hook.Add needs to be a string.

It works great, I got console command added too, my next question is, how would I go about centering this?



		frame = vgui.Create( "DFrame" )
		frame:SetPos( 50, 50 )
		frame:SetSize( 400, 600 )
		frame:SetTitle( "Test" )
		frame:SetVisible( true )
		frame:SetDraggable( false )
		frame:ShowCloseButton( true )
		frame:MakePopup()


EDIT:
Just noticed when I tried to get it to use chatCommand it doesn’t actually work with the chat command… example.



if ( string.sub( text, 1, 11 ) == chatCommand ) then


I assumed it would be that, but it didn’t work so I tried this



if ( string.sub() == chatCommand ) then


That also didn’t work, but it returned this inside console



[ERROR] addons/addon/lua/autorun/ui.lua:6: bad argument #1 to 'sub' (string expected, got no value)
	1. sub - [C]:1
		2. fn - addons/addon/lua/autorun/ui.lua:6


Which then again, points back to this line



if ( string.sub( text, 1, 11 ) == chatCommand ) then


EDIT 2:



if ( string.sub( chatCommand, 1, 11 )) then


Allows it to work for the sorda… but it also you know… allows it to open with anything at all that is typed

frame:Center()




if (string.sub(text, 1, 9) == "!openmenu") then




See, the thing about what you showed me up above, I want it to read from this of which I have in another line



chatCommand = "!openmenu"


Which is why I tried getting it to use chatCommand

Don’t make a global chatCommand. Just localize it in the top of your script.



if (string.sub(text, 1, 9) == chatCommand) then


string.sub() takes 3 arguments:

  1. The text to check
  2. the starting position
  3. the ending position
    Since your actual command is only 9 letters long, you use 9 instead of 11.

Ahh sweet, I didn’t know that was how it actually worked, thanks. Also I was looking at a derma thing on the forums, and it shows something like this…



MenuButton.DoClick = function ( btn )
    local MenuButtonOptions = DermaMenu() -- Creates the menu
    MenuButtonOptions:AddOption("hello", function() Msg("Hello") end ) -- Add options to the menu
    MenuButtonOptions:AddOption("how", function() Msg("How") end )
    MenuButtonOptions:AddOption("are", function() Msg("Are") end )
    MenuButtonOptions:AddOption("you", function() Msg("You") end )
    MenuButtonOptions:AddOption("?", function() Msg("?") end )
    MenuButtonOptions:Open() -- Open the menu AFTER adding your options
end


It seems that from what I can tell is actually outdated, as when I gave that a try, it physically didn’t do anything when I left or right clicked, any clues? thanks.

Because you have to bind it to a DButton, or something similar.



local DButton = vgui.Create( "DButton" )
DButton:SetPos( 40, 40 )
DButton:SetText( "Please click me!" )
DButton:SetSize( 120, 60 )
DButton.DoClick = function ( btn )
    local MenuButtonOptions = DermaMenu() -- Creates the menu
    MenuButtonOptions:AddOption("hello", function() Msg("Hello") end ) -- Add options to the menu
    MenuButtonOptions:AddOption("how", function() Msg("How") end )
    MenuButtonOptions:AddOption("are", function() Msg("Are") end )
    MenuButtonOptions:AddOption("you", function() Msg("You") end )
    MenuButtonOptions:AddOption("?", function() Msg("?") end )
    MenuButtonOptions:Open() -- Open the menu AFTER adding your options
end


DermaMenu() is just a shorthand way of doing vgui.Create(“DMenu”)

Well how would I use that with options inside a DListView?



local PlayerView = vgui.Create("DListView", frame2)


I tried something like this



		local PlayerView = vgui.Create("DListView", frame2)
		PlayerView:SetPos(25, 10)
		PlayerView:SetSize(450, 674)
		PlayerView:SetMultiSelect(false)
		PlayerView:AddColumn("List of Players")
		PlayerView.DoClick = function ( btn )
			local PlayerViewOptions = DermaMenu() -- Creates the menu
			PlayerViewOptions:AddOption("hello", function() Msg("Hello") end ) -- Add options to the menu
			PlayerViewOptions:AddOption("how", function() Msg("How") end )
			PlayerViewOptions:AddOption("are", function() Msg("Are") end )
			PlayerViewOptions:AddOption("you", function() Msg("You") end )
			PlayerViewOptions:AddOption("?", function() Msg("?") end )
			PlayerViewOptions:Open() -- Open the menu AFTER adding your options
		end


Which didn’t seem to work

Use PlayerView.OnClickLine = function()

Alright that works, thanks… my next question is, How would I customize the part that says List Of Players?
I’m assuming this wouldn’t work because it would customize the hole thing? Am I wrong? Any pointers?



PlayerView.Paint = function( self, w, h )


Not too sure about that one. I played around with it, and this:



PlayerView:AddColumn("List of Players").Paint = function()
    draw.RoundedBox(4, 0, 0, PlayerView:GetWide(), PlayerView:GetTall(), Color(255, 0, 0))
end


Caused it to draw the colored box, but I couldn’t figure out a way to hide the normal one.

You can try looking at these:

After you SetSize, call Center( ) on it.

See, i’ve been looking at that derma thing or whatever, I don’t entirely see how to hide the default box though, it should normally hide whenever .paint is used, from what I can tell at least.

EDIT:
Giving it a try now, but how would I use this with you know, auto updating the player list without having to reopen the UI? Would be very helpful, any pointers? Something I can look at for this?



PlayerView:AddColumn("List of Players").Paint = function()
    draw.RoundedBox(4, 0, 0, PlayerView:GetWide(), PlayerView:GetTall(), Color(255, 0, 0))
end


This doesn’t seem to effect it at all for some reason, so i’m not sure.

Auto Updating would look weird. You’d probably have to look into using Net Messages and the PlayerInitialSpawnhook. I would recommend just having a refresh button.

Also, That definitely affects it, but it’s set to only Paint in the bounds of the box that is covering it. If you look closely you can see like, 4 red pixels.

If I were to have a refresh button, how would I have that auto refresh? I just generally don’t want something that clutters the UI