How is the size of the chat decided?

Hello everyone !

Title says it all, I tried to play the game with different device (phone/tablet/computer) and I noticed that the size of the chat isn’t constant (its neither a constant Udim2.new(XValue1, 0, YValue1, 0) or Udim2.new(XValue2, 0, YValue2, 0)).

The XValue1 and YValue1 changes depending the screen size i guess ? I tried searching the net but didn’t found a clear answer. Any idea on how it works ?

Thank for reading :slight_smile:

2 Likes

You can use StarterGui:GetCore() to get information about the CoreGUI, including the chat. The page that that link goes to says this when you scroll down:

Given that, we can find out the size of the chat window:

local size = game.StarterGui:GetCore("ChatWindowSize") --UDim2

frame.Size  = size

Hopefully, I answered your question.

4 Likes

This doesn’t really solve my question which was how do they calculate the size in fonction of the screen. But I think this can help me in what I want to achieve !

I’ll leave the post unsolved a bit longer to see if anyone knows how it works, and if no one has an answer then i’ll put your post as the answer :slight_smile:

1 Like

Okay so after a lot of ctrl f and trying to understand the 50+ module script of the chat, I found what I needed. I found 2 modules (ChatSettings and ChatWindow) with stuff related to the size of the chat window, to get them play the game and go look in the chat section.
Capture1 Capture2

So there it is, put this in a module and the print at the end will give you the size the chat should be ! It will also update if you change the size of your game. There still might be some useless stuff in this code and i’ll try to make it cleaner. But just know that the last print gives the right size !

module.MinimumWindowSize = UDim2.new(0.3, 0, 0.25, 0)
module.MaximumWindowSize = UDim2.new(1, 0, 1, 0) -- if you change this to be greater than full screen size, weird things start to happen with size/position bounds checking.
module.DefaultWindowPosition = UDim2.new(0, 0, 0, 0)
local extraOffset = (7 * 2) + (5 * 2) -- Extra chatbar vertical offset
module.DefaultWindowSizePhone = UDim2.new(0.5, 0, 0.5, extraOffset)
module.DefaultWindowSizeTablet = UDim2.new(0.4, 0, 0.3, extraOffset)
module.DefaultWindowSizeDesktop = UDim2.new(0.3, 0, 0.25, extraOffset)

module.ChatWindowTextSize = 18
module.ChatChannelsTabTextSize = 18
module.ChatBarTextSize = 18
module.ChatWindowTextSizePhone = 14
module.ChatChannelsTabTextSizePhone = 18
module.ChatBarTextSizePhone = 14

module.WindowDraggable = false
module.WindowResizable = false
module.ShowChannelsBar = false

local FFlagFixMouseCapture = false do
	local ok, value = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserFixMouseCapture")
	end)
	if ok then
		FFlagFixMouseCapture = value
	end
end

local PHONE_SCREEN_WIDTH = 640
local TABLET_SCREEN_WIDTH = 1024

local DEVICE_PHONE = 1
local DEVICE_TABLET = 2
local DEVICE_DESKTOP = 3

local TestGui = Instance.new("ScreenGui")
TestGui.Parent = playerGui

local BaseFrame = Instance.new("Frame")
BaseFrame.BackgroundTransparency = 1
BaseFrame.Active = module.WindowDraggable
BaseFrame.Parent = TestGui
BaseFrame.AutoLocalize = false

local ChatBarParentFrame = Instance.new("Frame")
ChatBarParentFrame.Selectable = false
ChatBarParentFrame.Name = "ChatBarParentFrame"
ChatBarParentFrame.BackgroundTransparency = 1
ChatBarParentFrame.Parent = BaseFrame

local ChannelsBarParentFrame = Instance.new("Frame")
ChannelsBarParentFrame.Selectable = false
ChannelsBarParentFrame.Name = "ChannelsBarParentFrame"
ChannelsBarParentFrame.BackgroundTransparency = 1
ChannelsBarParentFrame.Position = UDim2.new(0, 0, 0, 0)
ChannelsBarParentFrame.Parent = BaseFrame

local ChatChannelParentFrame = Instance.new("Frame")
ChatChannelParentFrame.Selectable = false
ChatChannelParentFrame.Name = "ChatChannelParentFrame"
ChatChannelParentFrame.BackgroundTransparency = 1
ChatChannelParentFrame.BackgroundTransparency = 0.6
ChatChannelParentFrame.BorderSizePixel = 0
ChatChannelParentFrame.Parent = BaseFrame

local function GetScreenGuiParent()
    --// Travel up parent list until you find the ScreenGui that the chat window is parented to
    local screenGuiParent = BaseFrame
    while (screenGuiParent and not screenGuiParent:IsA("ScreenGui")) do
        screenGuiParent = screenGuiParent.Parent
    end

    return screenGuiParent
end


local deviceType = DEVICE_DESKTOP

local screenGuiParent = GetScreenGuiParent()
if (screenGuiParent.AbsoluteSize.X <= PHONE_SCREEN_WIDTH) then
    deviceType = DEVICE_PHONE

elseif (screenGuiParent.AbsoluteSize.X <= TABLET_SCREEN_WIDTH) then
    deviceType = DEVICE_TABLET

end

local checkSizeLock = false
local function doCheckSizeBounds()
    if (checkSizeLock) then return end
    checkSizeLock = true

    if (not BaseFrame:IsDescendantOf(playerGui)) then return end

    local screenGuiParent = GetScreenGuiParent()

    local minWinSize = module.MinimumWindowSize
    local maxWinSize = module.MaximumWindowSize

    local forceMinY = ChannelsBarParentFrame.AbsoluteSize.Y + ChatBarParentFrame.AbsoluteSize.Y

    local minSizePixelX = (minWinSize.X.Scale * screenGuiParent.AbsoluteSize.X) + minWinSize.X.Offset
    local minSizePixelY = math.max((minWinSize.Y.Scale * screenGuiParent.AbsoluteSize.Y) + minWinSize.Y.Offset, forceMinY)

    local maxSizePixelX = (maxWinSize.X.Scale * screenGuiParent.AbsoluteSize.X) + maxWinSize.X.Offset
    local maxSizePixelY = (maxWinSize.Y.Scale * screenGuiParent.AbsoluteSize.Y) + maxWinSize.Y.Offset

    local absSizeX = BaseFrame.AbsoluteSize.X
    local absSizeY = BaseFrame.AbsoluteSize.Y

    if (absSizeX < minSizePixelX) then
        local offset = UDim2.new(0, minSizePixelX - absSizeX, 0, 0)
        BaseFrame.Size = BaseFrame.Size + offset

    elseif (absSizeX > maxSizePixelX) then
        local offset = UDim2.new(0, maxSizePixelX - absSizeX, 0, 0)
        BaseFrame.Size = BaseFrame.Size + offset

    end

    if (absSizeY < minSizePixelY) then
        local offset = UDim2.new(0, 0, 0, minSizePixelY - absSizeY)
        BaseFrame.Size = BaseFrame.Size + offset

    elseif (absSizeY > maxSizePixelY) then
        local offset = UDim2.new(0, 0, 0, maxSizePixelY - absSizeY)
        BaseFrame.Size = BaseFrame.Size + offset

    end

    local xScale = BaseFrame.AbsoluteSize.X / screenGuiParent.AbsoluteSize.X
    local yScale = BaseFrame.AbsoluteSize.Y / screenGuiParent.AbsoluteSize.Y
    
    -- cap chat window scale at a value smaller than 0.5 to prevent center of screen overlap
    if FFlagFixMouseCapture then 
        xScale = math.min(xScale, 0.45)
        yScale = math.min(xScale, 0.45)
    end
    
    BaseFrame.Size = UDim2.new(xScale, 0, yScale, 0)

    checkSizeLock = false
end


BaseFrame.Changed:connect(function(prop)
    if (prop == "AbsoluteSize") then
        doCheckSizeBounds()
    end
end)


local function CalculateChannelsBarPixelSize(textSize)
    if (deviceType == DEVICE_PHONE) then
        textSize = textSize or module.ChatChannelsTabTextSizePhone
    else
        textSize = textSize or module.ChatChannelsTabTextSize
    end

    local channelsBarTextYSize = textSize
    local chatChannelYSize = math.max(32, channelsBarTextYSize + 8) + 2

    return chatChannelYSize
end

local function CalculateChatBarPixelSize(textSize)
    if (deviceType == DEVICE_PHONE) then
        textSize = textSize or module.ChatBarTextSizePhone
    else
        textSize = textSize or module.ChatBarTextSize
    end

    local chatBarTextSizeY = textSize
    local chatBarYSize = chatBarTextSizeY + (7 * 2) + (5 * 2)

    return chatBarYSize
end

local screenGuiParent = GetScreenGuiParent()

if (deviceType == DEVICE_PHONE) then
    BaseFrame.Size = module.DefaultWindowSizePhone

elseif (deviceType == DEVICE_TABLET) then
    BaseFrame.Size = module.DefaultWindowSizeTablet

else
    BaseFrame.Size = module.DefaultWindowSizeDesktop

end

BaseFrame.Position = module.DefaultWindowPosition

if (deviceType == DEVICE_PHONE) then
    module.ChatWindowTextSize = module.ChatWindowTextSizePhone
    module.ChatChannelsTabTextSize = module.ChatChannelsTabTextSizePhone
    module.ChatBarTextSize = module.ChatBarTextSizePhone
end


local function UpdateResizable(enabled)

    local frameSizeY = ChatBarParentFrame.Size.Y.Offset

    if (enabled) then
        ChatBarParentFrame.Size = UDim2.new(1, -frameSizeY - 2, 0, frameSizeY)
        ChatBarParentFrame.Position = UDim2.new(0, 0, 1, -frameSizeY)
    else
        ChatBarParentFrame.Size = UDim2.new(1, 0, 0, frameSizeY)
        ChatBarParentFrame.Position = UDim2.new(0, 0, 1, -frameSizeY)
    end
end

local function UpdateChatChannelParentFrameSize()
    local channelsBarSize = CalculateChannelsBarPixelSize()
    local chatBarSize = CalculateChatBarPixelSize()

    if (module.ShowChannelsBar) then
        ChatChannelParentFrame.Size = UDim2.new(1, 0, 1, -(channelsBarSize + chatBarSize + 2 + 2))
        ChatChannelParentFrame.Position = UDim2.new(0, 0, 0, channelsBarSize + 2)

    else
        ChatChannelParentFrame.Size = UDim2.new(1, 0, 1, -(chatBarSize + 2 + 2))
        ChatChannelParentFrame.Position = UDim2.new(0, 0, 0, 2)

    end
end

local function UpdateChatChannelsTabTextSize(size)
    local channelsBarSize = CalculateChannelsBarPixelSize(size)
    ChannelsBarParentFrame.Size = UDim2.new(1, 0, 0, channelsBarSize)

    UpdateChatChannelParentFrameSize()
end

local function UpdateChatBarTextSize(size)
    local chatBarSize = CalculateChatBarPixelSize(size)

    ChatBarParentFrame.Size = UDim2.new(1, 0, 0, chatBarSize)
    ChatBarParentFrame.Position = UDim2.new(0, 0, 1, -chatBarSize)

    UpdateChatChannelParentFrameSize()
    UpdateResizable(module.WindowResizable)
end

local function UpdateShowChannelsBar(enabled)
    ChannelsBarParentFrame.Visible = enabled
    UpdateChatChannelParentFrameSize()
end

UpdateChatChannelsTabTextSize(module.ChatChannelsTabTextSize)
UpdateChatBarTextSize(module.ChatBarTextSize)
UpdateResizable(module.WindowResizable)
UpdateShowChannelsBar(module.ShowChannelsBar)

doCheckSizeBounds()

print(BaseFrame.Size)

With those lines of code, you can get the size of the chat without using GetCore. This would allow you, if you want to create your own chat, to get the same size of the real one.
Problem with using GetCore is you can’t do it right off the bat, because it’d return nil.

Hope it helps whoever read this and need this !

2 Likes

I have been working on the code, here is the final result (last print is the size of the chat when you join the game) :

local Player = game.Players.LocalPlayer
local playerGui = Player.PlayerGui

local MinimumWindowSize = UDim2.new(0.3, 0, 0.25, 0) --
local MaximumWindowSize = UDim2.new(1, 0, 1, 0) --

local DefaultWindowSizePhone = UDim2.new(0.5, 0, 0.5, 24)
local DefaultWindowSizeTablet = UDim2.new(0.4, 0, 0.3, 24)
local DefaultWindowSizeDesktop = UDim2.new(0.3, 0, 0.25, 24)

local FFlagFixMouseCapture = false do
	local ok, value = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserFixMouseCapture")
	end)
	if ok then
		FFlagFixMouseCapture = value
	end
end

local PHONE_SCREEN_WIDTH = 640 --
local TABLET_SCREEN_WIDTH = 1024 --

local DEVICE_PHONE = 1 --
local DEVICE_TABLET = 2 --
local DEVICE_DESKTOP = 3 --

local TestGui = Instance.new("ScreenGui") --
TestGui.Parent = playerGui
TestGui.Enabled = false
TestGui.Name = "ChatSize"

local BaseFrame = Instance.new("Frame") --
BaseFrame.BackgroundTransparency = 1
BaseFrame.Parent = TestGui

local ChatBarParentFrame = Instance.new("Frame")
ChatBarParentFrame.BackgroundTransparency = 1
ChatBarParentFrame.Parent = BaseFrame

ChatBarParentFrame.Size = UDim2.new(1, 0, 0, 42)

local deviceType = DEVICE_DESKTOP

if (TestGui.AbsoluteSize.X <= PHONE_SCREEN_WIDTH) then
    deviceType = DEVICE_PHONE
elseif (TestGui.AbsoluteSize.X <= TABLET_SCREEN_WIDTH) then
    deviceType = DEVICE_TABLET
end

local checkSizeLock = false
local function doCheckSizeBounds()
    if (checkSizeLock) then return end
    checkSizeLock = true

    local minWinSize = MinimumWindowSize
    local maxWinSize = MaximumWindowSize

    local forceMinY = ChatBarParentFrame.AbsoluteSize.Y

    local minSizePixelX = (minWinSize.X.Scale * TestGui.AbsoluteSize.X) + minWinSize.X.Offset
    local minSizePixelY = math.max((minWinSize.Y.Scale * TestGui.AbsoluteSize.Y) + minWinSize.Y.Offset, forceMinY)

    local maxSizePixelX = (maxWinSize.X.Scale * TestGui.AbsoluteSize.X) + maxWinSize.X.Offset
    local maxSizePixelY = (maxWinSize.Y.Scale * TestGui.AbsoluteSize.Y) + maxWinSize.Y.Offset

    local absSizeX = BaseFrame.AbsoluteSize.X
    local absSizeY = BaseFrame.AbsoluteSize.Y

    if (absSizeX < minSizePixelX) then
        local offset = UDim2.new(0, minSizePixelX - absSizeX, 0, 0)
        BaseFrame.Size = BaseFrame.Size + offset

    elseif (absSizeX > maxSizePixelX) then
        local offset = UDim2.new(0, maxSizePixelX - absSizeX, 0, 0)
        BaseFrame.Size = BaseFrame.Size + offset

    end

    if (absSizeY < minSizePixelY) then
        local offset = UDim2.new(0, 0, 0, minSizePixelY - absSizeY)
        BaseFrame.Size = BaseFrame.Size + offset

    elseif (absSizeY > maxSizePixelY) then
        local offset = UDim2.new(0, 0, 0, maxSizePixelY - absSizeY)
        BaseFrame.Size = BaseFrame.Size + offset

    end

    local xScale = BaseFrame.AbsoluteSize.X / TestGui.AbsoluteSize.X
    local yScale = BaseFrame.AbsoluteSize.Y / TestGui.AbsoluteSize.Y
    
    -- cap chat window scale at a value smaller than 0.5 to prevent center of screen overlap
    if FFlagFixMouseCapture then 
        xScale = math.min(xScale, 0.45)
        yScale = math.min(xScale, 0.45)
    end
    
    BaseFrame.Size = UDim2.new(xScale, 0, yScale, 0)

    checkSizeLock = false
end


BaseFrame.Changed:connect(function(prop)
    if (prop == "AbsoluteSize") or (prop == "Size") then
        doCheckSizeBounds()
    end
end)


if (deviceType == DEVICE_PHONE) then
    BaseFrame.Size = DefaultWindowSizePhone
elseif (deviceType == DEVICE_TABLET) then
    BaseFrame.Size = DefaultWindowSizeTablet
else
    BaseFrame.Size = DefaultWindowSizeDesktop
end

print(BaseFrame.Size)
4 Likes