You can express a gui element’s position and rotation as a CFrame (like a part)
local absPos = gui.AbsolutePosition
local absAng = math.rad(gui.AbsoluteRotation)
local absSize = gui.AbsoluteSize
local center = absPos + absSize/2
local cframe = CFrame.new(center.x, center.y, 0)*CFrame.Angles(0, 0, absAng)
If you can generically represent your gui as a series of vertices, like this:
local rectVerts = {
Vector3.new(-1/2, -1/2, 0),
Vector3.new(1/2, -1/2, 0),
Vector3.new(1/2, 1/2, 0),
Vector3.new(-1/2, 1/2, 0),
}
Then you can write a little code to create a transformed set of vertices which represent exactly where the vertices of your specific gui is.
local function transformVerts(cframe, size, verts)
local newVerts = {}
for i, vert in verts do
newVerts[i] = cframe*(size*vert)
end
return newVerts
end
And then we can write a little algorithm to determine if a vertex is within a set of vertices.
local function isPointWithinVerts(point, verts)
local dir = Vector3.new(1, 0, 0) -- the test direction
local count = 0 -- the signed number of "walls" we need to pass through, starting from point, going in the direction d, to exit the shape defined by verts
for i, vert0 in verts do
local vert1 = verts[i%#verts + 1]
local rel = vert1 - vert0 -- the difference from one vert to the next in the polygon
local cr = rel:Cross(dir).z
local t = rel:Cross(vert0 - point).z/cr
local s = dir:Cross(vert0 - point).z/cr
if s < 1 and s >= 0 and t >= 0 then
count += cr < 0 and -1 or 1
end
end
return count > 0 -- we be inside
end
And finally, we can just test each of the verts of one shape to see if they are inside the other shape.
local function arePolysIntersecting(vertsA, vertsB)
for i, vertA in vertsA do
if isPointWithinVerts(vertA, vertsB) then
return true
end
end
for i, vertB in vertsB do
if isPointWithinVerts(vertB, vertsA) then
return true
end
end
return false
end