Quick actions

cmd+k|ctrl+k

Navigation

Languages

oxygen modules

Snippet info

Language

Lua

Visibility

public

Author

thosewhoknow

Created

2022-11-04T16:10:33.50125Z

Updated

2022-12-10T20:23:17.512395Z

-- This module displays a radial (circular) progress indicator based on images and config information
-- that is generated at https://eryn.io/RadialSpriteSheetGenerator/
-- @readme https://github.com/evaera/RadialSpriteSheetGenerator/blob/master/README.md
-- @author evaera

local HttpService = game:GetService("HttpService")
local ContentProvider = game:GetService("ContentProvider")

local RadialImage = { _version = 1 }
RadialImage.__index = RadialImage

local ConfigurationProperties = {
	version = "number";
	size = "number";
	count = "number";
	columns = "number";
	rows = "number";
	images = "table";
}

function RadialImage.new(config, label)
	if type(config) == "string" then
		config = HttpService:JSONDecode(config)
	elseif type(config) ~= "table" then
		error("Argument #1 (configuration) must be a JSON string or table.", 2)
	end

	for k, v in pairs(config) do
		if ConfigurationProperties[k] == nil then
			error(("Invalid property name in Radial Image configuration: %s"):format(k), 2)
		end

		if type(v) ~= ConfigurationProperties[k] then
			error(("Invalid property type %q in Radial Image configuration: must be a %s."):format(k, ConfigurationProperties[k]), 2)
		end
	end

	if config.version ~= RadialImage._version then
		error(("Passed configuration version does not match this module's version (which is %d)"):format(RadialImage._version), 2)
	end

	local self = { config = config; label = label }
	setmetatable(self, RadialImage)

	return self
end

function RadialImage:Preload()
	if self.label == nil then
		error("You must provide a label to RadialImage.new to use Preload", 2)
	end

	self.labels = {}

	for _, image in ipairs(self.config.images) do
		local label = self.label:Clone()
		label.Image = image
		label.Visible = true
		label.Size = UDim2.new(0, 0, 0, 0)
		label.Parent = self.label.Parent
		table.insert(self.labels, label)
	end

	ContentProvider:PreloadAsync(self.labels)

	for _, label in ipairs(self.labels) do
		label.Visible = false
	end
end

function RadialImage:Destroy()
	for _, label in ipairs(self.labels) do
		label:Destroy()
	end

	self.labels = nil
end

function RadialImage:GetFromAlpha(alpha)
	if type(alpha) ~= "number" then
		error("Argument #1 (alpha) to GetFromAlpha must be a number.", 2)
	end

	local count, size, columns, rows = self.config.count, self.config.size, self.config.columns, self.config.rows
	local index = alpha >= 1 and count - 1 or math.floor(alpha * count)
	local page = math.floor(index / (columns * rows)) + 1
	local pageIndex = index - (columns * rows * (page - 1))
	local x = (pageIndex % columns) * size
	local y = math.floor(pageIndex / columns) * size

	return x, y, page
end

function RadialImage:UpdateLabel(alpha, label)
	label = label or self.label

	if type(alpha) ~= "number" then
		error("Argument #1 (alpha) to UpdateLabel must be a number.", 2)
	end

	if typeof(label) ~= "Instance" or not (label:IsA("ImageLabel") or label:IsA("ImageButton")) then
		error("Attempt to update label but no label has been given. Either pass the label as argument #2 to \"new\", or as argument #2 to \"UpdateLabel\".", 2)
	end

	local x, y, page = self:GetFromAlpha(alpha)

	label.ImageRectSize = Vector2.new(self.config.size, self.config.size)
	label.ImageRectOffset = Vector2.new(x, y)
	label.Image = alpha <= 0 and "" or self.config.images[page]
end

return RadialImage
INFO