Thread Tools Display Modes
12-10-12, 12:26 AM   #1
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
WorldMapFrame Tainting (Not Green Maps)

Good evening everyone,

I have been working on a lightweight AddOn to perform some fairly simple modifications to the WorldMapFrame. I am running into issues with the WorldMapFrame tainting when it is opened in combat. I attempted to code my AddOn in such a way that the map won't be touched until combat is dropped, but it is still tainting. Would you guys look over my code and give me some advice?

Lua Code:
  1. -- Local definitions
  2. local hooksecurefunc = hooksecurefunc -- I don't know if this acctually helps, I just want to be cool =[
  3. local mapScale = 0.60 -- Map scale for easy modification
  4.  
  5. -- Nevcariel's function for fixing the scale of dropdown menus parented to the WorldMapFrame.
  6. local function dropdownScaleFix(self)
  7.     ToggleDropDownMenu(nil, nil, self:GetParent())
  8.     DropDownList1:SetScale(mapScale)
  9. end
  10.  
  11. local function onShow()
  12.     WorldMapFrame:SetScale(mapScale)
  13. end
  14.  
  15. local function sizeDown()
  16.     WorldMap_ToggleSizeUp()
  17. end
  18.  
  19. local function sizeUp()
  20.     WorldMapFrame:SetAttribute("UIPanelLayout-area", "center")
  21.     BlackoutWorld:Hide()
  22.     WorldMapFrame:EnableKeyboard(false)
  23.     WorldMapFrame:EnableMouse(false)
  24. end
  25.  
  26. local function modifyMap()
  27.     if eventHandler then eventHandler:UnregisterEvent("PLAYER_REGEN_ENABLED") end
  28.    
  29.     WorldMap_ToggleSizeUp()
  30.    
  31.     UIPanelWindows["WorldMapFrame"] = {area = "center", pushable = 9}
  32.     hooksecurefunc(WorldMapFrame, "Show", onShow)
  33.     hooksecurefunc("WorldMap_ToggleSizeDown", sizeDown)
  34.     hooksecurefunc("WorldMap_ToggleSizeUp", sizeUp)
  35.     WorldMapContinentDropDownButton:SetScript("OnClick", dropdownScaleFix)
  36.     WorldMapZoneDropDownButton:SetScript("OnClick", dropdownScaleFix)
  37. end
  38.  
  39. -- Perhaps a workaround to players opening the map in combat?  Who knows.
  40. do
  41.     if not InCombatLockdown() then
  42.         modifyMap()
  43.     else
  44.         local eventHandler = CreateFrame("Frame")
  45.         eventHandler:SetScript("OnEvent", modifyMap)
  46.         eventHandler:RegisterEvent("PLAYER_REGEN_ENABLED")
  47.     end
  48. end

Also, the
Lua Code:
  1. local eventHandler = CreateFrame("Frame")
  2. eventHandler:SetScript("OnEvent", modifyMap)
block of code only works when I create the frame and set the script outside of the ELSE condition in the IF statement. I can't conditionally create the frame?

I am generally at a loss of what to do. The map acts so quirky, and I feel like some of the code is pretty hacked up. Any advice would be most appreciated, as usual.

Thanks so much!
  Reply With Quote
12-10-12, 01:20 AM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Clamsoda View Post
Code:
	if not InCombatLockdown() then
		modifyMap()
	else
		local eventHandler = CreateFrame("Frame")
		eventHandler:SetScript("OnEvent", modifyMap)
		eventHandler:RegisterEvent("PLAYER_REGEN_ENABLED")
	end
... I can't conditionally create the frame?
You can, but here's the thing -- that block of code is only read and executed once, when your addon loads. Since you are never considered InCombatLockdown() when your addon's files are first being read and executed, your code is modifying the map once, and never creating a frame.

You should just be able to call the modifyMap function in the main chunk, instead of that whole do-end block at the end of your code (containing the above) since, again, InCombatLockdown() is never true when non-LoD addons are initially read.

Also, upvaluing hooksecurefunc is pointless. The purpose of upvaluing global functions is to speed up access time, but the speed-up is so minute that it's only useful for functions that are potentially called hundreds of times per second inside an OnUpdate handler or COMBAT_LOG_EVENT_UNFILTERED event handler. For a function that you call once or twice during the loading process, the upvalue is just a (granted, minute) waste of disk space and memory.

As for the taint problem, I don't really know, but my first guess would be related to the dropdown menu stuff, since the dropdown menu system is basically a house of cards in a dark basement. Try using a secure post-hook instead:

Code:
local function dropdownScaleFix(self)
-   ToggleDropDownMenu(nil, nil, self:GetParent())
+   if DropDownList1:IsVisible() then
        DropDownList1:SetScale(mapScale)
+   end
end
and:

Code:
    WorldMapContinentDropDownButton:HookScript("OnClick", dropdownScaleFix)
    WorldMapZoneDropDownButton:HookScript("OnClick", dropdownScaleFix)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
12-10-12, 01:31 AM   #3
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Thanks a lot for the insight Phanx. I implemented your changes, but I am still getting "Interface action failed because of an AddOn" message when I open the map while in combat.

Here is a link to the TaintLog produced: http://pastebin.com/ExwfJD1g

I see the the DropDownMenu is being tainted, but there are also other aspects of the map that are being tainted. As for the DropDownMenu, I am grabbing that directly from Mapster(Thanks Nev <.<), and I don't ever recall Mapster producing any issues -- and further more, how will I make any changes to the map if it just breaks in combat?
  Reply With Quote
12-10-12, 03:51 AM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I have seen taint errors from Mapster when opening the map in combat, though it's pretty rare.

Do you get the same errors when your world map addon is the only addon enabled?

Other than that, try just doing SetScale and SetAttribute once when you load, instead of every time the map is shown. I'm not sure why you'd need to repeat them. SetAttribute in particular is likely to have issues in combat.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
12-10-12, 04:07 AM   #5
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
When I was reading about InCombatLockdown(), it specified that setting frame attributes, and moving frames without a hardware event were protected, so I KNOW that is causing tainting issues.

Setting the WorldMapFrame scale doesn't work on load, it seems to only work on the map's Show method. m_Map, Mapster, and tekMapEnhancer all have the SetScale for the WorldMapFrame OnShow.

I think I am going to start fresh, after ~12 hours of looking and staring at it, and constant modifications, I am sure my code is less than optimal.
  Reply With Quote
12-12-12, 04:48 AM   #6
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Sorry for the double post!

So I have done some work on my map mod, and I've got it producing no taint at all. The only issue I am running into is that to set the scale for the WorldMapFrame, it has to be done OnShow, and to avoid taint, I have to use a combat lockdown function to handle scaling the map OnShow, so if the map is opened in combat, it doesn't taint, but the scale is wrong.

Is there any way to set the scale of the map permanently? Even doing:
Lua Code:
  1. /run WorldMapFrame:SetScale(0.60)
doesn't affect the scale of the world map, unless run when the frame is opened.

Code for refrence:
Lua Code:
  1. -- Local definitions
  2. local mapScale = 0.60 -- Map scale for easy modification
  3.  
  4. -- Thanks Nevcariel for the function, and Phanx for the modifiaction!
  5. local function dropdownScaleFix(self)
  6.     if DropDownList1:IsVisible() then
  7.         DropDownList1:SetScale(mapScale)
  8.     end
  9. end
  10.  
  11. do
  12.     local mini = GetCVarBool("miniWorldMap")
  13.     SetCVar("miniWorldMap", nil)
  14.     if mini then
  15.         WorldMap_ToggleSizeUp()
  16.     end
  17.  
  18.     WorldMapFrame:SetAttribute("UIPanelLayout-defined", true)
  19.     -- WorldMapFrame:SetAttribute("UIPanelLayout-enabled", true)
  20.     WorldMapFrame:SetAttribute("UIPanelLayout-area", "center")
  21.     WorldMapFrame:EnableKeyboard(false)
  22.     WorldMapFrame:EnableMouse(false)
  23.     WorldMapFrameSizeDownButton:Disable()
  24.     WorldMapContinentDropDownButton:HookScript("OnClick", dropdownScaleFix)   -----------------------------------------
  25.     WorldMapZoneDropDownButton:HookScript("OnClick", dropdownScaleFix)        -- Thanks for the modification, Phanx! --
  26.     WorldMapZoneMinimapDropDownButton:HookScript("OnClick", dropdownScaleFix) -----------------------------------------
  27.     BlackoutWorld:Hide()
  28.    
  29.     hooksecurefunc(WorldMapFrame, "Show", function(self)
  30.         if not InCombatLockdown() then
  31.             self:SetScale(mapScale)
  32.         end
  33.     end)
  34.    
  35.     hooksecurefunc(BlackoutWorld, "Show", function(self) self:Hide() end)
  36.    
  37.     -- This may not be neccesary because the map is forced to size up, then the frame attributes are set.
  38.     -- hooksecurefunc("WorldMap_ToggleSizeUp", function() WorldMapFrame:SetAttribute("UIPanelLayout-area", "center") end)
  39.  
  40.     -- Thanks very much Leatrix!
  41.     WorldMapButton:SetScript("OnMouseWheel", function(self, delta)
  42.         local newLevel = GetCurrentMapDungeonLevel() - delta
  43.         if newLevel >= 1 and newLevel <= GetNumDungeonMapLevels() then
  44.             SetDungeonMapLevel(newLevel)
  45.         end
  46.     end)
  47.    
  48.     -- Thanks very much Leatrix!
  49.     WorldMapShowDigSites:HookScript("OnClick", function(self)
  50.         local filename, texheight, void, void, sub = GetMapInfo()
  51.         if sub or not filename then
  52.             MiniMapWorldMapButton:Click(); MiniMapWorldMapButton:Click();
  53.         end
  54.     end)
  55. end
  Reply With Quote
12-12-12, 02:12 PM   #7
Clamsoda
A Frostmaul Preserver
Join Date: Nov 2011
Posts: 269
Yay three posts in a row =/.

I was able to achieve the desired goal...in a bit of a round-about fashion. I did some investigating as to what would cause the WorldMapFrame's scale to reset to 1 every time it is shown, and I noticed that it doesn't have a parent frame, which I thought was interesting. I tried parenting it to UIParent as a test, and voila, it inherited UIParent's scale.

I was able to manage the scale of the frame, without having to hook the OnShow function, by creating my own frame, setting that frame's scale, and parenting the WorldMapFrame to it. I'd like to not have to create my own frame just to handle the scaling, so if anyone has any insight, I'd greatly appreciate it.

Thanks so much for the time, help, and effort.

Last edited by Clamsoda : 12-12-12 at 02:27 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » WorldMapFrame Tainting (Not Green Maps)

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