This is my first module post on here, so I hope you take the time to read it!
Picture this:
You’re working on a Roblox game. You need icons. Don’t have any? Simple! Just plug in this module into your game, and just like that, you have high quality, crisp, and clean icons you can use in your game!
Features
Create icons by name with one line of code
Automatically sets image size, offset, and pixelated resampling
Switch icons dynamically at runtime
Comes with a full list of supported icon names under the module as README
How to Use
1. Require the module
local SilkIcon = require(path_to_SilkIconModule)
2. Create a new icon image
local icon = SilkIcon.Get("add")
icon.Parent = someGuiParent
3. Change the icon
SilkIcon.ApplyTo(icon, "delete")
Icon List
You can find the full list of available icons inside the module in the "README" script (or in the index file). This list contains all the icon names you can use with SilkIcon.new() or SetIcon() methods.
Example
repeat task.wait() until game:IsLoaded()
local IconService = require(game:GetService("ReplicatedStorage").Modules.SilkIcon)
local iconIndex = require(game:GetService("ReplicatedStorage").Modules.SilkIcon.index)
local screenGui = script.Parent
local iconsPerRow = 32
local padding = 0
local xPos, yPos, maxHeightInRow, count = 0, 0, 0, 0
for iconName, iconData in pairs(iconIndex.icons) do
local icon = IconService.Get(iconName)
icon.Position = UDim2.new(0, xPos, 0, yPos)
icon.AnchorPoint = Vector2.new(0, 0)
icon.Parent = screenGui
local width = iconData.imagerectsize[1]
local height = iconData.imagerectsize[2]
xPos += width + padding
maxHeightInRow = math.max(maxHeightInRow, height)
count += 1
if count % iconsPerRow == 0 then
xPos = 0
yPos += maxHeightInRow + padding
maxHeightInRow = 0
end
end
Installation and Usage
Drop the module into your project
Require it
Use the icon names from the README to create icons
If you want a good and clean way to add icons to your UI, give it a try! Feel free to ask questions or suggest improvements.
Here’s a functional version of this module that doesn’t use OOP because it is massively unnecessary in this case (replace the main module code with this):
--[[
A simple, functional module for creating and managing icon ImageLabels from a spritesheet.
This version includes optimizations to prevent redundant property setting and to
improve code readability by caching values.
]]
local IconService = {}
-- Load the icon data from the index file. This is done only once when the module is required.
local iconIndex = require(script.index)
-- A constant for the attribute name to ensure consistency.
local ICON_ATTRIBUTE_NAME = "IconName"
-- Type definition for the data expected for a single icon in the index.
type IconData = {
imagerectoffset: {number},
imagerectsize: {number},
}
--[[
Creates and returns a new ImageLabel configured with the specified icon.
@param iconName The name of the icon to create.
@return A new ImageLabel instance with the icon applied.
@error If the icon does not exist in the index.
]]
function IconService.Get(iconName: string): ImageLabel
local iconData: IconData = iconIndex.icons[iconName]
if not iconData then
error("IconService: Icon '" .. iconName .. "' does not exist.", 2)
end
local imageLabel = Instance.new("ImageLabel")
-- Configure the ImageLabel with shared properties
imageLabel.Image = iconIndex.image
imageLabel.ResampleMode = Enum.ResamplerMode.Pixelated
imageLabel.BackgroundTransparency = 1
-- Apply the specific icon's properties using the ApplyTo function to avoid code duplication.
-- The redundancy check inside ApplyTo is not strictly needed here since it's a new instance,
-- but this keeps the logic centralized and clean.
IconService.ApplyTo(imageLabel, iconName)
return imageLabel
end
--[[
Applies an icon's properties to an existing ImageLabel.
This is optimized to do nothing if the requested icon is already applied.
@param targetLabel The ImageLabel instance to modify.
@param iconName The name of the icon to apply.
@error If the icon does not exist in the index.
]]
function IconService.ApplyTo(targetLabel: ImageLabel, iconName: string)
-- Optimization: Check the instance's attribute to see if the icon is already set.
-- If it is, we can skip all the work.
if targetLabel:GetAttribute(ICON_ATTRIBUTE_NAME) == iconName then
return
end
local iconData: IconData = iconIndex.icons[iconName]
if not iconData then
error("IconService: Icon '" .. iconName .. "' does not exist.", 2)
end
-- Optimization: Cache the table values in local variables.
-- This avoids repeated lookups (e.g., `iconData.imagerectsize`) and is slightly faster.
local rectOffset = iconData.imagerectoffset
local rectSize = iconData.imagerectsize
-- Note: We only update properties that are specific to the icon.
-- Shared properties like Image and ResampleMode are assumed to be set on creation.
targetLabel.Size = UDim2.fromOffset(rectSize[1], rectSize[2])
targetLabel.ImageRectOffset = Vector2.new(rectOffset[1], rectOffset[2])
targetLabel.ImageRectSize = Vector2.new(rectSize[1], rectSize[2])
-- Store the current icon name in an attribute on the instance for the next check.
targetLabel:SetAttribute(ICON_ATTRIBUTE_NAME, iconName)
end
return IconService
Old usage:
local iconObject = SilkIcon.new("keyboard")
local keyboardIcon = iconObject:GetInstance()
keyboardIcon.Parent = someFrame
New usage:
local keyboardIcon = IconService.Get("keyboard")
keyboardIcon.Parent = someFrame
Hi, I noticed some issues with your “functional version” that I think could have been improved on.
For the Get() and ApplyTo() methods, you could have put the imagerectsize and imagerectoffset values into variables, as that would have saved redundant calls.
You could have stored the current icon name, so if the player tries to set it again to the same icon, it could catch that and prevent unnecessary changes, optimizing it.
I see that the OOP approach I took was unnecessary, however your case could be optimized aswell.
I don’t mind at all. And here is an updated version of the module to take those issues into account:
--[[
A simple, functional module for creating and managing icon ImageLabels from a spritesheet.
This version includes optimizations to prevent redundant property setting and to
improve code readability by caching values.
]]
local IconService = {}
-- Load the icon data from the index file. This is done only once when the module is required.
local iconIndex = require(script.index)
-- A constant for the attribute name to ensure consistency.
local ICON_ATTRIBUTE_NAME = "IconName"
-- Type definition for the data expected for a single icon in the index.
type IconData = {
imagerectoffset: {number},
imagerectsize: {number},
}
--[[
Creates and returns a new ImageLabel configured with the specified icon.
@param iconName The name of the icon to create.
@return A new ImageLabel instance with the icon applied.
@error If the icon does not exist in the index.
]]
function IconService.Get(iconName: string): ImageLabel
local iconData: IconData = iconIndex.icons[iconName]
if not iconData then
error("IconService: Icon '" .. iconName .. "' does not exist.", 2)
end
local imageLabel = Instance.new("ImageLabel")
-- Configure the ImageLabel with shared properties
imageLabel.Image = iconIndex.image
imageLabel.ResampleMode = Enum.ResamplerMode.Pixelated
imageLabel.BackgroundTransparency = 1
-- Apply the specific icon's properties using the ApplyTo function to avoid code duplication.
-- The redundancy check inside ApplyTo is not strictly needed here since it's a new instance,
-- but this keeps the logic centralized and clean.
IconService.ApplyTo(imageLabel, iconName)
return imageLabel
end
--[[
Applies an icon's properties to an existing ImageLabel.
This is optimized to do nothing if the requested icon is already applied.
@param targetLabel The ImageLabel instance to modify.
@param iconName The name of the icon to apply.
@error If the icon does not exist in the index.
]]
function IconService.ApplyTo(targetLabel: ImageLabel, iconName: string)
-- Optimization: Check the instance's attribute to see if the icon is already set.
-- If it is, we can skip all the work.
if targetLabel:GetAttribute(ICON_ATTRIBUTE_NAME) == iconName then
return
end
local iconData: IconData = iconIndex.icons[iconName]
if not iconData then
error("IconService: Icon '" .. iconName .. "' does not exist.", 2)
end
-- Optimization: Cache the table values in local variables.
-- This avoids repeated lookups (e.g., `iconData.imagerectsize`) and is slightly faster.
local rectOffset = iconData.imagerectoffset
local rectSize = iconData.imagerectsize
-- Note: We only update properties that are specific to the icon.
-- Shared properties like Image and ResampleMode are assumed to be set on creation.
targetLabel.Size = UDim2.fromOffset(rectSize[1], rectSize[2])
targetLabel.ImageRectOffset = Vector2.new(rectOffset[1], rectOffset[2])
targetLabel.ImageRectSize = Vector2.new(rectSize[1], rectSize[2])
-- Store the current icon name in an attribute on the instance for the next check.
targetLabel:SetAttribute(ICON_ATTRIBUTE_NAME, iconName)
end
return IconService
Also by functional I wasn’t saying that your implementation doesn’t work whereas mine does, just meant that this works purely off functions without any OOP.