Yes it indeed is, it actually took me some time to find the exact cause of the issue, it does not happen usually. The issue happens when you put a surface inside a ScreenGui. I donāt have an exact explanation on why the Mouse position bugs happen if for that specific scenario, but I suppose its because the ScreenGui affects the absolute sizes and positions very weirdly.
Here is a video of mine showcasing it
Watch 0531 | Streamable
Fixed function + place showcasing the issue/bug
function Canvas:GetMousePoint(): Vector2?
if RunService:IsClient() then
local MouseLocation = UserInputService:GetMouseLocation()
local GuiInset = game.GuiService:GetGuiInset()
local CanvasFrameSize = self.CurrentCanvasFrame.AbsoluteSize
local FastCanvasFrameSize = self.CurrentCanvasFrame.FastCanvas.AbsoluteSize
local CanvasPosition = self.CurrentCanvasFrame.AbsolutePosition
local SurfaceGui = Frame:FindFirstAncestorOfClass("SurfaceGui")
MouseLocation -= GuiInset
if not SurfaceGui then
-- Gui
local MousePoint = MouseLocation - CanvasPosition
local TransformedPoint = (MousePoint / FastCanvasFrameSize) -- Normalised
TransformedPoint *= self.Resolution -- Canvas space
-- Make sure everything is aligned when the canvas is at different aspect ratios
local RatioDifference = Vector2New(CanvasFrameSize.X / FastCanvasFrameSize.X, CanvasFrameSize.Y / FastCanvasFrameSize.Y) - Vector2New(1, 1)
TransformedPoint -= (RatioDifference / 2) * self.Resolution
local UnroundedVec = TransformedPoint
local RoundX = math.ceil(TransformedPoint.X)
local RoundY = math.ceil(TransformedPoint.Y)
TransformedPoint = Vector2.new(RoundX, RoundY)
-- If the point is within the canvas, return it.
--if TransformedPoint.X > 0 and TransformedPoint.Y > 0 and TransformedPoint.X <= self.CurrentResX and TransformedPoint.Y <= self.CurrentResY then
return TransformedPoint
--end
else
-- SurfaceGui
local Part = SurfaceGui.Adornee or SurfaceGui:FindFirstAncestorWhichIsA("BasePart")
local Camera = workspace.CurrentCamera
local FastCanvasFrame = Frame:FindFirstChild("FastCanvas")
if Part and FastCanvasFrame then
local mouse = UserInputService:GetMouseLocation()
local params = RaycastParams.new()
params.FilterDescendantsInstances = {Part}
params.FilterType = Enum.RaycastFilterType.Include
local unitRay = Camera:ViewportPointToRay(mouse.X, mouse.Y)
unitRay = Ray.new(unitRay.Origin, unitRay.Direction*1000)
local result = workspace:Raycast(unitRay.Origin, unitRay.Direction) --, params) you can enable them but my system does not need it
if result and result.Instance == Part then
local topleftCFrame = Part.CFrame * CFrame.new(Part.Size.X/2, Part.Size.Y/2, -Part.Size.Z/2)
local mouseCFrame = CFrame.lookAt(result.Position, result.Position+(result.Normal or Vector3.one)) * CFrame.Angles( 0, 0, math.rad(90) )
local RelCF = topleftCFrame:ToObjectSpace(mouseCFrame)
local res = self.Resolution
return RoundPoint(Vector2.new(
math.clamp( math.abs(RelCF.X)/Part.Size.X*res.X, 0, res.X ),
math.clamp( math.abs(RelCF.Y)/Part.Size.Y*res.Y, 0, res.Y )
))
end
--[[ old method
if Result then
local Normal = Result.Normal
local IntersectionPos = Result.Position
if VectorFuncs.normalVectorToFace(Part, Normal) ~= SurfaceGui.Face then
return
end
-- Credits to @Krystaltinan for some of this code
local hitCF = CFrame.lookAt(IntersectionPos, IntersectionPos + Normal)
local topLeftCorners = VectorFuncs.getTopLeftCorners(Part)
local topLeftCFrame = topLeftCorners[SurfaceGui.Face]
local hitOffset = topLeftCFrame:ToObjectSpace(hitCF)
local ScreenPos = Vector2.new(
math.abs(hitOffset.X),
math.abs(hitOffset.Y)
)
-- Ensure the calculations work for all faces
if SurfaceGui.Face == Enum.NormalId.Front or SurfaceGui.Face == Enum.NormalId.Back then
ScreenPos -= Vector2.new(Part.Size.X / 2, Part.Size.Y / 2)
ScreenPos /= Vector2.new(Part.Size.X, Part.Size.Y)
else
return -- Other faces don't seem to work for now
end
local PositionalOffset
local AspectRatioDifference = FastCanvasFrameSize / CanvasFrameSize
local SurfaceGuiSizeDifference = SurfaceGui.AbsoluteSize / CanvasFrameSize
--print(SurfaceGuiSizeDifference)
local PosFixed = ScreenPos + Vector2.new(0.5, 0.5) -- Move origin to top left
ScreenPos = PosFixed * SurfaceGui.AbsoluteSize -- Convert to SurfaceGui space
ScreenPos -= CanvasPosition
local TransformedPoint = (ScreenPos / FastCanvasFrameSize) -- Normalised
TransformedPoint *= self.Resolution -- Canvas space
TransformedPoint += Vector2.new(0.5, 0.5)
-- Make sure everything is aligned when the canvas is at different aspect ratios
local RatioDifference = Vector2New(CanvasFrameSize.X / FastCanvasFrameSize.X, CanvasFrameSize.Y / FastCanvasFrameSize.Y) - Vector2New(1, 1)
TransformedPoint -= (RatioDifference / 2) * self.Resolution
TransformedPoint = RoundPoint(TransformedPoint)
-- If the point is within the canvas, return it.
if TransformedPoint.X > 0 and TransformedPoint.Y > 0 and TransformedPoint.X <= self.CurrentResX and TransformedPoint.Y <= self.CurrentResY then
return TransformedPoint
end
return TransformedPoint
end
]]
end
end
else
OutputWarn("Failed to get point from mouse (you cannot use this function on the server. Please call this function from a client script).")
end
end
Here is the testing place (118.6 KB)
So yea I hope my contribution was helpful for those with or without the issue.
If there is anything you need to know feel free to ask