WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Using the new Map API (https://www.wowinterface.com/forums/showthread.php?t=56425)

Ferodra 07-24-18 05:14 AM

Using the new Map API
 
Hey guys!

I'm currently working on my own UI and already coded a lot of modules.
One of those modules adds markers to the worldmap which show old dungeon/raid entrances.

Since 8.0, i have to check the current Map ID via OnUpdate, since there seems to be no event anymore that indicates a change of the viewed zone.
My method to retrieve the current zone looks like that:

Code:

local EmptyMapInfo = {0, 0, 0, 0}
function WM:UpdateCurrentZone()
        self.CurrentZone        = WorldMapFrame:GetMapID()
        if not self.CurrentZone then
                self.MapInfo                = EmptyMapInfo
        else
                self.MapInfo                = C_Map.GetMapInfo(self.CurrentZone)
        end
end

I still have to set the MapInfo to empty by value of course.
But the main problem is that C_Map.GetMapInfo now returns a table.
And since this runs OnUpdate, yeah. The memory skyrockets.

I'm also experiencing the same problem with my coordinate module. But there i use C_Map.GetPlayerMapPosition. This also returns a table.
I already throttled the updates.

But there must be a workaround, right?

Thanks in advance!

LanceDH 07-24-18 10:31 AM

I don't know about getting around the table issue, but for less function calls try:

Lua Code:
  1. hooksecurefunc(WorldMapFrame, "OnMapChanged", function()
  2.     local mapID = WorldMapFrame.mapID;
  3. end);

Gello 07-24-18 10:50 AM

I'm not comfortably fluent in the new map yet, but you could also create a data provider (which you may already have if you're putting stuff on the map):
Code:

-- mixin is at Interface\AddOns\Blizzard_MapCanvas_DataProviderBase.lua
dataProvider = CreateFromMixins(MapCanvasDataProviderMixin)

-- the RefreshAllData() method is called in the default implementation
function dataProvider:OnMapChanged()
  print("OnMapChanged")
end

WorldMapFrame:AddDataProvider(dataProvider)

You could also use RefreshAllData() as your "map has changed" event (the default OnMapChanged() calls it)
Code:

function MapCanvasDataProviderMixin:OnMapChanged()
  --  Optionally override in your mixin, called when map ID changes
  self:RefreshAllData();
end

There's a thread in the PTR forums about the table creation from GetXY().

If you still need an OnUpdate, one idea to minimize calls would be to register for the events where you start and stop moving. (PLAYER_STARTED_MOVING, PLAYER_STOPPED_MOVING) But I don't know if the event still fires when on a taxi.

Vrul 07-24-18 05:33 PM

This may look a bit like overkill but here is what I'm using (the coordinate stuff is a modification of code provided by elcius):
Code:

local GetBestMapForUnit, UnitPosition = C_Map.GetBestMapForUnit, UnitPosition
local GetWorldPosFromMapPos = C_Map.GetWorldPosFromMapPos

local mapID, offsetX, offsetY, scaleX, scaleY, vector = nil, { }, { }, { }, { }, CreateVector2D(0, 0)

local mt = { __index = function(self, mapID)
    vector.x, vector.y = 0, 0
    local _, offset = GetWorldPosFromMapPos(mapID, vector)
    vector.x, vector.y = 1, 1
    local _, scale = GetWorldPosFromMapPos(mapID, vector)
    offsetX[mapID], offsetY[mapID] = offset.x, offset.y
    scaleX[mapID], scaleY[mapID] = scale.x - offset.x, scale.y - offset.y
    return self[mapID]
end }

setmetatable(offsetX, mt)
setmetatable(offsetY, mt)
setmetatable(scaleX, mt)
setmetatable(scaleY, mt)

local frame = CreateFrame("Frame", nil, UIParent)

local timer, X, Y = 1
frame:SetScript("OnUpdate", function(self, elapsed)
    timer = timer + elapsed
    if timer < 0.1 then return end
    timer = 0
    local x, y = UnitPosition("player")
    if x and y then -- Reversed axis
        x, y = (y - offsetY[mapID]) / scaleY[mapID], (x - offsetX[mapID]) / scaleX[mapID]
        if x ~= X or y ~= Y then
            -- Update coordinates stuff here
            X, Y = x, y
        end
    end
end)

frame:SetScript("OnEvent", function(self, event)
    mapID = GetBestMapForUnit("player")
    if mapID and UnitPosition("player") then
        self:Show()
    else
        self:Hide()
        timer, X, Y = 1, nil, nil
    end
end)
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("NEW_WMO_CHUNK")
frame:RegisterEvent("ZONE_CHANGED")
frame:RegisterEvent("ZONE_CHANGED_NEW_AREA")


Ferodra 07-25-18 01:04 PM

Quote:

Originally Posted by LanceDH (Post 328928)
Lua Code:
  1. hooksecurefunc(WorldMapFrame, "OnMapChanged", function()
  2.     local mapID = WorldMapFrame.mapID;
  3. end);

Well, that is indeed one option i will try :D


Quote:

Originally Posted by Gello (Post 328929)
I'm not comfortably fluent in the new map yet, but you could also create a data provider (which you may already have if you're putting stuff on the map):
Code:

-- mixin is at Interface\AddOns\Blizzard_MapCanvas_DataProviderBase.lua
dataProvider = CreateFromMixins(MapCanvasDataProviderMixin)

-- the RefreshAllData() method is called in the default implementation
function dataProvider:OnMapChanged()
  print("OnMapChanged")
end

WorldMapFrame:AddDataProvider(dataProvider)



I did not even touch the blizz mixins at all, since i simply did not understand them. But it looks kinda easy. I'll give it a shot!

Thanks @ you both!


All times are GMT -6. The time now is 01:27 AM.

vBulletin © 2020, Jelsoft Enterprises Ltd
© 2004 - 2020 MMOUI