I recently started my first serious project and got stuck at the interface stage, I wanted to make this part optimized and modular(?) so that I could use this piece of code for everything related to selecting things, so in some mechanics the choice is single and the interface immediately closes after the selection, and in others it does not close after the selection and stuff happens (I know it sounds weird and incomprehensible, I don’t know how to explain it)
My conclusions came to this code below. But for some reason, when calling the function, it immediately returns nil, although it was planned that when clicking on a folder it will return it
I’m not really asking for a huge ready-made code solution, more how can this be implemented and what functions should be used
Thanks in advance
local function TestGuiSelection(Frame)
Frame.ScrollingFrameFolder1.Visible = true
Frame.ScrollingFrameFolder2.Visible = false
Frame.ScrollingFrameFolder3.Visible = false
local repbutton = Frame.ScrollingFrameFolder1.Button
for z, Folder1 in pairs(FullFolder:GetChildren()) do
local newbuttonFolder1 = repbutton:Clone()
newbuttonFolder1.Name = Folder1.Name
newbuttonFolder1.Text = Folder1.Name
newbuttonFolder1.Parent = repbutton.Parent
newbuttonFolder1.Activated:Connect(function()
for x, Folder2 in pairs(ChooseFrame.ScrollingFrameFolder2:GetChildren()) do
if Folder2:IsA("Frame") == true or Folder2:IsA("TextButton") == true then
if Folder2.Visible == true then
Folder2:Destroy()
end
end
end
Frame.ScrollingFrameFolder1.Visible = false
Frame.ScrollingFrameFolder2.Visible = true
Frame.ScrollingFrameFolder3.Visible = false
local repbutton = Frame.ScrollingFrameFolder2.Button
for x, Folder2 in pairs(Folder1:GetChildren()) do
local newbuttonfull = repbutton:Clone()
newbuttonFolder2.Name = Folder2.Name
newbuttonFolder2.Text = packfull.Name
newbuttonFolder2.Parent = repbutton.Parent
newbuttonFolder2.Visible = true
newbuttonFolder2.Activated:Connect(function()
for c, pack in pairs(ChooseFrame.ScrollingFrameFolder3:GetChildren()) do
if Folder3:IsA("Frame") == true or Folder3:IsA("TextButton") == true then
if Folder3.Visible == true then
Folder3:Destroy()
end
end
end
Frame.ScrollingFrameFolder1.Visible = false
Frame.ScrollingFrameFolder2.Visible = false
Frame.ScrollingFrameFolder3.Visible = true
local repbutton = Frame.ScrollingFrameFolder3.Placeholderpack
for c, Folder3 in pairs(Folder2:GetChildren()) do
local newbutton = repbutton:Clone()
local cfg = pack.CFG
newbutton.TextLabel.Text = cfg:WaitForChild("Name").Value
newbutton.ImageButton.Image = cfg:WaitForChild("PictureID").Value
newbutton.Parent = repbutton.Parent
newbutton.Visible = true
newbutton.ImageButton.Activated:Connect(function()
return Folder3
end)
end
end)
end
end)
end
end
Placeholder.Activated:Connect(function() --so this needs to act multiple times but i dont know how to do it lol
if MainFrame.Visible == false then
MainFrame.Visible = true
local selected = nil
selected = TestGuiSelection(SelectionFrame) --instatly prints nil for some reason without waiting for return in function
print(selected)
else
MainFrame.Visible = false
end
end)
First of all, you need to understand why your function is returning nil. This happens because the return statement only executes when the button is clicked. If you want it to wait until a button is clicked and then return the value, you should do something like this:
local function TestGuiSelection(Frame)
Frame.ScrollingFrameFolder1.Visible = true
Frame.ScrollingFrameFolder2.Visible = false
Frame.ScrollingFrameFolder3.Visible = false
local value
local repbutton = Frame.ScrollingFrameFolder1.Button
for z, Folder1 in pairs(FullFolder:GetChildren()) do
local newbuttonFolder1 = repbutton:Clone()
newbuttonFolder1.Name = Folder1.Name
newbuttonFolder1.Text = Folder1.Name
newbuttonFolder1.Parent = repbutton.Parent
newbuttonFolder1.Activated:Connect(function()
for x, Folder2 in pairs(ChooseFrame.ScrollingFrameFolder2:GetChildren()) do
if Folder2:IsA("Frame") == true or Folder2:IsA("TextButton") == true then
if Folder2.Visible == true then
Folder2:Destroy()
end
end
end
Frame.ScrollingFrameFolder1.Visible = false
Frame.ScrollingFrameFolder2.Visible = true
Frame.ScrollingFrameFolder3.Visible = false
local repbutton = Frame.ScrollingFrameFolder2.Button
for x, Folder2 in pairs(Folder1:GetChildren()) do
local newbuttonfull = repbutton:Clone()
newbuttonFolder2.Name = Folder2.Name
newbuttonFolder2.Text = packfull.Name
newbuttonFolder2.Parent = repbutton.Parent
newbuttonFolder2.Visible = true
newbuttonFolder2.Activated:Connect(function()
for c, pack in pairs(ChooseFrame.ScrollingFrameFolder3:GetChildren()) do
if Folder3:IsA("Frame") == true or Folder3:IsA("TextButton") == true then
if Folder3.Visible == true then
Folder3:Destroy()
end
end
end
Frame.ScrollingFrameFolder1.Visible = false
Frame.ScrollingFrameFolder2.Visible = false
Frame.ScrollingFrameFolder3.Visible = true
local repbutton = Frame.ScrollingFrameFolder3.Placeholderpack
for c, Folder3 in pairs(Folder2:GetChildren()) do
local newbutton = repbutton:Clone()
local cfg = pack.CFG
newbutton.TextLabel.Text = cfg:WaitForChild("Name").Value
newbutton.ImageButton.Image = cfg:WaitForChild("PictureID").Value
newbutton.Parent = repbutton.Parent
newbutton.Visible = true
newbutton.ImageButton.Activated:Once(function()
value = Folder3
end)
end
end)
end
end)
end
repeat task.wait() until value
return value
end
Placeholder.Activated:Connect(function() --so this needs to act multiple times but i dont know how to do it lol
if MainFrame.Visible == false then
MainFrame.Visible = true
print(TestGuiSelection(SelectionFrame))
else
MainFrame.Visible = false
end
end)
i think there’s more than one button (correct me if I’m wrong). The for loop would stop and return only if the first button in the for loop is clicked. It would be better if it’s done like this instead:
I am not sure if I understood this well
I think that you are trying to do a specific thing once a Gui is selected
rather than returning a value and running code on it, you can add a callback parameter to the function
example: unrelated to main code
-- loops through all children of scrollingFrame and calls the callback variable when they are activated
local function onParentChildrenActivated(scrollingFrame, callback)
for _, frame :ImageButton in scrollingFrame do
frame.Activated:Connect(function()
-- some code
callback(frame) -- call the callback function with frame as an argument
end)
end
end
--later
local scrollingFrame = ...
onParentChildrenActivated(scrollingFrame, function(frame)
-- this function/callback would run for every child of scrollingFrame
frame.BackgroundColor3 = Color3.new(math.random(), math.random(), math.random()) -- sets a custom color
end)
also, consider adding more comments to the script so that people can understand what it is doing
not necessary a problem but there are many indentations in the function which is making it harder for me to read it
end) -- 1
end --2
end) --3
end --4
end) --5
end --6
end --7
you can break the function into multiple functions or use early exit rule (idk what it is called but its something like this
--do
if not canFly then return end
--code
--instead of
if canFly then
--code
end
the function would still return nil. newButton.ImageButton.Activated:Wait() would only be executed if newButtonFolder2.Activated:Connect(function()) was triggered. plus, there’s the fact that there might be more than one button that could be clicked inside the for loop
ohhhh ic what you mean. also would it make sense for each function to return the value of the function nested inside it? essentially just a chain of return statements to pass on folder3.
also, for the activated function
could they all be replaced with :Wait()? but then atp just use the task.wait() repetition…
ig your solution works best, although i still havent taken a look at the other guys solution
The “early exit rule” is a design pattern known as an “early return”. It’s attributed to the never-nesting ideology, which applies strategies like inversion (inverting conditionals for early-exit opportunities) and extraction to improve code readability. For more information:
Thanks you alot, you really saved me. Readability of my code is the thing im still working on, althrough i cant split it into multiple functions(at least i think i cant) ill look into eary exit more deeply, thanks again