How do I make a GUI detect the touched color of another GUI?

What I want to do is for the GUI to know which color it’s touching, like in this image.

5 Likes

Capture d'écran 2024-02-11 120846

3 Likes

Heya @pageotkillian1! How are you doing?

To understand properly, you want to create a GUI that detects what color the player is touching, right?

If so, another question: Does the player need to touch a part so the GUI can detect and print the color value?

4 Likes

Is that even Roblox? How are you using Block Code?

2 Likes

What I meant was that if a Gui touches a specific color of another Gui

2 Likes

it’s not from roblox, it’s from scratch

1 Like

To Detect the GUIs the gui is touching, you can first get the corners of the ui ( ui.Rotation must be 0, ui must be GuiObject, you can’t detect touch of an image ( image label ) )

local function getCorners(ui:GuiObject)
local absp = ui.AbsolutePosition
local abss = ui.AbsoluteSize
local c1 = absp + (Vector2.new(abss.X,abss.Y)/2) -- bottom right
local c2 = absp + (Vector2.new(abss.X, -abss.Y)/2) -- top right
local c3 = absp + (Vector2.new(-abss.X, abss.Y)/2) -- bottom left
local c4 = absp + (Vector2.new(-abss.X, -abss.Y)/2) -- top left

return {c1,c2,c3,c4}
end

The function above will get each corners of the rectangle GuiObject.
And then, You can do something like :

-- code from before
local gui = x -- change "x" to whatever you want (GuiObject, ex. Frame, TextLabel, TextBox, etc)

local PlayerGui = game.Players.LocalPlayer:WaitForChild('PlayerGui')
local CurrentTouchingColors = {}

gui:GetPropertyChangedSignal('AbsolutePosition'):Connect(function()
    local corners = getCorners(gui)
    local pos1 = PlayerGui:GetGuiObjectsAtPosition(corners[1].X,corners[1].Y)
    local pos2 = PlayerGui:GetGuiObjectsAtPosition(corners[2].X,corners[2].Y)
    local pos3 = PlayerGui:GetGuiObjectsAtPosition(corners[3].X,corners[3].Y)
    local pos4 = PlayerGui:GetGuiObjectsAtPosition(corners[4].X,corners[4].Y)

    for i, v in pairs(pos1) do
        if not table.find(CurrentTouchingColors, v.BackgroundColor3) then
            table.insert(CurrentTouchingColors, v.BackgroundColor3)
        end
    end
    for i, v in pairs(pos2) do
        if not table.find(CurrentTouchingColors, v.BackgroundColor3) then
            table.insert(CurrentTouchingColors, v.BackgroundColor3)
        end
    end
    for i, v in pairs(pos3) do
        if not table.find(CurrentTouchingColors, v.BackgroundColor3) then
            table.insert(CurrentTouchingColors, v.BackgroundColor3)
        end
    end
    for i, v in pairs(pos4) do
        if not table.find(CurrentTouchingColors, v.BackgroundColor3) then
            table.insert(CurrentTouchingColors, v.BackgroundColor3)
        end
    end
end)

This might look very confusing.
So What this script does do?
First, It gets the variables (gui, PlayerGui, CurrentTouchingColors)
As you can see, CurrentTouchingColors variable is table.
I setted it to table because to save the colors that gui is currently touching.

and after the line

gui:GetPropertyChangedSignal(‘AbsolutePosition’):Connect(function()

There are bunch of variables, and for i, v loops, right?


- Variables

There are total of 5 variables in the script, which are corners, pos1, pos2, pos3, pos4.
I will explain what they does.

  • corners - It gets the 4 corners of the rectangle GuiObject.
    Example Picture


    The red squares are the corners of the rectangle GuiObject at the middle. they are calculated by the function getCorners() at the top of this post.

  • pos1, pos2, pos3, pos4 - These are the variables which store the GuiObjects at the position of all the corners Positions.

- 4 for i, v in pairs…

As you can see, there are four same things that starts with “for i, v in pairs(. . .) do”.
These are for loops and their work is to detect touching guis, and store each touching gui’s BackgroundColor3 to table CurrentTouchingColors, also it checks if the table has same color touching.


These were the explainations, I hope this reply helped you!

This won’t work on smaller objects :frowning:

The script I’ve provided currently will not work on smaller objects that isnt touching the corner.
Example 1

= (44, 25, 255) which is color of the blue frame.

Example 2

= nil

And The reason Example1 works and Example2 doesn’t work is because the script I’ve provided doesn’t calculate anything that isn’t touching the corner of the white UI, and in Example2, the blue frame is currently NOT touching the corners ( red squares ).

And To be honest, I couldn’t think of any other ways to make this (Example2) work.
anyways consider that If you are gonna use my script

1 Like

For example 2, why not just calculate the distance between all the corners and use the results to find out if it touches between the 2 corners like raycasting?

To be honest, I can’t understand what are you saying.
Can you explain a bit deeper?

What I mean is that you calculate the distance between the 2 closest points of the Gui, draw an invisible line from the first corner to the second corner, and with this line you can tell whether the Gui touches the line or not.

Are you saying that

(ignore “This won’t work”)
you get the two closest corners of the blue frame, then draw a line between two corners, and detect whether the blue frame touches the line or not?

Actually if we go like that, then this gets bit off-topic.
And why i am saying this is because, you are trying to get the guis that the main gui is Touching, then get the colors of the guis that main gui is touching. but this is getting a TouchStatus of 2 guis, then get the color of the gui that isn’t main.

anyways, it is possible to get the touch status of the part if you actually set the gui that you want to check if it is touching main gui.

getTouchStatus(maingui, gui) = true or false

and then

getColorOfGui(gui) if getTouchStatus(maingui, gui)

It will go something like that.
And, I am actually working on some works that is related to this, and I can tell how to get touch status correctly.

Yea… to get touch status between two guis, you can first get corners of main gui

local function getCorners(ui:GuiObject)
local absp = ui.AbsolutePosition
local abss = ui.AbsoluteSize
local c1 = (absp + Vector2.new(abss.X, abss.Y)/2) + abss/2 -- bottom right ++
local c2 = (absp + Vector2.new(-abss.X, abss.Y)/2) + abss/2 -- bottom left -+
local c3 = (absp + Vector2.new(-abss.X, -abss.Y)/2) + abss/2 -- top left --
local c4 = (absp + Vector2.new(abss.X, -abss.Y)/2) + abss/2 -- top right +-

return {c1,c2,c3,c4}
end

-- just a function from my reply before, also I changed c1~c4 for later.
local corners = getCorners(maingui)

and then you can use this equation :

if ((b_r.X >= pos.X) and (b_r.Y >= pos.Y)) and ((b_l.X <= pos.X) and (b_l.Y >= pos.Y)) and ((t_l.X <= pos.X) and (t_l.Y <= pos.Y)) and ((t_r.X >= pos.X) and (t_r.Y <= pos.Y)) then
    -- do something
end

note : I will talk about “b_r” and “pos” later

And the equation above is from the module I am currently working on.
And full function of getting touch status is ( its from my module )

function GetTouchStatus(gui1:GuiObject, gui2:GuiObject)
	local c1 = getCorners(gui1) 
	local c2 = getCorners(gui2)
	
	local function check(t:{Vector2}, pos:Vector2)
		local b_r = t[1]
		local b_l = t[2]
		local t_l = t[3]
		local t_r = t[4]
		local res = false
		
		if ((b_r.X >= pos.X) and (b_r.Y >= pos.Y)) and ((b_l.X <= pos.X) and (b_l.Y >= pos.Y)) and ((t_l.X <= pos.X) and (t_l.Y <= pos.Y)) and ((t_r.X >= pos.X) and (t_r.Y <= pos.Y)) then
			res = true
		end
		
		return res
	end
	
	local res = false
	
	for i = 1, #c1 do
		local ch = check(c2, c1[i])
		if ch then res = true end
	end
	for i = 1, #c2 do
		local ch = check(c1, c2[i])
		if ch then res = true end
	end
	
	
	return res
end

the function getCorners(gui) returns table of corner positions.
and function check(t, pos) returns if a position is inside of 4 positions of table “t”. (table “t” is a result from function getCorners(maingui) )
I am currently tired to explain everything, so just ask things that you can’t understand in replies.

Can you show me the final script pls

what do you mean?
the entire module??

yes if you don’t mind ?
Ignore this

1 Like
local module = {}

local function getCorners(gui:GuiObject, returnAsTable:boolean?) : Vector2 | {Vector2}
	returnAsTable = returnAsTable or false
	local absp = gui.AbsolutePosition
	local abss = gui.AbsoluteSize
	local c1 = (absp + Vector2.new(abss.X, abss.Y)/2) + abss/2 -- bottom right ++
	local c2 = (absp + Vector2.new(-abss.X, abss.Y)/2) + abss/2 -- bottom left -+
	local c3 = (absp + Vector2.new(-abss.X, -abss.Y)/2) + abss/2 -- top left --
	local c4 = (absp + Vector2.new(abss.X, -abss.Y)/2) + abss/2 -- top right +-
	
	if returnAsTable then
		return {c1, c2, c3, c4}
	else
		return c1, c2, c3, c4
	end
end

function module:GetTouchStatus(gui1:GuiObject, gui2:GuiObject)
	local c1 = getCorners(gui1, true)
	local c2 = getCorners(gui2, true)
	
	local function check(t:{Vector2}, pos:Vector2)
		local b_r = t[1]
		local b_l = t[2]
		local t_l = t[3]
		local t_r = t[4]
		local res = false
		
		if ((b_r.X >= pos.X) and (b_r.Y >= pos.Y)) and ((b_l.X <= pos.X) and (b_l.Y >= pos.Y)) and ((t_l.X <= pos.X) and (t_l.Y <= pos.Y)) and ((t_r.X >= pos.X) and (t_r.Y <= pos.Y)) then
			res = true
		end
		
		return res
	end
	
	local res = false
	
	for i = 1, #c1 do
		local ch = check(c2, c1[i])
		if ch then res = true end
	end
	for i = 1, #c2 do
		local ch = check(c1, c2[i])
		if ch then res = true end
	end
	
	
	return res
end

return module

non-related functions, properties are deleted.

Thank you for your help
I needed this to do realistic physics with Gui.

Can I ask you how you did it with rotation??

For the rotation I had the idea of using the “Scratch” site to make the Gui because Scratch is in 2D so for me it’s Gui . I’m currently in the process of rotating it but it’s not easy to do.

I mean, you did get the “true” output when that image touches the slope.
And slope is rotated, how did you manage to get touch status correctly with a gui rotated?