my topbar buttons sometimes duplicate (using the new module)
is this a bug
Thanks for this. I does look like its a part of roblox.
Hey, so is it possible to make the icons not selectable or deselectable with debounce? Or is there another way?
Hello.
I’m making owner-only icon but it doesn’t show me. Here’s the script.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage:WaitForChild("Modules") -- Modules folder in ReplicatedStorage
local Icon = require(Modules:WaitForChild("Icon")) -- The Icon module
local OwnerOnly = Icon.new():setEnabled(false)
local SoundService = game:GetService("SoundService") -- Our click and hover sound
local Click = SoundService:WaitForChild("Click")
local Hover = SoundService:WaitForChild("Hover")
-- Sound IDs
-- Hover = rbxassetid://4658309128
-- Click = rbxassetid://6706935653
game.Players.PlayerAdded:Connect(function(plr)
if plr.Name == "nojuslopro123" --[[ My roblox username--]] then
OwnerOnly:setEnabled(true)
end
end)
OwnerOnly:bindEvent("hoverStarted", function(icon)
Hover:Play()
end)
OwnerOnly.selected:Connect(function()
Click:Play()
end)
OwnerOnly.deselected:Connect(function()
Click:Play()
end)
Try putting with UserId instead of username
Well it doesn’t work.
local Modules = ReplicatedStorage:WaitForChild("Modules") -- Modules folder in ReplicatedStorage
local Icon = require(Modules:WaitForChild("Icon")) -- The Icon module
local OwnerOnly = Icon.new():setEnabled(false)
local SoundService = game:GetService("SoundService") -- Our click and hover sound
local Click = SoundService:WaitForChild("Click")
local Hover = SoundService:WaitForChild("Hover")
-- Sound IDs
-- Hover = rbxassetid://4658309128
-- Click = rbxassetid://6706935653
game.Players.PlayerAdded:Connect(function(plr)
if plr.UserId == 1471122583 --[[ My roblox id--]] then
OwnerOnly:setEnabled(true)
end
end)
OwnerOnly:bindEvent("hoverStarted", function(icon)
Hover:Play()
end)
OwnerOnly.selected:Connect(function()
Click:Play()
end)
OwnerOnly.deselected:Connect(function()
Click:Play()
end)
Is it right?
You can’t use PlayerAdded to retrieve the Player on the client as the player has already loaded in.
I recommend using Players.LocalPlayer to retrieve the player.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SoundService = game:GetService("SoundService") -- Our click and hover sound
local Players = game:GetService("Players")
local Modules = ReplicatedStorage:WaitForChild("Modules") -- Modules folder in ReplicatedStorage
local Icon = require(Modules:WaitForChild("Icon")) -- The Icon module
local Player = Players.LocalPlayer --Only works on LocalScripts
local Click = SoundService:WaitForChild("Click")
local Hover = SoundService:WaitForChild("Hover")
-- Sound IDs
-- Hover = rbxassetid://4658309128
-- Click = rbxassetid://6706935653
if Player.UserId == 1471122583 then
local OwnerOnly = Icon.new()
--OwnerOnly:setEnabled(true)
OwnerOnly:bindEvent("hoverStarted", function()
Hover:Play()
end)
OwnerOnly.selected:Connect(function()
Click:Play()
end)
OwnerOnly.deselected:Connect(function()
Click:Play()
end)
end
It Worked, Thank You
-- dont pay attention here.
Off-topic: ok i won’t even pay any attention at that lol
Hi, you can achieve this with icon:lock()
, icon:unlock()
and the selected/deselected events. e.g:
local DEBOUNCE_TIME = 0.5
local heartbeat = game:GetService("RunService").Heartbeat
local debounceFunction = function(icon)
heartbeat:Wait()
icon:lock()
wait(DEBOUNCE_TIME)
icon:unlock()
end
icon:bindEvent("selected", debounceFunction)
icon:bindEvent("deselected", debounceFunction)
I’ll consider making this an official method in the future, thanks for the suggestion!
icon:setDebounce(0.5) -- defaults to 0
Thanks for the help! Really appreciated!
Very nice script. I tried struggling at beginning creating topbar and always had scaling issues.
I got one question, i’m having issues with the icons. No errors in log. I used a valid asset id.
local weather = Icon.new()
weather:setRight()
weather:setOrder(4)
weather:lock()
weather:setImage(7041056258)
Try 7041056248
(its assetId) instead of 7041056258
(the websiteId)
I really like this asset, I use on my personal projects and it’s pretty well made.
The only thing that I found kind of sad is that the syntax for Signals and things like that, could’ve been in PascalCase, just like Roblox events, so everyone’s code has similar syntax everywhere, and so that this, is consistent with Roblox naming and everything.
That is personal preference of course, and it’s not like this will change, not on this version, there’s no reason to, and would be worse, but if there was ever a v3 in the future, I feel like that could be something that could change if the team agrees on it.
For Instance, look at the difference here:
local function ToggleMenu()
--\\ Pretend this handles menus with TweenService
end
--// camelCase:
Icon.new()
:setCaption("Settings")
:setLabel(123)
:setOrder(2)
.toggled:Connect(ToggleMenu)
--// PascalCase:
Icon.new()
:SetCaption("Settings")
:SetLabel(123)
:SetOrder(2)
.Toggled:Connect(ToggleMenu)
Other than that, I think something that could help me move away from :bindToggleItem
to .toggled
and mess with menus with TweenService, would be that .toggled
is fired with (isToggled, icon)
instead of (isToggled)
only. That’s a change that wouldn’t break any code I believe. Correct me if I’m wrong though.
So you can have one function to handle all menus using less memory. I would love that!
TopbarPlus aims to follow the official Roblox Lua Styling guide which you can find here:
https://roblox.github.io/lua-style-guide/
Having a consistent formatting makes working with other open source modules/dependencies easier for everyone involved, hence most use camelCase. One notable project which doesn’t is AeroGameFramework, although this has created extra work for Sleitnick as it’s required him to convert modules like Evaera’s Promisie and various Nevemore modules (all camelCase) into PascalCase.
You’re welcome to create a fork which converts them into PascalCase although this won’t be something we maintain.
The toggled event only passes through a single argument, could you clarify what you mean by this?
By this I mean, that you would pass through self.isSelected, self
instead of just self.isSelected
.
That would mean I wouldn’t have to create a bunch of “intermediate” functions.
--\\ Here, .toggled fires with (isToggled)
local function SmoothToggleMenu(isToggled, icon)
--\\ Pretend this uses TweenService to close and open menus.
end
local icon = Icon.new()
:setCaption("Settings")
:setLabel(123)
:setOrder(1)
icon.toggled:Connect(function(isToggled)
SmoothToggleMenu(isToggled, icon)
--\\ Need to construct and connect a new function for every icon.
end)
And instead, I can just do this:
--\\ Here, .toggled fires with (isToggled, icon)
local function SmoothToggleMenu(isToggled, icon)
--\\ Pretend this uses TweenService to close and open menus.
end
Icon.new()
:setCaption("Settings")
:setLabel(123)
:setOrder(1)
.toggled:Connect(SmoothToggleMenu)
--\\ No need for constructing a new small function for every icon.
I suppose the memory use for just creating a function which calls another function with some extra arguments isn’t that big, but it’s also a question of syntax, I don’t need to set the icon to a variable, to THEN connect it.
That would make that way better organized and easier to handle.
Ah gotcha, bindEvent does exactly this!
(It passes through (icon, ...)
)
local function SmoothToggleMenu(icon, isToggled)
--\\ Pretend this uses TweenService to close and open menus.
end
Icon.new()
:setCaption("Settings")
:setLabel(123)
:setOrder(1)
:bindEvent("toggled", SmoothToggleMenu)
Im getting an issue when a user resets after using the TopBarGui one time…
It says this after trying to open it after respawn -
I don’t understand one bit.
Here’s my layout -
It looks like you’re referencing UI objects which get destroyed because your GUIs have ResetOnSpawn set to false.
Two solutions:
1.Set ‘ResetOnSpawn’ to false
for the GUIs you use with your icons
2. Move the localscript within the GUI and paste the following at the bottom:
local icons = IconController.getIcons()
for _, icon in pairs(icons) do
IconController.clearIconOnSpawn(icon)
end