DropDown Pro+ (V 1.0.0)

As some of you may know I am the creator of the Dropdown Module. Link to original devpost: DropDown Module! V.3. Now, there were some issues with the previous one, like you could only use this module once for creating a dropdown, so I made a new one! Introducing DropDown Module Pro+, it grants you access to so many new functions, but first we must explain how to basically install it.

Step By Step On How To Use It:

Step 1: Get the module off of the link provided.

Step 2: Put the module into the game. Place in any location you would like!

Step 3: Create two folders, one will be used to store your dropdown buttons, and one will be used to store the contents of the dropdown frame.

Step 4: Create all of the dropdown buttons. Then, inside of the DropDown contents folder, make a Folder for each DropDown button and name it THE SAME as the DropDown button it is paired with! Now, make your DropDown contents buttons, make sure to put them inside of the correct Folder. Name each of these dropdown content buttons with 1 NUMBER in the name, also ensure that each buttons number is numerical. Example: Content1, Content2, .. ect. Unacceptable: djwuidj239dwj23dj, has more than one set of numbers, and is not numerical and does not have a reasonable number!

Image For Confusion

Step 5: Position the buttons inside of the content folder at the same Y.Scale value as the dropdown button. Make sure that these buttons are hidden, so if needed, change the ZIndex of the dropdown button.

For confustion, you can paste this in your command tab!
local dropDownFolder = -- Put the location of the folder here
local dropDownContentFolder = -- Put location of the folder here
local zInD = 0

for _, x: TextButton in ipairs(dropDownFolder:GetChildren()) do
	for _, y: TextButton in ipairs(dropDownContentFolder:FindFirstChild(x.Name):GetChildren()) do
		if y.ZIndex > zInD then
			zInD = y.ZIndex
		end
		y.Position = UDim2.new(y.Position.X.Scale, 0, x.Position.Y.Scale, 0)
	end
	x.ZIndex = zInD + 1
end

Step 6: First, require the module. Second, get both the dropDown folder and the DropDown Content folder. The first parameter is the DropDown folder, and the second is the DropDown contents folder. Then we have three other parameters: autoClose, moveOthers, and advancedSettings. Later we will get into what moveOthers and advancedSettings are, but for now keep them as empty tables: {}. moveOthers is the third parameter which if set to true will close the previous button when another one is opened.

Sorry for the yap, but now we will get into requiring. Now this code is going to look a bit weird, so let’s break it down. The .New() function is so you can create a new Dropdown Instance. You can read more about the .New() function down below. We set this new Instance to a variable, like we would any other, so we can use our other functions on it. Now we use the :AnimateMenu() function, to connect all the buttons to actually open their contents, you can read more about that down below as well! Now time for the code!

Example of LocalScript Code:
local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(
	dropDownButtons, -- Holds all the buttons
	dropdownContents, -- Button Contents
	true, -- Auto Close
	{}, -- moveOthers
	{} -- advancedSettings
)

dropDown:AnimateMenu()

Functions
Here are all of the modules functions:

.New()

Q - How does this function work?

A - Think of it as Instance.new(), but with the new instance being a Instance of a dropdown menu! When we create a new instance, it is important to save it as a variable, so we can other functions with it! So, make sure to save it under like ‘dropDown’ or something to that nature. Then you can pass the 5 arguments through it, where you can see the full explanation of what each parameter is down below!

Sample code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(
	dropDownButtons, -- Holds all the buttons
	dropdownContents, -- Button Contents
	true, -- Auto Close
	{}, -- moveOthers
	{} -- advancedSettings
)
:AnimateMenu()

Q - What does this function do?

A - It allows the buttons to actually be animated! So if you want them to work, it is important you use them after the .New() event!

Sample code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(
	dropDownButtons, -- Holds all the buttons
	dropdownContents, -- Button Contents
	true, -- Auto Close
	{}, -- moveOthers
	{} -- advancedSettings
)

dropDown:AnimateMenu()
:DisconnectAll()

Q - What does the function do?

A - This disconnects all the buttons connections, so they will not animate or open anymore!

Sample Code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(dropDownButtons, dropdownContents, true, {}, {})
dropDown:AnimateMenu()

-- This dropdown no longer serves use, so you disconnect it
dropDown:DisconnectAll()
:PauseConnections()

Q - What does the function do?

A - It stops the buttons from working for a given amount of time, but not a permanent thing! It can either be done by passing an number value, so it can be paused during a cutscene. Or, it can be paused while a player does not have access to the menu for whatever reason, and can be reaccessed by using :ResumeConnections() function!

Passing a number value through the function:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(dropDownButtons, dropdownContents, true, {}, {})
dropDown:AnimateMenu()

-- random code here
loadCutscene()
dropDown:PauseConnections(60) -- pauses for 60 seconds while cutscene runs

Example of using the :ResumeConnections() function:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(dropDownButtons, dropdownContents, true, {}, {})
dropDown:AnimateMenu()

RemovePlayerAccessToMenu.OnClientEvent:Connect(function()
	dropDown:PauseConnections()
end)

GiveBackPlayerAccessToMenu.OnClientEvent:Connect(function()
	dropDown:ResumeConnections()
end)
:ResumeConnections()

Q - What does the function do?

A - It connects the buttons to work again from using the :PauseConnections() function!

Tip: Use this when the time base is unsure. For example, if you have a fixed time for a cutscene, just pass an amount of seconds through `:PauseConnections()’ function, but if you are unsure, then you can use this function!

Sample code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(dropDownButtons, dropdownContents, true, {}, {})
dropDown:AnimateMenu()

RemovePlayerAccessToMenu.OnClientEvent:Connect(function()
	dropDown:PauseConnections()
end)

GiveBackPlayerAccessToMenu.OnClientEvent:Connect(function()
	dropDown:ResumeConnections()
end)
:LockButton()

Q - What does this function do?

A - It stops the player from opening a certain button! This can be reversed by using the :UnlockButton() function!

Security: LOW | So, do not keep any sensitive data inside of this, or you will have to create a more secure way for sensitive data that a player should not be able to access

USE CASE: Why would you even need a :LockButton() function? Let’s say you were creating a dropdown menu that showed the specific powers a player unlocks with each level, but you don’t want them to see what they have until they reach that certain level. Then you can use this to keep the buttons locked from them!

Sample Code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(dropDownButtons, dropdownContents, true, {}, {})
dropDown:AnimateMenu()

for _, x in ipairs(dropdownContents:GetChildren()) do
	dropDown:LockButton(x)
end

local player = game.Players.LocalPlayer
local leaderstats = player.leaderstats
local level = leaderstats.level

level:GetPropertyChangedSignal("Value"):Connect(function()
	local value = level.Value
	
	local buttonToUnlock = dropDownButtons:FindFirstChild("Level-"..value.."-Powers")
	dropDown:UnlockButton(buttonToUnlock)
end)
:UnlockButton()

Q - What does this function do?

A - It unlocks the button from its locked state from the :LockButton() function.

Sample Code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(dropDownButtons, dropdownContents, true, {}, {})
dropDown:AnimateMenu()

for _, x in ipairs(dropdownContents:GetChildren()) do
	dropDown:LockButton(x)
end

local player = game.Players.LocalPlayer
local leaderstats = player.leaderstats
local level = leaderstats.level

level:GetPropertyChangedSignal("Value"):Connect(function()
	local value = level.Value
	
	local buttonToUnlock = dropDownButtons:FindFirstChild("Level-"..value.."-Powers")
	dropDown:UnlockButton(buttonToUnlock)
end)
:CloseButton()

Q - What does this function do?

A - I feel this is very self explanatory, but it overrides the players choice and force closes a button. (No animation shown when force closed!)

Sample Code:

dropDown:CloseButton(dropDownButtons.button1)
:OpenButton()

Q - What does this function do?

A - I feel this is very self explanatory, but it overrides the players choice and force opens a button. (No animation shown when force opened!)

Sample Code:

dropDown:OpenButton(dropDownButtons.button1)
:UpdateSettings()

Q - What is this function used for?

A - Let’s say you want the player to be able to customize their own settings you can use this function to change their settings!

Sample Game: Dropdown Module Function Usecases - Roblox

Sample Code:

-- Services ---
local rs = game:GetService("ReplicatedStorage")

-- Replicated Server ----
local moduleFolder = rs:WaitForChild("Modules")

-- Modules -----
local dropdownMod = require(moduleFolder.DropDownHandler)
local sliderMod = require(moduleFolder.SliderModule)

local UI = script.Parent
local otherDrop = UI.OtherDropDown
local settingsFrame = UI["Settings frame"]

local otherDropDown = dropdownMod.New(
	otherDrop.DropdownFolder,
	otherDrop.Content,
	true,
	{},
	{
		["DropDownSpace"] = 0.005
	}
)

local sampleDrop = settingsFrame.SampleDropDown

local sampleDropDown = dropdownMod.New(
	sampleDrop.DropdownFolder,
	sampleDrop.Content,
	true,
	{},
	{
		["DropDownSpace"] = 0.005
	}
)

otherDropDown:AnimateMenu()
sampleDropDown:AnimateMenu()

print(dropdownMod)

local previousValue = 0.005
function spaceUpdateFunction(value)
	if value == previousValue then
		return
	end
	
	sampleDropDown:OpenButton(sampleDrop.DropdownFolder.Bob)
	sampleDropDown:PauseConnections()
	
	otherDropDown:UpdateSettings({["DropDownSpace"] = value})
	sampleDropDown:UpdateSettings({["DropDownSpace"] = value})
	print(sampleDropDown["spaceInBetween"])
	sampleDropDown:ResumeConnections()
end

local timeValue = 0
function timeUpdateFunction(value)
	if value == timeValue then
		return
	end

	sampleDropDown:ResumeConnections()

	otherDropDown:UpdateSettings({["TweenTime"] = value})
	sampleDropDown:UpdateSettings({["TweenTime"] = value})
end

sliderMod.new(settingsFrame.Spacing, settingsFrame.Spacing.TextLabel, spaceUpdateFunction, 0.05, 0.005, 3)
sliderMod.new(settingsFrame.Time, settingsFrame.Time.TextLabel, timeUpdateFunction, 3, 0, 2)

local trueBtn = settingsFrame.True
local falseBtn = settingsFrame.False

trueBtn.MouseButton1Click:Connect(function()
	trueBtn.UIStroke.Enabled = true
	falseBtn.UIStroke.Enabled = false
	
	otherDropDown:UpdateSettings({["autoClose"] = true})
	sampleDropDown:UpdateSettings({["autoClose"] = true})
end)

falseBtn.MouseButton1Click:Connect(function()
	trueBtn.UIStroke.Enabled = false
	falseBtn.UIStroke.Enabled = true

	otherDropDown:UpdateSettings({["autoClose"] = false})
	sampleDropDown:UpdateSettings({["autoClose"] = false})
end)

local easingStyleInt = 1
local EasingStlyeTable = {
	[1] = Enum.EasingStyle.Linear,
	[2] = Enum.EasingStyle.Sine,
	[3] = Enum.EasingStyle.Back,
	[4] = Enum.EasingStyle.Quad,
	[5] = Enum.EasingStyle.Quart,
	[6] = Enum.EasingStyle.Quint,
	[7] = Enum.EasingStyle.Bounce,
	[8] = Enum.EasingStyle.Elastic,
	[9] = Enum.EasingStyle.Exponential,
	[10] = Enum.EasingStyle.Circular,
	[11] = Enum.EasingStyle.Cubic
} 

local easingDirectInt = 1
local EasingDirectTable = {
	[1] = Enum.EasingDirection.In,
	[2] = Enum.EasingDirection.Out,
	[3] = Enum.EasingDirection.InOut,
}

local styleDebounceTime = 1
local styleDebounceId = 0
local selectedStyle

settingsFrame.EasingStyle.MouseButton1Click:Connect(function()
	easingStyleInt += 1
	if easingStyleInt > 11 then
		easingStyleInt = 1
	end

	selectedStyle = EasingStlyeTable[easingStyleInt]
	local styleName = string.split(tostring(selectedStyle), ".")[3]
	settingsFrame.EasingStyle.Text = "Easing Style: "..styleName

	styleDebounceId += 1
	local currentId = styleDebounceId

	task.delay(styleDebounceTime, function()
		if currentId == styleDebounceId then
			-- Only apply after no clicks for 5 seconds
			otherDropDown:UpdateSettings({["EasingStyle"] = selectedStyle})
			sampleDropDown:UpdateSettings({["EasingStyle"] = selectedStyle})
			sampleDropDown:ResumeConnections()
			print("Applied easing style:", styleName)
		end
	end)
end)

local directionDebounceTime = 1
local directionDebounceId = 0
local selectedDirection

settingsFrame.EasingDirection.MouseButton1Click:Connect(function()
	easingDirectInt += 1
	if easingDirectInt > 3 then
		easingDirectInt = 1
	end

	selectedDirection = EasingDirectTable[easingDirectInt]
	local directionName = string.split(tostring(selectedDirection), ".")[3]
	settingsFrame.EasingDirection.Text = "Easing Direction: "..directionName

	directionDebounceId += 1
	local currentId = directionDebounceId

	task.delay(directionDebounceTime, function()
		if currentId == directionDebounceId then
			-- Only apply after no clicks for 5 seconds
			otherDropDown:UpdateSettings({["EasingDirection"] = selectedDirection})
			sampleDropDown:UpdateSettings({["EasingDirection"] = selectedDirection})
			sampleDropDown:ResumeConnections()
			print("Applied easing direction:", directionName)
		end
	end)
end)

local openSize = settingsFrame.Size
local closeSize = UDim2.new(0,0,0,0)

settingsFrame.Close.MouseButton1Click:Connect(function()
	settingsFrame:TweenSize(closeSize, EasingDirectTable[1], EasingStlyeTable[1], 0.5)
	
	task.wait(0.5)
	settingsFrame.Visible = false
	UI.OpenSettings.Visible = true
end)

UI.OpenSettings.MouseButton1Click:Connect(function()
	settingsFrame.Visible = true
	settingsFrame:TweenSize(openSize, EasingDirectTable[1], EasingStlyeTable[1], 0.5)
	UI.OpenSettings.Visible = false
end)

local lockButton = settingsFrame.LockButton
local lock = false

lockButton.MouseButton1Click:Connect(function()
	if lock then
		sampleDropDown:UnlockButton(sampleDrop.DropdownFolder.Amelia)
		otherDropDown:UnlockButton(otherDrop.DropdownFolder.Amelia)
		
		lockButton.Text = "Lock Grace"
	else
		sampleDropDown:LockButton(sampleDrop.DropdownFolder.Amelia)
		otherDropDown:LockButton(otherDrop.DropdownFolder.Amelia)
		
		lockButton.Text = "Unlock Grace"
	end
	
	lock = not lock
end)
:ResetSettings()

Q - What does this function do?

A - It resets all of the settings to what you set at the very beginning of the code, when you used the .New() function!

Sample Code:

local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local dropDown = dropDownModule.New(
	dropDownButtons, -- Holds all the buttons
	dropdownContents, -- Button Contents
	true, -- Auto Close
	{}, -- moveOthers
	{
		["DropDownSpace"] = 0.005
	} -- advancedSettings
)

dropDown:AnimateMenu()

ResetSettingsButton.MouseButton1Click:Connect(function()
	dropDown:ResetSettings() -- This will reset the DropDownSpace to 0.005 no matter what you changed it to!
end)
:RefreshPositions()

Q - What does this function do?

A - If you believe the function had a glitch with a miscalculation, you can always use the refresh function! Or let’s say something happened and the buttons are positioned all weird, you can just reset them, then boom, this does not close any buttons, but simply recalculated!

dropDown:RefreshPositions()
:ResetDropdownStates()

Q - What does this function do?

A - It closes all of the buttons and unlocks every single button!

Sample code

dropDown:ResetDropdownStates()
:ConnectChildedAddedConnectionWithDropdownFolder()

Q - What does this function do?

A - I know the name is intimidating, but all it does it makes sure if you add a button, it still works with the new addition!

Sample Code (I’ll write a better one later sorry!)

dropDown:ConnectChildedAddedConnectionWithDropdownFolder()
:DisconnectChildAdded()

Q - What does this function do?

A - It disconnects the previous function. This is useful when the player is not needing to check if anything is added, so it saves processing power!

Sample Code:

dropDown:DisconnectChildAdded()

Wow, that is a lot of functions! I will add more if I can think of them, or you can give me ideas below!


Parameters

The parameter moveOthers is a table, where you will store other elements to be moved with the drop down effect, ensuring they will be moved out of the way! You can use two sets of Folders, it will loop through the first folder and find GuiObjects there and will search through a second table for GuiObjects, but no third table will work!. You can also use a specific type of 1 GuiObject! You could even use the collection service and add it to a table and have it work like that!

Example: Before and After


CollectionService Code Example With Requiring
local dropDownModule = require(game:GetService("ReplicatedStorage").Modules.HandleDropDownMenu)

local moveOthers= {}

local cs = game:GetService("CollectionService")
local tag = "ToMove"

for _, x in ipairs(cs:GetTagged(tag)) do
	if x:IsA("GuiObject") then
		table.insert(moveOthers, x)
	end
end

local dropDown = dropDownModule.New(
	dropDownButtons, -- Holds all the buttons
	dropdownContents, -- Button Contents
	true, -- Auto Close
	moveOthers,
	{} -- advancedSettings
)

dropDown:AnimateMenu()

There is a 5th parameter! This parameters name is ADVANCED_SETTINGS, in this parameter, you can change the TweenTime, DropDownSpace, EasingDirection, and EasingStyle. More could be added, recommend any if you want them to be added.

  • Why is there the TweenTime and DropDownSpace again, isn’t it already at the top, used before?

Yes, it is, you would use this in case of creating MULTIPLE dropdowns, and wanting them to be spaced differently or be tweened faster.

Now, for EasingDirection and EasingStyle allows YOU to change the way it is animated!

  • So, how do I use this?

Well first you create a table, and inside of the table, you need to have [“TweenTime”] = to your value, not all are needed in there, you can only change one if you would like! All the other ones have the same capitals, and spelling as the matching ones.

  • Can I see this in code, so it all makes sense?

Yes, of course! (This table is what you would put inside of the required portion!

local advancedSettings = {
	["TweenTime"] = 0.1,
	["DropDownSpace"] = 0,
	["EasingDirection"] = Enum.EasingDirection.In,
	["EasingStyle"] = Enum.EasingStyle.Quad
}

Without using this, here are the defult values:

  • TweenTime is equal whatever the number value is childed to the module
  • DropDownSpace is equal whatever the number value is childed to the module
  • EasingDirection = Enum.EasingDirection.In
  • EasingStyle = Enum.EasingStyle.Linear

Now, that is all of the basics. I will let this module be out for free for 24 hours!! Please go test and let me know of any errors you encounter!

Module: https://create.roblox.com/store/asset/119281570862694/DropDown-Module-Pro

Someone also pointed out about an example game, yes I do have one that is uncopylocked, check out here: Dropdown Module Function Usecases - Roblox!

2 Likes

are you sure about that? there only 169 views, so that is bad idea

Why would that be a bad idea? Wouldn’t this entice people even more?

Prices usually discourage people, especially if it’s for something as simple as this.

2 Likes

example place showing what it can do , that is edible to check it out.

I’m not sure if I am answering what you are asking because I don’t quite understand you. But if you are asking about a uncopylocked game. Yes, I do have one I did have it behind the update settings function, I honestly should’ve pushed it out more, but here is the link to that: Dropdown Module Function Usecases - Roblox. Please note that doesn’t use all of the functions, but shows you how to use the update settings, and how to set it up. I plan to make a better one later for all the functions, but that is what I have currently. I also plan to add comments to describe what is going on, but yep!

ok, thanks for sharing the link , I will check it out