Quantcast
Using the new Map API - WoWInterface
Thread Tools Display Modes
07-24-18, 05:14 AM   #1
Ferodra
A Defias Bandit
Join Date: Jul 2018
Posts: 3
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!
  Reply With Quote
07-24-18, 10:31 AM   #2
LanceDH
A Cyclonian
 
LanceDH's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2012
Posts: 41
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);
  Reply With Quote
07-24-18, 10:50 AM   #3
Gello
A Firelord
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 492
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.
  Reply With Quote
07-24-18, 05:33 PM   #4
Vrul
An Onyxian Warder
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 360
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")
  Reply With Quote
07-25-18, 01:04 PM   #5
Ferodra
A Defias Bandit
Join Date: Jul 2018
Posts: 3
Originally Posted by LanceDH View Post
Lua Code:
  1. hooksecurefunc(WorldMapFrame, "OnMapChanged", function()
  2.     local mapID = WorldMapFrame.mapID;
  3. end);
Well, that is indeed one option i will try


Originally Posted by Gello View Post
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!
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Using the new Map API

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off