--!native --!optimize 2 -- Compiled with roblox-ts v3.0.0 local TS = _G[script] local ArrayTools = TS.import(script, script.Parent, "array_tools").ArrayTools local DetectingTools2D = TS.import(script, script.Parent, "detecting_tools_2d").DetectingTools2D local Vector2Tools = TS.import(script, script.Parent, "vector2_tools").Vector2Tools local GuiTools = {} do local _container = GuiTools local function IsPointInside(frame, point) local half_size = frame.AbsoluteSize * 0.5 local center = frame.AbsolutePosition + half_size local distance = point - center if frame.AbsoluteRotation ~= 0 then distance = Vector2Tools.Rotate(distance, -math.rad(frame.AbsoluteRotation)) end return math.abs(distance.X) <= half_size.X and math.abs(distance.Y) <= half_size.Y end _container.IsPointInside = IsPointInside local function GetBaseCorners(base) local abs_position = base.AbsolutePosition local abs_size = base.AbsoluteSize local max_position = abs_position + abs_size local points = { abs_position, Vector2.new(max_position.X, abs_position.Y), max_position, Vector2.new(abs_position.X, max_position.Y) } if base.AbsoluteRotation == 0 then return table.freeze(points) end local half_size = abs_size * 0.5 local center = abs_position + half_size local index = 0 for _, point in points do local offset = point - center local new_offset = Vector2Tools.Rotate(offset, math.rad(base.AbsoluteRotation)) local new_point = center + new_offset local _original = index index += 1 points[_original + 1] = new_point end return table.freeze(points) end _container.GetBaseCorners = GetBaseCorners local function OverlapTest(base_1, base_2) return DetectingTools2D.ArePolygonsIntersecting(GetBaseCorners(base_1), GetBaseCorners(base_2)) end local function IsNotClipped(object) --noop return true end local function ZIndexInsert(current_value, b) return current_value.ZIndex >= b.ZIndex end local function GetGuiObjectsAtPointSibling(base, point, list, ignore_clipped, ignore_not_visible) if ignore_clipped == nil then ignore_clipped = true end if ignore_not_visible == nil then ignore_not_visible = true end local children = table.freeze(base:GetChildren()) for _, child in children do if not child:IsA("GuiObject") then continue end if not (ignore_not_visible or child.Visible) then continue end local can_be_added = IsPointInside(child, point) and (ignore_clipped or IsNotClipped(child)) if can_be_added then ArrayTools.SortedInsert(list, child, ZIndexInsert) end GetGuiObjectsAtPointSibling(child, point, list, ignore_clipped, ignore_not_visible) end return list end local function GetGuiObjectsAtPointGlobal(base, point, ignore_clipped, ignore_not_visible) if ignore_clipped == nil then ignore_clipped = true end if ignore_not_visible == nil then ignore_not_visible = true end local descendands = table.freeze(base:GetDescendants()) local list = {} for _, child in descendands do if not child:IsA("GuiObject") then continue end if not (ignore_not_visible or child.Visible) then continue end if not (ignore_clipped or IsNotClipped(child)) then continue end if not IsPointInside(child, point) then continue end ArrayTools.SortedInsert(list, child, ZIndexInsert) end return list end --[[ * * * @param base base 2d where all gui objets will be checked * @param point position of the screen * @param ignore_clipped ignore all gui objects that are clipped ("behind the boundaries") default true * @param ignore_not_visible ignore all gui objects that are not visible default true * @param zindex_behaviour determites mode how it detects the elements ]] local function GetGuiObjectsAtPoint(base, point, ignore_clipped, ignore_not_visible, zindex_behaviour) if ignore_clipped == nil then ignore_clipped = true end if ignore_not_visible == nil then ignore_not_visible = true end if zindex_behaviour == nil then zindex_behaviour = Enum.ZIndexBehavior.Sibling end if zindex_behaviour == Enum.ZIndexBehavior.Sibling then return GetGuiObjectsAtPointSibling(base, point, {}, ignore_clipped, ignore_not_visible) end return GetGuiObjectsAtPointGlobal(base, point, ignore_clipped, ignore_not_visible) end _container.GetGuiObjectsAtPoint = GetGuiObjectsAtPoint --[[ * * * @param base base 2d where all gui objets will be checked * @param object object to check * @param point position of the screen * @param ignore_clipped ignore all gui objects that are clipped ("behind the boundaries") default true * @param ignore_not_visible ignore all gui objects that are not visible default true * @param zindex_behaviour defaults to Sibling * @returns ]] local function IsObjectSelectedAtPoint(base, object, point, ignore_clipped, ignore_not_visible, zindex_behaviour) if ignore_clipped == nil then ignore_clipped = true end if ignore_not_visible == nil then ignore_not_visible = true end if zindex_behaviour == nil then zindex_behaviour = Enum.ZIndexBehavior.Sibling end if not IsPointInside(object, point) then return nil end local stack = GetGuiObjectsAtPoint(base, point, ignore_clipped, ignore_not_visible, zindex_behaviour) local _object = object if not (table.find(stack, _object) ~= nil) then return false end local index = 0 for _, element in stack do index += 1 if element == object then return true end if element.Active then return false end end return false end _container.IsObjectSelectedAtPoint = IsObjectSelectedAtPoint local function GuiBaseToRect(base) local _exp = base.AbsolutePosition local _absolutePosition = base.AbsolutePosition local _absoluteSize = base.AbsoluteSize return Rect.new(_exp, _absolutePosition + _absoluteSize) end _container.GuiBaseToRect = GuiBaseToRect local function GetAbsoluteCenter(base) local _absolutePosition = base.AbsolutePosition local _arg0 = base.AbsoluteSize * 0.5 return _absolutePosition + _arg0 end _container.GetAbsoluteCenter = GetAbsoluteCenter end return { GuiTools = GuiTools, }