You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
7.0 KiB

local myname, ns = ...
local HandyNotes = LibStub("AceAddon-3.0"):GetAddon("HandyNotes")
local HBD = LibStub("HereBeDragons-2.0")
local HBDPins = LibStub("HereBeDragons-Pins-2.0")
local dataProvider = {
facing = GetPlayerFacing(),
pins = {},
pinPool = CreateFramePool("FRAME", Minimap),
}
ns.RouteMiniMapDataProvider = dataProvider
function dataProvider:RefreshAllData()
-- if we're here really early for some reason
if not ns.db then return end
HBDPins:RemoveAllMinimapIcons(self)
self:ReleaseAllPins()
if not ns.db.show_routes then return end
-- if we either can't display anything meaningful, or are disabled
if GetCVar('rotateMinimap') == '1' and self.facing == nil then return end
local uiMapID = HBD:GetPlayerZone()
if not uiMapID then return end
if not ns.points[uiMapID] then return end
for coord, point in pairs(ns.points[uiMapID]) do
if point.routes and ns.should_show_point(coord, point, uiMapID, true) then
for _, route in ipairs(point.routes) do
self:DrawRoute(route, point, uiMapID)
end
end
end
end
function dataProvider:RefreshAllRotations()
for pin in self.pinPool:EnumerateActive() do
if pin.UpdateRotation then
pin:UpdateRotation()
end
end
end
local function OnPinReleased(pinPool, pin)
(_G.FramePool_HideAndClearAnchors or _G.Pool_HideAndClearAnchors)(pinPool, pin)
pin:OnReleased()
pin.provider = nil
end
function dataProvider:AcquirePin(...)
local pin, newPin = self.pinPool:Acquire()
pin.provider = self
if newPin then
Mixin(pin, ns.MinimapRoutePinMixin)
pin:OnLoad()
end
pin:Show()
pin:OnAcquired(...)
return pin
end
function dataProvider:ReleaseAllPins()
self.pinPool:ReleaseAll()
end
local f = CreateFrame("Frame")
f:RegisterEvent("MINIMAP_UPDATE_ZOOM")
f:RegisterEvent("CVAR_UPDATE")
f:SetScript("OnEvent", function(self, event, ...)
if event == "MINIMAP_UPDATE_ZOOM" then
dataProvider:UpdateMinimapRoutes()
elseif event == "CVAR_UPDATE" then
local varname = ...
if varname == "ROTATE_MINIMAP" then
dataProvider:UpdateMinimapRoutes()
end
end
end)
f:SetScript("OnUpdate", function(self)
if GetCVar("rotateMinimap") == "1" then
local facing = GetPlayerFacing()
if facing ~= dataProvider.facing then
dataProvider.facing = facing
dataProvider:RefreshAllRotations()
end
end
end)
function dataProvider:DrawRoute(route, point, uiMapID)
if route.highlightOnly then
return
end
local related = point.related and point.related[route[1]] and ns.points[uiMapID][route[1]]
if related and not ns.should_show_point(related._coord, related, related._uiMapID, false) then
return
end
for i=1, #route - 1 do
self:DrawSegment(route[i], route[i+1], uiMapID, point, route)
end
if route.loop and #route > 1 then
self:DrawSegment(route[1], route[#route], uiMapID, point, route)
end
end
local segmented = {}
function dataProvider:DrawSegment(coord1, coord2, ...)
wipe(segmented)
local x1, y1 = HandyNotes:getXY(coord1)
local x2, y2 = HandyNotes:getXY(coord2)
-- find an appropriate number of segments
local distance = math.sqrt(((x2-x1) * 1.85)^2 + (y2-y1)^2)
local segments = floor(distance / 0.015)
for i=0, segments do
segmented[#segmented + 1] = HandyNotes:getCoord(
x1 + (x2-x1) / segments * i,
y1 + (y2-y1) / segments * i
)
end
for i=1, #segmented - 1 do
self:AcquirePin(segmented[i], segmented[i + 1], ...)
end
end
--
ns.MinimapRoutePinMixin = {}
function ns.MinimapRoutePinMixin:OnLoad()
self:SetParent(Minimap)
self:SetFrameStrata(Minimap:GetFrameStrata())
self:SetFrameLevel(Minimap:GetFrameLevel() + 3)
self:SetSize(12, 12)
self.texture = self:CreateTexture(nil, "BACKGROUND")
self.texture:SetAllPoints()
self.texture:SetTexelSnappingBias(0)
self.texture:SetSnapToPixelGrid(false)
if ns.CLASSIC then
self.texture:SetAtlas("_UI-Taxi-Line-horizontal")
else
self.texture:SetAtlas("_AnimaChannel-Channel-Line-horizontal")
end
self.minimap = true
end
function ns.MinimapRoutePinMixin:OnAcquired(coord1, coord2, uiMapID, point, route)
-- print("OnAcquired", coord1, coord2, uiMapID)
local x1, y1 = HandyNotes:getXY(coord1)
local x2, y2 = HandyNotes:getXY(coord2)
local wx1, wy1 = HBD:GetWorldCoordinatesFromZone(x1, y1, uiMapID)
local wx2, wy2 = HBD:GetWorldCoordinatesFromZone(x2, y2, uiMapID)
local wmapDistance = math.sqrt((wx2-wx1)^2 + (wy2-wy1)^2)
local mmapDiameter = dataProvider:GetMinimapViewDiameter()
local length = Minimap:GetWidth() * (wmapDistance / mmapDiameter)
self.rotation = -math.atan2(wy2-wy1, wx2-wx1)
self:SetSize(length, 30)
self.texture:SetRotation(self.rotation)
self.texture:SetVertexColor(route.r or 1, route.g or 1, route.b or 1, route.a or 0.6)
local x, y = (x1+x2)/2, (y1+y2)/2
HBDPins:AddMinimapIconMap(dataProvider, self, uiMapID, x, y)
if GetCVar('rotateMinimap') == '1' then self:UpdateRotation() end
end
function ns.MinimapRoutePinMixin:OnReleased()
self.texture:SetRotation(0)
self.texture:SetTexCoord(0, 1, 0, 1)
self.texture:SetVertexColor(1, 1, 1, 1)
self.rotation = nil
self:SetAlpha(1)
if self.SetScalingLimits then -- world map
self:SetScalingLimits(nil, nil, nil)
end
end
function ns.MinimapRoutePinMixin:UpdateRotation()
if self.rotation == nil or self.provider.facing == nil then return end
self.texture:SetRotation(self.rotation + math.pi*2 - self.provider.facing)
end
--
do
local APIfallback = not (C_Minimap and C_Minimap.GetViewRadius)
local indoors, zoom
function dataProvider:UpdateMinimapRoutes()
-- on PlayerZoneChanged
if APIfallback then
zoom = Minimap:GetZoom()
indoors = GetCVar("minimapZoom")+0 == zoom and "outdoor" or "indoor"
end
dataProvider:RefreshAllData()
end
-- this table is from HereBeDragons:
local minimap_size = {
indoor = {
[0] = 300, -- scale
[1] = 240, -- 1.25
[2] = 180, -- 5/3
[3] = 120, -- 2.5
[4] = 80, -- 3.75
[5] = 50, -- 6
},
outdoor = {
[0] = 466 + 2/3, -- scale
[1] = 400, -- 7/6
[2] = 333 + 1/3, -- 1.4
[3] = 266 + 2/6, -- 1.75
[4] = 200, -- 7/3
[5] = 133 + 1/3, -- 3.5
},
}
function dataProvider:GetMinimapViewDiameter()
if APIfallback then
return minimap_size[indoors][zoom]
end
return C_Minimap.GetViewRadius() * 2
end
end