Focus Lost and interrupting tweens

So currently I am making a command bar for a project. I want the opening and closing of it to be as smooth as possible, however when I continuously click the activate key and click right away to make focus lost activate, it decides to stay on the open position but never actually closes the bar.
(Red Bar is mine, other is BA 2.0’s command bar)

com-video-to-gif

If you could tell, the focus was lost but the gui stayed open and the core gui got re enabled. Any ways on how I could fix this issue? Here is my script currently.

local mouse = player:GetMouse()
open = false
open2 = false

consoleframe = player.PlayerGui:WaitForChild("ScreenGui")
mouse.KeyDown:connect(function(key)
    if key:lower() == ";" or key:upper() == ";" then
        print("Pressed e or E")
if not open then
	if not open2 then
end
	open = true
	print "open"
	game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)
		consoleframe.Frame.TextLabel.Text = "Enter command here..."
		consoleframe.Frame:TweenSize(UDim2.new(1,0,0.01,23),"Out","Sine", .2)
		consoleframe.Frame.TextBox:CaptureFocus()
		if consoleframe.Frame.TextBox.Text == "e" then
		 consoleframe.Frame.TextBox.Text = "" 
		end

end

		consoleframe.Frame.TextBox.FocusLost:connect(function()
			if open then
			open = false	
				print "not open"	
				wait()						
				consoleframe.Frame.TextBox:ReleaseFocus()
		consoleframe.Frame:TweenSize(UDim2.new(1,0,0,0),"Out","Sine", .2)
		consoleframe.Frame.TextBox:ReleaseFocus()	
			game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, true)
			
			open2 = true
		end

			end)
		    end
end)

Something you could solve by searching or reading the documentation page. TweenSize has a 5th parameter, override, which you can set as true to allow other tweens to override currently-running tweens on an object. It defaults to false. Simply add an extra argument to your TweenSize calls, true.

With that out of the way though, I want to talk about your code a bit. Just for future reference, while we’re addressing the problem at hand.

  • Please fix your indentation. It’s going to help collaborators or people reading your thread understand what you’re writing better and you’re going to breathe a sigh of relief for being able to read your code better.

  • Mouse.KeyDown is deprecated. Notice the big red banner. Change over to UserInputService when you can. It’s much more powerful in what it can do anyway.

    • To note; if you do change over to UserInputService, you can just check the KeyCode instead of checking both the upper and lower case of a letter.
  • Use local variables. You have at least three globals here. Keep conventions constant as much as possible. Local variables should be used wherever possible.

    • Consider assigning some of your more commonly used objects to variables. For example, consoleframe.Frame and its respective TextBox.
  • You can use one bool as opposed to two. Instead of open and open2, make it just open or something similar. When it’s true, open the frame. When it isn’t, close the frame.

  • Use TweenService. It can do everything these weird tween methods can and more. It also includes automatic overrides, which would’ve stopped your problem right there and then instead of not knowing that you have to pass a 5th argument to get that to work.

  • Instead of having both an empty TextBox and a TextLabel for instructions, consider only using a TextBox with the property TextBox.PlaceholderText.

    • This is what will show when there is nothing in the TextBox. You can set this to “Enter command here…” and it will auto clear when something is typed. This avoids needing to use a TextLabel and hide it after something gets typed.

Since you already have some code down and an attempt, I can provide you code that builds off of what you have right now and transitions to a better system. Remember to read documentation or ask around if you don’t understanding something. The only thing I didn’t put in from my suggestions was TweenService and change the arguments of each TweenSize (except for adding the fifth one), which is up to you to incorporate if you wish.

local StarterGui = game:GetService("StarterGui")
local UserInputService = game:GetService("UserInputService")

-- Not sure how you get player, including just in case
local LocalPlayer = game:GetService("Players").LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

-- Consider a proper name for your Gui that isn't ScreenGui
local ConsoleGui = PlayerGui:WaitForChild("ScreenGui")
local ConsoleFrame = ConsoleGui.Frame
local KeyToOpen = Enum.KeyCode.Semicolon

-- Condition to check if console is open
local ConsoleOpen = false

-- Run an action based on user input
UserInputService.InputBegan:Connect(function (inputObject, gameProcessedEvent)
    -- Check if the pressed key is our open key
    if inputObject.KeyCode == KeyToOpen then
        -- Check if console not open and Roblox script not using input
        if not ConsoleOpen and not gameProcessedEvent then
            -- Set ConsoleOpen to true and other properties
            ConsoleOpen = true
            StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)
            ConsoleFrame.TextLabel.Text = "Enter command here..."
            ConsoleFrame:TweenSize(UDim2.new(1, 0, 0.01, 23), "Out", "Sine", 0.2, true)
            ConsoleFrame.TextBox:CaptureFocus()
            -- Clear text if there is any: catch-all case
            if #ConsoleFrame.TextBox.Text > 0 then 0 -- Consider ClearTextOnFocus?
                ConsoleFrame.TextBox.Text = ""
            end
        end
    end
end)

ConsoleFrame.TextBox.FocusLost:Connect(function ()
    if ConsoleOpen then
        ConsoleOpen = false
        ConsoleFrame.TextBox:ReleaseFocus()
        ConsoleFrame:TweenSize(UDim2.new(1, 0, 0, 0), "Out", "Sine", 0.2, true)
        StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, true)
    end
end)
5 Likes

Thank you. I’m saving this for future reference.