How to use DBinder correctly ?

Hello,

I’m testing things. In a client side script, I have a convar “test_enabled”, that will be either 0 or 1. I also have a concmd “test_toggle” that will obviously toggle the value of test_enabled.

Instead of telling players to bind a key to command “test_toggle”, I would like to add a key binder in the control panel of my script. If there is no key bound to that command, the DBinder will show “<key>”, and if there is a key bound, then it will show the key name.

But I don’t know how to make it work.

Here is what I have actually:



if (CLIENT) then

	CreateClientConVar( "test_enabled", 0, true, false)
	
	local test_enabled = GetConVarNumber( "test_enabled" )
	
	concommand.Add( "test_toggle",
		function( ply )
			RunConsoleCommand( "test_enabled", ((test_enabled == 0) and "1" or "0") )
		end
	)

	cvars.AddChangeCallback( "test_enabled",
		function( cvarName, oldValue, newValue )
			test_enabled = tonumber( newValue )
			print( "test_enabled = " .. test_enabled )
		end
	)

	--[[
	hook.Add("PlayerButtonDown", "test_hook_cl_PlayerButtonDown",
		function( ply, button )
			if ( input.GetKeyName(button) == input.LookupBinding( "test_toggle" ) ) then
				ply:ChatPrint( tostring(button) .. " " .. input.GetKeyName(button) )
			end
		end
	)
	]]
	
	hook.Add("PopulateToolMenu", "test_hook_cl_PopulateToolMenu",
		function()
			spawnmenu.AddToolMenuOption("Options", "TEST", "test_settings", "TEST", "", "",
				function( panel )
					local binder = vgui.Create( "DBinder", panel )
						binder:SetText( input.LookupBinding( "test_toggle" ) or "<key>" )
					panel:AddItem( binder )
					panel:AddControl( "Numpad", { Label = "Toggle Enabled", Command = "test_toggle" } )
				end
			)
		end
	)

end


Actually the DBinder do nothing, because I don’t know what to do next… And as you can see I also tried to use a “Numpad” control (weird name since it’s possible to bind any keys), but it doesn’t work correctly: it will only work once, when I press the button and assign a key to it.

Can someone show me how to do what I want?

I’ve found one solution, that was simple enough but not so obvious!

But it’s not perfect because I can’t find how to set custom texts (instead of “NONE” and “PRESS A KEY”), I may have to copy the DBinder code and make my own control with it.



if ( CLIENT ) then

	CreateClientConVar( "test_enabled", 0, true, false )
	CreateClientConVar( "test_toggle_key", 0, true, false )
	
	local test_enabled = GetConVarNumber( "test_enabled" )
	local test_toggle_key = GetConVarNumber("test_toggle_key")
	
	local previousTime = 0

	cvars.AddChangeCallback( "test_enabled",
		function( cvarName, oldValue, newValue )
			test_enabled = tonumber( newValue )
			print( "test_enabled = " .. test_enabled )
		end
	)
	
	cvars.AddChangeCallback( "test_toggle_key",
		function( cvarName, oldValue, newValue )
			test_toggle_key = tonumber( newValue )
			print( "test_toggle_key = " .. test_toggle_key )
		end
	)

	
	hook.Add( "PlayerButtonDown", "test_hook_cl_PlayerButtonDown",
		function( ply, button )
			if ( button == test_toggle_key ) then
				local currentTime = os.clock()
				if ( currentTime - previousTime > 0.2 ) then
					RunConsoleCommand( "test_enabled", ((test_enabled == 0) and "1" or "0") )
					previousTime = currentTime
				end
			end
		end
	)
	
	hook.Add( "PopulateToolMenu", "test_hook_cl_PopulateToolMenu",
		function()
			spawnmenu.AddToolMenuOption( "Options", "TEST", "test_settings", "TEST", "", "",
				function( panel )
					local binder = vgui.Create( "DBinder", panel )
						binder:SetConVar( "test_toggle_key" )
					panel:AddItem( binder )
				end
			)
		end
	)

end


I added an “antispam” because sometimes the hook was called 2 or 3 times in a single key press.

If that can help someone :wink:

PS: I leave this thread open if someone know a better solution and want to share it.

I wouldn’t use “PlayerButtonDown” since it’s not called on every single keypress.

What would you use then… Check for input.WasKeyPressed in a Think hook? Because I don’t find any other function or hook related to keys.

Anyway I don’t think it ever skipped one key press. Can you tell how or when will it skip key presses?

This is why it skips key presses:
https://github.com/Facepunch/garrysmod-issues/issues/645

Yes, I’m using the input library with a Think hook instead for detecting key presses.

Ok thanks,

After a few tests in a Think hook, it appears that the function input.WasKeyPressed will always return true when I’m holding the key down (not sure if that’s the intended behaviour), and that the function input.WasKeyReleased always return false… There is definately something wrong with detecting key releases. So i use this, it works fine:



	local keyWasDown = false
	hook.Add( "Think", "test_hook_cl_Think",
		function()
			local keyIsDown = input.IsKeyDown( test_toggle_key ) 
			if ( keyIsDown and not keyWasDown ) then
				RunConsoleCommand( "test_enabled", ((test_enabled == 0) and "1" or "0") )
				keyWasDown = true
			elseif ( keyWasDown and not keyIsDown ) then
				keyWasDown = false
			end
		end
	)


It’s returning false because “test_toggle_key” is not the key emum you want.

http://wiki.garrysmod.com/page/Enums/KEY

Just wanted to share what I did when I woke up :slight_smile:



	hook.Add( "PopulateToolMenu", "test_hook_cl_PopulateToolMenu",
		function()
			spawnmenu.AddToolMenuOption( "Options", "TEST", "test_settings", "TEST", "", "",
				function( panel )

					local control = vgui.Create( "DSizeToContents", panel )
						control:SetTall( 30 )
						control:DockPadding( 10, 10, 10, 0 )
						control:Dock( TOP )
						
						local checkbox = vgui.Create( "DCheckBoxLabel", control )
							checkbox:SetText( "0123456789012345678901234567890123456789" )
							checkbox:SetDark( true )
							checkbox:SetConVar( "test_enabled" )
							checkbox:SetSize( 220, 20 )
							checkbox:DockMargin( 0, 3, 0, 0 )
							checkbox:Dock( LEFT )
										
						local binder = vgui.Create( "DBinder", control )
							binder:SetConVar( "test_toggle_key" )
							binder:SetToolTip( "You can assign a toggle key." )
							binder:SetSize( 70, 20 )
							binder:Dock( RIGHT )
										
					table.insert( panel.Items, control )
				end
			)
		end
	)


[editline]5th March 2014[/editline]

Sorry to post again so quickly, but I’ve just realized there is a problem with this key press thing… It detect that I pressed the key even when the chatbox is open, or a text entry is focused (or whatever, I don’t know all possibilities). What is the best way to prevent that ? I tried adding a vgui.CursorVisible( ) check in the Think hook, it seems to work, but I’m not sure it’s the best way.