Add guild/friend lists context menu item
Im considering adding a context menu item to the guilds, friends and group lists.. possibly chat as well for saving someone to a saved variable for use in my addon.
Im trying to keep this light and wanting to avoid mouse click events etc but might have no choice. Also im trying to avoid dependencies if possible. Is there a quick, easy and clean non-intrusive way to achieve this without utilizing libcustommenu? Literally just to save that persons @NAME to a saved variable? I have read Beartrams warning regarding not using it or doing this improperly which is why im here poking around :) |
Why don't you just use LibCustomMenu as it integrates and was build EXACTLY for that purpose? :confused:
Other addons using the same lib are compatible on the fly and you do not destroy other addons by making your own hacks and workarounds. Do what you like but those libs exist for a reason and often also provide the easiest way achieving the goal. Add it as an optional dependency and tell the guys that your addon's feature with the context menu only works if the lib is installed. Do an Lua Code:
check at the start of your function that adds the context menu and all is done. Users can use your adodn w/o dependecy then and only need it for the context menu features. |
Hmm.. ok u sold me on it. Its actually for a feature already done another way, this is just for convenience. I'll look into the lib then
|
ok ive begun integrating it..
ive added to my manifest: ## OptionalDependsOn: LibCustomMenu>=680 <<< ive found this in another addon but no idea what the number means... line#? and just starting throwing a function together with stuff till it makes sense to me :) Code:
function MyAddon.SaveContext() |
Quote:
https://wiki.esoui.com/Addon_manifest_(.txt)_format -> https://wiki.esoui.com/Addon_manifes...rmat#DependsOn https://wiki.esoui.com/Libraries#.23...ned_integer.3E And about LibCustomMenu: The description provides examples how to add such contextmenus. Guild roster - Just add 1 call at e.g. your EVENT_ADD_ON_LOADED. Lua Code:
|
thank you... ive been searching for the manifest number and where might be best to call this.. been peeking around a few addons for it too but so far been too complex to understand.
I'll give some of this this a whirl. |
Based on your example ive got this in addon loaded and appears to work with the category setting which i assumed wasnt nessisary if it was the default setting. This code does progress to the "MyAddon.SavePlayerContext" function and run it. I guess what I dont fully understand now is am I to "addcustommeenuitem" etc myself now? What exactly is "libcustommenu" doing that I dont have to if it so super easy?
Code:
if LibCustomMenu ~= nil then |
The library provides you the "entry" (a hook into vanilla code), via acallback function with fixed parameter (rowData) which is fired as the context menu is build by vanilla code.
You "Register" your callback function, just like you register your callback for an event or register a callback for a CALLBACK_MANAGER:FireCallbacks(.. function trigger. And then this function is executed as the vanilla code runs, and assists you with compatibility for addons, and vanilla code, and an easy way to add your own entries to the context menu. So yes, inside your callback you need to add a custom menu entyr IF this is your goal in the end. The callback function func(rowData) should be usedto do so and you have the benefit of already knowing rowData and it's values so you could add teh contexmenu entry based on that rowData information, e.g. Code:
if rowData.displayName and rowData.displayName == GetDisplayName() then do something for your own user else do something for another user end Attention: Do not call ClearMenu() inside that callback as else it will clear the total ZO_Menu and all vanilla and other addon context meneu entries will be gone! |
Well Ive never used a callback and trying to understand what that even is still but ive made progress.. with this ive got the menu item then when clicked drops an error stating it was expecting a function instead of nil..
I have this nagging feeling the AddMenuContext function should up up in the ONLOAD part tbh. What you see below particularly the last function thats mostly comented out is more or less all I want it to do. Code:
ONLOAD() |
Quote:
Every EVENT_MANAGER:RegisterFor is using a callbackFunction that is called as the event fires, e.g. the OnAddonLoaded function you have defined for your EVENT_ADD_ON_LOADED (hopefully). You cannot do such: Lua Code:
AddCustomMenuItem got a dedicated signature, which means you need to pass in a function as the 2nd parameter and not a result of a function, which is what would be passed in if you "call" your function MyAddon.SavePlayerContext(playerName) there! You need to add it with a closure around it so it does not get called as you pass it in the parameter, but get's called as it's own function as the 2nd param is needed: Lua Code:
This function() yourFunctionNameWithParam(param1, param2) end is doing the following: It will pass in a function (an anonymous one without name) and as this function is called at any time within LibCustomMenu code, the internal function MyAddon.SavePlayerContext(playerName) will be called, at that time (as the context emnu entry is clicked). Else you'd just pass in the return value of MyAddon.SavePlayerContext(playerName), at the point the AddCustomMenuItem("MyAddon Save", MyAddon.SavePlayerContext(playerName)) was read from the code interpreter (means as the code is read the first time which would be way too early even before the contex menu was opened)! And if that is nil as your function MyAddon.SavePlayerContext(playerName)) does not return anything, this is why you get the nil error but function expected ! If would work again if your function MyAddon.SavePlayerContext(playerName) would return a function e.g. return function() doSomething(playerName) end. |
Thank you. This stuff is way over my head but is last useful function and all our pain is over :) Well not entirely.. need todo this for guild list, friends list, group list and possibly chat.
Heres what i got so far but i need a break I cant even think anymore. I need to find a way to get the players @name down to the bottom function so it can be saved to the variable. Code:
ONLOAD() |
https://www.lua.org/pil/6.html
Maybe that will explain it (anonymous functions e.g.) with more details |
ok ive been reading that and some useful stuff in there but going slow. For the moment I've sidetracked a bit to working on the friendslist and chat functionality and managed to get chat working too as its very similar.
By working i mean i can chat output my own username or text or something locally to the function no problem but I'm still unable to get the playerName data from the rowdata down to the function. also.. is there a similar friendslist function in libcustommenu??? I dont see any mention of it in the addon description or inside the library itself ive scanned all through it. |
the chat context seems to be working perfectly but nomatter what I do i still get "table:000023908713BHS&HS" or similar from the rowdata for the guild context.
Also ive been digging for hours and there 0 info for friends list and group list context menus? are guild and chat my only options? Im trying to convert everything into an @NAME in "playerName" so i can use 1 function to save to variable & display it in chat that its doing that. Code:
if LibCustomMenu ~= nil then |
if you get something like table:000023908713BHS&HS then it means your are passing in the total table and not 1 value of that table, e.g. you pass in rowData and not rowData.subVariableInThatTable.
As I said, add the rowDate in your callback function to your global addon table like myAddon._rowdata = rowdata Then use an addon like merTorchbug or zgoo and inspect your global variable myAddon via slash command /tb myAddon or /zgoo myAddon You will see all values of that table (myAddon) that way and can click on the _rowData subtable to see what it contains. In there you might find something like characterName or memberIndex or similar whch was provided by the callback function of the guildRoster context menu and that way you can use the memberIndex or something that was provided in that rowData table to use for your usecase, like get the name of the clicked row etc. And you also need to pay attention if the signaure of the callback functions you pass in to RegisterGuildRosterContextMenu and RegisterPlayerContextMenu (I meant the first parameter, your callback function "MyAddon.AddMenuContext") is the same, if it uses the same parameters. Maybe 1 got rowData of the guildMember you right clicked on and the other one got no rowData table but just a string with the chat name you clicked on? Check it inside the LibCustomMenu.lua file, where the RegisterGuildRosterContextMenu and RegisterGuildRosterContextMenu functions are called OR at the description of the addon! About friendsList I'm not sure if LibCustomMenu provides that already or not. if the description lacks that info I doubt it's in there until now and must be added. But maybe it's in the code of the lib already, so check the lua file of LibCustomMenu for "friend" or similar, and maybe you can find the API function to register a context menu that way. Edit: I briefly scanned the code and it does not look like it supports the friendslist until now. Maybe raise a request at the addon comments of LibCustomMenu for that: lib:RegisterFriendsListContextMenu(func, category, ...) |
Thank you again.. ive tried mertorchbug and had trouble even making sense of how to use it. Ill give em another go but the chat context is working perfectly and saving at this moment at least... I got SOME satisfaction :)
I might try zgoo this time to see if its more userfriendly for me |
MerTorchbug UI is more user friendly than zgoo imo, but that's up to you in the end.
Both inspect vatisbles so that you see the values. For example if you define a global variable table MyAddon = {} you can inspect it via /tb MyAddon or /zgoo MyAddon (type to the chat editbox just like you would run a /script). The ui will show you the table then and all of its content. You can click tables in that table, or see the variables. If the insoected variable is a control you can see its values like height width anchor hidden etc. This way you can see values of variables instead of having to write them to the chat via d() debug messages. If you use /tb alone you'll see the global inspector showing you all kind of tabs like loaded addons, loaded libraries, String constants SI_* which can be used with the GetString function, constsnts in the game like BAG_BACKPACK and its value, global classes like ZO_Smithing and its created object SMITHING, fonts and so on. All those global variables are stored inside one global table _G in lua. So basically all is stored in tables in lua and with merTorchbug or zgoo you can insprct this tables at runtime. |
Ya both seem informative but i kept getting stuck with blank windows open with torchbug... zgoo feels better for me so far.
Also got it all fixed up now.. "rowData" was actually "data". I picked up on this after votan upgraded LibCustomMenu after i requested it to include group and friends list.. his additional descriptions made it all suddenly clear. Thank you for all your help. |
You need to use merTorchbug updated! The original one is outdated and not functioning.
If your window that opens is blank try to resize it, sometimes the size is too small to show the info. Or if it's blank your inspected table is maybe empty and just shows as blank window. |
I messed up my save player function somehow this morning cleaning up notes and many unessissary variables or so I thought.
The saved variable is saving correctly.. the DF output is outputting correctly and yet Im getting a nil value error on editing the text field in the setting panel just below it. Heres what i got setup atm and shud only be a local variable to fix it I would think. Any suggestions would be appreciated. I was soo close to done with this thing. Code:
--ADDON LOADED-- Code:
user:/AddOns/MyAddon/MyAddon.lua:248: attempt to index a nil value |
Seriously, you should please follow the rules like all others too.
If you get any error message: 1. Post the whole error message so we can see the error message AND the line numbers AND the exapanded variables from the error mesasge 2. Post your code or at least the code block around the lines of the error message WITH line numbers or at least the line number where the error message hits We cannot assume things nor do we like to and I personally often do not understand what you talk about in your posted code lines (what should "on editing the text field in the setting panel just below it." relate to in your posted code :confused:) Many thanks for easing it for us all. I also posted you the "how to read lua error messages" before already so maybe read the info there and learn to read the error messages, or ask questions about the error mesasges in detail so we can explain it to you better. You often, especially for nil errors, find out what's up if you understand the error messages and learn them, instead of ignoring them :p They tell you what is missing by the error text like "try to index a nil value" -> you got a table which is nil and try to access it somehow before it was created properly with = {}, etc. |
Quote:
ERRORS: ill add to bottom of my post as well so they close and handy for all to see and add the codes lines! Code:
user:/AddOns/MyAddon/MyAddon.lua:248: attempt to index a nil value |
Quote:
And yes: I do not need to answer each PM if the info is valuable for others too, that's what forums are made for. I also provided you the link to the addon devs gitter chat where you could ask the same questions and addon/lua/xml related things, but you do not want to post there, so the forums here are okay. But if you post here the same rules apply to you as to anyone else: Read before write please! -> I'm a forum mod, that's why I "jump on your post" (and any others around here!) and I'm just telling you the same as I do write to any other here :rolleyes: Especially if we/I had linked you the ressources already where there is written how to read the lua error messages. Here you go once again: https://www.esoui.com/forums/showthread.php?t=8858 -> "lua error messages ingame - How do I read them?" And how errors should be posted to all of us (not me in particular) so we can understand and help more easily and effectively: https://www.esoui.com/forums/showthread.php?t=8858 -> "How to report a lua error message/a bug to the developers" I also adviced you, in case you do not understand the written information/explanation there, to feel free to name us and ask about what you do not understand, and we might be able to help you understand it (better). This got nothing to do with being a professional developer (neither am I) or not, that's communication and if you are willing to learn we are willing to help. As an exaplanation: The error says user:/AddOns/MyAddon/MyAddon.lua:248: attempt to index a nil value So the error happens in file MyAddon/MyAddon.lua line 248 As I wrote before it's about "index a nil value" -> means there is a variable in that line which should be a table, but it does not exist. Your line 248 is: MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data.text = "Saved Player: " .. tostring(displayName)-- ERRORS APPEAR TO BE HERE AND BELOW REPORTING NIL VALUE FOR IM ASSUMING "displayName" So what is a table in this line? MyAddon_SETTINGS_SAVEDPLAYER_TEXT for example is Or MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data is too Any of these seems to be nil at the point where the error happens. So either MyAddon_SETTINGS_SAVEDPLAYER_TEXT or MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data does not exist. Add some d(tostring(MyAddon_SETTINGS_SAVEDPLAYER_TEXT)) or d(tostring(MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data)) to see which one is nil. And then work yor way back from the error (the error message shows you the "call stack -> from bottom to top where the error occurs) to the start and check where your variables MyAddon_SETTINGS_SAVEDPLAYER_TEXT and MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data are properly created and filled. Keep in mind that lua does not know local defined variables if they are defined after the calling code, or inside any if .. end, for .. do, or other closure, and you want to use the same variable otuside of the closure! Either define MyAddon_SETTINGS_SAVEDPLAYER_TEXT at the top of your addon file MyAddon.lua, as a local. And also define MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data there as {} empty tbale directly. Or at least once before it is tried to be accessed in line 248 finally. btw: Looks like MyAddon_SETTINGS_SAVEDPLAYER_TEXT is a LibAddonMenu control you wan to create for your settings panel? It's not accessible before the addon panel was loaded!!! Before it's simply nil. LibAddonMenu provides a callback that fires as the panel get's loaded, and as the controls were created. So you could use that to see if the control was created: https://www.esoui.com/downloads/info7-LibAddonMenu.html -> WIKI about callbacks: https://github.com/sirinsidiator/ESO...LAM2-callbacks But basically you do not need to manually update MyAddon_SETTINGS_SAVEDPLAYER_TEXT if it got a getFunc. Just let it read the actual value from your SavedVariables there. But as the control is a description it got no getFunc so you need to manually update it. -> Thus you need to use LibAddonMenu's callback for PanelControlsCreated to update it for the first time, as your panel was loaded and all controls were build properly. Be carefull with that callback functions, as it will run for EACH addon once! So you must check the panel loaded is yours as described or it will run too often. Lua Code:
myPanel is the variable that your addon settings panel returns as you create it via function LibAddonMenu2:RegisterAddonPanel(yourPanelName, yourPanelData) ! In order to let the callbacks work properly you night need to add the registerForRefresh at yourPanelData table! Check the Wiki documentation if this is needed for the LAM-PanelControlsCreated calback please. And in your function where you try to access MyAddon_SETTINGS_SAVEDPLAYER_TEXT you need to check if it's nil or not! Lua Code:
|
ty for all of that. I will try to make use of it but it appears none of them solve my solution. If MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data.text doesn't exist yet until the addon options are opened, and CALLBACK_MANAGER:RegisterCallback("LAM-PanelControlsCreated", function(panel) as per its description fires only after all controls are created after its opened then even it wont help me.
What im apparenrly needing is all controls created and existing upon load/reload. Im really not sure how I never noticed this before or if its related to the recent libcustommenu update but this is big problem for me. Its a primary function and having to open addon settings 1st doesn't work for me =p |
MyAddon_SETTINGS_SAVEDPLAYER_TEXT is the reference to the control in my settings menu.
The function having the error is attempting to edit the text on it but apparently cant until the user goes into the addon settings 1st because it doesn't exist yet. is there a way to make the addon settings and controls exist when the addon loads? |
No.
Why do dou even need your addon to use that control,it only shows in the settings panel? So why should it update before one opens this? As I said you could add a nil check in your function so it does not try to update that description control at the settings if it does not exist yet. That way your function still runs even without having the addon settings opened once. And with the Lam Panel Controls Created callback you can update it as someone opens the settings. |
Quote:
im going to try the callback and detect if it exists already or not maybe.. if it doesn't exist yet then just save the variable and be done with it... It might work like this. |
It cannot work by any other way ;)
If settings were not opened the control is nil, so just save without updating the control. As noone opened the settings noone will see the label or tries to see the label, so there is no reason to update it ! If the settings were opened, use the controls created calback, check for YOUR addon's panel and then update the description text of the label. If it does not dautomatically update by changing the conrol.data.title or control.data.text value, try to change the control.data.title or .text attributes and then call control:UpdateValue() function, it should update the label's text then based on the data table. |
Quote:
I would be happy doing that except the settings panel IS getting its data ON_LOAD and storing it someplace during the MyAddon:CreateSettingsWindow(). So whats happening is user logs in and plays etc, then right clicks someone to "Save players @NAME" for my addon use which works fine except the settings panel still shows the OLD @NAME when you open the addon settings. SO it IS getting the data and storing it someplace and then creating the controls with it later when you open the addon settings. I need to find where that place is and edit that when the control data is NIL. I currently have a temporary fix for people with your idea of detectinf if the data is nil so it just skips it.. addon works fine but cosmetically the settings panel will always show the previous @NAME the 1st time they open addon settings. Infact will always show the previous one until they have opened the addon settings so I can then edit the field properly. |
I have partially described how to fix that settings panel showing the old value above already, using LibAddonMenu's callback for LAM-PanelControlsCreated.
And if you had looked at the LibAddonMenu WIKI pages I linked above you would have seen there is another callback LAM-PanelOpened, which you could use in to update the label each time your LAM panel opens (Add a nil chck in there as the 1st time it's called maybe before LAM-PanelControlsCreated!). Both in combination should fix your issues. |
*EDIT*
I got it figured out.. I used the reference for the description field to detect the right addon settings are selected and when its created. Did the job. |
But my post above explains how to detect it's YOUR addon panel that was created, or opened...
>myPanel is the variable that your addon settings panel returns as you create it via function LibAddonMenu2:RegisterAddonPanel(yourPanelName, yourPanelData) ! ---> local myPanel --- do addon options etc and add it to yourPanelData ---- ... addon controls here ---myPanel = LibAddonMenu2:RegisterAddonPanel(yourPanelName, yourPanelData) --in the callback functions check for the parameter panel of the callbacks == myPanel or else return All you need to do now is use the 2 callbacks, "controls created" and "panel opened", check for your panel or else return (as it's another panel then) and then update your descriptions data and use UpdateValue to force the update on it. I had prepared all that for you already, you just need to take the time and read it, read the Wiki, and try to understand it. If you do not understand it, ask as adviced, instead of reinventing the wheel (which sometimes makes sense for a learning effect but will result in errors in longterm). |
I do thank you very much for all your help. Its very difficult for me to know when what you type is directly the answer or random hypothetical and for me to research for days. I did spend the day on it and came up with this below because i had troule making sense of the panel and myPanel data.
Code:
------ Save player ------ if it does exist then it just saves variable and edits the description field as normal. I couldnt find a reference that made sense to me for the panel but did have one for the description field so this worked perfectly i think. What I have seems to work perfectly and is the last bug I can find so im gonna pump it out to the masses but.. i will research this more and look at your suggestion till im blue in the face and see if i can make it work soon. |
The callback for lam needs to be registered once! In you addons settings code. Not each time in your "SavePlayer" function.
Having it the way you use it now will make the else... execute for each addon, not only yours! If you use 30 addons with settings (or anyone else using your addon does) it will run the panel callback code 30 times for nuts! Just move the callback code to the lam creation and use the panel parameter of the callback to check if it is your panel as described above in my last post (you get the panel to compare from your lam registerAddonPanel function! After that create the callback for controlsCreated once, and also create the callback for panelOpened to update your description. This will update the description label each time your settings panel opens, so using your player saved function does not need to update that label, unless you use it while the settings panel is actually opened? Then just check if the control is not nil and update directly ). |
1 Attachment(s)
Here is your RidinDirty.lua file with my changes, hope you understand it better that way seeing the code.
If you got questions, ask ;) It's untested so please test if it works as expected. |
Quote:
|
Quote:
|
Glad it worked out, yw. Thanks for the feedback.
|
I did just have one other super fast question regarding another function im tuning.. am I doing this correctly?
Code:
local _, isRidingGroupMount, hasFreePassengerSlot = GetTargetMountedStateInfo(savedPlayer) **EDIT Seems to be functioning correctly. |
You can always have a look at the API documentation txt file
https://wiki.esoui.com/APIVersion#live_API_version -> link to "API TXT Documentation" .txt file -> Download and open with a text editor and search for the function name "GetTargetMountedStateInfo" in it. It will show you the parameters to use and the return variables then: Code:
* GetTargetMountedStateInfo(*string* _characterOrDisplayName_) If you do not need the 1st one "MountedState" you can use the placeholder _ to show that, correct. And the other 2 return values are _isRidingGroupMount_ and _hasFreePassengerSlot_. Your code looks okay to me. |
All times are GMT -6. The time now is 05:53 PM. |
vBulletin © 2024, Jelsoft Enterprises Ltd
© 2014 - 2022 MMOUI