Quantcast Is there a global public function to safely update the map? - ESOUI
Thread Tools Display Modes
01/06/19, 12:33 AM   #1
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24
Is there a global public function to safely update the map?

I'd like to replace the use of ZO_WorldMap_UpdateMap() in my Addon to something public if available.

reference function https://esoapi.uesp.net/100025/src/i....lua.html#6073
  Reply With Quote
01/06/19, 03:04 AM   #2
votan
 
votan's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2014
Posts: 468
I highly doubt you want to update the whole map all the time.
I think you are looking for
Code:
ZO_WorldMap_RefreshCustomPinsOfType(pinType)
or for more control:
Code:
ZO_WorldMap_GetPinManager()
__________________
@votan73 (EU - megaserver)
  Reply With Quote
01/07/19, 12:19 AM   #3
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24
Thanks! That's precisely what I'm looking for. Just want to update the pin.

My custom pin is declared in Pointer.lua. Here's the abbreviated file, showing only snippets of code that is relevant here.
lua Code:
  1. local Pointer = {}
  2. ZGV.Pointer = Pointer
  3.  
  4. Pointer.Icons = {
  5.     default =   "ESOdot",
  6.     ESOdot =    { icon=ZGV.DIR.."/Arrows/Stealth/arrow-error.dds", size=40, minisize=25, rotates=false, edgeicon=ZGV.DIR.."\\Skins\\minimaparrow-green-edge", edgesize=60, spinner=true, onminimap=always },
  7. }

The ZGV:SetWaypoint function is found in GuideHandling.lua and responsible for setting the pin on the map when the guide moves to the next or previous steps. I put the following snippet there.
lua Code:
  1. for k,v in pairs(ZGV.Pointer.Icons) do
  2.     if type(v) == "table" then
  3.         if k == "ESOdot" then
  4.             print(k)
  5.             ZO_WorldMap_RefreshCustomPinsOfType(k)
  6.         end
  7.     end
  8. end

The good news is the print statement returns "ESOdot." However, ZO_WorldMap_RefreshCustomPinsOfType(k) doesn't update the pin on the map. For a brief moment the only time I see the pin change locations is when I close the map (or enable ZO_WorldMap_UpdateMap, which I want to move away from).

Is ESOdot not the required pinType?

Any ideas, thoughts, sage advice?

Last edited by Hydra9268 : 01/07/19 at 12:36 AM.
  Reply With Quote
01/07/19, 02:53 AM   #4
votan
 
votan's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2014
Posts: 468
Originally Posted by Hydra9268 View Post
Is ESOdot not the required pinType?

Any ideas, thoughts, sage advice?
No. pinType is the integer identifier you got from ZO_WorldMap_AddCustomPin(). Which is _G[k] in your case.
__________________
@votan73 (EU - megaserver)
  Reply With Quote
01/07/19, 12:30 PM   #5
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24
Originally Posted by votan View Post
No. pinType is the integer identifier you got from ZO_WorldMap_AddCustomPin(). Which is _G[k] in your case.
That makes more sense. Thanks!

Can't wait to try it after work.
  Reply With Quote
01/08/19, 03:47 AM   #6
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24
I see what the problem is. Zygor isn't using the LibGPS. They created their own metatable overload! Which means ZO_WorldMap_RefreshCustomPinsOfType(_G[pinType]) doesn't work. WTF Zygor? Oh, and all the crap below ESOdot isn't used. Looks like they were doing something with marching ants?

lua Code:
  1. Pointer.Icons = {
  2.     default =   "ESOdot",
  3.     ESOdot =    { icon=ZGV.DIR.."/Arrows/Stealth/arrow-error.dds", size=40, minisize=25, rotates=false, edgeicon=ZGV.DIR.."\\Skins\\minimaparrow-green-edge", edgesize=60, spinner=true, onminimap=always },
  4.     greendot =  { icon=ZGV.DIR.."\\Skins\\minimaparrow-green-dot", size=40, minisize=25, rotates=false, edgeicon=ZGV.DIR.."\\Skins\\minimaparrow-green-edge", edgesize=60, spinner=true, onminimap=always },
  5.     graydot =   { icon=ZGV.DIR.."\\Skins\\minimaparrow-green-dot", size=40, minisize=25, rotates=false, edgeicon=ZGV.DIR.."\\Skins\\minimaparrow-green-edge", edgesize=60, spinner=true, desat=1, onminimap=always },
  6.     arrow =     { icon=ZGV.DIR.."\\Skins\\minimaparrow-path", size=70, minisize=60, rotates=true, edgeicon=ZGV.DIR.."\\Skins\\minimaparrow-path", edgesize=50 },
  7.     ant =       { icon=ZGV.DIR.."\\Skins\\minimaparrow-ant", alpha=0.8, size=30, minisize=25, rotates=false, edgeicon=nil, edgesize=1 },
  8.     ant_g =     { icon=ZGV.DIR.."\\Skins\\minimaparrow-ant", r=0.4, g=1, b=0, alpha=0.8, size=30, minisize=25, rotates=false, edgeicon=nil, edgesize=1 },
  9.     ant_b =     { icon=ZGV.DIR.."\\Skins\\minimaparrow-ant", r=0, g=0.7, b=1, alpha=0.8, size=30, minisize=25, rotates=false, edgeicon=nil, edgesize=1 },
  10.     ant_p =     { icon=ZGV.DIR.."\\Skins\\minimaparrow-ant", r=0.8, g=0.3, b=1, alpha=0.8, size=30, minisize=25, rotates=false, edgeicon=nil, edgesize=1 },
  11.     ant_y =     { icon=ZGV.DIR.."\\Skins\\minimaparrow-ant", r=1, g=0.8, b=0, alpha=0.8, size=30, minisize=25, rotates=false, edgeicon=nil, edgesize=1 },
  12.     none =      { icon="", alpha=0.0, size=1, minisize=1, rotates=false, edgeicon=nil, edgesize=1 },
  13.  
  14.     ant_g_default = { r=0.4, g=1, b=0, alpha=0.8 },
  15.     ant_b_default = { r=0, g=0.7, b=1, alpha=0.8 },
  16.     ant_p_default = { r=0.8, g=0.3, b=1, alpha=0.8 },
  17.     ant_y_default = { r=1, g=0.8, b=0, alpha=0.8 },
  18.     ant_default = { r=1, g=1, b=1, alpha=0.8 },
  19. }
  20.  
  21. setmetatable(Pointer.Icons,{__index=function(k) return Pointer.Icons[Pointer.Icons.default] end})
  22. for k,v in pairs(Pointer.Icons) do if type(v)=="table" then __CLASS[v]="PointerIcon_"..k end end

And here's how they get the pin.
lua Code:
  1. function Pointer:GetMapMarker (m,f,x,y,data)
  2.     if not m and not f then
  3.         m,f = self:GetMapTex(),0
  4.     end
  5.  
  6.     if not m or not f or not x or not y then
  7.         Pointer:Debug("GetMapMarker bailing out; map=%s/%d %.2f %.2f",m,f or -1,x or -99,y or -99)
  8.         return
  9.     end
  10.  
  11.     local waypoint = self:GetUnusedMarker()
  12.     waypoint.m = m
  13.     waypoint.f = f
  14.     waypoint.x = x
  15.     waypoint.y = y
  16.  
  17.     ZGV.Utils.table_join(waypoint,data)
  18.     return waypoint
  19. end

The code is gross! This whole time I thought they were using LibGPS. It looks like they loaded the library into the txt file and never bothered to use it.

Well, I guess that's good news. It means I can rip out all their bull**** and move to LibsGPS and hopefully make this Addon more friendly with other Addons like Bandit's mini-map. I'm not at that level of LUA scripting but I need to give it go out of necessity. Hopefully, it's not too too complicated with one pin. There's also this awesome HOW-TO guide by Garkin. I hope it is still relevant in 2018.

If you know of a updated guide or a better guide please let me know. I'll take all the guidance I can get.
  Reply With Quote
01/09/19, 03:04 AM   #7
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24
Based on Garkin's awesome script (Big kudos).

lua Code:
  1. -- Based on Garkin's Guide
  2. -- [url]https://www.esoui.com/forums/showthread.php?t=1557[/url]
  3.  
  4. local ZGESO = {}
  5.  
  6. -- Pin's unique ID
  7. ZGESO.pinType = "MyMapPin"
  8.  
  9. -- Pin Data
  10. ZGESO.pinLayoutData = {
  11.     { level = 50, texture = "/Arrows/Stealth/arrow-error.dds", size = 40 },
  12. }
  13.  
  14. -- Unit test sample data
  15. ZGESO.pinData = {
  16.     ["alikr"] = {
  17.         ["sentinel_base"] = {
  18.             { x = 0.130820446, y = 0.378319359 },
  19.         },
  20.     },
  21. }
  22.  
  23. -- Tooltip Creator
  24. ZGESO.pinTooltipCreator = {
  25.     creator = function(pin)
  26.         local x, y = pin:GetNormalizedPosition()
  27.         InformationTooltip:AddLine( zo_strformat( "Position of my pin is: <<1>>,<<2>>", x*1000, y*1000 ) )
  28.     end,
  29.     tooltip = InformationTooltip,
  30. }
  31.  
  32. -- Add a Callback Function
  33. function ZGESO.pinTypeAddCallback(pinManager)
  34.     -- Do not create pins if your pinType is not enabled
  35.     if not ZO_WorldMap_IsCustomPinEnabled(_G[ZGESO.pinType]) then return end
  36.    
  37.     -- Do not create pins on world, alliance and cosmic maps
  38.     if (GetMapType() > MAPTYPE_ZONE) then return end
  39.  
  40.     -- Okay to continue
  41.     local textureName = GetMapTileTexture()
  42.     textureName = string.lower(textureName)
  43.     local _,_,_,zone,subzone = string.find(textureName, "(maps/)([%w%-]+)/([%w%-]+_%w+)")
  44.     local pins
  45.     print(zone, subzone)
  46.  
  47.     if ZGESO.pinData[zone] and ZGESO.pinData[zone][subzone] then
  48.         pins = ZGESO.pinData[zone][subzone]
  49.     else
  50.         return  -- Return if there's no current map data
  51.     end
  52.  
  53.     for _, pinInfo in ipairs(pins) do
  54.         -- ZO_WorldMapPins:CreatePin(pinTypeId, pinTag, locX, locY, areaRadius)
  55.         -- pinTag can be anything, but I recommend using table or string with additional info about pin, you can use it later in code
  56.         pinManager:CreatePin(_G[ZGESO.pinType], pinInfo, pinInfo.x, pinInfo.y)
  57.    end
  58. end
  59.  
  60. -- Resize callback function (usualy just nil)
  61. function ZGESO.pinTypeOnResizeCallback(pinManager, mapWidth, mapHeight)
  62.     local visibleWidth, visibleHeight = ZO_WorldMapScroll:GetDimensions()
  63.     local currentZoom = mapWidth / visibleWidth
  64.    
  65.     if currentZoom < 1.5 then
  66.         ZO_WorldMap_SetCustomPinEnabled(_G[ZGESO.pinType], false)
  67.     else
  68.         ZO_WorldMap_SetCustomPinEnabled(_G[ZGESO.pinType], true)
  69.     end
  70.  
  71.    ZO_WorldMap_RefreshCustomPinsOfType(_G[ZGESO.pinType])
  72. end
  73.  
  74. function OnLoad(eventCode, name)
  75.     -- The name of this addon
  76.     if name ~= "ZGESO" then return end
  77.  
  78.    -- Initialize map pins
  79.    ZO_WorldMap_AddCustomPin(ZGESO.pinType, ZGESO.pinTypeAddCallback, ZGESO.pinTypeOnResizeCallback, ZGESO.pinLayoutData, ZGESO.pinTooltipCreator)
  80.    
  81.    -- Custom pins are disabled by default, you have to enable them
  82.    ZO_WorldMap_SetCustomPinEnabled(_G[ZGESO.pinType], true)
  83.    
  84.    -- Force refresh pins to call pinTypeAddCalback for the current map
  85.    ZO_WorldMap_RefreshCustomPinsOfType(_G[ZGESO.pinType])
  86.  
  87.    EVENT_MANAGER:UnregisterForEvent("ZGESO_OnLoad", EVENT_ADD_ON_LOADED)
  88. end
  89.  
  90. EVENT_MANAGER:RegisterForEvent("ZGESO_OnLoad", EVENT_ADD_ON_LOADED, OnLoad)

It looks like the code works but there's a problem with the level value in ZO_MapPin.SetData?
https://esodata.uesp.net/100025/src/....lua.html#3347

lua Code:
  1. bad argument #1 to 'math.max' (number expected, got nil)
  2. stack traceback:
  3. [C]: in function 'math.max'
  4. EsoUI/Ingame/Map/WorldMap.lua:3347: in function 'ZO_MapPin:SetData'
  5.     <Locals> self = tbl, pinType = 206, pinTag = tbl, control = ud, labelControl = ud, singlePinData = tbl, overlayControl = ud, highlightControl = ud </Locals>   
  6. EsoUI/Ingame/Map/WorldMap.lua:3687: in function 'ZO_WorldMapPins:CreatePin'
  7.     <Locals> self = tbl, pinType = 206, pinTag = tbl, xLoc = 0.130820446, yLoc = 0.378319359, pin = tbl, pinKey = 71 </Locals> 
  8. user:/AddOns/ZGESO/Pointer.lua:181: in function 'ZGESO.pinTypeAddCallback'
  9.     <Locals> pinManager = tbl, textureName = "art/maps/alikr/sentinel_bas...", _ = 5, _ = 28, _ = "maps/", zone = "alikr", subzone = "sentinel_base", pins = tbl, _ = 1, pinInfo = tbl </Locals>   
  10. EsoUI/Ingame/Map/WorldMap.lua:3667: in function 'ZO_WorldMapPins:RefreshCustomPins'
  11.     <Locals> self = tbl, pinTypeId = 206, pinData = tbl </Locals>  
  12. EsoUI/Ingame/Map/WorldMap.lua:6100: in function 'ZO_WorldMap_UpdateMap'
  13.     <Locals> zoneName = "Sentinel", mapTitle = "Sentinel" </Locals>
  14. user:/AddOns/ZGESO/Viewer/GuideViewerFrame.lua:1095: in function 'Viewer:HandleActionLayer'
  15.     <Locals> self = tbl, isActive = [C]:-1 </Locals>   
  16. user:/AddOns/ZGESO/Viewer/GuideViewerFrame.lua:1133: in function 'Viewer:EVENT_ACTION_LAYER_POPPED'
  17.     <Locals> self = tbl, event = 65553, layerIndex = 7, activeLayerIndex = 2 </Locals> 
  18. user:/AddOns/ZGESO/Events.lua:58: in function 'EventHandler'
  19.     <Locals> event = 65553, self = tbl, eventString = "EVENT_ACTION_LAYER_POPPED", _ = 1, hand = tbl, func = user:/AddOns/ZGESO/Viewer/GuideViewerFrame.lua:1131, funcSelf = tbl </Locals>

Extra information:

1. The pinLayoutData array has a value for level.

2. The print(zone, subzone) on line 45 splits out what appears to be an endless list of zone, subzone. My conclusion is there needs to be a max value to stop it from overloading ZO_MapPin.SetData. Is that causing the problem?


3. An observational finding https://i.imgur.com/SpnGhqf.png

Last edited by Hydra9268 : 01/09/19 at 03:40 AM.
  Reply With Quote
01/09/19, 08:09 AM   #8
Shinni
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 126
The LUA error is caused because your ZGESO.pinLayoutData is a table inside a table.
You want to use one of the following two:
Code:
ZGESO.pinLayoutData = { level = 50, texture = "/Arrows/Stealth/arrow-error.dds", size = 40 }
OR
Code:
ZO_WorldMap_AddCustomPin(ZGESO.pinType, ZGESO.pinTypeAddCallback, ZGESO.pinTypeOnResizeCallback, ZGESO.pinLayoutData[0], ZGESO.pinTooltipCreator)
Also please note the following:
The ZGESO.pinTypeOnResizeCallback is called every time that scaling of the map changes. For example if you scroll your mouse wheel on the map, then this function will be called every single frame until the zoom animation finishes.
Your pinTypeOnResizeCallback calls ZO_WorldMap_RefreshCustomPinsOfType. The function ZO_WorldMap_RefreshCustomPinsOfType will remove all your pins and then call ZGESO.pinTypeAddCallback to re-create your pins.
Re-creating all your pins every single frame will cause tons of performance issues for you.
Also this is probably also the reason why line 45 is executed so often.
  Reply With Quote
01/09/19, 01:00 PM   #9
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24
Great insights and info. I'll review all your points. Thanks, Shinni!

Is there a more efficient way to handle pinTypeOnResizeCallback?

Last edited by Hydra9268 : 01/09/19 at 01:04 PM.
  Reply With Quote
01/09/19, 11:14 PM   #10
Hydra9268
 
Hydra9268's Avatar
AddOn Author - Click to view addons
Join Date: May 2018
Posts: 24


  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » Is there a global public function to safely update the map?

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