local _, ns = ... local oUF = ns.oUF or oUF assert(oUF, 'oUF not loaded') local cos, sin, sqrt2, max, atan2, floor = math.cos, math.sin, math.sqrt(2), math.max, math.atan2, math.floor; local tinsert, tremove = table.insert, table.remove; local _FRAME, _GPS, _TRACKER, _SWITCH, _ARROW, _SPINNER, _TEXT, _HANDLER; local spin, unit, angle, distance; local SuperVillain; do local function _calc(radius) return 0.5 + cos(radius) / sqrt2, 0.5 + sin(radius) / sqrt2; end function spin(texture, angle) local LRx, LRy = _calc(angle + 0.785398163); local LLx, LLy = _calc(angle + 2.35619449); local ULx, ULy = _calc(angle + 3.92699082); local URx, URy = _calc(angle - 0.785398163); texture:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy); end end local Update = function(self, elapsed) if self.elapsed and self.elapsed > (self.throttle or 0.02) then unit = _FRAME.unit if((UnitInParty(unit) or UnitInRaid(unit)) and not UnitIsUnit(unit, "player")) then _SWITCH.Trackable = true else _SWITCH.Trackable = false end if(_SWITCH.Trackable) then if(_TRACKER:IsShown()) then _SWITCH:Hide() if(not SuperVillain) then SuperVillain = SVUI[1] end distance, angle = SuperVillain:Triangulate("player", unit, true) if not angle then _TRACKER:Hide() _SWITCH:Show() else local out = floor(tonumber(distance)) spin(_ARROW, angle) if(out > 100) then _ARROW:SetVertexColor(1,0.1,0.1) _SPINNER:SetVertexColor(0.8,0.1,0.1,0.5) elseif(out > 40) then _ARROW:SetVertexColor(1,0.8,0.1) _SPINNER:SetVertexColor(0.8,0.8,0.1,0.5) elseif(out > 5) then _ARROW:SetVertexColor(0.1,1,0.8) _SPINNER:SetVertexColor(0.1,0.8,0.8,0.5) else _TRACKER:Hide() _SWITCH:Show() end _TEXT:SetText(out) end end else _TRACKER:Hide() _SWITCH:Show() end self.elapsed = 0 self.throttle = 0.02 else self.elapsed = (self.elapsed or 0) + elapsed end end local function Path(self, ...) return (self.GPS.Override or Update) (self, ...) end local function ForceUpdate(element) return Path(element.__owner, 'ForceUpdate') end local Enable = function(self) if(self.GPS) then _FRAME = self _GPS = self.GPS _TRACKER = self.GPS.Tracker _SWITCH = self.GPS.Switch _ARROW = self.GPS.Tracker.Arrow _SPINNER = self.GPS.Tracker.Spinner _TEXT = self.GPS.Tracker.Text _GPS.__owner = self _GPS.ForceUpdate = ForceUpdate --self:RegisterEvent('PLAYER_TARGET_CHANGED', Path) if not _HANDLER then _HANDLER = CreateFrame("Frame") _HANDLER:SetScript("OnUpdate", Update) end _GPS:Show() return true end end local Disable = function(self) if self.GPS then self.GPS.LoopEnabled = nil self.GPS:Hide() --self:UnregisterEvent('PLAYER_TARGET_CHANGED', Path) _FRAME = nil _GPS = nil _TRACKER = nil _SWITCH = nil _ARROW = nil _SPINNER = nil _TEXT = nil end end oUF:AddElement('GPS', nil, Enable, Disable)