UITransparencyMod, to make scripting UI a tad easier

DISCLAIMER 2024-01-30T05:00:00Z

Its been brought to my attention that CanvasGroups are a thing and should be used instead. Only thing my module does in comparison is allow you to keep your setup exactly as it is currently rather than replacing certain Frames with CanvasGroups

UITransparencyModifier, to Modify entire UI Transparencys

  1. Why?

Well I, and many others like to layer my ui, a lot, with plenty of details, shadows and the like but coding each ui element takes way too much time, so i pieced this up its mainly for smoothly tweening entire frames and its descendants (if chosen) such as a shop frame or even a overhead health barThis text will be hidden

  1. What does it do?

Using TransparencyModifier:attach(GuiObject) on your ScreenGui or main Frame will loop through all of its descendants saving any Transparency value using SetAttribute (see below)

Anything not a Decal carrying any of these properties in your UI will be effected

;{‘TextTransparency’, ‘TextStrokeTransparency’, ‘ImageTransparency’, ‘BackgroundTransparency’, ‘ScrollBarImageTransparency’};

Having those original values, we can have a single 0 - 1 number as a 𝗠𝗢𝗗𝗜𝗙𝗜𝗘𝗥 for each property so when calling :adjust or :tween, all we have to do is grab the Main(GuiObject) iterate through descendants(if chosen) and add the 𝗠𝗢𝗗𝗜𝗙𝗜𝗘𝗥 to the original property value of any property that involves transparency

Using a Couple lines of code I can make smooth visual transitions for multiple ui with no issue, rather than coding each element


image
image

You can test out what you see here:
UITransparencyMod Example.rbxl (60.3 KB)

Extended FAQ inside the module itself
TransparencyMod.rbxm (6.9 KB)
OR https://create.roblox.com/store/asset/16180855913

Original Source Code

--  UITransparencyModifier by Savi_ooo (discord: totallynotegg)

local TransparencyModifier = {};
TransparencyModifier.Attached = {};
TransparencyModifier.Debug = true

local function Debug(Method, ...)
	local Tuple = {...};
	if TransparencyModifier.Debug then
		pcall(function()
			Method(unpack(Tuple))
		end)
	end
end

local function Tween(Object, Direction, Style, Time, Properties) -- using ROBLOX's Tween
	local S = type(Style) == 'string' and Enum.EasingStyle[Style] or Style
	local D = type(Direction) == 'string' and Enum.EasingDirection[Direction] or Direction

	local TweenService = game:GetService('TweenService')
	local TweenData = TweenInfo.new(Time, S, D, 0, false, 0)
	local Result = TweenService:Create(Object, TweenData, Properties)

	Result:Play()
	return Result
end

function TransparencyModifier:properties(Main: GuiObject)
	local Properties = {'TextTransparency', 'TextStrokeTransparency', 'ImageTransparency', 'BackgroundTransparency', 'ScrollBarImageTransparency'};
	local Return = nil;

	for Index, Property in next, Properties do
		local Success = pcall(function()
			Main[Property] = Main[Property]
		end)

		if Success then
			Return = Return or {};
			table.insert(Return, Property)
		end
	end return Return
end

function TransparencyModifier:layer(Main: GuiObject, Number: number)
	for Index, GuiObject in next, Main:GetDescendants() do
		if not GuiObject:IsA('Decal') then
			local Success = pcall(function()
				GuiObject.ZIndex = GuiObject.ZIndex
			end)

			if Success then
				pcall(function()
					GuiObject.ZIndex = GuiObject:GetAttribute('ZIndex') + ((Number - 1) * 20)
				end)
			end
		end
	end
end

function TransparencyModifier:adjust(Main: GuiObject, Modifier: number, DescendantsToo: boolean)
	local List = {Main};

	if not Modifier then
		Debug(error, 'Modifier Required for TransparencyModifier:tween()', 2)
		return
	end

	if DescendantsToo then
		for Index, GuiObject in next, TransparencyModifier.Attached do
			if GuiObject:IsDescendantOf(Main) then
				table.insert(List, GuiObject)
			end
		end
	end

	local function Match(GuiObject, ClassName)
		return GuiObject:IsA(ClassName)
	end

	for Index, GuiObject in next, List do
		local Properties = TransparencyModifier:properties(GuiObject)

		if Properties then
			for Index, Property in next, Properties do
				if GuiObject:GetAttribute(Property) then
					GuiObject[Property] = math.min(1, GuiObject:GetAttribute(Property) + Modifier)
				end
			end
		end
	end
end

function TransparencyModifier:tween(Main: GuiObject, TweenData: table, DescendantsToo: boolean)
	local List = {Main};
	local Modifier = TweenData.Modifier
	local Time = TweenData.Time or 1
	local Direction = TweenData.Direction or 'Out'
	local Style = TweenData.Style or 'Quad'
	
	if not Modifier then
		Debug(warn, 'Modifier Required for TransparencyModifier:tween:' .. (debug.traceback():match(':%d+'):sub(2)))
		return
	end

	if DescendantsToo then
		for Index, GuiObject in next, Main:GetDescendants() do
			if GuiObject:IsA('GuiObject') then
				if not GuiObject:IsA('Decal') then
					local Success = pcall(function()
						GuiObject.ZIndex = GuiObject.ZIndex
					end)

					if Success then
						pcall(function()
							table.insert(List, GuiObject)
						end)
					end
				end
			end
		end
	end

	for Index, GuiObject in next, List do
		local Properties = TransparencyModifier:properties(GuiObject)

		if Properties then
			for Index, Property in next, Properties do
				task.spawn(function()
					repeat task.wait() until GuiObject:GetAttribute(Property)
					local Success, Error = pcall(function()
						Tween(GuiObject, Direction, Style, Time, {
							[Property] = math.min(1, GuiObject:GetAttribute(Property) + Modifier)});
					end)

					if not Success then
						Debug(print, 'Callback:', GuiObject:GetFullName(), '>', Property)
						Debug(warn, Error)
					end
				end)
			end
		end
	end
end

function TransparencyModifier:attach(UI: GuiObject) -- preferably the entire ScreenGui
	local Models = {};

	for Index, GuiObject in next, UI:GetDescendants() do
		if not GuiObject:IsA('Decal') and not GuiObject:HasTag('TransparencyMod') then
			local Properties = TransparencyModifier:properties(GuiObject)

			if GuiObject:IsA('Model') then
				table.insert(Models, GuiObject)
			else
				if Properties then
					for Index, Property in next, Properties do
						GuiObject:SetAttribute(Property, GuiObject[Property])
						GuiObject:SetAttribute('ZIndex', GuiObject.ZIndex)
						table.insert(TransparencyModifier.Attached, GuiObject)
					end
				end
			end
		end GuiObject:AddTag('TransparencyMod')
	end 

	for Index, GuiObject in next, UI:GetDescendants() do
		if not GuiObject:HasTag('TransparencyMod') then
			repeat task.wait() until GuiObject:HasTag('TransparencyMod')
		end
	end return true
end return TransparencyModifier
5 Likes

Umm don’t Canvas Groups exist for this

1 Like

First time hearing of it :smiling_face_with_tear: but you’re right, im gonna end up using that instead. Thank you

1 Like

Rip to all that time making this module without realizing canvas groups exist.

2 Likes

canvas groups are incredibly wack on mobile, and less than performant when used overzealously; even on pc.

1 Like

This module still has practical use. As the above post points out, using too many canvas groups would cause a hit to performance on some devices; an issue this module wouldn’t have.

1 Like

Interesting, never heard of performant issues before on other devices

1 Like

And im pretty sure it makes images a bit less quality (At least from what I’ve experienced)

2 Likes

CanvasGroup forces ClipDescedants :C, only if i was able to make it change GroupTransparency…

This is where your script comes in handy :sob:

1 Like

Canvas groups exist but they have memory leaks therefore they aren’t good. But I have already made this module: Transparency Control Module - #8 by Crypt1lc

2 Likes

CanvasGroups work, but they become very blurry at lower graphics qualities, and on weaker devices. Something like this can still be useful!

1 Like