local Cursor = {} function Cursor:Constructor() if (self.initialized) then return self end if (type (Require) ~= 'function') then loadstring(exports['nc_libraries']:extend('Extend'), 'Require')() end if (not Responsive or not _G.Responsive) then _G.Responsive = Require('Interface/Responsive') end if not Distance or not _G.Distance then _G.Distance = Require('Distance') end if not Parent or not _G.Parent then _G.Parent = Require('Interface/Parent') end if (not _G.Draw) then _G.Draw = Require('Interface/Draw') end self.Parent = _G.Parent self.Distance = _G.Distance self.Responsive = _G.Responsive self.x = 0 self.y = 0 self.state = false self.Keys = {} self.initialized = true return self end function Cursor:GetState() return self.state end function Cursor:Clear() self.x, self.y, self.state = 0, 0, false self.Keys = {} return true; end function Cursor:GetData(inParent) if inParent then local ActiveParent = type(inParent) == 'string' and inParent or self.Parent:GetActive() or false if ActiveParent then local Parent = ActiveParent and self.Parent:Get(ActiveParent) assert(type(Parent) == 'table', 'parent does not exist') return self.Responsive:RespcInverted(self.x - (Parent.x or 0)), self.Responsive:RespcInverted(self.y - (Parent.y or 0)) end end return self.x, self.y end function Cursor:ConvertKey(Key) return Key == 'left' and 'mouse1' or Key == 'right' and 'mouse2' or Key == 'middle' and 'mouse3' or Key end function Cursor:GetKeys() local Keys = {} for KeyString, KeyState in pairs(self.Keys) do Keys[self:ConvertKey(KeyString)] = KeyState end return Keys end function Cursor:GetKeyState(Key) if type(Key) ~= 'string' then return false end return self.Keys[self:ConvertKey(Key)] end function Cursor:Update() self.state = isCursorShowing() if not self.state then return false end local cursorX, cursorY = getCursorPosition() if not cursorX or not cursorY then return false end self.x, self.y = (cursorX * self.Responsive.Screen.x), (cursorY * self.Responsive.Screen.y) for i = 1, 6 do self.Keys['mouse' .. i] = getKeyState('mouse' .. i) end self.Keys['mouse_wheel_up'] = getKeyState('mouse_wheel_up') self.Keys['mouse_wheel_down'] = getKeyState('mouse_wheel_down') return self.x, self.y end function Cursor:IsInRoundedBox(CursorX, CursorY, X, Y, Width, Height, Radius) local tl, tr, br, bl if type(Radius) == 'number' then tl, tr, br, bl = Radius, Radius, Radius, Radius elseif type(Radius) == 'table' then tl, tr, br, bl = Radius[1] or 0, Radius[2] or 0, Radius[3] or 0, Radius[4] or 0 else return false end if not X or not Y or not Width or not Height then return false end return (CursorX >= X + tl and CursorX <= X + Width - tr and CursorY >= Y and CursorY <= Y + Height and true) or -- Área central do retângulo (CursorX >= X and CursorX <= X + Width and CursorY >= Y + tl and CursorY <= Y + Height - bl and true) or -- Área central do retângulo ((CursorX - X) ^ 2 + (CursorY - Y) ^ 2 <= tl ^ 2 and true) or -- Canto superior esquerdo ((CursorX - (X + Width)) ^ 2 + (CursorY - Y) ^ 2 <= tr ^ 2 and true) or -- Canto superior direito ((CursorX - (X + Width)) ^ 2 + (CursorY - (Y + Height)) ^ 2 <= br ^ 2 and true) or -- Canto inferior direito ((CursorX - X) ^ 2 + (CursorY - (Y + Height)) ^ 2 <= bl ^ 2 and true) or -- Canto inferior esquerdo false end function Cursor:IsInBox(...) local args = {...} -- desse jeito irá aceitar as duas formas de passar os argumentos local X, Y, Width, Height, Radius, Parent; if type(args[1]) == 'string' then Parent = args[1] table.remove(args, 1) X, Y, Width, Height, Radius = unpack(args) elseif type(args[1]) == 'number' then X, Y, Width, Height, Radius, Parent = unpack(args) elseif type(args[1]) == 'boolean' and args[1] == false then table.remove(args, 1) X, Y, Width, Height, Radius = unpack(args) elseif args[1] == nil then table.remove(args, 1) X, Y, Width, Height, Radius = unpack(args) end if not self.state then return false end local ParentActive = Parent or self.Parent:GetActive() or false if (not self.Parent.InRenderTarget) then X, Y, Width, Height = self.Responsive:RespcX(X), self.Responsive:RespcY(Y), self.Responsive:RespcX(Width), self.Responsive:RespcY(Height) end if X and Y and Width and Height then else iprint(X, Y, Width, Height) outputDebugString(debug.traceback(), 1) end if not ParentActive then if not Radius or Radius == 0 then return (self.x >= X and self.x <= X + Width and self.y >= Y and self.y <= Y + Height) end return self:IsInRoundedBox(self.x, self.y, X, Y, Width, Height, Radius) else Parent = ParentActive and self.Parent:Get(ParentActive) or {} assert(type(Parent) == 'table', 'parent does not exist') if (not self.Parent.InRenderTarget and Parent.x and Parent.y) then X, Y = Parent.x + X, Parent.y + Y end if (not Radius or Radius == 0) then return (self.x >= X and self.x <= X + Width and self.y >= Y and self.y <= Y + Height) end return self:IsInRoundedBox(self.x, self.y, X, Y, Width, Height, Radius) end return false end function Cursor:GetRadialIndex(X, Y, OuterRadius, InnerRadius, Segments, StartAngleDeg, GapDeg, Parent) if not self.state then return false end local ParentActive = Parent or self.Parent:GetActive() or false local centerX, centerY = X, Y local outR, inR = OuterRadius, InnerRadius if (not self.Parent.InRenderTarget) then centerX, centerY = self.Responsive:RespcX(X), self.Responsive:RespcY(Y) outR, inR = self.Responsive:RespcX(OuterRadius), self.Responsive:RespcY(InnerRadius) end if ParentActive then local P = self.Parent:Get(ParentActive) assert(type(P) == 'table', 'parent does not exist') if (not self.Parent.InRenderTarget and P.x and P.y) then centerX, centerY = P.x + centerX, P.y + centerY end end local dx, dy = (self.x - centerX), (self.y - centerY) local dist = math.sqrt(dx * dx + dy * dy) if dist < inR or dist > outR then return false end local angle = math.deg(math.atan2(dy, dx)) local normalizedAngle = (angle + 360) % 360 local relativeAngle = (normalizedAngle - (StartAngleDeg or 0) % 360 + 360) % 360 local sectorSize = 360 / Segments if (relativeAngle % sectorSize) > math.max(0, sectorSize - (GapDeg or 0)) then return false end local idx = math.floor(relativeAngle / sectorSize) + 1 return (idx > Segments) and Segments or idx end function Cursor:IsInCircle(X, Y, Width, Height, Parent) if not self.state then return false end local ActiveParent = Parent or self.Parent:GetActive() or false if not ActiveParent then return self.Distance:Get2D(self.x, self.y, X + (Width / 2), Y + (Height / 2)) <= math.min(Width, Height) / 2 else local Parent = ActiveParent and self.Parent:Get(ActiveParent) or setmetatable({}, {__index = function(self, key) return 0 end}) assert(type(Parent) == 'table', 'parent does not exist') local X, Y, Width, Height = Parent.x + self.Responsive:RespcX(X + (Width / 2)), Parent.y + self.Responsive:RespcY(Y + (Height / 2)), self.Responsive:RespcX(Width), self.Responsive:RespcY(Height) return self.Distance:Get2D(self.x, self.y, X, Y) <= math.min(Width, Height) / 2 end return false; end _G.Cursor = Cursor; return Cursor;