[Plugin] AutoScale Lite for GUIs - Scale your UI

I just learned about that, but I’m not sure if I should use them or not, since it doesn’t seem like it’s going to be much more efficient or easy.

This currently works quite well for me, but it’s not really the most efficient; around 1% script usage for me when vigorously changing the resolution, and that’s with only 2 text label groups, but I think it should be OK since a small performance hit can generally be ignored when you’re resizing your game for half a second.

Would appreciate thoughts on if there’s a better way to do this though

Example place Smart Text Scaler.rbxl (20.2 KB)

Module modelSmartTextScaler.rbxm (2.8 KB)

Text scaling with module (updates with resolution):

Regular TextScaled:

Here is the module;

   --[[
	SmartTextHandler module by Bobby_Darin
	
	This simulates the TextScaled property for TextButtons and TextLabels,
	but allows you to set a "group" of TextButtons and TextLabels
	which will all scale to the same size (the largest size possible,
	without any one member of the group having a text size too big for
	their gui object).
	
	By default, the TextSize will update every time the game resolution
	is changed by the player.
	
	This works by finding the longest TextLabel/TextButton of the group,
	and then finding the largest possible text size for this TextObject
	(without the text escaping the bounds of the gui container),
	and then setting all the TextObjects in the group to that size.
	
	To use, Module:NewGroup(object : table)
	
	The object dictionary argument should consist of;
	
		Required properties
	
			array TextObjects : all TextLabels and TextButtons in the same 
			"group," which will all maintain the same text size whenever
			the resolution is changed.
	
		Optional properties
		
			bool OnlyUpdateWhenVisible (false)
				When the game resolution is changed, the text group
				size will only update if at least one member of
				TextObjects is visible.
				
			bool UpdateWhenMadeVisible (false)
				Update the text group size whenever a member of 
				TextObjects is made visible, in addition to
				whenever the resolution is changed
		
			int MinTextSize (1)
			int MaxTextSize(1)
			
			Vector2 TextBorderSize (2, 2)
			number SizeModifier (0.95)
			
			
	Example usage:
	
	----
	Module:NewGroup{
		TextObjects = {
			TextLabel1,
			TextLabel2,
			TextButton1
		},
		
		MaxTextSize = 50,
	}
	----
	
	TextLabel1, TextLabel2, and TextButton1 will now be automatically scaled,
	and all maintain the same text size too.
	
--]]

------------------------------------------

local SmartTextHandler = {}

local text_service = game:GetService("TextService")
local GetTextSize = text_service.GetTextSize

------------------------------------------
-- Methods

function SmartTextHandler:NewGroup(object)
	if not object then
		return
	end
	
	if not object.TextObjects then
		return
	end
	
	setmetatable(object, self)
	self.__index = self
	
	object.MinTextSize = object.MinTextSize or 1
	object.MaxTextSize = object.MaxTextSize or 100
	
	object.TextBorderSize = object.TextBorderSize or Vector2.new(2, 2)
	object.SizeModifier = object.SizeModifier or 0.95

	object:Update()
	
	if object.UpdateWhenMadeVisible then
		for k,text_object in next, object.TextObjects do
			text_object.Changed:connect(function(property)
				if property ~= "Visible" or not text_object.Visible then
					return
				end
				object:Update()
			end)
		end
	end
	
	workspace.CurrentCamera.Changed:connect(function(property)
		if property ~= "ViewportSize" then
			return
		end
		
		-- property == "ViewportSize"
		if not object.OnlyUpdateWhenVisible then
			object:Update()
			return
		end
		
		-- object.OnlyUpdateWhenVisible == true
		for k,text_object in next, object.TextObjects do
			if text_object.Visible then
				-- a TextObject is visible, so update the group
				object:Update()
				return
			end
		end
	end)
	
	return object
end

function SmartTextHandler:GetLongestTextObject()
	local longest_object = nil
	local longest_object_str_length = 0
	
	for k,text_object in next, self.TextObjects do
		if #text_object.Text > longest_object_str_length then
			longest_object = text_object
			longest_object_str_length = #text_object.Text
		end
	end
	
	return longest_object
end

function SmartTextHandler:Update()
	local best_size = 0

	-- Text sizing is based off of the TextObject with
	-- the most characters, as this object will have a lower possible 
	-- font size than the rest of the group
	
	local longest_object = self:GetLongestTextObject()
	local text = longest_object.Text
	local font = longest_object.Font
	
	local bounds = (longest_object.AbsoluteSize - self.TextBorderSize) * self.SizeModifier
	local wrap_size = Vector2.new(bounds.X, 1e4)
	
	for font_size = self.MinTextSize + 1, self.MaxTextSize + 1 do
		local text_size = GetTextSize(
			text_service, 
			text,
			font_size,
			font,
			wrap_size
		)
		
		if text_size.X >= bounds.X or text_size.Y >= bounds.Y then
			best_size = font_size - 1
			break
		end
	end
		
	for k,text_object in next, self.TextObjects do
		text_object.TextScaled = false
		text_object.TextWrapped = true
		text_object.TextSize = best_size
	end
	
	if self.OnUpdate then
		self:OnUpdate()
	end
end

return SmartTextHandler
16 Likes

Putting a UITextSizeConstraint inside of a text label seem sway easier than this. It’s probably more efficient since it’s built-in.

Don’t know for sure though. If that works for you I wouldn’t change.

2 Likes

I think a UITextSizeConstraint would only be useful for the minimum and maximum text sizes though, which I normally leave to default (1, and 100 respectively, which are the min/max that ROBLOX enforces),

since I’m re-calculating and setting a new text size every time the resolution is changed anyway.

It would be better I think if the TextLabels/TextButtons had a static size (i.e. using offset and not scale), then you’d just have to configure UITextSizeConstraint or set the TextSizes once, and it wouldn’t need to change, but that’s a little pointless since if you’re using static offset size, you might as well just set the text size manually since it doesn’t need to change.

3 Likes

You can accomplish that with the constraints too though. Just make the MinSize and MaxSize the same.

3 Likes

I’m super confused right now, are MinTextSize/Max in pixels --as in text bounds-- or in pixels as in font size? I think it’s the latter?

Bookmarked this for future use.

Very nice plug-in keep up the great work.

5 Likes

Me being a learning developer this has really helped me out.

4 Likes

This is so useful, easy to use. Made my life a whole much easier using this plugin. I’d highly recommend this to developers with little to no experience with GUI scaling and offset :slight_smile: It is much better than the other plugins that do the same thing.

7 Likes

Awesome plugin, thanks so much! I find it very useful.

1 Like

This will save a lot of my time. Good job!

2 Likes

I’ve been using this a ton for the aspect ratio constraint. Thanks :slight_smile:

However, I wanted to use the offset to scale feature recently and noticed it doesn’t work if you have say the x value as a scale value and the y value as an offset value. It just assumes it’s already in scale format.

Also, converting an offset value in a scrolling frame to a scale value does not give the same size the offset value was.

2 Likes

This is super useful, thank you so much! I was looking for a tool exactly like this! :smile:

2 Likes

Why would you have one parameter as offset and the other as scale?

And I’ll check out the scrolling frame thing

1 Like

Updated the plugin!

-Added new unloading event cleanup
-AutoScale button renamed to AutoConvert (important)
-Working on more features

2 Likes

Example: Make a frame, then you make a list of items in the frame. If it’s a verticle list, you scale the x axis to the parent frame, then make a y value for each item in the list.

Or… you could just use a UIListLayout constrant

1 Like

I am…

I originally had the y value has a offset value.

6 Likes

I see, let me try and fix this today.

3 Likes

Really nice. I made a plugin like this last year, which I’ve used since. I tested this out and I must say it’s really nice, honestly don’t know if I should use your plugin or not :eyes:

3 Likes

I spent today investigating the issue. The plugin doesn’t seem to be able to convert ui elements with one scale and one offset. I tried some fixes but a lot of them required a rework of my script and I’m not sure how to calculate the size if both scale and offset is used at the same time (for example X uses scale and offset size). I’ll try to figure out a solution, any idea?

(I’ll rewrite my code later to fix the one scale and one offset issue)

1 Like