Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Toggle function for key binding?

Hello,

I am trying to create a gui that will be opened and closed via a single key, say, the 'o' key. I have created a toggle function but it doesn't work as expected. The window only toggles (closed) if I HOLD DOWN the key. I have even tried an intermediate variable to hold the state, but to no effect. Could someone explain what I have missed or done incorrectly?

If I create separate key bindings for open and close, it works fine. Any assistance would be greatly appreciated.

local CAS = game:GetService("ContextActionService")
local cmdFrame = script.Parent.cmdFrame
local isOpen = false

local function make_visible()
	cmdFrame.Visible = true
end

local function make_invisible()
	cmdFrame.Visible = false
end

local function toggle_frame()
	if isOpen then
		cmdFrame.Visible = false
	else
		cmdFrame.Visible = true
	end
	isOpen = not isOpen
end

CAS:BindAction("OpenCmdFrame",toggle_frame,true,Enum.KeyCode.O)
--CAS:BindAction("CloseCmdFrame",make_invisible,true,Enum.KeyCode.P)

3 answers

✓ Accepted answer

Thanks to Qub_Lex for the suggestion!

local CAS = game:GetService("ContextActionService")
local cmdFrame = script.Parent.cmdFrame
-- local isOpen = false Unessecary. We can just use cmdFrame.Visible's value.
local debounce = false  -- Appearntly, when you realease the key it fires again. So i put these two to make sure it doesnt acknowledge second event.
local timesFired = 0

local function fired() -- The event must fire two times before the "toggle_frame" function can run again
	
	timesFired = timesFired + 1
	if timesFired == 2 then
		
		timesFired = 0
		debounce = false
		
	end
	
end

--local function make_visible() I don't see the importance of these
--
--	cmdFrame.Visible = true
--
--end
	 
--local function make_invisible()
--
--	cmdFrame.Visible = false
--
--end

local function toggle_frame() -- Now has a debounce which is disabled by the other function.
	
	fired()
	
	-- print(timesFired)
	
	if not debounce then
		
		debounce = true
		
		--if cmdFrame.Visible then
		--	
		--	cmdFrame.Visible = false
		--	
		--	else
		--	
		--	cmdFrame.Visible = true
		--
		--end

		cmdFrame.Visible = not cmdFrame.Visible -- Thank you Qub_lex!
		
	end
	
end

CAS:BindAction("OpenCmdFrame", toggle_frame, true, Enum.KeyCode.P) -- Set it to bind to P because O zooms out the camera :>

So apparently, when you release the bound key. It fires again. Hence, the weird "hold the key to keep it closed". I made it so the "toggle_frame" function doesn't run the core process again until the key is released.

This is my first time helping people. Please mark this as the answer if it worked. :D

It would be simpler to use

function toggle()
	cmdFrame.Visible = not cmdFrame.Visible
end

CAS:BindAction("OpenCmdFrame",toggle,true,"O")

Using not cmdFrame.Visible will simply be the opposite of its current state.

1 comment

0

oh wow. i never knew you could do that!

Hi, thanks for your answer PolandBall45. You rightly identified the problem but your code can be greatly simplified.

Since we know the button state will always start as false and always get called twice (unless your cat lays down on your keyboard or something!) then we can eliminate all complexity and just use a boolean. This is because the state change is deterministic:

  • false (nothing pressed)
  • true (pressed down)
  • false (released)
local CAS = game:GetService("ContextActionService")
local cmdFrame = script.Parent.cmdFrame
local shouldFire = false --state of the button

local function toggle_frame()
	shouldFire = not shouldFire
	
	if shouldFire then 
		cmdFrame.Visible = not cmdFrame.Visible
	end
	
end

CAS:BindAction("OpenCmdFrame",toggle_frame,true,Enum.KeyCode.P)

Thanks for your help! Russ

1 comment

0

Nice thinking!

This discussion is preserved as it was. New answers, comments, and votes are closed.