Thread Tools Display Modes
11/29/14, 05:17 PM   #1
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Event EVENT_MAIL_CLOSE_MAILBOX fired upon closing of inventory?

I just debugged some sourcecode and found out that the following event "EVENT_MAIL_CLOSE_MAILBOX" will be fired if the inventory of the player gets closed?
It fires even 3 times if I open the mailbox and close the mailbox afterwards sometime?

Lua Code:
  1. EVENT_MANAGER:RegisterForEvent(gAddonName, EVENT_MAIL_OPEN_MAILBOX, Open_Mail_Panel)
  2.     EVENT_MANAGER:RegisterForEvent(gAddonName, EVENT_MAIL_CLOSE_MAILBOX, Close_Mail_Panel)
  3.  
  4. --Event upon opening of the mail panel
  5. local function Open_Mail_Panel()
  6.     d("Open_Mail")
  7. end
  8.  
  9. --Event upon closing of the mail panel
  10. local function Close_Mail_Panel()
  11.     d("Close_Mail")
  12. end

Is this normal and wished?
Or do I have to unregister the event in the "Open_Mail_Panel()" function and register it again in "Close_Mail_panel()" function?

Thanks
  Reply With Quote
11/29/14, 05:50 PM   #2
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by Baertram View Post
I just debugged some sourcecode and found out that the following event "EVENT_MAIL_CLOSE_MAILBOX" will be fired if the inventory of the player gets closed?
It fires even 3 times if I open the mailbox and close the mailbox afterwards sometime?

Lua Code:
  1. EVENT_MANAGER:RegisterForEvent(gAddonName, EVENT_MAIL_OPEN_MAILBOX, Open_Mail_Panel)
  2.     EVENT_MANAGER:RegisterForEvent(gAddonName, EVENT_MAIL_CLOSE_MAILBOX, Close_Mail_Panel)
  3.  
  4. --Event upon opening of the mail panel
  5. local function Open_Mail_Panel()
  6.     d("Open_Mail")
  7. end
  8.  
  9. --Event upon closing of the mail panel
  10. local function Close_Mail_Panel()
  11.     d("Close_Mail")
  12. end

Is this normal and wished?
Or do I have to unregister the event in the "Open_Mail_Panel()" function and register it again in "Close_Mail_panel()" function?

Thanks
You are correct. I don't know why it does that, but it did the same for me.

I would think it is not wished...Don't unregister in the Open_Mail_Panel, if you want to know when the mail really opens & closes, its the other way around. You could register the Open mail event (it seems to work as desired) then register the close event in it, and unregister the close mail event in the close mail funciton. With only brief testing this seemed to work just fine:
Lua Code:
  1. --Event upon closing of the mail panel
  2.     local function Close_Mail_Panel(eventCode)
  3.         d("Close_Mail: "..eventCode)
  4.         EVENT_MANAGER:UnregisterForEvent(BuffIt.name, EVENT_MAIL_CLOSE_MAILBOX, Close_Mail_Panel)
  5.     end
  6.     --Event upon opening of the mail panel
  7.     local function Open_Mail_Panel()
  8.         d("Open_Mail")
  9.         EVENT_MANAGER:RegisterForEvent(BuffIt.name, EVENT_MAIL_CLOSE_MAILBOX, Close_Mail_Panel)
  10.     end
  11.    
  12.     EVENT_MANAGER:RegisterForEvent(BuffIt.name, EVENT_MAIL_OPEN_MAILBOX, Open_Mail_Panel)
  Reply With Quote
11/29/14, 06:52 PM   #3
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Not entirely sure, it's been some time since I've done anything with the mail, but IIRC these events don't speak about UI. MAIL_INTERACTION_FRAGMENT calls RequestOpenMailbox() when it's shown, and CloseMailbox() when it's hidden. I believe these functions guard access to the internal mailbox controller, and the OPEN/CLOSE events tell you when you can use mail-related API functions.

If you need to know when the mail UI is shown/hidden, you can MAIL_INTERACTION_FRAGMENT:RegisterCallback("StateChange", function(oldState, newState) ... end). If you're only interested in MAIL_INBOX_SCENE or MAIL_SEND_SCENE, then you can RegisterCallback on the desired scene.
  Reply With Quote
11/30/14, 10:45 AM   #4
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Thx for the info circonian and merlight.
I'm not trying to change any mail related stuff here.
I just noticed this mail event as I played around with the player inventory.

As you have already informed me about the callback functions for the mail fragment merlight you might help me with this idea too:

I'm searching for a reliable way to see if some of the gui panels (vendor, mail, player trade, bank, guild bank, guild store, player inventory, deconstruction tab at crafting station, improvement tab at crafting station, enchanting station create, enchanting creation destroy, alchemy station, etc.) are shown, and when they are hidden again.

Currently I've registered events like EVENT_CRAFTING_STATION_INTERACT or EVENT_OPEN_STORE and the relating close events to check if the gui panels are opened/closed. In the callback function for these events I've coded something like

if not ZO_SmithingTopLevelImprovementPanelInventory:IsHidden() then
--we are inside the improvement tab at a crafting station
elseif not ZO_SmithingTopLevelDeconstructionPanelInventory:IsHidden() then
--we are inside the deconstruction tab at a crafting station
...
end

to find out what the player is currently doing.

I'd like to find a way to find out where the player is currently working at the gui so I can use this input as a parameter for other functions. For example this would help me to only register the filters with libFilters in FCOItemSaver for the shown gui panel (and unregister the others).
  Reply With Quote
11/30/14, 02:30 PM   #5
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
SCENE_MANAGER switches between scenes. The base scene is "hud" or "hudui" (I always forget in which of those two mouse movement controls camera view and in which you have free mouse cursor). When you loot a container for example, it switches to the "loot" scene. When you hit your inventory keybind, it switches to the "inventory" scene.

SCENE_MANAGER:GetCurrentScene() returns the name of the currently active scene.
SCENE_MANAGER:GetScene(sceneName) returns the scene object with the given name.

Scenes consist of fragments. Fragments are responsible for showing controls, playing sounds, switching mouse mode and I don't know what not A fragment can be added to multiple scenes. For example "mailInbox" and "mailSend" are separate scenes, but they have many common fragments (background, title, sounds), so you don't even notice the SCENE_MANAGER switches scenes when you go from Inbox tab to Send tab.

If you want to be told when a certain scene or fragment is shown or hidden, the cleanest way is to register a callback. Callbacks are not hooks, they're just functions thrown into a table, so they don't interfere with other code and can even be unregistered. Scene and fragment objects are derived from ZO_CallbackObject and use similar callback interface, so you can use whichever suits you better.

Lua Code:
  1. LOOT_SCENE:RegisterCallback("StateChange", function(oldState, newState)
  2.    d("loot scene state change: " .. oldState .. " -> " .. newState)
  3. end)

For callbacks on scenes, valid states are:
SCENE_SHOWING
SCENE_SHOWN
SCENE_HIDING
SCENE_HIDDEN

For callbacks on fragments, valid states are:
SCENE_FRAGMENT_SHOWING
SCENE_FRAGMENT_SHOWN
SCENE_FRAGMENT_HIDING
SCENE_FRAGMENT_HIDDEN

(use these capitalized constants, not their string values, that was just for illustration in the d() output)

Many scene objects have global aliases in all caps, for example:
LOOT_SCENE == SCENE_MANAGER:GetScene("loot")
MAIL_SEND_SCENE == SCENE_MANAGER:GetScene("mailSend")
MAIL_INBOX_SCENE == SCENE_MANAGER:GetScene("mailInbox")
... etc., but some don't (for example "inventory").


Now to your specific question about deconstruction, improvement, etc. These are all in SMITHING_SCENE, in SMITHING_FRAGMENT, just separate tabs, so all of the above is useless in this case. Sorry, maybe next time

When I wanted to know that the Research tab was shown, I hooked OnEffectivelyShown handler on the panel control:
Lua Code:
  1. ZO_PreHookHandler(SMITHING.researchPanel.control, "OnEffectivelyShown", ...)
  2. -- actually it was a post-hook in my code, but I don't remember why

OnEffectivelyShown is triggered whenever the control actually becomes visible.
OnShow, on the other hand, is only triggered when its IsHidden() status changes from true to false (which doesn't mean it will be visible - its parent may still be hidden).
  Reply With Quote
11/30/14, 04:21 PM   #6
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Wow great explanation again. Thank you so much!

In the past hours I tried around much before I've read your answer here now.
My solution:
Where I wasn't able to see which tab I actually have opened I've added ZO_PreHookHandler for "OnMouseUp" to the main panel's head menu. At the enchanting station this will be for exmapleZO_EnchantingTopLevelModeMenuBarButton1 for "Creation" and ZO_EnchantingTopLevelModeMenuBarButton2 for "Extraction".
It's working pretty fine.

Now after reading your code examples I might change it to the "OnEffectivelyShown" hook
But for the SMITHING panels it is easier to just check "if not SMITHING.<smithing_panel_name>:IsHidden()" instead of PreHooking.
<smithing_panel_name> can be:
researchPanel
deconstructionPanel
improvementPanel
refinementPanel

Originally Posted by merlight View Post
SCENE_MANAGER switches between scenes. The base scene is "hud" or "hudui" (I always forget in which of those two mouse movement controls camera view and in which you have free mouse cursor). When you loot a container for example, it switches to the "loot" scene. When you hit your inventory keybind, it switches to the "inventory" scene.

SCENE_MANAGER:GetCurrentScene() returns the name of the currently active scene.
SCENE_MANAGER:GetScene(sceneName) returns the scene object with the given name.

Scenes consist of fragments. Fragments are responsible for showing controls, playing sounds, switching mouse mode and I don't know what not A fragment can be added to multiple scenes. For example "mailInbox" and "mailSend" are separate scenes, but they have many common fragments (background, title, sounds), so you don't even notice the SCENE_MANAGER switches scenes when you go from Inbox tab to Send tab.

If you want to be told when a certain scene or fragment is shown or hidden, the cleanest way is to register a callback. Callbacks are not hooks, they're just functions thrown into a table, so they don't interfere with other code and can even be unregistered. Scene and fragment objects are derived from ZO_CallbackObject and use similar callback interface, so you can use whichever suits you better.

Lua Code:
  1. LOOT_SCENE:RegisterCallback("StateChange", function(oldState, newState)
  2.    d("loot scene state change: " .. oldState .. " -> " .. newState)
  3. end)

For callbacks on scenes, valid states are:
SCENE_SHOWING
SCENE_SHOWN
SCENE_HIDING
SCENE_HIDDEN

For callbacks on fragments, valid states are:
SCENE_FRAGMENT_SHOWING
SCENE_FRAGMENT_SHOWN
SCENE_FRAGMENT_HIDING
SCENE_FRAGMENT_HIDDEN

(use these capitalized constants, not their string values, that was just for illustration in the d() output)

Many scene objects have global aliases in all caps, for example:
LOOT_SCENE == SCENE_MANAGER:GetScene("loot")
MAIL_SEND_SCENE == SCENE_MANAGER:GetScene("mailSend")
MAIL_INBOX_SCENE == SCENE_MANAGER:GetScene("mailInbox")
... etc., but some don't (for example "inventory").


Now to your specific question about deconstruction, improvement, etc. These are all in SMITHING_SCENE, in SMITHING_FRAGMENT, just separate tabs, so all of the above is useless in this case. Sorry, maybe next time

When I wanted to know that the Research tab was shown, I hooked OnEffectivelyShown handler on the panel control:
Lua Code:
  1. ZO_PreHookHandler(SMITHING.researchPanel.control, "OnEffectivelyShown", ...)
  2. -- actually it was a post-hook in my code, but I don't remember why

OnEffectivelyShown is triggered whenever the control actually becomes visible.
OnShow, on the other hand, is only triggered when its IsHidden() status changes from true to false (which doesn't mean it will be visible - its parent may still be hidden).

Last edited by Baertram : 11/30/14 at 04:25 PM.
  Reply With Quote
11/30/14, 06:52 PM   #7
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by Baertram View Post
Currently I've registered events like EVENT_CRAFTING_STATION_INTERACT or EVENT_OPEN_STORE and the relating close events to check if the gui panels are opened/closed. In the callback function for these events I've coded something like

if not ZO_SmithingTopLevelImprovementPanelInventory:IsHidden() then
--we are inside the improvement tab at a crafting station
elseif not ZO_SmithingTopLevelDeconstructionPanelInventory:IsHidden() then
--we are inside the deconstruction tab at a crafting station
...
end
The event itself tells you which crafting station they are at:
Lua Code:
  1. EVENT_MANAGER:RegisterForEvent(BuffIt.name, EVENT_CRAFTING_STATION_INTERACT, craft)
  2.  
  3. local function craft(eventCode, craftSkill, sameStation)
  4. -- craftSkill tells you which one your at
  5. -- just check the craftSkill against these:
  6. --CRAFTING_TYPE_ALCHEMY
  7. --CRAFTING_TYPE_BLACKSMITHING
  8. --CRAFTING_TYPE_CLOTHIER
  9. --CRAFTING_TYPE_ENCHANTING
  10. --CRAFTING_TYPE_PROVISIONING
  11. --CRAFTING_TYPE_WOODWORKING
  12.  
  13. -- like:
  14.    if craftSkill == CRAFTING_TYPE_BLACKSMITHING then
  15.       -- your at the blacksmithing craft station
  16.    end
  17. end
  Reply With Quote
11/30/14, 07:08 PM   #8
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by Baertram View Post
Now after reading your code examples I might change it to the "OnEffectivelyShown" hook
But for the SMITHING panels it is easier to just check "if not SMITHING.<smithing_panel_name>:IsHidden()" instead of PreHooking.
<smithing_panel_name> can be:
researchPanel
deconstructionPanel
improvementPanel
refinementPanel
You can hook the menu buttons to see when each of the panel buttons is pressed.

Here is what I did in my filtering feature, like AF, to show/hide the menu bars when the user pressed one of the menu buttons in the inventory:
Lua Code:
  1. ----------------------------------------------------------------------------------------
  2. -- Set a Callback for the inventory buttons so I can show/hide my menus when the buttons are pushed. --
  3. ----------------------------------------------------------------------------------------
  4. local function HookInvButtons()
  5.         -- menu bar buttons for the backpack inventory
  6.     local tButtons = ZO_PlayerInventoryTabs.m_object.m_buttons
  7.    
  8.     if _iFilterType == ITEMFILTERTYPE_ALL    then return end    --- just because I didn't need these
  9.     if _iFilterType == ITEMFILTERTYPE_QUEST  then return end -- same
  10.  
  11.         -- loop through the buttons
  12.     for k,v in pairs(tButtons) do
  13.         local tButtonData = v[1].m_object.m_buttonData
  14.         local hCallback = tButtonData.callback
  15.        
  16.         tButtonData.callback = function(...)   
  17.              -- set your callback to run BEFORE the hCallback
  18.                 ShowMenu(INVENTORY_BACKPACK, tButtonData.filterType)                   
  19.                 hCallback(...)
  20.             end    
  21.     end
  22. end

It could be altered for what your wanting easily, but you would still want to run your callback BEFORE the hCallback. That part is very important.

This would give your addon a head start for registering/unregistering your filters before the real button callback is called. This way there should be no lag in libFilters caused by your addon. LibFilters will not need to wait for your addon to register/unregister filters because it will be done before the button callback even fires to change the filter and libFilters would have absolutely no reason to ever update the list view more than once...because again all filters would be unregistered/registered before libFilters even gets notified that the filter is changing. So all it would have to do is run through the slots once to check against the filters & then update the list once. No need for any hack methods or zo_calllaters to ensure all filters are registered before updating.


Hope that helps if you have any questions just let me know.

Last edited by circonian : 11/30/14 at 07:10 PM.
  Reply With Quote
12/02/14, 11:40 PM   #9
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,989
Originally Posted by merlight View Post
When I wanted to know that the Research tab was shown, I hooked OnEffectivelyShown handler on the panel control:
Lua Code:
  1. ZO_PreHookHandler(SMITHING.researchPanel.control, "OnEffectivelyShown", ...)
  2. -- actually it was a post-hook in my code, but I don't remember why
I think I know why you've made it as a post hook:
The deconstruction, improvement, and ther panels won't be shown directly if you press the button to change it, or as the OnEfectivelyShown() function was called.
There is sometimes a slight delay before you can use e.g. IsHidden().
Either you put your function as a post hook, so everything else was done before your check "where am I?", or you try it with zo_callLater and about 50ms.
  Reply With Quote
12/03/14, 04:54 AM   #10
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by Baertram View Post
There is sometimes a slight delay before you can use e.g. IsHidden().
Either you put your function as a post hook, so everything else was done before your check "where am I?", or you try it with zo_callLater and about 50ms.
IIRC OnEffectivelyShown happens before OnShow, so I wouldn't bet on IsHidden returning true. But I surely didn't call IsHidden, when OnEffectivelyShown is called on a panel I assume the user will see it
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Event EVENT_MAIL_CLOSE_MAILBOX fired upon closing of inventory?


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