i have a problem, i made a imagebutton with an image of a triangle (since roblox doesnt have any ui triangles by itself) and set the backgroundtransparency to 1, but now using things like MouseEnter
fire too early (putting the mouse on background fires it, despite the fact its just an invisible part of ui)
so how do i detect whether the mouse is actually on the image, or just on the background?
You can try using UserInputService:GetMouseLocation()
and comparing with your GUI positions.
Not sure this will help but …
local UIS=game:GetService("UserInputService")
UIS.InputBegan:Connect(function(Input, gameProcessedEvent)
if gameProcessedEvent then
if Input.UserInputType == Enum.UserInputType.MouseButton1 then
--
end
end
end)
gameProcessedEvent will be true if it’s actually over a gui “part”.
The button’s InputBegan and InputChanged events provide an InputObject as their first parameter. These events fire on hovers as well as clicks. The X and Y of the InputObject’s Position property match the point on screen where the mouse is. The AbsolutePosition and AbsoluteSize of the button can tell you the rough square boundary of the ImageButton. Since it’s not yet possible to do pixel checks on images outside of Studio, you can do some math on the mouse coordinates on the image to guess if it overlaps the triangle. You can make this easier if you convert the coordinates to two decimals between 0 and 1 representing where in the boundary the mouse is, kinda how UDim’s Scale works.
Building off of this, all we need to try and figure out is if the mouse is in a specified triangular area.
To start, instead of using AbsoluteSize
and AbsolutePosition
, we can just use the image’s Position
and Size
properties. For this we will use scale
. To convert to scale we will need the ScreenGui
’s AbsoluteSize
, however.
Ensure that your image is converted to scale (Both Size
and Position
)
local screen_gui = --> path to ScreenGui
local screen_size = screen_gui.AbsoluteSize
local image = --> path to Image
local pos = image.Position
local size = image.Size
Before we go any further, we need to define the 3 vertices of your triangle. It is recommended that your base
vertices are in 2 of the corners and your 3rd vertex is on the opposite side in the middle. Here is an example:
Here we will define the vertices.
local p0 = Vector2.new(pos.X, pos.Y - size.Y/2) -- Top middle
local p1 = Vector2.new(pos.X - size.X/2, pos.Y + size.Y/2) -- Bottom right
local p2 = Vector2.new(pos.X + size.X/2, pos.Y + size.Y/2) -- Bottom left
Note: “p” represents “point”, starting at “point 0”
Now, let’s create a function that will determine if a given mouse input is in the bounds of our triangular area.
This function was sourced from this post here:
local function CheckInBounds(mouse_pos: Vector2): boolean
local p = Vector2.new(mouse_pos.X / screen_size.X, mouse_pos.Y / screen_size.Y)
local s = p0.Y * p2.X - p0.X * p2.Y + (p2.Y - p0.Y) * p.X + (p0.X - p2.X) * p.Y
local t = p0.X * p1.Y - p0.Y * p1.X + (p0.Y - p1.Y) * p.X + (p1.X - p0.X) * p.Y
if (s < 0) ~= (t < 0) then
return false
end
local area = -p1.Y * p2.X + p0.Y * (p2.X - p1.X) + p0.X * (p1.Y - p2.Y) + p1.X * p2.Y
if area < 0 then
return (s <= 0 and s + t >= area)
else
return (s >= 0 and s + t <= area)
end
end
Then, using the button.MouseButton1Click
function, we can get the location of the mouse (X and Y) using UserInputService
.
local uis = game:GetService("UserInputService")
image.MouseButton1Click:Connect(function()
local mouse_pos = uis:GetMouseLocation()
local in_bounds = CheckInBounds(mouse_pos)
--[[
if in_bounds then
-- Mouse clicked inside of triangle
end
]]
print(in_bounds)
end)
All of this should detect if the mouse position is between the three given vertices of your triangle.